From ecf09abe0ff44823804b0fdef3d468aa0e6f544f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 5 Feb 2008 13:14:30 +0000 Subject: [PATCH 0001/2215] Initial import of TellStick-driver --- driver/CMakeLists.txt | 6 + driver/TellUsbD101.sln | 20 + driver/TellUsbD101/CMakeLists.txt | 27 + driver/TellUsbD101/Device.cpp | 52 ++ driver/TellUsbD101/Device.h | 24 + driver/TellUsbD101/DeviceIkea.cpp | 141 ++++ driver/TellUsbD101/DeviceIkea.h | 23 + driver/TellUsbD101/DeviceNexa.cpp | 163 +++++ driver/TellUsbD101/DeviceNexa.h | 22 + driver/TellUsbD101/DeviceSartano.cpp | 128 ++++ driver/TellUsbD101/DeviceSartano.h | 21 + driver/TellUsbD101/DeviceWaveman.cpp | 58 ++ driver/TellUsbD101/DeviceWaveman.h | 11 + driver/TellUsbD101/Resource.h | 31 + driver/TellUsbD101/TellUsbD101.cpp | 321 +++++++++ driver/TellUsbD101/TellUsbD101.def | 24 + driver/TellUsbD101/TellUsbD101.h | 73 +++ driver/TellUsbD101/TellUsbD101.vcproj | 308 +++++++++ driver/TellUsbD101/TelldusSettings.cpp | 631 ++++++++++++++++++ driver/TellUsbD101/TelldusSettings.h | 42 ++ driver/TellUsbD101/linux/Device.cpp | 85 +++ driver/TellUsbD101/stdafx.cpp | 8 + driver/TellUsbD101/stdafx.h | 37 ++ driver/TellUsbD101/win/Device.cpp | 91 +++ driver/TellUsbD101/win/FTD2XX.H | 875 +++++++++++++++++++++++++ 25 files changed, 3222 insertions(+) create mode 100644 driver/CMakeLists.txt create mode 100644 driver/TellUsbD101.sln create mode 100644 driver/TellUsbD101/CMakeLists.txt create mode 100644 driver/TellUsbD101/Device.cpp create mode 100644 driver/TellUsbD101/Device.h create mode 100644 driver/TellUsbD101/DeviceIkea.cpp create mode 100644 driver/TellUsbD101/DeviceIkea.h create mode 100644 driver/TellUsbD101/DeviceNexa.cpp create mode 100644 driver/TellUsbD101/DeviceNexa.h create mode 100644 driver/TellUsbD101/DeviceSartano.cpp create mode 100644 driver/TellUsbD101/DeviceSartano.h create mode 100644 driver/TellUsbD101/DeviceWaveman.cpp create mode 100644 driver/TellUsbD101/DeviceWaveman.h create mode 100644 driver/TellUsbD101/Resource.h create mode 100644 driver/TellUsbD101/TellUsbD101.cpp create mode 100644 driver/TellUsbD101/TellUsbD101.def create mode 100644 driver/TellUsbD101/TellUsbD101.h create mode 100644 driver/TellUsbD101/TellUsbD101.vcproj create mode 100644 driver/TellUsbD101/TelldusSettings.cpp create mode 100644 driver/TellUsbD101/TelldusSettings.h create mode 100644 driver/TellUsbD101/linux/Device.cpp create mode 100644 driver/TellUsbD101/stdafx.cpp create mode 100644 driver/TellUsbD101/stdafx.h create mode 100644 driver/TellUsbD101/win/Device.cpp create mode 100644 driver/TellUsbD101/win/FTD2XX.H diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt new file mode 100644 index 00000000..18cc7359 --- /dev/null +++ b/driver/CMakeLists.txt @@ -0,0 +1,6 @@ +PROJECT( tellstick ) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) + +ADD_SUBDIRECTORY(TellUsbD101) + diff --git a/driver/TellUsbD101.sln b/driver/TellUsbD101.sln new file mode 100644 index 00000000..1b22fbc9 --- /dev/null +++ b/driver/TellUsbD101.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TellUsbD101", "TellUsbD101\TellUsbD101.vcproj", "{2A868E40-88D9-4800-A83F-21D0F8DCB611}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Debug|Win32.ActiveCfg = Release|Win32 + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Debug|Win32.Build.0 = Release|Win32 + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Release|Win32.ActiveCfg = Release|Win32 + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/driver/TellUsbD101/CMakeLists.txt b/driver/TellUsbD101/CMakeLists.txt new file mode 100644 index 00000000..55842bce --- /dev/null +++ b/driver/TellUsbD101/CMakeLists.txt @@ -0,0 +1,27 @@ + +SET( tellusbd101_SRCS + Device.cpp + linux/Device.cpp + DeviceIkea.cpp + DeviceNexa.cpp + DeviceSartano.cpp + DeviceWaveman.cpp + ) + +ADD_DEFINITIONS( + -DOS_LINUX + ) + +ADD_LIBRARY(tellusbd101 SHARED + ${tellusbd101_SRCS} + ${tellusbd101_MOC_SRCS} + ) + +# TARGET_LINK_LIBRARIES(tellusbd101 +# ${MIDAS_LIBRARY} +# ) + +INSTALL(TARGETS tellusbd101 LIBRARY + DESTINATION lib + ) + diff --git a/driver/TellUsbD101/Device.cpp b/driver/TellUsbD101/Device.cpp new file mode 100644 index 00000000..3d6a6322 --- /dev/null +++ b/driver/TellUsbD101/Device.cpp @@ -0,0 +1,52 @@ +#include "Device.h" + +/* +* Constructor +*/ +Device::Device(int intDongleIndex) +{ + this->intDongleIndex = intDongleIndex; +} + +/* +* Destructor +*/ +Device::~Device(void) +{ + intDongleIndex = -1; +} + +/* +* Turn on, virtual +*/ +void Device::turnOn(void){ + //do nothing +} + +/* +* Turn off, virtual +*/ +void Device::turnOff(void){ + //do nothing +} + +/* +* Bell, virtual +*/ +void Device::bell(void){ + //do nothing +} + +/* +* Dim, virtual +*/ +void Device::dim(unsigned char level){ + //do nothing +} + +/* +* Has Method, virtual +*/ +bool Device::hasMethod(int methodname, char* strModel){ + return false; +} diff --git a/driver/TellUsbD101/Device.h b/driver/TellUsbD101/Device.h new file mode 100644 index 00000000..4f4e5f1d --- /dev/null +++ b/driver/TellUsbD101/Device.h @@ -0,0 +1,24 @@ +#pragma once + +#include "TellUsbD101.h" + +class Device +{ +private: + int intDongleIndex; +protected: + void send(char* strMessage); +public: + Device(int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual void bell(void); + virtual void dim(unsigned char level); + virtual bool hasMethod(int methodname, char* strModel); + static int getDongleIndex(); + + static void debugLog(char* debugstring); + +public: + ~Device(void); +}; diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/driver/TellUsbD101/DeviceIkea.cpp new file mode 100644 index 00000000..a32f00ff --- /dev/null +++ b/driver/TellUsbD101/DeviceIkea.cpp @@ -0,0 +1,141 @@ +// #include "StdAfx.h" //Needed? +#include "DeviceIkea.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceIkea::DeviceIkea(int intNewSystem, int intNewUnits, int intNewFadeStyle, int intDeviceIndex):Device(intDeviceIndex){ + intSystem = intNewSystem; + intUnits = intNewUnits; + intFadeStyle = intNewFadeStyle; +} + +/* +* Destructor +*/ +DeviceIkea::~DeviceIkea(void) +{ + intSystem = -1; + intUnits = -1; + intFadeStyle = -1; +} + +/* +* Turn on this device +*/ +void DeviceIkea::turnOn(void){ + try{ + string strCode = getStringCode(255); + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceIkea::turnOff(void){ + try{ + string strCode = getStringCode(0); + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceIkea::dim(unsigned char level){ + try{ + string strCode = getStringCode(level); + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Convert an integer to byte string where 0 is represented by ª and 1 by TT +*/ +string DeviceIkea::getStringCode(unsigned char level){ + + string strReturn = "STTTTTTª"; //Startcode, always like this; + + try{ + string strChannels = ""; + int intCode = (intSystem << 10) | intUnits; + int checksum1 = 0; + int checksum2 = 0; + for (int i = 13; i >= 0; --i) { + if ((intCode>>i) & 1) { + strChannels.append("TT"); + if (13 % 2 == 0) + checksum2++; + else + checksum1++; + } else { + strChannels.append("ª"); + } + } + strReturn.append(strChannels); //System + Units + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + if (level <= 12) { + strReturn.append("ªTTªTT"); //Level 0 - Off + } else if (level <= 137) { + strReturn.append("TTªTTª"); //Level 5 + } else if (level <= 162) { + strReturn.append("ªTTTTª"); //Level 6 + } else { + strReturn.append("ªªªª"); //Level 10 - On + } + + if (intFadeStyle == 1) + strReturn.append("TTTTªª"); //Smooth + else + strReturn.append("TTªªTT"); //Instant + strReturn.append("+"); + + } + catch(...){ + throw; + } + return strReturn; + +} + +/* +* Has the device got the method? +*/ +bool DeviceIkea::hasMethod(int methodname, char* strModel){ + + if(strcmp(strModel, TELLSTICK_DEVICE_KOPPLA) == 0) { + if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF || methodname == TELLSTICK_DIM){ + return true; + } + } + return false; +} diff --git a/driver/TellUsbD101/DeviceIkea.h b/driver/TellUsbD101/DeviceIkea.h new file mode 100644 index 00000000..bbe34c75 --- /dev/null +++ b/driver/TellUsbD101/DeviceIkea.h @@ -0,0 +1,23 @@ +#pragma once +#include "Device.h" +#include + +class DeviceIkea : public Device +{ +public: + DeviceIkea(int intSystem, int intUnits, int fadeStyle, int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual void dim(unsigned char level); + virtual bool hasMethod(int methodname, char* strModel); + +public: + ~DeviceIkea(void); + +protected: + int intSystem; + int intUnits; + int intFadeStyle; + std::string getStringCode(unsigned char); +}; + diff --git a/driver/TellUsbD101/DeviceNexa.cpp b/driver/TellUsbD101/DeviceNexa.cpp new file mode 100644 index 00000000..4deb98d7 --- /dev/null +++ b/driver/TellUsbD101/DeviceNexa.cpp @@ -0,0 +1,163 @@ +// #include "StdAfx.h" +#include "DeviceNexa.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceNexa::DeviceNexa(int intNewHouse, int intNewCode, int intDeviceIndex):Device(intDeviceIndex){ + intHouse = intNewHouse; + intCode = intNewCode; +} + +/* +* Destructor +*/ +DeviceNexa::~DeviceNexa(void) +{ + intHouse = -1; + intCode = -1; +} + +/* +* Turn on this device +*/ +void DeviceNexa::turnOn(void){ + + try{ + //char* model = getModel(intDeviceId); + string strCode = getStringCode(intCode); + string strHouse = getStringCode(intHouse); + strCode.append(strHouse); + + strCode.insert(0, "S"); + strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceNexa::turnOff(void){ + + try{ + string strCode = getStringCode(intCode); + string strHouse = getStringCode(intHouse); + + strCode.append(strHouse); + strCode.insert(0, "S"); + strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Send a bell +*/ +void DeviceNexa::bell(void){ + + try{ + string strCode = getStringCode(intCode); + + strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time + strCode.insert(0, "S"); + strCode.append("$kk$$kk$$kk$$kk$$k+"); //the "bell"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed +*/ +string DeviceNexa::getStringCode(int intToConvert){ + + string strReturn = ""; + + try{ + bitset<4> bs ((long)intToConvert); + + strReturn = bs.to_string(); + reverse(strReturn.begin(), strReturn.end()); + + int intPos = (int)strReturn.find("0"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "$k"); + intPos = (int)strReturn.find("0", intPos + 1); + } + + intPos = (int)strReturn.find("1"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "k$"); + intPos = (int)strReturn.find("1", intPos + 1); + } + + intPos = 0; + while (intPos < (int)strReturn.length()){ + strReturn.insert(intPos, "$k"); + intPos = intPos + 4; + } + } + catch(...){ + throw; + } + return strReturn; + +} + +/* +* Has the device got the method? +*/ +bool DeviceNexa::hasMethod(int methodname, char* strModel){ + + if( strcmp(strModel, TELLSTICK_DEVICE_YCR3500) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_YCR300D) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_WSR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_CMR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_CMR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_PA33300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2005) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2006) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_SYCR3500) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_SYCR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_HDR105) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2004) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2016) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2010) == 0 + ) + { + if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF){ + return true; + } + } else if ( strcmp(strModel, TELLSTICK_DEVICE_ML7100) == 0 ) { + if(methodname == TELLSTICK_BELL) { + return true; + } + } + return false; +} diff --git a/driver/TellUsbD101/DeviceNexa.h b/driver/TellUsbD101/DeviceNexa.h new file mode 100644 index 00000000..9ae10a72 --- /dev/null +++ b/driver/TellUsbD101/DeviceNexa.h @@ -0,0 +1,22 @@ +#pragma once +#include "Device.h" +#include + +class DeviceNexa : public Device +{ +public: + DeviceNexa(int intHouse, int intCode, int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual void bell(void); + virtual bool hasMethod(int methodname, char* strModel); + +public: + ~DeviceNexa(void); + +protected: + int intHouse; + int intCode; + std::string getStringCode(int); +}; + diff --git a/driver/TellUsbD101/DeviceSartano.cpp b/driver/TellUsbD101/DeviceSartano.cpp new file mode 100644 index 00000000..c06a7f0b --- /dev/null +++ b/driver/TellUsbD101/DeviceSartano.cpp @@ -0,0 +1,128 @@ +#include "DeviceSartano.h" +#include "DeviceNexa.h" +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceSartano::DeviceSartano(int intNewSystem, int intNewCode, int intDeviceIndex) + :Device(intDeviceIndex) +{ + intSystem = intNewSystem; + intCode = intNewCode; +} + + +DeviceSartano::~DeviceSartano(void) +{ + intSystem = -1; + intCode = -1; +} + + +/* +* Turn on this device +*/ +void DeviceSartano::turnOn(void){ + + try{ + string strSystem = getStringCode(intSystem); + string strCode = getStringCode(intCode); + strSystem.append(strCode); + + strSystem.insert(0, "S"); + strSystem.append("$k$k$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strSystem.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceSartano::turnOff(void){ + + try{ + string strSystem = getStringCode(intSystem); + string strCode = getStringCode(intCode); + strSystem.append(strCode); + + strSystem.insert(0, "S"); + strSystem.append("$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strSystem.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Has the device got the method? +*/ +bool DeviceSartano::hasMethod(int methodname, char* strModel){ + + bool blnExists = false; + + try{ +// if(strModel == "xxxx" || strModel == "yyyy"){ + if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF){ + blnExists = true; +// } + } + } + catch(...){ + throw; + } + return blnExists; +} + +/* +* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed +*/ +string DeviceSartano::getStringCode(int intToConvert){ + + string strReturn = ""; + + try{ + bitset<5> bs ((long)intToConvert); + + strReturn = bs.to_string(); + + int intPos = (int)strReturn.find("0"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "$k"); + intPos = (int)strReturn.find("0", intPos + 1); + } + + intPos = (int)strReturn.find("1"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "k$"); + intPos = (int)strReturn.find("1", intPos + 1); + } + + intPos = 0; + while (intPos < (int)strReturn.length()){ + strReturn.insert(intPos, "$k"); + intPos = intPos + 4; + } + } + catch(...){ + throw; + } + return strReturn; + +} + diff --git a/driver/TellUsbD101/DeviceSartano.h b/driver/TellUsbD101/DeviceSartano.h new file mode 100644 index 00000000..929cf32d --- /dev/null +++ b/driver/TellUsbD101/DeviceSartano.h @@ -0,0 +1,21 @@ +#pragma once +#include "Device.h" +#include + + +class DeviceSartano : public Device +{ +public: + DeviceSartano(int intSystem, int intCode, int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual bool hasMethod(int methodname, char* strModel); + + ~DeviceSartano(void); + +protected: + std::string getStringCode(int); + + int intSystem; + int intCode; +}; diff --git a/driver/TellUsbD101/DeviceWaveman.cpp b/driver/TellUsbD101/DeviceWaveman.cpp new file mode 100644 index 00000000..dbbf3f69 --- /dev/null +++ b/driver/TellUsbD101/DeviceWaveman.cpp @@ -0,0 +1,58 @@ +// #include "StdAfx.h" +#include "DeviceWaveman.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceWaveman::DeviceWaveman(int intNewHouse, int intNewCode, int intDeviceIndex) + :DeviceNexa(intNewHouse, intNewCode, intDeviceIndex){ +} + +/* +* Turn off this device +*/ +void DeviceWaveman::turnOff(void){ + + try{ + string strCode = getStringCode(intCode); + string strHouse = getStringCode(intHouse); + + strCode.append(strHouse); + strCode.insert(0, "S"); + strCode.append("$k$k$k$k$k$k$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Has the device got the method? +*/ +bool DeviceWaveman::hasMethod(int methodname, char* strModel){ + + bool blnExists = false; + + try{ +// if(strModel == "xxxx" || strModel == "yyyy"){ + if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF){ + blnExists = true; +// } + } + } + catch(...){ + throw; + } + return blnExists; +} diff --git a/driver/TellUsbD101/DeviceWaveman.h b/driver/TellUsbD101/DeviceWaveman.h new file mode 100644 index 00000000..ab013172 --- /dev/null +++ b/driver/TellUsbD101/DeviceWaveman.h @@ -0,0 +1,11 @@ +#pragma once +#include "DeviceNexa.h" +#include + +class DeviceWaveman : public DeviceNexa +{ +public: + DeviceWaveman(int intHouse, int intCode, int intDeviceIndex); + virtual void turnOff(void); + virtual bool hasMethod(int methodname, char* strModel); +}; diff --git a/driver/TellUsbD101/Resource.h b/driver/TellUsbD101/Resource.h new file mode 100644 index 00000000..0c5cdd60 --- /dev/null +++ b/driver/TellUsbD101/Resource.h @@ -0,0 +1,31 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by testruntelldus3.rc +// + +#define IDS_APP_TITLE 103 + +#define IDR_MAINFRAME 128 +#define IDD_TESTRUNTELLDUS3_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_TESTRUNTELLDUS3 107 +#define IDI_SMALL 108 +#define IDC_TESTRUNTELLDUS3 109 +#define IDC_MYICON 2 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp new file mode 100644 index 00000000..c51be172 --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -0,0 +1,321 @@ +//DLL entry point + +#include "stdafx.h" +#include "TellUsbD101.h" +#include "TelldusSettings.h" +#include "Device.h" +#include +#include +#include +#include + +void handleException(std::exception e); + + +#define MAX_LOADSTRING 100 + +//TODO: +//delete on created objects +//comment (just copy from the called methods) + +bool __stdcall devTurnOn(int intDeviceId){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + dev->turnOn(); + + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +bool __stdcall devTurnOff(int intDeviceId){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + dev->turnOff(); + + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +bool __stdcall devBell(int intDeviceId){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + dev->bell(); + + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +bool __stdcall devDim(int intDeviceId, unsigned char level){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + if (level == 0) { + dev->turnOff(); + } else if (level == 255) { + dev->turnOn(); + } else { + dev->dim(level); + } + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +int __stdcall devGetNumberOfDevices(void){ + int intReturn = -1; + try{ + TelldusSettings ts; + intReturn = ts.getNumberOfDevices(); + } + catch(exception e){ + intReturn = -1; + handleException(e); + } + return intReturn; +} + +int __stdcall devGetDeviceId(int intDeviceIndex){ + int intReturn = -1; + try{ + TelldusSettings ts; + intReturn = ts.getDeviceId(intDeviceIndex); + } + catch(exception e){ + intReturn = -1; + handleException(e); + } + return intReturn; +} + +//general settings: +char * __stdcall devGetName(int intDeviceId){ + char* strReturn; + try{ + TelldusSettings ts; + strReturn = ts.getName(intDeviceId); + } + catch(exception e){ + strReturn = ""; + handleException(e); + } + return strReturn; +} + +bool __stdcall devSetName(int intDeviceId, char* strNewName){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.setName(intDeviceId, strNewName); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +char* __stdcall devGetVendor(int intDeviceId){ + char* strReturn = ""; + try{ + TelldusSettings ts; + strReturn = ts.getVendor(intDeviceId); + } + catch(exception e){ + strReturn = ""; + handleException(e); + } + return strReturn; +} + +bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.setVendor(intDeviceId, strVendor); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + + char* __stdcall devGetModel(int intDeviceId){ + char* strReturn = ""; + try{ + TelldusSettings ts; + strReturn = ts.getModel(intDeviceId); + } + catch(exception e){ + strReturn = ""; + handleException(e); + } + return strReturn; +} + +bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.setModel(intDeviceId, strNewModel); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ + + vector vArguments; + //int intArguments[] = new int[]; //bort? + try{ + char* strTemp = strtok(strArguments, ","); + + while(strTemp != NULL){ + vArguments.push_back(atoi(strTemp)); + strTemp = strtok(NULL, ","); + } + TelldusSettings ts; + return ts.setArguments(intDeviceId, vArguments); + } + catch(exception e){ + handleException(e); + return false; + } +} + +int __stdcall devGetArgument(int intDeviceId, int intArgumentIndex){ + int intReturn; + try{ + if(intArgumentIndex != -1){ + TelldusSettings ts; + int* intArguments = ts.getArguments(intDeviceId); + intReturn = intArguments[intArgumentIndex]; + } + } + catch(exception e){ + handleException(e); + } + return intReturn; +} + +int __stdcall devGetNumberOfArguments(int intDeviceId){ + int intReturn; + try{ + TelldusSettings ts; + intReturn = ts.getNumberOfArguments(intDeviceId); + } + catch(exception e){ + handleException(e); + } + return intReturn; +} + +int __stdcall devAddDevice(){ + int intNewDeviceId = -1; + try{ + TelldusSettings ts; + int intNewDeviceId = ts.addDevice(); + } + catch(exception e){ + intNewDeviceId = -1; + handleException(e); + } + return intNewDeviceId; +} + +bool __stdcall devRemoveDevice(int intDeviceId){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.removeDevice(intDeviceId); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +bool __stdcall devHasMethod(int id, int methodname){ + + bool blnExists = false; + try{ + TelldusSettings ts; + char* strModel = ts.getModel(id); + Device* dev = ts.getDevice(id); + blnExists = dev->hasMethod(methodname, strModel); + } + catch(exception e){ + blnExists = false; + handleException(e); + } + return blnExists; +} + + +//******** +//* Error management, set strLogName to "" to turn off +//* +void handleException(exception e){ + + char* strLogName = "c:\\errorlog.txt"; + //char* strLogName = ""; + + if(strlen(strLogName) > 0){ + ofstream errorfile(strLogName, ios::app); + if(errorfile){ + errorfile << e.what() << endl; + errorfile.close(); + } + } +} + diff --git a/driver/TellUsbD101/TellUsbD101.def b/driver/TellUsbD101/TellUsbD101.def new file mode 100644 index 00000000..e79daad8 --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.def @@ -0,0 +1,24 @@ +LIBRARY TellUsbD101 +EXPORTS + devGetNumberOfDevices @1 + devGetDeviceId @2 + + devGetName @3 + devGetVendor @4 + devGetModel @5 + devGetNumberOfArguments @6 + devGetArgument @7 + + devSetName @8 + devSetVendor @9 + devSetModel @10 + devSetArguments @11 + + devAddDevice @12 + devRemoveDevice @13 + + devHasMethod @14 + devTurnOn @16 + devTurnOff @17 + devBell @18 + devDim @19 diff --git a/driver/TellUsbD101/TellUsbD101.h b/driver/TellUsbD101/TellUsbD101.h new file mode 100644 index 00000000..a5aeb6b8 --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.h @@ -0,0 +1,73 @@ +#ifndef TELLUSBD101_H +#define TELLUSBD101_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TellUsbD101_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLSTICK_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef TellUsbD101_EXPORTS + #define TELLSTICK_API __declspec(dllexport) +#else + #define TELLSTICK_API __declspec(dllimport) +#endif +#ifdef _WINDOWS + #define WINAPI __stdcall +#else + #define WINAPI +#endif + + +extern "C" { + TELLSTICK_API bool WINAPI devTurnOn(int intDeviceId); + TELLSTICK_API bool WINAPI devTurnOff(int intDeviceId); + TELLSTICK_API bool WINAPI devBell(int intDeviceId); + TELLSTICK_API bool WINAPI devDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI devGetNumberOfDevices(); + TELLSTICK_API char * WINAPI devGetName(int intDeviceId); + TELLSTICK_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char* WINAPI devGetVendor(int intDeviceId); + TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); + TELLSTICK_API char* WINAPI devGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, const char* chNewName); + TELLSTICK_API int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex); + TELLSTICK_API int WINAPI devGetNumberOfArguments(int intDeviceId); + TELLSTICK_API bool WINAPI devSetArguments(int intDeviceId, const char* strArguments); + TELLSTICK_API int WINAPI devAddDevice(); + TELLSTICK_API int WINAPI devAddDeviceWithArguments(char* strVendor, int* intArguments[], int intNumberOfArguments); + TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); + TELLSTICK_API int WINAPI devGetDeviceId(int intDeviceIndex); + TELLSTICK_API bool WINAPI devHasMethod(int id, int methodname); +} + +#define TELLSTICK_TURNON 1 +#define TELLSTICK_TURNOFF 2 +#define TELLSTICK_BELL 4 +#define TELLSTICK_TOGGLE 8 +#define TELLSTICK_DIM 16 + +//Protocol Nexa +#define TELLSTICK_DEVICE_YCR3500 "1" +#define TELLSTICK_DEVICE_YCR300D "2" +#define TELLSTICK_DEVICE_WSR1000 "3" +#define TELLSTICK_DEVICE_CMR1000 "4" +#define TELLSTICK_DEVICE_CMR300 "5" +#define TELLSTICK_DEVICE_PA33300 "6" +#define TELLSTICK_DEVICE_EL2000 "8" +#define TELLSTICK_DEVICE_EL2005 "9" +#define TELLSTICK_DEVICE_EL2006 "10" +#define TELLSTICK_DEVICE_SYCR3500 "12" +#define TELLSTICK_DEVICE_SYCR300 "13" +#define TELLSTICK_DEVICE_HDR105 "14" +#define TELLSTICK_DEVICE_ML7100 "15" +#define TELLSTICK_DEVICE_EL2004 "16" +#define TELLSTICK_DEVICE_EL2016 "17" +#define TELLSTICK_DEVICE_EL2010 "18" + +//Protocol Ikea +#define TELLSTICK_DEVICE_KOPPLA "19" + +#endif diff --git a/driver/TellUsbD101/TellUsbD101.vcproj b/driver/TellUsbD101/TellUsbD101.vcproj new file mode 100644 index 00000000..5758d02b --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.vcproj @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/driver/TellUsbD101/TelldusSettings.cpp b/driver/TellUsbD101/TelldusSettings.cpp new file mode 100644 index 00000000..d15b6e2f --- /dev/null +++ b/driver/TellUsbD101/TelldusSettings.cpp @@ -0,0 +1,631 @@ +#include "StdAfx.h" +#include "TelldusSettings.h" +#include "Device.h" +#include "DeviceNexa.h" +#include "DeviceWaveman.h" +#include "DeviceSartano.h" +#include "DeviceIkea.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +TelldusSettings::TelldusSettings(void) +{ + strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; + strRegPath = "SOFTWARE\\Telldus\\"; + + intMaxRegValueLength = 1000; +} + +/* +* Destructor +*/ +TelldusSettings::~TelldusSettings(void) +{ + //RegCloseKey(hk); //close all, if still open //TODO: Need some way to know if open or closed + strRegPath = ""; + strRegPathDevice = ""; + intMaxRegValueLength = -1; + +} + +/* +* Return the number of stored devices +*/ +int TelldusSettings::getNumberOfDevices(void){ + + int intNumberOfDevices = 0; + + try{ + + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + + string strNumSubKeys; + DWORD dNumSubKeys; + RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + intNumberOfDevices = (int)dNumSubKeys; + + RegCloseKey(hk); + } + else{ + throw exception(); //couldn't open reg key + } + } + catch(...){ + intNumberOfDevices = -1; + } + return intNumberOfDevices; +} + +/* +* Get the requested device +*/ +Device* TelldusSettings::getDevice(int intDeviceId){ + + try{ + int intDongleIndex = Device::getDongleIndex(); + if(intDongleIndex != -1){ + return getDevice(intDeviceId, intDongleIndex); + } + else{ + return NULL; + } + } + catch(...){ + throw; + } +} + +/* +* Get the requested device, when the index of the USB dongle is known +* Note that the returned Device should be deleted when not in use anymore +*/ +Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ + + Device* dev = 0; + + try{ + char* vendor = getVendor(intDeviceId); + + int* args = getArguments(intDeviceId); + + //each new brand must be added here + if (strcmp(vendor, "Nexa") == 0){ + dev = new DeviceNexa((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Waveman") == 0) { + dev = new DeviceWaveman((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Sartano") == 0) { + dev = new DeviceSartano((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Ikea") == 0) { + dev = new DeviceIkea((int)args[0], (int)args[1], (int)args[2], intDongleIndex); + } + } + catch(...){ + throw; + } + return dev; +} + +/* +* Get the name of the device +*/ +char* TelldusSettings::getName(int intDeviceId){ + + char* strReturn = ""; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + strReturn = Buff; + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + strReturn = ""; + } + return strReturn; +} + +/* +* Set the name of the device +*/ +bool TelldusSettings::setName(int intDeviceId, char* strNewName){ + + bool blnSuccess = true; + try{ + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + intMaxRegValueLength = (int)strlen(strNewName); + RegSetValueEx(hk, "Name", 0, REG_SZ, (LPBYTE)strNewName, intMaxRegValueLength); + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +/* +* Get the device vendor +*/ +char* TelldusSettings::getVendor(int intDeviceId){ + + char* strReturn = ""; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + + strReturn = Buff; + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(exception e){ + strReturn = ""; + ofstream errorfile("c:\\errorlog.txt", ios::app); + if(errorfile){ + errorfile << e.what() << endl; + errorfile.close(); + } + } + return strReturn; +} + +/* +* Set the device vendor +*/ +bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ + + bool blnSuccess = true; + try{ + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + intMaxRegValueLength = (int)strlen(strVendor); + RegSetValueEx(hk, "Vendor", 0, REG_SZ, (LPBYTE)strVendor, intMaxRegValueLength); + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +/* +* Get the device model +*/ +char* TelldusSettings::getModel(int intDeviceId){ + + char* strReturn = ""; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + strReturn = Buff; + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + strReturn = ""; + } + return strReturn; +} + +/* +* Set the device model +*/ +bool TelldusSettings::setModel(int intDeviceId, char* strVendor){ + + bool blnSuccess = true; + try{ + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + intMaxRegValueLength = (int)strlen(strVendor); + RegSetValueEx(hk, "Model", 0, REG_SZ, (LPBYTE)strVendor, intMaxRegValueLength); + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +int TelldusSettings::getDeviceId(int intDeviceIndex){ + int intReturn = -1; + + try{ + + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_READ, &hk); + + if(lnExists == ERROR_SUCCESS){ + + char* Buff = new char[intMaxRegValueLength]; + DWORD size; + if (RegEnumKeyEx(hk, intDeviceIndex, (LPSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + intReturn = (int)_atoi64(Buff); + } + + delete Buff; + + RegCloseKey(hk); + } + else{ + throw exception(); //couldn't open reg key + } + } + catch(...){ + intReturn = -1; + } + return intReturn; + + +} + +/* +* Get number of device arguments +*/ +int TelldusSettings::getNumberOfArguments(int intDeviceId){ + int intReturn = -1; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dNumValues; + RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); + intReturn = (int)dNumValues - 3; //total number of values - model, name and vendor + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + //error management + } + + return intReturn; +} + +/* +* Get device arguments +*/ +int* TelldusSettings::getArguments(int intDeviceId){ + vector vReturn; + int* intReturn = new int[]; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dNumValues; + RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); + + int intNumberOfArguments = (int)dNumValues - 3; //total number of values - model, name and vendor + DWORD dwLength; + char chConvertBuffer[20]; + int i = 0; + + while(i < intNumberOfArguments){ + + char* Buff = new char[intMaxRegValueLength]; + + _itoa(i, chConvertBuffer, 10); + long lngStatus = RegQueryValueEx(hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + lngStatus = RegQueryValueEx(hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); + } + int intReturn = (int)_atoi64(Buff); + vReturn.push_back(intReturn); + + i++; + delete Buff; + } + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + intReturn = new int[vReturn.size()]; + + int i = 0; + while(i < (int)vReturn.size()){ + intReturn[i] = vReturn.at(i); + i++; + } + } + catch(...){ + //error management + } + + return intReturn; +} + +/* +* Set device arguments +*/ +bool TelldusSettings::setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments){ + + bool blnSuccess = true; + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + char chConvertBuffer [20]; + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + int i = 0; + while(i < intNumberOfArguments){ + _itoa(i, chConvertBuffer, 10); + RegSetValueEx(hk, chConvertBuffer, 0, REG_SZ, (LPBYTE)intArguments[i], intMaxRegValueLength); + i++; + } + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +/* +* Set device arguments +*/ +bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ + + bool blnSuccess = true; + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + char chConvertBuffer [20]; + char chConvertBufferValue [20]; + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + int i = 0; + while(i < vArguments.size()){ + _itoa(i, chConvertBuffer, 10); + _itoa(vArguments.at(i), chConvertBufferValue, 10); + intMaxRegValueLength = (int)strlen(chConvertBufferValue); + RegSetValueEx(hk, chConvertBuffer, 0, REG_SZ, (LPBYTE)chConvertBufferValue, intMaxRegValueLength); + i++; + } + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + + +/* +* Add a new device +*/ +int TelldusSettings::addDevice(){ + + int intDeviceId = -1; + try{ + + DWORD dwDisp; + intDeviceId = getNextDeviceId(); + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + + if(RegCreateKeyEx(HKEY_CURRENT_USER, + strCompleteRegPath.c_str(), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hk, + &dwDisp)){ + //fail + throw exception("Create Key failed"); + } + + RegCloseKey(hk); + + } + catch(...){ + intDeviceId = -1; + } + return intDeviceId; +} + +/* +* Get next available device id +*/ +int TelldusSettings::getNextDeviceId(){ + + int intReturn = -1; + try{ + DWORD dwDisp; + long lnExists = RegCreateKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hk, + &dwDisp); //create or open if already created + + if(lnExists == ERROR_SUCCESS){ + + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + + + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + + if(lngStatus == ERROR_SUCCESS){ + + int intLast = (int)Buff[0]; + intReturn = intLast + 1; + } + else{ + intReturn = 1; + } + delete Buff; + + DWORD dwVal = intReturn; + + RegSetValueEx (hk, "LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + + } + RegCloseKey(hk); + } + catch(...){ + intReturn = -1; + } + return intReturn; +} + +/* +* Remove a device +*/ +bool TelldusSettings::removeDevice(int intDeviceId){ + + bool blnSuccess = true; + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + + long lngSuccess = RegDeleteKey(HKEY_CURRENT_USER, strCompleteRegPath.c_str()); + if(lngSuccess != ERROR_SUCCESS){ + blnSuccess = false; + } + } + catch(...){ + blnSuccess = false; + } + + return blnSuccess; +} + +//only for debug reasons +void TelldusSettings::debugLog(char* debugstring){ + ofstream debugfile("c:\\telldusdebug.txt", ios::app); + if(debugfile){ + debugfile << debugstring << endl; + debugfile.close(); + } +} + +//only for debug reasons +void TelldusSettings::debugLog(int debugint){ + ofstream debugfile("c:\\telldusdebug.txt", ios::app); + if(debugfile){ + debugfile << debugint << endl; + debugfile.close(); + } +} \ No newline at end of file diff --git a/driver/TellUsbD101/TelldusSettings.h b/driver/TellUsbD101/TelldusSettings.h new file mode 100644 index 00000000..65de9cc2 --- /dev/null +++ b/driver/TellUsbD101/TelldusSettings.h @@ -0,0 +1,42 @@ +#pragma once +#include "device.h" +#include "devicenexa.h" +#include +#include + +using namespace std; + +class TelldusSettings +{ +public: + TelldusSettings(void); + int getNumberOfDevices(void); + Device* getDevice(int intDeviceId); + Device* getDevice(int intDeviceId, int intDongleIndex); + char* getName(int intDeviceId); + bool setName(int intDeviceId, char* strNewName); + char* getVendor(int intDeviceId); + bool setVendor(int intDeviceId, char* strVendor); + char* getModel(int intDeviceId); + bool setModel(int intDeviceId, char* strModel); + int* getArguments(int intDeviceId); + bool setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments); + bool setArguments(int intDeviceId, vector vArguments); + int addDevice(); + int getDeviceId(int intDeviceIndex); + bool removeDevice(int intDeviceId); + void debugLog(char* debugstring); + void debugLog(int debugint); + int getNumberOfArguments(int intDeviceId); + + ~TelldusSettings(void); + +private: + int getNextDeviceId(); + + //variables + HKEY hk; + std::string strRegPathDevice; + std::string strRegPath; + int intMaxRegValueLength; +}; diff --git a/driver/TellUsbD101/linux/Device.cpp b/driver/TellUsbD101/linux/Device.cpp new file mode 100644 index 00000000..7aeff050 --- /dev/null +++ b/driver/TellUsbD101/linux/Device.cpp @@ -0,0 +1,85 @@ +#include "../Device.h" +#include +#include +#include + +/* +* Send message to the USB dongle +*/ +void Device::send(char* strMessage) { + int fd = -1; + struct termios tio; + + debugLog(strMessage); + + if( 0 > ( fd = open( "/dev/tellstick", O_RDWR ) ) ) { + return; + } + + /* adjust serial port parameters */ + bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ + tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ + tio.c_iflag = IGNPAR; + tio.c_oflag = 0; + tcflush(fd, TCIFLUSH); + tcsetattr(fd,TCSANOW,&tio); + + write(fd, strMessage, strlen(strMessage)); + + close(fd); +} + +/* +* Get the device index of the Telldus dongle (the first one if many are connected) +* -1 if no such device exists +*/ +int Device::getDongleIndex(){ + int intReturn = -1; +/* FT_HANDLE fthHandle = 0; + FT_STATUS ftStatus = FT_OK; + + try{ + DWORD dwNumberOfDevices = 0; + + ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); + if (ftStatus == FT_OK) { + for (int i = 0; i < (int)dwNumberOfDevices; i++) { + + FT_PROGRAM_DATA pData; + char ManufacturerBuf[32]; + char ManufacturerIdBuf[16]; + char DescriptionBuf[64]; + char SerialNumberBuf[16]; + + pData.Signature1 = 0x00000000; + pData.Signature2 = 0xffffffff; + pData.Version = 0x00000002; // EEPROM structure with FT232R extensions + pData.Manufacturer = ManufacturerBuf; + pData.ManufacturerId = ManufacturerIdBuf; + pData.Description = DescriptionBuf; + pData.SerialNumber = SerialNumberBuf; + + ftStatus = FT_Open(i, &fthHandle); + ftStatus = FT_EE_Read(fthHandle, &pData); + if(ftStatus == FT_OK){ + if(pData.VendorId == 6017 && pData.ProductId == 3120){ + intReturn = i; + ftStatus = FT_Close(fthHandle); + break; + } + } + ftStatus = FT_Close(fthHandle); + } + } + } + catch(...){ + throw; + }*/ + return intReturn; +} + +//only for debugging purpose +void Device::debugLog(char* debugstring){ + std::cout << debugstring << std::endl; +} + diff --git a/driver/TellUsbD101/stdafx.cpp b/driver/TellUsbD101/stdafx.cpp new file mode 100644 index 00000000..54385d7a --- /dev/null +++ b/driver/TellUsbD101/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// testruntelldus3.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/driver/TellUsbD101/stdafx.h b/driver/TellUsbD101/stdafx.h new file mode 100644 index 00000000..5df7bbe1 --- /dev/null +++ b/driver/TellUsbD101/stdafx.h @@ -0,0 +1,37 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include + +// C RunTime Header Files +#include +#include +#include +#include + + +// TODO: reference additional headers your program requires here diff --git a/driver/TellUsbD101/win/Device.cpp b/driver/TellUsbD101/win/Device.cpp new file mode 100644 index 00000000..ce5a065c --- /dev/null +++ b/driver/TellUsbD101/win/Device.cpp @@ -0,0 +1,91 @@ +#include "..\Device.h" +#include +#include +#include +#include +#include +#include "..\StdAfx.h" +#include "FTD2XX.H" + +/* +* Send message to the USB dongle +*/ +void Device::send(char* strMessage){ + + try{ + FT_STATUS ftStatus = FT_OK; + FT_HANDLE fthHandle = 0; + + ftStatus = FT_Open(this->intDongleIndex, &fthHandle); + int intBaudRate = 4800; //always 4800 + ftStatus = FT_SetBaudRate(fthHandle, intBaudRate); + ULONG bytesWritten; + + int intLen = (int)strlen(strMessage); + ftStatus = FT_Write(fthHandle, strMessage, intLen, &bytesWritten); + + ftStatus = FT_Close(fthHandle); + } + catch(...){ + throw; + } +} + +/* +* Get the device index of the Telldus dongle (the first one if many are connected) +* -1 if no such device exists +*/ +int Device::getDongleIndex(){ + int intReturn = -1; + FT_HANDLE fthHandle = 0; + FT_STATUS ftStatus = FT_OK; + + try{ + DWORD dwNumberOfDevices = 0; + + ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); + if (ftStatus == FT_OK) { + for (int i = 0; i < (int)dwNumberOfDevices; i++) { + + FT_PROGRAM_DATA pData; + char ManufacturerBuf[32]; + char ManufacturerIdBuf[16]; + char DescriptionBuf[64]; + char SerialNumberBuf[16]; + + pData.Signature1 = 0x00000000; + pData.Signature2 = 0xffffffff; + pData.Version = 0x00000002; // EEPROM structure with FT232R extensions + pData.Manufacturer = ManufacturerBuf; + pData.ManufacturerId = ManufacturerIdBuf; + pData.Description = DescriptionBuf; + pData.SerialNumber = SerialNumberBuf; + + ftStatus = FT_Open(i, &fthHandle); + ftStatus = FT_EE_Read(fthHandle, &pData); + if(ftStatus == FT_OK){ + if(pData.VendorId == 6017 && pData.ProductId == 3120){ + intReturn = i; + ftStatus = FT_Close(fthHandle); + break; + } + } + ftStatus = FT_Close(fthHandle); + } + } + } + catch(...){ + throw; + } + return intReturn; +} + +//only for debugging purpose +void Device::debugLog(char* debugstring){ + std::ofstream debugfile("c:\\telldusdebug.txt", std::ios::app); + if(debugfile){ + debugfile << debugstring << std::endl; + debugfile.close(); + } +} + diff --git a/driver/TellUsbD101/win/FTD2XX.H b/driver/TellUsbD101/win/FTD2XX.H new file mode 100644 index 00000000..2507326c --- /dev/null +++ b/driver/TellUsbD101/win/FTD2XX.H @@ -0,0 +1,875 @@ +/*++ + +Copyright (c) 2001-2005 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB device driver for FTDI FT8U232/245 + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + 23/01/04 awm Added support for open-by-location. + 16/03/04 awm Added support for FT2232C. + 23/09/04 awm Added support for FT232R. + 20/10/04 awm Added FT_CyclePort. + 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. + 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. + 25/08/05 awm Added FT_SetDeadmanTimeout. + 02/12/05 awm Removed obsolete references. + 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // FT2232C extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // FT232R extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + + UCHAR RIsVCP; // non-zero if using VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + From be464c4efc3e8d3b08f75cb28dc4bf7b8c160ecf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Feb 2008 13:23:28 +0000 Subject: [PATCH 0002/2215] Fixed 2 bug Returned correct id when adding a new device. Fixed crash if no device was found in devHasMethod(). --- driver/TellUsbD101/TellUsbD101.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index c51be172..c2945454 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -263,7 +263,7 @@ int __stdcall devAddDevice(){ int intNewDeviceId = -1; try{ TelldusSettings ts; - int intNewDeviceId = ts.addDevice(); + intNewDeviceId = ts.addDevice(); } catch(exception e){ intNewDeviceId = -1; @@ -292,7 +292,9 @@ bool __stdcall devHasMethod(int id, int methodname){ TelldusSettings ts; char* strModel = ts.getModel(id); Device* dev = ts.getDevice(id); - blnExists = dev->hasMethod(methodname, strModel); + if (dev != NULL) { + blnExists = dev->hasMethod(methodname, strModel); + } } catch(exception e){ blnExists = false; From 08c02530a6a4d60236532fd16fbb410d86899652 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Feb 2008 15:52:06 +0000 Subject: [PATCH 0003/2215] Removed function bool devHasMethod(int id, int method) and replaced with int devMethods(int id) --- driver/TellUsbD101/Device.cpp | 6 +++--- driver/TellUsbD101/Device.h | 2 +- driver/TellUsbD101/DeviceIkea.cpp | 8 +++----- driver/TellUsbD101/DeviceIkea.h | 2 +- driver/TellUsbD101/DeviceNexa.cpp | 12 ++++-------- driver/TellUsbD101/DeviceNexa.h | 2 +- driver/TellUsbD101/DeviceSartano.cpp | 17 ++--------------- driver/TellUsbD101/DeviceSartano.h | 2 +- driver/TellUsbD101/DeviceWaveman.cpp | 17 ++--------------- driver/TellUsbD101/DeviceWaveman.h | 2 +- driver/TellUsbD101/TellUsbD101.cpp | 10 +++++----- driver/TellUsbD101/TellUsbD101.def | 2 +- driver/TellUsbD101/TellUsbD101.h | 2 +- 13 files changed, 26 insertions(+), 58 deletions(-) diff --git a/driver/TellUsbD101/Device.cpp b/driver/TellUsbD101/Device.cpp index 3d6a6322..0281375a 100644 --- a/driver/TellUsbD101/Device.cpp +++ b/driver/TellUsbD101/Device.cpp @@ -45,8 +45,8 @@ void Device::dim(unsigned char level){ } /* -* Has Method, virtual +* Methods, virtual */ -bool Device::hasMethod(int methodname, char* strModel){ - return false; +int Device::methods(char* strModel){ + return 0; } diff --git a/driver/TellUsbD101/Device.h b/driver/TellUsbD101/Device.h index 4f4e5f1d..f4aec627 100644 --- a/driver/TellUsbD101/Device.h +++ b/driver/TellUsbD101/Device.h @@ -14,7 +14,7 @@ public: virtual void turnOff(void); virtual void bell(void); virtual void dim(unsigned char level); - virtual bool hasMethod(int methodname, char* strModel); + virtual int methods(char* strModel); static int getDongleIndex(); static void debugLog(char* debugstring); diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/driver/TellUsbD101/DeviceIkea.cpp index a32f00ff..c83f1a50 100644 --- a/driver/TellUsbD101/DeviceIkea.cpp +++ b/driver/TellUsbD101/DeviceIkea.cpp @@ -130,12 +130,10 @@ string DeviceIkea::getStringCode(unsigned char level){ /* * Has the device got the method? */ -bool DeviceIkea::hasMethod(int methodname, char* strModel){ +int DeviceIkea::methods(char* strModel){ if(strcmp(strModel, TELLSTICK_DEVICE_KOPPLA) == 0) { - if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF || methodname == TELLSTICK_DIM){ - return true; - } + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); } - return false; + return 0; } diff --git a/driver/TellUsbD101/DeviceIkea.h b/driver/TellUsbD101/DeviceIkea.h index bbe34c75..4a672653 100644 --- a/driver/TellUsbD101/DeviceIkea.h +++ b/driver/TellUsbD101/DeviceIkea.h @@ -9,7 +9,7 @@ public: virtual void turnOn(void); virtual void turnOff(void); virtual void dim(unsigned char level); - virtual bool hasMethod(int methodname, char* strModel); + virtual int methods(char* strModel); public: ~DeviceIkea(void); diff --git a/driver/TellUsbD101/DeviceNexa.cpp b/driver/TellUsbD101/DeviceNexa.cpp index 4deb98d7..97a194fc 100644 --- a/driver/TellUsbD101/DeviceNexa.cpp +++ b/driver/TellUsbD101/DeviceNexa.cpp @@ -132,7 +132,7 @@ string DeviceNexa::getStringCode(int intToConvert){ /* * Has the device got the method? */ -bool DeviceNexa::hasMethod(int methodname, char* strModel){ +int DeviceNexa::methods(char* strModel){ if( strcmp(strModel, TELLSTICK_DEVICE_YCR3500) == 0 || strcmp(strModel, TELLSTICK_DEVICE_YCR300D) == 0 || @@ -151,13 +151,9 @@ bool DeviceNexa::hasMethod(int methodname, char* strModel){ strcmp(strModel, TELLSTICK_DEVICE_EL2010) == 0 ) { - if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF){ - return true; - } + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } else if ( strcmp(strModel, TELLSTICK_DEVICE_ML7100) == 0 ) { - if(methodname == TELLSTICK_BELL) { - return true; - } + return TELLSTICK_BELL; } - return false; + return 0; } diff --git a/driver/TellUsbD101/DeviceNexa.h b/driver/TellUsbD101/DeviceNexa.h index 9ae10a72..abe8fa0d 100644 --- a/driver/TellUsbD101/DeviceNexa.h +++ b/driver/TellUsbD101/DeviceNexa.h @@ -9,7 +9,7 @@ public: virtual void turnOn(void); virtual void turnOff(void); virtual void bell(void); - virtual bool hasMethod(int methodname, char* strModel); + virtual int methods(char* strModel); public: ~DeviceNexa(void); diff --git a/driver/TellUsbD101/DeviceSartano.cpp b/driver/TellUsbD101/DeviceSartano.cpp index c06a7f0b..1f38a2dc 100644 --- a/driver/TellUsbD101/DeviceSartano.cpp +++ b/driver/TellUsbD101/DeviceSartano.cpp @@ -72,21 +72,8 @@ void DeviceSartano::turnOff(void){ /* * Has the device got the method? */ -bool DeviceSartano::hasMethod(int methodname, char* strModel){ - - bool blnExists = false; - - try{ -// if(strModel == "xxxx" || strModel == "yyyy"){ - if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF){ - blnExists = true; -// } - } - } - catch(...){ - throw; - } - return blnExists; +int DeviceSartano::methods(char* strModel){ + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } /* diff --git a/driver/TellUsbD101/DeviceSartano.h b/driver/TellUsbD101/DeviceSartano.h index 929cf32d..c7c86324 100644 --- a/driver/TellUsbD101/DeviceSartano.h +++ b/driver/TellUsbD101/DeviceSartano.h @@ -9,7 +9,7 @@ public: DeviceSartano(int intSystem, int intCode, int intDeviceIndex); virtual void turnOn(void); virtual void turnOff(void); - virtual bool hasMethod(int methodname, char* strModel); + virtual int methods(char* strModel); ~DeviceSartano(void); diff --git a/driver/TellUsbD101/DeviceWaveman.cpp b/driver/TellUsbD101/DeviceWaveman.cpp index dbbf3f69..855afe5c 100644 --- a/driver/TellUsbD101/DeviceWaveman.cpp +++ b/driver/TellUsbD101/DeviceWaveman.cpp @@ -40,19 +40,6 @@ void DeviceWaveman::turnOff(void){ /* * Has the device got the method? */ -bool DeviceWaveman::hasMethod(int methodname, char* strModel){ - - bool blnExists = false; - - try{ -// if(strModel == "xxxx" || strModel == "yyyy"){ - if(methodname == TELLSTICK_TURNON || methodname == TELLSTICK_TURNOFF){ - blnExists = true; -// } - } - } - catch(...){ - throw; - } - return blnExists; +int DeviceWaveman::methods(char* strModel){ + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } diff --git a/driver/TellUsbD101/DeviceWaveman.h b/driver/TellUsbD101/DeviceWaveman.h index ab013172..c099a563 100644 --- a/driver/TellUsbD101/DeviceWaveman.h +++ b/driver/TellUsbD101/DeviceWaveman.h @@ -7,5 +7,5 @@ class DeviceWaveman : public DeviceNexa public: DeviceWaveman(int intHouse, int intCode, int intDeviceIndex); virtual void turnOff(void); - virtual bool hasMethod(int methodname, char* strModel); + virtual int methods(char* strModel); }; diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index c2945454..abae47c4 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -285,22 +285,22 @@ bool __stdcall devRemoveDevice(int intDeviceId){ return blnSuccess; } -bool __stdcall devHasMethod(int id, int methodname){ +int __stdcall devMethods(int id){ - bool blnExists = false; + int intMethods = 0; try{ TelldusSettings ts; char* strModel = ts.getModel(id); Device* dev = ts.getDevice(id); if (dev != NULL) { - blnExists = dev->hasMethod(methodname, strModel); + intMethods = dev->methods(strModel); } } catch(exception e){ - blnExists = false; + intMethods = 0; handleException(e); } - return blnExists; + return intMethods; } diff --git a/driver/TellUsbD101/TellUsbD101.def b/driver/TellUsbD101/TellUsbD101.def index e79daad8..fc32ffca 100644 --- a/driver/TellUsbD101/TellUsbD101.def +++ b/driver/TellUsbD101/TellUsbD101.def @@ -17,7 +17,7 @@ EXPORTS devAddDevice @12 devRemoveDevice @13 - devHasMethod @14 + devMethods @14 devTurnOn @16 devTurnOff @17 devBell @18 diff --git a/driver/TellUsbD101/TellUsbD101.h b/driver/TellUsbD101/TellUsbD101.h index a5aeb6b8..8227ae1f 100644 --- a/driver/TellUsbD101/TellUsbD101.h +++ b/driver/TellUsbD101/TellUsbD101.h @@ -40,7 +40,7 @@ extern "C" { TELLSTICK_API int WINAPI devAddDeviceWithArguments(char* strVendor, int* intArguments[], int intNumberOfArguments); TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); TELLSTICK_API int WINAPI devGetDeviceId(int intDeviceIndex); - TELLSTICK_API bool WINAPI devHasMethod(int id, int methodname); + TELLSTICK_API int WINAPI devMethods(int id); } #define TELLSTICK_TURNON 1 From e794d406f2738e31e0c411d3a4060f97d98f7864 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Feb 2008 17:05:51 +0000 Subject: [PATCH 0004/2215] Imported project 'tellstickd' --- tellstickd/LICENSE | 674 ++++++++++++++++++++++++++++++ tellstickd/README | 46 ++ tellstickd/init_script/tellstickd | 85 ++++ tellstickd/tellstickd | 478 +++++++++++++++++++++ tellstickd/tellstickd.conf | 17 + 5 files changed, 1300 insertions(+) create mode 100644 tellstickd/LICENSE create mode 100644 tellstickd/README create mode 100755 tellstickd/init_script/tellstickd create mode 100755 tellstickd/tellstickd create mode 100644 tellstickd/tellstickd.conf diff --git a/tellstickd/LICENSE b/tellstickd/LICENSE new file mode 100644 index 00000000..8f829aec --- /dev/null +++ b/tellstickd/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/tellstickd/README b/tellstickd/README new file mode 100644 index 00000000..446a9753 --- /dev/null +++ b/tellstickd/README @@ -0,0 +1,46 @@ +General +================= +This software is intended for controlling remote switch devices with rfcmd. + +Dependencies +================= +For this script to run you need perl and the following perl-modules: +DateTime +DateTime::Event::Sunrise + + +Installation +================= +0. Install rfcmd and necessary perl modules (on a typical Fedora/Centos/RHEL with the necessary repos installed, this should do it for you: yum install perl-DateTime perl-DateTime-Event-Sunrise). +1. Copy the file tellstickd-version/tellstickd to /usr/local/bin/ +2. Copy the file tellstickd-version/tellstickd.conf to /etc/ +3. If you have a Redhat-type system (like RHEL, Centos or Fedora), copy the script found under tellstickd-version/init_script to /etc/rc.d/init.d, this way you can control the script as any other service, easily make it start at boot (with chkconfig --level 35 tellstickd on). +4. Remember to make the perl-script and init script executable. As root chmod 755 /usr/local/bin/tellstickd /etc/rc.d/init.d/tellstickd + +Configuration +================= +1. In the very top of the perl file /usr/local/bin/tellstickd: + a. Set appropriate coordinates and timezone to suit your geographical location (further information: http://search.cpan.org/dist/DateTime-Event-Sunrise/lib/DateTime/Event/Sunrise.pm). + b. Specifiy the rfcmd binary location. Default: /usr/local/bin/rfcmd + c. Specify the tellstick device name. Default: /dev/tellstick + d. If the default locations of the config and logfile not are according to your wishes, modify them here. Note 1: this can also be done with the tellstickd options --config and --logfile. Note 2: If you use the init script, these settings must be done in the init-script /etc/rc.d/init.d/tellstickd. +2. If you would like this script to start at boot-time, on a RHEL/Centos/Fedora system, execute the following command chkconfig --level 35 tellstickd on + + +Licensing +================= +This software is freely distributable under the GNU General Public License, +the full content of the license is included in the file LICENSE. +Feel free to improve the program. + +Revision history +================= +2008-02-10 0.1.3 Modified switch logic. When dawn is before on-time, lights are not switched on. If dusk time is after off time, lights are not switched on. +2008-01-30 0.1.2 Corrected a bug regarding datetimelocal. +2008-01-15 0.1.1 Fixed some bugs. Added logfile capability. +2008-01-11 0.1.0 Initial release + +Author +================= +Magnus Juntti +juntti@mail.com diff --git a/tellstickd/init_script/tellstickd b/tellstickd/init_script/tellstickd new file mode 100755 index 00000000..dec3248a --- /dev/null +++ b/tellstickd/init_script/tellstickd @@ -0,0 +1,85 @@ +#!/bin/bash +# +# Init file for tellstickd remote light switch daemon +# +# Written by Magnus Juntti +# +# chkconfig: 35 54 46 +# description: tellstickd remote light switch daemon +# +# processname: tellstickd +# config: /etc/tellstickd.conf +# pidfile: /var/run/tellstick + +source /etc/rc.d/init.d/functions + +EXECUTABLE="/usr/local/bin/tellstickd" +CONFIG_FILE="/etc/tellstickd.conf" +LOG_FILE="/var/log/tellstickd" +OPTIONS="" + +[ -x $EXECUTABLE ] || exit 1 +[ -r $CONFIG_FILE ] || exit 1 + +RETVAL=0 +prog="tellstickd" +desc="remote switch daemon" + +start() { + echo -n $"Starting $desc ($prog): " + daemon --user root $prog --daemon --config $CONFIG_FILE --logfile $LOG_FILE $OPTIONS + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog + return $RETVAL +} + +stop() { + echo -n $"Shutting down $desc ($prog): " + killproc $prog + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog + return $RETVAL +} + +restart() { + stop + start +} + +reload() { + echo -n $"Reloading $desc ($prog): " + killproc $prog -HUP + RETVAL=$? + echo + return $RETVAL +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + reload) + reload + ;; + condrestart) + [ -e /var/lock/subsys/$prog ] && restart + RETVAL=$? + ;; + status) + status $prog + RETVAL=$? + ;; + *) + echo $"Usage: $0 {start|stop|restart|reload|condrestart|status}" + RETVAL=1 +esac + +exit $RETVAL diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd new file mode 100755 index 00000000..69285bb7 --- /dev/null +++ b/tellstickd/tellstickd @@ -0,0 +1,478 @@ +#!/usr/bin/perl + +use DateTime; +use DateTime::Event::Sunrise; +use Time::Local; + +# The following variables should be adapted to your geographical location and system setup +$LATITUDE = "65.603"; # 65.603N 22.18W -> LuleÃ¥, Sweden +$LONGITUDE = "22.18"; +$TIMEZONE = "Europe/Stockholm"; +$RFCMD = "/usr/local/bin/rfcmd"; +$TELLSTICK_DEVICE = "/dev/tellstick"; +$CONFIG_FILE = "/etc/tellstickd.conf"; +$LOG_FILE = "/var/log/tellstickd"; + +# After this point you really shouldn't need to go +$AUTHOR = "Magnus Juntti, juntti\@mail.com"; +$PROGRAM_NAME = "tellstickd"; +$VERSION = "0.1.3"; + + +# Structure of the configurations to be read; +# $device_cfg[$i][0]; # Protocol, only NEXA and SARTANO supported so far by rfcmd +# $device_cfg[$i][1]; # Housecode A-P +# $device_cfg[$i][2]; # Channel 1-3 +# $device_cfg[$i][3]; # On time +# $device_cfg[$i][4]; # Off time +# $device_cfg[$i][5]; # Off when bright +# $device_cfg[$i][6]; # Off when bright delay +# $device_cfg[$i][7]; # Time in advance when getting dark +# $device_cfg[$i][20]; # Sunrise off time, calculated in this program and stored here +# $device_cfg[$i][21]; # Sunset on time, calculated in this program and stored here + +sub daemonize { + chdir '/' or die "$PROGRAM_NAME: Can't chdir to /: $!"; + open STDIN, '/dev/null' or die "$PROGRAM_NAME: Can't read /dev/null: $!"; + defined(my $pid = fork) or die "$PROGRAM_NAME: Can't fork: $!"; + exit if $pid; + setsid or die "$PROGRAM_NAME: Can't start a new session: $!"; + umask 0; +} + +sub get_sunrise_time +{ + ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); + $Year += 1900; + $Month++; + + my $dt = DateTime->new( year => $Year, month => $Month, day => $Day, time_zone => $TIMEZONE, ); + my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '0', iteration => '1'); + + $Month--; + + my $dt1 = $sunrise->sunrise_datetime($dt); + + ($sunrise_time) = $dt1->datetime =~ /T(.*)\:/; + + return $sunrise_time +} + +sub get_sunset_time +{ + ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); + $Year += 1900; + $Month++; + + my $dt = DateTime->new( year => $Year, month => $Month, day => $Day, time_zone => $TIMEZONE, ); + my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '0', iteration => '1'); + + $Month--; + + my $dt2 = $sunrise->sunset_datetime($dt); + + ($sunset_time) = $dt2->datetime =~ /T(.*)\:/; + + return $sunset_time; +} + +sub is_sun_up +{ + $sunrise_time = get_sunrise_time(); + $sunset_time = get_sunset_time(); + +# printf("sunrise: $sunrise_time\nsunset: $sunset_time\n"); + + my $curr_time = sprintf("%0d%02d", $Hour, $Minute); + $sunrise_time =~ s/://g; + $sunset_time =~ s/://g; + + #Remove leading zeroes. + $curr_time =~ s/^0*//; + $sunrise_time =~ s/^0*//; + $sunset_time =~ s/^0*//; + +# printf("curr_time = $curr_time, sunrise_time = $sunrise_time, sunset_time = $sunset_time\n"); + + if ($curr_time > $sunrise_time && $curr_time < $sunset_time) { + return $YES; + } + else { + return $NO; + } +} + +sub add_time +{ + my $time1 = $_[0]; + my $time2 = $_[1]; + + ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); + $Year += 1900; + + ($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/; + ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/; + + $time1_epoch_seconds = timelocal(0,$time1_minute,$time1_hour, $Day, $Month, $Year); + $time2_offset_seconds = 3600*$time2_hour + 60*$time2_minute; + + my $result_seconds = $time1_epoch_seconds + $time2_offset_seconds; + + ($min,$hour)= (localtime($result_seconds))[1,2]; + + return sprintf("%02d:%02d", $hour, $min); + +} + +sub subtract_time +{ + my $time1 = $_[0]; + my $time2 = $_[1]; + + ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); + $Year += 1900; + + ($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/; + ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/; + + $time1_epoch_seconds = timelocal(0,$time1_minute,$time1_hour, $Day, $Month, $Year); + $time2_offset_seconds = 3600*$time2_hour + 60*$time2_minute; + + my $result_seconds = $time1_epoch_seconds - $time2_offset_seconds; + + ($min,$hour)= (localtime($result_seconds))[1,2]; + + return sprintf("%02d:%02d", $hour, $min); + +} + +# Time format sanity check routine +sub is_time_format_correct +{ + my $time = $_[0]; + my $ok = $YES; + + my $number_of_matches = 0; + + my $tmp = $time; + while ($tmp =~ /\:/g) { + $number_of_matches++; + } + + if ($number_of_matches != 1) { + $ok = $NO; + } + + (my $hour, my $minute) = $time =~ /^(.*?)\:(.*?)$/; + + if ($hour !~ /^[0-9]+$/) { + $ok = $NO; + } + + if ($minute !~ /^[0-9]+$/) { + $ok = $NO; + } + + if ($hour < 0 || $hour > 23 || $minute < 0 || $minute > 59) { + $ok = $NO; + } + + + return $ok; +} + +sub read_config +{ + my $input_file = $_[0]; + + printf("$PROGRAM_NAME: Reading configuration file $conf_file...\n"); + + open(CFG_FILE, "<$input_file") or die "$PROGRAM_NAME: Could not access config file: $conf_file\n"; + + my $i = 0; + while ($_ = ) { + if ($_ !~ /^\#/ && $_ !~ /^\s/ && $_ !~ /^\n/) { + chomp($_); + @inrad = split /\s+/, $_; + $device_cfg[$i][0] = $inrad[0]; # Protocol + $device_cfg[$i][1] = $inrad[1]; # Housecode A-P + $device_cfg[$i][2] = $inrad[2]; # Channel 1-3 + $device_cfg[$i][3] = $inrad[3]; # On time + $device_cfg[$i][4] = $inrad[4]; # Off time + $device_cfg[$i][5] = $inrad[5]; # Off when bright + $device_cfg[$i][6] = $inrad[6]; # Off when bright delay + $device_cfg[$i][7] = $inrad[7]; # Time in advance when getting dark + + + # Some sanity checks + # If the turn on time is not to be used, this is marked with -1 + if ($device_cfg[$i][3] != -1) { + if (is_time_format_correct($device_cfg[$i][3]) == $NO) { + die("$PROGRAM_NAME: Format of turn on time for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + } + } + else { + printf("$PROGRAM_NAME: Noted configuration for device $device_cfg[$i][1]$device_cfg[$i][2] with no turn on time.\n"); + } + + # If the turn off time is not to be used, this is marked with -1 + if ($device_cfg[$i][4] != -1) { + if (is_time_format_correct($device_cfg[$i][4]) == $NO) { + die("$PROGRAM_NAME: Format of turn off time for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + } + } + else { + printf("$PROGRAM_NAME: Noted configuration for device $device_cfg[$i][1]$device_cfg[$i][2] with no turn off time.\n"); + } + + if (is_time_format_correct($device_cfg[$i][6]) == $NO) { + die("$PROGRAM_NAME: Format of turn off after sunrise for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + } + + if (is_time_format_correct($device_cfg[$i][7]) == $NO) { + die("$PROGRAM_NAME: Format of turn on before sunset for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + } + + + + printf("$PROGRAM_NAME: $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] config:\n"); + if ($device_cfg[$i][3] == -1) { + printf(" On time: N/A\n"); + } + else { + printf(" On time: $device_cfg[$i][3]\n"); + } + + if ($device_cfg[$i][4] == -1) { + printf(" Off time: N/A\n"); + } + else { + printf(" Off time: $device_cfg[$i][4]\n"); + } + + if ($device_cfg[$i][5] == $YES) { + printf(" Turned off daytime: yes\n"); + printf(" Off post sunrise: $device_cfg[$i][6]\n"); + printf(" On pre sunset: $device_cfg[$i][7]\n"); + } + else { + printf(" Turned off daytime: no\n"); + } + + $i++; + } + } + + return $i; + + close(CFG_FILE); +} + +sub usageprompt +{ + printf("This program is intended for control of Tellstick remote devices.\n"); + printf("Authour: $AUTHOR\n"); + printf("Version: %s\n", $VERSION); + + printf("\nUsage: %s [options]\n", $PROGRAM_NAME); + printf("\nOptions:\n"); + printf("-c, --config filename Searchpath to configuration file, if not given $CONFIG_FILE is assumed.\n"); + printf("-d, --daemon Run the program as a daemon and write a logfile.\n"); + printf("-h, --help Show this message and exit.\n"); + printf("-l, --logfile filename Redirect daemon logs to filename. Default $LOG_FILE\n"); +} + + +# ############## Main section ###################### + +@months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); +@weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun); +$NO = 0; +$YES = 1; +$conf_file = ""; +$make_daemon = $NO; +$output_to_logfile = $NO; + +$i = -1; +while ($i < $#ARGV) { + if ($i+1 <= $#ARGV) { + if ($ARGV[$i+1] =~ /^--config$/ || $ARGV[$i+1] =~ /^-c$/) { + $i++; + $conf_file = $ARGV[$i+1]; + } + elsif ($ARGV[$i+1] =~ /^-d$/ || $ARGV[$i+1] =~ /^--daemon$/) { + $output_to_logfile = $YES; + $make_daemon = $YES; + } + elsif ($ARGV[$i+1] =~ /^-h$/ || $ARGV[$i+1] =~ /^--help$/) { + usageprompt(); + exit; + } + elsif ($ARGV[$i+1] =~ /^-l$/ || $ARGV[$i+1] =~ /^--logfile$/) { + $output_to_logfile = $YES; + $i++; + $LOG_FILE = $ARGV[$i+1]; + } + else { + die("$PROGRAM_NAME: Unknown input argument: $ARGV[$i+1]\n"); + } + } + + $i++; +} + + +if ($output_to_logfile == $YES) { + open STDOUT, "> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; + open STDERR, ">> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; +} + +if ($make_daemon == $YES) { + &daemonize(); +} + +if (length($conf_file) < 1) { + $conf_file = $CONFIG_FILE; +} + +printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION...\n"); + +# Read the configuration file +$number_of_devices = read_config($conf_file); + +if ($number_of_devices < 1) { + die("$PROGRAM_NAME: Configuration file has no devices to control, exiting.\n"); +} +else { + printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n"); +} + +################################################################################################### +# Now to the eternal loop +my $first_loop = $YES; +while (1) { + # What is the current time + ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); + $year = 1900 + $yearOffset; + # $current_time = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year"; + $current_time = sprintf("%02d:%02d", $hour, $minute); + # printf("$PROGRAM_NAME: Time is $current_time\n"); + + ################################################################################################### + + # First, lets set the sunrise and sunset times for the devices that applies to, once a day, at 00:00. + if ($first_loop == $YES || $current_time eq "00:00") { + my $sunrise_time = get_sunrise_time(); + printf("$PROGRAM_NAME: Sunrise today is expected at $sunrise_time\n"); + + my $sunset_time = get_sunset_time(); + printf("$PROGRAM_NAME: Sunset today is expected at $sunset_time\n"); + + my $i = 0; + while($i < $number_of_devices) { + # If the device is supposed to be off daytime, the following applies + + # Sunrise time + requested offset + if ($device_cfg[$i][5] == $YES) { + $device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]); + printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); + } + + # Sunset time - requested offset + if ($device_cfg[$i][5] == $YES) { + $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); + printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); + } + + $i++; + } + } + + ################################################################################################### + + # Below the required actions are performed for each device + my $i = 0; + while($i < $number_of_devices) { + + + + # ON + # This is where we turn devices on depending on the state of the sun and the settings in daytime savings field $device_cfg[$i][5] + if ($device_cfg[$i][3] eq $current_time) { + # In case daytime turn off is activated, check if sun is up before turning on lamp + if ($device_cfg[$i][5] == $YES) { + if (is_sun_up() == $NO) { + printf("$PROGRAM_NAME: Time is $current_time and the sun is not yet up. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; + } + # This is where we end up when daytime saving is on and the sun is already up + else { + printf("$PROGRAM_NAME: Time is $current_time and the sun is up. $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] not turned on.\n"); + } + } + # If daytime turn off is not activated, always turn on the lamps on. + else { + printf("$PROGRAM_NAME: Time is $current_time. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; + } + } + + + + + + + + # DAWN / DUSK ACTIONS + # If on when bright feature is 1 (yes) then do the following (i.e. if lights are supposed to be turned off daytime) + if ($device_cfg[$i][5] == $YES) { + # Sunrise turn off + if ($device_cfg[$i][20] eq $current_time) { + printf("$PROGRAM_NAME: Time is $current_time. Turning off $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 0`; + } + + # Sunset turn on if the sunset turn on time is before the desired turn off time + if ($device_cfg[$i][21] eq $current_time) { + my $t_off = $device_cfg[$i][4]; + my $ss_on = $device_cfg[$i][21]; + $t_off =~ s/://g; + $ss_on =~ s/://g; + $t_off =~ s/^0*//; + $ss_on =~ s/^0*//; + + # If sunset on time is before the desired off time then turn the device on. + if ($ss_on < $t_off) { + printf("$PROGRAM_NAME: Time is $current_time. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; + } + # If the sunset on time is after the desired off time then do nothing + else { + printf("$PROGRAM_NAME: Time is $current_time. Not turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] since the desired turn off time is already passed.\n"); + } + } + } + + + + + + + # OFF + # This is where we turn devices off, we do this regardless of any other settings. + if ($device_cfg[$i][4] eq $current_time) { + printf("$PROGRAM_NAME: Time is $current_time. Turning off $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 0`; + } + + + + + + # Move on to next device + $i++; + } + + $first_loop = $NO; + sleep(60); # Wait a while until next round should be less than or equal to a minute, [seconds] +} diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf new file mode 100644 index 00000000..33736948 --- /dev/null +++ b/tellstickd/tellstickd.conf @@ -0,0 +1,17 @@ +# Configuration file for control of remote switches +# +# +# (no = 0, yes = 1) +# Multiple definitions are possible for each device +# +# Time format xx:yy where xx is hour and yy is minute +# If no turn on time or turn off time should be used. Note this with -1. See the example line below. Only to be used on turn on or turn off times. +# NEXA A 1 -1 22:45 1 00:30 00:30 + + +# Sample to control NEXA device A 1 +NEXA A 1 05:30 22:45 1 00:30 00:30 + + + + From c5f092fc723ff73e36bb44d2210c47df3eede419 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 11 Feb 2008 18:27:48 +0000 Subject: [PATCH 0005/2215] --- tellstickd/README | 1 + tellstickd/tellstickd | 177 +++++++++++++++++-------------------- tellstickd/tellstickd.conf | 11 +-- 3 files changed, 88 insertions(+), 101 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 446a9753..b1e3aa26 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Feel free to improve the program. Revision history ================= +2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs. 2008-02-10 0.1.3 Modified switch logic. When dawn is before on-time, lights are not switched on. If dusk time is after off time, lights are not switched on. 2008-01-30 0.1.2 Corrected a bug regarding datetimelocal. 2008-01-15 0.1.1 Fixed some bugs. Added logfile capability. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 69285bb7..aa0d3c71 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -16,7 +16,7 @@ $LOG_FILE = "/var/log/tellstickd"; # After this point you really shouldn't need to go $AUTHOR = "Magnus Juntti, juntti\@mail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.1.3"; +$VERSION = "0.1.4"; # Structure of the configurations to be read; @@ -25,11 +25,12 @@ $VERSION = "0.1.3"; # $device_cfg[$i][2]; # Channel 1-3 # $device_cfg[$i][3]; # On time # $device_cfg[$i][4]; # Off time -# $device_cfg[$i][5]; # Off when bright +# $device_cfg[$i][5]; # Off when bright, 0 = no, 1 = yes # $device_cfg[$i][6]; # Off when bright delay # $device_cfg[$i][7]; # Time in advance when getting dark # $device_cfg[$i][20]; # Sunrise off time, calculated in this program and stored here # $device_cfg[$i][21]; # Sunset on time, calculated in this program and stored here +# $device_cfg[$i][22]; # Switch state, 0 = off, 1 = on sub daemonize { chdir '/' or die "$PROGRAM_NAME: Can't chdir to /: $!"; @@ -76,30 +77,67 @@ sub get_sunset_time return $sunset_time; } -sub is_sun_up +# Checks if $current_time is inbetween argument 1 ($time1) and argument 2 ($time2) +sub is_inbetween_times { - $sunrise_time = get_sunrise_time(); - $sunset_time = get_sunset_time(); + my $time1 = $_[0]; + my $time2 = $_[1]; -# printf("sunrise: $sunrise_time\nsunset: $sunset_time\n"); - - my $curr_time = sprintf("%0d%02d", $Hour, $Minute); - $sunrise_time =~ s/://g; - $sunset_time =~ s/://g; - - #Remove leading zeroes. + my $curr_time = $current_time; + $curr_time =~ s/://g; + $time1 =~ s/://g; + $time2 =~ s/://g; $curr_time =~ s/^0*//; $sunrise_time =~ s/^0*//; $sunset_time =~ s/^0*//; -# printf("curr_time = $curr_time, sunrise_time = $sunrise_time, sunset_time = $sunset_time\n"); + # If we pass midnight, the following has to be checked + if ($time2 <= $time1) { + $time2 += 2400; + } - if ($curr_time > $sunrise_time && $curr_time < $sunset_time) { + if ($curr_time >= $time1 && $curr_time <= $time2) { return $YES; } - else { - return $NO; + + return $NO; +} + + + +sub rfcmd_exec { + my $device_id = $_[0]; + my $action = $_[1]; + + + # Action = 1 means turn lamp on + if ($action == 1) { + # Only turn the device on if it is not already turned on to avoid flashing dimmers. + if ($device_cfg[$device_id][22] == 0) { + printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2] 1`; + $device_cfg[$device_id][22] = 1; + + return; + } + else { + return; + } } + elsif ($action == 0) { + if ($device_cfg[$device_id][22] == 1) { + printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); + `$RFCMD $TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2] 0`; + $device_cfg[$device_id][22] = 0; + + return; + } + else { + return; + } + } + + return; } sub add_time @@ -185,7 +223,7 @@ sub read_config { my $input_file = $_[0]; - printf("$PROGRAM_NAME: Reading configuration file $conf_file...\n"); + printf("$PROGRAM_NAME: Reading configuration file $conf_file\n"); open(CFG_FILE, "<$input_file") or die "$PROGRAM_NAME: Could not access config file: $conf_file\n"; @@ -202,6 +240,7 @@ sub read_config $device_cfg[$i][5] = $inrad[5]; # Off when bright $device_cfg[$i][6] = $inrad[6]; # Off when bright delay $device_cfg[$i][7] = $inrad[7]; # Time in advance when getting dark + $device_cfg[$i][22] = 1; # Initial state set to so that they will be switched of at startup # Some sanity checks @@ -335,7 +374,7 @@ if (length($conf_file) < 1) { $conf_file = $CONFIG_FILE; } -printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION...\n"); +printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION\n"); # Read the configuration file $number_of_devices = read_config($conf_file); @@ -360,7 +399,7 @@ while (1) { ################################################################################################### - # First, lets set the sunrise and sunset times for the devices that applies to, once a day, at 00:00. + # First, lets set the sunrise and sunset times for the devices that it applies to, once a day, at 00:00. if ($first_loop == $YES || $current_time eq "00:00") { my $sunrise_time = get_sunrise_time(); printf("$PROGRAM_NAME: Sunrise today is expected at $sunrise_time\n"); @@ -368,111 +407,57 @@ while (1) { my $sunset_time = get_sunset_time(); printf("$PROGRAM_NAME: Sunset today is expected at $sunset_time\n"); - my $i = 0; - while($i < $number_of_devices) { + for (my $i = 0; $i < $number_of_devices; $i++) { + # Initially all devices are switched off to get a known state + if ($first_loop == $YES) { + rfcmd_exec($i, 0); + } + + # If the device is supposed to be off daytime, the following applies # Sunrise time + requested offset if ($device_cfg[$i][5] == $YES) { $device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]); printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); - } - # Sunset time - requested offset - if ($device_cfg[$i][5] == $YES) { + # Sunset time - requested offset $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); } - - $i++; } } ################################################################################################### # Below the required actions are performed for each device - my $i = 0; - while($i < $number_of_devices) { + for ($i = 0; $i < $number_of_devices; $i++) { - - # ON - # This is where we turn devices on depending on the state of the sun and the settings in daytime savings field $device_cfg[$i][5] - if ($device_cfg[$i][3] eq $current_time) { - # In case daytime turn off is activated, check if sun is up before turning on lamp - if ($device_cfg[$i][5] == $YES) { - if (is_sun_up() == $NO) { - printf("$PROGRAM_NAME: Time is $current_time and the sun is not yet up. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; - } - # This is where we end up when daytime saving is on and the sun is already up - else { - printf("$PROGRAM_NAME: Time is $current_time and the sun is up. $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] not turned on.\n"); - } - } - # If daytime turn off is not activated, always turn on the lamps on. - else { - printf("$PROGRAM_NAME: Time is $current_time. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; - } - } - - - - - - - - # DAWN / DUSK ACTIONS - # If on when bright feature is 1 (yes) then do the following (i.e. if lights are supposed to be turned off daytime) + # First if we consider daytime off if ($device_cfg[$i][5] == $YES) { - # Sunrise turn off - if ($device_cfg[$i][20] eq $current_time) { - printf("$PROGRAM_NAME: Time is $current_time. Turning off $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 0`; + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4]) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21]) == $NO) { + rfcmd_exec($i, 1); } - - # Sunset turn on if the sunset turn on time is before the desired turn off time - if ($device_cfg[$i][21] eq $current_time) { - my $t_off = $device_cfg[$i][4]; - my $ss_on = $device_cfg[$i][21]; - $t_off =~ s/://g; - $ss_on =~ s/://g; - $t_off =~ s/^0*//; - $ss_on =~ s/^0*//; - - # If sunset on time is before the desired off time then turn the device on. - if ($ss_on < $t_off) { - printf("$PROGRAM_NAME: Time is $current_time. Turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 1`; - } - # If the sunset on time is after the desired off time then do nothing - else { - printf("$PROGRAM_NAME: Time is $current_time. Not turning on $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] since the desired turn off time is already passed.\n"); - } + else { + rfcmd_exec($i, 0); } } - - - - - # OFF - # This is where we turn devices off, we do this regardless of any other settings. - if ($device_cfg[$i][4] eq $current_time) { - printf("$PROGRAM_NAME: Time is $current_time. Turning off $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$i][0] $device_cfg[$i][1] $device_cfg[$i][2] 0`; + # Then if daytime off is not considered + else { + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4]) == $YES) { + rfcmd_exec($i, 1); + } + else { + rfcmd_exec($i, 0); + } } - - - - # Move on to next device - $i++; } $first_loop = $NO; - sleep(60); # Wait a while until next round should be less than or equal to a minute, [seconds] + sleep(60); # Wait a while until next round should be less than or equal to a minute [seconds]. } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 33736948..4bc079fa 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -1,16 +1,17 @@ # Configuration file for control of remote switches # -# +# # (no = 0, yes = 1) # Multiple definitions are possible for each device -# +# +# Setting and to the same means that the device will always be switched on +# # Time format xx:yy where xx is hour and yy is minute # If no turn on time or turn off time should be used. Note this with -1. See the example line below. Only to be used on turn on or turn off times. # NEXA A 1 -1 22:45 1 00:30 00:30 - -# Sample to control NEXA device A 1 -NEXA A 1 05:30 22:45 1 00:30 00:30 +# Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. +NEXA A 1 05:30 22:45 1 00:30 00:15 From 75cd57445aa97179d21f6e4243225f897108d4f0 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 11 Feb 2008 22:17:40 +0000 Subject: [PATCH 0006/2215] Added support for SARTANO. Cleaned the code. --- tellstickd/README | 1 + tellstickd/tellstickd | 30 ++++++++++++++++++++++-------- tellstickd/tellstickd.conf | 3 +++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index b1e3aa26..201a21e3 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Feel free to improve the program. Revision history ================= +2008-02-11 0.2.0 Added support for SARTANO devices. General code cleanups. 2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs. 2008-02-10 0.1.3 Modified switch logic. When dawn is before on-time, lights are not switched on. If dusk time is after off time, lights are not switched on. 2008-01-30 0.1.2 Corrected a bug regarding datetimelocal. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index aa0d3c71..b90c06d3 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -13,10 +13,10 @@ $TELLSTICK_DEVICE = "/dev/tellstick"; $CONFIG_FILE = "/etc/tellstickd.conf"; $LOG_FILE = "/var/log/tellstickd"; -# After this point you really shouldn't need to go +# You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, juntti\@mail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.1.4"; +$VERSION = "0.2.0"; # Structure of the configurations to be read; @@ -96,7 +96,7 @@ sub is_inbetween_times $time2 += 2400; } - if ($curr_time >= $time1 && $curr_time <= $time2) { + if ($curr_time >= $time1 && $curr_time < $time2) { return $YES; } @@ -109,13 +109,23 @@ sub rfcmd_exec { my $device_id = $_[0]; my $action = $_[1]; + if ($device_cfg[$device_id][0] eq "SARTANO") { + $RFCMD_OPTIONS = "$TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1]"; + } + elsif ($device_cfg[$device_id][0] eq "NEXA") { + $RFCMD_OPTIONS = "$TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2]"; + } + else { + die("$PROGRAM_NAME: Device $device_id has an unknown protocol. Only NEXA and SARTANO allowed.\n"); + } - # Action = 1 means turn lamp on + + # Action = 1 means turn device on, 0 turn device off if ($action == 1) { # Only turn the device on if it is not already turned on to avoid flashing dimmers. if ($device_cfg[$device_id][22] == 0) { printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2] 1`; + `$RFCMD $RFCMD_OPTIONS 1`; $device_cfg[$device_id][22] = 1; return; @@ -127,7 +137,7 @@ sub rfcmd_exec { elsif ($action == 0) { if ($device_cfg[$device_id][22] == 1) { printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); - `$RFCMD $TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2] 0`; + `$RFCMD $RFCMD_OPTIONS 0`; $device_cfg[$device_id][22] = 0; return; @@ -243,6 +253,10 @@ sub read_config $device_cfg[$i][22] = 1; # Initial state set to so that they will be switched of at startup + if ($device_cfg[$device_id][0] eq "SARTANO") { + $device_cfg[$i][2] = ""; + } + # Some sanity checks # If the turn on time is not to be used, this is marked with -1 if ($device_cfg[$i][3] != -1) { @@ -419,11 +433,11 @@ while (1) { # Sunrise time + requested offset if ($device_cfg[$i][5] == $YES) { $device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]); - printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); + printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); # Sunset time - requested offset $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); - printf("$PROGRAM_NAME: Device $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); + printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); } } } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 4bc079fa..7f596b11 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -9,6 +9,9 @@ # Time format xx:yy where xx is hour and yy is minute # If no turn on time or turn off time should be used. Note this with -1. See the example line below. Only to be used on turn on or turn off times. # NEXA A 1 -1 22:45 1 00:30 00:30 +# +# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning. +SARTANO 0000000000 0 05:30 22:45 1 00:30 00:15 # Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. NEXA A 1 05:30 22:45 1 00:30 00:15 From 7e66f1c05785b96c4e1070d2de76949f7943be7c Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 12 Feb 2008 17:34:31 +0000 Subject: [PATCH 0007/2215] 2008-02-12 0.2.1 Changed behaviour when program is called without argument . Now presents: Try "tellstickd --help" for more information. --- tellstickd/README | 1 + tellstickd/tellstickd | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/tellstickd/README b/tellstickd/README index 201a21e3..4982558a 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Feel free to improve the program. Revision history ================= +2008-02-12 0.2.1 Changed behaviour when program is called without argument. Now presents: Try "tellstickd --help" for more information. 2008-02-11 0.2.0 Added support for SARTANO devices. General code cleanups. 2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs. 2008-02-10 0.1.3 Modified switch logic. When dawn is before on-time, lights are not switched on. If dusk time is after off time, lights are not switched on. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index b90c06d3..7c689254 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -16,7 +16,7 @@ $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, juntti\@mail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.2.0"; +$VERSION = "0.2.1"; # Structure of the configurations to be read; @@ -374,6 +374,9 @@ while ($i < $#ARGV) { $i++; } +if ($#ARGV < 0) { + die "Try \"$PROGRAM_NAME --help\" for more information.\n"; +} if ($output_to_logfile == $YES) { open STDOUT, "> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; From 396ca1e72b006e6d1f4c81916ea3a7773c85ed25 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Wed, 13 Feb 2008 18:07:24 +0000 Subject: [PATCH 0008/2215] Changed mailaddress to mjuntti@gmail.com --- tellstickd/README | 2 +- tellstickd/tellstickd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 4982558a..d3aa3ace 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -46,4 +46,4 @@ Revision history Author ================= Magnus Juntti -juntti@mail.com +mjuntti@gmail.com diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 7c689254..f783c517 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -14,7 +14,7 @@ $CONFIG_FILE = "/etc/tellstickd.conf"; $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). -$AUTHOR = "Magnus Juntti, juntti\@mail.com"; +$AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; $VERSION = "0.2.1"; From 809659ea17bb2850ee8dd099128c3478fcd4144f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Feb 2008 10:53:09 +0000 Subject: [PATCH 0009/2215] Added project "Scheduler" --- scheduler/DeviceHandler/DeviceHandler.csproj | 47 + scheduler/DeviceHandler/Handler.cs | 176 + .../DeviceHandler/Properties/AssemblyInfo.cs | 35 + scheduler/DeviceScheduler/Alarm.ico | Bin 0 -> 120824 bytes .../DeviceScheduler/DataStorage.Designer.cs | 1115 +++++ scheduler/DeviceScheduler/DataStorage.xsc | 10 + scheduler/DeviceScheduler/DataStorage.xsd | 61 + scheduler/DeviceScheduler/DataStorage.xss | 26 + .../DeviceScheduler/DeviceScheduler.csproj | 242 + scheduler/DeviceScheduler/EncryptDecrypt.cs | 338 ++ .../DeviceScheduler/Languages/Localization.cs | 100 + .../Languages/WinFormStrings.en.resx | 144 + .../Languages/WinFormStrings.resx | 144 + .../Languages/WinFormStrings.sv.resx | 144 + scheduler/DeviceScheduler/Program.cs | 39 + .../Properties/AssemblyInfo.cs | 33 + .../DeviceScheduler/Properties/Resources.resx | 117 + .../Properties/Settings.settings | 7 + scheduler/DeviceScheduler/Tasks.cs | 10 + .../DeviceScheduler/frmAbout.Designer.cs | 184 + scheduler/DeviceScheduler/frmAbout.cs | 142 + scheduler/DeviceScheduler/frmAbout.en.resx | 942 ++++ scheduler/DeviceScheduler/frmAbout.resx | 1195 +++++ scheduler/DeviceScheduler/frmAbout.sv.resx | 897 ++++ .../frmAskSecurityPolicy.Designer.cs | 172 + .../DeviceScheduler/frmAskSecurityPolicy.cs | 54 + .../frmAskSecurityPolicy.en.resx | 222 + .../DeviceScheduler/frmAskSecurityPolicy.resx | 446 ++ .../frmAskSecurityPolicy.sv.resx | 189 + .../frmAskUsername.Designer.cs | 176 + scheduler/DeviceScheduler/frmAskUsername.cs | 50 + .../DeviceScheduler/frmAskUsername.en.resx | 230 + scheduler/DeviceScheduler/frmAskUsername.resx | 451 ++ .../DeviceScheduler/frmAskUsername.sv.resx | 206 + scheduler/DeviceScheduler/frmMain.Designer.cs | 679 +++ scheduler/DeviceScheduler/frmMain.cs | 396 ++ scheduler/DeviceScheduler/frmMain.en.resx | 3264 ++++++++++++++ scheduler/DeviceScheduler/frmMain.resx | 4001 +++++++++++++++++ scheduler/DeviceScheduler/frmMain.sv.resx | 3072 +++++++++++++ .../DeviceScheduler/frmSchedule.Designer.cs | 960 ++++ scheduler/DeviceScheduler/frmSchedule.cs | 480 ++ scheduler/DeviceScheduler/frmSchedule.en.resx | 451 ++ scheduler/DeviceScheduler/frmSchedule.resx | 1854 ++++++++ scheduler/DeviceScheduler/frmSchedule.sv.resx | 187 + .../frmScheduleAddDevice.Designer.cs | 156 + .../DeviceScheduler/frmScheduleAddDevice.cs | 70 + .../frmScheduleAddDevice.en.resx | 148 + .../DeviceScheduler/frmScheduleAddDevice.resx | 321 ++ .../frmSelectDevice.Designer.cs | 100 + scheduler/DeviceScheduler/frmSelectDevice.cs | 18 + .../DeviceScheduler/frmSelectDevice.resx | 120 + .../DeviceScheduler/frmSplash.Designer.cs | 99 + scheduler/DeviceScheduler/frmSplash.cs | 43 + scheduler/DeviceScheduler/frmSplash.resx | 900 ++++ .../DataStorage.Designer.cs | 1050 +++++ .../DeviceSchedulerAgent/DataStorage.xsc | 10 + .../DeviceSchedulerAgent/DataStorage.xsd | 55 + .../DeviceSchedulerAgent/DataStorage.xss | 26 + .../DeviceSchedulerAgent.csproj | 80 + .../DeviceSchedulerAgent/EncryptDecrypt.cs | 338 ++ scheduler/DeviceSchedulerAgent/Program.cs | 83 + .../Properties/AssemblyInfo.cs | 33 + scheduler/DeviceSchedulerAgent/clock_run.ico | Bin 0 -> 26694 bytes .../DeviceSchedulerAgent/security_agent.ico | Bin 0 -> 26694 bytes 64 files changed, 27338 insertions(+) create mode 100644 scheduler/DeviceHandler/DeviceHandler.csproj create mode 100644 scheduler/DeviceHandler/Handler.cs create mode 100644 scheduler/DeviceHandler/Properties/AssemblyInfo.cs create mode 100644 scheduler/DeviceScheduler/Alarm.ico create mode 100644 scheduler/DeviceScheduler/DataStorage.Designer.cs create mode 100644 scheduler/DeviceScheduler/DataStorage.xsc create mode 100644 scheduler/DeviceScheduler/DataStorage.xsd create mode 100644 scheduler/DeviceScheduler/DataStorage.xss create mode 100644 scheduler/DeviceScheduler/DeviceScheduler.csproj create mode 100644 scheduler/DeviceScheduler/EncryptDecrypt.cs create mode 100644 scheduler/DeviceScheduler/Languages/Localization.cs create mode 100644 scheduler/DeviceScheduler/Languages/WinFormStrings.en.resx create mode 100644 scheduler/DeviceScheduler/Languages/WinFormStrings.resx create mode 100644 scheduler/DeviceScheduler/Languages/WinFormStrings.sv.resx create mode 100644 scheduler/DeviceScheduler/Program.cs create mode 100644 scheduler/DeviceScheduler/Properties/AssemblyInfo.cs create mode 100644 scheduler/DeviceScheduler/Properties/Resources.resx create mode 100644 scheduler/DeviceScheduler/Properties/Settings.settings create mode 100644 scheduler/DeviceScheduler/Tasks.cs create mode 100644 scheduler/DeviceScheduler/frmAbout.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmAbout.cs create mode 100644 scheduler/DeviceScheduler/frmAbout.en.resx create mode 100644 scheduler/DeviceScheduler/frmAbout.resx create mode 100644 scheduler/DeviceScheduler/frmAbout.sv.resx create mode 100644 scheduler/DeviceScheduler/frmAskSecurityPolicy.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmAskSecurityPolicy.cs create mode 100644 scheduler/DeviceScheduler/frmAskSecurityPolicy.en.resx create mode 100644 scheduler/DeviceScheduler/frmAskSecurityPolicy.resx create mode 100644 scheduler/DeviceScheduler/frmAskSecurityPolicy.sv.resx create mode 100644 scheduler/DeviceScheduler/frmAskUsername.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmAskUsername.cs create mode 100644 scheduler/DeviceScheduler/frmAskUsername.en.resx create mode 100644 scheduler/DeviceScheduler/frmAskUsername.resx create mode 100644 scheduler/DeviceScheduler/frmAskUsername.sv.resx create mode 100644 scheduler/DeviceScheduler/frmMain.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmMain.cs create mode 100644 scheduler/DeviceScheduler/frmMain.en.resx create mode 100644 scheduler/DeviceScheduler/frmMain.resx create mode 100644 scheduler/DeviceScheduler/frmMain.sv.resx create mode 100644 scheduler/DeviceScheduler/frmSchedule.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmSchedule.cs create mode 100644 scheduler/DeviceScheduler/frmSchedule.en.resx create mode 100644 scheduler/DeviceScheduler/frmSchedule.resx create mode 100644 scheduler/DeviceScheduler/frmSchedule.sv.resx create mode 100644 scheduler/DeviceScheduler/frmScheduleAddDevice.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmScheduleAddDevice.cs create mode 100644 scheduler/DeviceScheduler/frmScheduleAddDevice.en.resx create mode 100644 scheduler/DeviceScheduler/frmScheduleAddDevice.resx create mode 100644 scheduler/DeviceScheduler/frmSelectDevice.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmSelectDevice.cs create mode 100644 scheduler/DeviceScheduler/frmSelectDevice.resx create mode 100644 scheduler/DeviceScheduler/frmSplash.Designer.cs create mode 100644 scheduler/DeviceScheduler/frmSplash.cs create mode 100644 scheduler/DeviceScheduler/frmSplash.resx create mode 100644 scheduler/DeviceSchedulerAgent/DataStorage.Designer.cs create mode 100644 scheduler/DeviceSchedulerAgent/DataStorage.xsc create mode 100644 scheduler/DeviceSchedulerAgent/DataStorage.xsd create mode 100644 scheduler/DeviceSchedulerAgent/DataStorage.xss create mode 100644 scheduler/DeviceSchedulerAgent/DeviceSchedulerAgent.csproj create mode 100644 scheduler/DeviceSchedulerAgent/EncryptDecrypt.cs create mode 100644 scheduler/DeviceSchedulerAgent/Program.cs create mode 100644 scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs create mode 100644 scheduler/DeviceSchedulerAgent/clock_run.ico create mode 100644 scheduler/DeviceSchedulerAgent/security_agent.ico diff --git a/scheduler/DeviceHandler/DeviceHandler.csproj b/scheduler/DeviceHandler/DeviceHandler.csproj new file mode 100644 index 00000000..33c6a5e0 --- /dev/null +++ b/scheduler/DeviceHandler/DeviceHandler.csproj @@ -0,0 +1,47 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {292E034F-C3B8-4CED-87DD-479040094118} + Library + Properties + DeviceHandler + DeviceHandler + + + 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/scheduler/DeviceHandler/Handler.cs b/scheduler/DeviceHandler/Handler.cs new file mode 100644 index 00000000..3fc19abe --- /dev/null +++ b/scheduler/DeviceHandler/Handler.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +namespace DeviceHandler +{ + public class Handler + { + + + #region Unmanaged Code + [DllImport("TellUsbD101.dll")] + private static extern bool devTurnOn(int value); + + [DllImport("TellUsbD101.dll")] + private static extern bool devTurnOff(int value); + + [DllImport("TellUsbD101.dll")] + private static extern int devGetDeviceId(int value); + + [DllImport("TellUsbD101.dll")] + private static extern string devGetName(int value); + + [DllImport("TellUsbD101.dll")] + private static extern string devGetVendor(int value); + + [DllImport("TellUsbD101.dll")] + private static extern int devGetNumberOfDevices(); + #endregion + + private List m_Devices = new List(); + + public Device Find(int deviceID) + { + foreach (Device item in m_Devices) + { + if (item.ID == deviceID) + return item; + } + + return null; + } + + /// + /// Turns off a specific device. + /// + /// The item in question. + /// True if the command was successfull and false if not. + public bool TurnOff(Device item) + { + return devTurnOff(item.ID); + } + + public bool TurnOffWithDelay(Device item) + { + bool result = devTurnOff(item.ID); + System.Threading.Thread.Sleep(1000); + return result; + } + + /// + /// Turns on a specific device. + /// + /// The device in question. + /// True if the command was successfull. + public bool TurnOn(Device item) + { + return devTurnOn(item.ID); + } + + + public bool TurnOnWithDelay(Device item) + { + //Makesure that we halt for 1 second so that the Telldus stick have time to send the signal. + bool result = devTurnOn(item.ID); + System.Threading.Thread.Sleep(1000); + return result; + } + + /// + /// Loads all known devices into a collection. + /// + /// True if the process was successfull. + public bool Load() + { + try + { + m_Devices.Clear(); + + int count = devGetNumberOfDevices() - 1; + for (int i = 0; i <= count; i++) + { + //Collect information from the driver. + int deviceID = devGetDeviceId(i); + string deviceName = devGetName(deviceID); + string deviceVendor = devGetVendor(deviceID); + + m_Devices.Add(new Device(deviceID, deviceName, deviceVendor)); + } + + return true; + } + catch + { + return false; + } + } + + public List Devices + { + get + { + if (m_Devices.Count == 0) + Load(); + + return m_Devices; + + } + set { m_Devices = value; } + } + } + + [Serializable] + public class Device:ISerializable + { + private int m_ID = -1; + private string m_Name = ""; + private string m_Vendor = ""; + + public Device(SerializationInfo info,StreamingContext cntx) + { + + } + + public Device(int id, string name,string vendor) + { + m_ID = id; + m_Name = name; + m_Vendor = vendor; + } + + public int ID + { + get { return m_ID; } + set { m_ID = value; } + } + + public string Name + { + get { return m_Name; } + set { m_Name = value; } + } + + public string Vendor + { + get { return m_Vendor; } + set { m_Vendor = value; } + } + + public override string ToString() + { + return m_Name; + } + + #region ISerializable Members + + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + } +} diff --git a/scheduler/DeviceHandler/Properties/AssemblyInfo.cs b/scheduler/DeviceHandler/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..627588c0 --- /dev/null +++ b/scheduler/DeviceHandler/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +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("DeviceHandler")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Telldus Technologies")] +[assembly: AssemblyProduct("DeviceHandler")] +[assembly: AssemblyCopyright("Copyright © Telldus Technologies 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("f38b6a0f-16f2-4be8-9e86-8706f5335778")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("2007.1.*")] +[assembly: AssemblyFileVersion("2007.1.*")] diff --git a/scheduler/DeviceScheduler/Alarm.ico b/scheduler/DeviceScheduler/Alarm.ico new file mode 100644 index 0000000000000000000000000000000000000000..2bfa140561222ab79e16172f1b97d9543494b948 GIT binary patch literal 120824 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%0D8y=;y+se3)w@qk*y%ZFn|oe%{__#_)C6` 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 +// This code was generated by a tool. +// Runtime Version:2.0.50727.312 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 + +namespace DeviceScheduler { + using System; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [Serializable()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.ComponentModel.ToolboxItem(true)] + [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedDataSetSchema")] + [System.Xml.Serialization.XmlRootAttribute("DataStorage")] + [System.ComponentModel.Design.HelpKeywordAttribute("vs.data.DataSet")] + public partial class DataStorage : System.Data.DataSet { + + private JobDataTable tableJob; + + private JobActionsDataTable tableJobActions; + + private System.Data.DataRelation relationJob_JobActions; + + private System.Data.SchemaSerializationMode _schemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public DataStorage() { + this.BeginInit(); + this.InitClass(); + System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + base.Tables.CollectionChanged += schemaChangedHandler; + base.Relations.CollectionChanged += schemaChangedHandler; + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected DataStorage(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context, false) { + if ((this.IsBinarySerialized(info, context) == true)) { + this.InitVars(false); + System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler1 = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + this.Tables.CollectionChanged += schemaChangedHandler1; + this.Relations.CollectionChanged += schemaChangedHandler1; + return; + } + string strSchema = ((string)(info.GetValue("XmlSchema", typeof(string)))); + if ((this.DetermineSchemaSerializationMode(info, context) == System.Data.SchemaSerializationMode.IncludeSchema)) { + System.Data.DataSet ds = new System.Data.DataSet(); + ds.ReadXmlSchema(new System.Xml.XmlTextReader(new System.IO.StringReader(strSchema))); + if ((ds.Tables["Job"] != null)) { + base.Tables.Add(new JobDataTable(ds.Tables["Job"])); + } + if ((ds.Tables["JobActions"] != null)) { + base.Tables.Add(new JobActionsDataTable(ds.Tables["JobActions"])); + } + this.DataSetName = ds.DataSetName; + this.Prefix = ds.Prefix; + this.Namespace = ds.Namespace; + this.Locale = ds.Locale; + this.CaseSensitive = ds.CaseSensitive; + this.EnforceConstraints = ds.EnforceConstraints; + this.Merge(ds, false, System.Data.MissingSchemaAction.Add); + this.InitVars(); + } + else { + this.ReadXmlSchema(new System.Xml.XmlTextReader(new System.IO.StringReader(strSchema))); + } + this.GetSerializationData(info, context); + System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + base.Tables.CollectionChanged += schemaChangedHandler; + this.Relations.CollectionChanged += schemaChangedHandler; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)] + public JobDataTable Job { + get { + return this.tableJob; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)] + public JobActionsDataTable JobActions { + get { + return this.tableJobActions; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.BrowsableAttribute(true)] + [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Visible)] + public override System.Data.SchemaSerializationMode SchemaSerializationMode { + get { + return this._schemaSerializationMode; + } + set { + this._schemaSerializationMode = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new System.Data.DataTableCollection Tables { + get { + return base.Tables; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new System.Data.DataRelationCollection Relations { + get { + return base.Relations; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void InitializeDerivedDataSet() { + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override System.Data.DataSet Clone() { + DataStorage cln = ((DataStorage)(base.Clone())); + cln.InitVars(); + cln.SchemaSerializationMode = this.SchemaSerializationMode; + return cln; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override bool ShouldSerializeTables() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override bool ShouldSerializeRelations() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void ReadXmlSerializable(System.Xml.XmlReader reader) { + if ((this.DetermineSchemaSerializationMode(reader) == System.Data.SchemaSerializationMode.IncludeSchema)) { + this.Reset(); + System.Data.DataSet ds = new System.Data.DataSet(); + ds.ReadXml(reader); + if ((ds.Tables["Job"] != null)) { + base.Tables.Add(new JobDataTable(ds.Tables["Job"])); + } + if ((ds.Tables["JobActions"] != null)) { + base.Tables.Add(new JobActionsDataTable(ds.Tables["JobActions"])); + } + this.DataSetName = ds.DataSetName; + this.Prefix = ds.Prefix; + this.Namespace = ds.Namespace; + this.Locale = ds.Locale; + this.CaseSensitive = ds.CaseSensitive; + this.EnforceConstraints = ds.EnforceConstraints; + this.Merge(ds, false, System.Data.MissingSchemaAction.Add); + this.InitVars(); + } + else { + this.ReadXml(reader); + this.InitVars(); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Xml.Schema.XmlSchema GetSchemaSerializable() { + System.IO.MemoryStream stream = new System.IO.MemoryStream(); + this.WriteXmlSchema(new System.Xml.XmlTextWriter(stream, null)); + stream.Position = 0; + return System.Xml.Schema.XmlSchema.Read(new System.Xml.XmlTextReader(stream), null); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.InitVars(true); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars(bool initTable) { + this.tableJob = ((JobDataTable)(base.Tables["Job"])); + if ((initTable == true)) { + if ((this.tableJob != null)) { + this.tableJob.InitVars(); + } + } + this.tableJobActions = ((JobActionsDataTable)(base.Tables["JobActions"])); + if ((initTable == true)) { + if ((this.tableJobActions != null)) { + this.tableJobActions.InitVars(); + } + } + this.relationJob_JobActions = this.Relations["Job_JobActions"]; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.DataSetName = "DataStorage"; + this.Prefix = ""; + this.Namespace = "http://tempuri.org/DataStorage.xsd"; + this.EnforceConstraints = true; + this.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; + this.tableJob = new JobDataTable(); + base.Tables.Add(this.tableJob); + this.tableJobActions = new JobActionsDataTable(); + base.Tables.Add(this.tableJobActions); + this.relationJob_JobActions = new System.Data.DataRelation("Job_JobActions", new System.Data.DataColumn[] { + this.tableJob.IDColumn}, new System.Data.DataColumn[] { + this.tableJobActions.JobIDColumn}, false); + this.Relations.Add(this.relationJob_JobActions); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private bool ShouldSerializeJob() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private bool ShouldSerializeJobActions() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void SchemaChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e) { + if ((e.Action == System.ComponentModel.CollectionChangeAction.Remove)) { + this.InitVars(); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static System.Xml.Schema.XmlSchemaComplexType GetTypedDataSetSchema(System.Xml.Schema.XmlSchemaSet xs) { + DataStorage ds = new DataStorage(); + System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); + System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + xs.Add(ds.GetSchemaSerializable()); + System.Xml.Schema.XmlSchemaAny any = new System.Xml.Schema.XmlSchemaAny(); + any.Namespace = ds.Namespace; + sequence.Items.Add(any); + type.Particle = sequence; + return type; + } + + public delegate void JobRowChangeEventHandler(object sender, JobRowChangeEvent e); + + public delegate void JobActionsRowChangeEventHandler(object sender, JobActionsRowChangeEvent e); + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [System.Serializable()] + [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] + public partial class JobDataTable : System.Data.DataTable, System.Collections.IEnumerable { + + private System.Data.DataColumn columnID; + + private System.Data.DataColumn columnName; + + private System.Data.DataColumn columnDescription; + + private System.Data.DataColumn columnJobName; + + private System.Data.DataColumn columnUsername; + + private System.Data.DataColumn columnPassword; + + private System.Data.DataColumn columnStartTime; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobDataTable() { + this.TableName = "Job"; + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobDataTable(System.Data.DataTable table) { + this.TableName = table.TableName; + if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { + this.CaseSensitive = table.CaseSensitive; + } + if ((table.Locale.ToString() != table.DataSet.Locale.ToString())) { + this.Locale = table.Locale; + } + if ((table.Namespace != table.DataSet.Namespace)) { + this.Namespace = table.Namespace; + } + this.Prefix = table.Prefix; + this.MinimumCapacity = table.MinimumCapacity; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected JobDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + this.InitVars(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn IDColumn { + get { + return this.columnID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn NameColumn { + get { + return this.columnName; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn DescriptionColumn { + get { + return this.columnDescription; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn JobNameColumn { + get { + return this.columnJobName; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn UsernameColumn { + get { + return this.columnUsername; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn PasswordColumn { + get { + return this.columnPassword; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn StartTimeColumn { + get { + return this.columnStartTime; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + public int Count { + get { + return this.Rows.Count; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow this[int index] { + get { + return ((JobRow)(this.Rows[index])); + } + } + + public event JobRowChangeEventHandler JobRowChanging; + + public event JobRowChangeEventHandler JobRowChanged; + + public event JobRowChangeEventHandler JobRowDeleting; + + public event JobRowChangeEventHandler JobRowDeleted; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void AddJobRow(JobRow row) { + this.Rows.Add(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow AddJobRow(string Name, string Description, string JobName, string Username, string Password, string StartTime) { + JobRow rowJobRow = ((JobRow)(this.NewRow())); + rowJobRow.ItemArray = new object[] { + null, + Name, + Description, + JobName, + Username, + Password, + StartTime}; + this.Rows.Add(rowJobRow); + return rowJobRow; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow FindByID(int ID) { + return ((JobRow)(this.Rows.Find(new object[] { + ID}))); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public virtual System.Collections.IEnumerator GetEnumerator() { + return this.Rows.GetEnumerator(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override System.Data.DataTable Clone() { + JobDataTable cln = ((JobDataTable)(base.Clone())); + cln.InitVars(); + return cln; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataTable CreateInstance() { + return new JobDataTable(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.columnID = base.Columns["ID"]; + this.columnName = base.Columns["Name"]; + this.columnDescription = base.Columns["Description"]; + this.columnJobName = base.Columns["JobName"]; + this.columnUsername = base.Columns["Username"]; + this.columnPassword = base.Columns["Password"]; + this.columnStartTime = base.Columns["StartTime"]; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.columnID = new System.Data.DataColumn("ID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnID); + this.columnName = new System.Data.DataColumn("Name", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnName); + this.columnDescription = new System.Data.DataColumn("Description", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnDescription); + this.columnJobName = new System.Data.DataColumn("JobName", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnJobName); + this.columnUsername = new System.Data.DataColumn("Username", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnUsername); + this.columnPassword = new System.Data.DataColumn("Password", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnPassword); + this.columnStartTime = new System.Data.DataColumn("StartTime", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnStartTime); + this.Constraints.Add(new System.Data.UniqueConstraint("Constraint1", new System.Data.DataColumn[] { + this.columnID}, true)); + this.Constraints.Add(new System.Data.UniqueConstraint("Constraint2", new System.Data.DataColumn[] { + this.columnName}, false)); + this.columnID.AutoIncrement = true; + this.columnID.AutoIncrementSeed = 1; + this.columnID.AllowDBNull = false; + this.columnID.Unique = true; + this.columnName.AllowDBNull = false; + this.columnName.Unique = true; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow NewJobRow() { + return ((JobRow)(this.NewRow())); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataRow NewRowFromBuilder(System.Data.DataRowBuilder builder) { + return new JobRow(builder); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Type GetRowType() { + return typeof(JobRow); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanged(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanged(e); + if ((this.JobRowChanged != null)) { + this.JobRowChanged(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanging(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanging(e); + if ((this.JobRowChanging != null)) { + this.JobRowChanging(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleted(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleted(e); + if ((this.JobRowDeleted != null)) { + this.JobRowDeleted(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleting(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleting(e); + if ((this.JobRowDeleting != null)) { + this.JobRowDeleting(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void RemoveJobRow(JobRow row) { + this.Rows.Remove(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(System.Xml.Schema.XmlSchemaSet xs) { + System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); + System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + DataStorage ds = new DataStorage(); + xs.Add(ds.GetSchemaSerializable()); + System.Xml.Schema.XmlSchemaAny any1 = new System.Xml.Schema.XmlSchemaAny(); + any1.Namespace = "http://www.w3.org/2001/XMLSchema"; + any1.MinOccurs = new decimal(0); + any1.MaxOccurs = decimal.MaxValue; + any1.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any1); + System.Xml.Schema.XmlSchemaAny any2 = new System.Xml.Schema.XmlSchemaAny(); + any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; + any2.MinOccurs = new decimal(1); + any2.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any2); + System.Xml.Schema.XmlSchemaAttribute attribute1 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute1.Name = "namespace"; + attribute1.FixedValue = ds.Namespace; + type.Attributes.Add(attribute1); + System.Xml.Schema.XmlSchemaAttribute attribute2 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute2.Name = "tableTypeName"; + attribute2.FixedValue = "JobDataTable"; + type.Attributes.Add(attribute2); + type.Particle = sequence; + return type; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [System.Serializable()] + [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] + public partial class JobActionsDataTable : System.Data.DataTable, System.Collections.IEnumerable { + + private System.Data.DataColumn columnID; + + private System.Data.DataColumn columnJobID; + + private System.Data.DataColumn columnDeviceID; + + private System.Data.DataColumn columnTurnOn; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsDataTable() { + this.TableName = "JobActions"; + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobActionsDataTable(System.Data.DataTable table) { + this.TableName = table.TableName; + if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { + this.CaseSensitive = table.CaseSensitive; + } + if ((table.Locale.ToString() != table.DataSet.Locale.ToString())) { + this.Locale = table.Locale; + } + if ((table.Namespace != table.DataSet.Namespace)) { + this.Namespace = table.Namespace; + } + this.Prefix = table.Prefix; + this.MinimumCapacity = table.MinimumCapacity; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected JobActionsDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + this.InitVars(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn IDColumn { + get { + return this.columnID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn JobIDColumn { + get { + return this.columnJobID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn DeviceIDColumn { + get { + return this.columnDeviceID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn TurnOnColumn { + get { + return this.columnTurnOn; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + public int Count { + get { + return this.Rows.Count; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow this[int index] { + get { + return ((JobActionsRow)(this.Rows[index])); + } + } + + public event JobActionsRowChangeEventHandler JobActionsRowChanging; + + public event JobActionsRowChangeEventHandler JobActionsRowChanged; + + public event JobActionsRowChangeEventHandler JobActionsRowDeleting; + + public event JobActionsRowChangeEventHandler JobActionsRowDeleted; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void AddJobActionsRow(JobActionsRow row) { + this.Rows.Add(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow AddJobActionsRow(JobRow parentJobRowByJob_JobActions, int DeviceID, bool TurnOn) { + JobActionsRow rowJobActionsRow = ((JobActionsRow)(this.NewRow())); + rowJobActionsRow.ItemArray = new object[] { + null, + parentJobRowByJob_JobActions[0], + DeviceID, + TurnOn}; + this.Rows.Add(rowJobActionsRow); + return rowJobActionsRow; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow FindByID(int ID) { + return ((JobActionsRow)(this.Rows.Find(new object[] { + ID}))); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public virtual System.Collections.IEnumerator GetEnumerator() { + return this.Rows.GetEnumerator(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override System.Data.DataTable Clone() { + JobActionsDataTable cln = ((JobActionsDataTable)(base.Clone())); + cln.InitVars(); + return cln; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataTable CreateInstance() { + return new JobActionsDataTable(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.columnID = base.Columns["ID"]; + this.columnJobID = base.Columns["JobID"]; + this.columnDeviceID = base.Columns["DeviceID"]; + this.columnTurnOn = base.Columns["TurnOn"]; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.columnID = new System.Data.DataColumn("ID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnID); + this.columnJobID = new System.Data.DataColumn("JobID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnJobID); + this.columnDeviceID = new System.Data.DataColumn("DeviceID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnDeviceID); + this.columnTurnOn = new System.Data.DataColumn("TurnOn", typeof(bool), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnTurnOn); + this.Constraints.Add(new System.Data.UniqueConstraint("JobActionsKey1", new System.Data.DataColumn[] { + this.columnID}, true)); + this.columnID.AutoIncrement = true; + this.columnID.AutoIncrementSeed = 1; + this.columnID.AllowDBNull = false; + this.columnID.Unique = true; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow NewJobActionsRow() { + return ((JobActionsRow)(this.NewRow())); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataRow NewRowFromBuilder(System.Data.DataRowBuilder builder) { + return new JobActionsRow(builder); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Type GetRowType() { + return typeof(JobActionsRow); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanged(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanged(e); + if ((this.JobActionsRowChanged != null)) { + this.JobActionsRowChanged(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanging(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanging(e); + if ((this.JobActionsRowChanging != null)) { + this.JobActionsRowChanging(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleted(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleted(e); + if ((this.JobActionsRowDeleted != null)) { + this.JobActionsRowDeleted(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleting(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleting(e); + if ((this.JobActionsRowDeleting != null)) { + this.JobActionsRowDeleting(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void RemoveJobActionsRow(JobActionsRow row) { + this.Rows.Remove(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(System.Xml.Schema.XmlSchemaSet xs) { + System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); + System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + DataStorage ds = new DataStorage(); + xs.Add(ds.GetSchemaSerializable()); + System.Xml.Schema.XmlSchemaAny any1 = new System.Xml.Schema.XmlSchemaAny(); + any1.Namespace = "http://www.w3.org/2001/XMLSchema"; + any1.MinOccurs = new decimal(0); + any1.MaxOccurs = decimal.MaxValue; + any1.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any1); + System.Xml.Schema.XmlSchemaAny any2 = new System.Xml.Schema.XmlSchemaAny(); + any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; + any2.MinOccurs = new decimal(1); + any2.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any2); + System.Xml.Schema.XmlSchemaAttribute attribute1 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute1.Name = "namespace"; + attribute1.FixedValue = ds.Namespace; + type.Attributes.Add(attribute1); + System.Xml.Schema.XmlSchemaAttribute attribute2 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute2.Name = "tableTypeName"; + attribute2.FixedValue = "JobActionsDataTable"; + type.Attributes.Add(attribute2); + type.Particle = sequence; + return type; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public partial class JobRow : System.Data.DataRow { + + private JobDataTable tableJob; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobRow(System.Data.DataRowBuilder rb) : + base(rb) { + this.tableJob = ((JobDataTable)(this.Table)); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int ID { + get { + return ((int)(this[this.tableJob.IDColumn])); + } + set { + this[this.tableJob.IDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string Name { + get { + return ((string)(this[this.tableJob.NameColumn])); + } + set { + this[this.tableJob.NameColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string Description { + get { + try { + return ((string)(this[this.tableJob.DescriptionColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'Description\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.DescriptionColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string JobName { + get { + try { + return ((string)(this[this.tableJob.JobNameColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'JobName\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.JobNameColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string Username { + get { + try { + return ((string)(this[this.tableJob.UsernameColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'Username\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.UsernameColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string Password { + get { + try { + return ((string)(this[this.tableJob.PasswordColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'Password\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.PasswordColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string StartTime { + get { + try { + return ((string)(this[this.tableJob.StartTimeColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'StartTime\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.StartTimeColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsDescriptionNull() { + return this.IsNull(this.tableJob.DescriptionColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetDescriptionNull() { + this[this.tableJob.DescriptionColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsJobNameNull() { + return this.IsNull(this.tableJob.JobNameColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetJobNameNull() { + this[this.tableJob.JobNameColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsUsernameNull() { + return this.IsNull(this.tableJob.UsernameColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetUsernameNull() { + this[this.tableJob.UsernameColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsPasswordNull() { + return this.IsNull(this.tableJob.PasswordColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetPasswordNull() { + this[this.tableJob.PasswordColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsStartTimeNull() { + return this.IsNull(this.tableJob.StartTimeColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetStartTimeNull() { + this[this.tableJob.StartTimeColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow[] GetJobActionsRows() { + return ((JobActionsRow[])(base.GetChildRows(this.Table.ChildRelations["Job_JobActions"]))); + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public partial class JobActionsRow : System.Data.DataRow { + + private JobActionsDataTable tableJobActions; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobActionsRow(System.Data.DataRowBuilder rb) : + base(rb) { + this.tableJobActions = ((JobActionsDataTable)(this.Table)); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int ID { + get { + return ((int)(this[this.tableJobActions.IDColumn])); + } + set { + this[this.tableJobActions.IDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int JobID { + get { + try { + return ((int)(this[this.tableJobActions.JobIDColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'JobID\' in table \'JobActions\' is DBNull.", e); + } + } + set { + this[this.tableJobActions.JobIDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int DeviceID { + get { + try { + return ((int)(this[this.tableJobActions.DeviceIDColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'DeviceID\' in table \'JobActions\' is DBNull.", e); + } + } + set { + this[this.tableJobActions.DeviceIDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool TurnOn { + get { + try { + return ((bool)(this[this.tableJobActions.TurnOnColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'TurnOn\' in table \'JobActions\' is DBNull.", e); + } + } + set { + this[this.tableJobActions.TurnOnColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow JobRow { + get { + return ((JobRow)(this.GetParentRow(this.Table.ParentRelations["Job_JobActions"]))); + } + set { + this.SetParentRow(value, this.Table.ParentRelations["Job_JobActions"]); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsJobIDNull() { + return this.IsNull(this.tableJobActions.JobIDColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetJobIDNull() { + this[this.tableJobActions.JobIDColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsDeviceIDNull() { + return this.IsNull(this.tableJobActions.DeviceIDColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetDeviceIDNull() { + this[this.tableJobActions.DeviceIDColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsTurnOnNull() { + return this.IsNull(this.tableJobActions.TurnOnColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetTurnOnNull() { + this[this.tableJobActions.TurnOnColumn] = System.Convert.DBNull; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public class JobRowChangeEvent : System.EventArgs { + + private JobRow eventRow; + + private System.Data.DataRowAction eventAction; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRowChangeEvent(JobRow row, System.Data.DataRowAction action) { + this.eventRow = row; + this.eventAction = action; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow Row { + get { + return this.eventRow; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataRowAction Action { + get { + return this.eventAction; + } + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public class JobActionsRowChangeEvent : System.EventArgs { + + private JobActionsRow eventRow; + + private System.Data.DataRowAction eventAction; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRowChangeEvent(JobActionsRow row, System.Data.DataRowAction action) { + this.eventRow = row; + this.eventAction = action; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow Row { + get { + return this.eventRow; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataRowAction Action { + get { + return this.eventAction; + } + } + } + } +} + +#pragma warning restore 1591 \ No newline at end of file diff --git a/scheduler/DeviceScheduler/DataStorage.xsc b/scheduler/DeviceScheduler/DataStorage.xsc new file mode 100644 index 00000000..8b7f66df --- /dev/null +++ b/scheduler/DeviceScheduler/DataStorage.xsc @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/DataStorage.xsd b/scheduler/DeviceScheduler/DataStorage.xsd new file mode 100644 index 00000000..574b2772 --- /dev/null +++ b/scheduler/DeviceScheduler/DataStorage.xsd @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/DataStorage.xss b/scheduler/DeviceScheduler/DataStorage.xss new file mode 100644 index 00000000..6ec95ad8 --- /dev/null +++ b/scheduler/DeviceScheduler/DataStorage.xss @@ -0,0 +1,26 @@ + + + + + + + + + + + + 304 + 129 + + + 390 + 129 + + + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/DeviceScheduler.csproj b/scheduler/DeviceScheduler/DeviceScheduler.csproj new file mode 100644 index 00000000..8aeffe49 --- /dev/null +++ b/scheduler/DeviceScheduler/DeviceScheduler.csproj @@ -0,0 +1,242 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {8B613D91-8906-4A60-BAF7-328DA437DF01} + WinExe + Properties + DeviceScheduler + DeviceScheduler + Alarm.ico + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + False + References\TaskScheduler.dll + + + + + True + True + DataStorage.xsd + + + + Form + + + frmAbout.cs + + + Form + + + frmAskSecurityPolicy.cs + + + Form + + + frmAskUsername.cs + + + Form + + + frmMain.cs + + + Form + + + frmSchedule.cs + + + Form + + + frmScheduleAddDevice.cs + + + Form + + + frmSelectDevice.cs + + + Form + + + frmSplash.cs + + + + + + Designer + frmAbout.cs + + + Designer + frmAskSecurityPolicy.cs + + + Designer + frmAskUsername.cs + + + Designer + frmMain.cs + + + Designer + frmMain.cs + + + Designer + frmMain.cs + + + Designer + frmSchedule.cs + + + Designer + frmScheduleAddDevice.cs + + + Designer + frmSelectDevice.cs + + + Designer + frmSplash.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + DataStorage.xsd + + + Designer + MSDataSetGenerator + DataStorage.Designer.cs + + + DataStorage.xsd + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + True + True + WinFormStrings.resx + + + + + {292E034F-C3B8-4CED-87DD-479040094118} + DeviceHandler + + + + + + Designer + frmAbout.cs + + + Designer + frmAbout.cs + + + Designer + frmAskSecurityPolicy.cs + + + Designer + frmAskSecurityPolicy.cs + + + Designer + frmAskUsername.cs + + + Designer + frmAskUsername.cs + + + Designer + frmSchedule.cs + + + Designer + frmSchedule.cs + + + Designer + frmScheduleAddDevice.cs + + + Designer + + + Designer + ResXFileCodeGenerator + WinFormStrings.Designer.cs + + + Designer + + + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/EncryptDecrypt.cs b/scheduler/DeviceScheduler/EncryptDecrypt.cs new file mode 100644 index 00000000..e10080e1 --- /dev/null +++ b/scheduler/DeviceScheduler/EncryptDecrypt.cs @@ -0,0 +1,338 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace DeviceScheduler +{ + /// + /// Summary description for EncryptDecrypt. + /// + public class EncryptDecrypt + { + public EncryptDecrypt() + { + // + // TODO: Add constructor logic here + // + } + + // Encrypt a byte array into a byte array using a key and an IV + public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV) + { + + // Create a MemoryStream that is going to accept the encrypted bytes + MemoryStream ms = new MemoryStream(); + + // Create a symmetric algorithm. + // We are going to use Rijndael because it is strong and available on all platforms. + // You can use other algorithms, to do so substitute the next line with something like + // TripleDES alg = TripleDES.Create(); + + Rijndael alg = Rijndael.Create(); + + // Now set the key and the IV. + // We need the IV (Initialization Vector) because the algorithm is operating in its default + // mode called CBC (Cipher Block Chaining). The IV is XORed with the first block (8 byte) + // of the data before it is encrypted, and then each encrypted block is XORed with the + // following block of plaintext. This is done to make encryption more secure. + // There is also a mode called ECB which does not need an IV, but it is much less secure. + + alg.Key = Key; + alg.IV = IV; + + // Create a CryptoStream through which we are going to be pumping our data. + // CryptoStreamMode.Write means that we are going to be writing data to the stream + // and the output will be written in the MemoryStream we have provided. + CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); + + // Write the data and make it do the encryption + cs.Write(clearData, 0, clearData.Length); + + // Close the crypto stream (or do FlushFinalBlock). + // This will tell it that we have done our encryption and there is no more data coming in, + // and it is now a good time to apply the padding and finalize the encryption process. + cs.Close(); + + + // Now get the encrypted data from the MemoryStream. + // Some people make a mistake of using GetBuffer() here, which is not the right way. + byte[] encryptedData = ms.ToArray(); + + return encryptedData; + + } + + + // + // + /// + /// Encrypt a string into a string using a password + /// Uses Encrypt(byte[], byte[], byte[]) + /// + /// The text to encrypt. + /// The password to use. + /// An encrypted string. + public static string Encrypt(string clearText, string Password) + { + + // First we need to turn the input string into a byte array. + byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText); + + // Then, we need to turn the password into Key and IV + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + + // Now get the key/IV and do the encryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16)); + + + // Now we need to turn the resulting byte array into a string. + // A common mistake would be to use an Encoding class for that. It does not work + // because not all byte values can be represented by characters. + // We are going to be using Base64 encoding that is designed exactly for what we are + // trying to do. + return Convert.ToBase64String(encryptedData); + + } + + + // Encrypt bytes into bytes using a password + // Uses Encrypt(byte[], byte[], byte[]) + public static byte[] Encrypt(byte[] clearData, string Password) + { + + // We need to turn the password into Key and IV. + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + // Now get the key/IV and do the encryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16)); + + } + + + // Encrypt a file into another file using a password + public static void Encrypt(string fileIn, string fileOut, string Password) + { + + // First we are going to open the file streams + FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read); + FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write); + + + // Then we are going to derive a Key and an IV from the Password and create an algorithm + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + Rijndael alg = Rijndael.Create(); + + alg.Key = pdb.GetBytes(32); + alg.IV = pdb.GetBytes(16); + + // Now create a crypto stream through which we are going to be pumping data. + // Our fileOut is going to be receiving the encrypted bytes. + CryptoStream cs = new CryptoStream(fsOut, alg.CreateEncryptor(), CryptoStreamMode.Write); + + // Now will will initialize a buffer and will be processing the input file in chunks. + // This is done to avoid reading the whole file (which can be huge) into memory. + + int bufferLen = 4096; + byte[] buffer = new byte[bufferLen]; + int bytesRead; + + do + { + + // read a chunk of data from the input file + bytesRead = fsIn.Read(buffer, 0, bufferLen); + + // encrypt it + cs.Write(buffer, 0, bytesRead); + + } while(bytesRead != 0); + + + // close everything + cs.Close(); // this will also close the unrelying fsOut stream + fsIn.Close(); + + } + + + // Decrypt a byte array into a byte array using a key and an IV + public static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV) + { + + // Create a MemoryStream that is going to accept the decrypted bytes + MemoryStream ms = new MemoryStream(); + + // Create a symmetric algorithm. + // We are going to use Rijndael because it is strong and available on all platforms. + // You can use other algorithms, to do so substitute the next line with something like + // TripleDES alg = TripleDES.Create(); + + Rijndael alg = Rijndael.Create(); + + // Now set the key and the IV. + // We need the IV (Initialization Vector) because the algorithm is operating in its default + // mode called CBC (Cipher Block Chaining). The IV is XORed with the first block (8 byte) + // of the data after it is decrypted, and then each decrypted block is XORed with the previous + // cipher block. This is done to make encryption more secure. + // There is also a mode called ECB which does not need an IV, but it is much less secure. + + alg.Key = Key; + alg.IV = IV; + + + // Create a CryptoStream through which we are going to be pumping our data. + // CryptoStreamMode.Write means that we are going to be writing data to the stream + // and the output will be written in the MemoryStream we have provided. + CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write); + + + // Write the data and make it do the decryption + cs.Write(cipherData, 0, cipherData.Length); + + // Close the crypto stream (or do FlushFinalBlock). + // This will tell it that we have done our decryption and there is no more data coming in, + // and it is now a good time to remove the padding and finalize the decryption process. + cs.Close(); + + // Now get the decrypted data from the MemoryStream. + // Some people make a mistake of using GetBuffer() here, which is not the right way. + byte[] decryptedData = ms.ToArray(); + + + return decryptedData; + + } + + + /// + /// Decrypt a string into a string using a password. + /// Uses Decrypt(byte[], byte[], byte[]) + /// + /// The text to decrypt. + /// The password to use. + /// A decrypted string. + public static string Decrypt(string cipherText, string Password) + { + + // First we need to turn the input string into a byte array. + // We presume that Base64 encoding was used + byte[] cipherBytes = Convert.FromBase64String(cipherText); + + // Then, we need to turn the password into Key and IV + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + + // Now get the key/IV and do the decryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16)); + + // Now we need to turn the resulting byte array into a string. + // A common mistake would be to use an Encoding class for that. It does not work + // because not all byte values can be represented by characters. + // We are going to be using Base64 encoding that is designed exactly for what we are + // trying to do. + return System.Text.Encoding.Unicode.GetString(decryptedData); + + } + + + // Decrypt bytes into bytes using a password + // Uses Decrypt(byte[], byte[], byte[]) + public static byte[] Decrypt(byte[] cipherData, string Password) + { + + // We need to turn the password into Key and IV. + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + // Now get the key/IV and do the Decryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + + return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16)); + + } + + + // Decrypt a file into another file using a password + public static void Decrypt(string fileIn, string fileOut, string Password) + { + // First we are going to open the file streams + FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read); + FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write); + + // Then we are going to derive a Key and an IV from the Password and create an algorithm + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + Rijndael alg = Rijndael.Create(); + + alg.Key = pdb.GetBytes(32); + alg.IV = pdb.GetBytes(16); + + + // Now create a crypto stream through which we are going to be pumping data. + // Our fileOut is going to be receiving the Decrypted bytes. + + CryptoStream cs = new CryptoStream(fsOut, alg.CreateDecryptor(), CryptoStreamMode.Write); + + // Now will will initialize a buffer and will be processing the input file in chunks. + // This is done to avoid reading the whole file (which can be huge) into memory. + + int bufferLen = 4096; + byte[] buffer = new byte[bufferLen]; + int bytesRead; + + + do + { + + // read a chunk of data from the input file + bytesRead = fsIn.Read(buffer, 0, bufferLen); + + // Decrypt it + cs.Write(buffer, 0, bytesRead); + + } while(bytesRead != 0); + + // close everything + cs.Close(); // this will also close the unrelying fsOut stream + fsIn.Close(); + + } + + + } +} diff --git a/scheduler/DeviceScheduler/Languages/Localization.cs b/scheduler/DeviceScheduler/Languages/Localization.cs new file mode 100644 index 00000000..c0ff26ca --- /dev/null +++ b/scheduler/DeviceScheduler/Languages/Localization.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; +using System.Data; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using System.Resources; +using System.Reflection; + +namespace DeviceScheduler +{ + public enum eLanguage + { + Swedish=1053, + English=1033 + } + + /// + /// This class handles all localization such as retrieving specific strings and changing standard locale. + /// + class Localization + { + private static ResourceManager m_Mngr = null; + private static Assembly m_Assembly = null; + private static eLanguage m_SelectedLanguage = eLanguage.English; + + public static Assembly Assembly + { + get { return m_Assembly; } + set { m_Assembly = value; } + } + + public static void GetSelectedLanguage() + { + + Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Telldus"); + + if (key != null) + { + + if (key.GetValue("Language") != null) + { + m_SelectedLanguage = (eLanguage)Enum.Parse(typeof(eLanguage), key.GetValue("Language").ToString()); + } + key.Close(); + } + + } + + private static ResourceManager ResMngr + { + get + { + if (m_Mngr == null) + m_Mngr = new ResourceManager("DeviceScheduler.Languages.WinFormStrings", m_Assembly); + + return m_Mngr; + } + } + + public static string GetString(string name) + { + try + { + + return ResMngr.GetString(name); + + } + catch (Exception ex) + { + return ""; + } + } + + + public static void ChangeLanguage() + { + ChangeLanguage(m_SelectedLanguage); + } + + public static void ChangeLanguage(eLanguage language) + { + m_SelectedLanguage = language; + + if (language == eLanguage.English) + { + System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-GB"); + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-GB");//en + } + else if (language == eLanguage.Swedish) + { + System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("sv-SE");//sv + System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("sv-SE"); + } + + } + + + } +} diff --git a/scheduler/DeviceScheduler/Languages/WinFormStrings.en.resx b/scheduler/DeviceScheduler/Languages/WinFormStrings.en.resx new file mode 100644 index 00000000..158318e5 --- /dev/null +++ b/scheduler/DeviceScheduler/Languages/WinFormStrings.en.resx @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + You have to name the schedule. + + + You have not selected any units. + + + lication failed to set accountinformation (such as username and password) on the current schedule. + + + An unhandeld error has occurred in the application. + + + Do you want to remove selected schedule? + + + Do you want to remove the selected unit from the list? + + + Off + + + On + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/Languages/WinFormStrings.resx b/scheduler/DeviceScheduler/Languages/WinFormStrings.resx new file mode 100644 index 00000000..d2f3f74c --- /dev/null +++ b/scheduler/DeviceScheduler/Languages/WinFormStrings.resx @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Du mÃ¥ste ge schemaläggningen ett namn. + + + Du har inte valt nÃ¥gra enheter. + + + Programmet misslyckades med att sätta kontouppgifter (användarnamn och lösenord) pÃ¥ schemaläggningen. + + + Ett ohanterat fel har uppstÃ¥tt i programmet. + + + Vill du ta bort markerad schemaläggning? + + + Vill du ta bort markerad enhet? + + + Av + + + PÃ¥ + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/Languages/WinFormStrings.sv.resx b/scheduler/DeviceScheduler/Languages/WinFormStrings.sv.resx new file mode 100644 index 00000000..d2f3f74c --- /dev/null +++ b/scheduler/DeviceScheduler/Languages/WinFormStrings.sv.resx @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Du mÃ¥ste ge schemaläggningen ett namn. + + + Du har inte valt nÃ¥gra enheter. + + + Programmet misslyckades med att sätta kontouppgifter (användarnamn och lösenord) pÃ¥ schemaläggningen. + + + Ett ohanterat fel har uppstÃ¥tt i programmet. + + + Vill du ta bort markerad schemaläggning? + + + Vill du ta bort markerad enhet? + + + Av + + + PÃ¥ + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/Program.cs b/scheduler/DeviceScheduler/Program.cs new file mode 100644 index 00000000..5efeb96c --- /dev/null +++ b/scheduler/DeviceScheduler/Program.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace DeviceScheduler +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new frmMain()); + } + private static DeviceHandler.Handler m_Handler = new DeviceHandler.Handler(); + + public static DeviceHandler.Handler DeviceHandler + { + get + { + if (m_Handler == null) + { + m_Handler = new DeviceHandler.Handler(); + + } + + return m_Handler; + } + set + { + m_Handler = value; + } + } + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/Properties/AssemblyInfo.cs b/scheduler/DeviceScheduler/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..f4779a0b --- /dev/null +++ b/scheduler/DeviceScheduler/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("DeviceScheduler")] +[assembly: AssemblyDescription("Program for scheduling Telldus devices.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Telldus Technologies")] +[assembly: AssemblyProduct("DeviceScheduler")] +[assembly: AssemblyCopyright("Copyright © Telldus Technologies 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("604d814a-5ace-4cf6-9212-f84cd90058f5")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("2007.1.*")] +[assembly: AssemblyFileVersion("2007.1.*")] diff --git a/scheduler/DeviceScheduler/Properties/Resources.resx b/scheduler/DeviceScheduler/Properties/Resources.resx new file mode 100644 index 00000000..ffecec85 --- /dev/null +++ b/scheduler/DeviceScheduler/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/scheduler/DeviceScheduler/Properties/Settings.settings b/scheduler/DeviceScheduler/Properties/Settings.settings new file mode 100644 index 00000000..abf36c5d --- /dev/null +++ b/scheduler/DeviceScheduler/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/scheduler/DeviceScheduler/Tasks.cs b/scheduler/DeviceScheduler/Tasks.cs new file mode 100644 index 00000000..ae545fc5 --- /dev/null +++ b/scheduler/DeviceScheduler/Tasks.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace DeviceScheduler +{ + class Tasks + { + } +} diff --git a/scheduler/DeviceScheduler/frmAbout.Designer.cs b/scheduler/DeviceScheduler/frmAbout.Designer.cs new file mode 100644 index 00000000..5f6862ce --- /dev/null +++ b/scheduler/DeviceScheduler/frmAbout.Designer.cs @@ -0,0 +1,184 @@ +namespace DeviceScheduler +{ + partial class frmAbout + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + 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() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmAbout)); + this.cmdClose = new System.Windows.Forms.Button(); + this.lnkInternet = new System.Windows.Forms.LinkLabel(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.lblVersion = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.label7 = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // cmdClose + // + this.cmdClose.AccessibleDescription = null; + this.cmdClose.AccessibleName = null; + resources.ApplyResources(this.cmdClose, "cmdClose"); + this.cmdClose.BackgroundImage = null; + this.cmdClose.Font = null; + this.cmdClose.Name = "cmdClose"; + this.cmdClose.UseVisualStyleBackColor = true; + this.cmdClose.Click += new System.EventHandler(this.cmdClose_Click); + // + // lnkInternet + // + this.lnkInternet.AccessibleDescription = null; + this.lnkInternet.AccessibleName = null; + resources.ApplyResources(this.lnkInternet, "lnkInternet"); + this.lnkInternet.BackColor = System.Drawing.Color.Transparent; + this.lnkInternet.Font = null; + this.lnkInternet.Name = "lnkInternet"; + this.lnkInternet.TabStop = true; + this.lnkInternet.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // label2 + // + this.label2.AccessibleDescription = null; + this.label2.AccessibleName = null; + resources.ApplyResources(this.label2, "label2"); + this.label2.BackColor = System.Drawing.Color.Transparent; + this.label2.Font = null; + this.label2.Name = "label2"; + // + // label3 + // + this.label3.AccessibleDescription = null; + this.label3.AccessibleName = null; + resources.ApplyResources(this.label3, "label3"); + this.label3.BackColor = System.Drawing.Color.Transparent; + this.label3.Font = null; + this.label3.Name = "label3"; + // + // label4 + // + this.label4.AccessibleDescription = null; + this.label4.AccessibleName = null; + resources.ApplyResources(this.label4, "label4"); + this.label4.BackColor = System.Drawing.Color.Transparent; + this.label4.Font = null; + this.label4.Name = "label4"; + // + // label5 + // + this.label5.AccessibleDescription = null; + this.label5.AccessibleName = null; + resources.ApplyResources(this.label5, "label5"); + this.label5.BackColor = System.Drawing.Color.Transparent; + this.label5.Font = null; + this.label5.Name = "label5"; + // + // lblVersion + // + this.lblVersion.AccessibleDescription = null; + this.lblVersion.AccessibleName = null; + resources.ApplyResources(this.lblVersion, "lblVersion"); + this.lblVersion.BackColor = System.Drawing.Color.Transparent; + this.lblVersion.Font = null; + this.lblVersion.Name = "lblVersion"; + // + // label6 + // + this.label6.AccessibleDescription = null; + this.label6.AccessibleName = null; + resources.ApplyResources(this.label6, "label6"); + this.label6.BackColor = System.Drawing.Color.Transparent; + this.label6.Font = null; + this.label6.Name = "label6"; + // + // linkLabel1 + // + this.linkLabel1.AccessibleDescription = null; + this.linkLabel1.AccessibleName = null; + resources.ApplyResources(this.linkLabel1, "linkLabel1"); + this.linkLabel1.BackColor = System.Drawing.Color.Transparent; + this.linkLabel1.Font = null; + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.TabStop = true; + this.linkLabel1.Tag = "http://www.vistaico.com/link_to_us.htm"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked_1); + // + // label7 + // + this.label7.AccessibleDescription = null; + this.label7.AccessibleName = null; + resources.ApplyResources(this.label7, "label7"); + this.label7.BackColor = System.Drawing.Color.Transparent; + this.label7.Font = null; + this.label7.Name = "label7"; + // + // frmAbout + // + this.AccessibleDescription = null; + this.AccessibleName = null; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.label7); + this.Controls.Add(this.linkLabel1); + this.Controls.Add(this.label6); + this.Controls.Add(this.lblVersion); + this.Controls.Add(this.label5); + this.Controls.Add(this.label4); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.lnkInternet); + this.Controls.Add(this.cmdClose); + this.Font = null; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = null; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmAbout"; + this.ShowIcon = false; + this.ShowInTaskbar = false; + this.Load += new System.EventHandler(this.frmAbout_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button cmdClose; + private System.Windows.Forms.LinkLabel lnkInternet; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label lblVersion; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Label label7; + + } +} diff --git a/scheduler/DeviceScheduler/frmAbout.cs b/scheduler/DeviceScheduler/frmAbout.cs new file mode 100644 index 00000000..266e58ce --- /dev/null +++ b/scheduler/DeviceScheduler/frmAbout.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; + +namespace DeviceScheduler +{ + partial class frmAbout : Form + { + public frmAbout() + { + Localization.ChangeLanguage(); + InitializeComponent(); + + // Initialize the AboutBox to display the product information from the assembly information. + // Change assembly information settings for your application through either: + // - Project->Properties->Application->Assembly Information + // - AssemblyInfo.cs + + this.lblVersion.Text = AssemblyVersion; + + + } + + #region Assembly Attribute Accessors + + public string AssemblyTitle + { + get + { + // Get all Title attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); + // If there is at least one Title attribute + if (attributes.Length > 0) + { + // Select the first one + AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; + // If it is not an empty string, return it + if (titleAttribute.Title != "") + return titleAttribute.Title; + } + // If there was no Title attribute, or if the Title attribute was the empty string, return the .exe name + return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); + } + } + + public string AssemblyVersion + { + get + { + return Assembly.GetExecutingAssembly().GetName().Version.ToString(); + } + } + + public string AssemblyDescription + { + get + { + // Get all Description attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); + // If there aren't any Description attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Description attribute, return its value + return ((AssemblyDescriptionAttribute)attributes[0]).Description; + } + } + + public string AssemblyProduct + { + get + { + // Get all Product attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); + // If there aren't any Product attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Product attribute, return its value + return ((AssemblyProductAttribute)attributes[0]).Product; + } + } + + public string AssemblyCopyright + { + get + { + // Get all Copyright attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); + // If there aren't any Copyright attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Copyright attribute, return its value + return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; + } + } + + public string AssemblyCompany + { + get + { + // Get all Company attributes on this assembly + object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); + // If there aren't any Company attributes, return an empty string + if (attributes.Length == 0) + return ""; + // If there is a Company attribute, return its value + return ((AssemblyCompanyAttribute)attributes[0]).Company; + } + } + #endregion + + private void cmdClose_Click(object sender, EventArgs e) + { + this.Close(); + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process proc = new System.Diagnostics.Process(); + + proc.StartInfo.FileName = lnkInternet.Text; + proc.StartInfo.UseShellExecute = true; + proc.Start(); + } + + private void linkLabel1_LinkClicked_1(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process proc = new System.Diagnostics.Process(); + + proc.StartInfo.FileName = linkLabel1.Tag.ToString(); + proc.StartInfo.UseShellExecute = true; + proc.Start(); + } + + private void frmAbout_Load(object sender, EventArgs e) + { + + } + } +} diff --git a/scheduler/DeviceScheduler/frmAbout.en.resx b/scheduler/DeviceScheduler/frmAbout.en.resx new file mode 100644 index 00000000..016f572d --- /dev/null +++ b/scheduler/DeviceScheduler/frmAbout.en.resx @@ -0,0 +1,942 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Close + + + + 294, 187 + + + 230, 26 + + + This software is developed by Mattias Dahlgren +for Telldus Technologies. + + + 197, 26 + + + © Copyright Telldus Technologies 2008. +All rights reserved. + + + 237, 187 + + + 49, 13 + + + Website: + + + 214, 13 + + + This software is using icons from VistaIcons: + + + 260, 26 + + + In accordance with the Creative Commons Attribution +3.0 license + + + + iVBORw0KGgoAAAANSUhEUgAAAfQAAAEsCAIAAAC62dafAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewQAA + HsEBw2lUUwAAtDBJREFUeF7tvYefJMmV31fH4/k78A7AHXAADgfggAWw3s4aYL33drzb8b7duJ4e7733 + fg1wwDmKohFJSZRIiUaU6ClRXnf8T/TN+s68icmsrq7uru5pE/HZT29NVWZk5MvMb7z8xYsXv7Bjx45a + LtkC2QLZAtkCE8wCwD2XbIFsgWyBbIEJZoHazlyyBbIFsgWyBSacBTLcJ9wlzSeULZAtkC2wc2eGe74L + sgWyBbIFJqAFartyyRbIFsgWyBaYcBbIcJ9wlzSfULZAtkC2wK5dGe75LsgWyBbIFpiAFqjtziVbIFsg + WyBbYMJZIMN9wl3SfEITyAJ31p+cQIacjKeS4T4Zr3o+57Fggf7AvXfv3gMHDhw7duzMmTMXL166evXa + 5SvXLl26eurUuePHzx44cPzgwTMHD109dPjK9h1nNmw8trH3OP/1bjrR0Xnwnfc2vPv+rf/efnf96o79 + m/pOsMGGjce3bT996NCVg4cuHTh48tChk8dPnDl37tKlS1euXLl28eJFDnf06NH9+/fv2bPH2JFWupax + YMnchoYWqHEhc8kWyBZo0QKQ18L2pSeqYQ2lbdjx4MGDJ06cPHv2HOC+du36tWufXbx47fz562fOfnrg + wLlNfUfXrT/W2Xl0/se733pn0/MvbXjuxb4fP9s75akNd9/f8/17ur91V9e37+r61l0937qr+9t39dz2 + 3/d7vtPov3Qb9qrv2PWd73f98L6ehx9b99TTvRzi+Zc2vvlW77z5uzn0uvVHN285duTIpXPnPj137sql + yzTy00uXLp85c/bkSXqFQ5yp3G9C1RbtmTcbOQtkuI+cbXPNE80C1659snTZzu6eg13dB5Yu33nx4hUm + rIeHm5Ju3759eMFnz569jNd97dOLF2H39Z27Tnd2HZo7b/ejj3d/5/vdtdqKWm1xrbbs5n/La7VVtb+2 + pvYra2pfWPM7v9/5tW91f+M7xX/f/KPuP/xe97fr4P6jH7TnP7uBb32v55vfvXGUr327m4PWfqvegBr/ + razVaJLNW8p/X/lm530PdX3w0dY1HYe2bjtx6hR90tWrVz+5cOHiqVOngD4WaAL9iXY3jPnzyXAf85co + N3DMWODKlU9qtQW1X+8o/qstRDXZvHnzli1b4DsqCoyD4/jghw5dXNNx4K23N//hdzvrfFxS5yMfVtd+ + o+MLX+kseP3dwu9uF6lHoR56AjqYP/ij7i9/o6v2W5z+6voZ8R/cX/Ht73e+/8HWru7DR45chPhXrlw/ + d+7ckSNHAvdVN3/MXNUJ25BavGbmD9kC2QJNLAADrl79FJZJ0tpfW71zFw7rhd17Ti9ZtveRx9fWXV04 + Du9W1r7Q8Xt/0FUQvGVfOxSVP/xu9+9/q4vdwehv/G5n7a/jRK9K/sPf16EuvOlh/Gd/Q21WDqzrf391 + Dd3P736jaMBX/7ALmtMJ3WhbPy8NnCNnWkD/18PfX1r7jVWvvrEJ3B87duny5U8uXLxE/5e+3KRMzTfe + SFggw30krJrrnGgWgETILKdPX4GGwv17P+yB4HXIrvqVL3XgjA/oiYtIcPm7f9D1G7+HUy9PwauMFrVL + v/lHHc+9uOmNt/oYGp338dbOzv29m4729u7fuHFPb+/urVv3btu2b8eO/Tt3Hti+fc/Wrdu3bt2xZev2 + zZu3bdjQ299/fX1bt7DZlmLjnTv37dy5nxqoZ+u2fb29u3p792yg8k2H1284tHrN3llzNr/z3vo33970 + 4it99zzQddNDp23Ro9zsEr7Q8eWvd331m13IO55dvEMwKvCVb4p7T3D5j5/d0N1z5NSpy/j1DN6iXIU7 + n0E/Eg9MhvtIWDXXOREsAHFwNq9cQWT4fMuWU8+90Pvlb3S2IoB85wc3IP6lr3fVfimcWZ36Zfc91PP2 + u33z5m/ZsPHQpr59EBbabt68dd26DV1d3atWrVq4cOGcOXNmzpw5derU99577+3RLe++++6HH344bdo0 + GkAzPv54wfLlKzo7u3p61m3YsGnbtp27dx+kzX19+zb1HV62fNf7H/S+8trmL36NXkqV5ua7S231b/9+ + J75/OP5o+rwWyPrf/caahYv3HD128fLlaydPnlK90a8P0E+Ee+iOnkOG+x01fz742LMAcMGvvH79s4MH + L7z7/tabGshqpJKG45mgHF2CX3/5izjyDkIWMvR9D3W//+GWzs69mzfjJu/DcV67dt3Klavmz58/ffr0 + 999//616SdH9Tr2AVwtkp7Al5YN6AbuWj+oF+lMAcVqovHkpbc8/rcc64xB88KA2wGKTovArfcDcuXOX + LVvW1dW1ceOmHTsIpDm4ZevB9esPzpi15cWXN9V+FZrzH9Av/P1f+VJBfF5ffvXLvLsUoP/uD7s6Og6d + O8fw7AViQB2gzpQf/pNR4+Uol2yBbAGeJcYACUzcuvXUvQ8SygKgVyE99xeg8t0f9uCZBsqffWHjokU7 + Nm8+CMf7+rasWdOxYMECiAmsA98puwPcklpGA+UZM2aAS8qsWbNmz56N7ww6582bR5fwcb1QLQXvftHN + sjgpS1or6S5RD3VSrN9jcVAOTaEZFNpDq2we7bQLadI3sDFVYYqNG3t37dq7e/ehLVuPLlq84+XXemu/ + QC9oHM7K2i/jzqNQFWMA02duP3Hi8sWLl6F8ID4wl+/SQVkgw31Q5sobT0ALnDhxAj991+5z378HfRmm + r8avLMkvIB4FmdjE+P5LX++cO2/r5s0716/fuHTpMniHr11yw8MB1+kOgstuwS21hTXMBc5Lly5djhSy + YsVK/PxVq1bXyxoY2dHRWS/4yJTu7u6em2Xt7WVd/yXdMHbnA7VZrYegcDgO6tFpBo2hSTSMQgtpJ62l + zfYH0ROkfUDaAcTrAj0EO9KM7dt37t9/dPuOo0uX7UGOT8YeCA9dCuVPn75MdxuxlbxRZcoP6vHLcB+U + ufLGE8oCTCM6d/76m++gvRR+eonpAj2cylde7339zU2EnN+Ilqkt27Ch7+WXX37llVdef/31N998U0UF + 7UJnHJxBNyGO8xsEB4uIGLJbastr8ArywPL6etmwYcNGPN7e3k310lcvRF5aiL/c2qhsa6003Jc6KXEI + j+jRaQaNodAq2kYjaap9g/2BPUH0AZxg0F/0YwF6skB/vAHwge6NHTnugQOH9+07vqZjX531yDizCTzt + 7Dp88eJVguiRa9RqMuJbfAhrzDbOJVtgslng2vVP9u4792tfLoK1iV1J/XTiXmq/iFBQqASvvtG7YePB + 3bsPQDTc7W3bdvN9AvfNkh2HHd8cjQJUgTA5HhCHXBJcXxsyBrjltVQFuJB5e704N6qUA6A6HbSNEdoN + 55pG+oFojKuM2khaaydhl2BPYDfACdoB+EIA+unG9P2D+yWXP6Qn3gawEhg/duz09h0nXnltU60254f3 + dROqxMxetRr4HoCbbLdu6+eb4d66rfKWE8EC169/unXbGQf3mJUjqXHSQXx9OHTpA4/0dPcc2Lv3EN4z + xEEcV13BMd++HbjfjHOvLevt3fLaa69Bdvx0fFKohGQBymEZRNMN1/sOiINC2d1wamuTQJEWnbW2b1Yd + 1iv1KNErgF37gOgAAv3BfaGvCkRvp7Mv8VOpJxQqvmfjffv2nzx1nsQM777fe+zYeVIg6MUH4ifCfTkC + 55DhPgJGzVWOSQuQCWD3nrN1l3y1w6T8LaIV6zEbb73dxzxToIHcDayNDDFkRaUFxXzXrn23w30ragy/ + oiPDJmiFgw/KQzYJH7x5nF+LRB59o7bYMDdLu4HoAER/yn1sEs6+nn4Qv+Tjq+87/GCXyY6nT589deri + hQuXsAbVciCPPvrGGftHrDEqnUu2wMS2AL7ehYuf/vZXi0lDYp1ovLqfvuz9Dzfv3XsCZxpvEXwb/2fo + oUBHN4fduPDICIcOHUvh3te3HbedbfgJ9IAqlIpSjEcr6sHEMH4T2IURogMw7ZqyjzqPxNfHT1UdBX0H + k6E/jjw9KHuRf40d9d899MQwYxvPIsO9jcbMVY1FC1y//snc+YWcYjqX2i+gpy8lCeLevadw+/C4nS4U + 8d18Vj0X6EjneI4ICJDl1Ckc/1uyzJYtO3Dt2ZjwD6ADnkIraEi6sWidUWlTQ2uUiB+4R3IJQZ93IFif + DuQ64Mw3dAN0pWys857hXr2SGe6jcnfng9wJC+DcXb36eTHF/7c6vs70yEJ+Wblu/ZFjx06i+cJuCE5M + i5N3DG7BSSd4Ay8etZcxQKVzUYJfef785dvhvlO40wEAHVgTXmQVZ3fCAGPrmAPqGKm80x/rjeHxcmS4 + N7/ANR6AXLIFJp4FiF4/dPgiLGZKJPLLj57eeOToeR4G3HCC85zf76QhoxX5UicdBQA3HGUAn9HxzwjC + u3z5egr3rVt3ochTDz0B7iQqAfwiaK+VgsHTJ5NdDh8+HDuWfu3v6pT2Kj3q/e3FgdJjedDSEQesqlRJ + w+1bPym2JKT9MqMiV67y58KFC+SOJ6mkMo4KvvJ9OmYbw6q67RPvHh7mGWW4D9OAefexaAFE9q3bTtZq + i2AxOQBIQgsXkFbAN465My0NW0yZHk46LqF6rlHVMV53W1bI2rIq3E+fvrqm49i6dafWrjvZ5L/lKw4R + tBM1A6ZLlz5dteaoO65cdeTKlVu/9kcu2Hf4yNXO7uPutWLlYQSotM6GvGPFpe6eo2vXnao08vjGjYcP + HLhw/vwnTOkCr+lApeyOK03HuXPn2e6ekzcPfQgoVw99/frPV666cVIrVh25du3z6jb1GWSf96w98ugT + 63/ty0agrviDP+oiZmn23F2bt5xgIsLVq9flezV0JxVkxuKNeEfblOF+R82fDz4CFjh+/DhQqNVmfTRt + G8lmgQLUJtwCZZwIdIBuKDr/DD891XBLunnqkw4I9y1bjxfzoVjsovl/tfks9GEsjYc7dOh8sXCHe9UW + njhxIf21Id/JUrlk2YEi/8GNvRaQbdH3DGXoEpG1NN5xvc9r1MIix5n5v5b+5u+t7t10/PLlolOsEpm+ + 85XXNhYb3zj0XKaDVQ995iya2MI4qbNnr5VOip5mxSpOoThxphd863usYVKsLcXoCBPK/sZXTZy5cN7H + Rf7IsFUpNqbhaY7AbTX+qqy18gqZt8kWGEcWOHz4Uu23VqG2Ix0wIocajnrOwKm5U2A60XV8g/YC09kg + pVIVo6lUUoI7oTHE1SjLIOPUQ7x5XVh9K+3t93rQ+l1NKf0PnJ0+fY6GRYDNkSMXGA+4OT1qxdFjZ42q + RBeCa7QKtJQuAXBfveYIaYdjUtXpM+fYyzrhe8O9gPtvf3XFH37vVm5eMEojTeZFEjRrYwaAU3NPnrxk + TIvDCRIOuL/3wRYSuN889OITJ095aIwZhz537id0FTe3WX7y5MX0pMi4uWr1Ic76ux7xuzeOeDMB8krS + BTMfmJWhVqw6hCkoBiPZb6WsHUc352g2NcN9NK2djzXiFvj0s5+SzfHcufO4nJAR5hJCx9xI+OsMI/4p + Vfm1FGvRnBf82hzu9ck7t+COE3rPA2sff2r9Y0+U/0N5OHToKO1B36eDgVmHD+O534L7/v3H+BUdCRo6 + TivOUvPV4X44hfuhQ0eiTpoSEEz3qsKdZVSf+NGGl17tu/fBHjN5xdwusrTTDx08eJYBTKiNSe386nDf + nMKdcBUOjW1BcBz67Dk891twP3z4dHpSdWMuFv30Lt++q3Pb9uNHjpw+ePDooUMndu8+umbNvh/eS8Tq + gkWL95unAWtw1eg8qtYY8RtrHB4gw30cXrTc5H4sgDPImp48+dAQxEBwBBnTnsQwqZzSFa1qF01MO1i4 + Q3BSnxtMyXuDvYuFzoaAHNR/viRuh7eHEtwJ43bKK82mwQ2ddzT3EtyZgYXixOGok2CShhBM4Y7//p3v + d9D/OSMUkYokCDt2HP7CV4pU7KS9dJ4XMg6ZAOgRqVPHGeGrBHd25NCcZhyabqAEd5aVjZPi0hw8yHB3 + 0Z/Rl3zlmx28FWAQBkJMN2Z2TJgOyXfsOOYrl5MJ+nuVyY9FyQI1R71zyRaYGBbg/g64g0WzXIUakOrR + qSPcyrlTMwmB02gZZRl4BK9xwOuyzKmQZdiS5ObOcWVKlNGWYssQHWIxg4YluG/fsY9we3BJN4AvDM44 + KYNPolQ9d1b8oH6GE4AgHQZw9xzTva5cuRKyDNL2d+5aA9ltpJO2qIFkZc++sIG5u7rVJGZ48seF5EJP + Cd/x3+lES3AnyULp0DT47O2yzK7dB7GAJ0VtHZ0Ha79ZaEq/+Xudc+btotmGpTpxzBAmi0mPaSesx84N + rdHKFZxs22S4T7YrPsHPN+AOanmFN8dhBESHpK6PMyhbDAHuKBlMYQWdMMtFLUzwa0J2yA6tcJyrsgya + Of2B3QYbtAj33k2bATRHQX2iY4PCrcCdxtBIeinY6lxcyo6dTPtaGQsHkqNx375DuPaG82O3EtzpQDk0 + O3JGHrqAezGgekuWYV3AOCl6rM6ugywXDtzR+r9/bzdJMJ0VDNmdaoB9IuGMIyVMO/A9ptrVDepSTpKN + M9wnyYWeLKcJgiEa0kGkNIkZ6qlQOwRzDB7uK7ZvR4ku1qiDXOR8JKGhcZX41CaJBNxqHUeO3Ka5Iyyn + Q7Wtwr23Dz7i6gJ3XOPW4U5ONPxl3yRMIg/HO7v2E8Ryczh01caNB8zNi++MJd99/zbNnRxpHDrtV6pw + 37Fzf5wU71L1WQg3FqRlOPehx9Zt236IJV6xFZZRRjOxsKklHQB3rDjDvZUbuIZyl0u2wISxgNNz4DvP + f0xJT/30IZ8pNVdkmd0QDW8XFCoXpLIMmnU90yQxJ6X/VsyYdSOPisEwqP9Hj94WLRNwV/AR0zQgbTza + SElzJ/ukhNV9BoK+ncRefCYgvSTL8A4Ruc/AKIczu8uJE/Q3N/Ib/+qXO/DmoT8eNNtQ83tluK8vHZoG + lzR35niFikX9ly6x2vhiVii0/ygyLdezctZ+bRVrzPZtPnb23GVGbs2HbEpkxlFSsg/5Uk6SHTPcJ8mF + nkSnqVMTg0vh4wzTBIOFu6ORKBul/5gx+/ECFuQrEqDjhxqC0hzu5slqEe567sK9tBc1MP+zqrmH022s + i0Hl588X83sl7+//YfezL6xzzQ16DiSvMtzX3vDco1/pD+7IU2pNDGsfPkyXthC3PYJHiwVp74pOkRkD + q3bvPnP8OJndijHwCLIsmWKYV3ai7p7hPlGv7KQ+r9JLa1tsMVi447n/TrHIKt4oM4PS/5ZNnb5ZwQEf + GYwO6LmPNNxRupFcUEIixob+5vLlawF31hf80TM9kN2gfjZ77/2+NBSS3PUteu4p3OnYzpy5zGhtfd2l + Vb/ztU6CL9OFU+qxmMtZr+Po0WMRi2mPlfk+4F1dY8w9l2yBbIEBLcCzxAT6NFqG8VJlmYhpSWWZL3+j + c/7H2/v6DmzqO9C3+dCWLYe3bju6bduxrVuP79lzFESyF3yXp6VJTAjLKhgKPkCQFxEakDaSeMQ1t8e5 + b9q0OQjLm0F94utte1FDw2gZxnvxyhkG4E2CMQFfeq5dYwrSDc/9t7/aOXXaVrPxEGpJ5VW4O5aL5x6H + Lk1iUnMPFQv3n06L06d7I7Yd+3w0bctf/x0krGLJQyJ5pDx9JHzftesUzn4EuUv2AS/ZJN8gw32S3wD5 + 9Fu1wGDhDqSIlWQ1j7feestAQxNPujo2HDRw2/CPsQN3fHb94oMHLwHZGwOqv8RK2buNqCGOhTa/896m + 3701Q3UJq1ZV4X7mLJGj5WiZdIiC7gfEowXRJRhBxIwEpPUtWw59667OWI78a9/ufvypYt5Z9IU47xnu + A964Ge4DmihvkC1QWGAIcMe1h+wRaAjWQZuB23jKhKYQBIKfi2PeLrhXCZtCsLnnTmPw3IX7tWvX7r6/ + SJkQuQ127DxAFyXccaIXL93/y1+6lfmAl4bqofcU617dSMZAV8eocGn8mWPBd/QWKkzTutEFMqL6je90 + kpPAWU5f+EoH/QevO8Zi8nqRnfcBH8saY+65ZAtkCwxoAZ4l8heWZBmIBqydlVNPSFuexCTZUTMMNQHo + sW4cMEVycbJ+aUCVjAPBQRxbdBtYRgPSRpJPcU3HbekHJCwHApTIHRIw3YvPzOAtDajSKuIgcZyFO1FG + Z86c2biRDGg3uKzwzSRf4K4sU8xm2kpqtgD38p0795cOTfNmz935ha903uwelpKAPVQszBWD3rQT/91J + UrQc+5jibdmK3SZXEO6oRgwM4OOzpYFAJYMMeAUn2wYZ7v1eccKwTt8spK+jXKqXerLpovDjZLtdJvP5 + DgHuhHgwg8kQclOvOF0WR9WlVh1NhadHj96Yiw/LICmhkCncG2ruVbgTxBiEVfiuurdVuINRWqjmzi7k + Il6+gqViV5l+QMl769ZDriXrvCpO4dx5hltvBEpC8Bkzt0Ne49w99KefFjOYXNSQdI+//MXV/GQYvn0h + Sx+ePHXt6tVrzktAm6JrQfDBOC5r9eIrGw2kYZbT9+7ucs0s/sYyexnuzZ/HDPfCPqdYP+3sWahN5g1e + SD/55JOf/OQnP71Z/vhm8Yuf/exnfvHzn//8T/7kT9jy008/ZS/oz/M2mfE3sc99sHAnY+3S5awYd3Dn + ziP79p0k7Bv3/NixS8ePXz569NLlK58a4e58nBTuX/x654IFaBUHd+0+um/fKeY3nThx5dSp66dPXz95 + 6vqVK58VmdwPH8baqedONph16w/u2HmY7AAHD56mwpMnr7rX8RPXPvvspyrpaShkPca8q3fT/p31vfr6 + jkybsQMi/7Xf7kjIvmra9C1IMcCdcVd6KWdIkZqNDsAUY6R1rP3imtVr9u3YsRNAHzt2nLOb8uT63/9W + pI1kTat9TkCNDuBIEdr/8W8VuYVPcFJQnmeQJ+gkC2BfvLxq9YHa37gp+/w6ifh3mr+BloB+OkXshh0m + 9i03zLOrMeY+CQteOSyGyKAZQFP+9E//9M///M//4i/+4m/+zb/5X9TL3/pbf+u/vFn+9t/+2/GZ7yls + wJZs/2d/9mdQXu5DfEBPQAJO/SS06sQ+ZZ6069dvBZDgtzKlBuLEtEy0gp07T4dYAR9/4/cIhWRtv+p/ + H+/afcHAbeF+7Ngtz50dv/g1Zj813HHJ0mXFzH6V8TTlb+Fi/yIJ2RvuNe/cuWIdD/bi1bOU8rc+x6pY + gJAPBCPqa/Mf8Sqc46zZ2xj1hcsUpHBXi3Wa6IkTpIa/kdaxOPpvFIvTfuGr/C1WHifRo/UwLsr3zDvF + 8Y9XBBzzo/VTLnILF80mG+XSr3+78+EpG77xHc59aXQwZi4jTX0M5wp3/H2624l9yw3z7CYX3NFSrl+/ + justmoPgsPvv/t2/+/f+3t/7r24WPjcspQ3Y6+/8nb8j+qkQ0FM5jv9nn33Ggc6fPz/My5N3HzsWAO68 + 0aWaewnu9diPW3BP47VLn4Ha3n0XkCCcoVrS3Jvt+OsdHZ37nK4JXtMZqk0Pt/zU6cvm2MHtKME9JltB + 8699q6verxTxiF/++uq9e4+RzpIODLLjNZt+wNEFe5edu85AXmQZuwSmIAHryEhTF+sJ8F9Gbnl89rR7 + 4MWElfVqtflAHNXFNjB8yhCug6h+Q83Uv2VLkXEMuNO7uFwtRlNzHzu3xxhsyaSAO6oLUiPkBcHgOC18 + g/cN5Uvfp/8MygfZ48Pf//t/P8U9oJfy+PIgHi+JlwP+jsELn5s0WAvUPXd05Fn1tYr4bw7rUpi70WmZ + wL2v71ix9tCNDdys4X/zt249xeAhTig7Mpy4/wCBJfNb2HHxosXbEcfZEVjPX7CnvqxSkwP509zDh8/g + gDNiyVnUavNu34W48mW1XyDNS9fTz/VOm7F1U9+RgwdZLHAdGjcnqB7CaaK28yVcdqlYXiCg/KlT56dN + 36brXf/rEYt//vrvrl6/4SDjqOwO2dM8l+xYXyv1k1Wr9xOWc3N3anB3PhS1fTiV6J3DCP2m1aQNBP7H + CDPnMtiLOKm2ryFyTdSC9oLv/Pnnn0NbhBTIC6bB8T/4B/+Av/rpYJ0N4C/KjM57qaRAZ68BC9tTA748 + fQZCDSI+bQDx6om5jF8LwAVcBN7KmJfPBBo0FVJs4UuaYtfoFIRjBiTPnj1Pql3WYWWEc/36jSgSZH3B + 2962rVj0CWGa6TubNxdCNkOLxvZduIBI+El9x8NsQ9Ld2JFEvumO+OzsCOMg9alTZ9jxxIlTLKEBQxmm + re/VS9hMejgSljEIiaLiaOe5cyxmgvrPghj0RlsY4qWbWbVqNadDtVTuGrPpAuKcY6SEjCAcPHf6Myqk + 8voCTMQ1Ht29my+PHjzIRK19fM/wKSYC66acZDiUZhtwSffAXxe53rcfoYn6TrEQyIEDJ44cLZbs4Kzx + 0+1gKDTJzDaG9Oi2j9/baRRaPmHhjqSOAo63Dr7xplOsA2g4LuL5FZWcldcpfJm65ANy3A2oJy1+ST30 + JXQq8h05iP4Dyo/CFc2HGCELgBKAAlaAC4iBOy7H6uIYASzYB+jBPVNyABNQM427c5coMI5iqDuB20aG + uAA0oMQrZ0c2629HcIk8Yow8CgnHIrwEalNbHC6mSqWHI9gR1xu28q7AgfjA0WkGbRO+sZctjEaamtg1 + oSS7A31YA+EbOhPQyQb0CtRGG+JM7SH8pyknjet36iz1YEzUc2qmk+Os2YYaIo179DFmS3bpkoiD1G0f + oWs9MaqdaHDHWyfoBaQyQIrvjMMOsgPTMNfPeNYQmZ8YRMWtRrfhVmP7FOglag/qn/Kd+uG7bwZonTQs + 8310Hpsmb98NG1DdvroZ2wCUwBneLnCkuFQejDPnSQDLJblBalpcx5VivnLzuRvqTsH/hXTsSIfRcK90 + R5dGYhdwSQ+h091kr2gqfQmYhpKgli9jr2gYzaYBJkhQzFE7CrKHuYhX8XyL/OydnXQe1kZPQw9k8nrX + ouKkqMcZW8rlFD7QpXEWrmCOQaIx1mDue1eJsjMz+7FBkNGM0bmpxt1RatBwwhTQafQLmFZe17NO/XEZ + 7a+47Yx/4llzo9QzJV2ueuKDYnppY/133h7Q3yE7XYgx8hPG4GPtRBzKpvA2ZuGbevk0BrfjEWXEu7Tx + 9eufcEapP5ieILfH558T9vr5lSvXYAtAB0kuxwrduH8gnaG0Z8+eg57Ga0MucrhDND6DPwqQouDsFznN + Dx02DNccxZCuPhUWzWcX27h9ugt7UYAsczDQcIhHZC+wqzbCIazcsmlTH1viJtNO9uIvCHYBa+f9x178 + yr60k9hC1A5EHhrv8lW0ny31tVMlBMtg1c8//+mnn3527dp1rOo7hKdJz2cxPzBnx18PXQ8NusFlHgeU + Li4NtZEthuPSNNpJn2eha6E2W14P9bmCeMUl4NC8agv3uKBj7W684+2ZIHDHL+ZZZRgTTxxkg1TAmmJd + nz3gywZ0AJCdR5F9HRri4US9GQ7Nq/tSIe1BIOImVnZHL7rjV32iNuCRKYT0MVrIf4t+4QvLa7/F0BzD + m/zzHVKxO6MnXudPnWKB5rn1gTtGMtlm9vfuXsM1cr5+UANb1YOsfvbsCxtZrLlWm16rzaTaS5c+xQV2 + le1wabfvYN7mzN5Np2QZv/LCxhjs8y8U84NcFkrHuR4ucuilVzcQTfjlr68kzfrNBPTE23x49OhlWMnG + Bsa4PaVIfruDDYg1ZFx3BvsuWbqXfWkD20Rx4ytXrrPNXXev4cSpx+WoaKrLM7kYodl9T58+s2790fqo + JtVydstWrz5IF+WqhAbGpDIIneL2HYwA0wwMOA3TYUZmJHEIm23hM8e6+z42m3H5ynVXrLUqifzTn/5Z + ccRf5jJ9fPPCTSXSnY7TtPJG+NCMy5evvvfB1rr9ORwtnEd0PJcmvaBUOFFv7KGd10SAe+gwaCDoLQI6 + jWMpkV1BBuCilmA17j/Izi3OI60W38bCoXlLwHnneQDruGncghBkaFcr79XcAmfPfnL8xKcnTn7Wu+n0 + b32lg/mNW7edOXrs2v4Dl3H65FR4oKfPENe47I23tx09iid+jZyPJ05ec5CwxCBG5eudxMrDhy99+ulP + rl79dOu2U7gTsXpfxFzXQwOXbt5yzimXlPPnr/LNa29sBENA6sb4YR1z3AzvvLe1Hnq4kmWJlN0PHiRA + cMHxE5+wr3kTbTbb44XMmr2T7LjsdeXKpzSju6cg8i/8jdXnz19wY4PZXXPq889/xsaPPs6yGyfjV/NE + qpjzgX/y+Lz+Rh+NnDNv99WrnxHhtWz5fqq998EuoB9Rj0Fk3oeefm4d27/yet+VKz/55JPP2Wvb9lMb + Np7kISqGjB0jZcWp/ftp8+NPraUTonP1G3N+2Xf+7Gd/QQsfeGQ9F4hLcOjwFbKV0bBguufOxgsWEhe0 + bN9+7P9T3rhOnLxKuBFb2ldFhfkBSS1Q4w4bv4VbhxlDYFodxlHTf/gP/2FpLBRY82VaYC5uPrcXjwHF + QAj6Br4vbTnYf8ax7CEcvFX/4S2Bd0kOyt/xa/Mx23Jua2yrLI4zW48RXIGzjlaAG6jCoLoNwbnidbgv + xAMFRvyEn8g2xp67BCjsqHuXf1wPzltx8eKn7EsNbqwnrtTAEWXfrgLuS7ZuOw9n+am+5EUB9zfe3AhG + /cbtqRyqvvv+tt/7g64vfb2D+s+cOcuhyeyCG3vixPUAZUSnfPopsF781T/sRBeifjamDbPmMKd02fbt + xYpFJjOI3utnP/tTGjPlyQ1YJg7Nr4JVc1EuXcYOix9+bD35NTQFzXvtjc3se+jw+ZI1CtnqRHFGTz+7 + kVhGX1CwAwaBwr6X0Dadfc6ROp/8MT3BYroi+7bUXHW4L8IInCP7cpnQgvTZXcZEQ3E1732QSlYQjMSX + /KTlOVbY34tF88bs/Tn6DRvHcIfsEFmy47Crw8jTKFWsC2vHVBl0ZegVjR4xh6FXXf7WaR4OfrUvSVtC + tSXnHRDgvI/+xZ7YR5RWPOSQhfnrAAUcgBJG6ijmdXFAT2ScPl1kAZs3f8+FC9fPnr18+vSlEydOu66p + 3NQf/OzzPwFz3/peB10yWAE91KPazmdXQI2eoA73FbPn7kW0odqLF6/3bS4SbAF3WiK2AJzbC/df/mLH + jh3Hfu3LHaTiQrAm3wBwP3bsqp0N9dNge6Ndu4t177q6DhtXAwdpxvHjyD5Ln3uhGJVV/Y/G/OxniB4F + 3DkRfqLf8lduv/DvUJzWdBwq5hntLXx/tuG8bjZj6ccLigM5mmoHxtvn2+8ijyw7fbroYPiVRqqi2Il6 + FGCt9RiEEO68EPATzUht+8d//Oe08Mkf9547zyVgXvclouY5L6+US5RwUET5D6dy0JWz5+4+eYrNzmEB + rpQDHvDdw2W4lx7wcQx37huGT+EyAnro6Wl4YnNM61Ozr+HtuvwtlmC3Q7VpaHw1Lj7CIumHeM/gcSrc + xtOnJzZqR//sAu7w69KlG3CHSoRqUFwZI43WqMN9xS99Ea8ZGXdqrfYm2VEYxDOoA3yIVPwHAPTh1IIg + cMdxTodDRVX0FnXPHUF8za98yTqtdsXXv9MN3MG0Y4N8qK+rdwPuVH7mDDIOvcL8Qrc4cBK4o/84dmra + SBhH5es38tMy1vowvMSxVm4lanjkcVat28H2Th+15QF3Dse5G11Tnw1bOLleILg5c3YxBenY8YvGRzqG + ebxYQHXJ1OmE6m/UbhiknjH46o+e2cRPFy4UsOYnctG/8tr6ufO2TZ22CTFf2kbXGHC/cOGK3QadAdS2 + hXW4L2WGal3rx1Yf/MKvr8Cwnkj0KLT2Jz/54zff5mUCcQyVf8EvfXHVgYOnaVXaE2e4TwS48xjj9aBi + 43qnPnuqlbeI6SFsFoI+TKdjoAGmH/BD9BYp5dmMNwNeEYjbMBqS5wTKjz4BJ/AR9UZBBuC4epWxxMJz + Z/6OcDfo0NmVOpV1uC9ZvHTv8eOMuzCh5iAb4+MHywTQp5/+nM0eenQtfQZkpx7YB4AgC9gNSVqtow73 + FYsW7yf91aHDzPNkRhKy+Ko33iT4ZB3xfOyrpJPAfdHp02epCsx1de/v7SUj4+KDBy/QEnuaulZTePr1 + MUwSmhdCEwjmV9pz8hQUXvrEjwpXl2+cQer2IctwOENuDBJPnVzeIJcsLeTsAwcucFLEt1jtocMca+ns + 2btMw+s0JfoYnrsXX+nlJwRRjsXGR46cXLf+CAvDYiUOGnDXegH3c+cuUS3Npiq7K1zy+oDq4mee72XQ + GlvRs9G9cbiIegwRybcNpo+dOHl+1ep9v1kk7Vm1YeNBanMpKw+XZZn0Aa9FVtvx8oHWg0UEGVRsiKka + U2X0f92+klYePjtkN9kAejq6kAXVnm+cCpvC3TmrvGQQ8+6wKo8BlB8vNh8v7cSw8v2zzwB3AXccVfOn + O1cofX8/fYZtFmzbfhrwGZAe4dj1+MVClrmpubPC54qzZy/JPulvcEsI3HYtrAkK4zZvPUudRG1TIRJ3 + XXPfALDsY3BdhTt3ArIMojNwB+V79rLlkj/6fqG/HzhwjjBzmo0PS7NF4dWrhTj+4KPrOC710Bi0kM6u + QlTpWXuE+qmEv74ZsP3Pf16g8/GnNuAC6487cZ9D3wbB059w3NffLPoqaqivhbS1PnK7jMXt7EW0npLO + jp2c47IZs1Dnt9oD4Yl/7VvQdjkRohzCtxlpy6uqsgxwN0SSLoEDSe26577onfe28SXmMqTddyxeC6yE + S8DzjiaGEehg2BKbTJuxnbQzv/alBa5Da6oZKhRt4+V2Hel2jjO4+/TqthOCAkalbcrftlC92lukCrtK + i3lpeHugm6Go3TshNvz3UGzShAQmgjfAeaQv8GSr3zukPgpawJ2wEQEEFGCcCBDEdbgvnTtvN04h6WNZ + OpQ4PSV1u4GQL3buwo1d/O27Oo8dO4NrSQ14F4xDOmaozy5WhPumzUWHAcqZkgOWhTuUNAFAI7ifE/r3 + PLC2nkORPumMs5yAdVAVh+axJ4g8Wb6mg0SSzB46WM9IQ/TnQmLeOaJDC3Q8Nl7P/b6H1h0/TrbhE0eP + MdhYzMQOI9hmOkKSwFBt76aiTl5idhVnQbVLGZ60WngaahKx7fUgyBVd3cwyPUpHdfr0eYaFMREGwdPH + hrr53OQluMe7RQL3JU89vfHYMcKRj+zdxxkdJuwzBDT7VypZtnwPKiwjyRibs3hkyobaL65eu+6gLzch + N9lpTbZ7vr/zHWdw50pzJqrtBreU4D40svcnzpRiIiO8UjUm0kCa3h2+x7TY0GcU9N2enkDZXbjX1YOr + +UZsuwV4vMm6b7QMqNLJRcqoL1VawOKGf1fAfcVXvgmVIunVrN279/Cmn8Jdz3H/gfPfvostzWmFIz// + 0qXPnZIacRqQpY7FJZv6Crinnvvr/XjuOK11z/0c6MdVP3SoUHU4CnBnciadAfVALl1mClN4GAE2a2P9 + v5XPPt97/sIVhRo9d+CeeO5Lv3UXqRkLUtdPczrat68vhvf4osPcrw8+pCVkcPTsVr72Rh+rG0S14bnX + J5ayItVnU6dvv7l9ke2LlL/z5uOR7zAbWnQwPKpIRuG5l+D+07rmThrIm4alhdNoVwx7eL14xZm/oJCt + bv63/Je+uGb7jpM0D6MpuKnje3HbfkeN0wprLio0LgqXjRsRb1dNBge5FLk4QmRPsxeYVCAEGVx1HHYa + 4yIeOu8hzui/W+wM2IbGY23hjgQ/Liw/vhrJo8hSK909R9ZvKFLBlBSJePg/+eTnPWuPbuw9tn7DkXXr + D+EGMvfTVCcmUVG+oPAB/5TVXBYt2nHvA8unTe87caKYGmpcuVMu9RkvXPy0o+vI8ROXARzyAoVf1qwh + Hc1RXgjU3BEchC8voCT+7eg8hNCIawyaOXpX9wEcc1JoqVGwvbKM7wfcMxxoz96TL77c/eOn19BmxH3n + hTojVM39pl/8866uI72bjm/YeJQT5D9agsJhxGSI1FbLJd62/cRLVPtMB1khmcgV1YZQbrUUPnC6u3ad + eO2NdY9MWbVi5R6GMOiEOAVO2XPEgJwjU0l27DjFOTKZNjR3XqEE8R//7E9vtPDmJVi1GnseduzX4QEN + yzzYM2evLVq8++77lr397oaDB09xmSA7PShH5LN1Fi9kBOfnUrfAeIK7vgbvlU5GDcG9FFoe7nbrg6VV + D70EdL3vKOZwV20PuMt3nXfFmdR/F+5OVQ24cyL5Pmy7BYxEgsjQAUHWufWm5FUN0xEDBMae8yu6vNlU + 4KOv+SlZwJmCLxCBXMAuomVctkJQUjP3p3WCJzYDZ4ZL0gyOwjcmJHBqhV4zn8G30S8mCWAvugHbw/bC + Wi+b9gNNo2WozX5LaNqqGDK1WwKOKNdgGveWc1RgQf+h2fLdau29cLdtZKnasF70dlTLWWNSaotMAxzC + /iw0HPs8/tKZ0Wbq8eh62baQD3DZ3GGQWk88NHdPXKnNKUvmdbAv5Iy8ZBjZGeYZ7unTNG7gzgX2HU24 + g1QAaghjWkop19PISPuA6uzThruXaF4lewylqrlDdlfmo9dhMMCcZcF3PX2cepNEKstw4zKtqe1oyxUK + dzkIN2EBxayNIjjgDlkADb8CCHgaebIiFFK3MfBHbQbqRXIYAJeO5kkrQANknY9jfgIA7TegLYYTfRPl + NjBE3YVVqZC/euKmJAsU2nlYP5vZHwSLjTI0EMXTjGazscOtlEgEFs22j6EZfGMnVKrWqMR0xNLt+TK2 + d6jZUCJToYWyb9docjF+crC61E9QDzvaNyjslA5ahXs9TXEx/GtAkS9DXtz8CGiBGirHuCjcIsKdIBPU + DOBuxkfjUhy3VDDRrfZDxLCXMoJVHfOoIeV49bPVeggaoOzuMnvCveq8GyLJxmzJNsKdm5u737D3cWH/ + cdRITIqFg4MmWjH6BUbEk882Os78ahYwitHrzovhGgELawu48BOsjOQnusDhM8prk3nxkwII/zQbgd+E + 4JNWawfgxH235CgU4xrrgZsFszwv7hw2g2jgkgbbi8SsH8mebhyzkzzB8NxLzbZa4BvVOovKyUTRBmuW + 7+n2rv2t9VLUhumcc2tWSAfPPB0qt5+I2WHVFqYnTpOcyxrnEibNT1P6nI4buHMjpp47PDVBWAAd19il + TSMw0VX00tjzdLZRqrEEslv8ELwuwR12I7zQ8cBxVwjReXd5Jr4nLwdKq+/L3NMokmPtdmTwynSJ9FIY + mfcSV5TljCj8kxPkV8QlthyzxMeq4RebYeJGyoE6Imm2iJc7kMhsAc7R57Mz/gWQWwaIuWrm24psLYaF + pC8E1MmX5ngp1Ot6Fpf0m6hZZvmrCWE4LuzjM0exY9DJTfskd6F+QEkzos3hXMfGvsFQrdmTPEd2cagg + uoEwF0fn3K3WE4xsDXYYmkJr+PZpvxXJEiJzQygkcY4RPKpcE5eAf/JT2sIYzEhb6BG1f9oXhom8WGP2 + nhz9ho0PuHPZuO2ce4KNUDNAj2nCdKIVSRzehD6uVS2bVMBjhlEV3/402BIdSXjuxLBT4HvqvLuaNoW2 + 0SSXZNLr4aZEYvIWH/0Lnx6RlyF4jbnsF10oPNYKjy5KE7lQeKwSzl70WGMN9FpVHcMxQKVb2RSQUrvw + pZArYhHHKdntDFR76o7zkb7NB3o37evdtH9T3/7NWw7u2Vv4+PI9PajHVVyOlpR0YUEZjWQztzQuRWk+ + sJX2NDab58JHwxGpOLu0A7M2uw1KRHD215JqtRhv585j23cc3VH/y8ysfftujBkYGlBEULZQcxik1GuW + LkHEIEWPEv1rei7VE7mzz9FYO3rNRYjGeOEaB9y5zGmysIZwh7DhRBu+UlLAQ1oZFNPlWpSQZehR6E4g + O4gMuBvz7tsDDaCbYQM0Gcf69OnU6OkM4KO5xSmjeS1oj+sLRgiQhgo5qzSHwNm5TuAqsZ7zpfG8l4xm + +5scyydNGiJUILHs2l2A6eDBk8fQLW4Ks+GHSudgdPS4cYiocMfOo3c/sO77966N/956d6sUDs03VX6j + GeFQWxU1p42MX1MHudqMdC/7EkvqJVTbnG4ZjYxmRJ1pN5ZWu3PX8XseWPeDe9f6HyfuKdt13RzsPbF7 + z9H9B7DDjcbgne/bj+pCt6qZb5TqcaPvbHIJwlbpuaTe+hi58cZOM8YH3NUZ7ai5nKgZMBSXWdVFRxKA + hucu3EsKuNhqV9Fz54gxoCqaS8oMrVK6oTFmhVST5dWSz5GAPuSjGCoQuIFRfX+7h7bcPdRDq2ImrWMS + DDj/Ny0XAk/ZxflcqUdvuGdbGjnMSiAeE3Peenfbo09ufPDRDT+8v8DTfQ+tf/Cx9c++0LdsBaLHbUQu + vUI1PDqIwXu996H1f/SDHv+76561L722iWvKLaqEMqA+UKp5QI+v2pL+dml9y5Swpc6gWjlwb3jKOOyK + pVu2HvnRs5vueXA95n3znW18R5jmU8/03nvjm63EE6Wdn32bpfnpp2fU+lkP886ZGLuPJ7j7yswtEmOq + RpQ3hHvKWZ13negS4kM2GdQHXXK7E+EO010ACP7qj/O9+gYMRZBByDarjKIhSiVdFF+6vXOg2As/msK+ + FKNuSiMHhgPB/VhGagg3Iq11uMKJAi3zvN8NqaREeRrPC9YQ2tauXbZuO/biq1sAOm4mU2yCxX743t2F + +/nqG30wWQkYIjfkXbU9kA6ERYXfv2fti69sMAltOmyb8qtdJ3Wn6ml+yowUPP/SZuygTXitWbh45xM/ + 3oiF45vlK4pcAoM19Z0634lx3BrEGfvFyIdQZjA9XjBANFWvJTx3UasCnsYmpnAfFMqrGwt3wQ2RaQnH + cl03Pij3pyOQLrMHQSA7AcIMB/EZ95btfb1g+yj802GDtDhDynFa0xuE0+1iT5xyK9eRZmA0Q0hxvaH1 + f9u+Qm348mnMEl0UrwitNKy92zDN5+Ept+BSIrv/RGd478NeroUzNrki4njAlhSkeziFe8/zLxXZtSLJ + F7dri1UNeKwxskHzUyZiKDUIuddffbP3vgfXhdnvfmDtB1OLeMrBmnqMnP44bcb4gDsPXjoWpDKDp+xy + qf350WyQojZGCIPyQW1raL1AWMlecttTz11YA+jw2Q0JIMqNcwF5MYapJhPKRnQbMT1KNT9K9FhsWQI9 + YKVJuMwNb0eMRrNxscW6pX1sv1FTID6m5rbY8bTrETp1+twzL2xGLWnI9PjyngeZMV9MGop8tgi+rUC5 + SrpnX+xkQimR8sRxc4nxT1F4Wukn2nXKI11P81MmuOXFV/t+cN863ocw+30Pr1u6bN1zL677wX3FO9P3 + 7+m596G1S5cXGfAxtUHuPMITyT4jbf+h1T8+4M6tgM/riHwEROq868xK26pIUhLB1WeUaJoXN6uWiLP0 + WOJbt71YhvmmLKPrzdHhLLxwch2eC7HJeO48+XZO1ADZXSQkcie4lohqe4zZeiB24Sj0Fpw7fz0cTj1G + 4HToHpTpDflnF/z0uC1oCZtRc0lbaTvcrZCjeBY2BruNmgu/ZNk+QBMQhzg/vL/nB/f13Pdw9wOPdt/z + YPe9D/Z8/94ePsydt5gpjmZepOtt4nGn7+lV0j3zfMesWbNI9UVVBAVyiw4BXh6iyWNc0gpiy/i+v31b + xGhaf1oV3w94yn2b930wdeuTT2947qX1M2d3Y9UFC1a+8Vb3lKd6nn1h7bQZHUuWLKXzoyt1wm2L/SjN + 6K9VA/KulR1b2abUhtSYrVyvAds5chvUeP7HfsGIAXeVu3DeHZNM4V7SSSKCRVkjTc/bH8FbITtV6Vmr + tsNciu8KikL80+y+3MqxGpkz/ZxnC6DhNY0HyqF9g8V/9I/+UfDRQUszBoNvDsoR7UtQdeA1xKSf4AOH + s6ujP1C0seDa0yq2obVU1dxV59DtLSI+xgkM8x/p8vzLm1Of/b6H1r7zXues2YtmzpwzY8asadPnTp26 + 4MWXVz/7wprZs+csXLiQeZXme+EF0cfVFp48xWLZLCLK0n3EQd4aACyT7t6eZ55bM2PGDJz3NR3d69Zv + 27O3gFfpyW941rxksOgEItKJkwT2lOHOLqR75Nddu/3vxN59RQspCEi0irYdvtGP3NYrcBLEDLMj21T7 + i7QlnCNbUg//HT1GUOaN0ywRh0PfpkQlp8zcV+ejUpjw1NOzcdHiNfPmL6+nxiGdwApAzyfsbD/qm2vY + J0zNmrIc3eOSdpMjxn9x1tGqOAXaP6gdqaGVU25ieV45OCJto5GplWzSgBd0pG/+tP7xAXdabCxtOO/E + nHCLAzhIarouPfeSCK43HXx3nJNtIpQ7WN/iB3b0KKGZhDct3/WsYS7uuRNkuPVxDF21x+UdnHZh/ySU + aZXxmnLZZaFCPOGD7ry+PA3gREC8BzL6UD3BKUgp5XXh2XhAkb29WI/a6KhsvJTneo3o/Q2qHn2iN3Xb + n/xxNxCfPn36tGnTQDAu9uyizJk9Zx4F7jAj3/zswp2nd3XHwVde34pqT4gILwEPPLJhylMbX39r64aN + h7hqxFNWSTd16rwXXu588FGGE9ey4vOrb2zp23LYsJmgfHriW7cdf+u97VOeIs3vekYgH3x0/XMvbSbC + xCDNUId27znJBhGD+PiPeglE2bjp0EuvbaFVtI2WPPlM74JFe8jo65SJ3r6jL7++5QGig+otf/XNrZu3 + FD1A2hL6jL4tx95+b8dDUzZaj6f52JMbiXGkfpsRLxMN4Y49SV1ZT222vWftnjfe3kIY0v0PF2oML0b3 + P9Tz8OM9L72K9tVBzhgzfJnMnWc53mywA8149MleIm1YT+qNd7b19h1evnIfg7ERdkkcDlFIpVMY7I50 + z32bj7793vYWT7lqebJXYGesTVNp3opVxfLfcbG2bD3WygUN12FEnwIrHzdwN84k5TuPIicAy1wHVWRD + yapDrU9tkKIjkyI+ishusTQkO92MrjS85pEwWZKrGLsYJr6hywc7A9v1gBzEg8js67zQUpi8SgtMDDgq + 1+jFczp0XRwUO3CTxVwY3CLuIWUrzpcOgF3S3qKhFDNCcLdaX0EsNGnk7ux9+08BqYA7mu9jT3ZB9alT + p86cOVOa40K6goeZTFwbSOLs3HUCvR7SVSV7nudpMwjyO8KsJWTlW9Ey9/Y8+EjXvQ91Iy7Hl4DpwUfW + LV66i/UrnI2ZOPIXPl64l0YSyZO+YVD//Y+snzpjGyu8Oh2JewOqpjGIdBvTZ22nZsCddmA0+K13ydly + +O33toKetGZ+evTxDbSEqVm25NTps+99uIMaIpolNRctv/ehdR8v3GnLbUbDlxXh3tHZ9ebbvU1qY2zj + o2nd5F3GbTcVsGMSmGTx0v1F15KEM2F22k9XGifIN0Cfubq+shvTv3jpvkHtSBD1O+9va/2UuVgly9P7 + vvx6H4PwqHyYCwsvWlJkkKZJhPvPX7CnxQuqsz9y9/9tnjtkGRcllBn5HuIMjYfdEX0o3FNlRlc6NJNq + 3GGEHhqA2LCk3UBI7frscBl60gwJaxi7A6cmIQHu3NMUcmKYXQSVJibEKz56vamEvoHaZD3glvXpMiAx + 9GqUvV45HGdfjg4UzFoTYaNUrtQeIY+SfURR3rByDuq4Ai2h2SN01yGH4N6m0Lz7ge6nn1/z0dQFc+fN + B+vICAx7clEsrpan4L5y9QHcuv5GYu99cO3yFVuKFIYbdrECRhLnTqh7d8NoywceWUem8UjMUldvzy9a + uh9Xvb/BXhz/N9/ZxJIgZrbZufO2yJwf3r/27vsbdDxFAOL96370LExsMIwMj2hJZ+eNnGLw+vW3t1XJ + niKeiJfOrhuLYtMMQvvLLyvPr+FlCCUKe778em/z2uD7wkU9JhTDGsWE3VNn3v1gB3VW7cY3nGZcBWp+ + 9AlS1mwxLQ9zCcD0EHZ87c3NrZ9yvZu/zfIYhKVUbo3GP7Bu/oLiZmABgHkf72j9gvI8yt8Ruv/Tamuj + cIx2HcIUHFHMFgLR1CIcWoyAQpzWUMP51aJEoyxuoKG+raUUj+g/46fYwMBHasNl5tA8sYU3dDNjlN56 + 5JYS6CYtMS0UNyin4AT3cOi82F71krCopA6+ZX2kVbATshvjpILv2ATLOE8KxLNvVee5U3wH+g7nwndX + HGx7wYAfTtuJ93ebU3wPA6ogvmvhQpacLsIfnWpAiV52+45jeIhNnv8HHgHuXcWaoh2b8G3T+quE8lcG + cl97k0U+t5ptGGT0bT72yBMbY3ugADIAegplBgmWr7ixyNy2bYdTqoLp/o5VxKXcWw7nj0bSkudfYt3X + oiU8R6s79msi/HpIet/DRRvS3WnPcy+u79t8Y7nBbduPNIH7oiVb7qkHPiLI3Kzttsb84F6GVUn1uI5n + Qflr6fL9CEf99XDpOdKqZ14gR2aHkaYfL9zxwKO3Xdz+LkS6I4/h0uU7hnPKGESf/eaVXTtz9nqatHzF + poen3OqiBrygvqyPDt/HE9xBoUmgTLGU+u8Yy7DxoLajmml4CfgzyCQGPwV9WpzaWvqyFImo0i3TAbS5 + NSIYBqybY5b7CZRT8NN5otBhnM5ndj1eRKA2bY4mUa3aTrwHcAing8fMch381LU3PpITt7NhAyo3oxNH + pHl49wg7eu6hzNxBuBtIY7gkbR4JuJNm4JEp66s+LE87MTPPvbSho5O0hUX6B/Ox0DGfPHX6tbe2lfQc + kAdn73+kiKthx8ee7F6wYBG+/7LlxPaV4c77AcrMD+/vBmQpbh54pIeVUM0mf/hIoYZHx0NH8uNn1y9d + 1j17zhoU6lTnefo50jcWfm7vJkLIy8f6IZE/DxKn38OHEh85R/B6/8NriQgq/Xrfwz3Llhct4Ybctfsg + Lx8Q+a13Ny1bvn7Z8tVz56149InulO/Uv3DRjQTx5NIpKVHPJJ47iY1v1ta7dNnaJUtXzpmzrFTb3Q/0 + LFjQaeJ1EuA/8sSGlJX46bT2gYeLuKZSF8U/n3uhiDRFSeOlC5IOYUe0/k2bdgz+lMu9CMqbYVf3PtQz + ddpqbgWmONAvehUGvKCuKOJg8ig47zUQM46KWVlS8T2UuMClHrolAgcVxKOIUXEf0DfEMC2xvUEpOtcA + l+5XpgNQHhUeQlAe3roJY22n8kgkdbKRuuFOX3JKqlKSeeENhmEbFXwRD7Ij/5Q8UgzlV8Uci83jV5vH + T8g44bmncA/l5L9rRwHWdCFmR2BounmVhgOxCw3TsG0snDJGXrZiz0OPoSk38GT5kqdxzjzSu9/Ie47F + GA17eMptjiTbvPte55w5i2bNmjNz5txp0z+ePn3h3LlzkeyXLEVhvw249zzQ/ebbiz78cDrDqo890XUb + Ih/snjFzNdoFTiujjrjtgWMOMXNWNxUyEvDci53pXqB58ZJiacC167ans2EL+aU41gqaNHPmgilPdcGa + 2/uS7nffX80KfXPnFni9KxkGoIuaNr3It17PqL6PSaRr1+1GLKRtLk795jurQXDSvJ4Pp65x+429eyqe + e4cBQvVT275g4Y7unl1oXC4eixb/5tuV2j5a7dj1ytW77n7gFjeB9cNTembPWT579rxp0xc+9FjX9+6+ + rauLSNN58wtVKh1saHHHItp127Zo5BBOuS589Ux5qvOjqQsJu5o1a/7cuR/Pmr3iocdSi62dMaubiNh+ + LmgHFxRc8GzqvKdPbhsfgahqnMEdloXzHpQ3p4cesVZTuaYYLBgECemjvwENJZGb0WbFdHRzHTlWyVUx + faBMN2c3N6urEAB3e2azE9dHWm6k9DOOxYBF3gwifDPNjWOymtKsVzV9B2ljyNQUsmk6wDhQ2lo241gB + 90gBhuqdau7DZzu1UQnVIu7TSIxDNwnBm9Qc+jvKUntva+FOOisk40efaMx33voB6+tv9SKSKW1/NH1X + quTcff9auEZEDfyiMBI7Z04RW6P/uHxFMeSYIvXhKZ3vv//RBx98wLDthx8tgr+3EHl/z9vvrsTdZ9j2 + 9bf6lC/8DxGfUQBqJnbnvQ9WpmClt5g+Y0Wx+mvHphLcYd9HH9GLTKVhU6ctphtIW/LIlK5p02fRYOqc + Om3JbS15oGgJHHetcB4fFzPp7mYhqlWLFq94/4NOHNJbysN93W+8tRpSIz70rL2tjykUj+dvwd2k863X + 9t4Hfan8xbV47/01tBkRn5N6/c3bTMF4xjPPr1bff/Od27QjLNbijnau3JmtN7J0ypjlvoe63/9g3kcf + fcRIsoPzL73aFW57KxeU0Xvjsgx5yHAvP/vYhSvEdbKESpMmPk3z3hkmmOobEjDyz6UesZlX4XIAFJTj + gHtb8GZtqmtuFF11w2AcJmIvgW6SvOhp6FocEjDk0UWaIgbGPIvO93HifikJmiHz6vvpS0PaKg0SLwqi + n8ZwLFM8xlolVed9mHBX4TEYhrMD7qbb5rhNagb9ykQ0DOO0ke/23xgfC2zs3fbu++uYuMTLflXevefB + tdNnwvfdvF8980JfOo5KROOcOfMlO/AFK0byuYxRR2dfCndI9/RzayA7j32dqktS4MKm517ooIbVqzun + PHXb+OH9D/fMmLl4+vSPmf/07vtrUrAW2PpgBU59qSOJYxn8Uz3Wj59d/eGHH0KferRng5bgU4MYl0Mi + aGvZ8m3PvrDhgUeJUTHd4y1D1anaMX/+fPoYTvm2dDoVuHPvESWwbMX2Vmp77sXbXpIeeKQbVBqoirVn + zlpeMiBwNzLnmRduGy5ucUdfL+iBBtXI0ilz/zw0pYvuG/PSTsjOMoiPPXXbEAgXdPqMZhfUnpJhOSO5 + RxzuOrbjq0BPR8OqiI/kkYFaaSu1A9yyO/xfw0u49nYVgXLcc1fGcXEA3ByeCvreNMrCagV6SS3RVY9J + pKaFCQU8zQFgGEmaULc6NxWhRpUGcnFEGq+7FC2knSHx8xM9QcCdYErDEAPuyjIpf//7wRcddgr184rA + iwJmt/Pj7YRf+6uSn5TdgTtmae/tp5W4HBihEAFWdiGwgPiSGs67P4L4mg4WG9qZajJIGU893TVz5ixZ + wwPp0nH04pwXZ7dh4+4K6db4zAOghYvA9C0GiUj0nGXLVz3y+C23nbcHGgBM/c/Y8NTff/2tldS2eAne + 9G1hl4jdTY9VwB3uQ7RFizuqLeGMiAHt7d20es3OJ5/eiOPZX3RQveVr2J53ldVreivNKDx3pibVJ+Xu + 7Oze++TTva3UxrSmx568zQ6IS9OnF247VqITXbIE1atkwMJzx7RD2xFTDLaRDU/5R8/QhRcdJ2Rng87O + niFcUO4l7iIeXmOgQ2No7yNgbbWRqHQU6gSmkNexyoh8COKng64RGh/sFt8Wd6GG4Lgod4EbLgNABxA8 + 2EbOxcrCqZMefrrjJMa3NPTWI9NAOlPUAUZjBE2iSwcAK+F7qDRwUyFeicbgnIiKcSkcW2sxTsbEammk + fPBdZWaYcKcSJ9DSaTFswM2KMW0G7e8P7nFQ96Vwam28ZxwdwUqYiPZw+Xi2Fy9Z+cprnSURAwd52ozu + Vas3MPUmHc9kBA+aMN0JePE0mnzG8XCu+9Zth6qhI7jScBD5ZcXK9VUO4kaTe4bh2f7iQ0rf2yUULw0L + V6ekq+sha5oea3XTX9GaZgPQqdM3NAGxjVEPoZ+ge1vZ6KRuwr1n5uwtRIk0T+YTtTFT9cHHbtmBM3r2 + hQ6FDtTq+vKttwUj1U95deEsz1/MG1V6mVrc0R5oUI3s55TX8HLGXcEbFaE/PWu3lsa6m1zc6ON5/+N2 + 4l4yzC/DvfGDj3eGjeBaFKNT9F7TIrstsY17BcdxzKUSvnm456ournHstFKd9PDTY36awyPGsRhT73p7 + 4BUlPead6udKdn3nKtmdpuTaUsA9DauP+MsYNS0NANByeiD+8j3NEO6RQjKWC0/bEKgdrOPOjtDZGVU0 + krZhH/oYVUV+agj3tDtxTNX0xW2Ee4x+YyWnHXBxXQX7rXe60hiSH97X/dKrnfjUj97uU095svAldXIJ + 8DCQMdKh1COgbwkLAhc8hYJRhXsh0c5fRvhNi3CnzpdfXQmIP16wsgr3W8dqwMGBWzJ3HnWW5k8Vrw5E + o/M3WiiOoSrMrapDau5wc8nS8giELyL91TZv3rLSGf342QLuYe116wlrSZJu1s3LsXDrh7bjEBrZzykX + tuX1AkAXkuym3Q8kyUGbX9m4oHT/UEXZPR0dbO/9f8NzT2NIxuNnkMoDjA+ucmJEean4vQWCW/Rw5biL + EeubY3qXPwYHDILx1386v9RYda5NZJZ32BafWqanSYbTdAJpft10an7qs4fyrtue5os3a1jAvT5L/saq + zSnfnRBrbibkoDTVjAle5LsTmhwIbSKeDIh7KjQvJm2jn6PvdCgCT5z6B9ydDcJ5N8lau4o3t/47TxGv + OAAa4yxbvqEEiJdfW71gwcKnn0eduOUV3lsElsDq+fQH7MXunJ2PImXP3lMluJOmJkJHenq2ldiEg1nX + SRY98vgtdKLJcMT7H+564BH+6y7/9yhjd4sKuH9chvtAxxqwJbOefaE77eGIm3zxlXULFnbOmctbQklz + L+AOHIF7Om9Ld5uTWrhw0XMvrWP8OdDWvLa6urL4oUdv6+QentI1fcassPamvn2lFyNPmR0fHPyOQ2hk + /6dczNsy40I9Iu7QlCdvxT61ckF9twMm8IrnV3ewXfd8tZ7ayFU9mjX7MPMEGp5obKLgtojvEsTluBCn + EEUQxW9SuLOx9KcSauaZj+mmkBRlhsfeRGBm4lUMieWNqpNCDQdM1ZiSzx4phSMfpFHwUCbgbgAPbzCK + 706L5Y2EJrEX5DVbJDULd4tJKDl6KDOtgLi6DZ0EjaRJnL5xCHYtHK7FPoMG2OXQznbdMLv3nF63gZHt + IhohbFV34Q9Om7ElnWdIMMn7HyzhkXvj7dt0XgZgf/QsY4kLGEENhRTJzdts777TFbhLuuL1vxS8GBxE + +f3xc7eghub+6ONdH3w4/cMPpzKUSMAl8TiM4s6eTYzjbGCH6F/E51RkGUg34LGatGTGzDkPPnYrmAct + 5cmn15KRAbaiN1RHMsFZkfNreWO4f7xg8cOJxtJKbUjnU8rjkN3o7QHN1R17WL/pdvlFuC+c8mRPOr/p + /ocH3LG4LkNoZH+nbBfOVcbJ4z2VJUqinS1eUN4FeUbwDjPcW33efRPnSUYwAS6SXWccfAepSx9SlPO5 + CnT2heli3eQwKdb14nFXI6o90hFDYcBqft2GWE/JbkatWMU0zeeezrON+U2GReKQOoXK6ExuFxrDuTtL + BdybcicdUw3nvdTltAjiKtxBM42nJ8NV54hmzuG49Byt9xaONPDX95Lhlw+m7mLi5f0PbyD518LF+7rX + HmL2/OqOA0xbv//2+e7QAakcB3nmrFUPT7nNnUSxYdbSex/0rFi5efWa3VNn7Hzvw53MPqHDIKVUf3Av + lNjbI9OFu1B4693bdA/GeN99byFhNga3gHIIC+PmzfuYD4boLF3a1Y/LvLC/Y4n+/n7ljeS+xD3H35zy + VPecOXOLcMz3VxALX5JlmsMdjSXVmohYp7a5c+c1qY3zeuW1tan+w1V4+93lnHp9sHH72+9tSYPZ6wa8 + 8ToyhB3rMYuDbmST/kzbGvEybcbONLl0Kxe0nmetGBLjEVZwH/4N318NNafzjOviuUF2IKuSbiJG4S6d + Q2yR15HDywgT3tljzpFBhFw5euZ01NR/Gl0eQTXGYjpTKdaqLzIb1RNFAQLkGggLVfWRFWSqZK/67OYV + MIOCk1f12dM5TRH8Y5NMLMwpYwfaY0B9Cnc1GcMiS7K7LP7Hgy/GvVCnUhJ/Vdsb1hTE91f/GSE3vAQM + /z5kOsGzL25xEmN9Lb0i32F9kv26dOIMv9bnExYDp5Bo0aKlOLDp1Ec2+O4PiwgWJnzyHxsTCL97T5Hu + As2dTqI0sud4IIFu5D28/3bJ+KaCgYaB/JImpSnyy7/4ymrC1efMWTp9Zufb7/U89+La515au2LFGl4a + 8BDrce63DfZaW/NjNfmVCKB0WJKzIKb+vQ+WEQLPrNc0/NxoGY/Vnyzz8cdLSlJJ89rs5BYsJKX+bXag + v3nz7TX4xMyYTW1bv0w3JKAh7zjYRjY/ZW3Ls4ZrtanvyINJljos1vyC0is4V5knlwdZsg//nu+vhgkC + d7MwGvrtlNEIdNHdNhejeV2MiC+xWyKXkr34Gp4mCShlpwGgSO1sY4Si0ZCOsqa5wBTlgTVeuVSNwMeI + jcH/DZE9TXwm2X0v0WdPJ1VFPL6eO2cN3E05aQgmMlFoREH2hnAP/33whP/H7GuPpY7fXw0ldz4Qr0Ho + 4YZ/ox89ej5N+dvfMBcv0Q8+ykv9fCPwisUlFt6mHVd3RElniik3z+YtB4YG946OztffIvqwPJhZH4E0 + GrLoYAg5X7W6cEG4b/vrKoYB95nPvNDFZMvEQy/mXtIGOrP0rFuBO/3V87dr7gwkNKlNORs7PPtiOY2P + RqAfLVk+0feHvOPgGtk63JknThrOQV1Q6MSzaajMiJKdR2ncwx3eueS8bjWMc6oRLnmafLEUih4Qj2ik + IHiKb3Bsoi5KZBU283ss55Su1cf3bGkar8gNFC9fHsIE7lAerOuwNxw+LSUhCO24SIRyc7psGq0P0M1Z + xquJLxNG7DimGgMAN9Pu3ua5R6oZ+T4EuLe+S/A91YLMCUxxRu5wypatJ0tZw6qYLmI5Huj58KPlkN2Q + cNxkYDp9JjNImZbSOKYFsX7u/CIp/5CByyv5+vV9Tz1Dst9+83/VXem18z8uQp7Q/Zj33/A9YMhwL055 + 1hJm7VcTkMHl1HPHDk/8mLeEYoWp/gdUFy5a3P3IlHUt1sZsX6NLV63exEtMFeWcfj0lZGlct5Blbu7Y + N9gd6yH/g2hk81MOz93s/wcPnvjRs72tX1CTYo6C217AvZRNZRz9E3/ZZPlON1VISVPNpIskBGFN1FUi + uBkf03U8ZDdYxO0FviCY4iJ2adiJrAy5w59irilgxbVXSo5UNmYuc4U8DupRUp/d9DJsY3oZup/IIKbO + nk7FCs9duBdpQDZu9O3ETMiu5BeTVJ0Xms5TjVGBiJyR1P9kBEraByjIhJvvwDI96DDvwAMHz73wyhZE + GAQZvOBQWuBFHV5Fvq1X3+hCiQHrTiJ37VNTRa5avY2ZKWzm9nYMMdvo/Q97mOvIvKd7bstwgm7Qafhz + Icus30nW7+hR2NdfXYSvGPHevHPGLNBWaD4cIvKoGG5hYsUPpm6gs2Hj3t49DWtrfqwmv3LKCPrTZnSS + pYtjefT6cbsfebznsSdunTXfP/gok7nm0HIWyGt4yvXI9K6583oBbiu1zZiJAlbYgT6SFfd+/CzrhNww + At0DzeDcHywytaX5F4uoUL3pIe/Y0dnZeiObnzK2ZXyOW8UUAkCGjHAzZ29u5YKap8EgyJQJw7zn+9t9 + XMIdu0QSGNO/mGgNDobTF9kWI8dvulKHKzEFwU2SnuI7laeDhmk4Y8P1LkoBMI6UwnoIDrYAfZqWMjoY + oydLa4ywpcF8IbI3JHvA3bSUwB1OGalJDS5TxdGrcJfvDUdWA8EjgPd/EpULdwch+Ox8KPqhYd7o3ACE + tWzsPfTmO5tffGX94z8ilXn3w1OQjzsJaX//w5Wst8daTK7HBOYQZGJhT9PSkeNw9ty1L79W7PLQlG7+ + 48Orr6+ZPmPpxx8XWSFXrmLYcP2Dj7J8UkEi6n/9zVXOZeWx7+3d9fiPNrImUbHB7b9yIJOS82bZ09NL + 1jCSkzz9XBdCLS187sVuDjp9ZteiRWtWrixyjdVHjPqtrfmx+vuVE8eTXbVq1cqVpJpZ99QzhTz19HOd + b72zatasjz+augpFPuIyn36OtWHngLNVq9ZVTxkD8pNLcKxdt+Xd9zf86Jm1rdSG9Azm4OOWLTvmzt/4 + 8ms9rJbF8PXzL3V88NGqDz5akwbt3H0/w61LgLs9lgYc1I72CoNtZMNT9ioTeSHcfTvnA65Vz9pNrVxQ + dsQ/y3Bv8JirPhviZrfpC06sxWGu9irHww0v+eAR9y3BI7tW6pKX3PNwfp1/VIqH0Rt11LQ6cMp7AP2K + Sr1wj77HVMMm743AmHT4tOqzA6MS3LmDA+6YRdmdbsxlWkOT8RR8C0n195LzPhL+exXuIdY7O3f4cOf2 + 4HnjKeIlZsWKVbyUz51LiOGNwvOJyA7W6w5psWQzDjLvOg6WYGQeVMxo4kCCVohQdE92JJSlvtxHN0Py + jONs2NhHxhjm8RAfQoUx44m+dd9+FhTd3tFJjsAbvzJh3aSARjfxmkXzSNtClklayIGovBAQFi1yrSh+ + uvE+sa9I27J587a0tubHav5rEYJTX7GEgvy9ZAmRKuQ4nFsP1yFQZyGNqVts7qz6UoTmGquPW+1ihhwD + vXHKtNOV8+iucMbJQbZkaRH30qQ2d6mrpiTPKOaXcQnIncswK8eiFc88f1uqy3vu7/7gw4+dKMuORfjD + vkOD2tFewVG3FhvZ5JTryRt6DVR33gMPKS/TVD7gBWUDR2JHCe6xkMXY/yDyNKh5wAFBrLxh+lyXwDaL + i2vUmfA2qF3yvkFzYD2yawUEG36IYcmgfOkDh4jwx5T1EdVubAmCSeSON4+8yeidi+8EnEj2G2Q3Z04U + xSh44TQuPXdcG77kBjKxMDbBGmEHT0q5Pzz6aHPI7iPhtkedMZQaHaGyDH+NDhpy8Y0HuyFM8TyDAyjp + Gs1yE0bAWVxXvDmeUpcs50F1jhJ/TUoD8XHQ0OLZmEc9dkQvZi+X06J+tqEq1+2DmLCDfsIQVTbwaU9/ + dW1oc+6zQeFOsvrHmjUggxqKZPEkMFhR5IPke66ml5LrG+xo/Vj9tYRT4J3A1WM4BAficB49Vh+Ms+ZL + jGB8rfcYN1h6UjbS+SUaZMDaOGsWOHjx1c1P/HjjzNnbFi3eQs6GxYs7Z87qeP2trlKKCKQhchPQudIk + LE/gcX3H3tZ35BTsVp3u12Ijm5yy89p4PI224K8ra+JPNL+g7BgR7uw45Ju8xR1rLW53ZzfjicUWqDHC + nb9mbnEpJeVysy3GoqPSvOE8+8hiWGK31FYxN+rcoU68fnoLS7qOtm8DDSWd6EtsQ5rIRadelnE4aqD9 + KdxdIopTjsCYJmSPkYbQ3LmPAQFEYHetRP20PFIgKBbZ7DTbe8xpirDIkeZ7KDPxioNZ6KSHc7N5q/iy + DN2AEU9pkRj9ZoE+xsLyE0bjmUxDF4w3Bb7wFBzwNLKxE9z4C6xhWT2RZDGq4XQ5N3B5FqPcvHBswCHA + aOlXExAVeYnrywI7DJ4exSRl9TmQxXKjDqEDpoa1NT9Ww19NlWP8rg2ItNUc2lkdaXtiWhw3FdtXTzlt + JMbBDuzum0HD2urxbIfqcw7Q/Qux3nhTPqTx78ZBPv8ik/6LiCYn/W/dtn9oO9rVUTjxVhrpTMCGp8x1 + 0ft2IC343soFNR8kt5kK7YiW8QR3jSiw1F501SFXTPRXZEhhGqgykUt42SG2xASiyOUSq2eog3MggZuu + 0xSOtr8qBCmdR08TPE3fG2LSf1CeX4GsorzOexzO5AqOoFZ99vhJzz0GVHn8nE6FxRxWTWNmfG+IYiNL + douYmZHju3Hu4bnHa41paoZcVHWc95AuShXJhZzT4BqNbKCsF8PdMYjNEwhSY/av+ekwMg+8OxqQquWp + nF/BBz+5ooChsdVfXa1FN4XNFIJKRzFg1/wWURuIH+yxmrSEe8mU1GYYtaMyzaoTPkw46nmZVUnZquEp + m5vB02mlNo6+fMWNdf6apGRhiLVY8Gjqx6bbdLYwK30PGA2V7ojilE4zdgG1VhrZ/JQD0N5vMQ1lwAvq + DRCxeUO+z1vZcUzD3fXwOA3Nx99YSA+MplgH0CUfOfDkLJtUOVHbNfMiHQP1VBdCimAVX9XV99O88HxW + 8Y+kzAazG4oTbxWKRaW86tHUEG1sIZwFbSncncQkpEpqTKQwc5Kqce6GQuKIGchP4zWazrt+uieeljQL + cfSLGnB04J72u9iqlRu3yTbB99LkADP4G2Gl+xyzSMKNSp/VdDRbmseOqoJpfKq/qu3IboU1R/vj17Qj + SUdWdLGjxCQ4W9hfbc2P1eRX79uY1x3zJ5zq4eIHtjydkdf8lKPHaqW219/a3mS5WgN4WOCQ9UZMz6lu + jvvy6ptbhrAjj4a+tjNX0ikjQzvldPqLgArEe9tUL2jYfHTITqtqAnQMllgnT74HMcFlackLsKikkPqb + gEmsG0AdMgggw81nVNPMLVAvcnJ51U24qNwRvbcPsze37eGD3zhxieLcKHbkGy4t11K2uvqSi+pxRBWS + UoIXfVjlGlpI8wLxodLop1siMyXHUuHFo4wZqvC9nqz+CI8Zj1zJeQ8dybFlSzXhTGrM/6HdxT4jdd7t + 3nirwD7DvxtFv8+bgp7okZUxeSR6iNIR091Lc7utMB7mUs3pc1s9bsOnOiTH6oHSN/fmtQ3515KJSm0I + i8VZD3hSqcH7q43ub9Waw48+sZGIVdLRRK7gmznuC4nm6ee6Z81mQbuZkB23nYENNBleKpat2DeEHXkX + 4bkO96uVRrZyyultE/dSKxd0+Hd4KzWMRbhHGImLoBoJEzpMJNHVW0+xHsiISTFVpoNXCioKzjXXw8EQ + 0GymAT7zJYdjGyd2DrbIZS4wcPdVGvjq08nZOBFc1JSqqVzDSeFi0/2kchA70luUyB7xkXQtvEcjyPAM + AHczEJjOjNuUM9J5d8qVo83+DdYH3xs67+3Fu2QX7uG2+zqFWVq5cVvZppU3gCb1tLL7ELZp2JE0qUdn + YowXT6r1RnJPnjx1bvWafa+92ffcS+sffKxYOGVKEQ3Z9da7a2bOWkx0UoSrMpRqnAwPaT1N/5lVa/YO + akeeGiXy1ls44Jb93TlD3rGVW3pQ24w5uBsaaIygzrsSR7i9Bn6oEZuwJdQDPuj8WpRfAKjaC4VKqA3y + 4nGrdYg/vmSb/jieKhiOr6aI5FfDTvorHJcj4jjwHgDo+cARuQNceA/RRl8+Qs5TrYY6Y7iV7bWMcnAs + /OSAWyq7GwSiMqNQQAPoG5ylFYiPubV+ULSJyEhtm4ozbeR76rbH+LYBPPSOg7qD88bjzgLc/A56w1yU + FtLxMHmAKFBCMRk4JeQ0DVdlHNVARtwXVy8y9HCwO+Jaid1xZ64hN7gmQMdIkeMRIJgOnMaiQry5O2Qa + 3BE6ijAxLmdACG4gO+qqc45gzuEU+Aglnd2TFlfJiCmj7ttigZtsLzoN2qkWSM1tbRu4U43Qt+tid/aK + 1xHBqlfL9yYRC75TiTJuyKNUGMqMSYmFu6EgHsixX0Utzr1Ugu9h4SZw/x+HUbhYvmOFGMUbmN2w8wDG + yN2YmzFCFtDH557kHmasiHuVaU1GlBKoirxO7GmEqxK6g8/Ozezzwp3PUzyEHRVIR+iMxma1YwjuESgS + FAuH3QFJPDt1mNRbhxQwooR1Ng6sU5sSuYvhcRmcjh8FdPKNC9q1yPEWNzPoviHrASutUlRRGXehDxx5 + tq8inhOn2wi4ezM5zOtIL1WB8oh255Ew4sL64buikIin/c7RdU5AlMhEHwt6xEhGjKyG/z40vLt7eO66 + 7Uag2q3StrH5qORWtdEC3Ic6784qCDnRLNyGq5pdh1/1xgwfVNEewo6TjexcrDEBd7kWEYcizEn58NHl + JuBd1WFXhylNDkqxzn1QF+kKxQ1upkw3C2MrQIeDUVIaxpetVBKgL2k4fA927XhwSXTkzTmTdmZO0Ocb + lz2K0ebIxODbgM67S3aozFDSGA8PEVGknoIWC9ZHFskY0mijC19y2x1H1W33TYLL1EaI5KrGpgV03sV0 + GrHqgsYukBDjVbomut7D2XFsmmLkWlVT3b6DRenZcHLFh3TsVC8bITh12AEEbmPqsLMBmznJCFxSD7eC + I6XcQFTiQsyUCH9UhS+V0FUiX1js2MqHkqrT8BBSXoCmdcJ0KEyDuZUD8Xrx0auJeE4z5TsPiUKkDwlP + hfNiVGbiCTFALd4SHMNIO62Yn+X8Xgd7U77H2MZwnPfw3EN0crqs14ViWs1cJrwFgBr3Oc8p4HYSf0Qb + R8ZswwEUylMIDnbHCW/Mhid4h+EeZBfukj2NDdd7VWHnXT6wki4tDYNCJWdfLrxvbdw3DhJa1HMbAt2X + gxJtW6H5gNukmk/6BhAus3JTFIBr44251MVmG3VwRRL8aE7ZUQTvcgqPgQOtrhfqciV48QZoGmqNRMMH + niK2N+2M4wTptNvw350XlobQ9Oe/t67PpJqMoZ/htquM0RjOa3I+ipPwrOMF1LjViMv0c4x/ullqnyHv + OKmMfIfhrs9uCbI74hdSjEST7HAklWJw+gCQUgkQ5MrBOACHPBfeuoHtDZke81oHZPTwN6AZnBG9SBXx + jhU7U9TC6XAKnAguOfexadnZPd5gdHsNCffBcJ4LLg/iDGq7S+6Z6gStxrgg1yeB8mzJXhgco1XF95Ce + olV2LWl+giF48VWyq7ZjmRgj4TQjVmpSPYeT+WQH1CX6M86Qd5wk1q4pcN+REutgOJOoNM2Hxz6kGLGu + FGO2Rbmgbg6MTEjifGv+aV51sV6FaWjKbjb6BY6HoxouvBEsOssW/mnIJuA2RQzbgH5deGdpsZkB+7y9 + xpRIR1YRZ+C7WUTw33HbnZZlOCZ18mzovDcMnlEBV5/hoDHEajx+KVRJcDd34RsKMgY1RZ9Hv35HbsV8 + 0GyBiWeBOwZ3hw0tDqWmEziD7OGwAw5f5CW77i1QgE3O7gGCXB6xGCJMSnbn348+ypsc0VHEkipSQjyn + YLwj+NbXBrjpIATKBqbTeXeYAXw7p4kxVfQZs1zhswt30zwhzlChfYYjDRG/H/HvwXc1KyUaVfgS4o2l + aR4In8a2x3xU+zkvU0wum3iPWT6jbIHRt8CdgTuQGhTZoUasKw1cYvDNyApzvDj2SFGoSbFuPPsdxHrz + o/uGUUJ8ZCmw2eDblAa625xdyYVn98iWJcRx2BHf4TsSjet6G/kO3KE/fSFvOYrvijP66WlJZzk5V0sX + PkV8OtepeS6amI+q1B6CDGcq2bklRv8ByEfMFpioFqhFstlR+2A0d2ReVJwx5NGJmg6f+pr/T//pP+Vv + kN0EimxpWIUzP7k2ka235AgbUBjLKo3+B5hreiaaSoPheH9tUKBIo86dDxXt5wPyC1AG4tpQF15zUdhd + 590MsRR8dviOPmNgmWQ30YIJcFBynLxqdjND8ktF3PuTcZyB+BDiA/GRkaa0qqotjPw5BrZ7vo5y0wBO + iks5avdhPlC2wMS2wB2Au3lxLSU1pjnZzX4uvukSYBx44rO41GGPorc++jRPj0gbaKGh5b6s4J8O2CS1 + mpTyCvHuyAk6tIALrwrPT0DWiV18dgasMZGmb4Xvhs0E3FO+h/+uPqP/3gTxqvAiPoSaSLMs5avF5fTS + TANVsnNGE/thy2eXLTCaFhhtuOunV8nOow65mvjs/KooDIDoEoz8cy8okzrsChoDMnQUNtCPVis3BMig + l1YOHZN6FL7Tvgqk0luowjvdlI0jUJLKcfDNNoPsbnJw05HzTSlvsP67OZUIITAsJzIoUG1Kef13+1f+ + ppQPrUZf3qERpw1HMYlbGtWOQWi8fbzzU0bz1s/HyhaY2BaolVLLjug/jdq2GP4YKXBTsiPF/LN/9s/4 + 60oO0EGf3YA5rofJUnQbHVmNovLecHm80f8SidxwdVXyGJ9ssSWctRpUFCwQZ8eXJv6PUdaYEIDF8IJj + WBW3Hb4TP+PCQ6XUwZGg2PiZSD4T+AbxFkEv4qNJKeWjbaXs+XG+ocY4LyHUGI7LexgnMqK3X648W2BS + WWBU4e7sJIoRMuq8AgseqbPDdEtKdrUCyS4u5YWzUi0h2beIzlHYzNwA+NFBTBDvhNvWC8YJl1nHmf7M + 3fngIZRosIBRNGY8Rr825h24uzKcKk1DviPl21Wk85t04fXQU7gH37W8cfFeo4jWN2bJv5RI/MAGbMbG + mMKEl1xNE0JNqgcvn2y2wEhbYPTgni5Epzjj5B2jPkB5jKA2IbuTekRbKlyMKYc9wA3yTHjkRCRPuXWs + p1saURPFkWcLtwgqPFD2/UAJ3ogU+I7O7iJNrgnZkO/miHfNncg7H7l9AtzhuVfhHvNaQ7FRuE9jb2J3 + tsFnj/TLKmxmXMglWyBboF0WqJnRZRQKD7Nqux94vFOyEwStGkNxeg54glwGacAXdXYo6St/SnaDRlIp + YOx8pm0mwIOzEHA47VSlCVyq3Xum9iIcxUlJ9peOXmK34DthkcZEuoJow6WdwoUPFd5AyfDiowGKM+G8 + p3kL0iFZe4LoDxx4MP2ZE69cIkfFP5dsgWyBdllgtOEO1pXaVVEAExoCZCfeUbKbmZ0v+UlGsCVnm5Kd + L8OH5fPYQfkotMT5WVHw0z0o32Mi3hIcYsXTd2zTKU4u5aH/bjYxpzU15DsuvJmbTLJqzk5DfWK6U2ju + yjIxq0CJJn3JsAOIaUqpFGOyM44VS5e067bO9WQLZAuMNtzTpGA4ntAHP914dsjuNFQl4xi7YxdzkYfP + HuwAYaPA07F2iNSFx0pg3RbyWmCCPSV++075DlJd4R64u1yZy2rj1PfnwgfizcyH/Xn5UFxyRacoZrfH + wfdDmowsZidxEQ1j9z3GTAlOpjXRjZXnki2QLdAuC9Qib9fIfQi1XUGGB740iArW//k//+f8jXku4Z8C + CxOnQCiIb5Ipi+LD5CxYw0xkFgdpjTVEuQKXwfeG/jthkS7OF3Oa+nPh9axduN2c2tQPiKnfy2op3Y7p + 92yJ7y/TzW7m2vCuLmLmHF8ORu4OzDVnC0xCC4w43H3sw7KGUetx46SH1A7cldpx2w18hFl0A6CEh59v + zCeTyZ52ZuZasGhSfzWmyOB6Q+Bdz4SroP+O887IqqoIvnNJnxH0fE+JlVrNBS/lDW4xKavx6SanLH2I + pNtsT3vM1k09HJRqqdwVdhyQSG+SSfgc5lPOFmi7BUYc7o78+uga+xjzlRRkdNvN+KjUDtlBkoOooEQ8 + wfdUaJ6cDnv1rJ2aG0X/ncIbknynN9WAMb4q34mPRJZxPBMnGs42QXyJ8uwi6DlEqaRf8tkVGALowXR8 + djNTRvLhDPe2P9u5wklugVok8BqJDxgXvgTZjX00qj0lu2676XyNp4bj9AToAOyiahwShLvnEhZQoomi + zk7BbQed8p1fjX/nL24yWHfaqtNc2YwPkDf12fXcS4VtwpfHAS8VOom0+Kv6j/XQf0T+YccGjMlRr8sl + WyBboI0WGFm48/QG3GMyKt6lETIMooJ1Cp912wG3bjtM56Wex16yxwwaIZVLyQJqVlW+00Gqv6d8pwfF + tvKd5AQOVoPa1IXXi2/I9/gykK3AEqXhGwBfurgrPQqfDWw3/Ea1vY33dK4qWyBbAAuMINx5Yk3yh+du + rHSMo6ZuO4h3HFVBBkIRPMcDzzu78y35JmTljPUmFmjId64C4OYSmCXYPOz0o3xpWmDEdxemcbJrqPBm + GQtkV0FfArr54o2zjMTxbIMKBNY3b968adMm/jqWa0g+FxpZyQicXLIFsgXaa4FaJHtp+wdD3/TLzOhr + 8LWTUZXa/8W/+Bfhtgtx5BccOh5+NHfnMYVDqnCcSxMLmLzFef9hLuxPT8l9YwZNly3EsCaPdEIT23Cl + GBR1vmggPmBtFviGRb3eItYpVOvMWFf7Y7VuyM4H3hXoQjgW19d4JyW4XLIFsgXaa4GRgjsowRnUcy+N + o4YgA9lx2w2ScTKquWLYkSAZBwBTqSFjvRULgO9YlgQ3311Ut70QmNo4JdiqDg6IXZ6Qq8YlIwzGgdYU + 8WyjXO6iH5FgMmqIcVpoDsopfGBOrKtB8dkC3KncaVZOYaO0957OtWULZAtggZGCO0wX7rx0p247PqMR + MpA93HboY7A2Thx8QR9QlwdSwl1/M5dWLIAxS3x3L6MVvRbGofL+xGf9btDM9YqsL5EboOTFi/jIMQmp + TRbP3CgIjmOOe95XL8Kd7/nVzGXOnyJQB8+djoQ2qBFxSyAZ5acxWyBboL0WGCm443oLd9UAqG1S33Qc + Ndx2c7UDcbaEQQDImEjJrlLcCtfyNlpAvkfRenjxpnAxq49pOLkcOPXBdxxqM/nwge+5iDGbNMJplFxK + iC/xHcQDd3AP+ukJ3BiVBrLzl6pogwKdhWvd3ts615YtkC1Qc8p4ewsCrnA3Di/U9qrbjiYDepxuqtuO + JiCe1I4jZ2TD9X2af8m+VDWEHSfALpx4pI3UT1f7Mv87njLDG2zjqqdAX74TAGPOXq4FiOfxcH6pq28j + 3RhRY9CklBf0IBsvXsTjsBMVo9vO91aremNOG/7J+xxwd+09S3vvwFxbtkC2wIjA3STd5vkzSKbktiPI + mP2Rp9r5qKrtdAn0BLpyCscKxEMr1Ek3M7R9J8BeDkdbwk2G3WAas7g+n+I7XjzetHyH4xrfvJsKJiIe + VcfcNeYPSCeaCm4o7/QosE7BbecbUI62o7xjl+BRuDop3DlWfhqzBbIF2miBWpoBql2fYbSeOw0tue1E + yPxP9YLyDlZU210bGojQJRjwHpKCoR1DKxANkNFzDG33CbCXWd0tfPaMwDps9Y0KE9HFIr6DWsPVIS8/ + sX2smhSIp6uOzF9OLsWXT+egUoPhlSAeR56/EB+mm7HAOEv5zmf6crqWWEeb5rXr9sv1ZAtkC2CB9sMd + aQUXz/RSEdvOo8tj7Kwl3PaYuIRTqSYDQRzQgz6SxXwywyEs7EAyptB5DKeecb2vs8As0VM63O1YiJcG + vsNu4Q6jcdsdlQX6Jlg2DzsdMJuxO9fX1DGYV3fe7DHi2zhIinDnV7dB1aFyvsSd522AJgl3LMzf/EBm + C2QLtNEC7Yc7T745pKAA3pmJZyO2HbLjtkN53HZYY8ZaCIKPzy6KIeG2G0oxnGLUBzU7fjg5i1nDLJoU + oLu4NsjG/oozFBxqw9VhsSvkCXeX2jAtO1eK/tu5xwatGodj0kcQj2IjwRlEleN8yU8uF653T+EQJWWG + Q7Txzs5VZQtMcgu0H+6RIBAvD08cQJhJJtx2IyD5ximprhHqFHm4A4BCJh4+i8GQzjv1D7+rGH577lQN + wffo5Oh0was5IbgQNMzI95iLxOWLaWUm0HddDi4Te/GrmX5dP96kvjHuirdueKUzpHDYXUiEzgPWOxLL + l9SWym60bZI/jfn0swXaaIFarKHTlg889maCxaGLBJA8wE5J1W1Hk+Gf0ASUGJthBKSicGgIvqoPs8Aj + GmPhBIdZ2/jdHWNG3oJQuun5uEyYSHEGuKfiDFExJl6OFfJi0SXhzu7yXS8eFY7auPrOcQXiDrGCcqrC + eVe6Ce5HzExq1bbchLmSbIFsASzQZrjzqAt3nvbQZCALw6eq7aHJGAFpxlqVXB5yw9spOvvDL/iekXCc + Dxxr+HWO0xoMdbfYcfI31DOHJRzixqfWf+c6pmTndtGtUJkpkT113vXQhTtF590BWMNy8NyBPrcKx03t + ma7Yl5/PbIFsgeFYoM1wV+MGCjz5rn9d1WRwD3meHUo1DpKeQOyGNNwWt11q0HMYvWOJQbxxyujhNDvN + XmA92N/IGXriiJzBW49cMeo2MjcEmYZkjyFW5RcXWkJ2V3nnn6Z6jzFV+M433APptYb1w7mb877ZAtkC + YYGai9a3q4B1PXcOACOMUofm4bbjvIcmY34rDk2XoCMZrqXje0MuKQFpAK8FJj6kKL4PueZxvaPvRiKe + z56LOfd9zfJi8ZrFRZTvkNp7ownZEWQcWfXqx7AqHrpzU+E446hoNUbUyH1+QqLhPqFJYVUa0K5bMdeT + LTDJLdBOuPOguswmD3lVkzG8HeUdfKjJmPERzxr30OAZ4T58+NpVOILKZ+pUFLZ4uMlZMEgkadACfMP1 + 4ipwybgimIsLRKcbuR7NDtSfzp4GzBgZmcLdmEj4Tj8Byl2bKWR3iM914V0qvRaT/IHMp58t0C4LtBPu + 5vxybZ2SJqPaHnOXjJMBJXj3sAPE83i3y203FAeySzH5Dq2M67AQxjM54c5Zp5bRCHS0pZFVnHd6QZ13 + cNw62SPmPQIiDXg364CL85Vkd6ShuBb0K6pAuWQLZAsM0wI1nqV2FaCp54704UKpEScD1v/lv/yXwl3U + Ok0GyAIRn23lAncZZhHuVqj/LsJc0NXC0Yd5lHG6u3y38NmzMMWbq2dgPS4THXAssURv3URnN/g1ndBk + xmCjHk0ZhghDbXwJ3OMntHhCaOzaw5jcG+26IXM92QKT2QLthLur+Zg3POYuGScj3PHf+SdMUY5XcIca + qvA62soCwyzyC7Kb0NzgP77kcLwoWNCa+WmYBxqnu9v52e15CqBc5503Ks3ClcJELreEkKLRIuoxVWOC + 7Goy8DrW3cbxN61YqsykeWZgvdOSw5IcfTI/kPncswXaZYF2wh3fTbgjvrvoUgRBqskY4c7TC0GgiYI7 + z7bEF+5iZTiFGpSSQ8QPvvMlCkOsic7R9VInW7E3tWArT9+FTNXTNAsGNJ0AxfBWBy1KOnv47JLdeHbX + +hDuZvo1ZsZhVZ13QyQR9ON1zYxD7bq5cz3ZApPZAjXY2q4C2ZVlnHfqvBhGUHXbKY6murIacMe7Byh8 + EO6WdnE2xGWlfMV3vuSDE3AsXPt2HXF81cOFiJgiW46VzMrpnCY2YFIx9hHuCOXCPcheUmO49OYY0HMH + 4srukWdG2R1XPeivCs9V4HBhPQ7arhsy15MtMJkt0Da4o3jwYPOEO/OlKrgDd1PKKLgb5w4veKrhiGQH + N2wz/GKdobyHOOPrP4dOE/nzAjH8I47HGlK42344i2Vcx1znnb/hvNNtN1Rj7NTDbZfdDpxGkpmQ3fne + PsAN8Ny5B+jvOVbYcDI/kPncswXaZYG2wR25Q7jj/clu3fAQ3J2bCl6BqYnaOQdoEusxsb3eYltKyvcI + 7rb/4CimKosCXNpy0PFVSTjv9Li2HDvovIfyzpfgPpz3SBMG6FM1JsiOz27Rc3dMVdndMVW4j3BnlgLT + BVMnN0MKd4Zk2nV/53qyBSatBWrmhBp+AdPCnTf3ENxBA4OoajLC3dFUIIJrj7PPW3+s2gH32YB/tqVI + KzXcNLhbcQaupTkIGSTg+7Ycd3xVEjGIYXmEMvo8372EPpcMrRwuU3wzS0dQUzVGwT3yvLtsEx2DGSKV + ZfgVPccZT0bE85ljpZee22P4N2SuIVtgklugbXAnlEK4E1CRZh0IuPOBB9jpS+gkTjSnGxDulraTMeW7 + Y7aGiBgLT9cSU3Ud1217A8Z4hXZ+9nY21QlfXCP6YN+9sCH8Fe442mnUY39kj0U8kHTM8QvZTf8L/akt + Xb2Pf3LDpMbnuJP8scynny0wfAu0De4QQbjj+jUcTUWfcdQOcOCa8TzjIaqHSHZHX9tegu8R/xd850M6 + ZQactf3oY7/CiEEM3zkWR2SsW6HMmPdw3l2gownZgbt8T513EC/cjannKGDdKW/oeOnV5/Pw7+xcQ7bA + JLdADdS2pfDECneQHaOpCu7/c70IdzABQ0E8cDcSEXboPCrQj0SBsKkLHyGAkIuWpJIc4u9INGAs14lx + jFTBRLaTvpkeGuDyXhWvU1xc0Gy4S0O4h9qefkj5TlgkKg13iPkMKPIdt4BbghsgrERL2nJP5kqyBSaz + BdoGd55S4c5DCyKNXOZxRW0PuPONOX5BKuDAfWODgHvAxcS/hsm3C4sp3wGWOQmUI5woG4Wjt+ug46We + CEO0wdgK2QSvx25YwQT7CHeUlvDZq+Ookt2lOSiR5pcdcfzdl56DFyYqxA9wtjBPYAp3DjeZn8l87tkC + bbFA2+Du+BiPLsOkaahMwJ0n1jhIFXkQz7OtEK8y4GoeOvXUANxNIsaXwywBWb3UNMRbvtPTpG9wfDPM + I46v3e35lGVsOeSlk+Yacb0UTPgVNMt3F7yO4dOSzy7Znc5mqhmjHnHb+cuXdOpq+twqTijjn/S1XiaX + 2G3LzZ0ryRaYzBao8Yy1pQTc4YLLtkWoTHjuYAKMAm7hzmCmcNdzNDkBZMeVjmlHUU+7cOm7QgwkCnf+ + 0p64D/gsZSZPibEBTxmzm9ANUxhHhEGIXxTuKOkxX0nERxHrZgaNtVWD74zH8hOdut0GN56Lbuu5p9Zu + yz2ZK8kWmMwWaBvcTeTNg40L7LIPVbjzpVGSsNtYZuMjA+5whGeevsEl91RO+NXsBcMv4kPlQRc+YkU4 + XHof0MGw5RCOSM0xJ8vJsZwO/Zl/ObtY/rv0wdh/iztG1jPfJIbQmNZ3SeHuXqYiUENzOIRrJ9zxwUtM + T7117gSwHgn0+Yy3jnfvYh3m+vcq05Gjz8B3PXevjkefzM9kPvdsgbZYoG1w5wHmCQfuRjo6EMezqtvu + gCpf0mjzebk4p3kiLXxmg4C7E46sp3VItbJlie+KQjSAhsGyKPxzwNoM9WFLeixoBa/luGMGkcQ4El5G + LvX+Prhl7GhV1GlPIPdd3aK9ZsEm8p3L5Fn7asXlCGWGX52XRHFNVKPaG5KdYVL1dEba4Ts3huoNn6mW + E+E0naXsui6YMbV2W27uXEm2wGS2QC3F2XA+h+cuvoM+Vbibr5HNOJw5CVR7TRspHMNp9Zl3GlQbC3WK + +HhvMFwEIuOfRuEsSgdlF76U5jaVD8HuyJAzQh+cagvfPbojE1qb0xmOfTBIjExYDwbBeXcR8xjZ5irj + tlNQZoS7+oyTTnXYoTlMR0mPRbQBPQ67w7Bs4JJ+1EnLMbXrunAKKdyHcyvmfbMFsgWwQNvgbrpXHuCA + uz6gcAcW/FPpI+AOOMwmZpEpElZmyZThMKvJvsH3CKSR7xCThkXx/QP0GMMTPHU+1B0v4j56Gp36hqAf + sI+0t/OqaTfozPWCvxzCWCbuGOHO4GrqsKuwA244jlhPr4Cw7gQx03Dyk+kK+IAcZ2Iyrq+L6JbgzqHz + w5ktkC0wTAuMKtzNPaDLxgce7IB7CeLqAyOE9bRaER9815GnYcCdWA74xex5TGxnE0CPfLlj5IN9TAp6 + Gsw32pCzo/Fae8DeTtXbzThx3GoVIQNbVWbkOxpLjJ0SCBtkp0tARsd6RpfywZBH6A/fXQaLphoC67wH + 1+tI2zbM2zrvni2QLVBLVYjhfA5ZBptWg9zV3PXcUVrYgM3wgvXoDU0JAWc0PwgURQkRTyMhGrlQtm/f + vqNeCNCOAYCbiRLG7v/tb2iwiQQc/MQ7ptPiTJvbNoQRN6MeZy0IXwc8qU24OzpqohgV9nDYXfTDpwtV + 3SVZFN+NavedDGurzNCV0nmkcEfoH87dmPfNFsgWaBvcIxQSfLcOd6F/B+EeqhGgMZcZjidiAm6pZLfg + oo5dnFdahtvO5di3b9/OnTsRx/GUVbocwGjC9xLc2RKnW87SW6hQYRzhTlxjSYoJh11nHGS7L6DXece7 + R7SJ4VOuO7eKm2W4ZxhlC7TXAm2DO8+5mjt+WStwN+AdfER082g67OmxwIq5bmiSAZqu3oIgk/Id33Ps + 8x3jw1yYDtnhu0APX151Ho+eU25obV9i0g4Aa+B9A1+zAHGxqFC4U9Kx0xLZjXoy+pMaXOCQ7U1soAjD + gQx+rcK9vXd5ri1bYBJaoJYOHg7nM05ZxLmncP9f6kWIK8vwYOMGOlmJn8JbdMtRK8AFTimmm0qMDy7+ + h6cJ1HBRyUIOKC27d+9WnRiDhcbT95CZi3aSwgU3OTJfVjskzxTEcyJcl9TgDn2r3vg918hEb3wwXJXr + SMQ6A6oUBJmQYrAYWwJur2wEEdlx8iuvREo3mJGqvCtog4GefJP2N8O5FfO+2QLZAligbXCPxGH4vP3B + 3Th3nmf9NZ7qOwJ31QBzGzhPyuJggJNr4JRriezZsyf4DuuNOxw7JRSYXbt2IYJH9yPTFd8tMSksPVmM + wPfQPBBfgjsbc0HNCaHsDt8ZXxHuRL80dNjTGViO5WJPuhycdxBPI3kJ+Ff/6l9xUN4hjCjlmwz3jKRs + gTZaoG1wxynTc8fhLckygsM3ejw7uWMMRsAdpvC0j3QxbsQgSxnnDKYmfMc5Dbjzgfk7sVcky70jH0KB + YflpXpvSXkcdJoLiRW2ccumsHXrlr5cgnHevBf8E33Z4ht8Ad3Av3BlcdexUkZ0LypaROsL+kr1cL5cb + w5VAqAqU/+t//a+5+jjsTtTKcG/jU52ryhYoPHcVz+GXWImJp1e4G22duoSm6JIy8gJ8RIzEiJJdb50C + bmJKakyONRVBJCSAR3jEJj+BXHjE+MVRcFfd+I4U2o+pWfiC9tDTQMzoWoSpWHeiEyWmWcWJlxrv7mo1 + bBMRNXE5sIA9MRsIdzYmIJKCvk8fwzX1PSxmJ9h/OD2NOmkM2xgzQ1fBxvSy/+bf/Bv4HtMa+CYViIZ/ + Q+YasgUmuQXaBnce2lisoyrL8NxCDR54gO4EFt/0ebxTV5F/tr0AoxTrAxJZRx5+0UIHA6Ebg6sp3znZ + Aetp+wagEz1k7969KEWY2tjzePPQR06xHnPB+NIOtXmfJOKplu314r0WGEGXnArNeaDsLt8xjmRPHXbO + 3ZkKZtrhinOt8fGNRKI2fvq3//bfBtzZN4U7t8Qkfyzz6WcLDN8CbYM7j24ssye+nUFT8tyNuzCRC96c + cLcETdrFdw6tjK7T6gTUAYtQlnRABxI5lwfBPfgOXjmRFisc8IgDboB3DEY5OtH3yF9APGW6wnqkJZDp + ojYGFeJlpfmxOCN24dRCOeFaUD9k5/sYU4XvvL4Id2AdM7y0s8kkVOf5S520hDpN4C7c+R6447yzsapR + hvvwH+ZcQ7ZAaoG2wR0ACXdEavVf4R5xF3x28qeMcLaqwutIwF2HcVBYD/A15DteJwEzwXc4C7NGlO80 + HpGa1Uc5KAK3q7xWXfUU64JSV72qwwzYizhr1GQGXCZq4OpwHb2gTjUyuomhUeFOCw03KpE9ZodBbTuG + gDuVC3c9d9vMUVI/ID+l2QLZAsO0QE3aDr/Qjsjl3dBzh+A852rZfIAFeO467D7VfMCVG35RXqd+yRu5 + awb1QQ7CMurhdJylSb+VijMAdziHaNIePGUVGAo+suONMSQQCoxYF44R0JnKL0Hz1s9d2loU8bEnHzg6 + F44PJiegYxbujOWq+SjF6LBHj+4kNSrBgAg4yFm8A3E6bPPv/t2/03O35ewYdwK/Dv+GzDVkC0xyC7QN + 7tgRHrn+Dp952tVnS885TzIqBz+xgZRvI9ypSvCFOCDU4A6epocbVBGpKd9Lg6tMFBpy/9GwJRCQPoMu + BIfdaVMp1kOBkebNmT6oM003jj4j9fTZAEDTAMfJ2Ua4c8VLUoxX3PHYiJJiX1d3MiUkNfz7f//vgbsC + HafJrRJ3Av3BJH8s8+lnCwzfAjUzx7alEOoO2SlOQQzNPX3OIS+/8hNPNR4cm/GEuwEv6byqD7lQp1h3 + KK9UCNpDVCFqEDoDTXWAVgq1KVYYAo//zuAqVUUhCKThEVupPLahfhUYqiUExf7PQ2OoiCl0ZNgScesx + nOAugzpuw41V8CkcPd1A5V24cyASG1CwZzjsDrF4KX0D47M5NfXcEdxNCclmwp1DcC5skMbC8mVbbshc + SbbAZLZAO+EOnvTc8c703ONp1ynDO8NH440eZPg+zoMdcGeboZEdlBjfUoJRCia8xZTIfEY0h/ig2fDt + 5kWJxpBtRhfYN2pDOeEGGjJVqRCLUQkdDykcsEkwPeJ2DIOxhLodcv+QD93fKRsWWYW7A6f22RSwLt8x + TryiBdm9lMJdWcZJvyCesxDuXDiHW/mrQGehAZP5mcznni3QFgu0E+6AUrgz9ihqU1kmoiFxfo2lkZUi + wDIEuAOF1GGPTDV+CH5BQDziEt/jn4SNoynBHTqJUg1RCTUE34EUATOxOx539BDV3Rt+Q8OAHQoMlZgw + wHeO1FVXhEmZrrStEJSiucWDtriZIUYyN92FbxDiA+5YTLjTzpBi9Nm5jkjqKdwdUMVudI2cFNdauHPW + VMsZhZLDTyalySVbIFtgOBZoJ9wRE4Q7+kx/cHdcDgfQt3WeeaMmhLtcaL0AmnDYm5DLFwU6lf7gnn6P + 6sIgIefCLmmdVKJ87xQnzjHdC/WZn9hmQIBy1gwA6PubMMDmpeOlkTagpL0E0wc8ynA2UIOqwt2YSF/I + KKT5Fe5YI5ViJHsKd8PnhbsJ/bniwJ297C+xQHTwfBjODZ33zRbIFtACNSd/t6sId3w6ntjw3OO5xTsD + DWahwqlXWpXpxrYHF6RDk8KWitFwIVKPNfwg5tTNmdLZCt9jG5BNXDm9kUEgUZUh8KQFTsUZ3gw4L06w + v/ZgZOyDAkPIvP1fdBgqMM4vbSimB6ybn2xbfrUDo/AhrZBGCndDV3k/45QpXEQVdi8f1LbwmWtKyzkj + 49x5t/O9jY3/w3/4D8KdXzlKTG7Qc88lWyBbYJgWaDPcHVMF7gazO/hWip3AJcQv5nkGEwq7Ou++0Q9E + 9eJ3tjTSUeYOWIQ7u2AsBBBayPobqa4yIPHJoMucTEZi6ZmiNj5Tj7COgsLDkEPaJLaHayTI5ShsD+Ac + GwhvnYaJdf5GIKPai0wf8ATbu0F/cLcz5q9w5zSFO7z2ZSslu3CH1OpvzlDl3PlA/WwM3KnEXo2bJODO + 52He03n3bIFsASzQZriDP+HOY5xOUg3nHQxBMYRXHWH1B3ndItwhglKM1IvUNP19EHwgRgXAGToUuh8i + 84hlRPhmMHNAvscGcByfHb+VGvDrU7LHZ+R7DsoR2QAFJhIG0OaSsC7ZU6aHthPIHvAc27sBtg3PPa2Z + lnPKAXczl1FQWkpkB9wBd/aiO6cDMEu+Lzd2A1TuKALXNODu+0Eu2QLZAsO0QM3Z6u0qPPDAHWLCvmo0 + JIjnMeZhdq6jc1bRN3jOnYyu5x7v9dUP7O60mshvFdkLmnxgY18UVJNNqlUyHDhGagdVhw4dgsUtFsDd + sOC/E4qDU09t8N1xWkMVQ1vnS5keTro0D562cmojsQ2NVB0KjnsU2mZckJPO4LVwx3RcKYBeKlxKhTje + z4Q7bzCYnXrcUrizQUhz3ACR8qxd92SuJ1tgclqgzXDn4ddzZzJnNRqSZ9inXbA6fRG7K9cOCHdZoNQz + WKgF3xV5jUJxto4XPmU9qhFjntAZRjehPFpNf3DnewZmYZkxLaXoxpTpMWYg0wd7XiOxfRO463cLd2R0 + 4Q61S1j/j//xP/IN19S+HCPj3ZscmM98ya+g30H1kuA+OZ/DfNbZAm23QJvhTvvwf4E7zju4LEVAC3ce + aV05nUFQ63t6DMo19NzZy8QmQ8aZfE9RG2OYKetTz5FT4CWDtxB6LAZjzcgYpTncifrXVQ9tPZ1tpPai + nz7kMxqhHYU7b0gxdhqeewp3OnLhjgQXcAfrkl24c3bKLC6THXGQ/up7DNvEiDqf236L5wqzBSanBWqR + SKRdHxixBO7Mx8FvVRkHDWmgGw+wU5kkNY83KFGZsVTf8alECqQpv4f2WU4JeqpNPWtzcjm2GbgvefcE + 83FqRNEgr6PUo7r0VxD0xXpEphvImAJ9aKcw0nvRTkcCaG16LFqewh1kM8hMwSWX6WkB3yCbXWJ6Kpu5 + UBTfsyV/7fw4RCQUwmLtug9zPdkCk9wC7Yc7moZwZ3AVVgr3dIoK/+QZ5qXemYoQhGtgWHRDuKdkTzuJ + oX1OaZV6vinuSypKQ9zTZmjVH9mZ1uTcHIFectKjDUM7hZHey8EJFbD0WPwz1dybw905SmkcJJ09Fx2b + cK2BO0aw749cBQruuWQLZAu0xQLthztvQGgyFPhuKHcaDakyI9B51B1iNW9UOO88/PGa76BryfdvL90a + 4l4F3EjEqmgu7sE3E3ka8h0lp8T0MQ701KTOCTBCMf2eMwLoobk3h7txkGyMlVwg29FU7KnsRuUcSE0m + EtG05Z7OlWQLZAtggVqaX7Bdn/HZgTtjqr7Fl+AeQEeZkR26ig6yWYQ7QCzFybVrHY8B60knXsnlhmIO + zYPjR48eDcQzBosgo+LkjlY14BHHzgZcDhUqTiFtFd/Tc8dsUi4uM2wpKOn/6+0Fx9xQGfBtHlDectiM + z+loqv2Er2vwnZrbdQfmerIFsgVGBO5QW7ijUDummsoyOu8qMzAdfLABGreR0Rbnpt8psjfkbBPcw0FG + C/HiQRhtji3HDq8H1RKDNSmlPonvncPlCXL5hDvsLsE9QmWohF3AOpZxbXR2VI73zcZpyXruxi/lki2Q + LdAWC4wI3Hn7VpZxJYeq7M4TzpcqMzzVsF51Ppx3v9FzjNf2O/6hOfRLKLzjrR1yAyQ7pWR80MwlC7jT + hQt3XPgU7rjtCu702ezCr0RAKrg7N5Vfub6+0kUULNZryw2dK8kWyBbQArXIJdveD4gVeO7AnWcbH03R + PIUj3+C2u9KeYRU8+XKB55+BO/byyR/jJRg6xtvZYvO4HBHhU9rFCKIIS4fXwp3b6H+7WaB8wJ0rGII7 + zrtev29mxqRyS8QhOGh778BcW7bAJLfASMGdoDc9d5SZVHYPvuu7gX6QwRPOc24cBc67SQLMOZPLKFtA + Ncy8PaVD47bzHoa77UVkaEG4456X4M51LE1fohfnSeNLU00YPhSdt5pMLtkC2QJttMBIwR0QQHYKqcRc + vqca8cLjbRIxZzCBe6kB2dkFjvBlqPD5QxstAMGxPD1r1cgGqhrHUjoiahscj1FW0ioIdy6ucFeciQj3 + 0GQiwl1XnRqMoE+HUtt4T+eqsgWyBbBAzRRRI1Hw2YU7+A64p8qMwTAmNDfOXYmDL51EE2FzTbLN5J8G + awHMy7RS5mGR/oyZtyRawP5RiRGKFEBcqtlMnyGvMaxCDRQuWcBdTaYUBInmbgyl19cUOvbc8n0kbr9c + Z7bAJLfACMIdFgh39PeGykwMq6KwRwZwX9sjV6Ljb7m0ywLYkzml5B8GytCZq4MDTqYEbO4hAL1wL1ke + FjsFKeAu2SmpJpNmHeANzJQy/EWXV6ynR6fPDrddR36SP4T59LMFRsICIwh3mkvAO/ggRtBnuzSsCiZi + WJWnPeUXEJHvTm7KpV0W4KIQlY/bzrIhXBqwTtfLZcKzNhTVlACU0hG5EGwD+n334oNkZ9i85LYrqccC + HWoy6jlccd12IyAtJnvIJVsgW6C9FqiZ3HWEClMThTuRFQ2VGTEBNfDy0syC+ImRETfmNFWTyuZvBmsB + TM2SrcgypIjAZ4fsqGcMjSKdRfi5k4pLNXM56KFjQil3IVkzKez7n/7Tf5Lv6dwlBl2cu6QmQ2/tlC4n + PYSaD/FH6N7L1WYLTHILjCzcwQEEAe78BQdOVS1Fi5t+wAUfUqDEPMkqaAZLtLx9WABwh+eOaKbnTqEb + dkqwmdS4RiWjGSrDxVI3xxkX7uyYDqWG2254O3O7jJMxHNakaek4+SR//PLpZwuMnAVGFu60mydcuJsG + 0qmqJb7z5CO70xOkaQVBgFNpGMRDIqjmHczfDM0CAJ30xSjvjKbCd3tfLgG1GX7u+HapcmDNteDyCXdc + cuFuHKRBMgroJnDHbYfsbAb9ldfM1cPVD7dd9SaXbIFsgZGwQE1pe+QKzznsICQDpoTwmsIdUoTzzmOf + znWEMsZcg4bSBPf8zyFbgJ6StMwsLkgUI8o7ojk3FrXxvYnSqtbmujCayrtUaOVc08uXLwN3cK8g46xU + eU1P4HLYzl0yBYWDLo7TGiczcnddrjlbIFtgxOGOiXHecQ/hO+/ykUSs6ryjzNITpMzi+RfuTlsfMs7y + jlULAGVelbg6dK7+ygfhjnNd2t6UYTHtiA0gOwXfP9x2dndpDoNkIDuFK44cZ95jBRnJzl9T5+eSLZAt + MEIWGA2487QLd5x3xuUivXvDbAQliMeESQCBe5gxPXIW4LoI99L7E0ekG4DRCu563MKdN4AQZJxybL4B + sM5AK847apurLdIxKMgId9PO5JItkC0wchaoGZQy0gXnHbITcseTb5bwkufuGz2eOziIuGm9woi8Zq/0 + p/y5jRZQcLdUqzXnV6SCwR9Hz6HwfSrIxKJLRODAd2R3egV2NLWvZKfQPYz0/ZbrzxbIFhgluENtPHfg + TmCGznuV73zDqzpEgP4pX4CCSxpRGLVrI9FyVWGBmDhKL1syC9+Y/U23nUI/Ldyd2qogE+OoxlbitrMX + XolDJjEliivIVc4PXrZAtsBIW2CU4M5pMLZm4J34bhg2AwVc26HEF74X7g39yszo4VvAVQYp1e4TQCO2 + sIFk58IhtUN2/uqGp4IM4TFoNfAd2Z0eHY7TMcf0V7anCx/pezrXny2QLYAFapG8e6Q/AAg9dx5+eFGF + Ow4gFIDgvOzTGKbGROHd30E5/cf0p/x5+BYA6C4ryEWp1mYQZIQwcu2YAAXZ4TgvVeaQ4Ev0NPpvfHau + r247YTN8T4eRTkOLuWkjfb/l+rMFJrkFRg/uGBqtVrhDgYYTmgA3fIEI+H14ef97UgCEcKcAo/Sn/HmY + FgDQwr1kc6rlp9BkjE/n2gl3ems6Y9gdETI47E555d3LSU+u+BHzoUwJB98n+VOXTz9bYBQsMKpw52nX + s+Mv8ktDZcaAPAJsYEqJWdBHuJtjdphEy7trAd6KJDsDIVWbmOzC+HQzM5OmX7gb3QivuZR024ygOtlV + t529uNx2GMIdfYb+gO8z30fhwc6HyBYYVbhjbl7ehTssMN9IdXU6wx9NBZzihsgZsC7fG5Io83oIFsCz + Fu6wu7Q7BucqcC3YRredK0guSeDORWQXeY2MhkSD5kbRbTd00qhKyW6kPO4822e4Z+5kC4yCBWoxS2jU + PuDZCXeg0DBsxjmr+H2KM/9HUnAzjcWm4EumP+XPQ7AA+MbUFtT2Ug3cf+A4jXVBk8Fzh+98D6+5RvTW + xLnCesiu4MZkNCcucR3BupeMzdhF6AfcR+2WywfKFpiEFrgDcOfxFu64e8ivzcUZ4uJxJ1PoxCx5kAE4 + hkC0vEtYwKzLFChcMgtmx/gxlIrZcdXJVQDcKVw4yQ7NYbqTGLigCjJGyOizmzhItz3DfRIiJp/ynbLA + HYA7p4rPzvu7+WCd716a02TkDIxgS17kS9xxwYfIgpJhPTQLQF7Jjv1LPSgVgnKg7BuSk49wyYU7Fw6y + 809ereinnXvMB5MNROwj9bM7V7AEd/Z1TPVO3fT5uNkCk8ECNZfdGeXCgw3WYQQSDYxo6LwbQB3Tmv7P + pCAgmD/WXFSAKf01f27FAuAbpptjHXGmuosrpsZie6jneOhkkYTvwFqy00ODdeDOT/wTaqc+O2TH98eX + TzWZlOyjfNflw2ULTCoL3Bm4Y2JcPOEO5fHjGiYkiDXYePfHDUwBRLRMzLsBT6CqFaLlbcICeOKSnZek + qlliVmq47WjorLsC3F22iVHTIDsRMlwgXrBMUWB4DGRnG+Cu564mY17TcNsn1ZOWTzZbYJQtcMfgznny + zAt30IAy21CcAS6456ABTJQIDt8jHUrm+6D6LUwn2U3YW92XSwOF04QwXCnhzsVKfXZYz09coCrZgTtC + jc47mrtw523AOAG2H+V7PR8uW2BSWaAWa2bekQ9gQljw/DdMKAbccS1pG7jBN/y/bi/oCYbxUXA2gVRp + g/zPqgWwEialK6XgYlc3gOlcjlDbdcNjRS2uV/jskh1q88ykPjtAp0h2PHfhHkGQgfU7csvlg2YLTBIL + 3GG484aO5w7c8fIQaiROaXAVvhv5DinYvgSjmIMD31UYMtCbW8AEL5SG5uL1yLWTAtbAnQsk3M0bo87O + X4Q1fPaU7LyBSfa0wHeUHNPHcwWF+yR5wPJpZgvcKQvcYbjzkPPM4wz6Cu+rfZXvjObhTsIFKIMX2YTv + 2X9vTnbedbQwhXHp6sZcAkBsQhjVc3gNyoE7hZAYmM6HhmTnJtZVjyLiQ3an/85wv1OPej7uZLNALRK2 + 3JEPmBtP0GmNUqCh+O7c91iNjw9VvsdknMz3/vhOWFG8FUH56mbo71wFp6RGQhhz8ZuxOT6Ez27GR+eg + BtPRYSzpNygzwl23/Y7cb/mg2QKTxwJ3GO4wnbnsjNThkuO5q882jHwPvjMoh6fPP6v6e/AdtxR5Iesz + qQWU2oU7PWVD4+Czo4xjxkgIA+hlugWfPdXZg+wMkFbJzjBJIJ4PKjNcvpBlJs9jls80W2D0LXAn4c6j + DizME8n7vq/wDr41TEtgehO0dQBEZ1AdDMTxTPmOo5r5rgUgO92hZAfxDXs++lQTQLKlbjsb81IVcJfs + OPLYH9c7yO6K2CW4g3JKie8Oq2bnffSf83zESWiBWqRqGeUPPOGqMUIBWBN3oeduYAwie2lkNdJXxZoe + aAv/9+0FHTmC/PDfwX1pg8n5TzzxMCZkrxoBS5psQEGGYWoKg6X0u/S+MB1Zxnh2pBWek8gbwz9BthyP + wj/5MoqId56qMTOuvWeCz1yyBbIFRsICdwbuPNs4gCDA4TX+whFkGdghBWJ6ZJXvrv5j8LuZxUqowmEP + vvMBVE1OoHvWuO0p2TFO1Rpsg9lDkJHsvCG5YJ6pYyA71obLhkjq2vPuFQQPV93LZzIZC5+D+/yT/oBe + JMN9JJ7nXGe2QFjgDsAdf8012PigSgCCGWQT1vA96GDWqv74zjkYaYNWU+W71aaTMCch4qE2xgkD8lrT + 0AggGxxjTzaW7FiP3le4m+6Rrpc+OJZVYkupLcRLiK/CPVz7kvOeH8VsgWyBEbJALSZ5jtoHXv/BgShB + NoE4+IBGsoMAmIJWIx2cHRNKMcSJwi767+rvfP//VIrVRmwlTmt1mwn8DRx39WoLdm54stgQNQw7sw1Y + R5+hcIGIhyFzJ3B3OISONlbewPLhlTf5wOXj6lD4wGa69l5WlRllmVG78fKBsgUmlQVGG+7OZ3HUDtw4 + 8Z0PYAi7MzQHR2AKfyNJbPA9deHVfB1f5TUfvuOkV+FFzcF3PgAvkDeBgR6nps8+INnZBpc8ldohO4IJ + 4x/CHefdNVQNocGAmDEkFzCdlhT0QXauDnxPvXtX4AvZfVI9b/lkswVGzQKjCncXzwPWkN2UJgZyuNgb + 7OaBZxucdxRetjTbFGhozvdY2QOrVcHN+CE1B+Lh3TBdeBgHE8dyD8EJmrbB0t/5YnPIDmfN567bjq1Q + urgE8B240xNDdjpOyY6jnebvDYKHh66THhfOTGHw3e9DxomA9+y8j9qjng802SxQi9wsI/oBs/I847aD + b3ATZA+4gxVlFp13HEbCM0zm7jKeTfQZExzypq8uXMUu3rqBfVEcZR0soNmdRYguXLhw5coV4gJh4mBr + GIXtsS2WjELf1vCgphlwfVQMqBrDB/pURz5MGhMTmiA7n0v5e700ElyIS3mvmmnCLPI9SsBdWWZE771c + ebbA5LTACMI97SdhruSFj2YPj/hr/Ep4BDucg4qfiLcIWYjQIHU4AApSNOF7qPYGUzb0VfkyZvE4kDso + F56NL168eP78edaGJjkicKf7gaGjwOsWD2EfFljHnti5P7JjKFDr0qmSnQJzGfAQ7iaNMTLSn9JEArHU + deCbD/I9SvpTie9sU5LdJ+fjl886W2DkLDCycHcUGI/P+Gj8axfGU2rnQ5DdoT/gzsZghe2BO4v+XL58 + GdaEe9hQnxFA+uZs4DoSDbEL/lQeonDc/ghYwiJtOH369KVLl2iVQd/GkLRI3pHeTCkmCnbu74iYHbJj + ZENfYhCVbhV8C3ds6BCrco0J3EtwL7E7/qkXX/215NdHtHt23kfu8c41T2YL1GJKZ1s+YErqiWU0wAei + KgREbOUzpIi5kUrtDHiqBpj6kW1ADBsLdzQQnWVX+ZEX5iBMI2f8LIbSEBoGBv/fRoVDp4ONRonA/YYb + x5e04cyZM3Q2LliBcGQwSfO9RuFX3oFShx0LYNj+jstPKdkxPq9NFC4T34NvLlaMePs6JfEjf69ZBHS9 + Syu482ZGCaz7T7aJ73XtvZTOU+W4yjJtuf1yJdkC2QJhgXbC3U4y1BieW/BqKkf+htSu217y2XHq9fF5 + 34cyhGqgewB3Ms8gcOMvM8QnNZz35PzVEuLVjvnL6bGZITewryHp6FdKu8Oy/jamBqoC7rQEsYiOx5QJ + 8H0U8N3fIfDNOYvUYYfy2La/7YE4jAbN+uxBdq6ak0iNZQqthg9mY24C93QtSlkvyqPEl16+8Ou9jtwh + Ge6ZR9kCI2GBNsM9JTt+GU8vKDFjCTQx9hHnnQ+ARn8TNxyIsDFPPloBRFZwN4E4JIXvyNwgnu+Fu/4g + 5qjyXWalEg04A+INeadKU0J8f3ykzbxDMJpqpjMTmuOH3hG4i3VOtjR22qQxnCaMpu8skR37RxIYPhgY + g1kwNWRvAnfpHEvbSPnUl/cyRUmd+uikhXvm+0g827nOSW6BWjpTfziftaPOOz44Dy2PPc+zs1eEO0AP + nV2yc0R+4vkHOjiPoAQtOxb9Ae4UF2VG6abgLKfI4FhVfYZqHR7kiEbpADX6GPqV/69RqcoaZqB01k+6 + B631NQK+0yS0I7qHhnWO3Jdi3XDMKMpKTQ7KtcAIIDViY5w+BtmNUOQa8cFBEUzHNzrs+uzpmkpsycVy + KdTSmhsNQV917dNl9rj63jM0bDi3X943WyBboGSBtsGdekNt54mV7CBAZzxipXWrnROvww58Ha9DyBbi + 0BzX2NUhcJApUl7QQ/+U7+Z/byjBK9HE3Fd6Do7YHwGBYymIUKcY2KW9Ap0T/RZdBec7cgTvrxOihSnT + +Ywx6ZyatITzgtToLeZyYHuxTuF6Rfg5l8lAJiwJyoPsJbhH8q+GcLdH940t9eIb8j2yuofbnh/ObIFs + gTZaoG1wL7ntPM/4ibh4kMV8AzzMsBW+0Ho+AAI28FewrrbOX3R24S7WTVnFBpZY4I0uId73leCrfIfs + BllGBD3YAk9wrT8ahl+cyh068kZwlnz5UeA7dK666q1gnbbRZgcezNCLKYLsXIJIDMAHR0SwZCrFpJ67 + yTuFu2nZQzQvLXDTH9xT7qvnmDssw72Nz3OuKlsgLFBLZ+cP57OeO8UIGXM9gmCwDhHABFAw+k3uq8Uj + swB0hA7JrtuOhx6xhmxgXIqz4Z0Qb55Cdk89RLSghhK80SCq8NDE9GSQpTmmcYerbrJeM1WZW3HkyI50 + TgPMukMXVSoDijA0jBowjivThsiuw07BVkajm13d2afYsyTFhCBjEKQLbmBAZRk6V8Nd0iLoG3K81Ae4 + F23ztuH+Gc7tl/fNFsgWKFlgNOAOEaCDay05xRFSGOwI0KOgyeiwm4ZQoBMkQ2FjPcqYPAni8egZYgUx + oQD058JDLmMuY56UIIMsQLAJo/kVHUYdqVpkoqPEw2Q9B6IG0+w0BLrHojHNG+y50FRNrRqWSjFUAlJj + thEUpg9jm5LDLtabwz0894B7f2QPJ90AKkskHgi1PT+c2QLZAm20QDvhrvOu587TC1lCmRHoEARSg2zX + 9wHl+OmWwLrxhVA7Vs1Ol/gxFtuJNtRDH0DBkUyjMnBLqyq8w7mqNEgQbAPgqA1+0eYBiYmbD1j78+WD + +4F7HWQcfPaywO74bLyQIUO0p+qbp98M6kUBfx9r6LBzjobwhxRDtV4UQxK5UvxkWs3mcE81GT138wfo + vEvqoHbIMr5XxaBryccX7ulQahtv61xVtkC2QK2aLX1o32jKGFY1YEYFxrwi6jOBeAgeq/zggwfTdfBT + ESCyUIVGbAIy3wZEPDhLJZqGLryjoxGFKeKdVc8R9eL/soUipgeEcnNkN/81XghabBKtpvsBl8pfzvPS + YaeDsXBZ0/lEXqyIdEzl9dRhV5CJy2E+yIiWwc6SvaHznmK9mrE6ldq9eYZ24+W9sgWyBRpaoG1wN/Oi + Wr6Dq8F3A5xLiIcmkX0Qdz6YHkkH0+RT6aQYZ8E4VAt0qAc3X10+HWVll4aBNLrwTqFSiGczdlSogUc4 + vy0QvtgEASS0FCNzhlwMQKRVTkFqsQFuRhtoNgbkFDjrmILkqwOFmrkWMZkIItPPmaRhQLgH2dP1lQLu + qeeeOu+pvK6HXioR2+4Nk8me8ZQt0HYLtBPuDfnuM68srhqQUt5ZkYJDD9157b7yx3t9Gk/NZz1QqmJ7 + 9g0XHvcfQKfzJKmqIeLVOsKLp+XQh42pjS4HeIHpQRHWjcE9HrRTcCN5ThA2nGghbvY0x3WHcCyxzsmK + dRoPMdVhAusciM4sjUpkGy5H6DD9qTEuVp667VW4c0SvUWmktET2EtxjmlsIMtltb/tTnSvMFsACtWoE + 4TC/EfGWiHznkYaeAfqU9TEfXVIYgFFaoCdNbKAPaEAOuxhKnyIeoQbol2a9G0tTCnCEgwI3tHgORLVU + qDTBZ34dGnlHdC86JydnuQ4tzQ7RKYR+zs7TicI/SzHsJTWmxHTVmFjVNpZPMT9MzFAtKTOpSpNeRy9i + OmUpxfow77q8e7ZAtkDJAiMC9+g2U6GmBPpgfSl2In342SVqiFDLtB444mwpVRowBLxwveE7PqkAivFD + fdsmiMfhNVUWxzKkRO0CxhlVMqK8bqVywE1LHCSgB4LaDbFOUznNFOsY2QnAJR2mOdwl+5Dh3pzsqRqT + H8tsgWyBtlug/XCniek7UWnMOp1iUM38UAp2jpcAK0yrCnFfnQGQqdKAY4V4EQ8EzUHo+4EuZzWcxowF + evHpiCstBKbsYqg+hapoRuu6fCvIbr4Nug0mpZdSfaIltIdTxgL0QyHCGIpD+zkXlauAu1k203DSKuIb + Bj5WyR6jqakm0zAMxhes0NYVYaLEha5OTWj7LZ4rzBaYnBaolZSK9v4Tm1Jhf5YV2XYGrVs/eg53VPwR + 8cr6ID7CaRxuBfcp310qCAKyY3q+TkONgMUS5anf1GYG6YNaIAuzwCt0/qu2FsR0GsbpgFePxXE5Om2w + zREJk7aW7zVCkJ29TGDZn89udoGqwt7QYXdExM4yHUptOFhqMEwwPTr1khTT3vst15YtkC0QFhhZuA9o + 6IZML+1lD1HtJPxG1pvSAMpETpsS4kEkwNJ5N6TS6EzDvUtaje5wlfIcETaxPUeJSbbwkWgfiE+FfEkz + zKrIeOmAwKdXMMeZrwi0jXqctGXaAJrH9xyREwymp22jkezOrwpQkXXHwWE6NrM4tAL3CIxpSPZS8FIE + sKdkTwdL+yN72jd79Qe8SfIG2QLZAkOwwB2Ge0ptYT2Ec0hdeJgSQrxhOakXr4Cu5x45s1By2CaGJaMB + JUc+8lmmq4vE4WK6lgH4pUBPcen4JL+iF4FdSsSAOrPf7sH4E4HOqTkxyolI6TQop87SgPCmhTunZuJG + XzIIEiX/WhO1vRQVY1OpQbPEJIN0kY0ge39D31Wyl0JiolMfwuXOu2QLZAu0YoExAfdWGtp8G2GRqjSG + 05jfJhDvlFS1CL50GNaEt65WYQIcYwrjiDC0ClbVeUDvbCY2jheImKPrXM2YFOrQbikNekzUBOW+QJi+ + xpU0qsd1/hRbUq2nENjln4438Nd8vPzEmTIZuGFIe0OspyGPvt94iFLjI39Aw1HTVFsvhbFnb334d3uu + IVugFQvUGmZNGadfhnQTUZh68eI1KO9EWYcQAbro58tYjchwFL5PdfkYvYww9vRDOhgr8Smu7FrKvU49 + fONPbhYct5JYY7Z0ILZUfkkdaucTxSmEu+0kVU6fn4wdKiXvTcMcPffUVS91GyH4RLIBmV6KbkxzsjcM + c/SOHKd3V252tsD4ssCEgjumD50nvHiVkxhujSlUeutSHporRCieCHcz2DhFCIZG3KHad0wobcj60pdK + Os3Z3bAegxpBqkk0qwhOnWsjghzw5HyxBm4yHZvhoZ5mOuO0xHQVmP6wXpVi0qD1AbEeb0Lj6/HIrc0W + GL8WmGhw90qkUn548Wk6hNJEWSkv02Wourl8jzQJuMAUpw459xVmCXr1k1ZA32Qb6E9tNBg0mxEhPO5I + uht8h8KchVErMYPXz/7TTgj/Gk/fId8YKRXrSlLB9AGxnqZybB4JUxonzw77+AVEbvn4tUBtyOlQxv6O + JUe+lLRSRV65xvHVVHwPDxfcV/luWnkKCQ/EvbOKqCcIqHSu6pIWvkz9XOjMXqY9MMuxA62GpUeoom8Y + fgmjaTMEN6tiRBmm07scNqDL4S99gAHyvp3QzjQXW6raK79E7ocQYWLgtBTaWNVeUimw9FSM/RsmtzBb + YCJZYCLDPRW7hU6q1ThFNjLVpJR33ddQ4WOCD4jUeU/hbtphElvGilGElkcxEjFWlYrvXViKXdw9XZNE + vpdS2IN79mUZE36iE6JLAOWcjgq+ZxqDulIe6DvYSzdGJ9Ef05VxIjVbJIGIpAKpvF5aWCNmKlTDnCS7 + DZtID0w+l2yB8WKBCQ73AF9JrjGrgbOfqpSHd2m4ZAr6iLcB9ADXZaFahLurBloC7vI9hXt47k4r5SjG + TVLIeg/6wbSKkHJQ5IXnnaDEdweB2RhVxzMKP70J06tYbzizNKae9eetj5dnILczW2BCWqBm2MZkKHH9 + AvRGT0aO4moIo7kn1W3S0PgQcGJI1qlMsRZgZKvXow+/XpSr5yjsBMojmiWdMupLQ0TNm/UeBYmmujAT + c1lNO2xq3zQo08w8qkD0T5FuM11e3GHSqvxSXdc0svJGLGN/qstkuJfyOWYLjH0LTCK4x8WoUl65pkR5 + RZvIl6tAH059dSaUMk4aUqlwH5P7Sx/8tTrOmdbjZ0d6fVeA75BauLu2H/nfzTMcic/gr6eDOONnZ2xF + ZoIS0E0OE3lgQnupZoCpBjKmLs/Yv91zC7MFJo8FJiPcI/y8KtpEerIq6CMrfbqeUerXV117BzBD1SlR + O2aBGrViGKIl9HE+GIMfA6pmQ4POnEXkL3MJ1nDeU7g7N8oMl6mHLtDT3F6Z6ZPnsc9nOhksUHMezWQu + DT1650OVWK9AH8mK9X9Lrr0Ds5aQuZt/cOMIUY9w9chk6UxagmSUaFBy+InmIcuYs8xl9qrOu4MKeO40 + ErhHpsbm6QFKMen9+eaT+Z7J554tMPYtkOF+4xqlPXmq28Ss15J0Ax+D9Snu02WPIgTFufuqOvE5jTtU + MAnZpPRB6R8vXr6bBI2jI7LDdNOToc/gyJeUd+BuuCROOu5/GsgY+ZOrES/V+JbUOGP/ns4tzBbIFsAC + Ge7l26Ah5SPWMPJQCsdIK5+y3gmxlHDt03Uz0s8x+ai0mJG9hcWqYs0p9RnEd/oGnXewnjrvrg0LoB0r + dpSYgueeaujVWJcS00vvrflpyRbIFhhfFqiVptjkf6YWSK9lSb0pxVbq/1ZxH1lwm39IdZKY4hQBiO5L + T4ALr/+OOBPOO4J7OO8o7yYBjrBIarZ7QMp32aYYFPUFpTnE8/2QLZAtME4tkOHe6oUL0FeHYmK2VKrh + hF4v8dP1AtPlqErySKQ7Tz9E6AsOOA67uXxx3lXekdpLyrtLwppbhh7CoWAntWagt3q983bZAuPcAhnu + g7uADd/LqkpONcWNek76N4SRhllw0xpidFdSg2k0FrPNgHuahPLuWn148anyTs2uB6tqT4mmlk5kcFbI + W2cLZAuMeQvU8PJyGY4FSpe4oZIDUptMgWsxKosahLV8Z4DURcDpJKrOe8S88yuSjpI9ygzHKjU4zt3M + w7lkC2QLTAwLZLi38zo27MtLuPefQLbhS0DzrsIJqEjnyCyKM/jvsD6cd8T3qvPu9qYn87gexQb0x/p2 + 2iXXlS2QLTDqFshwH0GTD/a9zaY02cteAWeccBrnJeG8Q21EecNmUGb467CqYTN0Bjr7bMYYrDmKq+JM + etARtEiuOlsgW2C0LFAz81Quo28BL/GAxy3JJlAY/x2axwoeREaG825MZMl5tzNQyUF/j3yN6dtDVZMZ + sGF5g2yBbIGxbIEM97F8dW61LZx6nXcccJT0cN4R03HPmcFkzHvJeXdjwmyAO4inY4jFNCLpfKrPtNjr + jA/D5VZmC0xWC2S4j48rn8IdEENnlHSGSUlLYE4xs80gyBg2U8pGQJgNG5vcxnmqRmeaaaCE+HhXGB+m + ya3MFsgWaGSBWqztmT+MZQuYtN1R0FDSVWYYUyXmnfFVnXfnNKXOe8g4bKOGY04CcwKnfFd5D7FoLBsk + ty1bIFuguQUy3MfBHRJkh7ymFojZScgsTmiiEBIDx80DbCrgSCXG9qjtjKkytZWYd7YU8brwme/j4CbI + TcwWGKQFMtwHabBR39z3rXDbYzkOuIzn7jApZGcRD4Jn+JKNwbrDqpEHGO1FjR7PHSUH/d2VtUt8p3LF + 9+y8j/p1zgfMFmizBWrEzOUyli3ABU/h7lqpyCkmjYHXwBp/HLhTQDaAZpJqyXnnS7iPz25oPF0Cn01b + BvRjOVbjZyS7N9pYtkxuW7ZAtkATC2S4j93bI/rxgLtJbNRkcLqhs3DHH2cRDxbwc7xU511lBtBzhiDb + rO7Oa0WpZ0d6ghBn+JU+Q889w33s3hO5ZdkCLVsgw71lU92hDVPPXbgDYuDuKoBpHjEXZcUlB9Oo7Trv + hs2gtBDtLtwdfRXu1EA9jqw2hHt23u/QZc+HzRYYrgVqPPm5jGULcIWD7zGaaqJ2/G5Qbh4xnHdWaALu + CC8473jfYD2cd/6Zwh3PnV7BYVXqcSk+uo1w2/H9484ay8bJbcsWyBbozwIZ7mP33gi8BtxN5GtGAddX + 0nkH1rjkLuKBPmM2MfZiQJXCGbIju9ATILgj0Ku5N9dkMtzH7p2RW5Yt0IIFMtxbMNId2qQEd7xpcw8o + uwffccDN+GgeYBbhA998yTbGvTjpCZSjxqjJOJpqqIyCjPOY2N7gnFBj7tCp58NmC2QLDNcCNQbcchmb + FuDa2jA+hDhjqHuk/3UJ7HQdPhFPjjAkdbx7F/owcRjQ5yd99lSNiXHUiJCJ22psWia3KlsgW2BAC2S4 + D2iiO7xBcFby6r/LdzxuF0oF4rjhgXgTQIJyAmlQYEz2S5AMf9XZ2d65S66bqoOfyX6Hr3Q+fLZAWy2Q + 4d5Wc7a7svTFTOc91d9dAETE66HrxSO54LYbSGM+GT5Uh0/7C3z0oO0+lVxftkC2wKhaoOaYWy5j3AJx + U0jeVKUx20xo8QF6F92OpbcjU5iLYkcwu8p+leZj3CC5edkC2QLNLZDhPs7uECV4+Z5GSUZOMRfiMKgm + LTLdUVNFmMB66qqPM3Pk5mYLZAv0Y4EM93F2a1Rd+KC8io3TWSMXTSyxlKaL0VWvyi/jzBa5udkC2QL9 + W6DGVJdcxpEFGl7KVMlrEj8Vm6WVjKNzz03NFsgWaN0CGe6t22qMbjkE32WMnkluVrZAtkD7LJDh3j5b + 5pqyBbIFsgXGjAUy3MfMpcgNyRbIFsgWaJ8FamSFzSVbIFsgWyBbYIJZIMN9gl3QfDrZAtkC2QKFBTLc + 832QLZAtkC0wAS1Qc0mHXLIFsgWyBbIFJpIFMtwn0tXM55ItkC2QLXDDAhnu+VbIFsgWyBaYgBao/WUu + 2QLZAtkC2QITzgIZ7hPukuYTyhbIFsgW+Mu/zHDPd0G2QLZAtsAEtEDtr3LJFsgWyBbIFphwFshwn3CX + NJ9QtkC2QLbAX/1Vhnu+C7IFsgWyBSagBWr/OZdsgWyBbIFsgQlngQz3CXdJ8wllC2QLZAv85//8/wNu + r1zYpv3VXAAAAABJRU5ErkJggg== + + + + About + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAbout.resx b/scheduler/DeviceScheduler/frmAbout.resx new file mode 100644 index 00000000..f79061e7 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAbout.resx @@ -0,0 +1,1195 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 3 + + + + 259, 13 + + + Denna programvara använder ikoner ifrÃ¥n VistaIcons: + + + 49, 13 + + + 435, 264 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 9 + + + 222, 13 + + + 51, 13 + + + lnkInternet + + + Enligt licens Creative Commons Attribution 3.0 + + + 75, 23 + + + label7 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + label2 + + + + CenterParent + + + 522, 299 + + + label5 + + + $this + + + + 11 + + + 9, 9, 9, 9 + + + $this + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 237, 207 + + + Om... + + + 8 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 8 + + + 5 + + + linkLabel1 + + + True + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 7 + + + 234, 26 + + + lblVersion + + + 237, 235 + + + 7 + + + Detta program är utvecklat av Mattias Dahlgren +för Telldus Technologies. + + + 9 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + True + + + 200, 26 + + + $this + + + True + + + © Copyright Telldus Technologies 2007. +Alla rättigheter förbehÃ¥lles. + + + True + + + frmAbout + + + 5 + + + label3 + + + http://www.telldus.se + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + label4 + + + + iVBORw0KGgoAAAANSUhEUgAAAfQAAAEsCAIAAAC62dafAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewQAA + HsEBw2lUUwAAtDBJREFUeF7tvYefJMmV31fH4/k78A7AHXAADgfggAWw3s4aYL33drzb8b7duJ4e7733 + fg1wwDmKohFJSZRIiUaU6ClRXnf8T/TN+s68icmsrq7uru5pE/HZT29NVWZk5MvMb7z8xYsXv7Bjx45a + LtkC2QLZAtkCE8wCwD2XbIFsgWyBbIEJZoHazlyyBbIFsgWyBSacBTLcJ9wlzSeULZAtkC2wc2eGe74L + sgWyBbIFJqAFartyyRbIFsgWyBaYcBbIcJ9wlzSfULZAtkC2wK5dGe75LsgWyBbIFpiAFqjtziVbIFsg + WyBbYMJZIMN9wl3SfEITyAJ31p+cQIacjKeS4T4Zr3o+57Fggf7AvXfv3gMHDhw7duzMmTMXL166evXa + 5SvXLl26eurUuePHzx44cPzgwTMHD109dPjK9h1nNmw8trH3OP/1bjrR0Xnwnfc2vPv+rf/efnf96o79 + m/pOsMGGjce3bT996NCVg4cuHTh48tChk8dPnDl37tKlS1euXLl28eJFDnf06NH9+/fv2bPH2JFWupax + YMnchoYWqHEhc8kWyBZo0QKQ18L2pSeqYQ2lbdjx4MGDJ06cPHv2HOC+du36tWufXbx47fz562fOfnrg + wLlNfUfXrT/W2Xl0/se733pn0/MvbXjuxb4fP9s75akNd9/f8/17ur91V9e37+r61l0937qr+9t39dz2 + 3/d7vtPov3Qb9qrv2PWd73f98L6ehx9b99TTvRzi+Zc2vvlW77z5uzn0uvVHN285duTIpXPnPj137sql + yzTy00uXLp85c/bkSXqFQ5yp3G9C1RbtmTcbOQtkuI+cbXPNE80C1659snTZzu6eg13dB5Yu33nx4hUm + rIeHm5Ju3759eMFnz569jNd97dOLF2H39Z27Tnd2HZo7b/ejj3d/5/vdtdqKWm1xrbbs5n/La7VVtb+2 + pvYra2pfWPM7v9/5tW91f+M7xX/f/KPuP/xe97fr4P6jH7TnP7uBb32v55vfvXGUr327m4PWfqvegBr/ + razVaJLNW8p/X/lm530PdX3w0dY1HYe2bjtx6hR90tWrVz+5cOHiqVOngD4WaAL9iXY3jPnzyXAf85co + N3DMWODKlU9qtQW1X+8o/qstRDXZvHnzli1b4DsqCoyD4/jghw5dXNNx4K23N//hdzvrfFxS5yMfVtd+ + o+MLX+kseP3dwu9uF6lHoR56AjqYP/ij7i9/o6v2W5z+6voZ8R/cX/Ht73e+/8HWru7DR45chPhXrlw/ + d+7ckSNHAvdVN3/MXNUJ25BavGbmD9kC2QJNLAADrl79FJZJ0tpfW71zFw7rhd17Ti9ZtveRx9fWXV04 + Du9W1r7Q8Xt/0FUQvGVfOxSVP/xu9+9/q4vdwehv/G5n7a/jRK9K/sPf16EuvOlh/Gd/Q21WDqzrf391 + Dd3P736jaMBX/7ALmtMJ3WhbPy8NnCNnWkD/18PfX1r7jVWvvrEJ3B87duny5U8uXLxE/5e+3KRMzTfe + SFggw30krJrrnGgWgETILKdPX4GGwv17P+yB4HXIrvqVL3XgjA/oiYtIcPm7f9D1G7+HUy9PwauMFrVL + v/lHHc+9uOmNt/oYGp338dbOzv29m4729u7fuHFPb+/urVv3btu2b8eO/Tt3Hti+fc/Wrdu3bt2xZev2 + zZu3bdjQ299/fX1bt7DZlmLjnTv37dy5nxqoZ+u2fb29u3p792yg8k2H1284tHrN3llzNr/z3vo33970 + 4it99zzQddNDp23Ro9zsEr7Q8eWvd331m13IO55dvEMwKvCVb4p7T3D5j5/d0N1z5NSpy/j1DN6iXIU7 + n0E/Eg9MhvtIWDXXOREsAHFwNq9cQWT4fMuWU8+90Pvlb3S2IoB85wc3IP6lr3fVfimcWZ36Zfc91PP2 + u33z5m/ZsPHQpr59EBbabt68dd26DV1d3atWrVq4cOGcOXNmzpw5derU99577+3RLe++++6HH344bdo0 + GkAzPv54wfLlKzo7u3p61m3YsGnbtp27dx+kzX19+zb1HV62fNf7H/S+8trmL36NXkqV5ua7S231b/9+ + J75/OP5o+rwWyPrf/caahYv3HD128fLlaydPnlK90a8P0E+Ee+iOnkOG+x01fz742LMAcMGvvH79s4MH + L7z7/tabGshqpJKG45mgHF2CX3/5izjyDkIWMvR9D3W//+GWzs69mzfjJu/DcV67dt3Klavmz58/ffr0 + 999//616SdH9Tr2AVwtkp7Al5YN6AbuWj+oF+lMAcVqovHkpbc8/rcc64xB88KA2wGKTovArfcDcuXOX + LVvW1dW1ceOmHTsIpDm4ZevB9esPzpi15cWXN9V+FZrzH9Av/P1f+VJBfF5ffvXLvLsUoP/uD7s6Og6d + O8fw7AViQB2gzpQf/pNR4+Uol2yBbAGeJcYACUzcuvXUvQ8SygKgVyE99xeg8t0f9uCZBsqffWHjokU7 + Nm8+CMf7+rasWdOxYMECiAmsA98puwPcklpGA+UZM2aAS8qsWbNmz56N7ww6582bR5fwcb1QLQXvftHN + sjgpS1or6S5RD3VSrN9jcVAOTaEZFNpDq2we7bQLadI3sDFVYYqNG3t37dq7e/ehLVuPLlq84+XXemu/ + QC9oHM7K2i/jzqNQFWMA02duP3Hi8sWLl6F8ID4wl+/SQVkgw31Q5sobT0ALnDhxAj991+5z378HfRmm + r8avLMkvIB4FmdjE+P5LX++cO2/r5s0716/fuHTpMniHr11yw8MB1+kOgstuwS21hTXMBc5Lly5djhSy + YsVK/PxVq1bXyxoY2dHRWS/4yJTu7u6em2Xt7WVd/yXdMHbnA7VZrYegcDgO6tFpBo2hSTSMQgtpJ62l + zfYH0ROkfUDaAcTrAj0EO9KM7dt37t9/dPuOo0uX7UGOT8YeCA9dCuVPn75MdxuxlbxRZcoP6vHLcB+U + ufLGE8oCTCM6d/76m++gvRR+eonpAj2cylde7339zU2EnN+Ilqkt27Ch7+WXX37llVdef/31N998U0UF + 7UJnHJxBNyGO8xsEB4uIGLJbastr8ArywPL6etmwYcNGPN7e3k310lcvRF5aiL/c2qhsa6003Jc6KXEI + j+jRaQaNodAq2kYjaap9g/2BPUH0AZxg0F/0YwF6skB/vAHwge6NHTnugQOH9+07vqZjX531yDizCTzt + 7Dp88eJVguiRa9RqMuJbfAhrzDbOJVtgslng2vVP9u4792tfLoK1iV1J/XTiXmq/iFBQqASvvtG7YePB + 3bsPQDTc7W3bdvN9AvfNkh2HHd8cjQJUgTA5HhCHXBJcXxsyBrjltVQFuJB5e704N6qUA6A6HbSNEdoN + 55pG+oFojKuM2khaaydhl2BPYDfACdoB+EIA+unG9P2D+yWXP6Qn3gawEhg/duz09h0nXnltU60254f3 + dROqxMxetRr4HoCbbLdu6+eb4d66rfKWE8EC169/unXbGQf3mJUjqXHSQXx9OHTpA4/0dPcc2Lv3EN4z + xEEcV13BMd++HbjfjHOvLevt3fLaa69Bdvx0fFKohGQBymEZRNMN1/sOiINC2d1wamuTQJEWnbW2b1Yd + 1iv1KNErgF37gOgAAv3BfaGvCkRvp7Mv8VOpJxQqvmfjffv2nzx1nsQM777fe+zYeVIg6MUH4ifCfTkC + 55DhPgJGzVWOSQuQCWD3nrN1l3y1w6T8LaIV6zEbb73dxzxToIHcDayNDDFkRaUFxXzXrn23w30ragy/ + oiPDJmiFgw/KQzYJH7x5nF+LRB59o7bYMDdLu4HoAER/yn1sEs6+nn4Qv+Tjq+87/GCXyY6nT589deri + hQuXsAbVciCPPvrGGftHrDEqnUu2wMS2AL7ehYuf/vZXi0lDYp1ovLqfvuz9Dzfv3XsCZxpvEXwb/2fo + oUBHN4fduPDICIcOHUvh3te3HbedbfgJ9IAqlIpSjEcr6sHEMH4T2IURogMw7ZqyjzqPxNfHT1UdBX0H + k6E/jjw9KHuRf40d9d899MQwYxvPIsO9jcbMVY1FC1y//snc+YWcYjqX2i+gpy8lCeLevadw+/C4nS4U + 8d18Vj0X6EjneI4ICJDl1Ckc/1uyzJYtO3Dt2ZjwD6ADnkIraEi6sWidUWlTQ2uUiB+4R3IJQZ93IFif + DuQ64Mw3dAN0pWys857hXr2SGe6jcnfng9wJC+DcXb36eTHF/7c6vs70yEJ+Wblu/ZFjx06i+cJuCE5M + i5N3DG7BSSd4Ay8etZcxQKVzUYJfef785dvhvlO40wEAHVgTXmQVZ3fCAGPrmAPqGKm80x/rjeHxcmS4 + N7/ANR6AXLIFJp4FiF4/dPgiLGZKJPLLj57eeOToeR4G3HCC85zf76QhoxX5UicdBQA3HGUAn9HxzwjC + u3z5egr3rVt3ochTDz0B7iQqAfwiaK+VgsHTJ5NdDh8+HDuWfu3v6pT2Kj3q/e3FgdJjedDSEQesqlRJ + w+1bPym2JKT9MqMiV67y58KFC+SOJ6mkMo4KvvJ9OmYbw6q67RPvHh7mGWW4D9OAefexaAFE9q3bTtZq + i2AxOQBIQgsXkFbAN465My0NW0yZHk46LqF6rlHVMV53W1bI2rIq3E+fvrqm49i6dafWrjvZ5L/lKw4R + tBM1A6ZLlz5dteaoO65cdeTKlVu/9kcu2Hf4yNXO7uPutWLlYQSotM6GvGPFpe6eo2vXnao08vjGjYcP + HLhw/vwnTOkCr+lApeyOK03HuXPn2e6ekzcPfQgoVw99/frPV666cVIrVh25du3z6jb1GWSf96w98ugT + 63/ty0agrviDP+oiZmn23F2bt5xgIsLVq9flezV0JxVkxuKNeEfblOF+R82fDz4CFjh+/DhQqNVmfTRt + G8lmgQLUJtwCZZwIdIBuKDr/DD891XBLunnqkw4I9y1bjxfzoVjsovl/tfks9GEsjYc7dOh8sXCHe9UW + njhxIf21Id/JUrlk2YEi/8GNvRaQbdH3DGXoEpG1NN5xvc9r1MIix5n5v5b+5u+t7t10/PLlolOsEpm+ + 85XXNhYb3zj0XKaDVQ995iya2MI4qbNnr5VOip5mxSpOoThxphd863usYVKsLcXoCBPK/sZXTZy5cN7H + Rf7IsFUpNqbhaY7AbTX+qqy18gqZt8kWGEcWOHz4Uu23VqG2Ix0wIocajnrOwKm5U2A60XV8g/YC09kg + pVIVo6lUUoI7oTHE1SjLIOPUQ7x5XVh9K+3t93rQ+l1NKf0PnJ0+fY6GRYDNkSMXGA+4OT1qxdFjZ42q + RBeCa7QKtJQuAXBfveYIaYdjUtXpM+fYyzrhe8O9gPtvf3XFH37vVm5eMEojTeZFEjRrYwaAU3NPnrxk + TIvDCRIOuL/3wRYSuN889OITJ095aIwZhz537id0FTe3WX7y5MX0pMi4uWr1Ic76ux7xuzeOeDMB8krS + BTMfmJWhVqw6hCkoBiPZb6WsHUc352g2NcN9NK2djzXiFvj0s5+SzfHcufO4nJAR5hJCx9xI+OsMI/4p + Vfm1FGvRnBf82hzu9ck7t+COE3rPA2sff2r9Y0+U/0N5OHToKO1B36eDgVmHD+O534L7/v3H+BUdCRo6 + TivOUvPV4X44hfuhQ0eiTpoSEEz3qsKdZVSf+NGGl17tu/fBHjN5xdwusrTTDx08eJYBTKiNSe386nDf + nMKdcBUOjW1BcBz67Dk891twP3z4dHpSdWMuFv30Lt++q3Pb9uNHjpw+ePDooUMndu8+umbNvh/eS8Tq + gkWL95unAWtw1eg8qtYY8RtrHB4gw30cXrTc5H4sgDPImp48+dAQxEBwBBnTnsQwqZzSFa1qF01MO1i4 + Q3BSnxtMyXuDvYuFzoaAHNR/viRuh7eHEtwJ43bKK82mwQ2ddzT3EtyZgYXixOGok2CShhBM4Y7//p3v + d9D/OSMUkYokCDt2HP7CV4pU7KS9dJ4XMg6ZAOgRqVPHGeGrBHd25NCcZhyabqAEd5aVjZPi0hw8yHB3 + 0Z/Rl3zlmx28FWAQBkJMN2Z2TJgOyXfsOOYrl5MJ+nuVyY9FyQI1R71zyRaYGBbg/g64g0WzXIUakOrR + qSPcyrlTMwmB02gZZRl4BK9xwOuyzKmQZdiS5ObOcWVKlNGWYssQHWIxg4YluG/fsY9we3BJN4AvDM44 + KYNPolQ9d1b8oH6GE4AgHQZw9xzTva5cuRKyDNL2d+5aA9ltpJO2qIFkZc++sIG5u7rVJGZ48seF5EJP + Cd/x3+lES3AnyULp0DT47O2yzK7dB7GAJ0VtHZ0Ha79ZaEq/+Xudc+btotmGpTpxzBAmi0mPaSesx84N + rdHKFZxs22S4T7YrPsHPN+AOanmFN8dhBESHpK6PMyhbDAHuKBlMYQWdMMtFLUzwa0J2yA6tcJyrsgya + Of2B3QYbtAj33k2bATRHQX2iY4PCrcCdxtBIeinY6lxcyo6dTPtaGQsHkqNx375DuPaG82O3EtzpQDk0 + O3JGHrqAezGgekuWYV3AOCl6rM6ugywXDtzR+r9/bzdJMJ0VDNmdaoB9IuGMIyVMO/A9ptrVDepSTpKN + M9wnyYWeLKcJgiEa0kGkNIkZ6qlQOwRzDB7uK7ZvR4ku1qiDXOR8JKGhcZX41CaJBNxqHUeO3Ka5Iyyn + Q7Wtwr23Dz7i6gJ3XOPW4U5ONPxl3yRMIg/HO7v2E8Ryczh01caNB8zNi++MJd99/zbNnRxpHDrtV6pw + 37Fzf5wU71L1WQg3FqRlOPehx9Zt236IJV6xFZZRRjOxsKklHQB3rDjDvZUbuIZyl0u2wISxgNNz4DvP + f0xJT/30IZ8pNVdkmd0QDW8XFCoXpLIMmnU90yQxJ6X/VsyYdSOPisEwqP9Hj94WLRNwV/AR0zQgbTza + SElzJ/ukhNV9BoK+ncRefCYgvSTL8A4Ruc/AKIczu8uJE/Q3N/Ib/+qXO/DmoT8eNNtQ83tluK8vHZoG + lzR35niFikX9ly6x2vhiVii0/ygyLdezctZ+bRVrzPZtPnb23GVGbs2HbEpkxlFSsg/5Uk6SHTPcJ8mF + nkSnqVMTg0vh4wzTBIOFu6ORKBul/5gx+/ECFuQrEqDjhxqC0hzu5slqEe567sK9tBc1MP+zqrmH022s + i0Hl588X83sl7+//YfezL6xzzQ16DiSvMtzX3vDco1/pD+7IU2pNDGsfPkyXthC3PYJHiwVp74pOkRkD + q3bvPnP8OJndijHwCLIsmWKYV3ai7p7hPlGv7KQ+r9JLa1tsMVi447n/TrHIKt4oM4PS/5ZNnb5ZwQEf + GYwO6LmPNNxRupFcUEIixob+5vLlawF31hf80TM9kN2gfjZ77/2+NBSS3PUteu4p3OnYzpy5zGhtfd2l + Vb/ztU6CL9OFU+qxmMtZr+Po0WMRi2mPlfk+4F1dY8w9l2yBbIEBLcCzxAT6NFqG8VJlmYhpSWWZL3+j + c/7H2/v6DmzqO9C3+dCWLYe3bju6bduxrVuP79lzFESyF3yXp6VJTAjLKhgKPkCQFxEakDaSeMQ1t8e5 + b9q0OQjLm0F94utte1FDw2gZxnvxyhkG4E2CMQFfeq5dYwrSDc/9t7/aOXXaVrPxEGpJ5VW4O5aL5x6H + Lk1iUnMPFQv3n06L06d7I7Yd+3w0bctf/x0krGLJQyJ5pDx9JHzftesUzn4EuUv2AS/ZJN8gw32S3wD5 + 9Fu1wGDhDqSIlWQ1j7feestAQxNPujo2HDRw2/CPsQN3fHb94oMHLwHZGwOqv8RK2buNqCGOhTa/896m + 3701Q3UJq1ZV4X7mLJGj5WiZdIiC7gfEowXRJRhBxIwEpPUtWw59667OWI78a9/ufvypYt5Z9IU47xnu + A964Ge4DmihvkC1QWGAIcMe1h+wRaAjWQZuB23jKhKYQBIKfi2PeLrhXCZtCsLnnTmPw3IX7tWvX7r6/ + SJkQuQ127DxAFyXccaIXL93/y1+6lfmAl4bqofcU617dSMZAV8eocGn8mWPBd/QWKkzTutEFMqL6je90 + kpPAWU5f+EoH/QevO8Zi8nqRnfcBH8saY+65ZAtkCwxoAZ4l8heWZBmIBqydlVNPSFuexCTZUTMMNQHo + sW4cMEVycbJ+aUCVjAPBQRxbdBtYRgPSRpJPcU3HbekHJCwHApTIHRIw3YvPzOAtDajSKuIgcZyFO1FG + Z86c2biRDGg3uKzwzSRf4K4sU8xm2kpqtgD38p0795cOTfNmz935ha903uwelpKAPVQszBWD3rQT/91J + UrQc+5jibdmK3SZXEO6oRgwM4OOzpYFAJYMMeAUn2wYZ7v1eccKwTt8spK+jXKqXerLpovDjZLtdJvP5 + DgHuhHgwg8kQclOvOF0WR9WlVh1NhadHj96Yiw/LICmhkCncG2ruVbgTxBiEVfiuurdVuINRWqjmzi7k + Il6+gqViV5l+QMl769ZDriXrvCpO4dx5hltvBEpC8Bkzt0Ne49w99KefFjOYXNSQdI+//MXV/GQYvn0h + Sx+ePHXt6tVrzktAm6JrQfDBOC5r9eIrGw2kYZbT9+7ucs0s/sYyexnuzZ/HDPfCPqdYP+3sWahN5g1e + SD/55JOf/OQnP71Z/vhm8Yuf/exnfvHzn//8T/7kT9jy008/ZS/oz/M2mfE3sc99sHAnY+3S5awYd3Dn + ziP79p0k7Bv3/NixS8ePXz569NLlK58a4e58nBTuX/x654IFaBUHd+0+um/fKeY3nThx5dSp66dPXz95 + 6vqVK58VmdwPH8baqedONph16w/u2HmY7AAHD56mwpMnr7rX8RPXPvvspyrpaShkPca8q3fT/p31vfr6 + jkybsQMi/7Xf7kjIvmra9C1IMcCdcVd6KWdIkZqNDsAUY6R1rP3imtVr9u3YsRNAHzt2nLOb8uT63/9W + pI1kTat9TkCNDuBIEdr/8W8VuYVPcFJQnmeQJ+gkC2BfvLxq9YHa37gp+/w6ifh3mr+BloB+OkXshh0m + 9i03zLOrMeY+CQteOSyGyKAZQFP+9E//9M///M//4i/+4m/+zb/5X9TL3/pbf+u/vFn+9t/+2/GZ7yls + wJZs/2d/9mdQXu5DfEBPQAJO/SS06sQ+ZZ6069dvBZDgtzKlBuLEtEy0gp07T4dYAR9/4/cIhWRtv+p/ + H+/afcHAbeF+7Ngtz50dv/g1Zj813HHJ0mXFzH6V8TTlb+Fi/yIJ2RvuNe/cuWIdD/bi1bOU8rc+x6pY + gJAPBCPqa/Mf8Sqc46zZ2xj1hcsUpHBXi3Wa6IkTpIa/kdaxOPpvFIvTfuGr/C1WHifRo/UwLsr3zDvF + 8Y9XBBzzo/VTLnILF80mG+XSr3+78+EpG77xHc59aXQwZi4jTX0M5wp3/H2624l9yw3z7CYX3NFSrl+/ + justmoPgsPvv/t2/+/f+3t/7r24WPjcspQ3Y6+/8nb8j+qkQ0FM5jv9nn33Ggc6fPz/My5N3HzsWAO68 + 0aWaewnu9diPW3BP47VLn4Ha3n0XkCCcoVrS3Jvt+OsdHZ37nK4JXtMZqk0Pt/zU6cvm2MHtKME9JltB + 8699q6verxTxiF/++uq9e4+RzpIODLLjNZt+wNEFe5edu85AXmQZuwSmIAHryEhTF+sJ8F9Gbnl89rR7 + 4MWElfVqtflAHNXFNjB8yhCug6h+Q83Uv2VLkXEMuNO7uFwtRlNzHzu3xxhsyaSAO6oLUiPkBcHgOC18 + g/cN5Uvfp/8MygfZ48Pf//t/P8U9oJfy+PIgHi+JlwP+jsELn5s0WAvUPXd05Fn1tYr4bw7rUpi70WmZ + wL2v71ix9tCNDdys4X/zt249xeAhTig7Mpy4/wCBJfNb2HHxosXbEcfZEVjPX7CnvqxSkwP509zDh8/g + gDNiyVnUavNu34W48mW1XyDNS9fTz/VOm7F1U9+RgwdZLHAdGjcnqB7CaaK28yVcdqlYXiCg/KlT56dN + 36brXf/rEYt//vrvrl6/4SDjqOwO2dM8l+xYXyv1k1Wr9xOWc3N3anB3PhS1fTiV6J3DCP2m1aQNBP7H + CDPnMtiLOKm2ryFyTdSC9oLv/Pnnn0NbhBTIC6bB8T/4B/+Av/rpYJ0N4C/KjM57qaRAZ68BC9tTA748 + fQZCDSI+bQDx6om5jF8LwAVcBN7KmJfPBBo0FVJs4UuaYtfoFIRjBiTPnj1Pql3WYWWEc/36jSgSZH3B + 2962rVj0CWGa6TubNxdCNkOLxvZduIBI+El9x8NsQ9Ld2JFEvumO+OzsCOMg9alTZ9jxxIlTLKEBQxmm + re/VS9hMejgSljEIiaLiaOe5cyxmgvrPghj0RlsY4qWbWbVqNadDtVTuGrPpAuKcY6SEjCAcPHf6Myqk + 8voCTMQ1Ht29my+PHjzIRK19fM/wKSYC66acZDiUZhtwSffAXxe53rcfoYn6TrEQyIEDJ44cLZbs4Kzx + 0+1gKDTJzDaG9Oi2j9/baRRaPmHhjqSOAo63Dr7xplOsA2g4LuL5FZWcldcpfJm65ANy3A2oJy1+ST30 + JXQq8h05iP4Dyo/CFc2HGCELgBKAAlaAC4iBOy7H6uIYASzYB+jBPVNyABNQM427c5coMI5iqDuB20aG + uAA0oMQrZ0c2629HcIk8Yow8CgnHIrwEalNbHC6mSqWHI9gR1xu28q7AgfjA0WkGbRO+sZctjEaamtg1 + oSS7A31YA+EbOhPQyQb0CtRGG+JM7SH8pyknjet36iz1YEzUc2qmk+Os2YYaIo179DFmS3bpkoiD1G0f + oWs9MaqdaHDHWyfoBaQyQIrvjMMOsgPTMNfPeNYQmZ8YRMWtRrfhVmP7FOglag/qn/Kd+uG7bwZonTQs + 8310Hpsmb98NG1DdvroZ2wCUwBneLnCkuFQejDPnSQDLJblBalpcx5VivnLzuRvqTsH/hXTsSIfRcK90 + R5dGYhdwSQ+h091kr2gqfQmYhpKgli9jr2gYzaYBJkhQzFE7CrKHuYhX8XyL/OydnXQe1kZPQw9k8nrX + ouKkqMcZW8rlFD7QpXEWrmCOQaIx1mDue1eJsjMz+7FBkNGM0bmpxt1RatBwwhTQafQLmFZe17NO/XEZ + 7a+47Yx/4llzo9QzJV2ueuKDYnppY/133h7Q3yE7XYgx8hPG4GPtRBzKpvA2ZuGbevk0BrfjEWXEu7Tx + 9eufcEapP5ieILfH558T9vr5lSvXYAtAB0kuxwrduH8gnaG0Z8+eg57Ga0MucrhDND6DPwqQouDsFznN + Dx02DNccxZCuPhUWzWcX27h9ugt7UYAsczDQcIhHZC+wqzbCIazcsmlTH1viJtNO9uIvCHYBa+f9x178 + yr60k9hC1A5EHhrv8lW0ny31tVMlBMtg1c8//+mnn3527dp1rOo7hKdJz2cxPzBnx18PXQ8NusFlHgeU + Li4NtZEthuPSNNpJn2eha6E2W14P9bmCeMUl4NC8agv3uKBj7W684+2ZIHDHL+ZZZRgTTxxkg1TAmmJd + nz3gywZ0AJCdR5F9HRri4US9GQ7Nq/tSIe1BIOImVnZHL7rjV32iNuCRKYT0MVrIf4t+4QvLa7/F0BzD + m/zzHVKxO6MnXudPnWKB5rn1gTtGMtlm9vfuXsM1cr5+UANb1YOsfvbsCxtZrLlWm16rzaTaS5c+xQV2 + le1wabfvYN7mzN5Np2QZv/LCxhjs8y8U84NcFkrHuR4ucuilVzcQTfjlr68kzfrNBPTE23x49OhlWMnG + Bsa4PaVIfruDDYg1ZFx3BvsuWbqXfWkD20Rx4ytXrrPNXXev4cSpx+WoaKrLM7kYodl9T58+s2790fqo + JtVydstWrz5IF+WqhAbGpDIIneL2HYwA0wwMOA3TYUZmJHEIm23hM8e6+z42m3H5ynVXrLUqifzTn/5Z + ccRf5jJ9fPPCTSXSnY7TtPJG+NCMy5evvvfB1rr9ORwtnEd0PJcmvaBUOFFv7KGd10SAe+gwaCDoLQI6 + jWMpkV1BBuCilmA17j/Izi3OI60W38bCoXlLwHnneQDruGncghBkaFcr79XcAmfPfnL8xKcnTn7Wu+n0 + b32lg/mNW7edOXrs2v4Dl3H65FR4oKfPENe47I23tx09iid+jZyPJ05ec5CwxCBG5eudxMrDhy99+ulP + rl79dOu2U7gTsXpfxFzXQwOXbt5yzimXlPPnr/LNa29sBENA6sb4YR1z3AzvvLe1Hnq4kmWJlN0PHiRA + cMHxE5+wr3kTbTbb44XMmr2T7LjsdeXKpzSju6cg8i/8jdXnz19wY4PZXXPq889/xsaPPs6yGyfjV/NE + qpjzgX/y+Lz+Rh+NnDNv99WrnxHhtWz5fqq998EuoB9Rj0Fk3oeefm4d27/yet+VKz/55JPP2Wvb9lMb + Np7kISqGjB0jZcWp/ftp8+NPraUTonP1G3N+2Xf+7Gd/QQsfeGQ9F4hLcOjwFbKV0bBguufOxgsWEhe0 + bN9+7P9T3rhOnLxKuBFb2ldFhfkBSS1Q4w4bv4VbhxlDYFodxlHTf/gP/2FpLBRY82VaYC5uPrcXjwHF + QAj6Br4vbTnYf8ax7CEcvFX/4S2Bd0kOyt/xa/Mx23Jua2yrLI4zW48RXIGzjlaAG6jCoLoNwbnidbgv + xAMFRvyEn8g2xp67BCjsqHuXf1wPzltx8eKn7EsNbqwnrtTAEWXfrgLuS7ZuOw9n+am+5EUB9zfe3AhG + /cbtqRyqvvv+tt/7g64vfb2D+s+cOcuhyeyCG3vixPUAZUSnfPopsF781T/sRBeifjamDbPmMKd02fbt + xYpFJjOI3utnP/tTGjPlyQ1YJg7Nr4JVc1EuXcYOix9+bD35NTQFzXvtjc3se+jw+ZI1CtnqRHFGTz+7 + kVhGX1CwAwaBwr6X0Dadfc6ROp/8MT3BYroi+7bUXHW4L8IInCP7cpnQgvTZXcZEQ3E1732QSlYQjMSX + /KTlOVbY34tF88bs/Tn6DRvHcIfsEFmy47Crw8jTKFWsC2vHVBl0ZegVjR4xh6FXXf7WaR4OfrUvSVtC + tSXnHRDgvI/+xZ7YR5RWPOSQhfnrAAUcgBJG6ijmdXFAT2ScPl1kAZs3f8+FC9fPnr18+vSlEydOu66p + 3NQf/OzzPwFz3/peB10yWAE91KPazmdXQI2eoA73FbPn7kW0odqLF6/3bS4SbAF3WiK2AJzbC/df/mLH + jh3Hfu3LHaTiQrAm3wBwP3bsqp0N9dNge6Ndu4t177q6DhtXAwdpxvHjyD5Ln3uhGJVV/Y/G/OxniB4F + 3DkRfqLf8lduv/DvUJzWdBwq5hntLXx/tuG8bjZj6ccLigM5mmoHxtvn2+8ijyw7fbroYPiVRqqi2Il6 + FGCt9RiEEO68EPATzUht+8d//Oe08Mkf9547zyVgXvclouY5L6+US5RwUET5D6dy0JWz5+4+eYrNzmEB + rpQDHvDdw2W4lx7wcQx37huGT+EyAnro6Wl4YnNM61Ozr+HtuvwtlmC3Q7VpaHw1Lj7CIumHeM/gcSrc + xtOnJzZqR//sAu7w69KlG3CHSoRqUFwZI43WqMN9xS99Ea8ZGXdqrfYm2VEYxDOoA3yIVPwHAPTh1IIg + cMdxTodDRVX0FnXPHUF8za98yTqtdsXXv9MN3MG0Y4N8qK+rdwPuVH7mDDIOvcL8Qrc4cBK4o/84dmra + SBhH5es38tMy1vowvMSxVm4lanjkcVat28H2Th+15QF3Dse5G11Tnw1bOLleILg5c3YxBenY8YvGRzqG + ebxYQHXJ1OmE6m/UbhiknjH46o+e2cRPFy4UsOYnctG/8tr6ufO2TZ22CTFf2kbXGHC/cOGK3QadAdS2 + hXW4L2WGal3rx1Yf/MKvr8Cwnkj0KLT2Jz/54zff5mUCcQyVf8EvfXHVgYOnaVXaE2e4TwS48xjj9aBi + 43qnPnuqlbeI6SFsFoI+TKdjoAGmH/BD9BYp5dmMNwNeEYjbMBqS5wTKjz4BJ/AR9UZBBuC4epWxxMJz + Z/6OcDfo0NmVOpV1uC9ZvHTv8eOMuzCh5iAb4+MHywTQp5/+nM0eenQtfQZkpx7YB4AgC9gNSVqtow73 + FYsW7yf91aHDzPNkRhKy+Ko33iT4ZB3xfOyrpJPAfdHp02epCsx1de/v7SUj4+KDBy/QEnuaulZTePr1 + MUwSmhdCEwjmV9pz8hQUXvrEjwpXl2+cQer2IctwOENuDBJPnVzeIJcsLeTsAwcucFLEt1jtocMca+ns + 2btMw+s0JfoYnrsXX+nlJwRRjsXGR46cXLf+CAvDYiUOGnDXegH3c+cuUS3Npiq7K1zy+oDq4mee72XQ + GlvRs9G9cbiIegwRybcNpo+dOHl+1ep9v1kk7Vm1YeNBanMpKw+XZZn0Aa9FVtvx8oHWg0UEGVRsiKka + U2X0f92+klYePjtkN9kAejq6kAXVnm+cCpvC3TmrvGQQ8+6wKo8BlB8vNh8v7cSw8v2zzwB3AXccVfOn + O1cofX8/fYZtFmzbfhrwGZAe4dj1+MVClrmpubPC54qzZy/JPulvcEsI3HYtrAkK4zZvPUudRG1TIRJ3 + XXPfALDsY3BdhTt3ArIMojNwB+V79rLlkj/6fqG/HzhwjjBzmo0PS7NF4dWrhTj+4KPrOC710Bi0kM6u + QlTpWXuE+qmEv74ZsP3Pf16g8/GnNuAC6487cZ9D3wbB059w3NffLPoqaqivhbS1PnK7jMXt7EW0npLO + jp2c47IZs1Dnt9oD4Yl/7VvQdjkRohzCtxlpy6uqsgxwN0SSLoEDSe26577onfe28SXmMqTddyxeC6yE + S8DzjiaGEehg2BKbTJuxnbQzv/alBa5Da6oZKhRt4+V2Hel2jjO4+/TqthOCAkalbcrftlC92lukCrtK + i3lpeHugm6Go3TshNvz3UGzShAQmgjfAeaQv8GSr3zukPgpawJ2wEQEEFGCcCBDEdbgvnTtvN04h6WNZ + OpQ4PSV1u4GQL3buwo1d/O27Oo8dO4NrSQ14F4xDOmaozy5WhPumzUWHAcqZkgOWhTuUNAFAI7ifE/r3 + PLC2nkORPumMs5yAdVAVh+axJ4g8Wb6mg0SSzB46WM9IQ/TnQmLeOaJDC3Q8Nl7P/b6H1h0/TrbhE0eP + MdhYzMQOI9hmOkKSwFBt76aiTl5idhVnQbVLGZ60WngaahKx7fUgyBVd3cwyPUpHdfr0eYaFMREGwdPH + hrr53OQluMe7RQL3JU89vfHYMcKRj+zdxxkdJuwzBDT7VypZtnwPKiwjyRibs3hkyobaL65eu+6gLzch + N9lpTbZ7vr/zHWdw50pzJqrtBreU4D40svcnzpRiIiO8UjUm0kCa3h2+x7TY0GcU9N2enkDZXbjX1YOr + +UZsuwV4vMm6b7QMqNLJRcqoL1VawOKGf1fAfcVXvgmVIunVrN279/Cmn8Jdz3H/gfPfvostzWmFIz// + 0qXPnZIacRqQpY7FJZv6Crinnvvr/XjuOK11z/0c6MdVP3SoUHU4CnBnciadAfVALl1mClN4GAE2a2P9 + v5XPPt97/sIVhRo9d+CeeO5Lv3UXqRkLUtdPczrat68vhvf4osPcrw8+pCVkcPTsVr72Rh+rG0S14bnX + J5ayItVnU6dvv7l9ke2LlL/z5uOR7zAbWnQwPKpIRuG5l+D+07rmThrIm4alhdNoVwx7eL14xZm/oJCt + bv63/Je+uGb7jpM0D6MpuKnje3HbfkeN0wprLio0LgqXjRsRb1dNBge5FLk4QmRPsxeYVCAEGVx1HHYa + 4yIeOu8hzui/W+wM2IbGY23hjgQ/Liw/vhrJo8hSK909R9ZvKFLBlBSJePg/+eTnPWuPbuw9tn7DkXXr + D+EGMvfTVCcmUVG+oPAB/5TVXBYt2nHvA8unTe87caKYGmpcuVMu9RkvXPy0o+vI8ROXARzyAoVf1qwh + Hc1RXgjU3BEchC8voCT+7eg8hNCIawyaOXpX9wEcc1JoqVGwvbKM7wfcMxxoz96TL77c/eOn19BmxH3n + hTojVM39pl/8866uI72bjm/YeJQT5D9agsJhxGSI1FbLJd62/cRLVPtMB1khmcgV1YZQbrUUPnC6u3ad + eO2NdY9MWbVi5R6GMOiEOAVO2XPEgJwjU0l27DjFOTKZNjR3XqEE8R//7E9vtPDmJVi1GnseduzX4QEN + yzzYM2evLVq8++77lr397oaDB09xmSA7PShH5LN1Fi9kBOfnUrfAeIK7vgbvlU5GDcG9FFoe7nbrg6VV + D70EdL3vKOZwV20PuMt3nXfFmdR/F+5OVQ24cyL5Pmy7BYxEgsjQAUHWufWm5FUN0xEDBMae8yu6vNlU + 4KOv+SlZwJmCLxCBXMAuomVctkJQUjP3p3WCJzYDZ4ZL0gyOwjcmJHBqhV4zn8G30S8mCWAvugHbw/bC + Wi+b9gNNo2WozX5LaNqqGDK1WwKOKNdgGveWc1RgQf+h2fLdau29cLdtZKnasF70dlTLWWNSaotMAxzC + /iw0HPs8/tKZ0Wbq8eh62baQD3DZ3GGQWk88NHdPXKnNKUvmdbAv5Iy8ZBjZGeYZ7unTNG7gzgX2HU24 + g1QAaghjWkop19PISPuA6uzThruXaF4lewylqrlDdlfmo9dhMMCcZcF3PX2cepNEKstw4zKtqe1oyxUK + dzkIN2EBxayNIjjgDlkADb8CCHgaebIiFFK3MfBHbQbqRXIYAJeO5kkrQANknY9jfgIA7TegLYYTfRPl + NjBE3YVVqZC/euKmJAsU2nlYP5vZHwSLjTI0EMXTjGazscOtlEgEFs22j6EZfGMnVKrWqMR0xNLt+TK2 + d6jZUCJToYWyb9docjF+crC61E9QDzvaNyjslA5ahXs9TXEx/GtAkS9DXtz8CGiBGirHuCjcIsKdIBPU + DOBuxkfjUhy3VDDRrfZDxLCXMoJVHfOoIeV49bPVeggaoOzuMnvCveq8GyLJxmzJNsKdm5u737D3cWH/ + cdRITIqFg4MmWjH6BUbEk882Os78ahYwitHrzovhGgELawu48BOsjOQnusDhM8prk3nxkwII/zQbgd+E + 4JNWawfgxH235CgU4xrrgZsFszwv7hw2g2jgkgbbi8SsH8mebhyzkzzB8NxLzbZa4BvVOovKyUTRBmuW + 7+n2rv2t9VLUhumcc2tWSAfPPB0qt5+I2WHVFqYnTpOcyxrnEibNT1P6nI4buHMjpp47PDVBWAAd19il + TSMw0VX00tjzdLZRqrEEslv8ELwuwR12I7zQ8cBxVwjReXd5Jr4nLwdKq+/L3NMokmPtdmTwynSJ9FIY + mfcSV5TljCj8kxPkV8QlthyzxMeq4RebYeJGyoE6Imm2iJc7kMhsAc7R57Mz/gWQWwaIuWrm24psLYaF + pC8E1MmX5ngp1Ot6Fpf0m6hZZvmrCWE4LuzjM0exY9DJTfskd6F+QEkzos3hXMfGvsFQrdmTPEd2cagg + uoEwF0fn3K3WE4xsDXYYmkJr+PZpvxXJEiJzQygkcY4RPKpcE5eAf/JT2sIYzEhb6BG1f9oXhom8WGP2 + nhz9ho0PuHPZuO2ce4KNUDNAj2nCdKIVSRzehD6uVS2bVMBjhlEV3/402BIdSXjuxLBT4HvqvLuaNoW2 + 0SSXZNLr4aZEYvIWH/0Lnx6RlyF4jbnsF10oPNYKjy5KE7lQeKwSzl70WGMN9FpVHcMxQKVb2RSQUrvw + pZArYhHHKdntDFR76o7zkb7NB3o37evdtH9T3/7NWw7u2Vv4+PI9PajHVVyOlpR0YUEZjWQztzQuRWk+ + sJX2NDab58JHwxGpOLu0A7M2uw1KRHD215JqtRhv585j23cc3VH/y8ysfftujBkYGlBEULZQcxik1GuW + LkHEIEWPEv1rei7VE7mzz9FYO3rNRYjGeOEaB9y5zGmysIZwh7DhRBu+UlLAQ1oZFNPlWpSQZehR6E4g + O4gMuBvz7tsDDaCbYQM0Gcf69OnU6OkM4KO5xSmjeS1oj+sLRgiQhgo5qzSHwNm5TuAqsZ7zpfG8l4xm + +5scyydNGiJUILHs2l2A6eDBk8fQLW4Ks+GHSudgdPS4cYiocMfOo3c/sO77966N/956d6sUDs03VX6j + GeFQWxU1p42MX1MHudqMdC/7EkvqJVTbnG4ZjYxmRJ1pN5ZWu3PX8XseWPeDe9f6HyfuKdt13RzsPbF7 + z9H9B7DDjcbgne/bj+pCt6qZb5TqcaPvbHIJwlbpuaTe+hi58cZOM8YH3NUZ7ai5nKgZMBSXWdVFRxKA + hucu3EsKuNhqV9Fz54gxoCqaS8oMrVK6oTFmhVST5dWSz5GAPuSjGCoQuIFRfX+7h7bcPdRDq2ImrWMS + DDj/Ny0XAk/ZxflcqUdvuGdbGjnMSiAeE3Peenfbo09ufPDRDT+8v8DTfQ+tf/Cx9c++0LdsBaLHbUQu + vUI1PDqIwXu996H1f/SDHv+76561L722iWvKLaqEMqA+UKp5QI+v2pL+dml9y5Swpc6gWjlwb3jKOOyK + pVu2HvnRs5vueXA95n3znW18R5jmU8/03nvjm63EE6Wdn32bpfnpp2fU+lkP886ZGLuPJ7j7yswtEmOq + RpQ3hHvKWZ13negS4kM2GdQHXXK7E+EO010ACP7qj/O9+gYMRZBByDarjKIhSiVdFF+6vXOg2As/msK+ + FKNuSiMHhgPB/VhGagg3Iq11uMKJAi3zvN8NqaREeRrPC9YQ2tauXbZuO/biq1sAOm4mU2yCxX743t2F + +/nqG30wWQkYIjfkXbU9kA6ERYXfv2fti69sMAltOmyb8qtdJ3Wn6ml+yowUPP/SZuygTXitWbh45xM/ + 3oiF45vlK4pcAoM19Z0634lx3BrEGfvFyIdQZjA9XjBANFWvJTx3UasCnsYmpnAfFMqrGwt3wQ2RaQnH + cl03Pij3pyOQLrMHQSA7AcIMB/EZ95btfb1g+yj802GDtDhDynFa0xuE0+1iT5xyK9eRZmA0Q0hxvaH1 + f9u+Qm348mnMEl0UrwitNKy92zDN5+Ept+BSIrv/RGd478NeroUzNrki4njAlhSkeziFe8/zLxXZtSLJ + F7dri1UNeKwxskHzUyZiKDUIuddffbP3vgfXhdnvfmDtB1OLeMrBmnqMnP44bcb4gDsPXjoWpDKDp+xy + qf350WyQojZGCIPyQW1raL1AWMlecttTz11YA+jw2Q0JIMqNcwF5MYapJhPKRnQbMT1KNT9K9FhsWQI9 + YKVJuMwNb0eMRrNxscW6pX1sv1FTID6m5rbY8bTrETp1+twzL2xGLWnI9PjyngeZMV9MGop8tgi+rUC5 + SrpnX+xkQimR8sRxc4nxT1F4Wukn2nXKI11P81MmuOXFV/t+cN863ocw+30Pr1u6bN1zL677wX3FO9P3 + 7+m596G1S5cXGfAxtUHuPMITyT4jbf+h1T8+4M6tgM/riHwEROq868xK26pIUhLB1WeUaJoXN6uWiLP0 + WOJbt71YhvmmLKPrzdHhLLxwch2eC7HJeO48+XZO1ADZXSQkcie4lohqe4zZeiB24Sj0Fpw7fz0cTj1G + 4HToHpTpDflnF/z0uC1oCZtRc0lbaTvcrZCjeBY2BruNmgu/ZNk+QBMQhzg/vL/nB/f13Pdw9wOPdt/z + YPe9D/Z8/94ePsydt5gpjmZepOtt4nGn7+lV0j3zfMesWbNI9UVVBAVyiw4BXh6iyWNc0gpiy/i+v31b + xGhaf1oV3w94yn2b930wdeuTT2947qX1M2d3Y9UFC1a+8Vb3lKd6nn1h7bQZHUuWLKXzoyt1wm2L/SjN + 6K9VA/KulR1b2abUhtSYrVyvAds5chvUeP7HfsGIAXeVu3DeHZNM4V7SSSKCRVkjTc/bH8FbITtV6Vmr + tsNciu8KikL80+y+3MqxGpkz/ZxnC6DhNY0HyqF9g8V/9I/+UfDRQUszBoNvDsoR7UtQdeA1xKSf4AOH + s6ujP1C0seDa0yq2obVU1dxV59DtLSI+xgkM8x/p8vzLm1Of/b6H1r7zXues2YtmzpwzY8asadPnTp26 + 4MWXVz/7wprZs+csXLiQeZXme+EF0cfVFp48xWLZLCLK0n3EQd4aACyT7t6eZ55bM2PGDJz3NR3d69Zv + 27O3gFfpyW941rxksOgEItKJkwT2lOHOLqR75Nddu/3vxN59RQspCEi0irYdvtGP3NYrcBLEDLMj21T7 + i7QlnCNbUg//HT1GUOaN0ywRh0PfpkQlp8zcV+ejUpjw1NOzcdHiNfPmL6+nxiGdwApAzyfsbD/qm2vY + J0zNmrIc3eOSdpMjxn9x1tGqOAXaP6gdqaGVU25ieV45OCJto5GplWzSgBd0pG/+tP7xAXdabCxtOO/E + nHCLAzhIarouPfeSCK43HXx3nJNtIpQ7WN/iB3b0KKGZhDct3/WsYS7uuRNkuPVxDF21x+UdnHZh/ySU + aZXxmnLZZaFCPOGD7ry+PA3gREC8BzL6UD3BKUgp5XXh2XhAkb29WI/a6KhsvJTneo3o/Q2qHn2iN3Xb + n/xxNxCfPn36tGnTQDAu9uyizJk9Zx4F7jAj3/zswp2nd3XHwVde34pqT4gILwEPPLJhylMbX39r64aN + h7hqxFNWSTd16rwXXu588FGGE9ey4vOrb2zp23LYsJmgfHriW7cdf+u97VOeIs3vekYgH3x0/XMvbSbC + xCDNUId27znJBhGD+PiPeglE2bjp0EuvbaFVtI2WPPlM74JFe8jo65SJ3r6jL7++5QGig+otf/XNrZu3 + FD1A2hL6jL4tx95+b8dDUzZaj6f52JMbiXGkfpsRLxMN4Y49SV1ZT222vWftnjfe3kIY0v0PF2oML0b3 + P9Tz8OM9L72K9tVBzhgzfJnMnWc53mywA8149MleIm1YT+qNd7b19h1evnIfg7ERdkkcDlFIpVMY7I50 + z32bj7793vYWT7lqebJXYGesTVNp3opVxfLfcbG2bD3WygUN12FEnwIrHzdwN84k5TuPIicAy1wHVWRD + yapDrU9tkKIjkyI+ishusTQkO92MrjS85pEwWZKrGLsYJr6hywc7A9v1gBzEg8js67zQUpi8SgtMDDgq + 1+jFczp0XRwUO3CTxVwY3CLuIWUrzpcOgF3S3qKhFDNCcLdaX0EsNGnk7ux9+08BqYA7mu9jT3ZB9alT + p86cOVOa40K6goeZTFwbSOLs3HUCvR7SVSV7nudpMwjyO8KsJWTlW9Ey9/Y8+EjXvQ91Iy7Hl4DpwUfW + LV66i/UrnI2ZOPIXPl64l0YSyZO+YVD//Y+snzpjGyu8Oh2JewOqpjGIdBvTZ22nZsCddmA0+K13ydly + +O33toKetGZ+evTxDbSEqVm25NTps+99uIMaIpolNRctv/ehdR8v3GnLbUbDlxXh3tHZ9ebbvU1qY2zj + o2nd5F3GbTcVsGMSmGTx0v1F15KEM2F22k9XGifIN0Cfubq+shvTv3jpvkHtSBD1O+9va/2UuVgly9P7 + vvx6H4PwqHyYCwsvWlJkkKZJhPvPX7CnxQuqsz9y9/9tnjtkGRcllBn5HuIMjYfdEX0o3FNlRlc6NJNq + 3GGEHhqA2LCk3UBI7frscBl60gwJaxi7A6cmIQHu3NMUcmKYXQSVJibEKz56vamEvoHaZD3glvXpMiAx + 9GqUvV45HGdfjg4UzFoTYaNUrtQeIY+SfURR3rByDuq4Ai2h2SN01yGH4N6m0Lz7ge6nn1/z0dQFc+fN + B+vICAx7clEsrpan4L5y9QHcuv5GYu99cO3yFVuKFIYbdrECRhLnTqh7d8NoywceWUem8UjMUldvzy9a + uh9Xvb/BXhz/N9/ZxJIgZrbZufO2yJwf3r/27vsbdDxFAOL96370LExsMIwMj2hJZ+eNnGLw+vW3t1XJ + niKeiJfOrhuLYtMMQvvLLyvPr+FlCCUKe778em/z2uD7wkU9JhTDGsWE3VNn3v1gB3VW7cY3nGZcBWp+ + 9AlS1mwxLQ9zCcD0EHZ87c3NrZ9yvZu/zfIYhKVUbo3GP7Bu/oLiZmABgHkf72j9gvI8yt8Ruv/Tamuj + cIx2HcIUHFHMFgLR1CIcWoyAQpzWUMP51aJEoyxuoKG+raUUj+g/46fYwMBHasNl5tA8sYU3dDNjlN56 + 5JYS6CYtMS0UNyin4AT3cOi82F71krCopA6+ZX2kVbATshvjpILv2ATLOE8KxLNvVee5U3wH+g7nwndX + HGx7wYAfTtuJ93ebU3wPA6ogvmvhQpacLsIfnWpAiV52+45jeIhNnv8HHgHuXcWaoh2b8G3T+quE8lcG + cl97k0U+t5ptGGT0bT72yBMbY3ugADIAegplBgmWr7ixyNy2bYdTqoLp/o5VxKXcWw7nj0bSkudfYt3X + oiU8R6s79msi/HpIet/DRRvS3WnPcy+u79t8Y7nBbduPNIH7oiVb7qkHPiLI3Kzttsb84F6GVUn1uI5n + Qflr6fL9CEf99XDpOdKqZ14gR2aHkaYfL9zxwKO3Xdz+LkS6I4/h0uU7hnPKGESf/eaVXTtz9nqatHzF + poen3OqiBrygvqyPDt/HE9xBoUmgTLGU+u8Yy7DxoLajmml4CfgzyCQGPwV9WpzaWvqyFImo0i3TAbS5 + NSIYBqybY5b7CZRT8NN5otBhnM5ndj1eRKA2bY4mUa3aTrwHcAing8fMch381LU3PpITt7NhAyo3oxNH + pHl49wg7eu6hzNxBuBtIY7gkbR4JuJNm4JEp66s+LE87MTPPvbSho5O0hUX6B/Ox0DGfPHX6tbe2lfQc + kAdn73+kiKthx8ee7F6wYBG+/7LlxPaV4c77AcrMD+/vBmQpbh54pIeVUM0mf/hIoYZHx0NH8uNn1y9d + 1j17zhoU6lTnefo50jcWfm7vJkLIy8f6IZE/DxKn38OHEh85R/B6/8NriQgq/Xrfwz3Llhct4Ybctfsg + Lx8Q+a13Ny1bvn7Z8tVz56149InulO/Uv3DRjQTx5NIpKVHPJJ47iY1v1ta7dNnaJUtXzpmzrFTb3Q/0 + LFjQaeJ1EuA/8sSGlJX46bT2gYeLuKZSF8U/n3uhiDRFSeOlC5IOYUe0/k2bdgz+lMu9CMqbYVf3PtQz + ddpqbgWmONAvehUGvKCuKOJg8ig47zUQM46KWVlS8T2UuMClHrolAgcVxKOIUXEf0DfEMC2xvUEpOtcA + l+5XpgNQHhUeQlAe3roJY22n8kgkdbKRuuFOX3JKqlKSeeENhmEbFXwRD7Ij/5Q8UgzlV8Uci83jV5vH + T8g44bmncA/l5L9rRwHWdCFmR2BounmVhgOxCw3TsG0snDJGXrZiz0OPoSk38GT5kqdxzjzSu9/Ie47F + GA17eMptjiTbvPte55w5i2bNmjNz5txp0z+ePn3h3LlzkeyXLEVhvw249zzQ/ebbiz78cDrDqo890XUb + Ih/snjFzNdoFTiujjrjtgWMOMXNWNxUyEvDci53pXqB58ZJiacC167ans2EL+aU41gqaNHPmgilPdcGa + 2/uS7nffX80KfXPnFni9KxkGoIuaNr3It17PqL6PSaRr1+1GLKRtLk795jurQXDSvJ4Pp65x+429eyqe + e4cBQvVT275g4Y7unl1oXC4eixb/5tuV2j5a7dj1ytW77n7gFjeB9cNTembPWT579rxp0xc+9FjX9+6+ + rauLSNN58wtVKh1saHHHItp127Zo5BBOuS589Ux5qvOjqQsJu5o1a/7cuR/Pmr3iocdSi62dMaubiNh+ + LmgHFxRc8GzqvKdPbhsfgahqnMEdloXzHpQ3p4cesVZTuaYYLBgECemjvwENJZGb0WbFdHRzHTlWyVUx + faBMN2c3N6urEAB3e2azE9dHWm6k9DOOxYBF3gwifDPNjWOymtKsVzV9B2ljyNQUsmk6wDhQ2lo241gB + 90gBhuqdau7DZzu1UQnVIu7TSIxDNwnBm9Qc+jvKUntva+FOOisk40efaMx33voB6+tv9SKSKW1/NH1X + quTcff9auEZEDfyiMBI7Z04RW6P/uHxFMeSYIvXhKZ3vv//RBx98wLDthx8tgr+3EHl/z9vvrsTdZ9j2 + 9bf6lC/8DxGfUQBqJnbnvQ9WpmClt5g+Y0Wx+mvHphLcYd9HH9GLTKVhU6ctphtIW/LIlK5p02fRYOqc + Om3JbS15oGgJHHetcB4fFzPp7mYhqlWLFq94/4NOHNJbysN93W+8tRpSIz70rL2tjykUj+dvwd2k863X + 9t4Hfan8xbV47/01tBkRn5N6/c3bTMF4xjPPr1bff/Od27QjLNbijnau3JmtN7J0ypjlvoe63/9g3kcf + fcRIsoPzL73aFW57KxeU0Xvjsgx5yHAvP/vYhSvEdbKESpMmPk3z3hkmmOobEjDyz6UesZlX4XIAFJTj + gHtb8GZtqmtuFF11w2AcJmIvgW6SvOhp6FocEjDk0UWaIgbGPIvO93HifikJmiHz6vvpS0PaKg0SLwqi + n8ZwLFM8xlolVed9mHBX4TEYhrMD7qbb5rhNagb9ykQ0DOO0ke/23xgfC2zs3fbu++uYuMTLflXevefB + tdNnwvfdvF8980JfOo5KROOcOfMlO/AFK0byuYxRR2dfCndI9/RzayA7j32dqktS4MKm517ooIbVqzun + PHXb+OH9D/fMmLl4+vSPmf/07vtrUrAW2PpgBU59qSOJYxn8Uz3Wj59d/eGHH0KferRng5bgU4MYl0Mi + aGvZ8m3PvrDhgUeJUTHd4y1D1anaMX/+fPoYTvm2dDoVuHPvESWwbMX2Vmp77sXbXpIeeKQbVBqoirVn + zlpeMiBwNzLnmRduGy5ucUdfL+iBBtXI0ilz/zw0pYvuG/PSTsjOMoiPPXXbEAgXdPqMZhfUnpJhOSO5 + RxzuOrbjq0BPR8OqiI/kkYFaaSu1A9yyO/xfw0u49nYVgXLcc1fGcXEA3ByeCvreNMrCagV6SS3RVY9J + pKaFCQU8zQFgGEmaULc6NxWhRpUGcnFEGq+7FC2knSHx8xM9QcCdYErDEAPuyjIpf//7wRcddgr184rA + iwJmt/Pj7YRf+6uSn5TdgTtmae/tp5W4HBihEAFWdiGwgPiSGs67P4L4mg4WG9qZajJIGU893TVz5ixZ + wwPp0nH04pwXZ7dh4+4K6db4zAOghYvA9C0GiUj0nGXLVz3y+C23nbcHGgBM/c/Y8NTff/2tldS2eAne + 9G1hl4jdTY9VwB3uQ7RFizuqLeGMiAHt7d20es3OJ5/eiOPZX3RQveVr2J53ldVreivNKDx3pibVJ+Xu + 7Oze++TTva3UxrSmx568zQ6IS9OnF247VqITXbIE1atkwMJzx7RD2xFTDLaRDU/5R8/QhRcdJ2Rng87O + niFcUO4l7iIeXmOgQ2No7yNgbbWRqHQU6gSmkNexyoh8COKng64RGh/sFt8Wd6GG4Lgod4EbLgNABxA8 + 2EbOxcrCqZMefrrjJMa3NPTWI9NAOlPUAUZjBE2iSwcAK+F7qDRwUyFeicbgnIiKcSkcW2sxTsbEammk + fPBdZWaYcKcSJ9DSaTFswM2KMW0G7e8P7nFQ96Vwam28ZxwdwUqYiPZw+Xi2Fy9Z+cprnSURAwd52ozu + Vas3MPUmHc9kBA+aMN0JePE0mnzG8XCu+9Zth6qhI7jScBD5ZcXK9VUO4kaTe4bh2f7iQ0rf2yUULw0L + V6ekq+sha5oea3XTX9GaZgPQqdM3NAGxjVEPoZ+ge1vZ6KRuwr1n5uwtRIk0T+YTtTFT9cHHbtmBM3r2 + hQ6FDtTq+vKttwUj1U95deEsz1/MG1V6mVrc0R5oUI3s55TX8HLGXcEbFaE/PWu3lsa6m1zc6ON5/+N2 + 4l4yzC/DvfGDj3eGjeBaFKNT9F7TIrstsY17BcdxzKUSvnm456ournHstFKd9PDTY36awyPGsRhT73p7 + 4BUlPead6udKdn3nKtmdpuTaUsA9DauP+MsYNS0NANByeiD+8j3NEO6RQjKWC0/bEKgdrOPOjtDZGVU0 + krZhH/oYVUV+agj3tDtxTNX0xW2Ee4x+YyWnHXBxXQX7rXe60hiSH97X/dKrnfjUj97uU095svAldXIJ + 8DCQMdKh1COgbwkLAhc8hYJRhXsh0c5fRvhNi3CnzpdfXQmIP16wsgr3W8dqwMGBWzJ3HnWW5k8Vrw5E + o/M3WiiOoSrMrapDau5wc8nS8giELyL91TZv3rLSGf342QLuYe116wlrSZJu1s3LsXDrh7bjEBrZzykX + tuX1AkAXkuym3Q8kyUGbX9m4oHT/UEXZPR0dbO/9f8NzT2NIxuNnkMoDjA+ucmJEean4vQWCW/Rw5biL + EeubY3qXPwYHDILx1386v9RYda5NZJZ32BafWqanSYbTdAJpft10an7qs4fyrtue5os3a1jAvT5L/saq + zSnfnRBrbibkoDTVjAle5LsTmhwIbSKeDIh7KjQvJm2jn6PvdCgCT5z6B9ydDcJ5N8lau4o3t/47TxGv + OAAa4yxbvqEEiJdfW71gwcKnn0eduOUV3lsElsDq+fQH7MXunJ2PImXP3lMluJOmJkJHenq2ldiEg1nX + SRY98vgtdKLJcMT7H+564BH+6y7/9yhjd4sKuH9chvtAxxqwJbOefaE77eGIm3zxlXULFnbOmctbQklz + L+AOHIF7Om9Ld5uTWrhw0XMvrWP8OdDWvLa6urL4oUdv6+QentI1fcassPamvn2lFyNPmR0fHPyOQ2hk + /6dczNsy40I9Iu7QlCdvxT61ckF9twMm8IrnV3ewXfd8tZ7ayFU9mjX7MPMEGp5obKLgtojvEsTluBCn + EEUQxW9SuLOx9KcSauaZj+mmkBRlhsfeRGBm4lUMieWNqpNCDQdM1ZiSzx4phSMfpFHwUCbgbgAPbzCK + 706L5Y2EJrEX5DVbJDULd4tJKDl6KDOtgLi6DZ0EjaRJnL5xCHYtHK7FPoMG2OXQznbdMLv3nF63gZHt + IhohbFV34Q9Om7ElnWdIMMn7HyzhkXvj7dt0XgZgf/QsY4kLGEENhRTJzdts777TFbhLuuL1vxS8GBxE + +f3xc7eghub+6ONdH3w4/cMPpzKUSMAl8TiM4s6eTYzjbGCH6F/E51RkGUg34LGatGTGzDkPPnYrmAct + 5cmn15KRAbaiN1RHMsFZkfNreWO4f7xg8cOJxtJKbUjnU8rjkN3o7QHN1R17WL/pdvlFuC+c8mRPOr/p + /ocH3LG4LkNoZH+nbBfOVcbJ4z2VJUqinS1eUN4FeUbwDjPcW33efRPnSUYwAS6SXWccfAepSx9SlPO5 + CnT2heli3eQwKdb14nFXI6o90hFDYcBqft2GWE/JbkatWMU0zeeezrON+U2GReKQOoXK6ExuFxrDuTtL + BdybcicdUw3nvdTltAjiKtxBM42nJ8NV54hmzuG49Byt9xaONPDX95Lhlw+m7mLi5f0PbyD518LF+7rX + HmL2/OqOA0xbv//2+e7QAakcB3nmrFUPT7nNnUSxYdbSex/0rFi5efWa3VNn7Hzvw53MPqHDIKVUf3Av + lNjbI9OFu1B4693bdA/GeN99byFhNga3gHIIC+PmzfuYD4boLF3a1Y/LvLC/Y4n+/n7ljeS+xD3H35zy + VPecOXOLcMz3VxALX5JlmsMdjSXVmohYp7a5c+c1qY3zeuW1tan+w1V4+93lnHp9sHH72+9tSYPZ6wa8 + 8ToyhB3rMYuDbmST/kzbGvEybcbONLl0Kxe0nmetGBLjEVZwH/4N318NNafzjOviuUF2IKuSbiJG4S6d + Q2yR15HDywgT3tljzpFBhFw5euZ01NR/Gl0eQTXGYjpTKdaqLzIb1RNFAQLkGggLVfWRFWSqZK/67OYV + MIOCk1f12dM5TRH8Y5NMLMwpYwfaY0B9Cnc1GcMiS7K7LP7Hgy/GvVCnUhJ/Vdsb1hTE91f/GSE3vAQM + /z5kOsGzL25xEmN9Lb0i32F9kv26dOIMv9bnExYDp5Bo0aKlOLDp1Ec2+O4PiwgWJnzyHxsTCL97T5Hu + As2dTqI0sud4IIFu5D28/3bJ+KaCgYaB/JImpSnyy7/4ymrC1efMWTp9Zufb7/U89+La515au2LFGl4a + 8BDrce63DfZaW/NjNfmVCKB0WJKzIKb+vQ+WEQLPrNc0/NxoGY/Vnyzz8cdLSlJJ89rs5BYsJKX+bXag + v3nz7TX4xMyYTW1bv0w3JKAh7zjYRjY/ZW3Ls4ZrtanvyINJljos1vyC0is4V5knlwdZsg//nu+vhgkC + d7MwGvrtlNEIdNHdNhejeV2MiC+xWyKXkr34Gp4mCShlpwGgSO1sY4Si0ZCOsqa5wBTlgTVeuVSNwMeI + jcH/DZE9TXwm2X0v0WdPJ1VFPL6eO2cN3E05aQgmMlFoREH2hnAP/33whP/H7GuPpY7fXw0ldz4Qr0Ho + 4YZ/ox89ej5N+dvfMBcv0Q8+ykv9fCPwisUlFt6mHVd3RElniik3z+YtB4YG946OztffIvqwPJhZH4E0 + GrLoYAg5X7W6cEG4b/vrKoYB95nPvNDFZMvEQy/mXtIGOrP0rFuBO/3V87dr7gwkNKlNORs7PPtiOY2P + RqAfLVk+0feHvOPgGtk63JknThrOQV1Q6MSzaajMiJKdR2ncwx3eueS8bjWMc6oRLnmafLEUih4Qj2ik + IHiKb3Bsoi5KZBU283ss55Su1cf3bGkar8gNFC9fHsIE7lAerOuwNxw+LSUhCO24SIRyc7psGq0P0M1Z + xquJLxNG7DimGgMAN9Pu3ua5R6oZ+T4EuLe+S/A91YLMCUxxRu5wypatJ0tZw6qYLmI5Huj58KPlkN2Q + cNxkYDp9JjNImZbSOKYFsX7u/CIp/5CByyv5+vV9Tz1Dst9+83/VXem18z8uQp7Q/Zj33/A9YMhwL055 + 1hJm7VcTkMHl1HPHDk/8mLeEYoWp/gdUFy5a3P3IlHUt1sZsX6NLV63exEtMFeWcfj0lZGlct5Blbu7Y + N9gd6yH/g2hk81MOz93s/wcPnvjRs72tX1CTYo6C217AvZRNZRz9E3/ZZPlON1VISVPNpIskBGFN1FUi + uBkf03U8ZDdYxO0FviCY4iJ2adiJrAy5w59irilgxbVXSo5UNmYuc4U8DupRUp/d9DJsY3oZup/IIKbO + nk7FCs9duBdpQDZu9O3ETMiu5BeTVJ0Xms5TjVGBiJyR1P9kBEraByjIhJvvwDI96DDvwAMHz73wyhZE + GAQZvOBQWuBFHV5Fvq1X3+hCiQHrTiJ37VNTRa5avY2ZKWzm9nYMMdvo/Q97mOvIvKd7bstwgm7Qafhz + Icus30nW7+hR2NdfXYSvGPHevHPGLNBWaD4cIvKoGG5hYsUPpm6gs2Hj3t49DWtrfqwmv3LKCPrTZnSS + pYtjefT6cbsfebznsSdunTXfP/gok7nm0HIWyGt4yvXI9K6583oBbiu1zZiJAlbYgT6SFfd+/CzrhNww + At0DzeDcHywytaX5F4uoUL3pIe/Y0dnZeiObnzK2ZXyOW8UUAkCGjHAzZ29u5YKap8EgyJQJw7zn+9t9 + XMIdu0QSGNO/mGgNDobTF9kWI8dvulKHKzEFwU2SnuI7laeDhmk4Y8P1LkoBMI6UwnoIDrYAfZqWMjoY + oydLa4ywpcF8IbI3JHvA3bSUwB1OGalJDS5TxdGrcJfvDUdWA8EjgPd/EpULdwch+Ox8KPqhYd7o3ACE + tWzsPfTmO5tffGX94z8ilXn3w1OQjzsJaX//w5Wst8daTK7HBOYQZGJhT9PSkeNw9ty1L79W7PLQlG7+ + 48Orr6+ZPmPpxx8XWSFXrmLYcP2Dj7J8UkEi6n/9zVXOZeWx7+3d9fiPNrImUbHB7b9yIJOS82bZ09NL + 1jCSkzz9XBdCLS187sVuDjp9ZteiRWtWrixyjdVHjPqtrfmx+vuVE8eTXbVq1cqVpJpZ99QzhTz19HOd + b72zatasjz+augpFPuIyn36OtWHngLNVq9ZVTxkD8pNLcKxdt+Xd9zf86Jm1rdSG9Azm4OOWLTvmzt/4 + 8ms9rJbF8PXzL3V88NGqDz5akwbt3H0/w61LgLs9lgYc1I72CoNtZMNT9ioTeSHcfTvnA65Vz9pNrVxQ + dsQ/y3Bv8JirPhviZrfpC06sxWGu9irHww0v+eAR9y3BI7tW6pKX3PNwfp1/VIqH0Rt11LQ6cMp7AP2K + Sr1wj77HVMMm743AmHT4tOqzA6MS3LmDA+6YRdmdbsxlWkOT8RR8C0n195LzPhL+exXuIdY7O3f4cOf2 + 4HnjKeIlZsWKVbyUz51LiOGNwvOJyA7W6w5psWQzDjLvOg6WYGQeVMxo4kCCVohQdE92JJSlvtxHN0Py + jONs2NhHxhjm8RAfQoUx44m+dd9+FhTd3tFJjsAbvzJh3aSARjfxmkXzSNtClklayIGovBAQFi1yrSh+ + uvE+sa9I27J587a0tubHav5rEYJTX7GEgvy9ZAmRKuQ4nFsP1yFQZyGNqVts7qz6UoTmGquPW+1ihhwD + vXHKtNOV8+iucMbJQbZkaRH30qQ2d6mrpiTPKOaXcQnIncswK8eiFc88f1uqy3vu7/7gw4+dKMuORfjD + vkOD2tFewVG3FhvZ5JTryRt6DVR33gMPKS/TVD7gBWUDR2JHCe6xkMXY/yDyNKh5wAFBrLxh+lyXwDaL + i2vUmfA2qF3yvkFzYD2yawUEG36IYcmgfOkDh4jwx5T1EdVubAmCSeSON4+8yeidi+8EnEj2G2Q3Z04U + xSh44TQuPXdcG77kBjKxMDbBGmEHT0q5Pzz6aHPI7iPhtkedMZQaHaGyDH+NDhpy8Y0HuyFM8TyDAyjp + Gs1yE0bAWVxXvDmeUpcs50F1jhJ/TUoD8XHQ0OLZmEc9dkQvZi+X06J+tqEq1+2DmLCDfsIQVTbwaU9/ + dW1oc+6zQeFOsvrHmjUggxqKZPEkMFhR5IPke66ml5LrG+xo/Vj9tYRT4J3A1WM4BAficB49Vh+Ms+ZL + jGB8rfcYN1h6UjbS+SUaZMDaOGsWOHjx1c1P/HjjzNnbFi3eQs6GxYs7Z87qeP2trlKKCKQhchPQudIk + LE/gcX3H3tZ35BTsVp3u12Ijm5yy89p4PI224K8ra+JPNL+g7BgR7uw45Ju8xR1rLW53ZzfjicUWqDHC + nb9mbnEpJeVysy3GoqPSvOE8+8hiWGK31FYxN+rcoU68fnoLS7qOtm8DDSWd6EtsQ5rIRadelnE4aqD9 + KdxdIopTjsCYJmSPkYbQ3LmPAQFEYHetRP20PFIgKBbZ7DTbe8xpirDIkeZ7KDPxioNZ6KSHc7N5q/iy + DN2AEU9pkRj9ZoE+xsLyE0bjmUxDF4w3Bb7wFBzwNLKxE9z4C6xhWT2RZDGq4XQ5N3B5FqPcvHBswCHA + aOlXExAVeYnrywI7DJ4exSRl9TmQxXKjDqEDpoa1NT9Ww19NlWP8rg2ItNUc2lkdaXtiWhw3FdtXTzlt + JMbBDuzum0HD2urxbIfqcw7Q/Qux3nhTPqTx78ZBPv8ik/6LiCYn/W/dtn9oO9rVUTjxVhrpTMCGp8x1 + 0ft2IC343soFNR8kt5kK7YiW8QR3jSiw1F501SFXTPRXZEhhGqgykUt42SG2xASiyOUSq2eog3MggZuu + 0xSOtr8qBCmdR08TPE3fG2LSf1CeX4GsorzOexzO5AqOoFZ99vhJzz0GVHn8nE6FxRxWTWNmfG+IYiNL + douYmZHju3Hu4bnHa41paoZcVHWc95AuShXJhZzT4BqNbKCsF8PdMYjNEwhSY/av+ekwMg+8OxqQquWp + nF/BBz+5ooChsdVfXa1FN4XNFIJKRzFg1/wWURuIH+yxmrSEe8mU1GYYtaMyzaoTPkw46nmZVUnZquEp + m5vB02mlNo6+fMWNdf6apGRhiLVY8Gjqx6bbdLYwK30PGA2V7ojilE4zdgG1VhrZ/JQD0N5vMQ1lwAvq + DRCxeUO+z1vZcUzD3fXwOA3Nx99YSA+MplgH0CUfOfDkLJtUOVHbNfMiHQP1VBdCimAVX9XV99O88HxW + 8Y+kzAazG4oTbxWKRaW86tHUEG1sIZwFbSncncQkpEpqTKQwc5Kqce6GQuKIGchP4zWazrt+uieeljQL + cfSLGnB04J72u9iqlRu3yTbB99LkADP4G2Gl+xyzSMKNSp/VdDRbmseOqoJpfKq/qu3IboU1R/vj17Qj + SUdWdLGjxCQ4W9hfbc2P1eRX79uY1x3zJ5zq4eIHtjydkdf8lKPHaqW219/a3mS5WgN4WOCQ9UZMz6lu + jvvy6ptbhrAjj4a+tjNX0ikjQzvldPqLgArEe9tUL2jYfHTITqtqAnQMllgnT74HMcFlackLsKikkPqb + gEmsG0AdMgggw81nVNPMLVAvcnJ51U24qNwRvbcPsze37eGD3zhxieLcKHbkGy4t11K2uvqSi+pxRBWS + UoIXfVjlGlpI8wLxodLop1siMyXHUuHFo4wZqvC9nqz+CI8Zj1zJeQ8dybFlSzXhTGrM/6HdxT4jdd7t + 3nirwD7DvxtFv8+bgp7okZUxeSR6iNIR091Lc7utMB7mUs3pc1s9bsOnOiTH6oHSN/fmtQ3515KJSm0I + i8VZD3hSqcH7q43ub9Waw48+sZGIVdLRRK7gmznuC4nm6ee6Z81mQbuZkB23nYENNBleKpat2DeEHXkX + 4bkO96uVRrZyyultE/dSKxd0+Hd4KzWMRbhHGImLoBoJEzpMJNHVW0+xHsiISTFVpoNXCioKzjXXw8EQ + 0GymAT7zJYdjGyd2DrbIZS4wcPdVGvjq08nZOBFc1JSqqVzDSeFi0/2kchA70luUyB7xkXQtvEcjyPAM + AHczEJjOjNuUM9J5d8qVo83+DdYH3xs67+3Fu2QX7uG2+zqFWVq5cVvZppU3gCb1tLL7ELZp2JE0qUdn + YowXT6r1RnJPnjx1bvWafa+92ffcS+sffKxYOGVKEQ3Z9da7a2bOWkx0UoSrMpRqnAwPaT1N/5lVa/YO + akeeGiXy1ls44Jb93TlD3rGVW3pQ24w5uBsaaIygzrsSR7i9Bn6oEZuwJdQDPuj8WpRfAKjaC4VKqA3y + 4nGrdYg/vmSb/jieKhiOr6aI5FfDTvorHJcj4jjwHgDo+cARuQNceA/RRl8+Qs5TrYY6Y7iV7bWMcnAs + /OSAWyq7GwSiMqNQQAPoG5ylFYiPubV+ULSJyEhtm4ozbeR76rbH+LYBPPSOg7qD88bjzgLc/A56w1yU + FtLxMHmAKFBCMRk4JeQ0DVdlHNVARtwXVy8y9HCwO+Jaid1xZ64hN7gmQMdIkeMRIJgOnMaiQry5O2Qa + 3BE6ijAxLmdACG4gO+qqc45gzuEU+Aglnd2TFlfJiCmj7ttigZtsLzoN2qkWSM1tbRu4U43Qt+tid/aK + 1xHBqlfL9yYRC75TiTJuyKNUGMqMSYmFu6EgHsixX0Utzr1Ugu9h4SZw/x+HUbhYvmOFGMUbmN2w8wDG + yN2YmzFCFtDH557kHmasiHuVaU1GlBKoirxO7GmEqxK6g8/Ozezzwp3PUzyEHRVIR+iMxma1YwjuESgS + FAuH3QFJPDt1mNRbhxQwooR1Ng6sU5sSuYvhcRmcjh8FdPKNC9q1yPEWNzPoviHrASutUlRRGXehDxx5 + tq8inhOn2wi4ezM5zOtIL1WB8oh255Ew4sL64buikIin/c7RdU5AlMhEHwt6xEhGjKyG/z40vLt7eO66 + 7Uag2q3StrH5qORWtdEC3Ic6784qCDnRLNyGq5pdh1/1xgwfVNEewo6TjexcrDEBd7kWEYcizEn58NHl + JuBd1WFXhylNDkqxzn1QF+kKxQ1upkw3C2MrQIeDUVIaxpetVBKgL2k4fA927XhwSXTkzTmTdmZO0Ocb + lz2K0ebIxODbgM67S3aozFDSGA8PEVGknoIWC9ZHFskY0mijC19y2x1H1W33TYLL1EaI5KrGpgV03sV0 + GrHqgsYukBDjVbomut7D2XFsmmLkWlVT3b6DRenZcHLFh3TsVC8bITh12AEEbmPqsLMBmznJCFxSD7eC + I6XcQFTiQsyUCH9UhS+V0FUiX1js2MqHkqrT8BBSXoCmdcJ0KEyDuZUD8Xrx0auJeE4z5TsPiUKkDwlP + hfNiVGbiCTFALd4SHMNIO62Yn+X8Xgd7U77H2MZwnPfw3EN0crqs14ViWs1cJrwFgBr3Oc8p4HYSf0Qb + R8ZswwEUylMIDnbHCW/Mhid4h+EeZBfukj2NDdd7VWHnXT6wki4tDYNCJWdfLrxvbdw3DhJa1HMbAt2X + gxJtW6H5gNukmk/6BhAus3JTFIBr44251MVmG3VwRRL8aE7ZUQTvcgqPgQOtrhfqciV48QZoGmqNRMMH + niK2N+2M4wTptNvw350XlobQ9Oe/t67PpJqMoZ/htquM0RjOa3I+ipPwrOMF1LjViMv0c4x/ullqnyHv + OKmMfIfhrs9uCbI74hdSjEST7HAklWJw+gCQUgkQ5MrBOACHPBfeuoHtDZke81oHZPTwN6AZnBG9SBXx + jhU7U9TC6XAKnAguOfexadnZPd5gdHsNCffBcJ4LLg/iDGq7S+6Z6gStxrgg1yeB8mzJXhgco1XF95Ce + olV2LWl+giF48VWyq7ZjmRgj4TQjVmpSPYeT+WQH1CX6M86Qd5wk1q4pcN+REutgOJOoNM2Hxz6kGLGu + FGO2Rbmgbg6MTEjifGv+aV51sV6FaWjKbjb6BY6HoxouvBEsOssW/mnIJuA2RQzbgH5deGdpsZkB+7y9 + xpRIR1YRZ+C7WUTw33HbnZZlOCZ18mzovDcMnlEBV5/hoDHEajx+KVRJcDd34RsKMgY1RZ9Hv35HbsV8 + 0GyBiWeBOwZ3hw0tDqWmEziD7OGwAw5f5CW77i1QgE3O7gGCXB6xGCJMSnbn348+ypsc0VHEkipSQjyn + YLwj+NbXBrjpIATKBqbTeXeYAXw7p4kxVfQZs1zhswt30zwhzlChfYYjDRG/H/HvwXc1KyUaVfgS4o2l + aR4In8a2x3xU+zkvU0wum3iPWT6jbIHRt8CdgTuQGhTZoUasKw1cYvDNyApzvDj2SFGoSbFuPPsdxHrz + o/uGUUJ8ZCmw2eDblAa625xdyYVn98iWJcRx2BHf4TsSjet6G/kO3KE/fSFvOYrvijP66WlJZzk5V0sX + PkV8OtepeS6amI+q1B6CDGcq2bklRv8ByEfMFpioFqhFstlR+2A0d2ReVJwx5NGJmg6f+pr/T//pP+Vv + kN0EimxpWIUzP7k2ka235AgbUBjLKo3+B5hreiaaSoPheH9tUKBIo86dDxXt5wPyC1AG4tpQF15zUdhd + 590MsRR8dviOPmNgmWQ30YIJcFBynLxqdjND8ktF3PuTcZyB+BDiA/GRkaa0qqotjPw5BrZ7vo5y0wBO + iks5avdhPlC2wMS2wB2Au3lxLSU1pjnZzX4uvukSYBx44rO41GGPorc++jRPj0gbaKGh5b6s4J8O2CS1 + mpTyCvHuyAk6tIALrwrPT0DWiV18dgasMZGmb4Xvhs0E3FO+h/+uPqP/3gTxqvAiPoSaSLMs5avF5fTS + TANVsnNGE/thy2eXLTCaFhhtuOunV8nOow65mvjs/KooDIDoEoz8cy8okzrsChoDMnQUNtCPVis3BMig + l1YOHZN6FL7Tvgqk0luowjvdlI0jUJLKcfDNNoPsbnJw05HzTSlvsP67OZUIITAsJzIoUG1Kef13+1f+ + ppQPrUZf3qERpw1HMYlbGtWOQWi8fbzzU0bz1s/HyhaY2BaolVLLjug/jdq2GP4YKXBTsiPF/LN/9s/4 + 60oO0EGf3YA5rofJUnQbHVmNovLecHm80f8SidxwdVXyGJ9ssSWctRpUFCwQZ8eXJv6PUdaYEIDF8IJj + WBW3Hb4TP+PCQ6XUwZGg2PiZSD4T+AbxFkEv4qNJKeWjbaXs+XG+ocY4LyHUGI7LexgnMqK3X648W2BS + WWBU4e7sJIoRMuq8AgseqbPDdEtKdrUCyS4u5YWzUi0h2beIzlHYzNwA+NFBTBDvhNvWC8YJl1nHmf7M + 3fngIZRosIBRNGY8Rr825h24uzKcKk1DviPl21Wk85t04fXQU7gH37W8cfFeo4jWN2bJv5RI/MAGbMbG + mMKEl1xNE0JNqgcvn2y2wEhbYPTgni5Epzjj5B2jPkB5jKA2IbuTekRbKlyMKYc9wA3yTHjkRCRPuXWs + p1saURPFkWcLtwgqPFD2/UAJ3ogU+I7O7iJNrgnZkO/miHfNncg7H7l9AtzhuVfhHvNaQ7FRuE9jb2J3 + tsFnj/TLKmxmXMglWyBboF0WqJnRZRQKD7Nqux94vFOyEwStGkNxeg54glwGacAXdXYo6St/SnaDRlIp + YOx8pm0mwIOzEHA47VSlCVyq3Xum9iIcxUlJ9peOXmK34DthkcZEuoJow6WdwoUPFd5AyfDiowGKM+G8 + p3kL0iFZe4LoDxx4MP2ZE69cIkfFP5dsgWyBdllgtOEO1pXaVVEAExoCZCfeUbKbmZ0v+UlGsCVnm5Kd + L8OH5fPYQfkotMT5WVHw0z0o32Mi3hIcYsXTd2zTKU4u5aH/bjYxpzU15DsuvJmbTLJqzk5DfWK6U2ju + yjIxq0CJJn3JsAOIaUqpFGOyM44VS5e067bO9WQLZAuMNtzTpGA4ntAHP914dsjuNFQl4xi7YxdzkYfP + HuwAYaPA07F2iNSFx0pg3RbyWmCCPSV++075DlJd4R64u1yZy2rj1PfnwgfizcyH/Xn5UFxyRacoZrfH + wfdDmowsZidxEQ1j9z3GTAlOpjXRjZXnki2QLdAuC9Qib9fIfQi1XUGGB740iArW//k//+f8jXku4Z8C + CxOnQCiIb5Ipi+LD5CxYw0xkFgdpjTVEuQKXwfeG/jthkS7OF3Oa+nPh9axduN2c2tQPiKnfy2op3Y7p + 92yJ7y/TzW7m2vCuLmLmHF8ORu4OzDVnC0xCC4w43H3sw7KGUetx46SH1A7cldpx2w18hFl0A6CEh59v + zCeTyZ52ZuZasGhSfzWmyOB6Q+Bdz4SroP+O887IqqoIvnNJnxH0fE+JlVrNBS/lDW4xKavx6SanLH2I + pNtsT3vM1k09HJRqqdwVdhyQSG+SSfgc5lPOFmi7BUYc7o78+uga+xjzlRRkdNvN+KjUDtlBkoOooEQ8 + wfdUaJ6cDnv1rJ2aG0X/ncIbknynN9WAMb4q34mPRJZxPBMnGs42QXyJ8uwi6DlEqaRf8tkVGALowXR8 + djNTRvLhDPe2P9u5wklugVok8BqJDxgXvgTZjX00qj0lu2676XyNp4bj9AToAOyiahwShLvnEhZQoomi + zk7BbQed8p1fjX/nL24yWHfaqtNc2YwPkDf12fXcS4VtwpfHAS8VOom0+Kv6j/XQf0T+YccGjMlRr8sl + WyBboI0WGFm48/QG3GMyKt6lETIMooJ1Cp912wG3bjtM56Wex16yxwwaIZVLyQJqVlW+00Gqv6d8pwfF + tvKd5AQOVoPa1IXXi2/I9/gykK3AEqXhGwBfurgrPQqfDWw3/Ea1vY33dK4qWyBbAAuMINx5Yk3yh+du + rHSMo6ZuO4h3HFVBBkIRPMcDzzu78y35JmTljPUmFmjId64C4OYSmCXYPOz0o3xpWmDEdxemcbJrqPBm + GQtkV0FfArr54o2zjMTxbIMKBNY3b968adMm/jqWa0g+FxpZyQicXLIFsgXaa4FaJHtp+wdD3/TLzOhr + 8LWTUZXa/8W/+Bfhtgtx5BccOh5+NHfnMYVDqnCcSxMLmLzFef9hLuxPT8l9YwZNly3EsCaPdEIT23Cl + GBR1vmggPmBtFviGRb3eItYpVOvMWFf7Y7VuyM4H3hXoQjgW19d4JyW4XLIFsgXaa4GRgjsowRnUcy+N + o4YgA9lx2w2ScTKquWLYkSAZBwBTqSFjvRULgO9YlgQ3311Ut70QmNo4JdiqDg6IXZ6Qq8YlIwzGgdYU + 8WyjXO6iH5FgMmqIcVpoDsopfGBOrKtB8dkC3KncaVZOYaO0957OtWULZAtggZGCO0wX7rx0p247PqMR + MpA93HboY7A2Thx8QR9QlwdSwl1/M5dWLIAxS3x3L6MVvRbGofL+xGf9btDM9YqsL5EboOTFi/jIMQmp + TRbP3CgIjmOOe95XL8Kd7/nVzGXOnyJQB8+djoQ2qBFxSyAZ5acxWyBboL0WGCm443oLd9UAqG1S33Qc + Ndx2c7UDcbaEQQDImEjJrlLcCtfyNlpAvkfRenjxpnAxq49pOLkcOPXBdxxqM/nwge+5iDGbNMJplFxK + iC/xHcQDd3AP+ukJ3BiVBrLzl6pogwKdhWvd3ts615YtkC1Qc8p4ewsCrnA3Di/U9qrbjiYDepxuqtuO + JiCe1I4jZ2TD9X2af8m+VDWEHSfALpx4pI3UT1f7Mv87njLDG2zjqqdAX74TAGPOXq4FiOfxcH6pq28j + 3RhRY9CklBf0IBsvXsTjsBMVo9vO91aremNOG/7J+xxwd+09S3vvwFxbtkC2wIjA3STd5vkzSKbktiPI + mP2Rp9r5qKrtdAn0BLpyCscKxEMr1Ek3M7R9J8BeDkdbwk2G3WAas7g+n+I7XjzetHyH4xrfvJsKJiIe + VcfcNeYPSCeaCm4o7/QosE7BbecbUI62o7xjl+BRuDop3DlWfhqzBbIF2miBWpoBql2fYbSeOw0tue1E + yPxP9YLyDlZU210bGojQJRjwHpKCoR1DKxANkNFzDG33CbCXWd0tfPaMwDps9Y0KE9HFIr6DWsPVIS8/ + sX2smhSIp6uOzF9OLsWXT+egUoPhlSAeR56/EB+mm7HAOEv5zmf6crqWWEeb5rXr9sv1ZAtkC2CB9sMd + aQUXz/RSEdvOo8tj7Kwl3PaYuIRTqSYDQRzQgz6SxXwywyEs7EAyptB5DKeecb2vs8As0VM63O1YiJcG + vsNu4Q6jcdsdlQX6Jlg2DzsdMJuxO9fX1DGYV3fe7DHi2zhIinDnV7dB1aFyvsSd522AJgl3LMzf/EBm + C2QLtNEC7Yc7T745pKAA3pmJZyO2HbLjtkN53HZYY8ZaCIKPzy6KIeG2G0oxnGLUBzU7fjg5i1nDLJoU + oLu4NsjG/oozFBxqw9VhsSvkCXeX2jAtO1eK/tu5xwatGodj0kcQj2IjwRlEleN8yU8uF653T+EQJWWG + Q7Txzs5VZQtMcgu0H+6RIBAvD08cQJhJJtx2IyD5ximprhHqFHm4A4BCJh4+i8GQzjv1D7+rGH577lQN + wffo5Oh0was5IbgQNMzI95iLxOWLaWUm0HddDi4Te/GrmX5dP96kvjHuirdueKUzpHDYXUiEzgPWOxLL + l9SWym60bZI/jfn0swXaaIFarKHTlg889maCxaGLBJA8wE5J1W1Hk+Gf0ASUGJthBKSicGgIvqoPs8Aj + GmPhBIdZ2/jdHWNG3oJQuun5uEyYSHEGuKfiDFExJl6OFfJi0SXhzu7yXS8eFY7auPrOcQXiDrGCcqrC + eVe6Ce5HzExq1bbchLmSbIFsASzQZrjzqAt3nvbQZCALw6eq7aHJGAFpxlqVXB5yw9spOvvDL/iekXCc + Dxxr+HWO0xoMdbfYcfI31DOHJRzixqfWf+c6pmTndtGtUJkpkT113vXQhTtF590BWMNy8NyBPrcKx03t + ma7Yl5/PbIFsgeFYoM1wV+MGCjz5rn9d1WRwD3meHUo1DpKeQOyGNNwWt11q0HMYvWOJQbxxyujhNDvN + XmA92N/IGXriiJzBW49cMeo2MjcEmYZkjyFW5RcXWkJ2V3nnn6Z6jzFV+M433APptYb1w7mb877ZAtkC + YYGai9a3q4B1PXcOACOMUofm4bbjvIcmY34rDk2XoCMZrqXje0MuKQFpAK8FJj6kKL4PueZxvaPvRiKe + z56LOfd9zfJi8ZrFRZTvkNp7ownZEWQcWfXqx7AqHrpzU+E446hoNUbUyH1+QqLhPqFJYVUa0K5bMdeT + LTDJLdBOuPOguswmD3lVkzG8HeUdfKjJmPERzxr30OAZ4T58+NpVOILKZ+pUFLZ4uMlZMEgkadACfMP1 + 4ipwybgimIsLRKcbuR7NDtSfzp4GzBgZmcLdmEj4Tj8Byl2bKWR3iM914V0qvRaT/IHMp58t0C4LtBPu + 5vxybZ2SJqPaHnOXjJMBJXj3sAPE83i3y203FAeySzH5Dq2M67AQxjM54c5Zp5bRCHS0pZFVnHd6QZ13 + cNw62SPmPQIiDXg364CL85Vkd6ShuBb0K6pAuWQLZAsM0wI1nqV2FaCp54704UKpEScD1v/lv/yXwl3U + Ok0GyAIRn23lAncZZhHuVqj/LsJc0NXC0Yd5lHG6u3y38NmzMMWbq2dgPS4THXAssURv3URnN/g1ndBk + xmCjHk0ZhghDbXwJ3OMntHhCaOzaw5jcG+26IXM92QKT2QLthLur+Zg3POYuGScj3PHf+SdMUY5XcIca + qvA62soCwyzyC7Kb0NzgP77kcLwoWNCa+WmYBxqnu9v52e15CqBc5503Ks3ClcJELreEkKLRIuoxVWOC + 7Goy8DrW3cbxN61YqsykeWZgvdOSw5IcfTI/kPncswXaZYF2wh3fTbgjvrvoUgRBqskY4c7TC0GgiYI7 + z7bEF+5iZTiFGpSSQ8QPvvMlCkOsic7R9VInW7E3tWArT9+FTNXTNAsGNJ0AxfBWBy1KOnv47JLdeHbX + +hDuZvo1ZsZhVZ13QyQR9ON1zYxD7bq5cz3ZApPZAjXY2q4C2ZVlnHfqvBhGUHXbKY6murIacMe7Byh8 + EO6WdnE2xGWlfMV3vuSDE3AsXPt2HXF81cOFiJgiW46VzMrpnCY2YFIx9hHuCOXCPcheUmO49OYY0HMH + 4srukWdG2R1XPeivCs9V4HBhPQ7arhsy15MtMJkt0Da4o3jwYPOEO/OlKrgDd1PKKLgb5w4veKrhiGQH + N2wz/GKdobyHOOPrP4dOE/nzAjH8I47HGlK42344i2Vcx1znnb/hvNNtN1Rj7NTDbZfdDpxGkpmQ3fne + PsAN8Ny5B+jvOVbYcDI/kPncswXaZYG2wR25Q7jj/clu3fAQ3J2bCl6BqYnaOQdoEusxsb3eYltKyvcI + 7rb/4CimKosCXNpy0PFVSTjv9Li2HDvovIfyzpfgPpz3SBMG6FM1JsiOz27Rc3dMVdndMVW4j3BnlgLT + BVMnN0MKd4Zk2nV/53qyBSatBWrmhBp+AdPCnTf3ENxBA4OoajLC3dFUIIJrj7PPW3+s2gH32YB/tqVI + KzXcNLhbcQaupTkIGSTg+7Ycd3xVEjGIYXmEMvo8372EPpcMrRwuU3wzS0dQUzVGwT3yvLtsEx2DGSKV + ZfgVPccZT0bE85ljpZee22P4N2SuIVtgklugbXAnlEK4E1CRZh0IuPOBB9jpS+gkTjSnGxDulraTMeW7 + Y7aGiBgLT9cSU3Ud1217A8Z4hXZ+9nY21QlfXCP6YN+9sCH8Fe442mnUY39kj0U8kHTM8QvZTf8L/akt + Xb2Pf3LDpMbnuJP8scynny0wfAu0De4QQbjj+jUcTUWfcdQOcOCa8TzjIaqHSHZHX9tegu8R/xd850M6 + ZQactf3oY7/CiEEM3zkWR2SsW6HMmPdw3l2gownZgbt8T513EC/cjannKGDdKW/oeOnV5/Pw7+xcQ7bA + JLdADdS2pfDECneQHaOpCu7/c70IdzABQ0E8cDcSEXboPCrQj0SBsKkLHyGAkIuWpJIc4u9INGAs14lx + jFTBRLaTvpkeGuDyXhWvU1xc0Gy4S0O4h9qefkj5TlgkKg13iPkMKPIdt4BbghsgrERL2nJP5kqyBSaz + BdoGd55S4c5DCyKNXOZxRW0PuPONOX5BKuDAfWODgHvAxcS/hsm3C4sp3wGWOQmUI5woG4Wjt+ug46We + CEO0wdgK2QSvx25YwQT7CHeUlvDZq+Ookt2lOSiR5pcdcfzdl56DFyYqxA9wtjBPYAp3DjeZn8l87tkC + bbFA2+Du+BiPLsOkaahMwJ0n1jhIFXkQz7OtEK8y4GoeOvXUANxNIsaXwywBWb3UNMRbvtPTpG9wfDPM + I46v3e35lGVsOeSlk+Yacb0UTPgVNMt3F7yO4dOSzy7Znc5mqhmjHnHb+cuXdOpq+twqTijjn/S1XiaX + 2G3LzZ0ryRaYzBao8Yy1pQTc4YLLtkWoTHjuYAKMAm7hzmCmcNdzNDkBZMeVjmlHUU+7cOm7QgwkCnf+ + 0p64D/gsZSZPibEBTxmzm9ANUxhHhEGIXxTuKOkxX0nERxHrZgaNtVWD74zH8hOdut0GN56Lbuu5p9Zu + yz2ZK8kWmMwWaBvcTeTNg40L7LIPVbjzpVGSsNtYZuMjA+5whGeevsEl91RO+NXsBcMv4kPlQRc+YkU4 + XHof0MGw5RCOSM0xJ8vJsZwO/Zl/ObtY/rv0wdh/iztG1jPfJIbQmNZ3SeHuXqYiUENzOIRrJ9zxwUtM + T7117gSwHgn0+Yy3jnfvYh3m+vcq05Gjz8B3PXevjkefzM9kPvdsgbZYoG1w5wHmCQfuRjo6EMezqtvu + gCpf0mjzebk4p3kiLXxmg4C7E46sp3VItbJlie+KQjSAhsGyKPxzwNoM9WFLeixoBa/luGMGkcQ4El5G + LvX+Prhl7GhV1GlPIPdd3aK9ZsEm8p3L5Fn7asXlCGWGX52XRHFNVKPaG5KdYVL1dEba4Ts3huoNn6mW + E+E0naXsui6YMbV2W27uXEm2wGS2QC3F2XA+h+cuvoM+Vbibr5HNOJw5CVR7TRspHMNp9Zl3GlQbC3WK + +HhvMFwEIuOfRuEsSgdlF76U5jaVD8HuyJAzQh+cagvfPbojE1qb0xmOfTBIjExYDwbBeXcR8xjZ5irj + tlNQZoS7+oyTTnXYoTlMR0mPRbQBPQ67w7Bs4JJ+1EnLMbXrunAKKdyHcyvmfbMFsgWwQNvgbrpXHuCA + uz6gcAcW/FPpI+AOOMwmZpEpElZmyZThMKvJvsH3CKSR7xCThkXx/QP0GMMTPHU+1B0v4j56Gp36hqAf + sI+0t/OqaTfozPWCvxzCWCbuGOHO4GrqsKuwA244jlhPr4Cw7gQx03Dyk+kK+IAcZ2Iyrq+L6JbgzqHz + w5ktkC0wTAuMKtzNPaDLxgce7IB7CeLqAyOE9bRaER9815GnYcCdWA74xex5TGxnE0CPfLlj5IN9TAp6 + Gsw32pCzo/Fae8DeTtXbzThx3GoVIQNbVWbkOxpLjJ0SCBtkp0tARsd6RpfywZBH6A/fXQaLphoC67wH + 1+tI2zbM2zrvni2QLVBLVYjhfA5ZBptWg9zV3PXcUVrYgM3wgvXoDU0JAWc0PwgURQkRTyMhGrlQtm/f + vqNeCNCOAYCbiRLG7v/tb2iwiQQc/MQ7ptPiTJvbNoQRN6MeZy0IXwc8qU24OzpqohgV9nDYXfTDpwtV + 3SVZFN+NavedDGurzNCV0nmkcEfoH87dmPfNFsgWaBvcIxQSfLcOd6F/B+EeqhGgMZcZjidiAm6pZLfg + oo5dnFdahtvO5di3b9/OnTsRx/GUVbocwGjC9xLc2RKnW87SW6hQYRzhTlxjSYoJh11nHGS7L6DXece7 + R7SJ4VOuO7eKm2W4ZxhlC7TXAm2DO8+5mjt+WStwN+AdfER082g67OmxwIq5bmiSAZqu3oIgk/Id33Ps + 8x3jw1yYDtnhu0APX151Ho+eU25obV9i0g4Aa+B9A1+zAHGxqFC4U9Kx0xLZjXoy+pMaXOCQ7U1soAjD + gQx+rcK9vXd5ri1bYBJaoJYOHg7nM05ZxLmncP9f6kWIK8vwYOMGOlmJn8JbdMtRK8AFTimmm0qMDy7+ + h6cJ1HBRyUIOKC27d+9WnRiDhcbT95CZi3aSwgU3OTJfVjskzxTEcyJcl9TgDn2r3vg918hEb3wwXJXr + SMQ6A6oUBJmQYrAYWwJur2wEEdlx8iuvREo3mJGqvCtog4GefJP2N8O5FfO+2QLZAligbXCPxGH4vP3B + 3Th3nmf9NZ7qOwJ31QBzGzhPyuJggJNr4JRriezZsyf4DuuNOxw7JRSYXbt2IYJH9yPTFd8tMSksPVmM + wPfQPBBfgjsbc0HNCaHsDt8ZXxHuRL80dNjTGViO5WJPuhycdxBPI3kJ+Ff/6l9xUN4hjCjlmwz3jKRs + gTZaoG1wxynTc8fhLckygsM3ejw7uWMMRsAdpvC0j3QxbsQgSxnnDKYmfMc5Dbjzgfk7sVcky70jH0KB + YflpXpvSXkcdJoLiRW2ccumsHXrlr5cgnHevBf8E33Z4ht8Ad3Av3BlcdexUkZ0LypaROsL+kr1cL5cb + w5VAqAqU/+t//a+5+jjsTtTKcG/jU52ryhYoPHcVz+GXWImJp1e4G22duoSm6JIy8gJ8RIzEiJJdb50C + bmJKakyONRVBJCSAR3jEJj+BXHjE+MVRcFfd+I4U2o+pWfiC9tDTQMzoWoSpWHeiEyWmWcWJlxrv7mo1 + bBMRNXE5sIA9MRsIdzYmIJKCvk8fwzX1PSxmJ9h/OD2NOmkM2xgzQ1fBxvSy/+bf/Bv4HtMa+CYViIZ/ + Q+YasgUmuQXaBnce2lisoyrL8NxCDR54gO4EFt/0ebxTV5F/tr0AoxTrAxJZRx5+0UIHA6Ebg6sp3znZ + Aetp+wagEz1k7969KEWY2tjzePPQR06xHnPB+NIOtXmfJOKplu314r0WGEGXnArNeaDsLt8xjmRPHXbO + 3ZkKZtrhinOt8fGNRKI2fvq3//bfBtzZN4U7t8Qkfyzz6WcLDN8CbYM7j24ssye+nUFT8tyNuzCRC96c + cLcETdrFdw6tjK7T6gTUAYtQlnRABxI5lwfBPfgOXjmRFisc8IgDboB3DEY5OtH3yF9APGW6wnqkJZDp + ojYGFeJlpfmxOCN24dRCOeFaUD9k5/sYU4XvvL4Id2AdM7y0s8kkVOf5S520hDpN4C7c+R6447yzsapR + hvvwH+ZcQ7ZAaoG2wR0ACXdEavVf4R5xF3x28qeMcLaqwutIwF2HcVBYD/A15DteJwEzwXc4C7NGlO80 + HpGa1Uc5KAK3q7xWXfUU64JSV72qwwzYizhr1GQGXCZq4OpwHb2gTjUyuomhUeFOCw03KpE9ZodBbTuG + gDuVC3c9d9vMUVI/ID+l2QLZAsO0QE3aDr/Qjsjl3dBzh+A852rZfIAFeO467D7VfMCVG35RXqd+yRu5 + awb1QQ7CMurhdJylSb+VijMAdziHaNIePGUVGAo+suONMSQQCoxYF44R0JnKL0Hz1s9d2loU8bEnHzg6 + F44PJiegYxbujOWq+SjF6LBHj+4kNSrBgAg4yFm8A3E6bPPv/t2/03O35ewYdwK/Dv+GzDVkC0xyC7QN + 7tgRHrn+Dp952tVnS885TzIqBz+xgZRvI9ypSvCFOCDU4A6epocbVBGpKd9Lg6tMFBpy/9GwJRCQPoMu + BIfdaVMp1kOBkebNmT6oM003jj4j9fTZAEDTAMfJ2Ua4c8VLUoxX3PHYiJJiX1d3MiUkNfz7f//vgbsC + HafJrRJ3Av3BJH8s8+lnCwzfAjUzx7alEOoO2SlOQQzNPX3OIS+/8hNPNR4cm/GEuwEv6byqD7lQp1h3 + KK9UCNpDVCFqEDoDTXWAVgq1KVYYAo//zuAqVUUhCKThEVupPLahfhUYqiUExf7PQ2OoiCl0ZNgScesx + nOAugzpuw41V8CkcPd1A5V24cyASG1CwZzjsDrF4KX0D47M5NfXcEdxNCclmwp1DcC5skMbC8mVbbshc + SbbAZLZAO+EOnvTc8c703ONp1ynDO8NH440eZPg+zoMdcGeboZEdlBjfUoJRCia8xZTIfEY0h/ig2fDt + 5kWJxpBtRhfYN2pDOeEGGjJVqRCLUQkdDykcsEkwPeJ2DIOxhLodcv+QD93fKRsWWYW7A6f22RSwLt8x + TryiBdm9lMJdWcZJvyCesxDuXDiHW/mrQGehAZP5mcznni3QFgu0E+6AUrgz9ihqU1kmoiFxfo2lkZUi + wDIEuAOF1GGPTDV+CH5BQDziEt/jn4SNoynBHTqJUg1RCTUE34EUATOxOx539BDV3Rt+Q8OAHQoMlZgw + wHeO1FVXhEmZrrStEJSiucWDtriZIUYyN92FbxDiA+5YTLjTzpBi9Nm5jkjqKdwdUMVudI2cFNdauHPW + VMsZhZLDTyalySVbIFtgOBZoJ9wRE4Q7+kx/cHdcDgfQt3WeeaMmhLtcaL0AmnDYm5DLFwU6lf7gnn6P + 6sIgIefCLmmdVKJ87xQnzjHdC/WZn9hmQIBy1gwA6PubMMDmpeOlkTagpL0E0wc8ynA2UIOqwt2YSF/I + KKT5Fe5YI5ViJHsKd8PnhbsJ/bniwJ297C+xQHTwfBjODZ33zRbIFtACNSd/t6sId3w6ntjw3OO5xTsD + DWahwqlXWpXpxrYHF6RDk8KWitFwIVKPNfwg5tTNmdLZCt9jG5BNXDm9kUEgUZUh8KQFTsUZ3gw4L06w + v/ZgZOyDAkPIvP1fdBgqMM4vbSimB6ybn2xbfrUDo/AhrZBGCndDV3k/45QpXEQVdi8f1LbwmWtKyzkj + 49x5t/O9jY3/w3/4D8KdXzlKTG7Qc88lWyBbYJgWaDPcHVMF7gazO/hWip3AJcQv5nkGEwq7Ou++0Q9E + 9eJ3tjTSUeYOWIQ7u2AsBBBayPobqa4yIPHJoMucTEZi6ZmiNj5Tj7COgsLDkEPaJLaHayTI5ShsD+Ac + GwhvnYaJdf5GIKPai0wf8ATbu0F/cLcz5q9w5zSFO7z2ZSslu3CH1OpvzlDl3PlA/WwM3KnEXo2bJODO + 52He03n3bIFsASzQZriDP+HOY5xOUg3nHQxBMYRXHWH1B3ndItwhglKM1IvUNP19EHwgRgXAGToUuh8i + 84hlRPhmMHNAvscGcByfHb+VGvDrU7LHZ+R7DsoR2QAFJhIG0OaSsC7ZU6aHthPIHvAc27sBtg3PPa2Z + lnPKAXczl1FQWkpkB9wBd/aiO6cDMEu+Lzd2A1TuKALXNODu+0Eu2QLZAsO0QM3Z6u0qPPDAHWLCvmo0 + JIjnMeZhdq6jc1bRN3jOnYyu5x7v9dUP7O60mshvFdkLmnxgY18UVJNNqlUyHDhGagdVhw4dgsUtFsDd + sOC/E4qDU09t8N1xWkMVQ1vnS5keTro0D562cmojsQ2NVB0KjnsU2mZckJPO4LVwx3RcKYBeKlxKhTje + z4Q7bzCYnXrcUrizQUhz3ACR8qxd92SuJ1tgclqgzXDn4ddzZzJnNRqSZ9inXbA6fRG7K9cOCHdZoNQz + WKgF3xV5jUJxto4XPmU9qhFjntAZRjehPFpNf3DnewZmYZkxLaXoxpTpMWYg0wd7XiOxfRO463cLd2R0 + 4Q61S1j/j//xP/IN19S+HCPj3ZscmM98ya+g30H1kuA+OZ/DfNbZAm23QJvhTvvwf4E7zju4LEVAC3ce + aV05nUFQ63t6DMo19NzZy8QmQ8aZfE9RG2OYKetTz5FT4CWDtxB6LAZjzcgYpTncifrXVQ9tPZ1tpPai + nz7kMxqhHYU7b0gxdhqeewp3OnLhjgQXcAfrkl24c3bKLC6THXGQ/up7DNvEiDqf236L5wqzBSanBWqR + SKRdHxixBO7Mx8FvVRkHDWmgGw+wU5kkNY83KFGZsVTf8alECqQpv4f2WU4JeqpNPWtzcjm2GbgvefcE + 83FqRNEgr6PUo7r0VxD0xXpEphvImAJ9aKcw0nvRTkcCaG16LFqewh1kM8hMwSWX6WkB3yCbXWJ6Kpu5 + UBTfsyV/7fw4RCQUwmLtug9zPdkCk9wC7Yc7moZwZ3AVVgr3dIoK/+QZ5qXemYoQhGtgWHRDuKdkTzuJ + oX1OaZV6vinuSypKQ9zTZmjVH9mZ1uTcHIFectKjDUM7hZHey8EJFbD0WPwz1dybw905SmkcJJ09Fx2b + cK2BO0aw749cBQruuWQLZAu0xQLthztvQGgyFPhuKHcaDakyI9B51B1iNW9UOO88/PGa76BryfdvL90a + 4l4F3EjEqmgu7sE3E3ka8h0lp8T0MQ701KTOCTBCMf2eMwLoobk3h7txkGyMlVwg29FU7KnsRuUcSE0m + EtG05Z7OlWQLZAtggVqaX7Bdn/HZgTtjqr7Fl+AeQEeZkR26ig6yWYQ7QCzFybVrHY8B60knXsnlhmIO + zYPjR48eDcQzBosgo+LkjlY14BHHzgZcDhUqTiFtFd/Tc8dsUi4uM2wpKOn/6+0Fx9xQGfBtHlDectiM + z+loqv2Er2vwnZrbdQfmerIFsgVGBO5QW7ijUDummsoyOu8qMzAdfLABGreR0Rbnpt8psjfkbBPcw0FG + C/HiQRhtji3HDq8H1RKDNSmlPonvncPlCXL5hDvsLsE9QmWohF3AOpZxbXR2VI73zcZpyXruxi/lki2Q + LdAWC4wI3Hn7VpZxJYeq7M4TzpcqMzzVsF51Ppx3v9FzjNf2O/6hOfRLKLzjrR1yAyQ7pWR80MwlC7jT + hQt3XPgU7rjtCu702ezCr0RAKrg7N5Vfub6+0kUULNZryw2dK8kWyBbQArXIJdveD4gVeO7AnWcbH03R + PIUj3+C2u9KeYRU8+XKB55+BO/byyR/jJRg6xtvZYvO4HBHhU9rFCKIIS4fXwp3b6H+7WaB8wJ0rGII7 + zrtev29mxqRyS8QhOGh778BcW7bAJLfASMGdoDc9d5SZVHYPvuu7gX6QwRPOc24cBc67SQLMOZPLKFtA + Ncy8PaVD47bzHoa77UVkaEG4456X4M51LE1fohfnSeNLU00YPhSdt5pMLtkC2QJttMBIwR0QQHYKqcRc + vqca8cLjbRIxZzCBe6kB2dkFjvBlqPD5QxstAMGxPD1r1cgGqhrHUjoiahscj1FW0ioIdy6ucFeciQj3 + 0GQiwl1XnRqMoE+HUtt4T+eqsgWyBbBAzRRRI1Hw2YU7+A64p8qMwTAmNDfOXYmDL51EE2FzTbLN5J8G + awHMy7RS5mGR/oyZtyRawP5RiRGKFEBcqtlMnyGvMaxCDRQuWcBdTaYUBInmbgyl19cUOvbc8n0kbr9c + Z7bAJLfACMIdFgh39PeGykwMq6KwRwZwX9sjV6Ljb7m0ywLYkzml5B8GytCZq4MDTqYEbO4hAL1wL1ke + FjsFKeAu2SmpJpNmHeANzJQy/EWXV6ynR6fPDrddR36SP4T59LMFRsICIwh3mkvAO/ggRtBnuzSsCiZi + WJWnPeUXEJHvTm7KpV0W4KIQlY/bzrIhXBqwTtfLZcKzNhTVlACU0hG5EGwD+n334oNkZ9i85LYrqccC + HWoy6jlccd12IyAtJnvIJVsgW6C9FqiZ3HWEClMThTuRFQ2VGTEBNfDy0syC+ImRETfmNFWTyuZvBmsB + TM2SrcgypIjAZ4fsqGcMjSKdRfi5k4pLNXM56KFjQil3IVkzKez7n/7Tf5Lv6dwlBl2cu6QmQ2/tlC4n + PYSaD/FH6N7L1WYLTHILjCzcwQEEAe78BQdOVS1Fi5t+wAUfUqDEPMkqaAZLtLx9WABwh+eOaKbnTqEb + dkqwmdS4RiWjGSrDxVI3xxkX7uyYDqWG2254O3O7jJMxHNakaek4+SR//PLpZwuMnAVGFu60mydcuJsG + 0qmqJb7z5CO70xOkaQVBgFNpGMRDIqjmHczfDM0CAJ30xSjvjKbCd3tfLgG1GX7u+HapcmDNteDyCXdc + cuFuHKRBMgroJnDHbYfsbAb9ldfM1cPVD7dd9SaXbIFsgZGwQE1pe+QKzznsICQDpoTwmsIdUoTzzmOf + znWEMsZcg4bSBPf8zyFbgJ6StMwsLkgUI8o7ojk3FrXxvYnSqtbmujCayrtUaOVc08uXLwN3cK8g46xU + eU1P4HLYzl0yBYWDLo7TGiczcnddrjlbIFtgxOGOiXHecQ/hO+/ykUSs6ryjzNITpMzi+RfuTlsfMs7y + jlULAGVelbg6dK7+ygfhjnNd2t6UYTHtiA0gOwXfP9x2dndpDoNkIDuFK44cZ95jBRnJzl9T5+eSLZAt + MEIWGA2487QLd5x3xuUivXvDbAQliMeESQCBe5gxPXIW4LoI99L7E0ekG4DRCu563MKdN4AQZJxybL4B + sM5AK847apurLdIxKMgId9PO5JItkC0wchaoGZQy0gXnHbITcseTb5bwkufuGz2eOziIuGm9woi8Zq/0 + p/y5jRZQcLdUqzXnV6SCwR9Hz6HwfSrIxKJLRODAd2R3egV2NLWvZKfQPYz0/ZbrzxbIFhgluENtPHfg + TmCGznuV73zDqzpEgP4pX4CCSxpRGLVrI9FyVWGBmDhKL1syC9+Y/U23nUI/Ldyd2qogE+OoxlbitrMX + XolDJjEliivIVc4PXrZAtsBIW2CU4M5pMLZm4J34bhg2AwVc26HEF74X7g39yszo4VvAVQYp1e4TQCO2 + sIFk58IhtUN2/uqGp4IM4TFoNfAd2Z0eHY7TMcf0V7anCx/pezrXny2QLYAFapG8e6Q/AAg9dx5+eFGF + Ow4gFIDgvOzTGKbGROHd30E5/cf0p/x5+BYA6C4ryEWp1mYQZIQwcu2YAAXZ4TgvVeaQ4Ev0NPpvfHau + r247YTN8T4eRTkOLuWkjfb/l+rMFJrkFRg/uGBqtVrhDgYYTmgA3fIEI+H14ef97UgCEcKcAo/Sn/HmY + FgDQwr1kc6rlp9BkjE/n2gl3ems6Y9gdETI47E555d3LSU+u+BHzoUwJB98n+VOXTz9bYBQsMKpw52nX + s+Mv8ktDZcaAPAJsYEqJWdBHuJtjdphEy7trAd6KJDsDIVWbmOzC+HQzM5OmX7gb3QivuZR024ygOtlV + t529uNx2GMIdfYb+gO8z30fhwc6HyBYYVbhjbl7ehTssMN9IdXU6wx9NBZzihsgZsC7fG5Io83oIFsCz + Fu6wu7Q7BucqcC3YRredK0guSeDORWQXeY2MhkSD5kbRbTd00qhKyW6kPO4822e4Z+5kC4yCBWoxS2jU + PuDZCXeg0DBsxjmr+H2KM/9HUnAzjcWm4EumP+XPQ7AA+MbUFtT2Ug3cf+A4jXVBk8Fzh+98D6+5RvTW + xLnCesiu4MZkNCcucR3BupeMzdhF6AfcR+2WywfKFpiEFrgDcOfxFu64e8ivzcUZ4uJxJ1PoxCx5kAE4 + hkC0vEtYwKzLFChcMgtmx/gxlIrZcdXJVQDcKVw4yQ7NYbqTGLigCjJGyOizmzhItz3DfRIiJp/ynbLA + HYA7p4rPzvu7+WCd716a02TkDIxgS17kS9xxwYfIgpJhPTQLQF7Jjv1LPSgVgnKg7BuSk49wyYU7Fw6y + 809ereinnXvMB5MNROwj9bM7V7AEd/Z1TPVO3fT5uNkCk8ECNZfdGeXCgw3WYQQSDYxo6LwbQB3Tmv7P + pCAgmD/WXFSAKf01f27FAuAbpptjHXGmuosrpsZie6jneOhkkYTvwFqy00ODdeDOT/wTaqc+O2TH98eX + TzWZlOyjfNflw2ULTCoL3Bm4Y2JcPOEO5fHjGiYkiDXYePfHDUwBRLRMzLsBT6CqFaLlbcICeOKSnZek + qlliVmq47WjorLsC3F22iVHTIDsRMlwgXrBMUWB4DGRnG+Cu564mY17TcNsn1ZOWTzZbYJQtcMfgznny + zAt30IAy21CcAS6456ABTJQIDt8jHUrm+6D6LUwn2U3YW92XSwOF04QwXCnhzsVKfXZYz09coCrZgTtC + jc47mrtw523AOAG2H+V7PR8uW2BSWaAWa2bekQ9gQljw/DdMKAbccS1pG7jBN/y/bi/oCYbxUXA2gVRp + g/zPqgWwEialK6XgYlc3gOlcjlDbdcNjRS2uV/jskh1q88ykPjtAp0h2PHfhHkGQgfU7csvlg2YLTBIL + 3GG484aO5w7c8fIQaiROaXAVvhv5DinYvgSjmIMD31UYMtCbW8AEL5SG5uL1yLWTAtbAnQsk3M0bo87O + X4Q1fPaU7LyBSfa0wHeUHNPHcwWF+yR5wPJpZgvcKQvcYbjzkPPM4wz6Cu+rfZXvjObhTsIFKIMX2YTv + 2X9vTnbedbQwhXHp6sZcAkBsQhjVc3gNyoE7hZAYmM6HhmTnJtZVjyLiQ3an/85wv1OPej7uZLNALRK2 + 3JEPmBtP0GmNUqCh+O7c91iNjw9VvsdknMz3/vhOWFG8FUH56mbo71wFp6RGQhhz8ZuxOT6Ez27GR+eg + BtPRYSzpNygzwl23/Y7cb/mg2QKTxwJ3GO4wnbnsjNThkuO5q882jHwPvjMoh6fPP6v6e/AdtxR5Iesz + qQWU2oU7PWVD4+Czo4xjxkgIA+hlugWfPdXZg+wMkFbJzjBJIJ4PKjNcvpBlJs9jls80W2D0LXAn4c6j + DizME8n7vq/wDr41TEtgehO0dQBEZ1AdDMTxTPmOo5r5rgUgO92hZAfxDXs++lQTQLKlbjsb81IVcJfs + OPLYH9c7yO6K2CW4g3JKie8Oq2bnffSf83zESWiBWqRqGeUPPOGqMUIBWBN3oeduYAwie2lkNdJXxZoe + aAv/9+0FHTmC/PDfwX1pg8n5TzzxMCZkrxoBS5psQEGGYWoKg6X0u/S+MB1Zxnh2pBWek8gbwz9BthyP + wj/5MoqId56qMTOuvWeCz1yyBbIFRsICdwbuPNs4gCDA4TX+whFkGdghBWJ6ZJXvrv5j8LuZxUqowmEP + vvMBVE1OoHvWuO0p2TFO1Rpsg9lDkJHsvCG5YJ6pYyA71obLhkjq2vPuFQQPV93LZzIZC5+D+/yT/oBe + JMN9JJ7nXGe2QFjgDsAdf8012PigSgCCGWQT1vA96GDWqv74zjkYaYNWU+W71aaTMCch4qE2xgkD8lrT + 0AggGxxjTzaW7FiP3le4m+6Rrpc+OJZVYkupLcRLiK/CPVz7kvOeH8VsgWyBEbJALSZ5jtoHXv/BgShB + NoE4+IBGsoMAmIJWIx2cHRNKMcSJwi767+rvfP//VIrVRmwlTmt1mwn8DRx39WoLdm54stgQNQw7sw1Y + R5+hcIGIhyFzJ3B3OISONlbewPLhlTf5wOXj6lD4wGa69l5WlRllmVG78fKBsgUmlQVGG+7OZ3HUDtw4 + 8Z0PYAi7MzQHR2AKfyNJbPA9deHVfB1f5TUfvuOkV+FFzcF3PgAvkDeBgR6nps8+INnZBpc8ldohO4IJ + 4x/CHefdNVQNocGAmDEkFzCdlhT0QXauDnxPvXtX4AvZfVI9b/lkswVGzQKjCncXzwPWkN2UJgZyuNgb + 7OaBZxucdxRetjTbFGhozvdY2QOrVcHN+CE1B+Lh3TBdeBgHE8dyD8EJmrbB0t/5YnPIDmfN567bjq1Q + urgE8B240xNDdjpOyY6jnebvDYKHh66THhfOTGHw3e9DxomA9+y8j9qjng802SxQi9wsI/oBs/I847aD + b3ATZA+4gxVlFp13HEbCM0zm7jKeTfQZExzypq8uXMUu3rqBfVEcZR0soNmdRYguXLhw5coV4gJh4mBr + GIXtsS2WjELf1vCgphlwfVQMqBrDB/pURz5MGhMTmiA7n0v5e700ElyIS3mvmmnCLPI9SsBdWWZE771c + ebbA5LTACMI97SdhruSFj2YPj/hr/Ep4BDucg4qfiLcIWYjQIHU4AApSNOF7qPYGUzb0VfkyZvE4kDso + F56NL168eP78edaGJjkicKf7gaGjwOsWD2EfFljHnti5P7JjKFDr0qmSnQJzGfAQ7iaNMTLSn9JEArHU + deCbD/I9SvpTie9sU5LdJ+fjl886W2DkLDCycHcUGI/P+Gj8axfGU2rnQ5DdoT/gzsZghe2BO4v+XL58 + GdaEe9hQnxFA+uZs4DoSDbEL/lQeonDc/ghYwiJtOH369KVLl2iVQd/GkLRI3pHeTCkmCnbu74iYHbJj + ZENfYhCVbhV8C3ds6BCrco0J3EtwL7E7/qkXX/215NdHtHt23kfu8c41T2YL1GJKZ1s+YErqiWU0wAei + KgREbOUzpIi5kUrtDHiqBpj6kW1ADBsLdzQQnWVX+ZEX5iBMI2f8LIbSEBoGBv/fRoVDp4ONRonA/YYb + x5e04cyZM3Q2LliBcGQwSfO9RuFX3oFShx0LYNj+jstPKdkxPq9NFC4T34NvLlaMePs6JfEjf69ZBHS9 + Syu482ZGCaz7T7aJ73XtvZTOU+W4yjJtuf1yJdkC2QJhgXbC3U4y1BieW/BqKkf+htSu217y2XHq9fF5 + 34cyhGqgewB3Ms8gcOMvM8QnNZz35PzVEuLVjvnL6bGZITewryHp6FdKu8Oy/jamBqoC7rQEsYiOx5QJ + 8H0U8N3fIfDNOYvUYYfy2La/7YE4jAbN+uxBdq6ak0iNZQqthg9mY24C93QtSlkvyqPEl16+8Ou9jtwh + Ge6ZR9kCI2GBNsM9JTt+GU8vKDFjCTQx9hHnnQ+ARn8TNxyIsDFPPloBRFZwN4E4JIXvyNwgnu+Fu/4g + 5qjyXWalEg04A+INeadKU0J8f3ykzbxDMJpqpjMTmuOH3hG4i3VOtjR22qQxnCaMpu8skR37RxIYPhgY + g1kwNWRvAnfpHEvbSPnUl/cyRUmd+uikhXvm+0g827nOSW6BWjpTfziftaPOOz44Dy2PPc+zs1eEO0AP + nV2yc0R+4vkHOjiPoAQtOxb9Ae4UF2VG6abgLKfI4FhVfYZqHR7kiEbpADX6GPqV/69RqcoaZqB01k+6 + B631NQK+0yS0I7qHhnWO3Jdi3XDMKMpKTQ7KtcAIIDViY5w+BtmNUOQa8cFBEUzHNzrs+uzpmkpsycVy + KdTSmhsNQV917dNl9rj63jM0bDi3X943WyBboGSBtsGdekNt54mV7CBAZzxipXWrnROvww58Ha9DyBbi + 0BzX2NUhcJApUl7QQ/+U7+Z/byjBK9HE3Fd6Do7YHwGBYymIUKcY2KW9Ap0T/RZdBec7cgTvrxOihSnT + +Ywx6ZyatITzgtToLeZyYHuxTuF6Rfg5l8lAJiwJyoPsJbhH8q+GcLdH940t9eIb8j2yuofbnh/ObIFs + gTZaoG1wL7ntPM/4ibh4kMV8AzzMsBW+0Ho+AAI28FewrrbOX3R24S7WTVnFBpZY4I0uId73leCrfIfs + BllGBD3YAk9wrT8ahl+cyh068kZwlnz5UeA7dK666q1gnbbRZgcezNCLKYLsXIJIDMAHR0SwZCrFpJ67 + yTuFu2nZQzQvLXDTH9xT7qvnmDssw72Nz3OuKlsgLFBLZ+cP57OeO8UIGXM9gmCwDhHABFAw+k3uq8Uj + swB0hA7JrtuOhx6xhmxgXIqz4Z0Qb55Cdk89RLSghhK80SCq8NDE9GSQpTmmcYerbrJeM1WZW3HkyI50 + TgPMukMXVSoDijA0jBowjivThsiuw07BVkajm13d2afYsyTFhCBjEKQLbmBAZRk6V8Nd0iLoG3K81Ae4 + F23ztuH+Gc7tl/fNFsgWKFlgNOAOEaCDay05xRFSGOwI0KOgyeiwm4ZQoBMkQ2FjPcqYPAni8egZYgUx + oQD058JDLmMuY56UIIMsQLAJo/kVHUYdqVpkoqPEw2Q9B6IG0+w0BLrHojHNG+y50FRNrRqWSjFUAlJj + thEUpg9jm5LDLtabwz0894B7f2QPJ90AKkskHgi1PT+c2QLZAm20QDvhrvOu587TC1lCmRHoEARSg2zX + 9wHl+OmWwLrxhVA7Vs1Ol/gxFtuJNtRDH0DBkUyjMnBLqyq8w7mqNEgQbAPgqA1+0eYBiYmbD1j78+WD + +4F7HWQcfPaywO74bLyQIUO0p+qbp98M6kUBfx9r6LBzjobwhxRDtV4UQxK5UvxkWs3mcE81GT138wfo + vEvqoHbIMr5XxaBryccX7ulQahtv61xVtkC2QK2aLX1o32jKGFY1YEYFxrwi6jOBeAgeq/zggwfTdfBT + ESCyUIVGbAIy3wZEPDhLJZqGLryjoxGFKeKdVc8R9eL/soUipgeEcnNkN/81XghabBKtpvsBl8pfzvPS + YaeDsXBZ0/lEXqyIdEzl9dRhV5CJy2E+yIiWwc6SvaHznmK9mrE6ldq9eYZ24+W9sgWyBRpaoG1wN/Oi + Wr6Dq8F3A5xLiIcmkX0Qdz6YHkkH0+RT6aQYZ8E4VAt0qAc3X10+HWVll4aBNLrwTqFSiGczdlSogUc4 + vy0QvtgEASS0FCNzhlwMQKRVTkFqsQFuRhtoNgbkFDjrmILkqwOFmrkWMZkIItPPmaRhQLgH2dP1lQLu + qeeeOu+pvK6HXioR2+4Nk8me8ZQt0HYLtBPuDfnuM68srhqQUt5ZkYJDD9157b7yx3t9Gk/NZz1QqmJ7 + 9g0XHvcfQKfzJKmqIeLVOsKLp+XQh42pjS4HeIHpQRHWjcE9HrRTcCN5ThA2nGghbvY0x3WHcCyxzsmK + dRoPMdVhAusciM4sjUpkGy5H6DD9qTEuVp667VW4c0SvUWmktET2EtxjmlsIMtltb/tTnSvMFsACtWoE + 4TC/EfGWiHznkYaeAfqU9TEfXVIYgFFaoCdNbKAPaEAOuxhKnyIeoQbol2a9G0tTCnCEgwI3tHgORLVU + qDTBZ34dGnlHdC86JydnuQ4tzQ7RKYR+zs7TicI/SzHsJTWmxHTVmFjVNpZPMT9MzFAtKTOpSpNeRy9i + OmUpxfow77q8e7ZAtkDJAiMC9+g2U6GmBPpgfSl2In342SVqiFDLtB444mwpVRowBLxwveE7PqkAivFD + fdsmiMfhNVUWxzKkRO0CxhlVMqK8bqVywE1LHCSgB4LaDbFOUznNFOsY2QnAJR2mOdwl+5Dh3pzsqRqT + H8tsgWyBtlug/XCniek7UWnMOp1iUM38UAp2jpcAK0yrCnFfnQGQqdKAY4V4EQ8EzUHo+4EuZzWcxowF + evHpiCstBKbsYqg+hapoRuu6fCvIbr4Nug0mpZdSfaIltIdTxgL0QyHCGIpD+zkXlauAu1k203DSKuIb + Bj5WyR6jqakm0zAMxhes0NYVYaLEha5OTWj7LZ4rzBaYnBaolZSK9v4Tm1Jhf5YV2XYGrVs/eg53VPwR + 8cr6ID7CaRxuBfcp310qCAKyY3q+TkONgMUS5anf1GYG6YNaIAuzwCt0/qu2FsR0GsbpgFePxXE5Om2w + zREJk7aW7zVCkJ29TGDZn89udoGqwt7QYXdExM4yHUptOFhqMEwwPTr1khTT3vst15YtkC0QFhhZuA9o + 6IZML+1lD1HtJPxG1pvSAMpETpsS4kEkwNJ5N6TS6EzDvUtaje5wlfIcETaxPUeJSbbwkWgfiE+FfEkz + zKrIeOmAwKdXMMeZrwi0jXqctGXaAJrH9xyREwymp22jkezOrwpQkXXHwWE6NrM4tAL3CIxpSPZS8FIE + sKdkTwdL+yN72jd79Qe8SfIG2QLZAkOwwB2Ge0ptYT2Ec0hdeJgSQrxhOakXr4Cu5x45s1By2CaGJaMB + JUc+8lmmq4vE4WK6lgH4pUBPcen4JL+iF4FdSsSAOrPf7sH4E4HOqTkxyolI6TQop87SgPCmhTunZuJG + XzIIEiX/WhO1vRQVY1OpQbPEJIN0kY0ge39D31Wyl0JiolMfwuXOu2QLZAu0YoExAfdWGtp8G2GRqjSG + 05jfJhDvlFS1CL50GNaEt65WYQIcYwrjiDC0ClbVeUDvbCY2jheImKPrXM2YFOrQbikNekzUBOW+QJi+ + xpU0qsd1/hRbUq2nENjln4438Nd8vPzEmTIZuGFIe0OspyGPvt94iFLjI39Aw1HTVFsvhbFnb334d3uu + IVugFQvUGmZNGadfhnQTUZh68eI1KO9EWYcQAbro58tYjchwFL5PdfkYvYww9vRDOhgr8Smu7FrKvU49 + fONPbhYct5JYY7Z0ILZUfkkdaucTxSmEu+0kVU6fn4wdKiXvTcMcPffUVS91GyH4RLIBmV6KbkxzsjcM + c/SOHKd3V252tsD4ssCEgjumD50nvHiVkxhujSlUeutSHporRCieCHcz2DhFCIZG3KHad0wobcj60pdK + Os3Z3bAegxpBqkk0qwhOnWsjghzw5HyxBm4yHZvhoZ5mOuO0xHQVmP6wXpVi0qD1AbEeb0Lj6/HIrc0W + GL8WmGhw90qkUn548Wk6hNJEWSkv02Wourl8jzQJuMAUpw459xVmCXr1k1ZA32Qb6E9tNBg0mxEhPO5I + uht8h8KchVErMYPXz/7TTgj/Gk/fId8YKRXrSlLB9AGxnqZybB4JUxonzw77+AVEbvn4tUBtyOlQxv6O + JUe+lLRSRV65xvHVVHwPDxfcV/luWnkKCQ/EvbOKqCcIqHSu6pIWvkz9XOjMXqY9MMuxA62GpUeoom8Y + fgmjaTMEN6tiRBmm07scNqDL4S99gAHyvp3QzjQXW6raK79E7ocQYWLgtBTaWNVeUimw9FSM/RsmtzBb + YCJZYCLDPRW7hU6q1ThFNjLVpJR33ddQ4WOCD4jUeU/hbtphElvGilGElkcxEjFWlYrvXViKXdw9XZNE + vpdS2IN79mUZE36iE6JLAOWcjgq+ZxqDulIe6DvYSzdGJ9Ef05VxIjVbJIGIpAKpvF5aWCNmKlTDnCS7 + DZtID0w+l2yB8WKBCQ73AF9JrjGrgbOfqpSHd2m4ZAr6iLcB9ADXZaFahLurBloC7vI9hXt47k4r5SjG + TVLIeg/6wbSKkHJQ5IXnnaDEdweB2RhVxzMKP70J06tYbzizNKae9eetj5dnILczW2BCWqBm2MZkKHH9 + AvRGT0aO4moIo7kn1W3S0PgQcGJI1qlMsRZgZKvXow+/XpSr5yjsBMojmiWdMupLQ0TNm/UeBYmmujAT + c1lNO2xq3zQo08w8qkD0T5FuM11e3GHSqvxSXdc0svJGLGN/qstkuJfyOWYLjH0LTCK4x8WoUl65pkR5 + RZvIl6tAH059dSaUMk4aUqlwH5P7Sx/8tTrOmdbjZ0d6fVeA75BauLu2H/nfzTMcic/gr6eDOONnZ2xF + ZoIS0E0OE3lgQnupZoCpBjKmLs/Yv91zC7MFJo8FJiPcI/y8KtpEerIq6CMrfbqeUerXV117BzBD1SlR + O2aBGrViGKIl9HE+GIMfA6pmQ4POnEXkL3MJ1nDeU7g7N8oMl6mHLtDT3F6Z6ZPnsc9nOhksUHMezWQu + DT1650OVWK9AH8mK9X9Lrr0Ds5aQuZt/cOMIUY9w9chk6UxagmSUaFBy+InmIcuYs8xl9qrOu4MKeO40 + ErhHpsbm6QFKMen9+eaT+Z7J554tMPYtkOF+4xqlPXmq28Ss15J0Ax+D9Snu02WPIgTFufuqOvE5jTtU + MAnZpPRB6R8vXr6bBI2jI7LDdNOToc/gyJeUd+BuuCROOu5/GsgY+ZOrES/V+JbUOGP/ns4tzBbIFsAC + Ge7l26Ah5SPWMPJQCsdIK5+y3gmxlHDt03Uz0s8x+ai0mJG9hcWqYs0p9RnEd/oGnXewnjrvrg0LoB0r + dpSYgueeaujVWJcS00vvrflpyRbIFhhfFqiVptjkf6YWSK9lSb0pxVbq/1ZxH1lwm39IdZKY4hQBiO5L + T4ALr/+OOBPOO4J7OO8o7yYBjrBIarZ7QMp32aYYFPUFpTnE8/2QLZAtME4tkOHe6oUL0FeHYmK2VKrh + hF4v8dP1AtPlqErySKQ7Tz9E6AsOOA67uXxx3lXekdpLyrtLwppbhh7CoWAntWagt3q983bZAuPcAhnu + g7uADd/LqkpONcWNek76N4SRhllw0xpidFdSg2k0FrPNgHuahPLuWn148anyTs2uB6tqT4mmlk5kcFbI + W2cLZAuMeQvU8PJyGY4FSpe4oZIDUptMgWsxKosahLV8Z4DURcDpJKrOe8S88yuSjpI9ygzHKjU4zt3M + w7lkC2QLTAwLZLi38zo27MtLuPefQLbhS0DzrsIJqEjnyCyKM/jvsD6cd8T3qvPu9qYn87gexQb0x/p2 + 2iXXlS2QLTDqFshwH0GTD/a9zaY02cteAWeccBrnJeG8Q21EecNmUGb467CqYTN0Bjr7bMYYrDmKq+JM + etARtEiuOlsgW2C0LFAz81Quo28BL/GAxy3JJlAY/x2axwoeREaG825MZMl5tzNQyUF/j3yN6dtDVZMZ + sGF5g2yBbIGxbIEM97F8dW61LZx6nXcccJT0cN4R03HPmcFkzHvJeXdjwmyAO4inY4jFNCLpfKrPtNjr + jA/D5VZmC0xWC2S4j48rn8IdEENnlHSGSUlLYE4xs80gyBg2U8pGQJgNG5vcxnmqRmeaaaCE+HhXGB+m + ya3MFsgWaGSBWqztmT+MZQuYtN1R0FDSVWYYUyXmnfFVnXfnNKXOe8g4bKOGY04CcwKnfFd5D7FoLBsk + ty1bIFuguQUy3MfBHRJkh7ymFojZScgsTmiiEBIDx80DbCrgSCXG9qjtjKkytZWYd7YU8brwme/j4CbI + TcwWGKQFMtwHabBR39z3rXDbYzkOuIzn7jApZGcRD4Jn+JKNwbrDqpEHGO1FjR7PHSUH/d2VtUt8p3LF + 9+y8j/p1zgfMFmizBWrEzOUyli3ABU/h7lqpyCkmjYHXwBp/HLhTQDaAZpJqyXnnS7iPz25oPF0Cn01b + BvRjOVbjZyS7N9pYtkxuW7ZAtkATC2S4j93bI/rxgLtJbNRkcLqhs3DHH2cRDxbwc7xU511lBtBzhiDb + rO7Oa0WpZ0d6ghBn+JU+Q889w33s3hO5ZdkCLVsgw71lU92hDVPPXbgDYuDuKoBpHjEXZcUlB9Oo7Trv + hs2gtBDtLtwdfRXu1EA9jqw2hHt23u/QZc+HzRYYrgVqPPm5jGULcIWD7zGaaqJ2/G5Qbh4xnHdWaALu + CC8473jfYD2cd/6Zwh3PnV7BYVXqcSk+uo1w2/H9484ay8bJbcsWyBbozwIZ7mP33gi8BtxN5GtGAddX + 0nkH1rjkLuKBPmM2MfZiQJXCGbIju9ATILgj0Ku5N9dkMtzH7p2RW5Yt0IIFMtxbMNId2qQEd7xpcw8o + uwffccDN+GgeYBbhA998yTbGvTjpCZSjxqjJOJpqqIyCjPOY2N7gnFBj7tCp58NmC2QLDNcCNQbcchmb + FuDa2jA+hDhjqHuk/3UJ7HQdPhFPjjAkdbx7F/owcRjQ5yd99lSNiXHUiJCJ22psWia3KlsgW2BAC2S4 + D2iiO7xBcFby6r/LdzxuF0oF4rjhgXgTQIJyAmlQYEz2S5AMf9XZ2d65S66bqoOfyX6Hr3Q+fLZAWy2Q + 4d5Wc7a7svTFTOc91d9dAETE66HrxSO54LYbSGM+GT5Uh0/7C3z0oO0+lVxftkC2wKhaoOaYWy5j3AJx + U0jeVKUx20xo8QF6F92OpbcjU5iLYkcwu8p+leZj3CC5edkC2QLNLZDhPs7uECV4+Z5GSUZOMRfiMKgm + LTLdUVNFmMB66qqPM3Pk5mYLZAv0Y4EM93F2a1Rd+KC8io3TWSMXTSyxlKaL0VWvyi/jzBa5udkC2QL9 + W6DGVJdcxpEFGl7KVMlrEj8Vm6WVjKNzz03NFsgWaN0CGe6t22qMbjkE32WMnkluVrZAtkD7LJDh3j5b + 5pqyBbIFsgXGjAUy3MfMpcgNyRbIFsgWaJ8FamSFzSVbIFsgWyBbYIJZIMN9gl3QfDrZAtkC2QKFBTLc + 832QLZAtkC0wAS1Qc0mHXLIFsgWyBbIFJpIFMtwn0tXM55ItkC2QLXDDAhnu+VbIFsgWyBaYgBao/WUu + 2QLZAtkC2QITzgIZ7hPukuYTyhbIFsgW+Mu/zHDPd0G2QLZAtsAEtEDtr3LJFsgWyBbIFphwFshwn3CX + NJ9QtkC2QLbAX/1Vhnu+C7IFsgWyBSagBWr/OZdsgWyBbIFsgQlngQz3CXdJ8wllC2QLZAv85//8/wNu + r1zYpv3VXAAAAABJRU5ErkJggg== + + + + 45, 13 + + + $this + + + 237, 154 + + + 1 + + + Hemsida: + + + $this + + + Stäng + + + 10 + + + 6 + + + www.vistaico.com + + + $this + + + 4 + + + label6 + + + True + + + 294, 185 + + + $this + + + Version: + + + 237, 220 + + + 237, 120 + + + 2 + + + 109, 13 + + + 2007.1.0 + + + 93, 13 + + + 6 + + + 294, 101 + + + True + + + 6, 13 + + + True + + + 237, 101 + + + True + + + $this + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + 0 + + + cmdClose + + + 237, 185 + + + True + + + English + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAbout.sv.resx b/scheduler/DeviceScheduler/frmAbout.sv.resx new file mode 100644 index 00000000..cc814e94 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAbout.sv.resx @@ -0,0 +1,897 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + 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 + r1zYpv3VXAAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskSecurityPolicy.Designer.cs b/scheduler/DeviceScheduler/frmAskSecurityPolicy.Designer.cs new file mode 100644 index 00000000..4da78be2 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskSecurityPolicy.Designer.cs @@ -0,0 +1,172 @@ +namespace DeviceScheduler +{ + partial class frmAskSecurityPolicy + { + /// + /// 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() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmAskSecurityPolicy)); + this.label1 = new System.Windows.Forms.Label(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.cmdYes = new System.Windows.Forms.Button(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.chkHide = new System.Windows.Forms.CheckBox(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AccessibleDescription = null; + this.label1.AccessibleName = null; + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // linkLabel1 + // + this.linkLabel1.AccessibleDescription = null; + this.linkLabel1.AccessibleName = null; + resources.ApplyResources(this.linkLabel1, "linkLabel1"); + this.linkLabel1.Font = null; + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.TabStop = true; + this.linkLabel1.Tag = "http://support.microsoft.com/kb/310715/sv"; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // cmdYes + // + this.cmdYes.AccessibleDescription = null; + this.cmdYes.AccessibleName = null; + resources.ApplyResources(this.cmdYes, "cmdYes"); + this.cmdYes.BackgroundImage = null; + this.cmdYes.Font = null; + this.cmdYes.Name = "cmdYes"; + this.cmdYes.UseVisualStyleBackColor = true; + this.cmdYes.Click += new System.EventHandler(this.cmdYes_Click); + // + // pictureBox1 + // + this.pictureBox1.AccessibleDescription = null; + this.pictureBox1.AccessibleName = null; + resources.ApplyResources(this.pictureBox1, "pictureBox1"); + this.pictureBox1.BackgroundImage = null; + this.pictureBox1.Font = null; + this.pictureBox1.ImageLocation = null; + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.TabStop = false; + // + // panel1 + // + this.panel1.AccessibleDescription = null; + this.panel1.AccessibleName = null; + resources.ApplyResources(this.panel1, "panel1"); + this.panel1.BackColor = System.Drawing.Color.White; + this.panel1.BackgroundImage = null; + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.pictureBox1); + this.panel1.Controls.Add(this.label1); + this.panel1.Font = null; + this.panel1.Name = "panel1"; + // + // label3 + // + this.label3.AccessibleDescription = null; + this.label3.AccessibleName = null; + resources.ApplyResources(this.label3, "label3"); + this.label3.Font = null; + this.label3.Name = "label3"; + // + // label2 + // + this.label2.AccessibleDescription = null; + this.label2.AccessibleName = null; + resources.ApplyResources(this.label2, "label2"); + this.label2.Font = null; + this.label2.Name = "label2"; + // + // label4 + // + this.label4.AccessibleDescription = null; + this.label4.AccessibleName = null; + resources.ApplyResources(this.label4, "label4"); + this.label4.Font = null; + this.label4.Name = "label4"; + // + // chkHide + // + this.chkHide.AccessibleDescription = null; + this.chkHide.AccessibleName = null; + resources.ApplyResources(this.chkHide, "chkHide"); + this.chkHide.BackgroundImage = null; + this.chkHide.Font = null; + this.chkHide.Name = "chkHide"; + this.chkHide.UseVisualStyleBackColor = true; + // + // frmAskSecurityPolicy + // + this.AccessibleDescription = null; + this.AccessibleName = null; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = null; + this.Controls.Add(this.chkHide); + this.Controls.Add(this.label4); + this.Controls.Add(this.label2); + this.Controls.Add(this.panel1); + this.Controls.Add(this.cmdYes); + this.Controls.Add(this.linkLabel1); + this.Font = null; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = null; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmAskSecurityPolicy"; + this.Load += new System.EventHandler(this.frmAskSecurityPolicy_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Button cmdYes; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.CheckBox chkHide; + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskSecurityPolicy.cs b/scheduler/DeviceScheduler/frmAskSecurityPolicy.cs new file mode 100644 index 00000000..c1cbb850 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskSecurityPolicy.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace DeviceScheduler +{ + public partial class frmAskSecurityPolicy : Form + { + public frmAskSecurityPolicy() + { + Localization.ChangeLanguage(); + InitializeComponent(); + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.ProcessStartInfo info = new System.Diagnostics.ProcessStartInfo(); + + info.FileName = linkLabel1.Tag.ToString(); + info.UseShellExecute = true; + + System.Diagnostics.Process.Start(info); + } + + private void cmdYes_Click(object sender, EventArgs e) + { + SaveCheckbox(); + this.DialogResult = DialogResult.Yes; + this.Hide(); + } + + private void SaveCheckbox() + { + Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(@"Software\Telldus\Scheduler\Settings",true); + key.SetValue("AskSecurityPolicy", !chkHide.Checked); + key.Close(); + } + + private void cmdNo_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.No; + this.Hide(); + } + + private void frmAskSecurityPolicy_Load(object sender, EventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskSecurityPolicy.en.resx b/scheduler/DeviceScheduler/frmAskSecurityPolicy.en.resx new file mode 100644 index 00000000..686ed9fe --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskSecurityPolicy.en.resx @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + 248, 13 + + + Important information regarding scheduling + + + Scheduled tasks can not be performed with a blank password. + + + + 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 + gf8DCdMeTzy5zwoAAAAASUVORK5CYII= + + + + 177, 13 + + + Carefully read the information below. + + + The application has detected that the security policy for Windows Accounts with blank password is activated. If your account does not have a password, then you are recommended to turn of the security policy due to the fact that scheduling can not be performed with a Windows account that lacks password. + + + 306, 13 + + + For more information about this, see Microsofts knowledgebase: + + + 175, 17 + + + Don't show this message again. + + + Important information about Telldus Scheduler + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskSecurityPolicy.resx b/scheduler/DeviceScheduler/frmAskSecurityPolicy.resx new file mode 100644 index 00000000..df0d4295 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskSecurityPolicy.resx @@ -0,0 +1,446 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + 301, 13 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 179, 242 + + + panel1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + panel1 + + + panel1 + + + 316, 13 + + + + 8 + + + + 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 + gf8DCdMeTzy5zwoAAAAASUVORK5CYII= + + + + chkHide + + + label2 + + + + CenterParent + + + 435, 277 + + + 1 + + + 9, 156 + + + OK + + + True + + + 3 + + + $this + + + Visa inte detta meddelande i fortsättningen. + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Viktig information Telldus Schemaläggare + + + För mer info kring begränsningen se Microsofts kunskapsdatabas: + + + 6, 13 + + + 2 + + + 229, 17 + + + 2 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 260, 13 + + + linkLabel1 + + + AutoSize + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 12, 92 + + + 0 + + + 10 + + + 397, 59 + + + True + + + Programmet har upptäckt att säkerhetsprincipen för Windows konton med blanka lösenord är aktiverad. Om du inte har nÃ¥got lösenord pÃ¥ ditt Windows konto rekommenderas du att stänga av säkerhetsprincipen dÃ¥ schemläggning inte kan utföras med Windows konto som saknar lösenord. + + + 1 + + + panel1 + + + 48, 48 + + + pictureBox1 + + + 216, 13 + + + Läs noga igenom nedanstÃ¥ende information. + + + frmAskSecurityPolicy + + + 9 + + + label3 + + + $this + + + 3 + + + label1 + + + 12, 18 + + + label4 + + + cmdYes + + + -3, -3 + + + 5 + + + 6 + + + 7 + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + 9 + + + Schemalagda aktiviteter kan inte utföras med ett tomt lösenord + + + True + + + True + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 4 + + + 9, 169 + + + 31, 41 + + + 1 + + + 378, 15 + + + $this + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 75, 23 + + + 0 + + + Microsoft Sans Serif, 8.25pt, style=Bold + + + True + + + 475, 73 + + + $this + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Viktig information angÃ¥ende schemaläggning + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 13, 200 + + + $this + + + True + + + English + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskSecurityPolicy.sv.resx b/scheduler/DeviceScheduler/frmAskSecurityPolicy.sv.resx new file mode 100644 index 00000000..11662d8f --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskSecurityPolicy.sv.resx @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + 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 + gf8DCdMeTzy5zwoAAAAASUVORK5CYII= + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskUsername.Designer.cs b/scheduler/DeviceScheduler/frmAskUsername.Designer.cs new file mode 100644 index 00000000..17290092 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskUsername.Designer.cs @@ -0,0 +1,176 @@ +namespace DeviceScheduler +{ + partial class frmAskUsername + { + /// + /// 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() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmAskUsername)); + this.pictureBox2 = new System.Windows.Forms.PictureBox(); + this.label16 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.txtPassword = new System.Windows.Forms.TextBox(); + this.txtUsername = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.cmdOK = new System.Windows.Forms.Button(); + this.cmdCancel = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // pictureBox2 + // + this.pictureBox2.AccessibleDescription = null; + this.pictureBox2.AccessibleName = null; + resources.ApplyResources(this.pictureBox2, "pictureBox2"); + this.pictureBox2.BackgroundImage = null; + this.pictureBox2.Font = null; + this.pictureBox2.ImageLocation = null; + this.pictureBox2.Name = "pictureBox2"; + this.pictureBox2.TabStop = false; + // + // label16 + // + this.label16.AccessibleDescription = null; + this.label16.AccessibleName = null; + resources.ApplyResources(this.label16, "label16"); + this.label16.Font = null; + this.label16.Name = "label16"; + // + // label15 + // + this.label15.AccessibleDescription = null; + this.label15.AccessibleName = null; + resources.ApplyResources(this.label15, "label15"); + this.label15.Font = null; + this.label15.Name = "label15"; + // + // txtPassword + // + this.txtPassword.AccessibleDescription = null; + this.txtPassword.AccessibleName = null; + resources.ApplyResources(this.txtPassword, "txtPassword"); + this.txtPassword.BackgroundImage = null; + this.txtPassword.Font = null; + this.txtPassword.Name = "txtPassword"; + // + // txtUsername + // + this.txtUsername.AccessibleDescription = null; + this.txtUsername.AccessibleName = null; + resources.ApplyResources(this.txtUsername, "txtUsername"); + this.txtUsername.BackgroundImage = null; + this.txtUsername.Font = null; + this.txtUsername.Name = "txtUsername"; + this.txtUsername.TextChanged += new System.EventHandler(this.txtUsername_TextChanged); + // + // label14 + // + this.label14.AccessibleDescription = null; + this.label14.AccessibleName = null; + resources.ApplyResources(this.label14, "label14"); + this.label14.Font = null; + this.label14.Name = "label14"; + // + // groupBox1 + // + this.groupBox1.AccessibleDescription = null; + this.groupBox1.AccessibleName = null; + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.BackgroundImage = null; + this.groupBox1.Controls.Add(this.label14); + this.groupBox1.Controls.Add(this.label16); + this.groupBox1.Controls.Add(this.pictureBox2); + this.groupBox1.Controls.Add(this.label15); + this.groupBox1.Controls.Add(this.txtPassword); + this.groupBox1.Controls.Add(this.txtUsername); + this.groupBox1.Font = null; + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // cmdOK + // + this.cmdOK.AccessibleDescription = null; + this.cmdOK.AccessibleName = null; + resources.ApplyResources(this.cmdOK, "cmdOK"); + this.cmdOK.BackgroundImage = null; + this.cmdOK.Font = null; + this.cmdOK.Name = "cmdOK"; + this.cmdOK.UseVisualStyleBackColor = true; + this.cmdOK.Click += new System.EventHandler(this.cmdOK_Click); + // + // cmdCancel + // + this.cmdCancel.AccessibleDescription = null; + this.cmdCancel.AccessibleName = null; + resources.ApplyResources(this.cmdCancel, "cmdCancel"); + this.cmdCancel.BackgroundImage = null; + this.cmdCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cmdCancel.Font = null; + this.cmdCancel.Name = "cmdCancel"; + this.cmdCancel.UseVisualStyleBackColor = true; + this.cmdCancel.Click += new System.EventHandler(this.cmdCancel_Click); + // + // frmAskUsername + // + this.AcceptButton = this.cmdOK; + this.AccessibleDescription = null; + this.AccessibleName = null; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = null; + this.CancelButton = this.cmdCancel; + this.Controls.Add(this.cmdCancel); + this.Controls.Add(this.cmdOK); + this.Controls.Add(this.groupBox1); + this.Font = null; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = null; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmAskUsername"; + this.Load += new System.EventHandler(this.frmAskUsername_Load); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox2; + private System.Windows.Forms.Label label16; + private System.Windows.Forms.Label label15; + private System.Windows.Forms.TextBox txtPassword; + private System.Windows.Forms.TextBox txtUsername; + private System.Windows.Forms.Label label14; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Button cmdOK; + private System.Windows.Forms.Button cmdCancel; + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskUsername.cs b/scheduler/DeviceScheduler/frmAskUsername.cs new file mode 100644 index 00000000..f0924c65 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskUsername.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace DeviceScheduler +{ + public partial class frmAskUsername : Form + { + public frmAskUsername() + { + Localization.ChangeLanguage(); + InitializeComponent(); + } + + private void frmAskUsername_Load(object sender, EventArgs e) + { + txtUsername.Text = Environment.MachineName + @"\" + Environment.UserName; + } + + public string Username + { + get { return txtUsername.Text; } + } + public string Password + { + get { return txtPassword.Text; } + } + + private void cmdOK_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.OK; + this.Hide(); + } + + private void cmdCancel_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.Cancel; + this.Hide(); + } + + private void txtUsername_TextChanged(object sender, EventArgs e) + { + cmdOK.Enabled=(txtUsername.Text.Length>0); + } + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskUsername.en.resx b/scheduler/DeviceScheduler/frmAskUsername.en.resx new file mode 100644 index 00000000..7d2b33fc --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskUsername.en.resx @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + 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 + + + + 56, 13 + + + Password: + + + 32, 13 + + + User: + + + To be able to perform the scheduled task you need to specify the username and password that you enter when logging into Windows. This information is needed in order to get persmission to run. The application is storing the information in secure (encrypted) fashion. + + + User details + + + Cancel + + + User account + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskUsername.resx b/scheduler/DeviceScheduler/frmAskUsername.resx new file mode 100644 index 00000000..ec4c0534 --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskUsername.resx @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + 6 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + + 149, 132 + + + 2 + + + 403, 194 + + + 75, 23 + + + 4 + + + 13 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 + + + 74, 106 + + + + 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 + + + + 181, 20 + + + label16 + + + 487, 224 + + + 0 + + + $this + + + groupBox1 + + + 149, 106 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + Användarkonto + + + cmdOK + + + 75, 23 + + + 6, 13 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 3 + + + pictureBox2 + + + Användare: + + + txtUsername + + + label14 + + + groupBox1 + + + 14 + + + 62, 13 + + + 10 + + + Avbryt + + + 1 + + + cmdCancel + + + True + + + True + + + $this + + + label15 + + + frmAskUsername + + + 18, 31 + + + 12, 12 + + + txtPassword + + + 74, 135 + + + 7 + + + 48, 48 + + + För att kunna utföra schemaläggningen behöver du ange det användarnamn och lösenord som du loggar in med i Windows. Dessa uppgifter behövs för att schemaläggningen skall fÃ¥ tillÃ¥telse att kunna köras. Programmet sparar informationen pÃ¥ ett säkert (krypterat) sätt. + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 321, 194 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + OK + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 72, 31 + + + 12 + + + groupBox1 + + + 11 + + + Användaruppgifter + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + AutoSize + + + 181, 20 + + + 374, 52 + + + 54, 13 + + + 8 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 466, 176 + + + 9 + + + groupBox1 + + + * + + + groupBox1 + + + CenterParent + + + groupBox1 + + + 2 + + + Lösenord: + + + 1 + + + True + + + English + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmAskUsername.sv.resx b/scheduler/DeviceScheduler/frmAskUsername.sv.resx new file mode 100644 index 00000000..bfda575b --- /dev/null +++ b/scheduler/DeviceScheduler/frmAskUsername.sv.resx @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + 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 + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmMain.Designer.cs b/scheduler/DeviceScheduler/frmMain.Designer.cs new file mode 100644 index 00000000..8d847b25 --- /dev/null +++ b/scheduler/DeviceScheduler/frmMain.Designer.cs @@ -0,0 +1,679 @@ +namespace DeviceScheduler +{ + partial class frmMain + { + /// + /// 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(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmMain)); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuNew = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuExit = new System.Windows.Forms.ToolStripMenuItem(); + this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuRemove = new System.Windows.Forms.ToolStripMenuItem(); + this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolManageDevices = new System.Windows.Forms.ToolStripMenuItem(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuWebsite = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.toolNew = new System.Windows.Forms.ToolStripButton(); + this.toolEdit = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator = new System.Windows.Forms.ToolStripSeparator(); + this.toolRemove = new System.Windows.Forms.ToolStripButton(); + this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components); + this.lvwCommon = new System.Windows.Forms.ListView(); + this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader3 = new System.Windows.Forms.ColumnHeader(); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.cmdTurnOn = new System.Windows.Forms.ToolStripMenuItem(); + this.cmdTurnOff = new System.Windows.Forms.ToolStripMenuItem(); + this.imageList1 = new System.Windows.Forms.ImageList(this.components); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.pictureBox3 = new System.Windows.Forms.PictureBox(); + this.label5 = new System.Windows.Forms.Label(); + this.linkLabel2 = new System.Windows.Forms.LinkLabel(); + this.label6 = new System.Windows.Forms.Label(); + this.pictureBox2 = new System.Windows.Forms.PictureBox(); + this.label4 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.linkLabel1 = new System.Windows.Forms.LinkLabel(); + this.label2 = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.label1 = new System.Windows.Forms.Label(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.lvwTasks = new System.Windows.Forms.ListView(); + this.columnHeader4 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader5 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader6 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader7 = new System.Windows.Forms.ColumnHeader(); + this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.mnuRunTask = new System.Windows.Forms.ToolStripMenuItem(); + this.menuStrip1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + this.contextMenuStrip1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.contextMenuStrip2.SuspendLayout(); + this.SuspendLayout(); + // + // statusStrip1 + // + this.statusStrip1.AccessibleDescription = null; + this.statusStrip1.AccessibleName = null; + resources.ApplyResources(this.statusStrip1, "statusStrip1"); + this.statusStrip1.BackgroundImage = null; + this.statusStrip1.Font = null; + this.statusStrip1.Name = "statusStrip1"; + // + // menuStrip1 + // + this.menuStrip1.AccessibleDescription = null; + this.menuStrip1.AccessibleName = null; + resources.ApplyResources(this.menuStrip1, "menuStrip1"); + this.menuStrip1.BackgroundImage = null; + this.menuStrip1.Font = null; + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.editToolStripMenuItem, + this.toolsToolStripMenuItem, + this.helpToolStripMenuItem}); + this.menuStrip1.Name = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.AccessibleDescription = null; + this.fileToolStripMenuItem.AccessibleName = null; + resources.ApplyResources(this.fileToolStripMenuItem, "fileToolStripMenuItem"); + this.fileToolStripMenuItem.BackgroundImage = null; + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.newToolStripMenuItem, + this.toolStripMenuItem1, + this.mnuExit}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.ShortcutKeyDisplayString = null; + // + // newToolStripMenuItem + // + this.newToolStripMenuItem.AccessibleDescription = null; + this.newToolStripMenuItem.AccessibleName = null; + resources.ApplyResources(this.newToolStripMenuItem, "newToolStripMenuItem"); + this.newToolStripMenuItem.BackgroundImage = null; + this.newToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuNew}); + this.newToolStripMenuItem.Name = "newToolStripMenuItem"; + this.newToolStripMenuItem.ShortcutKeyDisplayString = null; + // + // mnuNew + // + this.mnuNew.AccessibleDescription = null; + this.mnuNew.AccessibleName = null; + resources.ApplyResources(this.mnuNew, "mnuNew"); + this.mnuNew.BackgroundImage = null; + this.mnuNew.Name = "mnuNew"; + this.mnuNew.ShortcutKeyDisplayString = null; + this.mnuNew.Click += new System.EventHandler(this.mnuNew_Click); + // + // toolStripMenuItem1 + // + this.toolStripMenuItem1.AccessibleDescription = null; + this.toolStripMenuItem1.AccessibleName = null; + resources.ApplyResources(this.toolStripMenuItem1, "toolStripMenuItem1"); + this.toolStripMenuItem1.Name = "toolStripMenuItem1"; + // + // mnuExit + // + this.mnuExit.AccessibleDescription = null; + this.mnuExit.AccessibleName = null; + resources.ApplyResources(this.mnuExit, "mnuExit"); + this.mnuExit.BackgroundImage = null; + this.mnuExit.Name = "mnuExit"; + this.mnuExit.ShortcutKeyDisplayString = null; + this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click); + // + // editToolStripMenuItem + // + this.editToolStripMenuItem.AccessibleDescription = null; + this.editToolStripMenuItem.AccessibleName = null; + resources.ApplyResources(this.editToolStripMenuItem, "editToolStripMenuItem"); + this.editToolStripMenuItem.BackgroundImage = null; + this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuRemove}); + this.editToolStripMenuItem.Name = "editToolStripMenuItem"; + this.editToolStripMenuItem.ShortcutKeyDisplayString = null; + // + // mnuRemove + // + this.mnuRemove.AccessibleDescription = null; + this.mnuRemove.AccessibleName = null; + resources.ApplyResources(this.mnuRemove, "mnuRemove"); + this.mnuRemove.BackgroundImage = null; + this.mnuRemove.Name = "mnuRemove"; + this.mnuRemove.ShortcutKeyDisplayString = null; + this.mnuRemove.Click += new System.EventHandler(this.mnuRemove_Click); + // + // toolsToolStripMenuItem + // + this.toolsToolStripMenuItem.AccessibleDescription = null; + this.toolsToolStripMenuItem.AccessibleName = null; + resources.ApplyResources(this.toolsToolStripMenuItem, "toolsToolStripMenuItem"); + this.toolsToolStripMenuItem.BackgroundImage = null; + this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolManageDevices}); + this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; + this.toolsToolStripMenuItem.ShortcutKeyDisplayString = null; + // + // toolManageDevices + // + this.toolManageDevices.AccessibleDescription = null; + this.toolManageDevices.AccessibleName = null; + resources.ApplyResources(this.toolManageDevices, "toolManageDevices"); + this.toolManageDevices.BackgroundImage = null; + this.toolManageDevices.Name = "toolManageDevices"; + this.toolManageDevices.ShortcutKeyDisplayString = null; + this.toolManageDevices.Click += new System.EventHandler(this.toolManageDevices_Click); + // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.AccessibleDescription = null; + this.helpToolStripMenuItem.AccessibleName = null; + resources.ApplyResources(this.helpToolStripMenuItem, "helpToolStripMenuItem"); + this.helpToolStripMenuItem.BackgroundImage = null; + this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuWebsite, + this.toolStripMenuItem2, + this.mnuAbout}); + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.ShortcutKeyDisplayString = null; + // + // mnuWebsite + // + this.mnuWebsite.AccessibleDescription = null; + this.mnuWebsite.AccessibleName = null; + resources.ApplyResources(this.mnuWebsite, "mnuWebsite"); + this.mnuWebsite.BackgroundImage = null; + this.mnuWebsite.Name = "mnuWebsite"; + this.mnuWebsite.ShortcutKeyDisplayString = null; + this.mnuWebsite.Click += new System.EventHandler(this.mnuWebsite_Click); + // + // toolStripMenuItem2 + // + this.toolStripMenuItem2.AccessibleDescription = null; + this.toolStripMenuItem2.AccessibleName = null; + resources.ApplyResources(this.toolStripMenuItem2, "toolStripMenuItem2"); + this.toolStripMenuItem2.Name = "toolStripMenuItem2"; + // + // mnuAbout + // + this.mnuAbout.AccessibleDescription = null; + this.mnuAbout.AccessibleName = null; + resources.ApplyResources(this.mnuAbout, "mnuAbout"); + this.mnuAbout.BackgroundImage = null; + this.mnuAbout.Name = "mnuAbout"; + this.mnuAbout.ShortcutKeyDisplayString = null; + this.mnuAbout.Click += new System.EventHandler(this.mnuAbout_Click); + // + // toolStrip1 + // + this.toolStrip1.AccessibleDescription = null; + this.toolStrip1.AccessibleName = null; + resources.ApplyResources(this.toolStrip1, "toolStrip1"); + this.toolStrip1.BackgroundImage = null; + this.toolStrip1.Font = null; + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolNew, + this.toolEdit, + this.toolStripSeparator, + this.toolRemove}); + this.toolStrip1.Name = "toolStrip1"; + // + // toolNew + // + this.toolNew.AccessibleDescription = null; + this.toolNew.AccessibleName = null; + resources.ApplyResources(this.toolNew, "toolNew"); + this.toolNew.BackgroundImage = null; + this.toolNew.Name = "toolNew"; + this.toolNew.Click += new System.EventHandler(this.toolNew_Click); + // + // toolEdit + // + this.toolEdit.AccessibleDescription = null; + this.toolEdit.AccessibleName = null; + resources.ApplyResources(this.toolEdit, "toolEdit"); + this.toolEdit.BackgroundImage = null; + this.toolEdit.Name = "toolEdit"; + this.toolEdit.Click += new System.EventHandler(this.toolEdit_Click); + // + // toolStripSeparator + // + this.toolStripSeparator.AccessibleDescription = null; + this.toolStripSeparator.AccessibleName = null; + resources.ApplyResources(this.toolStripSeparator, "toolStripSeparator"); + this.toolStripSeparator.Name = "toolStripSeparator"; + // + // toolRemove + // + this.toolRemove.AccessibleDescription = null; + this.toolRemove.AccessibleName = null; + resources.ApplyResources(this.toolRemove, "toolRemove"); + this.toolRemove.BackgroundImage = null; + this.toolRemove.Name = "toolRemove"; + this.toolRemove.Click += new System.EventHandler(this.toolRemove_Click); + // + // notifyIcon1 + // + resources.ApplyResources(this.notifyIcon1, "notifyIcon1"); + this.notifyIcon1.Icon = null; + // + // lvwCommon + // + this.lvwCommon.AccessibleDescription = null; + this.lvwCommon.AccessibleName = null; + resources.ApplyResources(this.lvwCommon, "lvwCommon"); + this.lvwCommon.BackgroundImage = null; + this.lvwCommon.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2, + this.columnHeader3}); + this.lvwCommon.ContextMenuStrip = this.contextMenuStrip1; + this.lvwCommon.Font = null; + this.lvwCommon.FullRowSelect = true; + this.lvwCommon.Name = "lvwCommon"; + this.lvwCommon.SmallImageList = this.imageList1; + this.lvwCommon.UseCompatibleStateImageBehavior = false; + this.lvwCommon.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + resources.ApplyResources(this.columnHeader1, "columnHeader1"); + // + // columnHeader2 + // + resources.ApplyResources(this.columnHeader2, "columnHeader2"); + // + // columnHeader3 + // + resources.ApplyResources(this.columnHeader3, "columnHeader3"); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.AccessibleDescription = null; + this.contextMenuStrip1.AccessibleName = null; + resources.ApplyResources(this.contextMenuStrip1, "contextMenuStrip1"); + this.contextMenuStrip1.BackgroundImage = null; + this.contextMenuStrip1.Font = null; + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.cmdTurnOn, + this.cmdTurnOff}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + // + // cmdTurnOn + // + this.cmdTurnOn.AccessibleDescription = null; + this.cmdTurnOn.AccessibleName = null; + resources.ApplyResources(this.cmdTurnOn, "cmdTurnOn"); + this.cmdTurnOn.BackgroundImage = null; + this.cmdTurnOn.Name = "cmdTurnOn"; + this.cmdTurnOn.ShortcutKeyDisplayString = null; + this.cmdTurnOn.Click += new System.EventHandler(this.cmdTurnOn_Click); + // + // cmdTurnOff + // + this.cmdTurnOff.AccessibleDescription = null; + this.cmdTurnOff.AccessibleName = null; + resources.ApplyResources(this.cmdTurnOff, "cmdTurnOff"); + this.cmdTurnOff.BackgroundImage = null; + this.cmdTurnOff.Name = "cmdTurnOff"; + this.cmdTurnOff.ShortcutKeyDisplayString = null; + this.cmdTurnOff.Click += new System.EventHandler(this.cmdTurnOff_Click); + // + // imageList1 + // + this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream"))); + this.imageList1.TransparentColor = System.Drawing.Color.Transparent; + this.imageList1.Images.SetKeyName(0, ""); + this.imageList1.Images.SetKeyName(1, ""); + this.imageList1.Images.SetKeyName(2, "IDI_ICON1.png"); + this.imageList1.Images.SetKeyName(3, "Alarm-005.png"); + // + // tabControl1 + // + this.tabControl1.AccessibleDescription = null; + this.tabControl1.AccessibleName = null; + resources.ApplyResources(this.tabControl1, "tabControl1"); + this.tabControl1.BackgroundImage = null; + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Font = null; + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.SelectedIndexChanged += new System.EventHandler(this.tabControl1_SelectedIndexChanged); + // + // tabPage3 + // + this.tabPage3.AccessibleDescription = null; + this.tabPage3.AccessibleName = null; + resources.ApplyResources(this.tabPage3, "tabPage3"); + this.tabPage3.BackgroundImage = null; + this.tabPage3.Controls.Add(this.pictureBox3); + this.tabPage3.Controls.Add(this.label5); + this.tabPage3.Controls.Add(this.linkLabel2); + this.tabPage3.Controls.Add(this.label6); + this.tabPage3.Controls.Add(this.pictureBox2); + this.tabPage3.Controls.Add(this.label4); + this.tabPage3.Controls.Add(this.label3); + this.tabPage3.Controls.Add(this.linkLabel1); + this.tabPage3.Controls.Add(this.label2); + this.tabPage3.Controls.Add(this.pictureBox1); + this.tabPage3.Controls.Add(this.label1); + this.tabPage3.Font = null; + this.tabPage3.Name = "tabPage3"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // pictureBox3 + // + this.pictureBox3.AccessibleDescription = null; + this.pictureBox3.AccessibleName = null; + resources.ApplyResources(this.pictureBox3, "pictureBox3"); + this.pictureBox3.BackgroundImage = null; + this.pictureBox3.Font = null; + this.pictureBox3.ImageLocation = null; + this.pictureBox3.Name = "pictureBox3"; + this.pictureBox3.TabStop = false; + // + // label5 + // + this.label5.AccessibleDescription = null; + this.label5.AccessibleName = null; + resources.ApplyResources(this.label5, "label5"); + this.label5.Font = null; + this.label5.Name = "label5"; + // + // linkLabel2 + // + this.linkLabel2.AccessibleDescription = null; + this.linkLabel2.AccessibleName = null; + resources.ApplyResources(this.linkLabel2, "linkLabel2"); + this.linkLabel2.Font = null; + this.linkLabel2.Name = "linkLabel2"; + this.linkLabel2.TabStop = true; + this.linkLabel2.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel2_LinkClicked); + // + // label6 + // + this.label6.AccessibleDescription = null; + this.label6.AccessibleName = null; + resources.ApplyResources(this.label6, "label6"); + this.label6.Name = "label6"; + // + // pictureBox2 + // + this.pictureBox2.AccessibleDescription = null; + this.pictureBox2.AccessibleName = null; + resources.ApplyResources(this.pictureBox2, "pictureBox2"); + this.pictureBox2.BackgroundImage = null; + this.pictureBox2.Font = null; + this.pictureBox2.ImageLocation = null; + this.pictureBox2.Name = "pictureBox2"; + this.pictureBox2.TabStop = false; + // + // label4 + // + this.label4.AccessibleDescription = null; + this.label4.AccessibleName = null; + resources.ApplyResources(this.label4, "label4"); + this.label4.Font = null; + this.label4.Name = "label4"; + // + // label3 + // + this.label3.AccessibleDescription = null; + this.label3.AccessibleName = null; + resources.ApplyResources(this.label3, "label3"); + this.label3.Font = null; + this.label3.Name = "label3"; + // + // linkLabel1 + // + this.linkLabel1.AccessibleDescription = null; + this.linkLabel1.AccessibleName = null; + resources.ApplyResources(this.linkLabel1, "linkLabel1"); + this.linkLabel1.Font = null; + this.linkLabel1.Name = "linkLabel1"; + this.linkLabel1.TabStop = true; + this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked); + // + // label2 + // + this.label2.AccessibleDescription = null; + this.label2.AccessibleName = null; + resources.ApplyResources(this.label2, "label2"); + this.label2.Name = "label2"; + // + // pictureBox1 + // + this.pictureBox1.AccessibleDescription = null; + this.pictureBox1.AccessibleName = null; + resources.ApplyResources(this.pictureBox1, "pictureBox1"); + this.pictureBox1.BackgroundImage = null; + this.pictureBox1.Font = null; + this.pictureBox1.ImageLocation = null; + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.TabStop = false; + // + // label1 + // + this.label1.AccessibleDescription = null; + this.label1.AccessibleName = null; + resources.ApplyResources(this.label1, "label1"); + this.label1.Name = "label1"; + // + // tabPage1 + // + this.tabPage1.AccessibleDescription = null; + this.tabPage1.AccessibleName = null; + resources.ApplyResources(this.tabPage1, "tabPage1"); + this.tabPage1.BackgroundImage = null; + this.tabPage1.Controls.Add(this.lvwCommon); + this.tabPage1.Font = null; + this.tabPage1.Name = "tabPage1"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabPage2 + // + this.tabPage2.AccessibleDescription = null; + this.tabPage2.AccessibleName = null; + resources.ApplyResources(this.tabPage2, "tabPage2"); + this.tabPage2.BackgroundImage = null; + this.tabPage2.Controls.Add(this.lvwTasks); + this.tabPage2.Font = null; + this.tabPage2.Name = "tabPage2"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // lvwTasks + // + this.lvwTasks.AccessibleDescription = null; + this.lvwTasks.AccessibleName = null; + resources.ApplyResources(this.lvwTasks, "lvwTasks"); + this.lvwTasks.BackgroundImage = null; + this.lvwTasks.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader4, + this.columnHeader5, + this.columnHeader6, + this.columnHeader7}); + this.lvwTasks.ContextMenuStrip = this.contextMenuStrip2; + this.lvwTasks.Font = null; + this.lvwTasks.FullRowSelect = true; + this.lvwTasks.MultiSelect = false; + this.lvwTasks.Name = "lvwTasks"; + this.lvwTasks.SmallImageList = this.imageList1; + this.lvwTasks.UseCompatibleStateImageBehavior = false; + this.lvwTasks.View = System.Windows.Forms.View.Details; + // + // columnHeader4 + // + resources.ApplyResources(this.columnHeader4, "columnHeader4"); + // + // columnHeader5 + // + resources.ApplyResources(this.columnHeader5, "columnHeader5"); + // + // columnHeader6 + // + resources.ApplyResources(this.columnHeader6, "columnHeader6"); + // + // columnHeader7 + // + resources.ApplyResources(this.columnHeader7, "columnHeader7"); + // + // contextMenuStrip2 + // + this.contextMenuStrip2.AccessibleDescription = null; + this.contextMenuStrip2.AccessibleName = null; + resources.ApplyResources(this.contextMenuStrip2, "contextMenuStrip2"); + this.contextMenuStrip2.BackgroundImage = null; + this.contextMenuStrip2.Font = null; + this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuRunTask}); + this.contextMenuStrip2.Name = "contextMenuStrip2"; + // + // mnuRunTask + // + this.mnuRunTask.AccessibleDescription = null; + this.mnuRunTask.AccessibleName = null; + resources.ApplyResources(this.mnuRunTask, "mnuRunTask"); + this.mnuRunTask.BackgroundImage = null; + this.mnuRunTask.Name = "mnuRunTask"; + this.mnuRunTask.ShortcutKeyDisplayString = null; + this.mnuRunTask.Click += new System.EventHandler(this.mnuRunTask_Click); + // + // frmMain + // + this.AccessibleDescription = null; + this.AccessibleName = null; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = null; + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.toolStrip1); + this.Controls.Add(this.statusStrip1); + this.Controls.Add(this.menuStrip1); + this.Font = null; + this.MainMenuStrip = this.menuStrip1; + this.Name = "frmMain"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.frmMain_FormClosing); + this.Load += new System.EventHandler(this.frmMain_Load); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.contextMenuStrip1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox3)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.contextMenuStrip2.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton toolNew; + private System.Windows.Forms.ToolStripButton toolRemove; + private System.Windows.Forms.ToolStripButton toolEdit; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolsToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; + private System.Windows.Forms.NotifyIcon notifyIcon1; + private System.Windows.Forms.ListView lvwCommon; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ColumnHeader columnHeader3; + private System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.ToolStripMenuItem newToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1; + private System.Windows.Forms.ToolStripMenuItem mnuExit; + private System.Windows.Forms.ToolStripMenuItem mnuNew; + private System.Windows.Forms.ToolStripMenuItem mnuAbout; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem cmdTurnOn; + private System.Windows.Forms.ToolStripMenuItem cmdTurnOff; + private System.Windows.Forms.ToolStripMenuItem toolManageDevices; + private System.Windows.Forms.ListView lvwTasks; + private System.Windows.Forms.ColumnHeader columnHeader4; + private System.Windows.Forms.ColumnHeader columnHeader5; + private System.Windows.Forms.ColumnHeader columnHeader6; + private System.Windows.Forms.ColumnHeader columnHeader7; + private System.Windows.Forms.ToolStripMenuItem mnuRemove; + private System.Windows.Forms.TabPage tabPage3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.LinkLabel linkLabel1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.LinkLabel linkLabel2; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.PictureBox pictureBox2; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip2; + private System.Windows.Forms.ToolStripMenuItem mnuRunTask; + private System.Windows.Forms.ToolStripMenuItem mnuWebsite; + private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; + private System.Windows.Forms.PictureBox pictureBox3; + } +} + diff --git a/scheduler/DeviceScheduler/frmMain.cs b/scheduler/DeviceScheduler/frmMain.cs new file mode 100644 index 00000000..76d716ee --- /dev/null +++ b/scheduler/DeviceScheduler/frmMain.cs @@ -0,0 +1,396 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using Microsoft.Win32; +using TaskScheduler; + +namespace DeviceScheduler +{ + public partial class frmMain : Form + { + public frmMain() + { + Localization.GetSelectedLanguage(); + Localization.ChangeLanguage(); + Localization.Assembly = this.GetType().Assembly; + InitializeComponent(); + } + private TaskScheduler.ScheduledTasks m_Tasks = null; + private DataStorage m_Data = null; + + private bool ShowSplash() + { + string[] cmds = Environment.GetCommandLineArgs(); + + foreach (string cmd in cmds) + { + if (cmd.ToLower() == "/nosplash") + return false; + } + + return true; + } + + + private void frmMain_Load(object sender, EventArgs e) + { + Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException); + + frmSplash frm = null; + bool splash = ShowSplash(); + + if (splash) + { + frm = new frmSplash(); + frm.TopMost = true; + frm.ShowDialog(this); + } + + + + SetupListViewDevices(); + m_Tasks = new ScheduledTasks(); + + LoadData(); + LoadTasks(); + + if (splash) + { + frm.TopMost = false; + frm.Close(); + } + + if (IsPasswordPrincipalActive()) + { + if (ShowAskSecurityPolicy()) + { + frmAskSecurityPolicy policy = new frmAskSecurityPolicy(); + DialogResult result = policy.ShowDialog(this); + + policy.Close(); + } + } + } + + private bool ShowAskSecurityPolicy() + { + RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Telldus\Scheduler\Settings"); + + if (key != null) + { + if (key.GetValue("AskSecurityPolicy") != null) + { + return Convert.ToBoolean(key.GetValue("AskSecurityPolicy")); + key.Close(); + } + } + + return true; + } + + //private void DisablePasswordPolicy() + //{ + // RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Lsa"); + // key.SetValue("LimitBlankPasswordUse", 0); + // key.Close(); + + //} + + private bool IsPasswordPrincipalActive() + { + RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Lsa"); + bool result = Convert.ToBoolean(key.GetValue("LimitBlankPasswordUse")); + key.Close(); + + return result; + + } + + /// + /// Handles unexpected errors. All roads lead here... + /// + /// + /// + void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e) + { + MessageBox.Show("Ett ohanterat fel har uppstÃ¥tt i programmet."+Environment.NewLine+e.Exception.Message, + "", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + private void LoadData() + { + string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + //string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath); + path = System.IO.Path.Combine(path, "Jobs.dat"); + + m_Data = new DataStorage(); + + if (System.IO.File.Exists(path)) + { + m_Data.ReadXml(path, XmlReadMode.ReadSchema); + } + } + + private void SetupListViewDevices() + { + lvwCommon.Items.Clear(); + + Program.DeviceHandler.Load(); + + foreach(DeviceHandler.Device dev in Program.DeviceHandler.Devices) + { + ListViewItem item = lvwCommon.Items.Add(dev.Name,2); + item.SubItems.Add(dev.ID.ToString()); + item.SubItems.Add(dev.Vendor); + item.Tag = dev; + } + } + + + + private void mnuAbout_Click(object sender, EventArgs e) + { + frmAbout frm = new frmAbout(); + frm.ShowDialog(this); + } + + private void cmdTurnOn_Click(object sender, EventArgs e) + { + + if (lvwCommon.SelectedItems.Count == 1) + { + DeviceHandler.Device item = (DeviceHandler.Device)lvwCommon.SelectedItems[0].Tag; + Program.DeviceHandler.TurnOn(item); + return; + } + + foreach (ListViewItem lvwItem in lvwCommon.SelectedItems) + { + DeviceHandler.Device item = (DeviceHandler.Device)lvwItem.Tag; + Program.DeviceHandler.TurnOnWithDelay(item); + } + } + + private void cmdTurnOff_Click(object sender, EventArgs e) + { + if (lvwCommon.SelectedItems.Count == 1) + { + DeviceHandler.Device item = (DeviceHandler.Device)lvwCommon.SelectedItems[0].Tag; + Program.DeviceHandler.TurnOff(item); + return; + } + + foreach (ListViewItem lvwItem in lvwCommon.SelectedItems) + { + DeviceHandler.Device item = (DeviceHandler.Device)lvwItem.Tag; + Program.DeviceHandler.TurnOffWithDelay(item); + } + } + + private void ConfigUnits() + { + RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Telldus"); + string path = key.GetValue("UninstallString").ToString(); + + path = System.IO.Path.GetDirectoryName(path); + + Cursor = Cursors.WaitCursor; + + System.Diagnostics.Process proc = new System.Diagnostics.Process(); + string filename = System.IO.Path.Combine(path, "TelldusSetup.exe"); + proc.StartInfo.FileName = filename; + proc.StartInfo.WorkingDirectory = path; + proc.Start(); + + + Cursor = Cursors.Default; + } + + private void toolManageDevices_Click(object sender, EventArgs e) + { + ConfigUnits(); + } + + private void LoadTasks() + { + + //Clear listview of tasks + lvwTasks.Items.Clear(); + + foreach (string item in m_Tasks.GetTaskNames()) + { + Task task = m_Tasks.OpenTask(item); + if(task != null) + { + if (task.Creator.ToLower().Contains("telldus")) + { + DataStorage.JobRow job = m_Data.Job.FindByID(Convert.ToInt32(task.Parameters)); + + ListViewItem lvwItem = lvwTasks.Items.Add(task.Name, 3); + lvwItem.SubItems.Add(job.StartTime.ToString()); + lvwItem.SubItems.Add(task.Triggers[0].BeginDate.ToShortDateString()); + lvwItem.Tag = task; + + } + task.Close(); + } + } + } + + private void toolNew_Click(object sender, EventArgs e) + { + CreateSchedule(); + } + + private void CreateSchedule() + { + frmSchedule frm = new frmSchedule(m_Data, m_Tasks, null, true); + DialogResult result = frm.ShowDialog(this); + + if (result == DialogResult.OK) + { + SaveDataStorage(); + LoadTasks(); + } + frm.Close(); + } + + private void mnuExit_Click(object sender, EventArgs e) + { + SaveDataStorage(); + Application.Exit(); + } + + private void toolRemove_Click(object sender, EventArgs e) + { + RemoveSchedule(); + } + + private void RemoveSchedule() + { + if (lvwTasks.SelectedItems.Count == 0) { return; } + + //"Vill du ta bort markerad schemaläggning?" + DialogResult result = MessageBox.Show(Localization.GetString("msg2"), + Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + + foreach (ListViewItem item in lvwTasks.SelectedItems) + { + Task task = m_Tasks.OpenTask(item.SubItems[0].Text); + int id = Convert.ToInt32(task.Parameters); + task.Close(); + + //First remove the task from windows scheduling + bool result2 = m_Tasks.DeleteTask(item.SubItems[0].Text); + + //Second remove the entry from the Job table in the datastorage. + DataStorage.JobRow job = m_Data.Job.FindByID(id); + + //Third remove all JobActions + DataStorage.JobActionsRow[] actions = m_Data.JobActions.Select("JobID=" + job.ID.ToString()) as DataStorage.JobActionsRow[]; + + foreach (DataStorage.JobActionsRow action in actions) + { + action.Delete(); + } + + //Forth remove the job + if (job != null) + job.Delete(); + + //Fifth remove the entry from the listview. + lvwTasks.Items.Remove(item); + } + + m_Data.AcceptChanges(); + } + } + + private void frmMain_FormClosing(object sender, FormClosingEventArgs e) + { + SaveDataStorage(); + } + + private void SaveDataStorage() + { + string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + + //string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath); + path = System.IO.Path.Combine(path, "Jobs.dat"); + + m_Data.WriteXml(path, XmlWriteMode.WriteSchema); + } + + private void mnuRunTask_Click(object sender, EventArgs e) + { + if (lvwTasks.SelectedItems.Count == 0) { return; } + Task item = m_Tasks.OpenTask(lvwTasks.SelectedItems[0].Text); + + item.Run(); + } + + private void toolEdit_Click(object sender, EventArgs e) + { + if (lvwTasks.SelectedItems.Count == 0) { return; } + + Task task = m_Tasks.OpenTask(lvwTasks.SelectedItems[0].Text); + DataStorage.JobRow job = m_Data.Job.FindByID(Convert.ToInt32(task.Parameters)); + task.Close(); + + frmSchedule frm = new frmSchedule(m_Data, m_Tasks, job, false); + DialogResult result = frm.ShowDialog(this); + + if (result == DialogResult.OK) + { + //Reload all tasks + LoadTasks(); + } + + frm.Close(); + + } + + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + CreateSchedule(); + } + + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + ConfigUnits(); + } + + private void mnuWebsite_Click(object sender, EventArgs e) + { + System.Diagnostics.Process proc = new System.Diagnostics.Process(); + + proc.StartInfo.FileName = "http://www.telldus.se"; + proc.StartInfo.UseShellExecute = true; + proc.Start(); + } + + private void mnuNew_Click(object sender, EventArgs e) + { + CreateSchedule(); + } + + private void mnuRemove_Click(object sender, EventArgs e) + { + RemoveSchedule(); + } + + private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) + { + if (tabControl1.SelectedIndex == 1) + SetupListViewDevices(); + } + + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmMain.en.resx b/scheduler/DeviceScheduler/frmMain.en.resx new file mode 100644 index 00000000..329594f9 --- /dev/null +++ b/scheduler/DeviceScheduler/frmMain.en.resx @@ -0,0 +1,3264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA01JREFUOE91U2tI + k2EUXnQFG1Ysi+5REfTDGEQJSRD+qWEGYkVChe7HlHU3c7RuFrIoK3Jpm0NikhfYJrqt3OalOafbbE3d + pruY07lZc1NLnZmYe/r2QUVWBw68533PeTjnfZ5DoSwwsVi8xePx5I+NjbVNTk5+nJqaCoyPj5vtdvtT + qVS6d2H+rzg9PX2RRqO5HQyNfPOFvLAOdcL4oRWtrma0u1tg83ZhOOCP2Gy2lyKRKOYvILlcLvZ+HISh + TwetS4MWdwPaP2ih62uEoluCyo4ylLcJ8c5pgMPhMJSUlPwGkclkWZ6hfqjtCiisEtR0VsA+1IWfprbV + Iq8uE+elp5BdfQJKUw0sFouQ7CIlJWWZy+UKqLprUWkphfjdc4gMj9DmbEIkEiG9sOEq9vOXYF/RYtCf + LcaBQhp6nPbvPB5vB4XD4SQN+j0QGB9A2VONrmEj6l2VcH3qxuzsLMLhMNqdGlSaHqPC9AQs2UEkli1F + tV4EhUKRRykuLr5k6TeBZzyPVrcKc3NzmJmZwcTEBEZHRzEyMkJ6MBgkY4H+Ko7XrABfewN6vV5CKSoq + 4pj723H27R5IDWUgKITb7YbX6yULQ6EQfD4feUdQidK3V8BsXoky4x3odLpaygXChkd9YKhicPLNGmTI + 1+Pi6w1Qd5SD0AIJIjNwUaDZgnz1ZtzUxeGyYRVaXHXREcopCQkJxwih4K7+NM6YqWB3rsZN61o0vBdj + YGCAdKWVg1LnJhQ7NuJhz3oChI7w1zAKCgruU2g0GlUikXwZHvOCSYzB6lyH69ZNqDe9gt/vRyAQwJue + fDx37sZTxy7cMu5EB6ER4i2SlJSUSFLJYDDuRecbDPbhctNRnNNvB7suETmSI8iTMnCj6SC45r3IUSdA + rq8g/0koFDbFxcUtIgGoVOoKNpvdrNVqMT09jcZeOR60XMQ19XHkqJJxp/4cXrzmQd2ogslkglKp9MbH + x2/9Q86xsbExaWlp5QKBYN5sNpPtR6mLMtDb2wuVShUtjBAS7qDT6dv+uVQsFouWmZlZyOVyA3w+f76q + qipCyDxCbOh8bm7u5+zsbAmRE//fjYw+JCcnL8nIyNiYlZV1iEhOizpxPsxkMrelpqYuX1j8A/bFYLQi + FLFKAAAAAElFTkSuQmCC + + + + 131, 22 + + + Schedule... + + + 98, 22 + + + &New + + + 95, 6 + + + 98, 22 + + + &Exit + + + 37, 20 + + + &File + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA2RJREFUOE91U2tM + k2cUrsniXBDR2NQYI2D8IxKrTI1kGi+ri5EAKtYlq1sYoAI2ZH9EG0mMsDA2syhCIDSoBDQS0nKxRS1t + qVBqsaWgpdiWYr9evnL52nIZKIEBffz6/dCIepKTvG/e8zznvHmew2Iti9ra2miCIArHx8efT09Pj8zM + zIxNTEyYBgYGbkml0p3L6z/cBQLBCqVSeS1AUXOTXg/GzC9B6rvg6dTAq+vEaP8rUMO+kMViqamuro74 + jEgmk9WOut0gn2vhbVfC0/YYLnkznE0NcDTch/3+XVjuiUEYXsBms3VXVlZ+JGlsbMzxOZ1wPpHDo1Jg + NhiAV62AvUYMa9VtEC0S/OdyoudaPp5l/AyzrAl9fX1iZorU1NSVg4ODY4Otj2Cru4tpGhyOpcVFWG// + hd5L57AwN4f5+XlQbhca4zl4GMeB4/XAYklJyVaWSCTijbgIvCr9B+YbRdAXXobfRyIUCmFh4X/MvnuH + qakpDJMkVOdPon3bd3i8dRV66+5ALpdfYVVUVPzhNhlhFOVBc3wvVHERUKfuATU6AloJ+P1+UBQF48UU + OA5EwbxvDXQ7V6Pn7wLodDoJq6ysTOQ26KE8sgNtcauh37MWQzWlDCicgUAAwWAQo5pHoE5vAfnTelj2 + r4O5tBBarbaFlUfHBD1yy7Y10Hy/HkOSGqZrGOSxv0a/Vg03rY7L5YLP2Al/+i684bFBKGXhL9SxEhMT + U2ijQCs8i/bEjTDKpExne48e5IV9CP4ejz5FM0PqHbLDdf4H9At2Y/btWxQXF//JYrPZkRKJZGqS9EDF + 2w7toc1Q37wO+6+7MPtLDObOxiKQHo/ehjtwCH8EcWoLiC4VfD5fiMfjHWCkTEpKKqKtiiAxhGeCo+je + vwG2Y5vgTomG71QMhul0n4iGkc/FC+kD0FaHWCxu53A4KxiCyMjIVUKhUNPR0cHI5njajO6rF9CVzkPX + b4fRmXcGyltFULcpYDAY0Nra6uFyuTGf2DkqKiqCz+fXVVVVLZlMpvCIzL9JWn+r1QqFQhEGhmgLGxMS + EmK/uFTZ2dnszMzMfwsKCsbKy8uX6uvrQ7TNQ/SGLuXn50/m5uZK6BruVzcy/JCcnPxNRkbGppycnIN0 + MT+c9PlIVlZWbFpa2rfLwe8BECxb5G8PU2sAAAAASUVORK5CYII= + + + + 117, 22 + + + &Remove + + + 39, 20 + + + &Edit + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAidJREFUOE9jYICC + 3HnFii3bJ1rD+CTRst58Mnnr0z+vebrrb/7qbHtCmtesWWOyfv16Ebg6XhMmMYtqhfdVO7P+N+8vvRfS + 4smLbkhnZ6fdtWvXPA8ePLjk1atXb/bt25ezYsUKf7g6pRi2iKApev96T9T9b9iVNwvdgOnTp3fs3r37 + /927d/+fOHHi2OnTp2+cO3euGEWdaaHA/Py1gf+nnWv6V74+1RNZ8tChQxeqKsv/AzX9f/To0f/nz5// + nzdvXjCKAcKWLDweLXK3Og8X/O873nIXJrl27dqkY8eO/Tty5Mifixcv/lywYMGJ+Pj4RKxhpRjAaeTb + Zf0uZ0Pxn7yZJaJTpkxJ2rlz529goN2NjIwMERYWFiIUyAxybnLsBuE6C+avWHDk5MmT/4Chvt/JyUmQ + oEaYgsysTObVa1ZPP3DgwH+g7XttbGy4iNacn5/PBQzhjR8/fvy/ZcuWncuBoKSkhJmQAYxABVyKiory + 27ZtO/ny5UuQ5q0WFhYcVlZWFqtXr66QkpICqcEN7O3tzZcuXfrk6tWr/ydPnrxHTk6OG6haFIhl3d3d + 24yNjb2BbHGsJgBTlPOuXbteAuP6/8yZM09ycXHJABWqQrEIGxsbd29v75G8vDwjrAbs2bNnWWxsrA8w + tO/x8/PrAxXxAzHI3yBn8wCxNNArDWfOnDmC1QCQ85KTk2cANZsCFTBhUQQyiM/Q0DCYg4ODjVCAkiQP + ADBk5tzXJg/8AAAAAElFTkSuQmCC + + + + 165, 22 + + + &Configure units... + + + 48, 20 + + + &Tools + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAt1JREFUOE+V030s + 1HEcB/DfeUrDsd1wtNap8xTNnIcjj5vCRIfWZfOUKKeIowcP1ehhkTxlidrE1GweNg8RFksoD5kwI+c0 + PUhUl4c7ws+7a23MUOv7z2ef7z6f13ff7fOhEJucwOoc+k42w3FuQVGru2V2amV+YKAtJL5ns9p1d0a8 + QqXAEnHWjW7xYvbQNFIFkzheO4f9pa0r5iXp7cyMMOstEbNrRbTQBlFv7SiJwW8k3k1L43cS9WMkkl4u + wfaxAHLcComcTbr7BsSY70IJ6GpprhCSEEgbv86TmPlJYlIah6V5mRQ93fYROrc7oBt/Z0bVOUpnHWJf + H3PoXM8bNH8mMTpLQiRtlixJgYU/ecW4BIkjfeC2PYNlWQ7YpfySdQCrJqzgQucw6j6R6PtB4oOYxIT0 + 9d+xQ7SIlKlKXBxpAE+QA5+BZNjWRs3TvE0UVxGtfLfOE41dKBhdxpMJEu0iEnUiIe6LqnB9/C7ihHkI + 63oFl6o6eLamgVXIB9WTvXcV2J7Afu1QlI8r3QtIHVlGikCIiP4ExLyNx/nhS4gcjENobxqYmR0wzEuG + 6lk/KDiaGa99gxP9UDe5H/6VX8BrnYFvSwdcazg40nQM3Oe+cH3qDfcmfzg38kG/Gg31dPtFwpiutAbo + Z7rKBtRgX9oQXB+9h1v5GCweRMKswA7sYgeYFtvBoNAKzCJrqCU6Q+mMXdXGeTDKfSHjXw31yz3QSx2C + UZYAzJRy7E6yAOOWCTRuGoKWoQ95vwOL8hyG5UZAjb+DYGQIiYMFIPyqIBPaCNmTuaCGGkA1WhfUWCa2 + hTNXKFZOvK1HWjFYnVCNLSO0k0nCMAWEjQsoXrugHGgAFR+2hGLqlE1ouVH/vhN0D3UVVsg9E27ShElQ + sNgsIlxsfCp6UoHl20nR804n6B7afwdodjKE9mFNBSNfayo72EvZPIgryzzqRjA4LGKPpwah6Sjzz638 + n4JfHjGLP3wxItMAAAAASUVORK5CYII= + + + + 164, 22 + + + Telldus website... + + + 161, 6 + + + 164, 22 + + + &About... + + + 44, 20 + + + &Help + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA0xJREFUOE91U2tI + 03EUnbUeYEllpfSOiqAPySBKaCSRH2wUfTCLPuRIwSnrbeZj9jYKtSKXtgypjXzAdDi3cpuP5rbcZmvq + Nt3DnM7NnJtawszE3Om/f0RkdeHw4144h3N/994wyrzg8/mb6HR6akRERDyVSt0KYAEBz8jIiNput79M + TEzsns/5lYcpFIrrPv/oN7ffBdNQJ3Qf1VDbW9HuaIPZ1YWBIWfQbDa/EAgE4X+JiMVivuvTILR9Kijt + CrQ5mtD+UQlVXzMk3UJUdVRA8O4Z3tu0sFqt2qKiot8iIpEo3TnUD7lFAolJCFFnJSxDXYTznyE31yNb + nIKztSeRUZMEqV4Eo9H4jHSRlJS02GazeWXd9agyloP//gmea4vwztaCYDBIorjpMvZyqdhTshC0xwux + r3g1LBbL98LCwm2U3NzcQ4MeJ3i6+5D21KBrWIdGexXsI92YmZlBIBBAu02BKv0DVOofglW3H/SKRajR + PIdEIsmmlJaWXjD263FPdxZqhwyzs7OYnp7G5OQkxsbGMDo6SsLn85E5T3MZx0RLwVXmQa1WCyklJSU5 + hv52JL/dhVptBZxOJxwOB1wuF0n0+/1wu91kjbCN8reXkNq6DBW6G1CpVPWUc0QMj7nBkIXjxJtVONMQ + jfOv10HeIcD4+DgpUqfl4K5iE27JNyJftRYXtSvQZheHWhBQYmNjj05MTOCm5hROG5aD3bkS+aY1aPrA + x8DAAAmpKQfltg0ota5HYU80IUJD4GsABQUFdyiRkZHLhULhl+FxF1KJNlidUbhq2oBG/St4PB54vV68 + 6bmFJ7adeGTdgWu67eggdoRoNRgfH08nR8lgMG6H+hv09eFiy2EwNVvBFtORKUxAdi0DeS37wTHEIFMe + iwZNJflPPB6vhaCG/drIpWw2u1WpVGJqagrNvQ2433YeV+THkCk7ghuNTDx9fQ/yZhn0ej2kUqmLRqNt + /mOdo6KiwolDERDKcwaDgbQfGl1oAr29vZDJZCA2NlhWVtYRExOz5Z8HlZaWtjolJaWYw+F4uVzuHHGZ + werq6iDxzmVlZX1OT08XZmRk7P7fNZL1uLg4anJy8npC7ACLxToeAkE6yGQytyQkJCyZT/4BXq9YqhOK + nicAAAAASUVORK5CYII= + + + + 75, 22 + + + &Schedule + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAbFJREFUOE9jYCAD + rO/vF9gxc6YGGVoZGO5t3qz/7eixZx8OHPj3ZsmSQpIMuXf0qPv9LVs+P+vr//9swoT/j5ublxJtwI+X + a4IfX9n4fV9F4/8TXd3/L2RkHFsZEiJKlAH/3q3M+XEl6s+nQ37/dy2f/D/X03Otj7ExF0HN//8zMP59 + s6j9+/mgf1922fy/0K36b0+jZhNQIyNBzTNnzmT9+2rmwj8XvP5/2GD2/3SPzM/dDRrxBDWCFOzfP4Xn + 7/PeHb9OOv9/vdTg/6kOxXdbKtUdidJ86fhs8T/Pms/8OGj7/9kczf/HmhXvLi9T1SRK8+OrS1V/P6q4 + 83W72f8Hk1X+H2lUOj4tQ0mMKM2v7m8z/HEv/dWntfr/b/Uq/j/QpLqmN0SGkyjN9fX1LN+eHrz0bpnh + /3PN8v/2Nal04whpUOjDMMLsR7cv5F7e2fd/Rav3y2xvsXxRUQYeoKwAEAsDMSixiEMxyDsgMW4gZoKZ + wGllqrNcX1O2iZmZ2QsoaA/E5kCsD8RqQCwPxBJQjXxAGpSAWJC9BnISOxCDbAVJsgExM9QGwgmGqEDC + owgA7kywHOvKSsIAAAAASUVORK5CYII= + + + + 47, 22 + + + &Edit + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA19JREFUOE91U21M + U2cYLYY4F7TT1EgWIx/xj0gU2DASbeyULkMS/AhiMt2oMi2whvhHNpHEKCNmwrIhBAKJWqlGQqqFUthK + Wyq0rtDyMUtZewF7b9tbLf3gY4sSGNDj7U2MkemTnLx53+Sc53lznhPFWVXNzc1xfD7/Oy6XK4yOjk4E + sIaB1+fzGcfHx+/m5uZaV3Pe3KM0Gs2VoN+/MOtxY8r6F2iTEe4+PTxP+uAbfQqaIsM2m00qk8li/iei + VCqbfS4X6D8N8PRo4O7uAqVqg1PRionWeyDu3YbtThNI8wAcDkd/dXX1WxGFQlHkdTrh/F0Ft1aN+VAQ + Hp0ahLQJ9sabINvl+IdyYvBKKR6fPQlrhwIjIyNN7BR5eXlrCYKYGu9UwiG7jX8ZcqRWlpdhv3kdwxfP + YWlhAYuLi/C7KDxK3oIHSVswNja2XFVVtZ1TVlaW+YIi8bTmBqxVFTBd+wEBL41wOIylpf8w/+oV5ubm + 8JymoT1/DD07PkbX9nUYlt2CSqX6kVNfX3/BNWSB5VIJ9If3QJsUA92RdPh9LzA9PY1AIAC/3w/L9zmY + 4H8C614unqSsx+DP5TAajXJObW3tJZfZBM3BXehOWg9T+kZMSmtYUgTBYBChUAg+vRL+3ETQX/Jg278J + 1pprMBgM7ZwSpmaYkdt3cKH/jIdJuZTtGiG5ib8xatDBxbhDURS8lj4ERKl4lrkZpKYj8gUZJyMjI2dm + ZgYGyWn0ZHwKS8dDtjMxaAIt3ovQmWSMqNtYUc8kAer8Poye+hzzL1+isrLyJw6Px9sgl8vnZmk3tJk7 + YRBsg+7XqyC+ScX81/FYOJ2AoCgZw623MCE5BPJ4IkijFiRJhoVCIZ+1Mjs7u4KxBSFyEo9PCdG/PxaO + r7bClRMH7/F4PGfgOhoHy4ndGHh4P0JGY2NjD0ONerOR6yQSib63t5e1beKPNvRfFsMoyoTx2y/QV5IH + zW8V0HWrYTab0dnZ6U5LS4t/Z51jY2NjmKDIGOWVoaEheL1e9t8047/dbodarQazseGGhgZLSkpKwnsD + JRaLNxcUFPxSXl4+VVdXt8IkM9zS0hJmzpXS0tLZoqIieXFx8e4PpZF9FwgE0fn5+VsZsQOFhYUnImBI + B0UiUUJWVtZHq8mvAXJeU9ifZ+GWAAAAAElFTkSuQmCC + + + + 70, 22 + + + &Remove + + + Name + + + Manufacturer + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewQAA + HsEBw2lUUwAAAWNJREFUOE+N0csvA1EUx/ErsbT1B9jYSfwLrGzYWPkv2LIVSwmJHYloUU00kZDQSFOv + SOrRTFtBK1WPmmpNr760nZnOV0uCours7jm/zz3JvS2AqCtDWHFRbdImWtvrR2+nKvgsK4Xpx4xghCmd + kj3GKNYFahd9VCWNcUJFxbxHD1M8JecmZsOqfDVfQN6DEaWi1UBRIbeNdHI1iqr8BiyL9DJGBEqYcV4O + kaskpjnqIehssCG5RGEL/ZpSkMwG6hSBIVyC4HoDkNjjaRLpIDXL7RiBPtyCecHTXQNQzHIxQnyU2DDn + gxx0YRfszzd+perkZpezXkL9HHazKpjrJKv9CXQd/ziPTrwDLAp8jm/p2i9/b52scDnDQgcTgodoc5BP + JuRtRFlf8yzYM/K5OXjOFB6Tcmdfca15tfQ/gJRZVU15vccOx6amyeYbymU9FArbbC6fTzFNszl4T+Ry + +Z/R984rn0GmMacbOKoAAAAASUVORK5CYII= + + + + 117, 22 + + + Turn on + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewQAA + HsEBw2lUUwAAAUxJREFUOE+VU12rglAQ7EL//1f0oI+9mNSLQg9BQRJRGUZBQdiHGib2ZXObvRy4pRYN + HNTjzOye3bM/eKBSgCzLKupXtVotovzt0eA/HkJcr1dZl8sFaZoijmPcbrdXqnw/GVB8Pp+FTAO+K4PV + aoX7/Z4zeTI4Ho8iVFkocRiGWCwW2G637w1IZNqMRKMkScA93/cxHA7hed57A0agiCan0wmHw0HEruvC + sqzPBrvdDlxRFMmT56a40+mg0WjI/iueasCos9kM6/Uay+VSIvb7fTSbTQwGg89dIIPi6XQqy3EcSd0w + DDlaEXL3gC0cj8dS8V6vh1arhdFoVCjO3QPFmkwmmM/nME0TmqZJPcqQy4BEVUBG13VdWvmVAdu32WzQ + brdRr9cRBMF3BozIYtq2LRns9/vvDDgDvHm1Wg3dbrd0kEqLqMJxCj/hF5B2pm1BgCdyAAAAAElFTkSu + QmCC + + + + 117, 22 + + + Turn off + + + 118, 48 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADG + DgAAAk1TRnQBSQFMAgEBBAEAAQwBAAEEAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AOQABAQMFAQcDDwQU + ARsDDQERAwMBBBQAAwUBBwMUARwDGgElAxoBJAMYASIDFwEgAxYBHgMUARwDEwEaAxIBGAMNAREDAwEE + EAAc/wH0AvMh/ycAAQEDBAEGJAADAwEEAw0BEQMgAS8DNwFbA0ABcAMyAVEDHQEpAw0BEQMDAQQMAAMU + ARwDPgFrA0oBigNIAYgDRwGDA0UBfQNDAXgDQQFzAz8BbQM7AWUDLwFKAw8BFBAAFP8B+gL5Af8B2gLU + Af8BrgKjAf8B0QLKAf8D/Bn/JAADJQE3A1oBvgMIAQsbAAEBAwcBCgMYASIDMwFSAVECTwGlA1gB3QFS + AlABowNQAZ4DRQF9AzIBUAMcAScDCwEPAwIBAwQAAWMCXAHqAXMCYgH1AWICWAHpAVwCVwHfAV4CWgHV + AVsCWAHLAVsCWQHDAVgCVgG8A1UBtQNTAaoDRgGAAxgBIhAAFP8B8gLvAf8B6wLnAf8BzALAAf8BuAKo + Af8B7wLtGf8UAAMLAQ8DLwFKA0IBdQNCAXQDVgG2A1MBqgMRARcDBAEFEAADAwEEAxEBFwMoATwDSAGG + A14B5QNgAf8DRwH/Az8B/wNXAd8BUgJQAaQDTwGcA0QBewEsAisBQwMLAQ8EAAGMAmoB+QH/AvQC/wLk + Af8B/QLjAf8B+wLgAf8B/ALkAf8B/QLlAf8B+QHZAdgB/wHLAcUB2QH/AX8BawFtAfcDSwGOAxsBJgMA + AQEMABT/AfUB8QHwAf8B7wHqAekB/wHRAcQBwQH/AcABsQGuAf8B8AHuAe0Z/wgAAyQBNQMoAT0DQAFw + A3sB5gPhAf8D6gH/A+oB/wPhAf8DYwHVAzgBXgMYASEDCQEMDAADDgETAzoBYQFbAlkBwwFzAm8B/gNj + Af8DXgH/A1YB/wNDAf8DQgH/Az0B/wNaAdsDUQGhA0MBeAMWAR4EAAGMAmoB+QH/Au4B/wH7AtwB/wH8 + AdkB1gH/AfgB0wHQAf8B+QHVAc8B/wH7AdUBzQH/AfYBywHFAf8B1AHAAcwB/wGAAWwBbQH3A0sBjgMc + AScDAAEBDAAU/wHoAeoB9AH/AdsB4gHvAf8BsQG0AdEB/wGkAaIBvgH/AfAB7wHxGf8IAAMxAU8DjgH0 + A9IB/gP0Af8D5QH/A/0F/wP8Af8D8QH/A4EB6wMxAU8DEgEYDAABSQJIAYcBbQJSAfcDggH/A2wB/wNg + Af8DVwH/A2cB/wNCAf8DQwH/A0EB/wM9Af8DWgHkAUkCSAGIAxoBJAQAAY0CagH5Bv8B+wH/AWUBlwH9 + Af8B3gHlAfwB/wFVAYgB/QH/ATcBZAH9Af8BVAGAAfoC/wH8AfQB/wGGAm0B9wNNAZYDKAE9Aw4BEwME + AQUIABT/AakBzQL/AZUB2QL/ARsBogL/AQABhgL/Ad4B5hr/CAADJQE3A8YB/AP1Af8D/QH/A/0B/wP9 + Af8D/QH/A/0B/wP7Af8D5QH/A4UB8QMkATYMAAFiAlgB7wOLAf8DgQH/A2oB/wGKAosB/wGkAqUB/wGe + Ap8B/wOJAf8DXAH/A0QB/wNAAf8DWQHrAUUCRAF8AxcBIAQAAYgCbQH3Bv8B+wH/AUQBhgH+Af8BxQHY + AfwB/wHhAeIB9wH/AQ8BTgL/AcMBygH4Av8B/gH6Af8BnQKSAfsDUwGsA0cBgwE1AjQBVQMbASYDBQEH + BAAQ/wL6Av8BhAHPAv8BqgHpAv8BSAHAAv8BAAGlAv8BqAHKGv8IAANYAbQD5QH/A/QB/wP0Af8D8gH/ + A+gB/wP0Af8D9AH/A+QB/wPgAf8D0AH/A2EBxwwAAWUCUgH0A4cB/wOYAf8BsgK1Af8BgQJvAf8BUwJI + Af8BRQJBAf8BWgJdAf8BhwKIAf8DgQH/A18B/wFZAlMB8gMuAUgDDQERBAABewJiAfYE/wFiAZwC/wEZ + AYcC/wHJAd0B/QH/AWQBlwH9Af8BvQHOAfkB/wGBAYwBuwH/AYMBhQGHAf8BaAFrAWwB/wNbAdkDUgGo + A1ABmgM+AWsDGgElAwMBBBD/AcIB4QL/ATwB1QL/AUcB1AL/ASoBxwL/AQABrQL/ASABnQL/Ae0B8hb/ + BAADBAEGA7AB+AP0Af8D7QH/A7gB/wOUAf8DqgH/A9IB/wPcAf8D5gH/A+EB/wPUAf8DzgH+AxQBHAgA + AXUCZQH4A84B/wHDAsQB/wGPAoEB/wHBApIB/wHXAp4B/wHLAo4B/wFZAkAB/wGEAocB/wF/An4B/gFe + AlwBzgNBAXIDDAEQAwIBAwQAAXsCYgH2CP8BbwGmAv8B3QHoAfkB/wHGAdoB+AH/AY8BigGZAf8BtQGm + AZkB/wH2AdUBrwL/Ad8BtAH/AfMB0gGsAf8BpwGZAYoB/wNZAckDTwGbATUCNAFVAw0BEgz/AfIB9wL/ + AWsB2AL/AXQB5QL/AWoB4AL/AU0B1wL/AScBxQL/AQABpAL/AaABxBb/BAADFAEbA9UB/wPtAf8D9AH/ + A+gB/wO+Af8D4AH/A98B/wPXAf8D3gH/A+AB/wOaAf8DuwH/AyABLwgAAzACTAJLAY8BXgJcAc4BcwJp + AfwB6gLZAf8B7wLRAf8BzwKWAf8BYQJUAe4DUAGdAyoBQQMHAQoDAQECDAABfQJiAfYB9AL3Af8BigKL + Af8BYgFgAV0B/wGuAagBpwH/Aa8CogH/AcIBsAGjAv8B5gG3Av8B5QG4Av8B5gG5Av8B5QG+Av8B6QHA + Af8BqQGaAYoB/wNSAakDRAF5AxYBHgz/AcMB6AL/AY4B7AL/AagB7wL/AZwB6wL/AXUB4gL/AUIB0gL/ + AQABugL/AQABoAL/AeMB7BL/BAADCAELA8AB/APiAf8D6gH/A9IB/wPrAf8D6wH/A+sB/wPrAf8D6QH/ + A7wB/wOOAf8DgwH+AxIBGBMAAQEDDQESA0ABcAFYAlYBuQFSAlEBoQEsAisBQwMNARIDAQECFAABWQJX + AcIBYQJcAdwBXQJXAe0BXgJaAdUBYQJcAdwBegFxAXIB+gH9AeIBvAL/AekBwQL/AfABxgH/AbABoQGE + Av8B5gG6Av8B5wG/Af8B+gHXAbAB/wNbAdkDSAGFAxkBIwz/AaYB6gL/AbkB9QL/Ad8B+gL/AdMB+AL/ + AbUB8QL/AZEB5wL/AVMB0gL/AQABrgL/AbQB0xL/CAADXQHAA9YB/wPjAf8D4QH/A+QB/wPkAf8D5AH/ + A+MB/wPIAf8DlQH/A3QB/wNgAdAbAAEBAyUBNwE1AjQBVQE/Aj4BbAMkATUDEQEXAwMBBBQAAwYBCAFW + AlUBtAFZAlcBvwNSAakBXAJYAdEBgAF3AXgB/AH/Ae8BywL/AfgB1wH/Ac8BxAGlAf8BSAFLAVMB/wGY + AYsBaAL/AekBvAL/AegBuwH/AWcCWQHyA0QBeQMWAR4I/wL+Av8BpwHuAv8B2wH7Av8B+AP/AeUB/AL/ + AccB9gL/Aa0B7wL/AZIB6AL/ATsBywL/AaoB0xL/CAADJgE4A7cB+APQAf8D2AH/A90B/wPUAf8D1AH/ + A8kB/wOFAf8DuwH/A+MB/wOSAe8DBgEIEwABAQMQARUDHgErA0MBeANAAXADOgFhAyQBNQMQARYDAwEE + GwABAQMAAQEDAAEBAWACWwHWAf8B8gHTAf8B7gHpAdMB/wE6ATkBNAH/AegB3QG8Af8CQQE7Af8B0wG+ + AZ0C/wHfAbcB/wFeAloB2AE1AjQBVQMNARIM/wG+AfQC/wHeAfsC/wHtAf0C/wHkAfwC/wHRAfcC/wG8 + AfMC/wGqAe8C/wF0AdwC/wHRAecS/wwAAygBPANpAdQDtQH/A70B/wPHAf8DzgH/A48B/wOvAf8D9AH/ + A/sB/wPpAf0DCwEPEAADBgEIAxABFQNQAZ4BXAJaAc0BWwJZAcQBQgJBAXMDMwFTAyABLgMIAQskAANE + AXsB7QHWAcYB/wGhAZ0BjQH/AukB0wP/Ad0C/wHxAcoC/wHxAcIB/wG/AawBnAH/AU4CTQGVAxsBJgMD + AQQM/wHuAf0C/wHNAfsC/wHnAf0C/wHkAfwC/wHaAfoC/wHOAfcC/wG6AfMC/wGjAeAC/wH9Af4S/wwA + AwkBDANpAd0DpQH/A6AB/wObAf8DywH/A6UB/gOTAe8D/gH/A+oB/wNQAZsUAAMIAQsDUAGdA0QBegFF + AkQBfAFJAkgBhwFRAk8BnAFKAkkBiQMUARsDAwEEJAADBAEGAVoCWAHAAe8B2gHJAv8B+AHYAv8B8wHP + Av8B6wHFAf8ByAG2AaYB/wFbAlkBxAMdASoDBgEIBAAQ/wHrAf4C/wHPAfwC/wHbAfwC/wHaAfsC/wHO + AfgC/wHMAfIC/wH3AfsW/wwAAw0BEgOhAfED8wH/A/EB/wPfAf8DQgFzAxQBHAMFAQcDMgFRAykBPxwA + AxgBIgNUAa4BZAFSAUsB7wFhAlsB4QNKAYoDEgEYAwQBBSwAAwQBBgNEAXsBYAJbAdYBdQJlAfQBXQJZ + AdcBRwJGAYADEgEYAwQBBQgAFP8B+gP/Ad8B/QL/Ad4B/AL/AeoB+x7/EAADGQEjA0oBiwNXAbEDSgGN + AwUBBxwAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/+BAAH4AR8BAAEPAgAB/wGf + AfABBwEAAQ8CAAH/AY8BwAEBAQABDwIAAfgBBwGAAQEBAAEHAgABwAEDAYABAQEAAQcCAAHAAQMBgAEB + AQABAwIAAcABAwGAAQEBAAEBAgABwAEDAYABAQQAAYABAQGAAQEEAAGAAQEBgAEHBAABgAEBAeABHwQA + AcABAwHwAR8EAAHAAQEB4AEPAcADAAHgAQEB4AEPAfgDAAHgAQMB4AEPAfgBAQIAAeABBwHwAR8B/AED + AgAB8AF/Cw== + + + + + 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 + + + + 276, 13 + + + Starts the application which allows you to configure units. + + + 29, 13 + + + Start + + + 100, 13 + + + Configure unit(s) + + + + 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 + HdfAfwC8OWB2rvuFqgAAAABJRU5ErkJggg== + + + + 387, 13 + + + This application allows you to easily schedule one or more units at the same time. + + + 276, 13 + + + Choose when and where each unit should be scheduled. + + + 107, 13 + + + Create new schedule + + + 99, 13 + + + Schedule unit(s) + + + + iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAACzBJREFUaEPdmQds + VdkRhtdgMBCKQ7JswhJtZFZsyCItECmroCgkrEKk7KKAIiAQRBNFoQREb6I3U00H0btN772a3nuvphow + YLpxOSf/d3Sv98Fa4r1n75LE0uiee3zvuTNn/vln5ryID/Lg7/79+/mstcUiIiJK5M+f3+j6sGTJkq/y + YOnvb4nbt28XevDgQb0nT54sunXrVtLTp0/Tnz9/bl68eGE0fnrnzp1NFy5cqP79aZCLlS9dulRXu349 + PT3dSlezaNEik5WVZc23f1b35tSpU5m7d+/+7zJi27ZtA549e+YrbDMzM+2rV69Q3snr16+tPGP1jH34 + 8KFdtmzZwdWrV0fkYr/y7tXp06d/sWPHjsyXL186qKCsvGDS0tK4d95ISUlh5+21a9eMvGTi4+Nfb9q0 + qdS7tHj8+HGJ1NTUjyXF3/Vs2P8fMWJEhzVr1pibN2+aI0eOmCtXrtjk5GRz9+5dxAr3RvFgjh49ao8f + P25OnDhhxo8fn37y5MkEwW5sUlLSQEmDc+fO/dJX4tGjR39U7CTK+JfyZJY24qWMOCzvtZEXo8JWNqcX + Bw4c2HjcuHFWitkDBw7YvXv32vPnz1sply1nzpyxgplduXKl7d69ux06dKiVAVZBb69fv24PHz5s5UWM + PKMgny4vZnjxIyL79g9oyoCz8vZneWZEnz59onv27Hl/8uTJZt26dWbFihV21apVZu3atUaeAe9m6tSp + plu3brZNmzZGz5sFCxbYnTt3mg0bNpjFixdbQcrMmzfPyJsOZsDQj33UZ6w5vOyPr8krP8kzI2TAl+3b + t9/Ytm3bF+3atbOtW7c2TZs2NfXq1bN16tQx3I8ZM8auX7/eyDOGYCY2BB2TmJhoMV7vGbwDFPU/x1j8 + +QbIu2bOnDnOAHnCKD5G5pkB2uHowYMHj5QB6VLW9ujRww4fPtxOmTLFamctuyxPOAiJQu3FixctsbJn + zx67cOFCO3LkSNu1a1eLl4CeYsCKBByDeQY49lJ+cXNASTBK1X3BXBkhmORbvnx5s4SEhGRh3Jw9e5aA + dYF748YNg6JiHyO8G2HbsuME9+XLl4kXI4McbPr27Ws6d+6Mp+yhQ4fcGvfu3TOwmUfFb3gD73iU/GXY + BmzZsqWIML9EdAjzsKCjy2PHjlnmED3jglMwMdu3b7e6N5s3b3bzMJIPoQkTJph+/fqZBg0aWMWHW0Os + 5NbLyMj4TjwAIf2PePlbWAZotwtJkUTgIF4Hz+y03bhxo921a5dFAVhJHrHsPJ7gyj3zUt7u27fPag3H + QMzPnTvXtmzZ0sFv5syZdv/+/e45edMlRZ+VuJJfWE/eqhqWAVu3bp2F8sKlAZvCsoFV2FUWhkk8eWNM + AOMBcC6jHLQOHjzoPCOqdYHeokUL06tXLytYurwC3WpNBz3lAqvgNVevXsWLT8RePwrZAO1yTXkgSxh1 + i2EIeEYBcToCt+c45sMYqmv2Mxhz+vRpN48xAwYMMCIDK2YzEydOxGC3Ppskg1yMQNGtWrXqH7LyCrpI + 1TBnSFTKlM79JC92XUEbtigWwLyDDdAaNGiQVb6wXbp0sXhj2LBhdtSoUY6t+vfvz1xajRo1Qk9mosNv + YBvRFxAB7w4ylAoBEngf0hhvsNvaZTt69GijOssQEyTAJk2aGClta9WqZSZNmmREDv8O2QPi9AXsFBRG + yUDwUQ5Q8yCM2UH/PtQrAQu8gCXrkENgLBlihwwZYps3b57tESW8AyEZIGaI0IIpVJPsNtAB6yrcXPHm + F3CUD4KYuw/8X7BjghVI4V0lOaM8Y5csWWL0faN84bzRsWNHPA8ZvLOizTZS2TaGTEoJQMKCDlGSOl/C + 1ZDAoExKBowM/F8oYzzHNxRjBvxPmzbNxMXFOQMaNmzokh50LRjXCNoLSjZfUVECH9iCGIBCSftcfSGL + EuTUOCQbfz7wuWDGeAwYiSptbGysC+zevXvbZs2auWAGWtqwLqEYUBvcE8C60pi4XUJJ5nyBq/EMtAqH + Mw/d8rxixPUNVJXeFa85D+o91vDXcjkGKNJHiI3YfecNrrSr6KLvjAjaADUhdaE5lJEHDLvIh8nClBG+ + QK+MwTJFHGUyeAVaJDJP3hiT1BCUIhliCGuwPgaofyDJGcWCnT9/PgxklDvwcFzQBmiBr8EdisP/fEQV + 4XdEBrp8ACXyPCU1JQbskpNQlSpmLMEK7Gh+mAOKfAsD6B/4P3HHM8zxjLw0KmgDxo4d+4UaEOcBLeB2 + ib6Xstfrf10Qky0JPgo12ERFnKldu7aDExWqJyhKw0NF6nadbIyXeM9Lim6OjVDpYsg/xJPqLDfP2tKl + X9AGqG0spJ1I1644FgLTdEkco+Bu8A1sKMBq1qxpSDgqB1xNM3v2bBocS20D/KBaaiIwTmlNPGC8lzey + r8CKeOEdNoJvsQbz5BwZUD9oA3hQTLQfxcm+sAStHzFAXeTRpBvzfxiEDgoj6tevb6tVq2YbN27s4Ee9 + 5AVv9nv++4FXYMJ6VLcwII0MsMRDxIcMyD4ICMoQ1SO9sZ5K03OhcysMEiDuHqj5gc7u0itTiOFBmOrt + 5717f95dSZRsGLCh2CPmFE8uSQrCx4NSOvAh1SCfKeAyyMbgleoSZTg+DJDA+7DGBK0YzyVDYMWYuANO + NEp0a/pus5AN4AUZscFPVuwwi9Jw5KWoXHaVKfABLrAUDEZpTRIVfE5oPrx+eMaMGb9XQGUSRApAV+8Q + xGr9fLF5MHaJjNM+4oA2E6aiaxOs0kWpvwtr9/2XVFgthD2IBzIxrqYBp9mm5fOuYY8JVmAKLIEq50rU + Q2pqslTMda9QoULhXBmg+qSUDq+SCWQyIvURrILyefEHNGE4YKMc4I5oFLyZ6sJipXiFwoUL5+54USm9 + nHYlBWaAEult2S3YJqdThMADqneNgSPUDFuRJ9TYWMVEmhqaHlL+N5LKkh+H7YFZs2aVEpdfIAaESdcX + wEYc2vJxAo+rryjxgIE5ne+8bQyKQ5/QJcmSTK0Afl69evWWUri85HPvWlbXfCEbERMTE6WiLoGP0I2p + N72tjHtYSSuTgMYIgpqeAapDEUoDNemObt8+7/QNIKNzBsRxCcZzRENrqWC9U7FiRVrHSpLSkk88idE1 + ZBbiB4lS6ktjdWR4s3Llyut130fyL43jFBOpGIUQF+wmQmYlPqhSqZsoBxCMo56CBDCOwIUyeZfEpR5g + t35Ta6T1ObwCNh9JPvaEccgGfFCwYMEo/VjHImDxD5JfeQt+Gh0d/Q+dbyYq1WdSPgMbdpIaiWIPhfGM + X/fzY4j3Q4hrTf0zJcHmgSAzRuv+U1Jb8o3kt5JfeN/6UNcSYUEoAHN4AwxyjdCvkBFihiIy7vOyZcu2 + 7tSpU6IUeU1lSl1EgUcpjEGUywjjwHnKZErmqlWrxmtNdr6uhJaR07dfS4DQTyXFJJEBuuTdUB6KKFCg + AD8HlStWrNjXVapUiW3UqNE2/QiSpOB/tXTp0kwOdKVolhr2NFW4yeL1EyKDLMoFTqvVfW3R+3/1PAx0 + PpXQvKM4sAk9eEM1EY9ICskj7BiMUVnGfSWj6kmaFC1atFFUVFQtzf9F8nf1ukcp/ugZFF+n2AAJkOFH + jCLejr+3HwX5MC4ne8LfBODPvV0tKSN/VqZMmebKuBkcFMg7qeXLl4+Wkbzz3pQO2mmRkZH55K1POnTo + sIMcQvclg/6keaCYP+iF3uODlAXlxGK9lCDTodBKlSoN1RyBm7ua5wcyqoCH9z+rFY1XoXi3dOnSTTVX + xgvaH0iN3H0mUjAqqkD/UMH9UfHixRn/T8And2b/v779H/5zKieSpVJSAAAAAElFTkSuQmCC + + + + 270, 24 + + + Welcome to Telldus Scheduler + + + Welcome + + + Units + + + Schedule + + + Starts + + + Latest run + + + Description + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK7wAA + Cu8BfXaKSAAAAyRJREFUOE9Vk3tIUwEYxWeiFZHNICkIojAsMBmJJRkhGiKZGUUPSkoriVolzSiopMyw + 1NCsiZr0QE0LjVDzUc3HFJ1uaWsmPipd6dbcarO0bGqdzl3+sS78uJd7v3Pu9333XBeR05GaWuk19s0m + 9ZjvFuEpnuM9NWWH0WR5b/lirunrV99vbHxuZPkkgbPOcZ2fr91R8rDFavpsxuDoFLSWSagNP6Hu/wxF + rQJXk7Ise/ccjWGpmLj+ZyCIm+q7p38B0E0BRp6HfgMDdkA7AdSagAZ1N26kZtpDQiJOULyIzHKYCG0X + FzVZxyl62tGDu0UFoA76aaCb4ld80E7qbECVUoMzp8+ZxGJxJKULiIso8WJhkkE/DA2LegxGuHG+0sZm + DNOklzQMfcdl+QO0jgGVvJmfk42AgIA8in2Jm+h6SklH38gPDLL1bxRUaF5jnqsLqnsG0WqewGJPD0Qf + l0HJDpq+AiU1LdgWsbWd4p3EU5SbXTbabhiHngv4IECTW6WVCN0YiECJH8oVSvRZuVQaqASDhl4ciT1g + oDiBLBXdziy2tQxY8e4noLECaraqpdH28DDcy89FaFYoNt/ajCdvnuPjD6BQ0YVDB6OHKb5CVogunpdr + WnXvUfeF83LbTWag7TsX+tYMnXEUQTcCcV+XhYSqk5A+jUdHVz+Oxh3upDjZYRB3JPFKbUUFyvWAggYv + uag6A1A/wnFotDbFD9kdyUhUxWKXYhXCC4IQL4/XUZxIlomCg8OXJyfdtLxQqlBOcS2p+gg8o2E/55Zc + XwOpcgt2N/hAqg1A+tcoBN1bbaf4ElkuRMF93764mLRrGfbyGgXKev+gmp3UkwF+WkmaL2TqMJx664+r + I5HYVCKZYOMF1F1wdOAIA+MZEhIplcWfNd2R30RRWRUKq9vQ2fsJ/pl+kI/EYH/zBoTmBFtYW0ZSSNhM + mByBFGLpJSTM3399XtS2rW2HYw8MlT5+ZJOkrZmWpPvaYzNiVKwpnnnzuhnxvzjPHMIPIsRTSJgQEhkR + Np1GMkgqOUb8yFxnofO1MI47WUiWkhVkJfEh3mQJme0s+Au+QgUxI1c9OgAAAABJRU5ErkJggg== + + + + 104, 22 + + + Run... + + + 105, 26 + + + Scheduled units + + + + AAABAAYAAAAAAAEAIAAqiwAAZgAAAICAAAABACAAKAgBAJCLAAAwMAAAAQAgAKglAAC4kwEAICAAAAEA + IACoEAAAYLkBABgYAAABACAAiAkAAAjKAQAQEAAAAQAgAGgEAACQ0wEAiVBORw0KGgoAAAANSUhEUgAA + AQAAAAEACAYAAABccqhmAAAgAElEQVR4nOy9aZRcZ3U2+pxT89zVs9TdmqxZlid5lm0ZPMdeBAeyCJCE + kNxAVu5KAsnNwJSbj8AyJnwJJlnmBseBAMb5AAMGG9uyBY5iDDE2WNjYaFar566qrq55rnN/dD+vdr19 + WmpJ3V0tq/datWques857372vDewTMu0TMu0TMu0TMu0TMu0TMu0TMu0TOcDGc1ewDI10uHDh1cZhtFh + miaKxaI7EAhsNwwDpmnCNE0YhhEzDOP49ONCW1vba81e8zKdu7QMAE2gAwcOXJjP57dZlrXBNM0LAFxg + mmaXYRgbpxnb9nuWZcHpdMKyLFiWBZfLBYfDgXq9/guXy/VqKBT6hcfj2QfgOZ/Pl13Ug1qmc5KWAWCB + aXJyMpLL5W6pVqvXW5Z1uWVZVwFwmKYJh8MBh8MBPibzOxwO9X3DMBTDy1u9Xke9XketVkO1WkWpVEKp + VCJIVA3D+O9IJPLt9vb2bzidztHmnYFlWsq0DAALQIcPH74iEoncCeBGALssywLVeDK90+mEw+GAYRgN + TE7iY6kNyMc6GBAIyuUySqUScrkc0uk0HA4H3G73c9Fo9NO9vb3fW6RTsEznCC0DwDzRT3/60w3t7e2/ + 5/f7/8Dr9XZ5PB7F2KRisYhCoQCXy4VgMHjS3yMw2D3WP8f/kGBQLpdRLBaRTqeRSCSQTqcRiUSOrV+/ + /iNtbW1fm89jX6Zzl5YB4CzoBz/4gb+tre3twWDwvYFA4Ea32w2XywW32w2n0wnTNBVDmqaJZDKJ48eP + Ix6P44ILLkBvb6/6LZ3BZ7uXdDJfgWVZSiPIZDJIJBIYGxtDLpdDT0/Pc5dffvm7DcM4Pq8nZJnOOXI2 + ewHnIj366KORvr6+PwwGg3/l8/k6PB4P3G43vF4vXC4XTNNUTFipVODxeJSUrlaryOVy2LdvH1auXAmX + y3VSJiedznvUCugkpMlhmiZGR0dx9OjR65LJ5L6xsbG7urq6fjQPp2SZzlFaBoDToCeeeKKlra3tT4LB + 4Ad8Pl+r1+uFx+OB3++Hy+VSn6vVaoopy+UyPB4PSqUSisUiyuUy8vk8JiYmMDk5ia6urlnt/LMhmg2G + YUCaI6VSCdVqFYlEouWFF154ZmJi4sbW1tb/mZc/XaZzjpYBYA60ZcsW44EHHvjjcDj8Sb/fH/H5fPD5 + fPB6vXC73TAMA/V6HdLZB0wxYa1WQz6fRy6XQzabRS6XQy6XQyaTwSuvvDIDAOabuB6Xy4VAIIDW1laU + SiVUKhUkk0nv888//7hlWRsNw5hYsEUs05KlZQA4Be3evfuqlpaWfw2HwxcHAgF4PB7F/A6HA7VaDbVa + DQAgY/i8dzgcSCaTSKfTGB8fRzweRyqVQi6Xw4EDB7Br1y54PJ4FPw6CgN/vRygUQrFYRLFYxOjoaNsP + fvCDBwHcveCLWKYlR8sAMAs98sgj7mg0+g9tbW1/GgwG4ff74ff7QXufTjZKfV3y6wAwMDCAWCyGWCyG + dDqNUqkEp9OJer2+aMdEEAgGgyoiUSwWcezYsV9/4YUXrrryyiuXTYHzjJYBwIa+8Y1vrG9ra/tGa2vr + JdFoFH6/Hz6fD263W0l9Mi6lvrxJcjgccLlcGBwcxMTEBCzLwqpVq7Bu3Tps2bJFgcbZkAw1yte4FplT + 4HK54PP5FKDl83mUSiVjYGDgnwBce9aLWaZzipbDgBo9/PDDv97Z2fnV9vb2YGtrK0KhkPLuA2hI2NGZ + 3s6Wr9VqKhafzWYRCATg9Xrh9XrV4zMBgdkShyTpiUMMSRYKBSSTScTjcYyPj2NiYgKFQsHasmXLzl27 + dv34tBezTOcsLWsAgr785S//XktLy79Fo1FHNBpFOByGz+dTqblkMqnqy3s7Mk0TwWAQLpcL9XodpmnC + 6XQ2ZALOlWTCDwCVDqyDgd3a5L3T6YTX621wZBaLRWNgYODTAK6f84KW6ZynZQCYpn/7t397XygU+lcy + PiW/npcvH8+Feal2O53OGb9xOiSZ37IsZYZUq9UGkwSAqhyUtQUSIOgLoEOTps3ExMTOPXv2XHHTTTf9 + 9IwWuUznHC0DAID777//LT6f719DoRACgYBifjIt6Wzi9WfC+HYqPqV+tVpFtVpFpVJBpVJBtVpFvV5X + DM9sRKfTaaup0DfB27Q2YmQymU8CuPW0F7tM5ySd9wDw2c9+doXb7f6idIydjPkXMmavq/E6ANgV/jCc + VywWAUBJdt0/wexEeTwEAWmOJJPJG7PZbCQYDKYW7ECXacnQeQ8ALpfrM263W2X10eFnJ+3ni/ln89rb + vSYlPwGA0r9YLKoyYOYikLGlCTAb6WXIhmFgYmLCFY/HfwPAF+flYJdpSdN5DQD/+I//eJdpmu/SHXM6 + MaRmx6QkndFm++ypXteZXr4m1X+mGzP/gFmHtVoNlUqlAQC4dgkIujYgS5KTyeQtWAaA84LOawAA8PeU + mCyYAU6EzKQKbZewIzWDk4GDJMngdkwv/1/W/Ouf05mf71erVQCYAQAENnk8do1GLMtCsVhcN9cTuEzn + Np23APCZz3zmRgCXAI3xfNlpZ7YGHHbZf3oasJ0Dz47RT3azI30N8r9lhKBarSr1nuYB1wZMAUClUlER + BAkIlUrFj6kckbmh2jKds3TeAoBlWX+oq8GyhFeStL/1oh9pR9vZ3LMx9lwZ3mbdJ01GoqZCAHA4HKhW + qzPClno0geZDvV5HuVyeAGACqGEZCN7QdF4CwKc//WmHZVl3AjOZm7dKpdLQWEN632keSA866+2lD0G3 + 4U/m5Z+N5uowlO+xAQmZmuAEnAA6hg/L5TLK5bLSBmq1GizL+jmmAKCOc5T5Dx48uKNer+8yDGOTYRjb + HQ6H2+FwBE3T3ORwOLIA9lPjA7Dfsqz9lmW9AuC1vr6+/c1d/eLReQkAlmVdAiAiVWZKP95zc9CpVi6X + USgUUC6XFVM5nU5VHMRuQNIsmOW/57K+U76vq+26X0E3A/T+g5VKRfUoYJ8CagPJZPJ7mAKAcwYExsfH + OyzL+oNarbarWq1eV6vVggRgqa1N50UEDcPYAajw6A7gBFAPDQ0VLMv6L8uy/gvAt9/IgHC+AsDW6XvF + KJSIsrxX1wzkd/gZXf1n1t1cowJzfd/u8ydzHkqThq+TarUaisWi6lNAYCsWiwgEAvkdO3b8/tjY2Hs8 + Hs+Yw+F42eVyWaZpWgDgdrv/87QWusA0Pj6+1eVy/TmAd1mW5ZN+GIfDAY/HozIfZeo172VGZaVS4fnz + WZZ1+/TtnsHBwUOWZT0I4MG+vr5Ykw51Qei8BIB6vb6Wjyn1dFVYetZnu0kpW6vVlPqvp97ORmcDCrrJ + omsE0plJjYXvlUol5PN5ZDIZZLNZ5PN5ZLNZFItFbNiwwZ/NZt9dq9VUKrTMFYjFYg9PP645nc6sYRiG + 0+lMGIaRAZABcNAwjB8CeM7j8Rw59dU4MxoZGdnucrn+t8PhuIXn3TRNVbshE7lOJ3+D5h8BcRo411uW + dU+9Xv9fg4OD37Ys6wt9fX0/mOdDagqdlwAAwAc0OsJkyy7G0YGZYTvJYBIAHA4HKpUKXC5XQ5RA0nyC + gpT2diAgIxry9XK5jFwuh1QqhcnJSUxOTiKVSiGfz8PhcMDv92N8fBw+n09JT0pOGVY0TdNhmmbE6XTC + 5XKFRSh1p2mav+d0OpHNZmuGYYybpvm6YRjPAnjI6/WeFSgcPnzYEQgE/pfL5fpLwzDcTqdTpT3PR6KW + aZrweDzweDwIBoMNppJhGG4A77As6x3Dw8M/tizrL3p6es7p6snzEgAkk5H5ifilUgkej6chJ0D3uvN1 + agrc/DLmLu3t+Vwvn0sA0j35wAktREY2WArM8uREIoGJiQmk02nk83lceOGFyrFJ5yal68m0DQANVY5u + t5u+EYfL5VrhcrlWOByONxuG8fFsNjtpmuaLhmF81efz/cfpnIcDBw60BgKBb7nd7l1MeT7disrTIcMw + lH8nEAgof8m0o/Qay7KeHxkZ+a5lWR9auXLlOTmi7bwEgHq9npTPmVZbKBSQz+cVAEgQABqZ3676zi7r + zm5zno0mIDUQFgFJAGDJ8fRxAoCKaJRKJUxOTiKRSCAejyORSCCVSiGbzWLNmjVYsWIFQqEQIpEIQqGQ + cmzyt/QiJGpLvHEyEY+fzUeYYj0tqVtcLtfNpmnenEqlHnQ4HAOmaX7bMIx/9fl8szrb9u3bt8Pn833D + 5/OtlSXai0Wmaao6kVKphEKhwGN9S71ev310dPTjAD7V3d1dO+WPLSE6LwHAsiylhpKRJAD4fD618fXU + WcnUlLaVSmVGpZ3UAuaqCcxF/dcjF7r01/0UdGyVSiWkUikl+SXzt7e3Y8WKFQowWE3IhiVUrwk80mlK + 7YkaFCcT8XkqlVJmBMuP2WHJ6/U6XC7XGtM0P2hZ1gfT6XTMNM0vmab5cb/fr2Yb7t27930ej+ez0WjU + 5/P55nCF0XDt5pPoZ/B4PMp56nA43JZlfaJer985Pj7+7s7OzqPz/scLROcrALwsGZpOwHw+r7r1UPrT + pidJW5g5Ajrj8jsyS/As1qru7fwPegRD/i8nBFHyU+rT7s/lcmhpaUEkEkE2m1WNQmhTS/Wazzn4BIAt + GBQKhYYb7WcCEQDla2DfBQJNvV7vMAzjLw3D+H/S6fTLpmn+/bPPPrs+HA5/uq+vb87NUxeyYpNkmiYC + gQDcbrfSBkzTvMayrF8kEonfbWtr+/aCL2Ie6LxtCfZ3f/d3/QBWASeadvj9frS0tKCtrQ3RaBShUEg5 + wmShDSVeuVxWKrdkDr3jj95BSKe5mAl20p8qOO+l+g9MmTaFQgETExOK8ZPJpGpNHgwGVVegYDCISCSC + lpYWtLa2KjOAJdIy14ENRKTpQxNBlijn83kVamS4sVAoKJOEDrdIJAI2YmHnZYfDgePHjyObzeKSSy5R + rdPswNSucnMxiRqW0MBq9Xr9/dFo9MFFX8xp0nmpAQBAvV7/JoA/l68Vi0XkcjnlCONmY4IPvevc9HL0 + l3SKkUH5G3qdwJlsUqmCE4ioufCxzOuvVCrI5XIN6n4mk0Eul0O1WoXL5VKMSC1GRkQymYxS1WWy02yP + CXhkaiZJscyan3M4HAoMcrkckskkRkdHFQi1traivb0dhmHg+PHj2LlzZ4MWZpdj0WyiWSBAwGGa5r+l + 0+nucDj8yWav72R0PgPAw4ZhKAAgUxUKhQYb3rKshqagwIkkE/oA9Pi7tM/tQmh2G9jOTyA/y8dUudkH + gCo+X6fU5zxAMn42m0WpVGpIjpG1DPx9ahaFQgH1eh3FYlGdD1k1SU2AQMAbtQTmHTgcDvh8vobJyHTg + 8RwVCgWkUimMjIzA7XYrs+Cqq66Cz+ebkeXI87HUyOPxKCCe3gufyGQytVAo9Klmr202Om8B4BOf+MSL + H/nIR35sGMY1fI1FQFJtp1TkJpaagMz80z3x1Wp1hgYwGwiczEkoowp06tHWlg1BOO2nWCwqxk+n08jl + cqpbUEtLC9xudwMzcqah1+tVXm6q/DIBSHcyAieqEKkxSTCQ5pA8Bo/HowCTRCAolUrIZrOoVqvo6+tD + V1fXjLyHUzU5aTbxmosCrE9ks9nXgsHgd5u9Njs6bwEAAOr1+j2GYXxXMnW5XAaAGeo2Z/xJm1fPEaCT + i7UE3AQyU82O+eV3+d/ysXzOLD7paKPdnc1mlXOPana9Xkd7ezui0WhD5SJ7AUrmlyPPJHjJIihqCAQE + jj4jyXwACQQ0owgmDocDXq+3wWyhKRKJRLBx48YZEQ2Z3jybFrUUiOdgWkN0GIbx5Ww2e30wGHyl2WvT + 6bwGgO985zuPvfWtb/0+gF8D0AACMtZOpqM9K80DAoFkEJKU9jrjy0xD3vMxJS1fl8zGcCVvfM6UXnre + LctCV1cXOjs7FfNJRyUTaSTj8zHz5mU0QfYh1B2h0gzheSAIEgwIONI5ymNk9KFer8PhcKCjowPhcFid + K5l3MR+DVOZKzJxMJpN47bXXMDExgQsvvBCbNm06JdjI1GsAEcMwvpFOpy8Kh8PlRVn8HOm8BoDXX3/d + uv322//c7XbfbJqmW0p2GWqjTUz1VnbblVJJ2H62duvJEoqkD0E6FmWBkoy3M7wmQaBcLiMQCGDVqlVY + sWJFQyWgnqXHuQBkesn8ZFi5Hq5FMr+M93MNXBc1J9myXPoP5DnksfP9vr6+GdIfOKFZ8d4u1Xq+tACa + W4xSdHZ24vDhw/jiF7+IG264AXfccccpwYh+oun1bwLwtwA+Oi8LnCc6rwEAAP7pn/5p/wc+8IH3u1yu + L9JO50biBuYml1JMD/PpTC8ZWrdj9XugMdNO3uvxfsl4vHe5XOjq6kJ3dzeCwaCS9mR+SnzG+OV0Itr9 + vNGBx2MCZmoAvKfvgc5At9utagpofuhhStrxVJNlxKVSqcDn86G9vX1WECXzL3Q0gPUgTG6SYc5HH30U + 27dvR19f3ynX4HQ6VZ5AvV7/y3g8/n/a29uXjClw3gMAAHz2s5/90p/8yZ/0OJ3OT9g56wgC0n4m88te + e3ZqvJSidgAgH0tVX8/0o4efoORwOBCJRNDd3Y1oNNrA9Dpzud1upeZT7aejj4NBdOaXJg4Bib9XqVQa + IgI6I+sVhDwfNKcIbnpkwO/3Y8WKFQAaS7GBxpZrUr1eCDCQAFwqlVQ4lTkU01OV0dvbe8r/5XWZBgF3 + vV6/B8Bd87bYs6RlAJimf/7nf/7kH//xH5cA/L1pml49v58X2uFwoFgs2nqjdRDQHYWS0aWZIV8j0+vO + NsMwEAqF0N3djZaWFvj9/hnJOFI7IVPSbKFzj6o/zQA66+gfkMci7xntILjoKjrXrps0ulakgxo/bxgG + 1q1bh9bW1hmAqav98vFCaAFS08rn80gkEhgaGkI8HkehUEC1WlVAdTLisTNbcNrJeefo6Oiu7u7u/5r3 + hZ8BLQOAoPvvv/8z73vf+560LOvvAdxpGIbLzoknbT/JKHYOPT1BSGcWO4lfr9fhdDrh9/sRDAbR1taG + cDjckJ8wW2zeNM0GJ58M85HpaQrQpJGtzGT4UzKidO7xsTxeuSauRe+0JD3+/B06NhnvDwQCDcxPZqfU + 57mmiTLfIGBZloqoMJNxdHQUx48fRyKRQKFQwMaNGxEKhU75O3KP+P1+TE5O8lzdgyUyiXkZADT6whe+ + 8CqAu//gD/6gu1arvdeyrNssy7oMQAiwz+Szk3R2kl9m3OnAILUBqsfZbBaJRAKxWEzZ7m63G+FwGMFg + sCFVlz4Jht7I/DJJh+9JX4ZeryDXbAdSsgJRjiWT48lkSJPM6na7G97nf/A11hcwT0DXnmSTFgkM820G + EABGR0dRLpeRyWRw/PhxDA0NIZPJoFwu44YbblD5FLP9hk6MvpRKJQC4JhaLXdPR0dH0XgLLADALPfjg + g6MA7gFwLwDH3XffvRPAjYFA4BoANxQKBa8d48vHdna/TBuW4T7pe+Bv8DEdUXSwxWIx5YdwuVwIBAKq + hqGrqws9PT0q6ccuh98uRVlqLHokQiY56UxvFxKUYCCZgf/tdrtn9CxkoY/T6WxIqNJtfQKBbp5JDexs + gYDRkMOHD2NoaAiDg4NIJBIolUpobW3FJZdcogDLjvTELj4OBAJyaMtfAviNs1roPNAyAJycjOmbs62t + bbi3t/fmQ4cOXVMsFk1KdMkIwMwR3iRdJaQ9zee0rRkL52syXVc63eTNMAzk83lUKhXE43EcOnQIgUAA + kUgEbW1tWL16NVavXj0ju0/fpLo2MhvzSwCQTK+DACMG0jfA43K5XCiVSkq1d7vdtiBEbYjflVqAZP75 + yhA0DANerxd9fX0IhUIIh8NIJBIAgNbWVvz+7/8+gsHgjH4EdlJfv97Md5hu0faWdDrdEw6Hh8560WdB + ywBwcjIAmPfff//HX3vttT8dGBhwu91uGIahQjsAlIorw3rAiQQXqt50utEul3n47L9XrVYbMvYcDgfy + +TwMw1ApvTIsxY0lHYB05uVyOZTLZcRiMfzyl79EKBRCb28v+vr60Nra2uC0nE3llw1HJADIZiBMQ5b9 + AWSxkrT/ATSo7Pw/rl0CjtSqJHPbmVjAzF6MZwIIdKaGw2HVFmzLli0q3BqJROD1emd1AHN9s63B7/cj + l8vBNE0HgN8D0NRioWUAmJ2Mhx566PpDhw59/eDBg520v/P5vMrzlxKTYSyZWKM76ijlKdWlA47v6Z/V + k3n0cJ9lWcjlcshmsw0dfvl5frZarSKTyeDAgQM4cuQI3G43Wltb0dXVpZKGpNQn8zPsaMf4fEwAoPSX + +QL8vsxrkKFSApl+PnVfAnDqSkoCgp2T9rQu/HQGI30qoVCIUltpUbN9z06r0h3ITBM2DOMdWAaApUeP + PfZY4NixY88cPnz46kAgoEJ/tFlleatMo6UqqjM+GZ1STjK3ZFL5mp7MI5le3oDGSAQZOJ1Oq/LfycnJ + GepzpVJBLBZDIpHAoUOHEIlE0NHRgZaWFuWw1G192T/RTvrbqf526cEAGrQM5hXIEKjUGIATTkr9mEn8 + jp1T80xNA5nKfDrfkf9LUJMmCiMk9Xp9ezKZXBWNRo+f0QLngZYBQNADDzxgmqb52QMHDvyxy+VyhMNh + pZKbpgmv16ti8H6/H8CJBBXJzLqtbheyo6opGZwbTmoFui/AzgEGzOwWzHg6NyAbgGYyGVUrQKpUKpiY + mEAqlYLT6UQoFFImgg4CurSXar8EDQkAdlmSMrNOagV6VSWABulJom/Asqby9XkN9PyDhcwWPBlJM4fJ + ZHKfCNPlTgCfb8oisQwAAIAvfelLAcMwfrtYLH7Wsiyvz+dTRT2GYSAajSpJz9ekc44eecngUvLbmQHc + GFLK69lukuH5mmT6U4UjpSrt9/vR09ODarWqqgapJcjv12o1pNNpZLNZFU5kmq4d40u/gM78Up23AyoZ + 9iRDl8tl+Hy+hpCpZGr5O7VaTTkSpePUzgO/mECgmwJS85L+julW47dgGQCaR1/5yld+s16v/3+1Wq3V + 4XCozepyudDS0oJQKNRQyiqlO5mcUltneLkxeU8pr3uzgZmeeG54du7hukhUTSUgATOnBUuHYa1Wg9/v + R2trK2q1GnK5HNLpNJLJpCrr5XconfnabD4AO+bnZuf6eK8fqy6xp6cTNeQc8PzqIJDNZtV55zlgmjQB + xS6sulikAwGABpNnmq6Z8cVFpPMWAB5++OEr6vX6/67X69cDJzap0+lEMBhEMBhssMl1T7tsg6Xb8TI0 + pefD68xhRzKurUt19iugvS/Xbvc7ukkBnJBE9XpdmTU9PT1Ip9NqTkC1WlWf5Xo8Ho8CDV36S/t9Ngce + GVQSj4+dldkzUGoa1LAkE9Ps0Fu3S3CV51HeLwbZaQHynNBsMQyje2Jioqe1tbUp4cDzDgC++c1vRuv1 + +gdrtdrHgMZc93A4PKMklgk0DOVJINBVe53hpWTUHVrcIJIZpaRmnjwZEcAMhtfBx84JKaUNGYKaCkt+ + qYp7PB60traiXC4jlUohHo8jl8s1nD/6P5LJJEZGRmznEuhST5oxkgHl40KhgGg0qvIZZKUhJTyZm23E + qB1JcJG+EZ4vag/N8geQ5Nq0iMZ2AMsAsND0yCOP3GFZ1gMAeqR0CAQCKp1W1szLTDqZTSelqu6Uk5JL + MgJz1yWzsK5ftvSmxKVEnS3mLZ2PUrpJMJCNObl+Wc3HtUsNp1arqTyFtrY21U48m802MFE0GkUkEsHQ + 0BCGh4dn1WrsMvb0m2mayOfzKqRZLpdhmqbqwUA7n58tFArq9xmxkL8ltRY9kxBobuegWfw265u0nPMH + AL7zne/8Y71e/6B8jYk6krllc0v5WNr9kvkphVjmqju5WNXHhqNkeL7P0Jq0eaVHXdcQZPLRbHkGekWg + 9E3I0CWPXX5fdgyq1WrweDwNQJBOp9X5MwwDvb296OzsxIEDB5BKpRre05lc3utaUyaTgWVZKo/BNE3V + ZESaWzqwAlB2vwy32TlLm+UP0KR9AzhNX9+1J/n6gtIbHgAee+yxzfV6/cv1ev0KvsaEDlkRR2Zn5p4s + npHxe6m+U03VmZ5Mzd74NAGkaitbe7GjDu1ay7IQDofhdDoRiUQaNk9bWxvq9TqSyRPTzcbHxxUgJRIJ + xeiy+k+vCKRd7fV6lQbE1yWAsANSR0cHotGomi6UTCbVeXC5XNi2bRsmJyexf//+hvRdyZB6arPMfUin + 0wrg0uk0HA6HasTC60DtyS7ZR4ZrdfCR6+HnFxsE9MiEliPRsWgL0egNDQDf//7376jX698AEOBrhmHM + yviyVFaqzNywwJQdTikFnPCYk+k5XozSm8ydy+UahmRMp4OqsVx+vx/RaBStra0nLTSZKyWTSRX7T6VS + GB8fRyqVgs/nQyAQQDAYVPa87N0fCAQQCoUawEBWDzIdNp1OY3R0VGkEBK3LL78co6OjGBwcnCH1yaB6 + BMXpdCq/Q0tLC7LZLPx+v9JIuDaef9ZMSCY2DIOVduq5zuASvBcTBCTzy1Rr+ogsy5r7vLN5pjcsADzx + xBMftabq+tVmkLXqlJBsjiFVYt3JB0xdRDI2n1NNZ/04mZ4gkMlkVKw9nU7D4/Ggq6sLa9euxYoVKxoa + X9qRdAACJ6IIMmLBxzIMCEzZ6NFodMZvxmIx9Pf3Y3R0FAMDAyrVleXFwWAQExMT8Hq96jnTmnne6CgN + h8NIJpMYHBxssMu7urrQ0dGBY8eOIZvNNvgqZJajbqKkUilEIhHkcjkV4+f/ulwulMtlBQS6h5+k5w3w + JrP5pFNwMUFAVllqztNlAJhPevLJJ79kWdZ7gMbKO6rG3MTsjiMloEzq4cag7Q6cYPxyuaykOmPmuVwO + mUwGk5OTmJycRDqdRltbGy644AKsXbsWwWBwxlppGuiZcwQaSXPZqHpyEpmH3+3o6EBHxwmNcxgO5gwA + ACAASURBVGBgAENDQwoQIpEIIpEIwuEwMpmM0gpaWloQCAQaBoJ4vV50dnYiGo1ibGwMg4ODDetetWoV + MpkMRkZGZpgCuoPV7XYjmUxi1apVqNfryGQyCIVCKBQKSkuo1+sIBoMNsxt14vljl2EZRj0ZCMz1/J4J + yfwOyfyyUKpZ9IYDgN27d3+zXq+/jc+ld1xKfXmzG28FQHUD5gWkxGfhDf0A6XRaJdMkk0m43W6sW7cO + GzZsUCnDJD2ffi4X/3Q2JqWMDiDSwSfHfvf19aGvrw/AVGLN66+/jmPHjmFwcBAtLS1qeGgqlVJmCmcm + So2gt7cX0WgUw8PDGBkZUf8bCASwfv16jIyMNGhPHo9HzVrweDwN05lZMUdpzwiBlNayIYfu5CsWi6jX + 66q5iCw1lhWDumNuPrUBPXKjS3+ZP2FZVvbUv7gw9IYBgGeeeWaFZVlftCzrNulhpdpJiSUZX5bqkvnp + UMrlcg3Zc5TwDIeR8aWt3dXVheuuuw49PT0Na5Ots08H7aXkBtDgiwDQEHU4VXJRvV5XDkj+lhzt5XA4 + EAwGccUVV+CKK65ALBbDwYMH0d/fryoHGadn8hBLY/k7zKNobW3F4cOHVQ5BvV5HZ2enMosANIQbvV6v + KrYaHx/H6tWrUSgUGtqDcWQbNQn6AqSmph+vnkRFhyXPoe7UXQhtwE76Sy1g+r1lADgb2rNnT69lWQ8B + uIGvyZRevQ8+H0uVnxuBXnkCSKVSURuXQJDJZDAxMYFYLIZsNou+vj7ceOONCASUr1FpD5RGs5FU0/Ww + 3pmSXsarJyIBaIhiZDIZOJ1OBYqmaSpT4dprr8WBAwfwy1/+EmNjY2rKUD6fx8TEhJokTCDweDxob29H + JBLB0aNHcfz4iUI3gi1DflSDfT6fGiGeTCbR29sLAMhkMgoEZA49Jb+szdDDfrVaTbbjbgAEmhMsypHJ + W/z+mWoDOuDoYVx5TZj7Ua1WJ077j+aJznkA2LNnzwoA3wBwNV+jo4zMr0++0e19XnAyOTdnsVhEOp1W + tppk/ImJCaxduxa33nprw9x6evh1Bx6JoTUyw9kw+mxEQJHENGKZqCQ3eK1WQzabRTabVQ1J2fhi06ZN + 2LRpE4aHh/GLX/wCv/rVr9DW1ob29naUSiWkUim0trYiHA6jXC4rMNiwYQNaW1uxf/9+ZDIZdZ5ZOk1A + pYbERifj4+Nob29XZgAdq9JMI2gzTKmbATxmArCujtMfoCd06cVEpLmAgR3zz+b4k0NTKpXKcjnwWdA/ + QzA/GU/OvZNxbm5OqT4yfCft50wmozYtx1iPj49jfHwc3d3deMtb3qI6w9ZqU/PxstkTmpzcMEw48vl8 + p1VbPp9kGIYCHgDKccn211JDYD+BdDqtQNPpdGLlypVYuXIlkskk9u3bh4MHD6K9vR3t7e0oFAqYnJxE + W1ub8hF4vV7VY+DQoUM4cuSIOi/sq+D3+xtKilm63NLSAtM0VUiQyVF6qbVuBugZgABmhGylRsDCIVlK + bJe4YwcKdqQzv95JSdY5EBhKpdJrZ3+Fz4zmX/wsIu3Zs+eTAN7P53Qykfl9Ph+CwaACAF3tJ3NT5WeO + eTKZVJJjcnJSecgBYNeuXdi2bZsaBU1w4CYjmaaJYDCIlpYWBINBVVa7VIi+EY/Ho7z7lMqSeE7YZcjh + mBr3vWbNGvT29mJoaAhDQ0MKeGlWyPoD1hi0tLQgkUioz1IVpk0vuwYBUP3zGAKU9jnXr/dc0KMN/DwB + Tk/I0aW2Hc2V+flZyfx6NyWpgU0Lm1qhUPjAQw89VDr1r88/nbMAsGfPnv8LwD/wuR3zBwIBW+bnxmDs + nsyfzWYxMTGhVMd4PI7BwUGMjIxg8+bNuO666+D3+1XO+uTkpFKlefN4PAiHww2juM8FIhj4/X5lPsic + ejoRdSBYv3492tracOjQISQSCSVZ6blniq7L5UIoFEJHR4fquS/9ELJSkSp/IBBocPpJCa1nE8oMQ7vi + LIKbXY6A3Y00mzPRDkh0lV/a+xIA6JuYrgd5/o477mhaP4BzEgD27NlzE4Bv8jnRVHr6yfx0bNHTr9v7 + VIUZtzcMA+l0GmNjY+jv70etVsMtt9yC1atXK3NhYmKiIesMmHJIRSKRGf0DluKtUqk0lC3rN5osHo9H + bVSSjCZQHQ+FQti6datqpZ3JZFQTkUKh0BDNCAQCWLlyJer1OuLxeAP4Sn8MTbFgMNgARLotLmsLdObX + zQLa97pTkK/xnsc5G+PrDK+/Jj3+ZHyeMxn7n271/rX//M//3DP/XDI3OucAYM+ePZsB7MW0/4InnJLf + 7/fPyvysFMtkMtL+UgzNHPuRkREMDg5i7dq1uPHGG+H1epWHmk0zpMRvbW1V2XJLmUZHR/HjH/8YR44c + wfDwMMrlMkKh0KzrppON3nbZ4IPSmzX5DocDbW1t2LRpEyYmJnD06FFlWzNngna22+1GZ2cngsEghoeH + larMECG99Kxa9Hg8ioF1+573egclmRkpzQGSZF5Ziakztu5A1CW9LvWlH4lRDn2gq2VZChyz2exffOtb + 32paa/ClvWNt6D3vec8jAC7g81KppCSWZH69uIX14pL5C4UCJiYmlKqWSCQwODiI8fFx3HDDDdiwYQMA + KL+AdJQ5nU5l358Lan48HscPf/hDuN1ule3ndDqRz+dnFBzpZBiGSvihZJfONmpDlMCrVq1Ce3s7Dh48 + iFQqpc59qVRS5oXT6URrays6OzsxPj6uKiKZf8EkHo4Nk55+oHHSsuwpyM/odQh8T9ciZM9C2ayF97MB + A9/TQ3xkfj3CIaMcDC1ns9mX3/Wud/3t/F7p06NzCgCefvrpDwB4Py9gsVhUFW0sbJE2/2ySn46tiYkJ + 9Ttk/kwmg9tuuw3t7e2oVquYnJxUzSe4oUKhEFpaWk6qRi+1249+9CNUq1WEw2F1Y8ENJf1cfsflcsHn + 8ylTgsSaCDrlQqEQNm3ahGQyiWPHjikNgNeM6n44HEZXVxdSqZTKD2DNhd/vV/4AuVZgpt0tm5FIT76u + /kswkElU0hfEPSKf20l/mdSjJ/roqr8MAbIoLJPJfPx73/vei4vIQjPonAGAp5566jLDML7FC0rHEcNN + dg4/2UuO5aa8ABMTE3A4psY2x2IxDAwMwOl04o477oDP50O5XFZSX27+aDQKr9fb7NNx2vTyyy+rbL9Q + KKTOEZnxdI6JGgHz7aWPgP0OCAR9fX3o7u7Gr371K+RyOVX5JxNxAoEA+vr6kM1mkUwmlROWjkD+LtOq + pQSXklom18hehvyOZH79eAA0MCmZWG91Ju/tsvsk8zO5SZoDZP50Oj2czWb/cPfu3Y3ho0WmcwIAnnji + CdMwjKcMw+g0DEMhMDchmZ92v2wjBQCpVKqB+ROJhFJ/WR3X3t6OG2+8UXWc0ZtbBINBRCKRc0Ldt6PB + wUGVdSeTZ6rVKoLB4IzEobkQAZiDPylhqbrTN8B6gOPHj2NsbEzF3qvVqrpObrdbdS2OxWLqN/L5PAKB + gEpkkklXJJ0xpdSW4T+7rD9gJiDI+P1sw00kQNi1ROf5IADwWLLZLNLpNMbHx//2Qx/60N7TPunzTOcE + ALz73e/+hGEYb9O92NLul1l+Ml1Ul/yJRAIul0sx//Hjx9HV1YVrr70WhmGofH/+l8PhUG3Bm63Gn80t + EAjg+PHjDeo3naft7e1n9dtSg5DtuSjpmZm4fv16lMtlHDp0CMAUgLDvH4uVuru7AUw1OSHTZzIZhMNh + FbGhuSJJj7/rfQp1NV7/vvyd2bz6erWm3RwE+R8647MsPJlMvn7//ff/RTabzdkuYhFpyQPA448/frVh + GP8hmZ+SR3f6kfllkg8vXKFQaGD+eDyOgYEBtLW1YefOnQCmNAVZ1+5yudDa2tq07L35pFAohM7OTqRS + KaWKR6NR9PT0zMoMp0OU4ro2QAnJ69Ld3Y22tja8/vrrqr6fab6si1ixYgVcLheGh4cBTPkXJicnEY1G + YZqm+p5cNxlWMqtMwtGBQNcMdNKjDPI4pS+Bn5FmCNPI2QiGWZXTt9JPf/rT33vxxRcHABTP+sSfJS15 + AHjXu951v2EYm6haAlOloLrTT1b1GYahWmxNJ1sotb9UKiGRSGBgYADRaBTXXXcdAGByclK2aobH40E0 + Gp0X5lgq5Pf7sXr1alxwwQXo6ek5pff/TMg0zQZtADhReCTzBtauXYuDBw8ik8moakDZjKWjowPBYBCD + g4NKqqfTaUSjUdUuTPZllESG1CvvJBjYmQp6HsBsuQAyn0ACjfT6y4YwsinM/v37P/P1r3/9SQB5AE3J + /pO0pAHg0UcfvdU0zb/nBaY6yeIeGeunBKFdy0YdjPMDUxuS2X3BYBA33HADDGMq8Ucm9nC0drPV9nP5 + RicsIwW8LswDcLvdWL9+PY4ePYpEIgGPx6O0OwIBqwr7+/uVSZHJZNDe3q7A3DBmxvild19n/pONMrO7 + 6V5+u0QfVn0WCgVVDEamz2QyqsjqyJEj3/7KV77yRQBJAAUAM7u+LDItad3WsqxPy4vJzaE375QlvQBU + 4kmlUlFDLgzDQCqVwtjYGEzTxPXXXw8AivkJMjQplunsye12qx5/slagVqupNuy33nornnvuOfT396Ov + r09JWUr6LVu2oF6v44knnlAZnENDQ1i7di1cLpeKOtCJKaU11XUCAcNyBBi99TsjFwQxmQNAkqnFABp+ + m7+v5/0Xi0UcPnz42YcffvhrAMoAqgBmrxFfRFqyAPDII4/8JoCLgRM56bIVlczyk8yfzWbVRSHyejwe + xfy5XA633347HA4HMpkMisUTZhibZS7T/BEHrrDfPwCV8MPpS7t27cILL7yAY8eOYfXq1eq70WgULpcL + F154Ier1Op588kkAU9d4aGgIW7ZsUb/LVuJSG5A5ARIImJDEdmOy6SkdyBIEpM0vTQAADRqG7PKktXiz + nn322e8ByGHK7i8DaF4fMEFL0gT4+te/7jJN8/8YhtHBC6Gn+jLTj8hNFZEShtl7Ho9HefxHRkawa9cu + 1Wsul8upC73M/AtHBG9mEQIn+hPQOdjT0wPLsnDo0CF4vV7FaNTwOjs74fF4MDQ0BMMwkM/nUavVlBOT + PiL2guD/kqQmKcN8UlozaYft2tnzka3KcrmcesznfJ/vsXKSvzs98ci4/vrrg7t3734KQBxABlMgMPcy + wwWiJakBWJb1JsuytvC57Gcn+9tLj79lWarKil5jOosmJycxMjKCiy++WI2+YqgPgCobXqaFJYbv5Lix + bDar8hAuvPBCOJ1OvPLKKwBOMG1raytcLheuvPJKVKtV7N27F6ZpIhaLoa2tDStWrFDanmx7NluNg8xX + IGDQl2DnT7Cr/pNmAJOOZCSAg0uZLt7b23vVunXrikeOHKHtv2wCnIT+HDhxouW4LrsefgCU069arSKT + yaBUKsHr9SKVSiEWiyEajWL9+vXKm0xyuVzLzL+IRGcteysCUz4b9iTYvHkzarUaXnvttQanIs2BnTt3 + olAo4MUXX4RhGDhw4AA6OjrQ1tYGp9OpgF12PZJCQieZKUgwkH4Eu0gA95wOFpVKBcPDw4jH4+jq6kJ3 + d7equwgGg84vf/nL77/uuus+iCn1v+nSH1iCAPDQQw/dYFnWbTzhsh+9dNpIW42qHPPG0+k0fD6fSvlN + p9P4tV/7NQBQXXuI+JFIpGnHer4S/QKszQAaQWDbtm2oVCo4fPiwYjImZLlcLtx2221Ip9M4ePAgTNPE + T3/6U9xyyy1oa2tTDj5OMJb9BqSvSCe7uL9dDQDQWGjEzNGxsTEMDw+jWCyqlOVAIIC2tjZEo1GEw2G0 + t7e/HcD/jSVi/wNLEAAsy3qHLPG0m9nHph68mFL1T6fTKvw0nXKJSy65BB6PB4VCoUHlO5dTe891Moyp + QqBsNqtU6EKhoBp8XHrppahWqxgYGMCaNWswPj6uANvtduOOO+7AxMQEJiYmYBgGXnzxRVW6TSGRy+WU + GUhvPIuSKFi4FmBmtyDe65oD8xoobDKZjPJtyCYwgUBADWiZdniGYrHYWzs6Oh5e2LM7d1pSTsD/+I// + uNA0zQdN0zQMw1C2vt7UU2oAvLi0uzKZDDweD7LZLEZGRuByuXDZZZep98n8wWBwXkZwLdOZE52DsoEq + Q3qmaaKnpweTk5MYGxtDIBBQacCcStTb24tXX30VpmmqlusbN25s8Orr3YEAqNLkQqGgogJ0ClLam6ap + 3mOPyEQigaGhIfT39yMej6veEDISRfBhgVNfXx/a2trUQBOPx7Pl3nvvvb8pJ9yGlpQGYFnWuwCYRGkZ + o5VTemeT/px9x061qVQKt9xyywzHE52Jy9R8Ihjb+QScTieuvfZaPP300xgeHsaqVasaBqGuWrUKd999 + N771rW/BsiwcPXoUPT09WLt2bUMbeCbnSC89fQTMBiSAyPJiWcXHzFK92zPDiOxfyJA1Ix4ej6ehJ2Sl + UtmazWb7gsHgQDPOt05LDQDu5iaQueH6vD46atgoktK9XC4r+y+RSGDDhg0IBAJq6ARwolnnMi0d4jWR + XZXz+bxqtvKmN70Jjz32GMbGxrBixQqMj48rLWHbtm0YGRnB888/DwB47rnnlFOQCWNMG2fojtOZZUYg + 75nlp7cV030DTGsmg7OLEb/PUnNZGi3yET4O4L2LepJnoSUDAA888MCbAGxm/JdMbzeplxeGNl25XEY6 + nUYwGESxWEQqlUKpVFJZZIz3A5jX1l3xeFxlrC3T2RF7FTCLE5hq1ELH4M0334zHH39clQ/HYjF0dXXB + NE28+c1vxsjICI4cOQK32409e/bgHe94h/IXMHRMjUCOZNfj9tIUYLWkZGKHw6Hak1Pys78CqxXZ9497 + UeYmAEC1Wv31Zp1nnZaMB0xKfzL7bJ5/AA0dXFj1x24yyWQSW7duhcPhUGm+tDfZ324+qFqt4sUXm9rQ + 5Q1F7B1AgCcTAVPVjNdffz1GRkaQTqeViUfn21133aW+WygU8MILL6j8jnA4jEgkgpaWFjWCnaPO2tra + 0NbWpkadRSIRRKNRNSCVr8v3g8Gg8kXRR8UW8AQDZhrGYjHV6YhUqVSimUzmatuTsMi0ZDQAAO+gx5Up + vnImvd7tldKfM/oo/dPpNCqVior5F4vFBq+sROKzpXA4jKNHj6K9vR3r16+ft989n4l9Hsj4bAzqdrvR + 29uLiy66CPv374fH40EsFlPjzVtaWvDWt74VX/3qV2EYBn75y19izZo1WLdunbLJuZdoGvB/mDMyWyqv + dBpSe6CzkqaA1+tVmiBNgXK5jHg8jomJCbS3tzc0XanVav8vgDuacY4lLQkN4P77798JoBM4EfeX9r+M + 38rWT6z6o/TndJrNmzcDmLIjCRjUIOaT2EP/5ZdfRjwen9ffPp+JGh81N+l827p1KyKRCGKxGKrVqWGi + 9PGsW7dONXYxDANPPfWUSvqSjEpTgNoBNQRKemoKvJfvSQ1A+qOYsCYb0tTrdRWKZsQAUOXK1zbl5Gq0 + JAAAwFso/cmocoKPDOcwy4uefw6QrFQqysGzfv165YwhLURHH5lI9OMf/xjFYnHRym3f6DdKVAkC9LDv + 3LlTTWZmzQfbbb/5zW9GR0cHgCnt4fnnn1fJPFITYF6JXl8i28sFg0F1C4VCCIVC6jk7FcuSY4YPpbaa + zWYxPj6uzACaApVKJbwUzIAlAQCWZb15+l6dWJoA0vlHtKWaRgcON0g6nUZfX5+yA7l5iMoLQaFQSIV8 + fvKTnzS0Dl+mMyfDMFQnYJptzPH3er24+uqrMTIyoro7c8qTaZq466671G/s378fR44caWj+QY3RMIyG + pCBWmDL/RN7LHhR+v19pptI8oMCR053ZgIZTpCTV6/U/XazzORs1HQDuu+++NZZlXU7vv+zlrzO/YZxo + KkHnn8fjQa02NZwznU5j8+bN6n3SQsb8w+GwQvvJyUns27dvwf7rfCNqArz28royyWZsbAyWZSEej6vE + nlWrVql+DwDw3//932pis2z7LdN75X9KKS6FkYxGMeOPjspCoaC0FPl9y7KQzWaRSCQaSs8BoFarvXnh + z+LJqekAYFnWddP3KllCDn3Ua7Pp/S+Xy8jlcvD5fEr9b2lpUS29+R0i9UJROBxuGEs1MDCA/v7+Bfu/ + 843oACRR1QeAq666CtVqFYlEAuVyWUUF6vU6rrzySkSjUQBTiUWvvfZaQ69AXXWXnYX1m2z2Sa1BaqTM + K6AvgiDCz2SzWcRisYZkNACoVCpdmUymqUkpSwEAdvGCUv0n6uoFHHrTReDErLpsNos1a9bAMIwGAJAS + ZD5uOvX19aGzs7PhM6+++iqSyWTT7eg3yk1OczYMQ4V2HQ4Hrr32WsRiMRSLRUxMTKiQcDgcxp133qmu + 2S9+8QtMTk42NPDQG4fKtuL6HABZNSi1BOYLMDpADVXu3XK5jEQi0ZDtyP0M4HcWkL1OSUsBAK6jc0QH + ABn3N4wT012p/jP9kid/1apVDR1p6UBcoHWri7ljxw4Vg+Z6X3rppRkDRJfpzEgCOXAizAYAnZ2d6Ozs + VING5ZzHjRs3YtOmTeo7r7/+uu1AD10j0DsL2wGB1AIIIswsJAAw+69Wq6l5AHJPGIaBer1+9yKfzgZq + KgD8wz/8QxTAZuDEHHmZcaUXcZC52WmFQzvz+Tw6OzuVM44oPddxV6cr/Yn63CwulwtXXHFFw6SdarWK + n//85w3NI5ZvZ35jdiifk9EMw8A111yjuu5Oj9xSe+X6669X1+7w4cOIx+MzGFx2DpZagA4Q0gzgmgzj + hGkqp/9y/1JzobOSbee5plqttmMxeU6nZmsAO2T4j8yjh/34GZmUwYvBcUsrVqwA0DiY4kym3ZyM+Luy + vxxvoVAI27dvbwCtVCqF119/fV7XcD6TbPsOnOjE43a7sX37djVRKJFIqPyQ1atX48orr1Tf2b9//0kl + vT7kQ39fmgJkcK5FVqbKsmMOQJGt5/kbtVotms1mm1aW2lQAsCxr1/Q9PB5PA/NLhJ1WldQF4SAJGYLp + 7e1tqPWXE3DmWwPgmnUQ6O7uxpo1axpAYGhoSPWxW76d/Y21AIZhKIltGAa2bNkCh8OhHIHsBk2HILXI + sbExjI+PN7T1tgMCfdyYPjcAaJw2LGcD6H4AaoTpdFpVr4r9ZFiWdeeiMJwNNRsA1k7fq9HT0gSQTMcL + QJU/EAgoAOCoaxn6W4haf15sGZvWbcmNGzeitbW1YXP86le/amhDtkxnThQSEgRIV199NRKJBGq1mprq + XKvV0N3drQbAAFNagJwWpA8KsTMRpAlAkio+gBkAwAgGHdqcFMQ1i/39awt+4mahZpsAW3lCZZNPu1JM + OgBZo82GDcViUU3wkRrAQo7uBjBjbbK2fPv27TPGWe/bt68hOrF8mx8tgOffMAx0dXWhpaUFk5OTsCwL + yWRSXZOrrrpKzXtgXF7a+rMxP5lZOh5lxyoKBLkPuFeZL8DsVqau62aAZVlN8wM0WwPYNH2vNACpust2 + XbwgDAHRJ1AsFtHV1aX8BPzeQsX+5e/zJp2C1WoVTqcT27dvV+ErqoCvvvqqbWPKZTo9Yqs4ktQCLr74 + YiSTSZUmTl9AJBLBLbfcoj43MDDQwOi8hvpNMr8URLo2KPekbEbKcmRqpHYaQL1ePzEMYZGpaQDwiU98 + YqVlWX4iJaW/nf0PnGjQWCwW1XhpOl26uroWTfrzJv0VsgqMIBAMBrFhw4YGf0Amk8HBgwebLkHfCDeq + 1ST6Ajo6OhCJRJBOp2EYU9OgKMW3bdumtADWEuixf7tkIPkaMLMzsMz6k5+T04c8Ho8qWJORKsMwUK/X + o4vGeBo1DQCk/S8jAJJheJIp3akBcHBEpVKB1+tVKZmkhZ7my/XJjEVdE6hUKujq6sLKlSsbLvbIyAhG + R0cXdH3nC8lMUakFXHTRRUgkEsoZSC3A7/fj2mtPFOGNjo6e1N63GxxKoJHaptyvMkogqw8ZkqaPgDS9 + x418Pn/BYp03Sc3sB9Ajkyr0k0nS7f9yuYxwOKxqssPhMFFUAYYMFS0USYAic1PSSG1k7dq1KBQKyGQy + 6ruHDh1CIBBAOBxe0DW+0cnlcqm9QQblCPJgMIh0Oo3W1lZkMhnVCeqSSy7Bs88+q8CBTWT1acD67/Kx + jARwr7KYiHUABAfWEBAYGL5mOrvc5wDeBODwYp/DZmoAPdP3qrBCxv4l8QLI8AqfsxxXR+SFJv6XXrnI + /5bSZOPGjQ1JLADwq1/9Ss3KW6YzJ2nuSS3w0ksvRTKZhGVZalBMvV5HS0sLtm7dqj5HM2A2lV8HBj0Z + SJqCUvDQT8FyY1YZAlCOQtL0d04sahGpmU7Abp5Uu44/EgRkzF1eiEqlgkgkMsMps5h0KhBg/7hNmzbN + cAoeOHBgUdf6RiS9VJxaZXd3N7xer5pMLIeQSDNgcnJSgcNsDA+c8EEBmMH80tMv97HegITFbow48LcA + wLKszYt20gQ1zQSwLKuDF0t32ukkcwCE4wTVahXhcLghOUPPH1gMkmuXNqn0IPv9fqxatQrHjx9X38tm + szh27BjWrl27qOt9o5HMAalWq8rjvmHDBhw8eBAtLS3IZDIqX6S3txd9fX0YGBiAZVlIp9NKkOgAIG+S + ZDcgmgzSR0ANgE5AvicBQJqQALoW85yRmgkAken7Gd1+7TQAxlidTmdDyCYYDKr0X6DxwnB4g2maqmnj + QoCDLD6SJENHANDW1oZCodDQPmxsbAzBYBCdnZ3zvq7zhahRAY2z/jZs2IBXX30VhUIBLpcL+Xxe9ZvY + sWMHBgamWvPncjmEQiFbxrdr8MI9Jk1WMjg1PukEpHnC/BVpRpAsy2pfhFM1g5rpBGyVJoCUnjqTShOA + Hv56va7Sh6kZACecc4ODg0in02qSTKFQQL1eR3v7/J9n6RXmGngvZTmpswAAIABJREFUnUm12tQ461Kp + 1NAjrr+/f3k8+VkQmY1AW6/XlTq+cuVK5HI5dHR0IJvNIhwOw+l0YseOHXjyySdVU1Cml0uVX5f63KMy + XE2HL/eo3hKMpgFrBfibekoxgMCinCyNmukEVLt9tqGNUvWSAEC0pcTVfQD5fB6Tk5MNnVw8Hg8AzOjK + Ml8k7UJ54WVJM9e9evXqhvmGhmHg0KFDM6bOLNPcSdZ9SObauHGjSsPO5/OqoYhpTo0eI3G6NGDP/GRs + vUOQbB1GYSOL2ugIZLsxhosBNAg7y7Lmr1/9aVAzNQA3GVxX/WfTAOr1Otxut3rO2CqABumbz+dnXARu + EGl7LRQxSkEmp6SQx7tq1Sr09/erzVCtVnHkyBFs3LhxXtZXLpeVZGMCiq6K0oyazfcCnDj3tKt53oET + 3XpMc6qVG3siNIPYn4/nk+e5o6NDTYvyer1q7Jhpmrjqqqtw+PBU5K1QKCAUCs1q79OpJ/cUj5XRHP6/ + NBGYCVir1VT+CtdHmj73TeHFZvoAfHZ5ADpDyxNGBw8dbAytyc/zxEswkb+xWE5CnanIfJQuPp8PK1as + aEgKymazGBwcxKpVq+b8Pxx3xbwI+kpkoYo8r/Ra6zkMJyPJFDIUVqvV1CSfycnJBs82azvYaZegsZAk + fQFSQ+zt7UUikUAkEkE+n1e+pK1bt8Lj8aBUKqkkM6YYE0Ckyi+b1VCocE8BUNdXmgHsQFyr1eDxeBrM + Ve28N2W8VNMHg0j1XX9dv+dF5UXWnW78HfaNpwdeahiLsRHtQEk+JgNFo1E1zIQUj8fVXHmdOAKNBSVk + dCmZ3G43/H7/nBj7dI/nVCSdZwSiZDKJ8fFxAFCMwySo+e7XQC2AayGtX78ex48fV3Y4s0lN08TKlStx + 9OhRAFPmIdekZ3sy2YfPWeVHwQScyP0geFADoG+BZqHd+bQs6/wCALlZdAY52edIUhXVv+t0OtHX16dS + PSkFW1tbm5InINfHiAVNmu7u7oYehwAwODioho6wy00+n2/ImaBdOZ+MfrYk1yLBWXrUWaobi8VgmqaK + kZ8MEPRrf7L/p/klv8fGrWTwQqGgBo9eeeWVCgBKpZJq827H/Hp3YK6XAMCKUAodCcqWZSmtyO5YmnUN + m64BSDrZSdBDJ/T8yu9JZgsGg7jgggtQKBRgmmaDv2AxiWumJ1gHAQBYsWKFqk6LxWL42c9+hgcffBC/ + +7u/i9bWVjgcUzPzyFRLheHnShIUKDUlIKRSKcRiMdWbv62tTdnr8Xgc2WwWW7dundNxM8wGnIgGAFOJ + QblcTg0gbWlpgcvlwrZt29QAUEpwKemlxJdJP3LSlF6cxutNQKLj2q7PZbNpSWgAs72vf44OPDv7Wt7L + 1/1+/wIdwdxIrkn6H6Sqms/nMT4+jgceeADHjx9v8F389V//9byrys0mO0Dw+Xyq29M3v/lN/PznP0d7 + ezt27tyJ7du3z/m3yYxAoxnQ09ODffv2KScx8/EdDgdaWloQi8UATEnxUCikJL8+qYqefmoChjFV4CMB + QPcfMHdF726sazbFYrHV6/VOzMc5nis1UwPISg/4XImoysf6e0sBVe2IF5taSrFYxLFjx9R0G6/Xi4su + ughDQ0PqO/v27cPXv/51/PZv/3YTV77wZBhTZbvPPPMMnnzySaTTaVx33XW46qqrsGLFCsTjcZRKJbS1 + tZ2y05NkLhluW7lyJV588UXFoHT8OZ1OXHTRRdizZw+AKT+LntotR9TLxzJ/pV6vKyciHYE6AOhhYRta + dH5spgZQmL63Dc3ZSXU9dDKb5F+KxDVOTEwgHo839K9nZOOqq67C0NAQfvGLX6jvfec738GaNWsaWlq9 + kejgwYPYvXs39u7di3A4jNtvvx033XSTSs2lQ7FQKODIkSNwOp1qrPdsJM0ACbzhcBilUgkej0e1C3M6 + nbjssssUADAhSDK8DgTyPf5+rVZr6PwjK1tpKsi6BWDmvvV6veMLcY5PRk3XAHiB9RRM3ZEjiRdU1gbI + 95YalUolNSdeFoiUy2XV4ISNIu666y6Mj483hAc///nPo7e3F2vWrGneQcwjcY7iE088gQMHDmDr1q34 + wAc+gCuuuEJJSym95VjvWq2GZDKJeDyOSCSCzs7OGdEgO0cgMJWKPTk5iUgkosaIeTweRCIR+P1+lZ1Z + LpcRDAYbVH5d8vMx18jQoj7RSg8lMnS4VPZpMzUAZevMpSxWD6npY8OWImUyGcRiMVQqFbjdbjVHkCRz + yQ3DUD3j3/GOd+CBBx5QG7JUKuEzn/kMPvWpTyEUCjXlWOaDJiYm8PTTT+Opp55CPp/Hm970Jrzvfe9T + wEZhIBtw2MXi2RG6UCjg4MGD8Pv96OrqUlEhqQFI6urqwtjYmBIe9AMYhoH29nZVqJXP57Fy5coZjC/t + f4ISqVwuN7QtlwBAppev2ezZpkyVbaYGMEGkZ2KPJD08yI0gNwW96qSlAgaTk5Mq9u12u2eE62QClBxd + RmptbcXb3vY2fOUrX1GvjY6O4rOf/Sw++tGPNi3b7kzp9ddfx1NPPYW9e/eivb0dd999N2688UaVeQdg + xtBOOkmlI07fC06nU2lSx44dg8fjwcqVK1XERw8fd3Z2olQqqSgMh3g4nU5s3rxZAQDNAN3hxzCeBAH+ + h4wc6MCuawKArabalGaRzQQApeMyP9tO/QfQcDLL5bIqAmKD0KVCZHzDmBplpdt8JG5OvifHXlET2LBh + A26++WY888wz6nsvv/wyHnroIfzO7/zOkjpuOyoWi3j++efx2GOP4ejRo7j44ovxN3/zN7j88svV8csu + vHIgh0yZlpGT2e7ZdJNA4Pf70d7ermxvGYolYJim2VCcs2XLFuzevRvAlObm8/lsfQAyC5ARDFl8JG1/ + eTuV2m8YRm3WNxeQmgoAvNDFYtEWACQZhqEq/1hUIWuvbXKrF41yuZzy3nO+4SxqniIZCpMgwOMpFAq4 + /vrrMTw8jNdee01979vf/jbWrVuH6667bkmCwPj4OJ566ins3r0b5XIZN910Ez74wQ+it7d3Rvxfn9Aj + 7X49Fk9GsiOpahMIXnvtNYRCIaxataqh2KylpQXAVFYi+/O5XC60trYqPwATeugHkIyvr2s25pdSXwes + WfZGUyrBmukDGOJJoA9gtpwA4AQAlMvlhh5sfK8ZVKlUMDQ0hFKppCTGqRjfjvgdqq5y4/zGb/wG4vG4 + MikA4F/+5V+watUqrF69esmAwCuvvILHHnsMP/nJT7BixQq8853vxA033KDyMKS0t2u9TQkt05qlKj2X + 86on3sRiMcTjcWzYsEH1W+js7EQqlUIoFFJzA4ApDz1rBYApUO/u7m6w96X05/pqtZlzAO2K2yQIzKIV + ZtAEaqYGcJQSgWmuQGMCkDxJZApOV5V539IfsFge1uHhYaTTaXi9XuXcO9P/ldqAXZz7ne98Jz7/+c8r + oCyVSrjnnntw7733IhKJNA0E8vk89u7di8ceewwDAwO4/PLL8bGPfQyXXXaZkvR2M/h0aa93V5YSW2eg + uRA1Kr/fj2q1iv7+fuTzefT09CAajSozUg7xMIypwSIjIyMApswASn69AIhr5brsbH593fJ47bQZwzCS + Z31BzoCaqQEc4skhAMxmAvCksauLrLbK5/MN1W0n0yLmg1jcQq/+fHUgtgMvPu7p6cHb3/52fO1rX1Pv + jY6O4r777sNHPvKRRemCLGloaAhPPfUUnn76aQDAzTffjA996ENYuXKlraSnY09qbHqF3WzzIM70uHhO + ZJ/GoaEhhMNh+P1+9b4cJ9/X14eXX34ZwEwAkGXlEqRkzF8XWDqQ8X/sKlINw4ijCdQ0APjUpz5V+fCH + P3zMsqw19Xod2WwWgUBgRggIaFTtKAUpLXO53Iw8/4Vghmq1iuPHjzfYhvJ/arUavv/972PLli1Yv379 + Gf0HN76ULqRLLrkEIyMj+OEPf6he+9nPfoavfe1ri+YUfOmll/D444/jxRdfRF9fH97znvfg+uuvh8/n + U9Gc2Rx6OtNLJpIScb6OgwxI0GGIsFKpqP3CpB3ute7ubvX9ycnJhnF10hchfTx6Mxs7SU8fFX1WszTA + GZmXAz9NanYx0AEAayzLQjabRUdHx0kdgLKgRgJAe3u7bRnofFE8Hkc8Hle17XYqqdPpRH9/Px544AGE + QiFceuml2LZtGy699FI1unyuJCWK/K/bb78dQ0NDDd2EH3nkkQan4HwDQS6Xw7PPPotHH30UIyMjuOaa + a/DJT34SF154IQDMYPhKpdLQUUdPgtHt5bOV9Ccj2X2HzyVJDQAAOjo61HvpdFpJf+49Mr+U4nb5Bvxt + XSuQ58TGBDhydkd7ZtRUALAsa79lWbcCU80w9AIgSVTnpMPI7XarTjcLYQLUajUMDAyo7sOz5XHzP+++ + +27s3r0bmUwGe/fuxd69ewFMbayLL74Yl112GbZt23bSNFYeK3PHJRCYpol3v/vduO+++zAxcaJm5HOf + +xx6e3tVd+H5YKb+/n488cQTeOaZZ+ByuXDbbbfh9ttvVyAt4/YEAV3a63FxO/V+ITUXea1kZSCJGgAr + ANm/n30C2cWH10EHL53sgI+fkybQLCbbT+bvyOdOzdYAXgamGCiVSjUMZdBBgOjrcDhUd1e32410Om3L + lGe7sbLZLAYGBlSt+mxOPm54y7LQ09ODnTt34kc/+lHDZ2KxGJ555hkV0+/t7cWOHTtw8cUXY8uWLbYT + gqTNKPMEAOC9730v7rvvPuXBLpVKuPfee3HPPfeoSclncvz1eh3/8z//g8ceewwvv/wy1q1bhz/6oz/C + tddeq9Jw5RRk3ku1l2PepMTkewsp7e3I6XSiUqmoY9P/1+12K42F62ppaVFp2NlsFpFIpIHxZVRC7k+7 + /SoTf+xMIY2e0V9YDGq2BvASTxoBYLY8AG4mt9uNyclJ9PT0qAvI9/UCkDOl8fFxJJNJ1aTC5mLNIILX + XXfdNQMAdBocHMTg4CAeffRRAFONK6+44gps3boVW7ZsURNkdBDg5rvgggvwW7/1W/jqV7+qfnN4eBif + +9zn8OEPf3jGFKJTUTqdxp49e/Cd73wHsVgMN954I+69915s2bJFMToz6PTaDckYupo81/DdQpF+DvR1 + sDmI3G+RSEQBQD6fb5D+upOS39MHigBoOB/8jNRepdAyDKPk9XqzC3MWTk5NBYBPfepT+z784Q/XLMty + pNNp277sUmqwv1o2m1VRARbSyJbO/PzpUr1eV46+lpaWOXvXuc5arYbVq1dj27Zt+OUvfznn/z1w4ECD + Xb9jxw5s374dF154ITZv3tyQJ8Bj27lzJwYHB/Hss8+q7+3btw+f+cxn8Ju/+ZtYu3btKZugHDp0CN// + /vfxzDPPwO/3484778Stt96K1tZW1T5Lpuby/Eomt3OMnUnobiFI70pk57eRqjkANT0YmNKsdKlvB2j6 + VCEp5cnosl+gboqYptm0abHNNgEA4EUAVwEn+uHJKSoknlSv14tUKgUAqoNMPB5HT09Pg701F6ktqVQq + 4fjx4yq8N9fv20mD97///Thw4ACOHj2Kw4cP4+DBgw2z4E5FL730El566SUAU2mul112GS666CJs375d + NQw1DANvf/vbMTw8jGPHjql6g9dffx0f//jHEQgE8O53vxtvetObGn67Wq3iJz/5Cb773e/ilVdewebN + m/Fnf/ZnuPbaa5VNTGmve/EZTtNt4mZL+tnoVGtiMpnUAGSxFbtL24UnSTJqRSbnXpWDQfk5Oz+SYRhN + mxG3FADgBcuyrrIsC2NjY+jt7Z11KAM9/0wGYmltOp1GX1+f+uzpOgIzmQyGhoYQDAbV/LbT2cxUhVnX + HwwGVTjw5ptvhmVZ6O/vx/Hjx3HkyBEcOnQIuVxuTr/NnPrnn38ewJSKeumll2LLli3YsGEDdu7c2ZAl + SMrlcvjCF74At9uNnTt3Ip1O44knnsB3v/tdpFIpvPnNb8Z73/tebNiwQan5xWJxhl1vp95LpictNeYn + nczhyKiSJJpfAFStiZ3zUjqsdd8VNSP6rKTZZGdSGobx6Lwf+Byp6QBgWdYPDMP4EwBqgONsvgAymdfr + xeTkJKLRKDweDzKZjLpQ8rtz2ZSTk5MYGxtDJBJRPe5Pl7ghCFCymo3rWbt2LdauXYtdu3YBmPIzHD58 + GMeOHcPBgwcbvPono1QqhWeffRbPPvssTNM85YjxBx98ED/60Y+wd+9eRCIR3HXXXbjtttsQCoWUmi8n + GUtHlS7x5ytJZ7FIX58dAOj7THaNZtfl2YCOe1XPcGTSkJT23A8EBUEWgIfP8lDPmJoOAACe40WIx+Mz + AECecDJYIBDA+Pg4Wltb4fF4YFlTLZ5o0wFzMwMSiQSSyeRZMb8kh8PRsIFcLlfDxpBM1t3dja6uLlxz + zTUAphxxx44dw5EjR3DgwAEMDw+f8v90W9KOCoUCjh07hr/6q7/C1VdfrWLfkvFJMtJix/TS3FnqzA+c + GgCkJCfJGn8CgP5d3eSTuRDUBmXPwGq1qpzVjJKI35pY7D6AkpoOAPfcc0/8ox/96GsAtlYqFUxMTKgJ + KnaOQNr9bCtNQIjFYli5cmVDPsDJNuno6CgymYxqyTUfG5q/wdgxQ0x26bG64ygajSIajeLSSy9V9RH9 + /f04duwYjh49autHmOuab7rpJlx55ZUz/ptaCxl9No+3/n/nAvMDjVl5s8XudZLMyfOtH7dkfruKRgoC + gomcxmTTvejnZ3mYZ0VNBwAAqNfre0zT3GpZFoaGhlSvfJlGSWIkgMkarPFOpVLo7e2VvzkrCAwPD6NQ + KKjW0PPJ/NJbLOvF7W6UGNxA8j2n04lt27Zh69atAKacd8eOHUN/fz+OHDmCw4cPK6lyKvL5fA3xbq5N + eqvnOxd/qdDJfACzZZ3O9n39u7LWgYVFFFLsWQFAnXv6BSSZpvnNszvCs6MlAQAAvgvgT4CptlEyPVNn + YtOcGiYRDAYxPDyMdevWwev1IpFINFQEAvZmALvwRiKReWN+Sfw9CVx2hU6680hqClJj4GPLsrBlyxZs + 2rRJgVt/fz/+/d//fdZ0VGBKpWVb7dky2nSn3rnO9CS5d2YL382F7JhfB3KCOAFATg4iAEhQ4BIAfPEs + DvGsaUkAgGVZz1mWVbEsyxWLxVSbbJ5gedKkHyCRSOCCCy6Ax+NBIBBAPB5HR0eH7Xw4YMrxxqEQp2ov + fbY0Wxx8rqAgPce66s7nGzduxB133IHHH3981nW87W1vQ3t7+0kl/RuF4XWSEt7OH8QJPiej2c4NrwMz + I2VREScG0ynNzkMyAjBtKhz1er2nboi5gLQkAOCee+4pfuxjH3vKsqy7LMtCLBZDJBKxdQYahqEAYHR0 + VHldCQg0H4BGhJ+YmEA6nVbM36xN//+39+VBcp3Vvb/bfXum9+7pZXr21dosL3Ik27EMoerJBmzrGQOu + glc8qHqVOCkW8yrYYPDDgYTgsDwSqMRAkkreIxBTRTBPXoKwZRmBbEuyxpKsxRp5ZiSNZl9637d73x89 + 5+vvfn17tHt67Pur+qr329s95zvL75zDv6+eCSoqBlp6VoKiKLjnnnvgdDqxY8cOlh4FKjv//fffj7vv + vrsmdafn178TcT4LgHZs/n6+QS2fEuSPCWiDfzQQRFEUTS9BAMw90CMAmc3mf78y3/TS0RAKAADK5fKT + ZrN5O1Chyvb39+vyAYCqG2C329k0XavVimg0yrQ6CX+5XJlgG4lEmPBfbrT/SqGe8Ikcc/5SZEsqioLt + 27fjPe95Dw4dOoSZmRl0dnZi8+bNCAaDuv78O1noefBNY/XcPeoNyN/PB1rrZZF44afuwrTpWCwWVqci + SRIb4kppQYApJgXAd6/k970UNIwCAJcOnJ6eRiqVYoMXRFYgRVldLhemp6fR19fH3IC5uTm0tbUxBRCP + x7G4uMhSho0i/MthOddBLC4h2Gw23HPPPbpm/btF4EXwFqBeFiCXy9UoAGrNDmhpwQTeTaPdn+80TDwV + SgFTw1uRAGQ2m99YKf4/j4aRhscff3zCbDY/A1R+5IWFBU3enIckVXjxTqcTqVQKpVKJuQHJZFJTq/3G + G2+gubmZBWDEnPZqWXxzCQrgiT309Mpv9fL474bFp/Dq1SnQGDB+U+AVgDhXUjT/8/k88vk841QQVZ38 + f6JVS5KkoQUDgMlkeuwqiNFFo5EsAJRKpf9jNpvvVVUVExMTGBgYYD+sXjaASnVPnz6NdevWwWazIZvN + IpfLQZZlHDt2jHURutA88GoEf2K9U7/jxeJ85j8A1syVVwDUFBSotQBo9+f9flIAiqIw4ScyGJn//BQh + ADCZTHNWq7V+5PZtRMNYAEt4WZKkHFAh6kQikRriCi2TycQack5MTDDzy+v1IpfLIZ1OI5vNslbPF1OM + sxpBu9q7Afl8HsePH8fLL7+Mt956S/e/5QfO1sv40DgvXgFQoRlQqbsgkIKlDEyxWEQ+n0cul2OBQyKp + UZERtbsnSjWdu2az+QeX9wtcOTSUBfDNb35z8Wtf+9q/q6r6x2QFBIPBmhgAUM0GuN1uzM7OYm5uDqFQ + CDabjSkLv9/PIuORSAShUGglvpaBK4jx8XF85zvfQbFYZDP92tvbcd9992l6+vEkqXpZH5rmyz8WjVab + 87a0tLDrvO9PMx3J2iTSms1mYzMrKDhIPSzISjOZTFmbzfY3V/p3uVQ0mgUARVH+ja5PT09rWjfrWQE2 + mw0+nw+jo6OQpGorKovFgra2NvbnJhKJixpDbqDxUCqV8L3vfQ+pVAputxterxctLS0ol8t45plnNP47 + n87TswCInMPX7KuqyoqyJEliQ0T43Z/8elIA/Jhxm82mqU0plUpsrBmds7Isr1jhjx4aTgF84xvf+L0s + y8dVtdIodH5+vm4wEKhUb7ndbiQSCaRSKU3AzG63w263M+0bjUZXPDhlrEtfJ0+exNTUFJqbm1kamBq1 + mkwmvPHGG+y/pqg8X5fPr0QiwfL1pABisRg7r/gGofzuXywWmQVAdHQ6Dyn6T0qCn/OwtGHlJUn6n1dT + fi4WDacAAKBUKv0NUPnRxsbG6pYIS1Ilwut0OtHS0oITJ07U/NGtra3sejwe15A/jLW6Fil4ntVI1l5T + UxNT8IVCgb2GH7nGr3A4zNp+S1LFSlxYWGDnVkdHBwBo+CQk2NlsFul0mo0RM5vNzPw3mUwsTkC7P0GW + 5X9shNQfj4aKARAURdljNpvTqqo6ZmdnMTs7i87OTl02F/3JXq8XY2NjyOVysNls7HG73Q6bzYZcLgeg + 4uPRmCgDqwu9vb2aXTifz7OIO7HwJEli/zWAum3REokEbDabJjfPl2CHQiEN2Yr3/TOZDDKZDHK5HHtf + u93OxpaXSiXGVZEk5vunbDZbQ+3+QINaAH/1V381rarqj4GKFTAxMVG3SQgAFgz0er04fvx4jbbnBT4W + izHz0Fira/X09OCDH/wgstksUqkUUqkUc/2SySTWr19fYwGQCyguGijD79CxWIwpC36YKTH+SPhTqRRT + AJSNohJwclfpNkGW5S9eNYG5DDSkAgAARVH+r7ok7efOnUM4HNaMmBL7Bdjtdvj9fkxOTmp2AACs3zv9 + uXottAysDvzpn/4p7rjjDsTjcUSjUUQiEaRSKWzbtg29vb0s+g6A+f8icrkcyuVyDTOUtwDa29s1jD8K + +qXTabZUVWW7PwX/aMYAH/mXZfmozWb78dX/dS4eDekCAMDXv/71448//vi/qKr6J1T66vf7dbvgUK7V + 5XLB5/Ph9ddfx+233655TmtrKyYmJgBU+r2n02ldqqeBxobFYsEDDzyAj3zkIxgZGYHD4UBfXx9r5kmD + YoBaJh9henqamezkAuTzedYO3Gazoa2tTUP3JW5JMplEKpViWQar1cpGwtOocdr9KfBnNpvvvNq/y6Wi + YRUAAJRKpX8xm81/AgBnz55FX18fi87qjXlyOBzw+/0YGRlBOp2G0+lkjzscDgSDQRbomZ+fR39/PztZ + DKwuBAIBBAKBmvv5VCB1ShaxsLDACDuEqakpdp0YqHzEn0x/UgClUollIvhZgzabTZN2lGX5YavV2rAm + Z8O6AADwF3/xF/vNZvNPye8fHx/XjKDiQVaA2+1GMBjEgQMHavw+n8/HTLNisYhwOLzifq2xrtwiX12S + JJYG1nteNBrVTAgGKhsMUNlIOjs7NVH/dDrNhD+ZTLIqQnItqREslQIT60+W5ddsNts/vK1Cc5FoaAUA + AKVS6e9J4MfHxzX0YL2AoMPhgM/nQyKRwOTkpOaPN5vNjA1IJwIfMDLW6l58q3V+iCu/wuEwK9rhrcgz + Z84wZbBhwwa2+1PEP5FIIJFIMFo50X5pMjIfCARApv+2qykbVwINrwC++tWvHpRl+WekBMbGxmp61/OQ + ZRlerxehUAgHDx6safvkcrmYb6iqlVkEescxsLpAxDEC7/7xGB8fh8vl0rTnSqfTmJycBFA5fzo7OzWm + fyKRQDweRyKRYAQf8v2JZEQxBYLJZHrSarVe2PCHFUTDKwAAKBaLf0fXZ2dnNexAMSMAVHw/v98Pi8WC + Y8eO1ewCxBmXJAnZbBaRSGTFdy9jXd6iGX+SVK3J13vezMwMHA6Hpj6AhB8ANm7cyFJ+oulP70EdqajZ + KlGAuZ6K6R/96EefB9DwAaZVoQAeffTRQ1RBpaoqqwAThZ9vHuJ2uxEKhTA8PMwGh9Cy2Wxob29nxw+H + w5ox48ZafSuRSLD/0+126z5ndnYWJpMJDodDk00aGRlh19euXctSfqlUCvF4HLFYDMlkkhX3OBwOZkVa + LBY4nU6+ZL187ty5Tzz88MNlVOSroZXAqlAAAFAsFr8tSVISqJRsnj17VmMB8CAihs/nQyAQwO9///ua + 47W0tGiixFNTU0ax0CpFNptlaTlJkjT1D7UwAAAgAElEQVTz/XiMjY3B6/Vq/P9isaghj4VCISb8iUQC + sViMmf6SJLH6A2Kb0nlELNXx8fEvbty48VVUMmyGArhS+PKXvzyjquqXSNhPnTrFRorrWQJAxQ8MBoPI + 5XI4efJkzTHb29vZiVAuly9oGo+BxgNfw08VfCLy+Tzm5uY08x+BivlPin9wcBBNTU2anT8ejyOdTjPi + kN1uh8vlgqIo8Pv98Hg8bPefmZn5++uuu+7/ATAvLVIADasEVo0CAICHHnrox7IsD5OQj46OsmYQohVA + kdqWlhZ0dHTg0KFDmhMFqPDEOzs7AVTjAeFw+O35MgauCKgmn1Av+HfixAm43W44nU6N+c/v/uvXr0c6 + nWZBv2g0WtNyjiZHUykycQnm5ub+ee3atU8sHZaE3oQGtwJWlQIAgGKx+D9IASwsLGBubk4zxppf5XIZ + drsdgUAAwWAQu3btYuObaTkcDk0jiXA4jEwms+I+rbEubPEl3j6fj+X2+QVU0nwtLS2w2+3M6otEIjhx + 4gSACrHM4/EgmUwiGo0iGo0iHo8zvr/D4YDH42GXgUCAFSLNzMz8ZM2aNd8HQD6kJKyGxapTAA899NB+ + i8XyQxLykydPMl62HjlIVVU4nU60tbVBlmXs3bu35phiPGB6erqmnsBA44ECc0AlfVdvUvLY2BhrH8d3 + ABoeHgZQsf7WrFmDcrmMWCzGFrEKqdrU5/PB7XYjEAiw82V2dvYX69at+ztUpvwCQBmViT+AdvdvSEWw + 6hQAABQKhb82m81hqtQSuQH8IvPN6/Wio6MDU1NTeOutt2p2ifb2dmYaKoqCqakpxiozVuMtVVVZ9R7t + /vU6IA8PD8Pn8zHOPlBxEU+dOsWUQSgUQjQaZROj0+k0CyZ7vV60tbXB6XQiEAgwktHs7Oyz69at+1tU + 5UitsxoWq1IB/Pmf//lMuVz+KFDZ5efn59mUID1SD/G2g8Egurq6sG/fPk33F6AaD6ATolQqYXJy8h3f + THS1IhaLMZKXxWKpW9g1OTmJYrEIt9ut6Q0wNTXF4j1UZEamfyqVYkE/2jioloTSf7Ozs8+uX7/+u6j6 + +bwSKGMVCD+wShUAADz44IO/M5vNTwAVJXDq1CkkEom6DMFSqQSHw4FQKIRQKIQXXnihRrhtNhu6u7vZ + 7UKhwHoRGGgcZLNZTd6fb94pYmhoCIFAgOXqCQcPHgRQMf/b2toQiURYaTFV9bW0tKCzsxNerxfBYJC1 + Hpubm9uxYcMGmuojoRLxF9N+vCvQsFi1CgAA/uzP/uxBSZKmgSpBKJvN6pKE6LbL5WLm/ksvvVRzTLvd + rhkznsvlMDU1ZdCFGwSKomgyNW63u27ZL7WTa2lpYe26gMruf+7cOUiSxFp4RyIRFlMg4e/u7obf72dm + v8lkwuzs7C+XhJ+EmxQALR4q97yGPIFWtQIAgFwut52EM51OM2GtZwXIsoyWlhZ0dXVhYWEBr776as3z + nE6nhimYyWQwNTVlWAINAGoMA1TrPvRQLpdx8OBBtLa2stQfmf9DQ0PseRT555l+Xq8Xvb29rOSYhH9y + cvLJa6+9lmjpJNwU6ScrQEbVCmj4OID+9MNVhJ07d87fc889CyaT6W6TyYRMJsMIG3ool8use6vZbMbI + yIimSpBAbDGaFFMsFpHNZuFyudiJZODtBRF0CMFgsO7Qj4MHD6JQKKCzs5ORdSRJwuTkJA4cOKAZLpNO + p9nO7/f70d/fj2AwyITfbDZjfHz8J5s2bfoxKkKvoFao6XZpaRWXLht611j1CgCAJMvy/aFQ6HaiZMZi + MVbxRZFgHlS+SZ1l33zzTdZMhAc1jaQy01KphHQ6DZfLtSqGjL6TkMvlNF17vV5vXcpvMpnEvn370N3d + rRkKq6oqnn/+eZY2bm5uRi6XY+O7fD4f+vv70draqhH+0dHRH958880/QXU3V1C7s9MJoaCqBMpLq2Gx + 6hXAJz7xiU8HAoFvFotF+P1+NhMgFouxvK8IvmqQhmkeOXIEra2tNblkKvmkUtNyuYxkMlkTVDJw9VAq + lTA3N8dcsObmZk3ffhE7d+7UpO4o9TcyMoITJ06w/19VVRSLRTQ3N8Pv92NgYEAUfvXIkSPfeO973/sU + qmY9v/vz/j1v9pOVUIK+smgYrOoz+DOf+cx/aWtrezIQCJicTidyuRzbFUwmE5LJJLxer+5gUJoKQ+6A + JEk4fPgwenp6atwHGvhIVYWKoiCVSrGuMgauHhRFwczMDMvYmM1mBIPBusr32LFjmJ+fR3d3N1paWljZ + byqVwvPPP6/pKFUqlZgyGRgYEM3+0vPPP//ghz70od9xh1e5S71UH8UD6HGyAvRchobAqlUAX/rSl65v + b29/vquryxYMBuFyudhOTRFfVVWRyWTgdrt1TXYa6UTtoRVFwaFDh9DX1wer1ap5Lk1+SSaTAConZjKZ + hMViYZRQA1cWxPHgx3y1tbXV/b2j0Sj27t2Lnp4eBINBTdXfwYMHWfMXRVFYHX8oFMLg4CCCwSCCwSBZ + hdmf/vSnn3rggQeO1vlofByABJu4/7ylQC5Aw1oBq1IBPProo51tbW17BgYGgpSqoRpvRVGQzWaZ30d9 + 4ihaLFoCfBtni8WCYrGIgwcPorOzs6awpKmpCTabjeWgqQsN1RwYwcErB0VRMD8/r6Fkt7a2aoa+8CiX + y3j22Wfh9/vR3t4Ot9vNIv+zs7Ms8KeqKgqFApqbm9He3o5rrrmGRfuXFEb0K1/5ykcef/zxCWiFlhde + Emgx18/z/+m1fDzAUACXi0cffdTW2tq6e3BwcG1PTw9aW1vh8XhYwI4UQD6fZ5YAzW+vxxajMU7Nzc2s + wePQ0BDa2tpqYgLEOqPe8kCl1DSTybB0kYHLg6IomJubY3P3ADDTvB727NmDYrGInp4ejemfTqfx4osv + Mqo4CX9XVxcGBgbg9/vh9/upr/+5j3/84x956qmnKNWwnMCKVgBpf5ERKFoBDYVVpQC+8pWvmP1+/38M + Dg6+r7u7mwk/+eImk4mZd8lkEuVymRVt8A0dAH1LoLm5mSkBSZLw+uuvw+fz1TDNKFdMPeOBSqAqmUyy + gZMGLg2KomB2dlZj9hOTrx6OHj2KsbEx9PX1sZ2cFPGBAwcQDoeZ6W82m9HZ2cme6/P5YLFYUC6Xj7a3 + t3/szJkzedTn8ks6j/E7O18CDFTdAN4CaCglsKoUwN133/3E4ODgf+eFnzqxks/PD3OIRCJoamrSzIxT + VVWXI0CvJSVALsThw4fhcDh0e9A7nU5YLBaWJlRVlcUI+ElEBi4MpVIJs7OzrMIPOL/wT05O4pVXXkF/ + fz9CoRAr95UkCaOjozh58qSGGNbT04Pu7m4Eg0FWz59KpXb39vZ+DlohracE+Ko/ej5f/WeC1m0oo8IJ + aEgrYNUogL/8y798aHBw8H/19vYyH48P9hHVl8w8Gh45MzMDl8vFlEA+n4eiKLo+u54SkGUZb7zxBmRZ + 1vQNIBDpiHLLAFhLKYorXEnMzs6yFOc7CZlMhvV2IJxP+MPhMHbu3Inu7m60t7fD4/Ewvz8ajeKVV17R + UMH7+vrQ3t6O1tZWtLS0QJZlTE5O/mLjxo1/g1pTXS/QJ6b/aIcX+QB8SpCOSynBhiIGNaICEJspmB57 + 7LEPDQwM/HNfX5+JhJ9IP/Tn8nPcyA3I5/PI5XIYHx9n1oLJZEI+n2eBO0DrDlBumFJ/ZNKfPHkS0WgU + vb29NYqDBpKUy2Xmt1KWgCoRLzc2MDo6ikceeQS//OUvsXfvXhw4cAAdHR3L5sNXC2jGH0/fDgaDywp/ + Op3G008/jVAohK6uLni9Xqbks9ksXnnlFRQKBXZ+UI4/FAoRM1A9fPjwP773ve/9CbRmumgFiLs2fz+/ + gNr6f3oeHwhsKCugERUA30fN/Mgjj/xhf3//0319fU0dHR2sqwsJlKIoKJVKbJHwkxWQzWaRyWQwNjbG + XitJlclApVKpbkyACCK0rFYrJicncfz4cQwMDNRQUE0mE+s3R+2jgUpFYSKRYOnGS0EqlcLnPvc5xmug + ne7EiRNYs2YNPB7PJR13pVEul7GwsKDp5y/LMkKhUN1oP1CxFnbs2AGPx8OCfnyfv8OHD7OCIUVR0NXV + hUAggFAoRNkB5de//vW377///heh3aFFJcALN28FiEpAjwtAzy0Lq6HqAxpNAVAQxQxAfuCBB3oGBgZe + HBgY8HR1dbGmDpTbpV2fhJkEn2IAJPw0DPTNN99kXV1ICRSLxbp1A4VCgaX+SBFkMhkcOHCAxSBE0Khy + AMwaUFUV6XSapScvljy0e/duvPTSS3C73fB4PHC5XIyhGA6HcdNNN13U8RoByWQS8/PzGn+fyrWXc5sy + mQyeeuopOJ1O9PT0wO/3a/L9R48exeTkJHMJ/X4/Ojo6GCvQZDKlv/vd7z7ypS996TiqAkx+OnH49SL3 + ogLg3QM9F0BUErxyaRg3YKVpbHzO1CQsuaen5wednZ2BUCgEr9erYd7xOz8JMr/zF4tFTUlwqVRCNptV + /umf/mnsk5/8pHP9+vXtQOWEmp+fZ00hREsgnU7Dbrcz6i9ZAzt37sQNN9yA2267reZLmc1mBAIB2O12 + LC4usoh2NpvFxMQEnE4nG1xyITh79izMZjNMJhNkWYYsy2yy7WrrZFwoFBAOhzUpPqDSlKMet5+QTCax + Y8cOjfDzE37GxsbYBGhJkuB2u1m03263o1gsnrvnnnu+fPToUZogKrqbJLCikCqoBvfEPL8YIyijupHx + ikLvvVYcK6kA+B+DWiiblj6T/NGPfrQ3EAh8kHZs0vLk09HOT4v8fZrhTlNcc7kc8vl8eXJy8vhrr712 + LBKJ4PXXX2/69re/fcumTZv6KDswNzeHQCCgmRhDSKfTsFqtTAGRVTA8PIzp6Wls375d17y32+3o6elB + PB7XFLKQReJ0OlnOejkEAgFNnINiHTSlZjVAURTE4/GazsxUhCMyL0WEw2Hs2LEDgUCA1enzO/+5c+cw + MjLCir9cLhfWrl3LlMTMzMxvN23a9ATqC55I9OGLePjcvhjM0bMM+MAgXzJs0nn9imIlXQCxbbIZQNPS + av7ABz7wh/39/R+l6C5P9OHNfZrflslkkEwmWUvnWCyGaDSqnjx58sh//ud//mpoaOjNbDbLfLAXX3xx + Yu3atc3d3d0B6jGXyWTQ1NSkawmQwFFwkAZDxmIxDA0NwePxwOfz6X5Rq9XKyoiJjwBU4wP5fB6yLNe1 + CLq6uvDMM89AURRWvESfacuWLVizZs3l/xtXCYqiIBaLYXFxsabRaiAQYJbXcjh9+jR+/etfIxQKobu7 + mzXlpHTf/Pw8K/Kh/+i6666jSkBlz549P7zjjjv+gzukmMfnS3hFF4B/zXKXdF1CrVLg4wwNFQdYSQVA + gk8+fxMAy9KlbcuWLQO9vb0f8nq9cDgcrGCHhJ92/FQqpZniEovFEA6H1aNHj775i1/84pldu3Ydj8Vi + +aX34YMxxd/+9rfjNpsts3Hjxl4SykwmA5PJpGsJkNVBSoAmwgLAkSNHMDExgd7eXl1BNpvNsNvtcDgc + LAtBIOJSMplkuzqfNbBarbj++uuxf/9+ZDIZlq7s6+vDxz72sYasShQFn4/wW63WZWm9PPbu3YvXXnuN + 5e+pHTcv/MePHwcAJvzXXnstKZbMt771rUcfeuihN4TD8rl88s8pBkBLL7jHE37okg/4iZe8AuBJQQ2T + CVgppgpPm9Ts/ACsqCiAtk9/+tO7+vr6TKFQiNX3l8tlzc5PwxtpfPPx48fHXnzxxUPDw8NhVP7UPCo/ + OplnZG3QZ2i69957ux988MH7TCYTkySbzQav16u7OxGjUJZl5PN5FtCamZlBNBrFbbfddt7AXKFQYBNn + xWMDYBNoePprKpXCG2+8gfn5eVxzzTW4/vrrL+jHfjtBHAhSVDyamppYC/bzIZ/P4+mnn0Ymk0FPTw+j + ZfM+/+TkJGv7RYVdGzduhNfrRSqVevN973vfN6empoqoL5QlVM6PPIAMgByA7NJt/nV6gz7oNkEsDeYf + 462LAqpWxopbASupAPg2SrT7WwHYATgA2L/1rW99fXBw8A6q029qamLFHCT8ZPIfO3Zs8oUXXjg2PDwc + ReVHppVH5Y8lzVuEVoObAZg3b97c9thjj33M5XKx0L7JZGK+ph4oO1Aul5FOpxGLxTA/P4/JyUnY7Xbc + dddddd0CAvnGxBkQYTKZ2Dw6Pv3ZSKBaCCqMEnGhfj5hbm4Ozz77LFwuF7q6usBXe9L3Hx8fx7lz51hs + xGKxYMOGDfB6vcr+/fv/7d577/0N9IN0vJ/OK4A8KsKfW7pegLbvX72YlXhcPU4Ab1kYCgBa058sAOvS + sqGiBOybNm1q/9SnPvW3HR0dXR6Phwo2mAJIJpMYHh6ee/rpp4+dPHkygeqPm1u6TtqcbouMLPpDZVSs + D9sPf/jDj65bt24j/2GdTmfdkmJZluFyudjnSqVSCIfDmJ6exvz8PK677jps3br1giL+1O2WqMV64EdT + X6hAXWmUy2XkcjkWdK03VLW5uZk15LzQ4+7duxfDw8Po6OhAR0cH/H4/s7bIOhodHcX8/Dzb+R0OB9au + XQur1Rr57Gc/+7Vf/epXi6gfpa+nAOh84RWAGAjk3VZSBIBW+HmlQaD3o/OzYWoDGkkBkPlPVgApgY77 + 7rvvMx0dHbdSi68lQVOHhoYO/+xnPzsBbRMG+gOz3KI/tACt+UcgF8QOwPG5z33u1g9/+MPbl44LVVVh + Npvr7mKSJLGZ8+VyGZlMBvF4HIuLi5ienkYqlcLNN9+MzZs3X9AOTizCRCKhyZOLMJlMrHiJGIt6sYvL + AWUcKO6ynMAD1XHZF9sx6fTp09i9ezebz9Da2gqv16vx9/P5PM6cOcNmAiiKAq/Xiw0bNmBmZmbfjTfe + +A9YnsvPKwB+RyZLUVzkOuoJv9gCXLQARAXAxxmKaJAeASvtAlDaj1wAUQnY6Pb27dv/oKura6Pdbu9I + JpP5oaGh04cPH06i2o9dReXHJT8uDe3uz2tfnsHFf4YmAE4ArltuuaX7kUce+ZjX620FoBkzRgMiRVCp + MJGMyC2gGYalUgm33norrr/++gs25UulEjKZDCM1XUh7crPZXKMMiEPAf1ZRuRSLRZZmJTLVhbwfDc60 + 2+0XzXbMZDLYtWsXpqam0NXVhVAohJaWFlZoRb9zMpnE6Ogo41QoioJQKITe3t7Mz372s7//whe+cAz1 + hZ9XACL5hz83eOGnc0XM4eul8vjUnx7JRyQbNUxdwEqWq/FmlAVVM5wWKYLmpcdtS9edS9edS4/LS8dQ + oPXlsqj8sTlUAzB8VVYJ1T/VsnQMcj8cANwAnI8++ugfbdu27f2qqkqkBCg2oBfMogCh1WplAct0Oo1I + JILFxUWmCDZv3ozNmzdfdASfzO5MJlNDpuE/w6XgQl9HtGbKglxKwVM+n8fQ0BCOHDkCn8+H9vZ2BAIB + uFwuVuFJn2dmZoa1e6e+gN3d3WqpVHr1pptu+jH0g3yi0NN1MSLPB+fywmW9Qh8x+Mcf90IUwHLK4m3F + SioAMaBCiqAZVZeATw1aUQ0UNqNqHVhQTfGR0JM2J+HnzT29Ag5SAMwNAOBCRck4b7/99s4vfOELH3e7 + 3e38sBGn08myEyJkWWYNKUulEnK5HNLpNJs/t7i4iEwmg+uuuw5btmxZtvClHsTKR+JGXOwQk+UEn5iH + 1Prscvsd5HI57N+/H8eOHYPL5UJbWxuCwSBjevKBvnw+j7NnzyKVSrHfXJZl9Pb2Jr7//e9/54knnjgH + fRO/ngLgd3+9/D8JP13n23rrpf7o+GQp6Ak1/55id6AVTwWutAIAtPRf3hrgL0kJ8PECUgY0iIH+SPrj + 8tx1vhKLAjsUBAS0PASyPtxYUgBYyko8/PDDW++8887/CsDMKwK3281KjkVQ7p9y95S+XCIqYWFhAZFI + BL29vbjpppvQ399/WT8qAFYQRSY9AMYgJFAffB4kfJIkMcbjlYonZDIZvPrqqzh58iRcLhdCoRD8fj/c + bjecTiejNtP7xWIxnD17VkPnbmlpUWOx2K73v//9P0ftzl5vx6+3+/NxANokCsLSUwD8dTH4V692QCQC + NYT/D6ysAuDfX48OTAFCEnCZW3z6UEy38L4+L/wStKaXXkrHjKrlYUfFCnCAUwKbNm1qffjhh/9bIBAY + FCcR85V6mi+5FCS02WxMEVDqLJlMIh6PIxwOs84169evx4033qjbhGS1YXx8HIcOHcLExARaWloY+8/t + drPAKW/uZzIZzMzMaCjDS0p2/POf//z/fu2116h0UNxt6wk9L2y8mc6TwkjYeeuRZwTWg3hMPYaf+F4N + Y/4DK68ACDy5AqgKvxh9JQKPzN3H+2O8tqWIP/05Jmg5APQ+BAomktXRjKoSYApg6dL6yU9+8tr77rvv + wzabrZXvSUDxAb1AIeX0KXZA0XW+foEsg2g0CofDgYGBAWzYsEEzqqzRsbi4iKNHj2JkZASlUonN16Nh + HsTs5AW/WCyyKc9A1S2RZTn/3HPP/fh73/veUdTf6YH6Qs8LP38+8NV5fIyItxyXUwDi7i++Lz2Htzoa + avcHGkcBiH6VXqqF7hcv+cos/rpYzqmgKvBl7vX8e/DHJU6CDYIVwN1v/exnP7vlzjvv/JAsyx5SAtR7 + jjraiK4BbxEAVfOcpzdTGjAWiyEej8NkMqGvrw89PT0YGBi4pJjB1UIul8Pp06cZOSeXy8Hr9aKlpQVe + r5ft9lTCzAs+DeacnJxEqVRi90uShOHh4d9/9atf/Xk8HicfG9D62vVSfPxtfofW2/1FBcBnBfQ6+YqK + RU8J1Ht/8XusOBpFAfDgyyV5F6He84DqDl+GtiEj76vxx+J3DnIDeEVBbgZlJOzccoBTAEvL9sUvfnHr + 1q1bt0uS5OLbkwGVMVZer7dGaEkR8K3NqMSZlAEx7HilkEqlYLPZ0N7ejs7OTrS1taGrq+ttYwmmUilM + TExgfHwcExMTiMfjLCDqcrmYX0/fjXog8D5+oVBALBbD9PQ0K5Ciz7+wsIBDhw7h+eef/8cTJ068jvqC + LloD/H8opvz0MgBiJkBk6vGEh+WCiuL7AbXKgRd+wFAAlw1ROfDFGoR6ARxV534CT/wwoRp0tNVZVu7S + 8uUvf/mPbrnllntVVXXwFgG1JadUl2gVWK1WtkNSTIFvcMqXO5PLwK9cLgePxwOPxwOn04nW1lZGXHI4 + HDWdjZeDoiisz8Ds7CyrroxEIojFYqywyeVyMUGn6kjiApBvT0JPgp9Opxkvolwus6AjFXotLCxgZmYG + s7OzOHLkyHN79+59Buff6RXhfl4oeeHnl6gA9C6XyzCIZj8v/OJn4BVJQ/j+hNWuAHhBFnd7VXhcFPrz + aWCeJkwBRz2iEn8fpSibHnzwwVu3bt16j9lsDpXLZRbNppPe7/ez7kQ8ZFlmNF/aEel1PCuPlAK/aB4C + KQtKDZZKJfZaWZbh8/k0qcJyuYzFxUU2V5GGphLDkBbVPtD9xAOg1CAJPAVB+QxCPB7H/Pw8pqam2PvQ + IivH6XSiWCwikUhgenoaR48ePbxjx44foVYQRYHnBZC/j/e7RcFfzgoQy4GXE34s8956lkpD7PyE1awA + 6kHPErjU5/PsL0pR8qlC3gLgCUyUpmy+//771911113bXS7XmkKhIBN/nS6tVis8Hg/8fj+8Xi8TekmS + mNCJ1gIpBL4rktgghRQFPYesEHouuSeSJDGBp6AlKQESaIvFwhbxAugxWnpTmFOpFGKxGKamppBIJFhX + I17wk8kkstksbDYbOjs70dzcjHg8jqmpKZw6dWrxiSeeeBS1gTxA3/TW8/X1fH4xJy9mjMSUMf9+dP18 + CkjMDFzsefm24J2oAK4GeGuAUpCULiSBbxau0+NNACwej8f66U9/+o82btz4/nK5HCQh5Dv9KIoCv9/P + iDEUMyDOPz+0hAef6+eVAy0+VckLP/tyS/43b47TIqElIeefo4d4PI5IJIKZmRlEIhH2Ov44vGXCWx2h + UAiBQADxeBzT09MYGRnBD37wg89GIpEc9AVNjOyLwl/inqcn3HrCX0Ltbq4XeFxOCdRLCTYcDAVw4RC5 + 4OQakEVQbxGJiRGatm/ffs22bdvucrlc6xVFcfAWAV2qqgqXy4WWlha43W7WEJQsA36e4YWCFAUpBQIJ + NXDxNOJsNssozouLi0ilUkyg+Uv++KIyoc/gdDrR2dmJQqGAqakpjIyM4Oc///lf79+/fwT1hUzM7evt + /PWsADEgWBaOd6GCT5aCntJoaKx0U9DVBvEkFGmkOdTu/qISaHruueeOPvfcc28CkLdt29a/devWW9rb + 22+VJCkAVIREVVXE43FEo1HNju52u1lWwev1wufzMcox74frgYTtUjoIFYtF1n+BeArhcFgj8LR4i4Mf + w07ZAF7w+ak9NHqdCq48Hg/a29s7AJyE/m4vpvj0iD78fyXeXk4xAFr/nQ8mni8QyWedGhqGArhw8Npc + zzQsoSLg1I+grgJAleYs7969+/ju3buHATy5Zs2alm3btv3BmjVr3mM2m/sVRbEA2l2ZovF8qrG5uZlN + w/X5fJBlGYFAgO2+ra2tzHXQE/5isYhwOKzZpefn51mbsnA4zFqlkZDz13nkcjklm82azGYzPB4PY0dS + 0RA/w5FcEj5lWiqV0NzczFKKoVCoA9rCHF4RnE8B1IsDLGclLBfhr+cO6KX3Gn73BwwFcCnQUwS8P1lA + 5XfNoyLspAxEJSCLa2RkJDMyMjIHYBcA87Zt29asW7fu+tbW1vXNzc2dhUJBdwIIVQcqioLx8fEav592 + WLFIiBd43iQXo/R8jp4/HgAUi8VMIpEYm5mZGXvrrbfOJJPJ7ltvvfX+np4eNDU1sd2c0oM8AYgf6EJW + Tj6fZxN8bSj1e6AAAArBSURBVDYbWltbe5d+y3qBvnrWwHLCr6cg+KBfPV+etwjEAJ+CVbLr8zAUwKWD + 1/R0AojBpSIqAp9DNQYgLr6+QXN79+7dR3bv3n186TFzU1OT6ZZbbukfHBxc097efq3FYukG4FdV1cwL + JbkQ5/0CqlozFo1ey6+l+4q5XC6Sz+cXM5nMTDgcnhwZGTl39OjRMLiaCrPZPLthw4b3KooSkmWZ8RDc + bjdr7ErFSsR+5D9DsVhELpdjaUafz9eDigLQC/aJBJ/zKQTRDdBbehaAqATYT1bnctXAUABXBrwZaELV + v6QTzoSqZcALfo3Q69xmq1AomF9++eVjL7/88gkAzywd13TNNdcEurq6OpqammwtLS19kiQ1e73ePrPZ + bJFlWZYkKagoiolXCqqqqko1HVDM5/PzxWKxuLTbq+l0ejKTyYSTyWRkfHx8amxsLCp8V1J8JPwyAEu5 + XDadOnXqucHBwT9WVRUWi4XVP1A6k6L/+XyetXrnsxPpdJoNYXE4HI4tW7Z4hoaGZrF89J+/X+Td8/9F + vazBhfj3QK3iX3VCz8NQAFce/InDm4bEJcijVgHwRUh6wk+36Xl8NsI0OjqaGR0dnVx6bB/3XuCeB+52 + PYo1CQN9fn6RcIikKjqeFRUhaz5y5MibN99885m+vr5+KpAi8hA1VAGgSVWSIlBVlRGZaADLwMBAz9DQ + 0Dhqd+nlhFi0EESFUO81et+dv0/sBbCqYSiAqwsSflIEZA0UoS/cdFuuc12vSpJ/LV/WbIY2dSk2tKhH + g9YLcvEEHJF1Se9ZRIUQZQIgDQ0NPbdhw4YHc7kcIyRRwJAae/A8AJ5foKoqcrkcyIXw+/29AHZDG6HX + CwqKQn2+uAGg/Z56Qk+XF8ogXVUwFMDVgxgsBLS7J5mlRWgFmFcM4m3+fr48mucm6JVN03MArQBTL0X+ + M4t9E/idkQ906fVyoCCadPjw4dHbbrvtaGdn5w3pdBput5spAVmWUS6X2XVeESiKwkZ8EyXa5/MNoBJH + 0RP0ejt5PQuhnm+/nNDz97+jYCiAqw/xxCEh4ncyvpKRF+iamYnCfeISlQivICTU7v585SX/efWCYPxj + ehYApUDpcftLL7307LXXXntdMBg0Ucsvq9WqoR+LHAJSABQgXBomsg71A4HnS9vxfr0h9AIMBfD2QvQn + AW0Ggd+ZJdQqBH73ryf8vAIQrQRRCYgnPH02PROZ//wKqtYD//mauNdJw8PD00eOHNkfCoW28j3/eIEX + LQA+HUlNT51OZ39vb68yPj7OKwFR0FWd+/TMfL3/4l0l9Dwab6jcuxN6wSa9dJZYwcY3OxUr2sR5d2LN + O3+f2BBD7JAjds0V26zzx6PPbwJgCYfD0xs3bnyP2+2WiQtA9GW+kxJd52sWcrkccQNMsizvOHz48Izw + 3fVovOLvdSE7/bsWhgXQWOAzB4DW1OZdBL2Anl5gsJ4FYFp6D34D4C0SvTQYXRetF3DHlqHtwWgaHx+X + hoaG9rS1tX2ACEE8I5B3BXgrgOoFqHmp1+tdB+B11Pry4ucSd3m9zwu8y3b6ejAUQONBLyin1HmuniIQ + lYF4WwwG8qk9MutFsot4H6BNb4K7TnMYJSzRoXfu3PnrG2+88Tafz+d2u92s1wFfCVjPFSgWi1QAtQHa + Lr28m7Lcb1fvcQMwFMBqgF42AajNx/P36wX7xD6K4mv03k9PGdAl/xqeZyCjqkxkAE3hcLhp3759O9vb + 2z/m8Xg0TUHrBQP5xiKKosDlctG8RpFnQffRbf53MQT+PDAUwOqFKABA/cCenttAIHeA5yvoZQbES73j + UQqRBFLGUsOUF1544febN2/e5vP5AmQF0C6vZwHwSkFRFDQ1Nd2IWgEXO0LTZxB/JwN1YAQB35lYLs0l + ptL0CmSWS7WJEH1yPvgmYYndWCgUmpuamnIDAwM30ahzvrkJHwTkm6QUi0Uag+ZwOBz/evLkyTyWJzph + mesGBLw9bWQNrCT0hL4eEUbP/Bd9bXpeWec4QDWOQGXRcQBJANnf/OY3r42MjJwLh8NIJBLI5/OMGqwX + DOTvkyQJLS0tmyH0XkQtbfpCGI8GlmAogHcv6ikAXkEs93wIr+E5AiR4lEbMoDKtubh79+5n5+fnEYlE + kMlk2KhxivyLvQb5WIDJZLoJlZFtfJt2mg/JKwGeH2EogWVgKAADVwpiuo0sgTKq1kBx3759oydOnHiL + twKIIiwGA/kGpCaTCTabbSOqw1k04+OXFm8R8DCsgTowFICBy4Ve+pGf3WiGlrSDXbt27Z6bm1Oj0SjS + 6TSzAkwmE7MA+OAgN514HQAPKlYArwjEidKkBAyBPw+MIKCBy4GYTeCLkajzET/a3QHAOT8/r7a1tQU6 + OztbaXoQPzWIDwbSlKSlgSju/fv3P1MqlXiCU72UphH9vwAYCsDA5ULc/fluyXRphXakmmNhYSFxww03 + 3OB0Ok00JZjKhfkGIcVikfUHSKfT5tnZ2dfn5uaSqG/S1wtyGtCBoQAMXA54KjBftkyCL05TYiuRSFjc + brejt7e3jaoEqWUY31GYLIBMJoNMJoO5ubnTY2NjU6hmJkQuAJ+GFAOahiIQYMQADFwq6gXWqCaAFAK1 + SadzjWIB+V27dh2emJgoRKNRZDIZFItFAKhJA1IMwGw2w+1296I6q5Gi/3pl0vWITwY4GArAwOWAzGs9 + ZcDHBPgCJFaFGIlEUnv27DkyPz+PeDzOqv/4YKDIBXA4HG2oWq56tOfldnmRMPSuh6EADFwp6PnaIr9A + xdLuDyALIPPiiy8eOnPmTIqGjBQKBdaJmAQfAGMHyrJshz5rUWzoyfMRDNSBUQtg4HLA77qioIs9DIgL + IKNCCjIBlUEiv/vd7/Z1dHTc6XA4IMsyHA4HALBBp4VCAYVCAblcDrlcbga1U32pHwHf9luMAYj1DQZg + KAADVwZiYVIJ1d4AeWgzBZS+YwG7PXv2vLZly5bNdrvdR+3CLRYLCoUCkskk4vE44vE4ksmkcvz48edR + USBZbuVQbVYiDvzQ6w9gYAlGFsDApUKszDsfB5+eWzOUU1GUgsViifv9/htVVZVKpRKy2SxSqRQikQgW + FxcxOzuLs2fP7ty1a9cuAClUhT/PLb6bkbj7A4bw18BQAAYuFSL5hi8GEmvy+fQcPzmJtRs7e/bsVHNz + 86Isy9flcjk5lUohGo1ifn4e09PTudOnTz/15JNP/isqwk+1BeLuTy3K9Cb8GsKvAyNAYuByoMfCE5uS + 8tOQLDq3iSfQDMAyODjou+WWW/7Q4/EMqKqqJpPJM6+++urus2fPRlER9jSqQs/3MKQYAO//82O7oXP9 + XQ9DARi4EtDLufPMQDY6DFqykEgcoks+niDOWswtXWahDQaKpcv1+iEY4GAoAANXEiIPQGxUWo+0YxIe + 44/HxwtICZShDfjxQi/u+kYGYBkYCsDA1YLYnIMEnR4T5xSIj/ECy5v2JPQl6PcjAGpbpBmoA0MBGLga + 0IsN6MUKgGoDUUnnOu3eIp+/zB1Lr5ORgQuEoQAMXG3opQP56yT0gFbo+eeIjUr554lpSEMBXAQMBWBg + JaF3/okKQA+GkF8hGDwAAyuNeju3sTkZMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY + MGDAwIXg/wNGXQMUZRIeQQAAAABJRU5ErkJggigAAACAAAAAAAEAAAEAIAAAAAAAAAgBAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AwMDAQoKCgEQEBACFBQUAhUVFQEVFRUCFhYWAhcXFwEWFhYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAYDAwMHCQkJCgYGBgsAAAANAAAAEAAAABAAAAAP + FBQUCxISEggeHh4EEhISAgcHBwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAUAAAAK + AAAAEAAAABcAAAAdAAAAIwAAACsAAAAxAAAAMQAAAC0AAAAlAAAAGgAAAA8FBQUJBwcHBgEBAQMAAAAB + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAIAAAADgAAABcAAAAiAAAALQAAADgAAABIEhISZGJiYruBgYHc + YGBguBYWFl0AAAA1AAAAJQAAABkAAAAPAAAACQAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAABgAAAAwAAAAZ + AAAAJQAAADYAAABHAAAAWwEBAXN6enrhvLy8/8jIyP+urq7/eXl57AsLC1YAAAA7AAAAKgAAABwAAAAR + AAAACAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAHAAAAEQAAACAAAAAyAAAARAAAAF0AAAB6NDQ0sru7u//j4+P/ + 4+Pj/8nJyf+YmJj/Ly8vkwAAAEoAAAA5AAAAKAAAABcAAAAMAAAABQAAAAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAgAAAAS + AAAAIAAAADQAAABJAAAAaQQEBI+Ojo7w29vb/+zs7P/i4uL/ysrK/5ycnP8sLCyPAAAATgAAAD0AAAAr + AAAAGgAAAA4AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAAAA4AAAAZAAAAKgAAAEgAAAByQUFBvcPDw//r6+v/ + 6urq/9zc3P/Dw8P/lpaW/x0dHWoAAABEAAAANQAAACYAAAAXAAAADAAAAAQAAAABAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAD + AQEBCAAAABIAAAAjAAAASgsLC32amprz4ODg/+/v7//l5eX/1tbW/7u7u/+KiorzAgICPwAAADIAAAAl + AAAAGgAAABEAAAAIAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgENDQ0EAAAACgAAACQAAABTUlJSt8nJyf/u7u7/ + 7e3t/9/f3//Pz8//srKy/35+fs0AAAAkAAAAHgAAABUAAAANAAAABwAAAAQAAAACAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAC + BwcHAhYWFgQICAgPAAAANRISEm6lpaX35OTk//Ly8v/o6Oj/2dnZ/8nJyf+rq6v/dnZ2nQAAAA8AAAAM + FBQUCAoKCgUAAAADAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAACAAAAAwAAAAQAAAAGAAAACAAAAAkAAAAK + AAAACgAAAAkAAAAJAAAABwAAAAcAAAAGAAAABgEBAQcGBgYIAAAADgAAACUAAABRYWFhv87Ozv/y8vL/ + 8PDw/+Li4v/U1NT/w8PD/6ioqP9FRUVtWlpaBEBAQAMlJSUDCwsLAQAAAAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwEBAQQAAAAG + AAAACAAAAAsAAAAPAAAAEwAAABYAAAAZAAAAGgAAABoAAAAaAAAAGgAAABgAAAAWAAAAFAAAABMAAAAT + AAAAFQAAABgAAAAjAAAARBsbG3murq776Ojo//b29v/r6+v/3Nzc/8/Pz/++vr7/qqqq/zs7O0IrKysH + KysrBSAgIAMHBwcCAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQEBAQICAgICAgIEAQEBBwEBAQsAAAAPAAAAEwAAABYAAAAbAAAAHwAAACUAAAApAAAALAAAAC4AAAAw + AAAAMAAAADAAAAAuAAAALAAAACkAAAAnAAAAJgAAACYAAAAoAAAALQAAAEIAAABgb29vzdPT0//19fX/ + 8/Pz/+Xl5f/W1tb/y8vL/7y8vP+qqqr+ICAgIgAAABMAAAAPAAAADAAAAAoAAAAHAAAABQAAAAMAAAAC + AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBBwcHAwcHBwUCAgIKAAAADgAAABMAAAAYAAAAHwAAACYAAAAq + AAAALgAAADIAAAA4AAAAPQAAAEAAAABDAAAARQAAAEYAAABGAAAARgAAAEQAAABBAAAAPgAAAD0AAAA8 + AAAAPAAAAD8AAABHAAAAXiQkJIuysrL+6urq//j4+P/u7u7/39/f/9HR0f/Hx8f/wsLC/52dneMAAAAk + AAAAIAAAABwAAAAZAAAAFgAAABMAAAAPAAAACwAAAAgAAAAGAAAABAAAAAIAAAABAAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAEICAgCCQkJBQcHBwkAAAAQ + AAAAFwAAAB0AAAAlAAAALAAAADMAAAA5AAAAPwAAAEIAAABHAAAATAAAAFAAAABVAAAAWAAAAFkAAABb + AAAAXAAAAF0AAABcAAAAWQAAAFcAAABVAAAAUQAAAFIAAABSAAAAVQAAAF8AAABub29v28vLy//x8fH/ + 8/Pz/+jo6P/Z2dn/zc3N/8XFxf/MzMz/g4ODwAAAADEAAAAuAAAAKgAAACYAAAAjAAAAHwAAABsAAAAX + AAAAEgAAAA8AAAALAAAACAAAAAUAAAAEAAAAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAcHBwENDQ0DBwcHBwAAAA4AAAAVAAAAHwAAACgAAAAxAAAAOAAAAEEAAABIAAAATgEBAVQmJiZw + PT09l0VFRa9bW1vEZGRk2GxsbOtubm70bGxs+mxsbPpra2v5bGxs92lpaepqamroZGRk1VVVVcE8PDyr + NTU1lSAgIHkAAABqAAAAcCIiIpuQkJD/ysrK/+bm5v/o6Oj/39/f/9PT0//Jycn/ysrK/87Ozv9XV1ej + AAAAQAAAADwAAAA4AAAANAAAADAAAAAsAAAAJwAAACMAAAAdAAAAGQAAABUAAAARAAAADQAAAAoAAAAH + AAAABQAAAAMAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQEQEBAECQkJCAAAABAAAAAaAAAAJgAAADEAAAA8 + AAAARQAAAE0JCQlYPT09iFdXV7V+fn7gg4OD+35+fv96enr/eXl5/4GBgf+Li4v/lZWV/5ubm/+kpKT/ + paWl/6Wlpf+lpaX/m5ub/52dnf+RkZH/hYWF/319ff+Dg4P/iIiI/4eHh/FwcHDOampq6ZGRkf+3t7f/ + y8vL/9HR0f/Ozs7/yMjI/8TExP/X19f/w8PD/zk5OYsAAABNAAAASQAAAEUAAABBAAAAPAAAADgAAAAz + AAAALgAAACgAAAAjAAAAHgAAABkAAAAUAAAAEQAAAA4AAAALAAAACAAAAAYAAAADAAAAAgAAAAEAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQERERED + CgoKCAAAABEAAAAdAAAAKwAAADgAAABEAAAATxMTE2FKSkqdfHx8zJSUlPqOjo7/jo6O/5ubm/+np6f/ + uLi4/87Ozv/i4uL/6Ojo/+zs7P/t7e3/7e3t/+zs7P/s7Oz/6+vr/+vr6//s7Oz/7e3t/+3t7f/t7e3/ + 5+fn/9nZ2f/Hx8f/tLS0/6Ghof+ZmZn/np6e/6Ojo/+rq6v/sbGx/7S0tP+0tLT/uLi4/9bW1v+qqqr/ + IiIidgAAAFkAAABVAAAAUQAAAE0AAABIAAAAQwAAAD4AAAA5AAAAMwAAAC4AAAAoAAAAIgAAABwAAAAX + AAAAFAAAABIAAAAPAAAACwAAAAkAAAAGAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8BERERBgAAAA8AAAAdAAAALQAAADwAAABLAAAAVzw8PIV1dXXB + oaGh+Zubm/+goKD/r6+v/8LCwv/V1dX/4ODg/+fn5//s7Oz/6urq/+bm5v/i4uL/29vb/9TU1P/Pz8// + y8vL/8bGxv/ExMT/xcXF/8rKyv/MzMz/0NDQ/9bW1v/e3t7/4+Pj/+jo6P/r6+v/7Ozs/+Hh4f/IyMj/ + tLS0/6mpqf+rq6v/paWl/5qamv+rq6v/vr6+/4mJifoEBARlAAAAYAAAAF0AAABaAAAAVwAAAFMAAABP + AAAASQAAAEUAAAA+AAAAOAAAADIAAAArAAAAIwAAABwAAAAYAAAAFgAAABQAAAARAAAADwAAAAwAAAAJ + AAAABQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAEAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQMDAwEKCgoBFBQUAwYGBgwAAAAa + AAAAKwAAAD0AAABNAAAAXUlJSZibm5vgqKio/6enp/+2trb/y8vL/9bW1v/c3Nz/5eXl/+rq6v/m5ub/ + 3d3d/9DQ0P/AwMD/rq6u/6Ojo/+qqqr/tbW1/7u7u//Dw8P/yMjI/8zMzP/Ly8v/wcHB/8PDw/+5ubn/ + sLCw/6enp/+jo6P/s7Oz/8fHx//V1dX/4uLi/+np6f/s7Oz/4ODg/8LCwv+zs7P/srKy/62trf+YmJj/ + Xl5e3wAAAGQAAABjAAAAYQAAAF4AAABcAAAAWQAAAFYAAABSAAAATQAAAEgAAABCAAAAOwAAADMAAAAq + AAAAIgAAABsAAAAaAAAAGAAAABYAAAATAAAAEAAAAA0AAAAKAAAABgAAAAMAAAABAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAACAgIBBgYGAgkJCQMCAgIFAgICBgICAgcCAgIIAgICCQEBAQgAAAAIAAAABQAAAAQAAAAE + AAAABAAAAAMBAQEGBQUFBwoKCggAAAATAAAAJAAAADoAAABOAAAAYEZGRpiioqLlr6+v/7Ozs//Dw8P/ + 1NTU/9fX1//f39//6Ojo/+fn5//b29v/yMjI/66urv+np6f/urq6/9DQ0P/q6ur//v7+//////////// + //////////////////////////////////////////////////////z8/P/i4uL/xsbG/7Gxsf+mpqb/ + vLy8/9TU1P/k5OT/6+vr/+bm5v/Nzc3/ubm5/7S0tP96enrVAwMDZQAAAGMAAABhAAAAXgAAAF0AAABb + AAAAWQAAAFYAAABSAAAATgAAAEkAAABDAAAAOwAAADEAAAAmAAAAHgAAABwAAAAbAAAAGQAAABcAAAAU + AAAAEAAAAA4AAAAMAAAACAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAQ0NDQQJCQkIAAAADgAAABMAAAAY + AAAAHgAAACQAAAAoAAAAJwAAACAAAAAXAAAAEgAAABAAAAAOAAAADwAAABIAAAAWAAAAIAAAADEAAABJ + AAAAXzU1NYyenp7ftbW1/7e3t//IyMj/1tbW/9fX1//f39//6Ojo/+Pj4//Q0ND/s7Oz/6ioqP/FxcX/ + 6Ojo//////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////r6+v/U1NT/srKy/66urv/Ozs7/4+Pj/+vr6//l5eX/ + yMjI/7u7u/+pqanhPz8/gwAAAGAAAABeAAAAXQAAAFsAAABZAAAAVwAAAFQAAABRAAAATQAAAEcAAAA/ + AAAANQAAACkAAAAgAAAAHAAAABwAAAAcAAAAGgAAABYAAAATAAAAEQAAABAAAAAMAAAABgAAAAIAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAELCwsFBAQECgAAABUAAAAgAAAAKgAAADYAAABCAAAAUQAAAFoAAABUAAAASAAAADsAAAAx + AAAAKgAAACUAAAAiAAAAJgAAAC8AAAA/AAAAVw4ODnN3d3fCubm5/rq6uv/IyMj/1tbW/9fX1//c3Nz/ + 6Ojo/+Li4v/Kysr/qqqq/7i4uP/i4uL////////////////////////////+/v7/+fn5//Pz8//u7u7/ + 6enp/+jo6P/l5eX/5eXl/+Pj4//l5eX/5ubm/+np6f/t7e3/8vLy//f39//9/f3///////////////// + ////////////////6+vr/7m5uf+srKz/z8/P/+Xl5f/s7Oz/29vb/729vf+9vb3+lJSUwhoaGmUAAABc + AAAAWgAAAFgAAABXAAAAVQAAAFIAAABOAAAASAAAAD8AAAA1AAAAKQAAAB4AAAAaAAAAGwAAABwAAAAc + AAAAGQAAABUAAAATAAAAEwAAABAAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAgMDAwkAAAAUAAAAIwAAADQAAABD + LS0tcDU1NZAMDAyEAAAAiAAAAIUAAAB3AAAAZQAAAFcAAABMAAAARQAAAEEAAABFAAAATwAAAGQ4ODiY + rKys7bu7u//ExMT/1dXV/9jY2P/Z2dn/4+Pj/+Tk5P/Nzc3/q6ur/7+/v//w8PD///////////////// + //////r6+v/x8fH/5+fn/97e3v/d3d3/3d3d/97e3v/j4+P/5eXl/+fn5//o6Oj/6enp/+jo6P/n5+f/ + 5eXl/+Hh4f/f39//39/f/+Dg4P/m5ub/7u7u//n5+f///////////////////////////+7u7v+3t7f/ + tra2/9ra2v/q6ur/5ubm/8PDw/+2trb/yMjI8F5eXo0AAABaAAAAWAAAAFYAAABUAAAAUwAAAE8AAABJ + AAAAPgAAADMAAAAlAAAAGgAAABgAAAAZAAAAHQAAAB4AAAAcAAAAFwAAABUAAAAVAAAAFAAAAA0AAAAF + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAACAgIEAAAADAAAABoAAAAsDAwMQ3l5ecKsrKz/rKys/46OjvIoKCi6AAAApQAAAJgAAACJ + AAAAeAAAAGwAAABmAAAAYgAAAGYAAABzb29vwL29vf6/v7//0NDQ/9nZ2f/Z2dn/3t7e/+fn5//Y2Nj/ + srKy/7y8vP/x8fH//////////////////Pz8//Dw8P/j4+P/3d3d/93d3f/i4uL/7Ozs//T09P/6+vr/ + /v7+//////////////////////////////////////////////////z8/P/39/f/7+/v/+fn5//g4OD/ + 39/f/+Tk5P/w8PD//f39///////////////////////c3Nz/rKys/8zMzP/m5ub/6+vr/8zMzP+ysrL/ + xMTE/6WlpcMUFBRdAAAAVgAAAFQAAABTAAAAUQAAAEoAAAA+AAAAMQAAACIAAAAWAAAAFAAAABcAAAAa + AAAAHgAAAB4AAAAaAAAAFwAAABgAAAAXAAAAEAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgIEBAQKAAAAFgAAAChWVlaN + v7+//9vb2//Z2dn/yMjI/66urv91dXXlJSUlsgAAAJUAAACIAAAAggAAAIAAAACBExMTjpaWluG9vb3/ + xsbG/9jY2P/a2tr/2tra/+Li4v/i4uL/w8PD/6ysrP/j4+P/////////////////+Pj4/+jo6P/d3d3/ + 3d3d/+Xl5f/x8fH/+Pj4/9zc3P/z8/P///////////////////////////////////////////////// + //////////////////////////////////////39/f/z8/P/5+fn/9/f3//g4OD/7u7u//z8/P////// + ///////////5+fn/ubm5/76+vv/i4uL/7Ozs/8/Pz/+tra3/uLi4/9fX1+Y9PT13AAAAVAAAAFMAAABR + AAAASwAAAD8AAAAuAAAAHgAAABQAAAAUAAAAFgAAABoAAAAdAAAAHgAAABwAAAAaAAAAHAAAABsAAAAS + AAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgICAhEREQYAAAAOAAAAGomJia7U1NT/8fHx/+/v7//k5OT/1NTU/8DAwP+np6f+ + cHBw2yEhIZsAAACKAAAAliAgIKmmpqbvvb29/83Nzf/a2tr/29vb/9zc3P/l5eX/2NjY/7CwsP/IyMj/ + /Pz8////////////+Pj4/+Tk5P/c3Nz/3t7e/+zs7P/6+vr///////v7+/9wcHD/YGBg/3p6ev/r6+v/ + //////////////////////////////////////////////////////////////////////////////// + ////////////////+vr6/+rq6v/f39//4eHh//Ly8v//////////////////////zc3N/7W1tf/e3t7/ + 6+vr/9HR0f+np6f/s7Oz/+Li4vyBgYGWAAAAUwAAAFEAAABMAAAAQQAAAC4AAAAdAAAAFQAAABYAAAAZ + AAAAGwAAAB0AAAAdAAAAHAAAAB8AAAAhAAAAHwAAABQAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBHh4eAi8vLwYXFxcL + W1tbe8TExP/v7+//9/f3//Hx8f/o6Oj/3Nzc/8zMzP+vr6//g4OD/kNDQ9swMDDDra2t9729vf/R0dH/ + 29vb/9vb2//e3t7/5OTk/83Nzf+urq7/6Ojo/////////////Pz8/+rq6v/b29v/3t7e/+/v7//9/f3/ + ////////////////z8/P/01NTf9zc3P/hYWF/8PDw/////////////////////////////////////// + //////////////////////////////////////////////////////////////////////r6+v/n5+f/ + 39/f/+bm5v/7+/v/////////////////3t7e/7Ozs//d3d3/6+vr/8rKyv+hoaH/rq6u/9zc3P+mpqa8 + CwsLUgAAAEwAAABBAAAALQAAAB4AAAAZAAAAGgAAAB0AAAAgAAAAHwAAAB0AAAAeAAAAIwAAACcAAAAh + AAAAEwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFxcQN/f38MlpaWxtbW1v/09PT/+Pj4//Ly8v/p6en/ + 2dnZ/7e3t/+Ghob/c3Nz/66urv+8vLz/1dXV/9zc3P/c3Nz/39/f/+Pj4//BwcH/tra2//f39/////// + //////Ly8v/e3t7/29vb/+zs7P/9/f3////////////////////////////p6en/Tk5O/2tra/98fHz/ + 39/f//////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////z8/P/4eHh/+Hh4f/19fX///////////////// + 4uLi/7S0tP/g4OD/7Ozs/8DAwP+ampr/ra2t/9nZ2f/MzMzXKCgoWgAAAD8AAAAuAAAAIwAAACAAAAAg + AAAAIwAAACUAAAAjAAAAHwAAACAAAAApAAAALAAAACMAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACcnJwUoqKi293d3f/29vb/+fn5/+/v7//U1NT/pqam/4qKiv+urq7/urq6/9bW1v/c3Nz/ + 3d3d/+Dg4P/h4eH/urq6/8rKyv/+/v7///////z8/P/m5ub/2tra/+Li4v/4+Pj///////////////// + ///////////////////////////Pz8//np6e/9LS0v////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////6+vr/5eXl/9/f3//x8fH/////////////////4ODg/7i4uP/k5OT/6urq/6ysrP+SkpL/ + q6ur/9bW1v/d3d3kMzMzVwAAAC8AAAAoAAAAJgAAACYAAAApAAAAKwAAACcAAAAiAAAAJQAAAC8AAAAv + AAAAIAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrKwmra2t6+Li4v/19fX/ + 5ubm/76+vv+Xl5f/q6ur/7e3t//X19f/3d3d/93d3f/g4OD/39/f/7a2tv/T09P////////////5+fn/ + 39/f/9ra2v/u7u7//v7+//////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////+/v7/6enp/9/f3//x8fH/ + ////////////////1NTU/8LCwv/n5+f/5OTk/5iYmP+Li4v/pKSk/9TU1P/l5eXuOTk5WAAAACwAAAAr + AAAAKwAAAC8AAAAvAAAAKwAAACYAAAArAAAAMwAAAC4AAAAYAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACQkJA8r6+v+NLS0v/ExMT/oqKi/6Wlpf+xsbH/1tbW/97e3v/e3t7/ + 4ODg/9/f3/+1tbX/2dnZ////////////8fHx/9ra2v/d3d3/9vb2//////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////+/v7/6urq/9/f3//x8fH/////////////////w8PD/9DQ0P/r6+v/ + zs7O/4qKiv+CgoL/n5+f/9HR0f/o6Oj3ZGRkZgAAAC8AAAAwAAAAMgAAADMAAAAtAAAAKwAAADEAAAA1 + AAAAJwAAAA8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJiYlX + kJCQ/pWVlf+goKD/q6ur/9HR0f/f39//39/f/+Hh4f/h4eH/t7e3/97e3v///////////+/v7//Z2dn/ + 4uLi//v7+/////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////+/v7/ + 6enp/9/f3//09PT////////////6+vr/uLi4/97e3v/s7Oz/qqqq/4KCgv9+fn7/m5ub/83Nzf/n5+f8 + iIiIegAAADUAAAA2AAAANAAAADAAAAAxAAAANgAAADEAAAAbAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABycnJ9kJCQ/6SkpP/Kysr/39/f/+Dg4P/h4eH/ + 4+Pj/7y8vP/V1dX////////////t7e3/2NjY/+Tk5P/9/f3///////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////+/v7/5ubm/+Dg4P/7+/v////////////n5+f/ + v7+//+jo6P/j4+P/h4eH/4CAgP9+fn7/mJiY/8rKyv/o6Oj+nJyckwAAADkAAAA1AAAANAAAADcAAAA2 + AAAAJgAAAA8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJ6enmefn5//wcHB/+Dg4P/h4eH/4eHh/+Tk5P/Dw8P/zc3N////////////7e3t/9fX1//m5ub/ + /v7+//////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////8/Pz/4eHh/+Xl5f/+/v7////////////Hx8f/19fX/+zs7P+3t7f/fHx8/4qKiv9/f3// + mJiY/8rKyv/o6Oj/o6OjnwAAADgAAAA5AAAAOgAAADEAAAAcBQUFCQUFBQEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6slmpqa+K6urv/e3t7/4uLi/+Li4v/k5OT/ + z8/P/8PDw////////////+/v7//X19f/5eXl//7+/v////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////19fX/39/f//Dw8P////// + //////b29v+7u7v/5ubm/+bm5v+CgoL/i4uL/5CQkP+CgoL/m5ub/8vLy//p6en/pqampAAAADwAAAA5 + AAAAKwAAABgAAAAKEhISAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + pqamBpWVlcqgoKD/2dnZ/+Li4v/j4+P/5OTk/9ra2v+2trb/+/v7///////y8vL/19fX/+Li4v/+/v7/ + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////q6ur/4ODg//z8/P///////////9DQ0P/X19f/7Ozs/6+vr/95eXn/ + ra2t/5GRkf+EhIT/oaGh/87Ozv/q6ur/p6enqAAAADUAAAAmAAAAGAAAAA4pKSkEAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZmZlzlZWV/8bGxv/j4+P/5OTk/+Tk5P/i4uL/ + t7e3/+3t7f/+/v7/+fn5/9jY2P/e3t7//Pz8//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//r6+v/f39// + 6+vr//7+/v/+/v7/9PT0/7+/v//p6en/2tra/3Nzc/+lpaX/srKy/4+Pj/+JiYn/q6ur/9DQ0P/s7Oz/ + qKionQAAACYAAAAbAAAAD0VFRQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + qqqqGpCQkPWqqqr/4eHh/+Tk5P/l5eX/5ubm/8XFxf/Y2Nj//f39//v7+//d3d3/2NjY//j4+P/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39/+zs7P/d3d3/+Pj4//39/f/9/f3/yMjI/93d3f/t7e3/ + k5OT/4mJif/Pz8//rq6u/46Ojv+SkpL/tra2/9TU1P/w8PD/qamplAAAABwAAAAMY2NjAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIymlJSU/9fX1//k5OT/5ubm/+bm5v/Z2dn/ + v7+///39/f/9/f3/5ubm/9TU1P/w8PD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + +vr6/97e3v/q6ur//f39//39/f/n5+f/ycnJ/+vr6/+6urr/bW1t/9XV1f/MzMz/pqam/46Ojv+hoaH/ + wcHB/9/f3//y8vL/p6endERERAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nJycNYuLi/+3t7f/4+Pj/+fn5//n5+f/5OTk/7q6uv/v7+//+/v7//Hx8f/T09P/5OTk//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/6enp/93d3f/5+fn/+/v7//v7+//AwMD/ + 5ubm/+Dg4P9tbW3/ubm5/+Hh4f/Dw8P/np6e/5OTk/+1tbX/z8/P/+7u7v/y8vL8srKyKwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGhoa1lJSU/9vb2//m5ub/6Ojo/+jo6P/R0dH/ + zc3N//r6+v/6+vr/2tra/9fX1//4+Pj/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/19fX/3Nzc/+7u7v/6+vr/+vr6/9HR0f/d3d3/7e3t/4ODg/+Wlpb/8PDw/9vb2/+5ubn/ + l5eX/6SkpP/Jycn/4ODg//Hx8f/09PSzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + mZmZNIeHh/+4uLj/5OTk/+jo6P/o6Oj/4+Pj/7m5uf/19fX/+Pj4/+fn5//R0dH/7e3t//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/l5eX/6urq//j4+P/g4OD/4+Pj//j4+P/4+Pj/ + 4uLi/9DQ0P/s7Oz/oaGh/3V1df/4+Pj/7Ozs/9LS0v+qqqr/mpqa/7y8vP/Y2Nj/5+fn//Hx8f/r6+te + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgoKtkJCQ/9vb2//o6Oj/6enp/+np6f/Pz8// + 1NTU//j4+P/19fX/0tLS/9zc3P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + mJiY/2JiYv97e3v/xsbG/+np6f/a2tr/9vb2//j4+P/29vb/w8PD/+rq6v++vr7/aGho/+np6f/29vb/ + 5eXl/8PDw/+goKD/q6ur/9bW1v/f39//7u7u//Ly8vPn5+caAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + lZWVHYODg/yysrL/5OTk/+rq6v/q6ur/5OTk/7q6uv/09PT/9vb2/+Li4v/Pz8//8PDw//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/+Dg4P9QUFD/eXl5/5KSkv+goKD/7+/v/9nZ2f/u7u7/ + 9vb2//b29v/Gxsb/5+fn/9PT0/9oaGj/0dHR//z8/P/y8vL/2NjY/7CwsP+hoaH/ysrK/+Pj4//k5OT/ + 8fHx//Dw8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIyEh4eH/9fX1//o6Oj/6+vr/+rq6v/U1NT/ + z8/P//T09P/y8vL/z8/P/9vb2//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 6Ojo/1VVVf91dXX/i4uL/7Gxsf/09PT/2NjY/+Xl5f/09PT/9PT0/8/Pz//i4uL/6Ojo/2hoaP+5ubn/ + /v7+//n5+f/n5+f/w8PD/6Ojo/+6urr/5ubm/+Hh4f/u7u7/8fHx/fLy8ioAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nZ2dBX9/f+Sfn5//4uLi/+rq6v/s7Oz/6Ojo/76+vv/s7Oz/7e3t/9vb2//Ly8v/7Ozs//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/xMTE/5CQkP+vr6//7e3t//Pz8//d3d3/ + 39/f//Pz8//z8/P/1tbW/9zc3P/t7e3/dXV1/6enp////////Pz8//Hx8f/U1NT/ra2t/62trf/g4OD/ + 6urq/+Xl5f/y8vL/8fHxmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJRAgICA/8PDw//n5+f/7Ozs/+3t7f/e3t7/ + x8fH/+vr6//n5+f/6urq/8vLy//x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy/+Hh4f/Z2dn/8vLy//Ly8v/c3Nz/1tbW/+3t7f+Dg4P/ + mJiY///////+/v7/+Pj4/+Hh4f+6urr/p6en/9LS0v/z8/P/4ODg//Dw8P/y8vL58PDwEgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHt7e52Hh4f/2tra/+rq6v/t7e3/7Ozs/83Nzf/a2tr/3Nzc//Pz8//19fX/6enp/+Xl5f/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/7+/v/+7u7v/t7e3/6+vr/+np6f/U1NT/wsLC/+jo6P/v7+// + 7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 4+Pj/9XV1f/v7+//8PDw/+Hh4f/R0dH/7e3t/4yMjP+Ojo7////////////7+/v/6+vr/8fHx/+np6f/ + w8PD//X19f/l5eX/6urq//Ly8v/z8/N1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcnJwCfHx86qKiov/i4uL/7Ozs/+7u7v/o6Oj/ + vr6+/+vr6//Y2Nj/9/f3//X19f/8/Pz/6enp/+Xl5f/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7e3t/+vr6//r6+v/6Ojo/+Xl5f/i4uL/ + 3t7e/9nZ2f/U1NT/j4+P/0JCQv9BQUH/WFhY/9HR0f/n5+f/6+vr/+zs7P/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/l5eX/09PT/+rq6v/u7u7/5ubm/8/Pz//t7e3/ + kpKS/4iIiP////////////39/f/x8fH/0tLS/6ysrP+2trb/7+/v/+7u7v/i4uL/8/Pz//T09NYAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJKSkjV9fX3/vLy8/+Xl5f/t7e3/7u7u/9/f3//Gxsb/5OTk/+Li4v/19fX/9/f3//z8/P/8/Pz/ + 5ubm/+Xl5f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7Ozs/+rq6v/o6Oj/ + 5eXl/+Pj4//f39//2tra/9XV1f/R0dH/zMzM/8jIyP+9vb3/m5ub/3d3d/9BQUH/QUFB/0FBQf9BQUH/ + fHx8/9vb2//d3d3/4eHh/+Xl5f/p6en/7Ozs/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+Xl5f/S0tL/5+fn/+3t7f/o6Oj/zc3N/+3t7f+Tk5P/hoaG//7+/v///////v7+//b29v/a2tr/ + srKy/66urv/m5ub/9vb2/93d3f/w8PD/8/Pz/vDw8BsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh4eHen9/f//V1dX/6urq/+7u7v/u7u7/ + 1NTU/9PT0//X19f/8fHx//T09P/5+fn/+/v7//v7+//7+/v/5+fn/+Li4v/r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+rq6v/l5eX/2tra/9PT0//Pz8//ysrK/8bGxv/ExMT/s7Oz/5CQkP9tbW3/ + TU1N/zExMf8xMTH/NDQ0/0FBQf9BQUH/QUFB/0FBQf9aWlr/0tLS/97e3v/Z2dn/2dnZ/9vb2//h4eH/ + 5ubm/+np6f/q6ur/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5eXl/9HR0f/l5eX/6+vr/+jo6P/Nzc3/ + 7e3t/5KSkv+Ghob//f39//7+/v/+/v7/+vr6/+Hh4f+6urr/qamp/9zc3P/7+/v/3Nzc/+3t7f/z8/P/ + 8PDwaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAB6enq4jo6O/93d3f/s7Oz/7+/v/+zs7P/ExMT/4+Pj/9DQ0P/39/f/9PT0//r6+v/7+/v/ + +/v7//v7+//7+/v/6urq/9/f3//o6Oj/6enp/+np6f/p6en/6enp/+np6f/p6en/5ubm/9fX1//Gxsb/ + wcHB/6mpqf+Hh4f/ZWVl/0NDQ/8xMTH/MTEx/zExMf8xMTH/MTEx/0RERP9vb2//VVVV/0FBQf9BQUH/ + QUFB/5SUlP94eHj/d3d3/76+vv/f39//2dnZ/9XV1f/X19f/3Nzc/+Li4v/m5ub/6Ojo/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/j4+P/0dHR/+Pj4//p6en/5ubm/87Ozv/t7e3/jY2N/4uLi//7+/v//Pz8//39/f/7+/v/ + 5+fn/8HBwf+np6f/0dHR//z8/P/g4OD/5ubm//Pz8//19fWeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHt7e/Cjo6P/4eHh/+3t7f/w8PD/ + 6enp/8HBwf/j4+P/1tbW//X19f/19fX/+/v7//v7+//7+/v/+/v7//v7+//7+/v/7+/v/9zc3P/m5ub/ + 6Ojo/+jo6P/o6Oj/6Ojo/+fn5//g4OD/srKy/15eXv87Ozv/MTEx/zExMf8xMTH/MTEx/zExMf89PT3/ + bGxs/5ycnP/Kysr/3Nzc/7S0tP88PDz/OTk5/2pqav+urq7/6Ojo/+jo6P/Y2Nj/jo6O/2tra/+jo6P/ + 29vb/9ra2v/V1dX/1NTU/9fX1//c3Nz/4ODg/+Xl5f/m5ub/5+fn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+Li4v/Pz8//4uLi/+jo6P/h4eH/ + 0dHR/+3t7f+EhIT/kpKS//f39//6+vr//Pz8//v7+//q6ur/xsbG/6enp//Jycn/+/v7/+Pj4//f39// + 8/Pz//T09OYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACQkJAke3t7/7S0tP/k5OT/7+/v//Hx8f/k5OT/x8fH/9zc3P/d3d3/8/Pz//X19f/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/9PT0/9zc3P/i4uL/5ubm/+bm5v/m5ub/5eXl/+Li4v9hYWH/ + MTEx/zExMf8xMTH/ODg4/2RkZP+RkZH/w8PD/+Tk5P/m5ub/5OTk/9vb2//AwMD/SUlJ/zExMf9sbGz/ + 4uLi/+bm5v/m5ub/5ubm/+bm5v/m5ub/4+Pj/6mpqf9sbGz/iIiI/87Ozv/c3Nz/19fX/9PT0//S0tL/ + 1dXV/9vb2//g4OD/5OTk/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/39/f/87Ozv/h4eH/5ubm/9zc3P/V1dX/7e3t/3d3d/+bm5v/8fHx//b29v/5+fn/ + +vr6/+3t7f/Kysr/qKio/8LCwv/5+fn/5+fn/9nZ2f/y8vL/8/Pz/e3t7QMAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJOTk1J8fHz/xMTE/+fn5//w8PD/ + 8fHx/97e3v/Nzc3/1NTU/+Xl5f/y8vL/9vb2//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/ + +Pj4/+Pj4//b29v/4+Pj/+Tk5P/k5OT/wcHB/zQ0NP9aWlr/iYmJ/7m5uf/f39//5OTk/+Tk5P/k5OT/ + 5OTk/+Li4v/Z2dn/xcXF/19fX/8xMTH/UFBQ/9ra2v/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/CwsL/enp6/3Nzc/+4uLj/39/f/9ra2v/U1NT/z8/P/9HR0f/W1tb/29vb/9/f3//i4uL/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/b29v/zc3N/+Li4v/k5OT/ + 1dXV/9ra2v/q6ur/ampq/6ampv/p6en/7+/v//X19f/4+Pj/7e3t/83Nzf+oqKj/vb29//f39//q6ur/ + 1dXV//Dw8P/z8/P/8PDwNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAlJSUeH5+fv/S0tL/6Ojo//Hx8f/x8fH/19fX/8/Pz//Kysr/7u7u//Hx8f/29vb/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4/+/v7//a2tr/3t7e/+Li4v/Pz8// + 2tra/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/g4OD/19fX/8TExP96enr/MTEx/z09Pf/Jycn/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/1tbW/5CQkP9paWn/ + nZ2d/9nZ2f/b29v/1NTU/8/Pz//Nzc3/0NDQ/9XV1f/b29v/39/f/+Hh4f/i4uL/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/9fX1//Ly8v/3d3d/+Hh4f/R0dH/4ODg/9fX1/9oaGj/r6+v/9/f3//n5+f/ + 7u7u//Pz8//r6+v/zc3N/6mpqf+6urr/9fX1/+zs7P/S0tL/7u7u//Pz8//v7+9bAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5eXmchoaG/9bW1v/q6ur/ + 8vLy//Dw8P/R0dH/1NTU/8bGxv/19fX/8PDw//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/m5ub/2NjY/9/f3//h4eH/4uLi/+Li4v/i4uL/4uLi/+Li4v/h4eH/ + 39/f/9bW1v/ExMT/k5OT/zIyMv8yMjL/r6+v/+Hh4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/9/f3/+rq6v/bW1t/4KCgv/Kysr/3Nzc/9fX1//R0dH/ + zc3N/8zMzP/Q0ND/19fX/9zc3P/f39//4eHh/+Li4v/i4uL/4uLi/+Li4v/h4eH/z8/P/8rKyv/u7u7/ + 1tbW/83Nzf/l5eX/vLy8/2hoaP+2trb/1NTU/93d3f/l5eX/7Ozs/+bm5v/Ly8v/qamp/7a2tv/z8/P/ + 7e3t/87Ozv/t7e3/8/Pz/+3t7W8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHp6eriOjo7/2NjY/+vr6//z8/P/8PDw/83Nzf/Y2Nj/xMTE//Pz8//u7u7/ + 9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//09PT/ + 4ODg/9bW1v/d3d3/4ODg/+Dg4P/g4OD/4ODg/97e3v/U1NT/wcHB/6SkpP87Ozv/MTEx/42Njf/g4OD/ + 4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/w8PD/3t7e/9wcHD/sbGx/93d3f/Z2dn/09PT/83Nzf/Kysr/zc3N/9fX1//f39// + 4ODg/+Dg4P/g4OD/3d3d/9fX1//d3d3/8/Pz//f39/++vr7/ycnJ/+np6f+mpqb/aWlp/7m5uf/Gxsb/ + 0dHR/9vb2//j4+P/4ODg/8bGxv+mpqb/tLS0//Hx8f/t7e3/y8vL/+vr6//z8/P/7OzsewAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe3t7zpWVlf/Z2dn/ + 7e3t//Pz8//v7+//ysrK/9vb2//FxcX/8fHx/+7u7v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/8vLy/+Dg4P/V1dX/29vb/93d3f/c3Nz/ + 09PT/7+/v/+urq7/SkpK/zExMf9ra2v/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/9TU1P+SkpL/ + Z2dn/5eXl//V1dX/2tra/9XV1f/S0tL/1tbW/93d3f/e3t7/2tra/9bW1v/i4uL/9PT0//Hx8f/09PT/ + 7+/v/7u7u//Nzc3/6+vr/4GBgf9zc3P/ra2t/7i4uP/ExMT/zs7O/9fX1//W1tb/v7+//6Ghof+wsLD/ + 7u7u/+rq6v/Jycn/6+vr//Pz8//r6+t+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB8fHzfm5ub/9ra2v/t7e3/9PT0/+/v7//Jycn/2dnZ/8PDw//w8PD/ + 7e3t//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/ + 9fX1//X19f/19fX/9fX1//Pz8//k5OT/1dXV/8rKyv+9vb3/sbGx/2FhYf8xMTH/Tk5O/9XV1f/d3d3/ + 3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/ + 3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/b29v/rKys/21tbf98fHz/xMTE/9vb2//Z2dn/ + 1dXV/9bW1v/l5eX/9PT0//X19f/z8/P/7+/v//T09P/Z2dn/wMDA/9bW1v/o6Oj/ampq/3x8fP+enp7/ + qqqq/7W1tf/AwMD/y8vL/8rKyv+2trb/m5ub/62trf/q6ur/5ubm/8XFxf/q6ur/8/Pz/+rq6n8AAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH19femenp7/ + 2tra/+7u7v/09PT/7+/v/8nJyf/Y2Nj/wsLC/+/v7//s7Oz/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//Pz8//x8fH/ + 39/f/8TExP+IiIj/Ly8v/zw8PP/ExMT/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/ + 3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/ + 3Nzc/9zc3P/c3Nz/3Nzc/8LCwv93d3f/gYGB/83Nzf/s7Oz/9PT0//T09P/09PT/9PT0//Hx8f/u7u7/ + 9PT0/8bGxv/Dw8P/4uLi/8DAwP9oaGj/f39//5GRkf+bm5v/pqam/7Kysv+8vLz/vb29/6qqqv+Tk5P/ + qqqq/+Tk5P/e3t7/wcHB/+np6f/z8/P/9fX1iQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfn5+7KCgoP/a2tr/7u7u//X19f/w8PD/y8vL/9bW1v/AwMD/ + 7u7u/+rq6v/z8/P/5+fn/9/f3//r6+v/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//y8vL/7+/v/+rq6v/m5ub/39/f/8TExP+srKz/vr6+/9fX1//S0tL/ + 1tbW/9nZ2f/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/ + 2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/Z2dn/1tbW/9LS0v/W1tb/39/f/+rq6v/w8PD/ + 4ODg//Pz8//z8/P/8/Pz//Pz8//z8/P/7u7u/+/v7//z8/P/tLS0/8nJyf/p6en/n5+f/2hoaP+AgID/ + h4eH/4+Pj/+YmJj/o6Oj/66urv+urq7/nZ2d/4mJif+lpaX/3d3d/9TU1P+8vLz/6enp//Ly8v/o6Oh/ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/f3/s + oKCg/9nZ2f/t7e3/9vb2//Hx8f/Nzc3/1dXV/729vf/t7e3/6Ojo/+3t7f/Ly8v/2NjY/97e3v/w8PD/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//y8vL/8vLy/+7u7v/o6Oj/ + 5OTk/+Li4v/Dw8P/wMDA/9ra2v/z8/P/8/Pz//Hx8f/m5ub/39/f/9jY2P/T09P/0dHR/9PT0//V1dX/ + 1tbW/9fX1//Y2Nj/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Y2Nj/19fX/9bW1v/U1NT/0tLS/9HR0f/U1NT/ + 2tra/+Dg4P/m5ub/8fHx//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Hx8f/r6+v/ + 8PDw/+Pj4/+3t7f/0dHR/+zs7P9ycnL/b29v/39/f/+AgID/hYWF/4yMjP+VlZX/n5+f/56env+Pj4// + f39//6CgoP/U1NT/x8fH/7e3t//p6en/8vLy/+fn534AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgOaenp7/19fX/+zs7P/29vb/8vLy/9HR0f/Q0ND/ + uLi4/+zs7P/m5ub/6enp/8nJyf/X19f/3t7e/+zs7P/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Dw8P/t7e3/5ubm/+Li4v/j4+P/xcXF/7y8vP/Nzc3/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/7Ozs/+bm5v/h4eH/39/f/97e3v/c3Nz/3d3d/93d3f/d3d3/ + 3Nzc/9/f3//f39//4uLi/+bm5v/t7e3/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/7e3t/+rq6v/x8fH/xcXF/76+vv/g4OD/ycnJ/2hoaP94eHj/ + gICA/39/f/9/f3//hISE/4qKiv+RkZH/j4+P/4CAgP92dnb/nJyc/8jIyP+4uLj/srKy/+jo6P/x8fH/ + 5eXlewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + gYGB2pubm//U1NT/6+vr//b29v/z8/P/19fX/83Nzf+1tbX/7Ozs/+Tk5P/u7u7/2dnZ/9DQ0P/g4OD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/v7+//6+vr/+Tk5P/g4OD/ + 5OTk/8vLy/+4uLj/wcHB/+3t7f/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/p6en/ + 6+vr//Dw8P+urq7/yMjI/+np6f+enp7/aWlp/4ODg/+CgoL/gICA/39/f/9/f3//goKC/4WFhf+AgID/ + cnJy/21tbf+Wlpb/urq6/6enp/+vr6//6enp//Dw8P/l5eVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDg4PJmJiY/9HR0f/p6en/9vb2//T09P/e3t7/ + ysrK/7m5uf/j4+P/4+Pj/+rq6v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+rq6v/i4uL/3t7e/+Li4v/T09P/tbW1/7i4uP/m5ub/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7Ozs/+fn5//s7Oz/0tLS/7W1tf/X19f/5eXl/29vb/90dHT/ + iYmJ/4aGhv+Dg4P/gYGB/39/f/9/f3//fX19/3V1df9lZWX/ZmZm/5GRkf+pqan/lpaW/62trf/p6en/ + 7+/v/+Tk5GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAISEhLGTk5P/zc3N/+fn5//19fX/9vb2/+Pj4//Kysr/v7+//9XV1f/i4uL/5+fn/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+3t7f/o6Oj/4ODg/9zc3P/g4OD/ + 29vb/7Gxsf+wsLD/29vb/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/m5ub/ + 5+fn/+7u7v+xsbH/w8PD/+bm5v+zs7P/aGho/4iIiP+NjY3/ioqK/4aGhv+EhIT/goKC/39/f/95eXn/ + a2tr/1tbW/9iYmL/ioqK/5iYmP+FhYX/sLCw/+vr6//u7u7/5eXlPAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhYWFlI+Pj//Jycn/4+Pj//T09P/4+Pj/ + 6enp/8jIyP/Gxsb/yMjI/+Pj4//j4+P/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/s7Oz/6Ojo/9/f3//a2tr/3t7e/+Hh4f+ysrL/rKys/83Nzf/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/6urq/+Tk5P/q6ur/1tbW/7CwsP/S0tL/6enp/3x8fP91dXX/ + l5eX/5KSkv+Ojo7/i4uL/4iIiP+EhIT/gYGB/3h4eP9mZmb/VFRU/2JiYv+EhIT/hoaG/3l5ef+3t7f/ + 7Ozs/+3t7f7Z2dkIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACcnJxwjY2N/8HBwf/f39//8fHx//j4+P/t7e3/zMzM/83Nzf+5ubn/5eXl/97e3v/r6+v/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+rq6v/h4eH/2dnZ/9zc3P/k5OT/ + t7e3/6ioqP+9vb3/6+vr/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+vr6//k5OT/ + 5OTk/+zs7P+xsbH/wcHB/+Xl5f+9vb3/aGho/5KSkv+cnJz/mJiY/5SUlP+Pj4//jIyM/4iIiP+Dg4P/ + d3d3/2JiYv9TU1P/ZmZm/4CAgP94eHj/cnJy/8TExP/r6+v/7u7u7gAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJubm0mOjo7/tra2/9nZ2f/u7u7/ + +fn5//Hx8f/W1tb/zc3N/6+vr//n5+f/3d3d/+bm5v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//q6ur/6Ojo/9/f3//c3Nz/5OTk/8HBwf+kpKT/r6+v/+fn5//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5ubm/+Hh4f/o6Oj/0tLS/6+vr//U1NT/5ubm/3h4eP93d3f/ + p6en/6Ojo/+enp7/mZmZ/5WVlf+RkZH/jY2N/4WFhf91dXX/X19f/1ZWVv9vb2//fX19/2tra/9ycnL/ + 1NTU/+rq6v/v7++6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAm5ubFY+Pj/+srKz/0dHR/+rq6v/4+Pj/9fX1/+Li4v/Kysr/ubm5/9TU1P/c3Nz/ + 4ODg/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+np6f/n5+f/4uLi/+Tk5P/Nzc3/ + oaGh/6Wlpf/e3t7/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/ + 6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/ + 6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+jo6P/g4OD/ + 4+Pj/+jo6P+oqKj/w8PD/+fn5/+xsbH/aGho/6Kiov+urq7/qqqq/6SkpP+fn5//mpqa/5aWlv+QkJD/ + hoaG/3Nzc/9cXFz/Xl5e/3l5ef97e3v/ZGRk/4KCgv/e3t7/6enp/9jY2HwAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQ3KSkpP/Kysr/ + 5OTk//X19f/5+fn/6enp/8zMzP/Hx8f/vLy8/+Dg4P/a2tr/6Ojo/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+jo6P/n5+f/2NjY/56env+cnJz/0dHR/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/o6Oj/4eHh/97e3v/o6Oj/v7+//7S0tP/b29v/5OTk/3Nzc/+EhIT/ + urq6/7W1tf+wsLD/q6ur/6Wlpf+hoaH/nJyc/5WVlf+Hh4f/b29v/1xcXP9paWn/goKC/3d3d/9iYmL/ + nJyc/+Xl5f/o6Oj/3NzcSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACSkpKenJyc/8LCwv/d3d3/8fHx//r6+v/w8PD/1dXV/87Ozv+rq6v/ + 4+Pj/9fX1//g4OD/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P+urq7/ + mJiY/8DAwP/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+Pj4//d3d3/ + 5OTk/9nZ2f+np6f/zMzM/+rq6v+cnJz/bGxs/7m5uf/BwcH/vLy8/7e3t/+xsbH/rKys/6ampv+hoaH/ + l5eX/4WFhf9ra2v/YGBg/3l5ef+Hh4f/cnJy/2dnZ/+6urr/6Ojo/+np6fnS0tIDAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKSkpFWampr/ + t7e3/9TU1P/r6+v/+Pj4//b29v/k5OT/zMzM/7u7u//Hx8f/29vb/9jY2P/n5+f/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/56env+tra3/5+fn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/k5OT/29vb/97e3v/m5ub/pqam/7+/v//k5OT/y8vL/2xsbP+fn5// + zc3N/8fHx//BwcH/uLi4/6+vr/+np6f/oaGh/5qamv+Ojo7/enp6/2RkZP9qamr/iIiI/4eHh/9tbW3/ + d3d3/9XV1f/o6Oj/7e3ttwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6urDpubm/mtra3/ysrK/+Pj4//19fX/+/v7/+zs7P/R0dH/ + y8vL/6urq//i4uL/1dXV/97e3v/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//k5OT/ + nZ2d/+Li4v/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5eXl/9ra2v/b29v/ + 5ubm/7e3t/+0tLT/29vb/+Xl5f99fX3/gICA/9PT0//Nzc3/wcHB/7S0tP+mpqb/mZmZ/5CQkP+JiYn/ + goKC/3V1df9iYmL/WFhY/3BwcP+MjIz/gYGB/2tra/+Xl5f/5OTk/+jo6P/W1tZqAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nJyctKampv/AwMD/2dnZ/+/v7//6+vr/9PT0/+Pj4//MzMz/tbW1/8nJyf/Z2dn/09PT/+Pj4//m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/9vb2//X19f/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+Xl5f/a2tr/2NjY/+Tk5P/Gxsb/qKio/9HR0f/s7Oz/l5eX/3BwcP/Dw8P/ + ysrK/7e3t/+mpqb/lZWV/4aGhv95eXn/cHBw/2pqav9iYmL/VVVV/0ZGRv9KSkr/aGho/3x8fP9wcHD/ + bW1t/7y8vP/o6Oj/6urq+sXFxQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6tXpKSk/7a2tv/Nzc3/5ubm//f39//7+/v/ + 6+vr/9LS0v/Kysr/qKio/+Dg4P/S0tL/19fX/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/k5OT/2dnZ/9bW1v/g4OD/ + 0tLS/6Ojo//Jycn/6enp/7W1tf9tbW3/oqKi/76+vv+np6f/kpKS/4CAgP9zc3P/ampq/2FhYf9cXFz/ + VlZW/0xMTP8/Pz//NTU1/z8/P/9UVFT/Wlpa/1ZWVv9wcHD/zc3N/+fn5//u7u6uAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALGxsQulpaXkrq6u/8LCwv/a2tr/8PDw//v7+//09PT/5OTk/83Nzf+6urr/uLi4/9zc3P/Q0ND/ + 3Nzc/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/4+Pj/9nZ2f/U1NT/3t7e/9bW1v+hoaH/w8PD/+Xl5f/Hx8f/bW1t/4SEhP+vr6// + lZWV/4CAgP9ycnL/bGxs/2tra/9ubm7/cHBw/3Jycv9ycnL/a2tr/2JiYv9VVVX/UVFR/0lJSf9AQED/ + Pj4+/3Fxcf+9vb3/3d3d/7+/v0sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKysrH2srKz/uLi4/83Nzf/l5eX/ + 9vb2//v7+//t7e3/2dnZ/8zMzP+oqKj/0tLS/9TU1P/Pz8//3t7e/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/X19f/09PT/9zc3P/Y2Nj/ + n5+f/76+vv/h4eH/1dXV/3Nzc/9tbW3/np6e/4iIiP93d3f/cXFx/3Nzc/91dXX/dnZ2/3Z2dv93d3f/ + dnZ2/3V1df9ycnL/cHBw/29vb/9ycnL/cXFx/1xcXP9BQUH/Z2dn/5ycnP/Hx8fjRUVFBwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAtra2Eq2trfSzs7P/wMDA/9jY2P/u7u7/+/v7//f39//p6en/0dHR/8bGxv+kpKT/ + 3d3d/9DQ0P/Pz8//4ODg/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//h4eH/1NTU/9HR0f/c3Nz/2NjY/6CgoP+9vb3/39/f/9bW1v93d3f/X19f/4yMjP+AgID/ + dXV1/3V1df92dnb/d3d3/3d3d/95eXn/fX19/4GBgf+FhYX/hoaG/4WFhf+EhIT/hISE/4SEhP+CgoL/ + fHx8/3d3d/9vb2//f39//1ZWVo0iIiITioqKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsrKyibS0tP+3t7f/ + ycnJ/+Hh4f/09PT//Pz8//Ly8v/l5eX/zs7O/7u7u/+qqqr/3t7e/87Ozv/Ozs7/39/f/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/3t7e/9LS0v/R0dH/3Nzc/9LS0v+dnZ3/ + vb29/97e3v/W1tb/enp6/1hYWP94eHj/d3d3/3V1df93d3f/d3d3/3h4eP97e3v/g4OD/42Njf+Xl5f/ + oqKi/6ioqP+qqqr/qKio/6ioqP+pqan/qqqq/6Wlpf+bm5v/kJCQ/4aGhv99fX3+HBwccwAAACFmZmYD + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAC6uroRtbW167a2tv+8vLz/0dHR/+jo6P/39/f//Pz8/+7u7v/f39// + zc3N/7Ozs/+vr6//3d3d/8zMzP/Nzc3/3d3d/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/9jY2P/Ozs7/0dHR/97e3v/Ly8v/nZ2d/7+/v//f39//19fX/319ff9WVlb/ampq/3Fxcf92dnb/ + d3d3/3h4eP97e3v/g4OD/5KSkv+ioqL/sbGx/7y8vP/Dw8P/xMTE/8HBwf+/v7//wMDA/8TExP/IyMj/ + xcXF/729vf+2trb/qKio/5WVlf96enrqFxcXPkVFRQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4uLhv + ubm5/7i4uP/CwsL/2NjY/+3t7f/6+vr/+vr6/+zs7P/c3Nz/zMzM/66urv+wsLD/3d3d/8zMzP/Ly8v/ + 2tra/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/8DAwP+goKD/t7e3/9nZ2f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/97e3v/S0tL/zc3N/9TU1P/f39//uLi4/5+fn//FxcX/ + 4+Pj/9bW1v9/f3//WVlZ/2NjY/9tbW3/d3d3/3h4eP95eXn/f39//46Ojv+hoaH/tbW1/8PDw//MzMz/ + z8/P/87Ozv/Kysr/xsbG/8TExP/Hx8f/zc3N/9DQ0P/Q0ND/zs7O/87Ozv/IyMj/tra2/5+fn/97e3vF + Tk5OCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6urrAu7u7/7e3t//Gxsb/3d3d//Dw8P/7+/v/ + +fn5/+vr6//b29v/y8vL/62trf+tra3/3Nzc/83Nzf/Jycn/0tLS/9/f3//g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/kZGR/6ysrP/FxcX/zc3N/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/9/f3//W1tb/ + zMzM/8zMzP/Y2Nj/2tra/6Wlpf+oqKj/zc3N/+jo6P/Y2Nj/g4OD/19fX/9iYmL/ampq/3h4eP95eXn/ + e3t7/4WFhf+YmJj/r6+v/8LCwv/Ozs7/0tLS/9LS0v/Q0ND/zc3N/8rKyv/Kysr/z8/P/9fX1//d3d3/ + 3t7e/93d3f/c3Nz/2tra/9PT0//IyMj/ubm5/6Wlpf+QkJBYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAL+/vxy8vLzvu7u7/7m5uf/Kysr/4ODg//Ly8v/7+/v/+Pj4/+vr6//d3d3/y8vL/7Kysv+hoaH/ + 2NjY/9LS0v/Hx8f/y8vL/9nZ2f/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39// + 39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+enp7/o6Oj/7y8vP/Nzc3/ + 39/f/9/f3//f39//39/f/9/f3//X19f/zc3N/8vLy//S0tL/3d3d/8PDw/+ZmZn/tbW1/9fX1//u7u7/ + 09PT/4mJif9paWn/ZWVl/2JiYv92dnb/eHh4/3t7e/+IiIj/n5+f/7m5uf/Ly8v/0tLS/9TU1P/T09P/ + 0dHR/8/Pz//S0tL/19fX/97e3v/k5OT/6urq/+zs7P/s7Oz/6+vr/+vr6//p6en/4eHh/9LS0v/FxcX/ + u7u7/6enp80AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL6+vli9vb3/ubm5/7u7u//MzMz/ + 4eHh//Ly8v/7+/v/+Pj4/+zs7P/h4eH/zs7O/7m5uf+cnJz/x8fH/9jY2P/Ly8v/xsbG/83Nzf/Z2dn/ + 39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39// + 39/f/9/f3//f39//39/f/9nZ2f+6urr/xsbG/93d3f/f39//39/f/97e3v/V1dX/zMzM/8nJyf/Ozs7/ + 2dnZ/9XV1f+mpqb/oaGh/8TExP/i4uL/8PDw/8vLy/+RkZH/dnZ2/2pqav9aWlr/cHBw/3V1df96enr/ + iIiI/6Ojo/+9vb3/zc3N/9PT0//S0tL/0tLS/9DQ0P/T09P/2tra/+Hh4f/o6Oj/7u7u//Ly8v/19fX/ + 9vb2//b29v/29vb/9fX1//Ly8v/r6+v/4ODg/9HR0f/FxcX/u7u7/7Kysi8AAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAL6+vnq9vb3/t7e3/7u7u//MzMz/4eHh//Hx8f/6+vr/+vr6/+7u7v/m5ub/ + 0tLS/8LCwv+fn5//q6ur/9jY2P/U1NT/yMjI/8XFxf/Ly8v/1dXV/93d3f/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/9jY2P/Q0ND/ycnJ/8jIyP/Nzc3/2NjY/9nZ2f+wsLD/mJiY/7a2tv/V1dX/7Ozs/+7u7v+9vb3/ + nZ2d/4mJif9zc3P/WFhY/2NjY/93d3f/dnZ2/4KCgv+enp7/urq6/8nJyf/Pz8//z8/P/87Ozv/Ozs7/ + 1tbW/+Dg4P/o6Oj/7+/v//T09P/4+Pj/+vr6//v7+//8/Pz//Pz8//z8/P/7+/v/+fn5//T09P/q6ur/ + 3t7e/87Ozv/FxcX/vb29cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL29vaK7u7v/ + t7e3/7u7u//Ly8v/3t7e/+7u7v/5+fn/+/v7//Hx8f/q6ur/2tra/8rKyv+zs7P/l5eX/7W1tf/b29v/ + 1NTU/8nJyf/ExMT/xcXF/8zMzP/U1NT/29vb/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/c3Nz/1tbW/8/Pz//Jycn/x8fH/8jIyP/Q0ND/2dnZ/9fX1/+wsLD/ + mJiY/6+vr//MzMz/5OTk//Hx8f/f39//s7Oz/6Wlpf+YmJj/gICA/19fX/9RUVH/cnJy/4ODg/9/f3// + lpaW/7Ozs//FxcX/ysrK/8vLy//Ly8v/zc3N/9jY2P/k5OT/7e3t//T09P/4+Pj/+/v7//39/f/9/f3/ + /v7+//7+/v/+/v7//v7+//7+/v/9/f3/+vr6//Ly8v/o6Oj/2tra/8zMzP/ExMSrAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv7+/B7u7u6S5ubn/tbW1/7q6uv/IyMj/2tra/+vr6//29vb/ + /Pz8//b29v/s7Oz/5eXl/9XV1f/FxcX/rKys/5eXl/+xsbH/1tbW/9fX1//Pz8//x8fH/8TExP/ExMT/ + xsbG/8vLy//Ozs7/0dHR/9PT0//U1NT/1tbW/9XV1f/T09P/0dHR/9DQ0P/Ly8v/x8fH/8XFxf/FxcX/ + yMjI/87Ozv/V1dX/3Nzc/8nJyf+oqKj/lpaW/6+vr//Jycn/4eHh//Dw8P/u7u7/y8vL/66urv+oqKj/ + mpqa/4qKiv9tbW3/T09P/2NjY/9+fn7/kZGR/5SUlP+urq7/wsLC/8nJyf/Kysr/ysrK/87Ozv/b29v/ + 5+fn//Dw8P/39/f/+/v7//39/f/9/f3//v7+//////////////////////////////////7+/v/9/f3/ + +Pj4/+/v7//j4+P/09PT/8zMzMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALq6upK2trb/tLS0/7e3t//Dw8P/1NTU/+Xl5f/y8vL/+fn5//v7+//z8/P/6+vr/+Pj4//U1NT/ + xMTE/6+vr/+Xl5f/o6Oj/7+/v//a2tr/2dnZ/9PT0//Ozs7/ysrK/8fHx//ExMT/xMTE/8TExP/FxcX/ + xcXF/8XFxf/FxcX/xsbG/8rKyv/Pz8//09PT/9nZ2f/d3d3/x8fH/66urv+Xl5f/nZ2d/7a2tv/Nzc3/ + 4uLi/+/v7//y8vL/29vb/7u7u/+ysrL/o6Oj/5CQkP+Ojo7/fX19/15eXv9GRkb/dnZ2/4+Pj/+ioqL/ + srKy/8TExP/Ozs7/z8/P/8/Pz//S0tL/3t7e/+np6f/y8vL/+Pj4//z8/P/9/f3//v7+//////////// + //////////////////////////////////////7+/v/7+/v/9PT0/+rq6v/c3Nz/09PT1gAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALi4uHGzs7P8sLCw/7S0tP+/v7// + zc3N/93d3f/r6+v/9fX1//v7+//6+vr/8vLy/+vr6//l5eX/19fX/8rKyv+6urr/pqam/5OTk/+cnJz/ + q6ur/76+vv/MzMz/29vb/9zc3P/b29v/2tra/9jY2P/Z2dn/29vb/9zc3P/d3d3/z8/P/76+vv+vr6// + oKCg/5OTk/+enp7/sbGx/8bGxv/Y2Nj/6Ojo//Hx8f/z8/P/4uLi/8TExP+3t7f/r6+v/5OTk/+Ghob/ + ioqK/4WFhf9xcXH/UlJS/1BQUP99fX3/n5+f/7S0tP/Nzc3/09PT/9fX1//X19f/2NjY/+Hh4f/s7Oz/ + 8/Pz//n5+f/8/Pz//f39//7+/v////////////////////////////////////////////////////// + /v7+//z8/P/4+Pj/8PDw/+Xl5f/c3NzXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALi4uDyvr6/irKys/66urv+5ubn/xcXF/9PT0//h4eH/7e3t//X19f/5+fn/ + +vr6//T09P/t7e3/6enp/+Hh4f/W1tb/zMzM/7+/v/+0tLT/p6en/5ubm/+RkZH/lJSU/5mZmf+Wlpb/ + np6e/5eXl/+VlZX/lJSU/4+Pj/+ZmZn/paWl/7CwsP++vr7/zMzM/9nZ2f/m5ub/7+/v//Pz8//y8vL/ + 4eHh/8jIyP+6urr/uLi4/5ubm/+AgID/gYGB/4ODg/+Ghob/f39//2pqav9JSUn/X19f/4qKiv+rq6v/ + xcXF/9zc3P/b29v/2tra/9vb2//h4eH/6+vr//Pz8//4+Pj//Pz8//39/f/+/v7///////////////// + ///////////////////////////////////////////+/v7//f39//n5+f/09PT/7e3t/+bm5ssAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALe3txKrq6ud + pqam/6Wlpf+vr6//vLy8/8fHx//T09P/39/f/+jo6P/v7+//9PT0//f39//19fX/8PDw/+vr6//o6Oj/ + 5eXl/+Dg4P/Y2Nj/0tLS/9DQ0P/Kysr/xsbG/8TExP/Dw8P/xcXF/8vLy//Nzc3/0dHR/9bW1v/e3t7/ + 5ubm/+zs7P/x8fH/8/Pz//T09P/u7u7/3Nzc/8TExP+6urr/u7u7/6urq/+Ojo7/goKC/39/f/9/f3// + gICA/4KCgv98fHz/ZmZm/0VFRf9tbW3/mpqa/7m5uf/T09P/4+Pj/+Pj4//a2tr/3d3d/+jo6P/x8fH/ + 9/f3//v7+//9/f3//v7+//////////////////////////////////////////////////////////// + //////7+/v/8/Pz/+fn5//T09P/v7+//7e3trAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvr689oqKi0J2dnf+enp7/q6ur/7m5uf+/v7// + xsbG/8/Pz//X19f/3d3d/+Pj4//n5+f/6+vr/+zs7P/r6+v/6+vr/+rq6v/q6ur/6enp/+np6f/p6en/ + 6Ojo/+vr6//t7e3/7+/v//Hx8f/y8vL/8/Pz//T09P/09PT/8vLy/+zs7P/g4OD/zMzM/7q6uv+2trb/ + ubm5/7i4uP+qqqr/nZ2d/5OTk/+Kior/g4OD/39/f/9/f3//gICA/3t7e/9lZWX/RUVF/3V1df+qqqr/ + x8fH/9/f3//p6en/6+vr/+Tk5P/m5ub/7u7u//X19f/6+vr//f39//7+/v////////////////////// + /////////////////////////////////////////////////v7+//z8/P/4+Pj/8/Pz/+/v7//u7u6A + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACsrKwCpKSkWJeXl+ORkZH/jY2N/5CQkP+YmJj/oqKi/6ampv+srKz/s7Oz/7q6uv/BwcH/ + x8fH/83Nzf/S0tL/19fX/9zc3P/g4OD/5OTk/+fn5//q6ur/7Ozs/+7u7v/v7+//7u7u/+3t7f/q6ur/ + 5ubm/9XV1f/Dw8P/tbW1/62trf+xsbH/ubm5/8jIyP/Kysr/wsLC/7a2tv+rq6v/oKCg/5WVlf+MjIz/ + hYWF/4CAgP9/f3//e3t7/2dnZ/9HR0f/d3d3/7W1tf/Pz8//5eXl/+zs7P/u7u7/8PDw//Dw8P/z8/P/ + +Pj4//z8/P/+/v7///////////////////////////////////////////////////////////////// + //////7+/v/9/f3//Pz8//n5+f/7+/v/7+/v//Dw8EUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoaGhApSUlIGAgID5 + dnZ2/2VlZf9eXl7/Y2Nj/25ubv96enr/hYWF/4uLi/+RkZH/mJiY/56env+kpKT/qqqq/7CwsP+1tbX/ + u7u7/8HBwf/FxcX/ycnJ/8fHx/+8vLz/srKy/6enp/+enp7/n5+f/6Wlpf+wsLD/ycnJ/9/f3//p6en/ + 4uLi/9nZ2f/Q0ND/xMTE/7q6uv+urq7/o6Oj/5iYmP+Pj4//h4eH/4GBgf98fHz/bGxs/05OTv93d3f/ + vb29/9TU1P/l5eX/6+vr/+3t7f/x8fH/9/f3//n5+f/7+/v//f39//7+/v////////////////////// + ///////////+/v7/+/v7//n5+f/9/f3//////////////////v7+//z8/P/7+/v//f39//n5+f/x8fHz + 8vLyBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGtraydsbGy4W1tb/lBQUP9ISEj/QkJC/0FBQf9BQUH/ + SEhI/05OTv9TU1P/WVlZ/1xcXP9jY2P/Y2Nj/2hoaP9paWn/aGho/2hoaP9paWn/bW1t/3Z2dv+AgID/ + j4+P/6mpqf/Ly8v/6Ojo//n5+f/5+fn/9vb2//Hx8f/r6+v/5OTk/9zc3P/S0tL/yMjI/729vf+ysrL/ + pqam/5ubm/+QkJD/h4eH/319ff9vb2//U1NT/3R0dP/Dw8P/2NjY/+Xl5f/p6en/7Ozs//Ly8v/39/f/ + /Pz8//7+/v/+/v7//////////////////////////////////f39/+7u7v++vr7/m5ub/+bm5v/+/v7/ + //////7+/v/9/f3//f39//7+/v/9/f3/8vLy//Hx8aQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzc3Mk + cXFxbldXV69dXV3rWVlZ/1hYWP9WVlb/VVVV/1NTU/9QUFD/TU1N/0hISP9FRUX/QkJC/0BAQP9AQED/ + QkJC/0lJSf9TU1P/X19f/3BwcP+Dg4P/mJiY/7S0tP/MzMz/2NjY/+Xl5f/u7u7/9vb2//n5+f/5+fn/ + 9/f3//Pz8//t7e3/5+fn/97e3v/V1dX/y8vL/7+/v/+ysrL/paWl/5aWlv+IiIj/eXl5/2lpaf9TU1P/ + bW1t/8bGxv/c3Nz/6Ojo/+rq6v/t7e3/9fX1//v7+//9/f3//v7+//////////////////////////// + ///////////09PT/wsLC/5KSkv9YWFj/kpKS//v7+/////////////7+/v/+/v7//f39//j4+P/o6Oj/ + 8fHxOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB6enodaGhotGpqav1sbGz/bm5u/3BwcP9ycnL/c3Nz/3R0dP9zc3P/ + cXFx/29vb/9sbGz/aWlp/2VlZf9gYGD/W1tb/1VVVf9VVVX/Xl5e/25ubv+BgYH/jY2N/5KSkv+ZmZn/ + oaGh/6urq/+4uLj/yMjI/9jY2P/m5ub/8PDw//b29v/5+fn/9/f3//Pz8//u7u7/5+fn/97e3v/S0tL/ + xcXF/7W1tf+kpKT/kpKS/35+fv9tbW3/Xl5e/1VVVf9qamr/wcHB/+Dg4P/q6ur/7e3t//Ly8v/4+Pj/ + /Pz8//7+/v////////////////////////////////////////////n5+f/k5OT/ysrK/35+fv9gYGD/ + 8vLy//////////////////7+/v/9/f3/7e3t/+fn58AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfHx8GHJyct51dXX/ + d3d3/3t7e/+BgYH/iYmJ/5CQkP+Tk5P/k5OT/5GRkf+Pj4//jIyM/4qKiv+Hh4f/hISE/4GBgf9+fn7/ + eHh4/3Jycv9ra2v/YmJi/1hYWP9WVlb/Z2dn/319ff+MjIz/kpKS/5qamv+oqKj/uLi4/8rKyv/b29v/ + 6enp//Hx8f/z8/P/8PDw/+rq6v/g4OD/1dXV/8fHx/+4uLj/paWl/5OTk/+BgYH/dHR0/21tbf9ubm7/ + dXV1/3t7e/+zs7P/4+Pj/+7u7v/x8fH/9fX1//v7+//9/f3//v7+//////////////////////////// + /////////////////v7+//f39//t7e3/q6ur/2VlZf/p6en///////////////////////n5+f/v7+/9 + 8fHxOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB2dna1eXl5/3p6ev+BgYH/kZGR/6Ghof+urq7/srKy/7Gxsf+tra3/ + qamp/6ioqP+pqan/qqqq/6qqqv+rq6v/qamp/6ioqP+lpaX/oaGh/5ycnP+VlZX/iIiI/3d3d/9mZmb/ + VFRU/1RUVP9qamr/f39//4WFhf+Pj4//nZ2d/7CwsP/CwsL/0NDQ/9fX1//V1dX/z8/P/8TExP+4uLj/ + rKys/52dnf+SkpL/i4uL/4uLi/+QkJD/mJiY/52dnf+ampr/jo6O/5ubm//m5ub/8PDw//T09P/4+Pj/ + /Pz8//39/f/+/v7//////////////////////////////////////////////////f39//X19f+1tbX/ + v7+///7+/v/////////////////+/v7/+Pj4//X19ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf39/RHt7e/98fHz/ + hISE/5mZmf+zs7P/xMTE/8jIyP/Dw8P/u7u7/7W1tf+2trb/u7u7/7+/v//CwsL/xcXF/8bGxv/Gxsb/ + xcXF/8XFxf/FxcX/xMTE/8TExP+6urr/qKio/5mZmf+Kior/c3Nz/1hYWP9PT0//X19f/2lpaf9wcHD/ + fX19/4+Pj/+hoaH/q6ur/66urv+qqqr/pqam/6Kiov+ioqL/pqam/66urv+5ubn/wsLC/8XFxf+/v7// + r6+v/5iYmP+BgYH/f39//9bW1v/y8vL/9/f3//r6+v/9/f3//f39//7+/v////////////////////// + /////////////////////////////////////////////////////////////////v7+//r6+v/29vbO + 9vb2CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB9fX2vfX19/4KCgv+Xl5f/t7e3/87Ozv/T09P/zc3N/8LCwv+6urr/ + urq6/8LCwv/Kysr/z8/P/9HR0f/T09P/1NTU/9TU1P/U1NT/1NTU/9TU1P/V1dX/1tbW/9DQ0P/FxcX/ + ubm5/7CwsP+oqKj/lZWV/3R0dP9aWlr/UVFR/1hYWP9hYWH/dHR0/4qKiv+enp7/rKys/7W1tf+/v7// + ysrK/9bW1v/i4uL/6Ojo/+fn5//c3Nz/ycnJ/7Kysv+cnJz/jY2N/4+Pj/+lpaX/urq6//Hx8f/5+fn/ + /Pz8//39/f/9/f3//v7+//////////////////////////////////////////////////////////// + //////////////////////39/f/39/f/9PT03vb29h4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh4eHCYCAgPeBgYH/ + j4+P/6+vr//Ozs7/2tra/9XV1f/Ly8v/v7+//729vf/FxcX/0NDQ/9fX1//a2tr/29vb/9vb2//b29v/ + 29vb/9zc3P/c3Nz/29vb/9vb2//Z2dn/1tbW/9DQ0P/FxcX/u7u7/7u7u/++vr7/sbGx/5CQkP9ubm7/ + W1tb/3BwcP+NjY3/sLCw/9DQ0P/k5OT/8PDw//f39//6+vr/+Pj4//Hx8f/j4+P/0dHR/7+/v/+wsLD/ + qKio/7CwsP/FxcX/3Nzc/+np6f7n5+fHzc3N3Pn5+f/9/f3//f39//39/f/+/v7//v7+//////////// + ///////////////////////////////////////////////////////////5+fn/8vLy/+/v78/19fUY + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACIiIgygoKC/4eHh/+fn5//xcXF/9zc3P/e3t7/1dXV/8nJyf/AwMD/ + xcXF/9HR0f/a2tr/39/f/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/39/f/9/f3//f39//39/f/97e3v/d3d3/ + 19fX/87Ozv/CwsL/vb29/8XFxf/Nzc3/w8PD/6Ojo/99fX3/aWlp/5+fn//Jycn/5OTk//Dw8P/v7+// + 6urq/+Dg4P/U1NT/y8vL/8PDw/+/v7//xsbG/9HR0f/e3t7/6urq/vHx8drm5uaE39/fJQAAAADU1NQZ + 4ODgwfn5+f/9/f3//f39//7+/v/+/v7//v7+//7+/v////////////////////////////////////// + ///////////8/Pz/8vLy/+zs7P3t7e2Q8/PzCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuLi0OFhYX/ + j4+P/6+vr//V1dX/5OTk/+Dg4P/V1dX/yMjI/8TExP/Nzc3/2tra/+Li4v/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/f39//1tbW/8jIyP/AwMD/x8fH/9PT0//Z2dn/ + ysrK/6ioqP+Dg4P/fHx8/7e3t//Jycn/z8/P/9DQ0P/Q0ND/0NDQ/9PT0//Y2Nj/4ODg/+rq6v7w8PDo + 9PT0p+Dg4GrS0tIXAAAAAAAAAAAAAAAAAAAAAAAAAADj4+ME6+vrkfLy8v35+fn//f39//7+/v/+/v7/ + /v7+//////////////////////////////////7+/v/6+vr/8fHx/+np6f/n5+e/7u7uNgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj4+PNoiIiP+Xl5f/vb29/+Dg4P/o6Oj/4+Pj/9fX1//Kysr/ + ycnJ/9XV1f/h4eH/5+fn/+np6f/p6en/6Ojo/+jo6P/o6Oj/6Ojo/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+Pj4//a2tr/zc3N/8TExP/Kysr/19fX/+Dg4P/e3t7/x8fH/6CgoP+BgYH/t7e35eXl5cru7u6s + 8vLyq+Li4n/o6Oh76urqc+vr62Xq6uo/4ODgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA7u7uOe7u7rHw8PD88PDw//Hx8f/29vb/+vr6//v7+//8/Pz/+vr6//b29v/x8fH/ + 6urq/+bm5vbk5OSh7OzsOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYmJgN + i4uL+52dnf/Gxsb/5ubm/+zs7P/n5+f/3t7e/9XV1f/X19f/4eHh/+rq6v/v7+//7+/v/+7u7v/t7e3/ + 7Ozs/+zs7P/s7Oz/7Ozs/+vr6//r6+v/6+vr/+vr6//q6ur/5ubm/9zc3P/Pz8//x8fH/87Ozv/b29v/ + 5eXl/+fn5//Z2dn/s7Oz/5CQkP+ampqzu7u7BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO/v7yPt7e1q + 3NzcqNzc3Nfg4ODo5ubm/Ofn5+Xm5ubb5eXls+np6Yfs7OxL8PDwCQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIy4oKCg/8rKyv/r6+v/9fX1//X19f/y8vL/ + 8PDw//Hx8f/09PT/+Pj4//n5+f/5+fn/+Pj4//f39//19fX/9PT0//Ly8v/w8PD/7+/v/+/v7//v7+// + 7+/v/+3t7f/n5+f/3Nzc/8/Pz//Ly8v/1dXV/+Li4v/q6ur/7Ozs/+Li4v+/v7//mJiY/6SkpOS6uroB + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAKGhoUaenp7/x8fH/+7u7v/7+/v//Pz8//z8/P/8/Pz//Pz8//39/f/+/v7//v7+//39/f/9/f3/ + /f39//z8/P/7+/v/+/v7//r6+v/5+fn/9vb2//X19f/z8/P/7+/v/+fn5//a2tr/z8/P/9HR0f/d3d3/ + 6enp/+/v7//x8fH/5+fn/8TExP+bm5v/q6ur2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJiYmKq9vb3/6urq//z8/P/9/f3/ + /v7+/////////////////////////////////////////////v7+//7+/v/+/v7//f39//39/f/9/f3/ + /Pz8//r6+v/19fX/6+vr/9vb2//R0dH/2dnZ/+bm5v/w8PD/9PT0//Pz8//o6Oj/w8PD/5ubm//AwMCa + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAvb29E6urq9jY2Nj/9/f3//39/f/9/f3//f39//7+/v////////////////////// + //////7+/v////////////////////////////7+/v/+/v7//f39//v7+//19fX/7e3t/+jo6P/p6en/ + 8PDw//X19f/39/f/9fX1/+Pj4/+7u7v/mJiY/ru7uzsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyMjIGLq6us/h4eH/ + 9/f3//z8/P/8/Pz//Pz8//7+/v/+/v7////////////4+Pj/4+Pj/+np6f/29vb//v7+//////////// + ///////////+/v7//v7+//z8/P/6+vr/+fn5//n5+f/6+vr/+/v7//r6+v/z8/P/19fX/62trf+lpaW+ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0NDQCczMzJnf39//8vLy//z8/P/6+vr/+vr6//z8/P/+/v7/ + /////+bm5v+enp7/ioqK/6qqqv/7+/v///////////////////////////////////////7+/v/+/v7/ + /v7+//7+/v/+/v7/+/v7/+rq6v/FxcX/oaGh/sPDwz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAANTU1ELU1NTW5+fn//f39//7+/v/+vr6//z8/P/9/f3/7u7u/9XV1f+fn5//kpKS//z8/P////// + //////////////////////////////////////////////////////7+/v/4+Pj/2NjY/6+vr//Dw8Or + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANvb2wTPz89e29vb1+zs7P/4+Pj/ + /f39//39/f/6+vr/8PDw/7e3t//Gxsb//Pz8//39/f/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + ///////////+/v7/+vr6/+bm5v+6urr/v7+/yNvb2w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAADi4uIC5OTkR+Dg4Krx8fH5+/v7//n5+f/z8/P/1tbW//Hx8f/4+Pj/ + +Pj4//n5+f/6+vr/+/v7//z8/P/9/f3//f39//39/f/9/f3/+/v7//Pz8//e3t7/xMTE99LS0ofk5OQH + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAOnp6Q3p6elQ6+vrmObm5tXo6Oj+7u7u//Ly8v/09PT/9fX1//b29v/29vb/9vb2//X19f/y8vL/ + 7u7u/+Xl5f/e3t7+2NjYyuHh4Xbl5eUTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOXl5Qvd3d00 + 3d3dWN/f33ba2tqT2dnZmt3d3bLe3t6y4eHhoOPj45bp6el07u7uR/Pz8xUAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////8Af////// + ////////////4AA//////////////////4AAB/////////////////8AAAP////////////////+AAAD + /////////////////gAAA/////////////////4AAAP/////////////////AAAD//////////////// + /wAAA/////////////////+AAAf///////////////gAAAAP//////////////8AAAAAH/////////// + ///wAAAAAA//////////////gAAAAAAA/////////////AAAAAAAAB///////////+AAAAAAAAAH//// + //////+AAAAAAAAAAP/////////+AAAAAAAAAAA/////////+AAAAAAAAAAAH/////////AAAAAAAAAA + AA///////x0AAAAAAAAAAAAD/////4AAAAAAAAAAAAAAAf////8AAAAAAAAAAAAAAAH////+AAAAAAAA + AAAAAAAB/////gAAAAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAD////+AAAAAAAAAAAAAAAA/////gAA + AAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAH/////wAAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf// + ///4AAAAAAAAAAAAAAP//////AAAAAAAAAAAAAAD//////4AAAAAAAAAAAAAB///////AAAAAAAAAAAA + AAf//////wAAAAAAAAAAAAAH//////4AAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAf//////AAAAAAA + AAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAA//////8AAAAAAAAAAAAAAP//////AA + AAAAAAAAAAAAD//////gAAAAAAAAAAAAAAf/////4AAAAAAAAAAAAAAD/////8AAAAAAAAAAAAAAA/// + ///AAAAAAAAAAAAAAAH/////gAAAAAAAAAAAAAAB/////4AAAAAAAAAAAAAAAP////+AAAAAAAAAAAAA + AAD/////AAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAH////8AAAAAAAAAAAAAAAB/////AAAAAAAA + AAAAAAAAf////wAAAAAAAAAAAAAAAH////4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAA + AAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD// + //4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAA + AAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAA////+AAAAAAAA + AAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAB////+AAAAAAAAAAAAAAAAf////gAA + AAAAAAAAAAAAAH////8AAAAAAAAAAAAAAAB/////AAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAP// + //8AAAAAAAAAAAAAAAD/////gAAAAAAAAAAAAAAA/////4AAAAAAAAAAAAAAAf////+AAAAAAAAAAAAA + AAH/////wAAAAAAAAAAAAAAB/////8AAAAAAAAAAAAAAAP/////gAAAAAAAAAAAAAAD/////4AAAAAAA + AAAAAAAA//////AAAAAAAAAAAAAAAP/////4AAAAAAAAAAAAAAD/////+AAAAAAAAAAAAAAA//////wA + AAAAAAAAAAAAAH/////+AAAAAAAAAAAAAAB//////wAAAAAAAAAAAAAAf/////8AAAAAAAAAAAAAAH// + ////wAAAAAAAAAAAAAB//////+AAAAAAAAAAAAAAf//////wAAAAAAAAAAAAAH//////+AAAAAAAAAAA + AAB///////4AAAAAAAAAAAAAf///////AAAAAAAAAAAAAH///////8AAAAAAAAAAAAB////////wAAAA + AAAAAAAA////////4AAAAAAAAAAAAP///////4AAAAAAAAAAAAH///////8AAAAAAAAAAAAB//////// + AAAAAAAAAAAAA////////gAAAAAAAAAAAAP///////4AAAAAAAAAAAAH///////8AAAAAAAAAAAAD/// + /////AAAAAAAABAAAB////////wAAAAAAAD4AAB////////8AAAAAAAP/gAB/////////AAAAAAP//+A + B/////////4AAAAAD//////////////+AAAAAB///////////////wAAAAAf//////////////8AAAAA + H///////////////gAAAAD///////////////8AAAAA////////////////wAAAAf/////////////// + +AAAAH////////////////4AAAD/////////////////wAAD//////////////////wAH/////////// + //////////////////////////////////////////8oAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDAwMMBgYGFQcHBxcODg4MBgYGAwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAB0AAABFUFBQqJ+fn+caGhpi + AAAAHAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAACYQEBB8 + zMzM+s/Pz/4xMTGIAAAAKgAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + BAQEAgMDAx9ycnLA6enp/729vf4cHBxBBAQEDgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACQAAABEAAAAX + AAAAGQAAABYAAAASAQEBGBwcHGXa2tr739/f/6+vr/ApKSkQDAwMBAAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwEDAwMIAQEBFAAAACMAAAAy + BgYGQw0NDVkNDQ1hDAwMXwcHB1EAAABHAAAAU35+fs7v7+/+0tLS/5mZmdMAAAAmAAAAHQAAABMAAAAK + AAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBgYBBQUFDgAAACYNDQ1L + Ojo6iV9fX76EhIThoKCg962trfyxsbH+r6+v/aenp/iTk5PobGxs0aOjo/3IyMj+xcXF/3Z2drwAAABK + AAAAPgAAADIAAAAkAAAAFgAAAA0AAAAGAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAEAAAABAwMDAQkJCQoBAQEr + IyMja3R0dMK0tLT5zc3N/9nZ2f/Q0ND/0dHR/9PT0//V1dX/1dXV/9PT0//Q0ND/0dHR/9PT0//CwsL/ + r6+v/z8/P6gAAABfAAAAVwAAAE0AAAA/AAAAKgAAABoAAAAUAAAADQAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGBwEBARsAAAAzAAAAPgAAACgAAAAb + AAAAJBAQEFh3d3fCw8PD/NnZ2f7S0tL+09PT/+Xl5f74+Pj+9vb2//Ly8v7w8PD+8fHx//X19f76+vr+ + +Pj4/+Dg4P7Q0ND+2dnZ/7S0tOtGRkaRAAAAWwAAAFUAAABMAAAANgAAAB0AAAAbAAAAFQAAAA8AAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAFk1NTYmZmZnj + MjIytwAAAH8AAABpMjIykLKysvDW1tb/1tbW/9TU1P/y8vL/8vLy/+vr6//m5ub/9PT0//j4+P/6+vr/ + +vr6//b29v/x8fH/7Ozs//Dw8P/8/Pz/4uLi/9TU1P/Pz8/+iYmJxBISEl8AAABPAAAAMgAAABcAAAAb + AAAAGwAAABcAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + IiIiB5SUlKnw8PD+1tbW/3x8fOVRUVHMx8fH/Nzc3P7R0dH+6Ojo//Ly8v7p6en+9vb2/+Hh4f5tbW3+ + 8PDw//7+/v7+/v7+//////7+/v7+/v7+//////n5+f7s7Oz+9fX1//Pz8/7T09P/ycnJ/q+vr+YwMDBu + AAAAMQAAABoAAAAfAAAAHwAAACIAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAKCgoBbMzMzZ5eXl/6Ojo/7Jycn/3t7e/tHR0f7z8/P+6enp//Pz8/7+/v7+ + //////v7+/7S0tL+/v7+//7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+8vLy//Dw8P729vb/ + 1tbW/rS0tP63t7f0RkZGZwAAACkAAAArAAAAKQAAACMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrKwmm5ub7MHBwf7g4OD/0tLS/vT09P7m5ub+ + +/v7//7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+ + //////Pz8/7y8vL/7u7u/tjY2P6Pj4//tbW1+GFhYXoAAAAzAAAAMgAAABEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoqKgWsrKy6OHh4f/U1NT/ + 8/Pz/+bm5v/9/f3///////////////////////////////////////////////////////////////// + ///////////////////////////u7u7/+fn5/97e3v+9vb3/i4uL/7m5ufxqamqJAAAALAkJCQcAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn5+n + 3Nzc/9ra2v7s7Oz/5OTk/vr6+v79/f3+/f39//39/f79/f3+/f39//39/f79/f3+/f39//39/f79/f3+ + /f39//39/f79/f3+/f39//39/f79/f3+/f39//39/f78/Pz/6urq/vT09P7a2tr/m5ub/pycnP7FxcX9 + bGxseSwsLAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJ6enjy/v7/85eXl/9zc3P7o6Oj/8/Pz/vv7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v+ + +/v7//v7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v/7e3t/vb29v7d3d3/ + pqam/tDQ0P6jo6P/4ODg+q+vrzkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAJeXl7jk5OT/2NjY/+7u7v/j4+P/9/f3//f39//39/f/9/f3//f39//39/f/ + 9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39/+1tbX/ + yMjI/+np6f/i4uL/t7e3/97e3v+7u7v/ysrK/+vr69Hi4uIGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5eXJ7e3t/vq6ur+2tra/97e3v7w8PD/9PT0/vT09P709PT+ + 9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+ + 9PT0//T09P6mpqb/yMjI/uTk5P7n5+f/yMjI/s7Ozv7j4+P/urq6/unp6f7w8PBkAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjo6Oftra2v7f39/+4eHh/+/v7/7t7e3/ + 8PDw/vDw8P7w8PD+8PDw//Dw8P7v7+/+7u7u/+vr6/7m5ub+sLCw/8vLy/7u7u7+8PDw//Dw8P7w8PD+ + 8PDw//Dw8P7w8PD+8PDw//Dw8P7w8PD/8PDw/uDg4P7q6ur/z8/P/sHBwf729vb/ubm5/ujo6P7x8fHQ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlZWVyOrq6v/Z2dn/ + 6Ojo//n5+f/y8vL/6enp/+vr6//r6+v/6enp/9nZ2f/Hx8f/oqKi/3t7e/9aWlr/QkJC/2BgYP/MzMz/ + 4ODg/+bm5v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/93d3f/p6en/z8/P/76+vv/8/Pz/ + w8PD/+Li4v/r6+v+7+/vIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTk5MI + pqam+u7u7v7W1tb+6urq//n5+f76+vr/8/Pz/uXl5f7n5+f+0NDQ/1BQUP5RUVH+e3t7/6mpqf6hoaH+ + YmJi/83Nzf7Kysr+tLS0/7u7u/7Y2Nj+3Nzc/+Pj4/7m5ub+5+fn/+fn5/7n5+f/5+fn/tra2v7j4+P/ + ysrK/r+/v/76+vr/zc3N/tra2v7l5eX/7+/vWgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACSkpIvuLi4/+/v7/7Ozs7+8fHx//j4+P74+Pj/+Pj4/vX19f7m5ub+zc3N/8zMzP7h4eH+ + 4eHh/7+/v/5VVVX+0tLS/+Li4v7i4uL+4uLi/9XV1f60tLT+sbGx/9DQ0P7U1NT+2tra/+Hh4f7i4uL/ + 4uLi/tTU1P7b29v/vb29/r6+vv7t7e3/z8/P/tTU1P7h4eH/7+/vgQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACRkZFLw8PD/+7u7v/MzMz/8fHx//b29v/29vb/9vb2//b29v/29vb/ + 7+/v/+Li4v/b29v/w8PD/1lZWf+5ubn/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3d3d/7e3t/+vr6// + wsLC/9XV1f/d3d3/5OTk/+7u7v/Ozs7/pqam/6+vr//R0dH/wsLC/87Ozv/d3d3/7e3tjgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJRXyMjI/+/v7/7Kysr+7u7u/+vr6/7y8vL/ + 8/Pz/vPz8/7z8/P+9PT0//Pz8/7n5+f+q6ur/6SkpP7Z2dn+2tra/9vb2/7b29v+29vb/9vb2/7b29v+ + 29vb/9ra2v7a2tr+xsbG/9DQ0P7x8fH/8/Pz/uvr6/7Ozs7/iIiI/pGRkf6srKz/paWl/sDAwP7U1NT/ + 7OzskAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVlZVVxsbG//Hx8f7Gxsb+ + 6urq/9bW1v7s7Oz/8fHx/vHx8f7x8fH+8PDw/+jo6P7V1dX+0tLS//Hx8f7v7+/+6urq/+Xl5f7j4+P+ + 4+Pj/+Pj4/7j4+P+5ubm/+vr6/7w8PD+8fHx//Hx8f7x8fH/7e3t/tjY2P7Ozs7/dnZ2/oCAgP6Kior/ + gICA/qqqqv7Gxsb/6OjojAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVlZVD + vr6+//Pz8//Kysr/39/f/+3t7f/u7u7/7e3t/+3t7f/t7e3/5OTk/9jY2P/CwsL/7Ozs/+3t7f/t7e3/ + 7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/6Ojo/8fHx/+oqKj/ + iYmJ/4WFhf9+fn7/ZGRk/42Njf+8vLz/5ubmdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACbm5sisbGx//Ly8v7W1tb+0dHR/+jo6P7r6+v/6+vr/uvr6/7m5ub+2tra/7e3t/7k5OT+ + 6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7n5+f/ + 1tbW/szMzP6Kior/nJyc/pCQkP6AgID/Xl5e/nV1df7Dw8P/39/fTQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACfn58BpKSk7Orq6v7k5OT+ycnJ/+Dg4P7o6Oj/6Ojo/ujo6P7n5+f+ + tLS0/9jY2P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+ + 6Ojo/+fn5/7h4eH/w8PD/qenp/6vr6//rKys/p+fn/6AgID/bGxs/nNzc/7Z2dn+29vbFgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApKSkptfX1//z8/P/xsbG/9bW1v/l5eX/ + 5+fn/+fn5//l5eX/x8fH/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5ubm/97e3v/ExMT/x8fH/6SkpP+8vLz/nZ2d/4eHh/9lZWX/fHx8/4qKiv/j4+PJ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6urTL6+vv7x8fH+ + 39/f/8PDw/7Z2dn/5OTk/uTk5P7k5OT+5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+ + 5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+29vb/8nJyf7Ly8v/j4+P/p2dnf56enr/bGxs/mFhYf5NTU3/ + UVFR/peXl/7AwMBuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + sbGxBLOzs9XY2Nj/9PT0/8zMzP/Jycn/2dnZ/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Hh4f/X19f/yMjI/8fHx/+FhYX/f39//3Z2dv98fHz/ + ioqK/46Ojv+NjY3/goKC/3x8fPhNTU0nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALm5uVC+vr796enp/+/v7/7ExMT/ycnJ/tXV1f7g4OD+4ODg/+Dg4P7g4OD+ + 4ODg/+Dg4P7g4OD+4ODg/97e3v7BwcH+3t7e/+Dg4P7g4OD+29vb/9TU1P7BwcH+ysrK/4ODg/5tbW3/ + e3t7/paWlv67u7v/ycnJ/sXFxf7Nzc3/y8vL/rW1tf5qamqCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9vb2gxMTE/+3t7f7t7e3/xcXF/sHBwf7Q0ND+ + 2dnZ/9/f3/7f39/+39/f/9/f3/7f39/+39/f/9vb2/67u7v+29vb/9ra2v7S0tL+ysrK/7y8vP7V1dX+ + kZGR/2ZmZv58fHz/qamp/s3Nzf7S0tL/2dnZ/ufn5/7w8PD/7+/v/t7e3v68vLzxqKioCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+vr4Iu7u7wsTExP/q6ur/ + 8vLy/9PT0/+5ubn/w8PD/8/Pz//R0dH/1tbW/9nZ2f/a2tr/2dnZ/9bW1v/R0dH/0NDQ/8fHx/+7u7v/ + zMzM/9bW1v+jo6P/Z2dn/3p6ev+fn5//yMjI/9DQ0P/m5ub/9/f3//39/f/+/v7//f39//X19f/Z2dn/ + y8vLPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + vLy8Cra2tqy6urr+3d3d/vPz8/7s7Oz+z8/P/7q6uv66urr+vLy8/8DAwP7CwsL+v7+//7y8vP67u7v+ + vLy8/9DQ0P7h4eH+wsLC/5WVlf6BgYH+XFxc/6ampv7Pz8//19fX/uzs7P77+/v//v7+/v7+/v7///// + /v7+/vz8/P7s7Oz/39/fTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALW1tQKvr69kqamp6L6+vv7W1tb+5OTk/+bm5v7i4uL+2tra/9PT0/7S0tL+ + 2dnZ/+Hh4f7n5+f+3Nzc/8nJyf6xsbH+jIyM/4CAgP51dXX+a2tr/8vLy/7k5OT/6enp/vr6+v7+/v7/ + /v7+/v7+/v7//////v7+/v39/f7z8/P/7e3tNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm5ubEIaGho1tbW36a2tr/3p6ev+Li4v/ + mZmZ/6SkpP+rq6v/rq6u/7Gxsf/ExMT/2tra/93d3f/FxcX/p6en/42Njf93d3f/eHh4/9vb2//u7u7/ + +Pj4//7+/v///////v7+/+3t7f/x8fH//v7+//z8/P/29vbw8fHxBgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe3t7N3BwcLltbW31 + b29v/2tra/5iYmL+WVlZ/1ZWVv5ra2v+kZGR/7e3t/7b29v+8/Pz//Ly8v7h4eH+wsLC/5iYmP5vb2/+ + eXl5/+Pj4/7y8vL//f39/v7+/v7//////v7+/snJyf6ioqL//v7+/vz8/P7v7++NAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/f38Q + e3t76piYmP62trb+sLCw/7Kysv61tbX+tLS0/66urv6bm5v+eHh4/2xsbP5/f3/+pqam/8HBwf64uLj+ + q6ur/6ioqP6kpKT+jIyM/9/f3/75+fn//v7+/v7+/v7//////v7+/vn5+f7j4+P//v7+/vn5+d/19fUT + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACEhIRgk5OT/9HR0f/Jycn/xsbG/9jY2P/b29v/29vb/9vb2//V1dX/vr6+/7Gxsf95eXn/ + iIiI/9LS0v/l5eX/4ODg/8zMzP/AwMD+zs7O1dnZ2Z35+fn7/f39//7+/v/////////////////8/Pz/ + 8/Pz1vb29icAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACMjIxytLS0/uPj4/7Nzc3+3d3d/+jo6P7n5+f+5+fn/+bm5v7k5OT+ + zs7O/9DQ0P7R0dH+lJSU+tLS0qnb29uS4eHhhOHh4VzX19cgAAAAAAAAAADu7u5A9PT0wvLy8vb39/f9 + 9fX19vDw8Mzt7e1s8/PzBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdnZ0vwMDA/Pb29v719fX++fn5//r6+v74+Pj+ + 9fX1//Ly8v7s7Oz+09PT/9/f3/7q6ur+qKio+bq6uhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAO/v7w/w8PAb8PDwDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvr6+g/Pz8/79/f3/ + /v7+//z8/P/39/f//v7+//7+/v/5+fn/6+vr//Pz8//t7e3/rq6uyrOzswEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAANvb21fq6urg+vr6//Ly8v6qqqr+/f39//7+/v7+/v7+/v7+//39/f7T09P8xMTERgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAADl5eUI6+vrWfHx8ark5OTh8vLy+vT09P719fX+8vLy8ubm5rrZ2dlG + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq6uoC6enpD+rq6h7t7e0c + 7u7uCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////AAD///// + //8AAP////A//wAA////4B//AAD////gH/8AAP///+Af/wAA///gAB//AAD//wAAA/8AAP/8AAAA/wAA + /wAAAAB/AAD8AAAAAD8AAPgAAAAAPwAA/AAAAAA/AAD+AAAAAD8AAP8AAAAAfwAA/wAAAAB/AAD/AAAA + AH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA + +AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD8AAAA + AD8AAPwAAAAAPwAA/gAAAAA/AAD/AAAAAB8AAP8AAAAAHwAA/4AAAAAfAAD/wAAAAB8AAP/wAAAAHwAA + //AAAAA/AAD/4AAAAD8AAP/gAAAAfwAA/+AAAwD/AAD/4AA/x/8AAP/wAD///wAA//gAf///AAD//AD/ + //8AAP//g////wAAKAAAACAAAABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAEBAQYGBgYPCgoKCgMDAwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAARo6OjtNMTEyaAAAAGgAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwc5OTmE4ODg/1FRUY0CAgIRAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQEBAwAAAAwAAAAXAAAAIwAAACUAAAAgAgICNLe3t+TT09P/QkJCVAUFBQgAAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAwMDDQcHBy8sLCxxUlJSpnNzc8Z+fn7UfHx80GZmZrtaWlrBzs7O/8jIyP8TExNY + AAAAMwAAACEAAAAPAAAABgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgIC + AAAACAAAAAoAAAAFAwMDCg8PDz5jY2Oqubm5883Nzf/b29v/4ODg/+Pj4//i4uL/4ODg/9nZ2f/IyMj/ + rq6u+g8PD2sAAABXAAAARgAAACkAAAAXAAAADQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAcHByJgYGCmFxcXjAAAAFg5OTmIurq68dXV1f/g4OD/7u7u/+/v7//y8vL/8vLy//Ly8v/z8/P/ + 8vLy//Dw8P/b29v/v7+/8EVFRYwAAABQAAAAKwAAABoAAAAYAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAR0dHF9ra2urLy8v8cXFx39PT0/7Y2Nj/7Ozs//Dw8P/7+/v/m5ub//j4+P////// + ///////////+/v7/9PT0//T09P/i4uL/xsbG/nd3d68DAwMsAAAAIAAAACMAAAANAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsrKyOa+vr/bV1dX/2tra/+7u7v/29vb///////////////// + ////////////////////////////////+vr6//Pz8//h4eH/qKio/42NjbkJCQk4AAAALAAAAAMAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjo6MmycnJ9dvb2//t7e3/+fn5//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/9/f3//T09P/Ly8v/k5OT/52dnckKCgoo + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK2trbnf39//6Ojo//Ly8v/8/Pz/ + /Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz/7+/v/+bm5v+0tLT/ + q6ur/7S0tLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJQ31NTU/+Hh4f/m5ub/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/8DAwP/Ly8v/ + 6Ojo/729vf/V1dX/0dHR/+np6VMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ6enprl5eX/ + 5OTk/+rq6v/x8fH/8fHx//Hx8f/x8fH/7+/v/+vr6//Gxsb/7u7u//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 6Ojo/+jo6P/m5ub/t7e3//b29v/Jycn/7e3tzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + s7Oz5ODg4P/t7e3/9/f3/+rq6v/q6ur/2NjY/56env96enr/eHh4/0pKSv+3t7f/1dXV/+Tk5P/p6en/ + 6urq/+rq6v/q6ur/6Ojo/+Hh4f+1tbX//Pz8/8jIyP/t7e3+8PDwIAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAIqKihjIyMj/2tra//Ly8v/4+Pj/9vb2/+jo6P+3t7f/sbGx/9jY2P+EhIT/xcXF/+Tk5P/Q0ND/ + wcHB/8PDw//a2tr/39/f/+Pj4//h4eH/2dnZ/7Ozs//s7Oz/x8fH/+np6f/v7+9PAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAi4uLNNTU1P/V1dX/8vLy//b29v/29vb/9vb2/+/v7//h4eH/lZWV/6ampv/e3t7/ + 3t7e/97e3v/e3t7/1dXV/7+/v/+7u7v/39/f/+rq6v/a2tr/np6e/8HBwf+1tbX/4eHh/+7u7l8AAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACPj4851tbW/9PT0//l5eX/5+fn//Ly8v/y8vL/8PDw/+Dg4P/V1dX/ + 6Ojo/+Pj4//g4OD/4ODg/+Dg4P/j4+P/5+fn/+7u7v/w8PD/7+/v/83Nzf98fHz/jo6O/46Ojv/Kysr/ + 6urqXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJGRkSjNzc3/2tra/+Hh4f/t7e3/7e3t/+zs7P/e3t7/ + ycnJ/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+zs7P/Z2dn/r6+v/4yMjP+BgYH/ + bGxs/6ysrP/n5+dJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5eXBbu7u/bo6Oj/0dHR/+jo6P/p6en/ + 5+fn/7+/v//k5OT/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/5OTk/8rKyv+fn5// + paWl/4iIiP9ubm7/sLCw/uHh4RgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6+vte3t7f/Ly8v/ + 39/f/+bm5v/l5eX/2NjY/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+Hh4f/MzMz/ + ra2t/6+vr/+Ghob/YGBg/3BwcP/Pz8/MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwsLBP + 09PT/+bm5v/IyMj/3t7e/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//d3d3/ + ysrK/6qqqv+BgYH/d3d3/4ODg/9+fn7/bm5u/3t7e3YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALS0tAG8vLzB5ubm/9nZ2f/Hx8f/2dnZ/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/xMTE/93d3f/e3t7/ + 1tbW/8bGxv+urq7/bW1t/42Njf+9vb3/y8vL/9TU1P/R0dH/k5OTwQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAL29vR2/v7/k5+fn/9/f3//CwsL/zMzM/9XV1f/Z2dn/29vb/9ra2v/S0tL/ + 09PT/8PDw//Kysr/vr6+/2xsbP+NjY3/x8fH/9vb2//z8/P/+/v7//n5+f/a2tr/w8PDIQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALm5uSC1tbXM1tbW/+zs7P/W1tb/x8fH/8HBwf+/v7// + wcHB/8fHx//Ozs7/1NTU/6Wlpf+CgoL/dHR0/87Ozv/h4eH/+fn5//7+/v///////v7+//Pz8//h4eEy + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmpqQObm5toioqK7JGRkf+mpqb/ + tbW1/8DAwP/ExMT/zs7O/9PT0//CwsL/mZmZ/3t7e/+SkpL/6urq//f39//+/v7//f39//Ly8v/+/v7/ + 9/f3+O/v7wwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHl5eYl+fn7v + gYGB/3l5ef9ubm7/b29v/4mJif+9vb3/5+fn/97e3v+vr6//gICA/5+fn//y8vL//v7+///////39/f/ + tra2//7+/v/09PScAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgoIy + m5ub/8rKyv/FxcX/1NTU/9XV1f/Pz8//qqqq/3t7e/+YmJj/z8/P/8/Pz//BwcH+vr6+1PLy8ur+/v7/ + /v7+///////+/v7/9/f3xfb29g8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAI2NjUPJycn/3Nzc/+jo6P/s7Oz/6enp/+fn5//Ozs7/2dnZ/6ioqNTV1dVk4ODgUd3d3SEAAAAA + 7e3tHPLy8o309PS58/Pzpe/v71nw8PADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAoaGhBM/Pz8f8/Pz//v7+//r6+v/9/f3/9/f3/+Xl5f/v7+//srKylgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1dXVCuXl5YT39/ftzMzM//z8/P/+/v7//f39/93d3eTDw8Mf + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrq6gXp6ek66urqX+3t7Wnq6upJ + 4eHhCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAD////////h////wP///8H///AA///AAB/wAAAP8AAAD/AAAA/4AAAP+AAAH/gAAB/wAAAP + 8AAAD/AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA/wAAAP8AAAD/gAAAf8AAAH/gAAB/8AAA/+AAAP + /gAIH/4Af///AH///8D//ygAAAAYAAAAMAAAAAEAIAAAAAAAYAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAB0/Pz9vCwsLIwAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQEBAiEhIWDQ0ND9FBQUQAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAEBAQIAAAAOAQEBIQYGBjgFBQU4AAAAMZmZmcu+vr7wDQ0NFgAAAAcAAAAB + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDDAwMKU1NTYuQkJDR + sbGx9cHBwf6/v7/8qKio7cDAwP6KiorYAAAAUAAAADgAAAAaAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAVFRUwMzMzgwAAAEs9PT1/urq679zc3P7l5eX+8vLy/vX19f719fX+9PT0/ufn5/7Q0ND6 + Z2dnqwQEBFQAAAAnAAAAGQAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsbGwy3t7e9Y6OjuvV1dX+ + 5eXl//Pz8/709PT/y8vL///////+/v7+//////j4+P7y8vL/2tra/5OTk9IRERE3AAAAJAAAABMAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqKiohNXV1f7o6Oj/9/f3//7+/v7////////////////+/v7+ + //////7+/v78/Pz/8vLy/8HBwf6WlpbbGhoaRwMDAwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOjo4P + yMjI6OLi4v7z8/P+/Pz8/vz8/P78/Pz+/Pz8/vz8/P78/Pz+/Pz8/vz8/P78/Pz+9PT0/ujo6P6rq6v+ + ra2t22xsbBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn5924ODg/+jo6P729vb/9vb2//X19f729vb/ + 9vb2//b29v/19fX+9vb2//X19f729vb/u7u7/+bm5v7Ly8v/yMjI/+rq6o4AAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAC6urrR4ODg//Ly8v7t7e3/7e3t/+Dg4P69vb3/jY2N/7m5uf/p6en+7e3t/+3t7f7u7u7/ + 7u7u/+Tk5P7Hx8f/29vb/+np6fPi4uIIAAAAAAAAAAAAAAAAAAAAAHFxcQ3Pz8/94ODg//n5+f7x8fH/ + 29vb/5SUlP6xsbH/ioqK/9fX1//Kysr+x8fH/9vb2/7i4uL/5eXl/9vb2/7BwcH/4eHh/93d3f7x8fE3 + AAAAAAAAAAAAAAAAAAAAAHR0dCja2tr+3d3d/vLy8v719fX+8/Pz/ubm5v6bm5v+09PT/t3d3f7d3d3+ + 3Nzc/sbGxv7Ly8v+6enp/t7e3v6bm5v+ubm5/tDQ0P7u7u5HAAAAAAAAAAAAAAAAAAAAAHh4eCba2tr/ + 1tbW/+fn5/7v7+//7Ozs/9bW1v7n5+f/7e3t/+np6f/o6Oj+6enp/+3t7f7v7+//7e3t/8XFxf6BgYH/ + e3t7/66urv7r6+tBAAAAAAAAAAAAAAAAAAAAAHp6egjMzMz61dXV/ufn5/7q6ur+19fX/tfX1/7q6ur+ + 6urq/urq6v7q6ur+6urq/urq6v7p6en+2NjY/qurq/6enp7+c3Nz/qGhof7h4eEYAAAAAAAAAAAAAAAA + AAAAAAAAAAC5ubm84uLi/9bW1v7l5eX/3d3d/+Xl5f7l5eX/5eXl/+Xl5f/l5eX+5eXl/+Xl5f7a2tr/ + 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 + + + + Telldus Scheduler + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmMain.resx b/scheduler/DeviceScheduler/frmMain.resx new file mode 100644 index 00000000..1c9b2bce --- /dev/null +++ b/scheduler/DeviceScheduler/frmMain.resx @@ -0,0 +1,4001 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + 57, 123 + + + 48, 48 + + + + 5 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + + 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 + HdfAfwC8OWB2rvuFqgAAAABJRU5ErkJggg== + + + + 102, 26 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pictureBox3 + + + tabControl1 + + + 3, 3 + + + 638, 249 + + + Beskrivning + + + tabPage3 + + + System.Windows.Forms.StatusStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 300 + + + tabPage2 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage3 + + + linkLabel2 + + + toolStrip1 + + + 188, 22 + + + 870, 24 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewQAA + HsEBw2lUUwAAAWNJREFUOE+N0csvA1EUx/ErsbT1B9jYSfwLrGzYWPkv2LIVSwmJHYloUU00kZDQSFOv + SOrRTFtBK1WPmmpNr760nZnOV0uCours7jm/zz3JvS2AqCtDWHFRbdImWtvrR2+nKvgsK4Xpx4xghCmd + kj3GKNYFahd9VCWNcUJFxbxHD1M8JecmZsOqfDVfQN6DEaWi1UBRIbeNdHI1iqr8BiyL9DJGBEqYcV4O + kaskpjnqIehssCG5RGEL/ZpSkMwG6hSBIVyC4HoDkNjjaRLpIDXL7RiBPtyCecHTXQNQzHIxQnyU2DDn + gxx0YRfszzd+perkZpezXkL9HHazKpjrJKv9CXQd/ziPTrwDLAp8jm/p2i9/b52scDnDQgcTgodoc5BP + JuRtRFlf8yzYM/K5OXjOFB6Tcmdfca15tfQ/gJRZVU15vccOx6amyeYbymU9FArbbC6fTzFNszl4T+Ry + +Z/R984rn0GmMacbOKoAAAAASUVORK5CYII= + + + + &Konfigurera enheter... + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + + Bottom, Right + + + 65, 20 + + + Starta + + + True + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + label3 + + + 108 + + + 9 + + + True + + + Fill + + + tabPage3 + + + mnuAbout + + + notifyIcon1 + + + toolStripMenuItem2 + + + 2 + + + 112, 22 + + + 5 + + + mnuNew + + + toolStrip1 + + + mnuWebsite + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Benämning + + + Välj när och vilka enheter som skall schemaläggas. + + + 59, 20 + + + System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 255 + + + Enheter + + + &Arkiv + + + 111, 232 + + + toolNew + + + 111, 210 + + + 53, 23 + + + 6, 25 + + + 1 + + + toolEdit + + + 482, 13 + + + 6 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAbFJREFUOE9jYCAD + rO/vF9gxc6YGGVoZGO5t3qz/7eixZ1+OHPn3ZsmSQpIMuXf0qPujLVs/P+vr//9swoT/j5ublxJtwI+X + a4If39j6fV9F4/8TXd3/L2RkHFsZEiJKlAH/3q3M+XM96s+nQ37/dy2f/D/X03Otj7ExF0HN//8zMP59 + s6j99+Wgf1922fy/0q/6b0+jZhNQIyNBzTNnzmT9+2rmwj8XvP5/2GD2/3yPws/dDRrxBDWCFOzfP4Xn + 7/PeHb9OOv9/vdTg/6kOxXdbKtUdidJ86fhs8T/Pms/8OGj7/9kczf/HWhTvLi9T1SRK8+OrS1X/PKq4 + 83W72f8Hk1X+H2lSOj4tQ0mMKM2v7m8z/HMv69Wntfr/b/Uq/j/QpLqmN0SGkyjN9fX1LN+eHbz0bpnh + /0vt8v/2Nal04whpUOjDMMLsR7cv5F7e2fd/VZvPy2xvsXxRUQYeoKwAEAsDMSixiEMxyDsgMW4gZoKZ + wGllqrNcX1O2iZmZ2QsoaA/E5kCsD8RqQCwPxBJQjXxAGpSAWJC9BnISOxCDbAVJsgExM9QGwgmGqEDC + owgAr0Wwanw/YAUAAAAASUVORK5CYII= + + + + cmdTurnOn + + + helpToolStripMenuItem + + + Detta program lÃ¥ter dig pÃ¥ ett enkelt sätt hantera schemaläggning av en eller flera enhet(er) samtidigt. + + + 0 + + + 0, 0 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &Hjälp + + + 0, 49 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 337, 24 + + + 856, 509 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + contextMenuStrip2 + + + Välkommen till Telldus Schemaläggare + + + Schemalagda enheter + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + editToolStripMenuItem + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADU + DgAAAk1TRnQBSQFMAgEBBAEAAQwBAAEEAQABEAEAARABAAT/ASEBEAj/AUIBTQE2BwABNgMAASgDAAFA + AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AOQABAQMFAQcDDwQU + ARsDDQERAwMBBBQAAwUBBwMUARwDGgElAxoBJAMYASIDFwEgAxYBHgMUARwDEwEaAxIBGAMNAREDAwEE + EAAc/wH0AvMh/ycAAQEDBAEGJAADAwEEAw0BEQMgAS8DNwFbA0ABcAMyAVEDHQEpAw0BEQMDAQQMAAMU + ARwDPgFrA0oBigNIAYgDRwGDA0UBfQNDAXgDQQFzAz8BbQM7AWUDLwFKAw8BFBAAFP8B+gL5Af8B2gLU + Af8BrgKjAf8B0QLKAf8D/Bn/JAADJQE3A2YBvgMIAQsbAAEBAwcBCgMYASIDMwFSAVECTwGlA1gB3QFS + AlABowNQAZ4DRQF9AzIBUAMcAScDCwEPAwIBAwQAAWcCXAHqAYACaAH1AWcCWAHpAV8CVwHfAV4CWgHV + AVsCWAHLAVsCWQHDAVgCVgG8A1UBtQNTAaoDRgGAAxgBIhAAFP8B8gLvAf8B6wLnAf8BzALAAf8BuAKo + Af8B7wLtGf8UAAMLAQ8DLwFKA0IBdQNBAXQDXwG2A1wBqgMRARcDBAEFEAADAwEEAxEBFwMoATwDSAGG + AV4CWAHlA2QB/wNLAf8DQwH/A1cB3wFSAlABpANPAZwDRAF7ASwCKwFDAwsBDwQAAZICagH5Af8C9AL/ + AuQB/wH9AuMB/wH7AuAB/wH8AuQB/wH9AuUB/wH5AdkB2AH/AcsBxQHZAf8BgwFrAW0B9wNLAY4DGwEm + AwABAQwAFP8B9QHxAfAB/wHvAeoB6QH/AdEBxAHBAf8BwAGxAa4B/wHwAe4B7Rn/CAADJAE1AygBPQNA + AXADmQHmA+EB/wPqAf8D6gH/A+EB/wN5AdUDOAFeAxgBIQMJAQwMAAMOARMDOgFhAVsCWQHDAXMCbwH+ + A2cB/wNiAf8DWgH/A0cB/wNGAf8DQQH/A1oB2wNRAaEDQwF4AxYBHgQAAZICagH5Af8C7gH/AfsC3AH/ + AfwB2QHWAf8B+AHTAdAB/wH5AdUBzwH/AfsB1QHNAf8B9gHLAcUB/wHUAcABzAH/AYQBbAFtAfcDSwGO + AxwBJwMAAQEMABT/AegB6gH0Af8B2wHiAe8B/wGxAbQB0QH/AaQBogG+Af8B8AHvAfEZ/wgAAzIBTwOj + AfQD2gH+A/QB/wPlAf8D/QX/A/wB/wPxAf8DnQHrAzEBTwMSARgMAAFJAkgBhwFtAlQB9wOCAf8DcAH/ + A2QB/wNbAf8DawH/A0YB/wNHAf8DRQH/A0EB/wFaAlUB5AFJAkgBiAMaASQEAAGUAmoB+Qb/AfsB/wFp + AZcB/QH/Ad4B5QH8Af8BWQGIAf0B/wE7AWgB/QH/AVgBgAH6Av8B/AH0Af8BigJtAfcDTQGWAygBPQMO + ARMDBAEFCAAU/wGpAc0C/wGVAdkC/wEfAaIC/wEAAYYC/wHeAeYa/wgAAyUBNwPSAfwD9QH/A/0B/wP9 + Af8D/QH/A/0B/wP9Af8D+wH/A+UB/wOXAfEDJAE2DAABYgJVAe8DiwH/A4EB/wNuAf8BigKLAf8BpAKl + Af8BngKfAf8DiQH/A2AB/wNIAf8DRAH/AVkCVQHrAUUCRAF8AxcBIAQAAY4CbQH3Bv8B+wH/AUgBhgH+ + Af8BxQHYAfwB/wHhAeIB9wH/ARMBUgL/AcMBygH4Av8B/gH6Af8BqwKWAfsDUwGsA0cBgwE1AjQBVQMb + ASYDBQEHBAAQ/wL6Av8BhAHPAv8BqgHpAv8BTAHAAv8BAAGlAv8BqAHKGv8IAANwAbQD5QH/A/QB/wP0 + Af8D8gH/A+gB/wP0Af8D9AH/A+QB/wPgAf8D0AH/A4sBxwwAAWUCUgH0A4cB/wOYAf8BsgK1Af8BgQJz + Af8BVwJMAf8BSQJFAf8BXgJhAf8BhwKIAf8DgQH/A2MB/wFZAk0B8gMuAUgDDQERBAABiQJkAfYE/wFm + AZwC/wEdAYcC/wHJAd0B/QH/AWgBlwH9Af8BvQHOAfkB/wGBAYwBuwH/AYMBhQGHAf8BbAFvAXAB/wFb + AloB2QNSAagDUAGaAz4BawMaASUDAwEEEP8BwgHhAv8BQAHVAv8BSwHUAv8BLgHHAv8BAAGtAv8BJAGd + Av8B7QHyFv8EAAMEAQYDwgH4A/QB/wPtAf8DuAH/A5QB/wOqAf8D0gH/A9wB/wPmAf8D4QH/A9QB/wPW + Af4DFAEcCAABeQJtAfgDzgH/AcMCxAH/AY8CgQH/AcECkgH/AdcCngH/AcsCjgH/AV0CRAH/AYQChwH/ + AX8CfgH+AV4CXAHOA0EBcgMMARADAgEDBAABiQJnAfYI/wFzAaYC/wHdAegB+QH/AcYB2gH4Af8BjwGK + AZkB/wG1AaYBmQH/AfYB1QGvAv8B3wG0Af8B8wHSAawB/wGnAZkBigH/A1kByQNPAZsBNQI0AVUDDQES + DP8B8gH3Av8BbwHYAv8BeAHlAv8BbgHgAv8BUQHXAv8BKwHFAv8BAAGkAv8BoAHEFv8EAAMUARsD1QH/ + A+0B/wP0Af8D6AH/A74B/wPgAf8D3wH/A9cB/wPeAf8D4AH/A5oB/wO7Af8DIQEvCAADMAJMAksBjwFe + AlwBzgF3Am0B/AHqAtkB/wHvAtEB/wHPApYB/wFhAlEB7gNQAZ0DKgFBAwcBCgMBAQIMAAGNAm0B9gH0 + AvcB/wGKAosB/wFmAWQBYQH/Aa4BqAGnAf8BrwKiAf8BwgGwAaMC/wHmAbcC/wHlAbgC/wHmAbkC/wHl + Ab4C/wHpAcAB/wGpAZoBigH/A1IBqQNEAXkDFgEeDP8BwwHoAv8BjgHsAv8BqAHvAv8BnAHrAv8BeQHi + Av8BRgHSAv8BAAG6Av8BAAGgAv8B4wHsEv8EAAMIAQsDzAH8A+IB/wPqAf8D0gH/A+sB/wPrAf8D6wH/ + A+sB/wPpAf8DvAH/A44B/wOLAf4DEgEYEwABAQMNARIDQAFwAVgCVgG5AVICUQGhASwCKwFDAw0BEgMB + AQIUAAFZAlcBwgFhAlwB3AFdAlMB7QFeAloB1QFhAlwB3AF+AXUBdgH6Af0B4gG8Av8B6QHBAv8B8AHG + Af8BsAGhAYQC/wHmAboC/wHnAb8B/wH6AdcBsAH/AVsCWgHZA0gBhQMZASMM/wGmAeoC/wG5AfUC/wHf + AfoC/wHTAfgC/wG1AfEC/wGRAecC/wFXAdIC/wEAAa4C/wG0AdMS/wgAA30BwAPWAf8D4wH/A+EB/wPk + Af8D5AH/A+QB/wPjAf8DyAH/A5UB/wN4Af8DcQHQGwABAQMlATcBNQI0AVUBPwI+AWwDJAE1AxEBFwMD + AQQUAAMGAQgBVgJVAbQBWQJXAb8DUgGpAVwCWAHRAYwBewF8AfwB/wHvAcsC/wH4AdcB/wHPAcQBpQH/ + AUwBTwFXAf8BmAGLAWwC/wHpAbwC/wHoAbsB/wFnAlkB8gNEAXkDFgEeCP8C/gL/AacB7gL/AdsB+wL/ + AfgD/wHlAfwC/wHHAfYC/wGtAe8C/wGSAegC/wE/AcsC/wGqAdMS/wgAAyYBOAPMAfgD0AH/A9gB/wPd + Af8D1AH/A9QB/wPJAf8DhQH/A7sB/wPjAf8DtgHvAwYBCBMAAQEDEAEVAx4BKwNDAXgDQAFwAzoBYQMk + ATUDEAEWAwMBBBsAAQEDAAEBAwABAQFgAlsB1gH/AfIB0wH/Ae4B6QHTAf8BPgE9ATgB/wHoAd0BvAH/ + AkUBPwH/AdMBvgGdAv8B3wG3Af8BXgJaAdgBNQI0AVUDDQESDP8BvgH0Av8B3gH7Av8B7QH9Av8B5AH8 + Av8B0QH3Av8BvAHzAv8BqgHvAv8BeAHcAv8B0QHnEv8MAAMoATwDiwHUA7UB/wO9Af8DxwH/A84B/wOP + Af8DrwH/A/QB/wP7Af8D9QH9AwsBDxAAAwYBCAMQARUDUAGeAVwCWgHNAVsCWQHEAUICQQFzAzMBUwMg + AS4DCAELJAADRAF7Ae0B1gHGAf8BoQGdAY0B/wLpAdMD/wHdAv8B8QHKAv8B8QHCAf8BvwGsAZwB/wFO + Ak0BlQMbASYDAwEEDP8B7gH9Av8BzQH7Av8B5wH9Av8B5AH8Av8B2gH6Av8BzgH3Av8BugHzAv8BowHg + Av8B/QH+Ev8MAAMJAQwDgAHdA6UB/wOgAf8DmwH/A8sB/wOtAf4DtwHvA/4B/wPqAf8DZgGbFAADCAEL + A1ABnQNEAXoBRQJEAXwBSQJIAYcBUQJPAZwBSgJJAYkDFAEbAwMBBCQAAwQBBgFaAlgBwAHvAdoByQL/ + AfgB2AL/AfMBzwL/AesBxQH/AcgBtgGmAf8BWwJZAcQDHQEqAwYBCAQAEP8B6wH+Av8BzwH8Av8B2wH8 + Av8B2gH7Av8BzgH4Av8BzAHyAv8B9wH7Fv8MAAMNARIDxQHxA/MB/wPxAf8D3wH/A0YBcwMUARwDBQEH + AzQBUQMqAT8cAAMYASIDVAGuAWsBTQFCAe8BYQFaAVYB4QNKAYoDEgEYAwQBBSwAAwQBBgNEAXsBYAJb + AdYBfQJqAfQBXQJZAdcBRwJGAYADEgEYAwQBBQgAFP8B+gP/Ad8B/QL/Ad4B/AL/AeoB+x7/EAADGQEj + A1cBiwN7AbEDWQGNAwUBBxwAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/+BAAH4 + AR8BAAEPAgAB/wGfAfABBwEAAQ8CAAH/AY8BwAEBAQABDwIAAfgBBwGAAQEBAAEHAgABwAEDAYABAQEA + AQcCAAHAAQMBgAEBAQABAwIAAcABAwGAAQEBAAEBAgABwAEDAYABAQQAAYABAQGAAQEEAAGAAQEBgAEH + BAABgAEBAeABHwQAAcABAwHwAR8EAAHAAQEB4AEPAcADAAHgAQEB4AEPAfgDAAHgAQMB4AEPAfgBAQIA + AeABBwHwAR8B/AEDAgAB8AF/FgAL + + + + label4 + + + Microsoft Sans Serif, 14.25pt + + + 6, 13 + + + tabPage3 + + + toolStripMenuItem1 + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + imageList1 + + + 73, 22 + + + tabPage3 + + + 4 + + + 3 + + + &Ta bort + + + Fill + + + &Redigera + + + True + + + Magenta + + + 169, 22 + + + 8 + + + mnuExit + + + 5 + + + 4, 22 + + + mnuRunTask + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 110, 6 + + + menuStrip1 + + + 132, 13 + + + 169, 22 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader5 + + + 856, 509 + + + 2 + + + + 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 + + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 870, 22 + + + notifyIcon1 + + + CenterScreen + + + System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Startar + + + 7 + + + 109 + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + 54, 56 + + + 6 + + + toolRemove + + + tabPage1 + + + True + + + 10 + + + fileToolStripMenuItem + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewQAA + HsEBw2lUUwAAAUxJREFUOE+VU12rglAQ7EL//1f0oI+9mNSLQg9BQRJRGUZBQdiHGib2ZXObvRy4pRYN + HNTjzOye3bM/eKBSgCzLKupXtVotovzt0eA/HkJcr1dZl8sFaZoijmPcbrdXqnw/GVB8Pp+FTAO+K4PV + aoX7/Z4zeTI4Ho8iVFkocRiGWCwW2G637w1IZNqMRKMkScA93/cxHA7hed57A0agiCan0wmHw0HEruvC + sqzPBrvdDlxRFMmT56a40+mg0WjI/iueasCos9kM6/Uay+VSIvb7fTSbTQwGg89dIIPi6XQqy3EcSd0w + DDlaEXL3gC0cj8dS8V6vh1arhdFoVCjO3QPFmkwmmM/nME0TmqZJPcqQy4BEVUBG13VdWvmVAdu32WzQ + brdRr9cRBMF3BozIYtq2LRns9/vvDDgDvHm1Wg3dbrd0kEqLqMJxCj/hF5B2pm1BgCdyAAAAAElFTkSu + QmCC + + + + Fill + + + 48, 48 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &Ta bort + + + 255 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AwMDAQoKCgEQEBACFBQUAhUVFQEVFRUCFhYWAhcXFwEWFhYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAYDAwMHCQkJCgYGBgsAAAANAAAAEAAAABAAAAAP + FBQUCxISEggeHh4EEhISAgcHBwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAUAAAAK + AAAAEAAAABcAAAAdAAAAIwAAACsAAAAxAAAAMQAAAC0AAAAlAAAAGgAAAA8FBQUJBwcHBgEBAQMAAAAB + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAIAAAADgAAABcAAAAiAAAALQAAADgAAABIEhISZGJiYruBgYHc + YGBguBYWFl0AAAA1AAAAJQAAABkAAAAPAAAACQAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAABgAAAAwAAAAZ + AAAAJQAAADYAAABHAAAAWwEBAXN6enrhvLy8/8jIyP+urq7/eXl57AsLC1YAAAA7AAAAKgAAABwAAAAR + AAAACAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAHAAAAEQAAACAAAAAyAAAARAAAAF0AAAB6NDQ0sru7u//j4+P/ + 4+Pj/8nJyf+YmJj/Ly8vkwAAAEoAAAA5AAAAKAAAABcAAAAMAAAABQAAAAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAgAAAAS + AAAAIAAAADQAAABJAAAAaQQEBI+Ojo7w29vb/+zs7P/i4uL/ysrK/5ycnP8sLCyPAAAATgAAAD0AAAAr + AAAAGgAAAA4AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAAAA4AAAAZAAAAKgAAAEgAAAByQUFBvcPDw//r6+v/ + 6urq/9zc3P/Dw8P/lpaW/x0dHWoAAABEAAAANQAAACYAAAAXAAAADAAAAAQAAAABAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAD + AQEBCAAAABIAAAAjAAAASgsLC32amprz4ODg/+/v7//l5eX/1tbW/7u7u/+KiorzAgICPwAAADIAAAAl + AAAAGgAAABEAAAAIAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgENDQ0EAAAACgAAACQAAABTUlJSt8nJyf/u7u7/ + 7e3t/9/f3//Pz8//srKy/35+fs0AAAAkAAAAHgAAABUAAAANAAAABwAAAAQAAAACAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAC + BwcHAhYWFgQICAgPAAAANRISEm6lpaX35OTk//Ly8v/o6Oj/2dnZ/8nJyf+rq6v/dnZ2nQAAAA8AAAAM + FBQUCAoKCgUAAAADAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAACAAAAAwAAAAQAAAAGAAAACAAAAAkAAAAK + AAAACgAAAAkAAAAJAAAABwAAAAcAAAAGAAAABgEBAQcGBgYIAAAADgAAACUAAABRYWFhv87Ozv/y8vL/ + 8PDw/+Li4v/U1NT/w8PD/6ioqP9FRUVtWlpaBEBAQAMlJSUDCwsLAQAAAAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwEBAQQAAAAG + AAAACAAAAAsAAAAPAAAAEwAAABYAAAAZAAAAGgAAABoAAAAaAAAAGgAAABgAAAAWAAAAFAAAABMAAAAT + AAAAFQAAABgAAAAjAAAARBsbG3murq776Ojo//b29v/r6+v/3Nzc/8/Pz/++vr7/qqqq/zs7O0IrKysH + KysrBSAgIAMHBwcCAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQEBAQICAgICAgIEAQEBBwEBAQsAAAAPAAAAEwAAABYAAAAbAAAAHwAAACUAAAApAAAALAAAAC4AAAAw + AAAAMAAAADAAAAAuAAAALAAAACkAAAAnAAAAJgAAACYAAAAoAAAALQAAAEIAAABgb29vzdPT0//19fX/ + 8/Pz/+Xl5f/W1tb/y8vL/7y8vP+qqqr+ICAgIgAAABMAAAAPAAAADAAAAAoAAAAHAAAABQAAAAMAAAAC + AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBBwcHAwcHBwUCAgIKAAAADgAAABMAAAAYAAAAHwAAACYAAAAq + AAAALgAAADIAAAA4AAAAPQAAAEAAAABDAAAARQAAAEYAAABGAAAARgAAAEQAAABBAAAAPgAAAD0AAAA8 + AAAAPAAAAD8AAABHAAAAXiQkJIuysrL+6urq//j4+P/u7u7/39/f/9HR0f/Hx8f/wsLC/52dneMAAAAk + AAAAIAAAABwAAAAZAAAAFgAAABMAAAAPAAAACwAAAAgAAAAGAAAABAAAAAIAAAABAAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAEICAgCCQkJBQcHBwkAAAAQ + AAAAFwAAAB0AAAAlAAAALAAAADMAAAA5AAAAPwAAAEIAAABHAAAATAAAAFAAAABVAAAAWAAAAFkAAABb + AAAAXAAAAF0AAABcAAAAWQAAAFcAAABVAAAAUQAAAFIAAABSAAAAVQAAAF8AAABub29v28vLy//x8fH/ + 8/Pz/+jo6P/Z2dn/zc3N/8XFxf/MzMz/g4ODwAAAADEAAAAuAAAAKgAAACYAAAAjAAAAHwAAABsAAAAX + AAAAEgAAAA8AAAALAAAACAAAAAUAAAAEAAAAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAcHBwENDQ0DBwcHBwAAAA4AAAAVAAAAHwAAACgAAAAxAAAAOAAAAEEAAABIAAAATgEBAVQmJiZw + PT09l0VFRa9bW1vEZGRk2GxsbOtubm70bGxs+mxsbPpra2v5bGxs92lpaepqamroZGRk1VVVVcE8PDyr + NTU1lSAgIHkAAABqAAAAcCIiIpuQkJD/ysrK/+bm5v/o6Oj/39/f/9PT0//Jycn/ysrK/87Ozv9XV1ej + AAAAQAAAADwAAAA4AAAANAAAADAAAAAsAAAAJwAAACMAAAAdAAAAGQAAABUAAAARAAAADQAAAAoAAAAH + AAAABQAAAAMAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQEQEBAECQkJCAAAABAAAAAaAAAAJgAAADEAAAA8 + AAAARQAAAE0JCQlYPT09iFdXV7V+fn7gg4OD+35+fv96enr/eXl5/4GBgf+Li4v/lZWV/5ubm/+kpKT/ + paWl/6Wlpf+lpaX/m5ub/52dnf+RkZH/hYWF/319ff+Dg4P/iIiI/4eHh/FwcHDOampq6ZGRkf+3t7f/ + y8vL/9HR0f/Ozs7/yMjI/8TExP/X19f/w8PD/zk5OYsAAABNAAAASQAAAEUAAABBAAAAPAAAADgAAAAz + AAAALgAAACgAAAAjAAAAHgAAABkAAAAUAAAAEQAAAA4AAAALAAAACAAAAAYAAAADAAAAAgAAAAEAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQERERED + CgoKCAAAABEAAAAdAAAAKwAAADgAAABEAAAATxMTE2FKSkqdfHx8zJSUlPqOjo7/jo6O/5ubm/+np6f/ + uLi4/87Ozv/i4uL/6Ojo/+zs7P/t7e3/7e3t/+zs7P/s7Oz/6+vr/+vr6//s7Oz/7e3t/+3t7f/t7e3/ + 5+fn/9nZ2f/Hx8f/tLS0/6Ghof+ZmZn/np6e/6Ojo/+rq6v/sbGx/7S0tP+0tLT/uLi4/9bW1v+qqqr/ + IiIidgAAAFkAAABVAAAAUQAAAE0AAABIAAAAQwAAAD4AAAA5AAAAMwAAAC4AAAAoAAAAIgAAABwAAAAX + AAAAFAAAABIAAAAPAAAACwAAAAkAAAAGAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8BERERBgAAAA8AAAAdAAAALQAAADwAAABLAAAAVzw8PIV1dXXB + oaGh+Zubm/+goKD/r6+v/8LCwv/V1dX/4ODg/+fn5//s7Oz/6urq/+bm5v/i4uL/29vb/9TU1P/Pz8// + y8vL/8bGxv/ExMT/xcXF/8rKyv/MzMz/0NDQ/9bW1v/e3t7/4+Pj/+jo6P/r6+v/7Ozs/+Hh4f/IyMj/ + tLS0/6mpqf+rq6v/paWl/5qamv+rq6v/vr6+/4mJifoEBARlAAAAYAAAAF0AAABaAAAAVwAAAFMAAABP + AAAASQAAAEUAAAA+AAAAOAAAADIAAAArAAAAIwAAABwAAAAYAAAAFgAAABQAAAARAAAADwAAAAwAAAAJ + AAAABQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAEAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQMDAwEKCgoBFBQUAwYGBgwAAAAa + AAAAKwAAAD0AAABNAAAAXUlJSZibm5vgqKio/6enp/+2trb/y8vL/9bW1v/c3Nz/5eXl/+rq6v/m5ub/ + 3d3d/9DQ0P/AwMD/rq6u/6Ojo/+qqqr/tbW1/7u7u//Dw8P/yMjI/8zMzP/Ly8v/wcHB/8PDw/+5ubn/ + sLCw/6enp/+jo6P/s7Oz/8fHx//V1dX/4uLi/+np6f/s7Oz/4ODg/8LCwv+zs7P/srKy/62trf+YmJj/ + Xl5e3wAAAGQAAABjAAAAYQAAAF4AAABcAAAAWQAAAFYAAABSAAAATQAAAEgAAABCAAAAOwAAADMAAAAq + AAAAIgAAABsAAAAaAAAAGAAAABYAAAATAAAAEAAAAA0AAAAKAAAABgAAAAMAAAABAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAACAgIBBgYGAgkJCQMCAgIFAgICBgICAgcCAgIIAgICCQEBAQgAAAAIAAAABQAAAAQAAAAE + AAAABAAAAAMBAQEGBQUFBwoKCggAAAATAAAAJAAAADoAAABOAAAAYEZGRpiioqLlr6+v/7Ozs//Dw8P/ + 1NTU/9fX1//f39//6Ojo/+fn5//b29v/yMjI/66urv+np6f/urq6/9DQ0P/q6ur//v7+//////////// + //////////////////////////////////////////////////////z8/P/i4uL/xsbG/7Gxsf+mpqb/ + vLy8/9TU1P/k5OT/6+vr/+bm5v/Nzc3/ubm5/7S0tP96enrVAwMDZQAAAGMAAABhAAAAXgAAAF0AAABb + AAAAWQAAAFYAAABSAAAATgAAAEkAAABDAAAAOwAAADEAAAAmAAAAHgAAABwAAAAbAAAAGQAAABcAAAAU + AAAAEAAAAA4AAAAMAAAACAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAQ0NDQQJCQkIAAAADgAAABMAAAAY + AAAAHgAAACQAAAAoAAAAJwAAACAAAAAXAAAAEgAAABAAAAAOAAAADwAAABIAAAAWAAAAIAAAADEAAABJ + AAAAXzU1NYyenp7ftbW1/7e3t//IyMj/1tbW/9fX1//f39//6Ojo/+Pj4//Q0ND/s7Oz/6ioqP/FxcX/ + 6Ojo//////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////r6+v/U1NT/srKy/66urv/Ozs7/4+Pj/+vr6//l5eX/ + yMjI/7u7u/+pqanhPz8/gwAAAGAAAABeAAAAXQAAAFsAAABZAAAAVwAAAFQAAABRAAAATQAAAEcAAAA/ + AAAANQAAACkAAAAgAAAAHAAAABwAAAAcAAAAGgAAABYAAAATAAAAEQAAABAAAAAMAAAABgAAAAIAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAELCwsFBAQECgAAABUAAAAgAAAAKgAAADYAAABCAAAAUQAAAFoAAABUAAAASAAAADsAAAAx + AAAAKgAAACUAAAAiAAAAJgAAAC8AAAA/AAAAVw4ODnN3d3fCubm5/rq6uv/IyMj/1tbW/9fX1//c3Nz/ + 6Ojo/+Li4v/Kysr/qqqq/7i4uP/i4uL////////////////////////////+/v7/+fn5//Pz8//u7u7/ + 6enp/+jo6P/l5eX/5eXl/+Pj4//l5eX/5ubm/+np6f/t7e3/8vLy//f39//9/f3///////////////// + ////////////////6+vr/7m5uf+srKz/z8/P/+Xl5f/s7Oz/29vb/729vf+9vb3+lJSUwhoaGmUAAABc + AAAAWgAAAFgAAABXAAAAVQAAAFIAAABOAAAASAAAAD8AAAA1AAAAKQAAAB4AAAAaAAAAGwAAABwAAAAc + AAAAGQAAABUAAAATAAAAEwAAABAAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAgMDAwkAAAAUAAAAIwAAADQAAABD + LS0tcDU1NZAMDAyEAAAAiAAAAIUAAAB3AAAAZQAAAFcAAABMAAAARQAAAEEAAABFAAAATwAAAGQ4ODiY + rKys7bu7u//ExMT/1dXV/9jY2P/Z2dn/4+Pj/+Tk5P/Nzc3/q6ur/7+/v//w8PD///////////////// + //////r6+v/x8fH/5+fn/97e3v/d3d3/3d3d/97e3v/j4+P/5eXl/+fn5//o6Oj/6enp/+jo6P/n5+f/ + 5eXl/+Hh4f/f39//39/f/+Dg4P/m5ub/7u7u//n5+f///////////////////////////+7u7v+3t7f/ + tra2/9ra2v/q6ur/5ubm/8PDw/+2trb/yMjI8F5eXo0AAABaAAAAWAAAAFYAAABUAAAAUwAAAE8AAABJ + AAAAPgAAADMAAAAlAAAAGgAAABgAAAAZAAAAHQAAAB4AAAAcAAAAFwAAABUAAAAVAAAAFAAAAA0AAAAF + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAACAgIEAAAADAAAABoAAAAsDAwMQ3l5ecKsrKz/rKys/46OjvIoKCi6AAAApQAAAJgAAACJ + AAAAeAAAAGwAAABmAAAAYgAAAGYAAABzb29vwL29vf6/v7//0NDQ/9nZ2f/Z2dn/3t7e/+fn5//Y2Nj/ + srKy/7y8vP/x8fH//////////////////Pz8//Dw8P/j4+P/3d3d/93d3f/i4uL/7Ozs//T09P/6+vr/ + /v7+//////////////////////////////////////////////////z8/P/39/f/7+/v/+fn5//g4OD/ + 39/f/+Tk5P/w8PD//f39///////////////////////c3Nz/rKys/8zMzP/m5ub/6+vr/8zMzP+ysrL/ + xMTE/6WlpcMUFBRdAAAAVgAAAFQAAABTAAAAUQAAAEoAAAA+AAAAMQAAACIAAAAWAAAAFAAAABcAAAAa + AAAAHgAAAB4AAAAaAAAAFwAAABgAAAAXAAAAEAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgIEBAQKAAAAFgAAAChWVlaN + v7+//9vb2//Z2dn/yMjI/66urv91dXXlJSUlsgAAAJUAAACIAAAAggAAAIAAAACBExMTjpaWluG9vb3/ + xsbG/9jY2P/a2tr/2tra/+Li4v/i4uL/w8PD/6ysrP/j4+P/////////////////+Pj4/+jo6P/d3d3/ + 3d3d/+Xl5f/x8fH/+Pj4/9zc3P/z8/P///////////////////////////////////////////////// + //////////////////////////////////////39/f/z8/P/5+fn/9/f3//g4OD/7u7u//z8/P////// + ///////////5+fn/ubm5/76+vv/i4uL/7Ozs/8/Pz/+tra3/uLi4/9fX1+Y9PT13AAAAVAAAAFMAAABR + AAAASwAAAD8AAAAuAAAAHgAAABQAAAAUAAAAFgAAABoAAAAdAAAAHgAAABwAAAAaAAAAHAAAABsAAAAS + AAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgICAhEREQYAAAAOAAAAGomJia7U1NT/8fHx/+/v7//k5OT/1NTU/8DAwP+np6f+ + cHBw2yEhIZsAAACKAAAAliAgIKmmpqbvvb29/83Nzf/a2tr/29vb/9zc3P/l5eX/2NjY/7CwsP/IyMj/ + /Pz8////////////+Pj4/+Tk5P/c3Nz/3t7e/+zs7P/6+vr///////v7+/9wcHD/YGBg/3p6ev/r6+v/ + //////////////////////////////////////////////////////////////////////////////// + ////////////////+vr6/+rq6v/f39//4eHh//Ly8v//////////////////////zc3N/7W1tf/e3t7/ + 6+vr/9HR0f+np6f/s7Oz/+Li4vyBgYGWAAAAUwAAAFEAAABMAAAAQQAAAC4AAAAdAAAAFQAAABYAAAAZ + AAAAGwAAAB0AAAAdAAAAHAAAAB8AAAAhAAAAHwAAABQAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBHh4eAi8vLwYXFxcL + W1tbe8TExP/v7+//9/f3//Hx8f/o6Oj/3Nzc/8zMzP+vr6//g4OD/kNDQ9swMDDDra2t9729vf/R0dH/ + 29vb/9vb2//e3t7/5OTk/83Nzf+urq7/6Ojo/////////////Pz8/+rq6v/b29v/3t7e/+/v7//9/f3/ + ////////////////z8/P/01NTf9zc3P/hYWF/8PDw/////////////////////////////////////// + //////////////////////////////////////////////////////////////////////r6+v/n5+f/ + 39/f/+bm5v/7+/v/////////////////3t7e/7Ozs//d3d3/6+vr/8rKyv+hoaH/rq6u/9zc3P+mpqa8 + CwsLUgAAAEwAAABBAAAALQAAAB4AAAAZAAAAGgAAAB0AAAAgAAAAHwAAAB0AAAAeAAAAIwAAACcAAAAh + AAAAEwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFxcQN/f38MlpaWxtbW1v/09PT/+Pj4//Ly8v/p6en/ + 2dnZ/7e3t/+Ghob/c3Nz/66urv+8vLz/1dXV/9zc3P/c3Nz/39/f/+Pj4//BwcH/tra2//f39/////// + //////Ly8v/e3t7/29vb/+zs7P/9/f3////////////////////////////p6en/Tk5O/2tra/98fHz/ + 39/f//////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////z8/P/4eHh/+Hh4f/19fX///////////////// + 4uLi/7S0tP/g4OD/7Ozs/8DAwP+ampr/ra2t/9nZ2f/MzMzXKCgoWgAAAD8AAAAuAAAAIwAAACAAAAAg + AAAAIwAAACUAAAAjAAAAHwAAACAAAAApAAAALAAAACMAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACcnJwUoqKi293d3f/29vb/+fn5/+/v7//U1NT/pqam/4qKiv+urq7/urq6/9bW1v/c3Nz/ + 3d3d/+Dg4P/h4eH/urq6/8rKyv/+/v7///////z8/P/m5ub/2tra/+Li4v/4+Pj///////////////// + ///////////////////////////Pz8//np6e/9LS0v////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////6+vr/5eXl/9/f3//x8fH/////////////////4ODg/7i4uP/k5OT/6urq/6ysrP+SkpL/ + q6ur/9bW1v/d3d3kMzMzVwAAAC8AAAAoAAAAJgAAACYAAAApAAAAKwAAACcAAAAiAAAAJQAAAC8AAAAv + AAAAIAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrKwmra2t6+Li4v/19fX/ + 5ubm/76+vv+Xl5f/q6ur/7e3t//X19f/3d3d/93d3f/g4OD/39/f/7a2tv/T09P////////////5+fn/ + 39/f/9ra2v/u7u7//v7+//////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////+/v7/6enp/9/f3//x8fH/ + ////////////////1NTU/8LCwv/n5+f/5OTk/5iYmP+Li4v/pKSk/9TU1P/l5eXuOTk5WAAAACwAAAAr + AAAAKwAAAC8AAAAvAAAAKwAAACYAAAArAAAAMwAAAC4AAAAYAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACQkJA8r6+v+NLS0v/ExMT/oqKi/6Wlpf+xsbH/1tbW/97e3v/e3t7/ + 4ODg/9/f3/+1tbX/2dnZ////////////8fHx/9ra2v/d3d3/9vb2//////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////+/v7/6urq/9/f3//x8fH/////////////////w8PD/9DQ0P/r6+v/ + zs7O/4qKiv+CgoL/n5+f/9HR0f/o6Oj3ZGRkZgAAAC8AAAAwAAAAMgAAADMAAAAtAAAAKwAAADEAAAA1 + AAAAJwAAAA8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJiYlX + kJCQ/pWVlf+goKD/q6ur/9HR0f/f39//39/f/+Hh4f/h4eH/t7e3/97e3v///////////+/v7//Z2dn/ + 4uLi//v7+/////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////+/v7/ + 6enp/9/f3//09PT////////////6+vr/uLi4/97e3v/s7Oz/qqqq/4KCgv9+fn7/m5ub/83Nzf/n5+f8 + iIiIegAAADUAAAA2AAAANAAAADAAAAAxAAAANgAAADEAAAAbAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABycnJ9kJCQ/6SkpP/Kysr/39/f/+Dg4P/h4eH/ + 4+Pj/7y8vP/V1dX////////////t7e3/2NjY/+Tk5P/9/f3///////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////+/v7/5ubm/+Dg4P/7+/v////////////n5+f/ + v7+//+jo6P/j4+P/h4eH/4CAgP9+fn7/mJiY/8rKyv/o6Oj+nJyckwAAADkAAAA1AAAANAAAADcAAAA2 + AAAAJgAAAA8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJ6enmefn5//wcHB/+Dg4P/h4eH/4eHh/+Tk5P/Dw8P/zc3N////////////7e3t/9fX1//m5ub/ + /v7+//////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////8/Pz/4eHh/+Xl5f/+/v7////////////Hx8f/19fX/+zs7P+3t7f/fHx8/4qKiv9/f3// + mJiY/8rKyv/o6Oj/o6OjnwAAADgAAAA5AAAAOgAAADEAAAAcBQUFCQUFBQEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6slmpqa+K6urv/e3t7/4uLi/+Li4v/k5OT/ + z8/P/8PDw////////////+/v7//X19f/5eXl//7+/v////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////19fX/39/f//Dw8P////// + //////b29v+7u7v/5ubm/+bm5v+CgoL/i4uL/5CQkP+CgoL/m5ub/8vLy//p6en/pqampAAAADwAAAA5 + AAAAKwAAABgAAAAKEhISAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + pqamBpWVlcqgoKD/2dnZ/+Li4v/j4+P/5OTk/9ra2v+2trb/+/v7///////y8vL/19fX/+Li4v/+/v7/ + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////q6ur/4ODg//z8/P///////////9DQ0P/X19f/7Ozs/6+vr/95eXn/ + ra2t/5GRkf+EhIT/oaGh/87Ozv/q6ur/p6enqAAAADUAAAAmAAAAGAAAAA4pKSkEAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZmZlzlZWV/8bGxv/j4+P/5OTk/+Tk5P/i4uL/ + t7e3/+3t7f/+/v7/+fn5/9jY2P/e3t7//Pz8//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//r6+v/f39// + 6+vr//7+/v/+/v7/9PT0/7+/v//p6en/2tra/3Nzc/+lpaX/srKy/4+Pj/+JiYn/q6ur/9DQ0P/s7Oz/ + qKionQAAACYAAAAbAAAAD0VFRQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + qqqqGpCQkPWqqqr/4eHh/+Tk5P/l5eX/5ubm/8XFxf/Y2Nj//f39//v7+//d3d3/2NjY//j4+P/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39/+zs7P/d3d3/+Pj4//39/f/9/f3/yMjI/93d3f/t7e3/ + k5OT/4mJif/Pz8//rq6u/46Ojv+SkpL/tra2/9TU1P/w8PD/qamplAAAABwAAAAMY2NjAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIymlJSU/9fX1//k5OT/5ubm/+bm5v/Z2dn/ + v7+///39/f/9/f3/5ubm/9TU1P/w8PD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + +vr6/97e3v/q6ur//f39//39/f/n5+f/ycnJ/+vr6/+6urr/bW1t/9XV1f/MzMz/pqam/46Ojv+hoaH/ + wcHB/9/f3//y8vL/p6endERERAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nJycNYuLi/+3t7f/4+Pj/+fn5//n5+f/5OTk/7q6uv/v7+//+/v7//Hx8f/T09P/5OTk//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/6enp/93d3f/5+fn/+/v7//v7+//AwMD/ + 5ubm/+Dg4P9tbW3/ubm5/+Hh4f/Dw8P/np6e/5OTk/+1tbX/z8/P/+7u7v/y8vL8srKyKwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGhoa1lJSU/9vb2//m5ub/6Ojo/+jo6P/R0dH/ + zc3N//r6+v/6+vr/2tra/9fX1//4+Pj/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/19fX/3Nzc/+7u7v/6+vr/+vr6/9HR0f/d3d3/7e3t/4ODg/+Wlpb/8PDw/9vb2/+5ubn/ + l5eX/6SkpP/Jycn/4ODg//Hx8f/09PSzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + mZmZNIeHh/+4uLj/5OTk/+jo6P/o6Oj/4+Pj/7m5uf/19fX/+Pj4/+fn5//R0dH/7e3t//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/l5eX/6urq//j4+P/g4OD/4+Pj//j4+P/4+Pj/ + 4uLi/9DQ0P/s7Oz/oaGh/3V1df/4+Pj/7Ozs/9LS0v+qqqr/mpqa/7y8vP/Y2Nj/5+fn//Hx8f/r6+te + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgoKtkJCQ/9vb2//o6Oj/6enp/+np6f/Pz8// + 1NTU//j4+P/19fX/0tLS/9zc3P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + mJiY/2JiYv97e3v/xsbG/+np6f/a2tr/9vb2//j4+P/29vb/w8PD/+rq6v++vr7/aGho/+np6f/29vb/ + 5eXl/8PDw/+goKD/q6ur/9bW1v/f39//7u7u//Ly8vPn5+caAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + lZWVHYODg/yysrL/5OTk/+rq6v/q6ur/5OTk/7q6uv/09PT/9vb2/+Li4v/Pz8//8PDw//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/+Dg4P9QUFD/eXl5/5KSkv+goKD/7+/v/9nZ2f/u7u7/ + 9vb2//b29v/Gxsb/5+fn/9PT0/9oaGj/0dHR//z8/P/y8vL/2NjY/7CwsP+hoaH/ysrK/+Pj4//k5OT/ + 8fHx//Dw8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIyEh4eH/9fX1//o6Oj/6+vr/+rq6v/U1NT/ + z8/P//T09P/y8vL/z8/P/9vb2//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 6Ojo/1VVVf91dXX/i4uL/7Gxsf/09PT/2NjY/+Xl5f/09PT/9PT0/8/Pz//i4uL/6Ojo/2hoaP+5ubn/ + /v7+//n5+f/n5+f/w8PD/6Ojo/+6urr/5ubm/+Hh4f/u7u7/8fHx/fLy8ioAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nZ2dBX9/f+Sfn5//4uLi/+rq6v/s7Oz/6Ojo/76+vv/s7Oz/7e3t/9vb2//Ly8v/7Ozs//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/xMTE/5CQkP+vr6//7e3t//Pz8//d3d3/ + 39/f//Pz8//z8/P/1tbW/9zc3P/t7e3/dXV1/6enp////////Pz8//Hx8f/U1NT/ra2t/62trf/g4OD/ + 6urq/+Xl5f/y8vL/8fHxmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJRAgICA/8PDw//n5+f/7Ozs/+3t7f/e3t7/ + x8fH/+vr6//n5+f/6urq/8vLy//x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy/+Hh4f/Z2dn/8vLy//Ly8v/c3Nz/1tbW/+3t7f+Dg4P/ + mJiY///////+/v7/+Pj4/+Hh4f+6urr/p6en/9LS0v/z8/P/4ODg//Dw8P/y8vL58PDwEgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHt7e52Hh4f/2tra/+rq6v/t7e3/7Ozs/83Nzf/a2tr/3Nzc//Pz8//19fX/6enp/+Xl5f/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/7+/v/+7u7v/t7e3/6+vr/+np6f/U1NT/wsLC/+jo6P/v7+// + 7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 4+Pj/9XV1f/v7+//8PDw/+Hh4f/R0dH/7e3t/4yMjP+Ojo7////////////7+/v/6+vr/8fHx/+np6f/ + w8PD//X19f/l5eX/6urq//Ly8v/z8/N1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcnJwCfHx86qKiov/i4uL/7Ozs/+7u7v/o6Oj/ + vr6+/+vr6//Y2Nj/9/f3//X19f/8/Pz/6enp/+Xl5f/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7e3t/+vr6//r6+v/6Ojo/+Xl5f/i4uL/ + 3t7e/9nZ2f/U1NT/j4+P/0JCQv9BQUH/WFhY/9HR0f/n5+f/6+vr/+zs7P/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/l5eX/09PT/+rq6v/u7u7/5ubm/8/Pz//t7e3/ + kpKS/4iIiP////////////39/f/x8fH/0tLS/6ysrP+2trb/7+/v/+7u7v/i4uL/8/Pz//T09NYAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJKSkjV9fX3/vLy8/+Xl5f/t7e3/7u7u/9/f3//Gxsb/5OTk/+Li4v/19fX/9/f3//z8/P/8/Pz/ + 5ubm/+Xl5f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7Ozs/+rq6v/o6Oj/ + 5eXl/+Pj4//f39//2tra/9XV1f/R0dH/zMzM/8jIyP+9vb3/m5ub/3d3d/9BQUH/QUFB/0FBQf9BQUH/ + fHx8/9vb2//d3d3/4eHh/+Xl5f/p6en/7Ozs/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+Xl5f/S0tL/5+fn/+3t7f/o6Oj/zc3N/+3t7f+Tk5P/hoaG//7+/v///////v7+//b29v/a2tr/ + srKy/66urv/m5ub/9vb2/93d3f/w8PD/8/Pz/vDw8BsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh4eHen9/f//V1dX/6urq/+7u7v/u7u7/ + 1NTU/9PT0//X19f/8fHx//T09P/5+fn/+/v7//v7+//7+/v/5+fn/+Li4v/r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+rq6v/l5eX/2tra/9PT0//Pz8//ysrK/8bGxv/ExMT/s7Oz/5CQkP9tbW3/ + TU1N/zExMf8xMTH/NDQ0/0FBQf9BQUH/QUFB/0FBQf9aWlr/0tLS/97e3v/Z2dn/2dnZ/9vb2//h4eH/ + 5ubm/+np6f/q6ur/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5eXl/9HR0f/l5eX/6+vr/+jo6P/Nzc3/ + 7e3t/5KSkv+Ghob//f39//7+/v/+/v7/+vr6/+Hh4f+6urr/qamp/9zc3P/7+/v/3Nzc/+3t7f/z8/P/ + 8PDwaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAB6enq4jo6O/93d3f/s7Oz/7+/v/+zs7P/ExMT/4+Pj/9DQ0P/39/f/9PT0//r6+v/7+/v/ + +/v7//v7+//7+/v/6urq/9/f3//o6Oj/6enp/+np6f/p6en/6enp/+np6f/p6en/5ubm/9fX1//Gxsb/ + wcHB/6mpqf+Hh4f/ZWVl/0NDQ/8xMTH/MTEx/zExMf8xMTH/MTEx/0RERP9vb2//VVVV/0FBQf9BQUH/ + QUFB/5SUlP94eHj/d3d3/76+vv/f39//2dnZ/9XV1f/X19f/3Nzc/+Li4v/m5ub/6Ojo/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/j4+P/0dHR/+Pj4//p6en/5ubm/87Ozv/t7e3/jY2N/4uLi//7+/v//Pz8//39/f/7+/v/ + 5+fn/8HBwf+np6f/0dHR//z8/P/g4OD/5ubm//Pz8//19fWeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHt7e/Cjo6P/4eHh/+3t7f/w8PD/ + 6enp/8HBwf/j4+P/1tbW//X19f/19fX/+/v7//v7+//7+/v/+/v7//v7+//7+/v/7+/v/9zc3P/m5ub/ + 6Ojo/+jo6P/o6Oj/6Ojo/+fn5//g4OD/srKy/15eXv87Ozv/MTEx/zExMf8xMTH/MTEx/zExMf89PT3/ + bGxs/5ycnP/Kysr/3Nzc/7S0tP88PDz/OTk5/2pqav+urq7/6Ojo/+jo6P/Y2Nj/jo6O/2tra/+jo6P/ + 29vb/9ra2v/V1dX/1NTU/9fX1//c3Nz/4ODg/+Xl5f/m5ub/5+fn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+Li4v/Pz8//4uLi/+jo6P/h4eH/ + 0dHR/+3t7f+EhIT/kpKS//f39//6+vr//Pz8//v7+//q6ur/xsbG/6enp//Jycn/+/v7/+Pj4//f39// + 8/Pz//T09OYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACQkJAke3t7/7S0tP/k5OT/7+/v//Hx8f/k5OT/x8fH/9zc3P/d3d3/8/Pz//X19f/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/9PT0/9zc3P/i4uL/5ubm/+bm5v/m5ub/5eXl/+Li4v9hYWH/ + MTEx/zExMf8xMTH/ODg4/2RkZP+RkZH/w8PD/+Tk5P/m5ub/5OTk/9vb2//AwMD/SUlJ/zExMf9sbGz/ + 4uLi/+bm5v/m5ub/5ubm/+bm5v/m5ub/4+Pj/6mpqf9sbGz/iIiI/87Ozv/c3Nz/19fX/9PT0//S0tL/ + 1dXV/9vb2//g4OD/5OTk/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/39/f/87Ozv/h4eH/5ubm/9zc3P/V1dX/7e3t/3d3d/+bm5v/8fHx//b29v/5+fn/ + +vr6/+3t7f/Kysr/qKio/8LCwv/5+fn/5+fn/9nZ2f/y8vL/8/Pz/e3t7QMAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJOTk1J8fHz/xMTE/+fn5//w8PD/ + 8fHx/97e3v/Nzc3/1NTU/+Xl5f/y8vL/9vb2//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/ + +Pj4/+Pj4//b29v/4+Pj/+Tk5P/k5OT/wcHB/zQ0NP9aWlr/iYmJ/7m5uf/f39//5OTk/+Tk5P/k5OT/ + 5OTk/+Li4v/Z2dn/xcXF/19fX/8xMTH/UFBQ/9ra2v/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/CwsL/enp6/3Nzc/+4uLj/39/f/9ra2v/U1NT/z8/P/9HR0f/W1tb/29vb/9/f3//i4uL/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/b29v/zc3N/+Li4v/k5OT/ + 1dXV/9ra2v/q6ur/ampq/6ampv/p6en/7+/v//X19f/4+Pj/7e3t/83Nzf+oqKj/vb29//f39//q6ur/ + 1dXV//Dw8P/z8/P/8PDwNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAlJSUeH5+fv/S0tL/6Ojo//Hx8f/x8fH/19fX/8/Pz//Kysr/7u7u//Hx8f/29vb/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4/+/v7//a2tr/3t7e/+Li4v/Pz8// + 2tra/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/g4OD/19fX/8TExP96enr/MTEx/z09Pf/Jycn/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/1tbW/5CQkP9paWn/ + nZ2d/9nZ2f/b29v/1NTU/8/Pz//Nzc3/0NDQ/9XV1f/b29v/39/f/+Hh4f/i4uL/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/9fX1//Ly8v/3d3d/+Hh4f/R0dH/4ODg/9fX1/9oaGj/r6+v/9/f3//n5+f/ + 7u7u//Pz8//r6+v/zc3N/6mpqf+6urr/9fX1/+zs7P/S0tL/7u7u//Pz8//v7+9bAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5eXmchoaG/9bW1v/q6ur/ + 8vLy//Dw8P/R0dH/1NTU/8bGxv/19fX/8PDw//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/m5ub/2NjY/9/f3//h4eH/4uLi/+Li4v/i4uL/4uLi/+Li4v/h4eH/ + 39/f/9bW1v/ExMT/k5OT/zIyMv8yMjL/r6+v/+Hh4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/9/f3/+rq6v/bW1t/4KCgv/Kysr/3Nzc/9fX1//R0dH/ + zc3N/8zMzP/Q0ND/19fX/9zc3P/f39//4eHh/+Li4v/i4uL/4uLi/+Li4v/h4eH/z8/P/8rKyv/u7u7/ + 1tbW/83Nzf/l5eX/vLy8/2hoaP+2trb/1NTU/93d3f/l5eX/7Ozs/+bm5v/Ly8v/qamp/7a2tv/z8/P/ + 7e3t/87Ozv/t7e3/8/Pz/+3t7W8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHp6eriOjo7/2NjY/+vr6//z8/P/8PDw/83Nzf/Y2Nj/xMTE//Pz8//u7u7/ + 9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//09PT/ + 4ODg/9bW1v/d3d3/4ODg/+Dg4P/g4OD/4ODg/97e3v/U1NT/wcHB/6SkpP87Ozv/MTEx/42Njf/g4OD/ + 4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/w8PD/3t7e/9wcHD/sbGx/93d3f/Z2dn/09PT/83Nzf/Kysr/zc3N/9fX1//f39// + 4ODg/+Dg4P/g4OD/3d3d/9fX1//d3d3/8/Pz//f39/++vr7/ycnJ/+np6f+mpqb/aWlp/7m5uf/Gxsb/ + 0dHR/9vb2//j4+P/4ODg/8bGxv+mpqb/tLS0//Hx8f/t7e3/y8vL/+vr6//z8/P/7OzsewAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe3t7zpWVlf/Z2dn/ + 7e3t//Pz8//v7+//ysrK/9vb2//FxcX/8fHx/+7u7v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/8vLy/+Dg4P/V1dX/29vb/93d3f/c3Nz/ + 09PT/7+/v/+urq7/SkpK/zExMf9ra2v/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/9TU1P+SkpL/ + Z2dn/5eXl//V1dX/2tra/9XV1f/S0tL/1tbW/93d3f/e3t7/2tra/9bW1v/i4uL/9PT0//Hx8f/09PT/ + 7+/v/7u7u//Nzc3/6+vr/4GBgf9zc3P/ra2t/7i4uP/ExMT/zs7O/9fX1//W1tb/v7+//6Ghof+wsLD/ + 7u7u/+rq6v/Jycn/6+vr//Pz8//r6+t+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB8fHzfm5ub/9ra2v/t7e3/9PT0/+/v7//Jycn/2dnZ/8PDw//w8PD/ + 7e3t//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/ + 9fX1//X19f/19fX/9fX1//Pz8//k5OT/1dXV/8rKyv+9vb3/sbGx/2FhYf8xMTH/Tk5O/9XV1f/d3d3/ + 3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/ + 3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/b29v/rKys/21tbf98fHz/xMTE/9vb2//Z2dn/ + 1dXV/9bW1v/l5eX/9PT0//X19f/z8/P/7+/v//T09P/Z2dn/wMDA/9bW1v/o6Oj/ampq/3x8fP+enp7/ + qqqq/7W1tf/AwMD/y8vL/8rKyv+2trb/m5ub/62trf/q6ur/5ubm/8XFxf/q6ur/8/Pz/+rq6n8AAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH19femenp7/ + 2tra/+7u7v/09PT/7+/v/8nJyf/Y2Nj/wsLC/+/v7//s7Oz/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//Pz8//x8fH/ + 39/f/8TExP+IiIj/Ly8v/zw8PP/ExMT/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/ + 3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/ + 3Nzc/9zc3P/c3Nz/3Nzc/8LCwv93d3f/gYGB/83Nzf/s7Oz/9PT0//T09P/09PT/9PT0//Hx8f/u7u7/ + 9PT0/8bGxv/Dw8P/4uLi/8DAwP9oaGj/f39//5GRkf+bm5v/pqam/7Kysv+8vLz/vb29/6qqqv+Tk5P/ + qqqq/+Tk5P/e3t7/wcHB/+np6f/z8/P/9fX1iQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfn5+7KCgoP/a2tr/7u7u//X19f/w8PD/y8vL/9bW1v/AwMD/ + 7u7u/+rq6v/z8/P/5+fn/9/f3//r6+v/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//y8vL/7+/v/+rq6v/m5ub/39/f/8TExP+srKz/vr6+/9fX1//S0tL/ + 1tbW/9nZ2f/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/ + 2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/Z2dn/1tbW/9LS0v/W1tb/39/f/+rq6v/w8PD/ + 4ODg//Pz8//z8/P/8/Pz//Pz8//z8/P/7u7u/+/v7//z8/P/tLS0/8nJyf/p6en/n5+f/2hoaP+AgID/ + h4eH/4+Pj/+YmJj/o6Oj/66urv+urq7/nZ2d/4mJif+lpaX/3d3d/9TU1P+8vLz/6enp//Ly8v/o6Oh/ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/f3/s + oKCg/9nZ2f/t7e3/9vb2//Hx8f/Nzc3/1dXV/729vf/t7e3/6Ojo/+3t7f/Ly8v/2NjY/97e3v/w8PD/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//y8vL/8vLy/+7u7v/o6Oj/ + 5OTk/+Li4v/Dw8P/wMDA/9ra2v/z8/P/8/Pz//Hx8f/m5ub/39/f/9jY2P/T09P/0dHR/9PT0//V1dX/ + 1tbW/9fX1//Y2Nj/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Y2Nj/19fX/9bW1v/U1NT/0tLS/9HR0f/U1NT/ + 2tra/+Dg4P/m5ub/8fHx//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Hx8f/r6+v/ + 8PDw/+Pj4/+3t7f/0dHR/+zs7P9ycnL/b29v/39/f/+AgID/hYWF/4yMjP+VlZX/n5+f/56env+Pj4// + f39//6CgoP/U1NT/x8fH/7e3t//p6en/8vLy/+fn534AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgOaenp7/19fX/+zs7P/29vb/8vLy/9HR0f/Q0ND/ + uLi4/+zs7P/m5ub/6enp/8nJyf/X19f/3t7e/+zs7P/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Dw8P/t7e3/5ubm/+Li4v/j4+P/xcXF/7y8vP/Nzc3/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/7Ozs/+bm5v/h4eH/39/f/97e3v/c3Nz/3d3d/93d3f/d3d3/ + 3Nzc/9/f3//f39//4uLi/+bm5v/t7e3/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/7e3t/+rq6v/x8fH/xcXF/76+vv/g4OD/ycnJ/2hoaP94eHj/ + gICA/39/f/9/f3//hISE/4qKiv+RkZH/j4+P/4CAgP92dnb/nJyc/8jIyP+4uLj/srKy/+jo6P/x8fH/ + 5eXlewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + gYGB2pubm//U1NT/6+vr//b29v/z8/P/19fX/83Nzf+1tbX/7Ozs/+Tk5P/u7u7/2dnZ/9DQ0P/g4OD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/v7+//6+vr/+Tk5P/g4OD/ + 5OTk/8vLy/+4uLj/wcHB/+3t7f/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/p6en/ + 6+vr//Dw8P+urq7/yMjI/+np6f+enp7/aWlp/4ODg/+CgoL/gICA/39/f/9/f3//goKC/4WFhf+AgID/ + cnJy/21tbf+Wlpb/urq6/6enp/+vr6//6enp//Dw8P/l5eVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDg4PJmJiY/9HR0f/p6en/9vb2//T09P/e3t7/ + ysrK/7m5uf/j4+P/4+Pj/+rq6v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+rq6v/i4uL/3t7e/+Li4v/T09P/tbW1/7i4uP/m5ub/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7Ozs/+fn5//s7Oz/0tLS/7W1tf/X19f/5eXl/29vb/90dHT/ + iYmJ/4aGhv+Dg4P/gYGB/39/f/9/f3//fX19/3V1df9lZWX/ZmZm/5GRkf+pqan/lpaW/62trf/p6en/ + 7+/v/+Tk5GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAISEhLGTk5P/zc3N/+fn5//19fX/9vb2/+Pj4//Kysr/v7+//9XV1f/i4uL/5+fn/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+3t7f/o6Oj/4ODg/9zc3P/g4OD/ + 29vb/7Gxsf+wsLD/29vb/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/m5ub/ + 5+fn/+7u7v+xsbH/w8PD/+bm5v+zs7P/aGho/4iIiP+NjY3/ioqK/4aGhv+EhIT/goKC/39/f/95eXn/ + a2tr/1tbW/9iYmL/ioqK/5iYmP+FhYX/sLCw/+vr6//u7u7/5eXlPAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhYWFlI+Pj//Jycn/4+Pj//T09P/4+Pj/ + 6enp/8jIyP/Gxsb/yMjI/+Pj4//j4+P/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/s7Oz/6Ojo/9/f3//a2tr/3t7e/+Hh4f+ysrL/rKys/83Nzf/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/6urq/+Tk5P/q6ur/1tbW/7CwsP/S0tL/6enp/3x8fP91dXX/ + l5eX/5KSkv+Ojo7/i4uL/4iIiP+EhIT/gYGB/3h4eP9mZmb/VFRU/2JiYv+EhIT/hoaG/3l5ef+3t7f/ + 7Ozs/+3t7f7Z2dkIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACcnJxwjY2N/8HBwf/f39//8fHx//j4+P/t7e3/zMzM/83Nzf+5ubn/5eXl/97e3v/r6+v/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+rq6v/h4eH/2dnZ/9zc3P/k5OT/ + t7e3/6ioqP+9vb3/6+vr/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+vr6//k5OT/ + 5OTk/+zs7P+xsbH/wcHB/+Xl5f+9vb3/aGho/5KSkv+cnJz/mJiY/5SUlP+Pj4//jIyM/4iIiP+Dg4P/ + d3d3/2JiYv9TU1P/ZmZm/4CAgP94eHj/cnJy/8TExP/r6+v/7u7u7gAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJubm0mOjo7/tra2/9nZ2f/u7u7/ + +fn5//Hx8f/W1tb/zc3N/6+vr//n5+f/3d3d/+bm5v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//q6ur/6Ojo/9/f3//c3Nz/5OTk/8HBwf+kpKT/r6+v/+fn5//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5ubm/+Hh4f/o6Oj/0tLS/6+vr//U1NT/5ubm/3h4eP93d3f/ + p6en/6Ojo/+enp7/mZmZ/5WVlf+RkZH/jY2N/4WFhf91dXX/X19f/1ZWVv9vb2//fX19/2tra/9ycnL/ + 1NTU/+rq6v/v7++6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAm5ubFY+Pj/+srKz/0dHR/+rq6v/4+Pj/9fX1/+Li4v/Kysr/ubm5/9TU1P/c3Nz/ + 4ODg/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+np6f/n5+f/4uLi/+Tk5P/Nzc3/ + oaGh/6Wlpf/e3t7/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/ + 6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/ + 6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+jo6P/g4OD/ + 4+Pj/+jo6P+oqKj/w8PD/+fn5/+xsbH/aGho/6Kiov+urq7/qqqq/6SkpP+fn5//mpqa/5aWlv+QkJD/ + hoaG/3Nzc/9cXFz/Xl5e/3l5ef97e3v/ZGRk/4KCgv/e3t7/6enp/9jY2HwAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQ3KSkpP/Kysr/ + 5OTk//X19f/5+fn/6enp/8zMzP/Hx8f/vLy8/+Dg4P/a2tr/6Ojo/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+jo6P/n5+f/2NjY/56env+cnJz/0dHR/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/o6Oj/4eHh/97e3v/o6Oj/v7+//7S0tP/b29v/5OTk/3Nzc/+EhIT/ + urq6/7W1tf+wsLD/q6ur/6Wlpf+hoaH/nJyc/5WVlf+Hh4f/b29v/1xcXP9paWn/goKC/3d3d/9iYmL/ + nJyc/+Xl5f/o6Oj/3NzcSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACSkpKenJyc/8LCwv/d3d3/8fHx//r6+v/w8PD/1dXV/87Ozv+rq6v/ + 4+Pj/9fX1//g4OD/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P+urq7/ + mJiY/8DAwP/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+Pj4//d3d3/ + 5OTk/9nZ2f+np6f/zMzM/+rq6v+cnJz/bGxs/7m5uf/BwcH/vLy8/7e3t/+xsbH/rKys/6ampv+hoaH/ + l5eX/4WFhf9ra2v/YGBg/3l5ef+Hh4f/cnJy/2dnZ/+6urr/6Ojo/+np6fnS0tIDAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKSkpFWampr/ + t7e3/9TU1P/r6+v/+Pj4//b29v/k5OT/zMzM/7u7u//Hx8f/29vb/9jY2P/n5+f/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/56env+tra3/5+fn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/k5OT/29vb/97e3v/m5ub/pqam/7+/v//k5OT/y8vL/2xsbP+fn5// + zc3N/8fHx//BwcH/uLi4/6+vr/+np6f/oaGh/5qamv+Ojo7/enp6/2RkZP9qamr/iIiI/4eHh/9tbW3/ + d3d3/9XV1f/o6Oj/7e3ttwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6urDpubm/mtra3/ysrK/+Pj4//19fX/+/v7/+zs7P/R0dH/ + y8vL/6urq//i4uL/1dXV/97e3v/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//k5OT/ + nZ2d/+Li4v/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5eXl/9ra2v/b29v/ + 5ubm/7e3t/+0tLT/29vb/+Xl5f99fX3/gICA/9PT0//Nzc3/wcHB/7S0tP+mpqb/mZmZ/5CQkP+JiYn/ + goKC/3V1df9iYmL/WFhY/3BwcP+MjIz/gYGB/2tra/+Xl5f/5OTk/+jo6P/W1tZqAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nJyctKampv/AwMD/2dnZ/+/v7//6+vr/9PT0/+Pj4//MzMz/tbW1/8nJyf/Z2dn/09PT/+Pj4//m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/9vb2//X19f/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+Xl5f/a2tr/2NjY/+Tk5P/Gxsb/qKio/9HR0f/s7Oz/l5eX/3BwcP/Dw8P/ + ysrK/7e3t/+mpqb/lZWV/4aGhv95eXn/cHBw/2pqav9iYmL/VVVV/0ZGRv9KSkr/aGho/3x8fP9wcHD/ + bW1t/7y8vP/o6Oj/6urq+sXFxQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6tXpKSk/7a2tv/Nzc3/5ubm//f39//7+/v/ + 6+vr/9LS0v/Kysr/qKio/+Dg4P/S0tL/19fX/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/k5OT/2dnZ/9bW1v/g4OD/ + 0tLS/6Ojo//Jycn/6enp/7W1tf9tbW3/oqKi/76+vv+np6f/kpKS/4CAgP9zc3P/ampq/2FhYf9cXFz/ + VlZW/0xMTP8/Pz//NTU1/z8/P/9UVFT/Wlpa/1ZWVv9wcHD/zc3N/+fn5//u7u6uAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALGxsQulpaXkrq6u/8LCwv/a2tr/8PDw//v7+//09PT/5OTk/83Nzf+6urr/uLi4/9zc3P/Q0ND/ + 3Nzc/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/4+Pj/9nZ2f/U1NT/3t7e/9bW1v+hoaH/w8PD/+Xl5f/Hx8f/bW1t/4SEhP+vr6// + lZWV/4CAgP9ycnL/bGxs/2tra/9ubm7/cHBw/3Jycv9ycnL/a2tr/2JiYv9VVVX/UVFR/0lJSf9AQED/ + Pj4+/3Fxcf+9vb3/3d3d/7+/v0sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKysrH2srKz/uLi4/83Nzf/l5eX/ + 9vb2//v7+//t7e3/2dnZ/8zMzP+oqKj/0tLS/9TU1P/Pz8//3t7e/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/X19f/09PT/9zc3P/Y2Nj/ + n5+f/76+vv/h4eH/1dXV/3Nzc/9tbW3/np6e/4iIiP93d3f/cXFx/3Nzc/91dXX/dnZ2/3Z2dv93d3f/ + dnZ2/3V1df9ycnL/cHBw/29vb/9ycnL/cXFx/1xcXP9BQUH/Z2dn/5ycnP/Hx8fjRUVFBwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAtra2Eq2trfSzs7P/wMDA/9jY2P/u7u7/+/v7//f39//p6en/0dHR/8bGxv+kpKT/ + 3d3d/9DQ0P/Pz8//4ODg/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//h4eH/1NTU/9HR0f/c3Nz/2NjY/6CgoP+9vb3/39/f/9bW1v93d3f/X19f/4yMjP+AgID/ + dXV1/3V1df92dnb/d3d3/3d3d/95eXn/fX19/4GBgf+FhYX/hoaG/4WFhf+EhIT/hISE/4SEhP+CgoL/ + fHx8/3d3d/9vb2//f39//1ZWVo0iIiITioqKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsrKyibS0tP+3t7f/ + ycnJ/+Hh4f/09PT//Pz8//Ly8v/l5eX/zs7O/7u7u/+qqqr/3t7e/87Ozv/Ozs7/39/f/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/3t7e/9LS0v/R0dH/3Nzc/9LS0v+dnZ3/ + vb29/97e3v/W1tb/enp6/1hYWP94eHj/d3d3/3V1df93d3f/d3d3/3h4eP97e3v/g4OD/42Njf+Xl5f/ + oqKi/6ioqP+qqqr/qKio/6ioqP+pqan/qqqq/6Wlpf+bm5v/kJCQ/4aGhv99fX3+HBwccwAAACFmZmYD + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAC6uroRtbW167a2tv+8vLz/0dHR/+jo6P/39/f//Pz8/+7u7v/f39// + zc3N/7Ozs/+vr6//3d3d/8zMzP/Nzc3/3d3d/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/9jY2P/Ozs7/0dHR/97e3v/Ly8v/nZ2d/7+/v//f39//19fX/319ff9WVlb/ampq/3Fxcf92dnb/ + d3d3/3h4eP97e3v/g4OD/5KSkv+ioqL/sbGx/7y8vP/Dw8P/xMTE/8HBwf+/v7//wMDA/8TExP/IyMj/ + xcXF/729vf+2trb/qKio/5WVlf96enrqFxcXPkVFRQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4uLhv + ubm5/7i4uP/CwsL/2NjY/+3t7f/6+vr/+vr6/+zs7P/c3Nz/zMzM/66urv+wsLD/3d3d/8zMzP/Ly8v/ + 2tra/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/8DAwP+goKD/t7e3/9nZ2f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/97e3v/S0tL/zc3N/9TU1P/f39//uLi4/5+fn//FxcX/ + 4+Pj/9bW1v9/f3//WVlZ/2NjY/9tbW3/d3d3/3h4eP95eXn/f39//46Ojv+hoaH/tbW1/8PDw//MzMz/ + z8/P/87Ozv/Kysr/xsbG/8TExP/Hx8f/zc3N/9DQ0P/Q0ND/zs7O/87Ozv/IyMj/tra2/5+fn/97e3vF + Tk5OCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6urrAu7u7/7e3t//Gxsb/3d3d//Dw8P/7+/v/ + +fn5/+vr6//b29v/y8vL/62trf+tra3/3Nzc/83Nzf/Jycn/0tLS/9/f3//g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/kZGR/6ysrP/FxcX/zc3N/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/9/f3//W1tb/ + zMzM/8zMzP/Y2Nj/2tra/6Wlpf+oqKj/zc3N/+jo6P/Y2Nj/g4OD/19fX/9iYmL/ampq/3h4eP95eXn/ + e3t7/4WFhf+YmJj/r6+v/8LCwv/Ozs7/0tLS/9LS0v/Q0ND/zc3N/8rKyv/Kysr/z8/P/9fX1//d3d3/ + 3t7e/93d3f/c3Nz/2tra/9PT0//IyMj/ubm5/6Wlpf+QkJBYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAL+/vxy8vLzvu7u7/7m5uf/Kysr/4ODg//Ly8v/7+/v/+Pj4/+vr6//d3d3/y8vL/7Kysv+hoaH/ + 2NjY/9LS0v/Hx8f/y8vL/9nZ2f/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39// + 39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+enp7/o6Oj/7y8vP/Nzc3/ + 39/f/9/f3//f39//39/f/9/f3//X19f/zc3N/8vLy//S0tL/3d3d/8PDw/+ZmZn/tbW1/9fX1//u7u7/ + 09PT/4mJif9paWn/ZWVl/2JiYv92dnb/eHh4/3t7e/+IiIj/n5+f/7m5uf/Ly8v/0tLS/9TU1P/T09P/ + 0dHR/8/Pz//S0tL/19fX/97e3v/k5OT/6urq/+zs7P/s7Oz/6+vr/+vr6//p6en/4eHh/9LS0v/FxcX/ + u7u7/6enp80AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL6+vli9vb3/ubm5/7u7u//MzMz/ + 4eHh//Ly8v/7+/v/+Pj4/+zs7P/h4eH/zs7O/7m5uf+cnJz/x8fH/9jY2P/Ly8v/xsbG/83Nzf/Z2dn/ + 39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39// + 39/f/9/f3//f39//39/f/9nZ2f+6urr/xsbG/93d3f/f39//39/f/97e3v/V1dX/zMzM/8nJyf/Ozs7/ + 2dnZ/9XV1f+mpqb/oaGh/8TExP/i4uL/8PDw/8vLy/+RkZH/dnZ2/2pqav9aWlr/cHBw/3V1df96enr/ + iIiI/6Ojo/+9vb3/zc3N/9PT0//S0tL/0tLS/9DQ0P/T09P/2tra/+Hh4f/o6Oj/7u7u//Ly8v/19fX/ + 9vb2//b29v/29vb/9fX1//Ly8v/r6+v/4ODg/9HR0f/FxcX/u7u7/7Kysi8AAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAL6+vnq9vb3/t7e3/7u7u//MzMz/4eHh//Hx8f/6+vr/+vr6/+7u7v/m5ub/ + 0tLS/8LCwv+fn5//q6ur/9jY2P/U1NT/yMjI/8XFxf/Ly8v/1dXV/93d3f/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/9jY2P/Q0ND/ycnJ/8jIyP/Nzc3/2NjY/9nZ2f+wsLD/mJiY/7a2tv/V1dX/7Ozs/+7u7v+9vb3/ + nZ2d/4mJif9zc3P/WFhY/2NjY/93d3f/dnZ2/4KCgv+enp7/urq6/8nJyf/Pz8//z8/P/87Ozv/Ozs7/ + 1tbW/+Dg4P/o6Oj/7+/v//T09P/4+Pj/+vr6//v7+//8/Pz//Pz8//z8/P/7+/v/+fn5//T09P/q6ur/ + 3t7e/87Ozv/FxcX/vb29cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL29vaK7u7v/ + t7e3/7u7u//Ly8v/3t7e/+7u7v/5+fn/+/v7//Hx8f/q6ur/2tra/8rKyv+zs7P/l5eX/7W1tf/b29v/ + 1NTU/8nJyf/ExMT/xcXF/8zMzP/U1NT/29vb/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/c3Nz/1tbW/8/Pz//Jycn/x8fH/8jIyP/Q0ND/2dnZ/9fX1/+wsLD/ + mJiY/6+vr//MzMz/5OTk//Hx8f/f39//s7Oz/6Wlpf+YmJj/gICA/19fX/9RUVH/cnJy/4ODg/9/f3// + lpaW/7Ozs//FxcX/ysrK/8vLy//Ly8v/zc3N/9jY2P/k5OT/7e3t//T09P/4+Pj/+/v7//39/f/9/f3/ + /v7+//7+/v/+/v7//v7+//7+/v/9/f3/+vr6//Ly8v/o6Oj/2tra/8zMzP/ExMSrAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv7+/B7u7u6S5ubn/tbW1/7q6uv/IyMj/2tra/+vr6//29vb/ + /Pz8//b29v/s7Oz/5eXl/9XV1f/FxcX/rKys/5eXl/+xsbH/1tbW/9fX1//Pz8//x8fH/8TExP/ExMT/ + xsbG/8vLy//Ozs7/0dHR/9PT0//U1NT/1tbW/9XV1f/T09P/0dHR/9DQ0P/Ly8v/x8fH/8XFxf/FxcX/ + yMjI/87Ozv/V1dX/3Nzc/8nJyf+oqKj/lpaW/6+vr//Jycn/4eHh//Dw8P/u7u7/y8vL/66urv+oqKj/ + mpqa/4qKiv9tbW3/T09P/2NjY/9+fn7/kZGR/5SUlP+urq7/wsLC/8nJyf/Kysr/ysrK/87Ozv/b29v/ + 5+fn//Dw8P/39/f/+/v7//39/f/9/f3//v7+//////////////////////////////////7+/v/9/f3/ + +Pj4/+/v7//j4+P/09PT/8zMzMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALq6upK2trb/tLS0/7e3t//Dw8P/1NTU/+Xl5f/y8vL/+fn5//v7+//z8/P/6+vr/+Pj4//U1NT/ + xMTE/6+vr/+Xl5f/o6Oj/7+/v//a2tr/2dnZ/9PT0//Ozs7/ysrK/8fHx//ExMT/xMTE/8TExP/FxcX/ + xcXF/8XFxf/FxcX/xsbG/8rKyv/Pz8//09PT/9nZ2f/d3d3/x8fH/66urv+Xl5f/nZ2d/7a2tv/Nzc3/ + 4uLi/+/v7//y8vL/29vb/7u7u/+ysrL/o6Oj/5CQkP+Ojo7/fX19/15eXv9GRkb/dnZ2/4+Pj/+ioqL/ + srKy/8TExP/Ozs7/z8/P/8/Pz//S0tL/3t7e/+np6f/y8vL/+Pj4//z8/P/9/f3//v7+//////////// + //////////////////////////////////////7+/v/7+/v/9PT0/+rq6v/c3Nz/09PT1gAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALi4uHGzs7P8sLCw/7S0tP+/v7// + zc3N/93d3f/r6+v/9fX1//v7+//6+vr/8vLy/+vr6//l5eX/19fX/8rKyv+6urr/pqam/5OTk/+cnJz/ + q6ur/76+vv/MzMz/29vb/9zc3P/b29v/2tra/9jY2P/Z2dn/29vb/9zc3P/d3d3/z8/P/76+vv+vr6// + oKCg/5OTk/+enp7/sbGx/8bGxv/Y2Nj/6Ojo//Hx8f/z8/P/4uLi/8TExP+3t7f/r6+v/5OTk/+Ghob/ + ioqK/4WFhf9xcXH/UlJS/1BQUP99fX3/n5+f/7S0tP/Nzc3/09PT/9fX1//X19f/2NjY/+Hh4f/s7Oz/ + 8/Pz//n5+f/8/Pz//f39//7+/v////////////////////////////////////////////////////// + /v7+//z8/P/4+Pj/8PDw/+Xl5f/c3NzXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALi4uDyvr6/irKys/66urv+5ubn/xcXF/9PT0//h4eH/7e3t//X19f/5+fn/ + +vr6//T09P/t7e3/6enp/+Hh4f/W1tb/zMzM/7+/v/+0tLT/p6en/5ubm/+RkZH/lJSU/5mZmf+Wlpb/ + np6e/5eXl/+VlZX/lJSU/4+Pj/+ZmZn/paWl/7CwsP++vr7/zMzM/9nZ2f/m5ub/7+/v//Pz8//y8vL/ + 4eHh/8jIyP+6urr/uLi4/5ubm/+AgID/gYGB/4ODg/+Ghob/f39//2pqav9JSUn/X19f/4qKiv+rq6v/ + xcXF/9zc3P/b29v/2tra/9vb2//h4eH/6+vr//Pz8//4+Pj//Pz8//39/f/+/v7///////////////// + ///////////////////////////////////////////+/v7//f39//n5+f/09PT/7e3t/+bm5ssAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALe3txKrq6ud + pqam/6Wlpf+vr6//vLy8/8fHx//T09P/39/f/+jo6P/v7+//9PT0//f39//19fX/8PDw/+vr6//o6Oj/ + 5eXl/+Dg4P/Y2Nj/0tLS/9DQ0P/Kysr/xsbG/8TExP/Dw8P/xcXF/8vLy//Nzc3/0dHR/9bW1v/e3t7/ + 5ubm/+zs7P/x8fH/8/Pz//T09P/u7u7/3Nzc/8TExP+6urr/u7u7/6urq/+Ojo7/goKC/39/f/9/f3// + gICA/4KCgv98fHz/ZmZm/0VFRf9tbW3/mpqa/7m5uf/T09P/4+Pj/+Pj4//a2tr/3d3d/+jo6P/x8fH/ + 9/f3//v7+//9/f3//v7+//////////////////////////////////////////////////////////// + //////7+/v/8/Pz/+fn5//T09P/v7+//7e3trAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvr689oqKi0J2dnf+enp7/q6ur/7m5uf+/v7// + xsbG/8/Pz//X19f/3d3d/+Pj4//n5+f/6+vr/+zs7P/r6+v/6+vr/+rq6v/q6ur/6enp/+np6f/p6en/ + 6Ojo/+vr6//t7e3/7+/v//Hx8f/y8vL/8/Pz//T09P/09PT/8vLy/+zs7P/g4OD/zMzM/7q6uv+2trb/ + ubm5/7i4uP+qqqr/nZ2d/5OTk/+Kior/g4OD/39/f/9/f3//gICA/3t7e/9lZWX/RUVF/3V1df+qqqr/ + x8fH/9/f3//p6en/6+vr/+Tk5P/m5ub/7u7u//X19f/6+vr//f39//7+/v////////////////////// + /////////////////////////////////////////////////v7+//z8/P/4+Pj/8/Pz/+/v7//u7u6A + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACsrKwCpKSkWJeXl+ORkZH/jY2N/5CQkP+YmJj/oqKi/6ampv+srKz/s7Oz/7q6uv/BwcH/ + x8fH/83Nzf/S0tL/19fX/9zc3P/g4OD/5OTk/+fn5//q6ur/7Ozs/+7u7v/v7+//7u7u/+3t7f/q6ur/ + 5ubm/9XV1f/Dw8P/tbW1/62trf+xsbH/ubm5/8jIyP/Kysr/wsLC/7a2tv+rq6v/oKCg/5WVlf+MjIz/ + hYWF/4CAgP9/f3//e3t7/2dnZ/9HR0f/d3d3/7W1tf/Pz8//5eXl/+zs7P/u7u7/8PDw//Dw8P/z8/P/ + +Pj4//z8/P/+/v7///////////////////////////////////////////////////////////////// + //////7+/v/9/f3//Pz8//n5+f/7+/v/7+/v//Dw8EUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoaGhApSUlIGAgID5 + dnZ2/2VlZf9eXl7/Y2Nj/25ubv96enr/hYWF/4uLi/+RkZH/mJiY/56env+kpKT/qqqq/7CwsP+1tbX/ + u7u7/8HBwf/FxcX/ycnJ/8fHx/+8vLz/srKy/6enp/+enp7/n5+f/6Wlpf+wsLD/ycnJ/9/f3//p6en/ + 4uLi/9nZ2f/Q0ND/xMTE/7q6uv+urq7/o6Oj/5iYmP+Pj4//h4eH/4GBgf98fHz/bGxs/05OTv93d3f/ + vb29/9TU1P/l5eX/6+vr/+3t7f/x8fH/9/f3//n5+f/7+/v//f39//7+/v////////////////////// + ///////////+/v7/+/v7//n5+f/9/f3//////////////////v7+//z8/P/7+/v//f39//n5+f/x8fHz + 8vLyBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGtraydsbGy4W1tb/lBQUP9ISEj/QkJC/0FBQf9BQUH/ + SEhI/05OTv9TU1P/WVlZ/1xcXP9jY2P/Y2Nj/2hoaP9paWn/aGho/2hoaP9paWn/bW1t/3Z2dv+AgID/ + j4+P/6mpqf/Ly8v/6Ojo//n5+f/5+fn/9vb2//Hx8f/r6+v/5OTk/9zc3P/S0tL/yMjI/729vf+ysrL/ + pqam/5ubm/+QkJD/h4eH/319ff9vb2//U1NT/3R0dP/Dw8P/2NjY/+Xl5f/p6en/7Ozs//Ly8v/39/f/ + /Pz8//7+/v/+/v7//////////////////////////////////f39/+7u7v++vr7/m5ub/+bm5v/+/v7/ + //////7+/v/9/f3//f39//7+/v/9/f3/8vLy//Hx8aQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzc3Mk + cXFxbldXV69dXV3rWVlZ/1hYWP9WVlb/VVVV/1NTU/9QUFD/TU1N/0hISP9FRUX/QkJC/0BAQP9AQED/ + QkJC/0lJSf9TU1P/X19f/3BwcP+Dg4P/mJiY/7S0tP/MzMz/2NjY/+Xl5f/u7u7/9vb2//n5+f/5+fn/ + 9/f3//Pz8//t7e3/5+fn/97e3v/V1dX/y8vL/7+/v/+ysrL/paWl/5aWlv+IiIj/eXl5/2lpaf9TU1P/ + bW1t/8bGxv/c3Nz/6Ojo/+rq6v/t7e3/9fX1//v7+//9/f3//v7+//////////////////////////// + ///////////09PT/wsLC/5KSkv9YWFj/kpKS//v7+/////////////7+/v/+/v7//f39//j4+P/o6Oj/ + 8fHxOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB6enodaGhotGpqav1sbGz/bm5u/3BwcP9ycnL/c3Nz/3R0dP9zc3P/ + cXFx/29vb/9sbGz/aWlp/2VlZf9gYGD/W1tb/1VVVf9VVVX/Xl5e/25ubv+BgYH/jY2N/5KSkv+ZmZn/ + oaGh/6urq/+4uLj/yMjI/9jY2P/m5ub/8PDw//b29v/5+fn/9/f3//Pz8//u7u7/5+fn/97e3v/S0tL/ + xcXF/7W1tf+kpKT/kpKS/35+fv9tbW3/Xl5e/1VVVf9qamr/wcHB/+Dg4P/q6ur/7e3t//Ly8v/4+Pj/ + /Pz8//7+/v////////////////////////////////////////////n5+f/k5OT/ysrK/35+fv9gYGD/ + 8vLy//////////////////7+/v/9/f3/7e3t/+fn58AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfHx8GHJyct51dXX/ + d3d3/3t7e/+BgYH/iYmJ/5CQkP+Tk5P/k5OT/5GRkf+Pj4//jIyM/4qKiv+Hh4f/hISE/4GBgf9+fn7/ + eHh4/3Jycv9ra2v/YmJi/1hYWP9WVlb/Z2dn/319ff+MjIz/kpKS/5qamv+oqKj/uLi4/8rKyv/b29v/ + 6enp//Hx8f/z8/P/8PDw/+rq6v/g4OD/1dXV/8fHx/+4uLj/paWl/5OTk/+BgYH/dHR0/21tbf9ubm7/ + dXV1/3t7e/+zs7P/4+Pj/+7u7v/x8fH/9fX1//v7+//9/f3//v7+//////////////////////////// + /////////////////v7+//f39//t7e3/q6ur/2VlZf/p6en///////////////////////n5+f/v7+/9 + 8fHxOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB2dna1eXl5/3p6ev+BgYH/kZGR/6Ghof+urq7/srKy/7Gxsf+tra3/ + qamp/6ioqP+pqan/qqqq/6qqqv+rq6v/qamp/6ioqP+lpaX/oaGh/5ycnP+VlZX/iIiI/3d3d/9mZmb/ + VFRU/1RUVP9qamr/f39//4WFhf+Pj4//nZ2d/7CwsP/CwsL/0NDQ/9fX1//V1dX/z8/P/8TExP+4uLj/ + rKys/52dnf+SkpL/i4uL/4uLi/+QkJD/mJiY/52dnf+ampr/jo6O/5ubm//m5ub/8PDw//T09P/4+Pj/ + /Pz8//39/f/+/v7//////////////////////////////////////////////////f39//X19f+1tbX/ + v7+///7+/v/////////////////+/v7/+Pj4//X19ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf39/RHt7e/98fHz/ + hISE/5mZmf+zs7P/xMTE/8jIyP/Dw8P/u7u7/7W1tf+2trb/u7u7/7+/v//CwsL/xcXF/8bGxv/Gxsb/ + xcXF/8XFxf/FxcX/xMTE/8TExP+6urr/qKio/5mZmf+Kior/c3Nz/1hYWP9PT0//X19f/2lpaf9wcHD/ + fX19/4+Pj/+hoaH/q6ur/66urv+qqqr/pqam/6Kiov+ioqL/pqam/66urv+5ubn/wsLC/8XFxf+/v7// + r6+v/5iYmP+BgYH/f39//9bW1v/y8vL/9/f3//r6+v/9/f3//f39//7+/v////////////////////// + /////////////////////////////////////////////////////////////////v7+//r6+v/29vbO + 9vb2CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB9fX2vfX19/4KCgv+Xl5f/t7e3/87Ozv/T09P/zc3N/8LCwv+6urr/ + urq6/8LCwv/Kysr/z8/P/9HR0f/T09P/1NTU/9TU1P/U1NT/1NTU/9TU1P/V1dX/1tbW/9DQ0P/FxcX/ + ubm5/7CwsP+oqKj/lZWV/3R0dP9aWlr/UVFR/1hYWP9hYWH/dHR0/4qKiv+enp7/rKys/7W1tf+/v7// + ysrK/9bW1v/i4uL/6Ojo/+fn5//c3Nz/ycnJ/7Kysv+cnJz/jY2N/4+Pj/+lpaX/urq6//Hx8f/5+fn/ + /Pz8//39/f/9/f3//v7+//////////////////////////////////////////////////////////// + //////////////////////39/f/39/f/9PT03vb29h4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh4eHCYCAgPeBgYH/ + j4+P/6+vr//Ozs7/2tra/9XV1f/Ly8v/v7+//729vf/FxcX/0NDQ/9fX1//a2tr/29vb/9vb2//b29v/ + 29vb/9zc3P/c3Nz/29vb/9vb2//Z2dn/1tbW/9DQ0P/FxcX/u7u7/7u7u/++vr7/sbGx/5CQkP9ubm7/ + W1tb/3BwcP+NjY3/sLCw/9DQ0P/k5OT/8PDw//f39//6+vr/+Pj4//Hx8f/j4+P/0dHR/7+/v/+wsLD/ + qKio/7CwsP/FxcX/3Nzc/+np6f7n5+fHzc3N3Pn5+f/9/f3//f39//39/f/+/v7//v7+//////////// + ///////////////////////////////////////////////////////////5+fn/8vLy/+/v78/19fUY + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACIiIgygoKC/4eHh/+fn5//xcXF/9zc3P/e3t7/1dXV/8nJyf/AwMD/ + xcXF/9HR0f/a2tr/39/f/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/39/f/9/f3//f39//39/f/97e3v/d3d3/ + 19fX/87Ozv/CwsL/vb29/8XFxf/Nzc3/w8PD/6Ojo/99fX3/aWlp/5+fn//Jycn/5OTk//Dw8P/v7+// + 6urq/+Dg4P/U1NT/y8vL/8PDw/+/v7//xsbG/9HR0f/e3t7/6urq/vHx8drm5uaE39/fJQAAAADU1NQZ + 4ODgwfn5+f/9/f3//f39//7+/v/+/v7//v7+//7+/v////////////////////////////////////// + ///////////8/Pz/8vLy/+zs7P3t7e2Q8/PzCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuLi0OFhYX/ + j4+P/6+vr//V1dX/5OTk/+Dg4P/V1dX/yMjI/8TExP/Nzc3/2tra/+Li4v/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/f39//1tbW/8jIyP/AwMD/x8fH/9PT0//Z2dn/ + ysrK/6ioqP+Dg4P/fHx8/7e3t//Jycn/z8/P/9DQ0P/Q0ND/0NDQ/9PT0//Y2Nj/4ODg/+rq6v7w8PDo + 9PT0p+Dg4GrS0tIXAAAAAAAAAAAAAAAAAAAAAAAAAADj4+ME6+vrkfLy8v35+fn//f39//7+/v/+/v7/ + /v7+//////////////////////////////////7+/v/6+vr/8fHx/+np6f/n5+e/7u7uNgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj4+PNoiIiP+Xl5f/vb29/+Dg4P/o6Oj/4+Pj/9fX1//Kysr/ + ycnJ/9XV1f/h4eH/5+fn/+np6f/p6en/6Ojo/+jo6P/o6Oj/6Ojo/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+Pj4//a2tr/zc3N/8TExP/Kysr/19fX/+Dg4P/e3t7/x8fH/6CgoP+BgYH/t7e35eXl5cru7u6s + 8vLyq+Li4n/o6Oh76urqc+vr62Xq6uo/4ODgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA7u7uOe7u7rHw8PD88PDw//Hx8f/29vb/+vr6//v7+//8/Pz/+vr6//b29v/x8fH/ + 6urq/+bm5vbk5OSh7OzsOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYmJgN + i4uL+52dnf/Gxsb/5ubm/+zs7P/n5+f/3t7e/9XV1f/X19f/4eHh/+rq6v/v7+//7+/v/+7u7v/t7e3/ + 7Ozs/+zs7P/s7Oz/7Ozs/+vr6//r6+v/6+vr/+vr6//q6ur/5ubm/9zc3P/Pz8//x8fH/87Ozv/b29v/ + 5eXl/+fn5//Z2dn/s7Oz/5CQkP+ampqzu7u7BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO/v7yPt7e1q + 3NzcqNzc3Nfg4ODo5ubm/Ofn5+Xm5ubb5eXls+np6Yfs7OxL8PDwCQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIy4oKCg/8rKyv/r6+v/9fX1//X19f/y8vL/ + 8PDw//Hx8f/09PT/+Pj4//n5+f/5+fn/+Pj4//f39//19fX/9PT0//Ly8v/w8PD/7+/v/+/v7//v7+// + 7+/v/+3t7f/n5+f/3Nzc/8/Pz//Ly8v/1dXV/+Li4v/q6ur/7Ozs/+Li4v+/v7//mJiY/6SkpOS6uroB + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAKGhoUaenp7/x8fH/+7u7v/7+/v//Pz8//z8/P/8/Pz//Pz8//39/f/+/v7//v7+//39/f/9/f3/ + /f39//z8/P/7+/v/+/v7//r6+v/5+fn/9vb2//X19f/z8/P/7+/v/+fn5//a2tr/z8/P/9HR0f/d3d3/ + 6enp/+/v7//x8fH/5+fn/8TExP+bm5v/q6ur2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJiYmKq9vb3/6urq//z8/P/9/f3/ + /v7+/////////////////////////////////////////////v7+//7+/v/+/v7//f39//39/f/9/f3/ + /Pz8//r6+v/19fX/6+vr/9vb2//R0dH/2dnZ/+bm5v/w8PD/9PT0//Pz8//o6Oj/w8PD/5ubm//AwMCa + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAvb29E6urq9jY2Nj/9/f3//39/f/9/f3//f39//7+/v////////////////////// + //////7+/v////////////////////////////7+/v/+/v7//f39//v7+//19fX/7e3t/+jo6P/p6en/ + 8PDw//X19f/39/f/9fX1/+Pj4/+7u7v/mJiY/ru7uzsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyMjIGLq6us/h4eH/ + 9/f3//z8/P/8/Pz//Pz8//7+/v/+/v7////////////4+Pj/4+Pj/+np6f/29vb//v7+//////////// + ///////////+/v7//v7+//z8/P/6+vr/+fn5//n5+f/6+vr/+/v7//r6+v/z8/P/19fX/62trf+lpaW+ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0NDQCczMzJnf39//8vLy//z8/P/6+vr/+vr6//z8/P/+/v7/ + /////+bm5v+enp7/ioqK/6qqqv/7+/v///////////////////////////////////////7+/v/+/v7/ + /v7+//7+/v/+/v7/+/v7/+rq6v/FxcX/oaGh/sPDwz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAANTU1ELU1NTW5+fn//f39//7+/v/+vr6//z8/P/9/f3/7u7u/9XV1f+fn5//kpKS//z8/P////// + //////////////////////////////////////////////////////7+/v/4+Pj/2NjY/6+vr//Dw8Or + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANvb2wTPz89e29vb1+zs7P/4+Pj/ + /f39//39/f/6+vr/8PDw/7e3t//Gxsb//Pz8//39/f/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + ///////////+/v7/+vr6/+bm5v+6urr/v7+/yNvb2w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAADi4uIC5OTkR+Dg4Krx8fH5+/v7//n5+f/z8/P/1tbW//Hx8f/4+Pj/ + +Pj4//n5+f/6+vr/+/v7//z8/P/9/f3//f39//39/f/9/f3/+/v7//Pz8//e3t7/xMTE99LS0ofk5OQH + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAOnp6Q3p6elQ6+vrmObm5tXo6Oj+7u7u//Ly8v/09PT/9fX1//b29v/29vb/9vb2//X19f/y8vL/ + 7u7u/+Xl5f/e3t7+2NjYyuHh4Xbl5eUTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOXl5Qvd3d00 + 3d3dWN/f33ba2tqT2dnZmt3d3bLe3t6y4eHhoOPj45bp6el07u7uR/Pz8xUAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////8Af////// + ////////////4AA//////////////////4AAB/////////////////8AAAP////////////////+AAAD + /////////////////gAAA/////////////////4AAAP/////////////////AAAD//////////////// + /wAAA/////////////////+AAAf///////////////gAAAAP//////////////8AAAAAH/////////// + ///wAAAAAA//////////////gAAAAAAA/////////////AAAAAAAAB///////////+AAAAAAAAAH//// + //////+AAAAAAAAAAP/////////+AAAAAAAAAAA/////////+AAAAAAAAAAAH/////////AAAAAAAAAA + AA///////x0AAAAAAAAAAAAD/////4AAAAAAAAAAAAAAAf////8AAAAAAAAAAAAAAAH////+AAAAAAAA + AAAAAAAB/////gAAAAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAD////+AAAAAAAAAAAAAAAA/////gAA + AAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAH/////wAAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf// + ///4AAAAAAAAAAAAAAP//////AAAAAAAAAAAAAAD//////4AAAAAAAAAAAAAB///////AAAAAAAAAAAA + AAf//////wAAAAAAAAAAAAAH//////4AAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAf//////AAAAAAA + AAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAA//////8AAAAAAAAAAAAAAP//////AA + AAAAAAAAAAAAD//////gAAAAAAAAAAAAAAf/////4AAAAAAAAAAAAAAD/////8AAAAAAAAAAAAAAA/// + ///AAAAAAAAAAAAAAAH/////gAAAAAAAAAAAAAAB/////4AAAAAAAAAAAAAAAP////+AAAAAAAAAAAAA + AAD/////AAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAH////8AAAAAAAAAAAAAAAB/////AAAAAAAA + AAAAAAAAf////wAAAAAAAAAAAAAAAH////4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAA + AAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD// + //4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAA + AAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAA////+AAAAAAAA + AAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAB////+AAAAAAAAAAAAAAAAf////gAA + AAAAAAAAAAAAAH////8AAAAAAAAAAAAAAAB/////AAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAP// + //8AAAAAAAAAAAAAAAD/////gAAAAAAAAAAAAAAA/////4AAAAAAAAAAAAAAAf////+AAAAAAAAAAAAA + AAH/////wAAAAAAAAAAAAAAB/////8AAAAAAAAAAAAAAAP/////gAAAAAAAAAAAAAAD/////4AAAAAAA + AAAAAAAA//////AAAAAAAAAAAAAAAP/////4AAAAAAAAAAAAAAD/////+AAAAAAAAAAAAAAA//////wA + AAAAAAAAAAAAAH/////+AAAAAAAAAAAAAAB//////wAAAAAAAAAAAAAAf/////8AAAAAAAAAAAAAAH// + ////wAAAAAAAAAAAAAB//////+AAAAAAAAAAAAAAf//////wAAAAAAAAAAAAAH//////+AAAAAAAAAAA + AAB///////4AAAAAAAAAAAAAf///////AAAAAAAAAAAAAH///////8AAAAAAAAAAAAB////////wAAAA + AAAAAAAA////////4AAAAAAAAAAAAP///////4AAAAAAAAAAAAH///////8AAAAAAAAAAAAB//////// + AAAAAAAAAAAAA////////gAAAAAAAAAAAAP///////4AAAAAAAAAAAAH///////8AAAAAAAAAAAAD/// + /////AAAAAAAABAAAB////////wAAAAAAAD4AAB////////8AAAAAAAP/gAB/////////AAAAAAP//+A + B/////////4AAAAAD//////////////+AAAAAB///////////////wAAAAAf//////////////8AAAAA + H///////////////gAAAAD///////////////8AAAAA////////////////wAAAAf/////////////// + +AAAAH////////////////4AAAD/////////////////wAAD//////////////////wAH/////////// + //////////////////////////////////////////8oAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDAwMMBgYGFQcHBxcODg4MBgYGAwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAB0AAABFUFBQqJ+fn+caGhpi + AAAAHAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAACYQEBB8 + zMzM+s/Pz/4xMTGIAAAAKgAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + BAQEAgMDAx9ycnLA6enp/729vf4cHBxBBAQEDgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACQAAABEAAAAX + AAAAGQAAABYAAAASAQEBGBwcHGXa2tr739/f/6+vr/ApKSkQDAwMBAAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwEDAwMIAQEBFAAAACMAAAAy + BgYGQw0NDVkNDQ1hDAwMXwcHB1EAAABHAAAAU35+fs7v7+/+0tLS/5mZmdMAAAAmAAAAHQAAABMAAAAK + AAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBgYBBQUFDgAAACYNDQ1L + Ojo6iV9fX76EhIThoKCg962trfyxsbH+r6+v/aenp/iTk5PobGxs0aOjo/3IyMj+xcXF/3Z2drwAAABK + AAAAPgAAADIAAAAkAAAAFgAAAA0AAAAGAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAEAAAABAwMDAQkJCQoBAQEr + IyMja3R0dMK0tLT5zc3N/9nZ2f/Q0ND/0dHR/9PT0//V1dX/1dXV/9PT0//Q0ND/0dHR/9PT0//CwsL/ + r6+v/z8/P6gAAABfAAAAVwAAAE0AAAA/AAAAKgAAABoAAAAUAAAADQAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGBwEBARsAAAAzAAAAPgAAACgAAAAb + AAAAJBAQEFh3d3fCw8PD/NnZ2f7S0tL+09PT/+Xl5f74+Pj+9vb2//Ly8v7w8PD+8fHx//X19f76+vr+ + +Pj4/+Dg4P7Q0ND+2dnZ/7S0tOtGRkaRAAAAWwAAAFUAAABMAAAANgAAAB0AAAAbAAAAFQAAAA8AAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAFk1NTYmZmZnj + MjIytwAAAH8AAABpMjIykLKysvDW1tb/1tbW/9TU1P/y8vL/8vLy/+vr6//m5ub/9PT0//j4+P/6+vr/ + +vr6//b29v/x8fH/7Ozs//Dw8P/8/Pz/4uLi/9TU1P/Pz8/+iYmJxBISEl8AAABPAAAAMgAAABcAAAAb + AAAAGwAAABcAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + IiIiB5SUlKnw8PD+1tbW/3x8fOVRUVHMx8fH/Nzc3P7R0dH+6Ojo//Ly8v7p6en+9vb2/+Hh4f5tbW3+ + 8PDw//7+/v7+/v7+//////7+/v7+/v7+//////n5+f7s7Oz+9fX1//Pz8/7T09P/ycnJ/q+vr+YwMDBu + AAAAMQAAABoAAAAfAAAAHwAAACIAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAKCgoBbMzMzZ5eXl/6Ojo/7Jycn/3t7e/tHR0f7z8/P+6enp//Pz8/7+/v7+ + //////v7+/7S0tL+/v7+//7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+8vLy//Dw8P729vb/ + 1tbW/rS0tP63t7f0RkZGZwAAACkAAAArAAAAKQAAACMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrKwmm5ub7MHBwf7g4OD/0tLS/vT09P7m5ub+ + +/v7//7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+ + //////Pz8/7y8vL/7u7u/tjY2P6Pj4//tbW1+GFhYXoAAAAzAAAAMgAAABEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoqKgWsrKy6OHh4f/U1NT/ + 8/Pz/+bm5v/9/f3///////////////////////////////////////////////////////////////// + ///////////////////////////u7u7/+fn5/97e3v+9vb3/i4uL/7m5ufxqamqJAAAALAkJCQcAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn5+n + 3Nzc/9ra2v7s7Oz/5OTk/vr6+v79/f3+/f39//39/f79/f3+/f39//39/f79/f3+/f39//39/f79/f3+ + /f39//39/f79/f3+/f39//39/f79/f3+/f39//39/f78/Pz/6urq/vT09P7a2tr/m5ub/pycnP7FxcX9 + bGxseSwsLAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJ6enjy/v7/85eXl/9zc3P7o6Oj/8/Pz/vv7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v+ + +/v7//v7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v/7e3t/vb29v7d3d3/ + pqam/tDQ0P6jo6P/4ODg+q+vrzkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAJeXl7jk5OT/2NjY/+7u7v/j4+P/9/f3//f39//39/f/9/f3//f39//39/f/ + 9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39/+1tbX/ + yMjI/+np6f/i4uL/t7e3/97e3v+7u7v/ysrK/+vr69Hi4uIGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5eXJ7e3t/vq6ur+2tra/97e3v7w8PD/9PT0/vT09P709PT+ + 9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+ + 9PT0//T09P6mpqb/yMjI/uTk5P7n5+f/yMjI/s7Ozv7j4+P/urq6/unp6f7w8PBkAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjo6Oftra2v7f39/+4eHh/+/v7/7t7e3/ + 8PDw/vDw8P7w8PD+8PDw//Dw8P7v7+/+7u7u/+vr6/7m5ub+sLCw/8vLy/7u7u7+8PDw//Dw8P7w8PD+ + 8PDw//Dw8P7w8PD+8PDw//Dw8P7w8PD/8PDw/uDg4P7q6ur/z8/P/sHBwf729vb/ubm5/ujo6P7x8fHQ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlZWVyOrq6v/Z2dn/ + 6Ojo//n5+f/y8vL/6enp/+vr6//r6+v/6enp/9nZ2f/Hx8f/oqKi/3t7e/9aWlr/QkJC/2BgYP/MzMz/ + 4ODg/+bm5v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/93d3f/p6en/z8/P/76+vv/8/Pz/ + w8PD/+Li4v/r6+v+7+/vIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTk5MI + pqam+u7u7v7W1tb+6urq//n5+f76+vr/8/Pz/uXl5f7n5+f+0NDQ/1BQUP5RUVH+e3t7/6mpqf6hoaH+ + YmJi/83Nzf7Kysr+tLS0/7u7u/7Y2Nj+3Nzc/+Pj4/7m5ub+5+fn/+fn5/7n5+f/5+fn/tra2v7j4+P/ + ysrK/r+/v/76+vr/zc3N/tra2v7l5eX/7+/vWgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACSkpIvuLi4/+/v7/7Ozs7+8fHx//j4+P74+Pj/+Pj4/vX19f7m5ub+zc3N/8zMzP7h4eH+ + 4eHh/7+/v/5VVVX+0tLS/+Li4v7i4uL+4uLi/9XV1f60tLT+sbGx/9DQ0P7U1NT+2tra/+Hh4f7i4uL/ + 4uLi/tTU1P7b29v/vb29/r6+vv7t7e3/z8/P/tTU1P7h4eH/7+/vgQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACRkZFLw8PD/+7u7v/MzMz/8fHx//b29v/29vb/9vb2//b29v/29vb/ + 7+/v/+Li4v/b29v/w8PD/1lZWf+5ubn/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3d3d/7e3t/+vr6// + wsLC/9XV1f/d3d3/5OTk/+7u7v/Ozs7/pqam/6+vr//R0dH/wsLC/87Ozv/d3d3/7e3tjgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJRXyMjI/+/v7/7Kysr+7u7u/+vr6/7y8vL/ + 8/Pz/vPz8/7z8/P+9PT0//Pz8/7n5+f+q6ur/6SkpP7Z2dn+2tra/9vb2/7b29v+29vb/9vb2/7b29v+ + 29vb/9ra2v7a2tr+xsbG/9DQ0P7x8fH/8/Pz/uvr6/7Ozs7/iIiI/pGRkf6srKz/paWl/sDAwP7U1NT/ + 7OzskAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVlZVVxsbG//Hx8f7Gxsb+ + 6urq/9bW1v7s7Oz/8fHx/vHx8f7x8fH+8PDw/+jo6P7V1dX+0tLS//Hx8f7v7+/+6urq/+Xl5f7j4+P+ + 4+Pj/+Pj4/7j4+P+5ubm/+vr6/7w8PD+8fHx//Hx8f7x8fH/7e3t/tjY2P7Ozs7/dnZ2/oCAgP6Kior/ + gICA/qqqqv7Gxsb/6OjojAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVlZVD + vr6+//Pz8//Kysr/39/f/+3t7f/u7u7/7e3t/+3t7f/t7e3/5OTk/9jY2P/CwsL/7Ozs/+3t7f/t7e3/ + 7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/6Ojo/8fHx/+oqKj/ + iYmJ/4WFhf9+fn7/ZGRk/42Njf+8vLz/5ubmdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACbm5sisbGx//Ly8v7W1tb+0dHR/+jo6P7r6+v/6+vr/uvr6/7m5ub+2tra/7e3t/7k5OT+ + 6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7n5+f/ + 1tbW/szMzP6Kior/nJyc/pCQkP6AgID/Xl5e/nV1df7Dw8P/39/fTQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACfn58BpKSk7Orq6v7k5OT+ycnJ/+Dg4P7o6Oj/6Ojo/ujo6P7n5+f+ + tLS0/9jY2P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+ + 6Ojo/+fn5/7h4eH/w8PD/qenp/6vr6//rKys/p+fn/6AgID/bGxs/nNzc/7Z2dn+29vbFgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApKSkptfX1//z8/P/xsbG/9bW1v/l5eX/ + 5+fn/+fn5//l5eX/x8fH/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5ubm/97e3v/ExMT/x8fH/6SkpP+8vLz/nZ2d/4eHh/9lZWX/fHx8/4qKiv/j4+PJ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6urTL6+vv7x8fH+ + 39/f/8PDw/7Z2dn/5OTk/uTk5P7k5OT+5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+ + 5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+29vb/8nJyf7Ly8v/j4+P/p2dnf56enr/bGxs/mFhYf5NTU3/ + UVFR/peXl/7AwMBuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + sbGxBLOzs9XY2Nj/9PT0/8zMzP/Jycn/2dnZ/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Hh4f/X19f/yMjI/8fHx/+FhYX/f39//3Z2dv98fHz/ + ioqK/46Ojv+NjY3/goKC/3x8fPhNTU0nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALm5uVC+vr796enp/+/v7/7ExMT/ycnJ/tXV1f7g4OD+4ODg/+Dg4P7g4OD+ + 4ODg/+Dg4P7g4OD+4ODg/97e3v7BwcH+3t7e/+Dg4P7g4OD+29vb/9TU1P7BwcH+ysrK/4ODg/5tbW3/ + e3t7/paWlv67u7v/ycnJ/sXFxf7Nzc3/y8vL/rW1tf5qamqCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9vb2gxMTE/+3t7f7t7e3/xcXF/sHBwf7Q0ND+ + 2dnZ/9/f3/7f39/+39/f/9/f3/7f39/+39/f/9vb2/67u7v+29vb/9ra2v7S0tL+ysrK/7y8vP7V1dX+ + kZGR/2ZmZv58fHz/qamp/s3Nzf7S0tL/2dnZ/ufn5/7w8PD/7+/v/t7e3v68vLzxqKioCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+vr4Iu7u7wsTExP/q6ur/ + 8vLy/9PT0/+5ubn/w8PD/8/Pz//R0dH/1tbW/9nZ2f/a2tr/2dnZ/9bW1v/R0dH/0NDQ/8fHx/+7u7v/ + zMzM/9bW1v+jo6P/Z2dn/3p6ev+fn5//yMjI/9DQ0P/m5ub/9/f3//39/f/+/v7//f39//X19f/Z2dn/ + y8vLPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + vLy8Cra2tqy6urr+3d3d/vPz8/7s7Oz+z8/P/7q6uv66urr+vLy8/8DAwP7CwsL+v7+//7y8vP67u7v+ + vLy8/9DQ0P7h4eH+wsLC/5WVlf6BgYH+XFxc/6ampv7Pz8//19fX/uzs7P77+/v//v7+/v7+/v7///// + /v7+/vz8/P7s7Oz/39/fTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALW1tQKvr69kqamp6L6+vv7W1tb+5OTk/+bm5v7i4uL+2tra/9PT0/7S0tL+ + 2dnZ/+Hh4f7n5+f+3Nzc/8nJyf6xsbH+jIyM/4CAgP51dXX+a2tr/8vLy/7k5OT/6enp/vr6+v7+/v7/ + /v7+/v7+/v7//////v7+/v39/f7z8/P/7e3tNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm5ubEIaGho1tbW36a2tr/3p6ev+Li4v/ + mZmZ/6SkpP+rq6v/rq6u/7Gxsf/ExMT/2tra/93d3f/FxcX/p6en/42Njf93d3f/eHh4/9vb2//u7u7/ + +Pj4//7+/v///////v7+/+3t7f/x8fH//v7+//z8/P/29vbw8fHxBgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe3t7N3BwcLltbW31 + b29v/2tra/5iYmL+WVlZ/1ZWVv5ra2v+kZGR/7e3t/7b29v+8/Pz//Ly8v7h4eH+wsLC/5iYmP5vb2/+ + eXl5/+Pj4/7y8vL//f39/v7+/v7//////v7+/snJyf6ioqL//v7+/vz8/P7v7++NAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/f38Q + e3t76piYmP62trb+sLCw/7Kysv61tbX+tLS0/66urv6bm5v+eHh4/2xsbP5/f3/+pqam/8HBwf64uLj+ + q6ur/6ioqP6kpKT+jIyM/9/f3/75+fn//v7+/v7+/v7//////v7+/vn5+f7j4+P//v7+/vn5+d/19fUT + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACEhIRgk5OT/9HR0f/Jycn/xsbG/9jY2P/b29v/29vb/9vb2//V1dX/vr6+/7Gxsf95eXn/ + iIiI/9LS0v/l5eX/4ODg/8zMzP/AwMD+zs7O1dnZ2Z35+fn7/f39//7+/v/////////////////8/Pz/ + 8/Pz1vb29icAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACMjIxytLS0/uPj4/7Nzc3+3d3d/+jo6P7n5+f+5+fn/+bm5v7k5OT+ + zs7O/9DQ0P7R0dH+lJSU+tLS0qnb29uS4eHhhOHh4VzX19cgAAAAAAAAAADu7u5A9PT0wvLy8vb39/f9 + 9fX19vDw8Mzt7e1s8/PzBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACdnZ0vwMDA/Pb29v719fX++fn5//r6+v74+Pj+ + 9fX1//Ly8v7s7Oz+09PT/9/f3/7q6ur+qKio+bq6uhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAO/v7w/w8PAb8PDwDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvr6+g/Pz8/79/f3/ + /v7+//z8/P/39/f//v7+//7+/v/5+fn/6+vr//Pz8//t7e3/rq6uyrOzswEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAANvb21fq6urg+vr6//Ly8v6qqqr+/f39//7+/v7+/v7+/v7+//39/f7T09P8xMTERgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAADl5eUI6+vrWfHx8ark5OTh8vLy+vT09P719fX+8vLy8ubm5rrZ2dlG + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADq6uoC6enpD+rq6h7t7e0c + 7u7uCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////AAD///// + //8AAP////A//wAA////4B//AAD////gH/8AAP///+Af/wAA///gAB//AAD//wAAA/8AAP/8AAAA/wAA + /wAAAAB/AAD8AAAAAD8AAPgAAAAAPwAA/AAAAAA/AAD+AAAAAD8AAP8AAAAAfwAA/wAAAAB/AAD/AAAA + AH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA + +AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD8AAAA + AD8AAPwAAAAAPwAA/gAAAAA/AAD/AAAAAB8AAP8AAAAAHwAA/4AAAAAfAAD/wAAAAB8AAP/wAAAAHwAA + //AAAAA/AAD/4AAAAD8AAP/gAAAAfwAA/+AAAwD/AAD/4AA/x/8AAP/wAD///wAA//gAf///AAD//AD/ + //8AAP//g////wAAKAAAACAAAABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAEBAQYGBgYPCgoKCgMDAwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAARo6OjtNMTEyaAAAAGgAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwc5OTmE4ODg/1FRUY0CAgIRAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQEBAwAAAAwAAAAXAAAAIwAAACUAAAAgAgICNLe3t+TT09P/QkJCVAUFBQgAAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAwMDDQcHBy8sLCxxUlJSpnNzc8Z+fn7UfHx80GZmZrtaWlrBzs7O/8jIyP8TExNY + AAAAMwAAACEAAAAPAAAABgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgIC + AAAACAAAAAoAAAAFAwMDCg8PDz5jY2Oqubm5883Nzf/b29v/4ODg/+Pj4//i4uL/4ODg/9nZ2f/IyMj/ + rq6u+g8PD2sAAABXAAAARgAAACkAAAAXAAAADQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAcHByJgYGCmFxcXjAAAAFg5OTmIurq68dXV1f/g4OD/7u7u/+/v7//y8vL/8vLy//Ly8v/z8/P/ + 8vLy//Dw8P/b29v/v7+/8EVFRYwAAABQAAAAKwAAABoAAAAYAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAR0dHF9ra2urLy8v8cXFx39PT0/7Y2Nj/7Ozs//Dw8P/7+/v/m5ub//j4+P////// + ///////////+/v7/9PT0//T09P/i4uL/xsbG/nd3d68DAwMsAAAAIAAAACMAAAANAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsrKyOa+vr/bV1dX/2tra/+7u7v/29vb///////////////// + ////////////////////////////////+vr6//Pz8//h4eH/qKio/42NjbkJCQk4AAAALAAAAAMAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjo6MmycnJ9dvb2//t7e3/+fn5//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/9/f3//T09P/Ly8v/k5OT/52dnckKCgoo + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK2trbnf39//6Ojo//Ly8v/8/Pz/ + /Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz/7+/v/+bm5v+0tLT/ + q6ur/7S0tLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJQ31NTU/+Hh4f/m5ub/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/8DAwP/Ly8v/ + 6Ojo/729vf/V1dX/0dHR/+np6VMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ6enprl5eX/ + 5OTk/+rq6v/x8fH/8fHx//Hx8f/x8fH/7+/v/+vr6//Gxsb/7u7u//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 6Ojo/+jo6P/m5ub/t7e3//b29v/Jycn/7e3tzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + s7Oz5ODg4P/t7e3/9/f3/+rq6v/q6ur/2NjY/56env96enr/eHh4/0pKSv+3t7f/1dXV/+Tk5P/p6en/ + 6urq/+rq6v/q6ur/6Ojo/+Hh4f+1tbX//Pz8/8jIyP/t7e3+8PDwIAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAIqKihjIyMj/2tra//Ly8v/4+Pj/9vb2/+jo6P+3t7f/sbGx/9jY2P+EhIT/xcXF/+Tk5P/Q0ND/ + wcHB/8PDw//a2tr/39/f/+Pj4//h4eH/2dnZ/7Ozs//s7Oz/x8fH/+np6f/v7+9PAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAi4uLNNTU1P/V1dX/8vLy//b29v/29vb/9vb2/+/v7//h4eH/lZWV/6ampv/e3t7/ + 3t7e/97e3v/e3t7/1dXV/7+/v/+7u7v/39/f/+rq6v/a2tr/np6e/8HBwf+1tbX/4eHh/+7u7l8AAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACPj4851tbW/9PT0//l5eX/5+fn//Ly8v/y8vL/8PDw/+Dg4P/V1dX/ + 6Ojo/+Pj4//g4OD/4ODg/+Dg4P/j4+P/5+fn/+7u7v/w8PD/7+/v/83Nzf98fHz/jo6O/46Ojv/Kysr/ + 6urqXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJGRkSjNzc3/2tra/+Hh4f/t7e3/7e3t/+zs7P/e3t7/ + ycnJ/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+zs7P/Z2dn/r6+v/4yMjP+BgYH/ + bGxs/6ysrP/n5+dJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5eXBbu7u/bo6Oj/0dHR/+jo6P/p6en/ + 5+fn/7+/v//k5OT/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/5OTk/8rKyv+fn5// + paWl/4iIiP9ubm7/sLCw/uHh4RgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6+vte3t7f/Ly8v/ + 39/f/+bm5v/l5eX/2NjY/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+Hh4f/MzMz/ + ra2t/6+vr/+Ghob/YGBg/3BwcP/Pz8/MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwsLBP + 09PT/+bm5v/IyMj/3t7e/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//d3d3/ + ysrK/6qqqv+BgYH/d3d3/4ODg/9+fn7/bm5u/3t7e3YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALS0tAG8vLzB5ubm/9nZ2f/Hx8f/2dnZ/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/xMTE/93d3f/e3t7/ + 1tbW/8bGxv+urq7/bW1t/42Njf+9vb3/y8vL/9TU1P/R0dH/k5OTwQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAL29vR2/v7/k5+fn/9/f3//CwsL/zMzM/9XV1f/Z2dn/29vb/9ra2v/S0tL/ + 09PT/8PDw//Kysr/vr6+/2xsbP+NjY3/x8fH/9vb2//z8/P/+/v7//n5+f/a2tr/w8PDIQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALm5uSC1tbXM1tbW/+zs7P/W1tb/x8fH/8HBwf+/v7// + wcHB/8fHx//Ozs7/1NTU/6Wlpf+CgoL/dHR0/87Ozv/h4eH/+fn5//7+/v///////v7+//Pz8//h4eEy + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmpqQObm5toioqK7JGRkf+mpqb/ + tbW1/8DAwP/ExMT/zs7O/9PT0//CwsL/mZmZ/3t7e/+SkpL/6urq//f39//+/v7//f39//Ly8v/+/v7/ + 9/f3+O/v7wwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHl5eYl+fn7v + gYGB/3l5ef9ubm7/b29v/4mJif+9vb3/5+fn/97e3v+vr6//gICA/5+fn//y8vL//v7+///////39/f/ + tra2//7+/v/09PScAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgoIy + m5ub/8rKyv/FxcX/1NTU/9XV1f/Pz8//qqqq/3t7e/+YmJj/z8/P/8/Pz//BwcH+vr6+1PLy8ur+/v7/ + /v7+///////+/v7/9/f3xfb29g8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAI2NjUPJycn/3Nzc/+jo6P/s7Oz/6enp/+fn5//Ozs7/2dnZ/6ioqNTV1dVk4ODgUd3d3SEAAAAA + 7e3tHPLy8o309PS58/Pzpe/v71nw8PADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAoaGhBM/Pz8f8/Pz//v7+//r6+v/9/f3/9/f3/+Xl5f/v7+//srKylgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1dXVCuXl5YT39/ftzMzM//z8/P/+/v7//f39/93d3eTDw8Mf + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrq6gXp6ek66urqX+3t7Wnq6upJ + 4eHhCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAD////////h////wP///8H///AA///AAB/wAAAP8AAAD/AAAA/4AAAP+AAAH/gAAB/wAAAP + 8AAAD/AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA/wAAAP8AAAD/gAAAf8AAAH/gAAB/8AAA/+AAAP + /gAIH/4Af///AH///8D//ygAAAAYAAAAMAAAAAEAIAAAAAAAYAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAB0/Pz9vCwsLIwAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQEBAiEhIWDQ0ND9FBQUQAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAEBAQIAAAAOAQEBIQYGBjgFBQU4AAAAMZmZmcu+vr7wDQ0NFgAAAAcAAAAB + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDDAwMKU1NTYuQkJDR + sbGx9cHBwf6/v7/8qKio7cDAwP6KiorYAAAAUAAAADgAAAAaAAAACgAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAVFRUwMzMzgwAAAEs9PT1/urq679zc3P7l5eX+8vLy/vX19f719fX+9PT0/ufn5/7Q0ND6 + Z2dnqwQEBFQAAAAnAAAAGQAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsbGwy3t7e9Y6OjuvV1dX+ + 5eXl//Pz8/709PT/y8vL///////+/v7+//////j4+P7y8vL/2tra/5OTk9IRERE3AAAAJAAAABMAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqKiohNXV1f7o6Oj/9/f3//7+/v7////////////////+/v7+ + //////7+/v78/Pz/8vLy/8HBwf6WlpbbGhoaRwMDAwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOjo4P + yMjI6OLi4v7z8/P+/Pz8/vz8/P78/Pz+/Pz8/vz8/P78/Pz+/Pz8/vz8/P78/Pz+9PT0/ujo6P6rq6v+ + ra2t22xsbBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn5924ODg/+jo6P729vb/9vb2//X19f729vb/ + 9vb2//b29v/19fX+9vb2//X19f729vb/u7u7/+bm5v7Ly8v/yMjI/+rq6o4AAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAC6urrR4ODg//Ly8v7t7e3/7e3t/+Dg4P69vb3/jY2N/7m5uf/p6en+7e3t/+3t7f7u7u7/ + 7u7u/+Tk5P7Hx8f/29vb/+np6fPi4uIIAAAAAAAAAAAAAAAAAAAAAHFxcQ3Pz8/94ODg//n5+f7x8fH/ + 29vb/5SUlP6xsbH/ioqK/9fX1//Kysr+x8fH/9vb2/7i4uL/5eXl/9vb2/7BwcH/4eHh/93d3f7x8fE3 + AAAAAAAAAAAAAAAAAAAAAHR0dCja2tr+3d3d/vLy8v719fX+8/Pz/ubm5v6bm5v+09PT/t3d3f7d3d3+ + 3Nzc/sbGxv7Ly8v+6enp/t7e3v6bm5v+ubm5/tDQ0P7u7u5HAAAAAAAAAAAAAAAAAAAAAHh4eCba2tr/ + 1tbW/+fn5/7v7+//7Ozs/9bW1v7n5+f/7e3t/+np6f/o6Oj+6enp/+3t7f7v7+//7e3t/8XFxf6BgYH/ + e3t7/66urv7r6+tBAAAAAAAAAAAAAAAAAAAAAHp6egjMzMz61dXV/ufn5/7q6ur+19fX/tfX1/7q6ur+ + 6urq/urq6v7q6ur+6urq/urq6v7p6en+2NjY/qurq/6enp7+c3Nz/qGhof7h4eEYAAAAAAAAAAAAAAAA + AAAAAAAAAAC5ubm84uLi/9bW1v7l5eX/3d3d/+Xl5f7l5eX/5eXl/+Xl5f/l5eX+5eXl/+Xl5f7a2tr/ + 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 + + + + &Om... + + + lvwTasks + + + newToolStripMenuItem + + + 3, 3 + + + &Redigera + + + tabPage3 + + + mnuRemove + + + $this + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA2ZJREFUOE91U21M + U2cUbo1MDa7bUiMxRj7iHxmZyNRItBGVmjESdAZZMj/ohlrAhuzPUJHEKCNmg0URAoFEh9SxhNQV2qKW + tlRoXbHlQ0trewF7295bLf3gw0UJjNJntzcxi7id5Px4T/I855z3OQ+Xsyza2toSBQLBKR6PJ4yLi0vh + crkrIpGIz+/3G8fGxm7n5+dbl2PevrkajeZSKBCYn6G8mLQ+AW0ywtuvB/WoH/7Rp/DTVNRms7VKpdL4 + 90gUCkWb3+MB/acBVK8G3p57cKs64ZJ3YLzjDog7t2D7tQWk+TGcTudAbW3tvyRyubzE53LBdV8Fr1aN + uXAIlE4NorUFjuYbILtkeOV2YfBSOR5+9zWsSjlGRkZa2CkKCgo+IAhicqxbAaf0Fv5iwLFYikTguHEV + wz+cxuL8PBYWFhDwuPFH2nr8nroehN0eqamp2cypqKjIfukm8bTuZ1hrqmC6cg5BH41oNIrFxb8x9+YN + Zmdn8YKmoT3zFXq3rMG9zasxLL0JlUp1ntPY2Pi9Z8gCy4Uy6L/cCW1qPHSHdiDgf4mpqSkEg0EEAgFY + zuZhXPARrLt4eJS+FoM/VcJoNMo49fX1FzxmEzT7P0NP6lqYdnyMidY6FhTLUCiEcDgMv16BQH4K6IN8 + 2PZ8AmvdFRgMhi5OGRPTzMhdW3jQf87HhKyV7RoDeYlnGDXo4GHUcbvd8Fn6ERRtw/PsdSA1ytgKUk5m + Zmbe9PQ0DJLj6M3cAIvyLtuZGDSBFu9C+Ns0jKg7WVJqgoD7zG6MHtuOudevUV1d/SOHz+d/KJPJZmdo + L7TZn8KQtQm6a5dBnNiGuW+SMH88GSFRGoY7bmJccgDkkRSQRi0oiooKhUIBK2Vubm6V3W5HmJzAw2NC + DOxJgPOLjfDkJcJ3JAkvmPQcToTl6FY8vvsbSJJEc3NzLwPlvr3I1RKJRN/X18fKNv6gEwMXxTCKsmE8 + uQ/9ZQXQXK+CrkcNs9mM7u5ub0ZGRtI755yQkBDPGEXKMC8NDQ3B5/Oxe9OM/g6HA2q1GkqlMtrU1GRJ + T09P/k9DicXidUVFRb9UVlZONjQ0LLW3t0eZ/4kyDl0qLy+fKSkpkZWWlm79Pzey9aysrJWFhYUbGbK9 + xcXFR2PJgPaLRKLknJycVcvB/wD+blEYqZtj7gAAAABJRU5ErkJggg== + + + + label6 + + + 199, 243 + + + True + + + columnHeader3 + + + Skapa ny schemaläggning + + + 119, 22 + + + label2 + + + &Verktyg + + + 2 + + + 111, 136 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 5 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Telldus Schemaläggare + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 92, 22 + + + 0, 590 + + + 3 + + + 131, 13 + + + System.Windows.Forms.ImageList, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 119, 22 + + + Senast körd + + + System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + pictureBox2 + + + 111, 158 + + + 0 + + + 2 + + + contextMenuStrip1 + + + frmMain + + + 2 + + + tabPage3 + + + 119, 13 + + + 113, 22 + + + 8 + + + Magenta + + + Telldus hemsida... + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA01JREFUOE91U2tI + k2EUXnQFG1Ysi+5REfTDGEQJSRD+qWEGYkVChe7HlHU3c7RuFrIoK3Jpm0NikhfYJrqt3OalOafbbE3d + pruY07lZc1NLnZmYe/r2QUVWBw68533PeTjnfZ5DoSwwsVi8xePx5I+NjbVNTk5+nJqaCoyPj5vtdvtT + qVS6d2H+rzg9PX2RRqO5HQyNfPOFvLAOdcL4oRWtrma0u1tg83ZhOOCP2Gy2lyKRKOYvILlcLvZ+HISh + TwetS4MWdwPaP2ih62uEoluCyo4ylLcJ8c5pgMPhMJSUlPwGkclkWZ6hfqjtCiisEtR0VsA+1IWfprbV + Iq8uE+elp5BdfQJKUw0sFouQ7CIlJWWZy+UKqLprUWkphfjdc4gMj9DmbEIkEiG9sOEq9vOXYF/RYtCf + LcaBQhp6nPbvPB5vB4XD4SQN+j0QGB9A2VONrmEj6l2VcH3qxuzsLMLhMNqdGlSaHqPC9AQs2UEkli1F + tV4EhUKRRykuLr5k6TeBZzyPVrcKc3NzmJmZwcTEBEZHRzEyMkJ6MBgkY4H+Ko7XrABfewN6vV5CKSoq + 4pj723H27R5IDWUgKITb7YbX6yULQ6EQfD4feUdQidK3V8BsXoky4x3odLpaygXChkd9YKhicPLNGmTI + 1+Pi6w1Qd5SD0AIJIjNwUaDZgnz1ZtzUxeGyYRVaXHXREcopCQkJxwih4K7+NM6YqWB3rsZN61o0vBdj + YGCAdKWVg1LnJhQ7NuJhz3oChI7w1zAKCgruU2g0GlUikXwZHvOCSYzB6lyH69ZNqDe9gt/vRyAQwJue + fDx37sZTxy7cMu5EB6ER4i2SlJSUSFLJYDDuRecbDPbhctNRnNNvB7suETmSI8iTMnCj6SC45r3IUSdA + rq8g/0koFDbFxcUtIgGoVOoKNpvdrNVqMT09jcZeOR60XMQ19XHkqJJxp/4cXrzmQd2ogslkglKp9MbH + x2/9Q86xsbExaWlp5QKBYN5sNpPtR6mLMtDb2wuVShUtjBAS7qDT6dv+uVQsFouWmZlZyOVyA3w+f76q + qipCyDxCbOh8bm7u5+zsbAmRE//fjYw+JCcnL8nIyNiYlZV1iEhOizpxPsxkMrelpqYuX1j8A/bFYLQi + FLFKAAAAAElFTkSuQmCC + + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 4 + + + pictureBox1 + + + tabControl1 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Microsoft Sans Serif, 8.25pt, style=Bold + + + Schemalägg enhet(er) + + + 111, 116 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Magenta + + + 4, 22 + + + 10 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Kör... + + + System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolsToolStripMenuItem + + + 57, 197 + + + &Avsluta + + + System.Windows.Forms.NotifyIcon, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAt1JREFUOE+V030s + 1HEcB/DfeUrDsd1wtNap8xTNnIcjj5vCRIfWZfOUKKeIowcP1ehhkTxlidrE1GweNg8RFksoD5kwI+c0 + PUhUl4c7ws+7a23MUOv7z2ef7z6f13ff7fOhEJucwOoc+k42w3FuQVGru2V2amV+YKAtJL5ns9p1d0a8 + QqXAEnHWjW7xYvbQNFIFkzheO4f9pa0r5iXp7cyMMOstEbNrRbTQBlFv7SiJwW8k3k1L43cS9WMkkl4u + wfaxAHLcComcTbr7BsSY70IJ6GpprhCSEEgbv86TmPlJYlIah6V5mRQ93fYROrc7oBt/Z0bVOUpnHWJf + H3PoXM8bNH8mMTpLQiRtlixJgYU/ecW4BIkjfeC2PYNlWQ7YpfySdQCrJqzgQucw6j6R6PtB4oOYxIT0 + 9d+xQ7SIlKlKXBxpAE+QA5+BZNjWRs3TvE0UVxGtfLfOE41dKBhdxpMJEu0iEnUiIe6LqnB9/C7ihHkI + 63oFl6o6eLamgVXIB9WTvXcV2J7Afu1QlI8r3QtIHVlGikCIiP4ExLyNx/nhS4gcjENobxqYmR0wzEuG + 6lk/KDiaGa99gxP9UDe5H/6VX8BrnYFvSwdcazg40nQM3Oe+cH3qDfcmfzg38kG/Gg31dPtFwpiutAbo + Z7rKBtRgX9oQXB+9h1v5GCweRMKswA7sYgeYFtvBoNAKzCJrqCU6Q+mMXdXGeTDKfSHjXw31yz3QSx2C + UZYAzJRy7E6yAOOWCTRuGoKWoQ95vwOL8hyG5UZAjb+DYGQIiYMFIPyqIBPaCNmTuaCGGkA1WhfUWCa2 + hTNXKFZOvK1HWjFYnVCNLSO0k0nCMAWEjQsoXrugHGgAFR+2hGLqlE1ouVH/vhN0D3UVVsg9E27ShElQ + sNgsIlxsfCp6UoHl20nR804n6B7afwdodjKE9mFNBSNfayo72EvZPIgryzzqRjA4LGKPpwah6Sjzz638 + n4JfHjGLP3wxItMAAAAASUVORK5CYII= + + + + 3, 3, 3, 3 + + + + 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 + + + + Konfigurera enheter + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAK7wAA + Cu8BfXaKSAAAAyRJREFUOE9Vk3tIUwEYxWeiFZHNICkIojAsMBmJJRkhGiKZGUUPSkoriVolzSiopMyw + 1NCsiZr0QE0LjVDzUc3HFJ1uaWsmPipd6dbcarO0bGqdzl3+sS78uJd7v3Pu9333XBeR05GaWuk19s0m + 9ZjvFuEpnuM9NWWH0WR5b/lirunrV99vbHxuZPkkgbPOcZ2fr91R8rDFavpsxuDoFLSWSagNP6Hu/wxF + rQJXk7Ise/ccjWGpmLj+ZyCIm+q7p38B0E0BRp6HfgMDdkA7AdSagAZ1N26kZtpDQiJOULyIzHKYCG0X + FzVZxyl62tGDu0UFoA76aaCb4ld80E7qbECVUoMzp8+ZxGJxJKULiIso8WJhkkE/DA2LegxGuHG+0sZm + DNOklzQMfcdl+QO0jgGVvJmfk42AgIA8in2Jm+h6SklH38gPDLL1bxRUaF5jnqsLqnsG0WqewGJPD0Qf + l0HJDpq+AiU1LdgWsbWd4p3EU5SbXTbabhiHngv4IECTW6WVCN0YiECJH8oVSvRZuVQaqASDhl4ciT1g + oDiBLBXdziy2tQxY8e4noLECaraqpdH28DDcy89FaFYoNt/ajCdvnuPjD6BQ0YVDB6OHKb5CVogunpdr + WnXvUfeF83LbTWag7TsX+tYMnXEUQTcCcV+XhYSqk5A+jUdHVz+Oxh3upDjZYRB3JPFKbUUFyvWAggYv + uag6A1A/wnFotDbFD9kdyUhUxWKXYhXCC4IQL4/XUZxIlomCg8OXJyfdtLxQqlBOcS2p+gg8o2E/55Zc + XwOpcgt2N/hAqg1A+tcoBN1bbaf4ElkuRMF93764mLRrGfbyGgXKev+gmp3UkwF+WkmaL2TqMJx664+r + I5HYVCKZYOMF1F1wdOAIA+MZEhIplcWfNd2R30RRWRUKq9vQ2fsJ/pl+kI/EYH/zBoTmBFtYW0ZSSNhM + mByBFGLpJSTM3399XtS2rW2HYw8MlT5+ZJOkrZmWpPvaYzNiVKwpnnnzuhnxvzjPHMIPIsRTSJgQEhkR + Np1GMkgqOUb8yFxnofO1MI47WUiWkhVkJfEh3mQJme0s+Au+QgUxI1c9OgAAAABJRU5ErkJggg== + + + + &Schemalägg + + + statusStrip1 + + + Schemaläggning... + + + 219, 13 + + + tabPage3 + + + 1 + + + 0, 24 + + + Startar konfigurationsprogrammet för enheter. + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 3, 3, 3, 3 + + + 196 + + + tabControl1 + + + 35, 13 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 862, 515 + + + tabPage3 + + + 166, 6 + + + cmdTurnOff + + + $this + + + AutoSize + + + 46, 20 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 870, 25 + + + AutoSize + + + 47, 20 + + + Tillverkare + + + 1 + + + Stäng av + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + tabControl1 + + + True + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + 120, 48 + + + 143 + + + Microsoft Sans Serif, 8.25pt, style=Bold + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 862, 515 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAidJREFUOE9jYICC + 3HnFii3bJ1rD+CTRst58Mnnr0z+vebrrb/7qbHtCmtesWWOyfv16Ebg6XhMmMYtqhfdVO7P+N+8vvRfS + 4smLbkhnZ6fdtWvXPA8ePLjk1atXb/bt25ezYsUKf7g6pRi2iKApev96T9T9b9iVNwvdgOnTp3fs3r37 + /927d/+fOHHi2OnTp2+cO3euGEWdaaHA/Py1gf+nnWv6V74+1RNZ8tChQxeqKsv/AzX9f/To0f/nz5// + nzdvXjCKAcKWLDweLXK3Og8X/O873nIXJrl27dqkY8eO/Tty5Mifixcv/lywYMGJ+Pj4RKxhpRjAaeTb + Zf0uZ0Pxn7yZJaJTpkxJ2rlz529goN2NjIwMERYWFiIUyAxybnLsBuE6C+avWHDk5MmT/4Chvt/JyUmQ + oEaYgsysTObVa1ZPP3DgwH+g7XttbGy4iNacn5/PBQzhjR8/fvy/ZcuWncuBoKSkhJmQAYxABVyKiory + 27ZtO/ny5UuQ5q0WFhYcVlZWFqtXr66QkpICqcEN7O3tzZcuXfrk6tWr/ydPnrxHTk6OG6haFIhl3d3d + 24yNjb2BbHGsJgBTlPOuXbteAuP6/8yZM09ycXHJABWqQrEIGxsbd29v75G8vDwjrAbs2bNnWWxsrA8w + tO/x8/PrAxXxAzHI3yBn8wCxNNArDWfOnDmC1QCQ85KTk2cANZsCFTBhUQQyiM/Q0DCYg4ODjVCAkiQP + ADBk5tzXJg/8AAAAAElFTkSuQmCC + + + + 9 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Sätt pÃ¥ + + + columnHeader4 + + + 3 + + + 172, 22 + + + menuStrip1 + + + 862, 515 + + + tabPage3 + + + ID + + + 870, 541 + + + AutoSize + + + 111, 190 + + + tabPage2 + + + System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + linkLabel1 + + + 870, 612 + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 4, 22 + + + columnHeader1 + + + tabPage3 + + + System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + columnHeader2 + + + 5 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA1VJREFUOE91U21I + 0wkc3s68Akvq7DJ6j4qDPiSDo4RGEvnBRtEHs7gP50jBKTN78cyXddebR6HWcS5tGVIbTYTZcC/lNl+a + 23Kb7aZuc2/qdC/m3NQS5pmoe/rvDxJZ/eD58PvB8/B7e6iUVcHn83fR6fTcxMTE9Pj4+L1UKvWHpaWl + wMTEhNblcj3LzMwcWM1ZyakqleqvUHjyoz/shcXXB8OwFlpXF3rc3bB6++F/54tardanAoEg4SsRiUTC + 974bg35IA7VLhW53O3qG1dAMdUA2IEJTbyMEbx7jrVMPh8Ohr66u/iwiFovzPb4RKG0yyCwiiPuEsPn6 + sRJKaytKJTkobDmPguYsyI1imM3mx2QXWVlZPzqdzqBioBVN5gbw3z7EE3013jg7EY1GSdS0X8Vh7hr8 + WhsH2r9xOFKzGTa7bamqqmofpby8/MRYwAOe4R7kg83oHzegzdUE18QAFhYWEIlE0ONUocl4H0LjA7Be + HAW9MR7NuieQyWSllLq6ukvmESPuGgqhdSuwuLiI+fl5zM7OYmpqCpOTkyRCoRCZ83RXcUa8Dlx1BbRa + rYhSW1tbZhrpQfbrg2jRN8Lj8cDtdsPr9ZLEcDgMv99P1mw2GxpeX0Fu13o0Gm5Ao9G0Ui4SMT7lB0OR + gHOvfsIF6VYUvdwGZa8A09PTpMgLPQd/q3bhlnInrmu24LJ+I7pdktgIAkpqaurpmZkZ3NT9ht9NG8Du + 24Trlp/R/h8fo6OjJOSWMjQ4d6DOsR1Vg1sJERoi/0dQWVl5h5KUlLRBJBJ9GJ/2IpcYg9WXjGuWHWgz + PkcgEEAwGMSrwVt46PwF/zgO4E/DfvQSP+Lz+aLp6el08pQMBuN2bL6x0BAud54EU7cXbAkdxaIMlLYw + UNF5FBxTCoqVqZDqhOSeeDxeJ0GlrnzkOjab3aVWqzE3N4cOuxT3uovwh/IMihWncKONiUcv70LZoYDR + aIRcLvfSaLTdX7xzcnJyAmEUAaG8bDKZyPZjp4tdwG63Q6FQQCqVRuvr63tTUlL2fNNQeXl5m3Nycmo4 + HE6Qy+UuC4XCKLGfKOHQ5ZKSkvf5+fmigoKCQ99zI1lPS0tbk52dvZ0QO8Zisc7GQJCOM5nMPRkZGWtX + kz8B5RdV6J337i8AAAAASUVORK5CYII= + + + + label5 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA2RJREFUOE91U2tM + k2cUrsniXBDR2NQYI2D8IxKrTI1kGi+ri5EAKtYlq1sYoAI2ZH9EG0mMsDA2syhCIDSoBDQS0nKxRS1t + qVBqsaWgpdiWYr9evnL52nIZKIEBffz6/dCIepKTvG/e8zznvHmew2Iti9ra2miCIArHx8efT09Pj8zM + zIxNTEyYBgYGbkml0p3L6z/cBQLBCqVSeS1AUXOTXg/GzC9B6rvg6dTAq+vEaP8rUMO+kMViqamuro74 + jEgmk9WOut0gn2vhbVfC0/YYLnkznE0NcDTch/3+XVjuiUEYXsBms3VXVlZ+JGlsbMzxOZ1wPpHDo1Jg + NhiAV62AvUYMa9VtEC0S/OdyoudaPp5l/AyzrAl9fX1iZorU1NSVg4ODY4Otj2Cru4tpGhyOpcVFWG// + hd5L57AwN4f5+XlQbhca4zl4GMeB4/XAYklJyVaWSCTijbgIvCr9B+YbRdAXXobfRyIUCmFh4X/MvnuH + qakpDJMkVOdPon3bd3i8dRV66+5ALpdfYVVUVPzhNhlhFOVBc3wvVHERUKfuATU6AloJ+P1+UBQF48UU + OA5EwbxvDXQ7V6Pn7wLodDoJq6ysTOQ26KE8sgNtcauh37MWQzWlDCicgUAAwWAQo5pHoE5vAfnTelj2 + r4O5tBBarbaFlUfHBD1yy7Y10Hy/HkOSGqZrGOSxv0a/Vg03rY7L5YLP2Al/+i684bFBKGXhL9SxEhMT + U2ijQCs8i/bEjTDKpExne48e5IV9CP4ejz5FM0PqHbLDdf4H9At2Y/btWxQXF//JYrPZkRKJZGqS9EDF + 2w7toc1Q37wO+6+7MPtLDObOxiKQHo/ehjtwCH8EcWoLiC4VfD5fiMfjHWCkTEpKKqKtiiAxhGeCo+je + vwG2Y5vgTomG71QMhul0n4iGkc/FC+kD0FaHWCxu53A4KxiCyMjIVUKhUNPR0cHI5njajO6rF9CVzkPX + b4fRmXcGyltFULcpYDAY0Nra6uFyuTGf2DkqKiqCz+fXVVVVLZlMpvCIzL9JWn+r1QqFQhEGhmgLGxMS + EmK/uFTZ2dnszMzMfwsKCsbKy8uX6uvrQ7TNQ/SGLuXn50/m5uZK6BruVzcy/JCcnPxNRkbGppycnIN0 + MT+c9PlIVlZWbFpa2rfLwe8BECxb5G8PU2sAAAAASUVORK5CYII= + + + + toolStripSeparator + + + 4 + + + System.Windows.Forms.ToolStrip, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Schemaläggning + + + 113, 22 + + + columnHeader7 + + + lvwCommon + + + columnHeader6 + + + label1 + + + &Ny + + + tabPage3 + + + 1 + + + statusStrip1 + + + 101, 22 + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + toolManageDevices + + + 0 + + + 65, 22 + + + 0 + + + 4 + + + tabPage1 + + + 247, 13 + + + 7 + + + True + + + Välkommen + + + 442, 17 + + + 0, 0 + + + 0, 24 + + + 552, 17 + + + 335, 17 + + + True + + + 707, 17 + + + 0, 590 + + + English + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmMain.sv.resx b/scheduler/DeviceScheduler/frmMain.sv.resx new file mode 100644 index 00000000..af9f0537 --- /dev/null +++ b/scheduler/DeviceScheduler/frmMain.sv.resx @@ -0,0 +1,3072 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA01JREFUOE91U2tI + k2EUXnQFG1Ysi+5REfTDGEQJSRD+qWEGYkVChe7HlHU3c7RuFrIoK3Jpm0NikhfYJrqt3OalOafbbE3d + pruY07lZc1NLnZmYe/r2QUVWBw68533PeTjnfZ5DoSwwsVi8xePx5I+NjbVNTk5+nJqaCoyPj5vtdvtT + qVS6d2H+rzg9PX2RRqO5HQyNfPOFvLAOdcL4oRWtrma0u1tg83ZhOOCP2Gy2lyKRKOYvILlcLvZ+HISh + TwetS4MWdwPaP2ih62uEoluCyo4ylLcJ8c5pgMPhMJSUlPwGkclkWZ6hfqjtCiisEtR0VsA+1IWfprbV + Iq8uE+elp5BdfQJKUw0sFouQ7CIlJWWZy+UKqLprUWkphfjdc4gMj9DmbEIkEiG9sOEq9vOXYF/RYtCf + LcaBQhp6nPbvPB5vB4XD4SQN+j0QGB9A2VONrmEj6l2VcH3qxuzsLMLhMNqdGlSaHqPC9AQs2UEkli1F + tV4EhUKRRykuLr5k6TeBZzyPVrcKc3NzmJmZwcTEBEZHRzEyMkJ6MBgkY4H+Ko7XrABfewN6vV5CKSoq + 4pj723H27R5IDWUgKITb7YbX6yULQ6EQfD4feUdQidK3V8BsXoky4x3odLpaygXChkd9YKhicPLNGmTI + 1+Pi6w1Qd5SD0AIJIjNwUaDZgnz1ZtzUxeGyYRVaXHXREcopCQkJxwih4K7+NM6YqWB3rsZN61o0vBdj + YGCAdKWVg1LnJhQ7NuJhz3oChI7w1zAKCgruU2g0GlUikXwZHvOCSYzB6lyH69ZNqDe9gt/vRyAQwJue + fDx37sZTxy7cMu5EB6ER4i2SlJSUSFLJYDDuRecbDPbhctNRnNNvB7suETmSI8iTMnCj6SC45r3IUSdA + rq8g/0koFDbFxcUtIgGoVOoKNpvdrNVqMT09jcZeOR60XMQ19XHkqJJxp/4cXrzmQd2ogslkglKp9MbH + x2/9Q86xsbExaWlp5QKBYN5sNpPtR6mLMtDb2wuVShUtjBAS7qDT6dv+uVQsFouWmZlZyOVyA3w+f76q + qipCyDxCbOh8bm7u5+zsbAmRE//fjYw+JCcnL8nIyNiYlZV1iEhOizpxPsxkMrelpqYuX1j8A/bFYLQi + FLFKAAAAAElFTkSuQmCC + + + + + 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 + ADBk5tzXJg/8AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAt1JREFUOE+V030s + 1HEcB/DfeUrDsd1wtNap8xTNnIcjj5vCRIfWZfOUKKeIowcP1ehhkTxlidrE1GweNg8RFksoD5kwI+c0 + PUhUl4c7ws+7a23MUOv7z2ef7z6f13ff7fOhEJucwOoc+k42w3FuQVGru2V2amV+YKAtJL5ns9p1d0a8 + QqXAEnHWjW7xYvbQNFIFkzheO4f9pa0r5iXp7cyMMOstEbNrRbTQBlFv7SiJwW8k3k1L43cS9WMkkl4u + wfaxAHLcComcTbr7BsSY70IJ6GpprhCSEEgbv86TmPlJYlIah6V5mRQ93fYROrc7oBt/Z0bVOUpnHWJf + H3PoXM8bNH8mMTpLQiRtlixJgYU/ecW4BIkjfeC2PYNlWQ7YpfySdQCrJqzgQucw6j6R6PtB4oOYxIT0 + 9d+xQ7SIlKlKXBxpAE+QA5+BZNjWRs3TvE0UVxGtfLfOE41dKBhdxpMJEu0iEnUiIe6LqnB9/C7ihHkI + 63oFl6o6eLamgVXIB9WTvXcV2J7Afu1QlI8r3QtIHVlGikCIiP4ExLyNx/nhS4gcjENobxqYmR0wzEuG + 6lk/KDiaGa99gxP9UDe5H/6VX8BrnYFvSwdcazg40nQM3Oe+cH3qDfcmfzg38kG/Gg31dPtFwpiutAbo + Z7rKBtRgX9oQXB+9h1v5GCweRMKswA7sYgeYFtvBoNAKzCJrqCU6Q+mMXdXGeTDKfSHjXw31yz3QSx2C + UZYAzJRy7E6yAOOWCTRuGoKWoQ95vwOL8hyG5UZAjb+DYGQIiYMFIPyqIBPaCNmTuaCGGkA1WhfUWCa2 + hTNXKFZOvK1HWjFYnVCNLSO0k0nCMAWEjQsoXrugHGgAFR+2hGLqlE1ouVH/vhN0D3UVVsg9E27ShElQ + sNgsIlxsfCp6UoHl20nR804n6B7afwdodjKE9mFNBSNfayo72EvZPIgryzzqRjA4LGKPpwah6Sjzz638 + n4JfHjGLP3wxItMAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAA1lJREFUOE91U21M + k2cULdo5E5Rs4sSIn9nMkv0YaWKUhEZi5Ac2Gn8gGn+MZpBQSJlTERGrIsqCAdwyKlgxxLUMAik2La3S + lq/SVtpiV6At9AMofWmR0gIbSRkSpGdv34QY0d3k/rj3yTm557n3xNA2hFAo3M9kMnPi4uLS6HT6IfJ5 + UyQS8c/MzOhcLtcfGRkZwxsx63WMWq2+EwzNvvWFCFinBmEc10Hn6kG/uw82YgiE3xux2WzPRCJR7Eck + MplMSLzxwjCmhcalRp+7E/3jGmjHuiAfFqN5oAGiV0/w2mmAw+EwVFVVvSeRSCR5nqkJqOxyyK1iSAab + YJ8awnqobFIUy7JR0HYB+S2ZUJgksFgsT6gpMjMztzidzoByWIpmSz2Erx/hqaEKr5zdILVTWd15FUf5 + dByp2QzG75txrHon7Hb7u8rKyq9pJSUlJ71+DwTGB1CMtGBo2ogOVzNcM8NYWVlBOBxGv1ONZtNDNJl+ + Bed5CpgNn6FF/xRyubyYVltb+7NlwoQKYwF0biVWV1exvLyMxcVFzM3NYXZ2lspgMEjVAv1VnJVsBV9z + EzqdTkyrqam5YZ7oR1bvd2gzNMDj8cDtdoMgCAoYCoXg8/moHjk26nuvIKdnGxqMpdBqtVLaT2RMz/nA + Usbi/Msd+LF9Ny692APVgAjz8/MUyXMDD7+o96NMtQ+3tLtw2fAF+lyyqAQRLTk5+czCwgLu6i/iB/N2 + cAe/xC3rV+j8S4jJyUkqFdYbqHfuRa0jEZUju0kSBsL/hlFeXn6fFh8fv10sFv8zPU8gh5TBGUzAdete + dJj+hN/vRyAQwMuRMjxyfovfHIdx2/gNBsgb8Xq9kbS0NCa1ShaLdS+qzxscw+XuU2DrD4ErY6JQnI7i + NhZudqeAZ05CoSoZ7fom6p8EAkE3CY1Zv8itXC63R6PRYGlpCV2j7XjQdwnXVGdRqDyN0g42Hr+ogKpL + CZPJBIVCQTAYjAMfnHNCQkIsaRQRybxmNpup8aOri25gdHQUSqUSUqk0UldXN5CUlHTwk4bKzc3dmZ2d + Xc3j8QJ8Pn+tsbEx0traGiEdulZUVPR3Xl6eOD8///v/cyPVT01NpWdlZSWSZMc5HM65aJKgE2w2+2B6 + evrnG8H/AbmrVcjwu0QfAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAbFJREFUOE9jYCAD + rO/vF9gxc6YGGVoZGO5t3qz/7eixZ58OHfr3ZsmSQpIMuXf0qPuDLVs+P+vr//9swoT/j5ublxJtwI+X + a4IfX9v8fV9F4/8TXd3/L2RkHFsZEiJKlAH/3q3M+XU16s+nQ37/dy2f/D/X03Otj7ExF0HN//8zMP59 + s6j958Wgf1922fy/1Kv6b0+jZhNQIyNBzTNnzmT9+2rmwj8XvP5/2GD2/2yP3M/dDRrxBDWCFOzfP4Xn + 7/PeHb9OOv9/vdTg/6kOxXdbKtUdidJ86fhs8T/Pms/8OGj7/9kczf/HmhXvLi9T1SRK8+OrS1V/P6q4 + 83W72f8Hk1X+H2lUOj4tQ0mMKM2v7m8z/HUv49Wntfr/b/Uq/j/QpLqmN0SGkyjN9fX1LN+eHrz0bpnh + /wut8v/2Nal04whpUOjDMMLsR7cv5F7e2fd/Rav3y2xvsXxRUQYeoKwAEAsDMSixiEMxyDsgMW4gZoKZ + wGllqrNcX1O2iZmZ2QsoaA/E5kCsD8RqQCwPxBJQjXxAGpSAWJC9BnISOxCDbAVJsgExM9QGwgmGqEDC + owgARBuwPYj2XjEAAAAASUVORK5CYII= + + + + + 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 + +Z/R984rn0GmMacbOKoAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAAewQAA + HsEBw2lUUwAAAUxJREFUOE+VU12rglAQ7EL//1f0oI+9mNSLQg9BQRJRGUZBQdiHGib2ZXObvRy4pRYN + HNTjzOye3bM/eKBSgCzLKupXtVotovzt0eA/HkJcr1dZl8sFaZoijmPcbrdXqnw/GVB8Pp+FTAO+K4PV + aoX7/Z4zeTI4Ho8iVFkocRiGWCwW2G637w1IZNqMRKMkScA93/cxHA7hed57A0agiCan0wmHw0HEruvC + sqzPBrvdDlxRFMmT56a40+mg0WjI/iueasCos9kM6/Uay+VSIvb7fTSbTQwGg89dIIPi6XQqy3EcSd0w + DDlaEXL3gC0cj8dS8V6vh1arhdFoVCjO3QPFmkwmmM/nME0TmqZJPcqQy4BEVUBG13VdWvmVAdu32WzQ + brdRr9cRBMF3BozIYtq2LRns9/vvDDgDvHm1Wg3dbrd0kEqLqMJxCj/hF5B2pm1BgCdyAAAAAElFTkSu + QmCC + + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADO + DgAAAk1TRnQBSQFMAgEBBAEAAQwBAAEEAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AOQABAQMFAQcDDwQU + ARsDDQERAwMBBBQAAwUBBwMUARwDGgElAxoBJAMYASIDFwEgAxYBHgMUARwDEwEaAxIBGAMNAREDAwEE + EAAc/wH0AvMh/ycAAQEDBAEGJAADAwEEAw0BEQMgAS8DNwFbA0ABcAMyAVEDHQEpAw0BEQMDAQQMAAMU + ARwDPgFrA0oBigNIAYgDRwGDA0UBfQNDAXgDQQFzAz8BbQM7AWUDLwFKAw8BFBAAFP8B+gL5Af8B2gLU + Af8BrgKjAf8B0QLKAf8D/Bn/JAADJQE3A10BvgMIAQsbAAEBAwcBCgMYASIDMwFSAVECTwGlA1gB3QFS + AlABowNQAZ4DRQF9AzIBUAMcAScDCwEPAwIBAwQAAWUCXAHqAXsCZgH1AWMCWAHpAV0CVwHfAV4CWgHV + AVsCWAHLAVsCWQHDAVgCVgG8A1UBtQNTAaoDRgGAAxgBIhAAFP8B8gLvAf8B6wLnAf8BzALAAf8BuAKo + Af8B7wLtGf8UAAMLAQ8DLwFKA0IBdQNCAXQDWAG2A1UBqgMRARcDBAEFEAADAwEEAxEBFwMoATwDSAGG + AV4CWwHlA2IB/wNJAf8DQQH/A1cB3wFSAlABpANPAZwDRAF7ASwCKwFDAwsBDwQAAY4CagH5Af8C9AL/ + AuQB/wH9AuMB/wH7AuAB/wH8AuQB/wH9AuUB/wH5AdkB2AH/AcsBxQHZAf8BgQFrAW0B9wNLAY4DGwEm + AwABAQwAFP8B9QHxAfAB/wHvAeoB6QH/AdEBxAHBAf8BwAGxAa4B/wHwAe4B7Rn/CAADJAE1AygBPQNA + AXADhQHmA+EB/wPqAf8D6gH/A+EB/wNsAdUDOAFeAxgBIQMJAQwMAAMOARMDOgFhAVsCWQHDAXMCbwH+ + A2UB/wNgAf8DWAH/A0UB/wNEAf8DPwH/A1oB2wNRAaEDQwF4AxYBHgQAAY4CagH5Af8C7gH/AfsC3AH/ + AfwB2QHWAf8B+AHTAdAB/wH5AdUBzwH/AfsB1QHNAf8B9gHLAcUB/wHUAcABzAH/AYIBbAFtAfcDSwGO + AxwBJwMAAQEMABT/AegB6gH0Af8B2wHiAe8B/wGxAbQB0QH/AaQBogG+Af8B8AHvAfEZ/wgAAzEBTwOY + AfQD1gH+A/QB/wPlAf8D/QX/A/wB/wPxAf8DjQHrAzEBTwMSARgMAAFJAkgBhwFtAlIB9wOCAf8DbgH/ + A2IB/wNZAf8DaQH/A0QB/wNFAf8DQwH/Az8B/wFaAlgB5AFJAkgBiAMaASQEAAGQAmoB+Qb/AfsB/wFn + AZcB/QH/Ad4B5QH8Af8BVwGIAf0B/wE5AWYB/QH/AVYBgAH6Av8B/AH0Af8BiAJtAfcDTQGWAygBPQMO + ARMDBAEFCAAU/wGpAc0C/wGVAdkC/wEdAaIC/wEAAYYC/wHeAeYa/wgAAyUBNwPMAfwD9QH/A/0B/wP9 + Af8D/QH/A/0B/wP9Af8D+wH/A+UB/wOOAfEDJAE2DAABYgJXAe8DiwH/A4EB/wNsAf8BigKLAf8BpAKl + Af8BngKfAf8DiQH/A14B/wNGAf8DQgH/AVkCVwHrAUUCRAF8AxcBIAQAAYoCbQH3Bv8B+wH/AUYBhgH+ + Af8BxQHYAfwB/wHhAeIB9wH/AREBUAL/AcMBygH4Av8B/gH6Af8BowKUAfsDUwGsA0cBgwE1AjQBVQMb + ASYDBQEHBAAQ/wL6Av8BhAHPAv8BqgHpAv8BSgHAAv8BAAGlAv8BqAHKGv8IAANdAbQD5QH/A/QB/wP0 + Af8D8gH/A+gB/wP0Af8D9AH/A+QB/wPgAf8D0AH/A20BxwwAAWUCUgH0A4cB/wOYAf8BsgK1Af8BgQJx + Af8BVQJKAf8BRwJDAf8BXAJfAf8BhwKIAf8DgQH/A2EB/wFZAk8B8gMuAUgDDQERBAABgQJiAfYE/wFk + AZwC/wEbAYcC/wHJAd0B/QH/AWYBlwH9Af8BvQHOAfkB/wGBAYwBuwH/AYMBhQGHAf8BagFtAW4B/wNb + AdkDUgGoA1ABmgM+AWsDGgElAwMBBBD/AcIB4QL/AT4B1QL/AUkB1AL/ASwBxwL/AQABrQL/ASIBnQL/ + Ae0B8hb/BAADBAEGA7kB+AP0Af8D7QH/A7gB/wOUAf8DqgH/A9IB/wPcAf8D5gH/A+EB/wPUAf8D0gH+ + AxQBHAgAAXcCaQH4A84B/wHDAsQB/wGPAoEB/wHBApIB/wHXAp4B/wHLAo4B/wFbAkIB/wGEAocB/wF/ + An4B/gFeAlwBzgNBAXIDDAEQAwIBAwQAAYECYgH2CP8BcQGmAv8B3QHoAfkB/wHGAdoB+AH/AY8BigGZ + Af8BtQGmAZkB/wH2AdUBrwL/Ad8BtAH/AfMB0gGsAf8BpwGZAYoB/wNZAckDTwGbATUCNAFVAw0BEgz/ + AfIB9wL/AW0B2AL/AXYB5QL/AWwB4AL/AU8B1wL/ASkBxQL/AQABpAL/AaABxBb/BAADFAEbA9UB/wPt + Af8D9AH/A+gB/wO+Af8D4AH/A98B/wPXAf8D3gH/A+AB/wOaAf8DuwH/AyABLwgAAzACTAJLAY8BXgJc + Ac4BdQJrAfwB6gLZAf8B7wLRAf8BzwKWAf8BYQJUAe4DUAGdAyoBQQMHAQoDAQECDAABhQJnAfYB9AL3 + Af8BigKLAf8BZAFiAV8B/wGuAagBpwH/Aa8CogH/AcIBsAGjAv8B5gG3Av8B5QG4Av8B5gG5Av8B5QG+ + Av8B6QHAAf8BqQGaAYoB/wNSAakDRAF5AxYBHgz/AcMB6AL/AY4B7AL/AagB7wL/AZwB6wL/AXcB4gL/ + AUQB0gL/AQABugL/AQABoAL/AeMB7BL/BAADCAELA8YB/APiAf8D6gH/A9IB/wPrAf8D6wH/A+sB/wPr + Af8D6QH/A7wB/wOOAf8DhwH+AxIBGBMAAQEDDQESA0ABcAFYAlYBuQFSAlEBoQEsAisBQwMNARIDAQEC + FAABWQJXAcIBYQJcAdwBXQJVAe0BXgJaAdUBYQJcAdwBfAFzAXQB+gH9AeIBvAL/AekBwQL/AfABxgH/ + AbABoQGEAv8B5gG6Av8B5wG/Af8B+gHXAbAB/wNbAdkDSAGFAxkBIwz/AaYB6gL/AbkB9QL/Ad8B+gL/ + AdMB+AL/AbUB8QL/AZEB5wL/AVUB0gL/AQABrgL/AbQB0xL/CAADZAHAA9YB/wPjAf8D4QH/A+QB/wPk + Af8D5AH/A+MB/wPIAf8DlQH/A3YB/wNlAdAbAAEBAyUBNwE1AjQBVQE/Aj4BbAMkATUDEQEXAwMBBBQA + AwYBCAFWAlUBtAFZAlcBvwNSAakBXAJYAdEBhgF5AXoB/AH/Ae8BywL/AfgB1wH/Ac8BxAGlAf8BSgFN + AVUB/wGYAYsBagL/AekBvAL/AegBuwH/AWcCWQHyA0QBeQMWAR4I/wL+Av8BpwHuAv8B2wH7Av8B+AP/ + AeUB/AL/AccB9gL/Aa0B7wL/AZIB6AL/AT0BywL/AaoB0xL/CAADJgE4A8AB+APQAf8D2AH/A90B/wPU + Af8D1AH/A8kB/wOFAf8DuwH/A+MB/wOiAe8DBgEIEwABAQMQARUDHgErA0MBeANAAXADOgFhAyQBNQMQ + ARYDAwEEGwABAQMAAQEDAAEBAWACWwHWAf8B8gHTAf8B7gHpAdMB/wE8ATsBNgH/AegB3QG8Af8CQwE9 + Af8B0wG+AZ0C/wHfAbcB/wFeAloB2AE1AjQBVQMNARIM/wG+AfQC/wHeAfsC/wHtAf0C/wHkAfwC/wHR + AfcC/wG8AfMC/wGqAe8C/wF2AdwC/wHRAecS/wwAAygBPAN1AdQDtQH/A70B/wPHAf8DzgH/A48B/wOv + Af8D9AH/A/sB/wPvAf0DCwEPEAADBgEIAxABFQNQAZ4BXAJaAc0BWwJZAcQBQgJBAXMDMwFTAyABLgMI + AQskAANEAXsB7QHWAcYB/wGhAZ0BjQH/AukB0wP/Ad0C/wHxAcoC/wHxAcIB/wG/AawBnAH/AU4CTQGV + AxsBJgMDAQQM/wHuAf0C/wHNAfsC/wHnAf0C/wHkAfwC/wHaAfoC/wHOAfcC/wG6AfMC/wGjAeAC/wH9 + Af4S/wwAAwkBDANxAd0DpQH/A6AB/wObAf8DywH/A6kB/gOjAe8D/gH/A+oB/wNSAZsUAAMIAQsDUAGd + A0QBegFFAkQBfAFJAkgBhwFRAk8BnAFKAkkBiQMUARsDAwEEJAADBAEGAVoCWAHAAe8B2gHJAv8B+AHY + Av8B8wHPAv8B6wHFAf8ByAG2AaYB/wFbAlkBxAMdASoDBgEIBAAQ/wHrAf4C/wHPAfwC/wHbAfwC/wHa + AfsC/wHOAfgC/wHMAfIC/wH3AfsW/wwAAw0BEgOxAfED8wH/A/EB/wPfAf8DQgFzAxQBHAMFAQcDMgFR + AykBPxwAAxgBIgNUAa4BZgFPAUkB7wFhAVsBWgHhA0oBigMSARgDBAEFLAADBAEGA0QBewFgAlsB1gF5 + AmYB9AFdAlkB1wFHAkYBgAMSARgDBAEFCAAU/wH6A/8B3wH9Av8B3gH8Av8B6gH7Hv8QAAMZASMDTAGL + A14BsQNMAY0DBQEHHAABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/4EAAfgBHwEA + AQ8CAAH/AZ8B8AEHAQABDwIAAf8BjwHAAQEBAAEPAgAB+AEHAYABAQEAAQcCAAHAAQMBgAEBAQABBwIA + AcABAwGAAQEBAAEDAgABwAEDAYABAQEAAQECAAHAAQMBgAEBBAABgAEBAYABAQQAAYABAQGAAQcEAAGA + AQEB4AEfBAABwAEDAfABHwQAAcABAQHgAQ8BwAMAAeABAQHgAQ8B+AMAAeABAwHgAQ8B+AEBAgAB4AEH + AfABHwH8AQMCAAHwAX8L + + + + + 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 + HdfAfwC8OWB2rvuFqgAAAABJRU5ErkJggg== + + + + + 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 + JaF3/okKQA+GkF8hGDwAAyuNeju3sTkZMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwY + MGDAwIXg/wNGXQMUZRIeQQAAAABJRU5ErkJggigAAACAAAAAAAEAAAEAIAAAAAAAAAgBAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AwMDAQoKCgEQEBACFBQUAhUVFQEVFRUCFhYWAhcXFwEWFhYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAYDAwMHCQkJCgYGBgsAAAANAAAAEAAAABAAAAAP + FBQUCxISEggeHh4EEhISAgcHBwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAUAAAAK + AAAAEAAAABcAAAAdAAAAIwAAACsAAAAxAAAAMQAAAC0AAAAlAAAAGgAAAA8FBQUJBwcHBgEBAQMAAAAB + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAIAAAADgAAABcAAAAiAAAALQAAADgAAABIEhISZGJiYruBgYHc + YGBguBYWFl0AAAA1AAAAJQAAABkAAAAPAAAACQAAAAQAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAABgAAAAwAAAAZ + AAAAJQAAADYAAABHAAAAWwEBAXN6enrhvLy8/8jIyP+urq7/eXl57AsLC1YAAAA7AAAAKgAAABwAAAAR + AAAACAAAAAQAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAHAAAAEQAAACAAAAAyAAAARAAAAF0AAAB6NDQ0sru7u//j4+P/ + 4+Pj/8nJyf+YmJj/Ly8vkwAAAEoAAAA5AAAAKAAAABcAAAAMAAAABQAAAAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAgAAAAS + AAAAIAAAADQAAABJAAAAaQQEBI+Ojo7w29vb/+zs7P/i4uL/ysrK/5ycnP8sLCyPAAAATgAAAD0AAAAr + AAAAGgAAAA4AAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAAAA4AAAAZAAAAKgAAAEgAAAByQUFBvcPDw//r6+v/ + 6urq/9zc3P/Dw8P/lpaW/x0dHWoAAABEAAAANQAAACYAAAAXAAAADAAAAAQAAAABAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAD + AQEBCAAAABIAAAAjAAAASgsLC32amprz4ODg/+/v7//l5eX/1tbW/7u7u/+KiorzAgICPwAAADIAAAAl + AAAAGgAAABEAAAAIAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgENDQ0EAAAACgAAACQAAABTUlJSt8nJyf/u7u7/ + 7e3t/9/f3//Pz8//srKy/35+fs0AAAAkAAAAHgAAABUAAAANAAAABwAAAAQAAAACAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAC + BwcHAhYWFgQICAgPAAAANRISEm6lpaX35OTk//Ly8v/o6Oj/2dnZ/8nJyf+rq6v/dnZ2nQAAAA8AAAAM + FBQUCAoKCgUAAAADAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAACAAAAAwAAAAQAAAAGAAAACAAAAAkAAAAK + AAAACgAAAAkAAAAJAAAABwAAAAcAAAAGAAAABgEBAQcGBgYIAAAADgAAACUAAABRYWFhv87Ozv/y8vL/ + 8PDw/+Li4v/U1NT/w8PD/6ioqP9FRUVtWlpaBEBAQAMlJSUDCwsLAQAAAAIAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAAwEBAQQAAAAG + AAAACAAAAAsAAAAPAAAAEwAAABYAAAAZAAAAGgAAABoAAAAaAAAAGgAAABgAAAAWAAAAFAAAABMAAAAT + AAAAFQAAABgAAAAjAAAARBsbG3murq776Ojo//b29v/r6+v/3Nzc/8/Pz/++vr7/qqqq/zs7O0IrKysH + KysrBSAgIAMHBwcCAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AQEBAQICAgICAgIEAQEBBwEBAQsAAAAPAAAAEwAAABYAAAAbAAAAHwAAACUAAAApAAAALAAAAC4AAAAw + AAAAMAAAADAAAAAuAAAALAAAACkAAAAnAAAAJgAAACYAAAAoAAAALQAAAEIAAABgb29vzdPT0//19fX/ + 8/Pz/+Xl5f/W1tb/y8vL/7y8vP+qqqr+ICAgIgAAABMAAAAPAAAADAAAAAoAAAAHAAAABQAAAAMAAAAC + AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBBwcHAwcHBwUCAgIKAAAADgAAABMAAAAYAAAAHwAAACYAAAAq + AAAALgAAADIAAAA4AAAAPQAAAEAAAABDAAAARQAAAEYAAABGAAAARgAAAEQAAABBAAAAPgAAAD0AAAA8 + AAAAPAAAAD8AAABHAAAAXiQkJIuysrL+6urq//j4+P/u7u7/39/f/9HR0f/Hx8f/wsLC/52dneMAAAAk + AAAAIAAAABwAAAAZAAAAFgAAABMAAAAPAAAACwAAAAgAAAAGAAAABAAAAAIAAAABAAAAAQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAEICAgCCQkJBQcHBwkAAAAQ + AAAAFwAAAB0AAAAlAAAALAAAADMAAAA5AAAAPwAAAEIAAABHAAAATAAAAFAAAABVAAAAWAAAAFkAAABb + AAAAXAAAAF0AAABcAAAAWQAAAFcAAABVAAAAUQAAAFIAAABSAAAAVQAAAF8AAABub29v28vLy//x8fH/ + 8/Pz/+jo6P/Z2dn/zc3N/8XFxf/MzMz/g4ODwAAAADEAAAAuAAAAKgAAACYAAAAjAAAAHwAAABsAAAAX + AAAAEgAAAA8AAAALAAAACAAAAAUAAAAEAAAAAgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAcHBwENDQ0DBwcHBwAAAA4AAAAVAAAAHwAAACgAAAAxAAAAOAAAAEEAAABIAAAATgEBAVQmJiZw + PT09l0VFRa9bW1vEZGRk2GxsbOtubm70bGxs+mxsbPpra2v5bGxs92lpaepqamroZGRk1VVVVcE8PDyr + NTU1lSAgIHkAAABqAAAAcCIiIpuQkJD/ysrK/+bm5v/o6Oj/39/f/9PT0//Jycn/ysrK/87Ozv9XV1ej + AAAAQAAAADwAAAA4AAAANAAAADAAAAAsAAAAJwAAACMAAAAdAAAAGQAAABUAAAARAAAADQAAAAoAAAAH + AAAABQAAAAMAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQEQEBAECQkJCAAAABAAAAAaAAAAJgAAADEAAAA8 + AAAARQAAAE0JCQlYPT09iFdXV7V+fn7gg4OD+35+fv96enr/eXl5/4GBgf+Li4v/lZWV/5ubm/+kpKT/ + paWl/6Wlpf+lpaX/m5ub/52dnf+RkZH/hYWF/319ff+Dg4P/iIiI/4eHh/FwcHDOampq6ZGRkf+3t7f/ + y8vL/9HR0f/Ozs7/yMjI/8TExP/X19f/w8PD/zk5OYsAAABNAAAASQAAAEUAAABBAAAAPAAAADgAAAAz + AAAALgAAACgAAAAjAAAAHgAAABkAAAAUAAAAEQAAAA4AAAALAAAACAAAAAYAAAADAAAAAgAAAAEAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQERERED + CgoKCAAAABEAAAAdAAAAKwAAADgAAABEAAAATxMTE2FKSkqdfHx8zJSUlPqOjo7/jo6O/5ubm/+np6f/ + uLi4/87Ozv/i4uL/6Ojo/+zs7P/t7e3/7e3t/+zs7P/s7Oz/6+vr/+vr6//s7Oz/7e3t/+3t7f/t7e3/ + 5+fn/9nZ2f/Hx8f/tLS0/6Ghof+ZmZn/np6e/6Ojo/+rq6v/sbGx/7S0tP+0tLT/uLi4/9bW1v+qqqr/ + IiIidgAAAFkAAABVAAAAUQAAAE0AAABIAAAAQwAAAD4AAAA5AAAAMwAAAC4AAAAoAAAAIgAAABwAAAAX + AAAAFAAAABIAAAAPAAAACwAAAAkAAAAGAAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8BERERBgAAAA8AAAAdAAAALQAAADwAAABLAAAAVzw8PIV1dXXB + oaGh+Zubm/+goKD/r6+v/8LCwv/V1dX/4ODg/+fn5//s7Oz/6urq/+bm5v/i4uL/29vb/9TU1P/Pz8// + y8vL/8bGxv/ExMT/xcXF/8rKyv/MzMz/0NDQ/9bW1v/e3t7/4+Pj/+jo6P/r6+v/7Ozs/+Hh4f/IyMj/ + tLS0/6mpqf+rq6v/paWl/5qamv+rq6v/vr6+/4mJifoEBARlAAAAYAAAAF0AAABaAAAAVwAAAFMAAABP + AAAASQAAAEUAAAA+AAAAOAAAADIAAAArAAAAIwAAABwAAAAYAAAAFgAAABQAAAARAAAADwAAAAwAAAAJ + AAAABQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAEAAAACAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQMDAwEKCgoBFBQUAwYGBgwAAAAa + AAAAKwAAAD0AAABNAAAAXUlJSZibm5vgqKio/6enp/+2trb/y8vL/9bW1v/c3Nz/5eXl/+rq6v/m5ub/ + 3d3d/9DQ0P/AwMD/rq6u/6Ojo/+qqqr/tbW1/7u7u//Dw8P/yMjI/8zMzP/Ly8v/wcHB/8PDw/+5ubn/ + sLCw/6enp/+jo6P/s7Oz/8fHx//V1dX/4uLi/+np6f/s7Oz/4ODg/8LCwv+zs7P/srKy/62trf+YmJj/ + Xl5e3wAAAGQAAABjAAAAYQAAAF4AAABcAAAAWQAAAFYAAABSAAAATQAAAEgAAABCAAAAOwAAADMAAAAq + AAAAIgAAABsAAAAaAAAAGAAAABYAAAATAAAAEAAAAA0AAAAKAAAABgAAAAMAAAABAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAACAgIBBgYGAgkJCQMCAgIFAgICBgICAgcCAgIIAgICCQEBAQgAAAAIAAAABQAAAAQAAAAE + AAAABAAAAAMBAQEGBQUFBwoKCggAAAATAAAAJAAAADoAAABOAAAAYEZGRpiioqLlr6+v/7Ozs//Dw8P/ + 1NTU/9fX1//f39//6Ojo/+fn5//b29v/yMjI/66urv+np6f/urq6/9DQ0P/q6ur//v7+//////////// + //////////////////////////////////////////////////////z8/P/i4uL/xsbG/7Gxsf+mpqb/ + vLy8/9TU1P/k5OT/6+vr/+bm5v/Nzc3/ubm5/7S0tP96enrVAwMDZQAAAGMAAABhAAAAXgAAAF0AAABb + AAAAWQAAAFYAAABSAAAATgAAAEkAAABDAAAAOwAAADEAAAAmAAAAHgAAABwAAAAbAAAAGQAAABcAAAAU + AAAAEAAAAA4AAAAMAAAACAAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEAQ0NDQQJCQkIAAAADgAAABMAAAAY + AAAAHgAAACQAAAAoAAAAJwAAACAAAAAXAAAAEgAAABAAAAAOAAAADwAAABIAAAAWAAAAIAAAADEAAABJ + AAAAXzU1NYyenp7ftbW1/7e3t//IyMj/1tbW/9fX1//f39//6Ojo/+Pj4//Q0ND/s7Oz/6ioqP/FxcX/ + 6Ojo//////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////r6+v/U1NT/srKy/66urv/Ozs7/4+Pj/+vr6//l5eX/ + yMjI/7u7u/+pqanhPz8/gwAAAGAAAABeAAAAXQAAAFsAAABZAAAAVwAAAFQAAABRAAAATQAAAEcAAAA/ + AAAANQAAACkAAAAgAAAAHAAAABwAAAAcAAAAGgAAABYAAAATAAAAEQAAABAAAAAMAAAABgAAAAIAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAELCwsFBAQECgAAABUAAAAgAAAAKgAAADYAAABCAAAAUQAAAFoAAABUAAAASAAAADsAAAAx + AAAAKgAAACUAAAAiAAAAJgAAAC8AAAA/AAAAVw4ODnN3d3fCubm5/rq6uv/IyMj/1tbW/9fX1//c3Nz/ + 6Ojo/+Li4v/Kysr/qqqq/7i4uP/i4uL////////////////////////////+/v7/+fn5//Pz8//u7u7/ + 6enp/+jo6P/l5eX/5eXl/+Pj4//l5eX/5ubm/+np6f/t7e3/8vLy//f39//9/f3///////////////// + ////////////////6+vr/7m5uf+srKz/z8/P/+Xl5f/s7Oz/29vb/729vf+9vb3+lJSUwhoaGmUAAABc + AAAAWgAAAFgAAABXAAAAVQAAAFIAAABOAAAASAAAAD8AAAA1AAAAKQAAAB4AAAAaAAAAGwAAABwAAAAc + AAAAGQAAABUAAAATAAAAEwAAABAAAAAKAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAgMDAwkAAAAUAAAAIwAAADQAAABD + LS0tcDU1NZAMDAyEAAAAiAAAAIUAAAB3AAAAZQAAAFcAAABMAAAARQAAAEEAAABFAAAATwAAAGQ4ODiY + rKys7bu7u//ExMT/1dXV/9jY2P/Z2dn/4+Pj/+Tk5P/Nzc3/q6ur/7+/v//w8PD///////////////// + //////r6+v/x8fH/5+fn/97e3v/d3d3/3d3d/97e3v/j4+P/5eXl/+fn5//o6Oj/6enp/+jo6P/n5+f/ + 5eXl/+Hh4f/f39//39/f/+Dg4P/m5ub/7u7u//n5+f///////////////////////////+7u7v+3t7f/ + tra2/9ra2v/q6ur/5ubm/8PDw/+2trb/yMjI8F5eXo0AAABaAAAAWAAAAFYAAABUAAAAUwAAAE8AAABJ + AAAAPgAAADMAAAAlAAAAGgAAABgAAAAZAAAAHQAAAB4AAAAcAAAAFwAAABUAAAAVAAAAFAAAAA0AAAAF + AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAACAgIEAAAADAAAABoAAAAsDAwMQ3l5ecKsrKz/rKys/46OjvIoKCi6AAAApQAAAJgAAACJ + AAAAeAAAAGwAAABmAAAAYgAAAGYAAABzb29vwL29vf6/v7//0NDQ/9nZ2f/Z2dn/3t7e/+fn5//Y2Nj/ + srKy/7y8vP/x8fH//////////////////Pz8//Dw8P/j4+P/3d3d/93d3f/i4uL/7Ozs//T09P/6+vr/ + /v7+//////////////////////////////////////////////////z8/P/39/f/7+/v/+fn5//g4OD/ + 39/f/+Tk5P/w8PD//f39///////////////////////c3Nz/rKys/8zMzP/m5ub/6+vr/8zMzP+ysrL/ + xMTE/6WlpcMUFBRdAAAAVgAAAFQAAABTAAAAUQAAAEoAAAA+AAAAMQAAACIAAAAWAAAAFAAAABcAAAAa + AAAAHgAAAB4AAAAaAAAAFwAAABgAAAAXAAAAEAAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgIEBAQKAAAAFgAAAChWVlaN + v7+//9vb2//Z2dn/yMjI/66urv91dXXlJSUlsgAAAJUAAACIAAAAggAAAIAAAACBExMTjpaWluG9vb3/ + xsbG/9jY2P/a2tr/2tra/+Li4v/i4uL/w8PD/6ysrP/j4+P/////////////////+Pj4/+jo6P/d3d3/ + 3d3d/+Xl5f/x8fH/+Pj4/9zc3P/z8/P///////////////////////////////////////////////// + //////////////////////////////////////39/f/z8/P/5+fn/9/f3//g4OD/7u7u//z8/P////// + ///////////5+fn/ubm5/76+vv/i4uL/7Ozs/8/Pz/+tra3/uLi4/9fX1+Y9PT13AAAAVAAAAFMAAABR + AAAASwAAAD8AAAAuAAAAHgAAABQAAAAUAAAAFgAAABoAAAAdAAAAHgAAABwAAAAaAAAAHAAAABsAAAAS + AAAABwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAgICAhEREQYAAAAOAAAAGomJia7U1NT/8fHx/+/v7//k5OT/1NTU/8DAwP+np6f+ + cHBw2yEhIZsAAACKAAAAliAgIKmmpqbvvb29/83Nzf/a2tr/29vb/9zc3P/l5eX/2NjY/7CwsP/IyMj/ + /Pz8////////////+Pj4/+Tk5P/c3Nz/3t7e/+zs7P/6+vr///////v7+/9wcHD/YGBg/3p6ev/r6+v/ + //////////////////////////////////////////////////////////////////////////////// + ////////////////+vr6/+rq6v/f39//4eHh//Ly8v//////////////////////zc3N/7W1tf/e3t7/ + 6+vr/9HR0f+np6f/s7Oz/+Li4vyBgYGWAAAAUwAAAFEAAABMAAAAQQAAAC4AAAAdAAAAFQAAABYAAAAZ + AAAAGwAAAB0AAAAdAAAAHAAAAB8AAAAhAAAAHwAAABQAAAAHAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMBHh4eAi8vLwYXFxcL + W1tbe8TExP/v7+//9/f3//Hx8f/o6Oj/3Nzc/8zMzP+vr6//g4OD/kNDQ9swMDDDra2t9729vf/R0dH/ + 29vb/9vb2//e3t7/5OTk/83Nzf+urq7/6Ojo/////////////Pz8/+rq6v/b29v/3t7e/+/v7//9/f3/ + ////////////////z8/P/01NTf9zc3P/hYWF/8PDw/////////////////////////////////////// + //////////////////////////////////////////////////////////////////////r6+v/n5+f/ + 39/f/+bm5v/7+/v/////////////////3t7e/7Ozs//d3d3/6+vr/8rKyv+hoaH/rq6u/9zc3P+mpqa8 + CwsLUgAAAEwAAABBAAAALQAAAB4AAAAZAAAAGgAAAB0AAAAgAAAAHwAAAB0AAAAeAAAAIwAAACcAAAAh + AAAAEwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFxcQN/f38MlpaWxtbW1v/09PT/+Pj4//Ly8v/p6en/ + 2dnZ/7e3t/+Ghob/c3Nz/66urv+8vLz/1dXV/9zc3P/c3Nz/39/f/+Pj4//BwcH/tra2//f39/////// + //////Ly8v/e3t7/29vb/+zs7P/9/f3////////////////////////////p6en/Tk5O/2tra/98fHz/ + 39/f//////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////z8/P/4eHh/+Hh4f/19fX///////////////// + 4uLi/7S0tP/g4OD/7Ozs/8DAwP+ampr/ra2t/9nZ2f/MzMzXKCgoWgAAAD8AAAAuAAAAIwAAACAAAAAg + AAAAIwAAACUAAAAjAAAAHwAAACAAAAApAAAALAAAACMAAAAQAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACcnJwUoqKi293d3f/29vb/+fn5/+/v7//U1NT/pqam/4qKiv+urq7/urq6/9bW1v/c3Nz/ + 3d3d/+Dg4P/h4eH/urq6/8rKyv/+/v7///////z8/P/m5ub/2tra/+Li4v/4+Pj///////////////// + ///////////////////////////Pz8//np6e/9LS0v////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////6+vr/5eXl/9/f3//x8fH/////////////////4ODg/7i4uP/k5OT/6urq/6ysrP+SkpL/ + q6ur/9bW1v/d3d3kMzMzVwAAAC8AAAAoAAAAJgAAACYAAAApAAAAKwAAACcAAAAiAAAAJQAAAC8AAAAv + AAAAIAAAAAsAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrKwmra2t6+Li4v/19fX/ + 5ubm/76+vv+Xl5f/q6ur/7e3t//X19f/3d3d/93d3f/g4OD/39/f/7a2tv/T09P////////////5+fn/ + 39/f/9ra2v/u7u7//v7+//////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////+/v7/6enp/9/f3//x8fH/ + ////////////////1NTU/8LCwv/n5+f/5OTk/5iYmP+Li4v/pKSk/9TU1P/l5eXuOTk5WAAAACwAAAAr + AAAAKwAAAC8AAAAvAAAAKwAAACYAAAArAAAAMwAAAC4AAAAYAAAABgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACQkJA8r6+v+NLS0v/ExMT/oqKi/6Wlpf+xsbH/1tbW/97e3v/e3t7/ + 4ODg/9/f3/+1tbX/2dnZ////////////8fHx/9ra2v/d3d3/9vb2//////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////+/v7/6urq/9/f3//x8fH/////////////////w8PD/9DQ0P/r6+v/ + zs7O/4qKiv+CgoL/n5+f/9HR0f/o6Oj3ZGRkZgAAAC8AAAAwAAAAMgAAADMAAAAtAAAAKwAAADEAAAA1 + AAAAJwAAAA8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACJiYlX + kJCQ/pWVlf+goKD/q6ur/9HR0f/f39//39/f/+Hh4f/h4eH/t7e3/97e3v///////////+/v7//Z2dn/ + 4uLi//v7+/////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////+/v7/ + 6enp/9/f3//09PT////////////6+vr/uLi4/97e3v/s7Oz/qqqq/4KCgv9+fn7/m5ub/83Nzf/n5+f8 + iIiIegAAADUAAAA2AAAANAAAADAAAAAxAAAANgAAADEAAAAbAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABycnJ9kJCQ/6SkpP/Kysr/39/f/+Dg4P/h4eH/ + 4+Pj/7y8vP/V1dX////////////t7e3/2NjY/+Tk5P/9/f3///////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////+/v7/5ubm/+Dg4P/7+/v////////////n5+f/ + v7+//+jo6P/j4+P/h4eH/4CAgP9+fn7/mJiY/8rKyv/o6Oj+nJyckwAAADkAAAA1AAAANAAAADcAAAA2 + AAAAJgAAAA8AAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJ6enmefn5//wcHB/+Dg4P/h4eH/4eHh/+Tk5P/Dw8P/zc3N////////////7e3t/9fX1//m5ub/ + /v7+//////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////8/Pz/4eHh/+Xl5f/+/v7////////////Hx8f/19fX/+zs7P+3t7f/fHx8/4qKiv9/f3// + mJiY/8rKyv/o6Oj/o6OjnwAAADgAAAA5AAAAOgAAADEAAAAcBQUFCQUFBQEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6slmpqa+K6urv/e3t7/4uLi/+Li4v/k5OT/ + z8/P/8PDw////////////+/v7//X19f/5eXl//7+/v////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////19fX/39/f//Dw8P////// + //////b29v+7u7v/5ubm/+bm5v+CgoL/i4uL/5CQkP+CgoL/m5ub/8vLy//p6en/pqampAAAADwAAAA5 + AAAAKwAAABgAAAAKEhISAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + pqamBpWVlcqgoKD/2dnZ/+Li4v/j4+P/5OTk/9ra2v+2trb/+/v7///////y8vL/19fX/+Li4v/+/v7/ + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////q6ur/4ODg//z8/P///////////9DQ0P/X19f/7Ozs/6+vr/95eXn/ + ra2t/5GRkf+EhIT/oaGh/87Ozv/q6ur/p6enqAAAADUAAAAmAAAAGAAAAA4pKSkEAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACZmZlzlZWV/8bGxv/j4+P/5OTk/+Tk5P/i4uL/ + t7e3/+3t7f/+/v7/+fn5/9jY2P/e3t7//Pz8//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//r6+v/f39// + 6+vr//7+/v/+/v7/9PT0/7+/v//p6en/2tra/3Nzc/+lpaX/srKy/4+Pj/+JiYn/q6ur/9DQ0P/s7Oz/ + qKionQAAACYAAAAbAAAAD0VFRQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + qqqqGpCQkPWqqqr/4eHh/+Tk5P/l5eX/5ubm/8XFxf/Y2Nj//f39//v7+//d3d3/2NjY//j4+P/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39/+zs7P/d3d3/+Pj4//39/f/9/f3/yMjI/93d3f/t7e3/ + k5OT/4mJif/Pz8//rq6u/46Ojv+SkpL/tra2/9TU1P/w8PD/qamplAAAABwAAAAMY2NjAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIymlJSU/9fX1//k5OT/5ubm/+bm5v/Z2dn/ + v7+///39/f/9/f3/5ubm/9TU1P/w8PD//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + /f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/ + +vr6/97e3v/q6ur//f39//39/f/n5+f/ycnJ/+vr6/+6urr/bW1t/9XV1f/MzMz/pqam/46Ojv+hoaH/ + wcHB/9/f3//y8vL/p6endERERAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nJycNYuLi/+3t7f/4+Pj/+fn5//n5+f/5OTk/7q6uv/v7+//+/v7//Hx8f/T09P/5OTk//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/ + +/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/6enp/93d3f/5+fn/+/v7//v7+//AwMD/ + 5ubm/+Dg4P9tbW3/ubm5/+Hh4f/Dw8P/np6e/5OTk/+1tbX/z8/P/+7u7v/y8vL8srKyKwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACGhoa1lJSU/9vb2//m5ub/6Ojo/+jo6P/R0dH/ + zc3N//r6+v/6+vr/2tra/9fX1//4+Pj/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/ + +vr6//r6+v/19fX/3Nzc/+7u7v/6+vr/+vr6/9HR0f/d3d3/7e3t/4ODg/+Wlpb/8PDw/9vb2/+5ubn/ + l5eX/6SkpP/Jycn/4ODg//Hx8f/09PSzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + mZmZNIeHh/+4uLj/5OTk/+jo6P/o6Oj/4+Pj/7m5uf/19fX/+Pj4/+fn5//R0dH/7e3t//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/l5eX/6urq//j4+P/g4OD/4+Pj//j4+P/4+Pj/ + 4uLi/9DQ0P/s7Oz/oaGh/3V1df/4+Pj/7Ozs/9LS0v+qqqr/mpqa/7y8vP/Y2Nj/5+fn//Hx8f/r6+te + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgoKtkJCQ/9vb2//o6Oj/6enp/+np6f/Pz8// + 1NTU//j4+P/19fX/0tLS/9zc3P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + mJiY/2JiYv97e3v/xsbG/+np6f/a2tr/9vb2//j4+P/29vb/w8PD/+rq6v++vr7/aGho/+np6f/29vb/ + 5eXl/8PDw/+goKD/q6ur/9bW1v/f39//7u7u//Ly8vPn5+caAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + lZWVHYODg/yysrL/5OTk/+rq6v/q6ur/5OTk/7q6uv/09PT/9vb2/+Li4v/Pz8//8PDw//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/+Dg4P9QUFD/eXl5/5KSkv+goKD/7+/v/9nZ2f/u7u7/ + 9vb2//b29v/Gxsb/5+fn/9PT0/9oaGj/0dHR//z8/P/y8vL/2NjY/7CwsP+hoaH/ysrK/+Pj4//k5OT/ + 8fHx//Dw8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIyEh4eH/9fX1//o6Oj/6+vr/+rq6v/U1NT/ + z8/P//T09P/y8vL/z8/P/9vb2//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 6Ojo/1VVVf91dXX/i4uL/7Gxsf/09PT/2NjY/+Xl5f/09PT/9PT0/8/Pz//i4uL/6Ojo/2hoaP+5ubn/ + /v7+//n5+f/n5+f/w8PD/6Ojo/+6urr/5ubm/+Hh4f/u7u7/8fHx/fLy8ioAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nZ2dBX9/f+Sfn5//4uLi/+rq6v/s7Oz/6Ojo/76+vv/s7Oz/7e3t/9vb2//Ly8v/7Ozs//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/xMTE/5CQkP+vr6//7e3t//Pz8//d3d3/ + 39/f//Pz8//z8/P/1tbW/9zc3P/t7e3/dXV1/6enp////////Pz8//Hx8f/U1NT/ra2t/62trf/g4OD/ + 6urq/+Xl5f/y8vL/8fHxmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJRAgICA/8PDw//n5+f/7Ozs/+3t7f/e3t7/ + x8fH/+vr6//n5+f/6urq/8vLy//x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/ + 8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy/+Hh4f/Z2dn/8vLy//Ly8v/c3Nz/1tbW/+3t7f+Dg4P/ + mJiY///////+/v7/+Pj4/+Hh4f+6urr/p6en/9LS0v/z8/P/4ODg//Dw8P/y8vL58PDwEgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAHt7e52Hh4f/2tra/+rq6v/t7e3/7Ozs/83Nzf/a2tr/3Nzc//Pz8//19fX/6enp/+Xl5f/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/7+/v/+7u7v/t7e3/6+vr/+np6f/U1NT/wsLC/+jo6P/v7+// + 7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 4+Pj/9XV1f/v7+//8PDw/+Hh4f/R0dH/7e3t/4yMjP+Ojo7////////////7+/v/6+vr/8fHx/+np6f/ + w8PD//X19f/l5eX/6urq//Ly8v/z8/N1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcnJwCfHx86qKiov/i4uL/7Ozs/+7u7v/o6Oj/ + vr6+/+vr6//Y2Nj/9/f3//X19f/8/Pz/6enp/+Xl5f/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7e3t/+vr6//r6+v/6Ojo/+Xl5f/i4uL/ + 3t7e/9nZ2f/U1NT/j4+P/0JCQv9BQUH/WFhY/9HR0f/n5+f/6+vr/+zs7P/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/l5eX/09PT/+rq6v/u7u7/5ubm/8/Pz//t7e3/ + kpKS/4iIiP////////////39/f/x8fH/0tLS/6ysrP+2trb/7+/v/+7u7v/i4uL/8/Pz//T09NYAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJKSkjV9fX3/vLy8/+Xl5f/t7e3/7u7u/9/f3//Gxsb/5OTk/+Li4v/19fX/9/f3//z8/P/8/Pz/ + 5ubm/+Xl5f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7Ozs/+rq6v/o6Oj/ + 5eXl/+Pj4//f39//2tra/9XV1f/R0dH/zMzM/8jIyP+9vb3/m5ub/3d3d/9BQUH/QUFB/0FBQf9BQUH/ + fHx8/9vb2//d3d3/4eHh/+Xl5f/p6en/7Ozs/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+Xl5f/S0tL/5+fn/+3t7f/o6Oj/zc3N/+3t7f+Tk5P/hoaG//7+/v///////v7+//b29v/a2tr/ + srKy/66urv/m5ub/9vb2/93d3f/w8PD/8/Pz/vDw8BsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh4eHen9/f//V1dX/6urq/+7u7v/u7u7/ + 1NTU/9PT0//X19f/8fHx//T09P/5+fn/+/v7//v7+//7+/v/5+fn/+Li4v/r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+rq6v/l5eX/2tra/9PT0//Pz8//ysrK/8bGxv/ExMT/s7Oz/5CQkP9tbW3/ + TU1N/zExMf8xMTH/NDQ0/0FBQf9BQUH/QUFB/0FBQf9aWlr/0tLS/97e3v/Z2dn/2dnZ/9vb2//h4eH/ + 5ubm/+np6f/q6ur/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5eXl/9HR0f/l5eX/6+vr/+jo6P/Nzc3/ + 7e3t/5KSkv+Ghob//f39//7+/v/+/v7/+vr6/+Hh4f+6urr/qamp/9zc3P/7+/v/3Nzc/+3t7f/z8/P/ + 8PDwaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAB6enq4jo6O/93d3f/s7Oz/7+/v/+zs7P/ExMT/4+Pj/9DQ0P/39/f/9PT0//r6+v/7+/v/ + +/v7//v7+//7+/v/6urq/9/f3//o6Oj/6enp/+np6f/p6en/6enp/+np6f/p6en/5ubm/9fX1//Gxsb/ + wcHB/6mpqf+Hh4f/ZWVl/0NDQ/8xMTH/MTEx/zExMf8xMTH/MTEx/0RERP9vb2//VVVV/0FBQf9BQUH/ + QUFB/5SUlP94eHj/d3d3/76+vv/f39//2dnZ/9XV1f/X19f/3Nzc/+Li4v/m5ub/6Ojo/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/j4+P/0dHR/+Pj4//p6en/5ubm/87Ozv/t7e3/jY2N/4uLi//7+/v//Pz8//39/f/7+/v/ + 5+fn/8HBwf+np6f/0dHR//z8/P/g4OD/5ubm//Pz8//19fWeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHt7e/Cjo6P/4eHh/+3t7f/w8PD/ + 6enp/8HBwf/j4+P/1tbW//X19f/19fX/+/v7//v7+//7+/v/+/v7//v7+//7+/v/7+/v/9zc3P/m5ub/ + 6Ojo/+jo6P/o6Oj/6Ojo/+fn5//g4OD/srKy/15eXv87Ozv/MTEx/zExMf8xMTH/MTEx/zExMf89PT3/ + bGxs/5ycnP/Kysr/3Nzc/7S0tP88PDz/OTk5/2pqav+urq7/6Ojo/+jo6P/Y2Nj/jo6O/2tra/+jo6P/ + 29vb/9ra2v/V1dX/1NTU/9fX1//c3Nz/4ODg/+Xl5f/m5ub/5+fn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+Li4v/Pz8//4uLi/+jo6P/h4eH/ + 0dHR/+3t7f+EhIT/kpKS//f39//6+vr//Pz8//v7+//q6ur/xsbG/6enp//Jycn/+/v7/+Pj4//f39// + 8/Pz//T09OYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACQkJAke3t7/7S0tP/k5OT/7+/v//Hx8f/k5OT/x8fH/9zc3P/d3d3/8/Pz//X19f/6+vr/ + +vr6//r6+v/6+vr/+vr6//r6+v/6+vr/9PT0/9zc3P/i4uL/5ubm/+bm5v/m5ub/5eXl/+Li4v9hYWH/ + MTEx/zExMf8xMTH/ODg4/2RkZP+RkZH/w8PD/+Tk5P/m5ub/5OTk/9vb2//AwMD/SUlJ/zExMf9sbGz/ + 4uLi/+bm5v/m5ub/5ubm/+bm5v/m5ub/4+Pj/6mpqf9sbGz/iIiI/87Ozv/c3Nz/19fX/9PT0//S0tL/ + 1dXV/9vb2//g4OD/5OTk/+Xl5f/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/39/f/87Ozv/h4eH/5ubm/9zc3P/V1dX/7e3t/3d3d/+bm5v/8fHx//b29v/5+fn/ + +vr6/+3t7f/Kysr/qKio/8LCwv/5+fn/5+fn/9nZ2f/y8vL/8/Pz/e3t7QMAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJOTk1J8fHz/xMTE/+fn5//w8PD/ + 8fHx/97e3v/Nzc3/1NTU/+Xl5f/y8vL/9vb2//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/ + +Pj4/+Pj4//b29v/4+Pj/+Tk5P/k5OT/wcHB/zQ0NP9aWlr/iYmJ/7m5uf/f39//5OTk/+Tk5P/k5OT/ + 5OTk/+Li4v/Z2dn/xcXF/19fX/8xMTH/UFBQ/9ra2v/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/CwsL/enp6/3Nzc/+4uLj/39/f/9ra2v/U1NT/z8/P/9HR0f/W1tb/29vb/9/f3//i4uL/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/b29v/zc3N/+Li4v/k5OT/ + 1dXV/9ra2v/q6ur/ampq/6ampv/p6en/7+/v//X19f/4+Pj/7e3t/83Nzf+oqKj/vb29//f39//q6ur/ + 1dXV//Dw8P/z8/P/8PDwNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAlJSUeH5+fv/S0tL/6Ojo//Hx8f/x8fH/19fX/8/Pz//Kysr/7u7u//Hx8f/29vb/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4/+/v7//a2tr/3t7e/+Li4v/Pz8// + 2tra/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/g4OD/19fX/8TExP96enr/MTEx/z09Pf/Jycn/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/1tbW/5CQkP9paWn/ + nZ2d/9nZ2f/b29v/1NTU/8/Pz//Nzc3/0NDQ/9XV1f/b29v/39/f/+Hh4f/i4uL/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/9fX1//Ly8v/3d3d/+Hh4f/R0dH/4ODg/9fX1/9oaGj/r6+v/9/f3//n5+f/ + 7u7u//Pz8//r6+v/zc3N/6mpqf+6urr/9fX1/+zs7P/S0tL/7u7u//Pz8//v7+9bAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5eXmchoaG/9bW1v/q6ur/ + 8vLy//Dw8P/R0dH/1NTU/8bGxv/19fX/8PDw//f39//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/ + +Pj4//j4+P/4+Pj/+Pj4//j4+P/m5ub/2NjY/9/f3//h4eH/4uLi/+Li4v/i4uL/4uLi/+Li4v/h4eH/ + 39/f/9bW1v/ExMT/k5OT/zIyMv8yMjL/r6+v/+Hh4f/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/9/f3/+rq6v/bW1t/4KCgv/Kysr/3Nzc/9fX1//R0dH/ + zc3N/8zMzP/Q0ND/19fX/9zc3P/f39//4eHh/+Li4v/i4uL/4uLi/+Li4v/h4eH/z8/P/8rKyv/u7u7/ + 1tbW/83Nzf/l5eX/vLy8/2hoaP+2trb/1NTU/93d3f/l5eX/7Ozs/+bm5v/Ly8v/qamp/7a2tv/z8/P/ + 7e3t/87Ozv/t7e3/8/Pz/+3t7W8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAHp6eriOjo7/2NjY/+vr6//z8/P/8PDw/83Nzf/Y2Nj/xMTE//Pz8//u7u7/ + 9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//09PT/ + 4ODg/9bW1v/d3d3/4ODg/+Dg4P/g4OD/4ODg/97e3v/U1NT/wcHB/6SkpP87Ozv/MTEx/42Njf/g4OD/ + 4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/w8PD/3t7e/9wcHD/sbGx/93d3f/Z2dn/09PT/83Nzf/Kysr/zc3N/9fX1//f39// + 4ODg/+Dg4P/g4OD/3d3d/9fX1//d3d3/8/Pz//f39/++vr7/ycnJ/+np6f+mpqb/aWlp/7m5uf/Gxsb/ + 0dHR/9vb2//j4+P/4ODg/8bGxv+mpqb/tLS0//Hx8f/t7e3/y8vL/+vr6//z8/P/7OzsewAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe3t7zpWVlf/Z2dn/ + 7e3t//Pz8//v7+//ysrK/9vb2//FxcX/8fHx/+7u7v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/8vLy/+Dg4P/V1dX/29vb/93d3f/c3Nz/ + 09PT/7+/v/+urq7/SkpK/zExMf9ra2v/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/9TU1P+SkpL/ + Z2dn/5eXl//V1dX/2tra/9XV1f/S0tL/1tbW/93d3f/e3t7/2tra/9bW1v/i4uL/9PT0//Hx8f/09PT/ + 7+/v/7u7u//Nzc3/6+vr/4GBgf9zc3P/ra2t/7i4uP/ExMT/zs7O/9fX1//W1tb/v7+//6Ghof+wsLD/ + 7u7u/+rq6v/Jycn/6+vr//Pz8//r6+t+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB8fHzfm5ub/9ra2v/t7e3/9PT0/+/v7//Jycn/2dnZ/8PDw//w8PD/ + 7e3t//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/ + 9fX1//X19f/19fX/9fX1//Pz8//k5OT/1dXV/8rKyv+9vb3/sbGx/2FhYf8xMTH/Tk5O/9XV1f/d3d3/ + 3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/ + 3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/b29v/rKys/21tbf98fHz/xMTE/9vb2//Z2dn/ + 1dXV/9bW1v/l5eX/9PT0//X19f/z8/P/7+/v//T09P/Z2dn/wMDA/9bW1v/o6Oj/ampq/3x8fP+enp7/ + qqqq/7W1tf/AwMD/y8vL/8rKyv+2trb/m5ub/62trf/q6ur/5ubm/8XFxf/q6ur/8/Pz/+rq6n8AAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH19femenp7/ + 2tra/+7u7v/09PT/7+/v/8nJyf/Y2Nj/wsLC/+/v7//s7Oz/9PT0//T09P/09PT/9PT0//T09P/09PT/ + 9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//Pz8//x8fH/ + 39/f/8TExP+IiIj/Ly8v/zw8PP/ExMT/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/ + 3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/ + 3Nzc/9zc3P/c3Nz/3Nzc/8LCwv93d3f/gYGB/83Nzf/s7Oz/9PT0//T09P/09PT/9PT0//Hx8f/u7u7/ + 9PT0/8bGxv/Dw8P/4uLi/8DAwP9oaGj/f39//5GRkf+bm5v/pqam/7Kysv+8vLz/vb29/6qqqv+Tk5P/ + qqqq/+Tk5P/e3t7/wcHB/+np6f/z8/P/9fX1iQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfn5+7KCgoP/a2tr/7u7u//X19f/w8PD/y8vL/9bW1v/AwMD/ + 7u7u/+rq6v/z8/P/5+fn/9/f3//r6+v/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//y8vL/7+/v/+rq6v/m5ub/39/f/8TExP+srKz/vr6+/9fX1//S0tL/ + 1tbW/9nZ2f/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/ + 2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/Z2dn/1tbW/9LS0v/W1tb/39/f/+rq6v/w8PD/ + 4ODg//Pz8//z8/P/8/Pz//Pz8//z8/P/7u7u/+/v7//z8/P/tLS0/8nJyf/p6en/n5+f/2hoaP+AgID/ + h4eH/4+Pj/+YmJj/o6Oj/66urv+urq7/nZ2d/4mJif+lpaX/3d3d/9TU1P+8vLz/6enp//Ly8v/o6Oh/ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/f3/s + oKCg/9nZ2f/t7e3/9vb2//Hx8f/Nzc3/1dXV/729vf/t7e3/6Ojo/+3t7f/Ly8v/2NjY/97e3v/w8PD/ + 8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//y8vL/8vLy/+7u7v/o6Oj/ + 5OTk/+Li4v/Dw8P/wMDA/9ra2v/z8/P/8/Pz//Hx8f/m5ub/39/f/9jY2P/T09P/0dHR/9PT0//V1dX/ + 1tbW/9fX1//Y2Nj/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Y2Nj/19fX/9bW1v/U1NT/0tLS/9HR0f/U1NT/ + 2tra/+Dg4P/m5ub/8fHx//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Hx8f/r6+v/ + 8PDw/+Pj4/+3t7f/0dHR/+zs7P9ycnL/b29v/39/f/+AgID/hYWF/4yMjP+VlZX/n5+f/56env+Pj4// + f39//6CgoP/U1NT/x8fH/7e3t//p6en/8vLy/+fn534AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICAgOaenp7/19fX/+zs7P/29vb/8vLy/9HR0f/Q0ND/ + uLi4/+zs7P/m5ub/6enp/8nJyf/X19f/3t7e/+zs7P/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Dw8P/t7e3/5ubm/+Li4v/j4+P/xcXF/7y8vP/Nzc3/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/7Ozs/+bm5v/h4eH/39/f/97e3v/c3Nz/3d3d/93d3f/d3d3/ + 3Nzc/9/f3//f39//4uLi/+bm5v/t7e3/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/7e3t/+rq6v/x8fH/xcXF/76+vv/g4OD/ycnJ/2hoaP94eHj/ + gICA/39/f/9/f3//hISE/4qKiv+RkZH/j4+P/4CAgP92dnb/nJyc/8jIyP+4uLj/srKy/+jo6P/x8fH/ + 5eXlewAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + gYGB2pubm//U1NT/6+vr//b29v/z8/P/19fX/83Nzf+1tbX/7Ozs/+Tk5P/u7u7/2dnZ/9DQ0P/g4OD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/v7+//6+vr/+Tk5P/g4OD/ + 5OTk/8vLy/+4uLj/wcHB/+3t7f/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/ + 8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/p6en/ + 6+vr//Dw8P+urq7/yMjI/+np6f+enp7/aWlp/4ODg/+CgoL/gICA/39/f/9/f3//goKC/4WFhf+AgID/ + cnJy/21tbf+Wlpb/urq6/6enp/+vr6//6enp//Dw8P/l5eVzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACDg4PJmJiY/9HR0f/p6en/9vb2//T09P/e3t7/ + ysrK/7m5uf/j4+P/4+Pj/+rq6v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+rq6v/i4uL/3t7e/+Li4v/T09P/tbW1/7i4uP/m5ub/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7Ozs/+fn5//s7Oz/0tLS/7W1tf/X19f/5eXl/29vb/90dHT/ + iYmJ/4aGhv+Dg4P/gYGB/39/f/9/f3//fX19/3V1df9lZWX/ZmZm/5GRkf+pqan/lpaW/62trf/p6en/ + 7+/v/+Tk5GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAISEhLGTk5P/zc3N/+fn5//19fX/9vb2/+Pj4//Kysr/v7+//9XV1f/i4uL/5+fn/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+3t7f/o6Oj/4ODg/9zc3P/g4OD/ + 29vb/7Gxsf+wsLD/29vb/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/ + 7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/m5ub/ + 5+fn/+7u7v+xsbH/w8PD/+bm5v+zs7P/aGho/4iIiP+NjY3/ioqK/4aGhv+EhIT/goKC/39/f/95eXn/ + a2tr/1tbW/9iYmL/ioqK/5iYmP+FhYX/sLCw/+vr6//u7u7/5eXlPAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhYWFlI+Pj//Jycn/4+Pj//T09P/4+Pj/ + 6enp/8jIyP/Gxsb/yMjI/+Pj4//j4+P/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/s7Oz/6Ojo/9/f3//a2tr/3t7e/+Hh4f+ysrL/rKys/83Nzf/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/ + 7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/6urq/+Tk5P/q6ur/1tbW/7CwsP/S0tL/6enp/3x8fP91dXX/ + l5eX/5KSkv+Ojo7/i4uL/4iIiP+EhIT/gYGB/3h4eP9mZmb/VFRU/2JiYv+EhIT/hoaG/3l5ef+3t7f/ + 7Ozs/+3t7f7Z2dkIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACcnJxwjY2N/8HBwf/f39//8fHx//j4+P/t7e3/zMzM/83Nzf+5ubn/5eXl/97e3v/r6+v/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+rq6v/h4eH/2dnZ/9zc3P/k5OT/ + t7e3/6ioqP+9vb3/6+vr/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/ + 7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+vr6//k5OT/ + 5OTk/+zs7P+xsbH/wcHB/+Xl5f+9vb3/aGho/5KSkv+cnJz/mJiY/5SUlP+Pj4//jIyM/4iIiP+Dg4P/ + d3d3/2JiYv9TU1P/ZmZm/4CAgP94eHj/cnJy/8TExP/r6+v/7u7u7gAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJubm0mOjo7/tra2/9nZ2f/u7u7/ + +fn5//Hx8f/W1tb/zc3N/6+vr//n5+f/3d3d/+bm5v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//q6ur/6Ojo/9/f3//c3Nz/5OTk/8HBwf+kpKT/r6+v/+fn5//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/ + 6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5ubm/+Hh4f/o6Oj/0tLS/6+vr//U1NT/5ubm/3h4eP93d3f/ + p6en/6Ojo/+enp7/mZmZ/5WVlf+RkZH/jY2N/4WFhf91dXX/X19f/1ZWVv9vb2//fX19/2tra/9ycnL/ + 1NTU/+rq6v/v7++6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAm5ubFY+Pj/+srKz/0dHR/+rq6v/4+Pj/9fX1/+Li4v/Kysr/ubm5/9TU1P/c3Nz/ + 4ODg/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+np6f/n5+f/4uLi/+Tk5P/Nzc3/ + oaGh/6Wlpf/e3t7/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/ + 6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/ + 6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+jo6P/g4OD/ + 4+Pj/+jo6P+oqKj/w8PD/+fn5/+xsbH/aGho/6Kiov+urq7/qqqq/6SkpP+fn5//mpqa/5aWlv+QkJD/ + hoaG/3Nzc/9cXFz/Xl5e/3l5ef97e3v/ZGRk/4KCgv/e3t7/6enp/9jY2HwAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkJCQ3KSkpP/Kysr/ + 5OTk//X19f/5+fn/6enp/8zMzP/Hx8f/vLy8/+Dg4P/a2tr/6Ojo/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+jo6P/n5+f/2NjY/56env+cnJz/0dHR/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/ + 6enp/+np6f/p6en/6enp/+np6f/o6Oj/4eHh/97e3v/o6Oj/v7+//7S0tP/b29v/5OTk/3Nzc/+EhIT/ + urq6/7W1tf+wsLD/q6ur/6Wlpf+hoaH/nJyc/5WVlf+Hh4f/b29v/1xcXP9paWn/goKC/3d3d/9iYmL/ + nJyc/+Xl5f/o6Oj/3NzcSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACSkpKenJyc/8LCwv/d3d3/8fHx//r6+v/w8PD/1dXV/87Ozv+rq6v/ + 4+Pj/9fX1//g4OD/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P+urq7/ + mJiY/8DAwP/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+Pj4//d3d3/ + 5OTk/9nZ2f+np6f/zMzM/+rq6v+cnJz/bGxs/7m5uf/BwcH/vLy8/7e3t/+xsbH/rKys/6ampv+hoaH/ + l5eX/4WFhf9ra2v/YGBg/3l5ef+Hh4f/cnJy/2dnZ/+6urr/6Ojo/+np6fnS0tIDAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKSkpFWampr/ + t7e3/9TU1P/r6+v/+Pj4//b29v/k5OT/zMzM/7u7u//Hx8f/29vb/9jY2P/n5+f/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/56env+tra3/5+fn/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/ + 6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/k5OT/29vb/97e3v/m5ub/pqam/7+/v//k5OT/y8vL/2xsbP+fn5// + zc3N/8fHx//BwcH/uLi4/6+vr/+np6f/oaGh/5qamv+Ojo7/enp6/2RkZP9qamr/iIiI/4eHh/9tbW3/ + d3d3/9XV1f/o6Oj/7e3ttwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6urDpubm/mtra3/ysrK/+Pj4//19fX/+/v7/+zs7P/R0dH/ + y8vL/6urq//i4uL/1dXV/97e3v/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//k5OT/ + nZ2d/+Li4v/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5eXl/9ra2v/b29v/ + 5ubm/7e3t/+0tLT/29vb/+Xl5f99fX3/gICA/9PT0//Nzc3/wcHB/7S0tP+mpqb/mZmZ/5CQkP+JiYn/ + goKC/3V1df9iYmL/WFhY/3BwcP+MjIz/gYGB/2tra/+Xl5f/5OTk/+jo6P/W1tZqAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + nJyctKampv/AwMD/2dnZ/+/v7//6+vr/9PT0/+Pj4//MzMz/tbW1/8nJyf/Z2dn/09PT/+Pj4//m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/9vb2//X19f/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/ + 5ubm/+bm5v/m5ub/5ubm/+Xl5f/a2tr/2NjY/+Tk5P/Gxsb/qKio/9HR0f/s7Oz/l5eX/3BwcP/Dw8P/ + ysrK/7e3t/+mpqb/lZWV/4aGhv95eXn/cHBw/2pqav9iYmL/VVVV/0ZGRv9KSkr/aGho/3x8fP9wcHD/ + bW1t/7y8vP/o6Oj/6urq+sXFxQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACrq6tXpKSk/7a2tv/Nzc3/5ubm//f39//7+/v/ + 6+vr/9LS0v/Kysr/qKio/+Dg4P/S0tL/19fX/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/ + 5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/k5OT/2dnZ/9bW1v/g4OD/ + 0tLS/6Ojo//Jycn/6enp/7W1tf9tbW3/oqKi/76+vv+np6f/kpKS/4CAgP9zc3P/ampq/2FhYf9cXFz/ + VlZW/0xMTP8/Pz//NTU1/z8/P/9UVFT/Wlpa/1ZWVv9wcHD/zc3N/+fn5//u7u6uAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALGxsQulpaXkrq6u/8LCwv/a2tr/8PDw//v7+//09PT/5OTk/83Nzf+6urr/uLi4/9zc3P/Q0ND/ + 3Nzc/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/4+Pj/9nZ2f/U1NT/3t7e/9bW1v+hoaH/w8PD/+Xl5f/Hx8f/bW1t/4SEhP+vr6// + lZWV/4CAgP9ycnL/bGxs/2tra/9ubm7/cHBw/3Jycv9ycnL/a2tr/2JiYv9VVVX/UVFR/0lJSf9AQED/ + Pj4+/3Fxcf+9vb3/3d3d/7+/v0sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKysrH2srKz/uLi4/83Nzf/l5eX/ + 9vb2//v7+//t7e3/2dnZ/8zMzP+oqKj/0tLS/9TU1P/Pz8//3t7e/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/X19f/09PT/9zc3P/Y2Nj/ + n5+f/76+vv/h4eH/1dXV/3Nzc/9tbW3/np6e/4iIiP93d3f/cXFx/3Nzc/91dXX/dnZ2/3Z2dv93d3f/ + dnZ2/3V1df9ycnL/cHBw/29vb/9ycnL/cXFx/1xcXP9BQUH/Z2dn/5ycnP/Hx8fjRUVFBwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAtra2Eq2trfSzs7P/wMDA/9jY2P/u7u7/+/v7//f39//p6en/0dHR/8bGxv+kpKT/ + 3d3d/9DQ0P/Pz8//4ODg/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/ + 4+Pj/+Pj4//h4eH/1NTU/9HR0f/c3Nz/2NjY/6CgoP+9vb3/39/f/9bW1v93d3f/X19f/4yMjP+AgID/ + dXV1/3V1df92dnb/d3d3/3d3d/95eXn/fX19/4GBgf+FhYX/hoaG/4WFhf+EhIT/hISE/4SEhP+CgoL/ + fHx8/3d3d/9vb2//f39//1ZWVo0iIiITioqKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsrKyibS0tP+3t7f/ + ycnJ/+Hh4f/09PT//Pz8//Ly8v/l5eX/zs7O/7u7u/+qqqr/3t7e/87Ozv/Ozs7/39/f/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/3t7e/9LS0v/R0dH/3Nzc/9LS0v+dnZ3/ + vb29/97e3v/W1tb/enp6/1hYWP94eHj/d3d3/3V1df93d3f/d3d3/3h4eP97e3v/g4OD/42Njf+Xl5f/ + oqKi/6ioqP+qqqr/qKio/6ioqP+pqan/qqqq/6Wlpf+bm5v/kJCQ/4aGhv99fX3+HBwccwAAACFmZmYD + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAC6uroRtbW167a2tv+8vLz/0dHR/+jo6P/39/f//Pz8/+7u7v/f39// + zc3N/7Ozs/+vr6//3d3d/8zMzP/Nzc3/3d3d/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/9jY2P/Ozs7/0dHR/97e3v/Ly8v/nZ2d/7+/v//f39//19fX/319ff9WVlb/ampq/3Fxcf92dnb/ + d3d3/3h4eP97e3v/g4OD/5KSkv+ioqL/sbGx/7y8vP/Dw8P/xMTE/8HBwf+/v7//wMDA/8TExP/IyMj/ + xcXF/729vf+2trb/qKio/5WVlf96enrqFxcXPkVFRQYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4uLhv + ubm5/7i4uP/CwsL/2NjY/+3t7f/6+vr/+vr6/+zs7P/c3Nz/zMzM/66urv+wsLD/3d3d/8zMzP/Ly8v/ + 2tra/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/8DAwP+goKD/t7e3/9nZ2f/h4eH/ + 4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/97e3v/S0tL/zc3N/9TU1P/f39//uLi4/5+fn//FxcX/ + 4+Pj/9bW1v9/f3//WVlZ/2NjY/9tbW3/d3d3/3h4eP95eXn/f39//46Ojv+hoaH/tbW1/8PDw//MzMz/ + z8/P/87Ozv/Kysr/xsbG/8TExP/Hx8f/zc3N/9DQ0P/Q0ND/zs7O/87Ozv/IyMj/tra2/5+fn/97e3vF + Tk5OCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC6urrAu7u7/7e3t//Gxsb/3d3d//Dw8P/7+/v/ + +fn5/+vr6//b29v/y8vL/62trf+tra3/3Nzc/83Nzf/Jycn/0tLS/9/f3//g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/ + 4ODg/+Dg4P/g4OD/kZGR/6ysrP/FxcX/zc3N/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/9/f3//W1tb/ + zMzM/8zMzP/Y2Nj/2tra/6Wlpf+oqKj/zc3N/+jo6P/Y2Nj/g4OD/19fX/9iYmL/ampq/3h4eP95eXn/ + e3t7/4WFhf+YmJj/r6+v/8LCwv/Ozs7/0tLS/9LS0v/Q0ND/zc3N/8rKyv/Kysr/z8/P/9fX1//d3d3/ + 3t7e/93d3f/c3Nz/2tra/9PT0//IyMj/ubm5/6Wlpf+QkJBYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAL+/vxy8vLzvu7u7/7m5uf/Kysr/4ODg//Ly8v/7+/v/+Pj4/+vr6//d3d3/y8vL/7Kysv+hoaH/ + 2NjY/9LS0v/Hx8f/y8vL/9nZ2f/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39// + 39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3/+enp7/o6Oj/7y8vP/Nzc3/ + 39/f/9/f3//f39//39/f/9/f3//X19f/zc3N/8vLy//S0tL/3d3d/8PDw/+ZmZn/tbW1/9fX1//u7u7/ + 09PT/4mJif9paWn/ZWVl/2JiYv92dnb/eHh4/3t7e/+IiIj/n5+f/7m5uf/Ly8v/0tLS/9TU1P/T09P/ + 0dHR/8/Pz//S0tL/19fX/97e3v/k5OT/6urq/+zs7P/s7Oz/6+vr/+vr6//p6en/4eHh/9LS0v/FxcX/ + u7u7/6enp80AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL6+vli9vb3/ubm5/7u7u//MzMz/ + 4eHh//Ly8v/7+/v/+Pj4/+zs7P/h4eH/zs7O/7m5uf+cnJz/x8fH/9jY2P/Ly8v/xsbG/83Nzf/Z2dn/ + 39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39// + 39/f/9/f3//f39//39/f/9nZ2f+6urr/xsbG/93d3f/f39//39/f/97e3v/V1dX/zMzM/8nJyf/Ozs7/ + 2dnZ/9XV1f+mpqb/oaGh/8TExP/i4uL/8PDw/8vLy/+RkZH/dnZ2/2pqav9aWlr/cHBw/3V1df96enr/ + iIiI/6Ojo/+9vb3/zc3N/9PT0//S0tL/0tLS/9DQ0P/T09P/2tra/+Hh4f/o6Oj/7u7u//Ly8v/19fX/ + 9vb2//b29v/29vb/9fX1//Ly8v/r6+v/4ODg/9HR0f/FxcX/u7u7/7Kysi8AAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAL6+vnq9vb3/t7e3/7u7u//MzMz/4eHh//Hx8f/6+vr/+vr6/+7u7v/m5ub/ + 0tLS/8LCwv+fn5//q6ur/9jY2P/U1NT/yMjI/8XFxf/Ly8v/1dXV/93d3f/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/9jY2P/Q0ND/ycnJ/8jIyP/Nzc3/2NjY/9nZ2f+wsLD/mJiY/7a2tv/V1dX/7Ozs/+7u7v+9vb3/ + nZ2d/4mJif9zc3P/WFhY/2NjY/93d3f/dnZ2/4KCgv+enp7/urq6/8nJyf/Pz8//z8/P/87Ozv/Ozs7/ + 1tbW/+Dg4P/o6Oj/7+/v//T09P/4+Pj/+vr6//v7+//8/Pz//Pz8//z8/P/7+/v/+fn5//T09P/q6ur/ + 3t7e/87Ozv/FxcX/vb29cwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL29vaK7u7v/ + t7e3/7u7u//Ly8v/3t7e/+7u7v/5+fn/+/v7//Hx8f/q6ur/2tra/8rKyv+zs7P/l5eX/7W1tf/b29v/ + 1NTU/8nJyf/ExMT/xcXF/8zMzP/U1NT/29vb/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/ + 3t7e/97e3v/e3t7/3t7e/97e3v/c3Nz/1tbW/8/Pz//Jycn/x8fH/8jIyP/Q0ND/2dnZ/9fX1/+wsLD/ + mJiY/6+vr//MzMz/5OTk//Hx8f/f39//s7Oz/6Wlpf+YmJj/gICA/19fX/9RUVH/cnJy/4ODg/9/f3// + lpaW/7Ozs//FxcX/ysrK/8vLy//Ly8v/zc3N/9jY2P/k5OT/7e3t//T09P/4+Pj/+/v7//39/f/9/f3/ + /v7+//7+/v/+/v7//v7+//7+/v/9/f3/+vr6//Ly8v/o6Oj/2tra/8zMzP/ExMSrAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv7+/B7u7u6S5ubn/tbW1/7q6uv/IyMj/2tra/+vr6//29vb/ + /Pz8//b29v/s7Oz/5eXl/9XV1f/FxcX/rKys/5eXl/+xsbH/1tbW/9fX1//Pz8//x8fH/8TExP/ExMT/ + xsbG/8vLy//Ozs7/0dHR/9PT0//U1NT/1tbW/9XV1f/T09P/0dHR/9DQ0P/Ly8v/x8fH/8XFxf/FxcX/ + yMjI/87Ozv/V1dX/3Nzc/8nJyf+oqKj/lpaW/6+vr//Jycn/4eHh//Dw8P/u7u7/y8vL/66urv+oqKj/ + mpqa/4qKiv9tbW3/T09P/2NjY/9+fn7/kZGR/5SUlP+urq7/wsLC/8nJyf/Kysr/ysrK/87Ozv/b29v/ + 5+fn//Dw8P/39/f/+/v7//39/f/9/f3//v7+//////////////////////////////////7+/v/9/f3/ + +Pj4/+/v7//j4+P/09PT/8zMzMkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALq6upK2trb/tLS0/7e3t//Dw8P/1NTU/+Xl5f/y8vL/+fn5//v7+//z8/P/6+vr/+Pj4//U1NT/ + xMTE/6+vr/+Xl5f/o6Oj/7+/v//a2tr/2dnZ/9PT0//Ozs7/ysrK/8fHx//ExMT/xMTE/8TExP/FxcX/ + xcXF/8XFxf/FxcX/xsbG/8rKyv/Pz8//09PT/9nZ2f/d3d3/x8fH/66urv+Xl5f/nZ2d/7a2tv/Nzc3/ + 4uLi/+/v7//y8vL/29vb/7u7u/+ysrL/o6Oj/5CQkP+Ojo7/fX19/15eXv9GRkb/dnZ2/4+Pj/+ioqL/ + srKy/8TExP/Ozs7/z8/P/8/Pz//S0tL/3t7e/+np6f/y8vL/+Pj4//z8/P/9/f3//v7+//////////// + //////////////////////////////////////7+/v/7+/v/9PT0/+rq6v/c3Nz/09PT1gAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALi4uHGzs7P8sLCw/7S0tP+/v7// + zc3N/93d3f/r6+v/9fX1//v7+//6+vr/8vLy/+vr6//l5eX/19fX/8rKyv+6urr/pqam/5OTk/+cnJz/ + q6ur/76+vv/MzMz/29vb/9zc3P/b29v/2tra/9jY2P/Z2dn/29vb/9zc3P/d3d3/z8/P/76+vv+vr6// + oKCg/5OTk/+enp7/sbGx/8bGxv/Y2Nj/6Ojo//Hx8f/z8/P/4uLi/8TExP+3t7f/r6+v/5OTk/+Ghob/ + ioqK/4WFhf9xcXH/UlJS/1BQUP99fX3/n5+f/7S0tP/Nzc3/09PT/9fX1//X19f/2NjY/+Hh4f/s7Oz/ + 8/Pz//n5+f/8/Pz//f39//7+/v////////////////////////////////////////////////////// + /v7+//z8/P/4+Pj/8PDw/+Xl5f/c3NzXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALi4uDyvr6/irKys/66urv+5ubn/xcXF/9PT0//h4eH/7e3t//X19f/5+fn/ + +vr6//T09P/t7e3/6enp/+Hh4f/W1tb/zMzM/7+/v/+0tLT/p6en/5ubm/+RkZH/lJSU/5mZmf+Wlpb/ + np6e/5eXl/+VlZX/lJSU/4+Pj/+ZmZn/paWl/7CwsP++vr7/zMzM/9nZ2f/m5ub/7+/v//Pz8//y8vL/ + 4eHh/8jIyP+6urr/uLi4/5ubm/+AgID/gYGB/4ODg/+Ghob/f39//2pqav9JSUn/X19f/4qKiv+rq6v/ + xcXF/9zc3P/b29v/2tra/9vb2//h4eH/6+vr//Pz8//4+Pj//Pz8//39/f/+/v7///////////////// + ///////////////////////////////////////////+/v7//f39//n5+f/09PT/7e3t/+bm5ssAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALe3txKrq6ud + pqam/6Wlpf+vr6//vLy8/8fHx//T09P/39/f/+jo6P/v7+//9PT0//f39//19fX/8PDw/+vr6//o6Oj/ + 5eXl/+Dg4P/Y2Nj/0tLS/9DQ0P/Kysr/xsbG/8TExP/Dw8P/xcXF/8vLy//Nzc3/0dHR/9bW1v/e3t7/ + 5ubm/+zs7P/x8fH/8/Pz//T09P/u7u7/3Nzc/8TExP+6urr/u7u7/6urq/+Ojo7/goKC/39/f/9/f3// + gICA/4KCgv98fHz/ZmZm/0VFRf9tbW3/mpqa/7m5uf/T09P/4+Pj/+Pj4//a2tr/3d3d/+jo6P/x8fH/ + 9/f3//v7+//9/f3//v7+//////////////////////////////////////////////////////////// + //////7+/v/8/Pz/+fn5//T09P/v7+//7e3trAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACvr689oqKi0J2dnf+enp7/q6ur/7m5uf+/v7// + xsbG/8/Pz//X19f/3d3d/+Pj4//n5+f/6+vr/+zs7P/r6+v/6+vr/+rq6v/q6ur/6enp/+np6f/p6en/ + 6Ojo/+vr6//t7e3/7+/v//Hx8f/y8vL/8/Pz//T09P/09PT/8vLy/+zs7P/g4OD/zMzM/7q6uv+2trb/ + ubm5/7i4uP+qqqr/nZ2d/5OTk/+Kior/g4OD/39/f/9/f3//gICA/3t7e/9lZWX/RUVF/3V1df+qqqr/ + x8fH/9/f3//p6en/6+vr/+Tk5P/m5ub/7u7u//X19f/6+vr//f39//7+/v////////////////////// + /////////////////////////////////////////////////v7+//z8/P/4+Pj/8/Pz/+/v7//u7u6A + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACsrKwCpKSkWJeXl+ORkZH/jY2N/5CQkP+YmJj/oqKi/6ampv+srKz/s7Oz/7q6uv/BwcH/ + x8fH/83Nzf/S0tL/19fX/9zc3P/g4OD/5OTk/+fn5//q6ur/7Ozs/+7u7v/v7+//7u7u/+3t7f/q6ur/ + 5ubm/9XV1f/Dw8P/tbW1/62trf+xsbH/ubm5/8jIyP/Kysr/wsLC/7a2tv+rq6v/oKCg/5WVlf+MjIz/ + hYWF/4CAgP9/f3//e3t7/2dnZ/9HR0f/d3d3/7W1tf/Pz8//5eXl/+zs7P/u7u7/8PDw//Dw8P/z8/P/ + +Pj4//z8/P/+/v7///////////////////////////////////////////////////////////////// + //////7+/v/9/f3//Pz8//n5+f/7+/v/7+/v//Dw8EUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoaGhApSUlIGAgID5 + dnZ2/2VlZf9eXl7/Y2Nj/25ubv96enr/hYWF/4uLi/+RkZH/mJiY/56env+kpKT/qqqq/7CwsP+1tbX/ + u7u7/8HBwf/FxcX/ycnJ/8fHx/+8vLz/srKy/6enp/+enp7/n5+f/6Wlpf+wsLD/ycnJ/9/f3//p6en/ + 4uLi/9nZ2f/Q0ND/xMTE/7q6uv+urq7/o6Oj/5iYmP+Pj4//h4eH/4GBgf98fHz/bGxs/05OTv93d3f/ + vb29/9TU1P/l5eX/6+vr/+3t7f/x8fH/9/f3//n5+f/7+/v//f39//7+/v////////////////////// + ///////////+/v7/+/v7//n5+f/9/f3//////////////////v7+//z8/P/7+/v//f39//n5+f/x8fHz + 8vLyBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGtraydsbGy4W1tb/lBQUP9ISEj/QkJC/0FBQf9BQUH/ + SEhI/05OTv9TU1P/WVlZ/1xcXP9jY2P/Y2Nj/2hoaP9paWn/aGho/2hoaP9paWn/bW1t/3Z2dv+AgID/ + j4+P/6mpqf/Ly8v/6Ojo//n5+f/5+fn/9vb2//Hx8f/r6+v/5OTk/9zc3P/S0tL/yMjI/729vf+ysrL/ + pqam/5ubm/+QkJD/h4eH/319ff9vb2//U1NT/3R0dP/Dw8P/2NjY/+Xl5f/p6en/7Ozs//Ly8v/39/f/ + /Pz8//7+/v/+/v7//////////////////////////////////f39/+7u7v++vr7/m5ub/+bm5v/+/v7/ + //////7+/v/9/f3//f39//7+/v/9/f3/8vLy//Hx8aQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABzc3Mk + cXFxbldXV69dXV3rWVlZ/1hYWP9WVlb/VVVV/1NTU/9QUFD/TU1N/0hISP9FRUX/QkJC/0BAQP9AQED/ + QkJC/0lJSf9TU1P/X19f/3BwcP+Dg4P/mJiY/7S0tP/MzMz/2NjY/+Xl5f/u7u7/9vb2//n5+f/5+fn/ + 9/f3//Pz8//t7e3/5+fn/97e3v/V1dX/y8vL/7+/v/+ysrL/paWl/5aWlv+IiIj/eXl5/2lpaf9TU1P/ + bW1t/8bGxv/c3Nz/6Ojo/+rq6v/t7e3/9fX1//v7+//9/f3//v7+//////////////////////////// + ///////////09PT/wsLC/5KSkv9YWFj/kpKS//v7+/////////////7+/v/+/v7//f39//j4+P/o6Oj/ + 8fHxOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB6enodaGhotGpqav1sbGz/bm5u/3BwcP9ycnL/c3Nz/3R0dP9zc3P/ + cXFx/29vb/9sbGz/aWlp/2VlZf9gYGD/W1tb/1VVVf9VVVX/Xl5e/25ubv+BgYH/jY2N/5KSkv+ZmZn/ + oaGh/6urq/+4uLj/yMjI/9jY2P/m5ub/8PDw//b29v/5+fn/9/f3//Pz8//u7u7/5+fn/97e3v/S0tL/ + xcXF/7W1tf+kpKT/kpKS/35+fv9tbW3/Xl5e/1VVVf9qamr/wcHB/+Dg4P/q6ur/7e3t//Ly8v/4+Pj/ + /Pz8//7+/v////////////////////////////////////////////n5+f/k5OT/ysrK/35+fv9gYGD/ + 8vLy//////////////////7+/v/9/f3/7e3t/+fn58AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfHx8GHJyct51dXX/ + d3d3/3t7e/+BgYH/iYmJ/5CQkP+Tk5P/k5OT/5GRkf+Pj4//jIyM/4qKiv+Hh4f/hISE/4GBgf9+fn7/ + eHh4/3Jycv9ra2v/YmJi/1hYWP9WVlb/Z2dn/319ff+MjIz/kpKS/5qamv+oqKj/uLi4/8rKyv/b29v/ + 6enp//Hx8f/z8/P/8PDw/+rq6v/g4OD/1dXV/8fHx/+4uLj/paWl/5OTk/+BgYH/dHR0/21tbf9ubm7/ + dXV1/3t7e/+zs7P/4+Pj/+7u7v/x8fH/9fX1//v7+//9/f3//v7+//////////////////////////// + /////////////////v7+//f39//t7e3/q6ur/2VlZf/p6en///////////////////////n5+f/v7+/9 + 8fHxOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB2dna1eXl5/3p6ev+BgYH/kZGR/6Ghof+urq7/srKy/7Gxsf+tra3/ + qamp/6ioqP+pqan/qqqq/6qqqv+rq6v/qamp/6ioqP+lpaX/oaGh/5ycnP+VlZX/iIiI/3d3d/9mZmb/ + VFRU/1RUVP9qamr/f39//4WFhf+Pj4//nZ2d/7CwsP/CwsL/0NDQ/9fX1//V1dX/z8/P/8TExP+4uLj/ + rKys/52dnf+SkpL/i4uL/4uLi/+QkJD/mJiY/52dnf+ampr/jo6O/5ubm//m5ub/8PDw//T09P/4+Pj/ + /Pz8//39/f/+/v7//////////////////////////////////////////////////f39//X19f+1tbX/ + v7+///7+/v/////////////////+/v7/+Pj4//X19ZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf39/RHt7e/98fHz/ + hISE/5mZmf+zs7P/xMTE/8jIyP/Dw8P/u7u7/7W1tf+2trb/u7u7/7+/v//CwsL/xcXF/8bGxv/Gxsb/ + xcXF/8XFxf/FxcX/xMTE/8TExP+6urr/qKio/5mZmf+Kior/c3Nz/1hYWP9PT0//X19f/2lpaf9wcHD/ + fX19/4+Pj/+hoaH/q6ur/66urv+qqqr/pqam/6Kiov+ioqL/pqam/66urv+5ubn/wsLC/8XFxf+/v7// + r6+v/5iYmP+BgYH/f39//9bW1v/y8vL/9/f3//r6+v/9/f3//f39//7+/v////////////////////// + /////////////////////////////////////////////////////////////////v7+//r6+v/29vbO + 9vb2CwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAB9fX2vfX19/4KCgv+Xl5f/t7e3/87Ozv/T09P/zc3N/8LCwv+6urr/ + urq6/8LCwv/Kysr/z8/P/9HR0f/T09P/1NTU/9TU1P/U1NT/1NTU/9TU1P/V1dX/1tbW/9DQ0P/FxcX/ + ubm5/7CwsP+oqKj/lZWV/3R0dP9aWlr/UVFR/1hYWP9hYWH/dHR0/4qKiv+enp7/rKys/7W1tf+/v7// + ysrK/9bW1v/i4uL/6Ojo/+fn5//c3Nz/ycnJ/7Kysv+cnJz/jY2N/4+Pj/+lpaX/urq6//Hx8f/5+fn/ + /Pz8//39/f/9/f3//v7+//////////////////////////////////////////////////////////// + //////////////////////39/f/39/f/9PT03vb29h4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAh4eHCYCAgPeBgYH/ + j4+P/6+vr//Ozs7/2tra/9XV1f/Ly8v/v7+//729vf/FxcX/0NDQ/9fX1//a2tr/29vb/9vb2//b29v/ + 29vb/9zc3P/c3Nz/29vb/9vb2//Z2dn/1tbW/9DQ0P/FxcX/u7u7/7u7u/++vr7/sbGx/5CQkP9ubm7/ + W1tb/3BwcP+NjY3/sLCw/9DQ0P/k5OT/8PDw//f39//6+vr/+Pj4//Hx8f/j4+P/0dHR/7+/v/+wsLD/ + qKio/7CwsP/FxcX/3Nzc/+np6f7n5+fHzc3N3Pn5+f/9/f3//f39//39/f/+/v7//v7+//////////// + ///////////////////////////////////////////////////////////5+fn/8vLy/+/v78/19fUY + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACIiIgygoKC/4eHh/+fn5//xcXF/9zc3P/e3t7/1dXV/8nJyf/AwMD/ + xcXF/9HR0f/a2tr/39/f/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/39/f/9/f3//f39//39/f/97e3v/d3d3/ + 19fX/87Ozv/CwsL/vb29/8XFxf/Nzc3/w8PD/6Ojo/99fX3/aWlp/5+fn//Jycn/5OTk//Dw8P/v7+// + 6urq/+Dg4P/U1NT/y8vL/8PDw/+/v7//xsbG/9HR0f/e3t7/6urq/vHx8drm5uaE39/fJQAAAADU1NQZ + 4ODgwfn5+f/9/f3//f39//7+/v/+/v7//v7+//7+/v////////////////////////////////////// + ///////////8/Pz/8vLy/+zs7P3t7e2Q8/PzCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIuLi0OFhYX/ + j4+P/6+vr//V1dX/5OTk/+Dg4P/V1dX/yMjI/8TExP/Nzc3/2tra/+Li4v/k5OT/5OTk/+Tk5P/k5OT/ + 5OTk/+Tk5P/k5OT/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/f39//1tbW/8jIyP/AwMD/x8fH/9PT0//Z2dn/ + ysrK/6ioqP+Dg4P/fHx8/7e3t//Jycn/z8/P/9DQ0P/Q0ND/0NDQ/9PT0//Y2Nj/4ODg/+rq6v7w8PDo + 9PT0p+Dg4GrS0tIXAAAAAAAAAAAAAAAAAAAAAAAAAADj4+ME6+vrkfLy8v35+fn//f39//7+/v/+/v7/ + /v7+//////////////////////////////////7+/v/6+vr/8fHx/+np6f/n5+e/7u7uNgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj4+PNoiIiP+Xl5f/vb29/+Dg4P/o6Oj/4+Pj/9fX1//Kysr/ + ycnJ/9XV1f/h4eH/5+fn/+np6f/p6en/6Ojo/+jo6P/o6Oj/6Ojo/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+Pj4//a2tr/zc3N/8TExP/Kysr/19fX/+Dg4P/e3t7/x8fH/6CgoP+BgYH/t7e35eXl5cru7u6s + 8vLyq+Li4n/o6Oh76urqc+vr62Xq6uo/4ODgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA7u7uOe7u7rHw8PD88PDw//Hx8f/29vb/+vr6//v7+//8/Pz/+vr6//b29v/x8fH/ + 6urq/+bm5vbk5OSh7OzsOgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYmJgN + i4uL+52dnf/Gxsb/5ubm/+zs7P/n5+f/3t7e/9XV1f/X19f/4eHh/+rq6v/v7+//7+/v/+7u7v/t7e3/ + 7Ozs/+zs7P/s7Oz/7Ozs/+vr6//r6+v/6+vr/+vr6//q6ur/5ubm/9zc3P/Pz8//x8fH/87Ozv/b29v/ + 5eXl/+fn5//Z2dn/s7Oz/5CQkP+ampqzu7u7BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO/v7yPt7e1q + 3NzcqNzc3Nfg4ODo5ubm/Ofn5+Xm5ubb5eXls+np6Yfs7OxL8PDwCQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACMjIy4oKCg/8rKyv/r6+v/9fX1//X19f/y8vL/ + 8PDw//Hx8f/09PT/+Pj4//n5+f/5+fn/+Pj4//f39//19fX/9PT0//Ly8v/w8PD/7+/v/+/v7//v7+// + 7+/v/+3t7f/n5+f/3Nzc/8/Pz//Ly8v/1dXV/+Li4v/q6ur/7Ozs/+Li4v+/v7//mJiY/6SkpOS6uroB + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAKGhoUaenp7/x8fH/+7u7v/7+/v//Pz8//z8/P/8/Pz//Pz8//39/f/+/v7//v7+//39/f/9/f3/ + /f39//z8/P/7+/v/+/v7//r6+v/5+fn/9vb2//X19f/z8/P/7+/v/+fn5//a2tr/z8/P/9HR0f/d3d3/ + 6enp/+/v7//x8fH/5+fn/8TExP+bm5v/q6ur2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJiYmKq9vb3/6urq//z8/P/9/f3/ + /v7+/////////////////////////////////////////////v7+//7+/v/+/v7//f39//39/f/9/f3/ + /Pz8//r6+v/19fX/6+vr/9vb2//R0dH/2dnZ/+bm5v/w8PD/9PT0//Pz8//o6Oj/w8PD/5ubm//AwMCa + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAvb29E6urq9jY2Nj/9/f3//39/f/9/f3//f39//7+/v////////////////////// + //////7+/v////////////////////////////7+/v/+/v7//f39//v7+//19fX/7e3t/+jo6P/p6en/ + 8PDw//X19f/39/f/9fX1/+Pj4/+7u7v/mJiY/ru7uzsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAyMjIGLq6us/h4eH/ + 9/f3//z8/P/8/Pz//Pz8//7+/v/+/v7////////////4+Pj/4+Pj/+np6f/29vb//v7+//////////// + ///////////+/v7//v7+//z8/P/6+vr/+fn5//n5+f/6+vr/+/v7//r6+v/z8/P/19fX/62trf+lpaW+ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0NDQCczMzJnf39//8vLy//z8/P/6+vr/+vr6//z8/P/+/v7/ + /////+bm5v+enp7/ioqK/6qqqv/7+/v///////////////////////////////////////7+/v/+/v7/ + /v7+//7+/v/+/v7/+/v7/+rq6v/FxcX/oaGh/sPDwz8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAANTU1ELU1NTW5+fn//f39//7+/v/+vr6//z8/P/9/f3/7u7u/9XV1f+fn5//kpKS//z8/P////// + //////////////////////////////////////////////////////7+/v/4+Pj/2NjY/6+vr//Dw8Or + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANvb2wTPz89e29vb1+zs7P/4+Pj/ + /f39//39/f/6+vr/8PDw/7e3t//Gxsb//Pz8//39/f/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/ + ///////////+/v7/+vr6/+bm5v+6urr/v7+/yNvb2w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAADi4uIC5OTkR+Dg4Krx8fH5+/v7//n5+f/z8/P/1tbW//Hx8f/4+Pj/ + +Pj4//n5+f/6+vr/+/v7//z8/P/9/f3//f39//39/f/9/f3/+/v7//Pz8//e3t7/xMTE99LS0ofk5OQH + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAOnp6Q3p6elQ6+vrmObm5tXo6Oj+7u7u//Ly8v/09PT/9fX1//b29v/29vb/9vb2//X19f/y8vL/ + 7u7u/+Xl5f/e3t7+2NjYyuHh4Xbl5eUTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOXl5Qvd3d00 + 3d3dWN/f33ba2tqT2dnZmt3d3bLe3t6y4eHhoOPj45bp6el07u7uR/Pz8xUAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////8Af////// + ////////////4AA//////////////////4AAB/////////////////8AAAP////////////////+AAAD + /////////////////gAAA/////////////////4AAAP/////////////////AAAD//////////////// + /wAAA/////////////////+AAAf///////////////gAAAAP//////////////8AAAAAH/////////// + ///wAAAAAA//////////////gAAAAAAA/////////////AAAAAAAAB///////////+AAAAAAAAAH//// + //////+AAAAAAAAAAP/////////+AAAAAAAAAAA/////////+AAAAAAAAAAAH/////////AAAAAAAAAA + AA///////x0AAAAAAAAAAAAD/////4AAAAAAAAAAAAAAAf////8AAAAAAAAAAAAAAAH////+AAAAAAAA + AAAAAAAB/////gAAAAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAD////+AAAAAAAAAAAAAAAA/////gAA + AAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAH/////wAAAAAAAAAAAAAAB//////AAAAAAAAAAAAAAAf// + ///4AAAAAAAAAAAAAAP//////AAAAAAAAAAAAAAD//////4AAAAAAAAAAAAAB///////AAAAAAAAAAAA + AAf//////wAAAAAAAAAAAAAH//////4AAAAAAAAAAAAAB//////8AAAAAAAAAAAAAAf//////AAAAAAA + AAAAAAAH//////gAAAAAAAAAAAAAB//////4AAAAAAAAAAAAAA//////8AAAAAAAAAAAAAAP//////AA + AAAAAAAAAAAAD//////gAAAAAAAAAAAAAAf/////4AAAAAAAAAAAAAAD/////8AAAAAAAAAAAAAAA/// + ///AAAAAAAAAAAAAAAH/////gAAAAAAAAAAAAAAB/////4AAAAAAAAAAAAAAAP////+AAAAAAAAAAAAA + AAD/////AAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAAH////8AAAAAAAAAAAAAAAB/////AAAAAAAA + AAAAAAAAf////wAAAAAAAAAAAAAAAH////4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAA + AAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD// + //4AAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAA + AAA////+AAAAAAAAAAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAA////+AAAAAAAA + AAAAAAAAP////gAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAB////+AAAAAAAAAAAAAAAAf////gAA + AAAAAAAAAAAAAH////8AAAAAAAAAAAAAAAB/////AAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAP// + //8AAAAAAAAAAAAAAAD/////gAAAAAAAAAAAAAAA/////4AAAAAAAAAAAAAAAf////+AAAAAAAAAAAAA + AAH/////wAAAAAAAAAAAAAAB/////8AAAAAAAAAAAAAAAP/////gAAAAAAAAAAAAAAD/////4AAAAAAA + AAAAAAAA//////AAAAAAAAAAAAAAAP/////4AAAAAAAAAAAAAAD/////+AAAAAAAAAAAAAAA//////wA + AAAAAAAAAAAAAH/////+AAAAAAAAAAAAAAB//////wAAAAAAAAAAAAAAf/////8AAAAAAAAAAAAAAH// + ////wAAAAAAAAAAAAAB//////+AAAAAAAAAAAAAAf//////wAAAAAAAAAAAAAH//////+AAAAAAAAAAA + AAB///////4AAAAAAAAAAAAAf///////AAAAAAAAAAAAAH///////8AAAAAAAAAAAAB////////wAAAA + AAAAAAAA////////4AAAAAAAAAAAAP///////4AAAAAAAAAAAAH///////8AAAAAAAAAAAAB//////// + AAAAAAAAAAAAA////////gAAAAAAAAAAAAP///////4AAAAAAAAAAAAH///////8AAAAAAAAAAAAD/// + /////AAAAAAAABAAAB////////wAAAAAAAD4AAB////////8AAAAAAAP/gAB/////////AAAAAAP//+A + B/////////4AAAAAD//////////////+AAAAAB///////////////wAAAAAf//////////////8AAAAA + H///////////////gAAAAD///////////////8AAAAA////////////////wAAAAf/////////////// + +AAAAH////////////////4AAAD/////////////////wAAD//////////////////wAH/////////// + //////////////////////////////////////////8oAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQDAwMMBgYGFQcHBxcODg4MBgYGAwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAB0AAABFUFBQqJ+fn+caGhpi + AAAAHAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAACYQEBB8 + zMzM+s/Pz/4xMTGIAAAAKgAAAAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + BAQEAgMDAx9ycnLA6enp/729vf4cHBxBBAQEDgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACQAAABEAAAAX + AAAAGQAAABYAAAASAQEBGBwcHGXa2tr739/f/6+vr/ApKSkQDAwMBAAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwEDAwMIAQEBFAAAACMAAAAy + BgYGQw0NDVkNDQ1hDAwMXwcHB1EAAABHAAAAU35+fs7v7+/+0tLS/5mZmdMAAAAmAAAAHQAAABMAAAAK + AAAABAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBgYBBQUFDgAAACYNDQ1L + Ojo6iV9fX76EhIThoKCg962trfyxsbH+r6+v/aenp/iTk5PobGxs0aOjo/3IyMj+xcXF/3Z2drwAAABK + AAAAPgAAADIAAAAkAAAAFgAAAA0AAAAGAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAEAAAABAwMDAQkJCQoBAQEr + IyMja3R0dMK0tLT5zc3N/9nZ2f/Q0ND/0dHR/9PT0//V1dX/1dXV/9PT0//Q0ND/0dHR/9PT0//CwsL/ + r6+v/z8/P6gAAABfAAAAVwAAAE0AAAA/AAAAKgAAABoAAAAUAAAADQAAAAQAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGBwEBARsAAAAzAAAAPgAAACgAAAAb + AAAAJBAQEFh3d3fCw8PD/NnZ2f7S0tL+09PT/+Xl5f74+Pj+9vb2//Ly8v7w8PD+8fHx//X19f76+vr+ + +Pj4/+Dg4P7Q0ND+2dnZ/7S0tOtGRkaRAAAAWwAAAFUAAABMAAAANgAAAB0AAAAbAAAAFQAAAA8AAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAFk1NTYmZmZnj + MjIytwAAAH8AAABpMjIykLKysvDW1tb/1tbW/9TU1P/y8vL/8vLy/+vr6//m5ub/9PT0//j4+P/6+vr/ + +vr6//b29v/x8fH/7Ozs//Dw8P/8/Pz/4uLi/9TU1P/Pz8/+iYmJxBISEl8AAABPAAAAMgAAABcAAAAb + AAAAGwAAABcAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + IiIiB5SUlKnw8PD+1tbW/3x8fOVRUVHMx8fH/Nzc3P7R0dH+6Ojo//Ly8v7p6en+9vb2/+Hh4f5tbW3+ + 8PDw//7+/v7+/v7+//////7+/v7+/v7+//////n5+f7s7Oz+9fX1//Pz8/7T09P/ycnJ/q+vr+YwMDBu + AAAAMQAAABoAAAAfAAAAHwAAACIAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAKCgoBbMzMzZ5eXl/6Ojo/7Jycn/3t7e/tHR0f7z8/P+6enp//Pz8/7+/v7+ + //////v7+/7S0tL+/v7+//7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+8vLy//Dw8P729vb/ + 1tbW/rS0tP63t7f0RkZGZwAAACkAAAArAAAAKQAAACMAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsrKwmm5ub7MHBwf7g4OD/0tLS/vT09P7m5ub+ + +/v7//7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+//////7+/v7+/v7+ + //////Pz8/7y8vL/7u7u/tjY2P6Pj4//tbW1+GFhYXoAAAAzAAAAMgAAABEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoqKgWsrKy6OHh4f/U1NT/ + 8/Pz/+bm5v/9/f3///////////////////////////////////////////////////////////////// + ///////////////////////////u7u7/+fn5/97e3v+9vb3/i4uL/7m5ufxqamqJAAAALAkJCQcAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn5+n + 3Nzc/9ra2v7s7Oz/5OTk/vr6+v79/f3+/f39//39/f79/f3+/f39//39/f79/f3+/f39//39/f79/f3+ + /f39//39/f79/f3+/f39//39/f79/f3+/f39//39/f78/Pz/6urq/vT09P7a2tr/m5ub/pycnP7FxcX9 + bGxseSwsLAkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAJ6enjy/v7/85eXl/9zc3P7o6Oj/8/Pz/vv7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v+ + +/v7//v7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v++/v7//v7+/77+/v/7e3t/vb29v7d3d3/ + pqam/tDQ0P6jo6P/4ODg+q+vrzkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAJeXl7jk5OT/2NjY/+7u7v/j4+P/9/f3//f39//39/f/9/f3//f39//39/f/ + 9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39/+1tbX/ + yMjI/+np6f/i4uL/t7e3/97e3v+7u7v/ysrK/+vr69Hi4uIGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5eXJ7e3t/vq6ur+2tra/97e3v7w8PD/9PT0/vT09P709PT+ + 9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+9PT0//T09P709PT+ + 9PT0//T09P6mpqb/yMjI/uTk5P7n5+f/yMjI/s7Ozv7j4+P/urq6/unp6f7w8PBkAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjo6Oftra2v7f39/+4eHh/+/v7/7t7e3/ + 8PDw/vDw8P7w8PD+8PDw//Dw8P7v7+/+7u7u/+vr6/7m5ub+sLCw/8vLy/7u7u7+8PDw//Dw8P7w8PD+ + 8PDw//Dw8P7w8PD+8PDw//Dw8P7w8PD/8PDw/uDg4P7q6ur/z8/P/sHBwf729vb/ubm5/ujo6P7x8fHQ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlZWVyOrq6v/Z2dn/ + 6Ojo//n5+f/y8vL/6enp/+vr6//r6+v/6enp/9nZ2f/Hx8f/oqKi/3t7e/9aWlr/QkJC/2BgYP/MzMz/ + 4ODg/+bm5v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/93d3f/p6en/z8/P/76+vv/8/Pz/ + w8PD/+Li4v/r6+v+7+/vIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACTk5MI + pqam+u7u7v7W1tb+6urq//n5+f76+vr/8/Pz/uXl5f7n5+f+0NDQ/1BQUP5RUVH+e3t7/6mpqf6hoaH+ + YmJi/83Nzf7Kysr+tLS0/7u7u/7Y2Nj+3Nzc/+Pj4/7m5ub+5+fn/+fn5/7n5+f/5+fn/tra2v7j4+P/ + ysrK/r+/v/76+vr/zc3N/tra2v7l5eX/7+/vWgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACSkpIvuLi4/+/v7/7Ozs7+8fHx//j4+P74+Pj/+Pj4/vX19f7m5ub+zc3N/8zMzP7h4eH+ + 4eHh/7+/v/5VVVX+0tLS/+Li4v7i4uL+4uLi/9XV1f60tLT+sbGx/9DQ0P7U1NT+2tra/+Hh4f7i4uL/ + 4uLi/tTU1P7b29v/vb29/r6+vv7t7e3/z8/P/tTU1P7h4eH/7+/vgQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACRkZFLw8PD/+7u7v/MzMz/8fHx//b29v/29vb/9vb2//b29v/29vb/ + 7+/v/+Li4v/b29v/w8PD/1lZWf+5ubn/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3d3d/7e3t/+vr6// + wsLC/9XV1f/d3d3/5OTk/+7u7v/Ozs7/pqam/6+vr//R0dH/wsLC/87Ozv/d3d3/7e3tjgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJRXyMjI/+/v7/7Kysr+7u7u/+vr6/7y8vL/ + 8/Pz/vPz8/7z8/P+9PT0//Pz8/7n5+f+q6ur/6SkpP7Z2dn+2tra/9vb2/7b29v+29vb/9vb2/7b29v+ + 29vb/9ra2v7a2tr+xsbG/9DQ0P7x8fH/8/Pz/uvr6/7Ozs7/iIiI/pGRkf6srKz/paWl/sDAwP7U1NT/ + 7OzskAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVlZVVxsbG//Hx8f7Gxsb+ + 6urq/9bW1v7s7Oz/8fHx/vHx8f7x8fH+8PDw/+jo6P7V1dX+0tLS//Hx8f7v7+/+6urq/+Xl5f7j4+P+ + 4+Pj/+Pj4/7j4+P+5ubm/+vr6/7w8PD+8fHx//Hx8f7x8fH/7e3t/tjY2P7Ozs7/dnZ2/oCAgP6Kior/ + gICA/qqqqv7Gxsb/6OjojAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVlZVD + vr6+//Pz8//Kysr/39/f/+3t7f/u7u7/7e3t/+3t7f/t7e3/5OTk/9jY2P/CwsL/7Ozs/+3t7f/t7e3/ + 7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/7u7u/+3t7f/t7e3/6Ojo/8fHx/+oqKj/ + iYmJ/4WFhf9+fn7/ZGRk/42Njf+8vLz/5ubmdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAACbm5sisbGx//Ly8v7W1tb+0dHR/+jo6P7r6+v/6+vr/uvr6/7m5ub+2tra/7e3t/7k5OT+ + 6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7r6+v+6+vr/+vr6/7n5+f/ + 1tbW/szMzP6Kior/nJyc/pCQkP6AgID/Xl5e/nV1df7Dw8P/39/fTQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACfn58BpKSk7Orq6v7k5OT+ycnJ/+Dg4P7o6Oj/6Ojo/ujo6P7n5+f+ + tLS0/9jY2P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+6Ojo/+jo6P7o6Oj+ + 6Ojo/+fn5/7h4eH/w8PD/qenp/6vr6//rKys/p+fn/6AgID/bGxs/nNzc/7Z2dn+29vbFgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApKSkptfX1//z8/P/xsbG/9bW1v/l5eX/ + 5+fn/+fn5//l5eX/x8fH/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/ + 5+fn/+fn5//n5+f/5ubm/97e3v/ExMT/x8fH/6SkpP+8vLz/nZ2d/4eHh/9lZWX/fHx8/4qKiv/j4+PJ + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAq6urTL6+vv7x8fH+ + 39/f/8PDw/7Z2dn/5OTk/uTk5P7k5OT+5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+ + 5OTk/+Tk5P7k5OT+5OTk/+Tk5P7k5OT+29vb/8nJyf7Ly8v/j4+P/p2dnf56enr/bGxs/mFhYf5NTU3/ + UVFR/peXl/7AwMBuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + sbGxBLOzs9XY2Nj/9PT0/8zMzP/Jycn/2dnZ/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/ + 4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Hh4f/X19f/yMjI/8fHx/+FhYX/f39//3Z2dv98fHz/ + ioqK/46Ojv+NjY3/goKC/3x8fPhNTU0nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALm5uVC+vr796enp/+/v7/7ExMT/ycnJ/tXV1f7g4OD+4ODg/+Dg4P7g4OD+ + 4ODg/+Dg4P7g4OD+4ODg/97e3v7BwcH+3t7e/+Dg4P7g4OD+29vb/9TU1P7BwcH+ysrK/4ODg/5tbW3/ + e3t7/paWlv67u7v/ycnJ/sXFxf7Nzc3/y8vL/rW1tf5qamqCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9vb2gxMTE/+3t7f7t7e3/xcXF/sHBwf7Q0ND+ + 2dnZ/9/f3/7f39/+39/f/9/f3/7f39/+39/f/9vb2/67u7v+29vb/9ra2v7S0tL+ysrK/7y8vP7V1dX+ + kZGR/2ZmZv58fHz/qamp/s3Nzf7S0tL/2dnZ/ufn5/7w8PD/7+/v/t7e3v68vLzxqKioCwAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC+vr4Iu7u7wsTExP/q6ur/ + 8vLy/9PT0/+5ubn/w8PD/8/Pz//R0dH/1tbW/9nZ2f/a2tr/2dnZ/9bW1v/R0dH/0NDQ/8fHx/+7u7v/ + zMzM/9bW1v+jo6P/Z2dn/3p6ev+fn5//yMjI/9DQ0P/m5ub/9/f3//39/f/+/v7//f39//X19f/Z2dn/ + y8vLPwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + vLy8Cra2tqy6urr+3d3d/vPz8/7s7Oz+z8/P/7q6uv66urr+vLy8/8DAwP7CwsL+v7+//7y8vP67u7v+ + vLy8/9DQ0P7h4eH+wsLC/5WVlf6BgYH+XFxc/6ampv7Pz8//19fX/uzs7P77+/v//v7+/v7+/v7///// + /v7+/vz8/P7s7Oz/39/fTwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAALW1tQKvr69kqamp6L6+vv7W1tb+5OTk/+bm5v7i4uL+2tra/9PT0/7S0tL+ + 2dnZ/+Hh4f7n5+f+3Nzc/8nJyf6xsbH+jIyM/4CAgP51dXX+a2tr/8vLy/7k5OT/6enp/vr6+v7+/v7/ + /v7+/v7+/v7//////v7+/v39/f7z8/P/7e3tNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAm5ubEIaGho1tbW36a2tr/3p6ev+Li4v/ + mZmZ/6SkpP+rq6v/rq6u/7Gxsf/ExMT/2tra/93d3f/FxcX/p6en/42Njf93d3f/eHh4/9vb2//u7u7/ + +Pj4//7+/v///////v7+/+3t7f/x8fH//v7+//z8/P/29vbw8fHxBgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAe3t7N3BwcLltbW31 + b29v/2tra/5iYmL+WVlZ/1ZWVv5ra2v+kZGR/7e3t/7b29v+8/Pz//Ly8v7h4eH+wsLC/5iYmP5vb2/+ + eXl5/+Pj4/7y8vL//f39/v7+/v7//////v7+/snJyf6ioqL//v7+/vz8/P7v7++NAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/f38Q + e3t76piYmP62trb+sLCw/7Kysv61tbX+tLS0/66urv6bm5v+eHh4/2xsbP5/f3/+pqam/8HBwf64uLj+ + q6ur/6ioqP6kpKT+jIyM/9/f3/75+fn//v7+/v7+/v7//////v7+/vn5+f7j4+P//v7+/vn5+d/19fUT + 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 + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAEBAQYGBgYPCgoKCgMDAwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAARo6OjtNMTEyaAAAAGgAAAAEAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwc5OTmE4ODg/1FRUY0CAgIRAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAQEBAwAAAAwAAAAXAAAAIwAAACUAAAAgAgICNLe3t+TT09P/QkJCVAUFBQgAAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAwMDDQcHBy8sLCxxUlJSpnNzc8Z+fn7UfHx80GZmZrtaWlrBzs7O/8jIyP8TExNY + AAAAMwAAACEAAAAPAAAABgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAgIC + AAAACAAAAAoAAAAFAwMDCg8PDz5jY2Oqubm5883Nzf/b29v/4ODg/+Pj4//i4uL/4ODg/9nZ2f/IyMj/ + rq6u+g8PD2sAAABXAAAARgAAACkAAAAXAAAADQAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAcHByJgYGCmFxcXjAAAAFg5OTmIurq68dXV1f/g4OD/7u7u/+/v7//y8vL/8vLy//Ly8v/z8/P/ + 8vLy//Dw8P/b29v/v7+/8EVFRYwAAABQAAAAKwAAABoAAAAYAAAACgAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAR0dHF9ra2urLy8v8cXFx39PT0/7Y2Nj/7Ozs//Dw8P/7+/v/m5ub//j4+P////// + ///////////+/v7/9PT0//T09P/i4uL/xsbG/nd3d68DAwMsAAAAIAAAACMAAAANAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsrKyOa+vr/bV1dX/2tra/+7u7v/29vb///////////////// + ////////////////////////////////+vr6//Pz8//h4eH/qKio/42NjbkJCQk4AAAALAAAAAMAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACjo6MmycnJ9dvb2//t7e3/+fn5//7+/v/+/v7/ + /v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/9/f3//T09P/Ly8v/k5OT/52dnckKCgoo + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK2trbnf39//6Ojo//Ly8v/8/Pz/ + /Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz/7+/v/+bm5v+0tLT/ + q6ur/7S0tLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUlJQ31NTU/+Hh4f/m5ub/ + 9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/8DAwP/Ly8v/ + 6Ojo/729vf/V1dX/0dHR/+np6VMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ6enprl5eX/ + 5OTk/+rq6v/x8fH/8fHx//Hx8f/x8fH/7+/v/+vr6//Gxsb/7u7u//Hx8f/x8fH/8fHx//Hx8f/x8fH/ + 6Ojo/+jo6P/m5ub/t7e3//b29v/Jycn/7e3tzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + s7Oz5ODg4P/t7e3/9/f3/+rq6v/q6ur/2NjY/56env96enr/eHh4/0pKSv+3t7f/1dXV/+Tk5P/p6en/ + 6urq/+rq6v/q6ur/6Ojo/+Hh4f+1tbX//Pz8/8jIyP/t7e3+8PDwIAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAIqKihjIyMj/2tra//Ly8v/4+Pj/9vb2/+jo6P+3t7f/sbGx/9jY2P+EhIT/xcXF/+Tk5P/Q0ND/ + wcHB/8PDw//a2tr/39/f/+Pj4//h4eH/2dnZ/7Ozs//s7Oz/x8fH/+np6f/v7+9PAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAi4uLNNTU1P/V1dX/8vLy//b29v/29vb/9vb2/+/v7//h4eH/lZWV/6ampv/e3t7/ + 3t7e/97e3v/e3t7/1dXV/7+/v/+7u7v/39/f/+rq6v/a2tr/np6e/8HBwf+1tbX/4eHh/+7u7l8AAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAACPj4851tbW/9PT0//l5eX/5+fn//Ly8v/y8vL/8PDw/+Dg4P/V1dX/ + 6Ojo/+Pj4//g4OD/4ODg/+Dg4P/j4+P/5+fn/+7u7v/w8PD/7+/v/83Nzf98fHz/jo6O/46Ojv/Kysr/ + 6urqXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJGRkSjNzc3/2tra/+Hh4f/t7e3/7e3t/+zs7P/e3t7/ + ycnJ/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+zs7P/Z2dn/r6+v/4yMjP+BgYH/ + bGxs/6ysrP/n5+dJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl5eXBbu7u/bo6Oj/0dHR/+jo6P/p6en/ + 5+fn/7+/v//k5OT/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np6f/p6en/5OTk/8rKyv+fn5// + paWl/4iIiP9ubm7/sLCw/uHh4RgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr6+vte3t7f/Ly8v/ + 39/f/+bm5v/l5eX/2NjY/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+Hh4f/MzMz/ + ra2t/6+vr/+Ghob/YGBg/3BwcP/Pz8/MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwsLBP + 09PT/+bm5v/IyMj/3t7e/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//d3d3/ + ysrK/6qqqv+BgYH/d3d3/4ODg/9+fn7/bm5u/3t7e3YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAALS0tAG8vLzB5ubm/9nZ2f/Hx8f/2dnZ/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/xMTE/93d3f/e3t7/ + 1tbW/8bGxv+urq7/bW1t/42Njf+9vb3/y8vL/9TU1P/R0dH/k5OTwQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAL29vR2/v7/k5+fn/9/f3//CwsL/zMzM/9XV1f/Z2dn/29vb/9ra2v/S0tL/ + 09PT/8PDw//Kysr/vr6+/2xsbP+NjY3/x8fH/9vb2//z8/P/+/v7//n5+f/a2tr/w8PDIQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALm5uSC1tbXM1tbW/+zs7P/W1tb/x8fH/8HBwf+/v7// + wcHB/8fHx//Ozs7/1NTU/6Wlpf+CgoL/dHR0/87Ozv/h4eH/+fn5//7+/v///////v7+//Pz8//h4eEy + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKmpqQObm5toioqK7JGRkf+mpqb/ + tbW1/8DAwP/ExMT/zs7O/9PT0//CwsL/mZmZ/3t7e/+SkpL/6urq//f39//+/v7//f39//Ly8v/+/v7/ + 9/f3+O/v7wwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHl5eYl+fn7v + gYGB/3l5ef9ubm7/b29v/4mJif+9vb3/5+fn/97e3v+vr6//gICA/5+fn//y8vL//v7+///////39/f/ + tra2//7+/v/09PScAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCgoIy + m5ub/8rKyv/FxcX/1NTU/9XV1f/Pz8//qqqq/3t7e/+YmJj/z8/P/8/Pz//BwcH+vr6+1PLy8ur+/v7/ + /v7+///////+/v7/9/f3xfb29g8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSchedule.Designer.cs b/scheduler/DeviceScheduler/frmSchedule.Designer.cs new file mode 100644 index 00000000..9fea2b92 --- /dev/null +++ b/scheduler/DeviceScheduler/frmSchedule.Designer.cs @@ -0,0 +1,960 @@ +namespace DeviceScheduler +{ + partial class frmSchedule + { + /// + /// 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() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmSchedule)); + this.cmdCancel = new System.Windows.Forms.Button(); + this.cmdOK = new System.Windows.Forms.Button(); + this.txtName = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.lvwDevices = new System.Windows.Forms.ListView(); + this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); + this.label2 = new System.Windows.Forms.Label(); + this.txtDescription = new System.Windows.Forms.TextBox(); + this.cmdAdd = new System.Windows.Forms.Button(); + this.cmdRemove = new System.Windows.Forms.Button(); + this.label4 = new System.Windows.Forms.Label(); + this.dtpDate = new System.Windows.Forms.DateTimePicker(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.grpMonth = new System.Windows.Forms.GroupBox(); + this.nupMonth = new System.Windows.Forms.NumericUpDown(); + this.label12 = new System.Windows.Forms.Label(); + this.cboMontDec = new System.Windows.Forms.CheckBox(); + this.cboMonthNov = new System.Windows.Forms.CheckBox(); + this.cboMontOct = new System.Windows.Forms.CheckBox(); + this.cboMontSept = new System.Windows.Forms.CheckBox(); + this.cboMonthAug = new System.Windows.Forms.CheckBox(); + this.cboMonthJuly = new System.Windows.Forms.CheckBox(); + this.cboMonthJune = new System.Windows.Forms.CheckBox(); + this.cboMonthMay = new System.Windows.Forms.CheckBox(); + this.cboMonthApr = new System.Windows.Forms.CheckBox(); + this.cboMonthMar = new System.Windows.Forms.CheckBox(); + this.cboMonthFeb = new System.Windows.Forms.CheckBox(); + this.cboMonthJan = new System.Windows.Forms.CheckBox(); + this.cboMonthDays = new System.Windows.Forms.ComboBox(); + this.cboOrder = new System.Windows.Forms.ComboBox(); + this.rdbMonthThe = new System.Windows.Forms.RadioButton(); + this.rdbMonthDay = new System.Windows.Forms.RadioButton(); + this.label11 = new System.Windows.Forms.Label(); + this.grpOnce = new System.Windows.Forms.GroupBox(); + this.label14 = new System.Windows.Forms.Label(); + this.grpDay = new System.Windows.Forms.GroupBox(); + this.nupDay = new System.Windows.Forms.NumericUpDown(); + this.label8 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.dtpTime = new System.Windows.Forms.DateTimePicker(); + this.grpWeek = new System.Windows.Forms.GroupBox(); + this.nupWeek = new System.Windows.Forms.NumericUpDown(); + this.label9 = new System.Windows.Forms.Label(); + this.label10 = new System.Windows.Forms.Label(); + this.cboWeekSaturday = new System.Windows.Forms.CheckBox(); + this.cboWeekSunday = new System.Windows.Forms.CheckBox(); + this.cboWeekFriday = new System.Windows.Forms.CheckBox(); + this.cboWeekThursday = new System.Windows.Forms.CheckBox(); + this.cboWeekWednesday = new System.Windows.Forms.CheckBox(); + this.cboWeekTuesday = new System.Windows.Forms.CheckBox(); + this.cboWeekMonday = new System.Windows.Forms.CheckBox(); + this.cboSchedule = new System.Windows.Forms.ComboBox(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.panel1 = new System.Windows.Forms.Panel(); + this.label13 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.grpMonth.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nupMonth)).BeginInit(); + this.grpOnce.SuspendLayout(); + this.grpDay.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nupDay)).BeginInit(); + this.grpWeek.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nupWeek)).BeginInit(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.panel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // cmdCancel + // + this.cmdCancel.AccessibleDescription = null; + this.cmdCancel.AccessibleName = null; + resources.ApplyResources(this.cmdCancel, "cmdCancel"); + this.cmdCancel.BackgroundImage = null; + this.cmdCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cmdCancel.Font = null; + this.cmdCancel.Name = "cmdCancel"; + this.cmdCancel.UseVisualStyleBackColor = true; + this.cmdCancel.Click += new System.EventHandler(this.cmdCancel_Click); + // + // cmdOK + // + this.cmdOK.AccessibleDescription = null; + this.cmdOK.AccessibleName = null; + resources.ApplyResources(this.cmdOK, "cmdOK"); + this.cmdOK.BackgroundImage = null; + this.cmdOK.Font = null; + this.cmdOK.Name = "cmdOK"; + this.cmdOK.UseVisualStyleBackColor = true; + this.cmdOK.Click += new System.EventHandler(this.cmdOK_Click); + // + // txtName + // + this.txtName.AccessibleDescription = null; + this.txtName.AccessibleName = null; + resources.ApplyResources(this.txtName, "txtName"); + this.txtName.BackgroundImage = null; + this.txtName.Font = null; + this.txtName.Name = "txtName"; + // + // label1 + // + this.label1.AccessibleDescription = null; + this.label1.AccessibleName = null; + resources.ApplyResources(this.label1, "label1"); + this.label1.Font = null; + this.label1.Name = "label1"; + // + // lvwDevices + // + this.lvwDevices.AccessibleDescription = null; + this.lvwDevices.AccessibleName = null; + resources.ApplyResources(this.lvwDevices, "lvwDevices"); + this.lvwDevices.BackgroundImage = null; + this.lvwDevices.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.lvwDevices.Font = null; + this.lvwDevices.Name = "lvwDevices"; + this.lvwDevices.UseCompatibleStateImageBehavior = false; + this.lvwDevices.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + resources.ApplyResources(this.columnHeader1, "columnHeader1"); + // + // columnHeader2 + // + resources.ApplyResources(this.columnHeader2, "columnHeader2"); + // + // label2 + // + this.label2.AccessibleDescription = null; + this.label2.AccessibleName = null; + resources.ApplyResources(this.label2, "label2"); + this.label2.Font = null; + this.label2.Name = "label2"; + // + // txtDescription + // + this.txtDescription.AccessibleDescription = null; + this.txtDescription.AccessibleName = null; + resources.ApplyResources(this.txtDescription, "txtDescription"); + this.txtDescription.BackgroundImage = null; + this.txtDescription.Font = null; + this.txtDescription.Name = "txtDescription"; + // + // cmdAdd + // + this.cmdAdd.AccessibleDescription = null; + this.cmdAdd.AccessibleName = null; + resources.ApplyResources(this.cmdAdd, "cmdAdd"); + this.cmdAdd.BackgroundImage = null; + this.cmdAdd.Font = null; + this.cmdAdd.Name = "cmdAdd"; + this.cmdAdd.UseVisualStyleBackColor = true; + this.cmdAdd.Click += new System.EventHandler(this.cmdAdd_Click); + // + // cmdRemove + // + this.cmdRemove.AccessibleDescription = null; + this.cmdRemove.AccessibleName = null; + resources.ApplyResources(this.cmdRemove, "cmdRemove"); + this.cmdRemove.BackgroundImage = null; + this.cmdRemove.Font = null; + this.cmdRemove.Name = "cmdRemove"; + this.cmdRemove.UseVisualStyleBackColor = true; + this.cmdRemove.Click += new System.EventHandler(this.cmdRemove_Click); + // + // label4 + // + this.label4.AccessibleDescription = null; + this.label4.AccessibleName = null; + resources.ApplyResources(this.label4, "label4"); + this.label4.Font = null; + this.label4.Name = "label4"; + + // + // dtpDate + // + this.dtpDate.AccessibleDescription = null; + this.dtpDate.AccessibleName = null; + resources.ApplyResources(this.dtpDate, "dtpDate"); + this.dtpDate.BackgroundImage = null; + this.dtpDate.CalendarFont = null; + this.dtpDate.CustomFormat = null; + this.dtpDate.Font = null; + this.dtpDate.Name = "dtpDate"; + + // + // groupBox1 + // + this.groupBox1.AccessibleDescription = null; + this.groupBox1.AccessibleName = null; + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.BackgroundImage = null; + this.groupBox1.Controls.Add(this.txtDescription); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.txtName); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Font = null; + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // groupBox2 + // + this.groupBox2.AccessibleDescription = null; + this.groupBox2.AccessibleName = null; + resources.ApplyResources(this.groupBox2, "groupBox2"); + this.groupBox2.BackgroundImage = null; + this.groupBox2.Controls.Add(this.lvwDevices); + this.groupBox2.Controls.Add(this.cmdAdd); + this.groupBox2.Controls.Add(this.cmdRemove); + this.groupBox2.Font = null; + this.groupBox2.Name = "groupBox2"; + this.groupBox2.TabStop = false; + // + // groupBox3 + // + this.groupBox3.AccessibleDescription = null; + this.groupBox3.AccessibleName = null; + resources.ApplyResources(this.groupBox3, "groupBox3"); + this.groupBox3.BackgroundImage = null; + this.groupBox3.Controls.Add(this.grpMonth); + this.groupBox3.Controls.Add(this.grpOnce); + this.groupBox3.Controls.Add(this.grpDay); + this.groupBox3.Controls.Add(this.dtpTime); + this.groupBox3.Controls.Add(this.grpWeek); + this.groupBox3.Controls.Add(this.cboSchedule); + this.groupBox3.Controls.Add(this.label7); + this.groupBox3.Controls.Add(this.label4); + this.groupBox3.Controls.Add(this.label6); + this.groupBox3.Controls.Add(this.dtpDate); + this.groupBox3.Font = null; + this.groupBox3.Name = "groupBox3"; + this.groupBox3.TabStop = false; + // + // grpMonth + // + this.grpMonth.AccessibleDescription = null; + this.grpMonth.AccessibleName = null; + resources.ApplyResources(this.grpMonth, "grpMonth"); + this.grpMonth.BackgroundImage = null; + this.grpMonth.Controls.Add(this.nupMonth); + this.grpMonth.Controls.Add(this.label12); + this.grpMonth.Controls.Add(this.cboMontDec); + this.grpMonth.Controls.Add(this.cboMonthNov); + this.grpMonth.Controls.Add(this.cboMontOct); + this.grpMonth.Controls.Add(this.cboMontSept); + this.grpMonth.Controls.Add(this.cboMonthAug); + this.grpMonth.Controls.Add(this.cboMonthJuly); + this.grpMonth.Controls.Add(this.cboMonthJune); + this.grpMonth.Controls.Add(this.cboMonthMay); + this.grpMonth.Controls.Add(this.cboMonthApr); + this.grpMonth.Controls.Add(this.cboMonthMar); + this.grpMonth.Controls.Add(this.cboMonthFeb); + this.grpMonth.Controls.Add(this.cboMonthJan); + this.grpMonth.Controls.Add(this.cboMonthDays); + this.grpMonth.Controls.Add(this.cboOrder); + this.grpMonth.Controls.Add(this.rdbMonthThe); + this.grpMonth.Controls.Add(this.rdbMonthDay); + this.grpMonth.Controls.Add(this.label11); + this.grpMonth.Font = null; + this.grpMonth.Name = "grpMonth"; + this.grpMonth.TabStop = false; + // + // nupMonth + // + this.nupMonth.AccessibleDescription = null; + this.nupMonth.AccessibleName = null; + resources.ApplyResources(this.nupMonth, "nupMonth"); + this.nupMonth.Font = null; + this.nupMonth.Maximum = new decimal(new int[] { + 30, + 0, + 0, + 0}); + this.nupMonth.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nupMonth.Name = "nupMonth"; + this.nupMonth.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // label12 + // + this.label12.AccessibleDescription = null; + this.label12.AccessibleName = null; + resources.ApplyResources(this.label12, "label12"); + this.label12.Font = null; + this.label12.Name = "label12"; + // + // cboMontDec + // + this.cboMontDec.AccessibleDescription = null; + this.cboMontDec.AccessibleName = null; + resources.ApplyResources(this.cboMontDec, "cboMontDec"); + this.cboMontDec.BackgroundImage = null; + this.cboMontDec.Font = null; + this.cboMontDec.Name = "cboMontDec"; + this.cboMontDec.UseVisualStyleBackColor = true; + // + // cboMonthNov + // + this.cboMonthNov.AccessibleDescription = null; + this.cboMonthNov.AccessibleName = null; + resources.ApplyResources(this.cboMonthNov, "cboMonthNov"); + this.cboMonthNov.BackgroundImage = null; + this.cboMonthNov.Font = null; + this.cboMonthNov.Name = "cboMonthNov"; + this.cboMonthNov.UseVisualStyleBackColor = true; + // + // cboMontOct + // + this.cboMontOct.AccessibleDescription = null; + this.cboMontOct.AccessibleName = null; + resources.ApplyResources(this.cboMontOct, "cboMontOct"); + this.cboMontOct.BackgroundImage = null; + this.cboMontOct.Font = null; + this.cboMontOct.Name = "cboMontOct"; + this.cboMontOct.UseVisualStyleBackColor = true; + // + // cboMontSept + // + this.cboMontSept.AccessibleDescription = null; + this.cboMontSept.AccessibleName = null; + resources.ApplyResources(this.cboMontSept, "cboMontSept"); + this.cboMontSept.BackgroundImage = null; + this.cboMontSept.Font = null; + this.cboMontSept.Name = "cboMontSept"; + this.cboMontSept.UseVisualStyleBackColor = true; + // + // cboMonthAug + // + this.cboMonthAug.AccessibleDescription = null; + this.cboMonthAug.AccessibleName = null; + resources.ApplyResources(this.cboMonthAug, "cboMonthAug"); + this.cboMonthAug.BackgroundImage = null; + this.cboMonthAug.Font = null; + this.cboMonthAug.Name = "cboMonthAug"; + this.cboMonthAug.UseVisualStyleBackColor = true; + // + // cboMonthJuly + // + this.cboMonthJuly.AccessibleDescription = null; + this.cboMonthJuly.AccessibleName = null; + resources.ApplyResources(this.cboMonthJuly, "cboMonthJuly"); + this.cboMonthJuly.BackgroundImage = null; + this.cboMonthJuly.Font = null; + this.cboMonthJuly.Name = "cboMonthJuly"; + this.cboMonthJuly.UseVisualStyleBackColor = true; + // + // cboMonthJune + // + this.cboMonthJune.AccessibleDescription = null; + this.cboMonthJune.AccessibleName = null; + resources.ApplyResources(this.cboMonthJune, "cboMonthJune"); + this.cboMonthJune.BackgroundImage = null; + this.cboMonthJune.Font = null; + this.cboMonthJune.Name = "cboMonthJune"; + this.cboMonthJune.UseVisualStyleBackColor = true; + // + // cboMonthMay + // + this.cboMonthMay.AccessibleDescription = null; + this.cboMonthMay.AccessibleName = null; + resources.ApplyResources(this.cboMonthMay, "cboMonthMay"); + this.cboMonthMay.BackgroundImage = null; + this.cboMonthMay.Font = null; + this.cboMonthMay.Name = "cboMonthMay"; + this.cboMonthMay.UseVisualStyleBackColor = true; + // + // cboMonthApr + // + this.cboMonthApr.AccessibleDescription = null; + this.cboMonthApr.AccessibleName = null; + resources.ApplyResources(this.cboMonthApr, "cboMonthApr"); + this.cboMonthApr.BackgroundImage = null; + this.cboMonthApr.Font = null; + this.cboMonthApr.Name = "cboMonthApr"; + this.cboMonthApr.UseVisualStyleBackColor = true; + // + // cboMonthMar + // + this.cboMonthMar.AccessibleDescription = null; + this.cboMonthMar.AccessibleName = null; + resources.ApplyResources(this.cboMonthMar, "cboMonthMar"); + this.cboMonthMar.BackgroundImage = null; + this.cboMonthMar.Font = null; + this.cboMonthMar.Name = "cboMonthMar"; + this.cboMonthMar.UseVisualStyleBackColor = true; + // + // cboMonthFeb + // + this.cboMonthFeb.AccessibleDescription = null; + this.cboMonthFeb.AccessibleName = null; + resources.ApplyResources(this.cboMonthFeb, "cboMonthFeb"); + this.cboMonthFeb.BackgroundImage = null; + this.cboMonthFeb.Font = null; + this.cboMonthFeb.Name = "cboMonthFeb"; + this.cboMonthFeb.UseVisualStyleBackColor = true; + // + // cboMonthJan + // + this.cboMonthJan.AccessibleDescription = null; + this.cboMonthJan.AccessibleName = null; + resources.ApplyResources(this.cboMonthJan, "cboMonthJan"); + this.cboMonthJan.BackgroundImage = null; + this.cboMonthJan.Font = null; + this.cboMonthJan.Name = "cboMonthJan"; + this.cboMonthJan.UseVisualStyleBackColor = true; + // + // cboMonthDays + // + this.cboMonthDays.AccessibleDescription = null; + this.cboMonthDays.AccessibleName = null; + resources.ApplyResources(this.cboMonthDays, "cboMonthDays"); + this.cboMonthDays.BackgroundImage = null; + this.cboMonthDays.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboMonthDays.Font = null; + this.cboMonthDays.FormattingEnabled = true; + this.cboMonthDays.Items.AddRange(new object[] { + resources.GetString("cboMonthDays.Items"), + resources.GetString("cboMonthDays.Items1"), + resources.GetString("cboMonthDays.Items2"), + resources.GetString("cboMonthDays.Items3"), + resources.GetString("cboMonthDays.Items4"), + resources.GetString("cboMonthDays.Items5"), + resources.GetString("cboMonthDays.Items6")}); + this.cboMonthDays.Name = "cboMonthDays"; + // + // cboOrder + // + this.cboOrder.AccessibleDescription = null; + this.cboOrder.AccessibleName = null; + resources.ApplyResources(this.cboOrder, "cboOrder"); + this.cboOrder.BackgroundImage = null; + this.cboOrder.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboOrder.Font = null; + this.cboOrder.FormattingEnabled = true; + this.cboOrder.Items.AddRange(new object[] { + resources.GetString("cboOrder.Items"), + resources.GetString("cboOrder.Items1"), + resources.GetString("cboOrder.Items2"), + resources.GetString("cboOrder.Items3"), + resources.GetString("cboOrder.Items4")}); + this.cboOrder.Name = "cboOrder"; + // + // rdbMonthThe + // + this.rdbMonthThe.AccessibleDescription = null; + this.rdbMonthThe.AccessibleName = null; + resources.ApplyResources(this.rdbMonthThe, "rdbMonthThe"); + this.rdbMonthThe.BackgroundImage = null; + this.rdbMonthThe.Font = null; + this.rdbMonthThe.Name = "rdbMonthThe"; + this.rdbMonthThe.UseVisualStyleBackColor = true; + // + // rdbMonthDay + // + this.rdbMonthDay.AccessibleDescription = null; + this.rdbMonthDay.AccessibleName = null; + resources.ApplyResources(this.rdbMonthDay, "rdbMonthDay"); + this.rdbMonthDay.BackgroundImage = null; + this.rdbMonthDay.Checked = true; + this.rdbMonthDay.Font = null; + this.rdbMonthDay.Name = "rdbMonthDay"; + this.rdbMonthDay.TabStop = true; + this.rdbMonthDay.UseVisualStyleBackColor = true; + // + // label11 + // + this.label11.AccessibleDescription = null; + this.label11.AccessibleName = null; + resources.ApplyResources(this.label11, "label11"); + this.label11.Font = null; + this.label11.Name = "label11"; + // + // grpOnce + // + this.grpOnce.AccessibleDescription = null; + this.grpOnce.AccessibleName = null; + resources.ApplyResources(this.grpOnce, "grpOnce"); + this.grpOnce.BackgroundImage = null; + this.grpOnce.Controls.Add(this.label14); + this.grpOnce.Font = null; + this.grpOnce.Name = "grpOnce"; + this.grpOnce.TabStop = false; + // + // label14 + // + this.label14.AccessibleDescription = null; + this.label14.AccessibleName = null; + resources.ApplyResources(this.label14, "label14"); + this.label14.Font = null; + this.label14.Name = "label14"; + // + // grpDay + // + this.grpDay.AccessibleDescription = null; + this.grpDay.AccessibleName = null; + resources.ApplyResources(this.grpDay, "grpDay"); + this.grpDay.BackgroundImage = null; + this.grpDay.Controls.Add(this.nupDay); + this.grpDay.Controls.Add(this.label8); + this.grpDay.Controls.Add(this.label5); + this.grpDay.Font = null; + this.grpDay.Name = "grpDay"; + this.grpDay.TabStop = false; + // + // nupDay + // + this.nupDay.AccessibleDescription = null; + this.nupDay.AccessibleName = null; + resources.ApplyResources(this.nupDay, "nupDay"); + this.nupDay.Font = null; + this.nupDay.Maximum = new decimal(new int[] { + 7, + 0, + 0, + 0}); + this.nupDay.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nupDay.Name = "nupDay"; + this.nupDay.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // label8 + // + this.label8.AccessibleDescription = null; + this.label8.AccessibleName = null; + resources.ApplyResources(this.label8, "label8"); + this.label8.Font = null; + this.label8.Name = "label8"; + // + // label5 + // + this.label5.AccessibleDescription = null; + this.label5.AccessibleName = null; + resources.ApplyResources(this.label5, "label5"); + this.label5.Font = null; + this.label5.Name = "label5"; + // + // dtpTime + // + this.dtpTime.AccessibleDescription = null; + this.dtpTime.AccessibleName = null; + resources.ApplyResources(this.dtpTime, "dtpTime"); + this.dtpTime.BackgroundImage = null; + this.dtpTime.CalendarFont = null; + this.dtpTime.Font = null; + this.dtpTime.Format = System.Windows.Forms.DateTimePickerFormat.Custom; + this.dtpTime.Name = "dtpTime"; + this.dtpTime.ShowUpDown = true; + // + // grpWeek + // + this.grpWeek.AccessibleDescription = null; + this.grpWeek.AccessibleName = null; + resources.ApplyResources(this.grpWeek, "grpWeek"); + this.grpWeek.BackgroundImage = null; + this.grpWeek.Controls.Add(this.nupWeek); + this.grpWeek.Controls.Add(this.label9); + this.grpWeek.Controls.Add(this.label10); + this.grpWeek.Controls.Add(this.cboWeekSaturday); + this.grpWeek.Controls.Add(this.cboWeekSunday); + this.grpWeek.Controls.Add(this.cboWeekFriday); + this.grpWeek.Controls.Add(this.cboWeekThursday); + this.grpWeek.Controls.Add(this.cboWeekWednesday); + this.grpWeek.Controls.Add(this.cboWeekTuesday); + this.grpWeek.Controls.Add(this.cboWeekMonday); + this.grpWeek.Font = null; + this.grpWeek.Name = "grpWeek"; + this.grpWeek.TabStop = false; + // + // nupWeek + // + this.nupWeek.AccessibleDescription = null; + this.nupWeek.AccessibleName = null; + resources.ApplyResources(this.nupWeek, "nupWeek"); + this.nupWeek.Font = null; + this.nupWeek.Maximum = new decimal(new int[] { + 52, + 0, + 0, + 0}); + this.nupWeek.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.nupWeek.Name = "nupWeek"; + this.nupWeek.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // label9 + // + this.label9.AccessibleDescription = null; + this.label9.AccessibleName = null; + resources.ApplyResources(this.label9, "label9"); + this.label9.Font = null; + this.label9.Name = "label9"; + // + // label10 + // + this.label10.AccessibleDescription = null; + this.label10.AccessibleName = null; + resources.ApplyResources(this.label10, "label10"); + this.label10.Font = null; + this.label10.Name = "label10"; + // + // cboWeekSaturday + // + this.cboWeekSaturday.AccessibleDescription = null; + this.cboWeekSaturday.AccessibleName = null; + resources.ApplyResources(this.cboWeekSaturday, "cboWeekSaturday"); + this.cboWeekSaturday.BackgroundImage = null; + this.cboWeekSaturday.Font = null; + this.cboWeekSaturday.Name = "cboWeekSaturday"; + this.cboWeekSaturday.UseVisualStyleBackColor = true; + // + // cboWeekSunday + // + this.cboWeekSunday.AccessibleDescription = null; + this.cboWeekSunday.AccessibleName = null; + resources.ApplyResources(this.cboWeekSunday, "cboWeekSunday"); + this.cboWeekSunday.BackgroundImage = null; + this.cboWeekSunday.Font = null; + this.cboWeekSunday.Name = "cboWeekSunday"; + this.cboWeekSunday.UseVisualStyleBackColor = true; + // + // cboWeekFriday + // + this.cboWeekFriday.AccessibleDescription = null; + this.cboWeekFriday.AccessibleName = null; + resources.ApplyResources(this.cboWeekFriday, "cboWeekFriday"); + this.cboWeekFriday.BackgroundImage = null; + this.cboWeekFriday.Font = null; + this.cboWeekFriday.Name = "cboWeekFriday"; + this.cboWeekFriday.UseVisualStyleBackColor = true; + // + // cboWeekThursday + // + this.cboWeekThursday.AccessibleDescription = null; + this.cboWeekThursday.AccessibleName = null; + resources.ApplyResources(this.cboWeekThursday, "cboWeekThursday"); + this.cboWeekThursday.BackgroundImage = null; + this.cboWeekThursday.Font = null; + this.cboWeekThursday.Name = "cboWeekThursday"; + this.cboWeekThursday.UseVisualStyleBackColor = true; + // + // cboWeekWednesday + // + this.cboWeekWednesday.AccessibleDescription = null; + this.cboWeekWednesday.AccessibleName = null; + resources.ApplyResources(this.cboWeekWednesday, "cboWeekWednesday"); + this.cboWeekWednesday.BackgroundImage = null; + this.cboWeekWednesday.Font = null; + this.cboWeekWednesday.Name = "cboWeekWednesday"; + this.cboWeekWednesday.UseVisualStyleBackColor = true; + // + // cboWeekTuesday + // + this.cboWeekTuesday.AccessibleDescription = null; + this.cboWeekTuesday.AccessibleName = null; + resources.ApplyResources(this.cboWeekTuesday, "cboWeekTuesday"); + this.cboWeekTuesday.BackgroundImage = null; + this.cboWeekTuesday.Font = null; + this.cboWeekTuesday.Name = "cboWeekTuesday"; + this.cboWeekTuesday.UseVisualStyleBackColor = true; + // + // cboWeekMonday + // + this.cboWeekMonday.AccessibleDescription = null; + this.cboWeekMonday.AccessibleName = null; + resources.ApplyResources(this.cboWeekMonday, "cboWeekMonday"); + this.cboWeekMonday.BackgroundImage = null; + this.cboWeekMonday.Font = null; + this.cboWeekMonday.Name = "cboWeekMonday"; + this.cboWeekMonday.UseVisualStyleBackColor = true; + // + // cboSchedule + // + this.cboSchedule.AccessibleDescription = null; + this.cboSchedule.AccessibleName = null; + resources.ApplyResources(this.cboSchedule, "cboSchedule"); + this.cboSchedule.BackgroundImage = null; + this.cboSchedule.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboSchedule.Font = null; + this.cboSchedule.FormattingEnabled = true; + this.cboSchedule.Items.AddRange(new object[] { + resources.GetString("cboSchedule.Items"), + resources.GetString("cboSchedule.Items1"), + resources.GetString("cboSchedule.Items2"), + resources.GetString("cboSchedule.Items3")}); + this.cboSchedule.Name = "cboSchedule"; + this.cboSchedule.SelectedIndexChanged += new System.EventHandler(this.cboSchedule_SelectedIndexChanged); + // + // label7 + // + this.label7.AccessibleDescription = null; + this.label7.AccessibleName = null; + resources.ApplyResources(this.label7, "label7"); + this.label7.Font = null; + this.label7.Name = "label7"; + // + // label6 + // + this.label6.AccessibleDescription = null; + this.label6.AccessibleName = null; + resources.ApplyResources(this.label6, "label6"); + this.label6.Font = null; + this.label6.Name = "label6"; + // + // tabControl1 + // + this.tabControl1.AccessibleDescription = null; + this.tabControl1.AccessibleName = null; + resources.ApplyResources(this.tabControl1, "tabControl1"); + this.tabControl1.BackgroundImage = null; + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Font = null; + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + // + // tabPage1 + // + this.tabPage1.AccessibleDescription = null; + this.tabPage1.AccessibleName = null; + resources.ApplyResources(this.tabPage1, "tabPage1"); + this.tabPage1.BackgroundImage = null; + this.tabPage1.Controls.Add(this.groupBox1); + this.tabPage1.Controls.Add(this.groupBox2); + this.tabPage1.Font = null; + this.tabPage1.Name = "tabPage1"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabPage2 + // + this.tabPage2.AccessibleDescription = null; + this.tabPage2.AccessibleName = null; + resources.ApplyResources(this.tabPage2, "tabPage2"); + this.tabPage2.BackgroundImage = null; + this.tabPage2.Controls.Add(this.groupBox3); + this.tabPage2.Font = null; + this.tabPage2.Name = "tabPage2"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // panel1 + // + this.panel1.AccessibleDescription = null; + this.panel1.AccessibleName = null; + resources.ApplyResources(this.panel1, "panel1"); + this.panel1.BackColor = System.Drawing.Color.White; + this.panel1.BackgroundImage = null; + this.panel1.Controls.Add(this.label13); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.pictureBox1); + this.panel1.Font = null; + this.panel1.Name = "panel1"; + // + // label13 + // + this.label13.AccessibleDescription = null; + this.label13.AccessibleName = null; + resources.ApplyResources(this.label13, "label13"); + this.label13.Font = null; + this.label13.Name = "label13"; + // + // label3 + // + this.label3.AccessibleDescription = null; + this.label3.AccessibleName = null; + resources.ApplyResources(this.label3, "label3"); + this.label3.Name = "label3"; + // + // pictureBox1 + // + this.pictureBox1.AccessibleDescription = null; + this.pictureBox1.AccessibleName = null; + resources.ApplyResources(this.pictureBox1, "pictureBox1"); + this.pictureBox1.BackgroundImage = null; + this.pictureBox1.Font = null; + this.pictureBox1.ImageLocation = null; + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.TabStop = false; + // + // frmSchedule + // + this.AcceptButton = this.cmdOK; + this.AccessibleDescription = null; + this.AccessibleName = null; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = null; + this.CancelButton = this.cmdCancel; + this.Controls.Add(this.panel1); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.cmdOK); + this.Controls.Add(this.cmdCancel); + this.Font = null; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = null; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmSchedule"; + this.Load += new System.EventHandler(this.frmSchedule_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.grpMonth.ResumeLayout(false); + this.grpMonth.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nupMonth)).EndInit(); + this.grpOnce.ResumeLayout(false); + this.grpOnce.PerformLayout(); + this.grpDay.ResumeLayout(false); + this.grpDay.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nupDay)).EndInit(); + this.grpWeek.ResumeLayout(false); + this.grpWeek.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.nupWeek)).EndInit(); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.Button cmdCancel; + private System.Windows.Forms.Button cmdOK; + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ListView lvwDevices; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox txtDescription; + private System.Windows.Forms.Button cmdAdd; + private System.Windows.Forms.Button cmdRemove; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.DateTimePicker dtpDate; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.ComboBox cboSchedule; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label6; + private System.Windows.Forms.GroupBox grpDay; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.GroupBox grpWeek; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.CheckBox cboWeekSaturday; + private System.Windows.Forms.CheckBox cboWeekSunday; + private System.Windows.Forms.CheckBox cboWeekFriday; + private System.Windows.Forms.CheckBox cboWeekThursday; + private System.Windows.Forms.CheckBox cboWeekWednesday; + private System.Windows.Forms.CheckBox cboWeekTuesday; + private System.Windows.Forms.CheckBox cboWeekMonday; + private System.Windows.Forms.GroupBox grpMonth; + private System.Windows.Forms.CheckBox cboMonthApr; + private System.Windows.Forms.CheckBox cboMonthMar; + private System.Windows.Forms.CheckBox cboMonthFeb; + private System.Windows.Forms.CheckBox cboMonthJan; + private System.Windows.Forms.ComboBox cboMonthDays; + private System.Windows.Forms.ComboBox cboOrder; + private System.Windows.Forms.RadioButton rdbMonthThe; + private System.Windows.Forms.RadioButton rdbMonthDay; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.CheckBox cboMontDec; + private System.Windows.Forms.CheckBox cboMonthNov; + private System.Windows.Forms.CheckBox cboMontOct; + private System.Windows.Forms.CheckBox cboMontSept; + private System.Windows.Forms.CheckBox cboMonthAug; + private System.Windows.Forms.CheckBox cboMonthJuly; + private System.Windows.Forms.CheckBox cboMonthJune; + private System.Windows.Forms.CheckBox cboMonthMay; + private System.Windows.Forms.Label label12; + private System.Windows.Forms.NumericUpDown nupWeek; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Label label13; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.NumericUpDown nupDay; + private System.Windows.Forms.NumericUpDown nupMonth; + private System.Windows.Forms.DateTimePicker dtpTime; + private System.Windows.Forms.GroupBox grpOnce; + private System.Windows.Forms.Label label14; + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSchedule.cs b/scheduler/DeviceScheduler/frmSchedule.cs new file mode 100644 index 00000000..0b86d5f1 --- /dev/null +++ b/scheduler/DeviceScheduler/frmSchedule.cs @@ -0,0 +1,480 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace DeviceScheduler +{ + public partial class frmSchedule : Form + { + public frmSchedule(DataStorage data, TaskScheduler.ScheduledTasks tasks, DataStorage.JobRow job, bool newJob) + { + Localization.ChangeLanguage(); + InitializeComponent(); + m_Data = data; + m_NewJob = newJob; + m_Job = job; + m_Tasks = tasks; + } + + private DataStorage m_Data = null; + private DataStorage.JobRow m_Job = null; + private bool m_NewJob = false; + private TaskScheduler.ScheduledTasks m_Tasks = null; + private TaskScheduler.Task m_Task = null; + + private void cboSchedule_SelectedIndexChanged(object sender, EventArgs e) + { + switch (cboSchedule.SelectedIndex) + { + case 0: //Day + grpDay.Visible = true; + grpDay.Location = new Point(13, 66); + grpWeek.Visible = false; + grpOnce.Visible = false; + grpMonth.Visible = false; + break; + + case 1: //Week + grpDay.Visible = false; + grpWeek.Visible = true; + grpWeek.Location = new Point(13, 66); + grpOnce.Visible = false; + grpMonth.Visible = false; + break; + + case 2: //Month + grpDay.Visible = false; + grpWeek.Visible = false; + grpOnce.Visible = false; + grpMonth.Visible = true; + grpMonth.Location = new Point(13, 66); + break; + + case 3: //Once + grpDay.Visible = false; + grpWeek.Visible = false; + grpMonth.Visible = false; + grpOnce.Visible = true; + grpOnce.Location = new Point(13, 66); + break; + + } + } + + private void frmSchedule_Load(object sender, EventArgs e) + { + grpDay.Left = 13; + grpDay.Top = 66; + grpWeek.Left = 13; + grpWeek.Top = 66; + grpMonth.Left = 13; + grpMonth.Top = 66; + + cboSchedule.SelectedIndex = 0; + txtName.Focus(); + dtpDate.Format = DateTimePickerFormat.Custom; + dtpDate.CustomFormat = System.Globalization.CultureInfo.CurrentUICulture.DateTimeFormat.LongDatePattern; + + ShowInformation(); + } + + private void ShowInformation() + { + if (m_NewJob) + { + return; + } + + m_Task = m_Tasks.OpenTask(m_Job.Name); + + txtName.Text = m_Task.Name; + txtDescription.Text = m_Task.Comment; + + //txtTime.Text = m_Task.Triggers[0].BeginDate.Hour.ToString() + ":" + m_Task.Triggers[0].BeginDate.Minute.ToString(); + + dtpTime.Value = DateTime.Parse(m_Job.StartTime); + dtpDate.Value = m_Task.Triggers[0].BeginDate; + + if (m_Task.Triggers[0] is TaskScheduler.DailyTrigger) + { + cboSchedule.SelectedIndex = 0; + + TaskScheduler.DailyTrigger dayTrigger = (TaskScheduler.DailyTrigger)m_Task.Triggers[0]; + nupDay.Value = Convert.ToDecimal(dayTrigger.DaysInterval); + + } + else if (m_Task.Triggers[0] is TaskScheduler.WeeklyTrigger) + { + cboSchedule.SelectedIndex = 1; + + TaskScheduler.WeeklyTrigger weekTrigger = (TaskScheduler.WeeklyTrigger)m_Task.Triggers[0]; + string days = weekTrigger.WeekDays.ToString(); + + cboWeekMonday.Checked = (days.IndexOf("Monday") > -1); + cboWeekTuesday.Checked = (days.IndexOf("Tuesday") > -1); + cboWeekWednesday.Checked = (days.IndexOf("Wednesday") > -1); + cboWeekThursday.Checked = (days.IndexOf("Thursday") > -1); + cboWeekFriday.Checked = (days.IndexOf("Friday") > -1); + cboWeekSaturday.Checked = (days.IndexOf("Saturday") > -1); + cboWeekSunday.Checked = (days.IndexOf("Sunday") > -1); + + nupWeek.Value = Convert.ToDecimal(weekTrigger.WeeksInterval); + + + } + else if (m_Task.Triggers[0] is TaskScheduler.MonthlyTrigger) + { + cboSchedule.SelectedIndex = 2; + + TaskScheduler.MonthlyTrigger monthTrigger = (TaskScheduler.MonthlyTrigger)m_Task.Triggers[0]; + string months = monthTrigger.Months.ToString(); + + cboMonthJan.Checked = (months.IndexOf("January") > -1); + cboMonthFeb.Checked = (months.IndexOf("February") > -1); + cboMonthMar.Checked = (months.IndexOf("March") > -1); + cboMonthApr.Checked = (months.IndexOf("Arpil") > -1); + cboMonthMay.Checked = (months.IndexOf("May") > -1); + cboMonthJune.Checked = (months.IndexOf("June") > -1); + cboMonthJuly.Checked = (months.IndexOf("July") > -1); + cboMonthAug.Checked = (months.IndexOf("August") > -1); + cboMontSept.Checked = (months.IndexOf("September") > -1); + cboMontOct.Checked = (months.IndexOf("October") > -1); + cboMonthNov.Checked = (months.IndexOf("November") > -1); + cboMontDec.Checked = (months.IndexOf("December") > -1); + + nupMonth.Value = Convert.ToInt32(monthTrigger.Days[0]); + } + else if (m_Task.Triggers[0] is TaskScheduler.RunOnceTrigger) + { + cboSchedule.SelectedIndex = 3; + } + + foreach (DataStorage.JobActionsRow action in m_Job.GetJobActionsRows()) + { + + DeviceHandler.Device device= GetDevice(action.DeviceID); + ListViewItem item = lvwDevices.Items.Add(device.Name); + item.SubItems.Add(action.TurnOn ? Localization.GetString("uniton") : Localization.GetString("unitoff")); + + item.Tag = device; + } + + } + + private DeviceHandler.Device GetDevice(int deviceID) + { + foreach (DeviceHandler.Device item in Program.DeviceHandler.Devices) + { + if (item.ID == deviceID) + return item; + } + + return null; + } + + private bool SetInformation() + { + try + { + + if (lvwDevices.Items.Count == 0) + { + MessageBox.Show(Localization.GetString("FailedToSelectUnits"), "", + MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return false; + } + + if (txtName.Text.Length == 0) + { + MessageBox.Show(Localization.GetString("FailedToNameSchedule"), "", + MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return false; + } + + if (m_NewJob) + { + frmAskUsername frm = new frmAskUsername(); + DialogResult result=frm.ShowDialog(this); + + if (result == DialogResult.Cancel) + return false; + + m_Job = m_Data.Job.NewJobRow(); + + + string encrypted = EncryptDecrypt.Encrypt(frm.Password, "ThisIsNotParadise"); + + m_Job.Username = frm.Username; + m_Job.Password = encrypted; + + frm.Close(); + } + + string password = EncryptDecrypt.Decrypt(m_Job.Password, "ThisIsNotParadise"); + + //Set general information. + m_Job.JobName = txtName.Text; + m_Job.Name = txtName.Text; + m_Job.Description = txtDescription.Text; + + if (!m_NewJob) //Clear previous actions and add new ones. + { + foreach (DataStorage.JobActionsRow action in m_Job.GetJobActionsRows()) + { + action.Delete(); + } + } + m_Data.AcceptChanges(); + + //Add actions. + foreach (ListViewItem item in lvwDevices.Items) + { + DataStorage.JobActionsRow action = m_Data.JobActions.NewJobActionsRow(); + DeviceHandler.Device device = (DeviceHandler.Device)item.Tag; + + action.DeviceID = device.ID; + action.JobID = m_Job.ID; + + if (item.SubItems[1].Text == Localization.GetString("uniton")) + action.TurnOn = true; + else + action.TurnOn = false; + + m_Data.JobActions.AddJobActionsRow(action); + } + + TaskScheduler.Task task = null; + + //Create a new schedule in windows. + if (m_Task != null) + { + task = m_Task; + } + else + { + + task = m_Tasks.CreateTask(txtName.Text); + } + + string path = System.IO.Path.GetDirectoryName(Application.ExecutablePath); + path = System.IO.Path.Combine(path, "DeviceSchedulerAgent.exe"); + + //Clear trigger. + if(task.Triggers!=null) + task.Triggers.Clear(); + + //Set general information. + task.ApplicationName = path; + task.Parameters = m_Job.ID.ToString(); + task.Comment = txtDescription.Text; + + //Set user account information. + try + { + if (password.Length == 0) + task.SetAccountInformation(m_Job.Username, null); + else + task.SetAccountInformation(m_Job.Username, password); + } + catch (Exception e) + { + MessageBox.Show(Localization.GetString("FailedToSetPassword"), + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + //Set Telldus as creator so we can recognize the task next time. + task.Creator = "Telldus"; + + m_Job.StartTime = dtpTime.Value.Hour.ToString() + ":" + dtpTime.Value.Minute.ToString(); + + dtpTime.Value= DateTime.Parse(dtpDate.Value.ToShortDateString() + " " + dtpTime.Value.ToShortTimeString()); + + DateTime time = dtpTime.Value; + short hour = short.Parse(dtpTime.Value.Hour.ToString()); + short minute = short.Parse(dtpTime.Value.Minute.ToString()); + + short interval = 1; + + switch (cboSchedule.SelectedIndex) + { + case 0: //Dailytrigger + interval = short.Parse(nupDay.Value.ToString()); + TaskScheduler.DailyTrigger dayTrigger = new TaskScheduler.DailyTrigger(hour, minute, interval); + dayTrigger.BeginDate = dtpDate.Value; + //trigger.BeginDate.AddHours(Convert.ToDouble(dtpTime.Value.Hour)); + //trigger.BeginDate.AddMinutes(Convert.ToDouble(dtpTime.Value.Minute)); + dayTrigger.Disabled = false; + task.Triggers.Add(dayTrigger); + break; + + case 1: //Weeklytrigger + TaskScheduler.DaysOfTheWeek weekDays = 0; + interval = short.Parse(nupWeek.Value.ToString()); + + if (cboWeekMonday.Checked) + weekDays = weekDays | TaskScheduler.DaysOfTheWeek.Monday; + + if (cboWeekTuesday.Checked) + weekDays = weekDays | TaskScheduler.DaysOfTheWeek.Tuesday; + + if (cboWeekWednesday.Checked) + weekDays = weekDays | TaskScheduler.DaysOfTheWeek.Wednesday; + + if (cboWeekThursday.Checked) + weekDays = weekDays | TaskScheduler.DaysOfTheWeek.Thursday; + + if (cboWeekFriday.Checked) + weekDays = weekDays | TaskScheduler.DaysOfTheWeek.Friday; + + if (cboWeekSaturday.Checked) + weekDays = weekDays | TaskScheduler.DaysOfTheWeek.Saturday; + + if (cboWeekSunday.Checked) + weekDays = weekDays | TaskScheduler.DaysOfTheWeek.Sunday; + + TaskScheduler.WeeklyTrigger weeklyTrigger = new TaskScheduler.WeeklyTrigger(hour, minute, weekDays, interval); + time = DateTime.Parse(time.ToShortDateString()+ " " + dtpTime.Value.Hour+":"+dtpTime.Value.Minute+":00" ); + //weeklyTrigger.BeginDate = time; + //weeklyTrigger.BeginDate=weeklyTrigger.BeginDate.AddHours(Convert.ToDouble(dtpTime.Value.Hour)); + //weeklyTrigger.BeginDate=weeklyTrigger.BeginDate.AddMinutes(Convert.ToDouble(dtpTime.Value.Minute)); + task.Triggers.Add(weeklyTrigger); + break; + + case 2: //Monthlytrigger + //interval = int.Parse(nupmo + + TaskScheduler.MonthsOfTheYear months = 0; + + if (cboMonthJan.Checked) + months = months | TaskScheduler.MonthsOfTheYear.January; + + if (cboMonthFeb.Checked) + months = months | TaskScheduler.MonthsOfTheYear.February; + + if (cboMonthMar.Checked) + months = months | TaskScheduler.MonthsOfTheYear.March; + + if (cboMonthApr.Checked) + months = months | TaskScheduler.MonthsOfTheYear.April; + + if (cboMonthMay.Checked) + months = months | TaskScheduler.MonthsOfTheYear.May; + + if (cboMonthJune.Checked) + months = months | TaskScheduler.MonthsOfTheYear.June; + + if (cboMonthJuly.Checked) + months = months | TaskScheduler.MonthsOfTheYear.July; + + if (cboMonthAug.Checked) + months = months | TaskScheduler.MonthsOfTheYear.August; + + if (cboMontSept.Checked) + months = months | TaskScheduler.MonthsOfTheYear.September; + + if (cboMontOct.Checked) + months = months | TaskScheduler.MonthsOfTheYear.October; + + if (cboMonthNov.Checked) + months = months | TaskScheduler.MonthsOfTheYear.November; + + if (cboMontDec.Checked) + months = months | TaskScheduler.MonthsOfTheYear.December; + + int[] days = new int[1] { int.Parse(nupMonth.Value.ToString()) }; + TaskScheduler.MonthlyTrigger monthlyTrigger = new TaskScheduler.MonthlyTrigger(hour, minute, days, months); + monthlyTrigger.BeginDate = dtpDate.Value; + //trigger.BeginDate.AddMinutes(Convert.ToDouble(dtpTime.Value.Minute)); + task.Triggers.Add(monthlyTrigger); + break; + + case 3: + TaskScheduler.RunOnceTrigger onceTrigger = new TaskScheduler.RunOnceTrigger(dtpDate.Value); + onceTrigger.StartHour = hour; + onceTrigger.StartMinute = minute; + task.Triggers.Add(onceTrigger); + break; + } + + + task.Triggers[0].BeginDate = time; + + task.Save(); + task.Close(); + + if(m_NewJob) + m_Data.Job.AddJobRow(m_Job); + + m_Data.AcceptChanges(); + + return true; + + } + catch (Exception ex) + { + //ett ohanterat fel har uppstått i programmet. + MessageBox.Show(Localization.GetString("msg1") + Environment.NewLine + ex.Message, + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + + return false; + } + } + + private void cmdOK_Click(object sender, EventArgs e) + { + if (SetInformation()) + { + this.DialogResult = DialogResult.OK; + this.Hide(); + } + } + + private void cmdCancel_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.Cancel; + this.Hide(); + } + + private void cmdAdd_Click(object sender, EventArgs e) + { + frmScheduleAddDevice frm = new frmScheduleAddDevice(); + DialogResult result = frm.ShowDialog(this); + + + if (result == DialogResult.OK) + { + + ListViewItem item = lvwDevices.Items.Add(frm.SelectedDevice.Name); + item.SubItems.Add(frm.SelectedDeviceAction == 0 ? Localization.GetString("uniton") : Localization.GetString("unitoff")); + item.Tag = frm.SelectedDevice; + } + + frm.Close(); + } + + + private string GetActionName(int actionID) + { + return ""; + } + + private void cmdRemove_Click(object sender, EventArgs e) + { + if (lvwDevices.SelectedItems.Count == 0) { return; } + + //Vill du ta bort markerad enhet? + DialogResult result = MessageBox.Show(Localization.GetString("msg3"), + Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + lvwDevices.Items.Remove(lvwDevices.SelectedItems[0]); + } + } + + + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSchedule.en.resx b/scheduler/DeviceScheduler/frmSchedule.en.resx new file mode 100644 index 00000000..6d4b4d6b --- /dev/null +++ b/scheduler/DeviceScheduler/frmSchedule.en.resx @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Cancel + + + + 38, 13 + + + Name: + + + Unit + + + Action + + + 63, 13 + + + Description: + + + Add... + + + Remove... + + + 56, 13 + + + Start date: + + + Generall information + + + Unit(s) + + + 48, 13 + + + a month. + + + October + + + 59, 17 + + + August + + + 44, 17 + + + July + + + 49, 17 + + + June + + + 46, 17 + + + May + + + 56, 17 + + + March + + + 67, 17 + + + February + + + 63, 17 + + + January + + + Monday + + + Tuesday + + + Wednesday + + + Thursday + + + Friday + + + Saturday + + + Sunday + + + First + + + Second + + + Third + + + Fourth + + + Last + + + 44, 17 + + + The + + + 44, 17 + + + Day + + + 48, 13 + + + a month. + + + Schedule, month + + + 176, 13 + + + This schedule only runs at one time. + + + Schedule, once + + + 30, 13 + + + day. + + + 34, 13 + + + Every + + + Schedule, days + + + 50, 13 + + + :st week. + + + 34, 13 + + + Every + + + 68, 17 + + + Saturday + + + 62, 17 + + + Sunday + + + 54, 17 + + + Friday + + + 70, 17 + + + Thursday + + + 83, 17 + + + Wednesday + + + 67, 17 + + + Tuesday + + + 64, 17 + + + Monday + + + Schedule, week + + + Every day + + + Every week + + + Every month + + + Once + + + 33, 13 + + + Time: + + + 55, 13 + + + Schedule: + + + Scheduling details + + + General + + + Schedule + + + 279, 13 + + + Fill out the information below to schedule on or more units. + + + 141, 13 + + + Create a new schedule. + + + + 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 + + + + Schedule unit(s) + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSchedule.resx b/scheduler/DeviceScheduler/frmSchedule.resx new file mode 100644 index 00000000..35b1b15b --- /dev/null +++ b/scheduler/DeviceScheduler/frmSchedule.resx @@ -0,0 +1,1854 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Sista + + + 2 + + + Dag + + + System.Windows.Forms.DateTimePicker, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Oktober + + + + 306, 38 + + + + 0 + + + cboMonthFeb + + + Var + + + label10 + + + grpWeek + + + cboSchedule + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpMonth + + + Tredje + + + 9 + + + 23, 13 + + + 0 + + + 1 + + + 45, 17 + + + 19 + + + label11 + + + groupBox1 + + + groupBox3 + + + True + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpOnce + + + 1 + + + 6 + + + 15 + + + True + + + 3 + + + Torsdag + + + grpWeek + + + 7 + + + label5 + + + Ta bort... + + + 8 + + + 61, 20 + + + 61, 147 + + + 13 + + + 1 + + + grpWeek + + + 2 + + + 22, 33 + + + 328, 418 + + + cboWeekTuesday + + + groupBox3 + + + 29 + + + 22 + + + 0 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 496, 449 + + + 2 + + + 112, 30 + + + 13 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Microsoft Sans Serif, 8.25pt, style=Bold + + + 17 + + + 31 + + + cboMonthAug + + + Mars + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpMonth + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + 0 + + + panel1 + + + 297, 98 + + + grpMonth + + + 30 + + + cmdCancel + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpWeek + + + tabControl1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 14 + + + MÃ¥ndag + + + 61, 113 + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 51, 20 + + + grpWeek + + + Andra + + + grpDay + + + Söndag + + + cboWeekMonday + + + groupBox3 + + + 1 + + + 0 + + + 11 + + + 3 + + + 4, 22 + + + 3 + + + 14 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + label12 + + + 64, 17 + + + 131, 129 + + + 18 + + + 19 + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBox1 + + + cboMonthMar + + + 69, 13 + + + grpMonth + + + 12, 12 + + + lvwDevices + + + 173, 19 + + + 1 + + + 131, 165 + + + False + + + label13 + + + 3 + + + 5 + + + 131, 113 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 394, 190 + + + label8 + + + 134 + + + 12 + + + grpWeek + + + 6 + + + True + + + 4 + + + 137 + + + 14 + + + True + + + varje vecka + + + $this + + + grpMonth + + + groupBox2 + + + 65, 13 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 59, 13 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 155, 20 + + + 7 + + + 77, 17 + + + 15, 19 + + + 55, 30 + + + True + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 16 + + + 2 + + + Onsdag + + + 93, 21 + + + grpMonth + + + 173, 51 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 173, 83 + + + 12 + + + 32 + + + Tisdag + + + 1 + + + 7 + + + cboMontOct + + + 59, 13 + + + True + + + columnHeader1 + + + 59, 17 + + + 14 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 18 + + + 314, 13 + + + $this + + + 23, 15 + + + 7 + + + + 3, 3, 3, 3 + + + 46, 17 + + + System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + December + + + 5 + + + 8 + + + nupMonth + + + grpMonth + + + txtName + + + 0 + + + 4 + + + True + + + 90, 54 + + + 0, 0 + + + 4 + + + 0 + + + 318, 19 + + + grpWeek + + + True + + + System.Windows.Forms.TabPage, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 514, 74 + + + 40, 13 + + + 9 + + + panel1 + + + nupWeek + + + 15 + + + Generellt + + + 225, 20 + + + 21 + + + Tisdag + + + 75, 23 + + + AutoSize + + + 59, 27 + + + cboWeekThursday + + + Lördag + + + 159, 65 + + + True + + + label6 + + + cboMonthMay + + + 75, 23 + + + 394, 190 + + + label9 + + + Maj + + + rdbMonthThe + + + Fjärde + + + 18 + + + Fredag + + + grpWeek + + + cboMonthJuly + + + 201, 113 + + + Vertical + + + cboWeekFriday + + + True + + + 13 + + + 60, 65 + + + grpDay + + + 61, 21 + + + tabControl1 + + + 8, 65 + + + 61, 17 + + + Söndag + + + En gÃ¥ng + + + True + + + Fyll i uppgifterna nedan för att schemalägga en eller flera enheter. + + + 131, 147 + + + 258, 69 + + + 8 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + cboMonthJan + + + 420, 270 + + + 19, 136 + + + True + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + cboMontSept + + + System.Windows.Forms.ListView, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpWeek + + + 5 + + + True + + + 1 + + + 24 + + + Tid: + + + Generell information + + + Denna schemaläggning körs enbart vid valt tillfälle. + + + groupBox2 + + + True + + + 12, 80 + + + 451, 36 + + + 13 + + + 61, 129 + + + 0 + + + Avbryt + + + cboOrder + + + 0 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.DateTimePicker, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Enhet(er) + + + 49, 17 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Var + + + 75, 17 + + + 3 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 45, 17 + + + 415, 110 + + + True + + + Schemaläggning, en gÃ¥ng + + + True + + + True + + + cmdRemove + + + 17 + + + 1 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 15, 60 + + + 201, 165 + + + Skapa en ny schemaläggning. + + + 75, 17 + + + 12 + + + 412, 134 + + + 3 + + + 2 + + + label2 + + + True + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 141, 20 + + + $this + + + 144, 36 + + + 65, 17 + + + cmdOK + + + 246, 13 + + + cboMonthDays + + + 16, 32 + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 16, 20 + + + panel1 + + + 173, 66 + + + groupBox3 + + + 90, 28 + + + 10 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 20 + + + groupBox3 + + + 0 + + + True + + + 16, 23 + + + 58, 17 + + + grpOnce + + + 23, 13 + + + 13 + + + True + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Lägg till... + + + Schemalägg enhet(er) + + + tabControl1 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + September + + + Schemaläggning, vecka + + + 14 + + + groupBox3 + + + 18 + + + True + + + 1 + + + label3 + + + 2 + + + 15 + + + 10, 20 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 2 + + + nupDay + + + panel1 + + + System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 75, 23 + + + True + + + 9 + + + frmSchedule + + + 109, 23 + + + grpMonth + + + 201, 129 + + + Schemaläggning + + + dtpDate + + + 4, 22 + + + Onsdag + + + 173, 35 + + + 244, 19 + + + 48, 20 + + + 113, 21 + + + Ã…tgärd + + + 244, 35 + + + i mÃ¥naden. + + + 61, 165 + + + cboMonthApr + + + grpMonth + + + 3 + + + 3 + + + System.Windows.Forms.RadioButton, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage1 + + + tabPage2 + + + tabPage1 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 15, 31 + + + groupBox2 + + + 16, 36 + + + 27 + + + dtpTime + + + 16 + + + 201, 147 + + + label1 + + + 43, 17 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + cboMontDec + + + Benämning: + + + Schemaläggnings detaljer + + + 109, 32 + + + Första + + + 13, 66 + + + 474, 330 + + + True + + + True + + + grpMonth + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 25 + + + 63, 13 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + grpWeek + + + txtDescription + + + 14, 281 + + + groupBox1 + + + 451, 232 + + + grpMonth + + + 0 + + + grpMonth + + + 394, 190 + + + 93, 21 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 60, 17 + + + Schemaläggning, mÃ¥nad + + + 63, 17 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Lördag + + + Startdatum: + + + 9 + + + True + + + 466, 304 + + + 48, 48 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + grpMonth + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + HH:mm + + + 8, 27 + + + cboMonthNov + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + 13, 36 + + + 65, 17 + + + columnHeader2 + + + grpMonth + + + 1 + + + grpDay + + + 16 + + + 3, 3, 3, 3 + + + groupBox3 + + + 11 + + + grpMonth + + + Enhet + + + 8 + + + 25, 13 + + + groupBox1 + + + 0 + + + Schemaläggning, dagar + + + Juli + + + MÃ¥ndag + + + 393, 190 + + + 14 + + + 15 + + + Schemalägg: + + + 28 + + + :e dag. + + + 42, 20 + + + 409, 418 + + + cboWeekSunday + + + grpMonth + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + November + + + False + + + 2 + + + True + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + cboMonthJune + + + Fredag + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 0 + + + groupBox1 + + + cboWeekWednesday + + + 9 + + + 1 + + + 8 + + + groupBox3 + + + groupBox3 + + + 10 + + + Den + + + 4 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 318, 48 + + + 75, 23 + + + cboWeekSaturday + + + Augusti + + + 466, 304 + + + label4 + + + 177, 13 + + + 306, 20 + + + Varje dag + + + 6, 13 + + + label14 + + + 1 + + + 417, 12 + + + True + + + 15 + + + grpWeek + + + Beskrivning: + + + 26 + + + grpMonth + + + cmdAdd + + + varje mÃ¥nad + + + groupBox2 + + + Februari + + + groupBox3 + + + 6 + + + CenterParent + + + grpDay + + + 4 + + + Juni + + + Januari + + + 64, 17 + + + 61, 13 + + + $this + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 16 + + + 23 + + + 6 + + + 2 + + + :e vecka. + + + tabPage2 + + + i mÃ¥naden. + + + grpMonth + + + 1 + + + Torsdag + + + 1 + + + System.Windows.Forms.TabControl, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + tabPage1 + + + groupBox3 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 52, 13 + + + 0 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + grpMonth + + + + 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 + + + + 228, 36 + + + 17 + + + grpMonth + + + 2 + + + April + + + 63, 17 + + + True + + + True + + + pictureBox1 + + + 45, 17 + + + 41, 17 + + + True + + + 59, 17 + + + rdbMonthDay + + + False + + + OK + + + True + + + label7 + + + True + + + English + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSchedule.sv.resx b/scheduler/DeviceScheduler/frmSchedule.sv.resx new file mode 100644 index 00000000..bc82abac --- /dev/null +++ b/scheduler/DeviceScheduler/frmSchedule.sv.resx @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + 59, 17 + + + Lördag + + + 63, 17 + + + Söndag + + + + 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 + + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmScheduleAddDevice.Designer.cs b/scheduler/DeviceScheduler/frmScheduleAddDevice.Designer.cs new file mode 100644 index 00000000..bc1d0ec8 --- /dev/null +++ b/scheduler/DeviceScheduler/frmScheduleAddDevice.Designer.cs @@ -0,0 +1,156 @@ +namespace DeviceScheduler +{ + partial class frmScheduleAddDevice + { + /// + /// 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() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmScheduleAddDevice)); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.cboDevices = new System.Windows.Forms.ComboBox(); + this.cboAction = new System.Windows.Forms.ComboBox(); + this.cmdOK = new System.Windows.Forms.Button(); + this.cmdCancel = new System.Windows.Forms.Button(); + this.groupBox1.SuspendLayout(); + this.SuspendLayout(); + // + // groupBox1 + // + this.groupBox1.AccessibleDescription = null; + this.groupBox1.AccessibleName = null; + resources.ApplyResources(this.groupBox1, "groupBox1"); + this.groupBox1.BackgroundImage = null; + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.cboDevices); + this.groupBox1.Controls.Add(this.cboAction); + this.groupBox1.Font = null; + this.groupBox1.Name = "groupBox1"; + this.groupBox1.TabStop = false; + // + // label1 + // + this.label1.AccessibleDescription = null; + this.label1.AccessibleName = null; + resources.ApplyResources(this.label1, "label1"); + this.label1.Font = null; + this.label1.Name = "label1"; + // + // label2 + // + this.label2.AccessibleDescription = null; + this.label2.AccessibleName = null; + resources.ApplyResources(this.label2, "label2"); + this.label2.Font = null; + this.label2.Name = "label2"; + this.label2.Click += new System.EventHandler(this.label2_Click); + // + // cboDevices + // + this.cboDevices.AccessibleDescription = null; + this.cboDevices.AccessibleName = null; + resources.ApplyResources(this.cboDevices, "cboDevices"); + this.cboDevices.BackgroundImage = null; + this.cboDevices.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboDevices.Font = null; + this.cboDevices.FormattingEnabled = true; + this.cboDevices.Name = "cboDevices"; + // + // cboAction + // + this.cboAction.AccessibleDescription = null; + this.cboAction.AccessibleName = null; + resources.ApplyResources(this.cboAction, "cboAction"); + this.cboAction.BackgroundImage = null; + this.cboAction.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cboAction.Font = null; + this.cboAction.FormattingEnabled = true; + this.cboAction.Items.AddRange(new object[] { + resources.GetString("cboAction.Items"), + resources.GetString("cboAction.Items1")}); + this.cboAction.Name = "cboAction"; + // + // cmdOK + // + this.cmdOK.AccessibleDescription = null; + this.cmdOK.AccessibleName = null; + resources.ApplyResources(this.cmdOK, "cmdOK"); + this.cmdOK.BackgroundImage = null; + this.cmdOK.Font = null; + this.cmdOK.Name = "cmdOK"; + this.cmdOK.UseVisualStyleBackColor = true; + this.cmdOK.Click += new System.EventHandler(this.cmdOK_Click); + // + // cmdCancel + // + this.cmdCancel.AccessibleDescription = null; + this.cmdCancel.AccessibleName = null; + resources.ApplyResources(this.cmdCancel, "cmdCancel"); + this.cmdCancel.BackgroundImage = null; + this.cmdCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.cmdCancel.Font = null; + this.cmdCancel.Name = "cmdCancel"; + this.cmdCancel.UseVisualStyleBackColor = true; + this.cmdCancel.Click += new System.EventHandler(this.cmdCancel_Click); + // + // frmScheduleAddDevice + // + this.AcceptButton = this.cmdOK; + this.AccessibleDescription = null; + this.AccessibleName = null; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = null; + this.CancelButton = this.cmdCancel; + this.Controls.Add(this.cmdCancel); + this.Controls.Add(this.cmdOK); + this.Controls.Add(this.groupBox1); + this.Font = null; + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Icon = null; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "frmScheduleAddDevice"; + this.Load += new System.EventHandler(this.frmScheduleAddDevice_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox cboDevices; + private System.Windows.Forms.ComboBox cboAction; + private System.Windows.Forms.Button cmdOK; + private System.Windows.Forms.Button cmdCancel; + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmScheduleAddDevice.cs b/scheduler/DeviceScheduler/frmScheduleAddDevice.cs new file mode 100644 index 00000000..50776c17 --- /dev/null +++ b/scheduler/DeviceScheduler/frmScheduleAddDevice.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace DeviceScheduler +{ + public partial class frmScheduleAddDevice : Form + { + public frmScheduleAddDevice() + { + Localization.ChangeLanguage(); + InitializeComponent(); + + } + + + private void frmScheduleAddDevice_Load(object sender, EventArgs e) + { + //Fill the combobox with Devices + FillCombo(); + + //Preselect device and action + cboDevices.SelectedIndex = 0; + cboAction.SelectedIndex = 0; + } + + private void FillCombo() + { + Program.DeviceHandler.Load(); + + foreach (DeviceHandler.Device item in Program.DeviceHandler.Devices) + { + cboDevices.Items.Add(item); + } + } + + private void cmdOK_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.OK; + this.Hide(); + } + + private void cmdCancel_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.Cancel; + this.Hide(); + } + + public DeviceHandler.Device SelectedDevice + { + get + { return (DeviceHandler.Device)cboDevices.SelectedItem;} + } + + public int SelectedDeviceAction + { + get + { return cboAction.SelectedIndex;} + } + + private void label2_Click(object sender, EventArgs e) + { + + } + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmScheduleAddDevice.en.resx b/scheduler/DeviceScheduler/frmScheduleAddDevice.en.resx new file mode 100644 index 00000000..47aed2b1 --- /dev/null +++ b/scheduler/DeviceScheduler/frmScheduleAddDevice.en.resx @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + 29, 13 + + + Unit: + + + 40, 13 + + + Action: + + + On + + + Off + + + Choose a unit to add + + + Cancel + + + Add unit + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmScheduleAddDevice.resx b/scheduler/DeviceScheduler/frmScheduleAddDevice.resx new file mode 100644 index 00000000..8545a3a0 --- /dev/null +++ b/scheduler/DeviceScheduler/frmScheduleAddDevice.resx @@ -0,0 +1,321 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + + 72, 30 + + + label2 + + + Ã…tgärd: + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Avbryt + + + cboAction + + + cmdCancel + + + 0 + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 75, 23 + + + 38, 13 + + + groupBox1 + + + 12, 12 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + True + + + 2 + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Enhet: + + + 72, 57 + + + 6 + + + 187, 21 + + + 2 + + + 290, 16 + + + 0 + + + 0 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 1 + + + groupBox1 + + + groupBox1 + + + $this + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 16, 60 + + + $this + + + PÃ¥ + + + 4 + + + 75, 23 + + + 373, 112 + + + 272, 90 + + + $this + + + 16, 33 + + + label1 + + + 1 + + + 1 + + + Av + + + 5 + + + Lägg till enhet + + + 290, 45 + + + groupBox1 + + + 3 + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Välj den enhet som skall läggas till + + + + CenterParent + + + OK + + + groupBox1 + + + 6, 13 + + + cboDevices + + + 3 + + + frmScheduleAddDevice + + + 41, 13 + + + cmdOK + + + 2 + + + 187, 21 + + + True + + + English + + \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSelectDevice.Designer.cs b/scheduler/DeviceScheduler/frmSelectDevice.Designer.cs new file mode 100644 index 00000000..f9f4c388 --- /dev/null +++ b/scheduler/DeviceScheduler/frmSelectDevice.Designer.cs @@ -0,0 +1,100 @@ +namespace DeviceScheduler +{ + partial class frmSelectDevice + { + /// + /// 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.listView1 = new System.Windows.Forms.ListView(); + this.columnHeader1 = new System.Windows.Forms.ColumnHeader(); + this.columnHeader2 = new System.Windows.Forms.ColumnHeader(); + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // listView1 + // + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.listView1.Location = new System.Drawing.Point(12, 12); + this.listView1.Name = "listView1"; + this.listView1.Size = new System.Drawing.Size(333, 166); + this.listView1.TabIndex = 5; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Device"; + this.columnHeader1.Width = 168; + // + // columnHeader2 + // + this.columnHeader2.Text = "Action"; + this.columnHeader2.Width = 135; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(351, 12); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(75, 23); + this.button1.TabIndex = 6; + this.button1.Text = "OK"; + this.button1.UseVisualStyleBackColor = true; + // + // button2 + // + this.button2.Location = new System.Drawing.Point(351, 41); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(75, 23); + this.button2.TabIndex = 7; + this.button2.Text = "Cancel"; + this.button2.UseVisualStyleBackColor = true; + // + // frmSelectDevice + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(435, 190); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); + this.Controls.Add(this.listView1); + this.Name = "frmSelectDevice"; + this.Text = "frmSelectDevice"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.ListView listView1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSelectDevice.cs b/scheduler/DeviceScheduler/frmSelectDevice.cs new file mode 100644 index 00000000..29a6b008 --- /dev/null +++ b/scheduler/DeviceScheduler/frmSelectDevice.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace DeviceScheduler +{ + public partial class frmSelectDevice : Form + { + public frmSelectDevice() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSelectDevice.resx b/scheduler/DeviceScheduler/frmSelectDevice.resx new file mode 100644 index 00000000..ff31a6db --- /dev/null +++ b/scheduler/DeviceScheduler/frmSelectDevice.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/scheduler/DeviceScheduler/frmSplash.Designer.cs b/scheduler/DeviceScheduler/frmSplash.Designer.cs new file mode 100644 index 00000000..d2ed6504 --- /dev/null +++ b/scheduler/DeviceScheduler/frmSplash.Designer.cs @@ -0,0 +1,99 @@ +namespace DeviceScheduler +{ + partial class frmSplash + { + /// + /// 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(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmSplash)); + this.label3 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.lblVersion = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.BackColor = System.Drawing.Color.Transparent; + this.label3.Location = new System.Drawing.Point(114, 280); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(341, 13); + this.label3.TabIndex = 6; + this.label3.Text = "© Copyright Telldus Technologies AB 2007. Alla rättigheter förbehålles."; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Location = new System.Drawing.Point(242, 195); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(45, 13); + this.label1.TabIndex = 7; + this.label1.Text = "Version:"; + // + // timer1 + // + this.timer1.Interval = 1500; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // lblVersion + // + this.lblVersion.AutoSize = true; + this.lblVersion.BackColor = System.Drawing.Color.Transparent; + this.lblVersion.Location = new System.Drawing.Point(293, 195); + this.lblVersion.Name = "lblVersion"; + this.lblVersion.Size = new System.Drawing.Size(45, 13); + this.lblVersion.TabIndex = 8; + this.lblVersion.Text = "Version:"; + // + // frmSplash + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage"))); + this.ClientSize = new System.Drawing.Size(522, 300); + this.Controls.Add(this.lblVersion); + this.Controls.Add(this.label1); + this.Controls.Add(this.label3); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.Name = "frmSplash"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Load += new System.EventHandler(this.frmSplash_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.Label lblVersion; + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSplash.cs b/scheduler/DeviceScheduler/frmSplash.cs new file mode 100644 index 00000000..8e8b5cf8 --- /dev/null +++ b/scheduler/DeviceScheduler/frmSplash.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; +using System.Reflection; + +namespace DeviceScheduler +{ + public partial class frmSplash : Form + { + public frmSplash() + { + InitializeComponent(); + } + + private void timer1_Tick(object sender, EventArgs e) + { + + timer1.Enabled = false; + Cursor = Cursors.Default; + this.Hide(); + + } + + private void frmSplash_Load(object sender, EventArgs e) + { + Cursor = Cursors.WaitCursor; + lblVersion.Text = AssemblyVersion; + timer1.Enabled = true; + } + public string AssemblyVersion + { + get + { + return Assembly.GetExecutingAssembly().GetName().Version.ToString(); + } + } + + } +} \ No newline at end of file diff --git a/scheduler/DeviceScheduler/frmSplash.resx b/scheduler/DeviceScheduler/frmSplash.resx new file mode 100644 index 00000000..3d25f107 --- /dev/null +++ b/scheduler/DeviceScheduler/frmSplash.resx @@ -0,0 +1,900 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 17, 17 + + + + + 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 + + + \ No newline at end of file diff --git a/scheduler/DeviceSchedulerAgent/DataStorage.Designer.cs b/scheduler/DeviceSchedulerAgent/DataStorage.Designer.cs new file mode 100644 index 00000000..8e1e78d2 --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/DataStorage.Designer.cs @@ -0,0 +1,1050 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:2.0.50727.312 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +#pragma warning disable 1591 + +namespace DeviceSchedulerAgent { + using System; + + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [Serializable()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.ComponentModel.ToolboxItem(true)] + [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedDataSetSchema")] + [System.Xml.Serialization.XmlRootAttribute("DataStorage")] + [System.ComponentModel.Design.HelpKeywordAttribute("vs.data.DataSet")] + public partial class DataStorage : System.Data.DataSet { + + private JobDataTable tableJob; + + private JobActionsDataTable tableJobActions; + + private System.Data.DataRelation relationJob_JobActions; + + private System.Data.SchemaSerializationMode _schemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public DataStorage() { + this.BeginInit(); + this.InitClass(); + System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + base.Tables.CollectionChanged += schemaChangedHandler; + base.Relations.CollectionChanged += schemaChangedHandler; + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected DataStorage(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context, false) { + if ((this.IsBinarySerialized(info, context) == true)) { + this.InitVars(false); + System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler1 = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + this.Tables.CollectionChanged += schemaChangedHandler1; + this.Relations.CollectionChanged += schemaChangedHandler1; + return; + } + string strSchema = ((string)(info.GetValue("XmlSchema", typeof(string)))); + if ((this.DetermineSchemaSerializationMode(info, context) == System.Data.SchemaSerializationMode.IncludeSchema)) { + System.Data.DataSet ds = new System.Data.DataSet(); + ds.ReadXmlSchema(new System.Xml.XmlTextReader(new System.IO.StringReader(strSchema))); + if ((ds.Tables["Job"] != null)) { + base.Tables.Add(new JobDataTable(ds.Tables["Job"])); + } + if ((ds.Tables["JobActions"] != null)) { + base.Tables.Add(new JobActionsDataTable(ds.Tables["JobActions"])); + } + this.DataSetName = ds.DataSetName; + this.Prefix = ds.Prefix; + this.Namespace = ds.Namespace; + this.Locale = ds.Locale; + this.CaseSensitive = ds.CaseSensitive; + this.EnforceConstraints = ds.EnforceConstraints; + this.Merge(ds, false, System.Data.MissingSchemaAction.Add); + this.InitVars(); + } + else { + this.ReadXmlSchema(new System.Xml.XmlTextReader(new System.IO.StringReader(strSchema))); + } + this.GetSerializationData(info, context); + System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + base.Tables.CollectionChanged += schemaChangedHandler; + this.Relations.CollectionChanged += schemaChangedHandler; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)] + public JobDataTable Job { + get { + return this.tableJob; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)] + public JobActionsDataTable JobActions { + get { + return this.tableJobActions; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.BrowsableAttribute(true)] + [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Visible)] + public override System.Data.SchemaSerializationMode SchemaSerializationMode { + get { + return this._schemaSerializationMode; + } + set { + this._schemaSerializationMode = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new System.Data.DataTableCollection Tables { + get { + return base.Tables; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new System.Data.DataRelationCollection Relations { + get { + return base.Relations; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void InitializeDerivedDataSet() { + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override System.Data.DataSet Clone() { + DataStorage cln = ((DataStorage)(base.Clone())); + cln.InitVars(); + cln.SchemaSerializationMode = this.SchemaSerializationMode; + return cln; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override bool ShouldSerializeTables() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override bool ShouldSerializeRelations() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void ReadXmlSerializable(System.Xml.XmlReader reader) { + if ((this.DetermineSchemaSerializationMode(reader) == System.Data.SchemaSerializationMode.IncludeSchema)) { + this.Reset(); + System.Data.DataSet ds = new System.Data.DataSet(); + ds.ReadXml(reader); + if ((ds.Tables["Job"] != null)) { + base.Tables.Add(new JobDataTable(ds.Tables["Job"])); + } + if ((ds.Tables["JobActions"] != null)) { + base.Tables.Add(new JobActionsDataTable(ds.Tables["JobActions"])); + } + this.DataSetName = ds.DataSetName; + this.Prefix = ds.Prefix; + this.Namespace = ds.Namespace; + this.Locale = ds.Locale; + this.CaseSensitive = ds.CaseSensitive; + this.EnforceConstraints = ds.EnforceConstraints; + this.Merge(ds, false, System.Data.MissingSchemaAction.Add); + this.InitVars(); + } + else { + this.ReadXml(reader); + this.InitVars(); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Xml.Schema.XmlSchema GetSchemaSerializable() { + System.IO.MemoryStream stream = new System.IO.MemoryStream(); + this.WriteXmlSchema(new System.Xml.XmlTextWriter(stream, null)); + stream.Position = 0; + return System.Xml.Schema.XmlSchema.Read(new System.Xml.XmlTextReader(stream), null); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.InitVars(true); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars(bool initTable) { + this.tableJob = ((JobDataTable)(base.Tables["Job"])); + if ((initTable == true)) { + if ((this.tableJob != null)) { + this.tableJob.InitVars(); + } + } + this.tableJobActions = ((JobActionsDataTable)(base.Tables["JobActions"])); + if ((initTable == true)) { + if ((this.tableJobActions != null)) { + this.tableJobActions.InitVars(); + } + } + this.relationJob_JobActions = this.Relations["Job_JobActions"]; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.DataSetName = "DataStorage"; + this.Prefix = ""; + this.Namespace = "http://tempuri.org/DataStorage.xsd"; + this.EnforceConstraints = true; + this.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; + this.tableJob = new JobDataTable(); + base.Tables.Add(this.tableJob); + this.tableJobActions = new JobActionsDataTable(); + base.Tables.Add(this.tableJobActions); + this.relationJob_JobActions = new System.Data.DataRelation("Job_JobActions", new System.Data.DataColumn[] { + this.tableJob.IDColumn}, new System.Data.DataColumn[] { + this.tableJobActions.JobIDColumn}, false); + this.Relations.Add(this.relationJob_JobActions); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private bool ShouldSerializeJob() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private bool ShouldSerializeJobActions() { + return false; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void SchemaChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e) { + if ((e.Action == System.ComponentModel.CollectionChangeAction.Remove)) { + this.InitVars(); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static System.Xml.Schema.XmlSchemaComplexType GetTypedDataSetSchema(System.Xml.Schema.XmlSchemaSet xs) { + DataStorage ds = new DataStorage(); + System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); + System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + xs.Add(ds.GetSchemaSerializable()); + System.Xml.Schema.XmlSchemaAny any = new System.Xml.Schema.XmlSchemaAny(); + any.Namespace = ds.Namespace; + sequence.Items.Add(any); + type.Particle = sequence; + return type; + } + + public delegate void JobRowChangeEventHandler(object sender, JobRowChangeEvent e); + + public delegate void JobActionsRowChangeEventHandler(object sender, JobActionsRowChangeEvent e); + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [System.Serializable()] + [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] + public partial class JobDataTable : System.Data.DataTable, System.Collections.IEnumerable { + + private System.Data.DataColumn columnID; + + private System.Data.DataColumn columnName; + + private System.Data.DataColumn columnDescription; + + private System.Data.DataColumn columnJobName; + + private System.Data.DataColumn columnStartTime; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobDataTable() { + this.TableName = "Job"; + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobDataTable(System.Data.DataTable table) { + this.TableName = table.TableName; + if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { + this.CaseSensitive = table.CaseSensitive; + } + if ((table.Locale.ToString() != table.DataSet.Locale.ToString())) { + this.Locale = table.Locale; + } + if ((table.Namespace != table.DataSet.Namespace)) { + this.Namespace = table.Namespace; + } + this.Prefix = table.Prefix; + this.MinimumCapacity = table.MinimumCapacity; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected JobDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + this.InitVars(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn IDColumn { + get { + return this.columnID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn NameColumn { + get { + return this.columnName; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn DescriptionColumn { + get { + return this.columnDescription; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn JobNameColumn { + get { + return this.columnJobName; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn StartTimeColumn { + get { + return this.columnStartTime; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + public int Count { + get { + return this.Rows.Count; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow this[int index] { + get { + return ((JobRow)(this.Rows[index])); + } + } + + public event JobRowChangeEventHandler JobRowChanging; + + public event JobRowChangeEventHandler JobRowChanged; + + public event JobRowChangeEventHandler JobRowDeleting; + + public event JobRowChangeEventHandler JobRowDeleted; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void AddJobRow(JobRow row) { + this.Rows.Add(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow AddJobRow(string Name, string Description, string JobName, string StartTime) { + JobRow rowJobRow = ((JobRow)(this.NewRow())); + rowJobRow.ItemArray = new object[] { + null, + Name, + Description, + JobName, + StartTime}; + this.Rows.Add(rowJobRow); + return rowJobRow; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow FindByID(int ID) { + return ((JobRow)(this.Rows.Find(new object[] { + ID}))); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public virtual System.Collections.IEnumerator GetEnumerator() { + return this.Rows.GetEnumerator(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override System.Data.DataTable Clone() { + JobDataTable cln = ((JobDataTable)(base.Clone())); + cln.InitVars(); + return cln; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataTable CreateInstance() { + return new JobDataTable(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.columnID = base.Columns["ID"]; + this.columnName = base.Columns["Name"]; + this.columnDescription = base.Columns["Description"]; + this.columnJobName = base.Columns["JobName"]; + this.columnStartTime = base.Columns["StartTime"]; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.columnID = new System.Data.DataColumn("ID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnID); + this.columnName = new System.Data.DataColumn("Name", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnName); + this.columnDescription = new System.Data.DataColumn("Description", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnDescription); + this.columnJobName = new System.Data.DataColumn("JobName", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnJobName); + this.columnStartTime = new System.Data.DataColumn("StartTime", typeof(string), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnStartTime); + this.Constraints.Add(new System.Data.UniqueConstraint("JobKey1", new System.Data.DataColumn[] { + this.columnID}, true)); + this.columnID.AutoIncrement = true; + this.columnID.AutoIncrementSeed = 1; + this.columnID.AllowDBNull = false; + this.columnID.Unique = true; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow NewJobRow() { + return ((JobRow)(this.NewRow())); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataRow NewRowFromBuilder(System.Data.DataRowBuilder builder) { + return new JobRow(builder); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Type GetRowType() { + return typeof(JobRow); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanged(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanged(e); + if ((this.JobRowChanged != null)) { + this.JobRowChanged(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanging(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanging(e); + if ((this.JobRowChanging != null)) { + this.JobRowChanging(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleted(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleted(e); + if ((this.JobRowDeleted != null)) { + this.JobRowDeleted(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleting(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleting(e); + if ((this.JobRowDeleting != null)) { + this.JobRowDeleting(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void RemoveJobRow(JobRow row) { + this.Rows.Remove(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(System.Xml.Schema.XmlSchemaSet xs) { + System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); + System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + DataStorage ds = new DataStorage(); + xs.Add(ds.GetSchemaSerializable()); + System.Xml.Schema.XmlSchemaAny any1 = new System.Xml.Schema.XmlSchemaAny(); + any1.Namespace = "http://www.w3.org/2001/XMLSchema"; + any1.MinOccurs = new decimal(0); + any1.MaxOccurs = decimal.MaxValue; + any1.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any1); + System.Xml.Schema.XmlSchemaAny any2 = new System.Xml.Schema.XmlSchemaAny(); + any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; + any2.MinOccurs = new decimal(1); + any2.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any2); + System.Xml.Schema.XmlSchemaAttribute attribute1 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute1.Name = "namespace"; + attribute1.FixedValue = ds.Namespace; + type.Attributes.Add(attribute1); + System.Xml.Schema.XmlSchemaAttribute attribute2 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute2.Name = "tableTypeName"; + attribute2.FixedValue = "JobDataTable"; + type.Attributes.Add(attribute2); + type.Particle = sequence; + return type; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [System.Serializable()] + [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] + public partial class JobActionsDataTable : System.Data.DataTable, System.Collections.IEnumerable { + + private System.Data.DataColumn columnID; + + private System.Data.DataColumn columnJobID; + + private System.Data.DataColumn columnDeviceID; + + private System.Data.DataColumn columnTurnOn; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsDataTable() { + this.TableName = "JobActions"; + this.BeginInit(); + this.InitClass(); + this.EndInit(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobActionsDataTable(System.Data.DataTable table) { + this.TableName = table.TableName; + if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { + this.CaseSensitive = table.CaseSensitive; + } + if ((table.Locale.ToString() != table.DataSet.Locale.ToString())) { + this.Locale = table.Locale; + } + if ((table.Namespace != table.DataSet.Namespace)) { + this.Namespace = table.Namespace; + } + this.Prefix = table.Prefix; + this.MinimumCapacity = table.MinimumCapacity; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected JobActionsDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + base(info, context) { + this.InitVars(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn IDColumn { + get { + return this.columnID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn JobIDColumn { + get { + return this.columnJobID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn DeviceIDColumn { + get { + return this.columnDeviceID; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataColumn TurnOnColumn { + get { + return this.columnTurnOn; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [System.ComponentModel.Browsable(false)] + public int Count { + get { + return this.Rows.Count; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow this[int index] { + get { + return ((JobActionsRow)(this.Rows[index])); + } + } + + public event JobActionsRowChangeEventHandler JobActionsRowChanging; + + public event JobActionsRowChangeEventHandler JobActionsRowChanged; + + public event JobActionsRowChangeEventHandler JobActionsRowDeleting; + + public event JobActionsRowChangeEventHandler JobActionsRowDeleted; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void AddJobActionsRow(JobActionsRow row) { + this.Rows.Add(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow AddJobActionsRow(JobRow parentJobRowByJob_JobActions, int DeviceID, bool TurnOn) { + JobActionsRow rowJobActionsRow = ((JobActionsRow)(this.NewRow())); + rowJobActionsRow.ItemArray = new object[] { + null, + parentJobRowByJob_JobActions[0], + DeviceID, + TurnOn}; + this.Rows.Add(rowJobActionsRow); + return rowJobActionsRow; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow FindByID(int ID) { + return ((JobActionsRow)(this.Rows.Find(new object[] { + ID}))); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public virtual System.Collections.IEnumerator GetEnumerator() { + return this.Rows.GetEnumerator(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override System.Data.DataTable Clone() { + JobActionsDataTable cln = ((JobActionsDataTable)(base.Clone())); + cln.InitVars(); + return cln; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataTable CreateInstance() { + return new JobActionsDataTable(); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal void InitVars() { + this.columnID = base.Columns["ID"]; + this.columnJobID = base.Columns["JobID"]; + this.columnDeviceID = base.Columns["DeviceID"]; + this.columnTurnOn = base.Columns["TurnOn"]; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void InitClass() { + this.columnID = new System.Data.DataColumn("ID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnID); + this.columnJobID = new System.Data.DataColumn("JobID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnJobID); + this.columnDeviceID = new System.Data.DataColumn("DeviceID", typeof(int), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnDeviceID); + this.columnTurnOn = new System.Data.DataColumn("TurnOn", typeof(bool), null, System.Data.MappingType.Element); + base.Columns.Add(this.columnTurnOn); + this.Constraints.Add(new System.Data.UniqueConstraint("JobActionsKey1", new System.Data.DataColumn[] { + this.columnID}, true)); + this.columnID.AutoIncrement = true; + this.columnID.AutoIncrementSeed = 1; + this.columnID.AllowDBNull = false; + this.columnID.Unique = true; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow NewJobActionsRow() { + return ((JobActionsRow)(this.NewRow())); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Data.DataRow NewRowFromBuilder(System.Data.DataRowBuilder builder) { + return new JobActionsRow(builder); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override System.Type GetRowType() { + return typeof(JobActionsRow); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanged(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanged(e); + if ((this.JobActionsRowChanged != null)) { + this.JobActionsRowChanged(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanging(System.Data.DataRowChangeEventArgs e) { + base.OnRowChanging(e); + if ((this.JobActionsRowChanging != null)) { + this.JobActionsRowChanging(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleted(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleted(e); + if ((this.JobActionsRowDeleted != null)) { + this.JobActionsRowDeleted(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleting(System.Data.DataRowChangeEventArgs e) { + base.OnRowDeleting(e); + if ((this.JobActionsRowDeleting != null)) { + this.JobActionsRowDeleting(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void RemoveJobActionsRow(JobActionsRow row) { + this.Rows.Remove(row); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(System.Xml.Schema.XmlSchemaSet xs) { + System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); + System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + DataStorage ds = new DataStorage(); + xs.Add(ds.GetSchemaSerializable()); + System.Xml.Schema.XmlSchemaAny any1 = new System.Xml.Schema.XmlSchemaAny(); + any1.Namespace = "http://www.w3.org/2001/XMLSchema"; + any1.MinOccurs = new decimal(0); + any1.MaxOccurs = decimal.MaxValue; + any1.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any1); + System.Xml.Schema.XmlSchemaAny any2 = new System.Xml.Schema.XmlSchemaAny(); + any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; + any2.MinOccurs = new decimal(1); + any2.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + sequence.Items.Add(any2); + System.Xml.Schema.XmlSchemaAttribute attribute1 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute1.Name = "namespace"; + attribute1.FixedValue = ds.Namespace; + type.Attributes.Add(attribute1); + System.Xml.Schema.XmlSchemaAttribute attribute2 = new System.Xml.Schema.XmlSchemaAttribute(); + attribute2.Name = "tableTypeName"; + attribute2.FixedValue = "JobActionsDataTable"; + type.Attributes.Add(attribute2); + type.Particle = sequence; + return type; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public partial class JobRow : System.Data.DataRow { + + private JobDataTable tableJob; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobRow(System.Data.DataRowBuilder rb) : + base(rb) { + this.tableJob = ((JobDataTable)(this.Table)); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int ID { + get { + return ((int)(this[this.tableJob.IDColumn])); + } + set { + this[this.tableJob.IDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string Name { + get { + try { + return ((string)(this[this.tableJob.NameColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'Name\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.NameColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string Description { + get { + try { + return ((string)(this[this.tableJob.DescriptionColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'Description\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.DescriptionColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string JobName { + get { + try { + return ((string)(this[this.tableJob.JobNameColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'JobName\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.JobNameColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public string StartTime { + get { + try { + return ((string)(this[this.tableJob.StartTimeColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'StartTime\' in table \'Job\' is DBNull.", e); + } + } + set { + this[this.tableJob.StartTimeColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsNameNull() { + return this.IsNull(this.tableJob.NameColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetNameNull() { + this[this.tableJob.NameColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsDescriptionNull() { + return this.IsNull(this.tableJob.DescriptionColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetDescriptionNull() { + this[this.tableJob.DescriptionColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsJobNameNull() { + return this.IsNull(this.tableJob.JobNameColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetJobNameNull() { + this[this.tableJob.JobNameColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsStartTimeNull() { + return this.IsNull(this.tableJob.StartTimeColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetStartTimeNull() { + this[this.tableJob.StartTimeColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow[] GetJobActionsRows() { + return ((JobActionsRow[])(base.GetChildRows(this.Table.ChildRelations["Job_JobActions"]))); + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public partial class JobActionsRow : System.Data.DataRow { + + private JobActionsDataTable tableJobActions; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobActionsRow(System.Data.DataRowBuilder rb) : + base(rb) { + this.tableJobActions = ((JobActionsDataTable)(this.Table)); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int ID { + get { + return ((int)(this[this.tableJobActions.IDColumn])); + } + set { + this[this.tableJobActions.IDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int JobID { + get { + try { + return ((int)(this[this.tableJobActions.JobIDColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'JobID\' in table \'JobActions\' is DBNull.", e); + } + } + set { + this[this.tableJobActions.JobIDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public int DeviceID { + get { + try { + return ((int)(this[this.tableJobActions.DeviceIDColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'DeviceID\' in table \'JobActions\' is DBNull.", e); + } + } + set { + this[this.tableJobActions.DeviceIDColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool TurnOn { + get { + try { + return ((bool)(this[this.tableJobActions.TurnOnColumn])); + } + catch (System.InvalidCastException e) { + throw new System.Data.StrongTypingException("The value for column \'TurnOn\' in table \'JobActions\' is DBNull.", e); + } + } + set { + this[this.tableJobActions.TurnOnColumn] = value; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow JobRow { + get { + return ((JobRow)(this.GetParentRow(this.Table.ParentRelations["Job_JobActions"]))); + } + set { + this.SetParentRow(value, this.Table.ParentRelations["Job_JobActions"]); + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsJobIDNull() { + return this.IsNull(this.tableJobActions.JobIDColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetJobIDNull() { + this[this.tableJobActions.JobIDColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsDeviceIDNull() { + return this.IsNull(this.tableJobActions.DeviceIDColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetDeviceIDNull() { + this[this.tableJobActions.DeviceIDColumn] = System.Convert.DBNull; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public bool IsTurnOnNull() { + return this.IsNull(this.tableJobActions.TurnOnColumn); + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public void SetTurnOnNull() { + this[this.tableJobActions.TurnOnColumn] = System.Convert.DBNull; + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public class JobRowChangeEvent : System.EventArgs { + + private JobRow eventRow; + + private System.Data.DataRowAction eventAction; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRowChangeEvent(JobRow row, System.Data.DataRowAction action) { + this.eventRow = row; + this.eventAction = action; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRow Row { + get { + return this.eventRow; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataRowAction Action { + get { + return this.eventAction; + } + } + } + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public class JobActionsRowChangeEvent : System.EventArgs { + + private JobActionsRow eventRow; + + private System.Data.DataRowAction eventAction; + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRowChangeEvent(JobActionsRow row, System.Data.DataRowAction action) { + this.eventRow = row; + this.eventAction = action; + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRow Row { + get { + return this.eventRow; + } + } + + [System.Diagnostics.DebuggerNonUserCodeAttribute()] + public System.Data.DataRowAction Action { + get { + return this.eventAction; + } + } + } + } +} + +#pragma warning restore 1591 \ No newline at end of file diff --git a/scheduler/DeviceSchedulerAgent/DataStorage.xsc b/scheduler/DeviceSchedulerAgent/DataStorage.xsc new file mode 100644 index 00000000..8b7f66df --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/DataStorage.xsc @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/scheduler/DeviceSchedulerAgent/DataStorage.xsd b/scheduler/DeviceSchedulerAgent/DataStorage.xsd new file mode 100644 index 00000000..1bffb91b --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/DataStorage.xsd @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/scheduler/DeviceSchedulerAgent/DataStorage.xss b/scheduler/DeviceSchedulerAgent/DataStorage.xss new file mode 100644 index 00000000..ec2113c8 --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/DataStorage.xss @@ -0,0 +1,26 @@ + + + + + + + + + + + + 304 + 129 + + + 390 + 129 + + + + + \ No newline at end of file diff --git a/scheduler/DeviceSchedulerAgent/DeviceSchedulerAgent.csproj b/scheduler/DeviceSchedulerAgent/DeviceSchedulerAgent.csproj new file mode 100644 index 00000000..2fb7d866 --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/DeviceSchedulerAgent.csproj @@ -0,0 +1,80 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {C06932EC-7FF5-420B-A637-BE5802E8B896} + WinExe + Properties + DeviceSchedulerAgent + DeviceSchedulerAgent + + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + True + True + DataStorage.xsd + + + + + + + {292E034F-C3B8-4CED-87DD-479040094118} + DeviceHandler + + + + + DataStorage.xsd + + + Designer + MSDataSetGenerator + DataStorage.Designer.cs + + + DataStorage.xsd + + + + + + + + + \ No newline at end of file diff --git a/scheduler/DeviceSchedulerAgent/EncryptDecrypt.cs b/scheduler/DeviceSchedulerAgent/EncryptDecrypt.cs new file mode 100644 index 00000000..d1ada6c9 --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/EncryptDecrypt.cs @@ -0,0 +1,338 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace DeviceSchedulerAgent +{ + /// + /// Summary description for EncryptDecrypt. + /// + public class EncryptDecrypt + { + public EncryptDecrypt() + { + // + // TODO: Add constructor logic here + // + } + + // Encrypt a byte array into a byte array using a key and an IV + public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV) + { + + // Create a MemoryStream that is going to accept the encrypted bytes + MemoryStream ms = new MemoryStream(); + + // Create a symmetric algorithm. + // We are going to use Rijndael because it is strong and available on all platforms. + // You can use other algorithms, to do so substitute the next line with something like + // TripleDES alg = TripleDES.Create(); + + Rijndael alg = Rijndael.Create(); + + // Now set the key and the IV. + // We need the IV (Initialization Vector) because the algorithm is operating in its default + // mode called CBC (Cipher Block Chaining). The IV is XORed with the first block (8 byte) + // of the data before it is encrypted, and then each encrypted block is XORed with the + // following block of plaintext. This is done to make encryption more secure. + // There is also a mode called ECB which does not need an IV, but it is much less secure. + + alg.Key = Key; + alg.IV = IV; + + // Create a CryptoStream through which we are going to be pumping our data. + // CryptoStreamMode.Write means that we are going to be writing data to the stream + // and the output will be written in the MemoryStream we have provided. + CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); + + // Write the data and make it do the encryption + cs.Write(clearData, 0, clearData.Length); + + // Close the crypto stream (or do FlushFinalBlock). + // This will tell it that we have done our encryption and there is no more data coming in, + // and it is now a good time to apply the padding and finalize the encryption process. + cs.Close(); + + + // Now get the encrypted data from the MemoryStream. + // Some people make a mistake of using GetBuffer() here, which is not the right way. + byte[] encryptedData = ms.ToArray(); + + return encryptedData; + + } + + + // + // + /// + /// Encrypt a string into a string using a password + /// Uses Encrypt(byte[], byte[], byte[]) + /// + /// The text to encrypt. + /// The password to use. + /// An encrypted string. + public static string Encrypt(string clearText, string Password) + { + + // First we need to turn the input string into a byte array. + byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText); + + // Then, we need to turn the password into Key and IV + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + + // Now get the key/IV and do the encryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16)); + + + // Now we need to turn the resulting byte array into a string. + // A common mistake would be to use an Encoding class for that. It does not work + // because not all byte values can be represented by characters. + // We are going to be using Base64 encoding that is designed exactly for what we are + // trying to do. + return Convert.ToBase64String(encryptedData); + + } + + + // Encrypt bytes into bytes using a password + // Uses Encrypt(byte[], byte[], byte[]) + public static byte[] Encrypt(byte[] clearData, string Password) + { + + // We need to turn the password into Key and IV. + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + // Now get the key/IV and do the encryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16)); + + } + + + // Encrypt a file into another file using a password + public static void Encrypt(string fileIn, string fileOut, string Password) + { + + // First we are going to open the file streams + FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read); + FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write); + + + // Then we are going to derive a Key and an IV from the Password and create an algorithm + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + Rijndael alg = Rijndael.Create(); + + alg.Key = pdb.GetBytes(32); + alg.IV = pdb.GetBytes(16); + + // Now create a crypto stream through which we are going to be pumping data. + // Our fileOut is going to be receiving the encrypted bytes. + CryptoStream cs = new CryptoStream(fsOut, alg.CreateEncryptor(), CryptoStreamMode.Write); + + // Now will will initialize a buffer and will be processing the input file in chunks. + // This is done to avoid reading the whole file (which can be huge) into memory. + + int bufferLen = 4096; + byte[] buffer = new byte[bufferLen]; + int bytesRead; + + do + { + + // read a chunk of data from the input file + bytesRead = fsIn.Read(buffer, 0, bufferLen); + + // encrypt it + cs.Write(buffer, 0, bytesRead); + + } while(bytesRead != 0); + + + // close everything + cs.Close(); // this will also close the unrelying fsOut stream + fsIn.Close(); + + } + + + // Decrypt a byte array into a byte array using a key and an IV + public static byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV) + { + + // Create a MemoryStream that is going to accept the decrypted bytes + MemoryStream ms = new MemoryStream(); + + // Create a symmetric algorithm. + // We are going to use Rijndael because it is strong and available on all platforms. + // You can use other algorithms, to do so substitute the next line with something like + // TripleDES alg = TripleDES.Create(); + + Rijndael alg = Rijndael.Create(); + + // Now set the key and the IV. + // We need the IV (Initialization Vector) because the algorithm is operating in its default + // mode called CBC (Cipher Block Chaining). The IV is XORed with the first block (8 byte) + // of the data after it is decrypted, and then each decrypted block is XORed with the previous + // cipher block. This is done to make encryption more secure. + // There is also a mode called ECB which does not need an IV, but it is much less secure. + + alg.Key = Key; + alg.IV = IV; + + + // Create a CryptoStream through which we are going to be pumping our data. + // CryptoStreamMode.Write means that we are going to be writing data to the stream + // and the output will be written in the MemoryStream we have provided. + CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write); + + + // Write the data and make it do the decryption + cs.Write(cipherData, 0, cipherData.Length); + + // Close the crypto stream (or do FlushFinalBlock). + // This will tell it that we have done our decryption and there is no more data coming in, + // and it is now a good time to remove the padding and finalize the decryption process. + cs.Close(); + + // Now get the decrypted data from the MemoryStream. + // Some people make a mistake of using GetBuffer() here, which is not the right way. + byte[] decryptedData = ms.ToArray(); + + + return decryptedData; + + } + + + /// + /// Decrypt a string into a string using a password. + /// Uses Decrypt(byte[], byte[], byte[]) + /// + /// The text to decrypt. + /// The password to use. + /// A decrypted string. + public static string Decrypt(string cipherText, string Password) + { + + // First we need to turn the input string into a byte array. + // We presume that Base64 encoding was used + byte[] cipherBytes = Convert.FromBase64String(cipherText); + + // Then, we need to turn the password into Key and IV + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + + // Now get the key/IV and do the decryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16)); + + // Now we need to turn the resulting byte array into a string. + // A common mistake would be to use an Encoding class for that. It does not work + // because not all byte values can be represented by characters. + // We are going to be using Base64 encoding that is designed exactly for what we are + // trying to do. + return System.Text.Encoding.Unicode.GetString(decryptedData); + + } + + + // Decrypt bytes into bytes using a password + // Uses Decrypt(byte[], byte[], byte[]) + public static byte[] Decrypt(byte[] cipherData, string Password) + { + + // We need to turn the password into Key and IV. + // We are using salt to make it harder to guess our key using a dictionary attack - + // trying to guess a password by enumerating all possible words. + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + // Now get the key/IV and do the Decryption using the function that accepts byte arrays. + // Using PasswordDeriveBytes object we are first getting 32 bytes for the Key + // (the default Rijndael key length is 256bit = 32bytes) and then 16 bytes for the IV. + // IV should always be the block size, which is by default 16 bytes (128 bit) for Rijndael. + // If you are using DES/TripleDES/RC2 the block size is 8 bytes and so should be the IV size. + // You can also read KeySize/BlockSize properties off the algorithm to find out the sizes. + + return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16)); + + } + + + // Decrypt a file into another file using a password + public static void Decrypt(string fileIn, string fileOut, string Password) + { + // First we are going to open the file streams + FileStream fsIn = new FileStream(fileIn, FileMode.Open, FileAccess.Read); + FileStream fsOut = new FileStream(fileOut, FileMode.OpenOrCreate, FileAccess.Write); + + // Then we are going to derive a Key and an IV from the Password and create an algorithm + PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, + new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76}); + + Rijndael alg = Rijndael.Create(); + + alg.Key = pdb.GetBytes(32); + alg.IV = pdb.GetBytes(16); + + + // Now create a crypto stream through which we are going to be pumping data. + // Our fileOut is going to be receiving the Decrypted bytes. + + CryptoStream cs = new CryptoStream(fsOut, alg.CreateDecryptor(), CryptoStreamMode.Write); + + // Now will will initialize a buffer and will be processing the input file in chunks. + // This is done to avoid reading the whole file (which can be huge) into memory. + + int bufferLen = 4096; + byte[] buffer = new byte[bufferLen]; + int bytesRead; + + + do + { + + // read a chunk of data from the input file + bytesRead = fsIn.Read(buffer, 0, bufferLen); + + // Decrypt it + cs.Write(buffer, 0, bytesRead); + + } while(bytesRead != 0); + + // close everything + cs.Close(); // this will also close the unrelying fsOut stream + fsIn.Close(); + + } + + + } +} diff --git a/scheduler/DeviceSchedulerAgent/Program.cs b/scheduler/DeviceSchedulerAgent/Program.cs new file mode 100644 index 00000000..a4fe3c2f --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/Program.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Text; +using DeviceHandler; +using System.Data; +using System.Windows.Forms; + +namespace DeviceSchedulerAgent +{ + class Program + { + + static void Main(string[] args) + { + //If no arguments are supplied then exit. + if (args.Length == 0) + { + MessageBox.Show("Inga argument har angivits!"); + return; + } + + try + { + + + + //Makesure that we have all data loaded. + DataStorage data = LoadData(); + + //Get the JobID. + int jobID = Convert.ToInt32(args[0]); + + DataStorage.JobRow job = data.Job.FindByID(jobID); + + if (job != null) + { + DeviceHandler.Handler handler = new Handler(); + + //Load devices. + handler.Load(); + + //Go through each action and execute it. + foreach (DataStorage.JobActionsRow action in job.GetJobActionsRows()) + { + Device item = handler.Find(action.DeviceID); + + if (action.TurnOn) + handler.TurnOnWithDelay(item); + else + handler.TurnOffWithDelay(item); + } + + } + else + { + MessageBox.Show("Programmet kunde inte hitta något jobb."); + } + } + catch (Exception ex) + { + MessageBox.Show(ex.Message); + } + + + } + + private static DataStorage LoadData() + { + + string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + path = System.IO.Path.Combine(path, "Jobs.dat"); + + DataStorage data = new DataStorage(); + + if (System.IO.File.Exists(path)) + { + data.ReadXml(path, XmlReadMode.ReadSchema); + } + + return data; + } + } +} diff --git a/scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs b/scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..efbf3bd3 --- /dev/null +++ b/scheduler/DeviceSchedulerAgent/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("DeviceSchedulerAgent")] +[assembly: AssemblyDescription("Executer of scheduled devices.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Telldus Technologies")] +[assembly: AssemblyProduct("DeviceSchedulerAgent")] +[assembly: AssemblyCopyright("Copyright © Telldus Technologies 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("7ec95bd9-249b-45f4-8426-a89da7155be2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("2007.1.*")] +[assembly: AssemblyFileVersion("2007.1.*")] diff --git a/scheduler/DeviceSchedulerAgent/clock_run.ico b/scheduler/DeviceSchedulerAgent/clock_run.ico new file mode 100644 index 0000000000000000000000000000000000000000..1b0922896067311ecc671ac9a1f3c3a7802281f1 GIT binary patch literal 26694 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 literal 0 HcmV?d00001 diff --git a/scheduler/DeviceSchedulerAgent/security_agent.ico b/scheduler/DeviceSchedulerAgent/security_agent.ico new file mode 100644 index 0000000000000000000000000000000000000000..395752909860b721438328bcfedff3a2a85c05dd GIT binary patch literal 26694 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 LlFn}#r}h5;TX~{- literal 0 HcmV?d00001 From 80ce55dc8cc07a9a0d4c96731c398e7b001a0896 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Thu, 14 Feb 2008 20:18:40 +0000 Subject: [PATCH 0010/2215] Version 0.3.0. New feature: possibility to randomize switch on and switch off time. --- tellstickd/README | 3 +- tellstickd/tellstickd | 123 +++++++++++++++++++++++++++++-------- tellstickd/tellstickd.conf | 17 ++--- 3 files changed, 108 insertions(+), 35 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index d3aa3ace..7c1e1090 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -31,10 +31,11 @@ Licensing ================= This software is freely distributable under the GNU General Public License, the full content of the license is included in the file LICENSE. -Feel free to improve the program. +Bug reports are welcome, but even more appreciated are patches with the solution to the problem. Revision history ================= +2008-02-14 0.3.0 New feature: On- and off times can be randomized within a given interval. 2008-02-12 0.2.1 Changed behaviour when program is called without argument. Now presents: Try "tellstickd --help" for more information. 2008-02-11 0.2.0 Added support for SARTANO devices. General code cleanups. 2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index f783c517..64689fd8 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -1,5 +1,6 @@ #!/usr/bin/perl +use POSIX; use DateTime; use DateTime::Event::Sunrise; use Time::Local; @@ -16,7 +17,7 @@ $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.2.1"; +$VERSION = "0.3.0"; # Structure of the configurations to be read; @@ -28,9 +29,13 @@ $VERSION = "0.2.1"; # $device_cfg[$i][5]; # Off when bright, 0 = no, 1 = yes # $device_cfg[$i][6]; # Off when bright delay # $device_cfg[$i][7]; # Time in advance when getting dark +# $device_cfg[$i][8]; # On time random interval +# $device_cfg[$i][9]; # Off time random interval # $device_cfg[$i][20]; # Sunrise off time, calculated in this program and stored here # $device_cfg[$i][21]; # Sunset on time, calculated in this program and stored here # $device_cfg[$i][22]; # Switch state, 0 = off, 1 = on +# $device_cfg[$i][23]; # Original on time +# $device_cfg[$i][24]; # Original off time sub daemonize { chdir '/' or die "$PROGRAM_NAME: Can't chdir to /: $!"; @@ -82,8 +87,8 @@ sub is_inbetween_times { my $time1 = $_[0]; my $time2 = $_[1]; + my $curr_time = $_[2]; - my $curr_time = $current_time; $curr_time =~ s/://g; $time1 =~ s/://g; $time2 =~ s/://g; @@ -150,6 +155,8 @@ sub rfcmd_exec { return; } + +# Time format xx:yy for input parameters sub add_time { my $time1 = $_[0]; @@ -159,7 +166,8 @@ sub add_time $Year += 1900; ($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/; - ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/; + ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/;$device_cfg[$i][8] = $inrad[8]; # On time random interval + $device_cfg[$i][9] = $inrad[9]; # Off time random interval $time1_epoch_seconds = timelocal(0,$time1_minute,$time1_hour, $Day, $Month, $Year); $time2_offset_seconds = 3600*$time2_hour + 60*$time2_minute; @@ -172,6 +180,7 @@ sub add_time } +# Time format xx:yy for input parameters sub subtract_time { my $time1 = $_[0]; @@ -194,6 +203,53 @@ sub subtract_time } +sub randomize_on +{ + my $device_id = $_[0]; + + (my $random_hour, my $random_minute) = $device_cfg[$device_id][8] =~ /(.*)\:(.*)/; + + my $rand_res = int(rand(60 * $random_hour + $random_minute)); + + my $rand_res_hour = floor($rand_res / 60); + my $rand_res_minute = $rand_res - 60*$rand_res_hour; + + # Here we have the random offset in format xx:yy + my $random_time = sprintf("%02d:%02d", $rand_res_hour, $rand_res_minute); + + $device_cfg[$device_id][3] = add_time($device_cfg[$device_id][23], $random_time); + + if (is_inbetween_times($device_cfg[$device_id][23], $device_cfg[$device_id][24], $device_cfg[$device_id][3]) == $NO) { + randomize_on($device_id); + } + + return; +} + +sub randomize_off +{ + my $device_id = $_[0]; + + (my $random_hour, my $random_minute) = $device_cfg[$device_id][9] =~ /(.*)\:(.*)/; + + my $rand_res = int(rand(60 * $random_hour + $random_minute)); + + my $rand_res_hour = floor($rand_res / 60); + my $rand_res_minute = $rand_res - 60*$rand_res_hour; + + # Here we have the random offset in format xx:yy + my $random_time = sprintf("%02d:%02d", $rand_res_hour, $rand_res_minute); + + $device_cfg[$device_id][4] = add_time($device_cfg[$device_id][24], $random_time); + + if (is_inbetween_times($device_cfg[$device_id][23], $device_cfg[$device_id][24], $device_cfg[$device_id][4]) == $YES) { + randomize_off($device_id); + } + + return; +} + + # Time format sanity check routine sub is_time_format_correct { @@ -242,18 +298,22 @@ sub read_config if ($_ !~ /^\#/ && $_ !~ /^\s/ && $_ !~ /^\n/) { chomp($_); @inrad = split /\s+/, $_; - $device_cfg[$i][0] = $inrad[0]; # Protocol - $device_cfg[$i][1] = $inrad[1]; # Housecode A-P - $device_cfg[$i][2] = $inrad[2]; # Channel 1-3 - $device_cfg[$i][3] = $inrad[3]; # On time - $device_cfg[$i][4] = $inrad[4]; # Off time - $device_cfg[$i][5] = $inrad[5]; # Off when bright - $device_cfg[$i][6] = $inrad[6]; # Off when bright delay - $device_cfg[$i][7] = $inrad[7]; # Time in advance when getting dark - $device_cfg[$i][22] = 1; # Initial state set to so that they will be switched of at startup + $device_cfg[$i][0] = $inrad[0]; # Protocol + $device_cfg[$i][1] = $inrad[1]; # Housecode A-P + $device_cfg[$i][2] = $inrad[2]; # Channel 1-3 + $device_cfg[$i][3] = $inrad[3]; # On time + $device_cfg[$i][4] = $inrad[4]; # Off time + $device_cfg[$i][5] = $inrad[5]; # Off when bright + $device_cfg[$i][6] = $inrad[6]; # Off when bright delay + $device_cfg[$i][7] = $inrad[7]; # Time in advance when getting dark + $device_cfg[$i][8] = $inrad[8]; # On time random interval + $device_cfg[$i][9] = $inrad[9]; # Off time random interval + $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched of at startup + $device_cfg[$i][23] = $device_cfg[$i][3]; # Original on time is stored here pos 3 will be used for random on times + $device_cfg[$i][24] = $device_cfg[$i][4]; # Original off time is stored here pos 4 will be used for random on times - if ($device_cfg[$device_id][0] eq "SARTANO") { + if ($device_cfg[$i][0] eq "SARTANO") { $device_cfg[$i][2] = ""; } @@ -290,26 +350,29 @@ sub read_config printf("$PROGRAM_NAME: $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] config:\n"); if ($device_cfg[$i][3] == -1) { - printf(" On time: N/A\n"); + printf(" On time: N/A\n"); } else { - printf(" On time: $device_cfg[$i][3]\n"); + printf(" On time: $device_cfg[$i][3]\n"); } if ($device_cfg[$i][4] == -1) { - printf(" Off time: N/A\n"); + printf(" Off time: N/A\n"); } else { - printf(" Off time: $device_cfg[$i][4]\n"); + printf(" Off time: $device_cfg[$i][4]\n"); } + printf(" On time random interval: $device_cfg[$i][8]\n"); + printf(" Off time random interval: $device_cfg[$i][9]\n"); + if ($device_cfg[$i][5] == $YES) { - printf(" Turned off daytime: yes\n"); - printf(" Off post sunrise: $device_cfg[$i][6]\n"); - printf(" On pre sunset: $device_cfg[$i][7]\n"); + printf(" Turned off daytime: yes\n"); + printf(" Off post sunrise: $device_cfg[$i][6]\n"); + printf(" On pre sunset: $device_cfg[$i][7]\n"); } else { - printf(" Turned off daytime: no\n"); + printf(" Turned off daytime: no\n"); } $i++; @@ -419,10 +482,10 @@ while (1) { # First, lets set the sunrise and sunset times for the devices that it applies to, once a day, at 00:00. if ($first_loop == $YES || $current_time eq "00:00") { my $sunrise_time = get_sunrise_time(); - printf("$PROGRAM_NAME: Sunrise today is expected at $sunrise_time\n"); + printf("$PROGRAM_NAME: Time is $current_time. Sunrise today is expected at $sunrise_time\n"); my $sunset_time = get_sunset_time(); - printf("$PROGRAM_NAME: Sunset today is expected at $sunset_time\n"); + printf("$PROGRAM_NAME: Time is $current_time. Sunset today is expected at $sunset_time\n"); for (my $i = 0; $i < $number_of_devices; $i++) { # Initially all devices are switched off to get a known state @@ -430,9 +493,15 @@ while (1) { rfcmd_exec($i, 0); } + # Lets set the actual on- and offtimes depending on random interval settings. + randomize_on($i); + printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned on $device_cfg[$i][3]\n"); + + randomize_off($i); + printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned off $device_cfg[$i][4]\n"); + # If the device is supposed to be off daytime, the following applies - # Sunrise time + requested offset if ($device_cfg[$i][5] == $YES) { $device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]); @@ -453,7 +522,7 @@ while (1) { # First if we consider daytime off if ($device_cfg[$i][5] == $YES) { - if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4]) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21]) == $NO) { + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21]) == $NO) { rfcmd_exec($i, 1); } else { @@ -464,7 +533,7 @@ while (1) { # Then if daytime off is not considered else { - if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4]) == $YES) { + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES) { rfcmd_exec($i, 1); } else { @@ -476,5 +545,5 @@ while (1) { } $first_loop = $NO; - sleep(60); # Wait a while until next round should be less than or equal to a minute [seconds]. + sleep(50); # Wait a while until next round [seconds]. } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 7f596b11..3b048abd 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -1,20 +1,23 @@ -# Configuration file for control of remote switches +# Tellstickd file for control of remote switches with rfcmd. # -# +# # (no = 0, yes = 1) # Multiple definitions are possible for each device # -# Setting and to the same means that the device will always be switched on +# Setting and to the same means that the device will always be switched on. +# The random interval times defines the allowed interval within the switch may take place +# =22:15 and =00:30 means that the actual switch will take +# place sometime between 22:15 and 22:44, with new randomized times set every night at 00:00. # # Time format xx:yy where xx is hour and yy is minute # If no turn on time or turn off time should be used. Note this with -1. See the example line below. Only to be used on turn on or turn off times. # NEXA A 1 -1 22:45 1 00:30 00:30 # -# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning. -SARTANO 0000000000 0 05:30 22:45 1 00:30 00:15 +# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning. On time will always be 05:30, off time will always be 22:45. +SARTANO 0000000000 0 05:30 22:45 1 00:30 00:15 00:00 00:00 -# Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. -NEXA A 1 05:30 22:45 1 00:30 00:15 +# Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. On time will be between 06:30 and 06:39, off time will be between 22:05 and 22:24. +NEXA A 1 06:30 22:05 1 00:30 00:15 00:10 00:20 From 96daffc46bab7a24bb0e4206b4bf19513795edb1 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Fri, 15 Feb 2008 07:21:56 +0000 Subject: [PATCH 0011/2215] Changed update interval back from 50 to 60 seconds: --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 64689fd8..e4a02167 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -545,5 +545,5 @@ while (1) { } $first_loop = $NO; - sleep(50); # Wait a while until next round [seconds]. + sleep(60); # Wait a while until next round [seconds]. } From a67fa2653b5e8412a8bda3700b365350c6fa6865 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Fri, 15 Feb 2008 07:24:07 +0000 Subject: [PATCH 0012/2215] Updated README file. --- tellstickd/README | 3 ++- tellstickd/tellstickd | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 7c1e1090..5bc9e9c9 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,7 +35,8 @@ Bug reports are welcome, but even more appreciated are patches with the solution Revision history ================= -2008-02-14 0.3.0 New feature: On- and off times can be randomized within a given interval. +2008-02-15 0.3.1 Changed update interval back from 50 to 60 seconds. +2008-02-14 0.3.0 New feature: On- and off times can be randomized within a given interval. Changed update interval from 60 to 50 seconds. 2008-02-12 0.2.1 Changed behaviour when program is called without argument. Now presents: Try "tellstickd --help" for more information. 2008-02-11 0.2.0 Added support for SARTANO devices. General code cleanups. 2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index e4a02167..99ce4011 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -17,7 +17,7 @@ $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.3.0"; +$VERSION = "0.3.1"; # Structure of the configurations to be read; From 6ba85200c4624fa0a7452fe73db888d3ae74a340 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Fri, 15 Feb 2008 08:12:35 +0000 Subject: [PATCH 0013/2215] Corrected a fatal bug regarding switch logic. --- tellstickd/README | 1 + tellstickd/tellstickd | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 5bc9e9c9..14314f5a 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Bug reports are welcome, but even more appreciated are patches with the solution Revision history ================= +2008-02-15 0.3.2 Corrected a fatal bug regarding switch logic. 2008-02-15 0.3.1 Changed update interval back from 50 to 60 seconds. 2008-02-14 0.3.0 New feature: On- and off times can be randomized within a given interval. Changed update interval from 60 to 50 seconds. 2008-02-12 0.2.1 Changed behaviour when program is called without argument. Now presents: Try "tellstickd --help" for more information. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 99ce4011..0f9746dc 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -17,7 +17,7 @@ $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.3.1"; +$VERSION = "0.3.2"; # Structure of the configurations to be read; @@ -93,8 +93,8 @@ sub is_inbetween_times $time1 =~ s/://g; $time2 =~ s/://g; $curr_time =~ s/^0*//; - $sunrise_time =~ s/^0*//; - $sunset_time =~ s/^0*//; + $time1 =~ s/^0*//; + $time2 =~ s/^0*//; # If we pass midnight, the following has to be checked if ($time2 <= $time1) { @@ -522,7 +522,7 @@ while (1) { # First if we consider daytime off if ($device_cfg[$i][5] == $YES) { - if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21]) == $NO) { + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21], $current_time) == $NO) { rfcmd_exec($i, 1); } else { From fc724216169bb3f0f7e4f9f24e6ee1623cd991ff Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Fri, 15 Feb 2008 20:59:09 +0000 Subject: [PATCH 0014/2215] General improvements. --- tellstickd/README | 1 + tellstickd/tellstickd | 50 +++++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 14314f5a..74a92263 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Bug reports are welcome, but even more appreciated are patches with the solution Revision history ================= +2008-02-15 0.3.3 General improvements. 2008-02-15 0.3.2 Corrected a fatal bug regarding switch logic. 2008-02-15 0.3.1 Changed update interval back from 50 to 60 seconds. 2008-02-14 0.3.0 New feature: On- and off times can be randomized within a given interval. Changed update interval from 60 to 50 seconds. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 0f9746dc..a2b65127 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -17,7 +17,7 @@ $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.3.2"; +$VERSION = "0.3.3"; # Structure of the configurations to be read; @@ -254,35 +254,37 @@ sub randomize_off sub is_time_format_correct { my $time = $_[0]; - my $ok = $YES; - my $number_of_matches = 0; - my $tmp = $time; + + if (length($time) < 4 || length($time) > 5) { + return $NO; + } + while ($tmp =~ /\:/g) { $number_of_matches++; } if ($number_of_matches != 1) { - $ok = $NO; + return $NO; } (my $hour, my $minute) = $time =~ /^(.*?)\:(.*?)$/; if ($hour !~ /^[0-9]+$/) { - $ok = $NO; + return $NO; } if ($minute !~ /^[0-9]+$/) { - $ok = $NO; + return $NO; } if ($hour < 0 || $hour > 23 || $minute < 0 || $minute > 59) { - $ok = $NO; + return $NO; } - return $ok; + return $YES; } sub read_config @@ -321,29 +323,37 @@ sub read_config # If the turn on time is not to be used, this is marked with -1 if ($device_cfg[$i][3] != -1) { if (is_time_format_correct($device_cfg[$i][3]) == $NO) { - die("$PROGRAM_NAME: Format of turn on time for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + die("$PROGRAM_NAME: Format of turn on time for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][3]\n"); } } else { - printf("$PROGRAM_NAME: Noted configuration for device $device_cfg[$i][1]$device_cfg[$i][2] with no turn on time.\n"); + printf("$PROGRAM_NAME: Noted configuration for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] with no turn on time.\n"); } # If the turn off time is not to be used, this is marked with -1 if ($device_cfg[$i][4] != -1) { if (is_time_format_correct($device_cfg[$i][4]) == $NO) { - die("$PROGRAM_NAME: Format of turn off time for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + die("$PROGRAM_NAME: Format of turn off time for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][4]\n"); } } else { - printf("$PROGRAM_NAME: Noted configuration for device $device_cfg[$i][1]$device_cfg[$i][2] with no turn off time.\n"); + printf("$PROGRAM_NAME: Noted configuration for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] with no turn off time.\n"); } if (is_time_format_correct($device_cfg[$i][6]) == $NO) { - die("$PROGRAM_NAME: Format of turn off after sunrise for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + die("$PROGRAM_NAME: Format of turn off after sunrise for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][6]\n"); } if (is_time_format_correct($device_cfg[$i][7]) == $NO) { - die("$PROGRAM_NAME: Format of turn on before sunset for device $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + die("$PROGRAM_NAME: Format of turn on before sunset for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct. Exiting.\n"); + } + + if (is_time_format_correct($device_cfg[$i][8]) == $NO) { + die("$PROGRAM_NAME: Format of on interfval for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][8]\n"); + } + + if (is_time_format_correct($device_cfg[$i][9]) == $NO) { + die("$PROGRAM_NAME: Format of off interval for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][9]\n"); } @@ -463,7 +473,7 @@ if ($number_of_devices < 1) { die("$PROGRAM_NAME: Configuration file has no devices to control, exiting.\n"); } else { - printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n"); + printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n\n"); } ################################################################################################### @@ -482,10 +492,11 @@ while (1) { # First, lets set the sunrise and sunset times for the devices that it applies to, once a day, at 00:00. if ($first_loop == $YES || $current_time eq "00:00") { my $sunrise_time = get_sunrise_time(); + printf("$PROGRAM_NAME: Recalculating sunrise/sunset. Current date: %d-%02d-%02d\n", $Year, $Month + 1, $Day); printf("$PROGRAM_NAME: Time is $current_time. Sunrise today is expected at $sunrise_time\n"); my $sunset_time = get_sunset_time(); - printf("$PROGRAM_NAME: Time is $current_time. Sunset today is expected at $sunset_time\n"); + printf("$PROGRAM_NAME: Time is $current_time. Sunset today is expected at $sunset_time\n\n"); for (my $i = 0; $i < $number_of_devices; $i++) { # Initially all devices are switched off to get a known state @@ -509,7 +520,10 @@ while (1) { # Sunset time - requested offset $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); - printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); + printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n\n"); + } + else { + printf("\n"); } } } From e7512dbe2eb256bf7e0422b24ca80ded728486e5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 16 Feb 2008 13:12:56 +0000 Subject: [PATCH 0015/2215] Changed the logic for calculating IKEA-dim message. --- driver/TellUsbD101/DeviceIkea.cpp | 60 ++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/driver/TellUsbD101/DeviceIkea.cpp index c83f1a50..2087161d 100644 --- a/driver/TellUsbD101/DeviceIkea.cpp +++ b/driver/TellUsbD101/DeviceIkea.cpp @@ -90,10 +90,10 @@ string DeviceIkea::getStringCode(unsigned char level){ for (int i = 13; i >= 0; --i) { if ((intCode>>i) & 1) { strChannels.append("TT"); - if (13 % 2 == 0) - checksum2++; - else + if (i % 2 == 0) checksum1++; + else + checksum2++; } else { strChannels.append("ª"); } @@ -103,22 +103,58 @@ string DeviceIkea::getStringCode(unsigned char level){ strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + int intLevel = 0; if (level <= 12) { - strReturn.append("ªTTªTT"); //Level 0 - Off + intLevel = 10; // Level 10 is actually off + } else if (level <= 37) { + intLevel = 1; + } else if (level <= 62) { + intLevel = 2; + } else if (level <= 87) { + intLevel = 3; + } else if (level <= 112) { + intLevel = 4; } else if (level <= 137) { - strReturn.append("TTªTTª"); //Level 5 + intLevel = 5; } else if (level <= 162) { - strReturn.append("ªTTTTª"); //Level 6 + intLevel = 6; + } else if (level <= 187) { + intLevel = 7; + } else if (level <= 212) { + intLevel = 8; + } else if (level <= 237) { + intLevel = 9; } else { - strReturn.append("ªªªª"); //Level 10 - On + intLevel = 0; // Level 0 is actually full on } - if (intFadeStyle == 1) - strReturn.append("TTTTªª"); //Smooth - else - strReturn.append("TTªªTT"); //Instant - strReturn.append("+"); + int intFade = 0; + if (intFadeStyle == 1) { + intFade = 11 << 4; //Smooth + } else { + intFade = 1 << 4; //Instant + } + intCode = intLevel | intFade; //Concat level and fade + + checksum1 = 0; + checksum2 = 0; + for (int i = 0; i < 6; ++i) { + if ((intCode>>i) & 1) { + strReturn.append("TT"); + if (i % 2 == 0) + checksum1++; + else + checksum2++; + } else { + strReturn.append("ª"); + } + } + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + strReturn.append("+"); } catch(...){ throw; From d2e941ba272fe0c1e1364cb73e14c963cbf08bf7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 16 Feb 2008 15:04:50 +0000 Subject: [PATCH 0016/2215] Bugfix in Ikea checksum calculation --- driver/TellUsbD101/DeviceIkea.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/driver/TellUsbD101/DeviceIkea.cpp index 2087161d..e5af5f79 100644 --- a/driver/TellUsbD101/DeviceIkea.cpp +++ b/driver/TellUsbD101/DeviceIkea.cpp @@ -91,9 +91,9 @@ string DeviceIkea::getStringCode(unsigned char level){ if ((intCode>>i) & 1) { strChannels.append("TT"); if (i % 2 == 0) - checksum1++; - else checksum2++; + else + checksum1++; } else { strChannels.append("ª"); } From b7e55de4435d82aec7793adacd24440e6cf2fbab Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 16 Feb 2008 16:06:36 +0000 Subject: [PATCH 0017/2215] Fixed a bug which made devMethods() return 0 if no TellStick was inserted. --- driver/TellUsbD101/TellUsbD101.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index abae47c4..cfd4f3e1 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -291,7 +291,7 @@ int __stdcall devMethods(int id){ try{ TelldusSettings ts; char* strModel = ts.getModel(id); - Device* dev = ts.getDevice(id); + Device* dev = ts.getDevice(id, -1); //We send dongleIndex=-1 sice we wouldn't send any data! if (dev != NULL) { intMethods = dev->methods(strModel); } From 28b7841310037347f73e1608ed5a7eecf168acf8 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Sun, 17 Feb 2008 19:59:20 +0000 Subject: [PATCH 0018/2215] Added possiblitiy to use a minus sign (-) when setting the off when bright delay and prelight in afternoon parameters in the tellstickd.conf file. --- tellstickd/README | 1 + tellstickd/tellstickd | 32 ++++++++++++++++++++++++-------- tellstickd/tellstickd.conf | 2 +- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 74a92263..0b3f8193 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Bug reports are welcome, but even more appreciated are patches with the solution Revision history ================= +2008-02-17 0.3.4 Now possible to use a minus sign (-) when setting and 2008-02-15 0.3.3 General improvements. 2008-02-15 0.3.2 Corrected a fatal bug regarding switch logic. 2008-02-15 0.3.1 Changed update interval back from 50 to 60 seconds. diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index a2b65127..afc186de 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -17,7 +17,7 @@ $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.3.3"; +$VERSION = "0.3.4"; # Structure of the configurations to be read; @@ -156,28 +156,34 @@ sub rfcmd_exec { } -# Time format xx:yy for input parameters +# Time format xx:yy for input parameters argument1 has to be positive, argument2 can be positive or negative sub add_time { my $time1 = $_[0]; my $time2 = $_[1]; + my $multiplier = 1; ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; + (my $sign) = $time2 =~ /^(.*?)[0-9]/; ($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/; - ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/;$device_cfg[$i][8] = $inrad[8]; # On time random interval - $device_cfg[$i][9] = $inrad[9]; # Off time random interval + # Remove any leading signs + $time2 =~ s/^.*?[0-9]//g; + ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/; + + if ($sign eq "-") { + $multiplier = -1; + } $time1_epoch_seconds = timelocal(0,$time1_minute,$time1_hour, $Day, $Month, $Year); $time2_offset_seconds = 3600*$time2_hour + 60*$time2_minute; - my $result_seconds = $time1_epoch_seconds + $time2_offset_seconds; + my $result_seconds = $time1_epoch_seconds + $multiplier*$time2_offset_seconds; ($min,$hour)= (localtime($result_seconds))[1,2]; return sprintf("%02d:%02d", $hour, $min); - } # Time format xx:yy for input parameters @@ -185,22 +191,29 @@ sub subtract_time { my $time1 = $_[0]; my $time2 = $_[1]; + my $multiplier = 1; ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; + (my $sign) = $time2 =~ /^(.*?)[0-9]/; ($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/; + # Remove any leading signs + $time2 =~ s/^.*?[0-9]//g; ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/; + if ($sign eq "-") { + $multiplier = -1; + } + $time1_epoch_seconds = timelocal(0,$time1_minute,$time1_hour, $Day, $Month, $Year); $time2_offset_seconds = 3600*$time2_hour + 60*$time2_minute; - my $result_seconds = $time1_epoch_seconds - $time2_offset_seconds; + my $result_seconds = $time1_epoch_seconds - $multiplier*$time2_offset_seconds; ($min,$hour)= (localtime($result_seconds))[1,2]; return sprintf("%02d:%02d", $hour, $min); - } sub randomize_on @@ -257,6 +270,9 @@ sub is_time_format_correct my $number_of_matches = 0; my $tmp = $time; + # Remove a leading signs, if it exists + $time =~ s/^.*?[0-9]//g; + if (length($time) < 4 || length($time) > 5) { return $NO; } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 3b048abd..399b7337 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -1,6 +1,6 @@ # Tellstickd file for control of remote switches with rfcmd. # -# +# # (no = 0, yes = 1) # Multiple definitions are possible for each device # From 9359c895a2718465b5ef5ba545adcfd9b49da158 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 18 Feb 2008 21:31:07 +0000 Subject: [PATCH 0019/2215] Changed sunset calculation parameters. Added init script for Debian and adaptions of tellstickd. All contributions of Anders Betner. --- tellstickd/tellstickd | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index afc186de..a10c77fb 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -53,7 +53,7 @@ sub get_sunrise_time $Month++; my $dt = DateTime->new( year => $Year, month => $Month, day => $Day, time_zone => $TIMEZONE, ); - my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '0', iteration => '1'); + my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '-0.833', iteration => '1'); $Month--; @@ -71,7 +71,7 @@ sub get_sunset_time $Month++; my $dt = DateTime->new( year => $Year, month => $Month, day => $Day, time_zone => $TIMEZONE, ); - my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '0', iteration => '1'); + my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '-0.833', iteration => '1'); $Month--; @@ -476,6 +476,12 @@ if ($make_daemon == $YES) { &daemonize(); } +# Create pidfile +my $pidFile = '/var/run/tellstickd.pid'; +open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; +print PIDFILE $$; +close PIDFILE; + if (length($conf_file) < 1) { $conf_file = $CONFIG_FILE; } From fb980ff35a57eb0a79820f2771e79777e1a7d483 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 18 Feb 2008 21:34:06 +0000 Subject: [PATCH 0020/2215] Changed sunset calculation parameters. Added init script for Debian and adaptions of tellstickd. All contributions of Anders Betner. --- tellstickd/README | 1 + tellstickd/init_script/tellstickd.debian | 74 ++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100755 tellstickd/init_script/tellstickd.debian diff --git a/tellstickd/README b/tellstickd/README index 0b3f8193..842efac1 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -35,6 +35,7 @@ Bug reports are welcome, but even more appreciated are patches with the solution Revision history ================= +2008-02-18 0.3.5 Changed sunset calculation parameters. Added init script for Debian and adaptions of tellstickd. All contributions of Anders Betner. 2008-02-17 0.3.4 Now possible to use a minus sign (-) when setting and 2008-02-15 0.3.3 General improvements. 2008-02-15 0.3.2 Corrected a fatal bug regarding switch logic. diff --git a/tellstickd/init_script/tellstickd.debian b/tellstickd/init_script/tellstickd.debian new file mode 100755 index 00000000..efe97c74 --- /dev/null +++ b/tellstickd/init_script/tellstickd.debian @@ -0,0 +1,74 @@ +#!/bin/bash +# +# Init file for tellstickd remote light switch daemon +# +# Written by Magnus Juntti +# +# chkconfig: 35 54 46 +# description: tellstickd remote light switch daemon +# +# processname: tellstickd +# config: /etc/tellstickd.conf +# pidfile: /var/run/tellstick + +. /lib/lsb/init-functions + +DAEMON="/usr/local/bin/tellstickd" +NAME="tellstickd" +CONFIG_FILE="/etc/tellstickd.conf" +LOG_FILE="/var/log/tellstickd" +PID_FILE="/var/run/tellstickd.pid" +OPTIONS="" + +[ -x $DAEMON ] || exit 1 +[ -r $CONFIG_FILE ] || exit 1 + + +RETVAL=0 +prog="tellstickd" +desc="remote switch daemon" + +start() { + log_begin_msg "Starting $desc ($prog): " + start-stop-daemon --start --quiet --pidfile "$PID_FILE" --name $NAME --exec $DAEMON -- --daemon --config $CONFIG_FILE --logfile $LOG_FILE $OPTIONS + log_end_msg $? + +} + +stop() { + log_begin_msg "Shutting down $desc ($prog): " + start-stop-daemon --stop --quiet --pidfile "$PID_FILE" --name $NAME + log_end_msg $? +} + +restart() { + stop + start +} + +reload() { + log_begin_msg "Reloading $desc ($prog): " + start-stop-daemon --stop --quiet --pidfile "$PID_FILE" --name $NAME --signal 1 + log_end_msg $? +} + +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + restart + ;; + reload) + reload + ;; + + *) + echo $"Usage: $0 {start|stop|restart|reload}" + RETVAL=1 +esac + +exit $RETVAL From 7596c989e4b08dc659002cda251eb8f890d120d6 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 18 Feb 2008 21:39:31 +0000 Subject: [PATCH 0021/2215] Changed sunset calculation parameters. Added init script for Debian and adaptions of tellstickd. All contributions of Anders Betner. --- tellstickd/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/README b/tellstickd/README index 842efac1..6ad9379a 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -14,7 +14,7 @@ Installation 0. Install rfcmd and necessary perl modules (on a typical Fedora/Centos/RHEL with the necessary repos installed, this should do it for you: yum install perl-DateTime perl-DateTime-Event-Sunrise). 1. Copy the file tellstickd-version/tellstickd to /usr/local/bin/ 2. Copy the file tellstickd-version/tellstickd.conf to /etc/ -3. If you have a Redhat-type system (like RHEL, Centos or Fedora), copy the script found under tellstickd-version/init_script to /etc/rc.d/init.d, this way you can control the script as any other service, easily make it start at boot (with chkconfig --level 35 tellstickd on). +3. Copy the suitable init script found under tellstickd-version/init_script to /etc/rc.d/init.d, this way you can control the script as any other service, easily make it start at boot (with chkconfig --level 35 tellstickd on). The file init_script/tellstickd is a Redhat type script whereas init_script/tellstickd.debian not unexpectedly should work on Debian type systems. 4. Remember to make the perl-script and init script executable. As root chmod 755 /usr/local/bin/tellstickd /etc/rc.d/init.d/tellstickd Configuration From a1b0c20786ab6a2630cf7c539d14ca6a89b53dab Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 19 Feb 2008 07:14:44 +0000 Subject: [PATCH 0022/2215] Minor edit. --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index a10c77fb..1cbe9306 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -17,7 +17,7 @@ $LOG_FILE = "/var/log/tellstickd"; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; -$VERSION = "0.3.4"; +$VERSION = "0.3.5"; # Structure of the configurations to be read; From 8b8daa616d3e6dbb7ec2ef9fb6743c48aaf72b73 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 19 Feb 2008 17:38:14 +0000 Subject: [PATCH 0023/2215] Added a patch from Anders Betner (thanks). --- tellstickd/tellstickd | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 1cbe9306..c8193353 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -13,6 +13,9 @@ $RFCMD = "/usr/local/bin/rfcmd"; $TELLSTICK_DEVICE = "/dev/tellstick"; $CONFIG_FILE = "/etc/tellstickd.conf"; $LOG_FILE = "/var/log/tellstickd"; +$pidFile = '/var/run/tellstickd.pid'; + + # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). $AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; @@ -128,7 +131,8 @@ sub rfcmd_exec { # Action = 1 means turn device on, 0 turn device off if ($action == 1) { # Only turn the device on if it is not already turned on to avoid flashing dimmers. - if ($device_cfg[$device_id][22] == 0) { + # and check that it is not disabled by on/off time set to -1 in the config file + if ($device_cfg[$device_id][22] == 0 && $device_cfg[$device_id][23] != -1)) { printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 1`; $device_cfg[$device_id][22] = 1; @@ -140,7 +144,7 @@ sub rfcmd_exec { } } elsif ($action == 0) { - if ($device_cfg[$device_id][22] == 1) { + if ($device_cfg[$device_id][22] == 1 && $device_cfg[$device_id][24] != -1)) { printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 0`; $device_cfg[$device_id][22] = 0; @@ -421,7 +425,8 @@ sub usageprompt printf("-c, --config filename Searchpath to configuration file, if not given $CONFIG_FILE is assumed.\n"); printf("-d, --daemon Run the program as a daemon and write a logfile.\n"); printf("-h, --help Show this message and exit.\n"); - printf("-l, --logfile filename Redirect daemon logs to filename. Default $LOG_FILE\n"); + printf("-l, --logfile filename Redirect daemon logs to filename. Default $LOG_FILE\n"); + printf("--nopid Do not write process id into file $PIDFILE\n"); } @@ -450,6 +455,9 @@ while ($i < $#ARGV) { usageprompt(); exit; } + elsif ($ARGV[$i+1] =~ /^--nopid$/) { + $write_pid = $NO; + } elsif ($ARGV[$i+1] =~ /^-l$/ || $ARGV[$i+1] =~ /^--logfile$/) { $output_to_logfile = $YES; $i++; @@ -477,10 +485,11 @@ if ($make_daemon == $YES) { } # Create pidfile -my $pidFile = '/var/run/tellstickd.pid'; -open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; -print PIDFILE $$; -close PIDFILE; +if (write_pid == $YES) { + open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; + print PIDFILE $$; + close PIDFILE; +} if (length($conf_file) < 1) { $conf_file = $CONFIG_FILE; From 33f719a988b5b36a3b361a69f5923a173b5eb47f Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 19 Feb 2008 18:32:23 +0000 Subject: [PATCH 0024/2215] Fixed a minor bug on lines 135 and 147. --- tellstickd/tellstickd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index c8193353..25774bb9 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -132,7 +132,7 @@ sub rfcmd_exec { if ($action == 1) { # Only turn the device on if it is not already turned on to avoid flashing dimmers. # and check that it is not disabled by on/off time set to -1 in the config file - if ($device_cfg[$device_id][22] == 0 && $device_cfg[$device_id][23] != -1)) { + if ($device_cfg[$device_id][22] == 0 && $device_cfg[$device_id][23] != -1) { printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 1`; $device_cfg[$device_id][22] = 1; @@ -144,7 +144,7 @@ sub rfcmd_exec { } } elsif ($action == 0) { - if ($device_cfg[$device_id][22] == 1 && $device_cfg[$device_id][24] != -1)) { + if ($device_cfg[$device_id][22] == 1 && $device_cfg[$device_id][24] != -1) { printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 0`; $device_cfg[$device_id][22] = 0; From a864dd50b5b8d5d4ad411814bf7fc3135ae9bac9 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 19 Feb 2008 19:00:57 +0000 Subject: [PATCH 0025/2215] --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 25774bb9..7e572d0d 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -426,7 +426,7 @@ sub usageprompt printf("-d, --daemon Run the program as a daemon and write a logfile.\n"); printf("-h, --help Show this message and exit.\n"); printf("-l, --logfile filename Redirect daemon logs to filename. Default $LOG_FILE\n"); - printf("--nopid Do not write process id into file $PIDFILE\n"); + printf("--nopid Do not write process id into file $pidFile\n"); } From b1b178084fca2739ff17fb4421260adbc22e2b8f Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 19 Feb 2008 19:14:16 +0000 Subject: [PATCH 0026/2215] Fixed a bug which caused the the program to stick in an eternal loop when on and off times were the same. The problem was within the function randomize_off --- tellstickd/tellstickd | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 7e572d0d..cb453d2c 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -224,6 +224,11 @@ sub randomize_on { my $device_id = $_[0]; + # If the on- and off times are the same, just return + if ($device_cfg[$device_id][23] eq $device_cfg[$device_id][24]) { + return; + } + (my $random_hour, my $random_minute) = $device_cfg[$device_id][8] =~ /(.*)\:(.*)/; my $rand_res = int(rand(60 * $random_hour + $random_minute)); @@ -247,6 +252,11 @@ sub randomize_off { my $device_id = $_[0]; + # If the on- and off times are the same, just return + if ($device_cfg[$device_id][23] eq $device_cfg[$device_id][24]) { + return; + } + (my $random_hour, my $random_minute) = $device_cfg[$device_id][9] =~ /(.*)\:(.*)/; my $rand_res = int(rand(60 * $random_hour + $random_minute)); @@ -369,7 +379,7 @@ sub read_config } if (is_time_format_correct($device_cfg[$i][8]) == $NO) { - die("$PROGRAM_NAME: Format of on interfval for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][8]\n"); + die("$PROGRAM_NAME: Format of on interval for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][8]\n"); } if (is_time_format_correct($device_cfg[$i][9]) == $NO) { @@ -559,6 +569,7 @@ while (1) { } } + ################################################################################################### # Below the required actions are performed for each device From f6ed1545bdc2abb7542aecfda97a567a8b218159 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 19 Feb 2008 20:56:16 +0000 Subject: [PATCH 0027/2215] Update is_time_format_correct. Added extra delay after each rfcmd call to get more robust operation. --- tellstickd/README | 17 +------------- tellstickd/tellstickd | 54 +++++++++++++++---------------------------- 2 files changed, 19 insertions(+), 52 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 6ad9379a..99e52e32 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -33,23 +33,8 @@ This software is freely distributable under the GNU General Public License, the full content of the license is included in the file LICENSE. Bug reports are welcome, but even more appreciated are patches with the solution to the problem. -Revision history -================= -2008-02-18 0.3.5 Changed sunset calculation parameters. Added init script for Debian and adaptions of tellstickd. All contributions of Anders Betner. -2008-02-17 0.3.4 Now possible to use a minus sign (-) when setting and -2008-02-15 0.3.3 General improvements. -2008-02-15 0.3.2 Corrected a fatal bug regarding switch logic. -2008-02-15 0.3.1 Changed update interval back from 50 to 60 seconds. -2008-02-14 0.3.0 New feature: On- and off times can be randomized within a given interval. Changed update interval from 60 to 50 seconds. -2008-02-12 0.2.1 Changed behaviour when program is called without argument. Now presents: Try "tellstickd --help" for more information. -2008-02-11 0.2.0 Added support for SARTANO devices. General code cleanups. -2008-02-11 0.1.4 Completely new switch logic, hopefully more robust with fewer bugs. -2008-02-10 0.1.3 Modified switch logic. When dawn is before on-time, lights are not switched on. If dusk time is after off time, lights are not switched on. -2008-01-30 0.1.2 Corrected a bug regarding datetimelocal. -2008-01-15 0.1.1 Fixed some bugs. Added logfile capability. -2008-01-11 0.1.0 Initial release - Author ================= Magnus Juntti mjuntti@gmail.com + diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index cb453d2c..e57c1051 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -136,7 +136,7 @@ sub rfcmd_exec { printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 1`; $device_cfg[$device_id][22] = 1; - + sleep(1); return; } else { @@ -148,7 +148,7 @@ sub rfcmd_exec { printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 0`; $device_cfg[$device_id][22] = 0; - + sleep(1); return; } else { @@ -281,40 +281,13 @@ sub randomize_off sub is_time_format_correct { my $time = $_[0]; - my $number_of_matches = 0; - my $tmp = $time; - - # Remove a leading signs, if it exists - $time =~ s/^.*?[0-9]//g; - - if (length($time) < 4 || length($time) > 5) { - return $NO; + (my $hour, my $minute) = $time =~ /^-?(\d\d)\:(\d\d)$/; + if ($hour && $minute) { + if ($hour >=0 && $hour <= 23 && $minute >= 0 && $minute <= 59) { + return $YES; + } } - - while ($tmp =~ /\:/g) { - $number_of_matches++; - } - - if ($number_of_matches != 1) { - return $NO; - } - - (my $hour, my $minute) = $time =~ /^(.*?)\:(.*?)$/; - - if ($hour !~ /^[0-9]+$/) { - return $NO; - } - - if ($minute !~ /^[0-9]+$/) { - return $NO; - } - - if ($hour < 0 || $hour > 23 || $minute < 0 || $minute > 59) { - return $NO; - } - - - return $YES; + return $NO; } sub read_config @@ -521,6 +494,8 @@ else { # Now to the eternal loop my $first_loop = $YES; while (1) { + $n_rfcmd_calls = 0; + # What is the current time ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); $year = 1900 + $yearOffset; @@ -580,9 +555,11 @@ while (1) { if ($device_cfg[$i][5] == $YES) { if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21], $current_time) == $NO) { rfcmd_exec($i, 1); + $n_rfcmd_calls++; } else { rfcmd_exec($i, 0); + $n_rfcmd_calls++; } } @@ -591,9 +568,11 @@ while (1) { else { if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES) { rfcmd_exec($i, 1); + $n_rfcmd_calls++; } else { rfcmd_exec($i, 0); + $n_rfcmd_calls++; } } @@ -601,5 +580,8 @@ while (1) { } $first_loop = $NO; - sleep(60); # Wait a while until next round [seconds]. + + if ($n_rfcmd_calls < 30) { + sleep(60 - 2*$n_rfcmd_calls); # Wait a while until next round [seconds]. If rfcmd has been called, reduce this figure by 2 seconds per call. + } } From 813d72861d9445eff5e4398626032a72bdbf4fc7 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 19 Feb 2008 21:56:11 +0000 Subject: [PATCH 0028/2215] All configurations now possible to make in the tellstickd.conf file (many thanks to Anders Betner). --- tellstickd/README | 3 ++ tellstickd/tellstickd | 56 ++++++++++++++++++++++++++++++++------ tellstickd/tellstickd.conf | 23 ++++++++++++++++ 3 files changed, 74 insertions(+), 8 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index 99e52e32..fe4a2e46 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -38,3 +38,6 @@ Author Magnus Juntti mjuntti@gmail.com +Co-author +================= +Anders Betnér diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index e57c1051..09eead6b 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -99,7 +99,7 @@ sub is_inbetween_times $time1 =~ s/^0*//; $time2 =~ s/^0*//; - # If we pass midnight, the following has to be checked + # If we pass midnight, the following has to be checked/done if ($time2 <= $time1) { $time2 += 2400; } @@ -136,7 +136,7 @@ sub rfcmd_exec { printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 1`; $device_cfg[$device_id][22] = 1; - sleep(1); + return; } else { @@ -148,7 +148,7 @@ sub rfcmd_exec { printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); `$RFCMD $RFCMD_OPTIONS 0`; $device_cfg[$device_id][22] = 0; - sleep(1); + return; } else { @@ -300,7 +300,11 @@ sub read_config my $i = 0; while ($_ = ) { - if ($_ !~ /^\#/ && $_ !~ /^\s/ && $_ !~ /^\n/) { + if ($_ =~ /^[\#|\s|\n]/) { + # skip lines beginning with # or space or just a new line + next; + } + if ($_ =~ /^[NEXA|SARTANO]/ ) { chomp($_); @inrad = split /\s+/, $_; $device_cfg[$i][0] = $inrad[0]; # Protocol @@ -315,7 +319,7 @@ sub read_config $device_cfg[$i][9] = $inrad[9]; # Off time random interval $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched of at startup $device_cfg[$i][23] = $device_cfg[$i][3]; # Original on time is stored here pos 3 will be used for random on times - $device_cfg[$i][24] = $device_cfg[$i][4]; # Original off time is stored here pos 4 will be used for random on times + $device_cfg[$i][24] = $device_cfg[$i][4]; # Original off time is stored here pos 4 will be used for random off times if ($device_cfg[$i][0] eq "SARTANO") { @@ -389,12 +393,48 @@ sub read_config } $i++; + next; + } + # Try to get config parameter name and value + (my $param, my $value) = $_ =~ /\s*(\w+)\s*=\s*([a-zA-Z0-9_\/\.]*)/; + if ($param && $value) { + print "$param = $value\n"; + if ($param eq 'latitude') { + $Latitude = $value; + next; + } + if ($param eq 'longitude') { + $LONGITUDE = $value; + next; + } + if ($param eq 'timezone') { + $TIMEZONE = $value; + next; + } + if ($param eq 'rfcmd') { + $RFCMD = $value; + next; + } + if ($param eq 'tellstick_device') { + $TELLSTICK_DEVICE = $value; + next; + } + if ($param eq 'log_file') { + $LOG_FILE = $value; + next; + } + if ($param eq 'pid_file') { + $pidFile = $value; + next; + } + die ("$PROGRAM_NAME: Unknown config parameter $param = $value\n"); + } + else { + die("$PROGRAM_NAME: Unknown config file line $_\n"); } } - - return $i; - close(CFG_FILE); + return $i; } sub usageprompt diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 399b7337..6427c88c 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -1,4 +1,27 @@ # Tellstickd file for control of remote switches with rfcmd. + +# To be able to calculate sunrise and sunset times tellstickd needs to know your position +# Your latitude +latitude = 65.603 + +# Your longitude +longitude = 22.18 + +# Your timezone +timezone = Europe/Stockholm + +# Where to find the rfcmd command +rfcmd = /usr/local/bin/rfcmd + +# The tellstick device name +tellstick_device = /dev/tellstick + +# Where to put the log file +log_file = /var/log/tellstickd + +# Where to put the pid file +pid_file = /var/run/tellstickd.pid + # # # (no = 0, yes = 1) From 00dc68bd1bd92cbf2d6209f89a087b4d91feee8e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Feb 2008 14:15:53 +0000 Subject: [PATCH 0029/2215] Added project "Systray" --- systray/src/SysTray_sv.ts | 41 +++++ systray/src/icon.cpp | 200 ++++++++++++++++++++++ systray/src/icon.h | 51 ++++++ systray/src/images/bell.png | Bin 0 -> 1803 bytes systray/src/images/lamp-off.png | Bin 0 -> 1453 bytes systray/src/images/lamp-on.png | Bin 0 -> 1478 bytes systray/src/images/preferences-system.png | Bin 0 -> 2129 bytes systray/src/images/system-log-out.png | Bin 0 -> 1725 bytes systray/src/images/systray.ico | Bin 0 -> 13094 bytes systray/src/main.cpp | 47 +++++ systray/src/resource.qrc | 9 + systray/src/src.pro | 19 ++ systray/src/systray.rc | 1 + systray/systray.pro | 4 + 14 files changed, 372 insertions(+) create mode 100644 systray/src/SysTray_sv.ts create mode 100644 systray/src/icon.cpp create mode 100644 systray/src/icon.h create mode 100644 systray/src/images/bell.png create mode 100644 systray/src/images/lamp-off.png create mode 100644 systray/src/images/lamp-on.png create mode 100644 systray/src/images/preferences-system.png create mode 100644 systray/src/images/system-log-out.png create mode 100644 systray/src/images/systray.ico create mode 100644 systray/src/main.cpp create mode 100644 systray/src/resource.qrc create mode 100644 systray/src/src.pro create mode 100644 systray/src/systray.rc create mode 100644 systray/systray.pro diff --git a/systray/src/SysTray_sv.ts b/systray/src/SysTray_sv.ts new file mode 100644 index 00000000..5767f648 --- /dev/null +++ b/systray/src/SysTray_sv.ts @@ -0,0 +1,41 @@ + + + + Icon + + + TellStick + TellStick + + + + &On + &PÃ¥ + + + + O&ff + &Av + + + + &Configure devices + &Konfigurera enheter + + + + &Quit + &Avsluta + + + + Error + Fel + + + + An error occurred while trying to transmit + Ett fel uppstod vid försök att sända + + + diff --git a/systray/src/icon.cpp b/systray/src/icon.cpp new file mode 100644 index 00000000..5ca35f29 --- /dev/null +++ b/systray/src/icon.cpp @@ -0,0 +1,200 @@ +// +// C++ Implementation: icon +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "icon.h" +#include +#include +#include +#include +#include "TellUsbD101.h" + +Icon::Icon() + : QObject() +{ + this->setMenu(); + connect( &i, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason))); + i.setIcon( QIcon(":/images/lamp-on.png") ); + i.setToolTip( tr("TellStick") ); + i.show(); +} + + +Icon::~Icon() +{ +} + + +/** + * @fn Icon::activated( QSystemTrayIcon::ActivationReason reason ) + */ +void Icon::activated( QSystemTrayIcon::ActivationReason reason ) +{ + if (reason == QSystemTrayIcon::DoubleClick) { + if (hasTelldusSetup()) { + configure(); + } + } +} + +/** + * @fn Icon::bell() + */ +void Icon::bell() +{ + QAction *action = (QAction *) sender(); + if (!devBell( action->data().toInt() )) + i.showMessage( tr("Error"), tr("An error occurred while trying to transmit"), QSystemTrayIcon::Critical ); +} + +/** + * @fn Icon::dim() + */ +void Icon::dim() +{ + QAction *action = (QAction *) sender(); + int intId = action->data().toString().section(":", 0, 0).toInt(); + int intLevel = action->data().toString().section(":", 1, 1).toInt(); + //i.showMessage( "", QString::number(intId)); + if (!devDim( intId, intLevel )) + i.showMessage( tr("Error"), tr("An error occurred while trying to transmit"), QSystemTrayIcon::Critical ); +} + +/** + * @fn Icon::on() + */ +void Icon::on() +{ + QAction *action = (QAction *) sender(); + if (!devTurnOn( action->data().toInt() )) + i.showMessage( tr("Error"), tr("An error occurred while trying to transmit"), QSystemTrayIcon::Critical ); +} + +/** + * @fn Icon::off() + */ +void Icon::off() +{ + QAction *action = (QAction *) sender(); + if (!devTurnOff( action->data().toInt() )) + i.showMessage( tr("Error"), tr("An error occurred while trying to transmit"), QSystemTrayIcon::Critical ); +} + + +/** + * @fn Icon::configure() + */ +void Icon::configure() +{ + QProcess *process = new QProcess(this); + connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(setMenu())); + process->setWorkingDirectory(QCoreApplication::applicationDirPath()); + process->start("TelldusSetup.exe"); +} + + +/** + * @fn Icon::setMenu() + */ +void Icon::setMenu() +{ + menu.clear(); + + int intNum = devGetNumberOfDevices(); + int index = 0; + while (index < intNum) { + addDevice(index, &menu); + index++; + } + + menu.addSeparator(); + + if (hasTelldusSetup()) { + QAction *configure = menu.addAction(tr("&Configure devices")); + connect(configure, SIGNAL(triggered()), this, SLOT(configure())); + configure->setIcon( QIcon(":/images/preferences-system.png") ); + } + + QAction *quit = menu.addAction(tr("&Quit")); + quit->setIcon( QIcon(":/images/system-log-out.png") ); + connect(quit, SIGNAL(triggered()), qApp, SLOT(quit())); + + i.setContextMenu(&menu); + +} + +void Icon::addDevice( int index, QMenu *menu ) { + int intId = devGetDeviceId(index); + QMenu *m = menu->addMenu( devGetName(intId) ); + + int methods = devMethods(intId); + if (methods & TELLSTICK_TURNON) { + QAction *on = m->addAction(tr("&On")); + on->setIcon(QIcon(":/images/lamp-on.png")); + on->setData( intId ); + connect( on, SIGNAL(triggered()), this, SLOT(on())); + } + + if (methods & TELLSTICK_DIM) { + QAction *dim = m->addAction(tr("90%")); + dim->setData( QString("%1:230").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("80%")); + dim->setData( QString("%1:204").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("70%")); + dim->setData( QString("%1:179").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("60%")); + dim->setData( QString("%1:153").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("50%")); + dim->setData( QString("%1:128").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("40%")); + dim->setData( QString("%1:102").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("30%")); + dim->setData( QString("%1:77").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("20%")); + dim->setData( QString("%1:51").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("10%")); + dim->setData( QString("%1:25").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + } + + if (methods & TELLSTICK_TURNON) { + QAction *off = m->addAction(tr("O&ff")); + off->setData( intId ); + off->setIcon(QIcon(":/images/lamp-off.png")); + connect( off, SIGNAL(triggered()), this, SLOT(off())); + } + + if (methods & TELLSTICK_BELL) { + QAction *bell = m->addAction(tr("&Bell")); + bell->setData( intId ); + bell->setIcon(QIcon(":/images/bell.png")); + connect( bell, SIGNAL(triggered()), this, SLOT(bell())); + } +} + +bool Icon::hasTelldusSetup() { + return QFile::exists("TelldusSetup.exe"); +} diff --git a/systray/src/icon.h b/systray/src/icon.h new file mode 100644 index 00000000..68243342 --- /dev/null +++ b/systray/src/icon.h @@ -0,0 +1,51 @@ +// +// C++ Interface: icon +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef ICON_H +#define ICON_H + +#include +#include + +/** + @author Micke Prag +*/ +class Icon : public QObject +{ + Q_OBJECT +public: + Icon(); + + ~Icon(); + +protected: + QSystemTrayIcon i; + QMenu menu; + +protected slots: + void activated( QSystemTrayIcon::ActivationReason reason ); + void setMenu(); + +private slots: + void bell(); + void dim(); + void on(); + void off(); + +public slots: + void configure(); + +private: + void addDevice( int index, QMenu *menu ); + static bool hasTelldusSetup(); +}; + +#endif diff --git a/systray/src/images/bell.png b/systray/src/images/bell.png new file mode 100644 index 0000000000000000000000000000000000000000..7876598021f853aa10c9502cc3b260d58d2b08e7 GIT binary patch literal 1803 zcmV+m2lV)fP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iO7w z5F;6!D73u*00xUmL_t(o!_}8tY+S_|$A2?(=A1pd>-DbhiIX^vO-Lb$b0di;D2>{x z&_)RLBGEqeq4fGdQAHI&C8$)WP=&-(U#eDAl`24`O@so1DpF}^5?V+oPSoHyapL&8 zw%3>S?zx}o14gPqN*y~z>PY{G`E=%+pZ?!>Ml*s{j2C{^y}=8tuO`NBG-+}sG5Xkd ze%>G7NDi^m&7Xg2+ktt%`IwQ7f3dU})QY?P#pzI5?iU_>;?E1q%_CO|kXjv23#a3e z?>=$#(6=5t@%b=h z;H%zI-zz^fdS&ux&ux3H>FJ4@l{&Y7@qwRI{wIGy7``c#vZYtk`KgKI@chi+_t$jP z3P~`>+|&rulamBdvnjOhdaJQ{-Q!z!e*X2F+5?uQ9FW`nntXfs!YhZj+-?_&&7HV~ zUh<_|DV91=!8vj9)RX%!pF95QrSoq-c+*Odrl%y(T3g8fYT(=-dUxN|hiyZgb2F2>v-t^JS0hM}vWgG} zX=N};og|zD6nVSG*zj2^^s3LUx&&!@N&t<4Z-2dBAELdzNNQq0AP`6?5Tqp0Bqpt6 zXI(NG@D@f1z1baqKk;hsY8}vND!L=z>`UV@Y+Ha)7$jg2LINoQA3Kx5(iwzQ)aNe~ z1wJN?_O1#*2;nBN`?)Br+afJvDMgwXAYJ;vAS5Uyuyh8?aZ#2g@Mj6UMT|+etQf$U z(*h`jzPzhe9mBC>gfJv=h)L5AHYY_0fu%Ltaj~?EWoL+z7~fkU3jChcIG~I%MZXs8 z4E+flTOkl6QAnCb2n>i6Ar+RBLpxb4+eK;zDJ5~_K^kpX4S-H!*&9b;%gppJQW%Ue z#BoFtCm53;FbJVgRtD|3*qJQaamhLsNfJ@3R@SZtz=Dlq=o(;1V?z|wiKB=# z6&PbMCPu0Z+IF#>EVi3PYa8F2B@P$!Y3zxWIG~I%#raCOt#Y-WJU*cp5cq;9SR{@D z;#iO-F=|1>WjmmM@z%CfkDpx^`BU| zb~-n8(X+LWHJjRT3kxVEkTOE*9BHaqtik+(AyM<3IQbr#d`k;ZT{gh!)4vtQh^)8h zJ{*Qa;?mXkC>9z>$Eu7Ek5evtj9fFU-5Ao=xsgmZk5{WQH9pMv@Brnpi)cII)*anc zDiiG4(su_iv}}M)UE5W4-gzcioW5gt=wC!}o#w7JOroz76O>EeZedNe^W!>Sczn4iQH_ z9UX0-x$oYCr=LIiw@cS`V03JvTG7?P)`oiT)*XE~xe~}M3zbP0E8}(?UwfH?>e| zUq`9ElZK`y9M=T_0*fd}sm;$)ug;tP^COibuMNEX;*o#+qP-<|VeraK`riQLk}SYp zk^>YP3)!B{x2*ZprmmLWb!&>9ZEeM-QgdUjp)qe4iAE)9vYn2e>mmFI#29N)T@o)CC)0DI&AgBNU002ovPDHLkV1nP8WRU;> literal 0 HcmV?d00001 diff --git a/systray/src/images/lamp-off.png b/systray/src/images/lamp-off.png new file mode 100644 index 0000000000000000000000000000000000000000..007a177832a03e7c3cc84a343591e8bf67f79cd1 GIT binary patch literal 1453 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 TV_b!o00000NkvXXu0mjf;6OQF literal 0 HcmV?d00001 diff --git a/systray/src/images/systray.ico b/systray/src/images/systray.ico new file mode 100644 index 0000000000000000000000000000000000000000..9aeccbdc7fc3eb03dbcad03a6355058c373f37df GIT binary patch literal 13094 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 literal 0 HcmV?d00001 diff --git a/systray/src/main.cpp b/systray/src/main.cpp new file mode 100644 index 00000000..295fc7c2 --- /dev/null +++ b/systray/src/main.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2006 by Micke Prag * + * micke.prag@telldus.se * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#include +#include +#include +#include "icon.h" + +int main(int argc, char *argv[]) +{ + QApplication a( argc, argv ); + + QCoreApplication::setOrganizationName("Telldus"); + QCoreApplication::setOrganizationDomain("telldus.se"); + QCoreApplication::setApplicationName("SysTray"); + + Q_INIT_RESOURCE(resource); + + QTranslator qtTranslator; + qtTranslator.load("qt_" + QLocale::system().name()); + a.installTranslator(&qtTranslator); + + QTranslator myappTranslator; + myappTranslator.load("SysTray_" + QLocale::system().name()); + a.installTranslator(&myappTranslator); + + Icon icon; + return a.exec(); +} diff --git a/systray/src/resource.qrc b/systray/src/resource.qrc new file mode 100644 index 00000000..325beebe --- /dev/null +++ b/systray/src/resource.qrc @@ -0,0 +1,9 @@ + + + images/bell.png + images/lamp-on.png + images/lamp-off.png + images/preferences-system.png + images/system-log-out.png + + diff --git a/systray/src/src.pro b/systray/src/src.pro new file mode 100644 index 00000000..c3669dde --- /dev/null +++ b/systray/src/src.pro @@ -0,0 +1,19 @@ +TEMPLATE = app + +SOURCES += main.cpp \ +icon.cpp +#menu.cpp +LIBS += -ltellusbd101 -L../bin +win32{ + TARGET = ../../bin/SysTray + CONFIG += release +} +unix{ + TARGET = ../bin/systray + CONFIG += debug +} +HEADERS += icon.h +#menu.h +RESOURCES += resource.qrc +RC_FILE = systray.rc +TRANSLATIONS = SysTray_sv.ts \ No newline at end of file diff --git a/systray/src/systray.rc b/systray/src/systray.rc new file mode 100644 index 00000000..3d90079c --- /dev/null +++ b/systray/src/systray.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "images/systray.ico" diff --git a/systray/systray.pro b/systray/systray.pro new file mode 100644 index 00000000..b2d719f0 --- /dev/null +++ b/systray/systray.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = src +CONFIG += warn_on + From d2a7fca21b48b31a8a5c5264c644c4780a47dd6f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Feb 2008 14:22:37 +0000 Subject: [PATCH 0030/2215] Added project "rfcmd" --- rfcmd/CMakeLists.txt | 19 +++ rfcmd/COPYING | 340 +++++++++++++++++++++++++++++++++++++++++++ rfcmd/Makefile | 11 ++ rfcmd/build.sh | 5 + rfcmd/rfcmd.c | 233 +++++++++++++++++++++++++++++ 5 files changed, 608 insertions(+) create mode 100644 rfcmd/CMakeLists.txt create mode 100644 rfcmd/COPYING create mode 100644 rfcmd/Makefile create mode 100644 rfcmd/build.sh create mode 100644 rfcmd/rfcmd.c diff --git a/rfcmd/CMakeLists.txt b/rfcmd/CMakeLists.txt new file mode 100644 index 00000000..c9b2d9af --- /dev/null +++ b/rfcmd/CMakeLists.txt @@ -0,0 +1,19 @@ +PROJECT(rfcmd) + +SET(rfcmd_SRCS + rfcmd.c +) + +IF(${RFCMD_DEBUG}) + ADD_DEFINITIONS( -DRFCMD_DEBUG ) +ENDIF(${RFCMD_DEBUG}) + +INCLUDE_DIRECTORIES( + /usr/src/linux/include +) + +ADD_EXECUTABLE(rfcmd + ${rfcmd_SRCS} +) + +INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) \ No newline at end of file diff --git a/rfcmd/COPYING b/rfcmd/COPYING new file mode 100644 index 00000000..60549be5 --- /dev/null +++ b/rfcmd/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/rfcmd/Makefile b/rfcmd/Makefile new file mode 100644 index 00000000..77792ecd --- /dev/null +++ b/rfcmd/Makefile @@ -0,0 +1,11 @@ +FILES = rfcmd + +INCLUDEDIR = /usr/src/linux/include + +CFLAGS = -O2 -Wall + +all: $(FILES) + +clean: + rm -f $(FILES) *~ core + diff --git a/rfcmd/build.sh b/rfcmd/build.sh new file mode 100644 index 00000000..b3da439a --- /dev/null +++ b/rfcmd/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +make clean +make +echo rfcmd built! + diff --git a/rfcmd/rfcmd.c b/rfcmd/rfcmd.c new file mode 100644 index 00000000..d782d514 --- /dev/null +++ b/rfcmd/rfcmd.c @@ -0,0 +1,233 @@ +/**************************************************************************** + ** rfcmd.c *********************************************************** + **************************************************************************** + * + * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick + USB interface + * + * Copyright (C) 2007 Tord Andersson + * + * License: GPL v. 2 + * + */ + +#include +#include +#include +#include +#include +#include + +#define PROG_NAME "rfcmd" +#define PROG_VERSION "0.2" +/* #define RFCMD_DEBUG */ + +/* Local function declarations */ +int createNexaString(const char * pHouseStr, const char * pChannelStr, + const char * pOn_offStr, char * pTxStr, int waveman); +int createSartanoString(const char * pChannelStr, const char * pOn_offStr, + char * pTxStr); + +void printUsage(void); + +int main( int argc, char **argv ) +{ + struct termios tio; + int fd = -1; + char txStr[250]; + + + + if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) + { + + if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) + { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ + } + else if( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) + { + if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) + { + printUsage(); + exit(1); + } + } + else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) + { + + if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) + { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ + } + else /* protocol or parameters not recognized */ + { + printUsage(); + exit(1); + } + + +#ifdef RFCMD_DEBUG + printf("txStr: %s\n", txStr); +#endif + + if( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) + { + fprintf(stderr, "%s - Error opening %s\n", PROG_NAME, *(argv+1)); + exit(1); + } + + + if(strlen(txStr) > 0) + { + /* adjust serial port parameters */ + bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ + tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ + tio.c_iflag = IGNPAR; + tio.c_oflag = 0; + tcflush(fd, TCIFLUSH); + tcsetattr(fd,TCSANOW,&tio); + + write(fd, txStr, strlen(txStr)); + sleep(1); /* one second sleep to avoid device 'choking' */ + } + exit(0); +} + + +int createNexaString(const char * pHouseStr, const char * pChannelStr, + const char * pOn_offStr, char * pTxStr, int waveman) +{ + * pTxStr = '\0'; /* Make sure tx string is empty */ + int houseCode; + int channelCode; + int on_offCode; + int txCode = 0; + const int unknownCode = 0x6; + int bit; + int bitmask = 0x0001; + + houseCode = (int)((* pHouseStr) - 65); /* House 'A'..'P' */ + channelCode = atoi(pChannelStr) - 1; /* Channel 1..16 */ + on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ + +#ifdef RFCMD_DEBUG + printf("House: %d, channel: %d, on_off: %d\n", houseCode, channelCode, on_offCode); +#endif + + /* check converted parameters for validity */ + if((houseCode < 0) || (houseCode > 15) || // House 'A'..'P' + (channelCode < 0) || (channelCode > 15) || + (on_offCode < 0) || (on_offCode > 1)) + { + + } + else + { + /* b0..b11 txCode where 'X' will be represented by 1 for simplicity. + b0 will be sent first */ + txCode = houseCode; + txCode |= (channelCode << 4); + if (waveman && on_offCode == 0) { + } else { + txCode |= (unknownCode << 8); + txCode |= (on_offCode << 11); + } + + /* convert to send cmd string */ + strcat(pTxStr,"S"); + for(bit=0;bit<12;bit++) + { + if((bitmask & txCode) == 0) + { + /* bit timing might need further refinement */ + strcat(pTxStr," ` `"); /* 320 us high, 960 us low, 320 us high, 960 us low */ + /* strcat(pTxStr,"$k$k"); *//* 360 us high, 1070 us low, 360 us high, 1070 us low */ + } + else /* add 'X' (floating bit) */ + { + strcat(pTxStr," `` "); /* 320 us high, 960 us low, 960 us high, 320 us low */ + /*strcat(pTxStr,"$kk$"); *//* 360 us high, 1070 us low, 1070 us high, 360 us low */ + } + bitmask = bitmask<<1; + } + /* add stop/sync bit and command termination char '+'*/ + strcat(pTxStr," }+"); + /* strcat(pTxStr,"$}+"); */ + } + +#ifdef RFCMD_DEBUG + printf("txCode: %04X\n", txCode); +#endif + + return strlen(pTxStr); +} + +int createSartanoString(const char * pChannelStr, const char * pOn_offStr, + char * pTxStr) +{ + * pTxStr = '\0'; /* Make sure tx string is empty */ + int on_offCode; + int bit; + + on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ + +#ifdef RFCMD_DEBUG + printf("Channel: %s, on_off: %d\n", pChannelStr, on_offCode); +#endif + + /* check converted parameters for validity */ + if((strlen(pChannelStr) != 10) || + (on_offCode < 0) || (on_offCode > 1)) + { + + } + else + { + strcat(pTxStr,"S"); + for(bit=0;bit<=9;bit++) + { + if(strncmp(pChannelStr+bit, "1", 1) == 0) //If it is a "1" + { + strcat(pTxStr,"$k$k"); + } + else + { + strcat(pTxStr,"$kk$"); + } + } + if (on_offCode >= 1) + strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code + else + strcat(pTxStr,"$kk$$k$k"); //the "turn off"-code + + /* add stop/sync bit and command termination char '+'*/ + strcat(pTxStr,"$k+"); + } + +#ifdef RFCMD_DEBUG + printf("txCode: %04X\n", txCode); +#endif + + return strlen(pTxStr); + +} + +void printUsage(void) +{ + printf("%s %s - Send RF remote commands\n", PROG_NAME, PROG_VERSION); + printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n"); + printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); + printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN\n" ); + printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN: \n"); + printf("\t\t HOUSE_CODE: A..P\n\t\t CHANNEL: 1..16\n\t\t ON_OFF: 0..1\n" ); + printf("\t PROTOCOL ARGUMENTS - SARTANO: \n"); + printf("\t\t CHANNEL: 0000000000..1111111111\n\t\t ON_OFF: 0..1\n" ); + printf("Copyright(C) Tord Andersson 2007\r\n"); +} From 759d0c044122784a4e3be8a409a22830e16fa2c2 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Wed, 20 Feb 2008 17:15:47 +0000 Subject: [PATCH 0031/2215] Changed ill-spelled variable ($Latititue should be $LATITUDE). Write logfile is on by default. --- tellstickd/tellstickd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 09eead6b..a234d5c9 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -400,7 +400,7 @@ sub read_config if ($param && $value) { print "$param = $value\n"; if ($param eq 'latitude') { - $Latitude = $value; + $LATITUDE = $value; next; } if ($param eq 'longitude') { @@ -461,7 +461,7 @@ $NO = 0; $YES = 1; $conf_file = ""; $make_daemon = $NO; -$output_to_logfile = $NO; +$output_to_logfile = $YES; $i = -1; while ($i < $#ARGV) { From 5d4d7ac7ca7e7ec668295e17f3a95192e3e79cf8 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Wed, 20 Feb 2008 17:38:28 +0000 Subject: [PATCH 0032/2215] Minor cleanups. --- tellstickd/README | 13 ++++++++----- tellstickd/tellstickd | 2 -- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index fe4a2e46..b702939e 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -12,18 +12,23 @@ DateTime::Event::Sunrise Installation ================= 0. Install rfcmd and necessary perl modules (on a typical Fedora/Centos/RHEL with the necessary repos installed, this should do it for you: yum install perl-DateTime perl-DateTime-Event-Sunrise). + 1. Copy the file tellstickd-version/tellstickd to /usr/local/bin/ + 2. Copy the file tellstickd-version/tellstickd.conf to /etc/ + 3. Copy the suitable init script found under tellstickd-version/init_script to /etc/rc.d/init.d, this way you can control the script as any other service, easily make it start at boot (with chkconfig --level 35 tellstickd on). The file init_script/tellstickd is a Redhat type script whereas init_script/tellstickd.debian not unexpectedly should work on Debian type systems. -4. Remember to make the perl-script and init script executable. As root chmod 755 /usr/local/bin/tellstickd /etc/rc.d/init.d/tellstickd +4. Remember to make the perl-script and init scripts executable. As root chmod 755 /usr/local/bin/tellstickd /etc/rc.d/init.d/tellstickd Configuration ================= -1. In the very top of the perl file /usr/local/bin/tellstickd: +1. In tellstickd.conf: a. Set appropriate coordinates and timezone to suit your geographical location (further information: http://search.cpan.org/dist/DateTime-Event-Sunrise/lib/DateTime/Event/Sunrise.pm). b. Specifiy the rfcmd binary location. Default: /usr/local/bin/rfcmd c. Specify the tellstick device name. Default: /dev/tellstick d. If the default locations of the config and logfile not are according to your wishes, modify them here. Note 1: this can also be done with the tellstickd options --config and --logfile. Note 2: If you use the init script, these settings must be done in the init-script /etc/rc.d/init.d/tellstickd. + e. Add device configurations. Multiple definitions for each device are possible (avoid having on and off times of multiple definitions overlapping each other). + 2. If you would like this script to start at boot-time, on a RHEL/Centos/Fedora system, execute the following command chkconfig --level 35 tellstickd on @@ -33,11 +38,9 @@ This software is freely distributable under the GNU General Public License, the full content of the license is included in the file LICENSE. Bug reports are welcome, but even more appreciated are patches with the solution to the problem. -Author +Authors ================= Magnus Juntti mjuntti@gmail.com -Co-author -================= Anders Betnér diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index a234d5c9..a4e809e1 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -18,7 +18,6 @@ $pidFile = '/var/run/tellstickd.pid'; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). -$AUTHOR = "Magnus Juntti, mjuntti\@gmail.com"; $PROGRAM_NAME = "tellstickd"; $VERSION = "0.3.5"; @@ -440,7 +439,6 @@ sub read_config sub usageprompt { printf("This program is intended for control of Tellstick remote devices.\n"); - printf("Authour: $AUTHOR\n"); printf("Version: %s\n", $VERSION); printf("\nUsage: %s [options]\n", $PROGRAM_NAME); From b6fbe49e84cde8e8034cd499a200b2975459ec63 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Wed, 20 Feb 2008 19:18:13 +0000 Subject: [PATCH 0033/2215] Problems regarding the writing of pidfiles resolved. --- tellstickd/tellstickd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index a4e809e1..c3c59872 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -460,6 +460,7 @@ $YES = 1; $conf_file = ""; $make_daemon = $NO; $output_to_logfile = $YES; +$write_pid = $YES; $i = -1; while ($i < $#ARGV) { @@ -506,7 +507,7 @@ if ($make_daemon == $YES) { } # Create pidfile -if (write_pid == $YES) { +if ($write_pid == $YES) { open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; print PIDFILE $$; close PIDFILE; From 79ac83b6dce880098749bfc7d5d7b31cb2cfc2c4 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Wed, 20 Feb 2008 19:43:33 +0000 Subject: [PATCH 0034/2215] Added use strict and declared all necessary variables. --- tellstickd/tellstickd | 88 ++++++++++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 26 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index c3c59872..7ca15442 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -4,23 +4,49 @@ use POSIX; use DateTime; use DateTime::Event::Sunrise; use Time::Local; +use strict; # The following variables should be adapted to your geographical location and system setup -$LATITUDE = "65.603"; # 65.603N 22.18W -> LuleÃ¥, Sweden -$LONGITUDE = "22.18"; -$TIMEZONE = "Europe/Stockholm"; -$RFCMD = "/usr/local/bin/rfcmd"; -$TELLSTICK_DEVICE = "/dev/tellstick"; -$CONFIG_FILE = "/etc/tellstickd.conf"; -$LOG_FILE = "/var/log/tellstickd"; -$pidFile = '/var/run/tellstickd.pid'; - +my $LATITUDE = "65.603"; # 65.603N 22.18W -> LuleÃ¥, Sweden +my $LONGITUDE = "22.18"; +my $TIMEZONE = "Europe/Stockholm"; +my $RFCMD = "/usr/local/bin/rfcmd"; +my $TELLSTICK_DEVICE = "/dev/tellstick"; +my $CONFIG_FILE = "/etc/tellstickd.conf"; +my $LOG_FILE = "/var/log/tellstickd"; +my $pidFile = '/var/run/tellstickd.pid'; # You should not need to go beyond this point (unless you have found a bug or need to improve the functionality). -$PROGRAM_NAME = "tellstickd"; -$VERSION = "0.3.5"; +my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); +my @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun); +my $NO = 0; +my $YES = 1; +my @device_cfg; +my $conf_file = ""; +my $make_daemon = $NO; +my $output_to_logfile = $YES; +my $write_pid = $YES; +my $i = -1; +my $n_rfcmd_calls; +my $current_time; +my $number_of_devices; +my $Day; +my $Month; +my $Year; +my $Minute; +my $Hour; +my $Second; +my $WeekDay; +my $DayOfYear; +my $IsDST; +my $daylightSavings; +my $dayOfYear; +my $dayOfWeek; +my $dayOfMonth; +my $PROGRAM_NAME = "tellstickd"; +my $VERSION = "0.3.5"; # Structure of the configurations to be read; # $device_cfg[$i][0]; # Protocol, only NEXA and SARTANO supported so far by rfcmd @@ -50,6 +76,8 @@ sub daemonize { sub get_sunrise_time { + my $sunrise_time; + ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; $Month++; @@ -68,6 +96,8 @@ sub get_sunrise_time sub get_sunset_time { + my $sunset_time; + ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; $Month++; @@ -115,6 +145,7 @@ sub is_inbetween_times sub rfcmd_exec { my $device_id = $_[0]; my $action = $_[1]; + my $RFCMD_OPTIONS; if ($device_cfg[$device_id][0] eq "SARTANO") { $RFCMD_OPTIONS = "$TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1]"; @@ -165,6 +196,14 @@ sub add_time my $time1 = $_[0]; my $time2 = $_[1]; my $multiplier = 1; + my $hour; + my $min; + my $time1_hour; + my $time1_minute; + my $time2_hour; + my $time2_minute; + my $time1_epoch_seconds; + my $time2_offset_seconds; ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; @@ -195,6 +234,14 @@ sub subtract_time my $time1 = $_[0]; my $time2 = $_[1]; my $multiplier = 1; + my $hour; + my $min; + my $time1_hour; + my $time1_minute; + my $time2_hour; + my $time2_minute; + my $time1_epoch_seconds; + my $time2_offset_seconds; ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; @@ -292,6 +339,7 @@ sub is_time_format_correct sub read_config { my $input_file = $_[0]; + my @inrad; printf("$PROGRAM_NAME: Reading configuration file $conf_file\n"); @@ -453,16 +501,6 @@ sub usageprompt # ############## Main section ###################### -@months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); -@weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun); -$NO = 0; -$YES = 1; -$conf_file = ""; -$make_daemon = $NO; -$output_to_logfile = $YES; -$write_pid = $YES; - -$i = -1; while ($i < $#ARGV) { if ($i+1 <= $#ARGV) { if ($ARGV[$i+1] =~ /^--config$/ || $ARGV[$i+1] =~ /^-c$/) { @@ -536,11 +574,9 @@ while (1) { $n_rfcmd_calls = 0; # What is the current time - ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime(); - $year = 1900 + $yearOffset; - # $current_time = "$hour:$minute:$second, $weekDays[$dayOfWeek] $months[$month] $dayOfMonth, $year"; - $current_time = sprintf("%02d:%02d", $hour, $minute); - # printf("$PROGRAM_NAME: Time is $current_time\n"); + ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(); + $Year += 1900; + $current_time = sprintf("%02d:%02d", $Hour, $Minute); ################################################################################################### From ff0bc287a53bd96d30ba8e533fc359cf45f3ca30 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Wed, 20 Feb 2008 20:39:59 +0000 Subject: [PATCH 0035/2215] Minor cosmetic edits. --- tellstickd/tellstickd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 7ca15442..6190c6d7 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -341,7 +341,7 @@ sub read_config my $input_file = $_[0]; my @inrad; - printf("$PROGRAM_NAME: Reading configuration file $conf_file\n"); + printf("$PROGRAM_NAME: Reading configuration file $conf_file...\n"); open(CFG_FILE, "<$input_file") or die "$PROGRAM_NAME: Could not access config file: $conf_file\n"; @@ -445,7 +445,7 @@ sub read_config # Try to get config parameter name and value (my $param, my $value) = $_ =~ /\s*(\w+)\s*=\s*([a-zA-Z0-9_\/\.]*)/; if ($param && $value) { - print "$param = $value\n"; + printf("$PROGRAM_NAME: $param = $value\n"); if ($param eq 'latitude') { $LATITUDE = $value; next; From 361a972be7ca059490562e05e743be81593f2b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Thu, 21 Feb 2008 21:35:01 +0000 Subject: [PATCH 0036/2215] Allow config file parameters with negative values --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 6190c6d7..6528bd75 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -443,7 +443,7 @@ sub read_config next; } # Try to get config parameter name and value - (my $param, my $value) = $_ =~ /\s*(\w+)\s*=\s*([a-zA-Z0-9_\/\.]*)/; + (my $param, my $value) = $_ =~ /\s*(\w+)\s*=\s*(-?[a-zA-Z0-9_\/\.]*)/; if ($param && $value) { printf("$PROGRAM_NAME: $param = $value\n"); if ($param eq 'latitude') { From 489e8aaf8857cc1894659fccca3076f32437320a Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Sat, 23 Feb 2008 10:39:34 +0000 Subject: [PATCH 0037/2215] Added a possibility to apply each rule to specific weekdays. --- tellstickd/tellstickd | 99 ++++++++++++++++++++++++++------------ tellstickd/tellstickd.conf | 17 ++++--- 2 files changed, 79 insertions(+), 37 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 6528bd75..89b65f55 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -27,7 +27,6 @@ my $conf_file = ""; my $make_daemon = $NO; my $output_to_logfile = $YES; my $write_pid = $YES; -my $i = -1; my $n_rfcmd_calls; my $current_time; my $number_of_devices; @@ -46,7 +45,7 @@ my $dayOfWeek; my $dayOfMonth; my $PROGRAM_NAME = "tellstickd"; -my $VERSION = "0.3.5"; +my $VERSION = "0.4.0"; # Structure of the configurations to be read; # $device_cfg[$i][0]; # Protocol, only NEXA and SARTANO supported so far by rfcmd @@ -59,6 +58,7 @@ my $VERSION = "0.3.5"; # $device_cfg[$i][7]; # Time in advance when getting dark # $device_cfg[$i][8]; # On time random interval # $device_cfg[$i][9]; # Off time random interval +# $device_cfg[$i][10]; # Rule active these days [11234567], 1=monday, ... 7=sunday. # $device_cfg[$i][20]; # Sunrise off time, calculated in this program and stored here # $device_cfg[$i][21]; # Sunset on time, calculated in this program and stored here # $device_cfg[$i][22]; # Switch state, 0 = off, 1 = on @@ -329,13 +329,27 @@ sub is_time_format_correct my $time = $_[0]; (my $hour, my $minute) = $time =~ /^-?(\d\d)\:(\d\d)$/; if ($hour && $minute) { - if ($hour >=0 && $hour <= 23 && $minute >= 0 && $minute <= 59) { + if ($hour >= 0 && $hour <= 23 && $minute >= 0 && $minute <= 59) { return $YES; } } + return $NO; } +# Time format sanity check routine +sub is_rule_valid_today +{ + my $device_id = $_[0]; + my $current_day = $_[1]; + + if ($device_cfg[$device_id][10] =~ /$current_day/) { + return $YES; + } + + return $NO; +} + sub read_config { my $input_file = $_[0]; @@ -357,13 +371,14 @@ sub read_config $device_cfg[$i][0] = $inrad[0]; # Protocol $device_cfg[$i][1] = $inrad[1]; # Housecode A-P $device_cfg[$i][2] = $inrad[2]; # Channel 1-3 - $device_cfg[$i][3] = $inrad[3]; # On time - $device_cfg[$i][4] = $inrad[4]; # Off time - $device_cfg[$i][5] = $inrad[5]; # Off when bright - $device_cfg[$i][6] = $inrad[6]; # Off when bright delay - $device_cfg[$i][7] = $inrad[7]; # Time in advance when getting dark - $device_cfg[$i][8] = $inrad[8]; # On time random interval - $device_cfg[$i][9] = $inrad[9]; # Off time random interval + $device_cfg[$i][10] = $inrad[3]; # Rule valid days [1234567] + $device_cfg[$i][3] = $inrad[4]; # On time + $device_cfg[$i][4] = $inrad[5]; # Off time + $device_cfg[$i][5] = $inrad[6]; # Off when bright + $device_cfg[$i][6] = $inrad[7]; # Off when bright delay + $device_cfg[$i][7] = $inrad[8]; # Time in advance when getting dark + $device_cfg[$i][8] = $inrad[9]; # On time random interval + $device_cfg[$i][9] = $inrad[10]; # Off time random interval $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched of at startup $device_cfg[$i][23] = $device_cfg[$i][3]; # Original on time is stored here pos 3 will be used for random on times $device_cfg[$i][24] = $device_cfg[$i][4]; # Original off time is stored here pos 4 will be used for random off times @@ -410,9 +425,22 @@ sub read_config die("$PROGRAM_NAME: Format of off interval for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][9]\n"); } + if ($device_cfg[$i][10] =~ /[^1-7]/) { + die("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2]: Specified rule validity day out of range: $device_cfg[$i][10]\n"); + } + printf("$PROGRAM_NAME: $device_cfg[$i][0] device $device_cfg[$i][1]$device_cfg[$i][2] config:\n"); + + printf(" This rule is valid: "); + for (my $j = 1 ; $j <= 7 ; $j++) { + if ($device_cfg[$i][10] =~ /$j/) { + printf(" $weekDays[$j]"); + } + } + printf("\n"); + if ($device_cfg[$i][3] == -1) { printf(" On time: N/A\n"); } @@ -500,6 +528,7 @@ sub usageprompt # ############## Main section ###################### +my $i = -1; while ($i < $#ARGV) { if ($i+1 <= $#ARGV) { @@ -626,30 +655,40 @@ while (1) { for ($i = 0; $i < $number_of_devices; $i++) { - # First if we consider daytime off - if ($device_cfg[$i][5] == $YES) { - if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21], $current_time) == $NO) { - rfcmd_exec($i, 1); - $n_rfcmd_calls++; - } - else { - rfcmd_exec($i, 0); - $n_rfcmd_calls++; - } - } + # Lets check if the rule is to be applied today + if (is_rule_valid_today($i, $WeekDay) == $YES) { - # Then if daytime off is not considered - else { - if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES) { - rfcmd_exec($i, 1); - $n_rfcmd_calls++; + + # First if we consider daytime off + if ($device_cfg[$i][5] == $YES) { + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES && is_inbetween_times($device_cfg[$i][20], $device_cfg[$i][21], $current_time) == $NO) { + rfcmd_exec($i, 1); + $n_rfcmd_calls++; + } + else { + rfcmd_exec($i, 0); + $n_rfcmd_calls++; + } } + + + # Then if daytime off is not considered else { - rfcmd_exec($i, 0); - $n_rfcmd_calls++; + if (is_inbetween_times($device_cfg[$i][3], $device_cfg[$i][4], $current_time) == $YES) { + rfcmd_exec($i, 1); + $n_rfcmd_calls++; + } + else { + rfcmd_exec($i, 0); + $n_rfcmd_calls++; + } } - } + + + + } + } @@ -657,6 +696,6 @@ while (1) { $first_loop = $NO; if ($n_rfcmd_calls < 30) { - sleep(60 - 2*$n_rfcmd_calls); # Wait a while until next round [seconds]. If rfcmd has been called, reduce this figure by 2 seconds per call. + sleep(60 - 1*$n_rfcmd_calls); # Wait a while until next round [seconds]. If rfcmd has been called, reduce this figure by 1 second per call. } } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 6427c88c..f61aafb8 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -23,8 +23,11 @@ log_file = /var/log/tellstickd pid_file = /var/run/tellstickd.pid # -# +# # (no = 0, yes = 1) +# +# In valid day field, days are numbered 1=Monday, 2=Tuesday, ... , 7=Sunday. I.e. 1234567 means that the rule should be active every weekday. +# # Multiple definitions are possible for each device # # Setting and to the same means that the device will always be switched on. @@ -33,14 +36,14 @@ pid_file = /var/run/tellstickd.pid # place sometime between 22:15 and 22:44, with new randomized times set every night at 00:00. # # Time format xx:yy where xx is hour and yy is minute -# If no turn on time or turn off time should be used. Note this with -1. See the example line below. Only to be used on turn on or turn off times. -# NEXA A 1 -1 22:45 1 00:30 00:30 +# If no turn on time or turn off time should be used. Note this with -1. See the example line below only turning off at 22:45. Only to be used on turn on or turn off times. +# NEXA A 1 1234567 -1 22:45 1 00:30 00:30 # -# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning. On time will always be 05:30, off time will always be 22:45. -SARTANO 0000000000 0 05:30 22:45 1 00:30 00:15 00:00 00:00 +# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning. On time will always be 05:30, off time will always be 22:45. The rule only applies monday to wednesday. +SARTANO 0000000000 0 123 05:30 22:45 1 00:30 00:15 00:00 00:00 -# Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. On time will be between 06:30 and 06:39, off time will be between 22:05 and 22:24. -NEXA A 1 06:30 22:05 1 00:30 00:15 00:10 00:20 +# Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. On time will be between 06:30 and 06:39, off time will be between 22:05 and 22:24. The rule applies all days in the week +NEXA P 1 1234567 06:30 22:05 1 00:30 00:15 00:10 00:20 From f79cc13854ea7ae39e4f159a95ba6bb1bf7ae358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sat, 23 Feb 2008 20:44:58 +0000 Subject: [PATCH 0038/2215] Added config file validation for longitude, latitude and timezone --- tellstickd/tellstickd | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 89b65f55..478b8232 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -475,14 +475,29 @@ sub read_config if ($param && $value) { printf("$PROGRAM_NAME: $param = $value\n"); if ($param eq 'latitude') { + if ($value !~ /^-?[0-9\.]*$/) { + die ("$PROGRAM_NAME: Latitude must be a valid number\n"); + } + if ($value < -90 || $value > 90) { + die ("$PROGRAM_NAME: Latitude must be between -90 and 90 degrees\n"); + } $LATITUDE = $value; next; } if ($param eq 'longitude') { + if ($value !~ /^-?[0-9\.]*$/) { + die ("$PROGRAM_NAME: Longitude must be a valid number\n"); + } + if ($value < -90 || $value > 90) { + die ("$PROGRAM_NAME: Longitude must be between -180 and 180 degrees\n"); + } $LONGITUDE = $value; next; } if ($param eq 'timezone') { + if (!DateTime::TimeZone->is_valid_name($value)) { + die ("$PROGRAM_NAME: Invalid timezone\n"); + } $TIMEZONE = $value; next; } From 8b769925db5282b47cd5c8c5dc00fb3c3850e8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sat, 23 Feb 2008 21:02:38 +0000 Subject: [PATCH 0039/2215] According to the FHS http://www.pathname.com/fhs/pub/fhs-2.3.html#VARRUNRUNTIMEVARIABLEDATA the pid file must contain a newline character at the end of the pid. --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 478b8232..cfed9341 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -591,7 +591,7 @@ if ($make_daemon == $YES) { # Create pidfile if ($write_pid == $YES) { open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; - print PIDFILE $$; + print PIDFILE $$ . "\n"; close PIDFILE; } From 2af137790b63b0b2bc66a0a97c20165443c8e797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sat, 23 Feb 2008 21:54:11 +0000 Subject: [PATCH 0040/2215] Scan command line for -c option and read the file first to make sure command line options will override config file -logfile is the only one both in config and on commandline Only write a pid file if running as a daemon Default to not writing a log file unless specified on command line or in config file --- tellstickd/tellstickd | 58 ++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index cfed9341..3ce4c8f6 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -23,9 +23,9 @@ my @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun); my $NO = 0; my $YES = 1; my @device_cfg; -my $conf_file = ""; +my $conf_file = $CONFIG_FILE; my $make_daemon = $NO; -my $output_to_logfile = $YES; +my $output_to_logfile = $NO; my $write_pid = $YES; my $n_rfcmd_calls; my $current_time; @@ -511,6 +511,7 @@ sub read_config } if ($param eq 'log_file') { $LOG_FILE = $value; + $output_to_logfile = $YES; next; } if ($param eq 'pid_file') { @@ -543,15 +544,30 @@ sub usageprompt # ############## Main section ###################### -my $i = -1; +my $i; + +# Check if the command line specifies a config file +foreach $i (0 .. $#ARGV) { + if ($ARGV[$i] =~ /^--config$/ || $ARGV[$i] =~ /^-c$/) { + $conf_file = $ARGV[$i+1]; + } +} + +# Read the configuration file +$number_of_devices = read_config($conf_file); + +if ($number_of_devices < 1) { + die("$PROGRAM_NAME: Configuration file has no devices to control, exiting.\n"); +} +else { + printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n\n"); +} + +$i = -1; while ($i < $#ARGV) { if ($i+1 <= $#ARGV) { - if ($ARGV[$i+1] =~ /^--config$/ || $ARGV[$i+1] =~ /^-c$/) { - $i++; - $conf_file = $ARGV[$i+1]; - } - elsif ($ARGV[$i+1] =~ /^-d$/ || $ARGV[$i+1] =~ /^--daemon$/) { + if ($ARGV[$i+1] =~ /^-d$/ || $ARGV[$i+1] =~ /^--daemon$/) { $output_to_logfile = $YES; $make_daemon = $YES; } @@ -586,30 +602,16 @@ if ($output_to_logfile == $YES) { if ($make_daemon == $YES) { &daemonize(); -} - -# Create pidfile -if ($write_pid == $YES) { - open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; - print PIDFILE $$ . "\n"; - close PIDFILE; -} - -if (length($conf_file) < 1) { - $conf_file = $CONFIG_FILE; + # Create pidfile + if ($write_pid == $YES) { + open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; + print PIDFILE $$ . "\n"; + close PIDFILE; + } } printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION\n"); -# Read the configuration file -$number_of_devices = read_config($conf_file); - -if ($number_of_devices < 1) { - die("$PROGRAM_NAME: Configuration file has no devices to control, exiting.\n"); -} -else { - printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n\n"); -} ################################################################################################### # Now to the eternal loop From 71bf6457913740b50e987d8d03a8e61e5d3452de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sat, 23 Feb 2008 22:32:18 +0000 Subject: [PATCH 0041/2215] Reverted to r39, mostly because I'm a idiot. We can't read the config file before figuring out what to do on the command line. --- tellstickd/tellstickd | 58 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 3ce4c8f6..cfed9341 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -23,9 +23,9 @@ my @weekDays = qw(Sun Mon Tue Wed Thu Fri Sat Sun); my $NO = 0; my $YES = 1; my @device_cfg; -my $conf_file = $CONFIG_FILE; +my $conf_file = ""; my $make_daemon = $NO; -my $output_to_logfile = $NO; +my $output_to_logfile = $YES; my $write_pid = $YES; my $n_rfcmd_calls; my $current_time; @@ -511,7 +511,6 @@ sub read_config } if ($param eq 'log_file') { $LOG_FILE = $value; - $output_to_logfile = $YES; next; } if ($param eq 'pid_file') { @@ -544,30 +543,15 @@ sub usageprompt # ############## Main section ###################### -my $i; - -# Check if the command line specifies a config file -foreach $i (0 .. $#ARGV) { - if ($ARGV[$i] =~ /^--config$/ || $ARGV[$i] =~ /^-c$/) { - $conf_file = $ARGV[$i+1]; - } -} - -# Read the configuration file -$number_of_devices = read_config($conf_file); - -if ($number_of_devices < 1) { - die("$PROGRAM_NAME: Configuration file has no devices to control, exiting.\n"); -} -else { - printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n\n"); -} - -$i = -1; +my $i = -1; while ($i < $#ARGV) { if ($i+1 <= $#ARGV) { - if ($ARGV[$i+1] =~ /^-d$/ || $ARGV[$i+1] =~ /^--daemon$/) { + if ($ARGV[$i+1] =~ /^--config$/ || $ARGV[$i+1] =~ /^-c$/) { + $i++; + $conf_file = $ARGV[$i+1]; + } + elsif ($ARGV[$i+1] =~ /^-d$/ || $ARGV[$i+1] =~ /^--daemon$/) { $output_to_logfile = $YES; $make_daemon = $YES; } @@ -602,16 +586,30 @@ if ($output_to_logfile == $YES) { if ($make_daemon == $YES) { &daemonize(); - # Create pidfile - if ($write_pid == $YES) { - open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; - print PIDFILE $$ . "\n"; - close PIDFILE; - } +} + +# Create pidfile +if ($write_pid == $YES) { + open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; + print PIDFILE $$ . "\n"; + close PIDFILE; +} + +if (length($conf_file) < 1) { + $conf_file = $CONFIG_FILE; } printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION\n"); +# Read the configuration file +$number_of_devices = read_config($conf_file); + +if ($number_of_devices < 1) { + die("$PROGRAM_NAME: Configuration file has no devices to control, exiting.\n"); +} +else { + printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n\n"); +} ################################################################################################### # Now to the eternal loop From 38c6eee752eb47d4f34607e657071ce528e232ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 24 Feb 2008 00:21:56 +0000 Subject: [PATCH 0042/2215] Bugfix for perl sunday = 0 vs config file sunday = 7 --- tellstickd/tellstickd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index cfed9341..5bcf03a1 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -343,6 +343,11 @@ sub is_rule_valid_today my $device_id = $_[0]; my $current_day = $_[1]; + if (0 == $current_day) { + # Perl thinks 0 = Sunday, config file thinks 7 = Sunday + $current_day = 7; + } + if ($device_cfg[$device_id][10] =~ /$current_day/) { return $YES; } From ffa238c9f344bc8a68e0a562552c44ef284ad4a3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Feb 2008 13:36:10 +0000 Subject: [PATCH 0043/2215] Added project "tdtool" --- tdtool/Makefile | 14 ++++++++ tdtool/main.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 tdtool/Makefile create mode 100644 tdtool/main.cpp diff --git a/tdtool/Makefile b/tdtool/Makefile new file mode 100644 index 00000000..04d13026 --- /dev/null +++ b/tdtool/Makefile @@ -0,0 +1,14 @@ +CC=g++ +CFLAGS=-Wall +FILES=main.cpp +LIBS=-L. -ltellusbd101 + +APP = tdtool + +all: $(APP) + +$(APP): main.cpp + $(CC) -o $(APP) $(CFLAGS) $(LIBS) $(FILES) + +clean: + rm -f *.o ; rm $(APP) diff --git a/tdtool/main.cpp b/tdtool/main.cpp new file mode 100644 index 00000000..903f8cde --- /dev/null +++ b/tdtool/main.cpp @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include "TellUsbD101.h" +#ifdef __MINGW32__ + #define sleep(x) _sleep((x)*1000) +#endif + +void print_usage( char *name ) { + printf("Usage:\n"); + printf(" %s [ options ]\n", name); + printf("\n"); + printf("Options: -[lh] [--list] [--help]\n"); + printf(" [--on device] [--off device]\n"); + printf("\n"); + printf("Options:\n"); + printf(" --list (-l short option)\n"); + printf(" List currently configured devices.\n"); + printf("\n"); + printf(" --help (-h short option)\n"); + printf(" Shows this screen.\n"); + printf("\n"); + printf(" --on device\n"); + printf(" Turns on device. device should be an integer of the device-id.\n"); + printf(" The device-id is outputed with the --list option\n"); + printf("\n"); + printf(" --off device\n"); + printf(" Turns off device. device should be an integer of the device-id.\n"); + printf(" The device-id is outputed with the --list option\n"); + printf("\n"); +} + +void print_device( int index ) { + int intId = devGetDeviceId(index); + char *name = devGetName(intId); + printf("%i\t%s\n", intId, name); +} + +void list_devices() { + int intNum = devGetNumberOfDevices(); + printf("Number of devices: %i\n", intNum); + int i = 0; + while (i < intNum) { + print_device( i ); + i++; + } +} + +void switch_device( bool turnOn, int device ) { + if (turnOn) { + char *name = devGetName( device ); + bool ok = devTurnOn( device ); + printf("Turning on device: %i %s - %s\n", device, name, (ok ? "ok" : "failed")); + } else { + char *name = devGetName( device ); + bool ok = devTurnOff( device ); + printf("Turning off device: %i %s - %s\n", device, name, (ok ? "ok" : "failed")); + } + sleep(1); +} + +int main(int argc, char **argv) +{ + int optch, longindex; + static char optstring[] = "ln:f:h"; + static struct option long_opts[] = { + { "list", 0, 0, 'l' }, + { "on", 1, 0, 'n' }, + { "off", 1, 0, 'f' }, + { "help", 1, 0, 'h' }, + { 0, 0, 0, 0} + }; + + while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) + switch (optch) { + case 'f' : + switch_device(false, atoi(&optarg[0])); + break; + case 'h' : + print_usage( argv[0] ); + break; + case 'l' : + list_devices(); + break; + case 'n' : + switch_device(true, atoi(&optarg[0])); + break; + default : + print_usage( argv[0] ); + return -1; + } + + return 0; +} From 8a560a2086d2390a1627110af383c789152e0d9c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Feb 2008 13:30:49 +0000 Subject: [PATCH 0044/2215] Added some new devices. --- driver/TellUsbD101/DeviceNexa.cpp | 11 ++++++++++- driver/TellUsbD101/TellUsbD101.h | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/driver/TellUsbD101/DeviceNexa.cpp b/driver/TellUsbD101/DeviceNexa.cpp index 97a194fc..42f48cb9 100644 --- a/driver/TellUsbD101/DeviceNexa.cpp +++ b/driver/TellUsbD101/DeviceNexa.cpp @@ -148,7 +148,16 @@ int DeviceNexa::methods(char* strModel){ strcmp(strModel, TELLSTICK_DEVICE_HDR105) == 0 || strcmp(strModel, TELLSTICK_DEVICE_EL2004) == 0 || strcmp(strModel, TELLSTICK_DEVICE_EL2016) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2010) == 0 + strcmp(strModel, TELLSTICK_DEVICE_EL2010) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LYCR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LYCR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LCMR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LCMR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2023) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2024) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2021) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2017) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2019) == 0 ) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); diff --git a/driver/TellUsbD101/TellUsbD101.h b/driver/TellUsbD101/TellUsbD101.h index 8227ae1f..9e7fa756 100644 --- a/driver/TellUsbD101/TellUsbD101.h +++ b/driver/TellUsbD101/TellUsbD101.h @@ -66,6 +66,15 @@ extern "C" { #define TELLSTICK_DEVICE_EL2004 "16" #define TELLSTICK_DEVICE_EL2016 "17" #define TELLSTICK_DEVICE_EL2010 "18" +#define TELLSTICK_DEVICE_LYCR1000 "20" +#define TELLSTICK_DEVICE_LYCR300 "21" +#define TELLSTICK_DEVICE_LCMR1000 "22" +#define TELLSTICK_DEVICE_LCMR300 "23" +#define TELLSTICK_DEVICE_EL2023 "24" +#define TELLSTICK_DEVICE_EL2024 "25" +#define TELLSTICK_DEVICE_EL2021 "26" +#define TELLSTICK_DEVICE_EL2017 "27" +#define TELLSTICK_DEVICE_EL2019 "28" //Protocol Ikea #define TELLSTICK_DEVICE_KOPPLA "19" From ae827999bdba0d98bb45b3d2529c327aa605dfa4 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 25 Feb 2008 21:37:59 +0000 Subject: [PATCH 0045/2215] Code cleanups in functions get_sunrise_time and get_sunset_time. --- tellstickd/tellstickd | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 5bcf03a1..e270fe40 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -80,13 +80,11 @@ sub get_sunrise_time ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; - $Month++; - my $dt = DateTime->new( year => $Year, month => $Month, day => $Day, time_zone => $TIMEZONE, ); + # Note, localtime returns months 0..11, Datetime->new expects months 1..12. + my $dt = DateTime->new( year => $Year, month => $Month+1, day => $Day, time_zone => $TIMEZONE, ); my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '-0.833', iteration => '1'); - $Month--; - my $dt1 = $sunrise->sunrise_datetime($dt); ($sunrise_time) = $dt1->datetime =~ /T(.*)\:/; @@ -100,13 +98,11 @@ sub get_sunset_time ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(time); $Year += 1900; - $Month++; - my $dt = DateTime->new( year => $Year, month => $Month, day => $Day, time_zone => $TIMEZONE, ); + # Note, localtime returns months 0..11, Datetime->new expects months 1..12. + my $dt = DateTime->new( year => $Year, month => $Month+1, day => $Day, time_zone => $TIMEZONE, ); my $sunrise = DateTime::Event::Sunrise ->new( longitude => $LONGITUDE, latitude => $LATITUDE, altitude => '-0.833', iteration => '1'); - $Month--; - my $dt2 = $sunrise->sunset_datetime($dt); ($sunset_time) = $dt2->datetime =~ /T(.*)\:/; From 1a1b386c21b6ea31b5acf59da1cb63de295dce2e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Feb 2008 18:32:27 +0000 Subject: [PATCH 0046/2215] Creating a 1.2 branch. --- driver/CMakeLists.txt | 6 + driver/TellUsbD101.sln | 20 + driver/TellUsbD101/CMakeLists.txt | 27 + driver/TellUsbD101/Device.cpp | 52 ++ driver/TellUsbD101/Device.h | 24 + driver/TellUsbD101/DeviceIkea.cpp | 175 +++++ driver/TellUsbD101/DeviceIkea.h | 23 + driver/TellUsbD101/DeviceNexa.cpp | 168 +++++ driver/TellUsbD101/DeviceNexa.h | 22 + driver/TellUsbD101/DeviceSartano.cpp | 115 ++++ driver/TellUsbD101/DeviceSartano.h | 21 + driver/TellUsbD101/DeviceWaveman.cpp | 45 ++ driver/TellUsbD101/DeviceWaveman.h | 11 + driver/TellUsbD101/Resource.h | 31 + driver/TellUsbD101/TellUsbD101.cpp | 323 +++++++++ driver/TellUsbD101/TellUsbD101.def | 24 + driver/TellUsbD101/TellUsbD101.h | 82 +++ driver/TellUsbD101/TellUsbD101.vcproj | 308 +++++++++ driver/TellUsbD101/TelldusSettings.cpp | 631 ++++++++++++++++++ driver/TellUsbD101/TelldusSettings.h | 42 ++ driver/TellUsbD101/linux/Device.cpp | 85 +++ driver/TellUsbD101/stdafx.cpp | 8 + driver/TellUsbD101/stdafx.h | 37 ++ driver/TellUsbD101/win/Device.cpp | 91 +++ driver/TellUsbD101/win/FTD2XX.H | 875 +++++++++++++++++++++++++ 25 files changed, 3246 insertions(+) create mode 100644 driver/CMakeLists.txt create mode 100644 driver/TellUsbD101.sln create mode 100644 driver/TellUsbD101/CMakeLists.txt create mode 100644 driver/TellUsbD101/Device.cpp create mode 100644 driver/TellUsbD101/Device.h create mode 100644 driver/TellUsbD101/DeviceIkea.cpp create mode 100644 driver/TellUsbD101/DeviceIkea.h create mode 100644 driver/TellUsbD101/DeviceNexa.cpp create mode 100644 driver/TellUsbD101/DeviceNexa.h create mode 100644 driver/TellUsbD101/DeviceSartano.cpp create mode 100644 driver/TellUsbD101/DeviceSartano.h create mode 100644 driver/TellUsbD101/DeviceWaveman.cpp create mode 100644 driver/TellUsbD101/DeviceWaveman.h create mode 100644 driver/TellUsbD101/Resource.h create mode 100644 driver/TellUsbD101/TellUsbD101.cpp create mode 100644 driver/TellUsbD101/TellUsbD101.def create mode 100644 driver/TellUsbD101/TellUsbD101.h create mode 100644 driver/TellUsbD101/TellUsbD101.vcproj create mode 100644 driver/TellUsbD101/TelldusSettings.cpp create mode 100644 driver/TellUsbD101/TelldusSettings.h create mode 100644 driver/TellUsbD101/linux/Device.cpp create mode 100644 driver/TellUsbD101/stdafx.cpp create mode 100644 driver/TellUsbD101/stdafx.h create mode 100644 driver/TellUsbD101/win/Device.cpp create mode 100644 driver/TellUsbD101/win/FTD2XX.H diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt new file mode 100644 index 00000000..18cc7359 --- /dev/null +++ b/driver/CMakeLists.txt @@ -0,0 +1,6 @@ +PROJECT( tellstick ) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) + +ADD_SUBDIRECTORY(TellUsbD101) + diff --git a/driver/TellUsbD101.sln b/driver/TellUsbD101.sln new file mode 100644 index 00000000..1b22fbc9 --- /dev/null +++ b/driver/TellUsbD101.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TellUsbD101", "TellUsbD101\TellUsbD101.vcproj", "{2A868E40-88D9-4800-A83F-21D0F8DCB611}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Debug|Win32.ActiveCfg = Release|Win32 + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Debug|Win32.Build.0 = Release|Win32 + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Release|Win32.ActiveCfg = Release|Win32 + {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/driver/TellUsbD101/CMakeLists.txt b/driver/TellUsbD101/CMakeLists.txt new file mode 100644 index 00000000..55842bce --- /dev/null +++ b/driver/TellUsbD101/CMakeLists.txt @@ -0,0 +1,27 @@ + +SET( tellusbd101_SRCS + Device.cpp + linux/Device.cpp + DeviceIkea.cpp + DeviceNexa.cpp + DeviceSartano.cpp + DeviceWaveman.cpp + ) + +ADD_DEFINITIONS( + -DOS_LINUX + ) + +ADD_LIBRARY(tellusbd101 SHARED + ${tellusbd101_SRCS} + ${tellusbd101_MOC_SRCS} + ) + +# TARGET_LINK_LIBRARIES(tellusbd101 +# ${MIDAS_LIBRARY} +# ) + +INSTALL(TARGETS tellusbd101 LIBRARY + DESTINATION lib + ) + diff --git a/driver/TellUsbD101/Device.cpp b/driver/TellUsbD101/Device.cpp new file mode 100644 index 00000000..0281375a --- /dev/null +++ b/driver/TellUsbD101/Device.cpp @@ -0,0 +1,52 @@ +#include "Device.h" + +/* +* Constructor +*/ +Device::Device(int intDongleIndex) +{ + this->intDongleIndex = intDongleIndex; +} + +/* +* Destructor +*/ +Device::~Device(void) +{ + intDongleIndex = -1; +} + +/* +* Turn on, virtual +*/ +void Device::turnOn(void){ + //do nothing +} + +/* +* Turn off, virtual +*/ +void Device::turnOff(void){ + //do nothing +} + +/* +* Bell, virtual +*/ +void Device::bell(void){ + //do nothing +} + +/* +* Dim, virtual +*/ +void Device::dim(unsigned char level){ + //do nothing +} + +/* +* Methods, virtual +*/ +int Device::methods(char* strModel){ + return 0; +} diff --git a/driver/TellUsbD101/Device.h b/driver/TellUsbD101/Device.h new file mode 100644 index 00000000..f4aec627 --- /dev/null +++ b/driver/TellUsbD101/Device.h @@ -0,0 +1,24 @@ +#pragma once + +#include "TellUsbD101.h" + +class Device +{ +private: + int intDongleIndex; +protected: + void send(char* strMessage); +public: + Device(int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual void bell(void); + virtual void dim(unsigned char level); + virtual int methods(char* strModel); + static int getDongleIndex(); + + static void debugLog(char* debugstring); + +public: + ~Device(void); +}; diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/driver/TellUsbD101/DeviceIkea.cpp new file mode 100644 index 00000000..e5af5f79 --- /dev/null +++ b/driver/TellUsbD101/DeviceIkea.cpp @@ -0,0 +1,175 @@ +// #include "StdAfx.h" //Needed? +#include "DeviceIkea.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceIkea::DeviceIkea(int intNewSystem, int intNewUnits, int intNewFadeStyle, int intDeviceIndex):Device(intDeviceIndex){ + intSystem = intNewSystem; + intUnits = intNewUnits; + intFadeStyle = intNewFadeStyle; +} + +/* +* Destructor +*/ +DeviceIkea::~DeviceIkea(void) +{ + intSystem = -1; + intUnits = -1; + intFadeStyle = -1; +} + +/* +* Turn on this device +*/ +void DeviceIkea::turnOn(void){ + try{ + string strCode = getStringCode(255); + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceIkea::turnOff(void){ + try{ + string strCode = getStringCode(0); + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceIkea::dim(unsigned char level){ + try{ + string strCode = getStringCode(level); + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Convert an integer to byte string where 0 is represented by ª and 1 by TT +*/ +string DeviceIkea::getStringCode(unsigned char level){ + + string strReturn = "STTTTTTª"; //Startcode, always like this; + + try{ + string strChannels = ""; + int intCode = (intSystem << 10) | intUnits; + int checksum1 = 0; + int checksum2 = 0; + for (int i = 13; i >= 0; --i) { + if ((intCode>>i) & 1) { + strChannels.append("TT"); + if (i % 2 == 0) + checksum2++; + else + checksum1++; + } else { + strChannels.append("ª"); + } + } + strReturn.append(strChannels); //System + Units + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + int intLevel = 0; + if (level <= 12) { + intLevel = 10; // Level 10 is actually off + } else if (level <= 37) { + intLevel = 1; + } else if (level <= 62) { + intLevel = 2; + } else if (level <= 87) { + intLevel = 3; + } else if (level <= 112) { + intLevel = 4; + } else if (level <= 137) { + intLevel = 5; + } else if (level <= 162) { + intLevel = 6; + } else if (level <= 187) { + intLevel = 7; + } else if (level <= 212) { + intLevel = 8; + } else if (level <= 237) { + intLevel = 9; + } else { + intLevel = 0; // Level 0 is actually full on + } + + int intFade = 0; + if (intFadeStyle == 1) { + intFade = 11 << 4; //Smooth + } else { + intFade = 1 << 4; //Instant + } + + intCode = intLevel | intFade; //Concat level and fade + + checksum1 = 0; + checksum2 = 0; + for (int i = 0; i < 6; ++i) { + if ((intCode>>i) & 1) { + strReturn.append("TT"); + if (i % 2 == 0) + checksum1++; + else + checksum2++; + } else { + strReturn.append("ª"); + } + } + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + strReturn.append("+"); + } + catch(...){ + throw; + } + return strReturn; + +} + +/* +* Has the device got the method? +*/ +int DeviceIkea::methods(char* strModel){ + + if(strcmp(strModel, TELLSTICK_DEVICE_KOPPLA) == 0) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); + } + return 0; +} diff --git a/driver/TellUsbD101/DeviceIkea.h b/driver/TellUsbD101/DeviceIkea.h new file mode 100644 index 00000000..4a672653 --- /dev/null +++ b/driver/TellUsbD101/DeviceIkea.h @@ -0,0 +1,23 @@ +#pragma once +#include "Device.h" +#include + +class DeviceIkea : public Device +{ +public: + DeviceIkea(int intSystem, int intUnits, int fadeStyle, int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual void dim(unsigned char level); + virtual int methods(char* strModel); + +public: + ~DeviceIkea(void); + +protected: + int intSystem; + int intUnits; + int intFadeStyle; + std::string getStringCode(unsigned char); +}; + diff --git a/driver/TellUsbD101/DeviceNexa.cpp b/driver/TellUsbD101/DeviceNexa.cpp new file mode 100644 index 00000000..42f48cb9 --- /dev/null +++ b/driver/TellUsbD101/DeviceNexa.cpp @@ -0,0 +1,168 @@ +// #include "StdAfx.h" +#include "DeviceNexa.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceNexa::DeviceNexa(int intNewHouse, int intNewCode, int intDeviceIndex):Device(intDeviceIndex){ + intHouse = intNewHouse; + intCode = intNewCode; +} + +/* +* Destructor +*/ +DeviceNexa::~DeviceNexa(void) +{ + intHouse = -1; + intCode = -1; +} + +/* +* Turn on this device +*/ +void DeviceNexa::turnOn(void){ + + try{ + //char* model = getModel(intDeviceId); + string strCode = getStringCode(intCode); + string strHouse = getStringCode(intHouse); + strCode.append(strHouse); + + strCode.insert(0, "S"); + strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceNexa::turnOff(void){ + + try{ + string strCode = getStringCode(intCode); + string strHouse = getStringCode(intHouse); + + strCode.append(strHouse); + strCode.insert(0, "S"); + strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Send a bell +*/ +void DeviceNexa::bell(void){ + + try{ + string strCode = getStringCode(intCode); + + strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time + strCode.insert(0, "S"); + strCode.append("$kk$$kk$$kk$$kk$$k+"); //the "bell"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed +*/ +string DeviceNexa::getStringCode(int intToConvert){ + + string strReturn = ""; + + try{ + bitset<4> bs ((long)intToConvert); + + strReturn = bs.to_string(); + reverse(strReturn.begin(), strReturn.end()); + + int intPos = (int)strReturn.find("0"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "$k"); + intPos = (int)strReturn.find("0", intPos + 1); + } + + intPos = (int)strReturn.find("1"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "k$"); + intPos = (int)strReturn.find("1", intPos + 1); + } + + intPos = 0; + while (intPos < (int)strReturn.length()){ + strReturn.insert(intPos, "$k"); + intPos = intPos + 4; + } + } + catch(...){ + throw; + } + return strReturn; + +} + +/* +* Has the device got the method? +*/ +int DeviceNexa::methods(char* strModel){ + + if( strcmp(strModel, TELLSTICK_DEVICE_YCR3500) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_YCR300D) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_WSR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_CMR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_CMR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_PA33300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2005) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2006) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_SYCR3500) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_SYCR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_HDR105) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2004) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2016) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2010) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LYCR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LYCR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LCMR1000) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_LCMR300) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2023) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2024) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2021) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2017) == 0 || + strcmp(strModel, TELLSTICK_DEVICE_EL2019) == 0 + ) + { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); + } else if ( strcmp(strModel, TELLSTICK_DEVICE_ML7100) == 0 ) { + return TELLSTICK_BELL; + } + return 0; +} diff --git a/driver/TellUsbD101/DeviceNexa.h b/driver/TellUsbD101/DeviceNexa.h new file mode 100644 index 00000000..abe8fa0d --- /dev/null +++ b/driver/TellUsbD101/DeviceNexa.h @@ -0,0 +1,22 @@ +#pragma once +#include "Device.h" +#include + +class DeviceNexa : public Device +{ +public: + DeviceNexa(int intHouse, int intCode, int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual void bell(void); + virtual int methods(char* strModel); + +public: + ~DeviceNexa(void); + +protected: + int intHouse; + int intCode; + std::string getStringCode(int); +}; + diff --git a/driver/TellUsbD101/DeviceSartano.cpp b/driver/TellUsbD101/DeviceSartano.cpp new file mode 100644 index 00000000..1f38a2dc --- /dev/null +++ b/driver/TellUsbD101/DeviceSartano.cpp @@ -0,0 +1,115 @@ +#include "DeviceSartano.h" +#include "DeviceNexa.h" +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceSartano::DeviceSartano(int intNewSystem, int intNewCode, int intDeviceIndex) + :Device(intDeviceIndex) +{ + intSystem = intNewSystem; + intCode = intNewCode; +} + + +DeviceSartano::~DeviceSartano(void) +{ + intSystem = -1; + intCode = -1; +} + + +/* +* Turn on this device +*/ +void DeviceSartano::turnOn(void){ + + try{ + string strSystem = getStringCode(intSystem); + string strCode = getStringCode(intCode); + strSystem.append(strCode); + + strSystem.insert(0, "S"); + strSystem.append("$k$k$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strSystem.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Turn off this device +*/ +void DeviceSartano::turnOff(void){ + + try{ + string strSystem = getStringCode(intSystem); + string strCode = getStringCode(intCode); + strSystem.append(strCode); + + strSystem.insert(0, "S"); + strSystem.append("$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strSystem.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Has the device got the method? +*/ +int DeviceSartano::methods(char* strModel){ + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); +} + +/* +* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed +*/ +string DeviceSartano::getStringCode(int intToConvert){ + + string strReturn = ""; + + try{ + bitset<5> bs ((long)intToConvert); + + strReturn = bs.to_string(); + + int intPos = (int)strReturn.find("0"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "$k"); + intPos = (int)strReturn.find("0", intPos + 1); + } + + intPos = (int)strReturn.find("1"); + while (intPos < string::npos){ + strReturn.replace(intPos, 1, "k$"); + intPos = (int)strReturn.find("1", intPos + 1); + } + + intPos = 0; + while (intPos < (int)strReturn.length()){ + strReturn.insert(intPos, "$k"); + intPos = intPos + 4; + } + } + catch(...){ + throw; + } + return strReturn; + +} + diff --git a/driver/TellUsbD101/DeviceSartano.h b/driver/TellUsbD101/DeviceSartano.h new file mode 100644 index 00000000..c7c86324 --- /dev/null +++ b/driver/TellUsbD101/DeviceSartano.h @@ -0,0 +1,21 @@ +#pragma once +#include "Device.h" +#include + + +class DeviceSartano : public Device +{ +public: + DeviceSartano(int intSystem, int intCode, int intDeviceIndex); + virtual void turnOn(void); + virtual void turnOff(void); + virtual int methods(char* strModel); + + ~DeviceSartano(void); + +protected: + std::string getStringCode(int); + + int intSystem; + int intCode; +}; diff --git a/driver/TellUsbD101/DeviceWaveman.cpp b/driver/TellUsbD101/DeviceWaveman.cpp new file mode 100644 index 00000000..855afe5c --- /dev/null +++ b/driver/TellUsbD101/DeviceWaveman.cpp @@ -0,0 +1,45 @@ +// #include "StdAfx.h" +#include "DeviceWaveman.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +DeviceWaveman::DeviceWaveman(int intNewHouse, int intNewCode, int intDeviceIndex) + :DeviceNexa(intNewHouse, intNewCode, intDeviceIndex){ +} + +/* +* Turn off this device +*/ +void DeviceWaveman::turnOff(void){ + + try{ + string strCode = getStringCode(intCode); + string strHouse = getStringCode(intHouse); + + strCode.append(strHouse); + strCode.insert(0, "S"); + strCode.append("$k$k$k$k$k$k$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time + + char* strMessage = const_cast(strCode.c_str()); + + Device::send(strMessage); + } + catch(...){ + throw; + } +} + +/* +* Has the device got the method? +*/ +int DeviceWaveman::methods(char* strModel){ + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); +} diff --git a/driver/TellUsbD101/DeviceWaveman.h b/driver/TellUsbD101/DeviceWaveman.h new file mode 100644 index 00000000..c099a563 --- /dev/null +++ b/driver/TellUsbD101/DeviceWaveman.h @@ -0,0 +1,11 @@ +#pragma once +#include "DeviceNexa.h" +#include + +class DeviceWaveman : public DeviceNexa +{ +public: + DeviceWaveman(int intHouse, int intCode, int intDeviceIndex); + virtual void turnOff(void); + virtual int methods(char* strModel); +}; diff --git a/driver/TellUsbD101/Resource.h b/driver/TellUsbD101/Resource.h new file mode 100644 index 00000000..0c5cdd60 --- /dev/null +++ b/driver/TellUsbD101/Resource.h @@ -0,0 +1,31 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by testruntelldus3.rc +// + +#define IDS_APP_TITLE 103 + +#define IDR_MAINFRAME 128 +#define IDD_TESTRUNTELLDUS3_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_TESTRUNTELLDUS3 107 +#define IDI_SMALL 108 +#define IDC_TESTRUNTELLDUS3 109 +#define IDC_MYICON 2 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp new file mode 100644 index 00000000..cfd4f3e1 --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -0,0 +1,323 @@ +//DLL entry point + +#include "stdafx.h" +#include "TellUsbD101.h" +#include "TelldusSettings.h" +#include "Device.h" +#include +#include +#include +#include + +void handleException(std::exception e); + + +#define MAX_LOADSTRING 100 + +//TODO: +//delete on created objects +//comment (just copy from the called methods) + +bool __stdcall devTurnOn(int intDeviceId){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + dev->turnOn(); + + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +bool __stdcall devTurnOff(int intDeviceId){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + dev->turnOff(); + + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +bool __stdcall devBell(int intDeviceId){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + dev->bell(); + + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +bool __stdcall devDim(int intDeviceId, unsigned char level){ + + try{ + TelldusSettings ts; + Device* dev = ts.getDevice(intDeviceId); + if(dev != NULL){ + if (level == 0) { + dev->turnOff(); + } else if (level == 255) { + dev->turnOn(); + } else { + dev->dim(level); + } + delete(dev); + return true; + } + else{ + return false; + } + } + catch(exception e){ + handleException(e); + } + return false; +} + +int __stdcall devGetNumberOfDevices(void){ + int intReturn = -1; + try{ + TelldusSettings ts; + intReturn = ts.getNumberOfDevices(); + } + catch(exception e){ + intReturn = -1; + handleException(e); + } + return intReturn; +} + +int __stdcall devGetDeviceId(int intDeviceIndex){ + int intReturn = -1; + try{ + TelldusSettings ts; + intReturn = ts.getDeviceId(intDeviceIndex); + } + catch(exception e){ + intReturn = -1; + handleException(e); + } + return intReturn; +} + +//general settings: +char * __stdcall devGetName(int intDeviceId){ + char* strReturn; + try{ + TelldusSettings ts; + strReturn = ts.getName(intDeviceId); + } + catch(exception e){ + strReturn = ""; + handleException(e); + } + return strReturn; +} + +bool __stdcall devSetName(int intDeviceId, char* strNewName){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.setName(intDeviceId, strNewName); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +char* __stdcall devGetVendor(int intDeviceId){ + char* strReturn = ""; + try{ + TelldusSettings ts; + strReturn = ts.getVendor(intDeviceId); + } + catch(exception e){ + strReturn = ""; + handleException(e); + } + return strReturn; +} + +bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.setVendor(intDeviceId, strVendor); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + + char* __stdcall devGetModel(int intDeviceId){ + char* strReturn = ""; + try{ + TelldusSettings ts; + strReturn = ts.getModel(intDeviceId); + } + catch(exception e){ + strReturn = ""; + handleException(e); + } + return strReturn; +} + +bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.setModel(intDeviceId, strNewModel); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ + + vector vArguments; + //int intArguments[] = new int[]; //bort? + try{ + char* strTemp = strtok(strArguments, ","); + + while(strTemp != NULL){ + vArguments.push_back(atoi(strTemp)); + strTemp = strtok(NULL, ","); + } + TelldusSettings ts; + return ts.setArguments(intDeviceId, vArguments); + } + catch(exception e){ + handleException(e); + return false; + } +} + +int __stdcall devGetArgument(int intDeviceId, int intArgumentIndex){ + int intReturn; + try{ + if(intArgumentIndex != -1){ + TelldusSettings ts; + int* intArguments = ts.getArguments(intDeviceId); + intReturn = intArguments[intArgumentIndex]; + } + } + catch(exception e){ + handleException(e); + } + return intReturn; +} + +int __stdcall devGetNumberOfArguments(int intDeviceId){ + int intReturn; + try{ + TelldusSettings ts; + intReturn = ts.getNumberOfArguments(intDeviceId); + } + catch(exception e){ + handleException(e); + } + return intReturn; +} + +int __stdcall devAddDevice(){ + int intNewDeviceId = -1; + try{ + TelldusSettings ts; + intNewDeviceId = ts.addDevice(); + } + catch(exception e){ + intNewDeviceId = -1; + handleException(e); + } + return intNewDeviceId; +} + +bool __stdcall devRemoveDevice(int intDeviceId){ + bool blnSuccess = false; + try{ + TelldusSettings ts; + blnSuccess = ts.removeDevice(intDeviceId); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +int __stdcall devMethods(int id){ + + int intMethods = 0; + try{ + TelldusSettings ts; + char* strModel = ts.getModel(id); + Device* dev = ts.getDevice(id, -1); //We send dongleIndex=-1 sice we wouldn't send any data! + if (dev != NULL) { + intMethods = dev->methods(strModel); + } + } + catch(exception e){ + intMethods = 0; + handleException(e); + } + return intMethods; +} + + +//******** +//* Error management, set strLogName to "" to turn off +//* +void handleException(exception e){ + + char* strLogName = "c:\\errorlog.txt"; + //char* strLogName = ""; + + if(strlen(strLogName) > 0){ + ofstream errorfile(strLogName, ios::app); + if(errorfile){ + errorfile << e.what() << endl; + errorfile.close(); + } + } +} + diff --git a/driver/TellUsbD101/TellUsbD101.def b/driver/TellUsbD101/TellUsbD101.def new file mode 100644 index 00000000..fc32ffca --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.def @@ -0,0 +1,24 @@ +LIBRARY TellUsbD101 +EXPORTS + devGetNumberOfDevices @1 + devGetDeviceId @2 + + devGetName @3 + devGetVendor @4 + devGetModel @5 + devGetNumberOfArguments @6 + devGetArgument @7 + + devSetName @8 + devSetVendor @9 + devSetModel @10 + devSetArguments @11 + + devAddDevice @12 + devRemoveDevice @13 + + devMethods @14 + devTurnOn @16 + devTurnOff @17 + devBell @18 + devDim @19 diff --git a/driver/TellUsbD101/TellUsbD101.h b/driver/TellUsbD101/TellUsbD101.h new file mode 100644 index 00000000..9e7fa756 --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.h @@ -0,0 +1,82 @@ +#ifndef TELLUSBD101_H +#define TELLUSBD101_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TellUsbD101_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLSTICK_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef TellUsbD101_EXPORTS + #define TELLSTICK_API __declspec(dllexport) +#else + #define TELLSTICK_API __declspec(dllimport) +#endif +#ifdef _WINDOWS + #define WINAPI __stdcall +#else + #define WINAPI +#endif + + +extern "C" { + TELLSTICK_API bool WINAPI devTurnOn(int intDeviceId); + TELLSTICK_API bool WINAPI devTurnOff(int intDeviceId); + TELLSTICK_API bool WINAPI devBell(int intDeviceId); + TELLSTICK_API bool WINAPI devDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI devGetNumberOfDevices(); + TELLSTICK_API char * WINAPI devGetName(int intDeviceId); + TELLSTICK_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char* WINAPI devGetVendor(int intDeviceId); + TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); + TELLSTICK_API char* WINAPI devGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, const char* chNewName); + TELLSTICK_API int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex); + TELLSTICK_API int WINAPI devGetNumberOfArguments(int intDeviceId); + TELLSTICK_API bool WINAPI devSetArguments(int intDeviceId, const char* strArguments); + TELLSTICK_API int WINAPI devAddDevice(); + TELLSTICK_API int WINAPI devAddDeviceWithArguments(char* strVendor, int* intArguments[], int intNumberOfArguments); + TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); + TELLSTICK_API int WINAPI devGetDeviceId(int intDeviceIndex); + TELLSTICK_API int WINAPI devMethods(int id); +} + +#define TELLSTICK_TURNON 1 +#define TELLSTICK_TURNOFF 2 +#define TELLSTICK_BELL 4 +#define TELLSTICK_TOGGLE 8 +#define TELLSTICK_DIM 16 + +//Protocol Nexa +#define TELLSTICK_DEVICE_YCR3500 "1" +#define TELLSTICK_DEVICE_YCR300D "2" +#define TELLSTICK_DEVICE_WSR1000 "3" +#define TELLSTICK_DEVICE_CMR1000 "4" +#define TELLSTICK_DEVICE_CMR300 "5" +#define TELLSTICK_DEVICE_PA33300 "6" +#define TELLSTICK_DEVICE_EL2000 "8" +#define TELLSTICK_DEVICE_EL2005 "9" +#define TELLSTICK_DEVICE_EL2006 "10" +#define TELLSTICK_DEVICE_SYCR3500 "12" +#define TELLSTICK_DEVICE_SYCR300 "13" +#define TELLSTICK_DEVICE_HDR105 "14" +#define TELLSTICK_DEVICE_ML7100 "15" +#define TELLSTICK_DEVICE_EL2004 "16" +#define TELLSTICK_DEVICE_EL2016 "17" +#define TELLSTICK_DEVICE_EL2010 "18" +#define TELLSTICK_DEVICE_LYCR1000 "20" +#define TELLSTICK_DEVICE_LYCR300 "21" +#define TELLSTICK_DEVICE_LCMR1000 "22" +#define TELLSTICK_DEVICE_LCMR300 "23" +#define TELLSTICK_DEVICE_EL2023 "24" +#define TELLSTICK_DEVICE_EL2024 "25" +#define TELLSTICK_DEVICE_EL2021 "26" +#define TELLSTICK_DEVICE_EL2017 "27" +#define TELLSTICK_DEVICE_EL2019 "28" + +//Protocol Ikea +#define TELLSTICK_DEVICE_KOPPLA "19" + +#endif diff --git a/driver/TellUsbD101/TellUsbD101.vcproj b/driver/TellUsbD101/TellUsbD101.vcproj new file mode 100644 index 00000000..5758d02b --- /dev/null +++ b/driver/TellUsbD101/TellUsbD101.vcproj @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/driver/TellUsbD101/TelldusSettings.cpp b/driver/TellUsbD101/TelldusSettings.cpp new file mode 100644 index 00000000..d15b6e2f --- /dev/null +++ b/driver/TellUsbD101/TelldusSettings.cpp @@ -0,0 +1,631 @@ +#include "StdAfx.h" +#include "TelldusSettings.h" +#include "Device.h" +#include "DeviceNexa.h" +#include "DeviceWaveman.h" +#include "DeviceSartano.h" +#include "DeviceIkea.h" +#include +#include +#include +#include +#include + +using namespace std; + +/* +* Constructor +*/ +TelldusSettings::TelldusSettings(void) +{ + strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; + strRegPath = "SOFTWARE\\Telldus\\"; + + intMaxRegValueLength = 1000; +} + +/* +* Destructor +*/ +TelldusSettings::~TelldusSettings(void) +{ + //RegCloseKey(hk); //close all, if still open //TODO: Need some way to know if open or closed + strRegPath = ""; + strRegPathDevice = ""; + intMaxRegValueLength = -1; + +} + +/* +* Return the number of stored devices +*/ +int TelldusSettings::getNumberOfDevices(void){ + + int intNumberOfDevices = 0; + + try{ + + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + + string strNumSubKeys; + DWORD dNumSubKeys; + RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + intNumberOfDevices = (int)dNumSubKeys; + + RegCloseKey(hk); + } + else{ + throw exception(); //couldn't open reg key + } + } + catch(...){ + intNumberOfDevices = -1; + } + return intNumberOfDevices; +} + +/* +* Get the requested device +*/ +Device* TelldusSettings::getDevice(int intDeviceId){ + + try{ + int intDongleIndex = Device::getDongleIndex(); + if(intDongleIndex != -1){ + return getDevice(intDeviceId, intDongleIndex); + } + else{ + return NULL; + } + } + catch(...){ + throw; + } +} + +/* +* Get the requested device, when the index of the USB dongle is known +* Note that the returned Device should be deleted when not in use anymore +*/ +Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ + + Device* dev = 0; + + try{ + char* vendor = getVendor(intDeviceId); + + int* args = getArguments(intDeviceId); + + //each new brand must be added here + if (strcmp(vendor, "Nexa") == 0){ + dev = new DeviceNexa((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Waveman") == 0) { + dev = new DeviceWaveman((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Sartano") == 0) { + dev = new DeviceSartano((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Ikea") == 0) { + dev = new DeviceIkea((int)args[0], (int)args[1], (int)args[2], intDongleIndex); + } + } + catch(...){ + throw; + } + return dev; +} + +/* +* Get the name of the device +*/ +char* TelldusSettings::getName(int intDeviceId){ + + char* strReturn = ""; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + strReturn = Buff; + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + strReturn = ""; + } + return strReturn; +} + +/* +* Set the name of the device +*/ +bool TelldusSettings::setName(int intDeviceId, char* strNewName){ + + bool blnSuccess = true; + try{ + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + intMaxRegValueLength = (int)strlen(strNewName); + RegSetValueEx(hk, "Name", 0, REG_SZ, (LPBYTE)strNewName, intMaxRegValueLength); + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +/* +* Get the device vendor +*/ +char* TelldusSettings::getVendor(int intDeviceId){ + + char* strReturn = ""; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + + strReturn = Buff; + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(exception e){ + strReturn = ""; + ofstream errorfile("c:\\errorlog.txt", ios::app); + if(errorfile){ + errorfile << e.what() << endl; + errorfile.close(); + } + } + return strReturn; +} + +/* +* Set the device vendor +*/ +bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ + + bool blnSuccess = true; + try{ + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + intMaxRegValueLength = (int)strlen(strVendor); + RegSetValueEx(hk, "Vendor", 0, REG_SZ, (LPBYTE)strVendor, intMaxRegValueLength); + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +/* +* Get the device model +*/ +char* TelldusSettings::getModel(int intDeviceId){ + + char* strReturn = ""; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + strReturn = Buff; + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + strReturn = ""; + } + return strReturn; +} + +/* +* Set the device model +*/ +bool TelldusSettings::setModel(int intDeviceId, char* strVendor){ + + bool blnSuccess = true; + try{ + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + intMaxRegValueLength = (int)strlen(strVendor); + RegSetValueEx(hk, "Model", 0, REG_SZ, (LPBYTE)strVendor, intMaxRegValueLength); + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +int TelldusSettings::getDeviceId(int intDeviceIndex){ + int intReturn = -1; + + try{ + + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_READ, &hk); + + if(lnExists == ERROR_SUCCESS){ + + char* Buff = new char[intMaxRegValueLength]; + DWORD size; + if (RegEnumKeyEx(hk, intDeviceIndex, (LPSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + intReturn = (int)_atoi64(Buff); + } + + delete Buff; + + RegCloseKey(hk); + } + else{ + throw exception(); //couldn't open reg key + } + } + catch(...){ + intReturn = -1; + } + return intReturn; + + +} + +/* +* Get number of device arguments +*/ +int TelldusSettings::getNumberOfArguments(int intDeviceId){ + int intReturn = -1; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dNumValues; + RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); + intReturn = (int)dNumValues - 3; //total number of values - model, name and vendor + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + } + catch(...){ + //error management + } + + return intReturn; +} + +/* +* Get device arguments +*/ +int* TelldusSettings::getArguments(int intDeviceId){ + vector vReturn; + int* intReturn = new int[]; + + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dNumValues; + RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); + + int intNumberOfArguments = (int)dNumValues - 3; //total number of values - model, name and vendor + DWORD dwLength; + char chConvertBuffer[20]; + int i = 0; + + while(i < intNumberOfArguments){ + + char* Buff = new char[intMaxRegValueLength]; + + _itoa(i, chConvertBuffer, 10); + long lngStatus = RegQueryValueEx(hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + lngStatus = RegQueryValueEx(hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); + } + int intReturn = (int)_atoi64(Buff); + vReturn.push_back(intReturn); + + i++; + delete Buff; + } + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + intReturn = new int[vReturn.size()]; + + int i = 0; + while(i < (int)vReturn.size()){ + intReturn[i] = vReturn.at(i); + i++; + } + } + catch(...){ + //error management + } + + return intReturn; +} + +/* +* Set device arguments +*/ +bool TelldusSettings::setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments){ + + bool blnSuccess = true; + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + char chConvertBuffer [20]; + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + int i = 0; + while(i < intNumberOfArguments){ + _itoa(i, chConvertBuffer, 10); + RegSetValueEx(hk, chConvertBuffer, 0, REG_SZ, (LPBYTE)intArguments[i], intMaxRegValueLength); + i++; + } + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + +/* +* Set device arguments +*/ +bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ + + bool blnSuccess = true; + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + char chConvertBuffer [20]; + char chConvertBufferValue [20]; + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if(lnExists == ERROR_SUCCESS){ + int i = 0; + while(i < vArguments.size()){ + _itoa(i, chConvertBuffer, 10); + _itoa(vArguments.at(i), chConvertBufferValue, 10); + intMaxRegValueLength = (int)strlen(chConvertBufferValue); + RegSetValueEx(hk, chConvertBuffer, 0, REG_SZ, (LPBYTE)chConvertBufferValue, intMaxRegValueLength); + i++; + } + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(hk); + + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; +} + + +/* +* Add a new device +*/ +int TelldusSettings::addDevice(){ + + int intDeviceId = -1; + try{ + + DWORD dwDisp; + intDeviceId = getNextDeviceId(); + + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + + if(RegCreateKeyEx(HKEY_CURRENT_USER, + strCompleteRegPath.c_str(), + 0, + NULL, + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hk, + &dwDisp)){ + //fail + throw exception("Create Key failed"); + } + + RegCloseKey(hk); + + } + catch(...){ + intDeviceId = -1; + } + return intDeviceId; +} + +/* +* Get next available device id +*/ +int TelldusSettings::getNextDeviceId(){ + + int intReturn = -1; + try{ + DWORD dwDisp; + long lnExists = RegCreateKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hk, + &dwDisp); //create or open if already created + + if(lnExists == ERROR_SUCCESS){ + + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + + + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + + if(lngStatus == ERROR_SUCCESS){ + + int intLast = (int)Buff[0]; + intReturn = intLast + 1; + } + else{ + intReturn = 1; + } + delete Buff; + + DWORD dwVal = intReturn; + + RegSetValueEx (hk, "LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + + } + RegCloseKey(hk); + } + catch(...){ + intReturn = -1; + } + return intReturn; +} + +/* +* Remove a device +*/ +bool TelldusSettings::removeDevice(int intDeviceId){ + + bool blnSuccess = true; + try{ + std::ostringstream ssRegPath; + ssRegPath << strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + + long lngSuccess = RegDeleteKey(HKEY_CURRENT_USER, strCompleteRegPath.c_str()); + if(lngSuccess != ERROR_SUCCESS){ + blnSuccess = false; + } + } + catch(...){ + blnSuccess = false; + } + + return blnSuccess; +} + +//only for debug reasons +void TelldusSettings::debugLog(char* debugstring){ + ofstream debugfile("c:\\telldusdebug.txt", ios::app); + if(debugfile){ + debugfile << debugstring << endl; + debugfile.close(); + } +} + +//only for debug reasons +void TelldusSettings::debugLog(int debugint){ + ofstream debugfile("c:\\telldusdebug.txt", ios::app); + if(debugfile){ + debugfile << debugint << endl; + debugfile.close(); + } +} \ No newline at end of file diff --git a/driver/TellUsbD101/TelldusSettings.h b/driver/TellUsbD101/TelldusSettings.h new file mode 100644 index 00000000..65de9cc2 --- /dev/null +++ b/driver/TellUsbD101/TelldusSettings.h @@ -0,0 +1,42 @@ +#pragma once +#include "device.h" +#include "devicenexa.h" +#include +#include + +using namespace std; + +class TelldusSettings +{ +public: + TelldusSettings(void); + int getNumberOfDevices(void); + Device* getDevice(int intDeviceId); + Device* getDevice(int intDeviceId, int intDongleIndex); + char* getName(int intDeviceId); + bool setName(int intDeviceId, char* strNewName); + char* getVendor(int intDeviceId); + bool setVendor(int intDeviceId, char* strVendor); + char* getModel(int intDeviceId); + bool setModel(int intDeviceId, char* strModel); + int* getArguments(int intDeviceId); + bool setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments); + bool setArguments(int intDeviceId, vector vArguments); + int addDevice(); + int getDeviceId(int intDeviceIndex); + bool removeDevice(int intDeviceId); + void debugLog(char* debugstring); + void debugLog(int debugint); + int getNumberOfArguments(int intDeviceId); + + ~TelldusSettings(void); + +private: + int getNextDeviceId(); + + //variables + HKEY hk; + std::string strRegPathDevice; + std::string strRegPath; + int intMaxRegValueLength; +}; diff --git a/driver/TellUsbD101/linux/Device.cpp b/driver/TellUsbD101/linux/Device.cpp new file mode 100644 index 00000000..7aeff050 --- /dev/null +++ b/driver/TellUsbD101/linux/Device.cpp @@ -0,0 +1,85 @@ +#include "../Device.h" +#include +#include +#include + +/* +* Send message to the USB dongle +*/ +void Device::send(char* strMessage) { + int fd = -1; + struct termios tio; + + debugLog(strMessage); + + if( 0 > ( fd = open( "/dev/tellstick", O_RDWR ) ) ) { + return; + } + + /* adjust serial port parameters */ + bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ + tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ + tio.c_iflag = IGNPAR; + tio.c_oflag = 0; + tcflush(fd, TCIFLUSH); + tcsetattr(fd,TCSANOW,&tio); + + write(fd, strMessage, strlen(strMessage)); + + close(fd); +} + +/* +* Get the device index of the Telldus dongle (the first one if many are connected) +* -1 if no such device exists +*/ +int Device::getDongleIndex(){ + int intReturn = -1; +/* FT_HANDLE fthHandle = 0; + FT_STATUS ftStatus = FT_OK; + + try{ + DWORD dwNumberOfDevices = 0; + + ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); + if (ftStatus == FT_OK) { + for (int i = 0; i < (int)dwNumberOfDevices; i++) { + + FT_PROGRAM_DATA pData; + char ManufacturerBuf[32]; + char ManufacturerIdBuf[16]; + char DescriptionBuf[64]; + char SerialNumberBuf[16]; + + pData.Signature1 = 0x00000000; + pData.Signature2 = 0xffffffff; + pData.Version = 0x00000002; // EEPROM structure with FT232R extensions + pData.Manufacturer = ManufacturerBuf; + pData.ManufacturerId = ManufacturerIdBuf; + pData.Description = DescriptionBuf; + pData.SerialNumber = SerialNumberBuf; + + ftStatus = FT_Open(i, &fthHandle); + ftStatus = FT_EE_Read(fthHandle, &pData); + if(ftStatus == FT_OK){ + if(pData.VendorId == 6017 && pData.ProductId == 3120){ + intReturn = i; + ftStatus = FT_Close(fthHandle); + break; + } + } + ftStatus = FT_Close(fthHandle); + } + } + } + catch(...){ + throw; + }*/ + return intReturn; +} + +//only for debugging purpose +void Device::debugLog(char* debugstring){ + std::cout << debugstring << std::endl; +} + diff --git a/driver/TellUsbD101/stdafx.cpp b/driver/TellUsbD101/stdafx.cpp new file mode 100644 index 00000000..54385d7a --- /dev/null +++ b/driver/TellUsbD101/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// testruntelldus3.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/driver/TellUsbD101/stdafx.h b/driver/TellUsbD101/stdafx.h new file mode 100644 index 00000000..5df7bbe1 --- /dev/null +++ b/driver/TellUsbD101/stdafx.h @@ -0,0 +1,37 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Allow use of features specific to Windows XP or later. +#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. +#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. +#endif + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +// Windows Header Files: +#include + +// C RunTime Header Files +#include +#include +#include +#include + + +// TODO: reference additional headers your program requires here diff --git a/driver/TellUsbD101/win/Device.cpp b/driver/TellUsbD101/win/Device.cpp new file mode 100644 index 00000000..ce5a065c --- /dev/null +++ b/driver/TellUsbD101/win/Device.cpp @@ -0,0 +1,91 @@ +#include "..\Device.h" +#include +#include +#include +#include +#include +#include "..\StdAfx.h" +#include "FTD2XX.H" + +/* +* Send message to the USB dongle +*/ +void Device::send(char* strMessage){ + + try{ + FT_STATUS ftStatus = FT_OK; + FT_HANDLE fthHandle = 0; + + ftStatus = FT_Open(this->intDongleIndex, &fthHandle); + int intBaudRate = 4800; //always 4800 + ftStatus = FT_SetBaudRate(fthHandle, intBaudRate); + ULONG bytesWritten; + + int intLen = (int)strlen(strMessage); + ftStatus = FT_Write(fthHandle, strMessage, intLen, &bytesWritten); + + ftStatus = FT_Close(fthHandle); + } + catch(...){ + throw; + } +} + +/* +* Get the device index of the Telldus dongle (the first one if many are connected) +* -1 if no such device exists +*/ +int Device::getDongleIndex(){ + int intReturn = -1; + FT_HANDLE fthHandle = 0; + FT_STATUS ftStatus = FT_OK; + + try{ + DWORD dwNumberOfDevices = 0; + + ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); + if (ftStatus == FT_OK) { + for (int i = 0; i < (int)dwNumberOfDevices; i++) { + + FT_PROGRAM_DATA pData; + char ManufacturerBuf[32]; + char ManufacturerIdBuf[16]; + char DescriptionBuf[64]; + char SerialNumberBuf[16]; + + pData.Signature1 = 0x00000000; + pData.Signature2 = 0xffffffff; + pData.Version = 0x00000002; // EEPROM structure with FT232R extensions + pData.Manufacturer = ManufacturerBuf; + pData.ManufacturerId = ManufacturerIdBuf; + pData.Description = DescriptionBuf; + pData.SerialNumber = SerialNumberBuf; + + ftStatus = FT_Open(i, &fthHandle); + ftStatus = FT_EE_Read(fthHandle, &pData); + if(ftStatus == FT_OK){ + if(pData.VendorId == 6017 && pData.ProductId == 3120){ + intReturn = i; + ftStatus = FT_Close(fthHandle); + break; + } + } + ftStatus = FT_Close(fthHandle); + } + } + } + catch(...){ + throw; + } + return intReturn; +} + +//only for debugging purpose +void Device::debugLog(char* debugstring){ + std::ofstream debugfile("c:\\telldusdebug.txt", std::ios::app); + if(debugfile){ + debugfile << debugstring << std::endl; + debugfile.close(); + } +} + diff --git a/driver/TellUsbD101/win/FTD2XX.H b/driver/TellUsbD101/win/FTD2XX.H new file mode 100644 index 00000000..2507326c --- /dev/null +++ b/driver/TellUsbD101/win/FTD2XX.H @@ -0,0 +1,875 @@ +/*++ + +Copyright (c) 2001-2005 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB device driver for FTDI FT8U232/245 + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + 23/01/04 awm Added support for open-by-location. + 16/03/04 awm Added support for FT2232C. + 23/09/04 awm Added support for FT232R. + 20/10/04 awm Added FT_CyclePort. + 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. + 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. + 25/08/05 awm Added FT_SetDeadmanTimeout. + 02/12/05 awm Removed obsolete references. + 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // FT2232C extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // FT232R extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + + UCHAR RIsVCP; // non-zero if using VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + From 19e0c73686f36860f43d43aa98fe9e3dd59ba07f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Feb 2008 18:45:01 +0000 Subject: [PATCH 0047/2215] First commit with the driver working with libConfuse. Probably breaks windows-build! --- driver/TellUsbD101/CMakeLists.txt | 9 +- driver/TellUsbD101/TellUsbD101.cpp | 45 +-- driver/TellUsbD101/TellUsbD101.h | 19 +- .../TellUsbD101/settings/TelldusSettings.cpp | 36 +++ .../{ => settings}/TelldusSettings.h | 27 +- .../settings/TelldusSettingsConfuse.cpp | 299 ++++++++++++++++++ .../TelldusSettingsWinRegistry.cpp} | 35 -- 7 files changed, 389 insertions(+), 81 deletions(-) create mode 100644 driver/TellUsbD101/settings/TelldusSettings.cpp rename driver/TellUsbD101/{ => settings}/TelldusSettings.h (69%) create mode 100644 driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp rename driver/TellUsbD101/{TelldusSettings.cpp => settings/TelldusSettingsWinRegistry.cpp} (88%) diff --git a/driver/TellUsbD101/CMakeLists.txt b/driver/TellUsbD101/CMakeLists.txt index 55842bce..e14f88c1 100644 --- a/driver/TellUsbD101/CMakeLists.txt +++ b/driver/TellUsbD101/CMakeLists.txt @@ -6,6 +6,9 @@ SET( tellusbd101_SRCS DeviceNexa.cpp DeviceSartano.cpp DeviceWaveman.cpp + settings/TelldusSettings.cpp + settings/TelldusSettingsConfuse.cpp + TellUsbD101.cpp ) ADD_DEFINITIONS( @@ -17,9 +20,9 @@ ADD_LIBRARY(tellusbd101 SHARED ${tellusbd101_MOC_SRCS} ) -# TARGET_LINK_LIBRARIES(tellusbd101 -# ${MIDAS_LIBRARY} -# ) +TARGET_LINK_LIBRARIES(tellusbd101 + confuse + ) INSTALL(TARGETS tellusbd101 LIBRARY DESTINATION lib diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index cfd4f3e1..7141e919 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -1,15 +1,18 @@ //DLL entry point -#include "stdafx.h" +#ifdef _WINDOWS + #include "stdafx.h" + #include +#endif #include "TellUsbD101.h" -#include "TelldusSettings.h" +#include "settings/TelldusSettings.h" #include "Device.h" #include #include #include -#include void handleException(std::exception e); +using namespace std; #define MAX_LOADSTRING 100 @@ -18,7 +21,7 @@ void handleException(std::exception e); //delete on created objects //comment (just copy from the called methods) -bool __stdcall devTurnOn(int intDeviceId){ +bool WINAPI devTurnOn(int intDeviceId){ try{ TelldusSettings ts; @@ -39,7 +42,7 @@ bool __stdcall devTurnOn(int intDeviceId){ return false; } -bool __stdcall devTurnOff(int intDeviceId){ +bool WINAPI devTurnOff(int intDeviceId){ try{ TelldusSettings ts; @@ -60,7 +63,7 @@ bool __stdcall devTurnOff(int intDeviceId){ return false; } -bool __stdcall devBell(int intDeviceId){ +bool WINAPI devBell(int intDeviceId){ try{ TelldusSettings ts; @@ -81,7 +84,7 @@ bool __stdcall devBell(int intDeviceId){ return false; } -bool __stdcall devDim(int intDeviceId, unsigned char level){ +bool WINAPI devDim(int intDeviceId, unsigned char level){ try{ TelldusSettings ts; @@ -107,7 +110,7 @@ bool __stdcall devDim(int intDeviceId, unsigned char level){ return false; } -int __stdcall devGetNumberOfDevices(void){ +int WINAPI devGetNumberOfDevices(void){ int intReturn = -1; try{ TelldusSettings ts; @@ -120,7 +123,7 @@ int __stdcall devGetNumberOfDevices(void){ return intReturn; } -int __stdcall devGetDeviceId(int intDeviceIndex){ +int WINAPI devGetDeviceId(int intDeviceIndex){ int intReturn = -1; try{ TelldusSettings ts; @@ -134,7 +137,7 @@ int __stdcall devGetDeviceId(int intDeviceIndex){ } //general settings: -char * __stdcall devGetName(int intDeviceId){ +char * WINAPI devGetName(int intDeviceId){ char* strReturn; try{ TelldusSettings ts; @@ -147,7 +150,7 @@ char * __stdcall devGetName(int intDeviceId){ return strReturn; } -bool __stdcall devSetName(int intDeviceId, char* strNewName){ +bool WINAPI devSetName(int intDeviceId, char* strNewName){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -160,7 +163,7 @@ bool __stdcall devSetName(int intDeviceId, char* strNewName){ return blnSuccess; } -char* __stdcall devGetVendor(int intDeviceId){ +char* WINAPI devGetVendor(int intDeviceId){ char* strReturn = ""; try{ TelldusSettings ts; @@ -173,7 +176,7 @@ char* __stdcall devGetVendor(int intDeviceId){ return strReturn; } -bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ +bool WINAPI devSetVendor(int intDeviceId, char* strVendor){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -186,7 +189,7 @@ bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ return blnSuccess; } - char* __stdcall devGetModel(int intDeviceId){ + char* WINAPI devGetModel(int intDeviceId){ char* strReturn = ""; try{ TelldusSettings ts; @@ -199,7 +202,7 @@ bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ return strReturn; } -bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ +bool WINAPI devSetModel(int intDeviceId, char* strNewModel){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -212,7 +215,7 @@ bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ return blnSuccess; } -bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ +bool WINAPI devSetArguments(int intDeviceId, char* strArguments){ vector vArguments; //int intArguments[] = new int[]; //bort? @@ -232,7 +235,7 @@ bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ } } -int __stdcall devGetArgument(int intDeviceId, int intArgumentIndex){ +int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex){ int intReturn; try{ if(intArgumentIndex != -1){ @@ -247,7 +250,7 @@ int __stdcall devGetArgument(int intDeviceId, int intArgumentIndex){ return intReturn; } -int __stdcall devGetNumberOfArguments(int intDeviceId){ +int WINAPI devGetNumberOfArguments(int intDeviceId){ int intReturn; try{ TelldusSettings ts; @@ -259,7 +262,7 @@ int __stdcall devGetNumberOfArguments(int intDeviceId){ return intReturn; } -int __stdcall devAddDevice(){ +int WINAPI devAddDevice(){ int intNewDeviceId = -1; try{ TelldusSettings ts; @@ -272,7 +275,7 @@ int __stdcall devAddDevice(){ return intNewDeviceId; } -bool __stdcall devRemoveDevice(int intDeviceId){ +bool WINAPI devRemoveDevice(int intDeviceId){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -285,7 +288,7 @@ bool __stdcall devRemoveDevice(int intDeviceId){ return blnSuccess; } -int __stdcall devMethods(int id){ +int WINAPI devMethods(int id){ int intMethods = 0; try{ diff --git a/driver/TellUsbD101/TellUsbD101.h b/driver/TellUsbD101/TellUsbD101.h index 9e7fa756..980a6f45 100644 --- a/driver/TellUsbD101/TellUsbD101.h +++ b/driver/TellUsbD101/TellUsbD101.h @@ -9,15 +9,16 @@ // TELLSTICK_API functions as being imported from a DLL, whereas this DLL // sees symbols defined with this macro as being exported. -#ifdef TellUsbD101_EXPORTS - #define TELLSTICK_API __declspec(dllexport) -#else - #define TELLSTICK_API __declspec(dllimport) -#endif #ifdef _WINDOWS + #ifdef TellUsbD101_EXPORTS + #define TELLSTICK_API __declspec(dllexport) + #else + #define TELLSTICK_API __declspec(dllimport) + #endif #define WINAPI __stdcall #else #define WINAPI + #define TELLSTICK_API #endif @@ -28,14 +29,14 @@ extern "C" { TELLSTICK_API bool WINAPI devDim(int intDeviceId, unsigned char level); TELLSTICK_API int WINAPI devGetNumberOfDevices(); TELLSTICK_API char * WINAPI devGetName(int intDeviceId); - TELLSTICK_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API bool WINAPI devSetName(int intDeviceId, char* chNewName); TELLSTICK_API char* WINAPI devGetVendor(int intDeviceId); - TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); + TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, char* chNewName); TELLSTICK_API char* WINAPI devGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, const char* chNewName); + TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, char* chNewName); TELLSTICK_API int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex); TELLSTICK_API int WINAPI devGetNumberOfArguments(int intDeviceId); - TELLSTICK_API bool WINAPI devSetArguments(int intDeviceId, const char* strArguments); + TELLSTICK_API bool WINAPI devSetArguments(int intDeviceId, char* strArguments); TELLSTICK_API int WINAPI devAddDevice(); TELLSTICK_API int WINAPI devAddDeviceWithArguments(char* strVendor, int* intArguments[], int intNumberOfArguments); TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); diff --git a/driver/TellUsbD101/settings/TelldusSettings.cpp b/driver/TellUsbD101/settings/TelldusSettings.cpp new file mode 100644 index 00000000..f5d81e49 --- /dev/null +++ b/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -0,0 +1,36 @@ +#include "TelldusSettings.h" +#include "../DeviceNexa.h" +#include "../DeviceWaveman.h" +#include "../DeviceSartano.h" +#include "../DeviceIkea.h" + + +/* +* Get the requested device, when the index of the USB dongle is known +* Note that the returned Device should be deleted when not in use anymore +*/ +Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ + + Device* dev = 0; + + try{ + char* vendor = getVendor(intDeviceId); + + int* args = getArguments(intDeviceId); + + //each new brand must be added here + if (strcmp(vendor, "Nexa") == 0){ + dev = new DeviceNexa((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Waveman") == 0) { + dev = new DeviceWaveman((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Sartano") == 0) { + dev = new DeviceSartano((int)args[0], (int)args[1], intDongleIndex); + } else if (strcmp(vendor, "Ikea") == 0) { + dev = new DeviceIkea((int)args[0], (int)args[1], (int)args[2], intDongleIndex); + } + } + catch(...){ + throw; + } + return dev; +} diff --git a/driver/TellUsbD101/TelldusSettings.h b/driver/TellUsbD101/settings/TelldusSettings.h similarity index 69% rename from driver/TellUsbD101/TelldusSettings.h rename to driver/TellUsbD101/settings/TelldusSettings.h index 65de9cc2..a8836cc7 100644 --- a/driver/TellUsbD101/TelldusSettings.h +++ b/driver/TellUsbD101/settings/TelldusSettings.h @@ -1,10 +1,10 @@ -#pragma once -#include "device.h" -#include "devicenexa.h" -#include -#include +#ifndef TELLDUSSETTINGS_H +#define TELLDUSSETTINGS_H -using namespace std; +#include "../Device.h" +#include + +class privateVars; class TelldusSettings { @@ -20,7 +20,6 @@ public: char* getModel(int intDeviceId); bool setModel(int intDeviceId, char* strModel); int* getArguments(int intDeviceId); - bool setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments); bool setArguments(int intDeviceId, vector vArguments); int addDevice(); int getDeviceId(int intDeviceIndex); @@ -30,13 +29,15 @@ public: int getNumberOfArguments(int intDeviceId); ~TelldusSettings(void); + +protected: + char *getStringSetting(int intDeviceId, const char* name); + bool setStringSetting(int intDeviceId, const char* name, const char *value); private: int getNextDeviceId(); - - //variables - HKEY hk; - std::string strRegPathDevice; - std::string strRegPath; - int intMaxRegValueLength; + + privateVars *d; }; + +#endif diff --git a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp new file mode 100644 index 00000000..676ddccb --- /dev/null +++ b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp @@ -0,0 +1,299 @@ +// +// C++ Implementation: telldussettingsconfuse +// +// Description: +// +// +// Author: Micke Prag , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "TelldusSettings.h" +#include + +using namespace std; + +class privateVars { +public: + cfg_t *cfg; +}; + +bool readConfig(cfg_t **cfg); + +const char* CONFIG_FILE = "/etc/tellstick.conf"; + +/* +* Constructor +*/ +TelldusSettings::TelldusSettings(void) +{ + d = new privateVars(); + readConfig(&d->cfg); +// printf("Nu: %d\n", cfg_size(d->cfg, "device")); + +} + +/* +* Destructor +*/ +TelldusSettings::~TelldusSettings(void) +{ + if (d->cfg > 0) + cfg_free(d->cfg); +} + +/* +* Return the number of stored devices +*/ +int TelldusSettings::getNumberOfDevices(void){ + if (d->cfg > 0) { + return cfg_size(d->cfg, "device"); + } + return 0; +} + +/* +* Get the requested device +*/ +Device* TelldusSettings::getDevice(int intDeviceId){ + return NULL; +} + +/* +* Get the name of the device +*/ +char* TelldusSettings::getName(int intDeviceId){ + return getStringSetting(intDeviceId, "name"); +} + +/* +* Set the name of the device +*/ +bool TelldusSettings::setName(int intDeviceId, char* strNewName){ + bool blnSuccess = true; + setStringSetting(intDeviceId, "name", strNewName); + return blnSuccess; +} + +/* +* Get the device vendor +*/ +char* TelldusSettings::getVendor(int intDeviceId){ + return getStringSetting(intDeviceId, "vendor"); +} + +/* +* Set the device vendor +*/ +bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ + bool blnSuccess = true; + setStringSetting(intDeviceId, "vendor", strVendor); + return blnSuccess; +} + +/* +* Get the device model +*/ +char* TelldusSettings::getModel(int intDeviceId){ + return getStringSetting(intDeviceId, "model"); +} + +/* +* Set the device model +*/ +bool TelldusSettings::setModel(int intDeviceId, char* strVendor){ + bool blnSuccess = true; + setStringSetting(intDeviceId, "model", strVendor); + return blnSuccess; +} + +int TelldusSettings::getDeviceId(int intDeviceIndex){ + if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds + return -1; + } + cfg_t *cfg_device = cfg_getnsec(d->cfg, "device", intDeviceIndex); + int id = cfg_getint(cfg_device, "id"); + return id; +} + +/* +* Get number of device arguments +*/ +int TelldusSettings::getNumberOfArguments(int intDeviceId){ + int intReturn = -1; + + return intReturn; +} + +/* +* Get device arguments +*/ +int* TelldusSettings::getArguments(int intDeviceId){ +// vector vReturn; + int* intReturn = new int[2]; + + return intReturn; +} + +/* +* Set device arguments +*/ +bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ + + bool blnSuccess = false; + return blnSuccess; +} + +/* +* Add a new device +*/ +int TelldusSettings::addDevice(){ + int intDeviceId = getNextDeviceId(); + + FILE *fp = fopen(CONFIG_FILE, "w"); + cfg_print(d->cfg, fp); //Print the config-file + fprintf(fp, "device {\n id=%d\n}\n", intDeviceId); //Print the new device + fclose(fp); + + //Re-read config-file + cfg_free(d->cfg); + readConfig(&d->cfg); + return intDeviceId; +} + +/* +* Get next available device id +*/ +int TelldusSettings::getNextDeviceId(){ + int intDeviceId = 0; + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") >= intDeviceId) { + intDeviceId = cfg_getint(cfg_device, "id"); + } + } + intDeviceId++; + return intDeviceId; +} + +/* +* Remove a device +*/ +bool TelldusSettings::removeDevice(int intDeviceId){ + bool blnSuccess = true; + FILE *fp = fopen(CONFIG_FILE, "w"); + + // Print all opts + for(int i = 0; d->cfg->opts[i].name; i++) { + + // Check if it isn't a device section + if (strcmp(d->cfg->opts[i].name, "device") != 0) { + cfg_opt_print(&d->cfg->opts[i], fp); + } else { + // Print all sections except the one to remove + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") != intDeviceId) { //This isn't the one to skip + fprintf(fp, "device {\n"); + cfg_print_indent(cfg_device, fp, 1); + fprintf(fp, "}\n"); + } + } + } + } + fclose(fp); + + //Re-read config-file + cfg_free(d->cfg); + readConfig(&d->cfg); + + return blnSuccess; +} + +//only for debug reasons +void TelldusSettings::debugLog(char* debugstring){ +/* ofstream debugfile("c:\\telldusdebug.txt", ios::app); + if(debugfile){ + debugfile << debugstring << endl; + debugfile.close(); + }*/ +} + +//only for debug reasons +void TelldusSettings::debugLog(int debugint){ +/* ofstream debugfile("c:\\telldusdebug.txt", ios::app); + if(debugfile){ + debugfile << debugint << endl; + debugfile.close(); + }*/ +} + +char *TelldusSettings::getStringSetting(int intDeviceId, const char* name) { + if (d->cfg == 0) { + return ""; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + const char *strSetting = cfg_getstr(cfg_device, name); + char *strReturn = (char *)malloc(strlen(strSetting) * sizeof(char)); + strcpy(strReturn, strSetting); + return strReturn; + } + } + return ""; +} + +bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value) { + if (d->cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + cfg_setstr(cfg_device, name, value); + FILE *fp = fopen(CONFIG_FILE, "w"); + cfg_print(d->cfg, fp); + fclose(fp); + return true; + } + } + return false; +} + +bool readConfig(cfg_t **cfg) { + cfg_opt_t device_opts[] = { + CFG_INT("id", -1, CFGF_NONE), + CFG_STR("name", "Unnamed", CFGF_NONE), + CFG_STR("vendor", "Nexa", CFGF_NONE), + CFG_STR("model", "1", CFGF_NONE), + + //Nexa + CFG_STR("nexa_house", 0, CFGF_NONE), + CFG_STR("nexa_unit", 0, CFGF_NONE), + + //Ikea + CFG_STR("ikea_system", 0, CFGF_NONE), + CFG_STR("ikea_units", 0, CFGF_NONE), + CFG_STR("ikea_fade", 0, CFGF_NONE), + + CFG_END() + }; + cfg_opt_t opts[] = { + CFG_STR("deviceNode", "/dev/tellstick", CFGF_NONE), + CFG_SEC("device", device_opts, CFGF_MULTI), + CFG_END() + }; + (*cfg) = cfg_init(opts, CFGF_NOCASE); + if (cfg_parse((*cfg), CONFIG_FILE) == CFG_PARSE_ERROR) { + (*cfg) = 0; + return false; + } + + return true; +} diff --git a/driver/TellUsbD101/TelldusSettings.cpp b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp similarity index 88% rename from driver/TellUsbD101/TelldusSettings.cpp rename to driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp index d15b6e2f..63ba591f 100644 --- a/driver/TellUsbD101/TelldusSettings.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp @@ -1,10 +1,5 @@ #include "StdAfx.h" #include "TelldusSettings.h" -#include "Device.h" -#include "DeviceNexa.h" -#include "DeviceWaveman.h" -#include "DeviceSartano.h" -#include "DeviceIkea.h" #include #include #include @@ -86,36 +81,6 @@ Device* TelldusSettings::getDevice(int intDeviceId){ } } -/* -* Get the requested device, when the index of the USB dongle is known -* Note that the returned Device should be deleted when not in use anymore -*/ -Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ - - Device* dev = 0; - - try{ - char* vendor = getVendor(intDeviceId); - - int* args = getArguments(intDeviceId); - - //each new brand must be added here - if (strcmp(vendor, "Nexa") == 0){ - dev = new DeviceNexa((int)args[0], (int)args[1], intDongleIndex); - } else if (strcmp(vendor, "Waveman") == 0) { - dev = new DeviceWaveman((int)args[0], (int)args[1], intDongleIndex); - } else if (strcmp(vendor, "Sartano") == 0) { - dev = new DeviceSartano((int)args[0], (int)args[1], intDongleIndex); - } else if (strcmp(vendor, "Ikea") == 0) { - dev = new DeviceIkea((int)args[0], (int)args[1], (int)args[2], intDongleIndex); - } - } - catch(...){ - throw; - } - return dev; -} - /* * Get the name of the device */ From c5f3036078b3ac6ae5bb40179c25eada64c1e5a2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Feb 2008 20:32:06 +0000 Subject: [PATCH 0048/2215] Added project "TellStick.NET" --- tellstick.net/TellStick.NET.csproj | 102 +++++++++ tellstick.net/TellStick.cs | 318 +++++++++++++++++++++++++++++ 2 files changed, 420 insertions(+) create mode 100644 tellstick.net/TellStick.NET.csproj create mode 100644 tellstick.net/TellStick.cs diff --git a/tellstick.net/TellStick.NET.csproj b/tellstick.net/TellStick.NET.csproj new file mode 100644 index 00000000..b7e159e8 --- /dev/null +++ b/tellstick.net/TellStick.NET.csproj @@ -0,0 +1,102 @@ + + + Debug + AnyCPU + 8.0.50727 + 2.0 + {700E41E9-ADB6-4D5A-B9EB-B6560C1C0D3F} + Library + Properties + TellStick + TellStick.NET + + + + + + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + + + bin\x86\Release\ + TRACE + true + none + x86 + C:\Program Files (x86)\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + bin\x86\Release\TellStick.NET.XML + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + + + bin\x64\Release\ + TRACE + true + none + x64 + C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\\rules + true + GlobalSuppressions.cs + prompt + bin\x64\Release\TellStick.NET.XML + + + + + + + + + + + + + \ No newline at end of file diff --git a/tellstick.net/TellStick.cs b/tellstick.net/TellStick.cs new file mode 100644 index 00000000..889b39f5 --- /dev/null +++ b/tellstick.net/TellStick.cs @@ -0,0 +1,318 @@ +/* ------------------------------------------------------------------------------- + * TellStick.NET + * ------------------------------------------------------------------------------- + * Created by Mikael Levén (http://labs.leven.se) + * + * This piece of code is licensed as open source and can be freely used and + * redistributed in any type of project, both commercial and non-commercial, + * as long as this licensing policy is not altered. This means that any alterations + * of this code must also be licensed as open source and therefore cannot be + * protected or patented in any way. However, any software based on this code may + * still be copyrighted (and/or patented) and sold as propritary software as long as + * this code (and any alterations of it) can be freely used and modified by others. + * + * Altough the code is licensed as open source you don't need to republish any + * changes made back to the community (it will be much appreciated tough). + * + * The code comes without any kind of warrantys and the author cannot be held + * responsible for any kind of damage this software may (or may not) cause, no matter + * if it's direct or indirect damage. + * + * Please note: + * All TellStick core functionality is developed by Telldus Technologies + * and as of now (2007-12-14) that code is also licensed as open source. This may + * however change in the future and I suggest that you check there website + * to make sure the licensing terms are still the same: http://www.telldus.se/ + * The documentation and example code for Tellstic is available at their Wiki: + * http://www.telldus.se/wiki/ + * + * ------------------------------------------------------------------------------- + * Description: + * TellStick.NET is a Microsoft .NET wrapper for the native TellStick DLL. + * The wrapper also adds some functionality to make it easier to work with + * TellStick devices. + * + * Author: Mikael Levén + * Created: 2007-12-14 + * + * Dependencies: + * This library depends on the native DLL for TellStick. To be able to actually + * switch lights on and off you also need the driver to be installed as well + * as an TellStick USB device. + * + * Revisions: +------------------------------------------------------------------------------- +*/ + +using System.Collections.Generic; +using System.Runtime.InteropServices; + +/// +/// TellStick.NET is a Microsoft .NET wrapper for the native TellStick DLL. +/// The wrapper also adds some functionality to make it easier to work with TellStick devices. +/// +public sealed class TellStick +{ + private TellStick() + { } + + + #region TellStick native DLL imports class + public sealed class Native + { + private Native() + { } + + [DllImport("TellUsbD101.dll")] + public static extern int devAddDevice(); + + [DllImport("TellUsbD101.dll")] + public static extern bool devTurnOn(int intDeviceId); + + [DllImport("TellUsbD101.dll")] + public static extern bool devTurnOff(int intDeviceId); + + [DllImport("TellUsbD101.dll")] + public static extern int devGetNumberOfDevices(); + + [DllImport("TellUsbD101.dll")] + public static extern string devGetName(int intDeviceId); + + [DllImport("TellUsbD101.dll")] + public static extern bool devSetName(int intDeviceId, string chNewName); + + [DllImport("TellUsbD101.dll")] + public static extern string devGetVendor(int intDeviceId); + + [DllImport("TellUsbD101.dll")] + public static extern bool devSetVendor(int intDeviceId, string chNewName); + + [DllImport("TellUsbD101.dll")] + public static extern string devGetModel(int intDeviceId); + + [DllImport("TellUsbD101.dll")] + public static extern bool devSetModel(int intDeviceId, string chNewName); + + [DllImport("TellUsbD101.dll")] + public static extern int[] devGetArguments(int intDeviceId); + + [DllImport("TellUsbD101.dll")] + public static extern bool devSetArguments(int intDeviceId, int[] intArguments, int intNumberOfArguments); + + [DllImport("TellUsbD101.dll")] + public static extern int devAddDeviceWithArguments(string strVendor, int[] intArguments, int intNumberOfArguments); + + [DllImport("TellUsbD101.dll")] + public static extern bool devRemoveDevice(int intDeviceId); + + [DllImport("TellUsbD101.dll")] + public static extern int devGetDeviceId(int intDeviceIndex); + + } + #endregion + + /// + /// Gets the number of devices registered + /// + /// Returns the number of devices as an integer + /// The native DLL is required for this methods to run. If it's missing a ModuleNotFoundException exception will be thrown. + public static int GetNumberOfDevices() + { + try + { + return Native.devGetNumberOfDevices(); + } + catch (System.DllNotFoundException ex) + { + throw new ModuleNotFoundException("Could not find TellStick software. Please make sure it's installed before you run this application!", ex); + } + catch (System.Exception) + { + throw; + } + + } + + /// + /// Gets the unique idetifier of the device + /// + /// Index number of the device to get ID for + /// Returns the unique identifier as an integer + /// The native DLL is required for this methods to run. If it's missing a ModuleNotFoundException exception will be thrown. + public static int GetDeviceId(int deviceIndex) + { + // Retrieve and return the device unqiue identifier from the native method + try + { + return Native.devGetDeviceId(deviceIndex); + } + catch (System.DllNotFoundException ex) + { + throw new ModuleNotFoundException("Could not find TellStick software. Please make sure it's installed before you run this application!", ex); + } + catch (System.Exception) + { + throw; + } + + } + + + /// + /// Gets the user defined name of the device + /// + /// Device unqiue identification + /// Returns the user defined device name as a string + /// The native DLL is required for this methods to run. If it's missing a ModuleNotFoundException exception will be thrown. + public static string GetName(int deviceId) + { + // Retrieve and return the device name from the native method + try + { + return Native.devGetName(deviceId); + } + catch (System.DllNotFoundException ex) + { + throw new ModuleNotFoundException("Could not find TellStick software. Please make sure it's installed before you run this application!", ex); + } + catch (System.Exception) + { + throw; + } + } + + + /// + /// Turns on the selected device + /// + /// Device unqiue identification + /// Returns true if the device was succesfully turned on + /// The native DLL is required for this methods to run. If it's missing a ModuleNotFoundException exception will be thrown. + public static bool TurnOn(int deviceId) + { + // Send "on" signal + try + { + return Native.devTurnOn(deviceId); + } + catch (System.DllNotFoundException ex) + { + throw new ModuleNotFoundException("Could not find TellStick software. Please make sure it's installed before you run this application!", ex); + } + catch (System.Exception) + { + throw; + } + } + + /// + /// Turns off the selected device + /// + /// Device unqiue identification + /// Returns true if the device was succesfully turned off + /// The native DLL is required for this methods to run. If it's missing a ModuleNotFoundException exception will be thrown. + public static bool TurnOff(int deviceId) + { + // Send "off" signal + try + { + return Native.devTurnOff(deviceId); + } + catch (System.DllNotFoundException ex) + { + throw new ModuleNotFoundException("Could not find TellStick software. Please make sure it's installed before you run this application!", ex); + } + catch (System.Exception) + { + throw; + } + } + + /// + /// Gets the vendors name + /// + /// + /// + /// The native DLL is required for this methods to run. If it's missing a ModuleNotFoundException exception will be thrown. + public static string GetVendor(int deviceId) + { + // Retrieve and return the vendor from the native method + try + { + return Native.devGetVendor(deviceId); + } + catch (System.DllNotFoundException ex) + { + throw new ModuleNotFoundException("Could not find TellStick software. Please make sure it's installed before you run this application!", ex); + } + catch (System.Exception) + { + throw; + } + } + + + + #region "Support classes" + + public abstract class TellStickException : System.Exception + { + public TellStickException() : base() + { + } + + public TellStickException(string message) + : base(message) + { + } + + public TellStickException(string message, System.Exception innerException) + : base(message, innerException) + { + } + + } + + public class UnmanagedException : TellStickException + { + public UnmanagedException() : base() + { + } + + public UnmanagedException(string message) + : base(message) + { + } + + public UnmanagedException(string message, System.Exception innerException) + : base(message, innerException) + { + } + + } + + public class ModuleNotFoundException : TellStickException + { + public ModuleNotFoundException() + : base("Could not find TellStick software. Please make sure it's installed before you run this application!") + { + + } + + public ModuleNotFoundException(string message) + : base(message) + { + + } + + public ModuleNotFoundException(string message, System.Exception innerException) + : base(message, innerException) + { + + } + } + + + #endregion +} + From fbd494cc2129426c4f3604113030e9fb80efb5ca Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Feb 2008 21:52:31 +0000 Subject: [PATCH 0049/2215] Missed AssemblyInfo.cs in my previous commit --- tellstick.net/Properties/AssemblyInfo.cs | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tellstick.net/Properties/AssemblyInfo.cs diff --git a/tellstick.net/Properties/AssemblyInfo.cs b/tellstick.net/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..9d953f39 --- /dev/null +++ b/tellstick.net/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +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("TellStick.NET")] +[assembly: AssemblyDescription("A managed .NET wrapper class library for the TellStick native DLL")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Eyedealistic / Levén Labs (http://labs.leven.se)")] +[assembly: AssemblyProduct("TellStick.NET")] +[assembly: AssemblyCopyright("Created by Mikael Levén in 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("24411992-c766-4eb8-b7ac-c002f0d7d5ad")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("0.1.0.*")] +[assembly: AssemblyFileVersion("0.1.0.0")] From 42e322ea27f4cf0cd6513b19bb0a846765456031 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Thu, 28 Feb 2008 21:07:09 +0000 Subject: [PATCH 0050/2215] Introduced new simplified format of the configuration file. No new functionality --- tellstickd/tellstickd | 123 ++++++++++++++++++++++++++++++------- tellstickd/tellstickd.conf | 26 ++++---- 2 files changed, 114 insertions(+), 35 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index e270fe40..ce391206 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -29,7 +29,7 @@ my $output_to_logfile = $YES; my $write_pid = $YES; my $n_rfcmd_calls; my $current_time; -my $number_of_devices; +my $number_of_rules; my $Day; my $Month; my $Year; @@ -45,7 +45,7 @@ my $dayOfWeek; my $dayOfMonth; my $PROGRAM_NAME = "tellstickd"; -my $VERSION = "0.4.0"; +my $VERSION = "0.5.0"; # Structure of the configurations to be read; # $device_cfg[$i][0]; # Protocol, only NEXA and SARTANO supported so far by rfcmd @@ -245,7 +245,7 @@ sub subtract_time (my $sign) = $time2 =~ /^(.*?)[0-9]/; ($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/; # Remove any leading signs - $time2 =~ s/^.*?[0-9]//g; + $time2 =~ s/^-?//g; ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/; if ($sign eq "-") { @@ -355,6 +355,8 @@ sub read_config { my $input_file = $_[0]; my @inrad; + my $on_interval_end; + my $off_interval_end; printf("$PROGRAM_NAME: Reading configuration file $conf_file...\n"); @@ -366,29 +368,108 @@ sub read_config # skip lines beginning with # or space or just a new line next; } + + if ($_ =~ /^[NEXA|SARTANO]/ ) { chomp($_); + @inrad = split /\s+/, $_; $device_cfg[$i][0] = $inrad[0]; # Protocol - $device_cfg[$i][1] = $inrad[1]; # Housecode A-P - $device_cfg[$i][2] = $inrad[2]; # Channel 1-3 - $device_cfg[$i][10] = $inrad[3]; # Rule valid days [1234567] - $device_cfg[$i][3] = $inrad[4]; # On time - $device_cfg[$i][4] = $inrad[5]; # Off time - $device_cfg[$i][5] = $inrad[6]; # Off when bright - $device_cfg[$i][6] = $inrad[7]; # Off when bright delay - $device_cfg[$i][7] = $inrad[8]; # Time in advance when getting dark - $device_cfg[$i][8] = $inrad[9]; # On time random interval - $device_cfg[$i][9] = $inrad[10]; # Off time random interval - $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched of at startup - $device_cfg[$i][23] = $device_cfg[$i][3]; # Original on time is stored here pos 3 will be used for random on times - $device_cfg[$i][24] = $device_cfg[$i][4]; # Original off time is stored here pos 4 will be used for random off times + $device_cfg[$i][1] = $inrad[1]; # Housecode A and channel for NEXA, channel for S + $device_cfg[$i][10] = $inrad[2]; # Rule valid days [1234567] + $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched off at startup if ($device_cfg[$i][0] eq "SARTANO") { $device_cfg[$i][2] = ""; } + elsif ($device_cfg[$i][0] eq "NEXA") { + # Put the housecode and channel in the respective fields. + ($device_cfg[$i][2]) = $device_cfg[$i][1] =~ /^[A-P](.{1})$/; + ($device_cfg[$i][1]) = $device_cfg[$i][1] =~ /^(.{1})[1-3]$/; + } + else { + die("$PROGRAM_NAME: Unsupported protcol: $device_cfg[$i][0]. Only NEXA or SARTANO allowed.\n"); + } + + + + # Lets find the on interval and put it into the proper fields, $device_cfg[$i][3]=On time, $device_cfg[$i][8] = On time random interval + + if ($inrad[3] =~ /-/) { + ($device_cfg[$i][3], $on_interval_end) = $inrad[3] =~ /^(.*)-(.*)$/; + } + else { + ($device_cfg[$i][3]) = $inrad[3] =~ /^(.*)$/; + $on_interval_end = $device_cfg[$i][3]; + } + + $device_cfg[$i][8] = subtract_time($on_interval_end, $device_cfg[$i][3]); + + + + # Off time = $device_cfg[$i][4], Off time random interval = $device_cfg[$i][9] + if ($inrad[4] =~ /-/) { + ($device_cfg[$i][4], $off_interval_end) = $inrad[4] =~ /^(.*)-(.*)$/; + } + else { + ($device_cfg[$i][4]) = $inrad[4] =~ /^(.*)$/; + $off_interval_end = $device_cfg[$i][4]; + } + + $device_cfg[$i][9] = subtract_time($off_interval_end, $device_cfg[$i][4]); + + + + # Save the original on and off + $device_cfg[$i][23] = $device_cfg[$i][3]; # Original on time is stored here pos 3 will be used for random on times + $device_cfg[$i][24] = $device_cfg[$i][4]; # Original off time is stored here pos 4 will be used for random off times + + + + + + # $inrad[5] is the off post sunrise value including sign, $inrad[6] is the on pre sunrise value sign, + if ($inrad[5] && $inrad[6]) { + # Found a parameter after off interval, assuming daytime switch off is sought. + $device_cfg[$i][5] = 1; + + + # First the off post sunrise + (my $sign, my $minutes) = $inrad[5] =~ /^([-\+]?)(.*?)$/; + + if ($sign eq "+") { + $sign = ""; + } + + (my $hours) = floor($minutes / 60); + $minutes = $minutes - $hours * 60; + + $device_cfg[$i][6] = sprintf("%s%02d:%02d", $sign, $hours, $minutes); + + # Then figure on pre sunset out + (my $sign, my $minutes) = $inrad[6] =~ /^([-\+]?)(.*?)$/; + + if ($sign eq "+") { + $sign = ""; + } + + (my $hours) = floor($minutes / 60); + $minutes = $minutes - $hours * 60; + + $device_cfg[$i][7] = sprintf("%s%02d:%02d", $sign, $hours, $minutes); + } + else { + # If no parameters given after off interval it is assumed that the light will be on daytime + $device_cfg[$i][5] = 0; + $device_cfg[$i][6] = "00:00"; + $device_cfg[$i][7] = "00:00"; + } + + + + ############################################################################## # Some sanity checks # If the turn on time is not to be used, this is marked with -1 if ($device_cfg[$i][3] != -1) { @@ -603,13 +684,13 @@ if (length($conf_file) < 1) { printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION\n"); # Read the configuration file -$number_of_devices = read_config($conf_file); +$number_of_rules = read_config($conf_file); -if ($number_of_devices < 1) { +if ($number_of_rules < 1) { die("$PROGRAM_NAME: Configuration file has no devices to control, exiting.\n"); } else { - printf("$PROGRAM_NAME: Configurations for $number_of_devices device(s) read.\n\n"); + printf("\n$PROGRAM_NAME: $number_of_rules rule(s) has been read.\n\n"); } ################################################################################################### @@ -634,7 +715,7 @@ while (1) { my $sunset_time = get_sunset_time(); printf("$PROGRAM_NAME: Time is $current_time. Sunset today is expected at $sunset_time\n\n"); - for (my $i = 0; $i < $number_of_devices; $i++) { + for (my $i = 0; $i < $number_of_rules; $i++) { # Initially all devices are switched off to get a known state if ($first_loop == $YES) { rfcmd_exec($i, 0); @@ -668,7 +749,7 @@ while (1) { ################################################################################################### # Below the required actions are performed for each device - for ($i = 0; $i < $number_of_devices; $i++) { + for ($i = 0; $i < $number_of_rules; $i++) { # Lets check if the rule is to be applied today diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index f61aafb8..0d593e0a 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -23,27 +23,25 @@ log_file = /var/log/tellstickd pid_file = /var/run/tellstickd.pid # -# -# (no = 0, yes = 1) +# # # In valid day field, days are numbered 1=Monday, 2=Tuesday, ... , 7=Sunday. I.e. 1234567 means that the rule should be active every weekday. -# +# Time format xx:yy where xx is hour and yy is minute # Multiple definitions are possible for each device # # Setting and to the same means that the device will always be switched on. -# The random interval times defines the allowed interval within the switch may take place -# =22:15 and =00:30 means that the actual switch will take -# place sometime between 22:15 and 22:44, with new randomized times set every night at 00:00. # -# Time format xx:yy where xx is hour and yy is minute -# If no turn on time or turn off time should be used. Note this with -1. See the example line below only turning off at 22:45. Only to be used on turn on or turn off times. -# NEXA A 1 1234567 -1 22:45 1 00:30 00:30 -# -# Sample row for a SARTANO device. Note that the 0 in column three does not have a meaning. On time will always be 05:30, off time will always be 22:45. The rule only applies monday to wednesday. -SARTANO 0000000000 0 123 05:30 22:45 1 00:30 00:15 00:00 00:00 +# The sample rule below will turn on the device 06:10 (no random) and off between 22:00 and 23:00 monday to friday. +# The device will be turned off daytime 10 minutes after sunrise and 15 before sunset +SARTANO 0000000000 12345 06:10-06:10 22:00-23:00 10 15 + +# This device will be turned on between 07:34 and 07:48, turned off between 23:00 and 23:15 (applies for every day in the week). +# It will not be turned off daytime +NEXA P2 1234567 07:34-07:48 23:00-23:15 + +# This device will be turned on 07:00 off between 20:00 and 20:30 and will be on daytime on sundays. +NEXA P3 7 07:00 20:00-20:30 -# Sample to control NEXA device A 1. Turn on device 05:30 turn off 22:45. Turn off the device 30 minutes after sunrise, turn on again 15 minutes before sunset. On time will be between 06:30 and 06:39, off time will be between 22:05 and 22:24. The rule applies all days in the week -NEXA P 1 1234567 06:30 22:05 1 00:30 00:15 00:10 00:20 From 0b6db9eb1bf8565a20d05439ec6a56c0120fd9a2 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Sat, 1 Mar 2008 12:50:13 +0000 Subject: [PATCH 0051/2215] Fixed minor bug regarding leading signs in function add_time. --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index ce391206..51306f78 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -207,7 +207,7 @@ sub add_time (my $sign) = $time2 =~ /^(.*?)[0-9]/; ($time1_hour, $time1_minute) = $time1 =~ /(.*)\:(.*)/; # Remove any leading signs - $time2 =~ s/^.*?[0-9]//g; + $time2 =~ s/^-?//g; ($time2_hour, $time2_minute) = $time2 =~ /(.*)\:(.*)/; if ($sign eq "-") { From 37ba12675bd62b02ffec94b8b96ab5e0db041825 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Sun, 2 Mar 2008 08:02:28 +0000 Subject: [PATCH 0052/2215] Improved robustness of config file reading. --- tellstickd/tellstickd | 21 ++++++++++++++------- tellstickd/tellstickd.conf | 4 ++-- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 51306f78..832d7ca2 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -324,6 +324,7 @@ sub is_time_format_correct { my $time = $_[0]; (my $hour, my $minute) = $time =~ /^-?(\d\d)\:(\d\d)$/; + if ($hour && $minute) { if ($hour >= 0 && $hour <= 23 && $minute >= 0 && $minute <= 59) { return $YES; @@ -363,7 +364,9 @@ sub read_config open(CFG_FILE, "<$input_file") or die "$PROGRAM_NAME: Could not access config file: $conf_file\n"; my $i = 0; + my $conf_row = 0; while ($_ = ) { + $conf_row++; if ($_ =~ /^[\#|\s|\n]/) { # skip lines beginning with # or space or just a new line next; @@ -375,7 +378,7 @@ sub read_config @inrad = split /\s+/, $_; $device_cfg[$i][0] = $inrad[0]; # Protocol - $device_cfg[$i][1] = $inrad[1]; # Housecode A and channel for NEXA, channel for S + $device_cfg[$i][1] = $inrad[1]; # Housecode A and channel for NEXA, channel for SARTANO. $device_cfg[$i][10] = $inrad[2]; # Rule valid days [1234567] $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched off at startup @@ -385,8 +388,12 @@ sub read_config } elsif ($device_cfg[$i][0] eq "NEXA") { # Put the housecode and channel in the respective fields. - ($device_cfg[$i][2]) = $device_cfg[$i][1] =~ /^[A-P](.{1})$/; - ($device_cfg[$i][1]) = $device_cfg[$i][1] =~ /^(.{1})[1-3]$/; + ($device_cfg[$i][2]) = $device_cfg[$i][1] =~ /^[A-P](\d)$/; + ($device_cfg[$i][1]) = $device_cfg[$i][1] =~ /^([A-P])[1-3]$/; + + if (!$device_cfg[$i][2] || !$device_cfg[$i][1]) { + die("$PROGRAM_NAME: Housecode/channel out of range error on row $conf_row in configuration file.\n"); + } } else { die("$PROGRAM_NAME: Unsupported protcol: $device_cfg[$i][0]. Only NEXA or SARTANO allowed.\n"); @@ -398,10 +405,10 @@ sub read_config # Lets find the on interval and put it into the proper fields, $device_cfg[$i][3]=On time, $device_cfg[$i][8] = On time random interval if ($inrad[3] =~ /-/) { - ($device_cfg[$i][3], $on_interval_end) = $inrad[3] =~ /^(.*)-(.*)$/; + ($device_cfg[$i][3], $on_interval_end) = $inrad[3] =~ /^(\d?\d:\d\d)-(\d?\d:\d\d)$/; } else { - ($device_cfg[$i][3]) = $inrad[3] =~ /^(.*)$/; + ($device_cfg[$i][3]) = $inrad[3] =~ /^(\d?\d:\d\d)$/; $on_interval_end = $device_cfg[$i][3]; } @@ -411,10 +418,10 @@ sub read_config # Off time = $device_cfg[$i][4], Off time random interval = $device_cfg[$i][9] if ($inrad[4] =~ /-/) { - ($device_cfg[$i][4], $off_interval_end) = $inrad[4] =~ /^(.*)-(.*)$/; + ($device_cfg[$i][4], $off_interval_end) = $inrad[4] =~ /^(\d?\d:\d\d)-(\d?\d:\d\d)$/; } else { - ($device_cfg[$i][4]) = $inrad[4] =~ /^(.*)$/; + ($device_cfg[$i][4]) = $inrad[4] =~ /^(\d?\d:\d\d)$/; $off_interval_end = $device_cfg[$i][4]; } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 0d593e0a..6b3746c1 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -31,9 +31,9 @@ pid_file = /var/run/tellstickd.pid # # Setting and to the same means that the device will always be switched on. # -# The sample rule below will turn on the device 06:10 (no random) and off between 22:00 and 23:00 monday to friday. +# The sample rule below will turn on the device between 06:10 and 06:20 and off between 22:00 and 23:00 monday to friday. # The device will be turned off daytime 10 minutes after sunrise and 15 before sunset -SARTANO 0000000000 12345 06:10-06:10 22:00-23:00 10 15 +SARTANO 0000000000 12345 06:10-06:20 22:00-23:00 10 15 # This device will be turned on between 07:34 and 07:48, turned off between 23:00 and 23:15 (applies for every day in the week). # It will not be turned off daytime From 269393cf04bef7e6322c145c4f4494e0405614e0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 2 Mar 2008 11:07:07 +0000 Subject: [PATCH 0053/2215] Bugfix: When returning a string SysAllocStringByteLen() must be used so programming languages such as Visual Basic does not crash. --- driver/TellUsbD101/TellUsbD101.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index 7141e919..3964146f 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -142,6 +142,7 @@ char * WINAPI devGetName(int intDeviceId){ try{ TelldusSettings ts; strReturn = ts.getName(intDeviceId); + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); } catch(exception e){ strReturn = ""; @@ -168,6 +169,7 @@ char* WINAPI devGetVendor(int intDeviceId){ try{ TelldusSettings ts; strReturn = ts.getVendor(intDeviceId); + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); } catch(exception e){ strReturn = ""; @@ -194,6 +196,7 @@ bool WINAPI devSetVendor(int intDeviceId, char* strVendor){ try{ TelldusSettings ts; strReturn = ts.getModel(intDeviceId); + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); } catch(exception e){ strReturn = ""; From 9a594d4c1c613ce1198d6ca48af7323a2ccb2e29 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 2 Mar 2008 11:23:29 +0000 Subject: [PATCH 0054/2215] TellUsbD101.cpp: Ported r53 (bugfix when returning a string) from trunk. --- driver/TellUsbD101/TellUsbD101.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index cfd4f3e1..0d97ee0a 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -139,6 +139,7 @@ char * __stdcall devGetName(int intDeviceId){ try{ TelldusSettings ts; strReturn = ts.getName(intDeviceId); + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); } catch(exception e){ strReturn = ""; @@ -165,6 +166,7 @@ char* __stdcall devGetVendor(int intDeviceId){ try{ TelldusSettings ts; strReturn = ts.getVendor(intDeviceId); + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); } catch(exception e){ strReturn = ""; @@ -191,6 +193,7 @@ bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ try{ TelldusSettings ts; strReturn = ts.getModel(intDeviceId); + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); } catch(exception e){ strReturn = ""; From 858c772c125cbbba1003245032a1c67ebb636056 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 2 Mar 2008 16:58:01 +0000 Subject: [PATCH 0055/2215] Made the driver build on windows, still not working though. --- driver/TellUsbD101/TellUsbD101.cpp | 4 +- driver/TellUsbD101/TellUsbD101.def | 2 +- driver/TellUsbD101/TellUsbD101.vcproj | 16 +- driver/TellUsbD101/settings/TelldusSettings.h | 4 +- .../settings/TelldusSettingsWinRegistry.cpp | 155 +++++++++--------- 5 files changed, 97 insertions(+), 84 deletions(-) diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index 3964146f..e9aa95d3 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -218,7 +218,7 @@ bool WINAPI devSetModel(int intDeviceId, char* strNewModel){ return blnSuccess; } -bool WINAPI devSetArguments(int intDeviceId, char* strArguments){ +/*bool WINAPI devSetArguments(int intDeviceId, char* strArguments){ vector vArguments; //int intArguments[] = new int[]; //bort? @@ -236,7 +236,7 @@ bool WINAPI devSetArguments(int intDeviceId, char* strArguments){ handleException(e); return false; } -} +}*/ int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex){ int intReturn; diff --git a/driver/TellUsbD101/TellUsbD101.def b/driver/TellUsbD101/TellUsbD101.def index fc32ffca..cb3d80b9 100644 --- a/driver/TellUsbD101/TellUsbD101.def +++ b/driver/TellUsbD101/TellUsbD101.def @@ -12,7 +12,7 @@ EXPORTS devSetName @8 devSetVendor @9 devSetModel @10 - devSetArguments @11 +; devSetArguments @11 devAddDevice @12 devRemoveDevice @13 diff --git a/driver/TellUsbD101/TellUsbD101.vcproj b/driver/TellUsbD101/TellUsbD101.vcproj index 5758d02b..16a0e453 100644 --- a/driver/TellUsbD101/TellUsbD101.vcproj +++ b/driver/TellUsbD101/TellUsbD101.vcproj @@ -179,10 +179,6 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > - - @@ -205,6 +201,10 @@ /> + + @@ -226,7 +226,11 @@ > + + +//#include class privateVars; @@ -20,7 +20,7 @@ public: char* getModel(int intDeviceId); bool setModel(int intDeviceId, char* strModel); int* getArguments(int intDeviceId); - bool setArguments(int intDeviceId, vector vArguments); +// bool setArguments(int intDeviceId, vector vArguments); int addDevice(); int getDeviceId(int intDeviceIndex); bool removeDevice(int intDeviceId); diff --git a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp index 63ba591f..d4b4aca7 100644 --- a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp @@ -1,4 +1,4 @@ -#include "StdAfx.h" +#include "../StdAfx.h" #include "TelldusSettings.h" #include #include @@ -8,15 +8,24 @@ using namespace std; +class privateVars { +public: + HKEY hk; + std::string strRegPathDevice; + std::string strRegPath; + int intMaxRegValueLength; +}; + /* * Constructor */ TelldusSettings::TelldusSettings(void) { - strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; - strRegPath = "SOFTWARE\\Telldus\\"; + d = new privateVars(); + d->strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; + d->strRegPath = "SOFTWARE\\Telldus\\"; - intMaxRegValueLength = 1000; + d->intMaxRegValueLength = 1000; } /* @@ -25,9 +34,9 @@ TelldusSettings::TelldusSettings(void) TelldusSettings::~TelldusSettings(void) { //RegCloseKey(hk); //close all, if still open //TODO: Need some way to know if open or closed - strRegPath = ""; - strRegPathDevice = ""; - intMaxRegValueLength = -1; + d->strRegPath = ""; + d->strRegPathDevice = ""; + d->intMaxRegValueLength = -1; } @@ -40,17 +49,17 @@ int TelldusSettings::getNumberOfDevices(void){ try{ - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ string strNumSubKeys; DWORD dNumSubKeys; - RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + RegQueryInfoKey(d->hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); intNumberOfDevices = (int)dNumSubKeys; - RegCloseKey(hk); + RegCloseKey(d->hk); } else{ throw exception(); //couldn't open reg key @@ -90,25 +99,25 @@ char* TelldusSettings::getName(int intDeviceId){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; - char* Buff = new char[intMaxRegValueLength]; + char* Buff = new char[d->intMaxRegValueLength]; - long lngStatus = RegQueryValueEx(hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); + long lngStatus = RegQueryValueEx(d->hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA){ Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); + lngStatus = RegQueryValueEx(d->hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); } strReturn = Buff; } else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ strReturn = ""; @@ -125,18 +134,18 @@ bool TelldusSettings::setName(int intDeviceId, char* strNewName){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); if(lnExists == ERROR_SUCCESS){ - intMaxRegValueLength = (int)strlen(strNewName); - RegSetValueEx(hk, "Name", 0, REG_SZ, (LPBYTE)strNewName, intMaxRegValueLength); + d->intMaxRegValueLength = (int)strlen(strNewName); + RegSetValueEx(d->hk, "Name", 0, REG_SZ, (LPBYTE)strNewName, d->intMaxRegValueLength); } else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ @@ -154,18 +163,18 @@ char* TelldusSettings::getVendor(int intDeviceId){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; - char* Buff = new char[intMaxRegValueLength]; + char* Buff = new char[d->intMaxRegValueLength]; - long lngStatus = RegQueryValueEx(hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); + long lngStatus = RegQueryValueEx(d->hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA){ Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); + lngStatus = RegQueryValueEx(d->hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); } strReturn = Buff; @@ -173,7 +182,7 @@ char* TelldusSettings::getVendor(int intDeviceId){ else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(exception e){ strReturn = ""; @@ -195,18 +204,18 @@ bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); if(lnExists == ERROR_SUCCESS){ - intMaxRegValueLength = (int)strlen(strVendor); - RegSetValueEx(hk, "Vendor", 0, REG_SZ, (LPBYTE)strVendor, intMaxRegValueLength); + d->intMaxRegValueLength = (int)strlen(strVendor); + RegSetValueEx(d->hk, "Vendor", 0, REG_SZ, (LPBYTE)strVendor, d->intMaxRegValueLength); } else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ blnSuccess = false; @@ -223,26 +232,26 @@ char* TelldusSettings::getModel(int intDeviceId){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; - char* Buff = new char[intMaxRegValueLength]; + char* Buff = new char[d->intMaxRegValueLength]; - long lngStatus = RegQueryValueEx(hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); + long lngStatus = RegQueryValueEx(d->hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA){ Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); + lngStatus = RegQueryValueEx(d->hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); } strReturn = Buff; } else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ strReturn = ""; @@ -259,18 +268,18 @@ bool TelldusSettings::setModel(int intDeviceId, char* strVendor){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); if(lnExists == ERROR_SUCCESS){ - intMaxRegValueLength = (int)strlen(strVendor); - RegSetValueEx(hk, "Model", 0, REG_SZ, (LPBYTE)strVendor, intMaxRegValueLength); + d->intMaxRegValueLength = (int)strlen(strVendor); + RegSetValueEx(d->hk, "Model", 0, REG_SZ, (LPBYTE)strVendor, d->intMaxRegValueLength); } else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ blnSuccess = false; @@ -283,19 +292,19 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ try{ - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_READ, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, d->strRegPathDevice.c_str(), 0, KEY_READ, &d->hk); if(lnExists == ERROR_SUCCESS){ - char* Buff = new char[intMaxRegValueLength]; + char* Buff = new char[d->intMaxRegValueLength]; DWORD size; - if (RegEnumKeyEx(hk, intDeviceIndex, (LPSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + if (RegEnumKeyEx(d->hk, intDeviceIndex, (LPSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { intReturn = (int)_atoi64(Buff); } delete Buff; - RegCloseKey(hk); + RegCloseKey(d->hk); } else{ throw exception(); //couldn't open reg key @@ -317,19 +326,19 @@ int TelldusSettings::getNumberOfArguments(int intDeviceId){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ DWORD dNumValues; - RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); + RegQueryInfoKey(d->hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); intReturn = (int)dNumValues - 3; //total number of values - model, name and vendor } else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ //error management @@ -347,13 +356,13 @@ int* TelldusSettings::getArguments(int intDeviceId){ try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ DWORD dNumValues; - RegQueryInfoKey(hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); + RegQueryInfoKey(d->hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); int intNumberOfArguments = (int)dNumValues - 3; //total number of values - model, name and vendor DWORD dwLength; @@ -362,12 +371,12 @@ int* TelldusSettings::getArguments(int intDeviceId){ while(i < intNumberOfArguments){ - char* Buff = new char[intMaxRegValueLength]; + char* Buff = new char[d->intMaxRegValueLength]; _itoa(i, chConvertBuffer, 10); - long lngStatus = RegQueryValueEx(hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); + long lngStatus = RegQueryValueEx(d->hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA){ - lngStatus = RegQueryValueEx(hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); + lngStatus = RegQueryValueEx(d->hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); } int intReturn = (int)_atoi64(Buff); vReturn.push_back(intReturn); @@ -379,7 +388,7 @@ int* TelldusSettings::getArguments(int intDeviceId){ else{ throw exception(); //couldn't open reg key } - RegCloseKey(hk); + RegCloseKey(d->hk); intReturn = new int[vReturn.size()]; @@ -399,7 +408,7 @@ int* TelldusSettings::getArguments(int intDeviceId){ /* * Set device arguments */ -bool TelldusSettings::setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments){ +/* bool TelldusSettings::setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments){ bool blnSuccess = true; try{ @@ -427,12 +436,12 @@ bool TelldusSettings::setArguments(int intDeviceId, int* intArguments[], int int blnSuccess = false; } return blnSuccess; -} +}*/ /* * Set device arguments */ -bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ +/* bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ bool blnSuccess = true; try{ @@ -463,7 +472,7 @@ bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ blnSuccess = false; } return blnSuccess; -} +}*/ /* @@ -478,7 +487,7 @@ int TelldusSettings::addDevice(){ intDeviceId = getNextDeviceId(); std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); if(RegCreateKeyEx(HKEY_CURRENT_USER, @@ -488,13 +497,13 @@ int TelldusSettings::addDevice(){ REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, - &hk, + &d->hk, &dwDisp)){ //fail throw exception("Create Key failed"); } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ @@ -511,24 +520,24 @@ int TelldusSettings::getNextDeviceId(){ int intReturn = -1; try{ DWORD dwDisp; - long lnExists = RegCreateKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, + long lnExists = RegCreateKeyEx(HKEY_CURRENT_USER, d->strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, - &hk, + &d->hk, &dwDisp); //create or open if already created if(lnExists == ERROR_SUCCESS){ DWORD dwLength; - char* Buff = new char[intMaxRegValueLength]; + char* Buff = new char[d->intMaxRegValueLength]; - long lngStatus = RegQueryValueEx(hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + long lngStatus = RegQueryValueEx(d->hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA){ Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + lngStatus = RegQueryValueEx(d->hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); } if(lngStatus == ERROR_SUCCESS){ @@ -543,10 +552,10 @@ int TelldusSettings::getNextDeviceId(){ DWORD dwVal = intReturn; - RegSetValueEx (hk, "LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + RegSetValueEx (d->hk, "LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); } - RegCloseKey(hk); + RegCloseKey(d->hk); } catch(...){ intReturn = -1; @@ -562,7 +571,7 @@ bool TelldusSettings::removeDevice(int intDeviceId){ bool blnSuccess = true; try{ std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; + ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); long lngSuccess = RegDeleteKey(HKEY_CURRENT_USER, strCompleteRegPath.c_str()); From e6e6eaaaf39a4f1fc0b614b08875ff60b87f5e40 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 2 Mar 2008 17:33:33 +0000 Subject: [PATCH 0056/2215] Added TelldusSettings::getStringSetting() and TelldusSettings::setStringSetting() in TelldusSettingsWinRegistry. With this the Windows and Linux port can reuse most of the logic. --- driver/TellUsbD101/TellUsbD101.cpp | 10 +- driver/TellUsbD101/TellUsbD101.def | 2 +- .../TellUsbD101/settings/TelldusSettings.cpp | 43 +++ .../settings/TelldusSettingsConfuse.cpp | 47 ---- .../settings/TelldusSettingsWinRegistry.cpp | 254 ++++-------------- 5 files changed, 107 insertions(+), 249 deletions(-) diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index e9aa95d3..3ec1ffeb 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -218,9 +218,9 @@ bool WINAPI devSetModel(int intDeviceId, char* strNewModel){ return blnSuccess; } -/*bool WINAPI devSetArguments(int intDeviceId, char* strArguments){ - - vector vArguments; +bool WINAPI devSetArguments(int intDeviceId, char* strArguments){ + return false; +/* vector vArguments; //int intArguments[] = new int[]; //bort? try{ char* strTemp = strtok(strArguments, ","); @@ -235,8 +235,8 @@ bool WINAPI devSetModel(int intDeviceId, char* strNewModel){ catch(exception e){ handleException(e); return false; - } -}*/ + }*/ +} int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex){ int intReturn; diff --git a/driver/TellUsbD101/TellUsbD101.def b/driver/TellUsbD101/TellUsbD101.def index cb3d80b9..fc32ffca 100644 --- a/driver/TellUsbD101/TellUsbD101.def +++ b/driver/TellUsbD101/TellUsbD101.def @@ -12,7 +12,7 @@ EXPORTS devSetName @8 devSetVendor @9 devSetModel @10 -; devSetArguments @11 + devSetArguments @11 devAddDevice @12 devRemoveDevice @13 diff --git a/driver/TellUsbD101/settings/TelldusSettings.cpp b/driver/TellUsbD101/settings/TelldusSettings.cpp index f5d81e49..94e43a47 100644 --- a/driver/TellUsbD101/settings/TelldusSettings.cpp +++ b/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -34,3 +34,46 @@ Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ } return dev; } + +/* +* Get the name of the device +*/ +char* TelldusSettings::getName(int intDeviceId){ + return getStringSetting(intDeviceId, "name"); +} + +/* +* Set the name of the device +*/ +bool TelldusSettings::setName(int intDeviceId, char* strNewName){ + return setStringSetting(intDeviceId, "name", strNewName); +} + + +/* +* Get the device vendor +*/ +char* TelldusSettings::getVendor(int intDeviceId){ + return getStringSetting(intDeviceId, "vendor"); +} + +/* +* Set the device vendor +*/ +bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ + return setStringSetting(intDeviceId, "vendor", strVendor); +} + +/* +* Get the device model +*/ +char* TelldusSettings::getModel(int intDeviceId){ + return getStringSetting(intDeviceId, "model"); +} + +/* +* Set the device model +*/ +bool TelldusSettings::setModel(int intDeviceId, char* strModel){ + return setStringSetting(intDeviceId, "model", strModel); +} diff --git a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp index 676ddccb..3e6c7ce3 100644 --- a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp @@ -60,53 +60,6 @@ Device* TelldusSettings::getDevice(int intDeviceId){ return NULL; } -/* -* Get the name of the device -*/ -char* TelldusSettings::getName(int intDeviceId){ - return getStringSetting(intDeviceId, "name"); -} - -/* -* Set the name of the device -*/ -bool TelldusSettings::setName(int intDeviceId, char* strNewName){ - bool blnSuccess = true; - setStringSetting(intDeviceId, "name", strNewName); - return blnSuccess; -} - -/* -* Get the device vendor -*/ -char* TelldusSettings::getVendor(int intDeviceId){ - return getStringSetting(intDeviceId, "vendor"); -} - -/* -* Set the device vendor -*/ -bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ - bool blnSuccess = true; - setStringSetting(intDeviceId, "vendor", strVendor); - return blnSuccess; -} - -/* -* Get the device model -*/ -char* TelldusSettings::getModel(int intDeviceId){ - return getStringSetting(intDeviceId, "model"); -} - -/* -* Set the device model -*/ -bool TelldusSettings::setModel(int intDeviceId, char* strVendor){ - bool blnSuccess = true; - setStringSetting(intDeviceId, "model", strVendor); - return blnSuccess; -} int TelldusSettings::getDeviceId(int intDeviceIndex){ if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds diff --git a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp index d4b4aca7..6644b8cb 100644 --- a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp @@ -90,202 +90,6 @@ Device* TelldusSettings::getDevice(int intDeviceId){ } } -/* -* Get the name of the device -*/ -char* TelldusSettings::getName(int intDeviceId){ - - char* strReturn = ""; - - try{ - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - DWORD dwLength; - char* Buff = new char[d->intMaxRegValueLength]; - - long lngStatus = RegQueryValueEx(d->hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); - if(lngStatus == ERROR_MORE_DATA){ - Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(d->hk, "Name", NULL, NULL, (LPBYTE)Buff, &dwLength); - } - strReturn = Buff; - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - } - catch(...){ - strReturn = ""; - } - return strReturn; -} - -/* -* Set the name of the device -*/ -bool TelldusSettings::setName(int intDeviceId, char* strNewName){ - - bool blnSuccess = true; - try{ - - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - d->intMaxRegValueLength = (int)strlen(strNewName); - RegSetValueEx(d->hk, "Name", 0, REG_SZ, (LPBYTE)strNewName, d->intMaxRegValueLength); - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - - } - catch(...){ - blnSuccess = false; - } - return blnSuccess; -} - -/* -* Get the device vendor -*/ -char* TelldusSettings::getVendor(int intDeviceId){ - - char* strReturn = ""; - - try{ - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - DWORD dwLength; - char* Buff = new char[d->intMaxRegValueLength]; - - long lngStatus = RegQueryValueEx(d->hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); - if(lngStatus == ERROR_MORE_DATA){ - Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(d->hk, (LPCSTR)"Vendor", NULL, NULL, (LPBYTE)Buff, &dwLength); - } - - strReturn = Buff; - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - } - catch(exception e){ - strReturn = ""; - ofstream errorfile("c:\\errorlog.txt", ios::app); - if(errorfile){ - errorfile << e.what() << endl; - errorfile.close(); - } - } - return strReturn; -} - -/* -* Set the device vendor -*/ -bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ - - bool blnSuccess = true; - try{ - - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - d->intMaxRegValueLength = (int)strlen(strVendor); - RegSetValueEx(d->hk, "Vendor", 0, REG_SZ, (LPBYTE)strVendor, d->intMaxRegValueLength); - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - } - catch(...){ - blnSuccess = false; - } - return blnSuccess; -} - -/* -* Get the device model -*/ -char* TelldusSettings::getModel(int intDeviceId){ - - char* strReturn = ""; - - try{ - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - DWORD dwLength; - char* Buff = new char[d->intMaxRegValueLength]; - - long lngStatus = RegQueryValueEx(d->hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); - if(lngStatus == ERROR_MORE_DATA){ - - Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(d->hk, "Model", NULL, NULL, (LPBYTE)Buff, &dwLength); - } - strReturn = Buff; - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - } - catch(...){ - strReturn = ""; - } - return strReturn; -} - -/* -* Set the device model -*/ -bool TelldusSettings::setModel(int intDeviceId, char* strVendor){ - - bool blnSuccess = true; - try{ - - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - d->intMaxRegValueLength = (int)strlen(strVendor); - RegSetValueEx(d->hk, "Model", 0, REG_SZ, (LPBYTE)strVendor, d->intMaxRegValueLength); - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - } - catch(...){ - blnSuccess = false; - } - return blnSuccess; -} int TelldusSettings::getDeviceId(int intDeviceIndex){ int intReturn = -1; @@ -586,6 +390,64 @@ bool TelldusSettings::removeDevice(int intDeviceId){ return blnSuccess; } +char *TelldusSettings::getStringSetting(int intDeviceId, const char* name) { + char* strReturn = ""; + + try{ + std::ostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); + + if(lnExists == ERROR_SUCCESS){ + DWORD dwLength; + char* Buff = new char[d->intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(d->hk, name, NULL, NULL, (LPBYTE)Buff, &dwLength); + if(lngStatus == ERROR_MORE_DATA){ + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(d->hk, name, NULL, NULL, (LPBYTE)Buff, &dwLength); + } + strReturn = Buff; + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(d->hk); + } + catch(...){ + strReturn = ""; + } + return strReturn; +} + +bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value) { + + bool blnSuccess = true; + try{ + + std::ostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); + + if(lnExists == ERROR_SUCCESS){ + d->intMaxRegValueLength = (int)strlen(value); + RegSetValueEx(d->hk, name, 0, REG_SZ, (LPBYTE)value, d->intMaxRegValueLength); + } + else{ + throw exception(); //couldn't open reg key + } + RegCloseKey(d->hk); + + } + catch(...){ + blnSuccess = false; + } + return blnSuccess; + +} + //only for debug reasons void TelldusSettings::debugLog(char* debugstring){ ofstream debugfile("c:\\telldusdebug.txt", ios::app); From 145d86b8d6a853909839f776d2fc9610ffae87ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 20:29:29 +0000 Subject: [PATCH 0057/2215] Possible to make different week rules for odd and even weeks. Changed the is_rule_valid_today to check for odd and even weeks and to use the DateTime object which numbers the days 1 (monday) - 7 (sunday) like the config file. --- tellstickd/tellstickd | 31 ++++++++++++++++++++++--------- tellstickd/tellstickd.conf | 5 +++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 832d7ca2..39974c72 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -334,18 +334,23 @@ sub is_time_format_correct return $NO; } + # Time format sanity check routine sub is_rule_valid_today { - my $device_id = $_[0]; - my $current_day = $_[1]; + my $rule = $_[0]; + my $now = $_[1]; - if (0 == $current_day) { - # Perl thinks 0 = Sunday, config file thinks 7 = Sunday - $current_day = 7; + (my $week_rule) = $rule =~/^([e|o])/; + if ($week_rule) { + my $is_odd_week = ($now->week_number % 2); + if (($is_odd_week && ($week_rule eq "e")) || + (!$is_odd_week && ($week_rule eq "o"))) { + return $NO; + } } - - if ($device_cfg[$device_id][10] =~ /$current_day/) { + my $day_of_week = $now->day_of_week; + if ($rule =~ /$day_of_week/) { return $YES; } @@ -514,7 +519,7 @@ sub read_config die("$PROGRAM_NAME: Format of off interval for device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] not correct: $device_cfg[$i][9]\n"); } - if ($device_cfg[$i][10] =~ /[^1-7]/) { + if ($device_cfg[$i][10] =~ /^[o|e][^1-7]/) { die("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2]: Specified rule validity day out of range: $device_cfg[$i][10]\n"); } @@ -528,6 +533,12 @@ sub read_config printf(" $weekDays[$j]"); } } + if ($device_cfg[$i][10] =~ /o/) { + printf(" (odd weeks)"); + } + if ($device_cfg[$i][10] =~ /e/) { + printf(" (even weeks)"); + } printf("\n"); if ($device_cfg[$i][3] == -1) { @@ -703,6 +714,7 @@ else { ################################################################################################### # Now to the eternal loop my $first_loop = $YES; +my $now; while (1) { $n_rfcmd_calls = 0; @@ -710,6 +722,7 @@ while (1) { ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(); $Year += 1900; $current_time = sprintf("%02d:%02d", $Hour, $Minute); + $now = DateTime->now(); ################################################################################################### @@ -760,7 +773,7 @@ while (1) { # Lets check if the rule is to be applied today - if (is_rule_valid_today($i, $WeekDay) == $YES) { + if (is_rule_valid_today($device_cfg[$i][10], $now) == $YES) { diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 6b3746c1..91c85b9e 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -26,6 +26,9 @@ pid_file = /var/run/tellstickd.pid # # # In valid day field, days are numbered 1=Monday, 2=Tuesday, ... , 7=Sunday. I.e. 1234567 means that the rule should be active every weekday. +# The day fields can be prefixed with "o" or "e" making the rule valid on odd or even weeks. Week numbers are +# calculated according to ISO, with the first week of the year being the one containing 4 jan + # Time format xx:yy where xx is hour and yy is minute # Multiple definitions are possible for each device # @@ -42,6 +45,8 @@ NEXA P2 1234567 07:34-07:48 23:00-23:15 # This device will be turned on 07:00 off between 20:00 and 20:30 and will be on daytime on sundays. NEXA P3 7 07:00 20:00-20:30 +# This device will be turned on 07:00 and off 20:00 on fridays and sundays on even numbered weeks +NEXA P3 e57 07:00 20:00 From 29d98fa215c5d861f794a8151c58ca42c2cc48ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 20:55:03 +0000 Subject: [PATCH 0058/2215] Remove pid file on daemon termination --- tellstickd/tellstickd | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 39974c72..93caf042 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -5,6 +5,7 @@ use DateTime; use DateTime::Event::Sunrise; use Time::Local; use strict; +use sigtrap 'handler', \&daemon_exit, 'normal-signals'; # The following variables should be adapted to your geographical location and system setup my $LATITUDE = "65.603"; # 65.603N 22.18W -> LuleÃ¥, Sweden @@ -68,12 +69,20 @@ my $VERSION = "0.5.0"; sub daemonize { chdir '/' or die "$PROGRAM_NAME: Can't chdir to /: $!"; open STDIN, '/dev/null' or die "$PROGRAM_NAME: Can't read /dev/null: $!"; +#open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; +#open STDERR, '>/dev/null' or die "$PROGRAM_NAME: Can't write to /dev/null: $!"; defined(my $pid = fork) or die "$PROGRAM_NAME: Can't fork: $!"; exit if $pid; setsid or die "$PROGRAM_NAME: Can't start a new session: $!"; umask 0; } - +sub daemon_exit() { + # Remove pidfile + unlink $pidFile; + # Since tellstickd most probably is stuck sleeping just kill ourself + kill('TERM', $$); + die; +} sub get_sunrise_time { my $sunrise_time; From 894361bbbaafc28e9b422edb3edd86d6515338d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 21:13:50 +0000 Subject: [PATCH 0059/2215] Always create a pid file when running as a daemon, never create one when running on console --- tellstickd/tellstickd | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 93caf042..d36f248d 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -27,7 +27,6 @@ my @device_cfg; my $conf_file = ""; my $make_daemon = $NO; my $output_to_logfile = $YES; -my $write_pid = $YES; my $n_rfcmd_calls; my $current_time; my $number_of_rules; @@ -647,7 +646,6 @@ sub usageprompt printf("-d, --daemon Run the program as a daemon and write a logfile.\n"); printf("-h, --help Show this message and exit.\n"); printf("-l, --logfile filename Redirect daemon logs to filename. Default $LOG_FILE\n"); - printf("--nopid Do not write process id into file $pidFile\n"); } @@ -668,9 +666,6 @@ while ($i < $#ARGV) { usageprompt(); exit; } - elsif ($ARGV[$i+1] =~ /^--nopid$/) { - $write_pid = $NO; - } elsif ($ARGV[$i+1] =~ /^-l$/ || $ARGV[$i+1] =~ /^--logfile$/) { $output_to_logfile = $YES; $i++; @@ -695,10 +690,6 @@ if ($output_to_logfile == $YES) { if ($make_daemon == $YES) { &daemonize(); -} - -# Create pidfile -if ($write_pid == $YES) { open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; print PIDFILE $$ . "\n"; close PIDFILE; From 502aa351aab0034df579264c9d7e3c7c85728270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 21:22:56 +0000 Subject: [PATCH 0060/2215] Added command line option --simulate Tellstickd will run in foreground and log to console and it won't perform any actions on the device. --- tellstickd/tellstickd | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index d36f248d..1edebbec 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -27,6 +27,7 @@ my @device_cfg; my $conf_file = ""; my $make_daemon = $NO; my $output_to_logfile = $YES; +my $simulate = $NO; my $n_rfcmd_calls; my $current_time; my $number_of_rules; @@ -168,7 +169,9 @@ sub rfcmd_exec { # and check that it is not disabled by on/off time set to -1 in the config file if ($device_cfg[$device_id][22] == 0 && $device_cfg[$device_id][23] != -1) { printf("$PROGRAM_NAME: Time is $current_time. Switching on $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); - `$RFCMD $RFCMD_OPTIONS 1`; + if ($simulate == $NO) { + `$RFCMD $RFCMD_OPTIONS 1`; + } $device_cfg[$device_id][22] = 1; return; @@ -180,7 +183,9 @@ sub rfcmd_exec { elsif ($action == 0) { if ($device_cfg[$device_id][22] == 1 && $device_cfg[$device_id][24] != -1) { printf("$PROGRAM_NAME: Time is $current_time. Switching off $device_cfg[$device_id][0] device $device_cfg[$device_id][1]$device_cfg[$device_id][2].\n"); - `$RFCMD $RFCMD_OPTIONS 0`; + if ($simulate == $NO) { + `$RFCMD $RFCMD_OPTIONS 0`; + } $device_cfg[$device_id][22] = 0; return; @@ -646,6 +651,7 @@ sub usageprompt printf("-d, --daemon Run the program as a daemon and write a logfile.\n"); printf("-h, --help Show this message and exit.\n"); printf("-l, --logfile filename Redirect daemon logs to filename. Default $LOG_FILE\n"); + printf("--simulate Run in foreground, log to console, no actuall device operations performed.\n"); } @@ -671,6 +677,9 @@ while ($i < $#ARGV) { $i++; $LOG_FILE = $ARGV[$i+1]; } + elsif ($ARGV[$i+1] =~ /--simulate/) { + $simulate = $YES; + } else { die("$PROGRAM_NAME: Unknown input argument: $ARGV[$i+1]\n"); } @@ -683,12 +692,12 @@ if ($#ARGV < 0) { die "Try \"$PROGRAM_NAME --help\" for more information.\n"; } -if ($output_to_logfile == $YES) { +if ($output_to_logfile == $YES && $simulate == $NO) { open STDOUT, "> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; open STDERR, ">> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; } -if ($make_daemon == $YES) { +if ($make_daemon == $YES && $simulate == $NO) { &daemonize(); open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; print PIDFILE $$ . "\n"; From 5c5f8ffd3835e6cea64ce32a231d8170c0d357be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 22:48:07 +0000 Subject: [PATCH 0061/2215] Bugfix allow NEXA channels to be 1-16 --- tellstickd/tellstickd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 1edebbec..acaf1dc7 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -406,12 +406,12 @@ sub read_config } elsif ($device_cfg[$i][0] eq "NEXA") { # Put the housecode and channel in the respective fields. - ($device_cfg[$i][2]) = $device_cfg[$i][1] =~ /^[A-P](\d)$/; - ($device_cfg[$i][1]) = $device_cfg[$i][1] =~ /^([A-P])[1-3]$/; - - if (!$device_cfg[$i][2] || !$device_cfg[$i][1]) { + (my $house_code,my $channel) = $device_cfg[$i][1] =~ /^([A-P])(\d{1,2})$/; + if (!$house_code || !$channel || ($channel < 1) || ($channel > 16)) { die("$PROGRAM_NAME: Housecode/channel out of range error on row $conf_row in configuration file.\n"); } + $device_cfg[$i][1] = $house_code; + $device_cfg[$i][2] = $channel; } else { die("$PROGRAM_NAME: Unsupported protcol: $device_cfg[$i][0]. Only NEXA or SARTANO allowed.\n"); From 512ac0c4c5ebb231ef8ca77989ab5dba429f6815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 23:24:16 +0000 Subject: [PATCH 0062/2215] Only log device on and off times for devices with a valid rule for today --- tellstickd/tellstickd | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index acaf1dc7..685df173 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -752,21 +752,29 @@ while (1) { # Lets set the actual on- and offtimes depending on random interval settings. randomize_on($i); - printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned on $device_cfg[$i][3]\n"); - +#// if ($device_cfg[$i][2] == 16) { +# print "-- " . is_rule_valid_today($device_cfg[$i][10],$now) ."\n"; +# } + if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned on $device_cfg[$i][3]\n"); + } randomize_off($i); - printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned off $device_cfg[$i][4]\n"); - + if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned off $device_cfg[$i][4]\n"); + } # If the device is supposed to be off daytime, the following applies # Sunrise time + requested offset if ($device_cfg[$i][5] == $YES) { $device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]); - printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); - + if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); + } # Sunset time - requested offset $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); - printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n\n"); + if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n\n"); + } } else { printf("\n"); From 115c6560f44ef8e544da34fa467f52caf76a6137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 23:29:21 +0000 Subject: [PATCH 0063/2215] Removed debug code Reverted is_rule_valid_today to take device index instead of device rule as the first argument --- tellstickd/tellstickd | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 685df173..831fc9b3 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -351,8 +351,9 @@ sub is_time_format_correct # Time format sanity check routine sub is_rule_valid_today { - my $rule = $_[0]; + my $device_id = $_[0]; my $now = $_[1]; + my $rule = $device_cfg[$i][10]; (my $week_rule) = $rule =~/^([e|o])/; if ($week_rule) { @@ -752,14 +753,11 @@ while (1) { # Lets set the actual on- and offtimes depending on random interval settings. randomize_on($i); -#// if ($device_cfg[$i][2] == 16) { -# print "-- " . is_rule_valid_today($device_cfg[$i][10],$now) ."\n"; -# } - if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + if (is_rule_valid_today($i, $now) == $YES) { printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned on $device_cfg[$i][3]\n"); } randomize_off($i); - if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + if (is_rule_valid_today($i, $now) == $YES) { printf("$PROGRAM_NAME: Today device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] will be turned off $device_cfg[$i][4]\n"); } @@ -767,12 +765,12 @@ while (1) { # Sunrise time + requested offset if ($device_cfg[$i][5] == $YES) { $device_cfg[$i][20] = add_time($sunrise_time, $device_cfg[$i][6]); - if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + if (is_rule_valid_today($i, $now) == $YES) { printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunrise off time set to $device_cfg[$i][20].\n"); } # Sunset time - requested offset $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); - if (is_rule_valid_today($device_cfg[$i][10],$now) == $YES) { + if (is_rule_valid_today($i, $now) == $YES) { printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n\n"); } } @@ -790,7 +788,7 @@ while (1) { # Lets check if the rule is to be applied today - if (is_rule_valid_today($device_cfg[$i][10], $now) == $YES) { + if (is_rule_valid_today($i, $now) == $YES) { From 4ee6f4f8666134faadca50e59bbedc74c793a4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 23:34:59 +0000 Subject: [PATCH 0064/2215] First try the code, then commit. First try the code, then commit. First try the code, then commit. --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 831fc9b3..1c589a17 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -353,7 +353,7 @@ sub is_rule_valid_today { my $device_id = $_[0]; my $now = $_[1]; - my $rule = $device_cfg[$i][10]; + my $rule = $device_cfg[$device_id][10]; (my $week_rule) = $rule =~/^([e|o])/; if ($week_rule) { From f683a0f4a4cd2e8a36b8fd05088ab0070b6e39a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 23:50:03 +0000 Subject: [PATCH 0065/2215] Bugfix include timezone in the "$now" DateTime object it will default to UTC --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 1c589a17..52eae678 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -732,7 +732,7 @@ while (1) { ($Second, $Minute, $Hour, $Day, $Month, $Year, $WeekDay, $DayOfYear, $IsDST) = localtime(); $Year += 1900; $current_time = sprintf("%02d:%02d", $Hour, $Minute); - $now = DateTime->now(); + $now = DateTime->now( time_zone => $TIMEZONE); ################################################################################################### From ec9f466ce46941e090736aa2927a0033c8bfe9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Sun, 2 Mar 2008 23:53:23 +0000 Subject: [PATCH 0066/2215] Remove extra line breaks in log file --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 52eae678..8b05879d 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -774,7 +774,7 @@ while (1) { printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n\n"); } } - else { + elsif (is_rule_valid_today($i, $now) == $YES) { printf("\n"); } } From 4a89d9fb58b844538c8cae6d0e8b20d5f42cd696 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 3 Mar 2008 16:50:10 +0000 Subject: [PATCH 0067/2215] Changed the Redaht init_script (tellstickd) to exclude the obsolete option '--logfile' --- tellstickd/init_script/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/init_script/tellstickd b/tellstickd/init_script/tellstickd index dec3248a..fbe18612 100755 --- a/tellstickd/init_script/tellstickd +++ b/tellstickd/init_script/tellstickd @@ -27,7 +27,7 @@ desc="remote switch daemon" start() { echo -n $"Starting $desc ($prog): " - daemon --user root $prog --daemon --config $CONFIG_FILE --logfile $LOG_FILE $OPTIONS + daemon --user root $prog --daemon --config $CONFIG_FILE $OPTIONS RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog From 3141d48eb50e61e3e66988076544ff1c331b483b Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 3 Mar 2008 16:51:30 +0000 Subject: [PATCH 0068/2215] Fixed a minor thing in the Redhat init-script --- tellstickd/init_script/tellstickd | 1 - 1 file changed, 1 deletion(-) diff --git a/tellstickd/init_script/tellstickd b/tellstickd/init_script/tellstickd index fbe18612..4188db2c 100755 --- a/tellstickd/init_script/tellstickd +++ b/tellstickd/init_script/tellstickd @@ -15,7 +15,6 @@ source /etc/rc.d/init.d/functions EXECUTABLE="/usr/local/bin/tellstickd" CONFIG_FILE="/etc/tellstickd.conf" -LOG_FILE="/var/log/tellstickd" OPTIONS="" [ -x $EXECUTABLE ] || exit 1 From 7ac207383bac6ea99b95223001a40ed85c6b29ed Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 3 Mar 2008 16:57:00 +0000 Subject: [PATCH 0069/2215] Changed version from 0.5.0 to 0.6.0 --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 8b05879d..ebfa126f 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -46,7 +46,7 @@ my $dayOfWeek; my $dayOfMonth; my $PROGRAM_NAME = "tellstickd"; -my $VERSION = "0.5.0"; +my $VERSION = "0.6.0"; # Structure of the configurations to be read; # $device_cfg[$i][0]; # Protocol, only NEXA and SARTANO supported so far by rfcmd From ba759c158ad21edd87a31597f38bffb47f4e3541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Mon, 3 Mar 2008 19:47:07 +0000 Subject: [PATCH 0070/2215] Removed --logfile option and moved the init stuff around a bit, this version is most probably broken, hold on.... --- tellstickd/tellstickd | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index ebfa126f..f4bcf667 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -651,7 +651,6 @@ sub usageprompt printf("-c, --config filename Searchpath to configuration file, if not given $CONFIG_FILE is assumed.\n"); printf("-d, --daemon Run the program as a daemon and write a logfile.\n"); printf("-h, --help Show this message and exit.\n"); - printf("-l, --logfile filename Redirect daemon logs to filename. Default $LOG_FILE\n"); printf("--simulate Run in foreground, log to console, no actuall device operations performed.\n"); } @@ -673,11 +672,6 @@ while ($i < $#ARGV) { usageprompt(); exit; } - elsif ($ARGV[$i+1] =~ /^-l$/ || $ARGV[$i+1] =~ /^--logfile$/) { - $output_to_logfile = $YES; - $i++; - $LOG_FILE = $ARGV[$i+1]; - } elsif ($ARGV[$i+1] =~ /--simulate/) { $simulate = $YES; } @@ -693,23 +687,15 @@ if ($#ARGV < 0) { die "Try \"$PROGRAM_NAME --help\" for more information.\n"; } -if ($output_to_logfile == $YES && $simulate == $NO) { - open STDOUT, "> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; - open STDERR, ">> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; -} - -if ($make_daemon == $YES && $simulate == $NO) { - &daemonize(); - open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; - print PIDFILE $$ . "\n"; - close PIDFILE; -} if (length($conf_file) < 1) { $conf_file = $CONFIG_FILE; } -printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION\n"); +if ($output_to_logfile == $YES && $simulate == $NO) { + open STDOUT, "> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; + open STDERR, ">> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; +} # Read the configuration file $number_of_rules = read_config($conf_file); @@ -721,6 +707,17 @@ else { printf("\n$PROGRAM_NAME: $number_of_rules rule(s) has been read.\n\n"); } +if ($make_daemon == $YES && $simulate == $NO) { + &daemonize(); + open PIDFILE, ">$pidFile" or die "$PROGRAM_NAME: Can't open $pidFile: $!\n"; + print PIDFILE $$ . "\n"; + close PIDFILE; +} + + +printf("$PROGRAM_NAME: Starting $PROGRAM_NAME version $VERSION\n"); + + ################################################################################################### # Now to the eternal loop my $first_loop = $YES; From 7636cc068f167e53cdc4c7f8fafd47b12c078eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Mon, 3 Mar 2008 20:14:43 +0000 Subject: [PATCH 0071/2215] Remove the --logfile option from the debian start script and changed reload function to restart the daemon since tellstickd doesn't react to signal HUP --- tellstickd/init_script/tellstickd.debian | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tellstickd/init_script/tellstickd.debian b/tellstickd/init_script/tellstickd.debian index efe97c74..ad262510 100755 --- a/tellstickd/init_script/tellstickd.debian +++ b/tellstickd/init_script/tellstickd.debian @@ -16,7 +16,6 @@ DAEMON="/usr/local/bin/tellstickd" NAME="tellstickd" CONFIG_FILE="/etc/tellstickd.conf" -LOG_FILE="/var/log/tellstickd" PID_FILE="/var/run/tellstickd.pid" OPTIONS="" @@ -30,7 +29,7 @@ desc="remote switch daemon" start() { log_begin_msg "Starting $desc ($prog): " - start-stop-daemon --start --quiet --pidfile "$PID_FILE" --name $NAME --exec $DAEMON -- --daemon --config $CONFIG_FILE --logfile $LOG_FILE $OPTIONS + start-stop-daemon --start --quiet --pidfile "$PID_FILE" --name $NAME --exec $DAEMON -- --daemon --config $CONFIG_FILE $OPTIONS log_end_msg $? } @@ -47,9 +46,11 @@ restart() { } reload() { - log_begin_msg "Reloading $desc ($prog): " - start-stop-daemon --stop --quiet --pidfile "$PID_FILE" --name $NAME --signal 1 - log_end_msg $? + restart +# the daemon doesn't reacto to sig HUP, so just restart it +# log_begin_msg "Reloading $desc ($prog): " +# start-stop-daemon --stop --quiet --pidfile "$PID_FILE" --name $NAME --signal 1 +# log_end_msg $? } case "$1" in @@ -68,7 +69,7 @@ case "$1" in *) echo $"Usage: $0 {start|stop|restart|reload}" - RETVAL=1 + exit 2 esac -exit $RETVAL +exit 0 From 96ea8585bb42880cf4a295211959890555f579d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Mon, 3 Mar 2008 20:17:06 +0000 Subject: [PATCH 0072/2215] tellstickd should run as expected again, (I broke it in r70) Added a "pre config file parsing" parse to get the log file option --- tellstickd/tellstickd | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index f4bcf667..9a9c1eb6 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -371,6 +371,25 @@ sub is_rule_valid_today return $NO; } +# Ugly hack, but we have to get the log_file option from the config file +# before parsing the config file +sub get_config_log_file_param +{ + my $input_file = $_[0]; + open(CFG_FILE, "<$input_file") or die "$PROGRAM_NAME: Could not access config file: $conf_file\n"; + + while ($_ = ) { + chomp($_); + (my $value) = $_ =~ /^log_file\s*=\s*([a-zA-Z0-9_\/\.]*)/; + if ($value) { + close(CFG_FILE); + return $value; + } + } + close(CFG_FILE); + return $NO; +} + sub read_config { my $input_file = $_[0]; @@ -691,8 +710,9 @@ if ($#ARGV < 0) { if (length($conf_file) < 1) { $conf_file = $CONFIG_FILE; } +$LOG_FILE = get_config_log_file_param($conf_file); -if ($output_to_logfile == $YES && $simulate == $NO) { +if ($LOG_FILE && $make_daemon && !$simulate) { open STDOUT, "> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; open STDERR, ">> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; } From 8286b184fe469c284fa49f4089d0c83403605f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Betn=C3=A9r?= Date: Mon, 3 Mar 2008 20:21:10 +0000 Subject: [PATCH 0073/2215] Removed unused variable $output_to_logfile Allow daemon to run without a logfile --- tellstickd/tellstickd | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 9a9c1eb6..be8a8452 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -26,7 +26,6 @@ my $YES = 1; my @device_cfg; my $conf_file = ""; my $make_daemon = $NO; -my $output_to_logfile = $YES; my $simulate = $NO; my $n_rfcmd_calls; my $current_time; @@ -684,7 +683,6 @@ while ($i < $#ARGV) { $conf_file = $ARGV[$i+1]; } elsif ($ARGV[$i+1] =~ /^-d$/ || $ARGV[$i+1] =~ /^--daemon$/) { - $output_to_logfile = $YES; $make_daemon = $YES; } elsif ($ARGV[$i+1] =~ /^-h$/ || $ARGV[$i+1] =~ /^--help$/) { @@ -716,7 +714,11 @@ if ($LOG_FILE && $make_daemon && !$simulate) { open STDOUT, "> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; open STDERR, ">> $LOG_FILE" or die "$PROGRAM_NAME: Can't write to $LOG_FILE: $!"; } - +if (!$LOG_FILE && $make_daemon) { +# start a daemon without a log file + open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; + open STDERR, '>/dev/null' or die "$PROGRAM_NAME: Can't write to /dev/null: $!"; +} # Read the configuration file $number_of_rules = read_config($conf_file); From bd031f46d9227b7ae2c04e6c67d206c5aae97f12 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Mar 2008 08:20:43 +0000 Subject: [PATCH 0074/2215] Added project "tellstickController" --- tellstickcontroller/License | 674 +++++++++++++ tellstickcontroller/Readme | 83 ++ tellstickcontroller/tellstickController | 934 +++++++++++++++++++ tellstickcontroller/tellstickController.conf | 71 ++ 4 files changed, 1762 insertions(+) create mode 100644 tellstickcontroller/License create mode 100644 tellstickcontroller/Readme create mode 100755 tellstickcontroller/tellstickController create mode 100644 tellstickcontroller/tellstickController.conf diff --git a/tellstickcontroller/License b/tellstickcontroller/License new file mode 100644 index 00000000..8f829aec --- /dev/null +++ b/tellstickcontroller/License @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/tellstickcontroller/Readme b/tellstickcontroller/Readme new file mode 100644 index 00000000..84bdb607 --- /dev/null +++ b/tellstickcontroller/Readme @@ -0,0 +1,83 @@ + + NAME + tellstickController + + SYNOPSIS + tellstickController [options] + + DESCRIPTION + tellstickController is used for controlling wireless recevier + devices from a TellStick transmitter. This version uses the + rfcmd software for actual device control but this can be changed + to any other optional software. tellstickController can be used + for manual control of devices, or used as a daemon that is + controlled by a number of configuration file rules. + A small database is used for keeping track of device states + between every execution of tellstickController. + + -a, --aliases List of aliases for devices. + -c, --check Check content of configuration file. + -d, --daemon Starts in daemon mode. + -f, --file F Set configfile to file F. + -g, --get D Get state for device D. + -h, --help Print short help text. + -l, --list List states for all devices. + -s, --set D S Set device D to state S. + -t, --test Test mode, no real devices will used. + -v, --verbose Print extra information. + -x, --swap D Swap state for device D. + + EXAMPLES + tellstickController -l + tellstickController --set device_alias on + tellstickController --swap device_alias + tellstickController -d -f myConfigFile.conf + + DEPENDENCIES + The following Perl modules needs to be installed: + DB_File, DateTime and DateTime::Event::Sunrise + + FILES + tellstickController + tellstickController.conf + tellstickController.db + tellstickController.log + tellstickController.pid + + CONFIGURATION + The configuration file consists of a number of settings 'Set', + a number of device aliases 'Alias', and a number of device + rules 'Rules'. + + The settings controls sunrise/sunset, logfile, pidfile, etc. + + The aliases configures device name, channel, code, etc. + + The rules can be written as a string containing two parts. + The first part is optional and ends with an '/'. It can contain + one or more of these keywords 'Weekend', 'Workweek', 'Monday', + 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and + 'Sunday'. A specified date like '2008-03-18', '2008-03-##', + '####-03-##' or '####-##-15' is also allowed. + The second part is mandatory and is either a expression or the + keyword 'None'. The expression can contain one or more of these + keywords 'Sunrise', 'Sunset', 'Random(HH:MM)' and 'HH:MM'. + Example rule: Weekend/07:15 + Example rule: Monday+Sunday/07:15 + Example rule: 2008-03-15/18:45 + Example rule: 2008-03-##/12:10 + Example rule: 07:15+Random(02:00) + Example rule: Sunset-00:30 + Example rule: None + + AUTHOR + Original version written by Rickard Andersson + Improvments added by ... + + LICENSE + Copyright (C) 2008 Rickard Andersson + Version 1.3 + This program comes with ABSOLUTELY NO WARRANTY. + This is free software, and you are welcome to redistribute it + under certain conditions; See license file for details. + diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController new file mode 100755 index 00000000..76fc4fe1 --- /dev/null +++ b/tellstickcontroller/tellstickController @@ -0,0 +1,934 @@ +#!/usr/bin/perl +###################################################################### +# +# tellstickController program +# +# Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) +# Version 1.3 +# +###################################################################### +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +###################################################################### + + +use warnings; +use strict; +use sigtrap 'handler', \&daemon_exit, 'normal-signals'; +use sigtrap 'die', 'untrapped', 'normal-signals'; +use sigtrap 'stack-trace', 'any', 'error-signals'; +use POSIX 'setsid'; + + +use DB_File; +use DateTime; +use DateTime::Event::Sunrise; + + +###################################################################### + +# All these cfg settings can be altered from the configuration file. +# +my %cfg_set = ( + "configfile" => "/etc/tellstickController.conf", + "dbfile" => "/var/lib/tellstickController.db", + "logfile" => "/var/log/tellstickController.log", + "pidfile" => "/var/run/tellstickController.pid", + "device" => "/dev/tellstick", + "program" => "/usr/local/bin/rfcmd", + "altitude" => "-0.833", + "latitude" => "58.24", + "longitude" => "15.31", + "timezone" => "Europe/Stockholm", +); +my %cfg_alias = (); +my %cfg_dimmer = (); +my @cfg_rule = (); + + +my %option = ( + "aliases" => 0, + "check" => 0, + "daemon" => 0, + "list" => 0, + "device" => "", + "state" => "", + "swap" => 0, + "test" => 0, + "verbose" => 0, +); +my %device_state = (); +my @device_on = (); +my @device_off = (); + + +###################################################################### + + +sub check_args(@) { + my (@args) = @_; + + if (not @args) { + usage(); + exit; + } + while (@args) { + if ($args[0] =~ /^-(h|-help)$/) { + usage(); + exit; + } elsif ($args[0] =~ /^-(a|-aliases)$/) { + shift(@args); + $option{"aliases"} = 1; + next; + } elsif ($args[0] =~ /^-(c|-check)$/) { + shift(@args); + $option{"check"} = 1; + next; + } elsif ($args[0] =~ /^-(d|-daemon)$/) { + shift(@args); + $option{"daemon"} = 1; + next; + } elsif ($args[0] =~ /^-(f|-file)$/) { + shift(@args); + $cfg_set{"configfile"} = shift(@args); + next; + } elsif ($args[0] =~ /^-(g|-get)$/) { + shift(@args); + $option{"get"} = 1; + $option{"device"} = lc($args[0]); + shift(@args); + next; + } elsif ($args[0] =~ /^-(l|-list)$/) { + shift(@args); + $option{"list"} = 1; + next; + } elsif ($args[0] =~ /^-(s|-set)$/) { + shift(@args); + $option{"set"} = 1; + $option{"device"} = lc($args[0]); + shift(@args); + $option{"state"} = lc($args[0]); + shift(@args); + next; + } elsif ($args[0] =~ /^-(x|-swap)$/) { + shift(@args); + $option{"swap"} = 1; + $option{"device"} = lc($args[0]); + shift(@args); + next; + } elsif ($args[0] =~ /^-(t|-test)$/) { + shift(@args); + $option{"test"} = 1; + next; + } elsif ($args[0] =~ /^-(v|-verbose)$/) { + shift(@args); + $option{"verbose"} = 1; + next; + } + + usage(); + exit; + } +} + + +sub usage() { + while () { + if ($_ =~ /^#-(.*)/) { + print "$1\n"; + } + } +} + + +sub println($) { + my ($text) = @_; + + print "$text\n"; +} + + +sub printlogger($) { + my ($text) = @_; + + if ($option{"daemon"}) { + my $now = get_datetime_now(); + my $logfile = $cfg_set{"logfile"}; + my $output = "echo '$now $text' >> $logfile"; + system ($output); + } +} + + +###################################################################### + + +sub daemon_init() { + chdir "/"; + umask 0; + my $pid = fork; + exit if $pid; + die "Couldn't fork program" unless defined(\$pid); + setsid() or die "Couldn't start new program session"; + open STDIN, '/dev/null' or die "Couldn't read /dev/null!"; + open STDOUT, '>/dev/null' or die "Couldn't write to /dev/null!"; + open STDERR, '>/dev/null' or die "Couldn't write to /dev/null!"; + + my $pidfile = $cfg_set{"pidfile"}; + $0="tellstickControllerDaemon"; + $pid = $$; + system("echo $pid > $pidfile") if (defined($pidfile)); + + printlogger "> Daemon started"; +} + + +sub daemon_exit() { + printlogger "> Daemon stopped"; + + unlink $cfg_set{"pidfile"} if (defined($cfg_set{"pidfile"})); + my $pid = $$; + kill('TERM', $pid); + exit; +} + + +sub get_datetime_now() { + my $now = DateTime->now(time_zone => $cfg_set{"timezone"}); + + return $now; +} + + +sub get_datetime_sunrise($) { + my ($now) = @_; + + my $sunrise = DateTime::Event::Sunrise->sunrise ( + altitude => $cfg_set{"altitude"}, + latitude => $cfg_set{"latitude"}, + longitude => $cfg_set{"longitude"}, + iteration => '2' + ); + my $time = $sunrise->next($now); + + return $time; +} + + +sub get_datetime_sunset($) { + my ($now) = @_; + + my $sunset = DateTime::Event::Sunrise->sunset ( + altitude => $cfg_set{"altitude"}, + latitude => $cfg_set{"latitude"}, + longitude => $cfg_set{"longitude"}, + iteration => '2' + ); + my $time = $sunset->next($now); + + return $time; +} + + +sub read_db($) { + my ($dbfile) = @_; + + println "> Reading db started" if ($option{"verbose"}); + + tie %device_state, "DB_File", $dbfile, O_RDWR|O_CREAT, 0666, $DB_HASH + or die "Couldn't read dbfile '$dbfile'!\n"; + + foreach my $key (sort keys %cfg_alias) { + if (not $device_state{$key}) { + $device_state{$key} = "unknown"; + println "Added device $key to db!" if ($option{"verbose"}); + } + } + + foreach my $key (sort keys %device_state) { + if (not $cfg_alias{$key}) { + delete $device_state{$key}; + println "Removed device $key from db!" if ($option{"verbose"}); + } + } + + println "> Reading db finished" if ($option{"verbose"}); +} + + +sub write_db($) { + my ($dbfile) = @_; + + println "> Writing db started" if ($option{"verbose"}); + + untie %device_state; + + println "> Writing db finished" if ($option{"verbose"}); +} + + +sub read_config($) { + my ($infile) = @_; + + my $text = "> Reading configurationfile started"; + println $text if ($option{"verbose"}); + printlogger $text; + + open(my $indata, $infile) or die "Couldn't read configfile '$infile'!"; + + while(my $line = <$indata>) { + chomp($line); + $line =~ s/\s+/ /g; + + if ($line =~ /^Set\s+/i) { + #println $line if ($option{"verbose"}); + my (undef, $key, $val, $suffix) = split(/\s+/, $line); + if (defined($suffix)) { + println "Wrong argument '$suffix' in line '$line'!"; + } else { + if (defined($key)) { + if (defined($val)) { + $cfg_set{lc($key)} = $val; + } else { + println "Wrong value in line '$line'!"; + } + } else { + println "Wrong key in line '$line'!"; + } + } + next; + } + + if ($line =~ /^Alias\s+/i) { + #println $line if ($option{"verbose"}); + my (undef, $name, $dimmer, $prot, $code, $addr, $suffix) + = split(/\s+/, $line); + if (defined($suffix)) { + println "Wrong argument '$suffix' in line '$line'!"; + } else { + $name = lc($name); + $dimmer = lc($dimmer); + $prot = uc($prot); + $code = uc($code); + $addr = uc($addr); + if ($dimmer =~ /^no|yes$/) { + $cfg_dimmer{$name} = $dimmer; + if ($prot =~ /^NEXA|WAVEMAN$/) { + if ($code =~ /^[A-P]$/) { + if ($addr =~ /^[1-9]{1}|1{1}[0-6]{1}$/) { + $cfg_alias{$name} = "$prot $code $addr"; + } else { + println "Wrong channel '$addr' in line '$line'!"; + } + } else { + println "Wrong housecode '$code' in line '$line'!"; + } + } elsif ($prot =~ /^SARTANO$/) { + if ($code =~ /^[01]{10}$/) { + if ($addr eq "") { + $cfg_alias{$name} = "$prot $code"; + } else { + println "Wrong argument '$addr' in line '$line'!"; + } + } else { + println "Wrong channel '$code' in line '$line'!"; + } + } else { + println "Wrong protocol '$prot' in line '$line'!"; + } + } else { + println "Wrong dimmer mode '$dimmer' in line '$line'!"; + } + } + next; + } + + if ($line =~ /^Rule\s+/i) { + #println $line if ($option{"verbose"}); + my (undef, $alias, $on, $off, $suffix) = split(/\s+/, $line); + if (defined($suffix)) { + println "Wrong argument '$suffix' in line '$line'!"; + } else { + $alias = lc($alias); + $on = lc($on); + $off = lc($off); + if (exists($cfg_alias{$alias})) { + if ($on eq "") { + println "Wrong on time '$on' in line '$line'!"; + } elsif ($off eq "") { + println "Wrong off time '$off' in line '$line'!"; + } else { + if ($on !~ /[\w\/\+\-\:\$\(\)]+/) { + println "Wrong on time '$on' in line '$line'!"; + } elsif ($off !~ /[\w\/\+\-\:\$\(\)]+/) { + println "Wrong off time '$off' in line '$line'!"; + } else { + push @cfg_rule, [$alias, $on, $off]; + } + } + } else { + println "Wrong alias '$alias' in line '$line'!"; + } + } + next; + } + + if ($line =~ /^#/) { + next; + } + + if ($line =~ /^\s*/) { + next; + } + + println "Unhandled config line: '$line'!" if ($option{"check"}); + } + + close $indata; + + $text = "=== Set ==="; + println $text if ($option{"check"}); + printlogger $text; + foreach my $key (sort keys %cfg_set) { + $text = "$key = $cfg_set{$key}"; + println $text if ($option{"check"}); + printlogger $text; + } + $text = "=== Alias ==="; + println $text if ($option{"check"}); + printlogger $text; + foreach my $key (sort keys %cfg_alias) { + $text = "$key = $cfg_alias{$key}"; + println $text if ($option{"check"}); + printlogger $text; + } + $text = "=== Rule ==="; + println $text if ($option{"check"}); + printlogger $text; + foreach my $rule (@cfg_rule) { + my ($alias, $on, $off) = @$rule; + $text = "$alias = on at $on and off at $off"; + println $text if ($option{"check"}); + printlogger $text; + } + + $text = "> Reading configurationfile finished"; + println $text if ($option{"verbose"}); + printlogger $text; +} + + +sub call_program($$) { + my ($device, $state) = @_; + + if ($option{"test"}) { + my $text = "Test mode, no real device will be used"; + println $text if ($option{"verbose"}); + printlogger $text; + } else { + my $alias = $cfg_alias{$device}; + my $mode = 0; + if ($state eq "on") { + $mode = 1; + } + my $prog = $cfg_set{"program"}; + my $dev = $cfg_set{"device"}; + my $command = "$prog $dev $alias $mode"; + my $text = "Executing command: '$command'"; + println $text if ($option{"verbose"}); + system($command); + } +} + + +sub load_device_rules () { + my $text = "> Loading device rules started"; + println $text if ($option{"verbose"}); + printlogger $text; + + my $now = get_datetime_now(); + $text = "Time = $now"; + println $text if ($option{"verbose"}); + printlogger $text; + my $today = get_datetime_now(); + $today->set( hour => 0, minute => 0, second => 0 ); + $text = "Today = $today"; + println $text if ($option{"verbose"}); + printlogger $text; + my $sunrise = get_datetime_sunrise($today); + $text = "Sunrise = $sunrise"; + println $text if ($option{"verbose"}); + printlogger $text; + my $sunset = get_datetime_sunset($today); + $text = "Sunset = $sunset"; + println $text if ($option{"verbose"}); + printlogger $text; + + foreach my $rule (@cfg_rule) { + my ($alias, $on, $off) = @$rule; + my $time = get_rule_datetime($on, $today, $sunrise, $sunset); + push @device_on, [$time, $alias] if (defined($time) && ($now <= $time)); + $time = get_rule_datetime($off, $today, $sunrise, $sunset); + push @device_off, [$time, $alias] if (defined($time) && ($now <= $time)); + } + + @device_on = sort { $a->[0] cmp $b->[0] } @device_on; + @device_off = sort { $a->[0] cmp $b->[0] } @device_off; + + $text = "=== Device on ==="; + println $text if ($option{"verbose"}); + printlogger $text; + foreach my $rule (@device_on) { + my ($time, $alias) = @$rule; + $text = "$alias = $time"; + println $text if ($option{"verbose"}); + printlogger $text; + } + $text = "=== Device off ==="; + println $text if ($option{"verbose"}); + printlogger $text; + foreach my $rule (@device_off) { + my ($time, $alias) = @$rule; + $text = "$alias = $time"; + println $text if ($option{"verbose"}); + printlogger $text; + } + + $text = "> Loading device rules finished"; + println $text if ($option{"verbose"}); + printlogger $text; +} + + +sub get_rule_datetime($$$$) { + my ($rule, $now, $sunrise, $sunset) = @_; + + #println "Rule='$rule'" if ($option{"verbose"}); + + my ($date, $time) = split(/\//, $rule); + if (not defined($time)) { + $time = $date; + $date = $now->ymd; + } else { + my $today = 0; + my $match = 0; + if ($date =~ /([\d#]{4})-([\d#]{2})-([\d#]{2})/) { + $match = 1; + $today = 1 if ((($1 =~ /####/) || ($now->year == $1)) + && (($2 =~ /##/) || ($now->month == $2)) + && (($3 =~ /##/) || ($now->day == $3))); + } + if ($date =~ /workweek/) { + $match = 1; + $today = 1 if ($now->day_of_week < 6); + } + if ($date =~ /weekend/) { + $match = 1; + $today = 1 if ($now->day_of_week > 5); + } + if ($date =~ /monday/) { + $match = 1; + $today = 1 if ($now->day_of_week == 1); + } + if ($date =~ /tuesday/) { + $match = 1; + $today = 1 if ($now->day_of_week == 2); + } + if ($date =~ /wednesday/) { + $match = 1; + $today = 1 if ($now->day_of_week == 3); + } + if ($date =~ /thursday/) { + $match = 1; + $today = 1 if ($now->day_of_week == 4); + } + if ($date =~ /friday/) { + $match = 1; + $today = 1 if ($now->day_of_week == 5); + } + if ($date =~ /saturday/) { + $match = 1; + $today = 1 if ($now->day_of_week == 6); + } + if ($date =~ /sunday/) { + $match = 1; + $today = 1 if ($now->day_of_week == 7); + } + + if ($match) { + if ($today) { + $date = $now->ymd; + } else { + $time = undef; + } + } else { + println "Wrong date '$date' for rule '$rule'!"; + $time = undef; + } + } + + if (defined($time) && ($time !~ /^not$/)) { + my $days = 0; + my $hours = 0; + my $minutes = 0; + my $lastOp = "+"; + my $expr = ""; + my $op = ""; + my $rest = ""; + my $mins = 0; + #println "rule='$time'"; + + while ($time ne "") { + $op = $lastOp; + if ($time =~ /(.+?)(\+|-)(.*)/) { + $expr = $1; + $lastOp = $2; + $rest = $3; + $time = $rest; + } elsif ($time =~ /(.+)/) { + $expr = $1; + $lastOp = ""; + $rest = ""; + $time = ""; + } + + if ($expr =~ /^sunrise$/) { + $expr = 0; + if ($sunrise->hms =~ /(\d\d):(\d\d):(\d\d)/) { + $expr = $1*60+$2; + } + } elsif ($expr =~ /^sunset$/) { + $expr = 0; + if ($sunset->hms =~ /(\d\d):(\d\d):(\d\d)/) { + $expr = $1*60+$2; + } + } elsif ($expr =~ /^random\((\d\d):(\d\d)\)$/) { + $expr = int rand($1*60+$2+1); + } elsif ($expr =~ /^(\d\d):(\d\d)$/) { + $expr = $1*60+$2; + } else { + println "Wrong time '$expr' for rule '$rule'!"; + $expr = ""; + } + + #println "expr='$expr', op='$op', rest='$rest'"; + if ($op eq "+") { + $mins += $expr; + } elsif ($op eq "-") { + $mins -= $expr; + } + #println "mins='$mins'"; + } + if ($mins <= 0) { + $mins = $mins % (24*60); + $days = 1; + } elsif ($mins >= 24*60) { + $mins = $mins % (24*60); + $days = 1; + } + + $hours = int $mins/60; + $minutes = int $mins%60; + $time = DateTime->now(time_zone => $cfg_set{"timezone"}); + $time->set(hour => $hours, minute => $minutes, second => 0); + $time->add(days => $days); + #println "days='$days', hours='$hours', minutes='$minutes'"; + #println "time='$time'"; + } else { + $time = undef; + } + + return $time; +} + + +sub check_device_rules($) { + my ($now) = @_; + + println "Checking device rules '$now'" if ($option{verbose}); + + my $rule = $device_on[0]; + while (defined(@$rule)) { + my ($time, $device) = @$rule; + if ($time <= $now) { + shift(@device_on); + change_device_state($device, 'off') if ($cfg_dimmer{$device} eq 'yes'); + change_device_state($device, 'on'); + } else { + last; + } + $rule = $device_on[0]; + } + + $rule = $device_off[0]; + while (defined(@$rule)) { + my ($time, $device) = @$rule; + if ($time <= $now) { + shift(@device_off); + change_device_state($device, 'off'); + } else { + last; + } + $rule = $device_off[0]; + } + +} + + +sub change_device_state($$) { + my ($device, $state) = @_; + + $device_state{$device} = $state; + write_db($cfg_set{"dbfile"}); + read_db($cfg_set{"dbfile"}); + call_program($device, $state); + my $text = "Device $device = $state"; + println $text if ($option{"verbose"}); + printlogger $text; +} + + +###################################################################### + + +sub get_device_state() { + if ($option{"device"}) { + my $device = $option{"device"}; + if ($device_state{$device}) { + my $state = $device_state{$device}; + println "$state" if (not $option{"verbose"}); + println "Device $device = $state" if ($option{"verbose"}); + } else { + println "No device found with alias '$device'!"; + } + } +} + + +sub set_device_state() { + if ($option{"device"}) { + if ($option{"state"}) { + my $device = $option{"device"}; + if ($device_state{$device}) { + my $state = $option{"state"}; + if ($state =~ /^(on|off)$/i) { + change_device_state($device, $state); + } else { + println "No state found with name '$state'!"; + } + } else { + println "No device found with alias '$device'!"; + } + } + } +} + + +sub swap_device_state() { + if ($option{"device"}) { + if ($option{"swap"}) { + my $device = $option{"device"}; + if ($device_state{$device}) { + my $state = $device_state{$device}; + if ($state =~ /^off$/i) { + change_device_state($device, 'on'); + } else { + change_device_state($device, 'off'); + } + } else { + println "No device found with alias '$device'!"; + } + } + } +} + + +sub list_all_devices() { + foreach my $key (sort keys %device_state) { + println "Device $key = $device_state{$key}"; + } +} + + +sub list_all_aliases { + foreach my $key (sort keys %cfg_alias) { + my $dimmer = ""; + $dimmer = " dimmer" if $cfg_dimmer{$key} eq "yes"; + println "Device $key is an alias for$dimmer receiver $cfg_alias{$key}"; + } +} + + +sub daemon_loop() { + daemon_init(); + + while ($option{"daemon"}) { + my $now = get_datetime_now(); + my $next_day = get_datetime_now(); + $next_day->add( days => 1 ); + $next_day->set( hour => 0, minute => 0, second => 0 ); + println "Next reload of device rules = $next_day" if ($option{"verbose"}); + + my $wait_time = 60; + my $loop = 1; + + check_device_rules($now); + + while ($loop) { + $now = get_datetime_now(); + if ($now > $next_day) { + load_device_rules(); + $next_day->add( days => 1 ); + } + check_device_rules($now); + sleep($wait_time); + } + } + + daemon_exit(); +} + + +sub perform_action() { + if ($option{"aliases"}) { + list_all_aliases(); + } elsif ($option{"get"}) { + get_device_state(); + } elsif ($option{"set"}) { + set_device_state(); + } elsif ($option{"swap"}) { + swap_device_state(); + } elsif ($option{"list"}) { + list_all_devices(); + } elsif ($option{"daemon"}) { + daemon_loop(); + } +} + + +###################################################################### + + +sub main() { + # check arguments + check_args(@ARGV); + + # read configuration file + read_config($cfg_set{"configfile"}); + + # read DB + read_db($cfg_set{"dbfile"}); + + # Load rules + load_device_rules(); + + # perform action + perform_action(); + + # write DB + write_db($cfg_set{"dbfile"}); +} + + +main(); + + +###################################################################### + + +__DATA__ +#- +#- NAME +#- tellstickController +#- +#- SYNOPSIS +#- tellstickController [options] +#- +#- DESCRIPTION +#- tellstickController is used for controlling wireless recevier +#- devices from a TellStick transmitter. This version uses the +#- rfcmd software for actual device control but this can be changed +#- to any other optional software. tellstickController can be used +#- for manual control of devices, or used as a daemon that is +#- controlled by a number of configuration file rules. +#- A small database is used for keeping track of device states +#- between every execution of tellstickController. +#- +#- -a, --aliases List of aliases for devices. +#- -c, --check Check content of configuration file. +#- -d, --daemon Starts in daemon mode. +#- -f, --file F Set configfile to file F. +#- -g, --get D Get state for device D. +#- -h, --help Print this help text. +#- -l, --list List states for all devices. +#- -s, --set D S Set device D to state S. +#- -t, --test Test mode, no real devices will used. +#- -v, --verbose Print extra information. +#- -x, --swap D Swap state for device D. +#- +#- EXAMPLES +#- tellstickController -l +#- tellstickController --set device_alias on +#- tellstickController --swap device_alias +#- tellstickController -d -f myConfigFile.conf +#- +#- DEPENDENCIES +#- The following Perl modules needs to be installed: +#- DB_File, DateTime and DateTime::Event::Sunrise +#- +#- FILES +#- tellstickController +#- tellstickController.conf +#- tellstickController.db +#- tellstickController.log +#- tellstickController.pid +#- +#- CONFIGURATION +#- The configuration file consists of a number of settings 'Set', +#- a number of device aliases 'Alias', and a number of device +#- rules 'Rules'. +#- +#- The settings controls sunrise/sunset, logfile, pidfile, etc. +#- +#- The aliases configures device name, channel, code, etc. +#- +#- The rules can be written as a string containing two parts. +#- The first part is optional and ends with an '/'. It can contain +#- one or more of these keywords 'Weekend', 'Workweek', 'Monday', +#- 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' and +#- 'Sunday'. A specified date like '2008-03-18', '2008-03-##', +#- '####-03-##' or '####-##-15' is also allowed. +#- The second part is mandatory and is either a expression or the +#- keyword 'None'. The expression can contain one or more of these +#- keywords 'Sunrise', 'Sunset', 'Random(HH:MM)' and 'HH:MM'. +#- Example rule: Weekend/07:15 +#- Example rule: Monday+Sunday/07:15 +#- Example rule: 2008-03-15/18:45 +#- Example rule: 2008-03-##/12:10 +#- Example rule: 07:15+Random(02:00) +#- Example rule: Sunset-00:30 +#- Example rule: None +#- +#- AUTHOR +#- Original version written by Rickard Andersson +#- Improvments added by ... +#- +#- LICENSE +#- Copyright (C) 2008 Rickard Andersson +#- Version 1.3 +#- This program comes with ABSOLUTELY NO WARRANTY. +#- This is free software, and you are welcome to redistribute it +#- under certain conditions; See license file for details. +#- diff --git a/tellstickcontroller/tellstickController.conf b/tellstickcontroller/tellstickController.conf new file mode 100644 index 00000000..8ad92109 --- /dev/null +++ b/tellstickcontroller/tellstickController.conf @@ -0,0 +1,71 @@ +################################################################################ +# +# Configuration file for tellstickController +# +# Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) +# Version: 1.3 +# +################################################################################ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +################################################################################ + +# List of location settings. +# +# Usage example: +# Set Key Value +# +# Set Timezone Europe/Stockholm +# +# +Set Timezone Europe/Stockholm +Set Latitude 58.24 +Set Longitude 15.31 +Set dbfile /var/lib/tellstickController.db +Set pidfile /var/run/tellstickController.pid +Set logfile /var/log/tellstickController.log + + +# Aliases for recevier devices. +# +# Usage example: +# Alias Name Dimmer Protocol Housecode Channel +# +# Alias BedroomWindow yes Nexa A 1 +# Alias device42 No Waveman B 3 +# or +# Usage example: +# Alias Name Dimmer Protocol Channel +# +# Alias MythTv_Backlight No Sartano 000000001 +# +# +Alias device1 No Nexa A 1 + + +# Timer rules for reciever devices. +# +# Usage examples: +# Rule Alias DeviceOn DeviceOff +# +# Rule BedroomWindow Sunrise Sunrise+01:30 +# Rule BedroomWindow 18:33 23:10+Random(00:45) +# Rule MythTv_Backlight Weekend/20:00 Weekend/Sunset +# Rule device42 2008-03-##/18:45 2008-03-##/22:11 +# +# +Rule device1 weekend/sunrise weekend/08:45 +Rule device1 sunset+00:15 23:30+Random(00:20) + From 656fd684419cb3134d36655d6399ccc00ef06536 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Mar 2008 08:21:16 +0000 Subject: [PATCH 0075/2215] Missed the examples for tellstickController --- .../examples/power_off_all_lights | 12 +++ .../examples/power_off_bedroom_mythtv | 8 ++ .../examples/power_on_all_lights | 12 +++ .../examples/power_on_bedroom_mythtv | 9 +++ .../examples/tellstickController.conf | 81 +++++++++++++++++++ 5 files changed, 122 insertions(+) create mode 100755 tellstickcontroller/examples/power_off_all_lights create mode 100755 tellstickcontroller/examples/power_off_bedroom_mythtv create mode 100755 tellstickcontroller/examples/power_on_all_lights create mode 100755 tellstickcontroller/examples/power_on_bedroom_mythtv create mode 100644 tellstickcontroller/examples/tellstickController.conf diff --git a/tellstickcontroller/examples/power_off_all_lights b/tellstickcontroller/examples/power_off_all_lights new file mode 100755 index 00000000..b0b353d3 --- /dev/null +++ b/tellstickcontroller/examples/power_off_all_lights @@ -0,0 +1,12 @@ +#!/bin/sh +# +# Power off every device that control light sources. +# + +tellstickController --set bedroom_mythtv_leds off +tellstickController --set bedroom_window off +tellstickController --set kitchen_cabinets off +tellstickController --set livingroom_cabinets off +tellstickController --set livingroom_uplight off +tellstickController --set livingroom_walls off + diff --git a/tellstickcontroller/examples/power_off_bedroom_mythtv b/tellstickcontroller/examples/power_off_bedroom_mythtv new file mode 100755 index 00000000..448bef94 --- /dev/null +++ b/tellstickcontroller/examples/power_off_bedroom_mythtv @@ -0,0 +1,8 @@ +#!/bin/sh +# +# Power off bedroom MythTV, turn off backlight leds. +# + +tellstickController --set bedroom_mythtv_power off +tellstickController --set bedroom_mythtv_leds off + diff --git a/tellstickcontroller/examples/power_on_all_lights b/tellstickcontroller/examples/power_on_all_lights new file mode 100755 index 00000000..decbc4e6 --- /dev/null +++ b/tellstickcontroller/examples/power_on_all_lights @@ -0,0 +1,12 @@ +#!/bin/sh +# +# Power off every device that control light sources. +# + +tellstickController --set bedroom_mythtv_leds on +tellstickController --set bedroom_window on +tellstickController --set kitchen_cabinets on +tellstickController --set livingroom_cabinets on +tellstickController --set livingroom_uplight on +tellstickController --set livingroom_walls on + diff --git a/tellstickcontroller/examples/power_on_bedroom_mythtv b/tellstickcontroller/examples/power_on_bedroom_mythtv new file mode 100755 index 00000000..c91e5df5 --- /dev/null +++ b/tellstickcontroller/examples/power_on_bedroom_mythtv @@ -0,0 +1,9 @@ +#!/bin/sh +# +# Power on bedroom MythTV, turn on backlight leds and turn off window lamp. +# + +tellstickController --set bedroom_mythtv_power on +tellstickController --set bedroom_mythtv_leds on +tellstickController --set bedroom_window off + diff --git a/tellstickcontroller/examples/tellstickController.conf b/tellstickcontroller/examples/tellstickController.conf new file mode 100644 index 00000000..0cf22590 --- /dev/null +++ b/tellstickcontroller/examples/tellstickController.conf @@ -0,0 +1,81 @@ +################################################################################ +# +# Configuration file for tellstickController +# +# Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) +# Version: 1.3 +# +################################################################################ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +################################################################################ + +# List of location settings. +# +# Usage example: +# Set Key Value +# Set Timezone Europe/Stockholm +# +# +Set Timezone Europe/Stockholm +Set Latitude 58.24 +Set Longitude 15.31 +Set dbfile /var/lib/tellstickController.db +Set pidfile /var/run/tellstickController.pid +Set logfile /var/log/tellstickController.log + + +# Aliases for recevier devices. +# +# Usage example: +# Alias Name Dimmer Protocol Housecode Channel +# Alias BedroomWindow yes Nexa A 1 +# Alias device42 No Waveman B 3 +# or +# Usage example: +# Alias Name Dimmer Protocol Channel +# Alias MythTv_Backlight No Sartano 000000001 +# +# +Alias kitchen_cabinets No Nexa G 2 +Alias Bedroom_window No Nexa G 1 +Alias Bedroom_mythtv_power No Nexa G 6 +Alias Bedroom_mythtv_leds No Nexa G 7 +Alias Livingroom_cabinets No Nexa G 3 +Alias Livingroom_walls No Nexa G 4 +Alias Livingroom_uplight No Nexa G 5 +Alias Livingroom_mythtv_leds Yes Nexa G 8 + + +# Timer rules for reciever devices. +# +# Usage examples: +# Rule Alias DeviceOn DeviceOff +# Rule BedroomWindow Sunrise Sunrise+01:30 +# Rule BedroomWindow 18:33 23:10+Random(00:45) +# Rule MythTv_Backlight Weekend/20:00 Weekend/Sunset +# +# +Rule Bedroom_window Workweek/sunrise-00:30 Workweek/Sunrise+01:00 +Rule Bedroom_window Sunset+Random(00:30) 00:00+Random(00:30) +Rule Bedroom_mythtv_leds Not 02:00 +Rule kitchen_cabinets Sunrise-00:30 Sunrise+01:00 +Rule kitchen_cabinets Workweek/Sunset Workweek/00:00+Random(00:30) +Rule kitchen_cabinets Weekend/Sunset-01:00 Weekend/00:30+Random(00:30) +Rule Livingroom_cabinets Sunset+01:00+Random(00:30) 00:15+Random(00:30) +Rule Livingroom_walls Sunset+Random(00:30) 00:15+Random(00:30) +Rule Livingroom_uplight Not 02:00 +Rule Livingroom_mythtv_leds Not 02:00 + From 2e55ccb256d6358458a022cf609de96b41d03009 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Mar 2008 15:28:14 +0000 Subject: [PATCH 0076/2215] Added functions devSetArgument() and devGetArgument() which uses the new user friendly interface for saving the arguments. This only works on Linux with libConfuse. More work to be done on Windows. --- driver/TellUsbD101/TellUsbD101.cpp | 71 ++++++------ driver/TellUsbD101/TellUsbD101.def | 25 +++-- driver/TellUsbD101/TellUsbD101.h | 30 +++--- .../TellUsbD101/settings/TelldusSettings.cpp | 101 ++++++++++-------- driver/TellUsbD101/settings/TelldusSettings.h | 14 +-- .../settings/TelldusSettingsConfuse.cpp | 70 ++++++------ 6 files changed, 154 insertions(+), 157 deletions(-) diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index 3ec1ffeb..bd61a22b 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -142,7 +142,9 @@ char * WINAPI devGetName(int intDeviceId){ try{ TelldusSettings ts; strReturn = ts.getName(intDeviceId); +#ifdef _WINDOWS strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); +#endif } catch(exception e){ strReturn = ""; @@ -151,7 +153,7 @@ char * WINAPI devGetName(int intDeviceId){ return strReturn; } -bool WINAPI devSetName(int intDeviceId, char* strNewName){ +bool WINAPI devSetName(int intDeviceId, const char* strNewName){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -169,7 +171,9 @@ char* WINAPI devGetVendor(int intDeviceId){ try{ TelldusSettings ts; strReturn = ts.getVendor(intDeviceId); +#ifdef _WINDOWS strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); +#endif } catch(exception e){ strReturn = ""; @@ -178,7 +182,7 @@ char* WINAPI devGetVendor(int intDeviceId){ return strReturn; } -bool WINAPI devSetVendor(int intDeviceId, char* strVendor){ +bool WINAPI devSetVendor(int intDeviceId, const char* strVendor){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -196,7 +200,9 @@ bool WINAPI devSetVendor(int intDeviceId, char* strVendor){ try{ TelldusSettings ts; strReturn = ts.getModel(intDeviceId); +#ifdef _WINDOWS strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); +#endif } catch(exception e){ strReturn = ""; @@ -205,7 +211,7 @@ bool WINAPI devSetVendor(int intDeviceId, char* strVendor){ return strReturn; } -bool WINAPI devSetModel(int intDeviceId, char* strNewModel){ +bool WINAPI devSetModel(int intDeviceId, const char* strNewModel){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -218,51 +224,34 @@ bool WINAPI devSetModel(int intDeviceId, char* strNewModel){ return blnSuccess; } -bool WINAPI devSetArguments(int intDeviceId, char* strArguments){ - return false; -/* vector vArguments; - //int intArguments[] = new int[]; //bort? - try{ - char* strTemp = strtok(strArguments, ","); +bool WINAPI devSetArgument(int intDeviceId, const char *strName, const char *strValue){ - while(strTemp != NULL){ - vArguments.push_back(atoi(strTemp)); - strTemp = strtok(NULL, ","); - } - TelldusSettings ts; - return ts.setArguments(intDeviceId, vArguments); - } - catch(exception e){ - handleException(e); - return false; - }*/ -} - -int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex){ - int intReturn; - try{ - if(intArgumentIndex != -1){ - TelldusSettings ts; - int* intArguments = ts.getArguments(intDeviceId); - intReturn = intArguments[intArgumentIndex]; - } - } - catch(exception e){ - handleException(e); - } - return intReturn; -} - -int WINAPI devGetNumberOfArguments(int intDeviceId){ - int intReturn; try{ TelldusSettings ts; - intReturn = ts.getNumberOfArguments(intDeviceId); + return ts.setArgument(intDeviceId, strName, strValue); } catch(exception e){ handleException(e); } - return intReturn; + return false; +} + +const char * WINAPI devGetArgument(int intDeviceId, const char *strName, const char *defaultValue){ + char *strReturn = ""; + try{ + TelldusSettings ts; + strReturn = ts.getArgument(intDeviceId, strName); + if (strReturn == NULL) { + return defaultValue; + } +#ifdef _WINDOWS + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); +#endif + } + catch(exception e){ + handleException(e); + } + return strReturn; } int WINAPI devAddDevice(){ diff --git a/driver/TellUsbD101/TellUsbD101.def b/driver/TellUsbD101/TellUsbD101.def index fc32ffca..e0ec3c03 100644 --- a/driver/TellUsbD101/TellUsbD101.def +++ b/driver/TellUsbD101/TellUsbD101.def @@ -6,19 +6,18 @@ EXPORTS devGetName @3 devGetVendor @4 devGetModel @5 - devGetNumberOfArguments @6 - devGetArgument @7 + devGetArgument @6 - devSetName @8 - devSetVendor @9 - devSetModel @10 - devSetArguments @11 + devSetName @7 + devSetVendor @8 + devSetModel @9 + devSetArgument @10 - devAddDevice @12 - devRemoveDevice @13 + devAddDevice @11 + devRemoveDevice @12 - devMethods @14 - devTurnOn @16 - devTurnOff @17 - devBell @18 - devDim @19 + devMethods @13 + devTurnOn @14 + devTurnOff @15 + devBell @16 + devDim @17 diff --git a/driver/TellUsbD101/TellUsbD101.h b/driver/TellUsbD101/TellUsbD101.h index 980a6f45..162d039d 100644 --- a/driver/TellUsbD101/TellUsbD101.h +++ b/driver/TellUsbD101/TellUsbD101.h @@ -27,21 +27,23 @@ extern "C" { TELLSTICK_API bool WINAPI devTurnOff(int intDeviceId); TELLSTICK_API bool WINAPI devBell(int intDeviceId); TELLSTICK_API bool WINAPI devDim(int intDeviceId, unsigned char level); - TELLSTICK_API int WINAPI devGetNumberOfDevices(); - TELLSTICK_API char * WINAPI devGetName(int intDeviceId); - TELLSTICK_API bool WINAPI devSetName(int intDeviceId, char* chNewName); - TELLSTICK_API char* WINAPI devGetVendor(int intDeviceId); - TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, char* chNewName); - TELLSTICK_API char* WINAPI devGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, char* chNewName); - TELLSTICK_API int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex); - TELLSTICK_API int WINAPI devGetNumberOfArguments(int intDeviceId); - TELLSTICK_API bool WINAPI devSetArguments(int intDeviceId, char* strArguments); - TELLSTICK_API int WINAPI devAddDevice(); - TELLSTICK_API int WINAPI devAddDeviceWithArguments(char* strVendor, int* intArguments[], int intNumberOfArguments); - TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); - TELLSTICK_API int WINAPI devGetDeviceId(int intDeviceIndex); TELLSTICK_API int WINAPI devMethods(int id); + + TELLSTICK_API int WINAPI devGetNumberOfDevices(); + TELLSTICK_API int WINAPI devGetDeviceId(int intDeviceIndex); + + TELLSTICK_API char * WINAPI devGetName(int intDeviceId); + TELLSTICK_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI devGetVendor(int intDeviceId); + TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI devGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, const char* chNewName); + + TELLSTICK_API const char * WINAPI devGetArgument(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API bool WINAPI devSetArgument(int intDeviceId, const char *strName, const char* strValue); + + TELLSTICK_API int WINAPI devAddDevice(); + TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); } #define TELLSTICK_TURNON 1 diff --git a/driver/TellUsbD101/settings/TelldusSettings.cpp b/driver/TellUsbD101/settings/TelldusSettings.cpp index 94e43a47..a283cc6f 100644 --- a/driver/TellUsbD101/settings/TelldusSettings.cpp +++ b/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -16,7 +16,7 @@ Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ try{ char* vendor = getVendor(intDeviceId); - int* args = getArguments(intDeviceId); +/* int* args = getArguments(intDeviceId); //each new brand must be added here if (strcmp(vendor, "Nexa") == 0){ @@ -27,7 +27,7 @@ Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ dev = new DeviceSartano((int)args[0], (int)args[1], intDongleIndex); } else if (strcmp(vendor, "Ikea") == 0) { dev = new DeviceIkea((int)args[0], (int)args[1], (int)args[2], intDongleIndex); - } + }*/ } catch(...){ throw; @@ -35,45 +35,58 @@ Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ return dev; } -/* -* Get the name of the device -*/ -char* TelldusSettings::getName(int intDeviceId){ - return getStringSetting(intDeviceId, "name"); -} - -/* -* Set the name of the device -*/ -bool TelldusSettings::setName(int intDeviceId, char* strNewName){ - return setStringSetting(intDeviceId, "name", strNewName); -} - - -/* -* Get the device vendor -*/ -char* TelldusSettings::getVendor(int intDeviceId){ - return getStringSetting(intDeviceId, "vendor"); -} - -/* -* Set the device vendor -*/ -bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ - return setStringSetting(intDeviceId, "vendor", strVendor); -} - -/* -* Get the device model -*/ -char* TelldusSettings::getModel(int intDeviceId){ - return getStringSetting(intDeviceId, "model"); -} - -/* -* Set the device model -*/ -bool TelldusSettings::setModel(int intDeviceId, char* strModel){ - return setStringSetting(intDeviceId, "model", strModel); -} +/* +* Get the name of the device +*/ +char* TelldusSettings::getName(int intDeviceId){ + return getStringSetting(intDeviceId, "name", false); +} + +/* +* Set the name of the device +*/ +bool TelldusSettings::setName(int intDeviceId, const char* strNewName){ + return setStringSetting(intDeviceId, "name", strNewName, false); +} + +/* +* Get the device vendor +*/ +char* TelldusSettings::getVendor(int intDeviceId){ + return getStringSetting(intDeviceId, "vendor", false); +} + +/* +* Set the device vendor +*/ +bool TelldusSettings::setVendor(int intDeviceId, const char* strVendor){ + return setStringSetting(intDeviceId, "vendor", strVendor, false); +} + +/* +* Get the device model +*/ +char* TelldusSettings::getModel(int intDeviceId){ + return getStringSetting(intDeviceId, "model", false); +} + +/* +* Set the device model +*/ +bool TelldusSettings::setModel(int intDeviceId, const char* strModel){ + return setStringSetting(intDeviceId, "model", strModel, false); +} + +/* +* Set device argument +*/ +bool TelldusSettings::setArgument(int intDeviceId, const char *strName, const char *strValue){ + return setStringSetting(intDeviceId, strName, strValue, true); +} + +/* +* Get device argument +*/ +char* TelldusSettings::getArgument(int intDeviceId, const char *strName) { + return getStringSetting(intDeviceId, strName, true); +} \ No newline at end of file diff --git a/driver/TellUsbD101/settings/TelldusSettings.h b/driver/TellUsbD101/settings/TelldusSettings.h index e590f9cb..03edb981 100644 --- a/driver/TellUsbD101/settings/TelldusSettings.h +++ b/driver/TellUsbD101/settings/TelldusSettings.h @@ -14,13 +14,13 @@ public: Device* getDevice(int intDeviceId); Device* getDevice(int intDeviceId, int intDongleIndex); char* getName(int intDeviceId); - bool setName(int intDeviceId, char* strNewName); + bool setName(int intDeviceId, const char* strNewName); char* getVendor(int intDeviceId); - bool setVendor(int intDeviceId, char* strVendor); + bool setVendor(int intDeviceId, const char* strVendor); char* getModel(int intDeviceId); - bool setModel(int intDeviceId, char* strModel); - int* getArguments(int intDeviceId); -// bool setArguments(int intDeviceId, vector vArguments); + bool setModel(int intDeviceId, const char* strModel); + char* getArgument(int intDeviceId, const char *strName); + bool setArgument(int intDeviceId, const char *strName, const char *strValue); int addDevice(); int getDeviceId(int intDeviceIndex); bool removeDevice(int intDeviceId); @@ -31,8 +31,8 @@ public: ~TelldusSettings(void); protected: - char *getStringSetting(int intDeviceId, const char* name); - bool setStringSetting(int intDeviceId, const char* name, const char *value); + char *getStringSetting(int intDeviceId, const char* name, bool parameter); + bool setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter); private: int getNextDeviceId(); diff --git a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp index 3e6c7ce3..fddee76d 100644 --- a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp @@ -11,6 +11,8 @@ // #include "TelldusSettings.h" #include +#include +#include using namespace std; @@ -70,34 +72,6 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ return id; } -/* -* Get number of device arguments -*/ -int TelldusSettings::getNumberOfArguments(int intDeviceId){ - int intReturn = -1; - - return intReturn; -} - -/* -* Get device arguments -*/ -int* TelldusSettings::getArguments(int intDeviceId){ -// vector vReturn; - int* intReturn = new int[2]; - - return intReturn; -} - -/* -* Set device arguments -*/ -bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ - - bool blnSuccess = false; - return blnSuccess; -} - /* * Add a new device */ @@ -184,7 +158,7 @@ void TelldusSettings::debugLog(int debugint){ }*/ } -char *TelldusSettings::getStringSetting(int intDeviceId, const char* name) { +char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { if (d->cfg == 0) { return ""; } @@ -192,16 +166,22 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name) { for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { cfg_device = cfg_getnsec(d->cfg, "device", i); if (cfg_getint(cfg_device, "id") == intDeviceId) { + if (parameter) { + cfg_device = cfg_getsec(cfg_device, "parameters"); + } const char *strSetting = cfg_getstr(cfg_device, name); + if (strSetting == NULL) { + return NULL; + } char *strReturn = (char *)malloc(strlen(strSetting) * sizeof(char)); strcpy(strReturn, strSetting); return strReturn; } } - return ""; + return 0; } -bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value) { +bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { if (d->cfg == 0) { return false; } @@ -209,7 +189,12 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { cfg_device = cfg_getnsec(d->cfg, "device", i); if (cfg_getint(cfg_device, "id") == intDeviceId) { - cfg_setstr(cfg_device, name, value); + if (parameter) { + cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); + cfg_setstr(cfg_parameters, name, value); + } else { + cfg_setstr(cfg_device, name, value); + } FILE *fp = fopen(CONFIG_FILE, "w"); cfg_print(d->cfg, fp); fclose(fp); @@ -220,16 +205,14 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const } bool readConfig(cfg_t **cfg) { - cfg_opt_t device_opts[] = { - CFG_INT("id", -1, CFGF_NONE), - CFG_STR("name", "Unnamed", CFGF_NONE), - CFG_STR("vendor", "Nexa", CFGF_NONE), - CFG_STR("model", "1", CFGF_NONE), - + cfg_opt_t parameter_opts[] = { //Nexa CFG_STR("nexa_house", 0, CFGF_NONE), CFG_STR("nexa_unit", 0, CFGF_NONE), + //Sartano + CFG_STR("sartano_code", 0, CFGF_NONE), + //Ikea CFG_STR("ikea_system", 0, CFGF_NONE), CFG_STR("ikea_units", 0, CFGF_NONE), @@ -237,11 +220,22 @@ bool readConfig(cfg_t **cfg) { CFG_END() }; + + cfg_opt_t device_opts[] = { + CFG_INT("id", -1, CFGF_NONE), + CFG_STR("name", "Unnamed", CFGF_NONE), + CFG_STR("vendor", "Nexa", CFGF_NONE), + CFG_STR("model", "1", CFGF_NONE), + CFG_SEC("parameters", parameter_opts, CFGF_NONE), + CFG_END() + }; + cfg_opt_t opts[] = { CFG_STR("deviceNode", "/dev/tellstick", CFGF_NONE), CFG_SEC("device", device_opts, CFGF_MULTI), CFG_END() }; + (*cfg) = cfg_init(opts, CFGF_NOCASE); if (cfg_parse((*cfg), CONFIG_FILE) == CFG_PARSE_ERROR) { (*cfg) = 0; From 0fb525f0dc816de29069ff45530009041c652525 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 4 Mar 2008 17:39:20 +0000 Subject: [PATCH 0077/2215] When commands are executed, the waiting time is reduced by 2 seconds per rfcmd call (was 1). --- tellstickd/tellstickd | 7 ++----- tellstickd/tellstickd.conf | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index be8a8452..6a370bf1 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -416,7 +416,7 @@ sub read_config @inrad = split /\s+/, $_; $device_cfg[$i][0] = $inrad[0]; # Protocol $device_cfg[$i][1] = $inrad[1]; # Housecode A and channel for NEXA, channel for SARTANO. - $device_cfg[$i][10] = $inrad[2]; # Rule valid days [1234567] + $device_cfg[$i][10] = $inrad[2]; # Rule valid days [[oe]1234567] $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched off at startup @@ -835,9 +835,6 @@ while (1) { $n_rfcmd_calls++; } } - - - } @@ -847,6 +844,6 @@ while (1) { $first_loop = $NO; if ($n_rfcmd_calls < 30) { - sleep(60 - 1*$n_rfcmd_calls); # Wait a while until next round [seconds]. If rfcmd has been called, reduce this figure by 1 second per call. + sleep(60 - 2*$n_rfcmd_calls); # Wait a while until next round [seconds]. If rfcmd has been called, reduce this figure by 2 seconds per call. } } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 91c85b9e..e08bcbbd 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -32,7 +32,7 @@ pid_file = /var/run/tellstickd.pid # Time format xx:yy where xx is hour and yy is minute # Multiple definitions are possible for each device # -# Setting and to the same means that the device will always be switched on. +# Setting and the same means that the device will always be switched on. # # The sample rule below will turn on the device between 06:10 and 06:20 and off between 22:00 and 23:00 monday to friday. # The device will be turned off daytime 10 minutes after sunrise and 15 before sunset From ed570d0c99fcb9b640437b4fb5f1ddafb57d07a5 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 4 Mar 2008 21:11:10 +0000 Subject: [PATCH 0078/2215] Just modified some text in the README file and the tellstickd.conf file. --- tellstickd/README | 10 +++++----- tellstickd/tellstickd.conf | 19 +++++++++++++------ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/tellstickd/README b/tellstickd/README index b702939e..9e1885ba 100644 --- a/tellstickd/README +++ b/tellstickd/README @@ -13,20 +13,20 @@ Installation ================= 0. Install rfcmd and necessary perl modules (on a typical Fedora/Centos/RHEL with the necessary repos installed, this should do it for you: yum install perl-DateTime perl-DateTime-Event-Sunrise). -1. Copy the file tellstickd-version/tellstickd to /usr/local/bin/ +1. Copy the file tellstickd-version/tellstickd to /usr/local/bin/ (or anywhere else depending on your wishes). -2. Copy the file tellstickd-version/tellstickd.conf to /etc/ +2. Copy the file tellstickd-version/tellstickd.conf to /etc/ (or anywhere else depending on your wishes). 3. Copy the suitable init script found under tellstickd-version/init_script to /etc/rc.d/init.d, this way you can control the script as any other service, easily make it start at boot (with chkconfig --level 35 tellstickd on). The file init_script/tellstickd is a Redhat type script whereas init_script/tellstickd.debian not unexpectedly should work on Debian type systems. -4. Remember to make the perl-script and init scripts executable. As root chmod 755 /usr/local/bin/tellstickd /etc/rc.d/init.d/tellstickd +4. Remember to make the perl-script and init-script executable. As root chmod 755 /usr/local/bin/tellstickd /etc/rc.d/init.d/tellstickd Configuration ================= 1. In tellstickd.conf: a. Set appropriate coordinates and timezone to suit your geographical location (further information: http://search.cpan.org/dist/DateTime-Event-Sunrise/lib/DateTime/Event/Sunrise.pm). - b. Specifiy the rfcmd binary location. Default: /usr/local/bin/rfcmd + b. Specifiy the rfcmd-binary location. Default: /usr/local/bin/rfcmd c. Specify the tellstick device name. Default: /dev/tellstick - d. If the default locations of the config and logfile not are according to your wishes, modify them here. Note 1: this can also be done with the tellstickd options --config and --logfile. Note 2: If you use the init script, these settings must be done in the init-script /etc/rc.d/init.d/tellstickd. + d. Specify the location of the logfile. e. Add device configurations. Multiple definitions for each device are possible (avoid having on and off times of multiple definitions overlapping each other). 2. If you would like this script to start at boot-time, on a RHEL/Centos/Fedora system, execute the following command chkconfig --level 35 tellstickd on diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index e08bcbbd..081194e7 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -23,31 +23,38 @@ log_file = /var/log/tellstickd pid_file = /var/run/tellstickd.pid # -# +# # # In valid day field, days are numbered 1=Monday, 2=Tuesday, ... , 7=Sunday. I.e. 1234567 means that the rule should be active every weekday. # The day fields can be prefixed with "o" or "e" making the rule valid on odd or even weeks. Week numbers are # calculated according to ISO, with the first week of the year being the one containing 4 jan # Time format xx:yy where xx is hour and yy is minute -# Multiple definitions are possible for each device +# Multiple definitions are possible for each device. Be aware that overlapping rules (overlapping in time) can/will cause troubles. # # Setting and the same means that the device will always be switched on. # + +# Sample rules + + # The sample rule below will turn on the device between 06:10 and 06:20 and off between 22:00 and 23:00 monday to friday. # The device will be turned off daytime 10 minutes after sunrise and 15 before sunset SARTANO 0000000000 12345 06:10-06:20 22:00-23:00 10 15 -# This device will be turned on between 07:34 and 07:48, turned off between 23:00 and 23:15 (applies for every day in the week). -# It will not be turned off daytime -NEXA P2 1234567 07:34-07:48 23:00-23:15 +# This device will be turned on between 07:34 and 07:48, turned off between 23:00 and 23:15 (every day of the week). +# It will be turned off exactly on sunrise and off exactly on sunset. +NEXA P2 1234567 07:34-07:48 23:00-23:15 0 0 # This device will be turned on 07:00 off between 20:00 and 20:30 and will be on daytime on sundays. NEXA P3 7 07:00 20:00-20:30 -# This device will be turned on 07:00 and off 20:00 on fridays and sundays on even numbered weeks +# This device will be turned on 07:00 and off 20:00 on fridays and sundays on evenly numbered weeks NEXA P3 e57 07:00 20:00 +# This device will be turned on 07:00 and off 20:00 on fridays and sundays on oddly numbered weeks +NEXA P3 o57 07:00 20:00 + From 6663c30ad5c8935efb58d4af4997ad069fbbd96e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Mar 2008 16:08:52 +0000 Subject: [PATCH 0079/2215] First version which actually can turn on and off devices under Linux. Only Nexa working right now... --- driver/TellUsbD101/Device.cpp | 4 +- driver/TellUsbD101/Device.h | 21 +++---- driver/TellUsbD101/DeviceIkea.h | 2 +- driver/TellUsbD101/DeviceNexa.cpp | 38 +++++++----- driver/TellUsbD101/DeviceNexa.h | 2 +- driver/TellUsbD101/DeviceSartano.cpp | 8 +-- driver/TellUsbD101/DeviceSartano.h | 2 +- driver/TellUsbD101/DeviceWaveman.cpp | 4 +- driver/TellUsbD101/DeviceWaveman.h | 2 +- driver/TellUsbD101/TellUsbD101.cpp | 2 +- driver/TellUsbD101/linux/Device.cpp | 59 +------------------ .../TellUsbD101/settings/TelldusSettings.cpp | 39 ++++++++---- driver/TellUsbD101/settings/TelldusSettings.h | 3 +- .../settings/TelldusSettingsConfuse.cpp | 18 +++--- driver/TellUsbD101/win/Device.cpp | 32 +++++----- 15 files changed, 104 insertions(+), 132 deletions(-) diff --git a/driver/TellUsbD101/Device.cpp b/driver/TellUsbD101/Device.cpp index 0281375a..0b536781 100644 --- a/driver/TellUsbD101/Device.cpp +++ b/driver/TellUsbD101/Device.cpp @@ -3,9 +3,8 @@ /* * Constructor */ -Device::Device(int intDongleIndex) +Device::Device() { - this->intDongleIndex = intDongleIndex; } /* @@ -13,7 +12,6 @@ Device::Device(int intDongleIndex) */ Device::~Device(void) { - intDongleIndex = -1; } /* diff --git a/driver/TellUsbD101/Device.h b/driver/TellUsbD101/Device.h index f4aec627..0c7451e1 100644 --- a/driver/TellUsbD101/Device.h +++ b/driver/TellUsbD101/Device.h @@ -4,21 +4,22 @@ class Device { -private: - int intDongleIndex; -protected: - void send(char* strMessage); public: - Device(int intDeviceIndex); + Device(); + ~Device(void); + virtual void turnOn(void); virtual void turnOff(void); virtual void bell(void); virtual void dim(unsigned char level); virtual int methods(char* strModel); - static int getDongleIndex(); + +#ifndef _WINDOWS + void setDevice(const char *device); +protected: + char *strDevice; +#endif - static void debugLog(char* debugstring); - -public: - ~Device(void); +protected: + void send(char* strMessage); }; diff --git a/driver/TellUsbD101/DeviceIkea.h b/driver/TellUsbD101/DeviceIkea.h index 4a672653..7c704c4c 100644 --- a/driver/TellUsbD101/DeviceIkea.h +++ b/driver/TellUsbD101/DeviceIkea.h @@ -5,7 +5,7 @@ class DeviceIkea : public Device { public: - DeviceIkea(int intSystem, int intUnits, int fadeStyle, int intDeviceIndex); + DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle); virtual void turnOn(void); virtual void turnOff(void); virtual void dim(unsigned char level); diff --git a/driver/TellUsbD101/DeviceNexa.cpp b/driver/TellUsbD101/DeviceNexa.cpp index 42f48cb9..bbffaeb0 100644 --- a/driver/TellUsbD101/DeviceNexa.cpp +++ b/driver/TellUsbD101/DeviceNexa.cpp @@ -11,9 +11,20 @@ using namespace std; /* * Constructor */ -DeviceNexa::DeviceNexa(int intNewHouse, int intNewCode, int intDeviceIndex):Device(intDeviceIndex){ - intHouse = intNewHouse; - intCode = intNewCode; +DeviceNexa::DeviceNexa(char *strNewHouse, char *strNewCode) + :Device() +{ + if (strNewHouse != NULL && strlen(strNewHouse) > 0) { + intHouse = strNewHouse[0] - 'A'; + } else { + intHouse = 0; + } + + if (strNewCode != NULL && strlen(strNewCode) > 0) { + intCode = atoi(strNewCode) - 1; + } else { + intCode = 0; + } } /* @@ -21,8 +32,8 @@ DeviceNexa::DeviceNexa(int intNewHouse, int intNewCode, int intDeviceIndex):Devi */ DeviceNexa::~DeviceNexa(void) { - intHouse = -1; - intCode = -1; +// intHouse = -1; +// intCode = -1; } /* @@ -31,10 +42,9 @@ DeviceNexa::~DeviceNexa(void) void DeviceNexa::turnOn(void){ try{ - //char* model = getModel(intDeviceId); - string strCode = getStringCode(intCode); - string strHouse = getStringCode(intHouse); - strCode.append(strHouse); + string strCode = getStringCode(intHouse); + string strUnit = getStringCode(intCode); + strCode.append(strUnit); strCode.insert(0, "S"); strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time @@ -54,10 +64,10 @@ void DeviceNexa::turnOn(void){ void DeviceNexa::turnOff(void){ try{ - string strCode = getStringCode(intCode); - string strHouse = getStringCode(intHouse); - - strCode.append(strHouse); + string strCode = getStringCode(intHouse); + string strUnit = getStringCode(intCode); + strCode.append(strUnit); + strCode.insert(0, "S"); strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time @@ -76,7 +86,7 @@ void DeviceNexa::turnOff(void){ void DeviceNexa::bell(void){ try{ - string strCode = getStringCode(intCode); + string strCode = getStringCode(intHouse); strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time strCode.insert(0, "S"); diff --git a/driver/TellUsbD101/DeviceNexa.h b/driver/TellUsbD101/DeviceNexa.h index abe8fa0d..40468d2f 100644 --- a/driver/TellUsbD101/DeviceNexa.h +++ b/driver/TellUsbD101/DeviceNexa.h @@ -5,7 +5,7 @@ class DeviceNexa : public Device { public: - DeviceNexa(int intHouse, int intCode, int intDeviceIndex); + DeviceNexa(char *strHouse, char *strCode); virtual void turnOn(void); virtual void turnOff(void); virtual void bell(void); diff --git a/driver/TellUsbD101/DeviceSartano.cpp b/driver/TellUsbD101/DeviceSartano.cpp index 1f38a2dc..59260418 100644 --- a/driver/TellUsbD101/DeviceSartano.cpp +++ b/driver/TellUsbD101/DeviceSartano.cpp @@ -10,11 +10,11 @@ using namespace std; /* * Constructor */ -DeviceSartano::DeviceSartano(int intNewSystem, int intNewCode, int intDeviceIndex) - :Device(intDeviceIndex) +DeviceSartano::DeviceSartano(char *strNewCode) + :Device() { - intSystem = intNewSystem; - intCode = intNewCode; +// intSystem = intNewSystem; +// intCode = intNewCode; } diff --git a/driver/TellUsbD101/DeviceSartano.h b/driver/TellUsbD101/DeviceSartano.h index c7c86324..29e0299b 100644 --- a/driver/TellUsbD101/DeviceSartano.h +++ b/driver/TellUsbD101/DeviceSartano.h @@ -6,7 +6,7 @@ class DeviceSartano : public Device { public: - DeviceSartano(int intSystem, int intCode, int intDeviceIndex); + DeviceSartano(char *strCode); virtual void turnOn(void); virtual void turnOff(void); virtual int methods(char* strModel); diff --git a/driver/TellUsbD101/DeviceWaveman.cpp b/driver/TellUsbD101/DeviceWaveman.cpp index 855afe5c..69227080 100644 --- a/driver/TellUsbD101/DeviceWaveman.cpp +++ b/driver/TellUsbD101/DeviceWaveman.cpp @@ -11,8 +11,8 @@ using namespace std; /* * Constructor */ -DeviceWaveman::DeviceWaveman(int intNewHouse, int intNewCode, int intDeviceIndex) - :DeviceNexa(intNewHouse, intNewCode, intDeviceIndex){ +DeviceWaveman::DeviceWaveman(char *strNewHouse, char *strNewCode) + :DeviceNexa(strNewHouse, strNewCode){ } /* diff --git a/driver/TellUsbD101/DeviceWaveman.h b/driver/TellUsbD101/DeviceWaveman.h index c099a563..f00b13e1 100644 --- a/driver/TellUsbD101/DeviceWaveman.h +++ b/driver/TellUsbD101/DeviceWaveman.h @@ -5,7 +5,7 @@ class DeviceWaveman : public DeviceNexa { public: - DeviceWaveman(int intHouse, int intCode, int intDeviceIndex); + DeviceWaveman(char *strHouse, char *strCode); virtual void turnOff(void); virtual int methods(char* strModel); }; diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/driver/TellUsbD101/TellUsbD101.cpp index bd61a22b..110f3617 100644 --- a/driver/TellUsbD101/TellUsbD101.cpp +++ b/driver/TellUsbD101/TellUsbD101.cpp @@ -286,7 +286,7 @@ int WINAPI devMethods(int id){ try{ TelldusSettings ts; char* strModel = ts.getModel(id); - Device* dev = ts.getDevice(id, -1); //We send dongleIndex=-1 sice we wouldn't send any data! + Device* dev = ts.getDevice(id); if (dev != NULL) { intMethods = dev->methods(strModel); } diff --git a/driver/TellUsbD101/linux/Device.cpp b/driver/TellUsbD101/linux/Device.cpp index 7aeff050..a0fb3e2b 100644 --- a/driver/TellUsbD101/linux/Device.cpp +++ b/driver/TellUsbD101/linux/Device.cpp @@ -10,9 +10,7 @@ void Device::send(char* strMessage) { int fd = -1; struct termios tio; - debugLog(strMessage); - - if( 0 > ( fd = open( "/dev/tellstick", O_RDWR ) ) ) { + if( 0 > ( fd = open( strDevice, O_RDWR ) ) ) { return; } @@ -29,57 +27,6 @@ void Device::send(char* strMessage) { close(fd); } -/* -* Get the device index of the Telldus dongle (the first one if many are connected) -* -1 if no such device exists -*/ -int Device::getDongleIndex(){ - int intReturn = -1; -/* FT_HANDLE fthHandle = 0; - FT_STATUS ftStatus = FT_OK; - - try{ - DWORD dwNumberOfDevices = 0; - - ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); - if (ftStatus == FT_OK) { - for (int i = 0; i < (int)dwNumberOfDevices; i++) { - - FT_PROGRAM_DATA pData; - char ManufacturerBuf[32]; - char ManufacturerIdBuf[16]; - char DescriptionBuf[64]; - char SerialNumberBuf[16]; - - pData.Signature1 = 0x00000000; - pData.Signature2 = 0xffffffff; - pData.Version = 0x00000002; // EEPROM structure with FT232R extensions - pData.Manufacturer = ManufacturerBuf; - pData.ManufacturerId = ManufacturerIdBuf; - pData.Description = DescriptionBuf; - pData.SerialNumber = SerialNumberBuf; - - ftStatus = FT_Open(i, &fthHandle); - ftStatus = FT_EE_Read(fthHandle, &pData); - if(ftStatus == FT_OK){ - if(pData.VendorId == 6017 && pData.ProductId == 3120){ - intReturn = i; - ftStatus = FT_Close(fthHandle); - break; - } - } - ftStatus = FT_Close(fthHandle); - } - } - } - catch(...){ - throw; - }*/ - return intReturn; +void Device::setDevice(const char *device) { + strDevice = strdup(device); } - -//only for debugging purpose -void Device::debugLog(char* debugstring){ - std::cout << debugstring << std::endl; -} - diff --git a/driver/TellUsbD101/settings/TelldusSettings.cpp b/driver/TellUsbD101/settings/TelldusSettings.cpp index a283cc6f..a106a9c3 100644 --- a/driver/TellUsbD101/settings/TelldusSettings.cpp +++ b/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -6,28 +6,45 @@ /* -* Get the requested device, when the index of the USB dongle is known +* Get the requested device * Note that the returned Device should be deleted when not in use anymore */ -Device* TelldusSettings::getDevice(int intDeviceId, int intDongleIndex){ +Device* TelldusSettings::getDevice(int intDeviceId){ - Device* dev = 0; + Device* dev = NULL; try{ char* vendor = getVendor(intDeviceId); -/* int* args = getArguments(intDeviceId); - //each new brand must be added here if (strcmp(vendor, "Nexa") == 0){ - dev = new DeviceNexa((int)args[0], (int)args[1], intDongleIndex); + char *strHouse = getArgument(intDeviceId, "nexa_house"); + char *strCode = getArgument(intDeviceId, "nexa_unit"); + dev = new DeviceNexa(strHouse, strCode); + } else if (strcmp(vendor, "Waveman") == 0) { - dev = new DeviceWaveman((int)args[0], (int)args[1], intDongleIndex); + char *strHouse = getArgument(intDeviceId, "nexa_house"); + char *strCode = getArgument(intDeviceId, "nexa_unit"); + dev = new DeviceWaveman(strHouse, strCode); + } else if (strcmp(vendor, "Sartano") == 0) { - dev = new DeviceSartano((int)args[0], (int)args[1], intDongleIndex); + char *strCode = getArgument(intDeviceId, "sartano_code"); + dev = new DeviceSartano(strCode); + } else if (strcmp(vendor, "Ikea") == 0) { - dev = new DeviceIkea((int)args[0], (int)args[1], (int)args[2], intDongleIndex); - }*/ + char *strSystem = getArgument(intDeviceId, "ikea_system"); + char *strUnits = getArgument(intDeviceId, "ikea_units"); + char *strFade = getArgument(intDeviceId, "ikea_fade"); + dev = new DeviceIkea(strSystem, strUnits, strFade); + + } else { + return NULL; + } + +#ifndef _WINDOWS + dev->setDevice( getSetting("deviceNode") ); +#endif + } catch(...){ throw; @@ -89,4 +106,4 @@ bool TelldusSettings::setArgument(int intDeviceId, const char *strName, const ch */ char* TelldusSettings::getArgument(int intDeviceId, const char *strName) { return getStringSetting(intDeviceId, strName, true); -} \ No newline at end of file +} diff --git a/driver/TellUsbD101/settings/TelldusSettings.h b/driver/TellUsbD101/settings/TelldusSettings.h index 03edb981..be30959e 100644 --- a/driver/TellUsbD101/settings/TelldusSettings.h +++ b/driver/TellUsbD101/settings/TelldusSettings.h @@ -10,9 +10,9 @@ class TelldusSettings { public: TelldusSettings(void); + char * getSetting(const char *strName); int getNumberOfDevices(void); Device* getDevice(int intDeviceId); - Device* getDevice(int intDeviceId, int intDongleIndex); char* getName(int intDeviceId); bool setName(int intDeviceId, const char* strNewName); char* getVendor(int intDeviceId); @@ -26,7 +26,6 @@ public: bool removeDevice(int intDeviceId); void debugLog(char* debugstring); void debugLog(int debugint); - int getNumberOfArguments(int intDeviceId); ~TelldusSettings(void); diff --git a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp index fddee76d..6aeada9d 100644 --- a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp @@ -45,6 +45,16 @@ TelldusSettings::~TelldusSettings(void) cfg_free(d->cfg); } +/* +* Return a setting +*/ +char *TelldusSettings::getSetting(const char *strName) { + if (d->cfg > 0) { + return cfg_getstr(d->cfg, strName); + } + return ""; +} + /* * Return the number of stored devices */ @@ -55,14 +65,6 @@ int TelldusSettings::getNumberOfDevices(void){ return 0; } -/* -* Get the requested device -*/ -Device* TelldusSettings::getDevice(int intDeviceId){ - return NULL; -} - - int TelldusSettings::getDeviceId(int intDeviceIndex){ if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds return -1; diff --git a/driver/TellUsbD101/win/Device.cpp b/driver/TellUsbD101/win/Device.cpp index ce5a065c..87935ad0 100644 --- a/driver/TellUsbD101/win/Device.cpp +++ b/driver/TellUsbD101/win/Device.cpp @@ -7,6 +7,8 @@ #include "..\StdAfx.h" #include "FTD2XX.H" +int getDongleIndex(); + /* * Send message to the USB dongle */ @@ -15,16 +17,21 @@ void Device::send(char* strMessage){ try{ FT_STATUS ftStatus = FT_OK; FT_HANDLE fthHandle = 0; + + int intDongleIndex = getDongleIndex(); + if (intDongleIndex < 0) { + return; + } - ftStatus = FT_Open(this->intDongleIndex, &fthHandle); + ftStatus = FT_Open(intDongleIndex, &fthHandle); int intBaudRate = 4800; //always 4800 - ftStatus = FT_SetBaudRate(fthHandle, intBaudRate); + ftStatus = FT_SetBaudRate(fthHandle, intBaudRate); ULONG bytesWritten; int intLen = (int)strlen(strMessage); - ftStatus = FT_Write(fthHandle, strMessage, intLen, &bytesWritten); + ftStatus = FT_Write(fthHandle, strMessage, intLen, &bytesWritten); - ftStatus = FT_Close(fthHandle); + ftStatus = FT_Close(fthHandle); } catch(...){ throw; @@ -35,7 +42,7 @@ void Device::send(char* strMessage){ * Get the device index of the Telldus dongle (the first one if many are connected) * -1 if no such device exists */ -int Device::getDongleIndex(){ +int getDongleIndex(){ int intReturn = -1; FT_HANDLE fthHandle = 0; FT_STATUS ftStatus = FT_OK; @@ -46,13 +53,13 @@ int Device::getDongleIndex(){ ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); if (ftStatus == FT_OK) { for (int i = 0; i < (int)dwNumberOfDevices; i++) { - + FT_PROGRAM_DATA pData; char ManufacturerBuf[32]; char ManufacturerIdBuf[16]; char DescriptionBuf[64]; char SerialNumberBuf[16]; - + pData.Signature1 = 0x00000000; pData.Signature2 = 0xffffffff; pData.Version = 0x00000002; // EEPROM structure with FT232R extensions @@ -60,7 +67,7 @@ int Device::getDongleIndex(){ pData.ManufacturerId = ManufacturerIdBuf; pData.Description = DescriptionBuf; pData.SerialNumber = SerialNumberBuf; - + ftStatus = FT_Open(i, &fthHandle); ftStatus = FT_EE_Read(fthHandle, &pData); if(ftStatus == FT_OK){ @@ -80,12 +87,3 @@ int Device::getDongleIndex(){ return intReturn; } -//only for debugging purpose -void Device::debugLog(char* debugstring){ - std::ofstream debugfile("c:\\telldusdebug.txt", std::ios::app); - if(debugfile){ - debugfile << debugstring << std::endl; - debugfile.close(); - } -} - From 0f53ccbce939e8465acb05e2f7a2d391f1782fc3 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 5 Mar 2008 22:31:40 +0000 Subject: [PATCH 0080/2215] Changed keyword from 'Not' to 'No' --- tellstickcontroller/Readme | 4 ++-- .../examples/tellstickController.conf | 8 ++++---- tellstickcontroller/tellstickController | 15 +++++++++------ tellstickcontroller/tellstickController.conf | 3 ++- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/tellstickcontroller/Readme b/tellstickcontroller/Readme index 84bdb607..ae0f0a79 100644 --- a/tellstickcontroller/Readme +++ b/tellstickcontroller/Readme @@ -60,7 +60,7 @@ 'Sunday'. A specified date like '2008-03-18', '2008-03-##', '####-03-##' or '####-##-15' is also allowed. The second part is mandatory and is either a expression or the - keyword 'None'. The expression can contain one or more of these + keyword 'No'. The expression can contain one or more of these keywords 'Sunrise', 'Sunset', 'Random(HH:MM)' and 'HH:MM'. Example rule: Weekend/07:15 Example rule: Monday+Sunday/07:15 @@ -68,7 +68,7 @@ Example rule: 2008-03-##/12:10 Example rule: 07:15+Random(02:00) Example rule: Sunset-00:30 - Example rule: None + Example rule: No AUTHOR Original version written by Rickard Andersson diff --git a/tellstickcontroller/examples/tellstickController.conf b/tellstickcontroller/examples/tellstickController.conf index 0cf22590..3af811c3 100644 --- a/tellstickcontroller/examples/tellstickController.conf +++ b/tellstickcontroller/examples/tellstickController.conf @@ -3,7 +3,7 @@ # Configuration file for tellstickController # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version: 1.3 +# Version: 1.3.1 # ################################################################################ # @@ -70,12 +70,12 @@ Alias Livingroom_mythtv_leds Yes Nexa G 8 # Rule Bedroom_window Workweek/sunrise-00:30 Workweek/Sunrise+01:00 Rule Bedroom_window Sunset+Random(00:30) 00:00+Random(00:30) -Rule Bedroom_mythtv_leds Not 02:00 +Rule Bedroom_mythtv_leds No 02:00 Rule kitchen_cabinets Sunrise-00:30 Sunrise+01:00 Rule kitchen_cabinets Workweek/Sunset Workweek/00:00+Random(00:30) Rule kitchen_cabinets Weekend/Sunset-01:00 Weekend/00:30+Random(00:30) Rule Livingroom_cabinets Sunset+01:00+Random(00:30) 00:15+Random(00:30) Rule Livingroom_walls Sunset+Random(00:30) 00:15+Random(00:30) -Rule Livingroom_uplight Not 02:00 -Rule Livingroom_mythtv_leds Not 02:00 +Rule Livingroom_uplight No 02:00 +Rule Livingroom_mythtv_leds No 02:00 diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index 76fc4fe1..82dd6027 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -4,7 +4,7 @@ # tellstickController program # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version 1.3 +# Version 1.3.1 # ###################################################################### # @@ -419,7 +419,10 @@ sub read_config($) { printlogger $text; foreach my $rule (@cfg_rule) { my ($alias, $on, $off) = @$rule; - $text = "$alias = on at $on and off at $off"; + $text = "$alias ="; + $text .= " on at $on" if ($on !~ /no/); + $text .= " and" if (($on !~ /no/) && ($off !~ /no/)); + $text .= " off at $off" if ($off !~ /no/); println $text if ($option{"check"}); printlogger $text; } @@ -579,7 +582,7 @@ sub get_rule_datetime($$$$) { } } - if (defined($time) && ($time !~ /^not$/)) { + if (defined($time) && ($time !~ /^no$/)) { my $days = 0; my $hours = 0; my $minutes = 0; @@ -911,7 +914,7 @@ __DATA__ #- 'Sunday'. A specified date like '2008-03-18', '2008-03-##', #- '####-03-##' or '####-##-15' is also allowed. #- The second part is mandatory and is either a expression or the -#- keyword 'None'. The expression can contain one or more of these +#- keyword 'No'. The expression can contain one or more of these #- keywords 'Sunrise', 'Sunset', 'Random(HH:MM)' and 'HH:MM'. #- Example rule: Weekend/07:15 #- Example rule: Monday+Sunday/07:15 @@ -919,7 +922,7 @@ __DATA__ #- Example rule: 2008-03-##/12:10 #- Example rule: 07:15+Random(02:00) #- Example rule: Sunset-00:30 -#- Example rule: None +#- Example rule: No #- #- AUTHOR #- Original version written by Rickard Andersson @@ -927,7 +930,7 @@ __DATA__ #- #- LICENSE #- Copyright (C) 2008 Rickard Andersson -#- Version 1.3 +#- Version 1.3.1 #- This program comes with ABSOLUTELY NO WARRANTY. #- This is free software, and you are welcome to redistribute it #- under certain conditions; See license file for details. diff --git a/tellstickcontroller/tellstickController.conf b/tellstickcontroller/tellstickController.conf index 8ad92109..18773089 100644 --- a/tellstickcontroller/tellstickController.conf +++ b/tellstickcontroller/tellstickController.conf @@ -3,7 +3,7 @@ # Configuration file for tellstickController # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version: 1.3 +# Version: 1.3.1 # ################################################################################ # @@ -64,6 +64,7 @@ Alias device1 No Nexa A 1 # Rule BedroomWindow 18:33 23:10+Random(00:45) # Rule MythTv_Backlight Weekend/20:00 Weekend/Sunset # Rule device42 2008-03-##/18:45 2008-03-##/22:11 +# Rule device42 No 02:00 # # Rule device1 weekend/sunrise weekend/08:45 From a6715af1c1fbf2f924953c93a55148b0fb316c9a Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 5 Mar 2008 22:32:49 +0000 Subject: [PATCH 0081/2215] Changed keyword from 'Not' to 'No' --- tellstickcontroller/Readme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickcontroller/Readme b/tellstickcontroller/Readme index ae0f0a79..4bddaf1a 100644 --- a/tellstickcontroller/Readme +++ b/tellstickcontroller/Readme @@ -76,7 +76,7 @@ LICENSE Copyright (C) 2008 Rickard Andersson - Version 1.3 + Version 1.3.1 This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; See license file for details. From 454eda1c0938af49505159d40faade1668087768 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Sun, 9 Mar 2008 11:37:15 +0000 Subject: [PATCH 0082/2215] Corrected i missspelling in the help display. --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 6a370bf1..48dc4c1e 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -669,7 +669,7 @@ sub usageprompt printf("-c, --config filename Searchpath to configuration file, if not given $CONFIG_FILE is assumed.\n"); printf("-d, --daemon Run the program as a daemon and write a logfile.\n"); printf("-h, --help Show this message and exit.\n"); - printf("--simulate Run in foreground, log to console, no actuall device operations performed.\n"); + printf("--simulate Run in foreground, log to console, no actual device operations performed.\n"); } From f4066ea1e70668c85bc199c59a983f75cd9baf7e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 16 Mar 2008 21:34:36 +0000 Subject: [PATCH 0083/2215] Compilation fixes for Windows --- driver/TellUsbD101/DeviceIkea.cpp | 10 +- .../settings/TelldusSettingsWinRegistry.cpp | 143 +----------------- 2 files changed, 8 insertions(+), 145 deletions(-) diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/driver/TellUsbD101/DeviceIkea.cpp index e5af5f79..26e760bc 100644 --- a/driver/TellUsbD101/DeviceIkea.cpp +++ b/driver/TellUsbD101/DeviceIkea.cpp @@ -11,10 +11,12 @@ using namespace std; /* * Constructor */ -DeviceIkea::DeviceIkea(int intNewSystem, int intNewUnits, int intNewFadeStyle, int intDeviceIndex):Device(intDeviceIndex){ - intSystem = intNewSystem; - intUnits = intNewUnits; - intFadeStyle = intNewFadeStyle; +DeviceIkea::DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle) + :Device() +{ +// intSystem = intNewSystem; +// intUnits = intNewUnits; +// intFadeStyle = intNewFadeStyle; } /* diff --git a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp index 6644b8cb..b8695ead 100644 --- a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp @@ -71,25 +71,6 @@ int TelldusSettings::getNumberOfDevices(void){ return intNumberOfDevices; } -/* -* Get the requested device -*/ -Device* TelldusSettings::getDevice(int intDeviceId){ - - try{ - int intDongleIndex = Device::getDongleIndex(); - if(intDongleIndex != -1){ - return getDevice(intDeviceId, intDongleIndex); - } - else{ - return NULL; - } - } - catch(...){ - throw; - } -} - int TelldusSettings::getDeviceId(int intDeviceIndex){ int intReturn = -1; @@ -122,126 +103,6 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ } -/* -* Get number of device arguments -*/ -int TelldusSettings::getNumberOfArguments(int intDeviceId){ - int intReturn = -1; - - try{ - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - DWORD dNumValues; - RegQueryInfoKey(d->hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); - intReturn = (int)dNumValues - 3; //total number of values - model, name and vendor - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - } - catch(...){ - //error management - } - - return intReturn; -} - -/* -* Get device arguments -*/ -int* TelldusSettings::getArguments(int intDeviceId){ - vector vReturn; - int* intReturn = new int[]; - - try{ - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - DWORD dNumValues; - RegQueryInfoKey(d->hk, NULL, NULL, NULL, NULL, NULL, NULL, &dNumValues, NULL, NULL, NULL, NULL); - - int intNumberOfArguments = (int)dNumValues - 3; //total number of values - model, name and vendor - DWORD dwLength; - char chConvertBuffer[20]; - int i = 0; - - while(i < intNumberOfArguments){ - - char* Buff = new char[d->intMaxRegValueLength]; - - _itoa(i, chConvertBuffer, 10); - long lngStatus = RegQueryValueEx(d->hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); - if(lngStatus == ERROR_MORE_DATA){ - lngStatus = RegQueryValueEx(d->hk, chConvertBuffer, NULL, NULL, (LPBYTE)Buff, &dwLength); - } - int intReturn = (int)_atoi64(Buff); - vReturn.push_back(intReturn); - - i++; - delete Buff; - } - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - - intReturn = new int[vReturn.size()]; - - int i = 0; - while(i < (int)vReturn.size()){ - intReturn[i] = vReturn.at(i); - i++; - } - } - catch(...){ - //error management - } - - return intReturn; -} - -/* -* Set device arguments -*/ -/* bool TelldusSettings::setArguments(int intDeviceId, int* intArguments[], int intNumberOfArguments){ - - bool blnSuccess = true; - try{ - std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - char chConvertBuffer [20]; - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); - - if(lnExists == ERROR_SUCCESS){ - int i = 0; - while(i < intNumberOfArguments){ - _itoa(i, chConvertBuffer, 10); - RegSetValueEx(hk, chConvertBuffer, 0, REG_SZ, (LPBYTE)intArguments[i], intMaxRegValueLength); - i++; - } - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(hk); - - } - catch(...){ - blnSuccess = false; - } - return blnSuccess; -}*/ - /* * Set device arguments */ @@ -390,7 +251,7 @@ bool TelldusSettings::removeDevice(int intDeviceId){ return blnSuccess; } -char *TelldusSettings::getStringSetting(int intDeviceId, const char* name) { +char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { char* strReturn = ""; try{ @@ -421,7 +282,7 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name) { return strReturn; } -bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value) { +bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { bool blnSuccess = true; try{ From da8810db4bfb76f925a3346f7e86e6867bff4d3c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 16 Mar 2008 22:08:16 +0000 Subject: [PATCH 0084/2215] Enabled to store devices global on windows if you set the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Telldus\Devices\SharedDevices to 1 See #1 --- .../settings/TelldusSettingsWinRegistry.cpp | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp index b8695ead..8894b822 100644 --- a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp +++ b/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp @@ -7,10 +7,12 @@ #include using namespace std; +bool storeGlobal(privateVars *d); class privateVars { public: HKEY hk; + HKEY rootKey; std::string strRegPathDevice; std::string strRegPath; int intMaxRegValueLength; @@ -24,8 +26,12 @@ TelldusSettings::TelldusSettings(void) d = new privateVars(); d->strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; d->strRegPath = "SOFTWARE\\Telldus\\"; - d->intMaxRegValueLength = 1000; + if (storeGlobal(d)) { + d->rootKey = HKEY_LOCAL_MACHINE; + } else { + d->rootKey = HKEY_CURRENT_USER; + } } /* @@ -49,7 +55,7 @@ int TelldusSettings::getNumberOfDevices(void){ try{ - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &d->hk); + long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ @@ -77,7 +83,7 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ try{ - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, d->strRegPathDevice.c_str(), 0, KEY_READ, &d->hk); + long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_READ, &d->hk); if(lnExists == ERROR_SUCCESS){ @@ -155,7 +161,7 @@ int TelldusSettings::addDevice(){ ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - if(RegCreateKeyEx(HKEY_CURRENT_USER, + if(RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, @@ -185,7 +191,7 @@ int TelldusSettings::getNextDeviceId(){ int intReturn = -1; try{ DWORD dwDisp; - long lnExists = RegCreateKeyEx(HKEY_CURRENT_USER, d->strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, + long lnExists = RegCreateKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &d->hk, @@ -239,7 +245,7 @@ bool TelldusSettings::removeDevice(int intDeviceId){ ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lngSuccess = RegDeleteKey(HKEY_CURRENT_USER, strCompleteRegPath.c_str()); + long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); if(lngSuccess != ERROR_SUCCESS){ blnSuccess = false; } @@ -258,7 +264,7 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; @@ -290,7 +296,7 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); if(lnExists == ERROR_SUCCESS){ d->intMaxRegValueLength = (int)strlen(value); @@ -325,4 +331,37 @@ void TelldusSettings::debugLog(int debugint){ debugfile << debugint << endl; debugfile.close(); } +} + +bool storeGlobal(privateVars *d) { + bool blnReturn = false; + try{ + long lnExists = RegOpenKeyEx(HKEY_LOCAL_MACHINE, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &d->hk); + + if(lnExists == ERROR_SUCCESS){ + + DWORD dwLength; + char* Buff = new char[d->intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(d->hk, "SharedDevices", NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + + + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(d->hk, "SharedDevices", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + + if(lngStatus == ERROR_SUCCESS){ + + int intValue = (int)Buff[0]; + blnReturn = (intValue == 1); + } + delete Buff; + } + RegCloseKey(d->hk); + } + catch(...){ + } + return blnReturn; } \ No newline at end of file From 56f2d654073b214fd1651e539bee71c0672caf4e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 16 Mar 2008 22:25:40 +0000 Subject: [PATCH 0085/2215] TelldusSettings: Ported r84 (enabled to store devices global on windows) from trunk. This closes #1. --- driver/TellUsbD101/TelldusSettings.cpp | 70 ++++++++++++++++++++------ driver/TellUsbD101/TelldusSettings.h | 2 + 2 files changed, 56 insertions(+), 16 deletions(-) diff --git a/driver/TellUsbD101/TelldusSettings.cpp b/driver/TellUsbD101/TelldusSettings.cpp index d15b6e2f..d6616ca0 100644 --- a/driver/TellUsbD101/TelldusSettings.cpp +++ b/driver/TellUsbD101/TelldusSettings.cpp @@ -12,6 +12,7 @@ #include using namespace std; +bool storeGlobal(); /* * Constructor @@ -20,8 +21,12 @@ TelldusSettings::TelldusSettings(void) { strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; strRegPath = "SOFTWARE\\Telldus\\"; - intMaxRegValueLength = 1000; + if (storeGlobal()) { + rootKey = HKEY_LOCAL_MACHINE; + } else { + rootKey = HKEY_CURRENT_USER; + } } /* @@ -45,7 +50,7 @@ int TelldusSettings::getNumberOfDevices(void){ try{ - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ @@ -127,7 +132,7 @@ char* TelldusSettings::getName(int intDeviceId){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; @@ -162,7 +167,7 @@ bool TelldusSettings::setName(int intDeviceId, char* strNewName){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if(lnExists == ERROR_SUCCESS){ intMaxRegValueLength = (int)strlen(strNewName); @@ -191,7 +196,7 @@ char* TelldusSettings::getVendor(int intDeviceId){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(rootKey, (LPCSTR)strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; @@ -232,7 +237,7 @@ bool TelldusSettings::setVendor(int intDeviceId, char* strVendor){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if(lnExists == ERROR_SUCCESS){ intMaxRegValueLength = (int)strlen(strVendor); @@ -260,7 +265,7 @@ char* TelldusSettings::getModel(int intDeviceId){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; @@ -296,7 +301,7 @@ bool TelldusSettings::setModel(int intDeviceId, char* strVendor){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if(lnExists == ERROR_SUCCESS){ intMaxRegValueLength = (int)strlen(strVendor); @@ -318,7 +323,7 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ try{ - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, KEY_READ, &hk); + long lnExists = RegOpenKeyEx(rootKey, strRegPathDevice.c_str(), 0, KEY_READ, &hk); if(lnExists == ERROR_SUCCESS){ @@ -354,7 +359,7 @@ int TelldusSettings::getNumberOfArguments(int intDeviceId){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ DWORD dNumValues; @@ -384,7 +389,7 @@ int* TelldusSettings::getArguments(int intDeviceId){ std::ostringstream ssRegPath; ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ DWORD dNumValues; @@ -442,7 +447,7 @@ bool TelldusSettings::setArguments(int intDeviceId, int* intArguments[], int int ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); char chConvertBuffer [20]; - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if(lnExists == ERROR_SUCCESS){ int i = 0; @@ -476,7 +481,7 @@ bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ string strCompleteRegPath = ssRegPath.str(); char chConvertBuffer [20]; char chConvertBufferValue [20]; - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + long lnExists = RegOpenKeyEx(rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if(lnExists == ERROR_SUCCESS){ int i = 0; @@ -516,7 +521,7 @@ int TelldusSettings::addDevice(){ ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - if(RegCreateKeyEx(HKEY_CURRENT_USER, + if(RegCreateKeyEx(rootKey, strCompleteRegPath.c_str(), 0, NULL, @@ -546,7 +551,7 @@ int TelldusSettings::getNextDeviceId(){ int intReturn = -1; try{ DWORD dwDisp; - long lnExists = RegCreateKeyEx(HKEY_CURRENT_USER, strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, + long lnExists = RegCreateKeyEx(rootKey, strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, @@ -600,7 +605,7 @@ bool TelldusSettings::removeDevice(int intDeviceId){ ssRegPath << strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lngSuccess = RegDeleteKey(HKEY_CURRENT_USER, strCompleteRegPath.c_str()); + long lngSuccess = RegDeleteKey(rootKey, strCompleteRegPath.c_str()); if(lngSuccess != ERROR_SUCCESS){ blnSuccess = false; } @@ -628,4 +633,37 @@ void TelldusSettings::debugLog(int debugint){ debugfile << debugint << endl; debugfile.close(); } +} + +bool TelldusSettings::storeGlobal() { + bool blnReturn = false; + try{ + long lnExists = RegOpenKeyEx(HKEY_LOCAL_MACHINE, strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + + DWORD dwLength; + char* Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, "SharedDevices", NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + + + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, "SharedDevices", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + + if(lngStatus == ERROR_SUCCESS){ + + int intValue = (int)Buff[0]; + blnReturn = (intValue == 1); + } + delete Buff; + } + RegCloseKey(hk); + } + catch(...){ + } + return blnReturn; } \ No newline at end of file diff --git a/driver/TellUsbD101/TelldusSettings.h b/driver/TellUsbD101/TelldusSettings.h index 65de9cc2..54aee8e8 100644 --- a/driver/TellUsbD101/TelldusSettings.h +++ b/driver/TellUsbD101/TelldusSettings.h @@ -33,9 +33,11 @@ public: private: int getNextDeviceId(); + bool storeGlobal(); //variables HKEY hk; + HKEY rootKey; std::string strRegPathDevice; std::string strRegPath; int intMaxRegValueLength; From cff8a15b60e731f39f21ebe820c4e97750aa44a0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 23 Mar 2008 11:46:57 +0000 Subject: [PATCH 0086/2215] Fixed the misleading help text, closes #19 --- rfcmd/rfcmd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rfcmd/rfcmd.c b/rfcmd/rfcmd.c index d782d514..c0ceeb5d 100644 --- a/rfcmd/rfcmd.c +++ b/rfcmd/rfcmd.c @@ -226,8 +226,8 @@ void printUsage(void) printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN\n" ); printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN: \n"); - printf("\t\t HOUSE_CODE: A..P\n\t\t CHANNEL: 1..16\n\t\t ON_OFF: 0..1\n" ); + printf("\t\t HOUSE_CODE: A..P\n\t\t CHANNEL: 1..16\n\t\t OFF_ON: 0..1\n" ); printf("\t PROTOCOL ARGUMENTS - SARTANO: \n"); - printf("\t\t CHANNEL: 0000000000..1111111111\n\t\t ON_OFF: 0..1\n" ); + printf("\t\t CHANNEL: 0000000000..1111111111\n\t\t OFF_ON: 0..1\n" ); printf("Copyright(C) Tord Andersson 2007\r\n"); } From 4bc36dd343df6afb44b161a347defa70381180c3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 29 Mar 2008 18:42:39 +0000 Subject: [PATCH 0087/2215] Added Java JNI wrapper. --- bindings/java/example/test.java | 98 +++++++++++++++++++++++++++++++++ bindings/java/tellstick.c | 60 ++++++++++++++++++++ bindings/java/tellstick.h | 77 ++++++++++++++++++++++++++ bindings/java/tellstick.java | 27 +++++++++ 4 files changed, 262 insertions(+) create mode 100644 bindings/java/example/test.java create mode 100644 bindings/java/tellstick.c create mode 100644 bindings/java/tellstick.h create mode 100644 bindings/java/tellstick.java diff --git a/bindings/java/example/test.java b/bindings/java/example/test.java new file mode 100644 index 00000000..068ab743 --- /dev/null +++ b/bindings/java/example/test.java @@ -0,0 +1,98 @@ +import java.io.*; + +class test +{ + tellstick TS = new tellstick(); + + public void run() { + try { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + + int nbrDevices = TS.devGetNumberOfDevices(); + for (int i = 0; i < nbrDevices; i++) { + int id = TS.devGetDeviceId(i); + String deviceName = TS.devGetName(id); + System.out.println(id + "\t" + deviceName); + } + + System.out.print("Enter a device: "); + int device = Integer.parseInt(in.readLine()); + process(device); + + } catch (IOException e) { + } + } + + private void process(int device) { + try { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + int methods = TS.devMethods(device); + if ((methods & TS.TELLSTICK_TURNON) > 0) { + System.out.println(TS.TELLSTICK_TURNON + "\tTurn on"); + } + if ((methods & TS.TELLSTICK_TURNOFF) > 0) { + System.out.println(TS.TELLSTICK_TURNOFF + "\tTurn off"); + } + if ((methods & TS.TELLSTICK_BELL) > 0) { + System.out.println(TS.TELLSTICK_BELL + "\tBell"); + } + if ((methods & TS.TELLSTICK_DIM) > 0) { + System.out.println(TS.TELLSTICK_DIM + "\tDim"); + } + System.out.println("What do you want to do?"); + int action = Integer.parseInt(in.readLine()); + if ( (action & methods) == 0 ) { + System.out.println("The device doesn't support this method"); + return; + } + + if ((action & TS.TELLSTICK_TURNON) > 0) { + turnOn(device); + } else if ((action & TS.TELLSTICK_TURNOFF) > 0) { + turnOff(device); + } else if ((action & TS.TELLSTICK_BELL) > 0) { + bell(device); + } else if ((action & TS.TELLSTICK_DIM) > 0) { + dim(device); + } + + } catch (IOException e) { + } + } + + private void turnOn(int device) { + System.out.println("Turning on " + TS.devGetName(device)); + TS.devTurnOn(device); + } + + private void turnOff(int device) { + System.out.println("Turning off " + TS.devGetName(device)); + TS.devTurnOff(device); + } + + private void bell(int device) { + System.out.println("Sending bell to " + TS.devGetName(device)); + TS.devBell(device); + } + + private void dim(int device) { + try { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + System.out.print("Select level (0-255): "); + int level = Integer.parseInt(in.readLine()); + if (level >= 256 || level < 0) { + System.out.println("Out of range"); + } + System.out.println("Dim " + TS.devGetName(device)); + TS.devDim(device, level); + } catch (IOException e) { + } + } + + public static void main(String[] args) + { + test t = new test(); + t.run(); + } + +} \ No newline at end of file diff --git a/bindings/java/tellstick.c b/bindings/java/tellstick.c new file mode 100644 index 00000000..29b633dc --- /dev/null +++ b/bindings/java/tellstick.c @@ -0,0 +1,60 @@ +/*tellstick.c*/ +#include "tellstick.h" +#include +#include + +JNIEXPORT jboolean JNICALL +Java_tellstick_devTurnOn(JNIEnv *, jobject, jint intDeviceId) +{ + return (jboolean) devTurnOn( (int)intDeviceId); +} + + +JNIEXPORT jboolean JNICALL +Java_tellstick_devTurnOff(JNIEnv *, jobject, jint intDeviceId) +{ + return (jboolean) devTurnOff( (int)intDeviceId); +} + + +JNIEXPORT jboolean JNICALL +Java_tellstick_devBell(JNIEnv *, jobject, jint intDeviceId) +{ + return (jboolean) devBell( (int)intDeviceId); +} + + +JNIEXPORT jboolean JNICALL +Java_tellstick_devDim(JNIEnv *, jobject, jint intDeviceId, jint level) +{ + return (jboolean) devDim( (int)intDeviceId, (unsigned char) level); +} + + +JNIEXPORT jint JNICALL +Java_tellstick_devMethods(JNIEnv *, jobject, jint intDeviceId) +{ + return (jint) devMethods( (int)intDeviceId ); +} + + +JNIEXPORT jint JNICALL +Java_tellstick_devGetNumberOfDevices(JNIEnv *, jobject) +{ + return (jint)devGetNumberOfDevices(); +} + + +JNIEXPORT jint JNICALL +Java_tellstick_devGetDeviceId(JNIEnv *, jobject, jint intDeviceIndex) +{ + return (jint)devGetDeviceId( (int)intDeviceIndex ); +} + + +JNIEXPORT jstring JNICALL +Java_tellstick_devGetName(JNIEnv *env, jobject, jint intDeviceId) +{ + const char *name = devGetName( (int)intDeviceId ); + return env->NewStringUTF(name); +} diff --git a/bindings/java/tellstick.h b/bindings/java/tellstick.h new file mode 100644 index 00000000..cde08d2e --- /dev/null +++ b/bindings/java/tellstick.h @@ -0,0 +1,77 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class tellstick */ + +#ifndef _Included_tellstick +#define _Included_tellstick +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: tellstick + * Method: devTurnOn + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_tellstick_devTurnOn + (JNIEnv *, jobject, jint); + +/* + * Class: tellstick + * Method: devTurnOff + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_tellstick_devTurnOff + (JNIEnv *, jobject, jint); + +/* + * Class: tellstick + * Method: devBell + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_tellstick_devBell + (JNIEnv *, jobject, jint); + +/* + * Class: tellstick + * Method: devDim + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_tellstick_devDim + (JNIEnv *, jobject, jint, jint); + +/* + * Class: tellstick + * Method: devMethods + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_tellstick_devMethods + (JNIEnv *, jobject, jint); + +/* + * Class: tellstick + * Method: devGetNumberOfDevices + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_tellstick_devGetNumberOfDevices + (JNIEnv *, jobject); + +/* + * Class: tellstick + * Method: devGetDeviceId + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_tellstick_devGetDeviceId + (JNIEnv *, jobject, jint); + +/* + * Class: tellstick + * Method: devGetName + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_tellstick_devGetName + (JNIEnv *, jobject, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/bindings/java/tellstick.java b/bindings/java/tellstick.java new file mode 100644 index 00000000..c3325db9 --- /dev/null +++ b/bindings/java/tellstick.java @@ -0,0 +1,27 @@ +//firstJNI.java + +public class tellstick +{ + public final int TELLSTICK_TURNON = 1; + public final int TELLSTICK_TURNOFF = 2; + public final int TELLSTICK_BELL = 4; + public final int TELLSTICK_DIM = 16; + + public native boolean devTurnOn(int intDeviceId); + public native boolean devTurnOff(int intDeviceId); + public native boolean devBell(int intDeviceId); + public native boolean devDim(int intDeviceId, int level); + public native int devMethods(int intDeviceId); + + public native int devGetNumberOfDevices(); + public native int devGetDeviceId(int intDeviceIndex); + + public native String devGetName(int intDeviceId); + + static { + System.loadLibrary("tellstickJNI"); + } + + +} + From c3d3d57935f65d50a2f54723c42b0b640028fe63 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Wed, 2 Apr 2008 19:02:02 +0000 Subject: [PATCH 0088/2215] Added WAVEMAN as possible protocol since rfcmd me unknowingly supports that as well. --- tellstickd/tellstickd | 16 ++++++++-------- tellstickd/tellstickd.conf | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 48dc4c1e..72129b67 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -45,10 +45,10 @@ my $dayOfWeek; my $dayOfMonth; my $PROGRAM_NAME = "tellstickd"; -my $VERSION = "0.6.0"; +my $VERSION = "0.6.1"; # Structure of the configurations to be read; -# $device_cfg[$i][0]; # Protocol, only NEXA and SARTANO supported so far by rfcmd +# $device_cfg[$i][0]; # Protocol, only NEXA, WAVEMAN and SARTANO supported so far by rfcmd # $device_cfg[$i][1]; # Housecode A-P # $device_cfg[$i][2]; # Channel 1-3 # $device_cfg[$i][3]; # On time @@ -154,11 +154,11 @@ sub rfcmd_exec { if ($device_cfg[$device_id][0] eq "SARTANO") { $RFCMD_OPTIONS = "$TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1]"; } - elsif ($device_cfg[$device_id][0] eq "NEXA") { + elsif ($device_cfg[$device_id][0] eq "NEXA" || $device_cfg[$device_id][0] eq "WAVEMAN") { $RFCMD_OPTIONS = "$TELLSTICK_DEVICE $device_cfg[$device_id][0] $device_cfg[$device_id][1] $device_cfg[$device_id][2]"; } else { - die("$PROGRAM_NAME: Device $device_id has an unknown protocol. Only NEXA and SARTANO allowed.\n"); + die("$PROGRAM_NAME: Device $device_id has an unknown protocol. Only NEXA, WAVEMAN and SARTANO allowed.\n"); } @@ -410,12 +410,12 @@ sub read_config } - if ($_ =~ /^[NEXA|SARTANO]/ ) { + if ($_ =~ /^[NEXA|WAVEMAN|SARTANO]/ ) { chomp($_); @inrad = split /\s+/, $_; $device_cfg[$i][0] = $inrad[0]; # Protocol - $device_cfg[$i][1] = $inrad[1]; # Housecode A and channel for NEXA, channel for SARTANO. + $device_cfg[$i][1] = $inrad[1]; # Housecode A and channel for NEXA, WAVEMAN, channel for SARTANO. $device_cfg[$i][10] = $inrad[2]; # Rule valid days [[oe]1234567] $device_cfg[$i][22] = 1; # Initial state set to on (1) so that they will be switched off at startup @@ -423,7 +423,7 @@ sub read_config if ($device_cfg[$i][0] eq "SARTANO") { $device_cfg[$i][2] = ""; } - elsif ($device_cfg[$i][0] eq "NEXA") { + elsif ($device_cfg[$i][0] eq "NEXA" || $device_cfg[$i][0] eq "WAVEMAN") { # Put the housecode and channel in the respective fields. (my $house_code,my $channel) = $device_cfg[$i][1] =~ /^([A-P])(\d{1,2})$/; if (!$house_code || !$channel || ($channel < 1) || ($channel > 16)) { @@ -433,7 +433,7 @@ sub read_config $device_cfg[$i][2] = $channel; } else { - die("$PROGRAM_NAME: Unsupported protcol: $device_cfg[$i][0]. Only NEXA or SARTANO allowed.\n"); + die("$PROGRAM_NAME: Unsupported protcol: $device_cfg[$i][0]. Only NEXA, WAVEMAN or SARTANO allowed.\n"); } diff --git a/tellstickd/tellstickd.conf b/tellstickd/tellstickd.conf index 081194e7..a62e9de8 100644 --- a/tellstickd/tellstickd.conf +++ b/tellstickd/tellstickd.conf @@ -44,7 +44,7 @@ SARTANO 0000000000 12345 06:10-06:20 22:00-23:00 10 15 # This device will be turned on between 07:34 and 07:48, turned off between 23:00 and 23:15 (every day of the week). # It will be turned off exactly on sunrise and off exactly on sunset. -NEXA P2 1234567 07:34-07:48 23:00-23:15 0 0 +WAVEMAN P2 1234567 07:34-07:48 23:00-23:15 0 0 # This device will be turned on 07:00 off between 20:00 and 20:30 and will be on daytime on sundays. NEXA P3 7 07:00 20:00-20:30 From e8c484a9c41f851a74774159047ea3045b747d27 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 2 Apr 2008 21:22:21 +0000 Subject: [PATCH 0089/2215] bugfix for daylight saving time --- .../examples/tellstickController.conf | 2 +- tellstickcontroller/tellstickController | 26 ++++++++++--------- tellstickcontroller/tellstickController.conf | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/tellstickcontroller/examples/tellstickController.conf b/tellstickcontroller/examples/tellstickController.conf index 3af811c3..a6910f2c 100644 --- a/tellstickcontroller/examples/tellstickController.conf +++ b/tellstickcontroller/examples/tellstickController.conf @@ -3,7 +3,7 @@ # Configuration file for tellstickController # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version: 1.3.1 +# Version: 1.3.2 # ################################################################################ # diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index 82dd6027..8f2b64ce 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -4,7 +4,7 @@ # tellstickController program # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version 1.3.1 +# Version 1.3.2 # ###################################################################### # @@ -518,7 +518,7 @@ sub load_device_rules () { sub get_rule_datetime($$$$) { my ($rule, $now, $sunrise, $sunset) = @_; - #println "Rule='$rule'" if ($option{"verbose"}); +# println "Rule='$rule'" if ($option{"verbose"}); my ($date, $time) = split(/\//, $rule); if (not defined($time)) { @@ -591,7 +591,7 @@ sub get_rule_datetime($$$$) { my $op = ""; my $rest = ""; my $mins = 0; - #println "rule='$time'"; +# println "rule='$time'"; while ($time ne "") { $op = $lastOp; @@ -626,13 +626,13 @@ sub get_rule_datetime($$$$) { $expr = ""; } - #println "expr='$expr', op='$op', rest='$rest'"; +# println "expr='$expr', op='$op', rest='$rest'"; if ($op eq "+") { $mins += $expr; } elsif ($op eq "-") { $mins -= $expr; } - #println "mins='$mins'"; +# println "mins='$mins'"; } if ($mins <= 0) { $mins = $mins % (24*60); @@ -645,10 +645,12 @@ sub get_rule_datetime($$$$) { $hours = int $mins/60; $minutes = int $mins%60; $time = DateTime->now(time_zone => $cfg_set{"timezone"}); - $time->set(hour => $hours, minute => $minutes, second => 0); - $time->add(days => $days); - #println "days='$days', hours='$hours', minutes='$minutes'"; - #println "time='$time'"; + $time->set(hour => 0, minute => 0, second => 0); + $time->set_time_zone("UTC"); + $time->add(hours => $hours+24*$days, minutes => $minutes); + $time->set_time_zone($cfg_set{"timezone"}); + println "days='$days', hours='$hours', minutes='$minutes'"; + println "time='$time'"; } else { $time = undef; } @@ -780,7 +782,7 @@ sub daemon_loop() { while ($option{"daemon"}) { my $now = get_datetime_now(); my $next_day = get_datetime_now(); - $next_day->add( days => 1 ); + $next_day->add( hours => 24 ); $next_day->set( hour => 0, minute => 0, second => 0 ); println "Next reload of device rules = $next_day" if ($option{"verbose"}); @@ -793,7 +795,7 @@ sub daemon_loop() { $now = get_datetime_now(); if ($now > $next_day) { load_device_rules(); - $next_day->add( days => 1 ); + $next_day->add( hours => 24 ); } check_device_rules($now); sleep($wait_time); @@ -930,7 +932,7 @@ __DATA__ #- #- LICENSE #- Copyright (C) 2008 Rickard Andersson -#- Version 1.3.1 +#- Version 1.3.2 #- This program comes with ABSOLUTELY NO WARRANTY. #- This is free software, and you are welcome to redistribute it #- under certain conditions; See license file for details. diff --git a/tellstickcontroller/tellstickController.conf b/tellstickcontroller/tellstickController.conf index 18773089..452bb59e 100644 --- a/tellstickcontroller/tellstickController.conf +++ b/tellstickcontroller/tellstickController.conf @@ -3,7 +3,7 @@ # Configuration file for tellstickController # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version: 1.3.1 +# Version: 1.3.2 # ################################################################################ # From 157f785176930f9493b4714ada083f846e776f55 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Sun, 18 May 2008 07:18:07 +0000 Subject: [PATCH 0090/2215] Fixed a bug regarding rules extending over midnight. They didn't work properly before (lamps shut off at 00:00), now they should. --- tellstickd/tellstickd | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 72129b67..e2d93183 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -45,7 +45,7 @@ my $dayOfWeek; my $dayOfMonth; my $PROGRAM_NAME = "tellstickd"; -my $VERSION = "0.6.1"; +my $VERSION = "0.6.2"; # Structure of the configurations to be read; # $device_cfg[$i][0]; # Protocol, only NEXA, WAVEMAN and SARTANO supported so far by rfcmd @@ -134,11 +134,15 @@ sub is_inbetween_times # If we pass midnight, the following has to be checked/done if ($time2 <= $time1) { - $time2 += 2400; + if ($curr_time >= $time1 && $curr_time < 2400 || $curr_time >= 0000 && $curr_time < $time2) { + return $YES; + } } - - if ($curr_time >= $time1 && $curr_time < $time2) { - return $YES; + # The following applies to the most common rules within a day. + else { + if ($curr_time >= $time1 && $curr_time < $time2) { + return $YES; + } } return $NO; From 98fe59e4dc51456a32ee7aaa691dbf32abb2d9e7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 20 May 2008 10:05:25 +0000 Subject: [PATCH 0091/2215] Fixed so Ikea-devices works under Linux --- driver/TellUsbD101/DeviceIkea.cpp | 25 ++++++++++++++++++++++--- driver/TellUsbD101/TellUsbD101.h | 1 - 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/driver/TellUsbD101/DeviceIkea.cpp index 26e760bc..f80ef8e1 100644 --- a/driver/TellUsbD101/DeviceIkea.cpp +++ b/driver/TellUsbD101/DeviceIkea.cpp @@ -14,9 +14,28 @@ using namespace std; DeviceIkea::DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle) :Device() { -// intSystem = intNewSystem; -// intUnits = intNewUnits; -// intFadeStyle = intNewFadeStyle; + if (strSystem != NULL && strlen(strSystem) > 0) { + intSystem = atoi(strSystem) - 1; + } else { + intSystem = 0; + } + if (strUnits != NULL && strlen(strUnits) > 0) { + intUnits = 0; //Start without any units + + char *strTemp = strtok(strUnits, ","); + do { + int intUnit = atoi(strTemp); + if (intUnit == 10) { + intUnit = 0; + } + intUnits = intUnits | ( 1<<(9-intUnit) ); + } while ( (strTemp = strtok(NULL, ",")) != NULL ); + } + if (strUnits != NULL && strlen(strUnits) > 0 && strcasecmp(strFadeStyle, "true") == 0) { + intFadeStyle = 1; + } else { + intFadeStyle = 0; + } } /* diff --git a/driver/TellUsbD101/TellUsbD101.h b/driver/TellUsbD101/TellUsbD101.h index 162d039d..a5e8c016 100644 --- a/driver/TellUsbD101/TellUsbD101.h +++ b/driver/TellUsbD101/TellUsbD101.h @@ -21,7 +21,6 @@ #define TELLSTICK_API #endif - extern "C" { TELLSTICK_API bool WINAPI devTurnOn(int intDeviceId); TELLSTICK_API bool WINAPI devTurnOff(int intDeviceId); From 6422b4c6061ac83418b825326b7292d2ca1d89dc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 15 Jun 2008 12:20:25 +0000 Subject: [PATCH 0092/2215] Fixed so Sartano-devices works under Linux --- driver/TellUsbD101/DeviceSartano.cpp | 43 +++++++++------------------- driver/TellUsbD101/DeviceSartano.h | 6 ++-- 2 files changed, 15 insertions(+), 34 deletions(-) diff --git a/driver/TellUsbD101/DeviceSartano.cpp b/driver/TellUsbD101/DeviceSartano.cpp index 59260418..a78c1031 100644 --- a/driver/TellUsbD101/DeviceSartano.cpp +++ b/driver/TellUsbD101/DeviceSartano.cpp @@ -13,15 +13,12 @@ using namespace std; DeviceSartano::DeviceSartano(char *strNewCode) :Device() { -// intSystem = intNewSystem; -// intCode = intNewCode; + strCode = strNewCode; } DeviceSartano::~DeviceSartano(void) { - intSystem = -1; - intCode = -1; } @@ -31,14 +28,12 @@ DeviceSartano::~DeviceSartano(void) void DeviceSartano::turnOn(void){ try{ - string strSystem = getStringCode(intSystem); - string strCode = getStringCode(intCode); - strSystem.append(strCode); + string strCode = getStringCode(); - strSystem.insert(0, "S"); - strSystem.append("$k$k$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time + strCode.insert(0, "S"); + strCode.append("$k$k$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strSystem.c_str()); + char* strMessage = const_cast(strCode.c_str()); Device::send(strMessage); } @@ -53,14 +48,12 @@ void DeviceSartano::turnOn(void){ void DeviceSartano::turnOff(void){ try{ - string strSystem = getStringCode(intSystem); - string strCode = getStringCode(intCode); - strSystem.append(strCode); + string strCode = getStringCode(); - strSystem.insert(0, "S"); - strSystem.append("$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time + strCode.insert(0, "S"); + strCode.append("$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strSystem.c_str()); + char* strMessage = const_cast(strCode.c_str()); Device::send(strMessage); } @@ -79,32 +72,22 @@ int DeviceSartano::methods(char* strModel){ /* * Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed */ -string DeviceSartano::getStringCode(int intToConvert){ +string DeviceSartano::getStringCode(void){ - string strReturn = ""; + string strReturn = strCode; try{ - bitset<5> bs ((long)intToConvert); - - strReturn = bs.to_string(); - int intPos = (int)strReturn.find("0"); while (intPos < string::npos){ - strReturn.replace(intPos, 1, "$k"); + strReturn.replace(intPos, 1, "$kk$"); intPos = (int)strReturn.find("0", intPos + 1); } intPos = (int)strReturn.find("1"); while (intPos < string::npos){ - strReturn.replace(intPos, 1, "k$"); + strReturn.replace(intPos, 1, "$k$k"); intPos = (int)strReturn.find("1", intPos + 1); } - - intPos = 0; - while (intPos < (int)strReturn.length()){ - strReturn.insert(intPos, "$k"); - intPos = intPos + 4; - } } catch(...){ throw; diff --git a/driver/TellUsbD101/DeviceSartano.h b/driver/TellUsbD101/DeviceSartano.h index 29e0299b..13d4dd7a 100644 --- a/driver/TellUsbD101/DeviceSartano.h +++ b/driver/TellUsbD101/DeviceSartano.h @@ -14,8 +14,6 @@ public: ~DeviceSartano(void); protected: - std::string getStringCode(int); - - int intSystem; - int intCode; + std::string getStringCode(void); + std::string strCode; }; From a06b9c73684fb05165c4e0f3d4113a99509a0958 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 15 Jun 2008 13:55:28 +0000 Subject: [PATCH 0093/2215] Fixed so Waveman-devices work under Linux --- driver/TellUsbD101/DeviceWaveman.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/driver/TellUsbD101/DeviceWaveman.cpp b/driver/TellUsbD101/DeviceWaveman.cpp index 69227080..38376492 100644 --- a/driver/TellUsbD101/DeviceWaveman.cpp +++ b/driver/TellUsbD101/DeviceWaveman.cpp @@ -21,10 +21,10 @@ DeviceWaveman::DeviceWaveman(char *strNewHouse, char *strNewCode) void DeviceWaveman::turnOff(void){ try{ - string strCode = getStringCode(intCode); - string strHouse = getStringCode(intHouse); - - strCode.append(strHouse); + string strCode = getStringCode(intHouse); + string strUnit = getStringCode(intCode); + strCode.append(strUnit); + strCode.insert(0, "S"); strCode.append("$k$k$k$k$k$k$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time From 4ce2af5315e45ed7c6361f073bdd07740c433a4b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 17 Jun 2008 21:24:11 +0000 Subject: [PATCH 0094/2215] Updated CMakeList.txt in the driver and added one to tdtool --- driver/TellUsbD101/CMakeLists.txt | 15 +++++++++++++++ tdtool/CMakeLists.txt | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tdtool/CMakeLists.txt diff --git a/driver/TellUsbD101/CMakeLists.txt b/driver/TellUsbD101/CMakeLists.txt index e14f88c1..6cc167d1 100644 --- a/driver/TellUsbD101/CMakeLists.txt +++ b/driver/TellUsbD101/CMakeLists.txt @@ -28,3 +28,18 @@ INSTALL(TARGETS tellusbd101 LIBRARY DESTINATION lib ) +INSTALL(FILES + TellUsbD101.h + DESTINATION include + ) + +SET(SYSCONF_INSTALL_DIR + "/etc" + CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" + FORCE + ) + +INSTALL(FILES + tellstick.conf + DESTINATION ${SYSCONF_INSTALL_DIR} + ) diff --git a/tdtool/CMakeLists.txt b/tdtool/CMakeLists.txt new file mode 100644 index 00000000..6b6cb203 --- /dev/null +++ b/tdtool/CMakeLists.txt @@ -0,0 +1,20 @@ +PROJECT(tdtool) + +SET(tdtool_SRCS + main.cpp +) + +ADD_EXECUTABLE(tdtool + ${tdtool_SRCS} +) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/driver +) + +TARGET_LINK_LIBRARIES(tdtool + tellusbd101 +) + +INSTALL(TARGETS tdtool RUNTIME DESTINATION bin) From a5b6430a14834e8d96b9f6a09e554bee4c6dc53c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 17 Jun 2008 21:25:13 +0000 Subject: [PATCH 0095/2215] Removed the makefile since it is now depricated by cmake --- tdtool/Makefile | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 tdtool/Makefile diff --git a/tdtool/Makefile b/tdtool/Makefile deleted file mode 100644 index 04d13026..00000000 --- a/tdtool/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -CC=g++ -CFLAGS=-Wall -FILES=main.cpp -LIBS=-L. -ltellusbd101 - -APP = tdtool - -all: $(APP) - -$(APP): main.cpp - $(CC) -o $(APP) $(CFLAGS) $(LIBS) $(FILES) - -clean: - rm -f *.o ; rm $(APP) From 9b2c653fcd2dc387fef11231cfa4df8ab1c19dcf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 22 Jun 2008 10:48:17 +0000 Subject: [PATCH 0096/2215] rfcmd v0.3 with support for IKEA. Thanks to Gudmund Berggren! --- rfcmd/rfcmd.c | 281 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 243 insertions(+), 38 deletions(-) diff --git a/rfcmd/rfcmd.c b/rfcmd/rfcmd.c index c0ceeb5d..aaf80032 100644 --- a/rfcmd/rfcmd.c +++ b/rfcmd/rfcmd.c @@ -2,14 +2,38 @@ ** rfcmd.c *********************************************************** **************************************************************************** * - * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick + * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick USB interface * * Copyright (C) 2007 Tord Andersson * * License: GPL v. 2 * - */ + * Authors: + * Tord Andersson + * Micke Prag + * Gudmund Berggren + */ + +/******************************************************************************* + * Modifications from rfcmd.c ver 0.2 done by Gudmund + * Added support for IKEA + * Note: + * 1. System code + * 2. Level 0 == Off (For dimmers and non dimmers) + * Level 1== 10%. (for dimmers) + * .... + * Level 9 == 90 % (for dimmers) + * Level 10 == 100 % (or ON for non dimmers) + * 3. Command line syntax: + * /usr/local/bin/rfcmd /dev/ttyUSB0 IKEA 0 1 10 1" + * Arg 1: device + * Arg 2: Protocoll + * Arg 3: System code + * Arg 4: Device code + * Arg 5: Level (0=off, 1 = 10%, 2=20%,...9=90%, 10=100%) + * Arg 6: DimStyle (0=instant change, 1=gradually change) + ******************************************************************************/ #include #include @@ -19,14 +43,17 @@ #include #define PROG_NAME "rfcmd" -#define PROG_VERSION "0.2" +#define PROG_VERSION "0.3" /* #define RFCMD_DEBUG */ /* Local function declarations */ -int createNexaString(const char * pHouseStr, const char * pChannelStr, - const char * pOn_offStr, char * pTxStr, int waveman); -int createSartanoString(const char * pChannelStr, const char * pOn_offStr, - char * pTxStr); +int createNexaString(const char * pHouseStr, const char * pChannelStr, + const char * pOn_offStr, char * pTxStr, int waveman); +int createSartanoString(const char * pChannelStr, const char * pOn_offStr, + char * pTxStr); +int createIkeaString(const char * pSystemStr, const char * pChannelStr, + const char * pLevelStr, const char *pDimStyle, + char * pStrReturn); void printUsage(void); @@ -34,13 +61,10 @@ int main( int argc, char **argv ) { struct termios tio; int fd = -1; - char txStr[250]; - - + char txStr[100]; if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) { - if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) { printUsage(); @@ -58,7 +82,6 @@ int main( int argc, char **argv ) } else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) { - if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) { printUsage(); @@ -66,13 +89,22 @@ int main( int argc, char **argv ) } /* else - a send cmd string was created */ } + else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) + { + // System, Channel, Level, DimStyle, TXString + if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) + { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ + } else /* protocol or parameters not recognized */ { printUsage(); exit(1); } - #ifdef RFCMD_DEBUG printf("txStr: %s\n", txStr); #endif @@ -83,28 +115,29 @@ int main( int argc, char **argv ) exit(1); } - if(strlen(txStr) > 0) { /* adjust serial port parameters */ bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ - tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ + tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ tio.c_iflag = IGNPAR; tio.c_oflag = 0; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&tio); write(fd, txStr, strlen(txStr)); - sleep(1); /* one second sleep to avoid device 'choking' */ + + sleep(1); /* one second sleep to avoid device 'choking' */ + close(fd); /* Modified : Close fd to make a clean exit */ } exit(0); } -int createNexaString(const char * pHouseStr, const char * pChannelStr, - const char * pOn_offStr, char * pTxStr, int waveman) +int createNexaString(const char * pHouseStr, const char * pChannelStr, + const char * pOn_offStr, char * pTxStr, int waveman) { - * pTxStr = '\0'; /* Make sure tx string is empty */ + * pTxStr = '\0'; /* Make sure tx string is empty */ int houseCode; int channelCode; int on_offCode; @@ -130,18 +163,18 @@ int createNexaString(const char * pHouseStr, const char * pChannelStr, } else { - /* b0..b11 txCode where 'X' will be represented by 1 for simplicity. - b0 will be sent first */ + /* b0..b11 txCode where 'X' will be represented by 1 for simplicity. + b0 will be sent first */ txCode = houseCode; txCode |= (channelCode << 4); if (waveman && on_offCode == 0) { } else { txCode |= (unknownCode << 8); - txCode |= (on_offCode << 11); + txCode |= (on_offCode << 11); } - + /* convert to send cmd string */ - strcat(pTxStr,"S"); + strcat(pTxStr,"S"); for(bit=0;bit<12;bit++) { if((bitmask & txCode) == 0) @@ -158,7 +191,7 @@ int createNexaString(const char * pHouseStr, const char * pChannelStr, bitmask = bitmask<<1; } /* add stop/sync bit and command termination char '+'*/ - strcat(pTxStr," }+"); + strcat(pTxStr," }+"); /* strcat(pTxStr,"$}+"); */ } @@ -169,10 +202,10 @@ int createNexaString(const char * pHouseStr, const char * pChannelStr, return strlen(pTxStr); } -int createSartanoString(const char * pChannelStr, const char * pOn_offStr, - char * pTxStr) +int createSartanoString(const char * pChannelStr, const char * pOn_offStr, + char * pTxStr) { - * pTxStr = '\0'; /* Make sure tx string is empty */ + * pTxStr = '\0'; /* Make sure tx string is empty */ int on_offCode; int bit; @@ -190,7 +223,7 @@ int createSartanoString(const char * pChannelStr, const char * pOn_offStr, } else { - strcat(pTxStr,"S"); + strcat(pTxStr,"S"); for(bit=0;bit<=9;bit++) { if(strncmp(pChannelStr+bit, "1", 1) == 0) //If it is a "1" @@ -206,9 +239,9 @@ int createSartanoString(const char * pChannelStr, const char * pOn_offStr, strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code else strcat(pTxStr,"$kk$$k$k"); //the "turn off"-code - + /* add stop/sync bit and command termination char '+'*/ - strcat(pTxStr,"$k+"); + strcat(pTxStr,"$k+"); } #ifdef RFCMD_DEBUG @@ -216,18 +249,190 @@ int createSartanoString(const char * pChannelStr, const char * pOn_offStr, #endif return strlen(pTxStr); - + } +int createIkeaString( const char * pSystemStr, const char * pChannelStr, const char * pLevelStr, const char *pDimStyle, char * pStrReturn) +{ + *pStrReturn = '\0'; /* Make sure tx string is empty */ + + const char STARTCODE[] = "STTTTTTª"; + const char TT[] = "TT"; + const char A[] = "ª"; + int systemCode = atoi(pSystemStr) - 1; /* System 1..16 */ + int channelCode = atoi(pChannelStr); /* Channel 1..10 */ + int Level = atoi(pLevelStr); /* off,10,20,..,90,on */ + int DimStyle = atoi(pDimStyle); + int intCode = 0; + int checksum1 = 0; + int checksum2 = 0; + int intFade ; + int i ; + int rawChannelCode = 0; + + /* check converted parameters for validity */ + if ( (channelCode <= 0) || (channelCode > 10) || + (systemCode < 0) || (systemCode > 15) || + (Level < 0) || (Level > 10) || + (DimStyle < 0) || (DimStyle > 1)) + { + return 0; + } + + if (channelCode == 10) + { + channelCode = 0; + } + rawChannelCode = (1<<(9-channelCode)); + + strcat(pStrReturn, STARTCODE ) ; //Startcode, always like this; + intCode = (systemCode << 10) | rawChannelCode; + + for ( i = 13; i >= 0; --i) + { + if ((intCode>>i) & 1) + { + strcat(pStrReturn, TT ); + if (i % 2 == 0) + { + checksum2++; + } + else + { + checksum1++; + } + } + else + { + strcat(pStrReturn,A); + } + } + + if (checksum1 %2 == 0) + { + strcat(pStrReturn, TT ); + } + else + { + strcat(pStrReturn, A) ; //1st checksum + } + + if (checksum2 %2 == 0) + { + strcat(pStrReturn, TT ); + } + else + { + strcat(pStrReturn, A ) ; //2nd checksum + } + + if (DimStyle == 1) + { + intFade = 11 << 4; //Smooth + } + else + { + intFade = 1 << 4; //Instant + } + + switch ( Level ) + { + case 0 : + intCode = (10 | intFade) ; //Concat level and fade + break; + case 1 : + intCode = (1 | intFade) ; //Concat level and fade + break; + case 2 : + intCode = (2 | intFade) ; //Concat level and fade + break; + case 3 : + intCode = (3 | intFade) ; //Concat level and fade + break; + case 4 : + intCode = (4 | intFade) ; //Concat level and fade + break; + case 5 : + intCode = (5 | intFade) ; //Concat level and fade + break; + case 6 : + intCode = (6 | intFade) ; //Concat level and fade + break; + case 7 : + intCode = (7 | intFade) ; //Concat level and fade + break; + case 8 : + intCode = (8 | intFade) ; //Concat level and fade + break; + case 9 : + intCode = (9 | intFade) ; //Concat level and fade + break; + case 10 : + default : + intCode = (0 | intFade) ; //Concat level and fade + break; + } + + checksum1 = 0; + checksum2 = 0; + + for (i = 0; i < 6; ++i) + { + if ((intCode>>i) & 1) + { + strcat(pStrReturn, TT); + + if (i % 2 == 0) + { + checksum1++; + } + else + { + checksum2++; + } + } + else + { + strcat(pStrReturn, A ); + } + } + + if (checksum1 %2 == 0) + { + strcat(pStrReturn, TT); + } + else + { + strcat(pStrReturn, A ) ; //2nd checksum + } + + if (checksum2 %2 == 0) + { + strcat(pStrReturn, TT ); + } + else + { + strcat(pStrReturn, A ) ; //2nd checksum + } + + strcat(pStrReturn, "+"); + + return strlen(pStrReturn); +} + + void printUsage(void) { - printf("%s %s - Send RF remote commands\n", PROG_NAME, PROG_VERSION); + printf("%s v%s - Send RF remote commands\n", PROG_NAME, PROG_VERSION); printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n"); printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); - printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN\n" ); - printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN: \n"); - printf("\t\t HOUSE_CODE: A..P\n\t\t CHANNEL: 1..16\n\t\t OFF_ON: 0..1\n" ); - printf("\t PROTOCOL ARGUMENTS - SARTANO: \n"); - printf("\t\t CHANNEL: 0000000000..1111111111\n\t\t OFF_ON: 0..1\n" ); + printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA\n" ); + printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n"); + printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" ); + printf("\t PROTOCOL ARGUMENTS - SARTANO:\n"); + printf("\t\tCHANNEL: 0000000000..1111111111\n\t\tOFF_ON: 0..1\n" ); + printf("\t PROTOCOL ARGUMENTS - IKEA:\n"); + printf("\t\tSYSTEM: 1..16\n\t\tDEVICE: 1..10\n"); + printf("\t\tDIM_LEVEL: 0..10\n\t\tDIM_STYLE: 0..1\n" ); printf("Copyright(C) Tord Andersson 2007\r\n"); } From 3ea649d16ed94ec53afca1c74e041d72503df2bd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Jul 2008 08:07:43 +0000 Subject: [PATCH 0097/2215] Moved driver and tdtool to telldus-core --- rfcmd/CMakeLists.txt | 4 +++- telldus-core/CMakeLists.txt | 7 +++++++ {driver => telldus-core/driver}/CMakeLists.txt | 0 {driver => telldus-core/driver}/TellUsbD101.sln | 0 {driver => telldus-core/driver}/TellUsbD101/CMakeLists.txt | 0 {driver => telldus-core/driver}/TellUsbD101/Device.cpp | 0 {driver => telldus-core/driver}/TellUsbD101/Device.h | 0 {driver => telldus-core/driver}/TellUsbD101/DeviceIkea.cpp | 0 {driver => telldus-core/driver}/TellUsbD101/DeviceIkea.h | 0 {driver => telldus-core/driver}/TellUsbD101/DeviceNexa.cpp | 0 {driver => telldus-core/driver}/TellUsbD101/DeviceNexa.h | 0 .../driver}/TellUsbD101/DeviceSartano.cpp | 0 .../driver}/TellUsbD101/DeviceSartano.h | 0 .../driver}/TellUsbD101/DeviceWaveman.cpp | 0 .../driver}/TellUsbD101/DeviceWaveman.h | 0 {driver => telldus-core/driver}/TellUsbD101/Resource.h | 0 .../driver}/TellUsbD101/TellUsbD101.cpp | 0 .../driver}/TellUsbD101/TellUsbD101.def | 0 {driver => telldus-core/driver}/TellUsbD101/TellUsbD101.h | 0 .../driver}/TellUsbD101/TellUsbD101.vcproj | 0 .../driver}/TellUsbD101/linux/Device.cpp | 0 .../driver}/TellUsbD101/settings/TelldusSettings.cpp | 0 .../driver}/TellUsbD101/settings/TelldusSettings.h | 0 .../TellUsbD101/settings/TelldusSettingsConfuse.cpp | 0 .../TellUsbD101/settings/TelldusSettingsWinRegistry.cpp | 0 {driver => telldus-core/driver}/TellUsbD101/stdafx.cpp | 0 {driver => telldus-core/driver}/TellUsbD101/stdafx.h | 0 {driver => telldus-core/driver}/TellUsbD101/win/Device.cpp | 0 {driver => telldus-core/driver}/TellUsbD101/win/FTD2XX.H | 0 {tdtool => telldus-core/tdtool}/CMakeLists.txt | 0 {tdtool => telldus-core/tdtool}/main.cpp | 0 31 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 telldus-core/CMakeLists.txt rename {driver => telldus-core/driver}/CMakeLists.txt (100%) rename {driver => telldus-core/driver}/TellUsbD101.sln (100%) rename {driver => telldus-core/driver}/TellUsbD101/CMakeLists.txt (100%) rename {driver => telldus-core/driver}/TellUsbD101/Device.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/Device.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceIkea.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceIkea.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceNexa.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceNexa.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceSartano.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceSartano.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceWaveman.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/DeviceWaveman.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/Resource.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/TellUsbD101.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/TellUsbD101.def (100%) rename {driver => telldus-core/driver}/TellUsbD101/TellUsbD101.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/TellUsbD101.vcproj (100%) rename {driver => telldus-core/driver}/TellUsbD101/linux/Device.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/settings/TelldusSettings.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/settings/TelldusSettings.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/settings/TelldusSettingsConfuse.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/stdafx.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/stdafx.h (100%) rename {driver => telldus-core/driver}/TellUsbD101/win/Device.cpp (100%) rename {driver => telldus-core/driver}/TellUsbD101/win/FTD2XX.H (100%) rename {tdtool => telldus-core/tdtool}/CMakeLists.txt (100%) rename {tdtool => telldus-core/tdtool}/main.cpp (100%) diff --git a/rfcmd/CMakeLists.txt b/rfcmd/CMakeLists.txt index c9b2d9af..bed9007f 100644 --- a/rfcmd/CMakeLists.txt +++ b/rfcmd/CMakeLists.txt @@ -1,3 +1,5 @@ +cmake_minimum_required(VERSION 2.4) + PROJECT(rfcmd) SET(rfcmd_SRCS @@ -16,4 +18,4 @@ ADD_EXECUTABLE(rfcmd ${rfcmd_SRCS} ) -INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) \ No newline at end of file +INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt new file mode 100644 index 00000000..b8b15e37 --- /dev/null +++ b/telldus-core/CMakeLists.txt @@ -0,0 +1,7 @@ +PROJECT( telldus-core ) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) + +ADD_SUBDIRECTORY(driver) +ADD_SUBDIRECTORY(tdtool) + diff --git a/driver/CMakeLists.txt b/telldus-core/driver/CMakeLists.txt similarity index 100% rename from driver/CMakeLists.txt rename to telldus-core/driver/CMakeLists.txt diff --git a/driver/TellUsbD101.sln b/telldus-core/driver/TellUsbD101.sln similarity index 100% rename from driver/TellUsbD101.sln rename to telldus-core/driver/TellUsbD101.sln diff --git a/driver/TellUsbD101/CMakeLists.txt b/telldus-core/driver/TellUsbD101/CMakeLists.txt similarity index 100% rename from driver/TellUsbD101/CMakeLists.txt rename to telldus-core/driver/TellUsbD101/CMakeLists.txt diff --git a/driver/TellUsbD101/Device.cpp b/telldus-core/driver/TellUsbD101/Device.cpp similarity index 100% rename from driver/TellUsbD101/Device.cpp rename to telldus-core/driver/TellUsbD101/Device.cpp diff --git a/driver/TellUsbD101/Device.h b/telldus-core/driver/TellUsbD101/Device.h similarity index 100% rename from driver/TellUsbD101/Device.h rename to telldus-core/driver/TellUsbD101/Device.h diff --git a/driver/TellUsbD101/DeviceIkea.cpp b/telldus-core/driver/TellUsbD101/DeviceIkea.cpp similarity index 100% rename from driver/TellUsbD101/DeviceIkea.cpp rename to telldus-core/driver/TellUsbD101/DeviceIkea.cpp diff --git a/driver/TellUsbD101/DeviceIkea.h b/telldus-core/driver/TellUsbD101/DeviceIkea.h similarity index 100% rename from driver/TellUsbD101/DeviceIkea.h rename to telldus-core/driver/TellUsbD101/DeviceIkea.h diff --git a/driver/TellUsbD101/DeviceNexa.cpp b/telldus-core/driver/TellUsbD101/DeviceNexa.cpp similarity index 100% rename from driver/TellUsbD101/DeviceNexa.cpp rename to telldus-core/driver/TellUsbD101/DeviceNexa.cpp diff --git a/driver/TellUsbD101/DeviceNexa.h b/telldus-core/driver/TellUsbD101/DeviceNexa.h similarity index 100% rename from driver/TellUsbD101/DeviceNexa.h rename to telldus-core/driver/TellUsbD101/DeviceNexa.h diff --git a/driver/TellUsbD101/DeviceSartano.cpp b/telldus-core/driver/TellUsbD101/DeviceSartano.cpp similarity index 100% rename from driver/TellUsbD101/DeviceSartano.cpp rename to telldus-core/driver/TellUsbD101/DeviceSartano.cpp diff --git a/driver/TellUsbD101/DeviceSartano.h b/telldus-core/driver/TellUsbD101/DeviceSartano.h similarity index 100% rename from driver/TellUsbD101/DeviceSartano.h rename to telldus-core/driver/TellUsbD101/DeviceSartano.h diff --git a/driver/TellUsbD101/DeviceWaveman.cpp b/telldus-core/driver/TellUsbD101/DeviceWaveman.cpp similarity index 100% rename from driver/TellUsbD101/DeviceWaveman.cpp rename to telldus-core/driver/TellUsbD101/DeviceWaveman.cpp diff --git a/driver/TellUsbD101/DeviceWaveman.h b/telldus-core/driver/TellUsbD101/DeviceWaveman.h similarity index 100% rename from driver/TellUsbD101/DeviceWaveman.h rename to telldus-core/driver/TellUsbD101/DeviceWaveman.h diff --git a/driver/TellUsbD101/Resource.h b/telldus-core/driver/TellUsbD101/Resource.h similarity index 100% rename from driver/TellUsbD101/Resource.h rename to telldus-core/driver/TellUsbD101/Resource.h diff --git a/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp similarity index 100% rename from driver/TellUsbD101/TellUsbD101.cpp rename to telldus-core/driver/TellUsbD101/TellUsbD101.cpp diff --git a/driver/TellUsbD101/TellUsbD101.def b/telldus-core/driver/TellUsbD101/TellUsbD101.def similarity index 100% rename from driver/TellUsbD101/TellUsbD101.def rename to telldus-core/driver/TellUsbD101/TellUsbD101.def diff --git a/driver/TellUsbD101/TellUsbD101.h b/telldus-core/driver/TellUsbD101/TellUsbD101.h similarity index 100% rename from driver/TellUsbD101/TellUsbD101.h rename to telldus-core/driver/TellUsbD101/TellUsbD101.h diff --git a/driver/TellUsbD101/TellUsbD101.vcproj b/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj similarity index 100% rename from driver/TellUsbD101/TellUsbD101.vcproj rename to telldus-core/driver/TellUsbD101/TellUsbD101.vcproj diff --git a/driver/TellUsbD101/linux/Device.cpp b/telldus-core/driver/TellUsbD101/linux/Device.cpp similarity index 100% rename from driver/TellUsbD101/linux/Device.cpp rename to telldus-core/driver/TellUsbD101/linux/Device.cpp diff --git a/driver/TellUsbD101/settings/TelldusSettings.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp similarity index 100% rename from driver/TellUsbD101/settings/TelldusSettings.cpp rename to telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp diff --git a/driver/TellUsbD101/settings/TelldusSettings.h b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.h similarity index 100% rename from driver/TellUsbD101/settings/TelldusSettings.h rename to telldus-core/driver/TellUsbD101/settings/TelldusSettings.h diff --git a/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp similarity index 100% rename from driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp rename to telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp diff --git a/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp similarity index 100% rename from driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp rename to telldus-core/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp diff --git a/driver/TellUsbD101/stdafx.cpp b/telldus-core/driver/TellUsbD101/stdafx.cpp similarity index 100% rename from driver/TellUsbD101/stdafx.cpp rename to telldus-core/driver/TellUsbD101/stdafx.cpp diff --git a/driver/TellUsbD101/stdafx.h b/telldus-core/driver/TellUsbD101/stdafx.h similarity index 100% rename from driver/TellUsbD101/stdafx.h rename to telldus-core/driver/TellUsbD101/stdafx.h diff --git a/driver/TellUsbD101/win/Device.cpp b/telldus-core/driver/TellUsbD101/win/Device.cpp similarity index 100% rename from driver/TellUsbD101/win/Device.cpp rename to telldus-core/driver/TellUsbD101/win/Device.cpp diff --git a/driver/TellUsbD101/win/FTD2XX.H b/telldus-core/driver/TellUsbD101/win/FTD2XX.H similarity index 100% rename from driver/TellUsbD101/win/FTD2XX.H rename to telldus-core/driver/TellUsbD101/win/FTD2XX.H diff --git a/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt similarity index 100% rename from tdtool/CMakeLists.txt rename to telldus-core/tdtool/CMakeLists.txt diff --git a/tdtool/main.cpp b/telldus-core/tdtool/main.cpp similarity index 100% rename from tdtool/main.cpp rename to telldus-core/tdtool/main.cpp From a7595ac18bade99b6627987f766792796e354733 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Jul 2008 08:31:07 +0000 Subject: [PATCH 0098/2215] Added 'make install' to rfcmd makefile. Thanks to Hans Winzell --- rfcmd/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rfcmd/Makefile b/rfcmd/Makefile index 77792ecd..63eab51a 100644 --- a/rfcmd/Makefile +++ b/rfcmd/Makefile @@ -9,3 +9,5 @@ all: $(FILES) clean: rm -f $(FILES) *~ core +install: + cp rfcmd /usr/local/bin From 935e97c77d55b603bc728a5144d18a2f88feb67b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Jul 2008 08:32:26 +0000 Subject: [PATCH 0099/2215] Added 'make install' to rfcmd makefile. Thanks to Hans Winzell --- rfcmd/build.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rfcmd/build.sh b/rfcmd/build.sh index b3da439a..fb5100b9 100644 --- a/rfcmd/build.sh +++ b/rfcmd/build.sh @@ -1,5 +1,6 @@ #!/bin/sh -make clean -make -echo rfcmd built! - +set -e +make clean || { echo "Warning: make clean failed"; } +make || { echo "make failed"; exit 1; } +make install || { echo "make install failed"; exit 1; } +echo rfcmd built and installed! From c93df293e20d94a310bbe879246403f5036d02ef Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Jul 2008 09:12:28 +0000 Subject: [PATCH 0100/2215] Fixed 'Policy CMP0003' for CMake 2.6.0 and later --- telldus-core/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index b8b15e37..1d042060 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -2,6 +2,10 @@ PROJECT( telldus-core ) CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + ADD_SUBDIRECTORY(driver) ADD_SUBDIRECTORY(tdtool) From 57e74dd4966c2bb0038ddad8c643dda9dbdec140 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Jul 2008 09:23:13 +0000 Subject: [PATCH 0101/2215] Added #include to a lot of files --- .../driver/TellUsbD101/DeviceIkea.cpp | 6 ++-- .../driver/TellUsbD101/DeviceNexa.cpp | 28 +++++++++---------- .../driver/TellUsbD101/TellUsbD101.cpp | 17 +++++------ .../driver/TellUsbD101/linux/Device.cpp | 7 +++-- .../TellUsbD101/settings/TelldusSettings.cpp | 18 ++++++------ 5 files changed, 39 insertions(+), 37 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/DeviceIkea.cpp b/telldus-core/driver/TellUsbD101/DeviceIkea.cpp index f80ef8e1..6f0a188f 100644 --- a/telldus-core/driver/TellUsbD101/DeviceIkea.cpp +++ b/telldus-core/driver/TellUsbD101/DeviceIkea.cpp @@ -1,10 +1,10 @@ // #include "StdAfx.h" //Needed? #include "DeviceIkea.h" -#include #include #include #include #include +#include using namespace std; @@ -21,7 +21,7 @@ DeviceIkea::DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle) } if (strUnits != NULL && strlen(strUnits) > 0) { intUnits = 0; //Start without any units - + char *strTemp = strtok(strUnits, ","); do { int intUnit = atoi(strTemp); @@ -100,7 +100,7 @@ void DeviceIkea::dim(unsigned char level){ * Convert an integer to byte string where 0 is represented by ª and 1 by TT */ string DeviceIkea::getStringCode(unsigned char level){ - + string strReturn = "STTTTTTª"; //Startcode, always like this; try{ diff --git a/telldus-core/driver/TellUsbD101/DeviceNexa.cpp b/telldus-core/driver/TellUsbD101/DeviceNexa.cpp index bbffaeb0..d8392d5b 100644 --- a/telldus-core/driver/TellUsbD101/DeviceNexa.cpp +++ b/telldus-core/driver/TellUsbD101/DeviceNexa.cpp @@ -1,6 +1,6 @@ // #include "StdAfx.h" #include "DeviceNexa.h" -#include +#include #include #include #include @@ -19,7 +19,7 @@ DeviceNexa::DeviceNexa(char *strNewHouse, char *strNewCode) } else { intHouse = 0; } - + if (strNewCode != NULL && strlen(strNewCode) > 0) { intCode = atoi(strNewCode) - 1; } else { @@ -45,10 +45,10 @@ void DeviceNexa::turnOn(void){ string strCode = getStringCode(intHouse); string strUnit = getStringCode(intCode); strCode.append(strUnit); - + strCode.insert(0, "S"); strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time - + char* strMessage = const_cast(strCode.c_str()); Device::send(strMessage); @@ -62,17 +62,17 @@ void DeviceNexa::turnOn(void){ * Turn off this device */ void DeviceNexa::turnOff(void){ - + try{ string strCode = getStringCode(intHouse); string strUnit = getStringCode(intCode); strCode.append(strUnit); - + strCode.insert(0, "S"); strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - + char* strMessage = const_cast(strCode.c_str()); - + Device::send(strMessage); } catch(...){ @@ -84,16 +84,16 @@ void DeviceNexa::turnOff(void){ * Send a bell */ void DeviceNexa::bell(void){ - + try{ string strCode = getStringCode(intHouse); strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time strCode.insert(0, "S"); strCode.append("$kk$$kk$$kk$$kk$$k+"); //the "bell"-code, keeps it like this, doesn't have to be regenerated each time - + char* strMessage = const_cast(strCode.c_str()); - + Device::send(strMessage); } catch(...){ @@ -105,12 +105,12 @@ void DeviceNexa::bell(void){ * Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed */ string DeviceNexa::getStringCode(int intToConvert){ - + string strReturn = ""; try{ bitset<4> bs ((long)intToConvert); - + strReturn = bs.to_string(); reverse(strReturn.begin(), strReturn.end()); @@ -125,7 +125,7 @@ string DeviceNexa::getStringCode(int intToConvert){ strReturn.replace(intPos, 1, "k$"); intPos = (int)strReturn.find("1", intPos + 1); } - + intPos = 0; while (intPos < (int)strReturn.length()){ strReturn.insert(intPos, "$k"); diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index 110f3617..010f8ded 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -10,6 +10,7 @@ #include #include #include +#include void handleException(std::exception e); using namespace std; @@ -22,13 +23,13 @@ using namespace std; //comment (just copy from the called methods) bool WINAPI devTurnOn(int intDeviceId){ - + try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ dev->turnOn(); - + delete(dev); return true; } @@ -43,13 +44,13 @@ bool WINAPI devTurnOn(int intDeviceId){ } bool WINAPI devTurnOff(int intDeviceId){ - + try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ dev->turnOff(); - + delete(dev); return true; } @@ -64,13 +65,13 @@ bool WINAPI devTurnOff(int intDeviceId){ } bool WINAPI devBell(int intDeviceId){ - + try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ dev->bell(); - + delete(dev); return true; } @@ -85,7 +86,7 @@ bool WINAPI devBell(int intDeviceId){ } bool WINAPI devDim(int intDeviceId, unsigned char level){ - + try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); @@ -225,7 +226,7 @@ bool WINAPI devSetModel(int intDeviceId, const char* strNewModel){ } bool WINAPI devSetArgument(int intDeviceId, const char *strName, const char *strValue){ - + try{ TelldusSettings ts; return ts.setArgument(intDeviceId, strName, strValue); diff --git a/telldus-core/driver/TellUsbD101/linux/Device.cpp b/telldus-core/driver/TellUsbD101/linux/Device.cpp index a0fb3e2b..98e9ca5d 100644 --- a/telldus-core/driver/TellUsbD101/linux/Device.cpp +++ b/telldus-core/driver/TellUsbD101/linux/Device.cpp @@ -2,6 +2,7 @@ #include #include #include +#include /* * Send message to the USB dongle @@ -9,11 +10,11 @@ void Device::send(char* strMessage) { int fd = -1; struct termios tio; - + if( 0 > ( fd = open( strDevice, O_RDWR ) ) ) { return; } - + /* adjust serial port parameters */ bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ @@ -23,7 +24,7 @@ void Device::send(char* strMessage) { tcsetattr(fd,TCSANOW,&tio); write(fd, strMessage, strlen(strMessage)); - + close(fd); } diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp index a106a9c3..2ace6e18 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -3,7 +3,7 @@ #include "../DeviceWaveman.h" #include "../DeviceSartano.h" #include "../DeviceIkea.h" - +#include /* * Get the requested device @@ -12,39 +12,39 @@ Device* TelldusSettings::getDevice(int intDeviceId){ Device* dev = NULL; - + try{ char* vendor = getVendor(intDeviceId); - + //each new brand must be added here if (strcmp(vendor, "Nexa") == 0){ char *strHouse = getArgument(intDeviceId, "nexa_house"); char *strCode = getArgument(intDeviceId, "nexa_unit"); dev = new DeviceNexa(strHouse, strCode); - + } else if (strcmp(vendor, "Waveman") == 0) { char *strHouse = getArgument(intDeviceId, "nexa_house"); char *strCode = getArgument(intDeviceId, "nexa_unit"); dev = new DeviceWaveman(strHouse, strCode); - + } else if (strcmp(vendor, "Sartano") == 0) { char *strCode = getArgument(intDeviceId, "sartano_code"); dev = new DeviceSartano(strCode); - + } else if (strcmp(vendor, "Ikea") == 0) { char *strSystem = getArgument(intDeviceId, "ikea_system"); char *strUnits = getArgument(intDeviceId, "ikea_units"); char *strFade = getArgument(intDeviceId, "ikea_fade"); dev = new DeviceIkea(strSystem, strUnits, strFade); - + } else { return NULL; } - + #ifndef _WINDOWS dev->setDevice( getSetting("deviceNode") ); #endif - + } catch(...){ throw; From 3b46ada09caf41f2dc76a21f5b96716f4e136cfc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Jul 2008 09:25:05 +0000 Subject: [PATCH 0102/2215] Calling tdtool without any parameter shows help, closes #21 --- telldus-core/tdtool/main.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 903f8cde..06421e81 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -3,8 +3,8 @@ #include #include #include "TellUsbD101.h" -#ifdef __MINGW32__ - #define sleep(x) _sleep((x)*1000) +#ifdef __MINGW32__ + #define sleep(x) _sleep((x)*1000) #endif void print_usage( char *name ) { @@ -72,6 +72,11 @@ int main(int argc, char **argv) { 0, 0, 0, 0} }; + if (argc < 2) { + print_usage( argv[0] ); + return -1; + } + while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) switch (optch) { case 'f' : From 3471e05cbcf1636a5d24a4ed3d7c847d3ec5e454 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Jul 2008 09:40:51 +0000 Subject: [PATCH 0103/2215] Enable to turn on and off devices in tdtool by the device-name, closes #23 --- telldus-core/tdtool/main.cpp | 38 +++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 06421e81..ceff6b5d 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "TellUsbD101.h" #ifdef __MINGW32__ #define sleep(x) _sleep((x)*1000) @@ -47,15 +48,34 @@ void list_devices() { } } -void switch_device( bool turnOn, int device ) { +void switch_device( bool turnOn, char *device ) { + int deviceId = atoi(device); + if (deviceId == 0) { //Try to find the id from the name + int intNum = devGetNumberOfDevices(); + int index = 0; + while (index < intNum) { + int id = devGetDeviceId(index); + char *name = devGetName( id ); + if (strcasecmp(name, device) == 0) { + deviceId = id; + break; + } + index++; + } + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + } + if (turnOn) { - char *name = devGetName( device ); - bool ok = devTurnOn( device ); - printf("Turning on device: %i %s - %s\n", device, name, (ok ? "ok" : "failed")); + char *name = devGetName( deviceId ); + bool ok = devTurnOn( deviceId ); + printf("Turning on device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); } else { - char *name = devGetName( device ); - bool ok = devTurnOff( device ); - printf("Turning off device: %i %s - %s\n", device, name, (ok ? "ok" : "failed")); + char *name = devGetName( deviceId ); + bool ok = devTurnOff( deviceId ); + printf("Turning off device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); } sleep(1); } @@ -80,7 +100,7 @@ int main(int argc, char **argv) while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) switch (optch) { case 'f' : - switch_device(false, atoi(&optarg[0])); + switch_device(false, &optarg[0]); break; case 'h' : print_usage( argv[0] ); @@ -89,7 +109,7 @@ int main(int argc, char **argv) list_devices(); break; case 'n' : - switch_device(true, atoi(&optarg[0])); + switch_device(true, &optarg[0]); break; default : print_usage( argv[0] ); From c07eb54f01cc6cd1f414976e50481d15c77344ca Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Jul 2008 16:01:42 +0000 Subject: [PATCH 0104/2215] First version of settings engine for Mac OS X using Core Foundation Preferences. --- ...lldusSettingsCoreFoundationPreferences.cpp | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp new file mode 100644 index 00000000..84829505 --- /dev/null +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp @@ -0,0 +1,143 @@ +// +// C++ Implementation: telldussettingsconfuse +// +// Description: +// +// +// Author: Micke Prag , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "TelldusSettings.h" +#include +#include +#include + +using namespace std; + +class privateVars { +public: + CFStringRef app_ID; +}; + + +/* +* Constructor +*/ +TelldusSettings::TelldusSettings(void) +{ + d = new privateVars(); + d->app_ID = CFSTR( "com.telldus.core" ); +} + +/* +* Destructor +*/ +TelldusSettings::~TelldusSettings(void) +{ +} + +/* +* Return a setting +*/ +char *TelldusSettings::getSetting(const char *strName) { + return ""; +} + +/* +* Return the number of stored devices +*/ +int TelldusSettings::getNumberOfDevices(void) { + CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesAnyUser, kCFPreferencesAnyHost ); + if (!cfarray) return 0; + CFIndex size = CFArrayGetCount( cfarray ); + for (CFIndex k = 0; k < size; ++k) { + //TODO: + } + return 1; +} + +int TelldusSettings::getDeviceId(int intDeviceIndex){ + //TODO: + return intDeviceIndex + 1; +} + +/* +* Add a new device +*/ +int TelldusSettings::addDevice() { + int id = getNextDeviceId(); + setStringSetting( id, "name", "", false ); //Create a empty name so the device has an entry + return id; +} + +/* +* Get next available device id +*/ +int TelldusSettings::getNextDeviceId() { + //TODO: find the highest id used and return this id+1 + int id = getDeviceId( getNumberOfDevices()-1 ); + id++; + return id; +} + +/* +* Remove a device +*/ +bool TelldusSettings::removeDevice(int intDeviceId){ + //TODO: + return false; +} + +//only for debug reasons +void TelldusSettings::debugLog(char* debugstring){ +} + +//only for debug reasons +void TelldusSettings::debugLog(int debugint){ +} + +char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { + CFStringRef cfname = CFStringCreateWithCString( 0, name, 0 ); + + CFStringRef key; + if (parameter) { + key = CFStringCreateWithFormat(0, NULL, CFSTR("device.%d.parameters.%@"), intDeviceId, cfname); + } else { + key = CFStringCreateWithFormat(0, NULL, CFSTR("device.%d.%@"), intDeviceId, cfname); + } + + CFStringRef value; + + value = (CFStringRef)CFPreferencesCopyAppValue(key, d->app_ID); + if (!value) { + return ""; + } + + char *cp = NULL; + CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( value ), kCFStringEncodingUTF8) + 1; + cp = (char *)malloc(size); + CFStringGetCString( value, cp, size, kCFStringEncodingUTF8 ); + cp = (char *)realloc( cp, strlen(cp) + 1); + + CFRelease(value); + return cp; +} + +bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { + CFStringRef cfname = CFStringCreateWithCString( 0, name, 0 ); + CFStringRef cfvalue = CFStringCreateWithCString( 0, value, 0 ); + + CFStringRef key; + if (parameter) { + key = CFStringCreateWithFormat(0, NULL, CFSTR("device.%d.parameters.%@"), intDeviceId, cfname); + } else { + key = CFStringCreateWithFormat(0, NULL, CFSTR("device.%d.%@"), intDeviceId, cfname); + } + + CFPreferencesSetAppValue( key, cfvalue, d->app_ID ); + CFPreferencesAppSynchronize( d->app_ID ); + return false; +} + From 1ca3d00b05b26da23e875d1b7319b7b2c3f83f8f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Jul 2008 18:44:12 +0000 Subject: [PATCH 0105/2215] Adding and altering settings works. Only remove left! --- ...lldusSettingsCoreFoundationPreferences.cpp | 70 ++++++++++++++++--- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp index 84829505..325b2905 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp @@ -49,18 +49,59 @@ char *TelldusSettings::getSetting(const char *strName) { * Return the number of stored devices */ int TelldusSettings::getNumberOfDevices(void) { - CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesAnyUser, kCFPreferencesAnyHost ); + CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost ); if (!cfarray) return 0; CFIndex size = CFArrayGetCount( cfarray ); + int devices = 0; for (CFIndex k = 0; k < size; ++k) { - //TODO: + CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); + if (CFStringHasPrefix( key, CFSTR("device.") ) && + CFStringHasSuffix( key, CFSTR(".name") ) ) { + devices++; + } } - return 1; + return devices; } -int TelldusSettings::getDeviceId(int intDeviceIndex){ - //TODO: - return intDeviceIndex + 1; +int TelldusSettings::getDeviceId(int intDeviceIndex) { + CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost ); + if (!cfarray) return 0; + CFIndex size = CFArrayGetCount( cfarray ); + int index = 0; + int id = 0; + for (CFIndex k = 0; k < size; ++k) { + CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); + if (CFStringHasPrefix( key, CFSTR("device.") ) && + CFStringHasSuffix( key, CFSTR(".name") ) ) { + + if (index == intDeviceIndex) { + CFArrayRef split = CFStringCreateArrayBySeparatingStrings( 0, key, CFSTR(".") ); + if ( !split || CFArrayGetCount( split ) != 3 ) continue; + + // This code crashes! + //CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); + //if (cfid) + // CFNumberGetValue( cfid, kCFNumberIntType, &id); + + CFStringRef cfid = (CFStringRef) CFArrayGetValueAtIndex( split, 1 ); + char *cp = NULL; + CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1; + cp = (char *)malloc(size); + CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); + cp = (char *)realloc( cp, strlen(cp) + 1); + id = atoi(cp); + + + CFRelease(key); + CFRelease(split); + CFRelease(cfid); + break; + } + index++; + } + CFRelease( key ); + } + return id; } /* @@ -69,6 +110,7 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ int TelldusSettings::addDevice() { int id = getNextDeviceId(); setStringSetting( id, "name", "", false ); //Create a empty name so the device has an entry + setStringSetting( id, "model", "", false ); return id; } @@ -76,10 +118,16 @@ int TelldusSettings::addDevice() { * Get next available device id */ int TelldusSettings::getNextDeviceId() { - //TODO: find the highest id used and return this id+1 - int id = getDeviceId( getNumberOfDevices()-1 ); - id++; - return id; + int id = 0, max = 0; + int numberOfDevices = getNumberOfDevices(); + for( int i = 0; i < numberOfDevices; i++) { + id = getDeviceId( i ); + if (id > max) { + max = id; + } + } + max++; + return max; } /* @@ -138,6 +186,6 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const CFPreferencesSetAppValue( key, cfvalue, d->app_ID ); CFPreferencesAppSynchronize( d->app_ID ); - return false; + return true; } From e079018fe03d32c5b03ee21c92227bf4e8df3a84 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Jul 2008 20:02:54 +0000 Subject: [PATCH 0106/2215] Fixed removing of devices on Mac OS X. --- .../TelldusSettingsCoreFoundationPreferences.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp index 325b2905..d856d919 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp @@ -134,8 +134,20 @@ int TelldusSettings::getNextDeviceId() { * Remove a device */ bool TelldusSettings::removeDevice(int intDeviceId){ - //TODO: - return false; + CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("device.%d."), intDeviceId); // The key to search for + + CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost ); + if (!cfarray) return 0; + CFIndex size = CFArrayGetCount( cfarray ); + for (CFIndex k = 0; k < size; ++k) { + CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); + if (CFStringHasPrefix( key, filterKey ) ) { + CFPreferencesSetAppValue( key, NULL, d->app_ID ); //Remove the key + } + } + + CFPreferencesAppSynchronize( d->app_ID ); + return true; } //only for debug reasons From 0495a89b79e2ccca4784dc9adb9ceb9a7126b5e1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Jul 2008 11:53:32 +0000 Subject: [PATCH 0107/2215] Fixed CMakeLists.txt for building on Mac OS X. --- .../driver/TellUsbD101/CMakeLists.txt | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/CMakeLists.txt b/telldus-core/driver/TellUsbD101/CMakeLists.txt index 6cc167d1..50c64d3f 100644 --- a/telldus-core/driver/TellUsbD101/CMakeLists.txt +++ b/telldus-core/driver/TellUsbD101/CMakeLists.txt @@ -7,7 +7,6 @@ SET( tellusbd101_SRCS DeviceSartano.cpp DeviceWaveman.cpp settings/TelldusSettings.cpp - settings/TelldusSettingsConfuse.cpp TellUsbD101.cpp ) @@ -15,14 +14,29 @@ ADD_DEFINITIONS( -DOS_LINUX ) +IF (APPLE) + SET( tellusbd101_SRCS + ${tellusbd101_SRCS} + settings/TelldusSettingsCoreFoundationPreferences.cpp + ) +ELSE () + SET( tellusbd101_SRC + ${tellusbd101_SRCS} + settings/TelldusSettingsConfuse.cpp + ) +ENDIF () + ADD_LIBRARY(tellusbd101 SHARED ${tellusbd101_SRCS} - ${tellusbd101_MOC_SRCS} ) -TARGET_LINK_LIBRARIES(tellusbd101 - confuse +IF (APPLE) + FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) + + TARGET_LINK_LIBRARIES(tellusbd101 + ${COREFOUNDATION_LIBRARY} ) +ENDIF (APPLE) INSTALL(TARGETS tellusbd101 LIBRARY DESTINATION lib @@ -39,7 +53,9 @@ SET(SYSCONF_INSTALL_DIR FORCE ) -INSTALL(FILES - tellstick.conf - DESTINATION ${SYSCONF_INSTALL_DIR} +IF (UNIX) + INSTALL(FILES + tellstick.conf + DESTINATION ${SYSCONF_INSTALL_DIR} ) +ENDIF () \ No newline at end of file From 2d2b290372b93714aa60ff900a5ec739e76fe586 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Jul 2008 12:46:40 +0000 Subject: [PATCH 0108/2215] Updated so controlling devices under Max OS X works! --- .../driver/TellUsbD101/CMakeLists.txt | 15 +- .../TellUsbD101/settings/TelldusSettings.cpp | 2 +- .../driver/TellUsbD101/win/Device.cpp | 6 +- .../driver/TellUsbD101/win/WinTypes.h | 87 + .../TellUsbD101/win/{FTD2XX.H => ftd2xx.h} | 1787 +++++++++-------- 5 files changed, 1013 insertions(+), 884 deletions(-) create mode 100755 telldus-core/driver/TellUsbD101/win/WinTypes.h rename telldus-core/driver/TellUsbD101/win/{FTD2XX.H => ftd2xx.h} (85%) mode change 100644 => 100755 diff --git a/telldus-core/driver/TellUsbD101/CMakeLists.txt b/telldus-core/driver/TellUsbD101/CMakeLists.txt index 50c64d3f..8dee752e 100644 --- a/telldus-core/driver/TellUsbD101/CMakeLists.txt +++ b/telldus-core/driver/TellUsbD101/CMakeLists.txt @@ -1,7 +1,6 @@ SET( tellusbd101_SRCS Device.cpp - linux/Device.cpp DeviceIkea.cpp DeviceNexa.cpp DeviceSartano.cpp @@ -10,20 +9,25 @@ SET( tellusbd101_SRCS TellUsbD101.cpp ) -ADD_DEFINITIONS( - -DOS_LINUX - ) - IF (APPLE) SET( tellusbd101_SRCS ${tellusbd101_SRCS} + win/Device.cpp settings/TelldusSettingsCoreFoundationPreferences.cpp ) + ADD_DEFINITIONS( + -D_MACOSX + ) ELSE () SET( tellusbd101_SRC ${tellusbd101_SRCS} + linux/Device.cpp settings/TelldusSettingsConfuse.cpp ) + ADD_DEFINITIONS( + -D_LINUX + ) + ENDIF () ADD_LIBRARY(tellusbd101 SHARED @@ -35,6 +39,7 @@ IF (APPLE) TARGET_LINK_LIBRARIES(tellusbd101 ${COREFOUNDATION_LIBRARY} + ftd2xx ) ENDIF (APPLE) diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp index 2ace6e18..04b0888a 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -41,7 +41,7 @@ Device* TelldusSettings::getDevice(int intDeviceId){ return NULL; } -#ifndef _WINDOWS +#ifdef _LINUX dev->setDevice( getSetting("deviceNode") ); #endif diff --git a/telldus-core/driver/TellUsbD101/win/Device.cpp b/telldus-core/driver/TellUsbD101/win/Device.cpp index 87935ad0..556fec28 100644 --- a/telldus-core/driver/TellUsbD101/win/Device.cpp +++ b/telldus-core/driver/TellUsbD101/win/Device.cpp @@ -1,11 +1,10 @@ -#include "..\Device.h" +#include "../Device.h" #include #include #include #include #include -#include "..\StdAfx.h" -#include "FTD2XX.H" +#include "ftd2xx.h" int getDongleIndex(); @@ -50,6 +49,7 @@ int getDongleIndex(){ try{ DWORD dwNumberOfDevices = 0; + FT_SetVIDPID(0x1781, 0x0C30); ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); if (ftStatus == FT_OK) { for (int i = 0; i < (int)dwNumberOfDevices; i++) { diff --git a/telldus-core/driver/TellUsbD101/win/WinTypes.h b/telldus-core/driver/TellUsbD101/win/WinTypes.h new file mode 100755 index 00000000..c37d66ff --- /dev/null +++ b/telldus-core/driver/TellUsbD101/win/WinTypes.h @@ -0,0 +1,87 @@ +#ifndef __WINDOWS_TYPES__ +#define __WINDOWS_TYPES__ + +#define MAX_NUM_DEVICES 50 +#include + +typedef unsigned long DWORD; +typedef unsigned long ULONG; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned char UCHAR; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef unsigned char *LPBYTE; +typedef int BOOL; +typedef char BOOLEAN; +typedef char CHAR; +typedef int *LPBOOL; +typedef unsigned char *PUCHAR; +typedef const char *LPCSTR; +typedef char *PCHAR; +typedef void *PVOID; +typedef void *HANDLE; +typedef long LONG; +typedef int INT; +typedef unsigned int UINT; +typedef char *LPSTR; +typedef char *LPTSTR; +typedef DWORD *LPDWORD; +typedef WORD *LPWORD; +typedef ULONG *PULONG; +typedef PVOID LPVOID; +typedef void VOID; +typedef unsigned long long int ULONGLONG; + +typedef struct _OVERLAPPED { + DWORD Internal; + DWORD InternalHigh; + DWORD Offset; + DWORD OffsetHigh; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +typedef struct _SECURITY_ATTRIBUTES { + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; + +typedef struct timeval SYSTEMTIME; +typedef struct timeval FILETIME; +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +// +// Modem Status Flags +// +#define MS_CTS_ON ((DWORD)0x0010) +#define MS_DSR_ON ((DWORD)0x0020) +#define MS_RING_ON ((DWORD)0x0040) +#define MS_RLSD_ON ((DWORD)0x0080) + +// +// Error Flags +// + +#define CE_RXOVER 0x0001 // Receive Queue overflow +#define CE_OVERRUN 0x0002 // Receive Overrun Error +#define CE_RXPARITY 0x0004 // Receive Parity Error +#define CE_FRAME 0x0008 // Receive Framing error +#define CE_BREAK 0x0010 // Break Detected +#define CE_TXFULL 0x0100 // TX Queue is full +#define CE_PTO 0x0200 // LPTx Timeout +#define CE_IOE 0x0400 // LPTx I/O Error +#define CE_DNS 0x0800 // LPTx Device not selected +#define CE_OOP 0x1000 // LPTx Out-Of-Paper +#define CE_MODE 0x8000 // Requested mode unsupported + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE 0xFFFFFFFF +#endif + +#endif diff --git a/telldus-core/driver/TellUsbD101/win/FTD2XX.H b/telldus-core/driver/TellUsbD101/win/ftd2xx.h old mode 100644 new mode 100755 similarity index 85% rename from telldus-core/driver/TellUsbD101/win/FTD2XX.H rename to telldus-core/driver/TellUsbD101/win/ftd2xx.h index 2507326c..3972081c --- a/telldus-core/driver/TellUsbD101/win/FTD2XX.H +++ b/telldus-core/driver/TellUsbD101/win/ftd2xx.h @@ -1,875 +1,912 @@ -/*++ - -Copyright (c) 2001-2005 Future Technology Devices International Ltd. - -Module Name: - - ftd2xx.h - -Abstract: - - Native USB device driver for FTDI FT8U232/245 - FTD2XX library definitions - -Environment: - - kernel & user mode - -Revision History: - - 13/03/01 awm Created. - 13/01/03 awm Added device information support. - 19/03/03 awm Added FT_W32_CancelIo. - 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. - 18/09/03 awm Added FT_SetResetPipeRetryCount. - 10/10/03 awm Added FT_ResetPort. - 23/01/04 awm Added support for open-by-location. - 16/03/04 awm Added support for FT2232C. - 23/09/04 awm Added support for FT232R. - 20/10/04 awm Added FT_CyclePort. - 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. - 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. - 25/08/05 awm Added FT_SetDeadmanTimeout. - 02/12/05 awm Removed obsolete references. - 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. - - ---*/ - - -#ifndef FTD2XX_H -#define FTD2XX_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// FTD2XX_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef FTD2XX_EXPORTS -#define FTD2XX_API __declspec(dllexport) -#else -#define FTD2XX_API __declspec(dllimport) -#endif - - -typedef PVOID FT_HANDLE; -typedef ULONG FT_STATUS; - -// -// Device status -// -enum { - FT_OK, - FT_INVALID_HANDLE, - FT_DEVICE_NOT_FOUND, - FT_DEVICE_NOT_OPENED, - FT_IO_ERROR, - FT_INSUFFICIENT_RESOURCES, - FT_INVALID_PARAMETER, - FT_INVALID_BAUD_RATE, - - FT_DEVICE_NOT_OPENED_FOR_ERASE, - FT_DEVICE_NOT_OPENED_FOR_WRITE, - FT_FAILED_TO_WRITE_DEVICE, - FT_EEPROM_READ_FAILED, - FT_EEPROM_WRITE_FAILED, - FT_EEPROM_ERASE_FAILED, - FT_EEPROM_NOT_PRESENT, - FT_EEPROM_NOT_PROGRAMMED, - FT_INVALID_ARGS, - FT_NOT_SUPPORTED, - FT_OTHER_ERROR -}; - - -#define FT_SUCCESS(status) ((status) == FT_OK) - -// -// FT_OpenEx Flags -// - -#define FT_OPEN_BY_SERIAL_NUMBER 1 -#define FT_OPEN_BY_DESCRIPTION 2 -#define FT_OPEN_BY_LOCATION 4 - -// -// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags -// - -#define FT_LIST_NUMBER_ONLY 0x80000000 -#define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 - -#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) - -// -// Baud Rates -// - -#define FT_BAUD_300 300 -#define FT_BAUD_600 600 -#define FT_BAUD_1200 1200 -#define FT_BAUD_2400 2400 -#define FT_BAUD_4800 4800 -#define FT_BAUD_9600 9600 -#define FT_BAUD_14400 14400 -#define FT_BAUD_19200 19200 -#define FT_BAUD_38400 38400 -#define FT_BAUD_57600 57600 -#define FT_BAUD_115200 115200 -#define FT_BAUD_230400 230400 -#define FT_BAUD_460800 460800 -#define FT_BAUD_921600 921600 - -// -// Word Lengths -// - -#define FT_BITS_8 (UCHAR) 8 -#define FT_BITS_7 (UCHAR) 7 -#define FT_BITS_6 (UCHAR) 6 -#define FT_BITS_5 (UCHAR) 5 - -// -// Stop Bits -// - -#define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_1_5 (UCHAR) 1 -#define FT_STOP_BITS_2 (UCHAR) 2 - -// -// Parity -// - -#define FT_PARITY_NONE (UCHAR) 0 -#define FT_PARITY_ODD (UCHAR) 1 -#define FT_PARITY_EVEN (UCHAR) 2 -#define FT_PARITY_MARK (UCHAR) 3 -#define FT_PARITY_SPACE (UCHAR) 4 - -// -// Flow Control -// - -#define FT_FLOW_NONE 0x0000 -#define FT_FLOW_RTS_CTS 0x0100 -#define FT_FLOW_DTR_DSR 0x0200 -#define FT_FLOW_XON_XOFF 0x0400 - -// -// Purge rx and tx buffers -// -#define FT_PURGE_RX 1 -#define FT_PURGE_TX 2 - -// -// Events -// - -typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); - -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 - -// -// Timeouts -// - -#define FT_DEFAULT_RX_TIMEOUT 300 -#define FT_DEFAULT_TX_TIMEOUT 300 - -// -// Device types -// - -typedef ULONG FT_DEVICE; - -enum { - FT_DEVICE_BM, - FT_DEVICE_AM, - FT_DEVICE_100AX, - FT_DEVICE_UNKNOWN, - FT_DEVICE_2232C, - FT_DEVICE_232R -}; - - -#ifdef __cplusplus -extern "C" { -#endif - - -FTD2XX_API -FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten - ); - -FTD2XX_API -FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); - -// -// structure to hold program data for FT_Program function -// -typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232C extensions - // 2 = FT232R extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // FT2232C extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // FT232R extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - - UCHAR RIsVCP; // non-zero if using VCP drivers - -} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDeadmanTimeout( - FT_HANDLE ftHandle, - ULONG ulDeadmanTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - -FTD2XX_API -FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_CyclePort( - FT_HANDLE ftHandle - ); - - -// -// Win32-type functions -// - -FTD2XX_API -FT_HANDLE WINAPI FT_W32_CreateFile( - LPCSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); - - -// -// Win32 COMM API type functions -// -typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; -} FTCOMSTAT, *LPFTCOMSTAT; - -typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ -} FTDCB, *LPFTDCB; - -typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ -} FTTIMEOUTS,*LPFTTIMEOUTS; - - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - -FTD2XX_API -BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); - - -// -// Device information -// - -typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; -} FT_DEVICE_LIST_INFO_NODE; - - -FTD2XX_API -FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); - - -// -// Version information -// - -FTD2XX_API -FT_STATUS WINAPI FT_GetDriverVersion( - FT_HANDLE ftHandle, - LPDWORD lpdwVersion - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLibraryVersion( - LPDWORD lpdwVersion - ); - - - - -#ifdef __cplusplus -} -#endif - - -#endif /* FTD2XX_H */ - +/*++ + +Copyright (c) 2001-2003 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB interface for FTDI FT8U232/245/2232C + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + /03/04 st modified for linux users + 12/10/04 st added FT_SetVIDPID + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +#ifndef _WINDOWS +#include +#define WINAPI +#endif + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + +#ifndef _WINDOWS +#include "WinTypes.h" + +#ifdef FTD2XX_API +#undef FTD2XX_API +#define FTD2XX_API +#endif +#endif +typedef struct _EVENT_HANDLE{ + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; +} EVENT_HANDLE; + +typedef DWORD *FT_HANDLE; +//typedef unsigned int FT_HANDLE; +//typedef struct ftdi_device * FT_HANDLE; + +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, //7 + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R + }; + + +#ifdef __cplusplus +extern "C" { +#endif + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS FT_SetVIDPID( + DWORD dwVID, + DWORD dwPID + ); + +FTD2XX_API +FT_STATUS FT_GetVIDPID( + DWORD * pdwVID, + DWORD * pdwPID + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // FT2232C extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // FT232R extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + + UCHAR RIsVCP; // zero if using VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); +// +// Events +// + +#define EV_RXCHAR 0x0001 // Any Character received +#define EV_RXFLAG 0x0002 // Received certain character +#define EV_TXEMPTY 0x0004 // Transmitt Queue Empty +#define EV_CTS 0x0008 // CTS changed state +#define EV_DSR 0x0010 // DSR changed state +#define EV_RLSD 0x0020 // RLSD changed state +#define EV_BREAK 0x0040 // BREAK received +#define EV_ERR 0x0080 // Line status error occurred +#define EV_RING 0x0100 // Ring signal detected +#define EV_PERR 0x0200 // Printer error occured +#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full +#define EV_EVENT1 0x0800 // Provider specific event 1 +#define EV_EVENT2 0x1000 // Provider specific event 2 + +// +// Escape Functions +// + +#define SETXOFF 1 // Simulate XOFF received +#define SETXON 2 // Simulate XON received +#define SETRTS 3 // Set RTS high +#define CLRRTS 4 // Set RTS low +#define SETDTR 5 // Set DTR high +#define CLRDTR 6 // Set DTR low +#define RESETDEV 7 // Reset device if possible +#define SETBREAK 8 // Set the device break line. +#define CLRBREAK 9 // Clear the device break line. + +// +// PURGE function flags. +// +#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. +#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. +#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. +#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + + + + + + From 95972873a8cd415c4164f112216eaa1216b47fe7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 30 Jul 2008 15:38:38 +0000 Subject: [PATCH 0109/2215] Added Visual Basic binding. --- bindings/visual-basic/TellStick.bas | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 bindings/visual-basic/TellStick.bas diff --git a/bindings/visual-basic/TellStick.bas b/bindings/visual-basic/TellStick.bas new file mode 100644 index 00000000..558c266f --- /dev/null +++ b/bindings/visual-basic/TellStick.bas @@ -0,0 +1,17 @@ +Attribute VB_Name = "TellStickModule" +Public Declare Function devTurnOn Lib "TellUsbD101.dll" (ByVal lngDeviceId As Long) As Boolean +Public Declare Function devTurnOff Lib "TellUsbD101.dll" (ByVal lngDeviceId As Long) As Boolean +Public Declare Function devBell Lib "TellUsbD101.dll" (ByVal lngDeviceId As Long) As Boolean +Public Declare Function devDim Lib "TellUsbD101.dll" (ByVal lngDeviceId As Long, ByVal level As Byte) As Boolean +Public Declare Function devMethods Lib "TellUsbD101.dll" (ByVal lngDeviceId As Long) As Long + +Public Declare Function devGetDeviceId Lib "TellUsbD101.dll" (ByVal a As Long) As Long +Public Declare Function devGetName Lib "TellUsbD101.dll" (ByVal i As Long) As String +Public Declare Function devGetNumberOfDevices Lib "TellUsbD101.dll" () As Long + +Public Const TELLSTICK_TURNON = 1 +Public Const TELLSTICK_TURNOFF = 2 +Public Const TELLSTICK_BELL = 4 +Public Const TELLSTICK_TOGGLE = 8 +Public Const TELLSTICK_DIM = 16 + From 12366971e51eddbe2dd791b46bc7fc4a191e2c8a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 30 Jul 2008 17:17:27 +0000 Subject: [PATCH 0110/2215] Added dim and bell to tdtool, closes #25 --- telldus-core/tdtool/main.cpp | 65 +++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index ceff6b5d..ed3eef3d 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -48,7 +48,7 @@ void list_devices() { } } -void switch_device( bool turnOn, char *device ) { +int find_device( char *device ) { int deviceId = atoi(device); if (deviceId == 0) { //Try to find the id from the name int intNum = devGetNumberOfDevices(); @@ -62,35 +62,73 @@ void switch_device( bool turnOn, char *device ) { } index++; } - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } + } + return deviceId; +} + +void switch_device( bool turnOn, char *device ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; } + char *name = devGetName( deviceId ); if (turnOn) { - char *name = devGetName( deviceId ); bool ok = devTurnOn( deviceId ); printf("Turning on device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); } else { - char *name = devGetName( deviceId ); bool ok = devTurnOff( deviceId ); printf("Turning off device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); } sleep(1); } +void dim_device( char *device, int level ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + if (level < 0 || level > 255) { + printf("Level %i out of range!\n", level); + return; + } + + char *name = devGetName( deviceId ); + bool ok = devDim( deviceId, (unsigned char)level ); + printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, (ok ? "ok" : "failed")); + sleep(1); +} + +void bell_device( char *device ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + + char *name = devGetName( deviceId ); + bool ok = devBell( deviceId ); + printf("Dimming device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + sleep(1); +} + int main(int argc, char **argv) { int optch, longindex; - static char optstring[] = "ln:f:h"; + static char optstring[] = "ln:f:d:b:v:h"; static struct option long_opts[] = { { "list", 0, 0, 'l' }, { "on", 1, 0, 'n' }, { "off", 1, 0, 'f' }, + { "dim", 1, 0, 'd' }, + { "bell", 1, 0, 'b' }, + { "dimlevel", 1, 0, 'v' }, { "help", 1, 0, 'h' }, { 0, 0, 0, 0} }; + int level = -1; if (argc < 2) { print_usage( argv[0] ); @@ -99,6 +137,14 @@ int main(int argc, char **argv) while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) switch (optch) { + case 'b' : + bell_device( &optarg[0] ); + break; + case 'd' : + if (level >= 0) { + dim_device( &optarg[0], level ); + } + break; case 'f' : switch_device(false, &optarg[0]); break; @@ -111,6 +157,9 @@ int main(int argc, char **argv) case 'n' : switch_device(true, &optarg[0]); break; + case 'v' : + level = atoi( &optarg[0] ); + break; default : print_usage( argv[0] ); return -1; From b6efe89b0f269b2e7d986eb1bf0a1c6fccac5d86 Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Wed, 30 Jul 2008 17:28:16 +0000 Subject: [PATCH 0111/2215] Added help texts for dim and bell --- telldus-core/tdtool/main.cpp | 351 ++++++++++++++++++----------------- 1 file changed, 182 insertions(+), 169 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index ed3eef3d..bcd3f31a 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -1,169 +1,182 @@ -#include -#include -#include -#include -#include -#include "TellUsbD101.h" -#ifdef __MINGW32__ - #define sleep(x) _sleep((x)*1000) -#endif - -void print_usage( char *name ) { - printf("Usage:\n"); - printf(" %s [ options ]\n", name); - printf("\n"); - printf("Options: -[lh] [--list] [--help]\n"); - printf(" [--on device] [--off device]\n"); - printf("\n"); - printf("Options:\n"); - printf(" --list (-l short option)\n"); - printf(" List currently configured devices.\n"); - printf("\n"); - printf(" --help (-h short option)\n"); - printf(" Shows this screen.\n"); - printf("\n"); - printf(" --on device\n"); - printf(" Turns on device. device should be an integer of the device-id.\n"); - printf(" The device-id is outputed with the --list option\n"); - printf("\n"); - printf(" --off device\n"); - printf(" Turns off device. device should be an integer of the device-id.\n"); - printf(" The device-id is outputed with the --list option\n"); - printf("\n"); -} - -void print_device( int index ) { - int intId = devGetDeviceId(index); - char *name = devGetName(intId); - printf("%i\t%s\n", intId, name); -} - -void list_devices() { - int intNum = devGetNumberOfDevices(); - printf("Number of devices: %i\n", intNum); - int i = 0; - while (i < intNum) { - print_device( i ); - i++; - } -} - -int find_device( char *device ) { - int deviceId = atoi(device); - if (deviceId == 0) { //Try to find the id from the name - int intNum = devGetNumberOfDevices(); - int index = 0; - while (index < intNum) { - int id = devGetDeviceId(index); - char *name = devGetName( id ); - if (strcasecmp(name, device) == 0) { - deviceId = id; - break; - } - index++; - } - } - return deviceId; -} - -void switch_device( bool turnOn, char *device ) { - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } - - char *name = devGetName( deviceId ); - if (turnOn) { - bool ok = devTurnOn( deviceId ); - printf("Turning on device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); - } else { - bool ok = devTurnOff( deviceId ); - printf("Turning off device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); - } - sleep(1); -} - -void dim_device( char *device, int level ) { - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } - if (level < 0 || level > 255) { - printf("Level %i out of range!\n", level); - return; - } - - char *name = devGetName( deviceId ); - bool ok = devDim( deviceId, (unsigned char)level ); - printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, (ok ? "ok" : "failed")); - sleep(1); -} - -void bell_device( char *device ) { - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } - - char *name = devGetName( deviceId ); - bool ok = devBell( deviceId ); - printf("Dimming device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); - sleep(1); -} - -int main(int argc, char **argv) -{ - int optch, longindex; - static char optstring[] = "ln:f:d:b:v:h"; - static struct option long_opts[] = { - { "list", 0, 0, 'l' }, - { "on", 1, 0, 'n' }, - { "off", 1, 0, 'f' }, - { "dim", 1, 0, 'd' }, - { "bell", 1, 0, 'b' }, - { "dimlevel", 1, 0, 'v' }, - { "help", 1, 0, 'h' }, - { 0, 0, 0, 0} - }; - int level = -1; - - if (argc < 2) { - print_usage( argv[0] ); - return -1; - } - - while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) - switch (optch) { - case 'b' : - bell_device( &optarg[0] ); - break; - case 'd' : - if (level >= 0) { - dim_device( &optarg[0], level ); - } - break; - case 'f' : - switch_device(false, &optarg[0]); - break; - case 'h' : - print_usage( argv[0] ); - break; - case 'l' : - list_devices(); - break; - case 'n' : - switch_device(true, &optarg[0]); - break; - case 'v' : - level = atoi( &optarg[0] ); - break; - default : - print_usage( argv[0] ); - return -1; - } - - return 0; -} +#include +#include +#include +#include +#include +#include "TellUsbD101.h" +#ifdef __MINGW32__ + #define sleep(x) _sleep((x)*1000) +#endif + +void print_usage( char *name ) { + printf("Usage:\n"); + printf(" %s [ options ]\n", name); + printf("\n"); + printf("Options: -[lh] [--list] [--help]\n"); + printf(" [--on device] [--off device]\n"); + printf("\n"); + printf("Options:\n"); + printf(" --list (-l short option)\n"); + printf(" List currently configured devices.\n"); + printf("\n"); + printf(" --help (-h short option)\n"); + printf(" Shows this screen.\n"); + printf("\n"); + printf(" --on device (-n short option)\n"); + printf(" Turns on device. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --off device (-f short option)\n"); + printf(" Turns off device. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --dim device (-d short option)\n"); + printf(" Dims device. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf(" Note: The dimlevel parameter must be set before using this option. + printf("\n"); + printf(" --dimlevel level (-v short option)\n"); + printf(" Set dim level. 'level' should an integer, 0-255.\n"); + printf(" Note: This parameter must be set before using dim.\n"); + printf("\n"); + printf(" --bell device (-b short option)\n"); + printf(" Sends bell command to devices supporting this. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); +} + +void print_device( int index ) { + int intId = devGetDeviceId(index); + char *name = devGetName(intId); + printf("%i\t%s\n", intId, name); +} + +void list_devices() { + int intNum = devGetNumberOfDevices(); + printf("Number of devices: %i\n", intNum); + int i = 0; + while (i < intNum) { + print_device( i ); + i++; + } +} + +int find_device( char *device ) { + int deviceId = atoi(device); + if (deviceId == 0) { //Try to find the id from the name + int intNum = devGetNumberOfDevices(); + int index = 0; + while (index < intNum) { + int id = devGetDeviceId(index); + char *name = devGetName( id ); + if (strcasecmp(name, device) == 0) { + deviceId = id; + break; + } + index++; + } + } + return deviceId; +} + +void switch_device( bool turnOn, char *device ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + + char *name = devGetName( deviceId ); + if (turnOn) { + bool ok = devTurnOn( deviceId ); + printf("Turning on device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + } else { + bool ok = devTurnOff( deviceId ); + printf("Turning off device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + } + sleep(1); +} + +void dim_device( char *device, int level ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + if (level < 0 || level > 255) { + printf("Level %i out of range!\n", level); + return; + } + + char *name = devGetName( deviceId ); + bool ok = devDim( deviceId, (unsigned char)level ); + printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, (ok ? "ok" : "failed")); + sleep(1); +} + +void bell_device( char *device ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + + char *name = devGetName( deviceId ); + bool ok = devBell( deviceId ); + printf("Dimming device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + sleep(1); +} + +int main(int argc, char **argv) +{ + int optch, longindex; + static char optstring[] = "ln:f:d:b:v:h"; + static struct option long_opts[] = { + { "list", 0, 0, 'l' }, + { "on", 1, 0, 'n' }, + { "off", 1, 0, 'f' }, + { "dim", 1, 0, 'd' }, + { "bell", 1, 0, 'b' }, + { "dimlevel", 1, 0, 'v' }, + { "help", 1, 0, 'h' }, + { 0, 0, 0, 0} + }; + int level = -1; + + if (argc < 2) { + print_usage( argv[0] ); + return -1; + } + + while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) + switch (optch) { + case 'b' : + bell_device( &optarg[0] ); + break; + case 'd' : + if (level >= 0) { + dim_device( &optarg[0], level ); + } + break; + case 'f' : + switch_device(false, &optarg[0]); + break; + case 'h' : + print_usage( argv[0] ); + break; + case 'l' : + list_devices(); + break; + case 'n' : + switch_device(true, &optarg[0]); + break; + case 'v' : + level = atoi( &optarg[0] ); + break; + default : + print_usage( argv[0] ); + return -1; + } + + return 0; +} From 6ecf868c6547f15b32330d7709cdbb52a9324049 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 30 Jul 2008 17:44:47 +0000 Subject: [PATCH 0112/2215] Fixed some issues with the help texts. --- telldus-core/tdtool/main.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index bcd3f31a..eb388313 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -12,8 +12,9 @@ void print_usage( char *name ) { printf("Usage:\n"); printf(" %s [ options ]\n", name); printf("\n"); - printf("Options: -[lh] [--list] [--help]\n"); - printf(" [--on device] [--off device]\n"); + printf("Options: -[bdfhlnv] [--list] [--help]\n"); + printf(" [--on device] [--off device] [--bell device]\n"); + printf(" [--dimlevel level --dim device]\n"); printf("\n"); printf("Options:\n"); printf(" --list (-l short option)\n"); @@ -23,24 +24,28 @@ void print_usage( char *name ) { printf(" Shows this screen.\n"); printf("\n"); printf(" --on device (-n short option)\n"); - printf(" Turns on device. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Turns on device. 'device' could either be an integer of the\n"); + printf(" device-id, or the name of the device.\n"); printf(" Both device-id and name is outputed with the --list option\n"); printf("\n"); printf(" --off device (-f short option)\n"); - printf(" Turns off device. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Turns off device. 'device' could either be an integer of the\n"); + printf(" device-id, or the name of the device.\n"); printf(" Both device-id and name is outputed with the --list option\n"); printf("\n"); printf(" --dim device (-d short option)\n"); - printf(" Dims device. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Dims device. 'device' could either be an integer of the device-id,\n"); + printf(" or the name of the device.\n"); printf(" Both device-id and name is outputed with the --list option\n"); - printf(" Note: The dimlevel parameter must be set before using this option. + printf(" Note: The dimlevel parameter must be set before using this option.\n"); printf("\n"); printf(" --dimlevel level (-v short option)\n"); printf(" Set dim level. 'level' should an integer, 0-255.\n"); printf(" Note: This parameter must be set before using dim.\n"); printf("\n"); printf(" --bell device (-b short option)\n"); - printf(" Sends bell command to devices supporting this. 'device' could either be an integer of the device-id, or the name of the device.\n"); + printf(" Sends bell command to devices supporting this. 'device' could\n"); + printf(" either be an integer of the device-id, or the name of the device.\n"); printf(" Both device-id and name is outputed with the --list option\n"); printf("\n"); } @@ -123,7 +128,7 @@ void bell_device( char *device ) { char *name = devGetName( deviceId ); bool ok = devBell( deviceId ); - printf("Dimming device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + printf("Sending bell to: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); sleep(1); } From d6ee193ab474fe2723fb070617210773038313a2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 4 Aug 2008 14:09:15 +0000 Subject: [PATCH 0113/2215] Fixed headerfile for compiling with a C-compiler --- telldus-core/driver/TellUsbD101/TellUsbD101.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.h b/telldus-core/driver/TellUsbD101/TellUsbD101.h index a5e8c016..a2c5aa58 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.h +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.h @@ -20,8 +20,13 @@ #define WINAPI #define TELLSTICK_API #endif +#ifndef __cplusplus + #define bool char +#endif +#ifdef __cplusplus extern "C" { +#endif TELLSTICK_API bool WINAPI devTurnOn(int intDeviceId); TELLSTICK_API bool WINAPI devTurnOff(int intDeviceId); TELLSTICK_API bool WINAPI devBell(int intDeviceId); @@ -43,7 +48,9 @@ extern "C" { TELLSTICK_API int WINAPI devAddDevice(); TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); +#ifdef __cplusplus } +#endif #define TELLSTICK_TURNON 1 #define TELLSTICK_TURNOFF 2 From 366871fc01c5d1392afcfb242e320300066c4b94 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 4 Aug 2008 14:36:43 +0000 Subject: [PATCH 0114/2215] Added php-bindings --- bindings/php/config.m4 | 41 ++++++++ bindings/php/example/example.php | 39 ++++++++ bindings/php/php_telldus.h | 24 +++++ bindings/php/telldus.c | 156 +++++++++++++++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 bindings/php/config.m4 create mode 100644 bindings/php/example/example.php create mode 100644 bindings/php/php_telldus.h create mode 100644 bindings/php/telldus.c diff --git a/bindings/php/config.m4 b/bindings/php/config.m4 new file mode 100644 index 00000000..28238114 --- /dev/null +++ b/bindings/php/config.m4 @@ -0,0 +1,41 @@ +PHP_ARG_ENABLE(telldus, whether to enable Telldus TellStick support, +[ --enable-telldus Enable Telldus TellStick support]) + +if test "$PHP_TELLDUS" = "yes"; then + AC_DEFINE(HAVE_TELLDUS, 1, [Whether you have Telldus TellStick]) + + SEARCH_PATH="/usr/local /usr" + SEARCH_FOR="/include/TellUsbD101.h" + if test -r $PHP_TELLDUS/; then # path given as parameter + TELLDUS_DIR=$PHP_TELLDUS + else # search default path list + AC_MSG_CHECKING([for telldus files in default path]) + for i in $SEARCH_PATH ; do + if test -r $i/$SEARCH_FOR; then + TELLDUS_DIR=$i + AC_MSG_RESULT(found in $i) + fi + done + fi + if test -z "$TELLDUS_DIR"; then + AC_MSG_RESULT([not found]) + AC_MSG_ERROR([Please reinstall the telldus-core distribution]) + fi + # --enable-telldus -> add include path + PHP_ADD_INCLUDE($TELLDUS_DIR/include) + # --enable-telldus -> check for lib and symbol presence + LIBNAME=tellusbd101 + LIBSYMBOL=devGetNumberOfDevices + PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, + [ + PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $TELLDUS_DIR/lib, TELLDUS_SHARED_LIBADD) + AC_DEFINE(HAVE_TELLDUSLIB,1,[ ]) + ],[ + AC_MSG_ERROR([wrong telldus lib version or lib not found]) + ],[ + -L$TELLDUS_DIR/lib -lm + ]) + PHP_SUBST(TELLDUS_SHARED_LIBADD) + + PHP_NEW_EXTENSION(telldus, telldus.c, $ext_shared) +fi diff --git a/bindings/php/example/example.php b/bindings/php/example/example.php new file mode 100644 index 00000000..064f1a5c --- /dev/null +++ b/bindings/php/example/example.php @@ -0,0 +1,39 @@ += 20010901 + STANDARD_MODULE_HEADER, +#endif + PHP_TELLDUS_EXTNAME, + telldus_functions, + PHP_MINIT(telldus), + PHP_MSHUTDOWN(telldus), + PHP_RINIT(telldus), + NULL, + NULL, +#if ZEND_MODULE_API_NO >= 20010901 + PHP_TELLDUS_VERSION, +#endif + STANDARD_MODULE_PROPERTIES +}; + +#ifdef COMPILE_DL_TELLDUS + ZEND_GET_MODULE(telldus) +#endif + + +PHP_RINIT_FUNCTION(telldus) +{ + return SUCCESS; +} + +PHP_MINIT_FUNCTION(telldus) +{ + REGISTER_LONG_CONSTANT("TELLDUS_TURNON", TELLSTICK_TURNON, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("TELLDUS_TURNOFF", TELLSTICK_TURNOFF, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("TELLDUS_BELL", TELLSTICK_BELL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("TELLDUS_TOGGLE", TELLSTICK_TOGGLE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("TELLDUS_DIM", TELLSTICK_DIM, CONST_CS | CONST_PERSISTENT); + + return SUCCESS; +} + +PHP_MSHUTDOWN_FUNCTION(telldus) +{ + return SUCCESS; +} + +PHP_FUNCTION(telldus_dev_turn_on) +{ + long id; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &id) == FAILURE) { + RETURN_NULL(); + } + + RETURN_BOOL( devTurnOn( id ) ); +} + +PHP_FUNCTION(telldus_dev_turn_off) +{ + long id; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &id) == FAILURE) { + RETURN_NULL(); + } + + RETURN_BOOL( devTurnOff( id ) ); +} + +PHP_FUNCTION(telldus_dev_bell) +{ + long id; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &id) == FAILURE) { + RETURN_NULL(); + } + + RETURN_BOOL( devBell( id ) ); +} + +PHP_FUNCTION(telldus_dev_dim) +{ + long id; + long level; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &id, &level) == FAILURE) { + RETURN_NULL(); + } + if (level < 0 || level > 255) { + RETURN_NULL(); + } + + RETURN_BOOL( devDim( id, level ) ); +} + + +PHP_FUNCTION(telldus_dev_methods) +{ + long id; + long methods; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &id) == FAILURE) { + RETURN_NULL(); + } + + methods = devMethods( id ); + RETURN_LONG(methods); +} + +PHP_FUNCTION(telldus_get_number_of_devices) +{ + int nbr = devGetNumberOfDevices(); + RETURN_LONG(nbr); +} + +PHP_FUNCTION(telldus_get_device_id) +{ + long index; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &index) == FAILURE) { + RETURN_LONG(0); + } + + RETURN_LONG( devGetDeviceId( index ) ); +} + +PHP_FUNCTION(telldus_get_name) +{ + long id; + char *name; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &id) == FAILURE) { + RETURN_NULL(); + } + + name = devGetName( id ); + RETURN_STRING( name, 1 ); +} From d33b4f004446a3415e8868792dc20f5b1c0e767f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 7 Sep 2008 09:48:19 +0000 Subject: [PATCH 0115/2215] Fixed a typo and cleaned up CMakeLists.txt --- telldus-core/driver/TellUsbD101/CMakeLists.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/CMakeLists.txt b/telldus-core/driver/TellUsbD101/CMakeLists.txt index 8dee752e..c5dfd9d5 100644 --- a/telldus-core/driver/TellUsbD101/CMakeLists.txt +++ b/telldus-core/driver/TellUsbD101/CMakeLists.txt @@ -18,8 +18,8 @@ IF (APPLE) ADD_DEFINITIONS( -D_MACOSX ) -ELSE () - SET( tellusbd101_SRC +ELSE (APPLE) + SET( tellusbd101_SRCS ${tellusbd101_SRCS} linux/Device.cpp settings/TelldusSettingsConfuse.cpp @@ -28,7 +28,7 @@ ELSE () -D_LINUX ) -ENDIF () +ENDIF (APPLE) ADD_LIBRARY(tellusbd101 SHARED ${tellusbd101_SRCS} @@ -41,6 +41,10 @@ IF (APPLE) ${COREFOUNDATION_LIBRARY} ftd2xx ) +ELSE (APPLE) + TARGET_LINK_LIBRARIES(tellusbd101 + confuse + ) ENDIF (APPLE) INSTALL(TARGETS tellusbd101 LIBRARY @@ -63,4 +67,4 @@ IF (UNIX) tellstick.conf DESTINATION ${SYSCONF_INSTALL_DIR} ) -ENDIF () \ No newline at end of file +ENDIF (UNIX) From 2ce9f877960b374eddd4c98b94400b8a9d231a81 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 7 Sep 2008 12:00:47 +0000 Subject: [PATCH 0116/2215] Added some basic documentation to use with doxygen --- telldus-core/driver/TellUsbD101/TellUsbD101.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index 010f8ded..ca4df9af 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -1,4 +1,7 @@ -//DLL entry point +/** + * @defgroup core telldus-core + * Telldus Core is the base module used to interface a Telldus TellStick. + */ #ifdef _WINDOWS #include "stdafx.h" @@ -22,6 +25,11 @@ using namespace std; //delete on created objects //comment (just copy from the called methods) +/** + * Turns a device on, if the device supports this. + * @param intDeviceId The device id to turn on. + * @ingroup core + **/ bool WINAPI devTurnOn(int intDeviceId){ try{ @@ -43,6 +51,11 @@ bool WINAPI devTurnOn(int intDeviceId){ return false; } +/** + * Turns a device off, if the device supports this. + * @param intDeviceId The device id to turn off. + * @ingroup core + */ bool WINAPI devTurnOff(int intDeviceId){ try{ From 177c7760246f0c45aaf54e6015ae7111e54fbcb6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 7 Sep 2008 12:58:10 +0000 Subject: [PATCH 0117/2215] Added more documentation to telldus-core --- .../driver/TellUsbD101/TellUsbD101.cpp | 81 ++++++++++++++++++- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index ca4df9af..d66fc805 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -18,6 +18,27 @@ void handleException(std::exception e); using namespace std; +/** + * @def TELLSTICK_TURNON + * @ingroup core + * Device-flag for devices supporting the devTurnOn() call. + * + * @def TELLSTICK_TURNOFF + * @ingroup core + * Device-flag for devices supporting the devTurnOff() call. + * + * @def TELLSTICK_BELL + * @ingroup core + * Device-flag for devices supporting the devBell() call. + * + * @def TELLSTICK_TOGGLE + * @ingroup core + * This method is currently unimplemented + * + * @def TELLSTICK_DIM + * @ingroup core + * Device-flag for devices supporting the devDim() call. + */ #define MAX_LOADSTRING 100 @@ -26,7 +47,9 @@ using namespace std; //comment (just copy from the called methods) /** - * Turns a device on, if the device supports this. + * Turns a device on. + * Make sure the device supports this by calling devMethods() before any + * call to this function. * @param intDeviceId The device id to turn on. * @ingroup core **/ @@ -52,7 +75,9 @@ bool WINAPI devTurnOn(int intDeviceId){ } /** - * Turns a device off, if the device supports this. + * Turns a device off. + * Make sure the device supports this by calling devMethods() before any + * call to this function. * @param intDeviceId The device id to turn off. * @ingroup core */ @@ -77,6 +102,13 @@ bool WINAPI devTurnOff(int intDeviceId){ return false; } +/** + * Sends bell command to devices supporting this. + * Make sure the device supports this by calling devMethods() before any + * call to this function. + * @param intDeviceId The device id to send bell to + * @ingroup core + */ bool WINAPI devBell(int intDeviceId){ try{ @@ -98,6 +130,14 @@ bool WINAPI devBell(int intDeviceId){ return false; } +/** + * Dims a device. + * Make sure the device supports this by calling devMethods() before any + * call to this function. + * @param intDeviceId The device id to dim + * @param level The level the device should dim to. This value should be 0-255 + * @ingroup core + */ bool WINAPI devDim(int intDeviceId, unsigned char level){ try{ @@ -124,6 +164,11 @@ bool WINAPI devDim(int intDeviceId, unsigned char level){ return false; } +/** + * This function returns the number of devices configured + * @returns an integer of the total number of devices configured + * @ingroup core + */ int WINAPI devGetNumberOfDevices(void){ int intReturn = -1; try{ @@ -137,6 +182,20 @@ int WINAPI devGetNumberOfDevices(void){ return intReturn; } +/** + * This function returns the unique id of a device with a specific index. + * To get all the id numbers you should loop over all the devices: + * \code + * int intNumberOfDevices = devGetNumberOfDevices(); + * for (int i = 0; i < intNumberOfDevices; i++) { + * int id = devGetDeviceId( i ); + * // id now contains the id number of the device with index of i + * } + * \endcode + * @param intDeviceIndex The device index to query. The index starts from 0. + * @returns the unique id for the device or -1 if the device is not found. + * @ingroup core + */ int WINAPI devGetDeviceId(int intDeviceIndex){ int intReturn = -1; try{ @@ -150,7 +209,12 @@ int WINAPI devGetDeviceId(int intDeviceIndex){ return intReturn; } -//general settings: +/** + * Query a device for it's name. + * @param intDeviceId The unique id of the device to query + * @returns The name of the device or an empty string if the device is not found. + * @ingroup core + */ char * WINAPI devGetName(int intDeviceId){ char* strReturn; try{ @@ -294,6 +358,17 @@ bool WINAPI devRemoveDevice(int intDeviceId){ return blnSuccess; } +/** + * Query a device for which methods it supports. + * @param id The device id to query + * @returns The method-flags OR'ed into an integer. + * @ingroup core + * @sa TELLSTICK_TURNON + * @sa TELLSTICK_TURNOFF + * @sa TELLSTICK_BELL + * @sa TELLSTICK_TOGGLE + * @sa TELLSTICK_DIM + */ int WINAPI devMethods(int id){ int intMethods = 0; From 2be36e0fe1ea644fcc0a04d6a4c825d1abc53055 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Sep 2008 17:16:54 +0000 Subject: [PATCH 0118/2215] Bugfix if the device is not found --- .../driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp index 6aeada9d..4fac5f8e 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp @@ -180,7 +180,7 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool return strReturn; } } - return 0; + return ""; } bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { From 3602f433596506fd1a1f5ebe30090fc1355f1ad6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 12 Sep 2008 11:08:19 +0000 Subject: [PATCH 0119/2215] Implemented error codes for the methods devTurnOn(), devTurnOff(), devBell() and devDim(). A new function now exists, devGetErrorString(), which returns a human readable string for all of the error codes. --- telldus-core/driver/TellUsbD101/Device.cpp | 8 +- telldus-core/driver/TellUsbD101/Device.h | 10 +- .../driver/TellUsbD101/DeviceIkea.cpp | 15 ++- telldus-core/driver/TellUsbD101/DeviceIkea.h | 6 +- .../driver/TellUsbD101/DeviceNexa.cpp | 15 ++- telldus-core/driver/TellUsbD101/DeviceNexa.h | 6 +- .../driver/TellUsbD101/DeviceSartano.cpp | 10 +- .../driver/TellUsbD101/DeviceSartano.h | 4 +- .../driver/TellUsbD101/DeviceWaveman.cpp | 5 +- .../driver/TellUsbD101/DeviceWaveman.h | 2 +- .../driver/TellUsbD101/TellUsbD101.cpp | 121 ++++++++++++------ .../driver/TellUsbD101/TellUsbD101.def | 2 + telldus-core/driver/TellUsbD101/TellUsbD101.h | 22 +++- .../driver/TellUsbD101/linux/Device.cpp | 14 +- 14 files changed, 155 insertions(+), 85 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/Device.cpp b/telldus-core/driver/TellUsbD101/Device.cpp index 0b536781..fdf4abb4 100644 --- a/telldus-core/driver/TellUsbD101/Device.cpp +++ b/telldus-core/driver/TellUsbD101/Device.cpp @@ -17,28 +17,28 @@ Device::~Device(void) /* * Turn on, virtual */ -void Device::turnOn(void){ +int Device::turnOn(void){ //do nothing } /* * Turn off, virtual */ -void Device::turnOff(void){ +int Device::turnOff(void){ //do nothing } /* * Bell, virtual */ -void Device::bell(void){ +int Device::bell(void){ //do nothing } /* * Dim, virtual */ -void Device::dim(unsigned char level){ +int Device::dim(unsigned char level){ //do nothing } diff --git a/telldus-core/driver/TellUsbD101/Device.h b/telldus-core/driver/TellUsbD101/Device.h index 0c7451e1..d4860ccf 100644 --- a/telldus-core/driver/TellUsbD101/Device.h +++ b/telldus-core/driver/TellUsbD101/Device.h @@ -8,10 +8,10 @@ public: Device(); ~Device(void); - virtual void turnOn(void); - virtual void turnOff(void); - virtual void bell(void); - virtual void dim(unsigned char level); + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); + virtual int dim(unsigned char level); virtual int methods(char* strModel); #ifndef _WINDOWS @@ -21,5 +21,5 @@ protected: #endif protected: - void send(char* strMessage); + int send(char* strMessage); }; diff --git a/telldus-core/driver/TellUsbD101/DeviceIkea.cpp b/telldus-core/driver/TellUsbD101/DeviceIkea.cpp index 6f0a188f..722b5170 100644 --- a/telldus-core/driver/TellUsbD101/DeviceIkea.cpp +++ b/telldus-core/driver/TellUsbD101/DeviceIkea.cpp @@ -51,49 +51,52 @@ DeviceIkea::~DeviceIkea(void) /* * Turn on this device */ -void DeviceIkea::turnOn(void){ +int DeviceIkea::turnOn(void){ try{ string strCode = getStringCode(255); char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* * Turn off this device */ -void DeviceIkea::turnOff(void){ +int DeviceIkea::turnOff(void){ try{ string strCode = getStringCode(0); char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* * Turn off this device */ -void DeviceIkea::dim(unsigned char level){ +int DeviceIkea::dim(unsigned char level){ try{ string strCode = getStringCode(level); char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* diff --git a/telldus-core/driver/TellUsbD101/DeviceIkea.h b/telldus-core/driver/TellUsbD101/DeviceIkea.h index 7c704c4c..291e55e7 100644 --- a/telldus-core/driver/TellUsbD101/DeviceIkea.h +++ b/telldus-core/driver/TellUsbD101/DeviceIkea.h @@ -6,9 +6,9 @@ class DeviceIkea : public Device { public: DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle); - virtual void turnOn(void); - virtual void turnOff(void); - virtual void dim(unsigned char level); + virtual int turnOn(void); + virtual int turnOff(void); + virtual int dim(unsigned char level); virtual int methods(char* strModel); public: diff --git a/telldus-core/driver/TellUsbD101/DeviceNexa.cpp b/telldus-core/driver/TellUsbD101/DeviceNexa.cpp index d8392d5b..75cd827e 100644 --- a/telldus-core/driver/TellUsbD101/DeviceNexa.cpp +++ b/telldus-core/driver/TellUsbD101/DeviceNexa.cpp @@ -39,7 +39,7 @@ DeviceNexa::~DeviceNexa(void) /* * Turn on this device */ -void DeviceNexa::turnOn(void){ +int DeviceNexa::turnOn(void){ try{ string strCode = getStringCode(intHouse); @@ -51,17 +51,18 @@ void DeviceNexa::turnOn(void){ char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* * Turn off this device */ -void DeviceNexa::turnOff(void){ +int DeviceNexa::turnOff(void){ try{ string strCode = getStringCode(intHouse); @@ -73,17 +74,18 @@ void DeviceNexa::turnOff(void){ char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* * Send a bell */ -void DeviceNexa::bell(void){ +int DeviceNexa::bell(void){ try{ string strCode = getStringCode(intHouse); @@ -94,11 +96,12 @@ void DeviceNexa::bell(void){ char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* diff --git a/telldus-core/driver/TellUsbD101/DeviceNexa.h b/telldus-core/driver/TellUsbD101/DeviceNexa.h index 40468d2f..343060a8 100644 --- a/telldus-core/driver/TellUsbD101/DeviceNexa.h +++ b/telldus-core/driver/TellUsbD101/DeviceNexa.h @@ -6,9 +6,9 @@ class DeviceNexa : public Device { public: DeviceNexa(char *strHouse, char *strCode); - virtual void turnOn(void); - virtual void turnOff(void); - virtual void bell(void); + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); virtual int methods(char* strModel); public: diff --git a/telldus-core/driver/TellUsbD101/DeviceSartano.cpp b/telldus-core/driver/TellUsbD101/DeviceSartano.cpp index a78c1031..afc8e5a0 100644 --- a/telldus-core/driver/TellUsbD101/DeviceSartano.cpp +++ b/telldus-core/driver/TellUsbD101/DeviceSartano.cpp @@ -25,7 +25,7 @@ DeviceSartano::~DeviceSartano(void) /* * Turn on this device */ -void DeviceSartano::turnOn(void){ +int DeviceSartano::turnOn(void){ try{ string strCode = getStringCode(); @@ -35,17 +35,18 @@ void DeviceSartano::turnOn(void){ char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* * Turn off this device */ -void DeviceSartano::turnOff(void){ +int DeviceSartano::turnOff(void){ try{ string strCode = getStringCode(); @@ -55,11 +56,12 @@ void DeviceSartano::turnOff(void){ char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* diff --git a/telldus-core/driver/TellUsbD101/DeviceSartano.h b/telldus-core/driver/TellUsbD101/DeviceSartano.h index 13d4dd7a..c692a8ce 100644 --- a/telldus-core/driver/TellUsbD101/DeviceSartano.h +++ b/telldus-core/driver/TellUsbD101/DeviceSartano.h @@ -7,8 +7,8 @@ class DeviceSartano : public Device { public: DeviceSartano(char *strCode); - virtual void turnOn(void); - virtual void turnOff(void); + virtual int turnOn(void); + virtual int turnOff(void); virtual int methods(char* strModel); ~DeviceSartano(void); diff --git a/telldus-core/driver/TellUsbD101/DeviceWaveman.cpp b/telldus-core/driver/TellUsbD101/DeviceWaveman.cpp index 38376492..eed0cc41 100644 --- a/telldus-core/driver/TellUsbD101/DeviceWaveman.cpp +++ b/telldus-core/driver/TellUsbD101/DeviceWaveman.cpp @@ -18,7 +18,7 @@ DeviceWaveman::DeviceWaveman(char *strNewHouse, char *strNewCode) /* * Turn off this device */ -void DeviceWaveman::turnOff(void){ +int DeviceWaveman::turnOff(void){ try{ string strCode = getStringCode(intHouse); @@ -30,11 +30,12 @@ void DeviceWaveman::turnOff(void){ char* strMessage = const_cast(strCode.c_str()); - Device::send(strMessage); + return Device::send(strMessage); } catch(...){ throw; } + return TELLSTICK_ERROR_UNKNOWN; } /* diff --git a/telldus-core/driver/TellUsbD101/DeviceWaveman.h b/telldus-core/driver/TellUsbD101/DeviceWaveman.h index f00b13e1..57fc9fe8 100644 --- a/telldus-core/driver/TellUsbD101/DeviceWaveman.h +++ b/telldus-core/driver/TellUsbD101/DeviceWaveman.h @@ -6,6 +6,6 @@ class DeviceWaveman : public DeviceNexa { public: DeviceWaveman(char *strHouse, char *strCode); - virtual void turnOff(void); + virtual int turnOff(void); virtual int methods(char* strModel); }; diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index d66fc805..10e1b6cd 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -1,6 +1,7 @@ /** * @defgroup core telldus-core * Telldus Core is the base module used to interface a Telldus TellStick. + * @{ */ #ifdef _WINDOWS @@ -14,29 +15,25 @@ #include #include #include +#include void handleException(std::exception e); using namespace std; /** * @def TELLSTICK_TURNON - * @ingroup core * Device-flag for devices supporting the devTurnOn() call. * * @def TELLSTICK_TURNOFF - * @ingroup core * Device-flag for devices supporting the devTurnOff() call. * * @def TELLSTICK_BELL - * @ingroup core * Device-flag for devices supporting the devBell() call. * * @def TELLSTICK_TOGGLE - * @ingroup core * This method is currently unimplemented * * @def TELLSTICK_DIM - * @ingroup core * Device-flag for devices supporting the devDim() call. */ @@ -51,27 +48,33 @@ using namespace std; * Make sure the device supports this by calling devMethods() before any * call to this function. * @param intDeviceId The device id to turn on. - * @ingroup core **/ -bool WINAPI devTurnOn(int intDeviceId){ +int WINAPI devTurnOn(int intDeviceId){ try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - dev->turnOn(); + int methods = dev->methods( ts.getModel( intDeviceId ) ); + int retval = 0; + + if ( !(methods & TELLSTICK_TURNON) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } else { + retval = dev->turnOn(); + } delete(dev); - return true; + return retval; } else{ - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } catch(exception e){ handleException(e); } - return false; + return TELLSTICK_ERROR_UNKNOWN; } /** @@ -79,27 +82,33 @@ bool WINAPI devTurnOn(int intDeviceId){ * Make sure the device supports this by calling devMethods() before any * call to this function. * @param intDeviceId The device id to turn off. - * @ingroup core */ -bool WINAPI devTurnOff(int intDeviceId){ +int WINAPI devTurnOff(int intDeviceId){ try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - dev->turnOff(); + int methods = dev->methods( ts.getModel( intDeviceId ) ); + int retval = 0; + + if ( !(methods & TELLSTICK_TURNOFF) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } else { + retval = dev->turnOff(); + } delete(dev); - return true; + return retval; } else{ - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } catch(exception e){ handleException(e); } - return false; + return TELLSTICK_ERROR_UNKNOWN; } /** @@ -107,27 +116,33 @@ bool WINAPI devTurnOff(int intDeviceId){ * Make sure the device supports this by calling devMethods() before any * call to this function. * @param intDeviceId The device id to send bell to - * @ingroup core */ -bool WINAPI devBell(int intDeviceId){ +int WINAPI devBell(int intDeviceId){ try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - dev->bell(); + int methods = dev->methods( ts.getModel( intDeviceId ) ); + int retval = 0; + + if ( !(methods & TELLSTICK_BELL) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } else { + retval = dev->bell(); + } delete(dev); - return true; + return retval; } else{ - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } catch(exception e){ handleException(e); } - return false; + return TELLSTICK_ERROR_UNKNOWN; } /** @@ -136,38 +151,43 @@ bool WINAPI devBell(int intDeviceId){ * call to this function. * @param intDeviceId The device id to dim * @param level The level the device should dim to. This value should be 0-255 - * @ingroup core */ -bool WINAPI devDim(int intDeviceId, unsigned char level){ - +int WINAPI devDim(int intDeviceId, unsigned char level){ try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - if (level == 0) { - dev->turnOff(); - } else if (level == 255) { - dev->turnOn(); + int methods = dev->methods( ts.getModel( intDeviceId ) ); + int retval = 0; + + if ( !(methods & TELLSTICK_DIM) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } else { - dev->dim(level); + if (level == 0) { + retval = dev->turnOff(); + } else if (level == 255) { + retval = dev->turnOn(); + } else { + retval = dev->dim(level); + } } + delete(dev); - return true; + return retval; } else{ - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } catch(exception e){ handleException(e); } - return false; + return TELLSTICK_ERROR_UNKNOWN; } /** * This function returns the number of devices configured * @returns an integer of the total number of devices configured - * @ingroup core */ int WINAPI devGetNumberOfDevices(void){ int intReturn = -1; @@ -194,7 +214,6 @@ int WINAPI devGetNumberOfDevices(void){ * \endcode * @param intDeviceIndex The device index to query. The index starts from 0. * @returns the unique id for the device or -1 if the device is not found. - * @ingroup core */ int WINAPI devGetDeviceId(int intDeviceIndex){ int intReturn = -1; @@ -213,7 +232,6 @@ int WINAPI devGetDeviceId(int intDeviceIndex){ * Query a device for it's name. * @param intDeviceId The unique id of the device to query * @returns The name of the device or an empty string if the device is not found. - * @ingroup core */ char * WINAPI devGetName(int intDeviceId){ char* strReturn; @@ -362,7 +380,6 @@ bool WINAPI devRemoveDevice(int intDeviceId){ * Query a device for which methods it supports. * @param id The device id to query * @returns The method-flags OR'ed into an integer. - * @ingroup core * @sa TELLSTICK_TURNON * @sa TELLSTICK_TURNOFF * @sa TELLSTICK_BELL @@ -387,13 +404,38 @@ int WINAPI devMethods(int id){ return intMethods; } +char * WINAPI devGetErrorString(int intErrorNo) { + const int numResponses = 5; + const char *responses[numResponses] = { + "Success", + "TellStick not found", + "Permission denied", + "Device not found", + "The method you tried to use is not supported by the device" + }; + char *strReturn; + intErrorNo = abs(intErrorNo); //We don't use negative values here. + if (intErrorNo >= numResponses) { + strReturn = "Unknown error"; + } else { + // Copy the error string to strReturn + strReturn = (char *)malloc( sizeof(char) * strlen(responses[intErrorNo]) ); + strcpy( strReturn, responses[intErrorNo] ); + } + +#ifdef _WINDOWS + strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); +#endif + return strReturn; +} + //******** //* Error management, set strLogName to "" to turn off //* void handleException(exception e){ - char* strLogName = "c:\\errorlog.txt"; + char* strLogName = "errorlog.txt"; //char* strLogName = ""; if(strlen(strLogName) > 0){ @@ -405,3 +447,4 @@ void handleException(exception e){ } } +/*\@}*/ diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.def b/telldus-core/driver/TellUsbD101/TellUsbD101.def index e0ec3c03..9d3ecf89 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.def +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.def @@ -21,3 +21,5 @@ EXPORTS devTurnOff @15 devBell @16 devDim @17 + + devGetErrorString @18 diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.h b/telldus-core/driver/TellUsbD101/TellUsbD101.h index a2c5aa58..697b10d4 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.h +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.h @@ -20,22 +20,21 @@ #define WINAPI #define TELLSTICK_API #endif -#ifndef __cplusplus - #define bool char -#endif #ifdef __cplusplus extern "C" { #endif - TELLSTICK_API bool WINAPI devTurnOn(int intDeviceId); - TELLSTICK_API bool WINAPI devTurnOff(int intDeviceId); - TELLSTICK_API bool WINAPI devBell(int intDeviceId); - TELLSTICK_API bool WINAPI devDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI devTurnOn(int intDeviceId); + TELLSTICK_API int WINAPI devTurnOff(int intDeviceId); + TELLSTICK_API int WINAPI devBell(int intDeviceId); + TELLSTICK_API int WINAPI devDim(int intDeviceId, unsigned char level); TELLSTICK_API int WINAPI devMethods(int id); TELLSTICK_API int WINAPI devGetNumberOfDevices(); TELLSTICK_API int WINAPI devGetDeviceId(int intDeviceIndex); + TELLSTICK_API char * WINAPI devGetErrorString(int intErrorNo); + TELLSTICK_API char * WINAPI devGetName(int intDeviceId); TELLSTICK_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); TELLSTICK_API char * WINAPI devGetVendor(int intDeviceId); @@ -52,12 +51,21 @@ extern "C" { } #endif +//Device methods #define TELLSTICK_TURNON 1 #define TELLSTICK_TURNOFF 2 #define TELLSTICK_BELL 4 #define TELLSTICK_TOGGLE 8 #define TELLSTICK_DIM 16 +//Error codes +#define TELLSTICK_SUCCESS 0 +#define TELLSTICK_ERROR_NOT_FOUND -1 +#define TELLSTICK_ERROR_PERMISSION_DENIED -2 +#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 +#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 +#define TELLSTICK_ERROR_UNKNOWN -99 + //Protocol Nexa #define TELLSTICK_DEVICE_YCR3500 "1" #define TELLSTICK_DEVICE_YCR300D "2" diff --git a/telldus-core/driver/TellUsbD101/linux/Device.cpp b/telldus-core/driver/TellUsbD101/linux/Device.cpp index 98e9ca5d..2e1446c6 100644 --- a/telldus-core/driver/TellUsbD101/linux/Device.cpp +++ b/telldus-core/driver/TellUsbD101/linux/Device.cpp @@ -3,16 +3,22 @@ #include #include #include +#include /* * Send message to the USB dongle */ -void Device::send(char* strMessage) { +int Device::send(char* strMessage) { int fd = -1; struct termios tio; if( 0 > ( fd = open( strDevice, O_RDWR ) ) ) { - return; + if (errno == ENOENT) { + return TELLSTICK_ERROR_NOT_FOUND; + } else if (errno == EACCES) { + return TELLSTICK_ERROR_PERMISSION_DENIED; + } + return TELLSTICK_ERROR_UNKNOWN; } /* adjust serial port parameters */ @@ -23,9 +29,11 @@ void Device::send(char* strMessage) { tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&tio); - write(fd, strMessage, strlen(strMessage)); + write(fd, strMessage, strlen(strMessage)); close(fd); + + return TELLSTICK_SUCCESS; } void Device::setDevice(const char *device) { From 494f1366d28d66d549bfd098a971cc4d2d202e95 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 12 Sep 2008 11:42:38 +0000 Subject: [PATCH 0120/2215] Implemented error-codes in tdtool --- telldus-core/tdtool/main.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index eb388313..d63c2e31 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -93,11 +93,11 @@ void switch_device( bool turnOn, char *device ) { char *name = devGetName( deviceId ); if (turnOn) { - bool ok = devTurnOn( deviceId ); - printf("Turning on device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + int retval = devTurnOn( deviceId ); + printf("Turning on device: %i %s - %s\n", deviceId, name, devGetErrorString(retval)); } else { - bool ok = devTurnOff( deviceId ); - printf("Turning off device: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + int retval = devTurnOff( deviceId ); + printf("Turning off device: %i %s - %s\n", deviceId, name, devGetErrorString(retval)); } sleep(1); } @@ -114,8 +114,8 @@ void dim_device( char *device, int level ) { } char *name = devGetName( deviceId ); - bool ok = devDim( deviceId, (unsigned char)level ); - printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, (ok ? "ok" : "failed")); + int retval = devDim( deviceId, (unsigned char)level ); + printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, devGetErrorString(retval)); sleep(1); } @@ -127,8 +127,8 @@ void bell_device( char *device ) { } char *name = devGetName( deviceId ); - bool ok = devBell( deviceId ); - printf("Sending bell to: %i %s - %s\n", deviceId, name, (ok ? "ok" : "failed")); + int retval = devBell( deviceId ); + printf("Sending bell to: %i %s - %s\n", deviceId, name, devGetErrorString(retval)); sleep(1); } From 3210ed51c1b6b445609713e4201f902216ea187e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 12 Sep 2008 11:58:48 +0000 Subject: [PATCH 0121/2215] Documentation for telldus-core error codes. --- .../driver/TellUsbD101/TellUsbD101.cpp | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index 10e1b6cd..fa93c2bd 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -35,6 +35,26 @@ using namespace std; * * @def TELLSTICK_DIM * Device-flag for devices supporting the devDim() call. + * + * @def TELLSTICK_SUCCESS + * Error code. Returned when the command succeeded + * + * @def TELLSTICK_ERROR_NOT_FOUND + * Error code. Returned if a TellStick was not found on the system. + * + * @def TELLSTICK_ERROR_PERMISSION_DENIED + * Error code. Returned if the user doesn't have privileges to open + * the TellStick device + * + * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND + * Error code. The supplied device id was not found + * + * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + * Error code. The requested method is not supported device. + * This should be avoided by a call to devMethods(). + * + * @def TELLSTICK_ERROR_UNKNOWN + * Error code. An unkown error has occurred. */ #define MAX_LOADSTRING 100 @@ -404,6 +424,18 @@ int WINAPI devMethods(int id){ return intMethods; } +/** + * Get a human readable string from an error code returned + * from a function in telldus-core. + * @param intErrorNo The error code to translate. + * @returns a string ready to show to the user. + * @sa TELLSTICK_SUCCESS + * @sa TELLSTICK_ERROR_NOT_FOUND + * @sa TELLSTICK_ERROR_PERMISSION_DENIED + * @sa TELLSTICK_ERROR_DEVICE_NOT_FOUND + * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + * @sa TELLSTICK_ERROR_UNKNOWN + */ char * WINAPI devGetErrorString(int intErrorNo) { const int numResponses = 5; const char *responses[numResponses] = { From e55cf74e442872ca728bba751d5c2b6e87b535fd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 15 Sep 2008 09:42:43 +0000 Subject: [PATCH 0122/2215] Added first chapter to 'Telldus TellStick SDK documentation' --- docs/telldus-core.txt | 143 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 docs/telldus-core.txt diff --git a/docs/telldus-core.txt b/docs/telldus-core.txt new file mode 100644 index 00000000..b4e4f511 --- /dev/null +++ b/docs/telldus-core.txt @@ -0,0 +1,143 @@ +/** + * @page telldus_core Telldus Core API + * + * \section Introduction + * + * This is the guide to Telldus TellStick SDK. Even though all examples are + * written in C/C++ most of the code has an direct eqvivalent function in the + * other languages. See \ref sec_other_languages how to use the library in one + * of the supported languages by Telldus. + * + * \section Idea + * + * All of the devices used by TellStick must be predefined before they can be + * used in any software. Under all platforms this can be done with the + * software TelldusSetup but under Linux this can also be done by editing the + * file /etc/tellstick.conf with your favorite text editor. + * + * Having the devices preconfigured is an advantage to both the developer and + * the end user. + * + * \li The end user might use more then one program for controling his/hers + * TellStick. By having the devices preconfigured he/she doesn't have to + * reconfigure the same devices twice. If some settings changes in one of the + * devices, this change will affect all softwares using Telldus TellStick SDK. + * \li Telldus is adding support for new devices constantly. If every software + * defines it's own devices it will also mean that the developer has to keep + * it's software up to date with all the new devices and settings Telldus + * implements. By querying Telldus Tellstick SDK all the new devices will be + * available automaticly to the end user. + * + * \section sec_basic_usage Basic usage (telldus-core) + * + * Telldus provides a non-gui library to list, query and control the devices + * called telldus-core. + * + * \subsection sec_bu_listing Listing devices + * + * To list all of the configured devices, look at the following example: + * \code + * int intNumberOfDevices = devGetNumberOfDevices(); + * for (int i = 0; i < intNumberOfDevices; i++) { + * int id = devGetDeviceId( index ); + * char *name = devGetName( id ); + * printf("%d\t%s\n", id, name); + * } + * \endcode + * + * First, we call devGetNumberOfDevices(). This returnes the total number of + * devices configured. We then iterate over all of the devices with the index + * in the variable \c i. + * Since the devices could change between run of the program we could not be + * sure that the index points to the same device between two run of the + * program. That is why every device has an own unique id that is safe to + * store in a configuration file. Two different devices could never share the + * same device id. + * + * The call to devGetDeviceId() returns the id for a specific index. This + * function should only be called in a loop iterating over all of the devices. + * After we have found the id for a device it is safe to store this or use it + * the rest of the program. + * + * The next two lines of code queries the device for it's name with a call to + * devGetName() and then displays it to stdout. + * + * \subsection sec_bu_sending Sending commands to TellStick + * + * \subsubsection sec_bu_sending_features Device features + * + * TellStick can control many different types of devices and they + * all support different features. For example, a bell doesn't support turning + * on and not all lamp switches supports dimming. + * To find out what a specific device supports call devMethods(): + * \code + * function checkFeatures( int id ) { + * int methods = devMethods( id ); + * if ( methods & TELLSTICK_TURNON ) { + * printf( "The device %d supports devTurnOn()\n", id ); + * } + * if ( methods & TELLSTICK_TURNOFF ) { + * printf( "The device %d supports devTurnOff()\n", id ); + * } + * if ( methods & TELLSTICK_TURNBELL ) { + * printf( "The device %d supports devBell()\n", id ); + * } + * } + * \endcode + * + * When you know which fetures a device supports it is safe to call the + * controlling functions described in \ref sec_bu_controlling_functions. + * + * \subsubsection sec_bu_controlling_functions Controlling functions + * + * TellStick has a couple of functions for controlling the devices. Each of + * them should only be called if the device supports the feature. + * + * These functions all returns zero if the call was successfull and non-zero + * otherwise. + * + * \paragraph devTurnOn devTurnOn() + * Devices supporting \c TELLSTICK_TURNON. Most of the normal switches (for lamp + * etc.) supports this. + * \paragraph devTurnOff devTurnOff() + * Devices supporting \c TELLSTICK_TURNOFF. Almost all of the devices supporting + * \c TELLSTICK_TURNON also supports this. + * \paragraph devDim devDim() + * Devices supporting \c TELLSTICK_DIM. This is a quite unusual feature for + * dimmers. Many dimmers on the market that is dimmable has no way for sending + * a specific level which means it doesn't support this feature. + * \paragraph devBell devBell() + * Devices supporting \c TELLSTICK_BELL. This is mostly wireless doorbells. + * + * \subsubsection sec_bu_error_codes Error codes + * + * If any of the calls in \ref sec_bu_controlling_functions fails it returns + * a non-zero error code. This values is one of the \c TELLSTICK_ERROR_* defines. + * To translate the error code to a human readable string call the function + * devGetErrorString(). Example: + * \code + * printf("Error: %s\n", devGetErrorString( TELLSTICK_METHOD_NOT_SUPPORTED ) ); + * //Error: The method you tried to use is not supported by the device + * + * int retval = devTurnOn( deviceID ); + * if (retval != TELLSTICK_SUCCESS ) { + * printf("Error: %s\n", devGetErrorString( retval ) ); + * } + * \endcode + * + * \section sec_other_languages Notes using other languages than C/C++ + * + * \subsection sec_ol_java Java + * \subsection sec_ol_net .Net + * \subsection sec_ol_php PHP + * \subsection sec_ol_pyhon Python + * + * There is no native Python support for TellStick yet. If you are developing in + * Windows you can load the TellStick ActiveX and then access the Telldus + * TellStick SDK. + * + * \subsection sec_ol_visualbasic Visual Basic + * + * Include the file \c TellStick.bas to your project and all of the functions + * will be available. + */ From 8845ef5ab66055ef5f1aaa612b3934fffae7d0d3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 15 Sep 2008 09:48:05 +0000 Subject: [PATCH 0123/2215] Typo in docs --- docs/telldus-core.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/telldus-core.txt b/docs/telldus-core.txt index b4e4f511..b267dffb 100644 --- a/docs/telldus-core.txt +++ b/docs/telldus-core.txt @@ -79,7 +79,7 @@ * if ( methods & TELLSTICK_TURNOFF ) { * printf( "The device %d supports devTurnOff()\n", id ); * } - * if ( methods & TELLSTICK_TURNBELL ) { + * if ( methods & TELLSTICK_BELL ) { * printf( "The device %d supports devBell()\n", id ); * } * } From f9d5a302a360b119bee2bad32057315525f1b44b Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Mon, 15 Sep 2008 21:21:06 +0000 Subject: [PATCH 0124/2215] --- tellstickcontroller/examples/power_off_all_lights | 1 + tellstickcontroller/examples/power_on_all_lights | 1 + tellstickcontroller/tellstickController | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tellstickcontroller/examples/power_off_all_lights b/tellstickcontroller/examples/power_off_all_lights index b0b353d3..a1598783 100755 --- a/tellstickcontroller/examples/power_off_all_lights +++ b/tellstickcontroller/examples/power_off_all_lights @@ -9,4 +9,5 @@ tellstickController --set kitchen_cabinets off tellstickController --set livingroom_cabinets off tellstickController --set livingroom_uplight off tellstickController --set livingroom_walls off +tellstickController --set livingroom_mythtv_leds off diff --git a/tellstickcontroller/examples/power_on_all_lights b/tellstickcontroller/examples/power_on_all_lights index decbc4e6..97a2fd6e 100755 --- a/tellstickcontroller/examples/power_on_all_lights +++ b/tellstickcontroller/examples/power_on_all_lights @@ -9,4 +9,5 @@ tellstickController --set kitchen_cabinets on tellstickController --set livingroom_cabinets on tellstickController --set livingroom_uplight on tellstickController --set livingroom_walls on +tellstickController --set livingroom_mythtv_leds on diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index 8f2b64ce..26256721 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -649,8 +649,8 @@ sub get_rule_datetime($$$$) { $time->set_time_zone("UTC"); $time->add(hours => $hours+24*$days, minutes => $minutes); $time->set_time_zone($cfg_set{"timezone"}); - println "days='$days', hours='$hours', minutes='$minutes'"; - println "time='$time'"; +# println "days='$days', hours='$hours', minutes='$minutes'"; +# println "time='$time'"; } else { $time = undef; } From b163e8a9faab648a1d655d0ebee21da61f0d177b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 16 Sep 2008 19:05:04 +0000 Subject: [PATCH 0125/2215] Small typos and fixes in the documentation --- docs/telldus-core.txt | 20 +++++++++---------- .../driver/TellUsbD101/TellUsbD101.cpp | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/telldus-core.txt b/docs/telldus-core.txt index b267dffb..5627f9bb 100644 --- a/docs/telldus-core.txt +++ b/docs/telldus-core.txt @@ -68,43 +68,43 @@ * * TellStick can control many different types of devices and they * all support different features. For example, a bell doesn't support turning - * on and not all lamp switches supports dimming. - * To find out what a specific device supports call devMethods(): + * on and not all lamp switches support dimming. + * To find out what a specific device support call devMethods(): * \code * function checkFeatures( int id ) { * int methods = devMethods( id ); * if ( methods & TELLSTICK_TURNON ) { - * printf( "The device %d supports devTurnOn()\n", id ); + * printf( "The device %d support devTurnOn()\n", id ); * } * if ( methods & TELLSTICK_TURNOFF ) { - * printf( "The device %d supports devTurnOff()\n", id ); + * printf( "The device %d support devTurnOff()\n", id ); * } * if ( methods & TELLSTICK_BELL ) { - * printf( "The device %d supports devBell()\n", id ); + * printf( "The device %d support devBell()\n", id ); * } * } * \endcode * - * When you know which fetures a device supports it is safe to call the + * When you know which fetures a device support it is safe to call the * controlling functions described in \ref sec_bu_controlling_functions. * * \subsubsection sec_bu_controlling_functions Controlling functions * * TellStick has a couple of functions for controlling the devices. Each of - * them should only be called if the device supports the feature. + * them should only be called if the device support the feature. * * These functions all returns zero if the call was successfull and non-zero * otherwise. * * \paragraph devTurnOn devTurnOn() * Devices supporting \c TELLSTICK_TURNON. Most of the normal switches (for lamp - * etc.) supports this. + * etc.) support this. * \paragraph devTurnOff devTurnOff() * Devices supporting \c TELLSTICK_TURNOFF. Almost all of the devices supporting - * \c TELLSTICK_TURNON also supports this. + * \c TELLSTICK_TURNON also support this. * \paragraph devDim devDim() * Devices supporting \c TELLSTICK_DIM. This is a quite unusual feature for - * dimmers. Many dimmers on the market that is dimmable has no way for sending + * dimmers. Many dimmers on the market that are dimmable have no way for sending * a specific level which means it doesn't support this feature. * \paragraph devBell devBell() * Devices supporting \c TELLSTICK_BELL. This is mostly wireless doorbells. diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index fa93c2bd..86ad0456 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -31,23 +31,23 @@ using namespace std; * Device-flag for devices supporting the devBell() call. * * @def TELLSTICK_TOGGLE - * This method is currently unimplemented + * This method is currently unimplemented. * * @def TELLSTICK_DIM * Device-flag for devices supporting the devDim() call. * * @def TELLSTICK_SUCCESS - * Error code. Returned when the command succeeded + * Error code. Returned when the command succeeded. * * @def TELLSTICK_ERROR_NOT_FOUND * Error code. Returned if a TellStick was not found on the system. * * @def TELLSTICK_ERROR_PERMISSION_DENIED * Error code. Returned if the user doesn't have privileges to open - * the TellStick device + * the TellStick device. * * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND - * Error code. The supplied device id was not found + * Error code. The supplied device id was not found. * * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED * Error code. The requested method is not supported device. From f436498dcfc0b22e10ec81568808ee0f881cade4 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Tue, 16 Sep 2008 20:50:15 +0000 Subject: [PATCH 0126/2215] Added support for more than one tellstick sender --- tellstickcontroller/Readme | 5 +- .../examples/tellstickController.conf | 46 ++++++++++--------- tellstickcontroller/tellstickController | 15 +++--- tellstickcontroller/tellstickController.conf | 16 ++++--- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/tellstickcontroller/Readme b/tellstickcontroller/Readme index 4bddaf1a..78f63965 100644 --- a/tellstickcontroller/Readme +++ b/tellstickcontroller/Readme @@ -1,4 +1,3 @@ - NAME tellstickController @@ -20,7 +19,7 @@ -d, --daemon Starts in daemon mode. -f, --file F Set configfile to file F. -g, --get D Get state for device D. - -h, --help Print short help text. + -h, --help Print this help text. -l, --list List states for all devices. -s, --set D S Set device D to state S. -t, --test Test mode, no real devices will used. @@ -76,7 +75,7 @@ LICENSE Copyright (C) 2008 Rickard Andersson - Version 1.3.1 + Version 1.4.0 This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; See license file for details. diff --git a/tellstickcontroller/examples/tellstickController.conf b/tellstickcontroller/examples/tellstickController.conf index a6910f2c..e7e1ab86 100644 --- a/tellstickcontroller/examples/tellstickController.conf +++ b/tellstickcontroller/examples/tellstickController.conf @@ -3,7 +3,7 @@ # Configuration file for tellstickController # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version: 1.3.2 +# Version: 1.4.0 # ################################################################################ # @@ -40,23 +40,23 @@ Set logfile /var/log/tellstickController.log # Aliases for recevier devices. # # Usage example: -# Alias Name Dimmer Protocol Housecode Channel -# Alias BedroomWindow yes Nexa A 1 -# Alias device42 No Waveman B 3 +# Alias Name Sender Dimmer Protocol Housecode Channel +# Alias BedroomWindow /dev/tellstick0 yes Nexa A 1 +# Alias device42 /dev/tellstick1 No Waveman B 3 # or # Usage example: -# Alias Name Dimmer Protocol Channel -# Alias MythTv_Backlight No Sartano 000000001 +# Alias Name Sender Dimmer Protocol Channel +# Alias MythTv_Backlight /dev/ttyUSB0 No Sartano 000000001 # # -Alias kitchen_cabinets No Nexa G 2 -Alias Bedroom_window No Nexa G 1 -Alias Bedroom_mythtv_power No Nexa G 6 -Alias Bedroom_mythtv_leds No Nexa G 7 -Alias Livingroom_cabinets No Nexa G 3 -Alias Livingroom_walls No Nexa G 4 -Alias Livingroom_uplight No Nexa G 5 -Alias Livingroom_mythtv_leds Yes Nexa G 8 +Alias kitchen_cabinets /dev/tellstick0 No Nexa G 2 +Alias Bedroom_window /dev/tellstick0 No Nexa G 1 +Alias Bedroom_mythtv_power /dev/tellstick0 No Nexa G 6 +Alias Bedroom_mythtv_leds /dev/tellstick0 No Nexa G 7 +Alias Livingroom_cabinets /dev/tellstick0 No Nexa G 3 +Alias Livingroom_walls /dev/tellstick0 No Nexa G 4 +Alias Livingroom_uplight /dev/tellstick0 Yes Nexa G 5 +Alias Livingroom_mythtv_leds /dev/tellstick0 No Nexa G 8 # Timer rules for reciever devices. @@ -68,14 +68,18 @@ Alias Livingroom_mythtv_leds Yes Nexa G 8 # Rule MythTv_Backlight Weekend/20:00 Weekend/Sunset # # -Rule Bedroom_window Workweek/sunrise-00:30 Workweek/Sunrise+01:00 -Rule Bedroom_window Sunset+Random(00:30) 00:00+Random(00:30) +Rule Bedroom_window Workweek/sunrise+02:00 Workweek/Sunrise+03:00 +Rule Bedroom_window Sunset-Random(00:30) 00:00+Random(00:30) +Rule Bedroom_window No 02:00 Rule Bedroom_mythtv_leds No 02:00 -Rule kitchen_cabinets Sunrise-00:30 Sunrise+01:00 -Rule kitchen_cabinets Workweek/Sunset Workweek/00:00+Random(00:30) -Rule kitchen_cabinets Weekend/Sunset-01:00 Weekend/00:30+Random(00:30) -Rule Livingroom_cabinets Sunset+01:00+Random(00:30) 00:15+Random(00:30) -Rule Livingroom_walls Sunset+Random(00:30) 00:15+Random(00:30) +Rule Kitchen_cabinets Sunrise+01:00 Sunrise+03:00 +Rule Kitchen_cabinets Workweek/Sunset-01:00 Workweek/00:00+Random(00:30) +Rule Kitchen_cabinets Weekend/Sunset-01:00 Weekend/00:30+Random(00:30) +Rule Kitchen_cabinets No 02:00 +Rule Livingroom_cabinets Sunset-Random(00:30) 00:15+Random(00:30) +Rule Livingroom_cabinets No 02:00 +Rule Livingroom_walls Sunset-Random(00:30) 00:15+Random(00:30) +Rule Livingroom_walls No 02:00 Rule Livingroom_uplight No 02:00 Rule Livingroom_mythtv_leds No 02:00 diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index 26256721..74e4cc8b 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -4,7 +4,7 @@ # tellstickController program # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version 1.3.2 +# Version 1.4.0 # ###################################################################### # @@ -46,7 +46,6 @@ my %cfg_set = ( "dbfile" => "/var/lib/tellstickController.db", "logfile" => "/var/log/tellstickController.log", "pidfile" => "/var/run/tellstickController.pid", - "device" => "/dev/tellstick", "program" => "/usr/local/bin/rfcmd", "altitude" => "-0.833", "latitude" => "58.24", @@ -313,12 +312,13 @@ sub read_config($) { if ($line =~ /^Alias\s+/i) { #println $line if ($option{"verbose"}); - my (undef, $name, $dimmer, $prot, $code, $addr, $suffix) + my (undef, $name, $sender, $dimmer, $prot, $code, $addr, $suffix) = split(/\s+/, $line); if (defined($suffix)) { println "Wrong argument '$suffix' in line '$line'!"; } else { $name = lc($name); + $sender = $sender; $dimmer = lc($dimmer); $prot = uc($prot); $code = uc($code); @@ -328,7 +328,7 @@ sub read_config($) { if ($prot =~ /^NEXA|WAVEMAN$/) { if ($code =~ /^[A-P]$/) { if ($addr =~ /^[1-9]{1}|1{1}[0-6]{1}$/) { - $cfg_alias{$name} = "$prot $code $addr"; + $cfg_alias{$name} = "$sender $prot $code $addr"; } else { println "Wrong channel '$addr' in line '$line'!"; } @@ -338,7 +338,7 @@ sub read_config($) { } elsif ($prot =~ /^SARTANO$/) { if ($code =~ /^[01]{10}$/) { if ($addr eq "") { - $cfg_alias{$name} = "$prot $code"; + $cfg_alias{$name} = "$sender $prot $code"; } else { println "Wrong argument '$addr' in line '$line'!"; } @@ -447,8 +447,7 @@ sub call_program($$) { $mode = 1; } my $prog = $cfg_set{"program"}; - my $dev = $cfg_set{"device"}; - my $command = "$prog $dev $alias $mode"; + my $command = "$prog $alias $mode"; my $text = "Executing command: '$command'"; println $text if ($option{"verbose"}); system($command); @@ -932,7 +931,7 @@ __DATA__ #- #- LICENSE #- Copyright (C) 2008 Rickard Andersson -#- Version 1.3.2 +#- Version 1.4.0 #- This program comes with ABSOLUTELY NO WARRANTY. #- This is free software, and you are welcome to redistribute it #- under certain conditions; See license file for details. diff --git a/tellstickcontroller/tellstickController.conf b/tellstickcontroller/tellstickController.conf index 452bb59e..6eaca340 100644 --- a/tellstickcontroller/tellstickController.conf +++ b/tellstickcontroller/tellstickController.conf @@ -3,7 +3,7 @@ # Configuration file for tellstickController # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version: 1.3.2 +# Version: 1.4.0 # ################################################################################ # @@ -41,18 +41,20 @@ Set logfile /var/log/tellstickController.log # Aliases for recevier devices. # # Usage example: -# Alias Name Dimmer Protocol Housecode Channel +# Alias Name Sender Dimmer Protocol Housecode Channel +# +# Alias BedroomWindow /dev/tellstick0 yes Nexa A 1 +# Alias device42 /dev/tellstick1 No Waveman B 3 # -# Alias BedroomWindow yes Nexa A 1 -# Alias device42 No Waveman B 3 # or +# # Usage example: -# Alias Name Dimmer Protocol Channel +# Alias Name Sender Dimmer Protocol Channel # -# Alias MythTv_Backlight No Sartano 000000001 +# Alias MythTv_Backlight /dev/ttyUSB0 No Sartano 000000001 # # -Alias device1 No Nexa A 1 +Alias device1 /dev/tellstick No Nexa A 1 # Timer rules for reciever devices. From 946c0d15a13a63df90aef3b8f6eecaa3bed6722c Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 22 Sep 2008 17:40:36 +0000 Subject: [PATCH 0127/2215] Fixed a bug regarding sunset off/on times when not working when set to 0. /Magnus Juntti --- tellstickd/tellstickd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index e2d93183..49630816 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -45,7 +45,7 @@ my $dayOfWeek; my $dayOfMonth; my $PROGRAM_NAME = "tellstickd"; -my $VERSION = "0.6.2"; +my $VERSION = "pre 0.6.3"; # Structure of the configurations to be read; # $device_cfg[$i][0]; # Protocol, only NEXA, WAVEMAN and SARTANO supported so far by rfcmd @@ -479,7 +479,7 @@ sub read_config # $inrad[5] is the off post sunrise value including sign, $inrad[6] is the on pre sunrise value sign, - if ($inrad[5] && $inrad[6]) { + if (length($inrad[5]) > 0 && length($inrad[6]) > 0) { # Found a parameter after off interval, assuming daytime switch off is sought. $device_cfg[$i][5] = 1; From d89fd8da8eb0332a29d768ffc6dbde354929a97f Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Mon, 22 Sep 2008 17:43:00 +0000 Subject: [PATCH 0128/2215] Fixed very minor formatting issue. --- tellstickd/tellstickd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 49630816..5695bf44 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -794,7 +794,7 @@ while (1) { # Sunset time - requested offset $device_cfg[$i][21] = subtract_time($sunset_time, $device_cfg[$i][7]); if (is_rule_valid_today($i, $now) == $YES) { - printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n\n"); + printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); } } elsif (is_rule_valid_today($i, $now) == $YES) { From 6d967c6f3be8d8b99d7201486f1a98f926f2b27f Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Tue, 23 Sep 2008 10:18:02 +0000 Subject: [PATCH 0129/2215] Cosmetic change regarding formatting in log-file. --- tellstickd/tellstickd | 3 --- 1 file changed, 3 deletions(-) diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index 5695bf44..b48ff72f 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -797,9 +797,6 @@ while (1) { printf("$PROGRAM_NAME: Device $device_cfg[$i][0] $device_cfg[$i][1]$device_cfg[$i][2] sunset on time set to $device_cfg[$i][21].\n"); } } - elsif (is_rule_valid_today($i, $now) == $YES) { - printf("\n"); - } } } From 199143ec7cc785b03ec316a7cfed0979c3f85e4c Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Mon, 6 Oct 2008 19:49:18 +0000 Subject: [PATCH 0130/2215] Added VisualBasic example --- .../example/TellStick VB-example - simple.frm | 212 ++++++++++++++++++ .../example/TellStick VB-example - simple.frx | Bin 0 -> 10536 bytes .../example/TellStick VB-example - simple.vbp | 36 +++ 3 files changed, 248 insertions(+) create mode 100644 bindings/visual-basic/example/TellStick VB-example - simple.frm create mode 100644 bindings/visual-basic/example/TellStick VB-example - simple.frx create mode 100644 bindings/visual-basic/example/TellStick VB-example - simple.vbp diff --git a/bindings/visual-basic/example/TellStick VB-example - simple.frm b/bindings/visual-basic/example/TellStick VB-example - simple.frm new file mode 100644 index 00000000..04aa7196 --- /dev/null +++ b/bindings/visual-basic/example/TellStick VB-example - simple.frm @@ -0,0 +1,212 @@ +VERSION 5.00 +Begin VB.Form frmMain + BorderStyle = 4 'Fixed ToolWindow + Caption = "TellStick VB-example - simple" + ClientHeight = 4680 + ClientLeft = 2040 + ClientTop = 3600 + ClientWidth = 3990 + Icon = "TellStick VB-example - simple.frx":0000 + LinkTopic = "Form1" + MaxButton = 0 'False + MinButton = 0 'False + ScaleHeight = 4680 + ScaleWidth = 3990 + ShowInTaskbar = 0 'False + Begin VB.CommandButton cmdDim + Caption = "90%" + Height = 465 + Index = 8 + Left = 3480 + TabIndex = 12 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "80%" + Height = 465 + Index = 7 + Left = 3060 + TabIndex = 11 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "70%" + Height = 465 + Index = 6 + Left = 2640 + TabIndex = 10 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "60%" + Height = 465 + Index = 5 + Left = 2220 + TabIndex = 9 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "50%" + Height = 465 + Index = 4 + Left = 1800 + TabIndex = 8 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "40%" + Height = 465 + Index = 3 + Left = 1380 + TabIndex = 7 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "30%" + Height = 465 + Index = 2 + Left = 960 + TabIndex = 6 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "20%" + Height = 465 + Index = 1 + Left = 540 + TabIndex = 5 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdDim + Caption = "10%" + Height = 465 + Index = 0 + Left = 120 + TabIndex = 4 + Top = 4110 + Width = 420 + End + Begin VB.CommandButton cmdBell + Caption = "Bell" + Height = 735 + Left = 1500 + Picture = "TellStick VB-example - simple.frx":0ECA + Style = 1 'Graphical + TabIndex = 3 + Top = 3285 + Width = 1000 + End + Begin VB.ListBox deviceList + Height = 3180 + Left = 60 + TabIndex = 2 + Top = 60 + Width = 3810 + End + Begin VB.CommandButton cmdOff + Caption = "Off" + Height = 735 + Left = 120 + Picture = "TellStick VB-example - simple.frx":1794 + Style = 1 'Graphical + TabIndex = 1 + Top = 3285 + Width = 1000 + End + Begin VB.CommandButton cmdOn + Caption = "On" + Height = 735 + Left = 2900 + Picture = "TellStick VB-example - simple.frx":205E + Style = 1 'Graphical + TabIndex = 0 + Top = 3285 + Width = 1000 + End +End +Attribute VB_Name = "frmMain" +Attribute VB_GlobalNameSpace = False +Attribute VB_Creatable = False +Attribute VB_PredeclaredId = True +Attribute VB_Exposed = False +Private Sub cmdBell_Click() + Dim blnBell As Boolean + blnBell = devBell(deviceList.ItemData(deviceList.ListIndex)) +End Sub + +Private Sub cmdDim_Click(Index As Integer) + Dim blnDim As Boolean + Dim level As Byte + Select Case Index + Case "8" + level = 230 + Case "7" + level = 204 + Case "6" + level = 179 + Case "5" + level = 153 + Case "4" + level = 128 + Case "3" + level = 102 + Case "2" + level = 77 + Case "1" + level = 51 + Case "0" + level = 25 + End Select + blnDim = devDim(deviceList.ItemData(deviceList.ListIndex), level) +End Sub + +Private Sub cmdOff_Click() + Dim blnOff As Boolean + blnOff = devTurnOff(deviceList.ItemData(deviceList.ListIndex)) +End Sub + +Private Sub cmdOn_Click() + Dim blnOn As Boolean + blnOn = devTurnOn(deviceList.ItemData(deviceList.ListIndex)) +End Sub + +Private Sub deviceList_Click() + Dim intMethods As Integer + + intMethods = devMethods(deviceList.ItemData(deviceList.ListIndex)) + cmdOn.Enabled = (intMethods And TELLSTICK_TURNON) + cmdOff.Enabled = (intMethods And TELLSTICK_TURNOFF) + cmdBell.Enabled = (intMethods And TELLSTICK_BELL) + + For a = 0 To 8 + cmdDim(a).Enabled = (intMethods And TELLSTICK_DIM) + Next + +End Sub + +Private Sub Form_Load() + + Dim numDevices As Integer, i As Integer + numDevices = devGetNumberOfDevices() + + For i = 0 To numDevices - 1 + Dim strName As String + Dim intId As Integer + + intId = devGetDeviceId(i) + strName = devGetName(intId) + deviceList.AddItem strName + deviceList.ItemData(i) = intId + Next + + deviceList.ListIndex = 0 + +End Sub diff --git a/bindings/visual-basic/example/TellStick VB-example - simple.frx b/bindings/visual-basic/example/TellStick VB-example - simple.frx new file mode 100644 index 0000000000000000000000000000000000000000..aae195101e78bce0cb21f1153f636ec56e084b3c GIT binary patch literal 10536 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 T^P1~NF& Date: Tue, 7 Oct 2008 13:03:07 +0000 Subject: [PATCH 0131/2215] Added files LICENSE, AUTHORS, INSTALL and README to Telldus Core --- telldus-core/AUTHORS | 7 + telldus-core/INSTALL | 51 +++++++ telldus-core/LICENSE | 339 +++++++++++++++++++++++++++++++++++++++++++ telldus-core/README | 30 ++++ 4 files changed, 427 insertions(+) create mode 100644 telldus-core/AUTHORS create mode 100644 telldus-core/INSTALL create mode 100644 telldus-core/LICENSE create mode 100644 telldus-core/README diff --git a/telldus-core/AUTHORS b/telldus-core/AUTHORS new file mode 100644 index 00000000..a8356907 --- /dev/null +++ b/telldus-core/AUTHORS @@ -0,0 +1,7 @@ +telldus-core has been developed by : + + Micke Prag + Fredrik Jacobsson + Stefan Persson + +The package is maintained by Micke Prag \ No newline at end of file diff --git a/telldus-core/INSTALL b/telldus-core/INSTALL new file mode 100644 index 00000000..9d2b0b4a --- /dev/null +++ b/telldus-core/INSTALL @@ -0,0 +1,51 @@ +Unpacking +--------- + +Unpack the archive if you have not done so already: + + cd /usr/src + gunzip telldus-core-{version}.tar.gz #Change {version} to the downloaded version + tar xvf telldus-core-{version}.tar + +This creates the directory /usr/src/telldus-core-{version} containing the files +from the archive. We only support the GNU version of tar archiving utility. Note +on some systems it is called gtar. + +Configuring +----------- + +Telldus Core is built using CMake (http://www.cmake.org), version 2.4.0 is the +minimum required version. This means there is no configure-script, but you +need to run cmake. + +To configure telldus-core for your machine type: + + cmake . + +in the package directory. + +By default, Telldus Core is configured for installation in the /usr/local +directory, but this can be changed by using the -DCMAKE_INSTALL_PREFIX=/usr +option. Alternatively, the DESTDIR="/opt" option can be used to specify a "local" +installation within the source directory when running "make install". + +Building +-------- + +To create the library and compile all the tools type: + + make + +If you did not configure Telldus Core using the -DCMAKE_INSTALL_PREFIX=/usr +option, you need to install the library and tools in the appropriate place. To +do this, type: + + su -c "make install" + +and enter the root password. + +If you want to install in another directory, type: + + su -c "make DESTDIR=/opt install" + +Note that on some systems the make utility is named differently, e.g. gmake. diff --git a/telldus-core/LICENSE b/telldus-core/LICENSE new file mode 100644 index 00000000..82fa1daa --- /dev/null +++ b/telldus-core/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/telldus-core/README b/telldus-core/README new file mode 100644 index 00000000..5778ee2b --- /dev/null +++ b/telldus-core/README @@ -0,0 +1,30 @@ +This is Telldus Core version {version} + +Telldus Core is the driver and tools for controlling a Telldus Technologies +TellStick. It does not containing any GUI tools which makes it suitable for +server use. + + +INSTALLING Telldus Core + +On Windows, if you want to install the precompiles binary packages, simply +launch the package and follow the instructions in the installation wizard. + +If you have a source package (a .tag.gz file), follow the instruction in the +INSTALL file. + + +CONFIGURATION AND TOOLS + +Once Telldus Core is installed, we suggest that you start by adding the devices +you want to control. + +On Windows, this is done with the tool TelldusSetup. On Linux this is done in +the file /etc/tellstick.conf. + +Telldus Core installs the tool tdtool for controlling devices with TellStick. +Have a look in the man page for a description how to use it: + + man tdtool + +TellStick is a trademark of Telldus Technologies AB From e6ab48a4f8e181ced1a253a395296de1d5e655c7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 7 Oct 2008 14:11:38 +0000 Subject: [PATCH 0132/2215] Changed help text to work with the tool help2man --- telldus-core/tdtool/main.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index d63c2e31..3cf19165 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -9,14 +9,15 @@ #endif void print_usage( char *name ) { - printf("Usage:\n"); - printf(" %s [ options ]\n", name); + printf("\"tdtool\" is a command line utility to control a Telldus TellStick\n"); printf("\n"); - printf("Options: -[bdfhlnv] [--list] [--help]\n"); - printf(" [--on device] [--off device] [--bell device]\n"); - printf(" [--dimlevel level --dim device]\n"); + printf("Usage: %s [ options ]\n", name); printf("\n"); printf("Options:\n"); + printf(" -[bdfhlnv] [ --list ] [ --help ]\n"); + printf(" [ --on device ] [ --off device ] [ --bell device ]\n"); + printf(" [ --dimlevel level --dim device ]\n"); + printf("\n"); printf(" --list (-l short option)\n"); printf(" List currently configured devices.\n"); printf("\n"); @@ -48,6 +49,14 @@ void print_usage( char *name ) { printf(" either be an integer of the device-id, or the name of the device.\n"); printf(" Both device-id and name is outputed with the --list option\n"); printf("\n"); + printf("Written by Micke Prag \n"); + printf("Report bugs to \n"); + printf("\n"); + printf("Copyright (C) 2008 Telldus Technologies AB\n"); +} + +void print_version() { + printf("tdtool 2.0\n"); } void print_device( int index ) { @@ -135,7 +144,7 @@ void bell_device( char *device ) { int main(int argc, char **argv) { int optch, longindex; - static char optstring[] = "ln:f:d:b:v:h"; + static char optstring[] = "ln:f:d:b:v:hi"; static struct option long_opts[] = { { "list", 0, 0, 'l' }, { "on", 1, 0, 'n' }, @@ -143,7 +152,8 @@ int main(int argc, char **argv) { "dim", 1, 0, 'd' }, { "bell", 1, 0, 'b' }, { "dimlevel", 1, 0, 'v' }, - { "help", 1, 0, 'h' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'i'}, { 0, 0, 0, 0} }; int level = -1; @@ -169,6 +179,9 @@ int main(int argc, char **argv) case 'h' : print_usage( argv[0] ); break; + case 'i' : + print_version( ); + break; case 'l' : list_devices(); break; From d1e79e6195e8735237921c6fc4efc575e4a22759 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Oct 2008 12:56:44 +0000 Subject: [PATCH 0133/2215] Moved rfcmd into telldus-core --- {rfcmd => telldus-core/rfcmd}/CMakeLists.txt | 0 {rfcmd => telldus-core/rfcmd}/COPYING | 0 {rfcmd => telldus-core/rfcmd}/Makefile | 0 {rfcmd => telldus-core/rfcmd}/build.sh | 0 {rfcmd => telldus-core/rfcmd}/rfcmd.c | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) rename {rfcmd => telldus-core/rfcmd}/CMakeLists.txt (100%) rename {rfcmd => telldus-core/rfcmd}/COPYING (100%) rename {rfcmd => telldus-core/rfcmd}/Makefile (100%) rename {rfcmd => telldus-core/rfcmd}/build.sh (100%) rename {rfcmd => telldus-core/rfcmd}/rfcmd.c (99%) diff --git a/rfcmd/CMakeLists.txt b/telldus-core/rfcmd/CMakeLists.txt similarity index 100% rename from rfcmd/CMakeLists.txt rename to telldus-core/rfcmd/CMakeLists.txt diff --git a/rfcmd/COPYING b/telldus-core/rfcmd/COPYING similarity index 100% rename from rfcmd/COPYING rename to telldus-core/rfcmd/COPYING diff --git a/rfcmd/Makefile b/telldus-core/rfcmd/Makefile similarity index 100% rename from rfcmd/Makefile rename to telldus-core/rfcmd/Makefile diff --git a/rfcmd/build.sh b/telldus-core/rfcmd/build.sh similarity index 100% rename from rfcmd/build.sh rename to telldus-core/rfcmd/build.sh diff --git a/rfcmd/rfcmd.c b/telldus-core/rfcmd/rfcmd.c similarity index 99% rename from rfcmd/rfcmd.c rename to telldus-core/rfcmd/rfcmd.c index aaf80032..bdf6b42b 100644 --- a/rfcmd/rfcmd.c +++ b/telldus-core/rfcmd/rfcmd.c @@ -43,7 +43,7 @@ #include #define PROG_NAME "rfcmd" -#define PROG_VERSION "0.3" +#define PROG_VERSION "2.0" /* #define RFCMD_DEBUG */ /* Local function declarations */ From d2f81b089deba182b5323018d225e10841a81849 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Oct 2008 10:23:45 +0000 Subject: [PATCH 0134/2215] Fixed some possible memory leaks --- telldus-core/CMakeLists.txt | 1 + telldus-core/driver/TellUsbD101/Device.cpp | 9 ++++++ telldus-core/driver/TellUsbD101/Device.h | 2 +- .../driver/TellUsbD101/TellUsbD101.cpp | 19 ++++++++---- .../TellUsbD101/settings/TelldusSettings.cpp | 13 ++++++++- .../settings/TelldusSettingsConfuse.cpp | 5 ++-- telldus-core/tdtool/main.cpp | 29 ++++++++++++------- 7 files changed, 58 insertions(+), 20 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 1d042060..4ae8d1f2 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -8,4 +8,5 @@ endif(COMMAND cmake_policy) ADD_SUBDIRECTORY(driver) ADD_SUBDIRECTORY(tdtool) +ADD_SUBDIRECTORY(rfcmd) diff --git a/telldus-core/driver/TellUsbD101/Device.cpp b/telldus-core/driver/TellUsbD101/Device.cpp index fdf4abb4..cb10dc6a 100644 --- a/telldus-core/driver/TellUsbD101/Device.cpp +++ b/telldus-core/driver/TellUsbD101/Device.cpp @@ -1,10 +1,14 @@ #include "Device.h" +#include /* * Constructor */ Device::Device() { +#ifdef _LINUX + strDevice = 0; +#endif } /* @@ -12,6 +16,11 @@ Device::Device() */ Device::~Device(void) { +#ifdef _LINUX + if (strDevice != 0) { + free(strDevice); + } +#endif } /* diff --git a/telldus-core/driver/TellUsbD101/Device.h b/telldus-core/driver/TellUsbD101/Device.h index d4860ccf..77c0a116 100644 --- a/telldus-core/driver/TellUsbD101/Device.h +++ b/telldus-core/driver/TellUsbD101/Device.h @@ -14,7 +14,7 @@ public: virtual int dim(unsigned char level); virtual int methods(char* strModel); -#ifndef _WINDOWS +#ifdef _LINUX void setDevice(const char *device); protected: char *strDevice; diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index 86ad0456..466e0008 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -75,7 +75,10 @@ int WINAPI devTurnOn(int intDeviceId){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - int methods = dev->methods( ts.getModel( intDeviceId ) ); + char *model = ts.getModel( intDeviceId ); + int methods = dev->methods( model ); + free(model); + int retval = 0; if ( !(methods & TELLSTICK_TURNON) ) { @@ -109,7 +112,9 @@ int WINAPI devTurnOff(int intDeviceId){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - int methods = dev->methods( ts.getModel( intDeviceId ) ); + char *model = ts.getModel( intDeviceId ); + int methods = dev->methods( model ); + free(model); int retval = 0; if ( !(methods & TELLSTICK_TURNOFF) ) { @@ -143,7 +148,9 @@ int WINAPI devBell(int intDeviceId){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - int methods = dev->methods( ts.getModel( intDeviceId ) ); + char *model = ts.getModel( intDeviceId ); + int methods = dev->methods( model ); + free(model); int retval = 0; if ( !(methods & TELLSTICK_BELL) ) { @@ -177,7 +184,9 @@ int WINAPI devDim(int intDeviceId, unsigned char level){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - int methods = dev->methods( ts.getModel( intDeviceId ) ); + char *model = ts.getModel( intDeviceId ); + int methods = dev->methods( model ); + free(model); int retval = 0; if ( !(methods & TELLSTICK_DIM) ) { @@ -451,7 +460,7 @@ char * WINAPI devGetErrorString(int intErrorNo) { strReturn = "Unknown error"; } else { // Copy the error string to strReturn - strReturn = (char *)malloc( sizeof(char) * strlen(responses[intErrorNo]) ); + strReturn = (char *)malloc( sizeof(char) * (strlen(responses[intErrorNo])+1) ); strcpy( strReturn, responses[intErrorNo] ); } diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp index 04b0888a..8e57ad36 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -4,6 +4,7 @@ #include "../DeviceSartano.h" #include "../DeviceIkea.h" #include +#include /* * Get the requested device @@ -21,25 +22,35 @@ Device* TelldusSettings::getDevice(int intDeviceId){ char *strHouse = getArgument(intDeviceId, "nexa_house"); char *strCode = getArgument(intDeviceId, "nexa_unit"); dev = new DeviceNexa(strHouse, strCode); - + free(strHouse); + free(strCode); + } else if (strcmp(vendor, "Waveman") == 0) { char *strHouse = getArgument(intDeviceId, "nexa_house"); char *strCode = getArgument(intDeviceId, "nexa_unit"); dev = new DeviceWaveman(strHouse, strCode); + free(strHouse); + free(strCode); } else if (strcmp(vendor, "Sartano") == 0) { char *strCode = getArgument(intDeviceId, "sartano_code"); dev = new DeviceSartano(strCode); + free(strCode); } else if (strcmp(vendor, "Ikea") == 0) { char *strSystem = getArgument(intDeviceId, "ikea_system"); char *strUnits = getArgument(intDeviceId, "ikea_units"); char *strFade = getArgument(intDeviceId, "ikea_fade"); dev = new DeviceIkea(strSystem, strUnits, strFade); + free(strSystem); + free(strUnits); + free(strFade); } else { + free(vendor); return NULL; } + free(vendor); #ifdef _LINUX dev->setDevice( getSetting("deviceNode") ); diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp index 4fac5f8e..583c4072 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp @@ -32,8 +32,6 @@ TelldusSettings::TelldusSettings(void) { d = new privateVars(); readConfig(&d->cfg); -// printf("Nu: %d\n", cfg_size(d->cfg, "device")); - } /* @@ -43,6 +41,7 @@ TelldusSettings::~TelldusSettings(void) { if (d->cfg > 0) cfg_free(d->cfg); + delete d; } /* @@ -175,7 +174,7 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool if (strSetting == NULL) { return NULL; } - char *strReturn = (char *)malloc(strlen(strSetting) * sizeof(char)); + char *strReturn = (char *)malloc((strlen(strSetting)+1) * sizeof(char)); strcpy(strReturn, strSetting); return strReturn; } diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 3cf19165..056de9b6 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -50,19 +50,21 @@ void print_usage( char *name ) { printf(" Both device-id and name is outputed with the --list option\n"); printf("\n"); printf("Written by Micke Prag \n"); - printf("Report bugs to \n"); printf("\n"); printf("Copyright (C) 2008 Telldus Technologies AB\n"); } void print_version() { printf("tdtool 2.0\n"); + printf("\n"); + printf("Report bugs to \n"); } void print_device( int index ) { int intId = devGetDeviceId(index); char *name = devGetName(intId); printf("%i\t%s\n", intId, name); + free(name); } void list_devices() { @@ -85,8 +87,10 @@ int find_device( char *device ) { char *name = devGetName( id ); if (strcasecmp(name, device) == 0) { deviceId = id; + free(name); break; } + free(name); index++; } } @@ -101,13 +105,12 @@ void switch_device( bool turnOn, char *device ) { } char *name = devGetName( deviceId ); - if (turnOn) { - int retval = devTurnOn( deviceId ); - printf("Turning on device: %i %s - %s\n", deviceId, name, devGetErrorString(retval)); - } else { - int retval = devTurnOff( deviceId ); - printf("Turning off device: %i %s - %s\n", deviceId, name, devGetErrorString(retval)); - } + int retval = (turnOn ? devTurnOn( deviceId ) : devTurnOff( deviceId )); + char *errorString = devGetErrorString(retval); + + printf("Turning %s device: %i %s - %s\n", (turnOn ? "on" : "off"), deviceId, name, errorString); + free(name); + free(errorString); sleep(1); } @@ -124,7 +127,10 @@ void dim_device( char *device, int level ) { char *name = devGetName( deviceId ); int retval = devDim( deviceId, (unsigned char)level ); - printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, devGetErrorString(retval)); + char *errorString = devGetErrorString(retval); + printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); + free(name); + free(errorString); sleep(1); } @@ -137,7 +143,10 @@ void bell_device( char *device ) { char *name = devGetName( deviceId ); int retval = devBell( deviceId ); - printf("Sending bell to: %i %s - %s\n", deviceId, name, devGetErrorString(retval)); + char *errorString = devGetErrorString(retval); + printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); + free(name); + free(errorString); sleep(1); } From 05013a9074e406dd4e90db69723cd408f55321f9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 16 Oct 2008 13:16:44 +0000 Subject: [PATCH 0135/2215] Fixed segfault if the device is not found --- telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp | 3 +++ .../driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp index 8e57ad36..77b8065e 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp @@ -16,6 +16,9 @@ Device* TelldusSettings::getDevice(int intDeviceId){ try{ char* vendor = getVendor(intDeviceId); + if (vendor == NULL) { + return NULL; + } //each new brand must be added here if (strcmp(vendor, "Nexa") == 0){ diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp index 583c4072..5cefbcb9 100644 --- a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp +++ b/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp @@ -161,7 +161,7 @@ void TelldusSettings::debugLog(int debugint){ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { if (d->cfg == 0) { - return ""; + return NULL; } cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { @@ -179,7 +179,7 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool return strReturn; } } - return ""; + return NULL; } bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { From c865bb0fd64af811d6b68233ba1c313c1429488c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 16 Oct 2008 13:18:21 +0000 Subject: [PATCH 0136/2215] Don't sleep if the function returned an error --- telldus-core/tdtool/main.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 056de9b6..3c322430 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -111,7 +111,9 @@ void switch_device( bool turnOn, char *device ) { printf("Turning %s device: %i %s - %s\n", (turnOn ? "on" : "off"), deviceId, name, errorString); free(name); free(errorString); - sleep(1); + if (retval == TELLSTICK_SUCCESS) { + sleep(1); + } } void dim_device( char *device, int level ) { @@ -131,7 +133,9 @@ void dim_device( char *device, int level ) { printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); free(name); free(errorString); - sleep(1); + if (retval == TELLSTICK_SUCCESS) { + sleep(1); + } } void bell_device( char *device ) { @@ -147,7 +151,9 @@ void bell_device( char *device ) { printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); free(name); free(errorString); - sleep(1); + if (retval == TELLSTICK_SUCCESS) { + sleep(1); + } } int main(int argc, char **argv) From 46ba243c2f13b2decce2125ec7d1deb5f328cdcb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 16 Oct 2008 15:03:03 +0000 Subject: [PATCH 0137/2215] Renamed library TellUsbD101 to TelldusCore and some minor fixes for building on Windows. --- telldus-core/driver/CMakeLists.txt | 12 +- .../CMakeLists.txt | 140 +- .../Device.cpp | 8 +- .../{TellUsbD101 => libtelldus-core}/Device.h | 2 +- .../DeviceIkea.cpp | 4 + .../DeviceIkea.h | 0 .../DeviceNexa.cpp | 0 .../DeviceNexa.h | 0 .../DeviceSartano.cpp | 0 .../DeviceSartano.h | 0 .../DeviceWaveman.cpp | 0 .../DeviceWaveman.h | 0 .../Resource.h | 0 .../libtelldus-core.def} | 2 +- .../libtelldus-core.vcproj} | 33 +- .../linux/Device.cpp | 0 .../settings/TelldusSettings.cpp | 0 .../settings/TelldusSettings.h | 0 .../settings/TelldusSettingsConfuse.cpp | 0 ...lldusSettingsCoreFoundationPreferences.cpp | 0 .../settings/TelldusSettingsWinRegistry.cpp | 0 .../stdafx.cpp | 0 .../{TellUsbD101 => libtelldus-core}/stdafx.h | 0 .../telldus-core.cpp} | 2 +- .../telldus-core.h} | 8 +- .../win/Device.cpp | 13 +- .../win/WinTypes.h | 0 .../win/ftd2xx.h | 1787 ++++++++--------- 28 files changed, 993 insertions(+), 1018 deletions(-) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/CMakeLists.txt (89%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/Device.cpp (68%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/Device.h (87%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceIkea.cpp (93%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceIkea.h (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceNexa.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceNexa.h (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceSartano.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceSartano.h (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceWaveman.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/DeviceWaveman.h (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/Resource.h (100%) rename telldus-core/driver/{TellUsbD101/TellUsbD101.def => libtelldus-core/libtelldus-core.def} (87%) rename telldus-core/driver/{TellUsbD101/TellUsbD101.vcproj => libtelldus-core/libtelldus-core.vcproj} (88%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/linux/Device.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/settings/TelldusSettings.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/settings/TelldusSettings.h (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/settings/TelldusSettingsConfuse.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/settings/TelldusSettingsCoreFoundationPreferences.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/settings/TelldusSettingsWinRegistry.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/stdafx.cpp (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/stdafx.h (100%) rename telldus-core/driver/{TellUsbD101/TellUsbD101.cpp => libtelldus-core/telldus-core.cpp} (95%) rename telldus-core/driver/{TellUsbD101/TellUsbD101.h => libtelldus-core/telldus-core.h} (93%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/win/Device.cpp (87%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/win/WinTypes.h (100%) rename telldus-core/driver/{TellUsbD101 => libtelldus-core}/win/ftd2xx.h (85%) diff --git a/telldus-core/driver/CMakeLists.txt b/telldus-core/driver/CMakeLists.txt index 18cc7359..3d3a4e24 100644 --- a/telldus-core/driver/CMakeLists.txt +++ b/telldus-core/driver/CMakeLists.txt @@ -1,6 +1,6 @@ -PROJECT( tellstick ) - -CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) - -ADD_SUBDIRECTORY(TellUsbD101) - +PROJECT( tellstick ) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) + +ADD_SUBDIRECTORY(libtelldus-core) + diff --git a/telldus-core/driver/TellUsbD101/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt similarity index 89% rename from telldus-core/driver/TellUsbD101/CMakeLists.txt rename to telldus-core/driver/libtelldus-core/CMakeLists.txt index c5dfd9d5..8da57685 100644 --- a/telldus-core/driver/TellUsbD101/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -1,70 +1,70 @@ - -SET( tellusbd101_SRCS - Device.cpp - DeviceIkea.cpp - DeviceNexa.cpp - DeviceSartano.cpp - DeviceWaveman.cpp - settings/TelldusSettings.cpp - TellUsbD101.cpp - ) - -IF (APPLE) - SET( tellusbd101_SRCS - ${tellusbd101_SRCS} - win/Device.cpp - settings/TelldusSettingsCoreFoundationPreferences.cpp - ) - ADD_DEFINITIONS( - -D_MACOSX - ) -ELSE (APPLE) - SET( tellusbd101_SRCS - ${tellusbd101_SRCS} - linux/Device.cpp - settings/TelldusSettingsConfuse.cpp - ) - ADD_DEFINITIONS( - -D_LINUX - ) - -ENDIF (APPLE) - -ADD_LIBRARY(tellusbd101 SHARED - ${tellusbd101_SRCS} - ) - -IF (APPLE) - FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) - - TARGET_LINK_LIBRARIES(tellusbd101 - ${COREFOUNDATION_LIBRARY} - ftd2xx - ) -ELSE (APPLE) - TARGET_LINK_LIBRARIES(tellusbd101 - confuse - ) -ENDIF (APPLE) - -INSTALL(TARGETS tellusbd101 LIBRARY - DESTINATION lib - ) - -INSTALL(FILES - TellUsbD101.h - DESTINATION include - ) - -SET(SYSCONF_INSTALL_DIR - "/etc" - CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" - FORCE - ) - -IF (UNIX) - INSTALL(FILES - tellstick.conf - DESTINATION ${SYSCONF_INSTALL_DIR} - ) -ENDIF (UNIX) + +SET( tellusbd101_SRCS + Device.cpp + DeviceIkea.cpp + DeviceNexa.cpp + DeviceSartano.cpp + DeviceWaveman.cpp + settings/TelldusSettings.cpp + telldus-core.cpp + ) + +IF (APPLE) + SET( tellusbd101_SRCS + ${tellusbd101_SRCS} + win/Device.cpp + settings/TelldusSettingsCoreFoundationPreferences.cpp + ) + ADD_DEFINITIONS( + -D_MACOSX + ) +ELSE (APPLE) + SET( tellusbd101_SRCS + ${tellusbd101_SRCS} + linux/Device.cpp + settings/TelldusSettingsConfuse.cpp + ) + ADD_DEFINITIONS( + -D_LINUX + ) + +ENDIF (APPLE) + +ADD_LIBRARY(tellusbd101 SHARED + ${tellusbd101_SRCS} + ) + +IF (APPLE) + FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) + + TARGET_LINK_LIBRARIES(tellusbd101 + ${COREFOUNDATION_LIBRARY} + ftd2xx + ) +ELSE (APPLE) + TARGET_LINK_LIBRARIES(tellusbd101 + confuse + ) +ENDIF (APPLE) + +INSTALL(TARGETS tellusbd101 + DESTINATION lib + ) + +INSTALL(FILES + TellUsbD101.h + DESTINATION include + ) + +SET(SYSCONF_INSTALL_DIR + "/etc" + CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)" + FORCE + ) + +IF (UNIX) + INSTALL(FILES + tellstick.conf + DESTINATION ${SYSCONF_INSTALL_DIR} + ) +ENDIF (UNIX) diff --git a/telldus-core/driver/TellUsbD101/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp similarity index 68% rename from telldus-core/driver/TellUsbD101/Device.cpp rename to telldus-core/driver/libtelldus-core/Device.cpp index cb10dc6a..2ecc62b0 100644 --- a/telldus-core/driver/TellUsbD101/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -27,28 +27,28 @@ Device::~Device(void) * Turn on, virtual */ int Device::turnOn(void){ - //do nothing + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } /* * Turn off, virtual */ int Device::turnOff(void){ - //do nothing + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } /* * Bell, virtual */ int Device::bell(void){ - //do nothing + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } /* * Dim, virtual */ int Device::dim(unsigned char level){ - //do nothing + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } /* diff --git a/telldus-core/driver/TellUsbD101/Device.h b/telldus-core/driver/libtelldus-core/Device.h similarity index 87% rename from telldus-core/driver/TellUsbD101/Device.h rename to telldus-core/driver/libtelldus-core/Device.h index 77c0a116..2ec7fd3e 100644 --- a/telldus-core/driver/TellUsbD101/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -1,6 +1,6 @@ #pragma once -#include "TellUsbD101.h" +#include "telldus-core.h" class Device { diff --git a/telldus-core/driver/TellUsbD101/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp similarity index 93% rename from telldus-core/driver/TellUsbD101/DeviceIkea.cpp rename to telldus-core/driver/libtelldus-core/DeviceIkea.cpp index 722b5170..d2eb3e04 100644 --- a/telldus-core/driver/TellUsbD101/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -8,6 +8,10 @@ using namespace std; +#ifdef _WINDOWS +#define strcasecmp(x, y) _strcmpi(x, y) +#endif + /* * Constructor */ diff --git a/telldus-core/driver/TellUsbD101/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h similarity index 100% rename from telldus-core/driver/TellUsbD101/DeviceIkea.h rename to telldus-core/driver/libtelldus-core/DeviceIkea.h diff --git a/telldus-core/driver/TellUsbD101/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/DeviceNexa.cpp rename to telldus-core/driver/libtelldus-core/DeviceNexa.cpp diff --git a/telldus-core/driver/TellUsbD101/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h similarity index 100% rename from telldus-core/driver/TellUsbD101/DeviceNexa.h rename to telldus-core/driver/libtelldus-core/DeviceNexa.h diff --git a/telldus-core/driver/TellUsbD101/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/DeviceSartano.cpp rename to telldus-core/driver/libtelldus-core/DeviceSartano.cpp diff --git a/telldus-core/driver/TellUsbD101/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h similarity index 100% rename from telldus-core/driver/TellUsbD101/DeviceSartano.h rename to telldus-core/driver/libtelldus-core/DeviceSartano.h diff --git a/telldus-core/driver/TellUsbD101/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/DeviceWaveman.cpp rename to telldus-core/driver/libtelldus-core/DeviceWaveman.cpp diff --git a/telldus-core/driver/TellUsbD101/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h similarity index 100% rename from telldus-core/driver/TellUsbD101/DeviceWaveman.h rename to telldus-core/driver/libtelldus-core/DeviceWaveman.h diff --git a/telldus-core/driver/TellUsbD101/Resource.h b/telldus-core/driver/libtelldus-core/Resource.h similarity index 100% rename from telldus-core/driver/TellUsbD101/Resource.h rename to telldus-core/driver/libtelldus-core/Resource.h diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.def b/telldus-core/driver/libtelldus-core/libtelldus-core.def similarity index 87% rename from telldus-core/driver/TellUsbD101/TellUsbD101.def rename to telldus-core/driver/libtelldus-core/libtelldus-core.def index 9d3ecf89..a107e636 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.def +++ b/telldus-core/driver/libtelldus-core/libtelldus-core.def @@ -1,4 +1,4 @@ -LIBRARY TellUsbD101 +LIBRARY telldus-core EXPORTS devGetNumberOfDevices @1 devGetDeviceId @2 diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj b/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj similarity index 88% rename from telldus-core/driver/TellUsbD101/TellUsbD101.vcproj rename to telldus-core/driver/libtelldus-core/libtelldus-core.vcproj index 16a0e453..55c199b7 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj +++ b/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj @@ -2,9 +2,9 @@ @@ -61,8 +61,9 @@ /> + + @@ -201,10 +206,6 @@ /> - - @@ -225,6 +226,10 @@ RelativePath=".\stdafx.cpp" > + + @@ -233,10 +238,6 @@ RelativePath=".\settings\TelldusSettingsWinRegistry.cpp" > - - @@ -290,7 +291,7 @@ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" > diff --git a/telldus-core/driver/TellUsbD101/linux/Device.cpp b/telldus-core/driver/libtelldus-core/linux/Device.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/linux/Device.cpp rename to telldus-core/driver/libtelldus-core/linux/Device.cpp diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/settings/TelldusSettings.cpp rename to telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettings.h b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h similarity index 100% rename from telldus-core/driver/TellUsbD101/settings/TelldusSettings.h rename to telldus-core/driver/libtelldus-core/settings/TelldusSettings.h diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/settings/TelldusSettingsConfuse.cpp rename to telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsCoreFoundationPreferences.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/settings/TelldusSettingsCoreFoundationPreferences.cpp rename to telldus-core/driver/libtelldus-core/settings/TelldusSettingsCoreFoundationPreferences.cpp diff --git a/telldus-core/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/settings/TelldusSettingsWinRegistry.cpp rename to telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp diff --git a/telldus-core/driver/TellUsbD101/stdafx.cpp b/telldus-core/driver/libtelldus-core/stdafx.cpp similarity index 100% rename from telldus-core/driver/TellUsbD101/stdafx.cpp rename to telldus-core/driver/libtelldus-core/stdafx.cpp diff --git a/telldus-core/driver/TellUsbD101/stdafx.h b/telldus-core/driver/libtelldus-core/stdafx.h similarity index 100% rename from telldus-core/driver/TellUsbD101/stdafx.h rename to telldus-core/driver/libtelldus-core/stdafx.h diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp similarity index 95% rename from telldus-core/driver/TellUsbD101/TellUsbD101.cpp rename to telldus-core/driver/libtelldus-core/telldus-core.cpp index 466e0008..17afd0e1 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -8,7 +8,7 @@ #include "stdafx.h" #include #endif -#include "TellUsbD101.h" +#include "telldus-core.h" #include "settings/TelldusSettings.h" #include "Device.h" #include diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.h b/telldus-core/driver/libtelldus-core/telldus-core.h similarity index 93% rename from telldus-core/driver/TellUsbD101/TellUsbD101.h rename to telldus-core/driver/libtelldus-core/telldus-core.h index 697b10d4..a9818b99 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -1,16 +1,16 @@ -#ifndef TELLUSBD101_H -#define TELLUSBD101_H +#ifndef TELLDUSCORE_H +#define TELLDUSCORE_H // The following ifdef block is the standard way of creating macros // which make exporting from a DLL simpler. All files within this DLL -// are compiled with the TellUsbD101_EXPORTS symbol defined on the command line. +// are compiled with the TelldusCore_EXPORTS symbol defined on the command line. // This symbol should not be defined on any project that uses this DLL. // This way any other project whose source files include this file see // TELLSTICK_API functions as being imported from a DLL, whereas this DLL // sees symbols defined with this macro as being exported. #ifdef _WINDOWS - #ifdef TellUsbD101_EXPORTS + #ifdef TelldusCore_EXPORTS #define TELLSTICK_API __declspec(dllexport) #else #define TELLSTICK_API __declspec(dllimport) diff --git a/telldus-core/driver/TellUsbD101/win/Device.cpp b/telldus-core/driver/libtelldus-core/win/Device.cpp similarity index 87% rename from telldus-core/driver/TellUsbD101/win/Device.cpp rename to telldus-core/driver/libtelldus-core/win/Device.cpp index 556fec28..1405d9fc 100644 --- a/telldus-core/driver/TellUsbD101/win/Device.cpp +++ b/telldus-core/driver/libtelldus-core/win/Device.cpp @@ -4,6 +4,10 @@ #include #include #include + +#ifdef _WINDOWS +#include "..\StdAfx.h" +#endif #include "ftd2xx.h" int getDongleIndex(); @@ -11,7 +15,7 @@ int getDongleIndex(); /* * Send message to the USB dongle */ -void Device::send(char* strMessage){ +int Device::send(char* strMessage){ try{ FT_STATUS ftStatus = FT_OK; @@ -19,7 +23,7 @@ void Device::send(char* strMessage){ int intDongleIndex = getDongleIndex(); if (intDongleIndex < 0) { - return; + return TELLSTICK_ERROR_NOT_FOUND; } ftStatus = FT_Open(intDongleIndex, &fthHandle); @@ -35,6 +39,7 @@ void Device::send(char* strMessage){ catch(...){ throw; } + return TELLSTICK_SUCCESS; } /* @@ -48,8 +53,10 @@ int getDongleIndex(){ try{ DWORD dwNumberOfDevices = 0; - + +#ifndef _WINDOWS FT_SetVIDPID(0x1781, 0x0C30); +#endif ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); if (ftStatus == FT_OK) { for (int i = 0; i < (int)dwNumberOfDevices; i++) { diff --git a/telldus-core/driver/TellUsbD101/win/WinTypes.h b/telldus-core/driver/libtelldus-core/win/WinTypes.h similarity index 100% rename from telldus-core/driver/TellUsbD101/win/WinTypes.h rename to telldus-core/driver/libtelldus-core/win/WinTypes.h diff --git a/telldus-core/driver/TellUsbD101/win/ftd2xx.h b/telldus-core/driver/libtelldus-core/win/ftd2xx.h similarity index 85% rename from telldus-core/driver/TellUsbD101/win/ftd2xx.h rename to telldus-core/driver/libtelldus-core/win/ftd2xx.h index 3972081c..2507326c 100755 --- a/telldus-core/driver/TellUsbD101/win/ftd2xx.h +++ b/telldus-core/driver/libtelldus-core/win/ftd2xx.h @@ -1,912 +1,875 @@ -/*++ - -Copyright (c) 2001-2003 Future Technology Devices International Ltd. - -Module Name: - - ftd2xx.h - -Abstract: - - Native USB interface for FTDI FT8U232/245/2232C - FTD2XX library definitions - -Environment: - - kernel & user mode - -Revision History: - - 13/03/01 awm Created. - 13/01/03 awm Added device information support. - 19/03/03 awm Added FT_W32_CancelIo. - 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. - 18/09/03 awm Added FT_SetResetPipeRetryCount. - 10/10/03 awm Added FT_ResetPort. - /03/04 st modified for linux users - 12/10/04 st added FT_SetVIDPID - - ---*/ - - -#ifndef FTD2XX_H -#define FTD2XX_H - -#ifndef _WINDOWS -#include -#define WINAPI -#endif - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// FTD2XX_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef FTD2XX_EXPORTS -#define FTD2XX_API __declspec(dllexport) -#else -#define FTD2XX_API __declspec(dllimport) -#endif - -#ifndef _WINDOWS -#include "WinTypes.h" - -#ifdef FTD2XX_API -#undef FTD2XX_API -#define FTD2XX_API -#endif -#endif -typedef struct _EVENT_HANDLE{ - pthread_cond_t eCondVar; - pthread_mutex_t eMutex; - int iVar; -} EVENT_HANDLE; - -typedef DWORD *FT_HANDLE; -//typedef unsigned int FT_HANDLE; -//typedef struct ftdi_device * FT_HANDLE; - -typedef ULONG FT_STATUS; - -// -// Device status -// -enum { - FT_OK, - FT_INVALID_HANDLE, - FT_DEVICE_NOT_FOUND, - FT_DEVICE_NOT_OPENED, - FT_IO_ERROR, - FT_INSUFFICIENT_RESOURCES, - FT_INVALID_PARAMETER, - FT_INVALID_BAUD_RATE, //7 - - FT_DEVICE_NOT_OPENED_FOR_ERASE, - FT_DEVICE_NOT_OPENED_FOR_WRITE, - FT_FAILED_TO_WRITE_DEVICE, - FT_EEPROM_READ_FAILED, - FT_EEPROM_WRITE_FAILED, - FT_EEPROM_ERASE_FAILED, - FT_EEPROM_NOT_PRESENT, - FT_EEPROM_NOT_PROGRAMMED, - FT_INVALID_ARGS, - FT_NOT_SUPPORTED, - FT_OTHER_ERROR -}; - - -#define FT_SUCCESS(status) ((status) == FT_OK) - -// -// FT_OpenEx Flags -// - -#define FT_OPEN_BY_SERIAL_NUMBER 1 -#define FT_OPEN_BY_DESCRIPTION 2 - -// -// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags -// - -#define FT_LIST_NUMBER_ONLY 0x80000000 -#define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 - -#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) - -// -// Baud Rates -// - -#define FT_BAUD_300 300 -#define FT_BAUD_600 600 -#define FT_BAUD_1200 1200 -#define FT_BAUD_2400 2400 -#define FT_BAUD_4800 4800 -#define FT_BAUD_9600 9600 -#define FT_BAUD_14400 14400 -#define FT_BAUD_19200 19200 -#define FT_BAUD_38400 38400 -#define FT_BAUD_57600 57600 -#define FT_BAUD_115200 115200 -#define FT_BAUD_230400 230400 -#define FT_BAUD_460800 460800 -#define FT_BAUD_921600 921600 - -// -// Word Lengths -// - -#define FT_BITS_8 (UCHAR) 8 -#define FT_BITS_7 (UCHAR) 7 -#define FT_BITS_6 (UCHAR) 6 -#define FT_BITS_5 (UCHAR) 5 - -// -// Stop Bits -// - -#define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_1_5 (UCHAR) 1 -#define FT_STOP_BITS_2 (UCHAR) 2 - -// -// Parity -// - -#define FT_PARITY_NONE (UCHAR) 0 -#define FT_PARITY_ODD (UCHAR) 1 -#define FT_PARITY_EVEN (UCHAR) 2 -#define FT_PARITY_MARK (UCHAR) 3 -#define FT_PARITY_SPACE (UCHAR) 4 - -// -// Flow Control -// - -#define FT_FLOW_NONE 0x0000 -#define FT_FLOW_RTS_CTS 0x0100 -#define FT_FLOW_DTR_DSR 0x0200 -#define FT_FLOW_XON_XOFF 0x0400 - -// -// Purge rx and tx buffers -// -#define FT_PURGE_RX 1 -#define FT_PURGE_TX 2 - -// -// Events -// - -typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); - -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 - -// -// Timeouts -// - -#define FT_DEFAULT_RX_TIMEOUT 300 -#define FT_DEFAULT_TX_TIMEOUT 300 - -// -// Device types -// - -typedef ULONG FT_DEVICE; - -enum { - FT_DEVICE_BM, - FT_DEVICE_AM, - FT_DEVICE_100AX, - FT_DEVICE_UNKNOWN, - FT_DEVICE_2232C, - FT_DEVICE_232R - }; - - -#ifdef __cplusplus -extern "C" { -#endif - -FTD2XX_API -FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - -FTD2XX_API -FT_STATUS FT_SetVIDPID( - DWORD dwVID, - DWORD dwPID - ); - -FTD2XX_API -FT_STATUS FT_GetVIDPID( - DWORD * pdwVID, - DWORD * pdwPID - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten - ); - -FTD2XX_API -FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); - -// -// structure to hold program data for FT_Program function -// -typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232C extensions - // 2 = FT232R extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // FT2232C extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // FT232R extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - - UCHAR RIsVCP; // zero if using VCP drivers - -} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA lpData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA lpData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - -FTD2XX_API -FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - - -// -// Win32-type functions -// - -FTD2XX_API -FT_HANDLE WINAPI FT_W32_CreateFile( - LPCSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); - - -// -// Win32 COMM API type functions -// -typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; -} FTCOMSTAT, *LPFTCOMSTAT; - -typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ -} FTDCB, *LPFTDCB; - -typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ -} FTTIMEOUTS,*LPFTTIMEOUTS; - - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - -FTD2XX_API -BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); - -// -// Device information -// - -typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; -} FT_DEVICE_LIST_INFO_NODE; - -FTD2XX_API -FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); -// -// Events -// - -#define EV_RXCHAR 0x0001 // Any Character received -#define EV_RXFLAG 0x0002 // Received certain character -#define EV_TXEMPTY 0x0004 // Transmitt Queue Empty -#define EV_CTS 0x0008 // CTS changed state -#define EV_DSR 0x0010 // DSR changed state -#define EV_RLSD 0x0020 // RLSD changed state -#define EV_BREAK 0x0040 // BREAK received -#define EV_ERR 0x0080 // Line status error occurred -#define EV_RING 0x0100 // Ring signal detected -#define EV_PERR 0x0200 // Printer error occured -#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full -#define EV_EVENT1 0x0800 // Provider specific event 1 -#define EV_EVENT2 0x1000 // Provider specific event 2 - -// -// Escape Functions -// - -#define SETXOFF 1 // Simulate XOFF received -#define SETXON 2 // Simulate XON received -#define SETRTS 3 // Set RTS high -#define CLRRTS 4 // Set RTS low -#define SETDTR 5 // Set DTR high -#define CLRDTR 6 // Set DTR low -#define RESETDEV 7 // Reset device if possible -#define SETBREAK 8 // Set the device break line. -#define CLRBREAK 9 // Clear the device break line. - -// -// PURGE function flags. -// -#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. -#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. -#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. -#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. - -#ifdef __cplusplus -} -#endif - - -#endif /* FTD2XX_H */ - - - - - - +/*++ + +Copyright (c) 2001-2005 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB device driver for FTDI FT8U232/245 + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + 23/01/04 awm Added support for open-by-location. + 16/03/04 awm Added support for FT2232C. + 23/09/04 awm Added support for FT232R. + 20/10/04 awm Added FT_CyclePort. + 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. + 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. + 25/08/05 awm Added FT_SetDeadmanTimeout. + 02/12/05 awm Removed obsolete references. + 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // FT2232C extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // FT232R extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + + UCHAR RIsVCP; // non-zero if using VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + From 0eb8a432aed87a222e7e1e093bb4d50b9d3fd3f5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Oct 2008 12:17:29 +0000 Subject: [PATCH 0138/2215] Imported first version of TellUsbD101 backward compatibility wrapper. --- .../driver/TellUsbD101/TellUsbD101.cpp | 89 ++++++++ .../driver/TellUsbD101/TellUsbD101.def | 24 ++ telldus-core/driver/TellUsbD101/TellUsbD101.h | 81 +++++++ .../driver/TellUsbD101/TellUsbD101.vcproj | 214 ++++++++++++++++++ 4 files changed, 408 insertions(+) create mode 100644 telldus-core/driver/TellUsbD101/TellUsbD101.cpp create mode 100644 telldus-core/driver/TellUsbD101/TellUsbD101.def create mode 100644 telldus-core/driver/TellUsbD101/TellUsbD101.h create mode 100644 telldus-core/driver/TellUsbD101/TellUsbD101.vcproj diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp new file mode 100644 index 00000000..0a70e005 --- /dev/null +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -0,0 +1,89 @@ +//DLL entry point + +#include "TellUsbD101.h" +#include "../libtelldus-core/telldus-core.h" + +int __stdcall devGetNumberOfDevices(void){ + int intReturn = -1; + return intReturn; +} + +int __stdcall devGetDeviceId(int intDeviceIndex){ + int intReturn = -1; + return intReturn; +} + +char * __stdcall devGetName(int intDeviceId){ + char* strReturn; + return strReturn; +} + +char* __stdcall devGetVendor(int intDeviceId){ + char* strReturn = ""; + return strReturn; +} + +char* __stdcall devGetModel(int intDeviceId){ + char* strReturn = ""; + return strReturn; +} + +int __stdcall devGetNumberOfArguments(int intDeviceId){ + int intReturn = 0; + return intReturn; +} + +int __stdcall devGetArgument(int intDeviceId, int intArgumentIndex){ + int intReturn; + return intReturn; +} + +bool __stdcall devSetName(int intDeviceId, char* strNewName){ + bool blnSuccess = false; + return blnSuccess; +} + +bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ + bool blnSuccess = false; + return blnSuccess; +} + +bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ + bool blnSuccess = false; + return blnSuccess; +} + +bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ + return false; +} + +int __stdcall devAddDevice(){ + int intNewDeviceId = -1; + return intNewDeviceId; +} + +bool __stdcall devRemoveDevice(int intDeviceId){ + bool blnSuccess = false; + return blnSuccess; +} + +int __stdcall devMethods(int id){ + int intMethods = 0; + return intMethods; +} + +bool __stdcall devTurnOn(int intDeviceId){ + return false; +} + +bool __stdcall devTurnOff(int intDeviceId){ + return false; +} + +bool __stdcall devBell(int intDeviceId){ + return false; +} + +bool __stdcall devDim(int intDeviceId, unsigned char level){ + return false; +} diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.def b/telldus-core/driver/TellUsbD101/TellUsbD101.def new file mode 100644 index 00000000..fc32ffca --- /dev/null +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.def @@ -0,0 +1,24 @@ +LIBRARY TellUsbD101 +EXPORTS + devGetNumberOfDevices @1 + devGetDeviceId @2 + + devGetName @3 + devGetVendor @4 + devGetModel @5 + devGetNumberOfArguments @6 + devGetArgument @7 + + devSetName @8 + devSetVendor @9 + devSetModel @10 + devSetArguments @11 + + devAddDevice @12 + devRemoveDevice @13 + + devMethods @14 + devTurnOn @16 + devTurnOff @17 + devBell @18 + devDim @19 diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.h b/telldus-core/driver/TellUsbD101/TellUsbD101.h new file mode 100644 index 00000000..0b181a71 --- /dev/null +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.h @@ -0,0 +1,81 @@ +#ifndef TELLUSBD101_H +#define TELLUSBD101_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TellUsbD101_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLUSBD101_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef TellUsbD101_EXPORTS + #define TELLUSBD101_API __declspec(dllexport) +#else + #define TELLUSBD101_API __declspec(dllimport) +#endif +#ifdef _WINDOWS + #define WINAPI __stdcall +#else + #define WINAPI +#endif + + +extern "C" { + TELLUSBD101_API bool WINAPI devTurnOn(int intDeviceId); + TELLUSBD101_API bool WINAPI devTurnOff(int intDeviceId); + TELLUSBD101_API bool WINAPI devBell(int intDeviceId); + TELLUSBD101_API bool WINAPI devDim(int intDeviceId, unsigned char level); + TELLUSBD101_API int WINAPI devGetNumberOfDevices(); + TELLUSBD101_API char * WINAPI devGetName(int intDeviceId); + TELLUSBD101_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); + TELLUSBD101_API char* WINAPI devGetVendor(int intDeviceId); + TELLUSBD101_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); + TELLUSBD101_API char* WINAPI devGetModel(int intDeviceId); + TELLUSBD101_API bool WINAPI devSetModel(int intDeviceId, const char* chNewName); + TELLUSBD101_API int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex); + TELLUSBD101_API int WINAPI devGetNumberOfArguments(int intDeviceId); + TELLUSBD101_API bool WINAPI devSetArguments(int intDeviceId, const char* strArguments); + TELLUSBD101_API int WINAPI devAddDevice(); + TELLUSBD101_API bool WINAPI devRemoveDevice(int intDeviceId); + TELLUSBD101_API int WINAPI devGetDeviceId(int intDeviceIndex); + TELLUSBD101_API int WINAPI devMethods(int id); +} + +#define TELLSTICK_TURNON 1 +#define TELLSTICK_TURNOFF 2 +#define TELLSTICK_BELL 4 +#define TELLSTICK_TOGGLE 8 +#define TELLSTICK_DIM 16 + +//Protocol Nexa +#define TELLSTICK_DEVICE_YCR3500 "1" +#define TELLSTICK_DEVICE_YCR300D "2" +#define TELLSTICK_DEVICE_WSR1000 "3" +#define TELLSTICK_DEVICE_CMR1000 "4" +#define TELLSTICK_DEVICE_CMR300 "5" +#define TELLSTICK_DEVICE_PA33300 "6" +#define TELLSTICK_DEVICE_EL2000 "8" +#define TELLSTICK_DEVICE_EL2005 "9" +#define TELLSTICK_DEVICE_EL2006 "10" +#define TELLSTICK_DEVICE_SYCR3500 "12" +#define TELLSTICK_DEVICE_SYCR300 "13" +#define TELLSTICK_DEVICE_HDR105 "14" +#define TELLSTICK_DEVICE_ML7100 "15" +#define TELLSTICK_DEVICE_EL2004 "16" +#define TELLSTICK_DEVICE_EL2016 "17" +#define TELLSTICK_DEVICE_EL2010 "18" +#define TELLSTICK_DEVICE_LYCR1000 "20" +#define TELLSTICK_DEVICE_LYCR300 "21" +#define TELLSTICK_DEVICE_LCMR1000 "22" +#define TELLSTICK_DEVICE_LCMR300 "23" +#define TELLSTICK_DEVICE_EL2023 "24" +#define TELLSTICK_DEVICE_EL2024 "25" +#define TELLSTICK_DEVICE_EL2021 "26" +#define TELLSTICK_DEVICE_EL2017 "27" +#define TELLSTICK_DEVICE_EL2019 "28" + +//Protocol Ikea +#define TELLSTICK_DEVICE_KOPPLA "19" + +#endif diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj b/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj new file mode 100644 index 00000000..77b63267 --- /dev/null +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 142b0ffbd4f14e01297f782587507dc78b740fd4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Oct 2008 13:02:56 +0000 Subject: [PATCH 0139/2215] Renamed the documentation file. --- docs/{telldus-core.txt => telldus-core.dox} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{telldus-core.txt => telldus-core.dox} (100%) diff --git a/docs/telldus-core.txt b/docs/telldus-core.dox similarity index 100% rename from docs/telldus-core.txt rename to docs/telldus-core.dox From fc53195afa73635cde3b085eceb4ca075ac282bf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Oct 2008 14:14:38 +0000 Subject: [PATCH 0140/2215] Changed the setting "model" to be an integer instead of a string. --- .../driver/libtelldus-core/Device.cpp | 2 +- telldus-core/driver/libtelldus-core/Device.h | 2 +- .../driver/libtelldus-core/DeviceIkea.cpp | 4 +- .../driver/libtelldus-core/DeviceIkea.h | 2 +- .../driver/libtelldus-core/DeviceNexa.cpp | 52 ++++++------- .../driver/libtelldus-core/DeviceNexa.h | 2 +- .../driver/libtelldus-core/DeviceSartano.cpp | 2 +- .../driver/libtelldus-core/DeviceSartano.h | 2 +- .../driver/libtelldus-core/DeviceWaveman.cpp | 2 +- .../driver/libtelldus-core/DeviceWaveman.h | 2 +- .../libtelldus-core/libtelldus-core.vcproj | 10 +-- .../settings/TelldusSettings.cpp | 8 +- .../settings/TelldusSettings.h | 8 +- .../settings/TelldusSettingsWinRegistry.cpp | 73 ++++++------------- .../driver/libtelldus-core/telldus-core.cpp | 33 ++++----- .../driver/libtelldus-core/telldus-core.h | 60 +++++++-------- 16 files changed, 115 insertions(+), 149 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 2ecc62b0..6e7b60c7 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -54,6 +54,6 @@ int Device::dim(unsigned char level){ /* * Methods, virtual */ -int Device::methods(char* strModel){ +int Device::methods(int intModel){ return 0; } diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 2ec7fd3e..ec44749e 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -12,7 +12,7 @@ public: virtual int turnOff(void); virtual int bell(void); virtual int dim(unsigned char level); - virtual int methods(char* strModel); + virtual int methods(int intModel); #ifdef _LINUX void setDevice(const char *device); diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index d2eb3e04..14071dd4 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -194,9 +194,9 @@ string DeviceIkea::getStringCode(unsigned char level){ /* * Has the device got the method? */ -int DeviceIkea::methods(char* strModel){ +int DeviceIkea::methods(int intModel){ - if(strcmp(strModel, TELLSTICK_DEVICE_KOPPLA) == 0) { + if(intModel == TELLSTICK_DEVICE_KOPPLA) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); } return 0; diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index 291e55e7..669e1840 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -9,7 +9,7 @@ public: virtual int turnOn(void); virtual int turnOff(void); virtual int dim(unsigned char level); - virtual int methods(char* strModel); + virtual int methods(int intModel); public: ~DeviceIkea(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 75cd827e..3fc1b7cd 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -145,36 +145,36 @@ string DeviceNexa::getStringCode(int intToConvert){ /* * Has the device got the method? */ -int DeviceNexa::methods(char* strModel){ +int DeviceNexa::methods(int intModel){ - if( strcmp(strModel, TELLSTICK_DEVICE_YCR3500) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_YCR300D) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_WSR1000) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_CMR1000) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_CMR300) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_PA33300) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2000) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2005) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2006) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_SYCR3500) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_SYCR300) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_HDR105) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2004) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2016) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2010) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_LYCR1000) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_LYCR300) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_LCMR1000) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_LCMR300) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2023) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2024) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2021) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2017) == 0 || - strcmp(strModel, TELLSTICK_DEVICE_EL2019) == 0 + if( (intModel == TELLSTICK_DEVICE_YCR3500) || + (intModel == TELLSTICK_DEVICE_YCR300D) || + (intModel == TELLSTICK_DEVICE_WSR1000) || + (intModel == TELLSTICK_DEVICE_CMR1000) || + (intModel == TELLSTICK_DEVICE_CMR300) || + (intModel == TELLSTICK_DEVICE_PA33300) || + (intModel == TELLSTICK_DEVICE_EL2000) || + (intModel == TELLSTICK_DEVICE_EL2005) || + (intModel == TELLSTICK_DEVICE_EL2006) || + (intModel == TELLSTICK_DEVICE_SYCR3500) || + (intModel == TELLSTICK_DEVICE_SYCR300) || + (intModel == TELLSTICK_DEVICE_HDR105) || + (intModel == TELLSTICK_DEVICE_EL2004) || + (intModel == TELLSTICK_DEVICE_EL2016) || + (intModel == TELLSTICK_DEVICE_EL2010) || + (intModel == TELLSTICK_DEVICE_LYCR1000) || + (intModel == TELLSTICK_DEVICE_LYCR300) || + (intModel == TELLSTICK_DEVICE_LCMR1000) || + (intModel == TELLSTICK_DEVICE_LCMR300) || + (intModel == TELLSTICK_DEVICE_EL2023) || + (intModel == TELLSTICK_DEVICE_EL2024) || + (intModel == TELLSTICK_DEVICE_EL2021) || + (intModel == TELLSTICK_DEVICE_EL2017) || + (intModel == TELLSTICK_DEVICE_EL2019) == 0 ) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); - } else if ( strcmp(strModel, TELLSTICK_DEVICE_ML7100) == 0 ) { + } else if ( intModel == TELLSTICK_DEVICE_ML7100) { return TELLSTICK_BELL; } return 0; diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 343060a8..fa520ac2 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -9,7 +9,7 @@ public: virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); - virtual int methods(char* strModel); + virtual int methods(int intModel); public: ~DeviceNexa(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index afc8e5a0..fc8c3da5 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -67,7 +67,7 @@ int DeviceSartano::turnOff(void){ /* * Has the device got the method? */ -int DeviceSartano::methods(char* strModel){ +int DeviceSartano::methods(int){ return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index c692a8ce..490d08ea 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -9,7 +9,7 @@ public: DeviceSartano(char *strCode); virtual int turnOn(void); virtual int turnOff(void); - virtual int methods(char* strModel); + virtual int methods(int strModel); ~DeviceSartano(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index eed0cc41..115c1db2 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -41,6 +41,6 @@ int DeviceWaveman::turnOff(void){ /* * Has the device got the method? */ -int DeviceWaveman::methods(char* strModel){ +int DeviceWaveman::methods(int intModel){ return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index 57fc9fe8..b8e5f63e 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -7,5 +7,5 @@ class DeviceWaveman : public DeviceNexa public: DeviceWaveman(char *strHouse, char *strCode); virtual int turnOff(void); - virtual int methods(char* strModel); + virtual int methods(int intModel); }; diff --git a/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj b/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj index 55c199b7..1f7eb42c 100644 --- a/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj +++ b/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj @@ -40,7 +40,7 @@ - - @@ -206,6 +202,10 @@ /> + + diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp index 77b8065e..fdc56722 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp @@ -97,15 +97,15 @@ bool TelldusSettings::setVendor(int intDeviceId, const char* strVendor){ /* * Get the device model */ -char* TelldusSettings::getModel(int intDeviceId){ - return getStringSetting(intDeviceId, "model", false); +int TelldusSettings::getModel(int intDeviceId){ + return getIntSetting(intDeviceId, "model", false); } /* * Set the device model */ -bool TelldusSettings::setModel(int intDeviceId, const char* strModel){ - return setStringSetting(intDeviceId, "model", strModel, false); +bool TelldusSettings::setModel(int intDeviceId, int intModel){ + return setIntSetting(intDeviceId, "model", intModel, false); } /* diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h index be30959e..d9d24b22 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h @@ -17,21 +17,21 @@ public: bool setName(int intDeviceId, const char* strNewName); char* getVendor(int intDeviceId); bool setVendor(int intDeviceId, const char* strVendor); - char* getModel(int intDeviceId); - bool setModel(int intDeviceId, const char* strModel); + int getModel(int intDeviceId); + bool setModel(int intDeviceId, int intModel); char* getArgument(int intDeviceId, const char *strName); bool setArgument(int intDeviceId, const char *strName, const char *strValue); int addDevice(); int getDeviceId(int intDeviceIndex); bool removeDevice(int intDeviceId); - void debugLog(char* debugstring); - void debugLog(int debugint); ~TelldusSettings(void); protected: char *getStringSetting(int intDeviceId, const char* name, bool parameter); bool setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter); + int getIntSetting(int intDeviceId, const char* name, bool parameter); + bool setIntSetting(int intDeviceId, const char* name, int value, bool parameter); private: int getNextDeviceId(); diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp index 8894b822..841090a4 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp @@ -109,43 +109,6 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ } -/* -* Set device arguments -*/ -/* bool TelldusSettings::setArguments(int intDeviceId, vector vArguments){ - - bool blnSuccess = true; - try{ - std::ostringstream ssRegPath; - ssRegPath << strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); - char chConvertBuffer [20]; - char chConvertBufferValue [20]; - long lnExists = RegOpenKeyEx(HKEY_CURRENT_USER, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); - - if(lnExists == ERROR_SUCCESS){ - int i = 0; - while(i < vArguments.size()){ - _itoa(i, chConvertBuffer, 10); - _itoa(vArguments.at(i), chConvertBufferValue, 10); - intMaxRegValueLength = (int)strlen(chConvertBufferValue); - RegSetValueEx(hk, chConvertBuffer, 0, REG_SZ, (LPBYTE)chConvertBufferValue, intMaxRegValueLength); - i++; - } - } - else{ - throw exception(); //couldn't open reg key - } - RegCloseKey(hk); - - } - catch(...){ - blnSuccess = false; - } - return blnSuccess; -}*/ - - /* * Add a new device */ @@ -315,22 +278,32 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const } -//only for debug reasons -void TelldusSettings::debugLog(char* debugstring){ - ofstream debugfile("c:\\telldusdebug.txt", ios::app); - if(debugfile){ - debugfile << debugstring << endl; - debugfile.close(); - } +int TelldusSettings::getIntSetting(int intDeviceId, const char* name, bool parameter) { + int intReturn = 0; + + char *strSetting = getStringSetting(intDeviceId, name, parameter); + if (strlen(strSetting)) { + intReturn = (int)strSetting[0]; + } + + return intReturn; } -//only for debug reasons -void TelldusSettings::debugLog(int debugint){ - ofstream debugfile("c:\\telldusdebug.txt", ios::app); - if(debugfile){ - debugfile << debugint << endl; - debugfile.close(); +bool TelldusSettings::setIntSetting(int intDeviceId, const char* name, int value, bool parameter) { + bool blnReturn = false; + + std::ostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + string strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); + if (lnExists == ERROR_SUCCESS) { + DWORD dwVal = value; + if (RegSetValueEx (d->hk, name, 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)) == ERROR_SUCCESS) { + blnReturn = true; } + } + RegCloseKey(d->hk); + return blnReturn; } bool storeGlobal(privateVars *d) { diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 17afd0e1..42d5b74b 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -75,9 +75,8 @@ int WINAPI devTurnOn(int intDeviceId){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - char *model = ts.getModel( intDeviceId ); + int model = ts.getModel( intDeviceId ); int methods = dev->methods( model ); - free(model); int retval = 0; @@ -112,9 +111,8 @@ int WINAPI devTurnOff(int intDeviceId){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - char *model = ts.getModel( intDeviceId ); + int model = ts.getModel( intDeviceId ); int methods = dev->methods( model ); - free(model); int retval = 0; if ( !(methods & TELLSTICK_TURNOFF) ) { @@ -148,9 +146,8 @@ int WINAPI devBell(int intDeviceId){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - char *model = ts.getModel( intDeviceId ); + int model = ts.getModel( intDeviceId ); int methods = dev->methods( model ); - free(model); int retval = 0; if ( !(methods & TELLSTICK_BELL) ) { @@ -184,9 +181,8 @@ int WINAPI devDim(int intDeviceId, unsigned char level){ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ - char *model = ts.getModel( intDeviceId ); + int model = ts.getModel( intDeviceId ); int methods = dev->methods( model ); - free(model); int retval = 0; if ( !(methods & TELLSTICK_DIM) ) { @@ -320,27 +316,24 @@ bool WINAPI devSetVendor(int intDeviceId, const char* strVendor){ return blnSuccess; } - char* WINAPI devGetModel(int intDeviceId){ - char* strReturn = ""; +int WINAPI devGetModel(int intDeviceId){ + int intReturn = 0; try{ TelldusSettings ts; - strReturn = ts.getModel(intDeviceId); -#ifdef _WINDOWS - strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); -#endif + intReturn = ts.getModel(intDeviceId); } catch(exception e){ - strReturn = ""; + intReturn = 0; handleException(e); } - return strReturn; + return intReturn; } -bool WINAPI devSetModel(int intDeviceId, const char* strNewModel){ +bool WINAPI devSetModel(int intDeviceId, int intModel){ bool blnSuccess = false; try{ TelldusSettings ts; - blnSuccess = ts.setModel(intDeviceId, strNewModel); + blnSuccess = ts.setModel(intDeviceId, intModel); } catch(exception e){ blnSuccess = false; @@ -420,10 +413,10 @@ int WINAPI devMethods(int id){ int intMethods = 0; try{ TelldusSettings ts; - char* strModel = ts.getModel(id); + int intModel = ts.getModel(id); Device* dev = ts.getDevice(id); if (dev != NULL) { - intMethods = dev->methods(strModel); + intMethods = dev->methods(intModel); } } catch(exception e){ diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index a9818b99..e5b50b66 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -3,14 +3,14 @@ // The following ifdef block is the standard way of creating macros // which make exporting from a DLL simpler. All files within this DLL -// are compiled with the TelldusCore_EXPORTS symbol defined on the command line. +// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. // This symbol should not be defined on any project that uses this DLL. // This way any other project whose source files include this file see // TELLSTICK_API functions as being imported from a DLL, whereas this DLL // sees symbols defined with this macro as being exported. #ifdef _WINDOWS - #ifdef TelldusCore_EXPORTS + #ifdef TELLDUSCORE_EXPORTS #define TELLSTICK_API __declspec(dllexport) #else #define TELLSTICK_API __declspec(dllimport) @@ -39,8 +39,8 @@ extern "C" { TELLSTICK_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); TELLSTICK_API char * WINAPI devGetVendor(int intDeviceId); TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); - TELLSTICK_API char * WINAPI devGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, const char* chNewName); + TELLSTICK_API int WINAPI devGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, int intModel); TELLSTICK_API const char * WINAPI devGetArgument(int intDeviceId, const char *strName, const char *defaultValue); TELLSTICK_API bool WINAPI devSetArgument(int intDeviceId, const char *strName, const char* strValue); @@ -67,33 +67,33 @@ extern "C" { #define TELLSTICK_ERROR_UNKNOWN -99 //Protocol Nexa -#define TELLSTICK_DEVICE_YCR3500 "1" -#define TELLSTICK_DEVICE_YCR300D "2" -#define TELLSTICK_DEVICE_WSR1000 "3" -#define TELLSTICK_DEVICE_CMR1000 "4" -#define TELLSTICK_DEVICE_CMR300 "5" -#define TELLSTICK_DEVICE_PA33300 "6" -#define TELLSTICK_DEVICE_EL2000 "8" -#define TELLSTICK_DEVICE_EL2005 "9" -#define TELLSTICK_DEVICE_EL2006 "10" -#define TELLSTICK_DEVICE_SYCR3500 "12" -#define TELLSTICK_DEVICE_SYCR300 "13" -#define TELLSTICK_DEVICE_HDR105 "14" -#define TELLSTICK_DEVICE_ML7100 "15" -#define TELLSTICK_DEVICE_EL2004 "16" -#define TELLSTICK_DEVICE_EL2016 "17" -#define TELLSTICK_DEVICE_EL2010 "18" -#define TELLSTICK_DEVICE_LYCR1000 "20" -#define TELLSTICK_DEVICE_LYCR300 "21" -#define TELLSTICK_DEVICE_LCMR1000 "22" -#define TELLSTICK_DEVICE_LCMR300 "23" -#define TELLSTICK_DEVICE_EL2023 "24" -#define TELLSTICK_DEVICE_EL2024 "25" -#define TELLSTICK_DEVICE_EL2021 "26" -#define TELLSTICK_DEVICE_EL2017 "27" -#define TELLSTICK_DEVICE_EL2019 "28" +#define TELLSTICK_DEVICE_YCR3500 1 +#define TELLSTICK_DEVICE_YCR300D 2 +#define TELLSTICK_DEVICE_WSR1000 3 +#define TELLSTICK_DEVICE_CMR1000 4 +#define TELLSTICK_DEVICE_CMR300 5 +#define TELLSTICK_DEVICE_PA33300 6 +#define TELLSTICK_DEVICE_EL2000 8 +#define TELLSTICK_DEVICE_EL2005 9 +#define TELLSTICK_DEVICE_EL2006 10 +#define TELLSTICK_DEVICE_SYCR3500 12 +#define TELLSTICK_DEVICE_SYCR300 13 +#define TELLSTICK_DEVICE_HDR105 14 +#define TELLSTICK_DEVICE_ML7100 15 +#define TELLSTICK_DEVICE_EL2004 16 +#define TELLSTICK_DEVICE_EL2016 17 +#define TELLSTICK_DEVICE_EL2010 18 +#define TELLSTICK_DEVICE_LYCR1000 20 +#define TELLSTICK_DEVICE_LYCR300 21 +#define TELLSTICK_DEVICE_LCMR1000 22 +#define TELLSTICK_DEVICE_LCMR300 23 +#define TELLSTICK_DEVICE_EL2023 24 +#define TELLSTICK_DEVICE_EL2024 25 +#define TELLSTICK_DEVICE_EL2021 26 +#define TELLSTICK_DEVICE_EL2017 27 +#define TELLSTICK_DEVICE_EL2019 28 //Protocol Ikea -#define TELLSTICK_DEVICE_KOPPLA "19" +#define TELLSTICK_DEVICE_KOPPLA 19 #endif From 6dd66d7d7eeef77f2b2c8a842d56f896e6db05c4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Oct 2008 15:01:38 +0000 Subject: [PATCH 0141/2215] Added int-functions to TelldusSettingsConfuse to work with the new int version of getModel()/setModel() --- .../settings/TelldusSettingsConfuse.cpp | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp index 5cefbcb9..02c1d73e 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp @@ -141,24 +141,6 @@ bool TelldusSettings::removeDevice(int intDeviceId){ return blnSuccess; } -//only for debug reasons -void TelldusSettings::debugLog(char* debugstring){ -/* ofstream debugfile("c:\\telldusdebug.txt", ios::app); - if(debugfile){ - debugfile << debugstring << endl; - debugfile.close(); - }*/ -} - -//only for debug reasons -void TelldusSettings::debugLog(int debugint){ -/* ofstream debugfile("c:\\telldusdebug.txt", ios::app); - if(debugfile){ - debugfile << debugint << endl; - debugfile.close(); - }*/ -} - char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { if (d->cfg == 0) { return NULL; @@ -205,6 +187,47 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const return false; } +int TelldusSettings::getIntSetting(int intDeviceId, const char* name, bool parameter) { + if (d->cfg == 0) { + return 0; + } + cfg_t *cfg_device; + for(int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + if (parameter) { + cfg_device = cfg_getsec(cfg_device, "parameters"); + } + return cfg_getint(cfg_device, name); + } + } + return 0; +} + +bool TelldusSettings::setIntSetting(int intDeviceId, const char* name, int value, bool parameter) { + if (d->cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + if (parameter) { + cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); + cfg_setint(cfg_parameters, name, value); + } else { + cfg_setint(cfg_device, name, value); + } + FILE *fp = fopen(CONFIG_FILE, "w"); + cfg_print(d->cfg, fp); + fclose(fp); + return true; + } + } + return false; +} + + bool readConfig(cfg_t **cfg) { cfg_opt_t parameter_opts[] = { //Nexa @@ -226,7 +249,7 @@ bool readConfig(cfg_t **cfg) { CFG_INT("id", -1, CFGF_NONE), CFG_STR("name", "Unnamed", CFGF_NONE), CFG_STR("vendor", "Nexa", CFGF_NONE), - CFG_STR("model", "1", CFGF_NONE), + CFG_INT("model", 1, CFGF_NONE), CFG_SEC("parameters", parameter_opts, CFGF_NONE), CFG_END() }; From 5fe95ef98a2e206a2ebb202d6ed0edc2d130e9e9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 19 Oct 2008 19:06:12 +0000 Subject: [PATCH 0142/2215] Changed the prefix "dev" to "td" for our new platform independent API --- .../libtelldus-core/libtelldus-core.def | 36 ++++++------ .../driver/libtelldus-core/telldus-core.cpp | 58 +++++++++---------- .../driver/libtelldus-core/telldus-core.h | 36 ++++++------ telldus-core/tdtool/main.cpp | 32 +++++----- 4 files changed, 81 insertions(+), 81 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/libtelldus-core.def b/telldus-core/driver/libtelldus-core/libtelldus-core.def index a107e636..dd0b34fe 100644 --- a/telldus-core/driver/libtelldus-core/libtelldus-core.def +++ b/telldus-core/driver/libtelldus-core/libtelldus-core.def @@ -1,25 +1,25 @@ LIBRARY telldus-core EXPORTS - devGetNumberOfDevices @1 - devGetDeviceId @2 + tdGetNumberOfDevices @1 + tdGetDeviceId @2 - devGetName @3 - devGetVendor @4 - devGetModel @5 - devGetArgument @6 + tdGetName @3 + tdGetVendor @4 + tdGetModel @5 + tdGetArgument @6 - devSetName @7 - devSetVendor @8 - devSetModel @9 - devSetArgument @10 + tdSetName @7 + tdSetVendor @8 + tdSetModel @9 + tdSetArgument @10 - devAddDevice @11 - devRemoveDevice @12 + tdAddDevice @11 + tdRemoveDevice @12 - devMethods @13 - devTurnOn @14 - devTurnOff @15 - devBell @16 - devDim @17 + tdMethods @13 + tdTurnOn @14 + tdTurnOff @15 + tdBell @16 + tdDim @17 - devGetErrorString @18 + tdGetErrorString @18 diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 42d5b74b..bbd280d1 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -22,19 +22,19 @@ using namespace std; /** * @def TELLSTICK_TURNON - * Device-flag for devices supporting the devTurnOn() call. + * Device-flag for devices supporting the tdTurnOn() call. * * @def TELLSTICK_TURNOFF - * Device-flag for devices supporting the devTurnOff() call. + * Device-flag for devices supporting the tdTurnOff() call. * * @def TELLSTICK_BELL - * Device-flag for devices supporting the devBell() call. + * Device-flag for devices supporting the tdBell() call. * * @def TELLSTICK_TOGGLE * This method is currently unimplemented. * * @def TELLSTICK_DIM - * Device-flag for devices supporting the devDim() call. + * Device-flag for devices supporting the tdDim() call. * * @def TELLSTICK_SUCCESS * Error code. Returned when the command succeeded. @@ -51,7 +51,7 @@ using namespace std; * * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED * Error code. The requested method is not supported device. - * This should be avoided by a call to devMethods(). + * This should be avoided by a call to tdMethods(). * * @def TELLSTICK_ERROR_UNKNOWN * Error code. An unkown error has occurred. @@ -65,11 +65,11 @@ using namespace std; /** * Turns a device on. - * Make sure the device supports this by calling devMethods() before any + * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to turn on. **/ -int WINAPI devTurnOn(int intDeviceId){ +int WINAPI tdTurnOn(int intDeviceId){ try{ TelldusSettings ts; @@ -101,11 +101,11 @@ int WINAPI devTurnOn(int intDeviceId){ /** * Turns a device off. - * Make sure the device supports this by calling devMethods() before any + * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to turn off. */ -int WINAPI devTurnOff(int intDeviceId){ +int WINAPI tdTurnOff(int intDeviceId){ try{ TelldusSettings ts; @@ -136,11 +136,11 @@ int WINAPI devTurnOff(int intDeviceId){ /** * Sends bell command to devices supporting this. - * Make sure the device supports this by calling devMethods() before any + * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to send bell to */ -int WINAPI devBell(int intDeviceId){ +int WINAPI tdBell(int intDeviceId){ try{ TelldusSettings ts; @@ -171,12 +171,12 @@ int WINAPI devBell(int intDeviceId){ /** * Dims a device. - * Make sure the device supports this by calling devMethods() before any + * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to dim * @param level The level the device should dim to. This value should be 0-255 */ -int WINAPI devDim(int intDeviceId, unsigned char level){ +int WINAPI tdDim(int intDeviceId, unsigned char level){ try{ TelldusSettings ts; Device* dev = ts.getDevice(intDeviceId); @@ -214,7 +214,7 @@ int WINAPI devDim(int intDeviceId, unsigned char level){ * This function returns the number of devices configured * @returns an integer of the total number of devices configured */ -int WINAPI devGetNumberOfDevices(void){ +int WINAPI tdGetNumberOfDevices(void){ int intReturn = -1; try{ TelldusSettings ts; @@ -231,16 +231,16 @@ int WINAPI devGetNumberOfDevices(void){ * This function returns the unique id of a device with a specific index. * To get all the id numbers you should loop over all the devices: * \code - * int intNumberOfDevices = devGetNumberOfDevices(); + * int intNumberOfDevices = tdGetNumberOfDevices(); * for (int i = 0; i < intNumberOfDevices; i++) { - * int id = devGetDeviceId( i ); + * int id = tdGetDeviceId( i ); * // id now contains the id number of the device with index of i * } * \endcode * @param intDeviceIndex The device index to query. The index starts from 0. * @returns the unique id for the device or -1 if the device is not found. */ -int WINAPI devGetDeviceId(int intDeviceIndex){ +int WINAPI tdGetDeviceId(int intDeviceIndex){ int intReturn = -1; try{ TelldusSettings ts; @@ -258,7 +258,7 @@ int WINAPI devGetDeviceId(int intDeviceIndex){ * @param intDeviceId The unique id of the device to query * @returns The name of the device or an empty string if the device is not found. */ -char * WINAPI devGetName(int intDeviceId){ +char * WINAPI tdGetName(int intDeviceId){ char* strReturn; try{ TelldusSettings ts; @@ -274,7 +274,7 @@ char * WINAPI devGetName(int intDeviceId){ return strReturn; } -bool WINAPI devSetName(int intDeviceId, const char* strNewName){ +bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -287,7 +287,7 @@ bool WINAPI devSetName(int intDeviceId, const char* strNewName){ return blnSuccess; } -char* WINAPI devGetVendor(int intDeviceId){ +char* WINAPI tdGetVendor(int intDeviceId){ char* strReturn = ""; try{ TelldusSettings ts; @@ -303,7 +303,7 @@ char* WINAPI devGetVendor(int intDeviceId){ return strReturn; } -bool WINAPI devSetVendor(int intDeviceId, const char* strVendor){ +bool WINAPI tdSetVendor(int intDeviceId, const char* strVendor){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -316,7 +316,7 @@ bool WINAPI devSetVendor(int intDeviceId, const char* strVendor){ return blnSuccess; } -int WINAPI devGetModel(int intDeviceId){ +int WINAPI tdGetModel(int intDeviceId){ int intReturn = 0; try{ TelldusSettings ts; @@ -329,7 +329,7 @@ int WINAPI devGetModel(int intDeviceId){ return intReturn; } -bool WINAPI devSetModel(int intDeviceId, int intModel){ +bool WINAPI tdSetModel(int intDeviceId, int intModel){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -342,7 +342,7 @@ bool WINAPI devSetModel(int intDeviceId, int intModel){ return blnSuccess; } -bool WINAPI devSetArgument(int intDeviceId, const char *strName, const char *strValue){ +bool WINAPI tdSetArgument(int intDeviceId, const char *strName, const char *strValue){ try{ TelldusSettings ts; @@ -354,7 +354,7 @@ bool WINAPI devSetArgument(int intDeviceId, const char *strName, const char *str return false; } -const char * WINAPI devGetArgument(int intDeviceId, const char *strName, const char *defaultValue){ +const char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue){ char *strReturn = ""; try{ TelldusSettings ts; @@ -372,7 +372,7 @@ const char * WINAPI devGetArgument(int intDeviceId, const char *strName, const c return strReturn; } -int WINAPI devAddDevice(){ +int WINAPI tdAddDevice(){ int intNewDeviceId = -1; try{ TelldusSettings ts; @@ -385,7 +385,7 @@ int WINAPI devAddDevice(){ return intNewDeviceId; } -bool WINAPI devRemoveDevice(int intDeviceId){ +bool WINAPI tdRemoveDevice(int intDeviceId){ bool blnSuccess = false; try{ TelldusSettings ts; @@ -408,7 +408,7 @@ bool WINAPI devRemoveDevice(int intDeviceId){ * @sa TELLSTICK_TOGGLE * @sa TELLSTICK_DIM */ -int WINAPI devMethods(int id){ +int WINAPI tdMethods(int id){ int intMethods = 0; try{ @@ -438,7 +438,7 @@ int WINAPI devMethods(int id){ * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED * @sa TELLSTICK_ERROR_UNKNOWN */ -char * WINAPI devGetErrorString(int intErrorNo) { +char * WINAPI tdGetErrorString(int intErrorNo) { const int numResponses = 5; const char *responses[numResponses] = { "Success", diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index e5b50b66..eea76199 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -24,29 +24,29 @@ #ifdef __cplusplus extern "C" { #endif - TELLSTICK_API int WINAPI devTurnOn(int intDeviceId); - TELLSTICK_API int WINAPI devTurnOff(int intDeviceId); - TELLSTICK_API int WINAPI devBell(int intDeviceId); - TELLSTICK_API int WINAPI devDim(int intDeviceId, unsigned char level); - TELLSTICK_API int WINAPI devMethods(int id); + TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); + TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); + TELLSTICK_API int WINAPI tdBell(int intDeviceId); + TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI tdMethods(int id); - TELLSTICK_API int WINAPI devGetNumberOfDevices(); - TELLSTICK_API int WINAPI devGetDeviceId(int intDeviceIndex); + TELLSTICK_API int WINAPI tdGetNumberOfDevices(); + TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); - TELLSTICK_API char * WINAPI devGetErrorString(int intErrorNo); + TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); - TELLSTICK_API char * WINAPI devGetName(int intDeviceId); - TELLSTICK_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); - TELLSTICK_API char * WINAPI devGetVendor(int intDeviceId); - TELLSTICK_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); - TELLSTICK_API int WINAPI devGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI devSetModel(int intDeviceId, int intModel); + TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI tdGetVendor(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetVendor(int intDeviceId, const char* chNewName); + TELLSTICK_API int WINAPI tdGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, int intModel); - TELLSTICK_API const char * WINAPI devGetArgument(int intDeviceId, const char *strName, const char *defaultValue); - TELLSTICK_API bool WINAPI devSetArgument(int intDeviceId, const char *strName, const char* strValue); + TELLSTICK_API const char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API bool WINAPI tdSetArgument(int intDeviceId, const char *strName, const char* strValue); - TELLSTICK_API int WINAPI devAddDevice(); - TELLSTICK_API bool WINAPI devRemoveDevice(int intDeviceId); + TELLSTICK_API int WINAPI tdAddDevice(); + TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); #ifdef __cplusplus } #endif diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 3c322430..404a2275 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "TellUsbD101.h" +#include "../driver/libtelldus-core/telldus-core.h" #ifdef __MINGW32__ #define sleep(x) _sleep((x)*1000) #endif @@ -61,14 +61,14 @@ void print_version() { } void print_device( int index ) { - int intId = devGetDeviceId(index); - char *name = devGetName(intId); + int intId = tdGetDeviceId(index); + char *name = tdGetName(intId); printf("%i\t%s\n", intId, name); free(name); } void list_devices() { - int intNum = devGetNumberOfDevices(); + int intNum = tdGetNumberOfDevices(); printf("Number of devices: %i\n", intNum); int i = 0; while (i < intNum) { @@ -80,11 +80,11 @@ void list_devices() { int find_device( char *device ) { int deviceId = atoi(device); if (deviceId == 0) { //Try to find the id from the name - int intNum = devGetNumberOfDevices(); + int intNum = tdGetNumberOfDevices(); int index = 0; while (index < intNum) { - int id = devGetDeviceId(index); - char *name = devGetName( id ); + int id = tdGetDeviceId(index); + char *name = tdGetName( id ); if (strcasecmp(name, device) == 0) { deviceId = id; free(name); @@ -104,9 +104,9 @@ void switch_device( bool turnOn, char *device ) { return; } - char *name = devGetName( deviceId ); - int retval = (turnOn ? devTurnOn( deviceId ) : devTurnOff( deviceId )); - char *errorString = devGetErrorString(retval); + char *name = tdGetName( deviceId ); + int retval = (turnOn ? tdTurnOn( deviceId ) : tdTurnOff( deviceId )); + char *errorString = tdGetErrorString(retval); printf("Turning %s device: %i %s - %s\n", (turnOn ? "on" : "off"), deviceId, name, errorString); free(name); @@ -127,9 +127,9 @@ void dim_device( char *device, int level ) { return; } - char *name = devGetName( deviceId ); - int retval = devDim( deviceId, (unsigned char)level ); - char *errorString = devGetErrorString(retval); + char *name = tdGetName( deviceId ); + int retval = tdDim( deviceId, (unsigned char)level ); + char *errorString = tdGetErrorString(retval); printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); free(name); free(errorString); @@ -145,9 +145,9 @@ void bell_device( char *device ) { return; } - char *name = devGetName( deviceId ); - int retval = devBell( deviceId ); - char *errorString = devGetErrorString(retval); + char *name = tdGetName( deviceId ); + int retval = tdBell( deviceId ); + char *errorString = tdGetErrorString(retval); printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); free(name); free(errorString); From 099ee5871bf1cfbedcbec22a1c6c7b99b09c5b96 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 19 Oct 2008 19:24:03 +0000 Subject: [PATCH 0143/2215] Fixed some of the renaming of the library. --- .../driver/libtelldus-core/CMakeLists.txt | 22 +++++++++---------- telldus-core/tdtool/CMakeLists.txt | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 8da57685..c5c15b9d 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -1,5 +1,5 @@ -SET( tellusbd101_SRCS +SET( telldus-core_SRCS Device.cpp DeviceIkea.cpp DeviceNexa.cpp @@ -10,8 +10,8 @@ SET( tellusbd101_SRCS ) IF (APPLE) - SET( tellusbd101_SRCS - ${tellusbd101_SRCS} + SET( telldus-core_SRCS + ${telldus-core_SRCS} win/Device.cpp settings/TelldusSettingsCoreFoundationPreferences.cpp ) @@ -19,8 +19,8 @@ IF (APPLE) -D_MACOSX ) ELSE (APPLE) - SET( tellusbd101_SRCS - ${tellusbd101_SRCS} + SET( telldus-core_SRCS + ${telldus-core_SRCS} linux/Device.cpp settings/TelldusSettingsConfuse.cpp ) @@ -30,29 +30,29 @@ ELSE (APPLE) ENDIF (APPLE) -ADD_LIBRARY(tellusbd101 SHARED - ${tellusbd101_SRCS} +ADD_LIBRARY(telldus-core SHARED + ${telldus-core_SRCS} ) IF (APPLE) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) - TARGET_LINK_LIBRARIES(tellusbd101 + TARGET_LINK_LIBRARIES(telldus-core ${COREFOUNDATION_LIBRARY} ftd2xx ) ELSE (APPLE) - TARGET_LINK_LIBRARIES(tellusbd101 + TARGET_LINK_LIBRARIES(telldus-core confuse ) ENDIF (APPLE) -INSTALL(TARGETS tellusbd101 +INSTALL(TARGETS telldus-core DESTINATION lib ) INSTALL(FILES - TellUsbD101.h + telldus-core.h DESTINATION include ) diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt index 6b6cb203..5d2c6ed5 100644 --- a/telldus-core/tdtool/CMakeLists.txt +++ b/telldus-core/tdtool/CMakeLists.txt @@ -14,7 +14,7 @@ INCLUDE_DIRECTORIES( ) TARGET_LINK_LIBRARIES(tdtool - tellusbd101 + telldus-core ) INSTALL(TARGETS tdtool RUNTIME DESTINATION bin) From f654efebab05ae7c7aa6ed3eea014f9f5d24481c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 19 Oct 2008 19:30:31 +0000 Subject: [PATCH 0144/2215] Updated the documentation with the "td" prefix. --- docs/telldus-core.dox | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index 5627f9bb..969f247a 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -37,15 +37,15 @@ * * To list all of the configured devices, look at the following example: * \code - * int intNumberOfDevices = devGetNumberOfDevices(); + * int intNumberOfDevices = tdGetNumberOfDevices(); * for (int i = 0; i < intNumberOfDevices; i++) { - * int id = devGetDeviceId( index ); - * char *name = devGetName( id ); + * int id = tdGetDeviceId( index ); + * char *name = tdGetName( id ); * printf("%d\t%s\n", id, name); * } * \endcode * - * First, we call devGetNumberOfDevices(). This returnes the total number of + * First, we call tdGetNumberOfDevices(). This returnes the total number of * devices configured. We then iterate over all of the devices with the index * in the variable \c i. * Since the devices could change between run of the program we could not be @@ -54,13 +54,13 @@ * store in a configuration file. Two different devices could never share the * same device id. * - * The call to devGetDeviceId() returns the id for a specific index. This + * The call to tdGetDeviceId() returns the id for a specific index. This * function should only be called in a loop iterating over all of the devices. * After we have found the id for a device it is safe to store this or use it * the rest of the program. * * The next two lines of code queries the device for it's name with a call to - * devGetName() and then displays it to stdout. + * tdGetName() and then displays it to stdout. * * \subsection sec_bu_sending Sending commands to TellStick * @@ -69,18 +69,18 @@ * TellStick can control many different types of devices and they * all support different features. For example, a bell doesn't support turning * on and not all lamp switches support dimming. - * To find out what a specific device support call devMethods(): + * To find out what a specific device support call tdMethods(): * \code * function checkFeatures( int id ) { - * int methods = devMethods( id ); + * int methods = tdMethods( id ); * if ( methods & TELLSTICK_TURNON ) { - * printf( "The device %d support devTurnOn()\n", id ); + * printf( "The device %d support tdTurnOn()\n", id ); * } * if ( methods & TELLSTICK_TURNOFF ) { - * printf( "The device %d support devTurnOff()\n", id ); + * printf( "The device %d support tdTurnOff()\n", id ); * } * if ( methods & TELLSTICK_BELL ) { - * printf( "The device %d support devBell()\n", id ); + * printf( "The device %d support tdBell()\n", id ); * } * } * \endcode @@ -96,17 +96,17 @@ * These functions all returns zero if the call was successfull and non-zero * otherwise. * - * \paragraph devTurnOn devTurnOn() + * \paragraph tdTurnOn tdTurnOn() * Devices supporting \c TELLSTICK_TURNON. Most of the normal switches (for lamp * etc.) support this. - * \paragraph devTurnOff devTurnOff() + * \paragraph tdTurnOff tdTurnOff() * Devices supporting \c TELLSTICK_TURNOFF. Almost all of the devices supporting * \c TELLSTICK_TURNON also support this. - * \paragraph devDim devDim() + * \paragraph tdDim tdDim() * Devices supporting \c TELLSTICK_DIM. This is a quite unusual feature for * dimmers. Many dimmers on the market that are dimmable have no way for sending * a specific level which means it doesn't support this feature. - * \paragraph devBell devBell() + * \paragraph tdBell tdBell() * Devices supporting \c TELLSTICK_BELL. This is mostly wireless doorbells. * * \subsubsection sec_bu_error_codes Error codes @@ -114,14 +114,14 @@ * If any of the calls in \ref sec_bu_controlling_functions fails it returns * a non-zero error code. This values is one of the \c TELLSTICK_ERROR_* defines. * To translate the error code to a human readable string call the function - * devGetErrorString(). Example: + * tdGetErrorString(). Example: * \code - * printf("Error: %s\n", devGetErrorString( TELLSTICK_METHOD_NOT_SUPPORTED ) ); + * printf("Error: %s\n", tdGetErrorString( TELLSTICK_METHOD_NOT_SUPPORTED ) ); * //Error: The method you tried to use is not supported by the device * - * int retval = devTurnOn( deviceID ); + * int retval = tdTurnOn( deviceID ); * if (retval != TELLSTICK_SUCCESS ) { - * printf("Error: %s\n", devGetErrorString( retval ) ); + * printf("Error: %s\n", tdGetErrorString( retval ) ); * } * \endcode * From 325bc4e9d35e91fa0709202dff40837e2b241ef3 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Sun, 26 Oct 2008 13:02:14 +0000 Subject: [PATCH 0145/2215] Another bugfix for daylight saving time --- tellstickcontroller/tellstickController | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index 74e4cc8b..143d70b5 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -643,11 +643,12 @@ sub get_rule_datetime($$$$) { $hours = int $mins/60; $minutes = int $mins%60; - $time = DateTime->now(time_zone => $cfg_set{"timezone"}); +# $time = DateTime->now(time_zone => $cfg_set{"timezone"}); + $time = DateTime->now(); $time->set(hour => 0, minute => 0, second => 0); - $time->set_time_zone("UTC"); +# $time->set_time_zone("UTC"); $time->add(hours => $hours+24*$days, minutes => $minutes); - $time->set_time_zone($cfg_set{"timezone"}); +# $time->set_time_zone($cfg_set{"timezone"}); # println "days='$days', hours='$hours', minutes='$minutes'"; # println "time='$time'"; } else { From 5f36f7800a3f18ac824080b7ef8efdc1710d7f3c Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Sun, 26 Oct 2008 13:03:32 +0000 Subject: [PATCH 0146/2215] --- tellstickcontroller/tellstickController | 3 --- 1 file changed, 3 deletions(-) diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index 143d70b5..6cfa6a7f 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -643,12 +643,9 @@ sub get_rule_datetime($$$$) { $hours = int $mins/60; $minutes = int $mins%60; -# $time = DateTime->now(time_zone => $cfg_set{"timezone"}); $time = DateTime->now(); $time->set(hour => 0, minute => 0, second => 0); -# $time->set_time_zone("UTC"); $time->add(hours => $hours+24*$days, minutes => $minutes); -# $time->set_time_zone($cfg_set{"timezone"}); # println "days='$days', hours='$hours', minutes='$minutes'"; # println "time='$time'"; } else { From 3d159060cd123467ef1c8202c4fd4b51648b9a9e Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Sun, 26 Oct 2008 13:06:47 +0000 Subject: [PATCH 0147/2215] bugfix for daylight saving time --- tellstickcontroller/Readme | 2 +- tellstickcontroller/tellstickController | 4 ++-- tellstickcontroller/tellstickController.conf | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tellstickcontroller/Readme b/tellstickcontroller/Readme index 78f63965..7ebfd73e 100644 --- a/tellstickcontroller/Readme +++ b/tellstickcontroller/Readme @@ -75,7 +75,7 @@ LICENSE Copyright (C) 2008 Rickard Andersson - Version 1.4.0 + Version 1.4.1 This program comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under certain conditions; See license file for details. diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index 6cfa6a7f..b4a36947 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -4,7 +4,7 @@ # tellstickController program # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version 1.4.0 +# Version 1.4.1 # ###################################################################### # @@ -929,7 +929,7 @@ __DATA__ #- #- LICENSE #- Copyright (C) 2008 Rickard Andersson -#- Version 1.4.0 +#- Version 1.4.1 #- This program comes with ABSOLUTELY NO WARRANTY. #- This is free software, and you are welcome to redistribute it #- under certain conditions; See license file for details. diff --git a/tellstickcontroller/tellstickController.conf b/tellstickcontroller/tellstickController.conf index 6eaca340..77a7df04 100644 --- a/tellstickcontroller/tellstickController.conf +++ b/tellstickcontroller/tellstickController.conf @@ -3,7 +3,7 @@ # Configuration file for tellstickController # # Copyright (C) 2008 Rickard Andersson (ran42ran@gmail.com) -# Version: 1.4.0 +# Version: 1.4.1 # ################################################################################ # From 40f06e5787b01692db404d57e03907010bf76bda Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Mon, 27 Oct 2008 16:25:04 +0000 Subject: [PATCH 0148/2215] Stupid datetime object ;-) --- tellstickcontroller/tellstickController | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tellstickcontroller/tellstickController b/tellstickcontroller/tellstickController index b4a36947..0696d8aa 100755 --- a/tellstickcontroller/tellstickController +++ b/tellstickcontroller/tellstickController @@ -517,7 +517,7 @@ sub load_device_rules () { sub get_rule_datetime($$$$) { my ($rule, $now, $sunrise, $sunset) = @_; -# println "Rule='$rule'" if ($option{"verbose"}); +# println "Rule='$rule'"; my ($date, $time) = split(/\//, $rule); if (not defined($time)) { @@ -643,7 +643,8 @@ sub get_rule_datetime($$$$) { $hours = int $mins/60; $minutes = int $mins%60; - $time = DateTime->now(); +# UTC ? + $time = get_datetime_now(); $time->set(hour => 0, minute => 0, second => 0); $time->add(hours => $hours+24*$days, minutes => $minutes); # println "days='$days', hours='$hours', minutes='$minutes'"; From a9aa3c164b5bf5be36caae1b51cf3deec9f1a21c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 Oct 2008 11:23:36 +0000 Subject: [PATCH 0149/2215] Bugfix when storing values in the windows registry --- .../libtelldus-core/settings/TelldusSettingsWinRegistry.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp index 841090a4..426bb931 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp @@ -295,10 +295,11 @@ bool TelldusSettings::setIntSetting(int intDeviceId, const char* name, int value std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); if (lnExists == ERROR_SUCCESS) { DWORD dwVal = value; - if (RegSetValueEx (d->hk, name, 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)) == ERROR_SUCCESS) { + lnExists = RegSetValueEx (d->hk, name, 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + if (lnExists == ERROR_SUCCESS) { blnReturn = true; } } From 4d282cfee7ad37a45f9dbf122771d45b1ef4bb94 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 Oct 2008 14:50:52 +0000 Subject: [PATCH 0150/2215] Implemented the functions in the wrapper TellUsbD101. --- .../driver/TellUsbD101/TellUsbD101.cpp | 60 +++++++++---------- telldus-core/driver/TellUsbD101/TellUsbD101.h | 36 ----------- .../driver/TellUsbD101/TellUsbD101.vcproj | 7 ++- 3 files changed, 34 insertions(+), 69 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index 0a70e005..5591bdde 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -2,55 +2,58 @@ #include "TellUsbD101.h" #include "../libtelldus-core/telldus-core.h" +#include +#include +#include +#include + int __stdcall devGetNumberOfDevices(void){ - int intReturn = -1; - return intReturn; + return tdGetNumberOfDevices(); } int __stdcall devGetDeviceId(int intDeviceIndex){ - int intReturn = -1; - return intReturn; + return tdGetDeviceId(intDeviceIndex); } char * __stdcall devGetName(int intDeviceId){ - char* strReturn; - return strReturn; + return tdGetName(intDeviceId); } char* __stdcall devGetVendor(int intDeviceId){ - char* strReturn = ""; - return strReturn; + return tdGetVendor(intDeviceId); } char* __stdcall devGetModel(int intDeviceId){ - char* strReturn = ""; - return strReturn; + int intModel = tdGetModel(intDeviceId); + + std::ostringstream ss; + std::string str; + ss << intModel; + str = ss.str(); + char *strModel = (char *)SysAllocStringByteLen (str.c_str(), str.length()); + return strModel; } int __stdcall devGetNumberOfArguments(int intDeviceId){ - int intReturn = 0; - return intReturn; + return 0; } int __stdcall devGetArgument(int intDeviceId, int intArgumentIndex){ - int intReturn; - return intReturn; + return 0; } bool __stdcall devSetName(int intDeviceId, char* strNewName){ - bool blnSuccess = false; - return blnSuccess; + return tdSetName(intDeviceId, strNewName); } bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ - bool blnSuccess = false; - return blnSuccess; + return tdSetVendor(intDeviceId, strVendor); } bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ - bool blnSuccess = false; - return blnSuccess; + int intModel = atoi(strNewModel); + return tdSetModel(intDeviceId, intModel); } bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ @@ -58,32 +61,29 @@ bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ } int __stdcall devAddDevice(){ - int intNewDeviceId = -1; - return intNewDeviceId; + return tdAddDevice(); } bool __stdcall devRemoveDevice(int intDeviceId){ - bool blnSuccess = false; - return blnSuccess; + return tdRemoveDevice(intDeviceId); } int __stdcall devMethods(int id){ - int intMethods = 0; - return intMethods; + return tdMethods(id); } bool __stdcall devTurnOn(int intDeviceId){ - return false; + return (tdTurnOn(intDeviceId) == TELLSTICK_SUCCESS ? true : false); } bool __stdcall devTurnOff(int intDeviceId){ - return false; + return (tdTurnOff(intDeviceId) == TELLSTICK_SUCCESS ? true : false); } bool __stdcall devBell(int intDeviceId){ - return false; + return (tdBell(intDeviceId) == TELLSTICK_SUCCESS ? true : false); } bool __stdcall devDim(int intDeviceId, unsigned char level){ - return false; + return (tdDim(intDeviceId, level) == TELLSTICK_SUCCESS ? true : false); } diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.h b/telldus-core/driver/TellUsbD101/TellUsbD101.h index 0b181a71..4868c964 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.h +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.h @@ -42,40 +42,4 @@ extern "C" { TELLUSBD101_API int WINAPI devMethods(int id); } -#define TELLSTICK_TURNON 1 -#define TELLSTICK_TURNOFF 2 -#define TELLSTICK_BELL 4 -#define TELLSTICK_TOGGLE 8 -#define TELLSTICK_DIM 16 - -//Protocol Nexa -#define TELLSTICK_DEVICE_YCR3500 "1" -#define TELLSTICK_DEVICE_YCR300D "2" -#define TELLSTICK_DEVICE_WSR1000 "3" -#define TELLSTICK_DEVICE_CMR1000 "4" -#define TELLSTICK_DEVICE_CMR300 "5" -#define TELLSTICK_DEVICE_PA33300 "6" -#define TELLSTICK_DEVICE_EL2000 "8" -#define TELLSTICK_DEVICE_EL2005 "9" -#define TELLSTICK_DEVICE_EL2006 "10" -#define TELLSTICK_DEVICE_SYCR3500 "12" -#define TELLSTICK_DEVICE_SYCR300 "13" -#define TELLSTICK_DEVICE_HDR105 "14" -#define TELLSTICK_DEVICE_ML7100 "15" -#define TELLSTICK_DEVICE_EL2004 "16" -#define TELLSTICK_DEVICE_EL2016 "17" -#define TELLSTICK_DEVICE_EL2010 "18" -#define TELLSTICK_DEVICE_LYCR1000 "20" -#define TELLSTICK_DEVICE_LYCR300 "21" -#define TELLSTICK_DEVICE_LCMR1000 "22" -#define TELLSTICK_DEVICE_LCMR300 "23" -#define TELLSTICK_DEVICE_EL2023 "24" -#define TELLSTICK_DEVICE_EL2024 "25" -#define TELLSTICK_DEVICE_EL2021 "26" -#define TELLSTICK_DEVICE_EL2017 "27" -#define TELLSTICK_DEVICE_EL2019 "28" - -//Protocol Ikea -#define TELLSTICK_DEVICE_KOPPLA "19" - #endif diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj b/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj index 77b63267..c25d6338 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj @@ -3,7 +3,7 @@ ProjectType="Visual C++" Version="8,00" Name="TellUsbD101" - ProjectGUID="{2A868E40-88D9-4800-A83F-21D0F8DCB611}" + ProjectGUID="{F2BD0723-1E66-4191-AF6D-DEDD9605B028}" RootNamespace="TellUsbD101" Keyword="Win32Proj" > @@ -40,7 +40,7 @@ Date: Wed, 29 Oct 2008 14:51:23 +0000 Subject: [PATCH 0151/2215] Small buggfix for the methods in nexa-devices. --- telldus-core/driver/libtelldus-core/DeviceNexa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 3fc1b7cd..9e2e02ec 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -170,7 +170,7 @@ int DeviceNexa::methods(int intModel){ (intModel == TELLSTICK_DEVICE_EL2024) || (intModel == TELLSTICK_DEVICE_EL2021) || (intModel == TELLSTICK_DEVICE_EL2017) || - (intModel == TELLSTICK_DEVICE_EL2019) == 0 + (intModel == TELLSTICK_DEVICE_EL2019) ) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); From 46f50aabc3091d607aae08995638457adf0fdc1d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 29 Oct 2008 21:41:43 +0000 Subject: [PATCH 0152/2215] Many minor bugs. Project files upgraded to Visual Studio 2008 format now. --- .../DeviceScheduler/DataStorage.Designer.cs | 721 ++++++++++-------- .../DeviceScheduler/DeviceScheduler.csproj | 65 +- .../Languages/WinFormStrings.en.resx | 16 + .../Languages/WinFormStrings.resx | 15 + .../Languages/WinFormStrings.sv.resx | 15 + .../DeviceScheduler/frmAskSecurityPolicy.cs | 2 +- scheduler/DeviceScheduler/frmMain.cs | 52 +- scheduler/DeviceScheduler/frmSchedule.cs | 4 +- .../DeviceScheduler/frmScheduleAddDevice.cs | 16 +- 9 files changed, 582 insertions(+), 324 deletions(-) diff --git a/scheduler/DeviceScheduler/DataStorage.Designer.cs b/scheduler/DeviceScheduler/DataStorage.Designer.cs index 0d924dbc..9d771ac6 100644 --- a/scheduler/DeviceScheduler/DataStorage.Designer.cs +++ b/scheduler/DeviceScheduler/DataStorage.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:2.0.50727.312 +// Runtime Version:2.0.50727.3053 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -11,50 +11,52 @@ #pragma warning disable 1591 namespace DeviceScheduler { - using System; - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] - [Serializable()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.ComponentModel.ToolboxItem(true)] - [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedDataSetSchema")] - [System.Xml.Serialization.XmlRootAttribute("DataStorage")] - [System.ComponentModel.Design.HelpKeywordAttribute("vs.data.DataSet")] - public partial class DataStorage : System.Data.DataSet { + /// + ///Represents a strongly typed in-memory cache of data. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [global::System.Serializable()] + [global::System.ComponentModel.DesignerCategoryAttribute("code")] + [global::System.ComponentModel.ToolboxItem(true)] + [global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedDataSetSchema")] + [global::System.Xml.Serialization.XmlRootAttribute("DataStorage")] + [global::System.ComponentModel.Design.HelpKeywordAttribute("vs.data.DataSet")] + public partial class DataStorage : global::System.Data.DataSet { private JobDataTable tableJob; private JobActionsDataTable tableJobActions; - private System.Data.DataRelation relationJob_JobActions; + private global::System.Data.DataRelation relationJob_JobActions; - private System.Data.SchemaSerializationMode _schemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; + private global::System.Data.SchemaSerializationMode _schemaSerializationMode = global::System.Data.SchemaSerializationMode.IncludeSchema; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public DataStorage() { this.BeginInit(); this.InitClass(); - System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + global::System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new global::System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); base.Tables.CollectionChanged += schemaChangedHandler; base.Relations.CollectionChanged += schemaChangedHandler; this.EndInit(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected DataStorage(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected DataStorage(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : base(info, context, false) { if ((this.IsBinarySerialized(info, context) == true)) { this.InitVars(false); - System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler1 = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + global::System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler1 = new global::System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); this.Tables.CollectionChanged += schemaChangedHandler1; this.Relations.CollectionChanged += schemaChangedHandler1; return; } string strSchema = ((string)(info.GetValue("XmlSchema", typeof(string)))); - if ((this.DetermineSchemaSerializationMode(info, context) == System.Data.SchemaSerializationMode.IncludeSchema)) { - System.Data.DataSet ds = new System.Data.DataSet(); - ds.ReadXmlSchema(new System.Xml.XmlTextReader(new System.IO.StringReader(strSchema))); + if ((this.DetermineSchemaSerializationMode(info, context) == global::System.Data.SchemaSerializationMode.IncludeSchema)) { + global::System.Data.DataSet ds = new global::System.Data.DataSet(); + ds.ReadXmlSchema(new global::System.Xml.XmlTextReader(new global::System.IO.StringReader(strSchema))); if ((ds.Tables["Job"] != null)) { base.Tables.Add(new JobDataTable(ds.Tables["Job"])); } @@ -67,40 +69,40 @@ namespace DeviceScheduler { this.Locale = ds.Locale; this.CaseSensitive = ds.CaseSensitive; this.EnforceConstraints = ds.EnforceConstraints; - this.Merge(ds, false, System.Data.MissingSchemaAction.Add); + this.Merge(ds, false, global::System.Data.MissingSchemaAction.Add); this.InitVars(); } else { - this.ReadXmlSchema(new System.Xml.XmlTextReader(new System.IO.StringReader(strSchema))); + this.ReadXmlSchema(new global::System.Xml.XmlTextReader(new global::System.IO.StringReader(strSchema))); } this.GetSerializationData(info, context); - System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); + global::System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new global::System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged); base.Tables.CollectionChanged += schemaChangedHandler; this.Relations.CollectionChanged += schemaChangedHandler; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.ComponentModel.Browsable(false)] - [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] + [global::System.ComponentModel.DesignerSerializationVisibility(global::System.ComponentModel.DesignerSerializationVisibility.Content)] public JobDataTable Job { get { return this.tableJob; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.ComponentModel.Browsable(false)] - [System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Content)] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] + [global::System.ComponentModel.DesignerSerializationVisibility(global::System.ComponentModel.DesignerSerializationVisibility.Content)] public JobActionsDataTable JobActions { get { return this.tableJobActions; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.ComponentModel.BrowsableAttribute(true)] - [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Visible)] - public override System.Data.SchemaSerializationMode SchemaSerializationMode { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.BrowsableAttribute(true)] + [global::System.ComponentModel.DesignerSerializationVisibilityAttribute(global::System.ComponentModel.DesignerSerializationVisibility.Visible)] + public override global::System.Data.SchemaSerializationMode SchemaSerializationMode { get { return this._schemaSerializationMode; } @@ -109,52 +111,52 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Hidden)] - public new System.Data.DataTableCollection Tables { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.DesignerSerializationVisibilityAttribute(global::System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new global::System.Data.DataTableCollection Tables { get { return base.Tables; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.ComponentModel.DesignerSerializationVisibilityAttribute(System.ComponentModel.DesignerSerializationVisibility.Hidden)] - public new System.Data.DataRelationCollection Relations { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.DesignerSerializationVisibilityAttribute(global::System.ComponentModel.DesignerSerializationVisibility.Hidden)] + public new global::System.Data.DataRelationCollection Relations { get { return base.Relations; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] protected override void InitializeDerivedDataSet() { this.BeginInit(); this.InitClass(); this.EndInit(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public override System.Data.DataSet Clone() { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override global::System.Data.DataSet Clone() { DataStorage cln = ((DataStorage)(base.Clone())); cln.InitVars(); cln.SchemaSerializationMode = this.SchemaSerializationMode; return cln; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] protected override bool ShouldSerializeTables() { return false; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] protected override bool ShouldSerializeRelations() { return false; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void ReadXmlSerializable(System.Xml.XmlReader reader) { - if ((this.DetermineSchemaSerializationMode(reader) == System.Data.SchemaSerializationMode.IncludeSchema)) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void ReadXmlSerializable(global::System.Xml.XmlReader reader) { + if ((this.DetermineSchemaSerializationMode(reader) == global::System.Data.SchemaSerializationMode.IncludeSchema)) { this.Reset(); - System.Data.DataSet ds = new System.Data.DataSet(); + global::System.Data.DataSet ds = new global::System.Data.DataSet(); ds.ReadXml(reader); if ((ds.Tables["Job"] != null)) { base.Tables.Add(new JobDataTable(ds.Tables["Job"])); @@ -168,7 +170,7 @@ namespace DeviceScheduler { this.Locale = ds.Locale; this.CaseSensitive = ds.CaseSensitive; this.EnforceConstraints = ds.EnforceConstraints; - this.Merge(ds, false, System.Data.MissingSchemaAction.Add); + this.Merge(ds, false, global::System.Data.MissingSchemaAction.Add); this.InitVars(); } else { @@ -177,20 +179,20 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override System.Xml.Schema.XmlSchema GetSchemaSerializable() { - System.IO.MemoryStream stream = new System.IO.MemoryStream(); - this.WriteXmlSchema(new System.Xml.XmlTextWriter(stream, null)); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Xml.Schema.XmlSchema GetSchemaSerializable() { + global::System.IO.MemoryStream stream = new global::System.IO.MemoryStream(); + this.WriteXmlSchema(new global::System.Xml.XmlTextWriter(stream, null)); stream.Position = 0; - return System.Xml.Schema.XmlSchema.Read(new System.Xml.XmlTextReader(stream), null); + return global::System.Xml.Schema.XmlSchema.Read(new global::System.Xml.XmlTextReader(stream), null); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] internal void InitVars() { this.InitVars(true); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] internal void InitVars(bool initTable) { this.tableJob = ((JobDataTable)(base.Tables["Job"])); if ((initTable == true)) { @@ -207,50 +209,83 @@ namespace DeviceScheduler { this.relationJob_JobActions = this.Relations["Job_JobActions"]; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] private void InitClass() { this.DataSetName = "DataStorage"; this.Prefix = ""; this.Namespace = "http://tempuri.org/DataStorage.xsd"; this.EnforceConstraints = true; - this.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema; + this.SchemaSerializationMode = global::System.Data.SchemaSerializationMode.IncludeSchema; this.tableJob = new JobDataTable(); base.Tables.Add(this.tableJob); this.tableJobActions = new JobActionsDataTable(); base.Tables.Add(this.tableJobActions); - this.relationJob_JobActions = new System.Data.DataRelation("Job_JobActions", new System.Data.DataColumn[] { - this.tableJob.IDColumn}, new System.Data.DataColumn[] { + this.relationJob_JobActions = new global::System.Data.DataRelation("Job_JobActions", new global::System.Data.DataColumn[] { + this.tableJob.IDColumn}, new global::System.Data.DataColumn[] { this.tableJobActions.JobIDColumn}, false); this.Relations.Add(this.relationJob_JobActions); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] private bool ShouldSerializeJob() { return false; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] private bool ShouldSerializeJobActions() { return false; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - private void SchemaChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e) { - if ((e.Action == System.ComponentModel.CollectionChangeAction.Remove)) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + private void SchemaChanged(object sender, global::System.ComponentModel.CollectionChangeEventArgs e) { + if ((e.Action == global::System.ComponentModel.CollectionChangeAction.Remove)) { this.InitVars(); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public static System.Xml.Schema.XmlSchemaComplexType GetTypedDataSetSchema(System.Xml.Schema.XmlSchemaSet xs) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedDataSetSchema(global::System.Xml.Schema.XmlSchemaSet xs) { DataStorage ds = new DataStorage(); - System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); - System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); - xs.Add(ds.GetSchemaSerializable()); - System.Xml.Schema.XmlSchemaAny any = new System.Xml.Schema.XmlSchemaAny(); + global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); + global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); + global::System.Xml.Schema.XmlSchemaAny any = new global::System.Xml.Schema.XmlSchemaAny(); any.Namespace = ds.Namespace; sequence.Items.Add(any); type.Particle = sequence; + global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); + if (xs.Contains(dsSchema.TargetNamespace)) { + global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); + global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); + try { + global::System.Xml.Schema.XmlSchema schema = null; + dsSchema.Write(s1); + for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext(); ) { + schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); + s2.SetLength(0); + schema.Write(s2); + if ((s1.Length == s2.Length)) { + s1.Position = 0; + s2.Position = 0; + for (; ((s1.Position != s1.Length) + && (s1.ReadByte() == s2.ReadByte())); ) { + ; + } + if ((s1.Position == s1.Length)) { + return type; + } + } + } + } + finally { + if ((s1 != null)) { + s1.Close(); + } + if ((s2 != null)) { + s2.Close(); + } + } + } + xs.Add(dsSchema); return type; } @@ -258,26 +293,29 @@ namespace DeviceScheduler { public delegate void JobActionsRowChangeEventHandler(object sender, JobActionsRowChangeEvent e); - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] - [System.Serializable()] - [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] - public partial class JobDataTable : System.Data.DataTable, System.Collections.IEnumerable { + /// + ///Represents the strongly named DataTable class. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [global::System.Serializable()] + [global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] + public partial class JobDataTable : global::System.Data.TypedTableBase { - private System.Data.DataColumn columnID; + private global::System.Data.DataColumn columnID; - private System.Data.DataColumn columnName; + private global::System.Data.DataColumn columnName; - private System.Data.DataColumn columnDescription; + private global::System.Data.DataColumn columnDescription; - private System.Data.DataColumn columnJobName; + private global::System.Data.DataColumn columnJobName; - private System.Data.DataColumn columnUsername; + private global::System.Data.DataColumn columnUsername; - private System.Data.DataColumn columnPassword; + private global::System.Data.DataColumn columnPassword; - private System.Data.DataColumn columnStartTime; + private global::System.Data.DataColumn columnStartTime; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobDataTable() { this.TableName = "Job"; this.BeginInit(); @@ -285,8 +323,8 @@ namespace DeviceScheduler { this.EndInit(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - internal JobDataTable(System.Data.DataTable table) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobDataTable(global::System.Data.DataTable table) { this.TableName = table.TableName; if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { this.CaseSensitive = table.CaseSensitive; @@ -301,70 +339,70 @@ namespace DeviceScheduler { this.MinimumCapacity = table.MinimumCapacity; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected JobDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected JobDataTable(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : base(info, context) { this.InitVars(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn IDColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn IDColumn { get { return this.columnID; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn NameColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn NameColumn { get { return this.columnName; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn DescriptionColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn DescriptionColumn { get { return this.columnDescription; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn JobNameColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn JobNameColumn { get { return this.columnJobName; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn UsernameColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn UsernameColumn { get { return this.columnUsername; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn PasswordColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn PasswordColumn { get { return this.columnPassword; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn StartTimeColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn StartTimeColumn { get { return this.columnStartTime; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.ComponentModel.Browsable(false)] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] public int Count { get { return this.Rows.Count; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobRow this[int index] { get { return ((JobRow)(this.Rows[index])); @@ -379,15 +417,15 @@ namespace DeviceScheduler { public event JobRowChangeEventHandler JobRowDeleted; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void AddJobRow(JobRow row) { this.Rows.Add(row); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobRow AddJobRow(string Name, string Description, string JobName, string Username, string Password, string StartTime) { JobRow rowJobRow = ((JobRow)(this.NewRow())); - rowJobRow.ItemArray = new object[] { + object[] columnValuesArray = new object[] { null, Name, Description, @@ -395,34 +433,30 @@ namespace DeviceScheduler { Username, Password, StartTime}; + rowJobRow.ItemArray = columnValuesArray; this.Rows.Add(rowJobRow); return rowJobRow; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobRow FindByID(int ID) { return ((JobRow)(this.Rows.Find(new object[] { ID}))); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public virtual System.Collections.IEnumerator GetEnumerator() { - return this.Rows.GetEnumerator(); - } - - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public override System.Data.DataTable Clone() { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override global::System.Data.DataTable Clone() { JobDataTable cln = ((JobDataTable)(base.Clone())); cln.InitVars(); return cln; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override System.Data.DataTable CreateInstance() { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Data.DataTable CreateInstance() { return new JobDataTable(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] internal void InitVars() { this.columnID = base.Columns["ID"]; this.columnName = base.Columns["Name"]; @@ -433,25 +467,25 @@ namespace DeviceScheduler { this.columnStartTime = base.Columns["StartTime"]; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] private void InitClass() { - this.columnID = new System.Data.DataColumn("ID", typeof(int), null, System.Data.MappingType.Element); + this.columnID = new global::System.Data.DataColumn("ID", typeof(int), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnID); - this.columnName = new System.Data.DataColumn("Name", typeof(string), null, System.Data.MappingType.Element); + this.columnName = new global::System.Data.DataColumn("Name", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnName); - this.columnDescription = new System.Data.DataColumn("Description", typeof(string), null, System.Data.MappingType.Element); + this.columnDescription = new global::System.Data.DataColumn("Description", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnDescription); - this.columnJobName = new System.Data.DataColumn("JobName", typeof(string), null, System.Data.MappingType.Element); + this.columnJobName = new global::System.Data.DataColumn("JobName", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnJobName); - this.columnUsername = new System.Data.DataColumn("Username", typeof(string), null, System.Data.MappingType.Element); + this.columnUsername = new global::System.Data.DataColumn("Username", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnUsername); - this.columnPassword = new System.Data.DataColumn("Password", typeof(string), null, System.Data.MappingType.Element); + this.columnPassword = new global::System.Data.DataColumn("Password", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnPassword); - this.columnStartTime = new System.Data.DataColumn("StartTime", typeof(string), null, System.Data.MappingType.Element); + this.columnStartTime = new global::System.Data.DataColumn("StartTime", typeof(string), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnStartTime); - this.Constraints.Add(new System.Data.UniqueConstraint("Constraint1", new System.Data.DataColumn[] { + this.Constraints.Add(new global::System.Data.UniqueConstraint("Constraint1", new global::System.Data.DataColumn[] { this.columnID}, true)); - this.Constraints.Add(new System.Data.UniqueConstraint("Constraint2", new System.Data.DataColumn[] { + this.Constraints.Add(new global::System.Data.UniqueConstraint("Constraint2", new global::System.Data.DataColumn[] { this.columnName}, false)); this.columnID.AutoIncrement = true; this.columnID.AutoIncrementSeed = 1; @@ -461,102 +495,138 @@ namespace DeviceScheduler { this.columnName.Unique = true; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobRow NewJobRow() { return ((JobRow)(this.NewRow())); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override System.Data.DataRow NewRowFromBuilder(System.Data.DataRowBuilder builder) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Data.DataRow NewRowFromBuilder(global::System.Data.DataRowBuilder builder) { return new JobRow(builder); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override System.Type GetRowType() { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Type GetRowType() { return typeof(JobRow); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowChanged(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanged(global::System.Data.DataRowChangeEventArgs e) { base.OnRowChanged(e); if ((this.JobRowChanged != null)) { this.JobRowChanged(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowChanging(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanging(global::System.Data.DataRowChangeEventArgs e) { base.OnRowChanging(e); if ((this.JobRowChanging != null)) { this.JobRowChanging(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowDeleted(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleted(global::System.Data.DataRowChangeEventArgs e) { base.OnRowDeleted(e); if ((this.JobRowDeleted != null)) { this.JobRowDeleted(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowDeleting(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleting(global::System.Data.DataRowChangeEventArgs e) { base.OnRowDeleting(e); if ((this.JobRowDeleting != null)) { this.JobRowDeleting(this, new JobRowChangeEvent(((JobRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void RemoveJobRow(JobRow row) { this.Rows.Remove(row); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public static System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(System.Xml.Schema.XmlSchemaSet xs) { - System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); - System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(global::System.Xml.Schema.XmlSchemaSet xs) { + global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); + global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); DataStorage ds = new DataStorage(); - xs.Add(ds.GetSchemaSerializable()); - System.Xml.Schema.XmlSchemaAny any1 = new System.Xml.Schema.XmlSchemaAny(); + global::System.Xml.Schema.XmlSchemaAny any1 = new global::System.Xml.Schema.XmlSchemaAny(); any1.Namespace = "http://www.w3.org/2001/XMLSchema"; any1.MinOccurs = new decimal(0); any1.MaxOccurs = decimal.MaxValue; - any1.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + any1.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any1); - System.Xml.Schema.XmlSchemaAny any2 = new System.Xml.Schema.XmlSchemaAny(); + global::System.Xml.Schema.XmlSchemaAny any2 = new global::System.Xml.Schema.XmlSchemaAny(); any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; any2.MinOccurs = new decimal(1); - any2.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + any2.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any2); - System.Xml.Schema.XmlSchemaAttribute attribute1 = new System.Xml.Schema.XmlSchemaAttribute(); + global::System.Xml.Schema.XmlSchemaAttribute attribute1 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute1.Name = "namespace"; attribute1.FixedValue = ds.Namespace; type.Attributes.Add(attribute1); - System.Xml.Schema.XmlSchemaAttribute attribute2 = new System.Xml.Schema.XmlSchemaAttribute(); + global::System.Xml.Schema.XmlSchemaAttribute attribute2 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute2.Name = "tableTypeName"; attribute2.FixedValue = "JobDataTable"; type.Attributes.Add(attribute2); type.Particle = sequence; + global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); + if (xs.Contains(dsSchema.TargetNamespace)) { + global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); + global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); + try { + global::System.Xml.Schema.XmlSchema schema = null; + dsSchema.Write(s1); + for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext(); ) { + schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); + s2.SetLength(0); + schema.Write(s2); + if ((s1.Length == s2.Length)) { + s1.Position = 0; + s2.Position = 0; + for (; ((s1.Position != s1.Length) + && (s1.ReadByte() == s2.ReadByte())); ) { + ; + } + if ((s1.Position == s1.Length)) { + return type; + } + } + } + } + finally { + if ((s1 != null)) { + s1.Close(); + } + if ((s2 != null)) { + s2.Close(); + } + } + } + xs.Add(dsSchema); return type; } } - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] - [System.Serializable()] - [System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] - public partial class JobActionsDataTable : System.Data.DataTable, System.Collections.IEnumerable { + /// + ///Represents the strongly named DataTable class. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + [global::System.Serializable()] + [global::System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")] + public partial class JobActionsDataTable : global::System.Data.TypedTableBase { - private System.Data.DataColumn columnID; + private global::System.Data.DataColumn columnID; - private System.Data.DataColumn columnJobID; + private global::System.Data.DataColumn columnJobID; - private System.Data.DataColumn columnDeviceID; + private global::System.Data.DataColumn columnDeviceID; - private System.Data.DataColumn columnTurnOn; + private global::System.Data.DataColumn columnTurnOn; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobActionsDataTable() { this.TableName = "JobActions"; this.BeginInit(); @@ -564,8 +634,8 @@ namespace DeviceScheduler { this.EndInit(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - internal JobActionsDataTable(System.Data.DataTable table) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobActionsDataTable(global::System.Data.DataTable table) { this.TableName = table.TableName; if ((table.CaseSensitive != table.DataSet.CaseSensitive)) { this.CaseSensitive = table.CaseSensitive; @@ -580,49 +650,49 @@ namespace DeviceScheduler { this.MinimumCapacity = table.MinimumCapacity; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected JobActionsDataTable(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected JobActionsDataTable(global::System.Runtime.Serialization.SerializationInfo info, global::System.Runtime.Serialization.StreamingContext context) : base(info, context) { this.InitVars(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn IDColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn IDColumn { get { return this.columnID; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn JobIDColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn JobIDColumn { get { return this.columnJobID; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn DeviceIDColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn DeviceIDColumn { get { return this.columnDeviceID; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataColumn TurnOnColumn { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataColumn TurnOnColumn { get { return this.columnTurnOn; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.ComponentModel.Browsable(false)] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.ComponentModel.Browsable(false)] public int Count { get { return this.Rows.Count; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobActionsRow this[int index] { get { return ((JobActionsRow)(this.Rows[index])); @@ -637,47 +707,46 @@ namespace DeviceScheduler { public event JobActionsRowChangeEventHandler JobActionsRowDeleted; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void AddJobActionsRow(JobActionsRow row) { this.Rows.Add(row); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobActionsRow AddJobActionsRow(JobRow parentJobRowByJob_JobActions, int DeviceID, bool TurnOn) { JobActionsRow rowJobActionsRow = ((JobActionsRow)(this.NewRow())); - rowJobActionsRow.ItemArray = new object[] { + object[] columnValuesArray = new object[] { + null, null, - parentJobRowByJob_JobActions[0], DeviceID, TurnOn}; + if ((parentJobRowByJob_JobActions != null)) { + columnValuesArray[1] = parentJobRowByJob_JobActions[0]; + } + rowJobActionsRow.ItemArray = columnValuesArray; this.Rows.Add(rowJobActionsRow); return rowJobActionsRow; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobActionsRow FindByID(int ID) { return ((JobActionsRow)(this.Rows.Find(new object[] { ID}))); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public virtual System.Collections.IEnumerator GetEnumerator() { - return this.Rows.GetEnumerator(); - } - - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public override System.Data.DataTable Clone() { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public override global::System.Data.DataTable Clone() { JobActionsDataTable cln = ((JobActionsDataTable)(base.Clone())); cln.InitVars(); return cln; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override System.Data.DataTable CreateInstance() { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Data.DataTable CreateInstance() { return new JobActionsDataTable(); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] internal void InitVars() { this.columnID = base.Columns["ID"]; this.columnJobID = base.Columns["JobID"]; @@ -685,17 +754,17 @@ namespace DeviceScheduler { this.columnTurnOn = base.Columns["TurnOn"]; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] private void InitClass() { - this.columnID = new System.Data.DataColumn("ID", typeof(int), null, System.Data.MappingType.Element); + this.columnID = new global::System.Data.DataColumn("ID", typeof(int), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnID); - this.columnJobID = new System.Data.DataColumn("JobID", typeof(int), null, System.Data.MappingType.Element); + this.columnJobID = new global::System.Data.DataColumn("JobID", typeof(int), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnJobID); - this.columnDeviceID = new System.Data.DataColumn("DeviceID", typeof(int), null, System.Data.MappingType.Element); + this.columnDeviceID = new global::System.Data.DataColumn("DeviceID", typeof(int), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnDeviceID); - this.columnTurnOn = new System.Data.DataColumn("TurnOn", typeof(bool), null, System.Data.MappingType.Element); + this.columnTurnOn = new global::System.Data.DataColumn("TurnOn", typeof(bool), null, global::System.Data.MappingType.Element); base.Columns.Add(this.columnTurnOn); - this.Constraints.Add(new System.Data.UniqueConstraint("JobActionsKey1", new System.Data.DataColumn[] { + this.Constraints.Add(new global::System.Data.UniqueConstraint("JobActionsKey1", new global::System.Data.DataColumn[] { this.columnID}, true)); this.columnID.AutoIncrement = true; this.columnID.AutoIncrementSeed = 1; @@ -703,100 +772,136 @@ namespace DeviceScheduler { this.columnID.Unique = true; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobActionsRow NewJobActionsRow() { return ((JobActionsRow)(this.NewRow())); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override System.Data.DataRow NewRowFromBuilder(System.Data.DataRowBuilder builder) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Data.DataRow NewRowFromBuilder(global::System.Data.DataRowBuilder builder) { return new JobActionsRow(builder); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override System.Type GetRowType() { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override global::System.Type GetRowType() { return typeof(JobActionsRow); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowChanged(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanged(global::System.Data.DataRowChangeEventArgs e) { base.OnRowChanged(e); if ((this.JobActionsRowChanged != null)) { this.JobActionsRowChanged(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowChanging(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowChanging(global::System.Data.DataRowChangeEventArgs e) { base.OnRowChanging(e); if ((this.JobActionsRowChanging != null)) { this.JobActionsRowChanging(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowDeleted(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleted(global::System.Data.DataRowChangeEventArgs e) { base.OnRowDeleted(e); if ((this.JobActionsRowDeleted != null)) { this.JobActionsRowDeleted(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - protected override void OnRowDeleting(System.Data.DataRowChangeEventArgs e) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + protected override void OnRowDeleting(global::System.Data.DataRowChangeEventArgs e) { base.OnRowDeleting(e); if ((this.JobActionsRowDeleting != null)) { this.JobActionsRowDeleting(this, new JobActionsRowChangeEvent(((JobActionsRow)(e.Row)), e.Action)); } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void RemoveJobActionsRow(JobActionsRow row) { this.Rows.Remove(row); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public static System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(System.Xml.Schema.XmlSchemaSet xs) { - System.Xml.Schema.XmlSchemaComplexType type = new System.Xml.Schema.XmlSchemaComplexType(); - System.Xml.Schema.XmlSchemaSequence sequence = new System.Xml.Schema.XmlSchemaSequence(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static global::System.Xml.Schema.XmlSchemaComplexType GetTypedTableSchema(global::System.Xml.Schema.XmlSchemaSet xs) { + global::System.Xml.Schema.XmlSchemaComplexType type = new global::System.Xml.Schema.XmlSchemaComplexType(); + global::System.Xml.Schema.XmlSchemaSequence sequence = new global::System.Xml.Schema.XmlSchemaSequence(); DataStorage ds = new DataStorage(); - xs.Add(ds.GetSchemaSerializable()); - System.Xml.Schema.XmlSchemaAny any1 = new System.Xml.Schema.XmlSchemaAny(); + global::System.Xml.Schema.XmlSchemaAny any1 = new global::System.Xml.Schema.XmlSchemaAny(); any1.Namespace = "http://www.w3.org/2001/XMLSchema"; any1.MinOccurs = new decimal(0); any1.MaxOccurs = decimal.MaxValue; - any1.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + any1.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any1); - System.Xml.Schema.XmlSchemaAny any2 = new System.Xml.Schema.XmlSchemaAny(); + global::System.Xml.Schema.XmlSchemaAny any2 = new global::System.Xml.Schema.XmlSchemaAny(); any2.Namespace = "urn:schemas-microsoft-com:xml-diffgram-v1"; any2.MinOccurs = new decimal(1); - any2.ProcessContents = System.Xml.Schema.XmlSchemaContentProcessing.Lax; + any2.ProcessContents = global::System.Xml.Schema.XmlSchemaContentProcessing.Lax; sequence.Items.Add(any2); - System.Xml.Schema.XmlSchemaAttribute attribute1 = new System.Xml.Schema.XmlSchemaAttribute(); + global::System.Xml.Schema.XmlSchemaAttribute attribute1 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute1.Name = "namespace"; attribute1.FixedValue = ds.Namespace; type.Attributes.Add(attribute1); - System.Xml.Schema.XmlSchemaAttribute attribute2 = new System.Xml.Schema.XmlSchemaAttribute(); + global::System.Xml.Schema.XmlSchemaAttribute attribute2 = new global::System.Xml.Schema.XmlSchemaAttribute(); attribute2.Name = "tableTypeName"; attribute2.FixedValue = "JobActionsDataTable"; type.Attributes.Add(attribute2); type.Particle = sequence; + global::System.Xml.Schema.XmlSchema dsSchema = ds.GetSchemaSerializable(); + if (xs.Contains(dsSchema.TargetNamespace)) { + global::System.IO.MemoryStream s1 = new global::System.IO.MemoryStream(); + global::System.IO.MemoryStream s2 = new global::System.IO.MemoryStream(); + try { + global::System.Xml.Schema.XmlSchema schema = null; + dsSchema.Write(s1); + for (global::System.Collections.IEnumerator schemas = xs.Schemas(dsSchema.TargetNamespace).GetEnumerator(); schemas.MoveNext(); ) { + schema = ((global::System.Xml.Schema.XmlSchema)(schemas.Current)); + s2.SetLength(0); + schema.Write(s2); + if ((s1.Length == s2.Length)) { + s1.Position = 0; + s2.Position = 0; + for (; ((s1.Position != s1.Length) + && (s1.ReadByte() == s2.ReadByte())); ) { + ; + } + if ((s1.Position == s1.Length)) { + return type; + } + } + } + } + finally { + if ((s1 != null)) { + s1.Close(); + } + if ((s2 != null)) { + s2.Close(); + } + } + } + xs.Add(dsSchema); return type; } } - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] - public partial class JobRow : System.Data.DataRow { + /// + ///Represents strongly named DataRow class. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public partial class JobRow : global::System.Data.DataRow { private JobDataTable tableJob; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - internal JobRow(System.Data.DataRowBuilder rb) : + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobRow(global::System.Data.DataRowBuilder rb) : base(rb) { this.tableJob = ((JobDataTable)(this.Table)); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public int ID { get { return ((int)(this[this.tableJob.IDColumn])); @@ -806,7 +911,7 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public string Name { get { return ((string)(this[this.tableJob.NameColumn])); @@ -816,14 +921,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public string Description { get { try { return ((string)(this[this.tableJob.DescriptionColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'Description\' in table \'Job\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'Description\' in table \'Job\' is DBNull.", e); } } set { @@ -831,14 +936,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public string JobName { get { try { return ((string)(this[this.tableJob.JobNameColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'JobName\' in table \'Job\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'JobName\' in table \'Job\' is DBNull.", e); } } set { @@ -846,14 +951,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public string Username { get { try { return ((string)(this[this.tableJob.UsernameColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'Username\' in table \'Job\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'Username\' in table \'Job\' is DBNull.", e); } } set { @@ -861,14 +966,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public string Password { get { try { return ((string)(this[this.tableJob.PasswordColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'Password\' in table \'Job\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'Password\' in table \'Job\' is DBNull.", e); } } set { @@ -876,14 +981,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public string StartTime { get { try { return ((string)(this[this.tableJob.StartTimeColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'StartTime\' in table \'Job\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'StartTime\' in table \'Job\' is DBNull.", e); } } set { @@ -891,74 +996,82 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsDescriptionNull() { return this.IsNull(this.tableJob.DescriptionColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetDescriptionNull() { - this[this.tableJob.DescriptionColumn] = System.Convert.DBNull; + this[this.tableJob.DescriptionColumn] = global::System.Convert.DBNull; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsJobNameNull() { return this.IsNull(this.tableJob.JobNameColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetJobNameNull() { - this[this.tableJob.JobNameColumn] = System.Convert.DBNull; + this[this.tableJob.JobNameColumn] = global::System.Convert.DBNull; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsUsernameNull() { return this.IsNull(this.tableJob.UsernameColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetUsernameNull() { - this[this.tableJob.UsernameColumn] = System.Convert.DBNull; + this[this.tableJob.UsernameColumn] = global::System.Convert.DBNull; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsPasswordNull() { return this.IsNull(this.tableJob.PasswordColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetPasswordNull() { - this[this.tableJob.PasswordColumn] = System.Convert.DBNull; + this[this.tableJob.PasswordColumn] = global::System.Convert.DBNull; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsStartTimeNull() { return this.IsNull(this.tableJob.StartTimeColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetStartTimeNull() { - this[this.tableJob.StartTimeColumn] = System.Convert.DBNull; + this[this.tableJob.StartTimeColumn] = global::System.Convert.DBNull; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobActionsRow[] GetJobActionsRows() { - return ((JobActionsRow[])(base.GetChildRows(this.Table.ChildRelations["Job_JobActions"]))); + if ((this.Table.ChildRelations["Job_JobActions"] == null)) { + return new JobActionsRow[0]; + } + else { + return ((JobActionsRow[])(base.GetChildRows(this.Table.ChildRelations["Job_JobActions"]))); + } } } - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] - public partial class JobActionsRow : System.Data.DataRow { + /// + ///Represents strongly named DataRow class. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public partial class JobActionsRow : global::System.Data.DataRow { private JobActionsDataTable tableJobActions; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - internal JobActionsRow(System.Data.DataRowBuilder rb) : + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + internal JobActionsRow(global::System.Data.DataRowBuilder rb) : base(rb) { this.tableJobActions = ((JobActionsDataTable)(this.Table)); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public int ID { get { return ((int)(this[this.tableJobActions.IDColumn])); @@ -968,14 +1081,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public int JobID { get { try { return ((int)(this[this.tableJobActions.JobIDColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'JobID\' in table \'JobActions\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'JobID\' in table \'JobActions\' is DBNull.", e); } } set { @@ -983,14 +1096,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public int DeviceID { get { try { return ((int)(this[this.tableJobActions.DeviceIDColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'DeviceID\' in table \'JobActions\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'DeviceID\' in table \'JobActions\' is DBNull.", e); } } set { @@ -998,14 +1111,14 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool TurnOn { get { try { return ((bool)(this[this.tableJobActions.TurnOnColumn])); } - catch (System.InvalidCastException e) { - throw new System.Data.StrongTypingException("The value for column \'TurnOn\' in table \'JobActions\' is DBNull.", e); + catch (global::System.InvalidCastException e) { + throw new global::System.Data.StrongTypingException("The value for column \'TurnOn\' in table \'JobActions\' is DBNull.", e); } } set { @@ -1013,7 +1126,7 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobRow JobRow { get { return ((JobRow)(this.GetParentRow(this.Table.ParentRelations["Job_JobActions"]))); @@ -1023,87 +1136,93 @@ namespace DeviceScheduler { } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsJobIDNull() { return this.IsNull(this.tableJobActions.JobIDColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetJobIDNull() { - this[this.tableJobActions.JobIDColumn] = System.Convert.DBNull; + this[this.tableJobActions.JobIDColumn] = global::System.Convert.DBNull; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsDeviceIDNull() { return this.IsNull(this.tableJobActions.DeviceIDColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetDeviceIDNull() { - this[this.tableJobActions.DeviceIDColumn] = System.Convert.DBNull; + this[this.tableJobActions.DeviceIDColumn] = global::System.Convert.DBNull; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public bool IsTurnOnNull() { return this.IsNull(this.tableJobActions.TurnOnColumn); } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public void SetTurnOnNull() { - this[this.tableJobActions.TurnOnColumn] = System.Convert.DBNull; + this[this.tableJobActions.TurnOnColumn] = global::System.Convert.DBNull; } } - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] - public class JobRowChangeEvent : System.EventArgs { + /// + ///Row event argument class + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public class JobRowChangeEvent : global::System.EventArgs { private JobRow eventRow; - private System.Data.DataRowAction eventAction; + private global::System.Data.DataRowAction eventAction; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public JobRowChangeEvent(JobRow row, System.Data.DataRowAction action) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobRowChangeEvent(JobRow row, global::System.Data.DataRowAction action) { this.eventRow = row; this.eventAction = action; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobRow Row { get { return this.eventRow; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataRowAction Action { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataRowAction Action { get { return this.eventAction; } } } - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] - public class JobActionsRowChangeEvent : System.EventArgs { + /// + ///Row event argument class + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Design.TypedDataSetGenerator", "2.0.0.0")] + public class JobActionsRowChangeEvent : global::System.EventArgs { private JobActionsRow eventRow; - private System.Data.DataRowAction eventAction; + private global::System.Data.DataRowAction eventAction; - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public JobActionsRowChangeEvent(JobActionsRow row, System.Data.DataRowAction action) { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public JobActionsRowChangeEvent(JobActionsRow row, global::System.Data.DataRowAction action) { this.eventRow = row; this.eventAction = action; } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public JobActionsRow Row { get { return this.eventRow; } } - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - public System.Data.DataRowAction Action { + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public global::System.Data.DataRowAction Action { get { return this.eventAction; } diff --git a/scheduler/DeviceScheduler/DeviceScheduler.csproj b/scheduler/DeviceScheduler/DeviceScheduler.csproj index 8aeffe49..2544ba8b 100644 --- a/scheduler/DeviceScheduler/DeviceScheduler.csproj +++ b/scheduler/DeviceScheduler/DeviceScheduler.csproj @@ -1,8 +1,8 @@ - + Debug AnyCPU - 8.0.50727 + 9.0.30729 2.0 {8B613D91-8906-4A60-BAF7-328DA437DF01} WinExe @@ -10,6 +10,27 @@ DeviceScheduler DeviceScheduler Alarm.ico + + + 2.0 + v3.5 + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true true @@ -30,7 +51,13 @@ + + 3.5 + + + 3.5 + @@ -38,7 +65,7 @@ False - References\TaskScheduler.dll + ..\..\TellScheduler\TaskScheduler.dll @@ -231,6 +258,38 @@ Designer + + + False + .NET Framework Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + false + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + true + + + False + Windows Installer 3.1 + true + + - - Service - - - - - - - -
  Home

Service
-

- -

Description

-

The QtService component is useful for developing Windows services and Unix daemons.

-

The project provides a QtService template class that can be used to implement service applications, and a QtServiceController class to control a service.

-

On Windows systems the implementation uses the Service Control Manager.

-

On Unix systems services are implemented as daemons.

- -

Classes

- - -

Examples

- - -

Tested platforms

-
    -
  • Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005
  • -
  • Qt 4.4, 4.5 / Linux / gcc
  • -
  • Qt 4.4, 4.5 / MacOS X 10.5 / gcc
  • -
-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html deleted file mode 100644 index 8462fe78..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - A simple Service Controller - - - - - - - -
  Home

A simple Service Controller
-

-

It is a very simple implementation of universal command-line controller. This controller can install and control any service written using QtService component. It demonstrates how to use QtServiceController class. On Windows, this is an alternative to using the "Services" Administrative Tool or the built-in sc.exe command-line tool to control services.

-

A note about services on Windows Vista: Installing/uninstalling and starting/stopping services requires security privileges. The simplest way to achieve this is to set the "Run as Administrator" property on the executable (right-click the executable file, select Properties, and choose the Compatibilty tab in the Properties dialog). This applies even if you are logged in as Administrator. Also, the command-line shell should be started with "Run as Administrator". Note that the service itself does not need special privileges to run. Only if you want the service to be able to install itself (the -i option) or similar, then the service will need to be run as Administrator. Otherwise, the recommended procedure is to use a controller such as this example and/or the "Services" Administrative Tool to manage the service.

-

A usability hint: in some circumstances, e.g. when running this example on Windows Vista with the "Run as Administrator" property set, output will be sent to a shell window which will close immediately upon termination, not leaving the user enough time to read the output. In such cases, append the -w(ait) argument, which will make the controller wait for a keypress before terminating.

-

Here is the complete source code:

-
 /****************************************************************************
- **
- ** This file is part of a Qt Solutions component.
- **
- ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
- **
- ** Contact:  Qt Software Information (qt-info@nokia.com)
- **
- ** Commercial Usage
- ** Licensees holding valid Qt Commercial licenses may use this file in
- ** accordance with the Qt Solutions Commercial License Agreement provided
- ** with the Software or, alternatively, in accordance with the terms
- ** contained in a written agreement between you and Nokia.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain
- ** additional rights. These rights are described in the Nokia Qt LGPL
- ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
- ** package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- ** Please note Third Party Software included with Qt Solutions may impose
- ** additional restrictions and it is the user's responsibility to ensure
- ** that they have met the licensing requirements of the GPL, LGPL, or Qt
- ** Solutions Commercial license and the relevant license of the Third
- ** Party Software they are using.
- **
- ** If you are unsure which license is appropriate for your use, please
- ** contact the sales department at qt-sales@nokia.com.
- **
- ****************************************************************************/
-
- #include <QtCore/QStringList>
- #include <QtCore/QDir>
- #include <QtCore/QSettings>
- #include "qtservice.h"
-
- int processArgs(int argc, char **argv)
- {
-     if (argc > 2) {
-         QString arg1(argv[1]);
-         if (arg1 == QLatin1String("-i") ||
-             arg1 == QLatin1String("-install")) {
-             if (argc > 2) {
-                 QString account;
-                 QString password;
-                 QString path(argv[2]);
-                 if (argc > 3)
-                     account = argv[3];
-                 if (argc > 4)
-                     password = argv[4];
-                 printf("The service %s installed.\n",
-                        (QtServiceController::install(path, account, password) ? "was" : "was not"));
-                 return 0;
-             }
-         } else {
-             QString serviceName(argv[1]);
-             QtServiceController controller(serviceName);
-             QString option(argv[2]);
-             if (option == QLatin1String("-u") ||
-                 option == QLatin1String("-uninstall")) {
-                 printf("The service \"%s\" %s uninstalled.\n",
-                             controller.serviceName().toLatin1().constData(),
-                             (controller.uninstall() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-s") ||
-                        option == QLatin1String("-start")) {
-                 QStringList args;
-                 for (int i = 3; i < argc; ++i)
-                     args.append(QString::fromLocal8Bit(argv[i]));
-                 printf("The service \"%s\" %s started.\n",
-                        controller.serviceName().toLatin1().constData(),
-                             (controller.start(args) ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-t") ||
-                        option == QLatin1String("-terminate")) {
-                 printf("The service \"%s\" %s stopped.\n",
-                        controller.serviceName().toLatin1().constData(),
-                        (controller.stop() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-p") ||
-                     option == QLatin1String("-pause")) {
-                 printf("The service \"%s\" %s paused.\n",
-                        controller.serviceName().toLatin1().constData(),
-                        (controller.pause() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-r") ||
-                        option == QLatin1String("-resume")) {
-                 printf("The service \"%s\" %s resumed.\n",
-                        controller.serviceName().toLatin1().constData(),
-                        (controller.resume() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-c") ||
-                        option == QLatin1String("-command")) {
-                 if (argc > 3) {
-                     QString codestr(argv[3]);
-                     int code = codestr.toInt();
-                     printf("The command %s sent to the service \"%s\".\n",
-                            (controller.sendCommand(code) ? "was" : "was not"),
-                            controller.serviceName().toLatin1().constData());
-                     return 0;
-                 }
-             } else if (option == QLatin1String("-v") ||
-                     option == QLatin1String("-version")) {
-                 bool installed = controller.isInstalled();
-                 printf("The service\n"
-                         "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData());
-                 printf("is %s", (installed ? "installed" : "not installed"));
-                 printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running"));
-                 if (installed) {
-                     printf("path: %s\n", controller.serviceFilePath().toLatin1().data());
-                     printf("description: %s\n", controller.serviceDescription().toLatin1().data());
-                     printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual");
-                 }
-                 return 0;
-             }
-         }
-     }
-     printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n"
-             "\t-i(nstall) PATH\t: Install the service\n"
-             "\t-v(ersion)\t: Print status of the service\n"
-             "\t-u(ninstall)\t: Uninstall the service\n"
-             "\t-s(tart)\t: Start the service\n"
-             "\t-t(erminate)\t: Stop the service\n"
-             "\t-p(ause)\t: Pause the service\n"
-             "\t-r(esume)\t: Resume the service\n"
-             "\t-c(ommand) CODE\t: Send a command to the service\n"
-             "\t-h(elp)\t\t: Print this help info\n"
-             "\t-w(ait)\t\t: Wait for keypress when done\n");
-     return 0;
- }
-
- int main(int argc, char **argv)
- {
- #if !defined(Q_WS_WIN)
-     // QtService stores service settings in SystemScope, which normally require root privileges.
-     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
-     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
-     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
- #endif
-
-     int result = processArgs(argc, argv);
-
-     if (QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-w") ||
-         QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-wait")) {
-         printf("\nPress Enter to continue...");
-         QFile input;
-         input.open(stdin, QIODevice::ReadOnly);
-         input.readLine();
-         printf("\n");
-     }
-
-     return result;
- }
-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html deleted file mode 100644 index 34928841..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - An Interactive Service - - - - - - - -
  Home

An Interactive Service
-

-

This example implements a service with a simple user interface.

-

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes.

-

However, although not recommended in the general case, in certain circumstances a service may provide a GUI itself. This is typically only possible if the service process is run as the same user as the one that is logged in, so that it will have access to the screen. Note however that on Windows Vista, service GUIs are not allowed at all, since services run in a diferent session than all user sessions, for security reasons.

-

This example demonstrates how to subclass the QtService class, the use of start(), stop(), pause(), resume(), and how to use processCommand() to receive control commands while running.

-

Here is the complete source code:

-
 /****************************************************************************
- **
- ** This file is part of a Qt Solutions component.
- **
- ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
- **
- ** Contact:  Qt Software Information (qt-info@nokia.com)
- **
- ** Commercial Usage
- ** Licensees holding valid Qt Commercial licenses may use this file in
- ** accordance with the Qt Solutions Commercial License Agreement provided
- ** with the Software or, alternatively, in accordance with the terms
- ** contained in a written agreement between you and Nokia.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain
- ** additional rights. These rights are described in the Nokia Qt LGPL
- ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
- ** package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- ** Please note Third Party Software included with Qt Solutions may impose
- ** additional restrictions and it is the user's responsibility to ensure
- ** that they have met the licensing requirements of the GPL, LGPL, or Qt
- ** Solutions Commercial license and the relevant license of the Third
- ** Party Software they are using.
- **
- ** If you are unsure which license is appropriate for your use, please
- ** contact the sales department at qt-sales@nokia.com.
- **
- ****************************************************************************/
-
- #include <QtGui/QApplication>
- #include <QtGui/QDesktopWidget>
- #include <QtGui/QLabel>
- #include <QtCore/QDir>
- #include <QtCore/QSettings>
- #include "qtservice.h"
-
- class InteractiveService : public QtService<QApplication>
- {
- public:
-     InteractiveService(int argc, char **argv);
-     ~InteractiveService();
-
- protected:
-
-     void start();
-     void stop();
-     void pause();
-     void resume();
-     void processCommand(int code);
-
- private:
-     QLabel *gui;
- };
-
- InteractiveService::InteractiveService(int argc, char **argv)
-     : QtService<QApplication>(argc, argv, "Qt Interactive Service"), gui(0)
- {
-     setServiceDescription("A Qt service with user interface.");
-     setServiceFlags(QtServiceBase::CanBeSuspended);
- }
-
- InteractiveService::~InteractiveService()
- {
- }
-
- void InteractiveService::start()
- {
- #if defined(Q_OS_WIN)
-     if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) &&
-         (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) {
-         logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error );
-         return;
-     }
- #endif
-
-     qApp->setQuitOnLastWindowClosed(false);
-
-     gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
-     gui->move(QApplication::desktop()->availableGeometry().topLeft());
-     gui->show();
- }
-
- void InteractiveService::stop()
- {
-     delete gui;
- }
-
- void InteractiveService::pause()
- {
-     if (gui)
-         gui->hide();
- }
-
- void InteractiveService::resume()
- {
-     if (gui)
-         gui->show();
- }
-
- void InteractiveService::processCommand(int code)
- {
-     gui->setText("Command code " + QString::number(code));
-     gui->adjustSize();
- }
-
- int main(int argc, char **argv)
- {
- #if !defined(Q_WS_WIN)
-     // QtService stores service settings in SystemScope, which normally require root privileges.
-     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
-     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
-     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
- #endif
-     InteractiveService service(argc, argv);
-     return service.exec();
- }
-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html deleted file mode 100644 index 00cfb826..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - A simple HTTP Server - - - - - - - -
  Home

A simple HTTP Server
-

-

It is a very simple implementation of a HTTP daemon that listens on chosen port (defaultly 8080) and sends back a simple HTML page back for every GET request it gets. After sending the page, it closes the connection.

-
 // HttpDaemon is the the class that implements the simple HTTP server.
- class HttpDaemon : public QTcpServer
- {
-     Q_OBJECT
- public:
-     HttpDaemon(quint16 port, QObject* parent = 0)
-         : QTcpServer(parent), disabled(false)
-     {
-         listen(QHostAddress::Any, port);
-     }
-
-     void incomingConnection(int socket)
-     {
-         if (disabled)
-             return;
-
-         // When a new client connects, the server constructs a QTcpSocket and all
-         // communication with the client is done over this QTcpSocket. QTcpSocket
-         // works asynchronously, this means that all the communication is done
-         // in the two slots readClient() and discardClient().
-         QTcpSocket* s = new QTcpSocket(this);
-         connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
-         connect(s, SIGNAL(disconnected()), this, SLOT(discardClient()));
-         s->setSocketDescriptor(socket);
-
-         QtServiceBase::instance()->logMessage("New Connection");
-     }
-
-     void pause()
-     {
-         disabled = true;
-     }
-
-     void resume()
-     {
-         disabled = false;
-     }
-
- private slots:
-     void readClient()
-     {
-         if (disabled)
-             return;
-
-         // This slot is called when the client sent data to the server. The
-         // server looks if it was a get request and sends a very simple HTML
-         // document back.
-         QTcpSocket* socket = (QTcpSocket*)sender();
-         if (socket->canReadLine()) {
-             QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*"));
-             if (tokens[0] == "GET") {
-                 QTextStream os(socket);
-                 os.setAutoDetectUnicode(true);
-                 os << "HTTP/1.0 200 Ok\r\n"
-                     "Content-Type: text/html; charset=\"utf-8\"\r\n"
-                     "\r\n"
-                     "<h1>Nothing to see here</h1>\n"
-                     << QDateTime::currentDateTime().toString() << "\n";
-                 socket->close();
-
-                 QtServiceBase::instance()->logMessage("Wrote to client");
-
-                 if (socket->state() == QTcpSocket::UnconnectedState) {
-                     delete socket;
-                     QtServiceBase::instance()->logMessage("Connection closed");
-                 }
-             }
-         }
-     }
-     void discardClient()
-     {
-         QTcpSocket* socket = (QTcpSocket*)sender();
-         socket->deleteLater();
-
-         QtServiceBase::instance()->logMessage("Connection closed");
-     }
-
- private:
-     bool disabled;
- };
-

The server implementation uses the QtService::logMessage() function to send messages and status reports to the system event log. The server also supports a paused state in which case incoming requests are ignored.

-

The HttpService class subclasses QtService to implement the service functionality.

-
 class HttpService : public QtService<QCoreApplication>
- {
- public:
-     HttpService(int argc, char **argv)
-         : QtService<QCoreApplication>(argc, argv, "Qt HTTP Daemon")
-     {
-         setServiceDescription("A dummy HTTP service implemented with Qt");
-         setServiceFlags(QtServiceBase::CanBeSuspended);
-     }
-

The constructor calls the QtService constructor instantiated with QCoreApplication since our service will not use GUI. The first two parameters of our constructor are passed to QtService. The last parameter, "Qt HTTP Daemon", is the name of the service.

-
 protected:
-     void start()
-     {
-         QCoreApplication *app = application();
-
-         quint16 port = (app->argc() > 1) ?
-                 QString::fromLocal8Bit(app->argv()[1]).toUShort() : 8080;
-         daemon = new HttpDaemon(port, app);
-
-         if (!daemon->isListening()) {
-             logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error);
-             app->quit();
-         }
-     }
-

The implementation of start() first checks if the user passed a port number. If yes that port is used by server to listen on. Otherwise default 8080 port is used. Then creates an instance of the HTTP server using operator new, passing the application object as the parent to ensure that the object gets destroyed.

-
     void pause()
-     {
-         daemon->pause();
-     }
-
-     void resume()
-     {
-         daemon->resume();
-     }
-
- private:
-     HttpDaemon *daemon;
- };
-

The implementations of pause() and resume() forward the request to the server object.

-
 #include "main.moc"
-
- int main(int argc, char **argv)
- {
- #if !defined(Q_WS_WIN)
-     // QtService stores service settings in SystemScope, which normally require root privileges.
-     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
-     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
-     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
- #endif
-     HttpService service(argc, argv);
-     return service.exec();
- }
-

The main entry point function creates the service object and uses the exec() function to execute the service.

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html deleted file mode 100644 index 781a154b..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - List of All Members for QtService - - - - - - - -
  Home

List of All Members for QtService

-

This is the complete list of members for QtService, including inherited members.

-

- -
-

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf deleted file mode 100644 index 3ba64c80..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf +++ /dev/null @@ -1,76 +0,0 @@ - - -
-
- QtService - application -
-
-
- QtServiceBase - MessageType - QtServiceBase::Warning - QtServiceBase::Error - QtServiceBase::Success - QtServiceBase::Information - ServiceFlag - ServiceFlags - QtServiceBase::Default - QtServiceBase::CannotBeStopped - QtServiceBase::CanBeSuspended - createApplication - exec - executeApplication - instance - logMessage - pause - processCommand - resume - serviceDescription - serviceFlags - serviceName - setServiceDescription - setServiceFlags - setStartupType - start - startupType - stop -
-
-
- QtServiceController - StartupType - QtServiceController::AutoStartup - QtServiceController::ManualStartup - install - isInstalled - isRunning - pause - resume - sendCommand - serviceDescription - serviceFilePath - serviceName - start - startupType - stop - uninstall -
-
-
-
-
- A simple HTTP Server -
-
- A simple Service Controller -
-
- An Interactive Service -
-
- Service -
-
-
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html deleted file mode 100644 index 370c8ee6..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - QtService Class Reference - - - - - - - -
  Home

QtService Class Reference

-

The QtService is a convenient template class that allows you to create a service for a particular application type. More...

-
 #include <QtService>

Inherits QtServiceBase.

- - -

Public Functions

- - - -

Protected Functions

- - -

Additional Inherited Members

- - -
-

Detailed Description

-

The QtService is a convenient template class that allows you to create a service for a particular application type.

-

A Windows service or Unix daemon (a "service"), is a program that runs "in the background" independently of whether a user is logged in or not. A service is often set up to start when the machine boots up, and will typically run continuously as long as the machine is on.

-

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes. (In certain circumstances, a service may provide a GUI itself, ref. the "interactive" example documentation).

-

Note: On Unix systems, this class relies on facilities provided by the QtNetwork module, provided as part of the Qt Open Source Edition and certain Qt Commercial Editions.

-

The QtService class functionality is inherited from QtServiceBase, but in addition the QtService class binds an instance of QtServiceBase with an application type.

-

Typically, you will create a service by subclassing the QtService template class. For example:

-
 class MyService : public QtService<QApplication>
- {
- public:
-     MyService(int argc, char **argv);
-     ~MyService();
-
- protected:
-     void start();
-     void stop();
-     void pause();
-     void resume();
-     void processCommand(int code);
- };
-

The application type can be QCoreApplication for services without GUI, QApplication for services with GUI or you can use your own custom application type.

-

You must reimplement the QtServiceBase::start() function to perform the service's work. Usually you create some main object on the heap which is the heart of your service.

-

In addition, you might want to reimplement the QtServiceBase::pause(), QtServiceBase::processCommand(), QtServiceBase::resume() and QtServiceBase::stop() to intervene the service's process on controller requests. You can control any given service using an instance of the QtServiceController class which also allows you to control services from separate applications. The mentioned functions are all virtual and won't do anything unless they are reimplemented.

-

Your custom service is typically instantiated in the application's main function. Then the main function will call your service's exec() function, and return the result of that call. For example:

-
     int main(int argc, char **argv)
-     {
-         MyService service(argc, argv);
-         return service.exec();
-     }
-

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and exit.

-

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

-

See also QtServiceBase and QtServiceController.

-
-

Member Function Documentation

-

QtService::QtService ( int argc, char ** argv, const QString & name )

-

Constructs a QtService object called name. The argc and argv parameters are parsed after the exec() function has been called. Then they are passed to the application's constructor.

-

There can only be one QtService object in a process.

-

See also QtServiceBase().

-

QtService::~QtService ()

-

Destroys the service object.

-

Application * QtService::application () const   [protected]

-

Returns a pointer to the application object.

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index deleted file mode 100644 index 494e0060..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch deleted file mode 100644 index 2757197b7792d8ff6d6d45bcd457126e03c97151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57344 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 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp deleted file mode 100644 index 96d058f5..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp +++ /dev/null @@ -1,90 +0,0 @@ - - - com.trolltech.qtsolutions.qtservice_2.6 - qdoc - - qt - qtservice - solutions - - - qt - qtservice - solutions - -
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - qtservice-example-controller.html - index.html - qtservice-example-server.html - qtservice-example-interactive.html - qtservicebase.html - qtservice.html - qtservicecontroller.html - classic.css - images/qt-logo.png - -
-
diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html deleted file mode 100644 index 909b555c..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - List of All Members for QtServiceBase - - - - - - - -
  Home

List of All Members for QtServiceBase

-

This is the complete list of members for QtServiceBase, including inherited members.

-

- -
-

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html deleted file mode 100644 index 680a1df9..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - QtServiceBase Class Reference - - - - - - - -
  Home

QtServiceBase Class Reference

-

The QtServiceBase class provides an API for implementing Windows services and Unix daemons. More...

-
 #include <QtServiceBase>

Inherited by QtService.

- - -

Public Types

- - -

Public Functions

- - -

Static Public Members

- - -

Protected Functions

- - -
-

Detailed Description

-

The QtServiceBase class provides an API for implementing Windows services and Unix daemons.

-

A Windows service or Unix daemon (a "service"), is a program that runs "in the background" independently of whether a user is logged in or not. A service is often set up to start when the machine boots up, and will typically run continuously as long as the machine is on.

-

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes. (In certain circumstances, a service may provide a GUI itself, ref. the "interactive" example documentation).

-

Typically, you will create a service by subclassing the QtService template class which inherits QtServiceBase and allows you to create a service for a particular application type.

-

The Windows implementation uses the NT Service Control Manager, and the application can be controlled through the system administration tools. Services are usually launched using the system account, which requires that all DLLs that the service executable depends on (i.e. Qt), are located in the same directory as the service, or in a system path.

-

On Unix a service is implemented as a daemon.

-

You can retrieve the service's description, state, and startup type using the serviceDescription(), serviceFlags() and startupType() functions respectively. The service's state is decribed by the ServiceFlag enum. The mentioned properites can also be set using the corresponding set functions. In addition you can retrieve the service's name using the serviceName() function.

-

Several of QtServiceBase's protected functions are called on requests from the QtServiceController class:

- -

You can control any given service using an instance of the QtServiceController class which also allows you to control services from separate applications. The mentioned functions are all virtual and won't do anything unless they are reimplemented. You can reimplement these functions to pause and resume the service's execution, as well as process user commands and perform additional clean-ups before shutting down.

-

QtServiceBase also provides the static instance() function which returns a pointer to an application's QtServiceBase instance. In addition, a service can report events to the system's event log using the logMessage() function. The MessageType enum describes the different types of messages a service reports.

-

The implementation of a service application's main function typically creates an service object derived by subclassing the QtService template class. Then the main function will call this service's exec() function, and return the result of that call. For example:

-
 int main(int argc, char **argv)
- {
-     MyService service(argc, argv);
-     return service.exec();
- }
-

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and return.

-

The following arguments are recognized as service specific:

-

- - - - - - - - - -
ShortLongExplanation
-i-installInstall the service.
-u-uninstallUninstall the service.
-e-execExecute the service as a standalone application (useful for debug purposes). This is a blocking call, the service will be executed like a normal application. In this mode you will not be able to communicate with the service from the contoller.
-t-terminateStop the service.
-p-pausePause the service.
-r-resumeResume a paused service.
-c cmd-command cmdSend the user defined command code cmd to the service application.
-v-versionDisplay version and status information.

-

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

-

See also QtService and QtServiceController.

-
-

Member Type Documentation

-

enum QtServiceBase::MessageType

-

This enum describes the different types of messages a service reports to the system log.

-

- - - - - -
ConstantValueDescription
QtServiceBase::Success0An operation has succeeded, e.g. the service is started.
QtServiceBase::Error1An operation failed, e.g. the service failed to start.
QtServiceBase::Warning2An operation caused a warning that might require user interaction.
QtServiceBase::Information3Any type of usually non-critical information.

-

enum QtServiceBase::ServiceFlag
flags QtServiceBase::ServiceFlags

-

This enum describes the different states of a service.

-

- - - - -
ConstantValueDescription
QtServiceBase::Default0x00The service can be stopped, but not suspended.
QtServiceBase::CanBeSuspended0x01The service can be suspended.
QtServiceBase::CannotBeStopped0x02The service cannot be stopped.

-

The ServiceFlags type is a typedef for QFlags<ServiceFlag>. It stores an OR combination of ServiceFlag values.

-
-

Member Function Documentation

-

QtServiceBase::QtServiceBase ( int argc, char ** argv, const QString & name )

-

Creates a service instance called name. The argc and argv parameters are parsed after the exec() function has been called. Then they are passed to the application's constructor. The application type is determined by the QtService subclass.

-

The service is neither installed nor started. The name must not contain any backslashes or be longer than 255 characters. In addition, the name must be unique in the system's service database.

-

See also exec(), start(), and QtServiceController::install().

-

QtServiceBase::~QtServiceBase ()   [virtual]

-

Destroys the service object. This neither stops nor uninstalls the service.

-

To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the QtServiceController::uninstall() function.

-

See also stop() and QtServiceController::uninstall().

-

void QtServiceBase::createApplication ( int & argc, char ** argv )   [pure virtual protected]

-

Creates the application object using the argc and argv parameters.

-

This function is only called when no service specific arguments were passed to the service constructor, and is called by exec() before it calls the executeApplication() and start() functions.

-

The createApplication() function is implemented in QtService, but you might want to reimplement it, for example, if the chosen application type's constructor needs additional arguments.

-

See also exec() and QtService.

-

int QtServiceBase::exec ()

-

Executes the service.

-

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and exit.

-

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

-

See also QtServiceController.

-

int QtServiceBase::executeApplication ()   [pure virtual protected]

-

Executes the application previously created with the createApplication() function.

-

This function is only called when no service specific arguments were passed to the service constructor, and is called by exec() after it has called the createApplication() function and before start() function.

-

This function is implemented in QtService.

-

See also exec() and createApplication().

-

QtServiceBase * QtServiceBase::instance ()   [static]

-

Returns a pointer to the current application's QtServiceBase instance.

-

void QtServiceBase::logMessage ( const QString & message, MessageType type = Success, int id = 0, uint category = 0, const QByteArray & data = QByteArray() )

-

Reports a message of the given type with the given message to the local system event log. The message identifier id and the message category are user defined values. The data parameter can contain arbitrary binary data.

-

Message strings for id and category must be provided by a message file, which must be registered in the system registry. Refer to the MSDN for more information about how to do this on Windows.

-

See also MessageType.

-

void QtServiceBase::pause ()   [virtual protected]

-

Reimplement this function to pause the service's execution (for example to stop a polling timer, or to ignore socket notifiers).

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also resume() and QtServiceController::pause().

-

void QtServiceBase::processCommand ( int code )   [virtual protected]

-

Reimplement this function to process the user command code.

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also QtServiceController::sendCommand().

-

void QtServiceBase::resume ()   [virtual protected]

-

Reimplement this function to continue the service after a call to pause().

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also pause() and QtServiceController::resume().

-

QString QtServiceBase::serviceDescription () const

-

Returns the description of the service.

-

See also setServiceDescription() and serviceName().

-

ServiceFlags QtServiceBase::serviceFlags () const

-

Returns the service's state which is decribed using the ServiceFlag enum.

-

See also ServiceFlags and setServiceFlags().

-

QString QtServiceBase::serviceName () const

-

Returns the name of the service.

-

See also QtServiceBase() and serviceDescription().

-

void QtServiceBase::setServiceDescription ( const QString & description )

-

Sets the description of the service to the given description.

-

See also serviceDescription().

-

void QtServiceBase::setServiceFlags ( ServiceFlags flags )

-

Sets the service's state to the state described by the given flags.

-

See also ServiceFlags and serviceFlags().

-

void QtServiceBase::setStartupType ( QtServiceController::StartupType type )

-

Sets the service's startup type to the given type.

-

See also QtServiceController::StartupType and startupType().

-

void QtServiceBase::start ()   [pure virtual protected]

-

This function must be implemented in QtServiceBase subclasses in order to perform the service's work. Usually you create some main object on the heap which is the heart of your service.

-

The function is only called when no service specific arguments were passed to the service constructor, and is called by exec() after it has called the executeApplication() function.

-

Note that you don't need to create an application object or call its exec() function explicitly.

-

See also exec(), stop(), and QtServiceController::start().

-

QtServiceController::StartupType QtServiceBase::startupType () const

-

Returns the service's startup type.

-

See also QtServiceController::StartupType and setStartupType().

-

void QtServiceBase::stop ()   [virtual protected]

-

Reimplement this function to perform additional cleanups before shutting down (for example deleting a main object if it was created in the start() function).

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also start() and QtServiceController::stop().

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html deleted file mode 100644 index 1ea83044..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - List of All Members for QtServiceController - - - - - - - -
  Home

List of All Members for QtServiceController

-

This is the complete list of members for QtServiceController, including inherited members.

-

- -
-

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html deleted file mode 100644 index 6ec6d338..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - QtServiceController Class Reference - - - - - - - -
  Home

QtServiceController Class Reference

-

The QtServiceController class allows you to control services from separate applications. More...

-
 #include <QtServiceController>
- -

Public Types

- - -

Public Functions

- - -

Static Public Members

-
    -
  • bool install ( const QString & serviceFilePath, const QString & account = QString(), const QString & password = QString() )
  • -
- -
-

Detailed Description

-

The QtServiceController class allows you to control services from separate applications.

-

QtServiceController provides a collection of functions that lets you install and run a service controlling its execution, as well as query its status.

-

In order to run a service, the service must be installed in the system's service database using the install() function. The system will start the service depending on the specified StartupType; it can either be started during system startup, or when a process starts it manually.

-

Once a service is installed, the service can be run and controlled manually using the start(), stop(), pause(), resume() or sendCommand() functions. You can at any time query for the service's status using the isInstalled() and isRunning() functions, or you can query its properties using the serviceDescription(), serviceFilePath(), serviceName() and startupType() functions. For example:

-
 MyService service;       \\ which inherits QtService
- QString serviceFilePath;
-
- QtServiceController controller(service.serviceName());
-
- if (controller.install(serviceFilePath))
-     controller.start()
-
- if (controller.isRunning())
-     QMessageBox::information(this, tr("Service Status"),
-                              tr("The %1 service is started").arg(controller.serviceName()));
-
- ...
-
- controller.stop();
- controller.uninstall();
- }
-

An instance of the service controller can only control one single service. To control several services within one application, you must create en equal number of service controllers.

-

The QtServiceController destructor neither stops nor uninstalls the associated service. To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the uninstall() function.

-

See also QtServiceBase and QtService.

-
-

Member Type Documentation

-

enum QtServiceController::StartupType

-

This enum describes when a service should be started.

-

- - - -
ConstantValueDescription
QtServiceController::AutoStartup0The service is started during system startup.
QtServiceController::ManualStartup1The service must be started manually by a process.

-

Warning: The StartupType enum is ignored under UNIX-like systems. A service, or daemon, can only be started manually on such systems with current implementation.

-

See also startupType().

-
-

Member Function Documentation

-

QtServiceController::QtServiceController ( const QString & name )

-

Creates a controller object for the service with the given name.

-

QtServiceController::~QtServiceController ()   [virtual]

-

Destroys the service controller. This neither stops nor uninstalls the controlled service.

-

To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the uninstall() function.

-

See also stop() and QtServiceController::uninstall().

-

bool QtServiceController::install ( const QString & serviceFilePath, const QString & account = QString(), const QString & password = QString() )   [static]

-

Installs the service with the given serviceFilePath and returns true if the service is installed successfully; otherwise returns false.

-

On Windows service is installed in the system's service control manager with the given account and password.

-

On Unix service configuration is written to QSettings::SystemScope using "QtSoftware" as organization name. account and password arguments are ignored.

-

Warning: Due to the different implementations of how services (daemons) are installed on various UNIX-like systems, this method doesn't integrate the service into the system's startup scripts.

-

See also uninstall() and start().

-

bool QtServiceController::isInstalled () const

-

Returns true if the service is installed; otherwise returns false.

-

On Windows it uses the system's service control manager.

-

On Unix it checks configuration written to QSettings::SystemScope using "QtSoftware" as organization name.

-

See also install().

-

bool QtServiceController::isRunning () const

-

Returns true if the service is running; otherwise returns false. A service must be installed before it can be run using a controller.

-

See also start() and isInstalled().

-

bool QtServiceController::pause ()

-

Requests the running service to pause. If the service's state is QtServiceBase::CanBeSuspended, the service will call the QtServiceBase::pause() implementation. The function does nothing if the service is not running.

-

Returns true if a running service was successfully paused; otherwise returns false.

-

See also resume(), QtServiceBase::pause(), and QtServiceBase::ServiceFlags.

-

bool QtServiceController::resume ()

-

Requests the running service to continue. If the service's state is QtServiceBase::CanBeSuspended, the service will call the QtServiceBase::resume() implementation. This function does nothing if the service is not running.

-

Returns true if a running service was successfully resumed; otherwise returns false.

-

See also pause(), QtServiceBase::resume(), and QtServiceBase::ServiceFlags.

-

bool QtServiceController::sendCommand ( int code )

-

Sends the user command code to the service. The service will call the QtServiceBase::processCommand() implementation. This function does nothing if the service is not running.

-

Returns true if the request was sent to a running service; otherwise returns false.

-

See also QtServiceBase::processCommand().

-

QString QtServiceController::serviceDescription () const

-

Returns the description of the controlled service.

-

See also install() and serviceName().

-

QString QtServiceController::serviceFilePath () const

-

Returns the file path to the controlled service.

-

See also install() and serviceName().

-

QString QtServiceController::serviceName () const

-

Returns the name of the controlled service.

-

See also QtServiceController() and serviceDescription().

-

bool QtServiceController::start ( const QStringList & arguments )

-

Starts the installed service passing the given arguments to the service. A service must be installed before a controller can run it.

-

Returns true if the service could be started; otherwise returns false.

-

See also install() and stop().

-

bool QtServiceController::start ()

-

This is an overloaded member function, provided for convenience.

-

Starts the installed service without passing any arguments to the service.

-

StartupType QtServiceController::startupType () const

-

Returns the startup type of the controlled service.

-

See also install() and serviceName().

-

bool QtServiceController::stop ()

-

Requests the running service to stop. The service will call the QtServiceBase::stop() implementation unless the service's state is QtServiceBase::CannotBeStopped. This function does nothing if the service is not running.

-

Returns true if a running service was successfully stopped; otherwise false.

-

See also start(), QtServiceBase::stop(), and QtServiceBase::ServiceFlags.

-

bool QtServiceController::uninstall ()

-

Uninstalls the service and returns true if successful; otherwise returns false.

-

On Windows service is uninstalled using the system's service control manager.

-

On Unix service configuration is cleared using QSettings::SystemScope with "QtSoftware" as organization name.

-

See also install().

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png deleted file mode 100644 index 794162f5af58e7b38beebf472842fc9703ede19b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4075 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 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc deleted file mode 100644 index 31c3e87b..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc +++ /dev/null @@ -1,46 +0,0 @@ -/*! - \page index.html - \title Service - - \section1 Description - - The QtService component is useful for developing Windows - services and Unix daemons. - - - - The project provides a QtService template class that can be used to - implement service applications, and a QtServiceController class - to control a service. - - On Windows systems the implementation uses the Service Control - Manager. - - On Unix systems services are implemented as daemons. - - - - \section1 Classes - \list - \i QtServiceController \i QtServiceBase \i QtService\endlist - - \section1 Examples - \list - \i \link qtservice-example-interactive.html An Interactive Service \endlink \i \link qtservice-example-server.html A simple HTTP Server \endlink \i \link qtservice-example-controller.html A simple Service Controller \endlink \endlist - - - - - - - \section1 Tested platforms - \list - \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005 - \i Qt 4.4, 4.5 / Linux / gcc - \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc - \endlist - - - - - */ \ No newline at end of file diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro deleted file mode 100644 index 722084b8..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app -CONFIG += console qt -QT = core - -SOURCES = main.cpp - -include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc deleted file mode 100644 index 7de827bd..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -/*! \page qtservice-example-controller.html - \title A simple Service Controller - - It is a very simple implementation of universal command-line - controller. This controller can install and control any service - written using QtService component. It demonstrates how to use - QtServiceController class. On Windows, this is an alternative to - using the "Services" Administrative Tool or the built-in \c sc.exe - command-line tool to control services. - - A note about services on Windows Vista: Installing/uninstalling - and starting/stopping services requires security privileges. The - simplest way to achieve this is to set the "Run as Administrator" - property on the executable (right-click the executable file, - select Properties, and choose the Compatibilty tab in the - Properties dialog). This applies even if you are logged in as - Administrator. Also, the command-line shell should be started with - "Run as Administrator". Note that the service itself does not need - special privileges to run. Only if you want the service to be able - to install itself (the -i option) or similar, then the service - will need to be run as Administrator. Otherwise, the recommended - procedure is to use a controller such as this example and/or the - "Services" Administrative Tool to manage the service. - - A usability hint: in some circumstances, e.g. when running this - example on Windows Vista with the "Run as Administrator" property - set, output will be sent to a shell window which will close - immediately upon termination, not leaving the user enough time to - read the output. In such cases, append the -w(ait) argument, which - will make the controller wait for a keypress before terminating. - - Here is the complete source code: - - \quotefile controller/main.cpp -*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp deleted file mode 100644 index a64edc15..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include -#include -#include -#include "qtservice.h" - -int processArgs(int argc, char **argv) -{ - if (argc > 2) { - QString arg1(argv[1]); - if (arg1 == QLatin1String("-i") || - arg1 == QLatin1String("-install")) { - if (argc > 2) { - QString account; - QString password; - QString path(argv[2]); - if (argc > 3) - account = argv[3]; - if (argc > 4) - password = argv[4]; - printf("The service %s installed.\n", - (QtServiceController::install(path, account, password) ? "was" : "was not")); - return 0; - } - } else { - QString serviceName(argv[1]); - QtServiceController controller(serviceName); - QString option(argv[2]); - if (option == QLatin1String("-u") || - option == QLatin1String("-uninstall")) { - printf("The service \"%s\" %s uninstalled.\n", - controller.serviceName().toLatin1().constData(), - (controller.uninstall() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-s") || - option == QLatin1String("-start")) { - QStringList args; - for (int i = 3; i < argc; ++i) - args.append(QString::fromLocal8Bit(argv[i])); - printf("The service \"%s\" %s started.\n", - controller.serviceName().toLatin1().constData(), - (controller.start(args) ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-t") || - option == QLatin1String("-terminate")) { - printf("The service \"%s\" %s stopped.\n", - controller.serviceName().toLatin1().constData(), - (controller.stop() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-p") || - option == QLatin1String("-pause")) { - printf("The service \"%s\" %s paused.\n", - controller.serviceName().toLatin1().constData(), - (controller.pause() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-r") || - option == QLatin1String("-resume")) { - printf("The service \"%s\" %s resumed.\n", - controller.serviceName().toLatin1().constData(), - (controller.resume() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-c") || - option == QLatin1String("-command")) { - if (argc > 3) { - QString codestr(argv[3]); - int code = codestr.toInt(); - printf("The command %s sent to the service \"%s\".\n", - (controller.sendCommand(code) ? "was" : "was not"), - controller.serviceName().toLatin1().constData()); - return 0; - } - } else if (option == QLatin1String("-v") || - option == QLatin1String("-version")) { - bool installed = controller.isInstalled(); - printf("The service\n" - "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData()); - printf("is %s", (installed ? "installed" : "not installed")); - printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running")); - if (installed) { - printf("path: %s\n", controller.serviceFilePath().toLatin1().data()); - printf("description: %s\n", controller.serviceDescription().toLatin1().data()); - printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual"); - } - return 0; - } - } - } - printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n" - "\t-i(nstall) PATH\t: Install the service\n" - "\t-v(ersion)\t: Print status of the service\n" - "\t-u(ninstall)\t: Uninstall the service\n" - "\t-s(tart)\t: Start the service\n" - "\t-t(erminate)\t: Stop the service\n" - "\t-p(ause)\t: Pause the service\n" - "\t-r(esume)\t: Resume the service\n" - "\t-c(ommand) CODE\t: Send a command to the service\n" - "\t-h(elp)\t\t: Print this help info\n" - "\t-w(ait)\t\t: Wait for keypress when done\n"); - return 0; -} - - -int main(int argc, char **argv) -{ -#if !defined(Q_WS_WIN) - // QtService stores service settings in SystemScope, which normally require root privileges. - // To allow testing this example as non-root, we change the directory of the SystemScope settings file. - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); - qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); -#endif - - int result = processArgs(argc, argv); - - if (QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-w") || - QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-wait")) { - printf("\nPress Enter to continue..."); - QFile input; - input.open(stdin, QIODevice::ReadOnly); - input.readLine(); - printf("\n"); - } - - return result; -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro deleted file mode 100644 index 109b9294..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = interactive \ - server \ - controller diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro deleted file mode 100644 index 6dba6f80..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE = app -CONFIG += console qt - -SOURCES = main.cpp - -include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc deleted file mode 100644 index dcb57e9a..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -/*! \page qtservice-example-interactive.html - \title An Interactive Service - - This example implements a service with a simple user interface. - - Services are usually non-interactive console applications. User - interaction, if required, is usually implemented in a separate, - normal GUI application that communicates with the service through - an IPC channel. For simple communication, - QtServiceController::sendCommand() and QtService::processCommand() - may be used, possibly in combination with a shared settings - file. For more complex, interactive communication, a custom IPC - channel should be used, e.g. based on Qt's networking classes. - - However, although not recommended in the general case, in certain - circumstances a service may provide a GUI - itself. This is typically only possible if the service process is run as - the same user as the one that is logged in, so that it will have - access to the screen. Note however that on Windows Vista, service - GUIs are not allowed at all, since services run in a - diferent session than all user sessions, for security reasons. - - This example demonstrates how to subclass the QtService class, the use of - start(), stop(), pause(), resume(), and how to use - processCommand() to receive control commands while running. - - Here is the complete source code: - - \quotefile interactive/main.cpp -*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp deleted file mode 100644 index 4a99af57..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include "qtservice.h" - -class InteractiveService : public QtService -{ -public: - InteractiveService(int argc, char **argv); - ~InteractiveService(); - -protected: - - void start(); - void stop(); - void pause(); - void resume(); - void processCommand(int code); - -private: - QLabel *gui; -}; - -InteractiveService::InteractiveService(int argc, char **argv) - : QtService(argc, argv, "Qt Interactive Service"), gui(0) -{ - setServiceDescription("A Qt service with user interface."); - setServiceFlags(QtServiceBase::CanBeSuspended); -} - -InteractiveService::~InteractiveService() -{ -} - -void InteractiveService::start() -{ -#if defined(Q_OS_WIN) - if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) && - (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) { - logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error ); - return; - } -#endif - - qApp->setQuitOnLastWindowClosed(false); - - gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); - gui->move(QApplication::desktop()->availableGeometry().topLeft()); - gui->show(); -} - -void InteractiveService::stop() -{ - delete gui; -} - -void InteractiveService::pause() -{ - if (gui) - gui->hide(); -} - -void InteractiveService::resume() -{ - if (gui) - gui->show(); -} - -void InteractiveService::processCommand(int code) -{ - gui->setText("Command code " + QString::number(code)); - gui->adjustSize(); -} - -int main(int argc, char **argv) -{ -#if !defined(Q_WS_WIN) - // QtService stores service settings in SystemScope, which normally require root privileges. - // To allow testing this example as non-root, we change the directory of the SystemScope settings file. - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); - qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); -#endif - InteractiveService service(argc, argv); - return service.exec(); -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp deleted file mode 100644 index 43d2d501..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qtservice.h" - -// HttpDaemon is the the class that implements the simple HTTP server. -class HttpDaemon : public QTcpServer -{ - Q_OBJECT -public: - HttpDaemon(quint16 port, QObject* parent = 0) - : QTcpServer(parent), disabled(false) - { - listen(QHostAddress::Any, port); - } - - void incomingConnection(int socket) - { - if (disabled) - return; - - // When a new client connects, the server constructs a QTcpSocket and all - // communication with the client is done over this QTcpSocket. QTcpSocket - // works asynchronously, this means that all the communication is done - // in the two slots readClient() and discardClient(). - QTcpSocket* s = new QTcpSocket(this); - connect(s, SIGNAL(readyRead()), this, SLOT(readClient())); - connect(s, SIGNAL(disconnected()), this, SLOT(discardClient())); - s->setSocketDescriptor(socket); - - QtServiceBase::instance()->logMessage("New Connection"); - } - - void pause() - { - disabled = true; - } - - void resume() - { - disabled = false; - } - -private slots: - void readClient() - { - if (disabled) - return; - - // This slot is called when the client sent data to the server. The - // server looks if it was a get request and sends a very simple HTML - // document back. - QTcpSocket* socket = (QTcpSocket*)sender(); - if (socket->canReadLine()) { - QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*")); - if (tokens[0] == "GET") { - QTextStream os(socket); - os.setAutoDetectUnicode(true); - os << "HTTP/1.0 200 Ok\r\n" - "Content-Type: text/html; charset=\"utf-8\"\r\n" - "\r\n" - "

Nothing to see here

\n" - << QDateTime::currentDateTime().toString() << "\n"; - socket->close(); - - QtServiceBase::instance()->logMessage("Wrote to client"); - - if (socket->state() == QTcpSocket::UnconnectedState) { - delete socket; - QtServiceBase::instance()->logMessage("Connection closed"); - } - } - } - } - void discardClient() - { - QTcpSocket* socket = (QTcpSocket*)sender(); - socket->deleteLater(); - - QtServiceBase::instance()->logMessage("Connection closed"); - } - -private: - bool disabled; -}; - -class HttpService : public QtService -{ -public: - HttpService(int argc, char **argv) - : QtService(argc, argv, "Qt HTTP Daemon") - { - setServiceDescription("A dummy HTTP service implemented with Qt"); - setServiceFlags(QtServiceBase::CanBeSuspended); - } - -protected: - void start() - { - QCoreApplication *app = application(); - - quint16 port = (app->argc() > 1) ? - QString::fromLocal8Bit(app->argv()[1]).toUShort() : 8080; - daemon = new HttpDaemon(port, app); - - if (!daemon->isListening()) { - logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error); - app->quit(); - } - } - - void pause() - { - daemon->pause(); - } - - void resume() - { - daemon->resume(); - } - -private: - HttpDaemon *daemon; -}; - -#include "main.moc" - -int main(int argc, char **argv) -{ -#if !defined(Q_WS_WIN) - // QtService stores service settings in SystemScope, which normally require root privileges. - // To allow testing this example as non-root, we change the directory of the SystemScope settings file. - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); - qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); -#endif - HttpService service(argc, argv); - return service.exec(); -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro deleted file mode 100644 index 608b4d55..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro +++ /dev/null @@ -1,8 +0,0 @@ -TARGET = httpservice -TEMPLATE = app -CONFIG += console qt -QT = core network - -SOURCES = main.cpp - -include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc deleted file mode 100644 index 1728210f..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -/*! \page qtservice-example-server.html - \title A simple HTTP Server - - It is a very simple implementation of a HTTP daemon that listens on - chosen port (defaultly 8080) and sends back a simple HTML page back for every GET - request it gets. After sending the page, it closes the connection. - - \quotefromfile server/main.cpp - \skipto HttpDaemon - - \printuntil }; - The server implementation uses - the QtService::logMessage() function to send messages and status - reports to the system event log. The server also supports - a paused state in which case incoming requests are ignored. - - The \c HttpService class subclasses QtService to implement the - service functionality. - - \printto protected: - The constructor calls the QtService constructor instantiated with QCoreApplication - since our service will not use GUI. - The first two parameters of our constructor are passed to QtService. - The last parameter, "Qt HTTP Daemon", is the name of the service. - - \printto pause() - The implementation of \c start() first checks if the user passed a port number. - If yes that port is used by server to listen on. Otherwise default 8080 port is used. - Then creates an instance of the HTTP server using operator - new, passing the application object as the parent to ensure that the object - gets destroyed. - - \printto private: - \printuntil }; - The implementations of pause() and resume() forward the request to the - server object. - - \printuntil } - The main entry point function creates the service object and uses - the \c exec() function to execute the service. -*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro deleted file mode 100644 index 5aa57569..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE=subdirs -CONFIG += ordered -include(common.pri) -qtservice-uselib:SUBDIRS=buildlib -SUBDIRS+=examples diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase deleted file mode 100644 index 57e17a52..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase +++ /dev/null @@ -1 +0,0 @@ -#include "qtservice.h" diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController deleted file mode 100644 index 57e17a52..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController +++ /dev/null @@ -1 +0,0 @@ -#include "qtservice.h" diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp deleted file mode 100644 index e0084f1f..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp +++ /dev/null @@ -1,1117 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtservice.h" -#include "qtservice_p.h" -#include -#include -#include -#include -#include - -#if defined(QTSERVICE_DEBUG) -#include -#include -#include -#include -#if defined(Q_OS_WIN32) -#include -#else -#include -#include -#endif - -static QFile* f = 0; - -static void qtServiceCloseDebugLog() -{ - if (!f) - return; - QString ps(QTime::currentTime().toString("HH:mm:ss.zzz ") + QLatin1String("--- DEBUG LOG CLOSED ---\n\n")); - f->write(ps.toAscii()); - f->flush(); - f->close(); - delete f; - f = 0; -} - -void qtServiceLogDebug(QtMsgType type, const char* msg) -{ - static QMutex mutex; - QMutexLocker locker(&mutex); - QString s(QTime::currentTime().toString("HH:mm:ss.zzz ")); - s += QString("[%1] ").arg( -#if defined(Q_OS_WIN32) - GetCurrentProcessId()); -#else - getpid()); -#endif - - if (!f) { -#if defined(Q_OS_WIN32) - f = new QFile("c:/service-debuglog.txt"); -#else - f = new QFile("/tmp/service-debuglog.txt"); -#endif - if (!f->open(QIODevice::WriteOnly | QIODevice::Append)) { - delete f; - f = 0; - return; - } - QString ps(QLatin1String("\n") + s + QLatin1String("--- DEBUG LOG OPENED ---\n")); - f->write(ps.toAscii()); - } - - switch (type) { - case QtWarningMsg: - s += QLatin1String("WARNING: "); - break; - case QtCriticalMsg: - s += QLatin1String("CRITICAL: "); - break; - case QtFatalMsg: - s+= QLatin1String("FATAL: "); - break; - case QtDebugMsg: - s += QLatin1String("DEBUG: "); - break; - default: - // Nothing - break; - } - - s += msg; - s += QLatin1String("\n"); - - f->write(s.toAscii()); - f->flush(); - - if (type == QtFatalMsg) { - qtServiceCloseDebugLog(); - exit(1); - } -} - -#endif - -/*! - \class QtServiceController - - \brief The QtServiceController class allows you to control - services from separate applications. - - QtServiceController provides a collection of functions that lets - you install and run a service controlling its execution, as well - as query its status. - - In order to run a service, the service must be installed in the - system's service database using the install() function. The system - will start the service depending on the specified StartupType; it - can either be started during system startup, or when a process - starts it manually. - - Once a service is installed, the service can be run and controlled - manually using the start(), stop(), pause(), resume() or - sendCommand() functions. You can at any time query for the - service's status using the isInstalled() and isRunning() - functions, or you can query its properties using the - serviceDescription(), serviceFilePath(), serviceName() and - startupType() functions. For example: - - \code - MyService service; \\ which inherits QtService - QString serviceFilePath; - - QtServiceController controller(service.serviceName()); - - if (controller.install(serviceFilePath)) - controller.start() - - if (controller.isRunning()) - QMessageBox::information(this, tr("Service Status"), - tr("The %1 service is started").arg(controller.serviceName())); - - ... - - controller.stop(); - controller.uninstall(); - } - \endcode - - An instance of the service controller can only control one single - service. To control several services within one application, you - must create en equal number of service controllers. - - The QtServiceController destructor neither stops nor uninstalls - the associated service. To stop a service the stop() function must - be called explicitly. To uninstall a service, you can use the - uninstall() function. - - \sa QtServiceBase, QtService -*/ - -/*! - \enum QtServiceController::StartupType - This enum describes when a service should be started. - - \value AutoStartup The service is started during system startup. - \value ManualStartup The service must be started manually by a process. - - \warning The \a StartupType enum is ignored under UNIX-like - systems. A service, or daemon, can only be started manually on such - systems with current implementation. - - \sa startupType() -*/ - - -/*! - Creates a controller object for the service with the given - \a name. -*/ -QtServiceController::QtServiceController(const QString &name) - : d_ptr(new QtServiceControllerPrivate()) -{ - Q_D(QtServiceController); - d->q_ptr = this; - d->serviceName = name; -} -/*! - Destroys the service controller. This neither stops nor uninstalls - the controlled service. - - To stop a service the stop() function must be called - explicitly. To uninstall a service, you can use the uninstall() - function. - - \sa stop(), QtServiceController::uninstall() -*/ -QtServiceController::~QtServiceController() -{ - delete d_ptr; -} -/*! - \fn bool QtServiceController::isInstalled() const - - Returns true if the service is installed; otherwise returns false. - - On Windows it uses the system's service control manager. - - On Unix it checks configuration written to QSettings::SystemScope - using "QtSoftware" as organization name. - - \sa install() -*/ - -/*! - \fn bool QtServiceController::isRunning() const - - Returns true if the service is running; otherwise returns false. A - service must be installed before it can be run using a controller. - - \sa start(), isInstalled() -*/ - -/*! - Returns the name of the controlled service. - - \sa QtServiceController(), serviceDescription() -*/ -QString QtServiceController::serviceName() const -{ - Q_D(const QtServiceController); - return d->serviceName; -} -/*! - \fn QString QtServiceController::serviceDescription() const - - Returns the description of the controlled service. - - \sa install(), serviceName() -*/ - -/*! - \fn QtServiceController::StartupType QtServiceController::startupType() const - - Returns the startup type of the controlled service. - - \sa install(), serviceName() -*/ - -/*! - \fn QString QtServiceController::serviceFilePath() const - - Returns the file path to the controlled service. - - \sa install(), serviceName() -*/ - -/*! - Installs the service with the given \a serviceFilePath - and returns true if the service is installed - successfully; otherwise returns false. - - On Windows service is installed in the system's service control manager with the given - \a account and \a password. - - On Unix service configuration is written to QSettings::SystemScope - using "QtSoftware" as organization name. \a account and \a password - arguments are ignored. - - \warning Due to the different implementations of how services (daemons) - are installed on various UNIX-like systems, this method doesn't - integrate the service into the system's startup scripts. - - \sa uninstall(), start() -*/ -bool QtServiceController::install(const QString &serviceFilePath, const QString &account, - const QString &password) -{ - QStringList arguments; - arguments << QLatin1String("-i"); - arguments << account; - arguments << password; - return (QProcess::execute(serviceFilePath, arguments) == 0); -} - - -/*! - \fn bool QtServiceController::uninstall() - - Uninstalls the service and returns true if successful; otherwise returns false. - - On Windows service is uninstalled using the system's service control manager. - - On Unix service configuration is cleared using QSettings::SystemScope - with "QtSoftware" as organization name. - - - \sa install() -*/ - -/*! - \fn bool QtServiceController::start(const QStringList &arguments) - - Starts the installed service passing the given \a arguments to the - service. A service must be installed before a controller can run it. - - Returns true if the service could be started; otherwise returns - false. - - \sa install(), stop() -*/ - -/*! - \overload - - Starts the installed service without passing any arguments to the service. -*/ -bool QtServiceController::start() -{ - return start(QStringList()); -} - -/*! - \fn bool QtServiceController::stop() - - Requests the running service to stop. The service will call the - QtServiceBase::stop() implementation unless the service's state - is QtServiceBase::CannotBeStopped. This function does nothing if - the service is not running. - - Returns true if a running service was successfully stopped; - otherwise false. - - \sa start(), QtServiceBase::stop(), QtServiceBase::ServiceFlags -*/ - -/*! - \fn bool QtServiceController::pause() - - Requests the running service to pause. If the service's state is - QtServiceBase::CanBeSuspended, the service will call the - QtServiceBase::pause() implementation. The function does nothing - if the service is not running. - - Returns true if a running service was successfully paused; - otherwise returns false. - - \sa resume(), QtServiceBase::pause(), QtServiceBase::ServiceFlags -*/ - -/*! - \fn bool QtServiceController::resume() - - Requests the running service to continue. If the service's state - is QtServiceBase::CanBeSuspended, the service will call the - QtServiceBase::resume() implementation. This function does nothing - if the service is not running. - - Returns true if a running service was successfully resumed; - otherwise returns false. - - \sa pause(), QtServiceBase::resume(), QtServiceBase::ServiceFlags -*/ - -/*! - \fn bool QtServiceController::sendCommand(int code) - - Sends the user command \a code to the service. The service will - call the QtServiceBase::processCommand() implementation. This - function does nothing if the service is not running. - - Returns true if the request was sent to a running service; - otherwise returns false. - - \sa QtServiceBase::processCommand() -*/ - -class QtServiceStarter : public QObject -{ - Q_OBJECT -public: - QtServiceStarter(QtServiceBasePrivate *service) - : QObject(), d_ptr(service) {} -public slots: - void slotStart() - { - d_ptr->startService(); - } -private: - QtServiceBasePrivate *d_ptr; -}; -#include "qtservice.moc" - -QtServiceBase *QtServiceBasePrivate::instance = 0; - -QtServiceBasePrivate::QtServiceBasePrivate(const QString &name) - : startupType(QtServiceController::ManualStartup), serviceFlags(0), controller(name) -{ - -} - -QtServiceBasePrivate::~QtServiceBasePrivate() -{ - -} - -void QtServiceBasePrivate::startService() -{ - q_ptr->start(); -} - -int QtServiceBasePrivate::run(bool asService, const QStringList &argList) -{ - int argc = argList.size(); - QVector argv(argc); - QList argvData; - for (int i = 0; i < argc; ++i) - argvData.append(argList.at(i).toLocal8Bit()); - for (int i = 0; i < argc; ++i) - argv[i] = argvData[i].data(); - - if (asService && !sysInit()) - return -1; - - q_ptr->createApplication(argc, argv.data()); - QCoreApplication *app = QCoreApplication::instance(); - if (!app) - return -1; - - if (asService) - sysSetPath(); - - QtServiceStarter starter(this); - QTimer::singleShot(0, &starter, SLOT(slotStart())); - int res = q_ptr->executeApplication(); - delete app; - - if (asService) - sysCleanup(); - return res; -} - - -/*! - \class QtServiceBase - - \brief The QtServiceBase class provides an API for implementing - Windows services and Unix daemons. - - A Windows service or Unix daemon (a "service"), is a program that - runs "in the background" independently of whether a user is logged - in or not. A service is often set up to start when the machine - boots up, and will typically run continuously as long as the - machine is on. - - Services are usually non-interactive console applications. User - interaction, if required, is usually implemented in a separate, - normal GUI application that communicates with the service through - an IPC channel. For simple communication, - QtServiceController::sendCommand() and QtService::processCommand() - may be used, possibly in combination with a shared settings - file. For more complex, interactive communication, a custom IPC - channel should be used, e.g. based on Qt's networking classes. (In - certain circumstances, a service may provide a GUI itself, - ref. the "interactive" example documentation). - - Typically, you will create a service by subclassing the QtService - template class which inherits QtServiceBase and allows you to - create a service for a particular application type. - - The Windows implementation uses the NT Service Control Manager, - and the application can be controlled through the system - administration tools. Services are usually launched using the - system account, which requires that all DLLs that the service - executable depends on (i.e. Qt), are located in the same directory - as the service, or in a system path. - - On Unix a service is implemented as a daemon. - - You can retrieve the service's description, state, and startup - type using the serviceDescription(), serviceFlags() and - startupType() functions respectively. The service's state is - decribed by the ServiceFlag enum. The mentioned properites can - also be set using the corresponding set functions. In addition you - can retrieve the service's name using the serviceName() function. - - Several of QtServiceBase's protected functions are called on - requests from the QtServiceController class: - - \list - \o start() - \o pause() - \o processCommand() - \o resume() - \o stop() - \endlist - - You can control any given service using an instance of the - QtServiceController class which also allows you to control - services from separate applications. The mentioned functions are - all virtual and won't do anything unless they are - reimplemented. You can reimplement these functions to pause and - resume the service's execution, as well as process user commands - and perform additional clean-ups before shutting down. - - QtServiceBase also provides the static instance() function which - returns a pointer to an application's QtServiceBase instance. In - addition, a service can report events to the system's event log - using the logMessage() function. The MessageType enum describes - the different types of messages a service reports. - - The implementation of a service application's main function - typically creates an service object derived by subclassing the - QtService template class. Then the main function will call this - service's exec() function, and return the result of that call. For - example: - - \code - int main(int argc, char **argv) - { - MyService service(argc, argv); - return service.exec(); - } - \endcode - - When the exec() function is called, it will parse the service - specific arguments passed in \c argv, perform the required - actions, and return. - - \target serviceSpecificArguments - - The following arguments are recognized as service specific: - - \table - \header \i Short \i Long \i Explanation - \row \i -i \i -install \i Install the service. - \row \i -u \i -uninstall \i Uninstall the service. - \row \i -e \i -exec - \i Execute the service as a standalone application (useful for debug purposes). - This is a blocking call, the service will be executed like a normal application. - In this mode you will not be able to communicate with the service from the contoller. - \row \i -t \i -terminate \i Stop the service. - \row \i -p \i -pause \i Pause the service. - \row \i -r \i -resume \i Resume a paused service. - \row \i -c \e{cmd} \i -command \e{cmd} - \i Send the user defined command code \e{cmd} to the service application. - \row \i -v \i -version \i Display version and status information. - \endtable - - If \e none of the arguments is recognized as service specific, - exec() will first call the createApplication() function, then - executeApplication() and finally the start() function. In the end, - exec() returns while the service continues in its own process - waiting for commands from the service controller. - - \sa QtService, QtServiceController -*/ - -/*! - \enum QtServiceBase::MessageType - - This enum describes the different types of messages a service - reports to the system log. - - \value Success An operation has succeeded, e.g. the service - is started. - \value Error An operation failed, e.g. the service failed to start. - \value Warning An operation caused a warning that might require user - interaction. - \value Information Any type of usually non-critical information. -*/ - -/*! - \enum QtServiceBase::ServiceFlag - - This enum describes the different states of a service. - - \value Default The service can be stopped, but not suspended. - \value CanBeSuspended The service can be suspended. - \value CannotBeStopped The service cannot be stopped. -*/ - -/*! - Creates a service instance called \a name. The \a argc and \a argv - parameters are parsed after the exec() function has been - called. Then they are passed to the application's constructor. - The application type is determined by the QtService subclass. - - The service is neither installed nor started. The name must not - contain any backslashes or be longer than 255 characters. In - addition, the name must be unique in the system's service - database. - - \sa exec(), start(), QtServiceController::install() -*/ -QtServiceBase::QtServiceBase(int argc, char **argv, const QString &name) -{ -#if defined(QTSERVICE_DEBUG) - qInstallMsgHandler(qtServiceLogDebug); - qAddPostRoutine(qtServiceCloseDebugLog); -#endif - - Q_ASSERT(!QtServiceBasePrivate::instance); - QtServiceBasePrivate::instance = this; - - QString nm(name); - if (nm.length() > 255) { - qWarning("QtService: 'name' is longer than 255 characters."); - nm.truncate(255); - } - if (nm.contains('\\')) { - qWarning("QtService: 'name' contains backslashes '\\'."); - nm.replace((QChar)'\\', (QChar)'\0'); - } - - d_ptr = new QtServiceBasePrivate(nm); - d_ptr->q_ptr = this; - - d_ptr->serviceFlags = 0; - d_ptr->sysd = 0; - for (int i = 0; i < argc; ++i) - d_ptr->args.append(QString::fromLocal8Bit(argv[i])); -} - -/*! - Destroys the service object. This neither stops nor uninstalls the - service. - - To stop a service the stop() function must be called - explicitly. To uninstall a service, you can use the - QtServiceController::uninstall() function. - - \sa stop(), QtServiceController::uninstall() -*/ -QtServiceBase::~QtServiceBase() -{ - delete d_ptr; - QtServiceBasePrivate::instance = 0; -} - -/*! - Returns the name of the service. - - \sa QtServiceBase(), serviceDescription() -*/ -QString QtServiceBase::serviceName() const -{ - return d_ptr->controller.serviceName(); -} - -/*! - Returns the description of the service. - - \sa setServiceDescription(), serviceName() -*/ -QString QtServiceBase::serviceDescription() const -{ - return d_ptr->serviceDescription; -} - -/*! - Sets the description of the service to the given \a description. - - \sa serviceDescription() -*/ -void QtServiceBase::setServiceDescription(const QString &description) -{ - d_ptr->serviceDescription = description; -} - -/*! - Returns the service's startup type. - - \sa QtServiceController::StartupType, setStartupType() -*/ -QtServiceController::StartupType QtServiceBase::startupType() const -{ - return d_ptr->startupType; -} - -/*! - Sets the service's startup type to the given \a type. - - \sa QtServiceController::StartupType, startupType() -*/ -void QtServiceBase::setStartupType(QtServiceController::StartupType type) -{ - d_ptr->startupType = type; -} - -/*! - Returns the service's state which is decribed using the - ServiceFlag enum. - - \sa ServiceFlags, setServiceFlags() -*/ -QtServiceBase::ServiceFlags QtServiceBase::serviceFlags() const -{ - return d_ptr->serviceFlags; -} - -/*! - \fn void QtServiceBase::setServiceFlags(ServiceFlags flags) - - Sets the service's state to the state described by the given \a - flags. - - \sa ServiceFlags, serviceFlags() -*/ - -/*! - Executes the service. - - When the exec() function is called, it will parse the \l - {serviceSpecificArguments} {service specific arguments} passed in - \c argv, perform the required actions, and exit. - - If none of the arguments is recognized as service specific, exec() - will first call the createApplication() function, then executeApplication() and - finally the start() function. In the end, exec() - returns while the service continues in its own process waiting for - commands from the service controller. - - \sa QtServiceController -*/ -int QtServiceBase::exec() -{ - if (d_ptr->args.size() > 1) { - QString a = d_ptr->args.at(1); - if (a == QLatin1String("-i") || a == QLatin1String("-install")) { - if (!d_ptr->controller.isInstalled()) { - QString account; - QString password; - if (d_ptr->args.size() > 2) - account = d_ptr->args.at(2); - if (d_ptr->args.size() > 3) - password = d_ptr->args.at(3); - if (!d_ptr->install(account, password)) { - fprintf(stderr, "The service %s could not be installed\n", serviceName().toLatin1().constData()); - return -1; - } else { - printf("The service %s has been installed under: %s\n", - serviceName().toLatin1().constData(), d_ptr->filePath().toLatin1().constData()); - } - } else { - fprintf(stderr, "The service %s is already installed\n", serviceName().toLatin1().constData()); - } - return 0; - } else if (a == QLatin1String("-u") || a == QLatin1String("-uninstall")) { - if (d_ptr->controller.isInstalled()) { - if (!d_ptr->controller.uninstall()) { - fprintf(stderr, "The service %s could not be uninstalled\n", serviceName().toLatin1().constData()); - return -1; - } else { - printf("The service %s has been uninstalled.\n", - serviceName().toLatin1().constData()); - } - } else { - fprintf(stderr, "The service %s is not installed\n", serviceName().toLatin1().constData()); - } - return 0; - } else if (a == QLatin1String("-v") || a == QLatin1String("-version")) { - printf("The service\n" - "\t%s\n\t%s\n\n", serviceName().toLatin1().constData(), d_ptr->args.at(0).toLatin1().constData()); - printf("is %s", (d_ptr->controller.isInstalled() ? "installed" : "not installed")); - printf(" and %s\n\n", (d_ptr->controller.isRunning() ? "running" : "not running")); - return 0; - } else if (a == QLatin1String("-e") || a == QLatin1String("-exec")) { - d_ptr->args.removeAt(1); - int ec = d_ptr->run(false, d_ptr->args); - if (ec == -1) - qErrnoWarning("The service could not be executed."); - return ec; - } else if (a == QLatin1String("-t") || a == QLatin1String("-terminate")) { - if (!d_ptr->controller.stop()) - qErrnoWarning("The service could not be stopped."); - return 0; - } else if (a == QLatin1String("-p") || a == QLatin1String("-pause")) { - d_ptr->controller.pause(); - return 0; - } else if (a == QLatin1String("-r") || a == QLatin1String("-resume")) { - d_ptr->controller.resume(); - return 0; - } else if (a == QLatin1String("-c") || a == QLatin1String("-command")) { - int code = 0; - if (d_ptr->args.size() > 2) - code = d_ptr->args.at(2).toInt(); - d_ptr->controller.sendCommand(code); - return 0; - } else if (a == QLatin1String("-h") || a == QLatin1String("-help")) { - printf("\n%s -[i|u|e|s|v|h]\n" - "\t-i(nstall) [account] [password]\t: Install the service, optionally using given account and password\n" - "\t-u(ninstall)\t: Uninstall the service.\n" - "\t-e(xec)\t\t: Run as a regular application. Useful for debugging.\n" - "\t-t(erminate)\t: Stop the service.\n" - "\t-c(ommand) num\t: Send command code num to the service.\n" - "\t-v(ersion)\t: Print version and status information.\n" - "\t-h(elp) \t: Show this help\n" - "\tNo arguments\t: Start the service.\n", - d_ptr->args.at(0).toLatin1().constData()); - return 0; - } - } -#if defined(Q_OS_UNIX) - if (::getenv("QTSERVICE_RUN")) { - // Means we're the detached, real service process. - int ec = d_ptr->run(true, d_ptr->args); - if (ec == -1) - qErrnoWarning("The service failed to run."); - return ec; - } -#endif - if (!d_ptr->start()) { - fprintf(stderr, "The service %s could not start\n", serviceName().toLatin1().constData()); - return -4; - } - return 0; -} - -/*! - \fn void QtServiceBase::logMessage(const QString &message, MessageType type, - int id, uint category, const QByteArray &data) - - Reports a message of the given \a type with the given \a message - to the local system event log. The message identifier \a id and - the message \a category are user defined values. The \a data - parameter can contain arbitrary binary data. - - Message strings for \a id and \a category must be provided by a - message file, which must be registered in the system registry. - Refer to the MSDN for more information about how to do this on - Windows. - - \sa MessageType -*/ - -/*! - Returns a pointer to the current application's QtServiceBase - instance. -*/ -QtServiceBase *QtServiceBase::instance() -{ - return QtServiceBasePrivate::instance; -} - -/*! - \fn void QtServiceBase::start() - - This function must be implemented in QtServiceBase subclasses in - order to perform the service's work. Usually you create some main - object on the heap which is the heart of your service. - - The function is only called when no service specific arguments - were passed to the service constructor, and is called by exec() - after it has called the executeApplication() function. - - Note that you \e don't need to create an application object or - call its exec() function explicitly. - - \sa exec(), stop(), QtServiceController::start() -*/ - -/*! - Reimplement this function to perform additional cleanups before - shutting down (for example deleting a main object if it was - created in the start() function). - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa start(), QtServiceController::stop() -*/ -void QtServiceBase::stop() -{ -} - -/*! - Reimplement this function to pause the service's execution (for - example to stop a polling timer, or to ignore socket notifiers). - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa resume(), QtServiceController::pause() -*/ -void QtServiceBase::pause() -{ -} - -/*! - Reimplement this function to continue the service after a call to - pause(). - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa pause(), QtServiceController::resume() -*/ -void QtServiceBase::resume() -{ -} - -/*! - Reimplement this function to process the user command \a code. - - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa QtServiceController::sendCommand() -*/ -void QtServiceBase::processCommand(int /*code*/) -{ -} - -/*! - \fn void QtServiceBase::createApplication(int &argc, char **argv) - - Creates the application object using the \a argc and \a argv - parameters. - - This function is only called when no \l - {serviceSpecificArguments}{service specific arguments} were - passed to the service constructor, and is called by exec() before - it calls the executeApplication() and start() functions. - - The createApplication() function is implemented in QtService, but - you might want to reimplement it, for example, if the chosen - application type's constructor needs additional arguments. - - \sa exec(), QtService -*/ - -/*! - \fn int QtServiceBase::executeApplication() - - Executes the application previously created with the - createApplication() function. - - This function is only called when no \l - {serviceSpecificArguments}{service specific arguments} were - passed to the service constructor, and is called by exec() after - it has called the createApplication() function and before start() function. - - This function is implemented in QtService. - - \sa exec(), createApplication() -*/ - -/*! - \class QtService - - \brief The QtService is a convenient template class that allows - you to create a service for a particular application type. - - A Windows service or Unix daemon (a "service"), is a program that - runs "in the background" independently of whether a user is logged - in or not. A service is often set up to start when the machine - boots up, and will typically run continuously as long as the - machine is on. - - Services are usually non-interactive console applications. User - interaction, if required, is usually implemented in a separate, - normal GUI application that communicates with the service through - an IPC channel. For simple communication, - QtServiceController::sendCommand() and QtService::processCommand() - may be used, possibly in combination with a shared settings file. For - more complex, interactive communication, a custom IPC channel - should be used, e.g. based on Qt's networking classes. (In certain - circumstances, a service may provide a GUI itself, ref. the - "interactive" example documentation). - - \bold{Note:} On Unix systems, this class relies on facilities - provided by the QtNetwork module, provided as part of the - \l{Qt Open Source Edition} and certain \l{Qt Commercial Editions}. - - The QtService class functionality is inherited from QtServiceBase, - but in addition the QtService class binds an instance of - QtServiceBase with an application type. - - Typically, you will create a service by subclassing the QtService - template class. For example: - - \code - class MyService : public QtService - { - public: - MyService(int argc, char **argv); - ~MyService(); - - protected: - void start(); - void stop(); - void pause(); - void resume(); - void processCommand(int code); - }; - \endcode - - The application type can be QCoreApplication for services without - GUI, QApplication for services with GUI or you can use your own - custom application type. - - You must reimplement the QtServiceBase::start() function to - perform the service's work. Usually you create some main object on - the heap which is the heart of your service. - - In addition, you might want to reimplement the - QtServiceBase::pause(), QtServiceBase::processCommand(), - QtServiceBase::resume() and QtServiceBase::stop() to intervene the - service's process on controller requests. You can control any - given service using an instance of the QtServiceController class - which also allows you to control services from separate - applications. The mentioned functions are all virtual and won't do - anything unless they are reimplemented. - - Your custom service is typically instantiated in the application's - main function. Then the main function will call your service's - exec() function, and return the result of that call. For example: - - \code - int main(int argc, char **argv) - { - MyService service(argc, argv); - return service.exec(); - } - \endcode - - When the exec() function is called, it will parse the \l - {serviceSpecificArguments} {service specific arguments} passed in - \c argv, perform the required actions, and exit. - - If none of the arguments is recognized as service specific, exec() - will first call the createApplication() function, then executeApplication() and - finally the start() function. In the end, exec() - returns while the service continues in its own process waiting for - commands from the service controller. - - \sa QtServiceBase, QtServiceController -*/ - -/*! - \fn QtService::QtService(int argc, char **argv, const QString &name) - - Constructs a QtService object called \a name. The \a argc and \a - argv parameters are parsed after the exec() function has been - called. Then they are passed to the application's constructor. - - There can only be one QtService object in a process. - - \sa QtServiceBase() -*/ - -/*! - \fn QtService::~QtService() - - Destroys the service object. -*/ - -/*! - \fn Application *QtService::application() const - - Returns a pointer to the application object. -*/ - -/*! - \fn void QtService::createApplication(int &argc, char **argv) - - Creates application object of type Application passing \a argc and - \a argv to its constructor. - - \reimp - -*/ - -/*! - \fn int QtService::executeApplication() - - \reimp -*/ - - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h deleted file mode 100644 index a0230e28..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTSERVICE_H -#define QTSERVICE_H - -#include - -#if defined(Q_WS_WIN) -# if !defined(QT_QTSERVICE_EXPORT) && !defined(QT_QTSERVICE_IMPORT) -# define QT_QTSERVICE_EXPORT -# elif defined(QT_QTSERVICE_IMPORT) -# if defined(QT_QTSERVICE_EXPORT) -# undef QT_QTSERVICE_EXPORT -# endif -# define QT_QTSERVICE_EXPORT __declspec(dllimport) -# elif defined(QT_QTSERVICE_EXPORT) -# undef QT_QTSERVICE_EXPORT -# define QT_QTSERVICE_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTSERVICE_EXPORT -#endif - -class QStringList; -class QtServiceControllerPrivate; - -class QT_QTSERVICE_EXPORT QtServiceController -{ - Q_DECLARE_PRIVATE(QtServiceController) -public: - enum StartupType - { - AutoStartup = 0, ManualStartup - }; - - QtServiceController(const QString &name); - virtual ~QtServiceController(); - - bool isInstalled() const; - bool isRunning() const; - - QString serviceName() const; - QString serviceDescription() const; - StartupType startupType() const; - QString serviceFilePath() const; - - static bool install(const QString &serviceFilePath, const QString &account = QString(), - const QString &password = QString()); - bool uninstall(); - - bool start(const QStringList &arguments); - bool start(); - bool stop(); - bool pause(); - bool resume(); - bool sendCommand(int code); - -private: - QtServiceControllerPrivate *d_ptr; -}; - -class QtServiceBasePrivate; - -class QT_QTSERVICE_EXPORT QtServiceBase -{ - Q_DECLARE_PRIVATE(QtServiceBase) -public: - - enum MessageType - { - Success = 0, Error, Warning, Information - }; - - enum ServiceFlag - { - Default = 0x00, - CanBeSuspended = 0x01, - CannotBeStopped = 0x02 - }; - - Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag) - - QtServiceBase(int argc, char **argv, const QString &name); - virtual ~QtServiceBase(); - - QString serviceName() const; - - QString serviceDescription() const; - void setServiceDescription(const QString &description); - - QtServiceController::StartupType startupType() const; - void setStartupType(QtServiceController::StartupType startupType); - - ServiceFlags serviceFlags() const; - void setServiceFlags(ServiceFlags flags); - - int exec(); - - void logMessage(const QString &message, MessageType type = Success, - int id = 0, uint category = 0, const QByteArray &data = QByteArray()); - - static QtServiceBase *instance(); - -protected: - - virtual void start() = 0; - virtual void stop(); - virtual void pause(); - virtual void resume(); - virtual void processCommand(int code); - - virtual void createApplication(int &argc, char **argv) = 0; - - virtual int executeApplication() = 0; - -private: - - friend class QtServiceSysPrivate; - QtServiceBasePrivate *d_ptr; -}; - -template -class QtService : public QtServiceBase -{ -public: - QtService(int argc, char **argv, const QString &name) - : QtServiceBase(argc, argv, name), app(0) - { } - ~QtService() - { - } - -protected: - Application *application() const - { return app; } - - virtual void createApplication(int &argc, char **argv) - { - app = new Application(argc, argv); - QCoreApplication *a = app; - Q_UNUSED(a); - } - - virtual int executeApplication() - { return Application::exec(); } - -private: - Application *app; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QtServiceBase::ServiceFlags) - -#endif // QTSERVICE_H diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri deleted file mode 100644 index 658a3288..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri +++ /dev/null @@ -1,21 +0,0 @@ -include(../common.pri) -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD -!win32:QT += network -win32:LIBS += -luser32 - -qtservice-uselib:!qtservice-buildlib { - LIBS += -L$$QTSERVICE_LIBDIR -l$$QTSERVICE_LIBNAME -} else { - HEADERS += $$PWD/qtservice.h \ - $$PWD/qtservice_p.h - SOURCES += $$PWD/qtservice.cpp - win32:SOURCES += $$PWD/qtservice_win.cpp - unix:HEADERS += $$PWD/qtunixsocket.h $$PWD/qtunixserversocket.h - unix:SOURCES += $$PWD/qtservice_unix.cpp $$PWD/qtunixsocket.cpp $$PWD/qtunixserversocket.cpp -} - -win32 { - contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSERVICE_EXPORT - else:qtservice-uselib:DEFINES += QT_QTSERVICE_IMPORT -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h deleted file mode 100644 index fc5e6b82..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTSERVICE_P_H -#define QTSERVICE_P_H - -#include -#include "qtservice.h" - -class QtServiceControllerPrivate -{ - Q_DECLARE_PUBLIC(QtServiceController) -public: - QString serviceName; - QtServiceController *q_ptr; -}; - -class QtServiceBasePrivate -{ - Q_DECLARE_PUBLIC(QtServiceBase) -public: - - QtServiceBasePrivate(const QString &name); - ~QtServiceBasePrivate(); - - QtServiceBase *q_ptr; - - QString serviceDescription; - QtServiceController::StartupType startupType; - QtServiceBase::ServiceFlags serviceFlags; - QStringList args; - - static class QtServiceBase *instance; - - QtServiceController controller; - - void startService(); - int run(bool asService, const QStringList &argList); - bool install(const QString &account, const QString &password); - - bool start(); - - QString filePath() const; - bool sysInit(); - void sysSetPath(); - void sysCleanup(); - class QtServiceSysPrivate *sysd; -}; - -#endif diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp deleted file mode 100644 index 7e4ec700..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtservice.h" -#include "qtservice_p.h" -#include "qtunixsocket.h" -#include "qtunixserversocket.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static QString encodeName(const QString &name, bool allowUpper = false) -{ - QString n = name.toLower(); - QString legal = QLatin1String("abcdefghijklmnopqrstuvwxyz1234567890"); - if (allowUpper) - legal += QLatin1String("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - int pos = 0; - while (pos < n.size()) { - if (legal.indexOf(n[pos]) == -1) - n.remove(pos, 1); - else - ++pos; - } - return n; -} - -static QString login() -{ - QString l; - uid_t uid = getuid(); - passwd *pw = getpwuid(uid); - if (pw) - l = QString(pw->pw_name); - return l; -} - -static QString socketPath(const QString &serviceName) -{ - QString sn = encodeName(serviceName); - return QString(QLatin1String("/var/tmp/") + sn + QLatin1String(".") + login()); -} - -static bool sendCmd(const QString &serviceName, const QString &cmd) -{ - bool retValue = false; - QtUnixSocket sock; - if (sock.connectTo(socketPath(serviceName))) { - sock.write(QString(cmd+"\r\n").toLatin1().constData()); - sock.flush(); - sock.waitForReadyRead(-1); - QString reply = sock.readAll(); - if (reply == QLatin1String("true")) - retValue = true; - sock.close(); - } - return retValue; -} - -static QString absPath(const QString &path) -{ - QString ret; - if (path[0] != QChar('/')) { // Not an absolute path - int slashpos; - if ((slashpos = path.lastIndexOf('/')) != -1) { // Relative path - QDir dir = QDir::current(); - dir.cd(path.left(slashpos)); - ret = dir.absolutePath(); - } else { // Need to search $PATH - char *envPath = ::getenv("PATH"); - if (envPath) { - QStringList envPaths = QString::fromLocal8Bit(envPath).split(':'); - for (int i = 0; i < envPaths.size(); ++i) { - if (QFile::exists(envPaths.at(i) + QLatin1String("/") + QString(path))) { - QDir dir(envPaths.at(i)); - ret = dir.absolutePath(); - break; - } - } - } - } - } else { - QFileInfo fi(path); - ret = fi.absolutePath(); - } - return ret; -} - -QString QtServiceBasePrivate::filePath() const -{ - QString ret; - if (args.isEmpty()) - return ret; - QFileInfo fi(args[0]); - QDir dir(absPath(args[0])); - return dir.absoluteFilePath(fi.fileName()); -} - - -QString QtServiceController::serviceDescription() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - settings.beginGroup(serviceName()); - - QString desc = settings.value("description").toString(); - - settings.endGroup(); - settings.endGroup(); - - return desc; -} - -QtServiceController::StartupType QtServiceController::startupType() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - settings.beginGroup(serviceName()); - - StartupType startupType = (StartupType)settings.value("startupType").toInt(); - - settings.endGroup(); - settings.endGroup(); - - return startupType; -} - -QString QtServiceController::serviceFilePath() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - settings.beginGroup(serviceName()); - - QString path = settings.value("path").toString(); - - settings.endGroup(); - settings.endGroup(); - - return path; -} - -bool QtServiceController::uninstall() -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - - settings.remove(serviceName()); - - settings.endGroup(); - settings.sync(); - - QSettings::Status ret = settings.status(); - if (ret == QSettings::AccessError) { - fprintf(stderr, "Cannot uninstall \"%s\". Cannot write to: %s. Check permissions.\n", - serviceName().toLatin1().constData(), - settings.fileName().toLatin1().constData()); - } - return (ret == QSettings::NoError); -} - - -bool QtServiceController::start(const QStringList &arguments) -{ - if (!isInstalled()) - return false; - if (isRunning()) - return false; - return QProcess::startDetached(serviceFilePath(), arguments); -} - -bool QtServiceController::stop() -{ - return sendCmd(serviceName(), QLatin1String("terminate")); -} - -bool QtServiceController::pause() -{ - return sendCmd(serviceName(), QLatin1String("pause")); -} - -bool QtServiceController::resume() -{ - return sendCmd(serviceName(), QLatin1String("resume")); -} - -bool QtServiceController::sendCommand(int code) -{ - return sendCmd(serviceName(), QString(QLatin1String("num:") + QString::number(code))); -} - -bool QtServiceController::isInstalled() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - - QStringList list = settings.childGroups(); - - settings.endGroup(); - - QStringListIterator it(list); - while (it.hasNext()) { - if (it.next() == serviceName()) - return true; - } - - return false; -} - -bool QtServiceController::isRunning() const -{ - QtUnixSocket sock; - if (sock.connectTo(socketPath(serviceName()))) - return true; - return false; -} - - - - -/////////////////////////////////// - -class QtServiceSysPrivate : public QtUnixServerSocket -{ - Q_OBJECT -public: - QtServiceSysPrivate(); - ~QtServiceSysPrivate(); - - char *ident; - - QtServiceBase::ServiceFlags serviceFlags; - -protected: - void incomingConnection(int socketDescriptor); - -private slots: - void slotReady(); - void slotClosed(); - -private: - QString getCommand(const QTcpSocket *socket); - QMap cache; -}; - -QtServiceSysPrivate::QtServiceSysPrivate() - : QtUnixServerSocket(), ident(0), serviceFlags(0) -{ -} - -QtServiceSysPrivate::~QtServiceSysPrivate() -{ - if (ident) - delete[] ident; -} - -void QtServiceSysPrivate::incomingConnection(int socketDescriptor) -{ - QTcpSocket *s = new QTcpSocket(this); - s->setSocketDescriptor(socketDescriptor); - connect(s, SIGNAL(readyRead()), this, SLOT(slotReady())); - connect(s, SIGNAL(disconnected()), this, SLOT(slotClosed())); -} - -void QtServiceSysPrivate::slotReady() -{ - QTcpSocket *s = (QTcpSocket *)sender(); - cache[s] += QString(s->readAll()); - QString cmd = getCommand(s); - while (!cmd.isEmpty()) { - bool retValue = false; - if (cmd == QLatin1String("terminate")) { - if (!(serviceFlags & QtServiceBase::CannotBeStopped)) { - QtServiceBase::instance()->stop(); - QCoreApplication::instance()->quit(); - retValue = true; - } - } else if (cmd == QLatin1String("pause")) { - if (serviceFlags & QtServiceBase::CanBeSuspended) { - QtServiceBase::instance()->pause(); - retValue = true; - } - } else if (cmd == QLatin1String("resume")) { - if (serviceFlags & QtServiceBase::CanBeSuspended) { - QtServiceBase::instance()->resume(); - retValue = true; - } - } else if (cmd == QLatin1String("alive")) { - retValue = true; - } else if (cmd.length() > 4 && cmd.left(4) == QLatin1String("num:")) { - cmd = cmd.mid(4); - QtServiceBase::instance()->processCommand(cmd.toInt()); - retValue = true; - } - QString retString; - if (retValue) - retString = QLatin1String("true"); - else - retString = QLatin1String("false"); - s->write(retString.toLatin1().constData()); - s->flush(); - cmd = getCommand(s); - } -} - -void QtServiceSysPrivate::slotClosed() -{ - QTcpSocket *s = (QTcpSocket *)sender(); - s->deleteLater(); -} - -QString QtServiceSysPrivate::getCommand(const QTcpSocket *socket) -{ - int pos = cache[socket].indexOf("\r\n"); - if (pos >= 0) { - QString ret = cache[socket].left(pos); - cache[socket].remove(0, pos+2); - return ret; - } - return ""; -} - -#include "qtservice_unix.moc" - -bool QtServiceBasePrivate::sysInit() -{ - sysd = new QtServiceSysPrivate; - sysd->serviceFlags = serviceFlags; - // Restrict permissions on files that are created by the service - ::umask(027); - - return true; -} - -void QtServiceBasePrivate::sysSetPath() -{ - if (sysd) - sysd->setPath(socketPath(controller.serviceName())); -} - -void QtServiceBasePrivate::sysCleanup() -{ - if (sysd) { - sysd->close(); - delete sysd; - sysd = 0; - } -} - -bool QtServiceBasePrivate::start() -{ - if (sendCmd(controller.serviceName(), "alive")) { - // Already running - return false; - } - // Could just call controller.start() here, but that would fail if - // we're not installed. We do not want to strictly require installation. - ::setenv("QTSERVICE_RUN", "1", 1); // Tell the detached process it's it - return QProcess::startDetached(filePath(), args.mid(1), "/"); -} - -bool QtServiceBasePrivate::install(const QString &account, const QString &password) -{ - Q_UNUSED(account) - Q_UNUSED(password) - QSettings settings(QSettings::SystemScope, "QtSoftware"); - - settings.beginGroup("services"); - settings.beginGroup(controller.serviceName()); - - settings.setValue("path", filePath()); - settings.setValue("description", serviceDescription); - settings.setValue("automaticStartup", startupType); - - settings.endGroup(); - settings.endGroup(); - settings.sync(); - - QSettings::Status ret = settings.status(); - if (ret == QSettings::AccessError) { - fprintf(stderr, "Cannot install \"%s\". Cannot write to: %s. Check permissions.\n", - controller.serviceName().toLatin1().constData(), - settings.fileName().toLatin1().constData()); - } - return (ret == QSettings::NoError); -} - -void QtServiceBase::logMessage(const QString &message, QtServiceBase::MessageType type, - int, uint, const QByteArray &) -{ - if (!d_ptr->sysd) - return; - int st; - switch(type) { - case QtServiceBase::Error: - st = LOG_ERR; - break; - case QtServiceBase::Warning: - st = LOG_WARNING; - break; - default: - st = LOG_INFO; - } - if (!d_ptr->sysd->ident) { - QString tmp = encodeName(serviceName(), TRUE); - int len = tmp.toLocal8Bit().size(); - d_ptr->sysd->ident = new char[len+1]; - d_ptr->sysd->ident[len] = '\0'; - ::memcpy(d_ptr->sysd->ident, tmp.toLocal8Bit().constData(), len); - } - openlog(d_ptr->sysd->ident, LOG_PID, LOG_DAEMON); - foreach(QString line, message.split('\n')) - syslog(st, "%s", line.toLocal8Bit().constData()); - closelog(); -} - -void QtServiceBase::setServiceFlags(QtServiceBase::ServiceFlags flags) -{ - if (d_ptr->serviceFlags == flags) - return; - d_ptr->serviceFlags = flags; - if (d_ptr->sysd) - d_ptr->sysd->serviceFlags = flags; -} - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp deleted file mode 100644 index 7a737af1..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp +++ /dev/null @@ -1,903 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtservice.h" -#include "qtservice_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(QTSERVICE_DEBUG) -#include -#endif - -typedef SERVICE_STATUS_HANDLE(WINAPI*PRegisterServiceCtrlHandler)(const wchar_t*,LPHANDLER_FUNCTION); -static PRegisterServiceCtrlHandler pRegisterServiceCtrlHandler = 0; -typedef BOOL(WINAPI*PSetServiceStatus)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS); -static PSetServiceStatus pSetServiceStatus = 0; -typedef BOOL(WINAPI*PChangeServiceConfig2)(SC_HANDLE,DWORD,LPVOID); -static PChangeServiceConfig2 pChangeServiceConfig2 = 0; -typedef BOOL(WINAPI*PCloseServiceHandle)(SC_HANDLE); -static PCloseServiceHandle pCloseServiceHandle = 0; -typedef SC_HANDLE(WINAPI*PCreateService)(SC_HANDLE,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPCTSTR,LPDWORD,LPCTSTR,LPCTSTR,LPCTSTR); -static PCreateService pCreateService = 0; -typedef SC_HANDLE(WINAPI*POpenSCManager)(LPCTSTR,LPCTSTR,DWORD); -static POpenSCManager pOpenSCManager = 0; -typedef BOOL(WINAPI*PDeleteService)(SC_HANDLE); -static PDeleteService pDeleteService = 0; -typedef SC_HANDLE(WINAPI*POpenService)(SC_HANDLE,LPCTSTR,DWORD); -static POpenService pOpenService = 0; -typedef BOOL(WINAPI*PQueryServiceStatus)(SC_HANDLE,LPSERVICE_STATUS); -static PQueryServiceStatus pQueryServiceStatus = 0; -typedef BOOL(WINAPI*PStartServiceCtrlDispatcher)(CONST SERVICE_TABLE_ENTRY*); -static PStartServiceCtrlDispatcher pStartServiceCtrlDispatcher = 0; -typedef BOOL(WINAPI*PStartService)(SC_HANDLE,DWORD,const wchar_t**); -static PStartService pStartService = 0; -typedef BOOL(WINAPI*PControlService)(SC_HANDLE,DWORD,LPSERVICE_STATUS); -static PControlService pControlService = 0; -typedef HANDLE(WINAPI*PDeregisterEventSource)(HANDLE); -static PDeregisterEventSource pDeregisterEventSource = 0; -typedef BOOL(WINAPI*PReportEvent)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCTSTR*,LPVOID); -static PReportEvent pReportEvent = 0; -typedef HANDLE(WINAPI*PRegisterEventSource)(LPCTSTR,LPCTSTR); -static PRegisterEventSource pRegisterEventSource = 0; -typedef DWORD(WINAPI*PRegisterServiceProcess)(DWORD,DWORD); -static PRegisterServiceProcess pRegisterServiceProcess = 0; -typedef BOOL(WINAPI*PQueryServiceConfig)(SC_HANDLE,LPQUERY_SERVICE_CONFIG,DWORD,LPDWORD); -static PQueryServiceConfig pQueryServiceConfig = 0; -typedef BOOL(WINAPI*PQueryServiceConfig2)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD); -static PQueryServiceConfig2 pQueryServiceConfig2 = 0; - - -#define RESOLVE(name) p##name = (P##name)lib.resolve(#name); -#define RESOLVEA(name) p##name = (P##name)lib.resolve(#name"A"); -#define RESOLVEW(name) p##name = (P##name)lib.resolve(#name"W"); - -static bool winServiceInit() -{ - if (!pOpenSCManager) { - QLibrary lib("advapi32"); - - // only resolve unicode versions - RESOLVEW(RegisterServiceCtrlHandler); - RESOLVE(SetServiceStatus); - RESOLVEW(ChangeServiceConfig2); - RESOLVE(CloseServiceHandle); - RESOLVEW(CreateService); - RESOLVEW(OpenSCManager); - RESOLVE(DeleteService); - RESOLVEW(OpenService); - RESOLVE(QueryServiceStatus); - RESOLVEW(StartServiceCtrlDispatcher); - RESOLVEW(StartService); // need only Ansi version - RESOLVE(ControlService); - RESOLVE(DeregisterEventSource); - RESOLVEW(ReportEvent); - RESOLVEW(RegisterEventSource); - RESOLVEW(QueryServiceConfig); - RESOLVEW(QueryServiceConfig2); - } - return pOpenSCManager != 0; -} - -bool QtServiceController::isInstalled() const -{ - Q_D(const QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t*)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - - if (hService) { - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::isRunning() const -{ - Q_D(const QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_STATUS); - if (hService) { - SERVICE_STATUS info; - int res = pQueryServiceStatus(hService, &info); - if (res) - result = info.dwCurrentState != SERVICE_STOPPED; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - - -QString QtServiceController::serviceFilePath() const -{ - Q_D(const QtServiceController); - QString result; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - if (hService) { - DWORD sizeNeeded = 0; - char data[8 * 1024]; - if (pQueryServiceConfig(hService, (LPQUERY_SERVICE_CONFIG)data, 8 * 1024, &sizeNeeded)) { - LPQUERY_SERVICE_CONFIG config = (LPQUERY_SERVICE_CONFIG)data; - result = QString::fromUtf16((const ushort*)config->lpBinaryPathName); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -QString QtServiceController::serviceDescription() const -{ - Q_D(const QtServiceController); - QString result; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - if (hService) { - DWORD dwBytesNeeded; - char data[8 * 1024]; - if (pQueryServiceConfig2( - hService, - SERVICE_CONFIG_DESCRIPTION, - (unsigned char *)data, - 8096, - &dwBytesNeeded)) { - LPSERVICE_DESCRIPTION desc = (LPSERVICE_DESCRIPTION)data; - if (desc->lpDescription) - result = QString::fromUtf16((const ushort*)desc->lpDescription); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -QtServiceController::StartupType QtServiceController::startupType() const -{ - Q_D(const QtServiceController); - StartupType result = ManualStartup; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - if (hService) { - DWORD sizeNeeded = 0; - char data[8 * 1024]; - if (pQueryServiceConfig(hService, (QUERY_SERVICE_CONFIG *)data, 8 * 1024, &sizeNeeded)) { - QUERY_SERVICE_CONFIG *config = (QUERY_SERVICE_CONFIG *)data; - result = config->dwStartType == SERVICE_DEMAND_START ? ManualStartup : AutoStartup; - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::uninstall() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), DELETE); - if (hService) { - if (pDeleteService(hService)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::start(const QStringList &args) -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), SERVICE_START); - if (hService) { - QVector argv(args.size()); - for (int i = 0; i < args.size(); ++i) - argv[i] = (const wchar_t*)args.at(i).utf16(); - - if (pStartService(hService, args.size(), argv.data())) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::stop() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), SERVICE_STOP|SERVICE_QUERY_STATUS); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, SERVICE_CONTROL_STOP, &status)) { - bool stopped = status.dwCurrentState == SERVICE_STOPPED; - int i = 0; - while(!stopped && i < 10) { - Sleep(200); - if (!pQueryServiceStatus(hService, &status)) - break; - stopped = status.dwCurrentState == SERVICE_STOPPED; - ++i; - } - result = stopped; - } else { - qErrnoWarning(GetLastError(), "stopping"); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::pause() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_PAUSE_CONTINUE); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, SERVICE_CONTROL_PAUSE, &status)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::resume() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_PAUSE_CONTINUE); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, SERVICE_CONTROL_CONTINUE, &status)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::sendCommand(int code) -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - if (code < 0 || code > 127 || !isRunning()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_USER_DEFINED_CONTROL); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, 128 + code, &status)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -#if defined(QTSERVICE_DEBUG) -extern void qtServiceLogDebug(QtMsgType type, const char* msg); -#endif - -void QtServiceBase::logMessage(const QString &message, MessageType type, - int id, uint category, const QByteArray &data) -{ -#if defined(QTSERVICE_DEBUG) - QByteArray dbgMsg("[LOGGED "); - switch (type) { - case Error: dbgMsg += "Error] " ; break; - case Warning: dbgMsg += "Warning] "; break; - case Success: dbgMsg += "Success] "; break; - case Information: //fall through - default: dbgMsg += "Information] "; break; - } - dbgMsg += message.toAscii(); - qtServiceLogDebug((QtMsgType)-1, dbgMsg.constData()); -#endif - - Q_D(QtServiceBase); - if (!winServiceInit()) - return; - WORD wType; - switch (type) { - case Error: wType = EVENTLOG_ERROR_TYPE; break; - case Warning: wType = EVENTLOG_WARNING_TYPE; break; - case Information: wType = EVENTLOG_INFORMATION_TYPE; break; - default: wType = EVENTLOG_SUCCESS; break; - } - HANDLE h = pRegisterEventSource(0, (wchar_t *)d->controller.serviceName().utf16()); - if (h) { - const wchar_t *msg = (wchar_t*)message.utf16(); - const char *bindata = data.size() ? data.constData() : 0; - pReportEvent(h, wType, category, id, 0, 1, data.size(),(const wchar_t **)&msg, - const_cast(bindata)); - pDeregisterEventSource(h); - } -} - -class QtServiceControllerHandler : public QObject -{ - Q_OBJECT -public: - QtServiceControllerHandler(QtServiceSysPrivate *sys); - -protected: - void customEvent(QEvent *e); - -private: - QtServiceSysPrivate *d_sys; -}; - -class QtServiceSysPrivate -{ -public: - enum { - QTSERVICE_STARTUP = 256 - }; - QtServiceSysPrivate(); - - void setStatus( DWORD dwState ); - void setServiceFlags(QtServiceBase::ServiceFlags flags); - DWORD serviceFlags(QtServiceBase::ServiceFlags flags) const; - inline bool available() const; - static void WINAPI serviceMain( DWORD dwArgc, wchar_t** lpszArgv ); - static void WINAPI handler( DWORD dwOpcode ); - - SERVICE_STATUS status; - SERVICE_STATUS_HANDLE serviceStatus; - QStringList serviceArgs; - - static QtServiceSysPrivate *instance; - static QCoreApplication::EventFilter nextFilter; - - QWaitCondition condition; - QMutex mutex; - QSemaphore startSemaphore; - QSemaphore startSemaphore2; - - QtServiceControllerHandler *controllerHandler; - - void handleCustomEvent(QEvent *e); -}; - -QtServiceControllerHandler::QtServiceControllerHandler(QtServiceSysPrivate *sys) - : QObject(), d_sys(sys) -{ - -} - -void QtServiceControllerHandler::customEvent(QEvent *e) -{ - d_sys->handleCustomEvent(e); -} - - -QtServiceSysPrivate *QtServiceSysPrivate::instance = 0; -QCoreApplication::EventFilter QtServiceSysPrivate::nextFilter = 0; - -QtServiceSysPrivate::QtServiceSysPrivate() -{ - instance = this; -} - -inline bool QtServiceSysPrivate::available() const -{ - return 0 != pOpenSCManager; -} - -void WINAPI QtServiceSysPrivate::serviceMain(DWORD dwArgc, wchar_t** lpszArgv) -{ - if (!instance || !QtServiceBase::instance()) - return; - - // Windows spins off a random thread to call this function on - // startup, so here we just signal to the QApplication event loop - // in the main thread to go ahead with start()'ing the service. - - for (DWORD i = 0; i < dwArgc; i++) - instance->serviceArgs.append(QString::fromUtf16((unsigned short*)lpszArgv[i])); - - instance->startSemaphore.release(); // let the qapp creation start - instance->startSemaphore2.acquire(); // wait until its done - // Register the control request handler - instance->serviceStatus = pRegisterServiceCtrlHandler((TCHAR*)QtServiceBase::instance()->serviceName().utf16(), handler); - - if (!instance->serviceStatus) // cannot happen - something is utterly wrong - return; - - handler(QTSERVICE_STARTUP); // Signal startup to the application - - // causes QtServiceBase::start() to be called in the main thread - - // The MSDN doc says that this thread should just exit - the service is - // running in the main thread (here, via callbacks in the handler thread). -} - - -// The handler() is called from the thread that called -// StartServiceCtrlDispatcher, i.e. our HandlerThread, and -// not from the main thread that runs the event loop, so we -// have to post an event to ourselves, and use a QWaitCondition -// and a QMutex to synchronize. -void QtServiceSysPrivate::handleCustomEvent(QEvent *e) -{ - int code = e->type() - QEvent::User; - - switch(code) { - case QTSERVICE_STARTUP: // Startup - QtServiceBase::instance()->start(); - break; - case SERVICE_CONTROL_STOP: - QtServiceBase::instance()->stop(); - QCoreApplication::instance()->quit(); - break; - case SERVICE_CONTROL_PAUSE: - QtServiceBase::instance()->pause(); - break; - case SERVICE_CONTROL_CONTINUE: - QtServiceBase::instance()->resume(); - break; - default: - if (code >= 128 && code <= 255) - QtServiceBase::instance()->processCommand(code - 128); - break; - } - - mutex.lock(); - condition.wakeAll(); - mutex.unlock(); -} - -void WINAPI QtServiceSysPrivate::handler( DWORD code ) -{ - if (!instance) - return; - - instance->mutex.lock(); - switch (code) { - case QTSERVICE_STARTUP: // QtService startup (called from WinMain when started) - instance->setStatus(SERVICE_START_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - instance->setStatus(SERVICE_RUNNING); - break; - case SERVICE_CONTROL_STOP: // 1 - instance->setStatus(SERVICE_STOP_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - // status will be reported as stopped in start() when qapp::exec returns - break; - - case SERVICE_CONTROL_PAUSE: // 2 - instance->setStatus(SERVICE_PAUSE_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - instance->setStatus(SERVICE_PAUSED); - break; - - case SERVICE_CONTROL_CONTINUE: // 3 - instance->setStatus(SERVICE_CONTINUE_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - instance->setStatus(SERVICE_RUNNING); - break; - - case SERVICE_CONTROL_INTERROGATE: // 4 - break; - - default: - if ( code >= 128 && code <= 255 ) { - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - } - break; - } - - instance->mutex.unlock(); - - // Report current status - if (instance->available() && instance->status.dwCurrentState != SERVICE_STOPPED) - pSetServiceStatus(instance->serviceStatus, &instance->status); -} - -void QtServiceSysPrivate::setStatus(DWORD state) -{ - if (!available()) - return; - status.dwCurrentState = state; - pSetServiceStatus(serviceStatus, &status); -} - -void QtServiceSysPrivate::setServiceFlags(QtServiceBase::ServiceFlags flags) -{ - if (!available()) - return; - status.dwControlsAccepted = serviceFlags(flags); - pSetServiceStatus(serviceStatus, &status); -} - -DWORD QtServiceSysPrivate::serviceFlags(QtServiceBase::ServiceFlags flags) const -{ - DWORD control = 0; - if (flags & QtServiceBase::CanBeSuspended) - control |= SERVICE_ACCEPT_PAUSE_CONTINUE; - if (!(flags & QtServiceBase::CannotBeStopped)) - control |= SERVICE_ACCEPT_STOP; - return control; -} - -#include "qtservice_win.moc" - - -class HandlerThread : public QThread -{ -public: - HandlerThread() - : success(true), console(false), QThread() - {} - - bool calledOk() { return success; } - bool runningAsConsole() { return console; } - -protected: - bool success, console; - void run() - { - SERVICE_TABLE_ENTRYW st [2]; - st[0].lpServiceName = (wchar_t*)QtServiceBase::instance()->serviceName().utf16(); - st[0].lpServiceProc = QtServiceSysPrivate::serviceMain; - st[1].lpServiceName = 0; - st[1].lpServiceProc = 0; - - success = (pStartServiceCtrlDispatcher(st) != 0); // should block - - if (!success) { - if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { - // Means we're started from console, not from service mgr - // start() will ask the mgr to start another instance of us as a service instead - console = true; - } - else { - QtServiceBase::instance()->logMessage(QString("The Service failed to start [%1]").arg(qt_error_string(GetLastError())), QtServiceBase::Error); - } - QtServiceSysPrivate::instance->startSemaphore.release(); // let start() continue, since serviceMain won't be doing it - } - } -}; - -/* - Ignore WM_ENDSESSION system events, since they make the Qt kernel quit -*/ -bool myEventFilter(void* message, long* result) -{ - MSG* msg = reinterpret_cast(message); - if (!msg || (msg->message != WM_ENDSESSION) || !(msg->lParam & ENDSESSION_LOGOFF)) - return QtServiceSysPrivate::nextFilter ? QtServiceSysPrivate::nextFilter(message, result) : false; - - if (QtServiceSysPrivate::nextFilter) - QtServiceSysPrivate::nextFilter(message, result); - if (result) - *result = TRUE; - return true; -} - -/* There are three ways we can be started: - - - By a service controller (e.g. the Services control panel), with - no (service-specific) arguments. ServiceBase::exec() will then call - start() below, and the service will start. - - - From the console, but with no (service-specific) arguments. This - means we should ask a controller to start the service (i.e. another - instance of this executable), and then just terminate. We discover - this case (as different from the above) by the fact that - StartServiceCtrlDispatcher will return an error, instead of blocking. - - - From the console, with -e(xec) argument. ServiceBase::exec() will - then call ServiceBasePrivate::exec(), which calls - ServiceBasePrivate::run(), which runs the application as a normal - program. -*/ - -bool QtServiceBasePrivate::start() -{ - sysInit(); - if (!winServiceInit()) - return false; - - // Since StartServiceCtrlDispatcher() blocks waiting for service - // control events, we need to call it in another thread, so that - // the main thread can run the QApplication event loop. - HandlerThread* ht = new HandlerThread(); - ht->start(); - - QtServiceSysPrivate* sys = QtServiceSysPrivate::instance; - - // Wait until service args have been received by serviceMain. - // If Windows doesn't call serviceMain (or - // StartServiceControlDispatcher doesn't return an error) within - // a timeout of 20 secs, something is very wrong; give up - if (!sys->startSemaphore.tryAcquire(1, 20000)) - return false; - - if (!ht->calledOk()) { - if (ht->runningAsConsole()) - return controller.start(args.mid(1)); - else - return false; - } - - int argc = sys->serviceArgs.size(); - QVector argv(argc); - QList argvData; - for (int i = 0; i < argc; ++i) - argvData.append(sys->serviceArgs.at(i).toLocal8Bit()); - for (int i = 0; i < argc; ++i) - argv[i] = argvData[i].data(); - - q_ptr->createApplication(argc, argv.data()); - QCoreApplication *app = QCoreApplication::instance(); - if (!app) - return false; - QtServiceSysPrivate::nextFilter = app->setEventFilter(myEventFilter); - - sys->controllerHandler = new QtServiceControllerHandler(sys); - - sys->startSemaphore2.release(); // let serviceMain continue (and end) - - sys->status.dwWin32ExitCode = q_ptr->executeApplication(); - sys->setStatus(SERVICE_STOPPED); - - if (ht->isRunning()) - ht->wait(1000); // let the handler thread finish - delete sys->controllerHandler; - sys->controllerHandler = 0; - if (ht->isFinished()) - delete ht; - delete app; - sysCleanup(); - return true; -} - -bool QtServiceBasePrivate::install(const QString &account, const QString &password) -{ - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); - if (hSCM) { - QString acc = account; - DWORD dwStartType = startupType == QtServiceController::AutoStartup ? SERVICE_AUTO_START : SERVICE_DEMAND_START; - DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS; - wchar_t *act = 0; - wchar_t *pwd = 0; - if (!acc.isEmpty()) { - // The act string must contain a string of the format "Domain\UserName", - // so if only a username was specified without a domain, default to the local machine domain. - if (!acc.contains(QChar('\\'))) { - acc.prepend(QLatin1String(".\\")); - } - if (!acc.endsWith(QLatin1String("\\LocalSystem"))) - act = (wchar_t*)acc.utf16(); - } - if (!password.isEmpty() && act) { - pwd = (wchar_t*)password.utf16(); - } - - // Only set INTERACTIVE if act is LocalSystem. (and act should be 0 if it is LocalSystem). - if (!act) dwServiceType |= SERVICE_INTERACTIVE_PROCESS; - - // Create the service - SC_HANDLE hService = pCreateService(hSCM, (wchar_t *)controller.serviceName().utf16(), - (wchar_t *)controller.serviceName().utf16(), - SERVICE_ALL_ACCESS, - dwServiceType, // QObject::inherits ( const char * className ) for no inter active ???? - dwStartType, SERVICE_ERROR_NORMAL, (wchar_t *)filePath().utf16(), - 0, 0, 0, - act, pwd); - if (hService) { - result = true; - if (!serviceDescription.isEmpty()) { - SERVICE_DESCRIPTION sdesc; - sdesc.lpDescription = (wchar_t *)serviceDescription.utf16(); - pChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sdesc); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -QString QtServiceBasePrivate::filePath() const -{ - wchar_t path[_MAX_PATH]; - ::GetModuleFileNameW( 0, path, sizeof(path) ); - return QString::fromUtf16((unsigned short*)path); -} - -bool QtServiceBasePrivate::sysInit() -{ - sysd = new QtServiceSysPrivate(); - - sysd->serviceStatus = 0; - sysd->status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS; - sysd->status.dwCurrentState = SERVICE_STOPPED; - sysd->status.dwControlsAccepted = sysd->serviceFlags(serviceFlags); - sysd->status.dwWin32ExitCode = NO_ERROR; - sysd->status.dwServiceSpecificExitCode = 0; - sysd->status.dwCheckPoint = 0; - sysd->status.dwWaitHint = 0; - - return true; -} - -void QtServiceBasePrivate::sysSetPath() -{ - -} - -void QtServiceBasePrivate::sysCleanup() -{ - if (sysd) { - delete sysd; - sysd = 0; - } -} - -void QtServiceBase::setServiceFlags(QtServiceBase::ServiceFlags flags) -{ - if (d_ptr->serviceFlags == flags) - return; - d_ptr->serviceFlags = flags; - if (d_ptr->sysd) - d_ptr->sysd->setServiceFlags(flags); -} - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp deleted file mode 100644 index a04f0f4c..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtunixserversocket.h" -#include -#include -#include -#include -#include - -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ - +strlen ((ptr)->sun_path)) -#endif - -QtUnixServerSocket::QtUnixServerSocket(const QString &path, QObject *parent) - : QTcpServer(parent) -{ - setPath(path); -} - -QtUnixServerSocket::QtUnixServerSocket(QObject *parent) - : QTcpServer(parent) -{ -} - -void QtUnixServerSocket::setPath(const QString &path) -{ - path_.clear(); - - int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); - if (sock != -1) { - struct sockaddr_un addr; - ::memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - ::unlink(path.toLatin1().constData()); // ### This might need to be changed - unsigned int pathlen = strlen(path.toLatin1().constData()); - if (pathlen > sizeof(addr.sun_path)) pathlen = sizeof(addr.sun_path); - ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); - if ((::bind(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)) != -1) && - (::listen(sock, 5) != -1)) { - setSocketDescriptor(sock); - path_ = path; - } - } -} - -void QtUnixServerSocket::close() -{ - QTcpServer::close(); - if (!path_.isEmpty()) { - ::unlink(path_.toLatin1().constData()); - path_.clear(); - } -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h deleted file mode 100644 index 2ba2fd12..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTUNIXSERVERSOCKET_H -#define QTUNIXSERVERSOCKET_H - -#include - -class QtUnixServerSocket : public QTcpServer -{ - Q_OBJECT -public: - QtUnixServerSocket(const QString &path, QObject *parent = 0); - QtUnixServerSocket(QObject *parent = 0); - - void setPath(const QString &path); - void close(); - -private: - QString path_; -}; - - -#endif diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp deleted file mode 100644 index fae5ac1b..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtunixsocket.h" -#include -#include -#include -#include -#include - -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ - +strlen ((ptr)->sun_path)) -#endif - -QtUnixSocket::QtUnixSocket(QObject *parent) - : QTcpSocket(parent) -{ -} - -bool QtUnixSocket::connectTo(const QString &path) -{ - bool ret = false; - int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); - if (sock != -1) { - struct sockaddr_un addr; - ::memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - size_t pathlen = strlen(path.toLatin1().constData()); - pathlen = qMin(pathlen, sizeof(addr.sun_path)); - ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); - int err = ::connect(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)); - if (err != -1) { - setSocketDescriptor(sock); - ret = true; - } else { - ::close(sock); - } - } - return ret; -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h deleted file mode 100644 index b7aaebde..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTUNIXSOCKET_H -#define QTUNIXSOCKET_H - -#include - -class QtUnixSocket : public QTcpSocket -{ - Q_OBJECT -public: - QtUnixSocket(QObject *parent = 0); - - bool connectTo(const QString &path); -}; - -#endif diff --git a/telldus-core/3rdparty/qtservice.cmake b/telldus-core/3rdparty/qtservice.cmake deleted file mode 100644 index 652b0127..00000000 --- a/telldus-core/3rdparty/qtservice.cmake +++ /dev/null @@ -1,39 +0,0 @@ - -QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice.moc ) - -SET( qtservice_SRCS - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp - ${CMAKE_CURRENT_BINARY_DIR}/qtservice.moc -) - -IF (UNIX) - QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice_unix.moc ) - - SET( qtservice_MOC_HDRS - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h - ) - - QT4_WRAP_CPP( qtservice_MOC_SRCS ${qtservice_MOC_HDRS} ) - - SET( qtservice_SRCS - ${qtservice_SRCS} - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp - ${CMAKE_CURRENT_BINARY_DIR}/qtservice_unix.moc - ${qtservice_MOC_SRCS} - ) -ELSEIF (WIN32) - QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice_win.moc ) - SET(qtservice_SRCS - ${qtservice_SRCS} - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp - ${CMAKE_CURRENT_BINARY_DIR}/qtservice_win.moc - ) -ENDIF (UNIX) - -INCLUDE_DIRECTORIES( - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/ - ${CMAKE_CURRENT_BINARY_DIR} -) diff --git a/telldus-core/AUTHORS b/telldus-core/AUTHORS deleted file mode 100644 index a8356907..00000000 --- a/telldus-core/AUTHORS +++ /dev/null @@ -1,7 +0,0 @@ -telldus-core has been developed by : - - Micke Prag - Fredrik Jacobsson - Stefan Persson - -The package is maintained by Micke Prag \ No newline at end of file diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt deleted file mode 100644 index cd0f71d3..00000000 --- a/telldus-core/CMakeLists.txt +++ /dev/null @@ -1,95 +0,0 @@ -PROJECT( telldus-core ) - -CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) - -OPTION(FORCE_COMPILE_FROM_TRUNK FALSE "Accept compiling source from trunk. This is unsupported and highly unrecommended") -IF(NOT FORCE_COMPILE_FROM_TRUNK) - MESSAGE(FATAL_ERROR "You are compiling sources from trunk. Don't do that!") -ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) - -IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - INCLUDE_DIRECTORIES(/usr/local/include) - LINK_DIRECTORIES(/usr/local/lib) -ENDIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - -cmake_policy(SET CMP0003 NEW) - -SET(PACKAGE_MAJOR_VERSION 2) -SET(PACKAGE_MINOR_VERSION 0) -SET(PACKAGE_PATCH_VERSION 102) -SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION) -SET(PACKAGE_SOVERSION 2) - -IF (PACKAGE_SUBVERSION) - SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_${PACKAGE_SUBVERSION}") -ELSE (PACKAGE_SUBVERSION) - SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) -ENDIF(PACKAGE_SUBVERSION) - -SET(BUILD_LIBTELLDUS-CORE TRUE CACHE BOOL "Build libtelldus-core") -SET(BUILD_LIBTELLDUS-CORE_AS_SERVICE TRUE CACHE BOOL "Build libtelldus-core as a service on Windows") -SET(SUPPORT_TELLSTICK_DUO FALSE CACHE BOOL "Include support for TellStick Duo") -IF (UNIX AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - SET(SUPPORT_USB FALSE CACHE BOOL "Build support for usb-devices") -ELSE (UNIX AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - SET(SUPPORT_USB TRUE CACHE BOOL "Build support for usb-devices") -ENDIF(UNIX AND NOT CMAKE_SYSTEM_NAME MATCHES "FreeBSD") -SET(USE_QT_SETTINGS_BACKEND FALSE CACHE BOOL "Use QT as settings backend instead of the native one") -IF (WIN32) - SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") -ENDIF (WIN32) - -IF (UNIX AND NOT APPLE) - SET(BUILD_RFCMD FALSE CACHE BOOL "Build rfcmd") -ELSE (UNIX AND NOT APPLE) - SET(BUILD_RFCMD TRUE CACHE BOOL "Build rfcmd") -ENDIF (UNIX AND NOT APPLE) -IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - SET(BUILD_RFCMD_WITH_LIBFTDI TRUE CACHE BOOL "Enable support for using rfcmd with libftdi (does not need kernel-driver)") - SET(BUILD_RFCMD_WITH_SEMAPHORES FALSE CACHE BOOL "Enable support for using rfcmd with semaphores (Requires special kernel-config)") -ELSE(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - SET(BUILD_RFCMD_WITH_LIBFTDI FALSE CACHE BOOL "Enable support for using rfcmd with libftdi (does not need kernel-driver)") - SET(BUILD_RFCMD_WITH_SEMAPHORES TRUE CACHE BOOL "Enable support for using rfcmd with semaphores") -ENDIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") -SET(BUILD_TDTOOL TRUE CACHE BOOL "Build tdtool") - -SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") - -# Lets figure if we need to build against Qt or not -IF(USE_QT_SETTINGS_BACKEND) - SET(BUILD_WITH_QT TRUE) -ENDIF(USE_QT_SETTINGS_BACKEND) - -ADD_SUBDIRECTORY(driver) - -IF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - ADD_SUBDIRECTORY(telldus-service) -ENDIF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - -if(BUILD_TDTOOL) - ADD_SUBDIRECTORY(tdtool) -endif(BUILD_TDTOOL) - -if(BUILD_RFCMD) - ADD_SUBDIRECTORY(rfcmd) -endif(BUILD_RFCMD) - -########## CPack ############# -SET(CPACK_PACKAGE_NAME ${CMAKE_PROJECT_NAME}) -SET(CPACK_PACKAGE_VERSION "${PACKAGE_VERSION}${PACKAGE_SUBVERSION}") -SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") -SET(CPACK_PACKAGE_CONTACT "Micke Prag ") -SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Utilities for a Telldus TellStick") -SET(CPACK_PACKAGE_DESCRIPTION "Utilities and driver to control NEXA and other RF remote receivers through a TellStick USB interface") -SET(CPACK_PACKAGE_VENDOR "Telldus Technologies AB") -SET(CPACK_STRIP_FILES "usr/bin/tdtool;usr/bin/rfcmd") -# SET(CPACK_PACKAGE_INSTALL_DIRECTORY "") -# SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") - -#### .deb #### -SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.7-1), libconfuse0 (>=2.6-2), udev") -SET(CPACK_DEBIAN_PACKAGE_SECTION "utils") -SET(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/debian/postinst;${CMAKE_CURRENT_SOURCE_DIR}/debian/postrm") - -INCLUDE(CPack) diff --git a/telldus-core/ChangeLog b/telldus-core/ChangeLog deleted file mode 100644 index 82d7959b..00000000 --- a/telldus-core/ChangeLog +++ /dev/null @@ -1,10 +0,0 @@ -telldus-core 2.0.1 (2009-11-10) - - * Fixed bug when the number of devices is more then 9 on Windows - * Provided functions for possible memory leaks in some languages - * Better error-reporting when communication with TellStick doesn't work - * More friendlier configuration for GAO - -telldus-core 2.0.0 (2009-09-22) - - * Initial release diff --git a/telldus-core/INSTALL b/telldus-core/INSTALL deleted file mode 100644 index 9d2b0b4a..00000000 --- a/telldus-core/INSTALL +++ /dev/null @@ -1,51 +0,0 @@ -Unpacking ---------- - -Unpack the archive if you have not done so already: - - cd /usr/src - gunzip telldus-core-{version}.tar.gz #Change {version} to the downloaded version - tar xvf telldus-core-{version}.tar - -This creates the directory /usr/src/telldus-core-{version} containing the files -from the archive. We only support the GNU version of tar archiving utility. Note -on some systems it is called gtar. - -Configuring ------------ - -Telldus Core is built using CMake (http://www.cmake.org), version 2.4.0 is the -minimum required version. This means there is no configure-script, but you -need to run cmake. - -To configure telldus-core for your machine type: - - cmake . - -in the package directory. - -By default, Telldus Core is configured for installation in the /usr/local -directory, but this can be changed by using the -DCMAKE_INSTALL_PREFIX=/usr -option. Alternatively, the DESTDIR="/opt" option can be used to specify a "local" -installation within the source directory when running "make install". - -Building --------- - -To create the library and compile all the tools type: - - make - -If you did not configure Telldus Core using the -DCMAKE_INSTALL_PREFIX=/usr -option, you need to install the library and tools in the appropriate place. To -do this, type: - - su -c "make install" - -and enter the root password. - -If you want to install in another directory, type: - - su -c "make DESTDIR=/opt install" - -Note that on some systems the make utility is named differently, e.g. gmake. diff --git a/telldus-core/LICENSE b/telldus-core/LICENSE deleted file mode 100644 index 82fa1daa..00000000 --- a/telldus-core/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/telldus-core/README b/telldus-core/README deleted file mode 100644 index 5778ee2b..00000000 --- a/telldus-core/README +++ /dev/null @@ -1,30 +0,0 @@ -This is Telldus Core version {version} - -Telldus Core is the driver and tools for controlling a Telldus Technologies -TellStick. It does not containing any GUI tools which makes it suitable for -server use. - - -INSTALLING Telldus Core - -On Windows, if you want to install the precompiles binary packages, simply -launch the package and follow the instructions in the installation wizard. - -If you have a source package (a .tag.gz file), follow the instruction in the -INSTALL file. - - -CONFIGURATION AND TOOLS - -Once Telldus Core is installed, we suggest that you start by adding the devices -you want to control. - -On Windows, this is done with the tool TelldusSetup. On Linux this is done in -the file /etc/tellstick.conf. - -Telldus Core installs the tool tdtool for controlling devices with TellStick. -Have a look in the man page for a description how to use it: - - man tdtool - -TellStick is a trademark of Telldus Technologies AB diff --git a/telldus-core/cruise_build.sh b/telldus-core/cruise_build.sh deleted file mode 100755 index a0df64a1..00000000 --- a/telldus-core/cruise_build.sh +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - - -CMAKE_LOG="$CC_BUILD_ARTIFACTS/cmake.log" - -if [ ! -d "$CC_BUILD_ARTIFACTS" ] -then - echo "CC_BUILD_ARTIFACTS does not point to a valid directory!" - exit 1 -fi - -echo -n "Preparing directories... " -test -d build || mkdir build -echo "done." - -( - echo -n "Preparing build... " - echo -n "running cmake... " - cd build -# cmake .. -DCMAKE_BUILD_TYPE=Profile > "$CMAKE_LOG" - cmake .. > "$CMAKE_LOG" -) - -if [ "$?" -ne 0 ] -then - echo "failed" - exit 1 -fi -echo "done." - - -echo "Building..." -make -C build -if [ "$?" -ne 0 ] -then - exit 1 -fi - -#Mina egna tester här - -exit 0 - diff --git a/telldus-core/cruise_config.rb b/telldus-core/cruise_config.rb deleted file mode 100644 index 37f803ba..00000000 --- a/telldus-core/cruise_config.rb +++ /dev/null @@ -1,5 +0,0 @@ -Project.configure do |project| - project.email_notifier.emails = ["micke.prag@telldus.se"] - project.email_notifier.from = 'micke.prag@telldus.se' - project.build_command = './cruise_build.sh' -end diff --git a/telldus-core/debian/changelog b/telldus-core/debian/changelog deleted file mode 100644 index ed503d4d..00000000 --- a/telldus-core/debian/changelog +++ /dev/null @@ -1,12 +0,0 @@ -telldus-core (2.0.1-1) unstable; urgency=low - - * New upstream version - - -- Micke Prag Tue, 10 Nov 2009 21:55:00 +0200 - -telldus-core (2.0.0-1) unstable; urgency=low - - * Initial release (Closes: #544982) - - -- Micke Prag Thu, 03 Sep 2009 20:25:46 +0200 - diff --git a/telldus-core/debian/control b/telldus-core/debian/control deleted file mode 100644 index 91b36cba..00000000 --- a/telldus-core/debian/control +++ /dev/null @@ -1,36 +0,0 @@ -Source: telldus-core -Priority: extra -Maintainer: Micke Prag -Build-Depends: debhelper (>= 7) -Standards-Version: 3.7.3 -Section: libs -Homepage: http://www.telldus.se - -Package: libtelldus-core-dev -Section: libdevel -Architecture: any -Depends: libtelldus-core2 (= ${binary:Version}) -Description: Development file for libtelldus-core - This package contains the header file needed to - compile applications that use telldus-core. - -Package: libtelldus-core2 -Section: libs -Architecture: any -Depends: ${shlibs:Depends} -Description: Library to control a Telldus TellStick - libtelldus-core is the library for controlling wireless devices by a - Telldus TellStick. - . - It makes it very easy to add home automation capabilities to a - program using a simple API. - -Package: telldus-core -Architecture: any -Depends: ${shlibs:Depends} -Description: Utilities and driver to control wireless receivers through a TellStick - TellStick from Telldus Technologies is a USB-interface to various remote - controlled RF receivers on 433,92 MHz. - . - This package contains the command line interface utilities for controling - the devices. diff --git a/telldus-core/debian/copyright b/telldus-core/debian/copyright deleted file mode 100644 index 93c11822..00000000 --- a/telldus-core/debian/copyright +++ /dev/null @@ -1,20 +0,0 @@ -This package was debianized by Micke Prag on -Thu, 03 Sep 2009 20:25:46 +0200. - -It was downloaded from http://download.telldus.se/TellStick/Software/telldus-core/ - -Upstream Author: - - Micke Prag - -Copyright: - - Copyright (C) 2009 Telldus Technologies AB - -License: - - GPL-2 - -The Debian packaging is (C) 2009, Micke Prag and -is licensed under the GPL-2, see `/usr/share/common-licenses/GPL-2'. - diff --git a/telldus-core/debian/libtelldus-core-dev.install b/telldus-core/debian/libtelldus-core-dev.install deleted file mode 100644 index 354b1789..00000000 --- a/telldus-core/debian/libtelldus-core-dev.install +++ /dev/null @@ -1,3 +0,0 @@ -usr/include/* -usr/lib/lib*.so - diff --git a/telldus-core/debian/libtelldus-core2.install b/telldus-core/debian/libtelldus-core2.install deleted file mode 100644 index d0dbfd18..00000000 --- a/telldus-core/debian/libtelldus-core2.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/lib*.so.* diff --git a/telldus-core/debian/rules b/telldus-core/debian/rules deleted file mode 100755 index d0fdf24e..00000000 --- a/telldus-core/debian/rules +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/make -f -# -*- makefile -*- -# Sample debian/rules that uses debhelper. -# This file was originally written by Joey Hess and Craig Small. -# As a special exception, when this file is copied by dh-make into a -# dh-make output file, you may use that output file without restriction. -# This special exception was added by Craig Small in version 0.37 of dh-make. - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - - - - - - -# shared library versions, option 1 -version=2.0.0 -major=2 -# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so -#version=`ls src/.libs/lib*.so.* | \ -# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` -#major=`ls src/.libs/lib*.so.* | \ -# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` - -configure: configure-stamp -configure-stamp: - dh_testdir - # Add here commands to configure the package. - - mkdir build - cd build && \ - cmake \ - -DBUILD_RFCMD=1 \ - -DBUILD_RFCMD_WITH_LIBFTDI=0 \ - -DBUILD_LIBTELLDUS-CORE=1 \ - -DBUILD_TDTOOL=1 \ - -DSUPPORT_TELLSTICK_DUO=0 \ - -DSUPPORT_USB=0 \ - -DUSE_QT_SETTINGS_BACKEND=0 \ - -DGENERATE_MAN=1 \ - -DCMAKE_INSTALL_PREFIX=/usr \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_CXX_FLAGS="-Wl,--as-needed" \ - .. - - touch configure-stamp - - -build: build-stamp -build-stamp: configure-stamp - dh_testdir - - # Add here commands to compile the package. - cd build && \ - $(MAKE) - - touch $@ - -clean: - dh_testdir - dh_testroot - rm -f build-stamp configure-stamp - - # Add here commands to clean up after the build process. - if test -d build; then rm -rf build;fi - - dh_clean - -install: build - dh_testdir - dh_testroot - dh_clean -k - dh_installdirs - - # Add here commands to install the package into debian/tmp - cd build && \ - $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install - - -# Build architecture-independent files here. -binary-indep: build install -# We have nothing to do by default. - -# Build architecture-dependent files here. -binary-arch: build install - dh_testdir - dh_testroot - dh_installchangelogs - dh_installdocs - dh_installexamples - dh_install -# dh_installmenu -# dh_installdebconf -# dh_installlogrotate -# dh_installemacsen -# dh_installpam -# dh_installmime -# dh_installinit -# dh_installcron -# dh_installinfo - dh_installman - dh_link - dh_strip - dh_compress - dh_fixperms -# dh_perl -# dh_python - dh_makeshlibs - dh_installdeb - dh_shlibdeps - dh_gencontrol - dh_md5sums - dh_builddeb - -binary: binary-indep binary-arch -.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/telldus-core/debian/telldus-core.install b/telldus-core/debian/telldus-core.install deleted file mode 100644 index c7f3918e..00000000 --- a/telldus-core/debian/telldus-core.install +++ /dev/null @@ -1,4 +0,0 @@ -usr/bin/* -usr/share/man/man1/* -etc/* - diff --git a/telldus-core/debian/telldus-core.postinst b/telldus-core/debian/telldus-core.postinst deleted file mode 100644 index 5b34eb56..00000000 --- a/telldus-core/debian/telldus-core.postinst +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -# postinst script for telldus-core -# -# see: dh_installdeb(1) - -set -e - -# summary of how this script can be called: -# * `configure' -# * `abort-upgrade' -# * `abort-remove' `in-favour' -# -# * `abort-remove' -# * `abort-deconfigure' `in-favour' -# `removing' -# -# for details, see http://www.debian.org/doc/debian-policy/ or -# the debian-policy package - - -case "$1" in - configure) - chown root:plugdev /etc/tellstick.conf - chmod 664 /etc/tellstick.conf - - mkdir -p /var/state - touch /var/state/telldus-core.conf - chown root:plugdev /var/state/telldus-core.conf - chmod 666 /var/state/telldus-core.conf - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - - diff --git a/telldus-core/driver/CMakeLists.txt b/telldus-core/driver/CMakeLists.txt deleted file mode 100644 index 99033075..00000000 --- a/telldus-core/driver/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -PROJECT( tellstick ) - -if(BUILD_LIBTELLDUS-CORE) - ADD_SUBDIRECTORY(libtelldus-core) -endif(BUILD_LIBTELLDUS-CORE) - - -IF (WIN32) - SET(BUILD_TELLUSBD101 TRUE CACHE BOOL "Build wrapper TellUsbD101.dll") - IF (BUILD_TELLUSBD101) - ADD_SUBDIRECTORY(TellUsbD101) - ENDIF (BUILD_TELLUSBD101) -ENDIF (WIN32) - -ADD_SUBDIRECTORY(bindings) \ No newline at end of file diff --git a/telldus-core/driver/TellUsbD101.sln b/telldus-core/driver/TellUsbD101.sln deleted file mode 100644 index 1b22fbc9..00000000 --- a/telldus-core/driver/TellUsbD101.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual C++ Express 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TellUsbD101", "TellUsbD101\TellUsbD101.vcproj", "{2A868E40-88D9-4800-A83F-21D0F8DCB611}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Debug|Win32.ActiveCfg = Release|Win32 - {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Debug|Win32.Build.0 = Release|Win32 - {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Release|Win32.ActiveCfg = Release|Win32 - {2A868E40-88D9-4800-A83F-21D0F8DCB611}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/telldus-core/driver/TellUsbD101/CMakeLists.txt b/telldus-core/driver/TellUsbD101/CMakeLists.txt deleted file mode 100644 index 0d6c38dc..00000000 --- a/telldus-core/driver/TellUsbD101/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -SET( tellusbd101_SRCS - TellUsbD101.cpp - TellUsbD101.def -) - -SET( tellusbd101_HDRS - TellUsbD101.h -) - -SET( tellusbd101_TARGET TellUsbD101 ) - ADD_DEFINITIONS( - -D_WINDOWS - -DTellUsbD101_EXPORTS -) - -SET( tellusbd101_LIBRARIES - "${LIBRARY_OUTPUT_PATH}/Release/TelldusCore.lib" -) - - -######## Configuring ######## - -ADD_LIBRARY(${tellusbd101_TARGET} SHARED - ${tellusbd101_SRCS} - ${tellusbd101_HDRS} -) - -TARGET_LINK_LIBRARIES( ${tellusbd101_TARGET} ${tellusbd101_LIBRARIES} ) - -SET_PROPERTY(TARGET ${tellusbd101_TARGET} - PROPERTY PUBLIC_HEADER ${tellusbd101_HDRS} -) - diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp deleted file mode 100644 index 3765e4c4..00000000 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ /dev/null @@ -1,85 +0,0 @@ -//DLL entry point - -#include "TellUsbD101.h" -#include "../libtelldus-core/telldus-core.h" -#include -#include -#include -#include - - -int __stdcall devGetNumberOfDevices(void){ - return tdGetNumberOfDevices(); -} - -int __stdcall devGetDeviceId(int intDeviceIndex){ - return tdGetDeviceId(intDeviceIndex); -} - -char * __stdcall devGetName(int intDeviceId){ - return tdGetName(intDeviceId); -} - -char* __stdcall devGetVendor(int intDeviceId){ - return tdGetProtocol(intDeviceId); -} - -char* __stdcall devGetModel(int intDeviceId){ - return tdGetModel(intDeviceId); -} - -int __stdcall devGetNumberOfArguments(int intDeviceId){ - return 0; -} - -int __stdcall devGetArgument(int intDeviceId, int intArgumentIndex){ - return 0; -} - -bool __stdcall devSetName(int intDeviceId, char* strNewName){ - return tdSetName(intDeviceId, strNewName); -} - -bool __stdcall devSetVendor(int intDeviceId, char* strVendor) { - if (_stricmp(strVendor, "nexa") == 0) { - return tdSetProtocol(intDeviceId, "arctech"); - } else { - return tdSetProtocol(intDeviceId, strVendor); - } -} - -bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ - return tdSetModel(intDeviceId, strNewModel); -} - -bool __stdcall devSetArguments(int intDeviceId, char* strArguments){ - return false; -} - -int __stdcall devAddDevice(){ - return tdAddDevice(); -} - -bool __stdcall devRemoveDevice(int intDeviceId){ - return tdRemoveDevice(intDeviceId); -} - -int __stdcall devMethods(int id){ - return tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL); -} - -bool __stdcall devTurnOn(int intDeviceId){ - return (tdTurnOn(intDeviceId) == TELLSTICK_SUCCESS ? true : false); -} - -bool __stdcall devTurnOff(int intDeviceId){ - return (tdTurnOff(intDeviceId) == TELLSTICK_SUCCESS ? true : false); -} - -bool __stdcall devBell(int intDeviceId){ - return (tdBell(intDeviceId) == TELLSTICK_SUCCESS ? true : false); -} - -bool __stdcall devDim(int intDeviceId, unsigned char level){ - return (tdDim(intDeviceId, level) == TELLSTICK_SUCCESS ? true : false); -} diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.def b/telldus-core/driver/TellUsbD101/TellUsbD101.def deleted file mode 100644 index fc32ffca..00000000 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.def +++ /dev/null @@ -1,24 +0,0 @@ -LIBRARY TellUsbD101 -EXPORTS - devGetNumberOfDevices @1 - devGetDeviceId @2 - - devGetName @3 - devGetVendor @4 - devGetModel @5 - devGetNumberOfArguments @6 - devGetArgument @7 - - devSetName @8 - devSetVendor @9 - devSetModel @10 - devSetArguments @11 - - devAddDevice @12 - devRemoveDevice @13 - - devMethods @14 - devTurnOn @16 - devTurnOff @17 - devBell @18 - devDim @19 diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.h b/telldus-core/driver/TellUsbD101/TellUsbD101.h deleted file mode 100644 index 4868c964..00000000 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef TELLUSBD101_H -#define TELLUSBD101_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the TellUsbD101_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// TELLUSBD101_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef TellUsbD101_EXPORTS - #define TELLUSBD101_API __declspec(dllexport) -#else - #define TELLUSBD101_API __declspec(dllimport) -#endif -#ifdef _WINDOWS - #define WINAPI __stdcall -#else - #define WINAPI -#endif - - -extern "C" { - TELLUSBD101_API bool WINAPI devTurnOn(int intDeviceId); - TELLUSBD101_API bool WINAPI devTurnOff(int intDeviceId); - TELLUSBD101_API bool WINAPI devBell(int intDeviceId); - TELLUSBD101_API bool WINAPI devDim(int intDeviceId, unsigned char level); - TELLUSBD101_API int WINAPI devGetNumberOfDevices(); - TELLUSBD101_API char * WINAPI devGetName(int intDeviceId); - TELLUSBD101_API bool WINAPI devSetName(int intDeviceId, const char* chNewName); - TELLUSBD101_API char* WINAPI devGetVendor(int intDeviceId); - TELLUSBD101_API bool WINAPI devSetVendor(int intDeviceId, const char* chNewName); - TELLUSBD101_API char* WINAPI devGetModel(int intDeviceId); - TELLUSBD101_API bool WINAPI devSetModel(int intDeviceId, const char* chNewName); - TELLUSBD101_API int WINAPI devGetArgument(int intDeviceId, int intArgumentIndex); - TELLUSBD101_API int WINAPI devGetNumberOfArguments(int intDeviceId); - TELLUSBD101_API bool WINAPI devSetArguments(int intDeviceId, const char* strArguments); - TELLUSBD101_API int WINAPI devAddDevice(); - TELLUSBD101_API bool WINAPI devRemoveDevice(int intDeviceId); - TELLUSBD101_API int WINAPI devGetDeviceId(int intDeviceIndex); - TELLUSBD101_API int WINAPI devMethods(int id); -} - -#endif diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj b/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj deleted file mode 100644 index c25d6338..00000000 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.vcproj +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/telldus-core/driver/bindings/CMakeLists.txt b/telldus-core/driver/bindings/CMakeLists.txt deleted file mode 100644 index 6127fb9d..00000000 --- a/telldus-core/driver/bindings/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ - -SET(BUILD_EXTENSION_JAVA FALSE CACHE BOOL "Build extension for Java") -IF(BUILD_EXTENSION_JAVA) - ADD_SUBDIRECTORY(java) -ENDIF(BUILD_EXTENSION_JAVA) - -# ADD_SUBDIRECTORY(php) - -SET(BUILD_EXTENSION_PYTHON FALSE CACHE BOOL "Build extension for Python") -IF(BUILD_EXTENSION_PYTHON) - ADD_SUBDIRECTORY(python) -ENDIF(BUILD_EXTENSION_PYTHON) - -# ADD_SUBDIRECTORY(ruby) - diff --git a/telldus-core/driver/bindings/java/CMakeLists.txt b/telldus-core/driver/bindings/java/CMakeLists.txt deleted file mode 100644 index 5ffcd261..00000000 --- a/telldus-core/driver/bindings/java/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ - -#### JAVA #### -FIND_PACKAGE(SWIG REQUIRED) -FIND_PACKAGE(Java) -FIND_PACKAGE(JNI) - -INCLUDE(${SWIG_USE_FILE}) - -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${JAVA_INCLUDE_PATH} ${JNI_INCLUDE_DIRS}) - -SET(CMAKE_SWIG_FLAGS "") - -SET_SOURCE_FILES_PROPERTIES(../tellduscore.i PROPERTIES CPLUSPLUS OFF) -SET_SOURCE_FILES_PROPERTIES(../tellduscore.i PROPERTIES SWIG_FLAGS "-includeall") - -SWIG_ADD_MODULE(tellduscore java ../tellduscore.i) -SWIG_LINK_LIBRARIES(tellduscore telldus-core ${JNI_LIBRARIES}) - diff --git a/telldus-core/driver/bindings/python/CMakeLists.txt b/telldus-core/driver/bindings/python/CMakeLists.txt deleted file mode 100644 index efbb153f..00000000 --- a/telldus-core/driver/bindings/python/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ - -#### PYTHON #### -FIND_PACKAGE(SWIG REQUIRED) -FIND_PACKAGE(PythonInterp) -FIND_PACKAGE(PythonLibs) - -INCLUDE(${SWIG_USE_FILE}) - -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${PYTHON_INCLUDE_PATH}) - -SET(CMAKE_SWIG_FLAGS "") - -SET_SOURCE_FILES_PROPERTIES(../tellduscore.i PROPERTIES CPLUSPLUS OFF) -SET_SOURCE_FILES_PROPERTIES(../tellduscore.i PROPERTIES SWIG_FLAGS "-includeall") - -SWIG_ADD_MODULE(tellduscore python ../tellduscore.i) -SWIG_LINK_LIBRARIES(tellduscore telldus-core ${PYTHON_LIBRARIES}) - -EXECUTE_PROCESS( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()" OUTPUT_VARIABLE PYTHON_SITE_PACKAGES OUTPUT_STRIP_TRAILING_WHITESPACE) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SWIG_MODULE_tellduscore_REAL_NAME}.so DESTINATION ${PYTHON_SITE_PACKAGES}) -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tellduscore.py DESTINATION ${PYTHON_SITE_PACKAGES}) - diff --git a/telldus-core/driver/bindings/tellduscore.i b/telldus-core/driver/bindings/tellduscore.i deleted file mode 100644 index 25203d39..00000000 --- a/telldus-core/driver/bindings/tellduscore.i +++ /dev/null @@ -1,6 +0,0 @@ -%module tellduscore -%{ -#include "../../libtelldus-core/telldus-core.h" -%} - -%include "../../libtelldus-core/telldus-core.h" diff --git a/telldus-core/driver/libtelldus-core/99-tellstick.rules b/telldus-core/driver/libtelldus-core/99-tellstick.rules deleted file mode 100644 index 0fd29965..00000000 --- a/telldus-core/driver/libtelldus-core/99-tellstick.rules +++ /dev/null @@ -1,2 +0,0 @@ -KERNEL=="ttyUSB*", BUS=="usb", SYSFS{idVendor}=="1781", SYSFS{idProduct}=="0c30", NAME="tellstick", GROUP="plugdev" - diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt deleted file mode 100644 index d20c6fc3..00000000 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ /dev/null @@ -1,232 +0,0 @@ -IF (BUILD_WITH_QT) - FIND_PACKAGE( Qt4 REQUIRED ) - SET( QT_DONT_USE_QTGUI TRUE ) - INCLUDE( ${QT_USE_FILE} ) -ENDIF (BUILD_WITH_QT) - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -######## Non configurable options ######## -SET( telldus-core_SRCS - Device.cpp - DeviceBrateck.cpp - DeviceEverflourish.cpp - DeviceFuhaote.cpp - DeviceGroup.cpp - DeviceIkea.cpp - DeviceSilvanChip.cpp - DeviceNexa.cpp - DeviceRisingSun.cpp - DeviceSartano.cpp - DeviceUndefined.cpp - DeviceUpm.cpp - DeviceWaveman.cpp - DeviceX10.cpp - Controller.cpp - Manager.cpp - Settings.cpp - TellStick.cpp - Thread.cpp - telldus-core.cpp - ) - -SET( telldus-core_HDRS - telldus-core.h - telldus-core-service.h -) - -IF (BUILD_WITH_QT) - QT4_WRAP_CPP( telldus-core_MOC_SRCS ${telldus-core_MOC_HDRS} ) - QT4_AUTOMOC ( ${telldus-core_SRCS} ) - - SET( telldus-core_LIBRARIES - ${QT_LIBRARIES} - ) -ENDIF (BUILD_WITH_QT) - -IF (SUPPORT_USB) - OPTION(USE_FTD2XX_RATHER_THEN_LIBFTDI "Link against ftd2xx even if libftdi is the preferred one" OFF) - IF (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) - FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) - SET( telldus-core_LIBRARIES - ${telldus-core_LIBRARIES} - ${FTD2XX_LIBRARY} - ) - ADD_DEFINITIONS( -DLIBFTD2XX ) - ELSE (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) - FIND_LIBRARY(FTDI_LIBRARY ftdi) - SET( telldus-core_LIBRARIES - ${telldus-core_LIBRARIES} - ${FTDI_LIBRARY} - ) - ADD_DEFINITIONS( -DLIBFTDI ) - ENDIF (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) -ENDIF (SUPPORT_USB) - - -######## Configurable options for the platform ######## - -#### TellStickDuo #### -IF (SUPPORT_TELLSTICK_DUO) - ADD_DEFINITIONS( -DTELLSTICK_DUO ) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - TellStickDuo.cpp - ) -ENDIF(SUPPORT_TELLSTICK_DUO) - -#### Settings backend #### -IF(USE_QT_SETTINGS_BACKEND) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - SettingsQt.cpp - ) -ELSE (USE_QT_SETTINGS_BACKEND) - IF (APPLE) - FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) - - SET( telldus-core_LIBRARIES - ${telldus-core_LIBRARIES} - ${COREFOUNDATION_LIBRARY} - ) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - SettingsCoreFoundationPreferences.cpp - ) - ELSEIF (WIN32) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - SettingsWinRegistry.cpp - ) - ELSE (APPLE) - SET( telldus-core_LIBRARIES - ${telldus-core_LIBRARIES} - confuse - ) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - SettingsConfuse.cpp - ) - ADD_DEFINITIONS( -D_CONFUSE ) - ENDIF (APPLE) -ENDIF(USE_QT_SETTINGS_BACKEND) - - - -######## Platforms-specific, non configurable ######## - -IF (APPLE) - #### Mac OS X #### - IF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_TARGET TelldusCoreLib ) - ELSE(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_TARGET TelldusCore ) - ENDIF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - win/Device.cpp - ) - ADD_DEFINITIONS( - -D_MACOSX - ) -ELSEIF (WIN32) - #### Windows #### - IF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_TARGET TelldusCoreLib ) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - ${FTD2XX_LIBRARY} - ) - ELSE(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_TARGET TelldusCore ) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - libtelldus-core.def - ) - ENDIF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - - SET( telldus-core_SRCS - ${telldus-core_SRCS} - win/Device.cpp - ) - ADD_DEFINITIONS( - -D_WINDOWS - -DTELLDUSCORE_EXPORTS - ) -ELSE (APPLE) - #### Linux #### - IF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_TARGET telldus-core-lib ) - ELSE(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_TARGET telldus-core ) - ENDIF(BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - linux/Device.cpp - ) - ADD_DEFINITIONS( - -D_LINUX - ) -ENDIF (APPLE) - - - -######## Configuring ######## - -SET(TYPE "SHARED") -IF (BUILD_LIBTELLDUS-CORE_AS_SERVICE) - SET(TYPE "STATIC") -ENDIF (BUILD_LIBTELLDUS-CORE_AS_SERVICE) - -ADD_LIBRARY(${telldus-core_TARGET} ${TYPE} - ${telldus-core_SRCS} - ${telldus-core_HDRS} -) - -TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) - -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY FRAMEWORK TRUE -) -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY PUBLIC_HEADER ${telldus-core_HDRS} -) - -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY VERSION ${PACKAGE_VERSION} -) -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY SOVERSION ${PACKAGE_SOVERSION} -) - -IF (NOT LIBRARY_DIR) - SET(LIBRARY_DIR "lib") -ENDIF (NOT LIBRARY_DIR) - -IF (UNIX) - INSTALL(TARGETS ${telldus-core_TARGET} - LIBRARY DESTINATION ${LIBRARY_DIR} - ARCHIVE DESTINATION ${LIBRARY_DIR} - FRAMEWORK DESTINATION "/Library/Frameworks" - PUBLIC_HEADER DESTINATION include - ) -ENDIF (UNIX) - -IF (UNIX AND NOT APPLE) - SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) - SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) - SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) - - INSTALL(FILES tellstick.conf - DESTINATION ${SYSCONF_INSTALL_DIR} - ) - INSTALL(FILES telldus-core.conf - DESTINATION ${STATE_INSTALL_DIR} - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE - ) - INSTALL(FILES 99-tellstick.rules - DESTINATION ${UDEV_RULES_DIR} - ) -ENDIF (UNIX AND NOT APPLE) diff --git a/telldus-core/driver/libtelldus-core/Controller.cpp b/telldus-core/driver/libtelldus-core/Controller.cpp deleted file mode 100644 index 04d6225e..00000000 --- a/telldus-core/driver/libtelldus-core/Controller.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// -// C++ Implementation: controller -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "Controller.h" - -using namespace TelldusCore; - -Controller::Controller() -{ -} - - -Controller::~Controller() -{ -} - - diff --git a/telldus-core/driver/libtelldus-core/Controller.h b/telldus-core/driver/libtelldus-core/Controller.h deleted file mode 100644 index 500b8d56..00000000 --- a/telldus-core/driver/libtelldus-core/Controller.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// C++ Interface: controller -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef CONTROLLER_H -#define CONTROLLER_H - -#include - -/** - @author Micke Prag -*/ -namespace TelldusCore { - class Controller { - public: - virtual ~Controller(); - - virtual int firmwareVersion() = 0; - virtual int send( const std::string &message ) = 0; - - protected: - Controller(); - }; -} - -#endif diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp deleted file mode 100644 index e969831f..00000000 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "Device.h" -#include "Manager.h" -#include - -using namespace TelldusCore; -/* -* Constructor -*/ -Device::Device(int id, const std::string m, const std::string &name) - : deviceId(id), - deviceName(name), - model(m) -{ -} - -/* -* Destructor -*/ -Device::~Device(void) { -} - -std::string Device::getModel() const { - std::string strModel = model; - //Strip anything after : if it is found - size_t pos = strModel.find(":"); - if (pos != std::string::npos) { - strModel = strModel.substr(0, pos); - } - - return strModel; -} - -std::string Device::getFullModel() const { - return model; -} - -bool Device::setModel( const std::string &strModel ) { - Manager *manager = Manager::getInstance(); - if (manager->setDeviceModel( deviceId, strModel )) { - model = strModel; - return true; - } - return false; -} - -bool Device::setParameter(const std::string &strName, const std::string &strValue) { - if (setDeviceParameter( strName, strValue )) { - Manager *manager = Manager::getInstance(); - return manager->setDeviceParameter(deviceId, strName, strValue); - } - return false; -} - -/* -* Turn on, virtual -*/ -int Device::turnOn(Controller *){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -/* -* Turn off, virtual -*/ -int Device::turnOff(Controller *){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -/* -* Bell, virtual -*/ -int Device::bell(Controller *){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -/* -* Dim, virtual -*/ -int Device::dim(unsigned char level, Controller *){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -int Device::learn(Controller *controller) { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -int Device::methodId( const std::string &methodName ) { - if (methodName.compare("turnon") == 0) { - return TELLSTICK_TURNON; - } - if (methodName.compare("turnoff") == 0) { - return TELLSTICK_TURNOFF; - } - if (methodName.compare("bell") == 0) { - return TELLSTICK_BELL; - } - if (methodName.compare("dim") == 0) { - return TELLSTICK_DIM; - } - return 0; -} - -std::string Device::getName() const { - return deviceName; -} - -bool Device::setName(const std::string & newName) { - Manager *manager = Manager::getInstance(); - if (manager->setDeviceName(deviceId, newName)) { - deviceName = newName; - return true; - } - return false; -} - -int TelldusCore::Device::maskUnsupportedMethods(int methods, int supportedMethods) { - // Bell -> On - if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) { - methods |= TELLSTICK_TURNON; - } - //Cut of the rest of the unsupported methods we don't have a fallback for - return methods & supportedMethods; -} diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h deleted file mode 100644 index 7c19f2ec..00000000 --- a/telldus-core/driver/libtelldus-core/Device.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "telldus-core.h" -#include "Controller.h" -#include -//#include - -namespace TelldusCore { - - class Device - { - public: - Device(int id, const std::string model, const std::string &name); - virtual ~Device(void); - -// int switchState( int newState, const std::string &value = "" ); - virtual int methods() = 0; - virtual std::string getProtocol() const = 0; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const = 0; - bool setParameter(const std::string &strName, const std::string &strValue); - - std::string getModel() const; - std::string getFullModel() const; - bool setModel( const std::string & strModel ); - std::string getName() const; - bool setName( const std::string &newName ); - - static int methodId( const std::string &methodName ); - static int maskUnsupportedMethods( int methods, int supportedMethods ); - - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int bell(Controller *controller); - virtual int dim(unsigned char level, Controller *controller); - virtual int learn(Controller *controller); - - #ifdef _LINUX - void setDevice(const std::string &device); - protected: - std::string strDevice; - #endif - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue) = 0; - int send(const std::string &strMessage); - - private: - int deviceId; - std::string deviceName, model; - // static QMutex deviceMutex; - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceBrateck.cpp b/telldus-core/driver/libtelldus-core/DeviceBrateck.cpp deleted file mode 100644 index 575c0257..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceBrateck.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "DeviceBrateck.h" -#include -#include -#include -#include - -using namespace TelldusCore; - -const char S = '!'; -const char L = 'V'; -const char B1[] = {L,S,L,S,0}; -const char BX[] = {S,L,L,S,0}; -const char B0[] = {S,L,S,L,0}; -const char BUP[] = {L,S,L,S,S,L,S,L,S,L,S,L,S,L,S,L,S,0}; -const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; -const char BDOWN[] = {S,L,S,L,S,L,S,L,S,L,S,L,L,S,L,S,S,0}; - -/* -* Constructor -*/ -DeviceBrateck::DeviceBrateck(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - - -DeviceBrateck::~DeviceBrateck(void) -{ -} - -bool DeviceBrateck::setHouse(const std::string &strNewHouse) { - strHouse = strNewHouse; - return true; -} - -bool DeviceBrateck::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("house") == 0) { - return setHouse(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceBrateck::turnOn(Controller *controller){ - - try{ - std::string strCode = getStringCode(); - - strCode.insert(0, "S"); - strCode.append(BUP); - strCode.append("+"); //the "turn on"-code! - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceBrateck::turnOff(Controller *controller){ - - try{ - std::string strCode = getStringCode(); - - strCode.insert(0, "S"); - strCode.append(BDOWN); - strCode.append("+"); //the "turn off"-code! - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -bool DeviceBrateck::parameterMatches( const std::string &name, const std::string &value ) const { - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceBrateck::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -std::string DeviceBrateck::getStringCode(void){ - - std::string strReturn; - - try{ - for( size_t i = 0; i < strHouse.length(); ++i ) { - if (strHouse[i] == '1') { - strReturn.insert(0, B1); - } else if (strHouse[i] == '-') { - strReturn.insert(0, BX); - } else if (strHouse[i] == '0') { - strReturn.insert(0, B0); - } - } - } - catch(...){ - throw; - } - return strReturn; - -} - -std::string DeviceBrateck::getProtocol() const { - return "brateck"; -} - diff --git a/telldus-core/driver/libtelldus-core/DeviceBrateck.h b/telldus-core/driver/libtelldus-core/DeviceBrateck.h deleted file mode 100644 index a014aa24..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceBrateck.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceBrateck : public Device - { - public: - DeviceBrateck(int id, const std::string &model, const std::string &name); - virtual ~DeviceBrateck(void); - - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &strNewHouse); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - - std::string getStringCode(void); - std::string strHouse; - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceEverflourish.cpp b/telldus-core/driver/libtelldus-core/DeviceEverflourish.cpp deleted file mode 100644 index 2bf0090a..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceEverflourish.cpp +++ /dev/null @@ -1,189 +0,0 @@ -#include "DeviceEverflourish.h" -#include "common.h" - -using namespace TelldusCore; - -const unsigned char ON = 15; -const unsigned char OFF = 0; -const unsigned char LEARN = 10; - -/* -* Constructor -*/ -DeviceEverflourish::DeviceEverflourish(int id, const std::string &model, const std::string &name) - :Device(id, model, name), - intHouse(0), - intCode(0) -{ -} - -/* -* Destructor -*/ -DeviceEverflourish::~DeviceEverflourish(void) -{} - -bool DeviceEverflourish::setHouse(const std::string &newHouse) { - if (newHouse.length() > 0) { - intHouse = atoi(newHouse.c_str()); - } else { - intHouse = 0; - } - if (intHouse < 0) { - intHouse = 0; - } else if (intHouse > 16383) { - intHouse = 16383; - } - return true; -} - -bool DeviceEverflourish::setUnit(const std::string &newUnit) { - if (newUnit.length() > 0) { - intCode = atoi(newUnit.c_str()) - 1; - } else { - intCode = 0; - } - if (intCode < 0) { - intCode = 0; - } else if (intCode > 3) { - intCode = 3; - } - return true; -} - -bool DeviceEverflourish::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("house") == 0) { - return setHouse(strValue); - } else if (strName.compare("unit") == 0) { - return setUnit(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceEverflourish::turnOn(Controller *controller){ - try{ - std::string strCode = getCode(ON); - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceEverflourish::turnOff(Controller *controller){ - try{ - std::string strCode = getCode(OFF); - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -int DeviceEverflourish::learn(Controller *controller){ - try{ - std::string strCode = getCode(LEARN); - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - - -bool DeviceEverflourish::parameterMatches( const std::string &name, const std::string &value ) const { - if (name.compare("house") == 0) { - return intHouse == atoi(value.c_str()); - } else if (name.compare("unit") == 0) { - return intCode == atoi(value.c_str()) - 1; - } - return true; -} - -/* -* Has the device got the method? -*/ -int DeviceEverflourish::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); -} - -std::string DeviceEverflourish::getProtocol() const { - return "everflourish"; -} - -std::string DeviceEverflourish::getCode(unsigned char action) { - unsigned int deviceCode = intHouse; - - const char ssss = 85; - const char sssl = 84; // 0 - const char slss = 69; // 1 - - const char bits[2] = {sssl,slss}; - int i, check; - - std::string strCode; - - deviceCode = (deviceCode << 2) | intCode; - - check = calculateChecksum(deviceCode); - - char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss,0}; - strCode.append(preamble); - - for(i=15;i>=0;i--) { - strCode.append(1, bits[(deviceCode>>i)&0x01]); - } - for(i=3;i>=0;i--) { - strCode.append(1, bits[(check>>i)&0x01]); - } - for(i=3;i>=0;i--) { - strCode.append(1, bits[(action>>i)&0x01]); - } - - strCode.append(1, ssss); - strCode.append(1, '+'); - - return strCode; -} - -// The calculation used in this function is provided by Frank Stevenson -unsigned int DeviceEverflourish::calculateChecksum(unsigned int x) { - unsigned int bits[16] = { - 0xf ,0xa ,0x7 ,0xe, - 0xf ,0xd ,0x9 ,0x1, - 0x1 ,0x2 ,0x4 ,0x8, - 0x3 ,0x6 ,0xc ,0xb - }; - unsigned int bit = 1; - unsigned int res = 0x5; - int i; - unsigned int lo,hi; - - if ((x&0x3)==3) { - lo = x & 0x00ff; - hi = x & 0xff00; - lo += 4; - if (lo>0x100) { - lo = 0x12; - } - x = lo | hi; - } - - for(i=0;i<16;i++) { - if (x&bit) { - res = res ^ bits[i]; - } - bit = bit << 1; - } - - return res; -} diff --git a/telldus-core/driver/libtelldus-core/DeviceEverflourish.h b/telldus-core/driver/libtelldus-core/DeviceEverflourish.h deleted file mode 100644 index 8daaddae..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceEverflourish.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef DEVICEEVERFLOURISH_H -#define DEVICEEVERFLOURISH_H - -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceEverflourish : public Device - { - public: - DeviceEverflourish(int id, const std::string &model, const std::string &name); - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &newHouse); - bool setUnit(const std::string &newUnit); - - public: - ~DeviceEverflourish(void); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int learn(Controller *controller); - - int intHouse; - int intCode; - - std::string getCode(unsigned char action); - static unsigned int calculateChecksum(unsigned int x); - }; - -} - -#endif //DEVICEEVERFLOURISH_H \ No newline at end of file diff --git a/telldus-core/driver/libtelldus-core/DeviceFuhaote.cpp b/telldus-core/driver/libtelldus-core/DeviceFuhaote.cpp deleted file mode 100644 index dcca1fff..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceFuhaote.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "DeviceFuhaote.h" -//#include -//#include -//#include -//#include - -using namespace TelldusCore; - -const char S = 19; -const char L = 58; -const char B0[] = {S,L,L,S,0}; -const char B1[] = {L,S,L,S,0}; -const char OFF[] = {S,L,S,L,S,L,L,S,0}; -const char ON[] = {S,L,L,S,S,L,S,L,0}; - -/* -* Constructor -*/ -DeviceFuhaote::DeviceFuhaote(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - - -DeviceFuhaote::~DeviceFuhaote(void) -{ -} - -bool DeviceFuhaote::setCode(const std::string &strNewCode) { - strCode = strNewCode; - return true; -} - -bool DeviceFuhaote::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("code") == 0) { - return setCode(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceFuhaote::turnOn(Controller *controller){ - - std::string strCode = "S"; - strCode.append(getStringCode()); - strCode.append(ON); - strCode.append(1, S); - strCode.append("+"); - - return controller->send(strCode); -} - -/* -* Turn off this device -*/ -int DeviceFuhaote::turnOff(Controller *controller){ - - std::string strCode = "S"; - strCode.append(getStringCode()); - strCode.append(OFF); - strCode.append(1, S); - strCode.append("+"); - - return controller->send(strCode); -} - -bool DeviceFuhaote::parameterMatches( const std::string &name, const std::string &value ) const { - if (name.compare("code") == 0 && value.compare(strCode) == 0) { - return true; - } - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceFuhaote::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -std::string DeviceFuhaote::getStringCode(void){ - - std::string strReturn; - - //House code - for(size_t i = 0; i < 5; ++i) { - if (strCode[i] == '0') { - strReturn.append(B0); - } else if (strCode[i] == '1') { - strReturn.append(B1); - } - } - //Unit code - for(size_t i = 5; i < 10; ++i) { - if (strCode[i] == '0') { - strReturn.append(B0); - } else if (strCode[i] == '1') { - strReturn.append(1, S); - strReturn.append(1, L); - strReturn.append(1, S); - strReturn.append(1, L); - } - } - return strReturn; - -} - -std::string DeviceFuhaote::getProtocol() const { - return "fuhaote"; -} - diff --git a/telldus-core/driver/libtelldus-core/DeviceFuhaote.h b/telldus-core/driver/libtelldus-core/DeviceFuhaote.h deleted file mode 100644 index 239aa840..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceFuhaote.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DEVICEFUHAOTE_H -#define DEVICEFUHAOTE_H - -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceFuhaote : public Device - { - public: - DeviceFuhaote(int id, const std::string &model, const std::string &name); - virtual ~DeviceFuhaote(void); - - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setCode(const std::string &strNewCode); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - - std::string getStringCode(void); - std::string strCode; - }; - -} - -#endif //DEVICEFUHAOTE_H \ No newline at end of file diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp deleted file mode 100644 index 2f9e76c3..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include - -#include "DeviceGroup.h" -#include "Manager.h" - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceGroup::DeviceGroup(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - -/* -* Destructor -*/ -DeviceGroup::~DeviceGroup(void) { -} - -bool DeviceGroup::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("devices") == 0) { - return setDevices(strValue); - } - return false; -} - -bool DeviceGroup::setDevices(const std::string &newDevices) { -/* if (strDevices.length() > 0) { - char *tempDevices = new char[strDevices.size()+1]; - #ifdef _WINDOWS - strcpy_s(tempDevices, strDevices.size()+1, strDevices.c_str()); - #else - strcpy(tempDevices, strDevices.c_str()); - #endif - - Manager *manager = Manager::getInstance(); - char *strToken = strtok(tempDevices, ","); - do { - int intDevice = atoi(strToken); - Device *device = manager->getDevice(intDevice); - if (device != NULL) { - deviceList.push_back( device ); - } - } while ( (strToken = strtok(NULL, ",")) != NULL ); - - free(tempDevices); - }*/ - return true; -} - -/* -* Turn on this device -*/ -int DeviceGroup::turnOn(void) { - int retVal = TELLSTICK_ERROR_UNKNOWN; - - /*for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(); - if (methods & TELLSTICK_TURNON) { - int success = (*it)->switchState( TELLSTICK_TURNON ); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - }*/ - return retVal; -} - -/* -* Turn off this device -*/ -int DeviceGroup::turnOff(void) { - int retVal = TELLSTICK_ERROR_UNKNOWN; - -/* for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(); - if (methods & TELLSTICK_TURNOFF) { - int success = (*it)->switchState( TELLSTICK_TURNOFF ); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - }*/ - return retVal; -} - -/* -* Send a bell -*/ -int DeviceGroup::bell(void){ - int retVal = TELLSTICK_ERROR_UNKNOWN; - -/* for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(); - if (methods & TELLSTICK_BELL) { - int success = (*it)->switchState( TELLSTICK_BELL ); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - }*/ - return retVal; -} - -/* -* Turn off this device -*/ -int DeviceGroup::dim(unsigned char level){ - int retVal = TELLSTICK_ERROR_UNKNOWN; - -/* for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(); - if (methods & TELLSTICK_DIM) { - int success = (*it)->switchState( TELLSTICK_DIM, (char*)&level); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - }*/ - return retVal; -} - -bool DeviceGroup::parameterMatches( const std::string &name, const std::string &value ) const { - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceGroup::methods(){ - int retVal = 0; - - for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - retVal = retVal | (*it)->methods(); - } - - return retVal; -} - -std::string DeviceGroup::getProtocol() const { - return "group"; -} - diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.h b/telldus-core/driver/libtelldus-core/DeviceGroup.h deleted file mode 100644 index b3b1583e..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include "Device.h" -#include -#include - -class Controller; - -namespace TelldusCore { - - typedef std::list DeviceList; - - class DeviceGroup : public Device - { - public: - DeviceGroup(int id, const std::string &model, const std::string &name); - ~DeviceGroup(void); - - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setDevices(const std::string &newDevices); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - - virtual int turnOn(void); - virtual int turnOff(void); - virtual int bell(void); - virtual int dim(unsigned char level); - - private: - DeviceList deviceList; - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp deleted file mode 100644 index aaa65e9f..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ /dev/null @@ -1,233 +0,0 @@ -// #include "StdAfx.h" //Needed? -#include "DeviceIkea.h" -#include -#include -#include -#include -#include - -#ifdef _WINDOWS -#define strcasecmp(x, y) _strcmpi(x, y) -#endif - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceIkea::DeviceIkea(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - -bool DeviceIkea::setSystem(const std::string &strSystem) { - if (strSystem.length() > 0) { - intSystem = atoi(strSystem.c_str()) - 1; - } else { - intSystem = 0; - } - return true; -} - -bool DeviceIkea::setUnits(const std::string &strUnits) { - if (strUnits.length() > 0) { - intUnits = 0; //Start without any units - - char *tempUnits = new char[strUnits.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); -#else - strcpy(tempUnits, strUnits.c_str()); -#endif - - char *strToken = strtok(tempUnits, ","); - do { - int intUnit = atoi(strToken); - if (intUnit == 10) { - intUnit = 0; - } - intUnits = intUnits | ( 1<<(9-intUnit) ); - } while ( (strToken = strtok(NULL, ",")) != NULL ); - - free(tempUnits); - } - return true; -} - -bool DeviceIkea::setFade(const std::string &strFadeStyle) { - if (strFadeStyle.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { - intFadeStyle = 1; - } else { - intFadeStyle = 0; - } - return true; -} - -/* -* Destructor -*/ -DeviceIkea::~DeviceIkea(void) -{ - intSystem = -1; - intUnits = -1; - intFadeStyle = -1; -} - -bool DeviceIkea::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("system") == 0) { - return setSystem(strValue); - } else if (strName.compare("units") == 0) { - return setUnits(strValue); - } else if (strName.compare("fade") == 0) { - return setFade(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceIkea::turnOn(Controller *controller){ - try{ - std::string strMessage = getStringCode(255); - - return controller->send(strMessage); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceIkea::turnOff(Controller *controller){ - try{ - std::string strMessage = getStringCode(0); - - return controller->send(strMessage); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceIkea::dim(unsigned char level, Controller *controller){ - try{ - std::string strMessage = getStringCode(level); - - return controller->send(strMessage); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Convert an integer to byte string where 0 is represented by ª and 1 by TT -*/ -std::string DeviceIkea::getStringCode(unsigned char level){ - - std::string strReturn = "STTTTTTª"; //Startcode, always like this; - - try{ - std::string strChannels = ""; - int intCode = (intSystem << 10) | intUnits; - int checksum1 = 0; - int checksum2 = 0; - for (int i = 13; i >= 0; --i) { - if ((intCode>>i) & 1) { - strChannels.append("TT"); - if (i % 2 == 0) - checksum2++; - else - checksum1++; - } else { - strChannels.append("ª"); - } - } - strReturn.append(strChannels); //System + Units - - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum - - int intLevel = 0; - if (level <= 12) { - intLevel = 10; // Level 10 is actually off - } else if (level <= 37) { - intLevel = 1; - } else if (level <= 62) { - intLevel = 2; - } else if (level <= 87) { - intLevel = 3; - } else if (level <= 112) { - intLevel = 4; - } else if (level <= 137) { - intLevel = 5; - } else if (level <= 162) { - intLevel = 6; - } else if (level <= 187) { - intLevel = 7; - } else if (level <= 212) { - intLevel = 8; - } else if (level <= 237) { - intLevel = 9; - } else { - intLevel = 0; // Level 0 is actually full on - } - - int intFade = 0; - if (intFadeStyle == 1) { - intFade = 11 << 4; //Smooth - } else { - intFade = 1 << 4; //Instant - } - - intCode = intLevel | intFade; //Concat level and fade - - checksum1 = 0; - checksum2 = 0; - for (int i = 0; i < 6; ++i) { - if ((intCode>>i) & 1) { - strReturn.append("TT"); - if (i % 2 == 0) - checksum1++; - else - checksum2++; - } else { - strReturn.append("ª"); - } - } - - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum - - strReturn.append("+"); - } - catch(...){ - throw; - } - return strReturn; - -} - -bool DeviceIkea::parameterMatches( const std::string &name, const std::string &value ) const { - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceIkea::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); -} - -std::string DeviceIkea::getProtocol() const { - return "ikea"; -} diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h deleted file mode 100644 index cc671c96..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceIkea : public Device - { - public: - DeviceIkea(int id, const std::string &model, const std::string &name); - virtual ~DeviceIkea(void); - - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setSystem(const std::string &strSystem); - bool setUnits(const std::string &strUnits); - bool setFade(const std::string &strFade); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int dim(unsigned char level, Controller *controller); - - int intSystem; - int intUnits; - int intFadeStyle; - std::string getStringCode(unsigned char); - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp deleted file mode 100644 index 6a03a60f..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ /dev/null @@ -1,299 +0,0 @@ -// #include "StdAfx.h" -#include "DeviceNexa.h" -#include -#include -#include -#include -#include -#include "common.h" - -using namespace TelldusCore; - -const char START[] = {'T',127,255,24,1,0}; -//const char START[] = {'T',130,255,26,24,0}; - -/* -* Constructor -*/ -DeviceNexa::DeviceNexa(int id, const std::string &model, const std::string &name) - :Device(id, model, name), - intHouse(0), - intCode(0) -{ -} - -/* -* Destructor -*/ -DeviceNexa::~DeviceNexa(void) -{} - -bool DeviceNexa::setHouse(const std::string &newHouse) { - int house = atoi(newHouse.c_str()); - if (newHouse.length() == 1 && house == 0) { //Codeswitch - intHouse = newHouse[0] - 'A'; - } else { //Selflearning - intHouse = house; - } - return true; -} - -bool DeviceNexa::setUnit(const std::string &newUnit) { - if (newUnit.length() > 0) { - intCode = atoi(newUnit.c_str()) - 1; - } else { - intCode = 0; - } - return true; -} - -bool DeviceNexa::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("house") == 0) { - return setHouse(strValue); - } else if (strName.compare("unit") == 0) { - return setUnit(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceNexa::turnOn(Controller *controller){ - if (strcasecmp(this->getModel().c_str(), "bell") == 0) { - return bell(controller); - } - try{ - std::string strCode = ""; - if (isDimmer()) { - return dim(255, controller); - } else if (isSelflearning()) { - strCode.append( 1, 'R' ); - strCode.append( 1, 5 ); - strCode.append(getStringSelflearning(false, 255)); - } else { - strCode.append("S"); - strCode.append(getStringCodeSwitch(intHouse)); - strCode.append(getStringCodeSwitch(intCode)); - strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time - } - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceNexa::turnOff(Controller *controller){ - - try{ - std::string strCode = ""; - if (isSelflearning()) { - strCode.append( 1, 'R' ); - strCode.append( 1, 5 ); - strCode.append(getStringSelflearning(false, 0)); - } else { - strCode.append("S"); - strCode.append(getStringCodeSwitch(intHouse)); - strCode.append(getStringCodeSwitch(intCode)); - strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - } - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Dim this device -*/ -int DeviceNexa::dim(unsigned char level, Controller *controller) { - try{ - std::string strMessage = ""; - strMessage.append( 1, 'R' ); - strMessage.append( 1, 5 ); - strMessage.append(getStringSelflearning(true, level)); - return controller->send(strMessage); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - - -/* -* Send a bell -*/ -int DeviceNexa::bell(Controller *controller){ - - try{ - std::string strCode = getStringCodeSwitch(intHouse); - - strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time - strCode.insert(0, "S"); - strCode.append("$kk$$kk$$kk$$kk$$k+"); //the "bell"-code, keeps it like this, doesn't have to be regenerated each time - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -int DeviceNexa::learn(Controller *controller){ - std::string strCode = ""; - strCode.append( 1, 'R' ); - strCode.append( 1, 2 ); - strCode.append(getStringSelflearning(false, 255)); - - int retVal = 0; - for (int i = 0; i < 5; ++i) { - retVal = controller->send(strCode); - if (retVal != TELLSTICK_SUCCESS) { - return retVal; - } - msleep(200); - } - return retVal; -} - -/* -* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed -*/ -std::string DeviceNexa::getStringCodeSwitch(int intToConvert){ - - std::string strReturn = ""; - - try{ - for( int i = 0; i < 4; ++i ) { - if (intToConvert & 1) { //Convert 1 - strReturn.append("$kk$"); - } else { //Convert 0 - strReturn.append("$k$k"); - } - intToConvert >>= 1; - - } - } - catch(...){ - throw; - } - return strReturn; - -} - -std::string DeviceNexa::getStringSelflearning(bool dim, unsigned char level) { - std::string strMessage = START; - strMessage.append(1,(dim ? 147 : 132)); //Number of pulses - - std::string m; - for (int i = 25; i >= 0; --i) { - m.append( intHouse & 1 << i ? "10" : "01" ); - } - m.append("01"); //Group - - //On/off - if (dim) { - m.append("00"); - } else if (level == 0) { - m.append("01"); - } else { - m.append("10"); - } - - for (int i = 3; i >= 0; --i) { - m.append( intCode & 1 << i ? "10" : "01" ); - } - - if (dim) { - unsigned char newLevel = level/16; - for (int i = 3; i >= 0; --i) { - m.append(newLevel & 1 << i ? "10" : "01"); - } - } - - //The number of data is odd. - //Add this to make it even, otherwise the following loop will not work - m.append("0"); - - unsigned char code = 9; //b1001, startcode - for (unsigned int i = 0; i < m.length(); ++i) { - code <<= 4; - if (m[i] == '1') { - code |= 8; //b1000 - } else { - code |= 10; //b1010 -// code |= 11; //b1011 - } - if (i % 2 == 0) { - strMessage.append(1,code); - code = 0; - } - } - strMessage.append("+"); - -// for( int i = 0; i < strMessage.length(); ++i ) { -// printf("%i,", (unsigned char)strMessage[i]); -// } -// printf("\n"); - return strMessage; -} - -bool DeviceNexa::parameterMatches( const std::string &name, const std::string &value ) const { - if (name.compare("house") == 0) { - if (isSelflearning()) { - return intHouse == atoi(value.c_str()); - } - return intHouse == value[0] - 'A'; - } else if (name.compare("unit") == 0) { - return intCode == atoi(value.c_str()) - 1; - } else if (name.compare("type") == 0) { - if (isSelflearning()) { - return (value.compare("selflearning") == 0); - } - } - return true; -} - -/* -* Has the device got the method? -*/ -int DeviceNexa::methods(){ - std::string strModel = this->getModel(); - - if ( strcasecmp(strModel.c_str(), "codeswitch") == 0 ) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); - - } else if (strcasecmp(strModel.c_str(), "selflearning-switch") == 0) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); - - } else if (strcasecmp(strModel.c_str(), "selflearning-dimmer") == 0) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); - - } else if (strcasecmp(strModel.c_str(), "bell") == 0) { - return TELLSTICK_BELL; - } - return 0; -} - -bool DeviceNexa::isSelflearning() const { - return strncasecmp(getModel().c_str(), "selflearning", 12) == 0; -} - -bool DeviceNexa::isDimmer() const { - return strcasecmp(getModel().c_str(), "selflearning-dimmer") == 0; -} - -std::string DeviceNexa::getProtocol() const { - return "arctech"; -} diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h deleted file mode 100644 index 006c755b..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceNexa : public Device - { - public: - DeviceNexa(int id, const std::string &model, const std::string &name); - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &newHouse); - bool setUnit(const std::string &newUnit); - - public: - ~DeviceNexa(void); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int dim(unsigned char level, Controller *controller); - virtual int bell(Controller *controller); - virtual int learn(Controller *controller); - - bool isSelflearning() const; - bool isDimmer() const; - - int intHouse; - int intCode; - std::string getStringCodeSwitch(int); - std::string getStringSelflearning(bool dim, unsigned char level); - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceRisingSun.cpp b/telldus-core/driver/libtelldus-core/DeviceRisingSun.cpp deleted file mode 100644 index 6539bf0e..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceRisingSun.cpp +++ /dev/null @@ -1,219 +0,0 @@ -// #include "StdAfx.h" -#include "DeviceRisingSun.h" -#include -#include -#include -#include -#include -#include "common.h" - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceRisingSun::DeviceRisingSun(int id, const std::string &model, const std::string &name) - :Device(id, model, name), - intHouse(0), - intCode(0) -{ -} - -/* -* Destructor -*/ -DeviceRisingSun::~DeviceRisingSun(void) -{} - -bool DeviceRisingSun::setHouse(const std::string &newHouse) { - if (newHouse.length() > 0) { - intHouse = atoi(newHouse.c_str()) - 1; - } else { - intHouse = 0; - } - return true; -} - -bool DeviceRisingSun::setUnit(const std::string &newUnit) { - if (newUnit.length() > 0) { - intCode = atoi(newUnit.c_str()) - 1; - } else { - intCode = 0; - } - return true; -} - -bool DeviceRisingSun::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("house") == 0) { - return setHouse(strValue); - } else if (strName.compare("unit") == 0) { - return setUnit(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceRisingSun::turnOn(Controller *controller){ - - try{ - if (isSelflearning()) { - return controller->send(getStringSelflearning(true)); - - } else { - std::string strCode = getStringCodeswitch(intHouse); - std::string strUnit = getStringCodeswitch(intCode); - strCode.append(strUnit); - - strCode.insert(0, "S.e"); - strCode.append("e..ee..ee..ee..e+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time - - return controller->send(strCode); - } - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceRisingSun::turnOff(Controller *controller){ - - try{ - if (isSelflearning()) { - return controller->send(getStringSelflearning(false)); - - } else { - std::string strCode = getStringCodeswitch(intHouse); - std::string strUnit = getStringCodeswitch(intCode); - strCode.append(strUnit); - - strCode.insert(0, "S.e"); - strCode.append("e..ee..ee..e.e.e+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - - return controller->send(strCode); - } - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -int DeviceRisingSun::learn(Controller *controller){ - std::string strCode = "R"; - strCode.append( 1, 50 ); - strCode.append(getStringSelflearning(true)); - return controller->send(strCode); -} - -/* -* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed -*/ -std::string DeviceRisingSun::getStringCodeswitch(int intToConvert){ - - std::string strReturn = ""; - - try{ - for(int i = 0; i < 4; ++i) { - if (i == intToConvert) { - strReturn.append( ".e.e" ); - } else { - strReturn.append( "e..e" ); - } - } - } - catch(...){ - throw; - } - return strReturn; - -} - -std::string DeviceRisingSun::getStringSelflearning(bool on){ - const char code_on[][7] = { - "110110", "001110", "100110", "010110", - "111001", "000101", "101001", "011001", - "110000", "001000", "100000", "010000", - "111100", "000010", "101100", "011100" - }; - const char code_off[][7] = { - "111110", "000001", "101110", "011110", - "110101", "001101", "100101", "010101", - "111000", "000100", "101000", "011000", - "110010", "001010", "100010", "010010" - }; - const char l = 120; - const char s = 51; - - std::string strCode = "10"; - int code = intCode; - code = (code < 0 ? 0 : code); - code = (code > 15 ? 15 : code); - if (on) { - strCode.append(code_on[code]); - } else { - strCode.append(code_off[code]); - } - - int house = intHouse; - for(int i = 0; i < 25; ++i) { - if (house & 1) { - strCode.append(1, '1'); - } else { - strCode.append(1, '0'); - } - house >>= 1; - } - - std::string strReturn; - for(unsigned int i = 0; i < strCode.length(); ++i) { - if (strCode[i] == '1') { - strReturn.append(1, l); - strReturn.append(1, s); - } else { - strReturn.append(1, s); - strReturn.append(1, l); - } - } - - std::string prefix = "P"; - prefix.append(1, 5); - prefix.append("S"); - strReturn.insert(0, prefix); - strReturn.append(1, '+'); - return strReturn; -} - -bool DeviceRisingSun::parameterMatches( const std::string &name, const std::string &value ) const { - if (value.length() == 0) { - return false; - } - - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceRisingSun::methods() { - std::string strModel = this->getModel(); - - if (strcasecmp(strModel.c_str(), "selflearning") == 0) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); - } - - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -std::string DeviceRisingSun::getProtocol() const { - return "risingsun"; -} - -bool DeviceRisingSun::isSelflearning() const { - return (strcasecmp(getModel().c_str(), "selflearning") == 0); -} diff --git a/telldus-core/driver/libtelldus-core/DeviceRisingSun.h b/telldus-core/driver/libtelldus-core/DeviceRisingSun.h deleted file mode 100644 index c35471ff..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceRisingSun.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceRisingSun : public Device - { - public: - DeviceRisingSun(int id, const std::string &model, const std::string &name); - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &newHouse); - bool setUnit(const std::string &newUnit); - - public: - ~DeviceRisingSun(void); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int learn(Controller *controller); - - int intHouse; - int intCode; - bool isSelflearning() const; - - std::string getStringCodeswitch(int); - std::string getStringSelflearning(bool on); - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp deleted file mode 100644 index 1eeedbd3..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "DeviceSartano.h" -#include "DeviceNexa.h" -#include -#include -#include -#include - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceSartano::DeviceSartano(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - - -DeviceSartano::~DeviceSartano(void) -{ -} - -bool DeviceSartano::setCode(const std::string &strNewCode) { - strCode = strNewCode; - return true; -} - -bool DeviceSartano::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("code") == 0) { - return setCode(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceSartano::turnOn(Controller *controller){ - - try{ - std::string strCode = getStringCode(); - - strCode.insert(0, "S"); - strCode.append("$k$k$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceSartano::turnOff(Controller *controller){ - - try{ - std::string strCode = getStringCode(); - - strCode.insert(0, "S"); - strCode.append("$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -bool DeviceSartano::parameterMatches( const std::string &name, const std::string &value ) const { - if (name.compare("code") == 0 && value.compare(strCode) == 0) { - return true; - } - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceSartano::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -/* -* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed -*/ -std::string DeviceSartano::getStringCode(void){ - - std::string strReturn = strCode; - - try{ - size_t intPos = strReturn.find("0"); - while (intPos < std::string::npos){ - strReturn.replace(intPos, 1, "$kk$"); - intPos = strReturn.find("0", intPos + 1); - } - - intPos = strReturn.find("1"); - while (intPos < std::string::npos){ - strReturn.replace(intPos, 1, "$k$k"); - intPos = strReturn.find("1", intPos + 1); - } - } - catch(...){ - throw; - } - return strReturn; - -} - -std::string DeviceSartano::getProtocol() const { - return "sartano"; -} - diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h deleted file mode 100644 index bb4957f7..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceSartano : public Device - { - public: - DeviceSartano(int id, const std::string &model, const std::string &name); - virtual ~DeviceSartano(void); - - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setCode(const std::string &strNewCode); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - - std::string getStringCode(void); - std::string strCode; - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceSilvanChip.cpp b/telldus-core/driver/libtelldus-core/DeviceSilvanChip.cpp deleted file mode 100644 index adf040db..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceSilvanChip.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "DeviceSilvanChip.h" -#include "TellStick.h" -#include - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceSilvanChip::DeviceSilvanChip(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - - -DeviceSilvanChip::~DeviceSilvanChip(void) -{ -} - -bool DeviceSilvanChip::setHouse(const std::string &strNewHouse) { - intHouse = atoi(strNewHouse.c_str()); - return true; -} - -bool DeviceSilvanChip::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("house") == 0) { - return setHouse(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceSilvanChip::turnOn(Controller *controller){ - - std::string strCode = getStringCode(controller, TELLSTICK_TURNON); - - return controller->send(strCode); -} - -/* -* Turn off this device -*/ -int DeviceSilvanChip::turnOff(Controller *controller){ - std::string strCode = getStringCode(controller, TELLSTICK_TURNOFF); - - return controller->send(strCode); -} - -int DeviceSilvanChip::learn(Controller *controller) { - std::string strCode = getStringCode(controller, TELLSTICK_LEARN); - - return controller->send(strCode); -} - -bool DeviceSilvanChip::parameterMatches( const std::string &name, const std::string &value ) const { - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceSilvanChip::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); -} - -std::string DeviceSilvanChip::getStringCode(Controller *controller, int method){ - - std::string times = "\255\1\200\100"; - const unsigned char S = '3'; - const unsigned char L = '0'; - const std::string LONG = "012"; - - const std::string ONE = LONG + "3"; - const std::string ZERO = "3" + LONG; - std::string strReturn; - - strReturn.append(1, S); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, L); - strReturn.append(1, '1'); - strReturn.append(1, S); - - for( int i = 19; i >= 0; --i ) { - if (intHouse & (1 << i)) { - strReturn.append(ONE); - } else { - strReturn.append(ZERO); - } - } - - if (method == TELLSTICK_TURNON) { - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ONE); - strReturn.append(ZERO); - } else if (method == TELLSTICK_LEARN) { - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ONE); - } else { - strReturn.append(ONE); - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ZERO); - } - - strReturn.append(ZERO); - - return TellStick::convertSToT( 255, 1, 200, 100, strReturn); - -} - -std::string DeviceSilvanChip::getProtocol() const { - return "silvanchip"; -} - diff --git a/telldus-core/driver/libtelldus-core/DeviceSilvanChip.h b/telldus-core/driver/libtelldus-core/DeviceSilvanChip.h deleted file mode 100644 index ebc07304..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceSilvanChip.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceSilvanChip : public Device - { - public: - DeviceSilvanChip(int id, const std::string &model, const std::string &name); - virtual ~DeviceSilvanChip(void); - - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &strNewHouse); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int learn(Controller *controller); - - std::string getStringCode(Controller *controller, int method); - int intHouse; - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceUndefined.cpp b/telldus-core/driver/libtelldus-core/DeviceUndefined.cpp deleted file mode 100644 index 3e96b4bf..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceUndefined.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "DeviceUndefined.h" - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceUndefined::DeviceUndefined(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - -/* -* Destructor -*/ -DeviceUndefined::~DeviceUndefined(void) -{} - -bool DeviceUndefined::setDeviceParameter(const std::string &strName, const std::string &strValue) { - return true; -} - -bool DeviceUndefined::parameterMatches( const std::string &name, const std::string &value ) const { - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceUndefined::methods(){ - return 0; -} - -std::string DeviceUndefined::getProtocol() const { - return "undefined"; -} diff --git a/telldus-core/driver/libtelldus-core/DeviceUndefined.h b/telldus-core/driver/libtelldus-core/DeviceUndefined.h deleted file mode 100644 index 766b9021..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceUndefined.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceUndefined : public Device - { - public: - DeviceUndefined(int id, const std::string &model, const std::string &name); - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - public: - ~DeviceUndefined(void); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceUpm.cpp b/telldus-core/driver/libtelldus-core/DeviceUpm.cpp deleted file mode 100644 index 26ebaeeb..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceUpm.cpp +++ /dev/null @@ -1,173 +0,0 @@ -#include "DeviceUpm.h" -#include -#include -#include -#include - -using namespace TelldusCore; - -const char S = ';'; -const char L = '~'; -const char START[] = {S,0}; -const char B1[] = {L,S,0}; -const char B0[] = {S,L,0}; -const char BON[] = {S,L,L,S,0}; -const char BOFF[] = {S,L,S,L,0}; - -/* -* Constructor -*/ -DeviceUpm::DeviceUpm(int id, const std::string &model, const std::string &name) - :Device(id, model, name) -{ -} - - -DeviceUpm::~DeviceUpm(void) -{ -} - -bool DeviceUpm::setHouse(const std::string &strHouse) { - if (strHouse.length() > 0) { - intHouse = atoi(strHouse.c_str()); - } else { - intHouse = 0; - } - return true; -} - -bool DeviceUpm::setUnit(const std::string &strUnit) { - if (strUnit.length() > 0) { - intUnit = atoi(strUnit.c_str()) - 1; - } else { - intUnit = 0; - } - if (intUnit < 0) { - intUnit = 0; - } else if (intUnit > 3) { - intUnit = 3; - } - return true; -} - -bool DeviceUpm::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("house") == 0) { - return setHouse(strValue); - } - if (strName.compare("unit") == 0) { - return setUnit(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceUpm::turnOn(Controller *controller){ - - try{ - std::string strCode = getStringCode(true); - - strCode.insert(0, "S"); - strCode.append("+"); //the "turn on"-code! - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceUpm::turnOff(Controller *controller){ - - try{ - std::string strCode = getStringCode(false); - - strCode.insert(0, "S"); - strCode.append("+"); //the "turn off"-code! - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -bool DeviceUpm::parameterMatches( const std::string &name, const std::string &value ) const { - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceUpm::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -std::string DeviceUpm::getStringCode(bool on){ - - std::string strReturn; - - try{ - int code = intHouse; - for( size_t i = 0; i < 12; ++i ) { - if (code & 1) { - strReturn.insert(0, B1); - } else { - strReturn.insert(0, B0); - } - code >>= 1; - } - strReturn.insert(0, START); //Startcode, first - - code = 0; - if (on) { - code += 2; - } - code <<= 2; - code += intUnit; - - int check1 = 0, check2 = 0; - for( size_t i = 0; i < 6; ++i ) { - if (code & 1) { - if (i % 2 == 0) { - check1++; - } else { - check2++; - } - } - if (code & 1) { - strReturn.append(B1); - } else { - strReturn.append(B0); - } - code >>= 1; - } - - if (check1 % 2 == 0) { - strReturn.append(B0); - } else { - strReturn.append(B1); - } - if (check2 % 2 == 0) { - strReturn.append(B0); - } else { - strReturn.append(B1); - } - } - catch(...){ - throw; - } - return strReturn; - -} - -std::string DeviceUpm::getProtocol() const { - return "upm"; -} - diff --git a/telldus-core/driver/libtelldus-core/DeviceUpm.h b/telldus-core/driver/libtelldus-core/DeviceUpm.h deleted file mode 100644 index ecc6f0aa..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceUpm.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceUpm : public Device - { - public: - DeviceUpm(int id, const std::string &model, const std::string &name); - virtual ~DeviceUpm(void); - - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &strHouse); - bool setUnit(const std::string &strUnit); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - - std::string getStringCode(bool on); - int intHouse, intUnit; - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp deleted file mode 100644 index 5d99f7d6..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// #include "StdAfx.h" -#include "DeviceWaveman.h" -#include -#include -#include -#include -#include - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceWaveman::DeviceWaveman(int id, const std::string &model, const std::string &name) - :DeviceNexa(id, model, name){ -} - -/* -* Turn off this device -*/ -int DeviceWaveman::turnOff(Controller *controller){ - - try{ - std::string strCode = getStringCodeSwitch(intHouse); - std::string strUnit = getStringCodeSwitch(intCode); - strCode.append(strUnit); - - strCode.insert(0, "S"); - strCode.append("$k$k$k$k$k$k$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Has the device got the method? -*/ -int DeviceWaveman::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -std::string DeviceWaveman::getProtocol() const { - return "waveman"; -} diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h deleted file mode 100644 index 4882c209..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include "DeviceNexa.h" -#include - -namespace TelldusCore { - - class DeviceWaveman : public DeviceNexa - { - public: - DeviceWaveman(int id, const std::string &model, const std::string &name); - virtual int methods(); - virtual std::string getProtocol() const; - - protected: - virtual int turnOff(Controller *controller); - }; - -} diff --git a/telldus-core/driver/libtelldus-core/DeviceX10.cpp b/telldus-core/driver/libtelldus-core/DeviceX10.cpp deleted file mode 100644 index d96eeb17..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceX10.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#include "DeviceX10.h" -#include -#include -#include -#include -#include - -using namespace TelldusCore; - -const char S = 59, L = 169; -const char B0[] = {S,S,0}; -const char B1[] = {S,L,0}; -const int HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; -const char START_CODE[] = {255,1,255,1,255,1,100,255,1,180,0}; -const char STOP_CODE[] = {S,0}; - -/* -* Constructor -*/ -DeviceX10::DeviceX10(int id, const std::string &model, const std::string &name) - :Device(id, model, name), - intHouse(0), - intCode(0) -{ -} - -/* -* Destructor -*/ -DeviceX10::~DeviceX10(void) -{} - -bool DeviceX10::setHouse(const std::string &newHouse) { - int house = 0; - if (newHouse.length() > 0) { - house = newHouse[0] - 'A'; - } - if (house > 15) { - house = 15; - } else if (house < 0) { - house = 0; - } - intHouse = HOUSES[house]; - return true; -} - -bool DeviceX10::setUnit(const std::string &newUnit) { - if (newUnit.length() > 0) { - intCode = atoi(newUnit.c_str()) - 1; - } else { - intCode = 0; - } - return true; -} - -bool DeviceX10::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("house") == 0) { - return setHouse(strValue); - } else if (strName.compare("unit") == 0) { - return setUnit(strValue); - } - return false; -} - -/* -* Turn on this device -*/ -int DeviceX10::turnOn(Controller *controller){ - - try{ - std::string strCode = getStringCode(true); - - strCode.insert(0, "S"); - strCode.append("+"); - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/* -* Turn off this device -*/ -int DeviceX10::turnOff(Controller *controller){ - - try{ - std::string strCode = getStringCode(false); - - strCode.insert(0, "S"); - strCode.append("+"); - - return controller->send(strCode); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - -std::string DeviceX10::getStringCode(bool on){ - - std::string strReturn = START_CODE; - std::string strComplement = ""; - - try{ - int house = intHouse; - for( int i = 0; i < 4; ++i ) { - if (house & 1) { - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - house >>= 1; - } - strReturn.append( B0 ); - strComplement.append( B1 ); - - if (intCode >= 8) { - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - strReturn.append( B0 ); - strComplement.append( B1 ); - strReturn.append( B0 ); - strComplement.append( B1 ); - - strReturn.append( strComplement ); - strComplement = ""; - - strReturn.append( B0 ); - strComplement.append( B1 ); - - if (intCode >> 2 & 1) { //Bit 2 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - if (on) { - strReturn.append(B0); - strComplement.append(B1); - } else { - strReturn.append(B1); - strComplement.append(B0); - } - - if (intCode & 1) { //Bit 0 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - if (intCode >> 1 & 1) { //Bit 1 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - for( int i = 0; i < 3; ++i ) { - strReturn.append( B0 ); - strComplement.append( B1 ); - } - - strReturn.append( strComplement ); - strReturn.append( STOP_CODE ); - } - catch(...){ - throw; - } - return strReturn; - -} - -bool DeviceX10::parameterMatches( const std::string &name, const std::string &value ) const { - if (name.compare("house") == 0) { - int h = value[0] - 'A'; - if (h < 0) { - h = 0; - } else if (h > 15) { - h = 15; - } - return intHouse == HOUSES[h]; - } else if (name.compare("unit") == 0) { - return intCode == atoi(value.c_str()) - 1; - } - return true; -} - -/* -* Has the device got the method? -*/ -int DeviceX10::methods(){ - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -std::string DeviceX10::getProtocol() const { - return "x10"; -} diff --git a/telldus-core/driver/libtelldus-core/DeviceX10.h b/telldus-core/driver/libtelldus-core/DeviceX10.h deleted file mode 100644 index 279bf94d..00000000 --- a/telldus-core/driver/libtelldus-core/DeviceX10.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceX10 : public Device - { - public: - DeviceX10(int id, const std::string &model, const std::string &name); - virtual int methods(); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &newHouse); - bool setUnit(const std::string &newUnit); - - public: - ~DeviceX10(void); - - protected: - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - - int intHouse; - int intCode; - std::string getStringCode(bool); - }; - -} diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp deleted file mode 100644 index 3f38962d..00000000 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ /dev/null @@ -1,582 +0,0 @@ -// -// C++ Implementation: controller -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "Manager.h" -#include "Device.h" - -#include "DeviceBrateck.h" -#include "DeviceEverflourish.h" -#include "DeviceFuhaote.h" -#include "DeviceGroup.h" -#include "DeviceSilvanChip.h" -#include "DeviceNexa.h" -#include "DeviceRisingSun.h" -#include "DeviceWaveman.h" -#include "DeviceSartano.h" -#include "DeviceIkea.h" -#include "DeviceUndefined.h" -#include "DeviceUpm.h" -#include "DeviceX10.h" - -#include "Controller.h" -#include "TellStick.h" -#include "common.h" - -#include -#include -#include -#include - -#ifdef _WINDOWS -#define strcasecmp _stricmp -#endif - - -using namespace TelldusCore; - -Manager *Manager::instance = 0; - -Manager::Manager() - : lastCallbackId(0), - lastControllerId(0) -{ - Thread::initMutex(&mutex); - //Create and start our worker-thread - this->start(); - this->loadControllers(); -} - -Manager::~Manager() { - // Clean up the device-map - for (DeviceMap::iterator it = devices.begin(); it != devices.end(); ++it) { - delete( it->second ); - } - // Clean up the controller-map - for (ControllerMap::iterator it = controllers.begin(); it != controllers.end(); ++it) { - delete( it->second ); - } - Thread::destroyMutex(&mutex); -} - -/** - * Get the requested device - * Note that the Manager keeps ownership of the returned Device - * and should not be deleted when not in use anymore. - **/ -Device *Manager::getDevice(int intDeviceId){ - Device* dev = NULL; - - { - MutexLocker locker(&mutex); - DeviceMap::iterator iterator = devices.find(intDeviceId); - if (iterator != devices.end()) { - return iterator->second; - } - } - - try{ - std::string protocol = settings.getProtocol(intDeviceId); - std::string strModel = settings.getModel(intDeviceId); - std::string strName = settings.getName(intDeviceId); - - //each new brand must be added here - if (strcasecmp(protocol.c_str(), "arctech") == 0){ - dev = new DeviceNexa(intDeviceId, strModel, strName); - ((DeviceNexa*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - ((DeviceNexa*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "unit")); - - } else if (strcasecmp(protocol.c_str(), "brateck") == 0) { - dev = new DeviceBrateck(intDeviceId, strModel, strName); - ((DeviceBrateck*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - - } else if (strcasecmp(protocol.c_str(), "everflourish") == 0){ - dev = new DeviceEverflourish(intDeviceId, strModel, strName); - ((DeviceEverflourish*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - ((DeviceEverflourish*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "unit")); - - } else if (strcasecmp(protocol.c_str(), "fuhaote") == 0) { - dev = new DeviceFuhaote(intDeviceId, strModel, strName); - ((DeviceFuhaote*)dev)->setCode(settings.getDeviceParameter(intDeviceId, "code")); - - } else if (strcasecmp(protocol.c_str(), "silvanchip") == 0) { - dev = new DeviceSilvanChip(intDeviceId, strModel, strName); - ((DeviceSilvanChip*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - - } else if (strcasecmp(protocol.c_str(), "group") == 0) { - dev = new DeviceGroup(intDeviceId, strModel, strName); - ((DeviceGroup*)dev)->setDevices(settings.getDeviceParameter(intDeviceId, "devices")); - - } else if (strcasecmp(protocol.c_str(), "risingsun") == 0) { - dev = new DeviceRisingSun(intDeviceId, strModel, strName); - ((DeviceRisingSun*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - ((DeviceRisingSun*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "unit")); - - } else if (strcasecmp(protocol.c_str(), "Waveman") == 0) { - dev = new DeviceWaveman(intDeviceId, strModel, strName); - ((DeviceWaveman*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - ((DeviceWaveman*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "unit")); - - } else if (strcasecmp(protocol.c_str(), "Sartano") == 0) { - dev = new DeviceSartano(intDeviceId, strModel, strName); - ((DeviceSartano*)dev)->setCode(settings.getDeviceParameter(intDeviceId, "code")); - - } else if (strcasecmp(protocol.c_str(), "Ikea") == 0) { - dev = new DeviceIkea(intDeviceId, strModel, strName); - ((DeviceIkea*)dev)->setSystem(settings.getDeviceParameter(intDeviceId, "system")); - ((DeviceIkea*)dev)->setUnits(settings.getDeviceParameter(intDeviceId, "units")); - ((DeviceIkea*)dev)->setFade(settings.getDeviceParameter(intDeviceId, "fade")); - - } else if (strcasecmp(protocol.c_str(), "upm") == 0) { - dev = new DeviceUpm(intDeviceId, strModel, strName); - ((DeviceUpm*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - ((DeviceUpm*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "unit")); - - } else if (strcasecmp(protocol.c_str(), "x10") == 0) { - dev = new DeviceX10(intDeviceId, strModel, strName); - ((DeviceX10*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house")); - ((DeviceX10*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "unit")); - - } else { - //This is a dummy device needed when the parameters isn't setup correctly. - dev = new DeviceUndefined(intDeviceId, strModel, strName); - } - -#ifdef _LINUX - dev->setDevice( settings.getSetting("deviceNode") ); -#endif - - } - catch(...){ - throw; - } - - if (intDeviceId > 0) { - MutexLocker locker(&mutex); - devices[intDeviceId] = dev; - } - return dev; -} - -int Manager::getNumberOfDevices(void) const { - return settings.getNumberOfDevices(); -} - -int Manager::getDeviceId(int intDeviceIndex) const { - return settings.getDeviceId(intDeviceIndex); -} - -void Manager::loadAllDevices() { - int numberOfDevices = getNumberOfDevices(); - for (int i = 0; i < numberOfDevices; ++i) { - int id = settings.getDeviceId(i); - if (!deviceLoaded(id)) { - getDevice(id); - } - } -} - -bool Manager::setDeviceProtocol(int intDeviceId, const std::string &strProtocol) { - bool retval = settings.setProtocol( intDeviceId, strProtocol ); - - MutexLocker locker(&mutex); - // Delete the device to reload it when the protocol changes - DeviceMap::iterator iterator = devices.find(intDeviceId); - if (iterator != devices.end()) { - Device *device = iterator->second; - devices.erase( iterator ); - delete device; - } - - if (retval) { - emitDeviceChange(intDeviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); - } - - return retval; -} - -bool Manager::setDeviceModel(int intDeviceId, const std::string &strModel) { - if (settings.setModel(intDeviceId, strModel)) { - emitDeviceChange(intDeviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); - return true; - } - return false; -} - -bool Manager::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { - if (intDeviceState != TELLSTICK_BELL && - intDeviceState != TELLSTICK_LEARN - ) { - MutexLocker locker(&mutex); - bool retval = settings.setDeviceState(intDeviceId, intDeviceState, strDeviceStateValue); - for(CallbackList::const_iterator callback_it = callbacks.begin(); callback_it != callbacks.end(); ++callback_it) { - (*callback_it).event(intDeviceId, intDeviceState, wrapStdString(strDeviceStateValue), (*callback_it).id, (*callback_it).context); - } - - return retval; - } - return true; -} - -int Manager::getDeviceState( int intDeviceId ) const { - return settings.getDeviceState(intDeviceId); -} - -std::string Manager::getDeviceStateValue( int intDeviceId ) const { - return settings.getDeviceStateValue(intDeviceId); -} - -bool Manager::deviceLoaded(int deviceId) const { - MutexLocker locker(&mutex); - DeviceMap::const_iterator iterator = devices.find(deviceId); - if (iterator == devices.end()) { - return false; - } - return true; -} - -void Manager::parseMessage( const std::string &message, TelldusCore::Controller *controller ) { - //Find the controller - int controllerId = 0; - { - MutexLocker locker(&mutex); - for(ControllerMap::iterator it = controllers.begin(); it != controllers.end(); ++it) { - if (it->second == controller) { - controllerId = it->first; - break; - } - } - } - //Pass the message to our worker-thread! - this->sendEvent(message, controllerId); -} - -int Manager::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - int id = ++lastCallbackId; - CallbackStruct callback = {eventFunction, id, context}; - callbacks.push_back(callback); - return id; -} - -int Manager::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { - int id = ++lastCallbackId; - DeviceChangeCallbackStruct callback = {eventFunction, id, context}; - deviceChangeCallbacks.push_back(callback); - return id; -} - -int Manager::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { - int id = ++lastCallbackId; - RawCallbackStruct callback = {eventFunction, id, context}; - rawCallbacks.push_back(callback); - return id; -} - -bool Manager::unregisterCallback( int callbackId ) { - for(CallbackList::iterator callback_it = callbacks.begin(); callback_it != callbacks.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - callbacks.erase(callback_it); - return true; - } - - for(DeviceChangeCallbackList::iterator callback_it = deviceChangeCallbacks.begin(); callback_it != deviceChangeCallbacks.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - deviceChangeCallbacks.erase(callback_it); - return true; - } - - for(RawCallbackList::iterator callback_it = rawCallbacks.begin(); callback_it != rawCallbacks.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - rawCallbacks.erase(callback_it); - return true; - } - - return false; -} - -Manager *Manager::getInstance() { - if (Manager::instance == 0) { - Manager::instance = new Manager(); - } - return Manager::instance; -} - -void Manager::close() { - if (Manager::instance != 0) { - delete Manager::instance; - } -} - -bool TelldusCore::Manager::setDeviceParameter(int intDeviceId, const std::string & strName, const std::string & strValue) { - return settings.setDeviceParameter(intDeviceId, strName, strValue); -} - -std::string TelldusCore::Manager::getDeviceParameter(int intDeviceId, const std::string & strName) const { - return settings.getDeviceParameter( intDeviceId, strName ); -} - -int TelldusCore::Manager::addDevice() { - int intDeviceId = settings.addDevice(); - if (intDeviceId > 0) { //Success - emitDeviceChange(intDeviceId, TELLSTICK_DEVICE_ADDED, 0); - } - return intDeviceId; -} - -bool TelldusCore::Manager::removeDevice(int intDeviceId) { - if (deviceLoaded(intDeviceId)) { - DeviceMap::iterator iterator = devices.find(intDeviceId); - if (iterator == devices.end()) { // Should not be possible since deviceLoaded() returned true - return false; - } - Device *dev = iterator->second; - devices.erase(iterator); - delete dev; - } - - bool ok = settings.removeDevice(intDeviceId); - if (ok) { - emitDeviceChange(intDeviceId, TELLSTICK_DEVICE_REMOVED, 0); - } - return ok; -} - -void TelldusCore::Manager::connectTellStickController(int vid, int pid, const std::string &serial) { - if (serial.length() > 0) { //If we specify which TellStick to connect - //First check that it is not already loaded - int id = findTellStickController(vid, pid, serial); - if (id != 0) { - return; - } - } - TellStick *tellstick = TellStick::loadBy(vid, pid, serial); - if (!tellstick) { - return; - } - lastControllerId--; //Negative since preconfigured controllers should have positive ids - controllers[lastControllerId] = tellstick; -} - -void TelldusCore::Manager::disconnectTellStickController(int vid, int pid, const std::string &serial) { - if (serial == "") { - //We must loop all devices to see if they are still connected - for(ControllerMap::iterator it = controllers.begin(); it != controllers.end(); ++it) { - TellStick *tellstick = reinterpret_cast(it->second); - if (!tellstick) { //No TellStick controller - continue; - } - if (tellstick->vid() != vid || tellstick->pid() != pid) { - continue; - } - if (!tellstick->stillConnected()) { - controllers.erase(it); - delete tellstick; - return; - } - } - return; - } - int id = findTellStickController(vid, pid, serial); - if (id == 0) { - return; - } - TellStick *tellstick = reinterpret_cast(controllers[id]); - if (!tellstick) { - return; - } - controllers.erase(id); - delete tellstick; -} - -bool TelldusCore::Manager::setDeviceName(int intDeviceId, const std::string & strNewName) { - if (settings.setName(intDeviceId, strNewName)) { - emitDeviceChange(intDeviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME); - return true; - } - return false; -} - -int TelldusCore::Manager::switchState(int deviceId, int newState, const std::string & value) { - Device *dev = this->getDevice(deviceId); - if (dynamic_cast(dev)) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - int retVal = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - if (!Device::maskUnsupportedMethods(dev->methods(), newState)) { - return retVal; - } - if (controllers.size() == 0) { - return TELLSTICK_ERROR_NOT_FOUND; - } - Controller *controller = controllers.begin()->second; - - std::string stateValue = ""; - - switch (newState) { - case TELLSTICK_TURNON: - retVal = dev->turnOn(controller); - break; - case TELLSTICK_TURNOFF: - retVal = dev->turnOff(controller); - break; - case TELLSTICK_BELL: - retVal = dev->bell(controller); - break; - case TELLSTICK_LEARN: - retVal = dev->learn(controller); - break; - case TELLSTICK_DIM: - //Convert value to string - unsigned char v = value[0]; - std::stringstream st; - st << (int)v; - stateValue = st.str(); - - retVal = dev->dim( v, controller ); - break; - } - if (retVal == TELLSTICK_SUCCESS) { - this->setDeviceState(deviceId, newState, stateValue); - } - return retVal; -} - -int TelldusCore::Manager::sendRawCommand(const std::string &strMessage) { - if (controllers.size() == 0) { - return TELLSTICK_ERROR_NOT_FOUND; - } - Controller *controller = controllers.begin()->second; - - return controller->send(strMessage); -} - -void TelldusCore::Manager::loadControllers() { - if (controllers.size()) { - return; - } - while(1) { - TellStick *controller = TellStick::findFirstDevice(); - if (!controller) { - break; //All TellStick loaded - } - //Make sure this isn't already loaded - bool found = false; - for(ControllerMap::iterator it = controllers.begin(); it != controllers.end(); ++it) { - TellStick *tellstick = reinterpret_cast(it->second); - if (!tellstick) { //No TellStick controller - continue; - } - if (tellstick->serial().compare(controller->serial()) == 0) { //Found a duplicate - found = true; - break; - } - } - if (found) { - break; - } - lastControllerId--; - controllers[lastControllerId] = controller; - } -} - -void TelldusCore::Manager::emitDeviceChange( int deviceId, int event, int change ) { - for(DeviceChangeCallbackList::const_iterator callback_it = deviceChangeCallbacks.begin(); callback_it != deviceChangeCallbacks.end(); ++callback_it) { - (*callback_it).event(deviceId, event, change, (*callback_it).id, (*callback_it).context); - } - -} - -void TelldusCore::Manager::run() { - //Our worker-thread has started - while(1) { - int controllerId; - std::string m = this->waitForEvent(&controllerId); - this->processMessage(m, controllerId); - } -} - -void TelldusCore::Manager::processMessage(const std::string & message, int controllerId) { - loadAllDevices(); //Make sure all devices is loaded before we iterator the list. - - std::map parameters; - std::string protocol; - int method = 0; - - //Process our message into bits - size_t prevPos = 0; - size_t pos = message.find(";"); - while(pos != std::string::npos) { - std::string param = message.substr(prevPos, pos-prevPos); - prevPos = pos+1; - size_t delim = param.find(":"); - if (delim == std::string::npos) { - break; - } - if (param.substr(0, delim).compare("protocol") == 0) { - protocol = param.substr(delim+1, param.length()-delim); - } else if (param.substr(0, delim).compare("method") == 0) { - method = Device::methodId(param.substr(delim+1, param.length()-delim)); - } else { - parameters[param.substr(0, delim)] = param.substr(delim+1, param.length()-delim); - } - pos = message.find(";", pos+1); - } - - for (DeviceMap::const_iterator it = devices.begin(); it != devices.end(); ++it) { - if (it->second->getProtocol().compare(protocol) != 0) { - continue; - } - if (! (it->second->methods() & method)) { - continue; - } - bool found = true; - for (std::map::const_iterator p_it = parameters.begin(); p_it != parameters.end(); ++p_it) { - if (p_it->second.length() == 0) { - continue; - } - if (!it->second->parameterMatches(p_it->first, p_it->second)) { - found = false; - break; - } - } - if (found) { - //First save the last sent command, this also triggers the callback to the client - setDeviceState(it->first, method, ""); - } - } - - for(RawCallbackList::const_iterator it = rawCallbacks.begin(); it != rawCallbacks.end(); ++it) { - (*it).event(message.c_str(), controllerId, (*it).id, (*it).context); - } - -} - -int TelldusCore::Manager::findTellStickController(int vid, int pid, const std::string &serial) { - for(ControllerMap::iterator it = controllers.begin(); it != controllers.end(); ++it) { - TellStick *tellstick = reinterpret_cast(it->second); - if (!tellstick) { //No TellStick controller - continue; - } - if (tellstick->vid() != vid || tellstick->pid() != pid) { - continue; - } - if (tellstick->serial().compare(serial) == 0) { //Found the controller - return it->first; - } - } - return 0; -} diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h deleted file mode 100644 index dc88074a..00000000 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// C++ Interface: controller -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef MANAGER_H -#define MANAGER_H - -#include "Settings.h" -#include "Thread.h" -#include -#include - -namespace TelldusCore { - class Device; - class Controller; - - struct CallbackStruct { - TDDeviceEvent event; - int id; - void *context; - }; - struct DeviceChangeCallbackStruct { - TDDeviceChangeEvent event; - int id; - void *context; - }; - struct RawCallbackStruct { - TDRawDeviceEvent event; - int id; - void *context; - }; - - typedef std::map DeviceMap; - typedef std::map ControllerMap; - typedef std::list CallbackList; - typedef std::list DeviceChangeCallbackList; - typedef std::list RawCallbackList; - - /** - @author Micke Prag - */ - class Manager : private Thread { - public: - virtual ~Manager(); - - Device *getDevice(int deviceId); - - bool deviceLoaded(int deviceId) const; - - int getNumberOfDevices(void) const; - int getDeviceId(int intDeviceIndex) const; - bool setDeviceProtocol(int intDeviceId, const std::string &strProtocol); - bool setDeviceName(int intDeviceId, const std::string &strNewName); - bool setDeviceModel(int intDeviceId, const std::string &strModel); - bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); - std::string getDeviceParameter(int intDeviceId, const std::string &strName) const; - bool setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ); - int getDeviceState( int intDeviceId ) const; - std::string getDeviceStateValue( int intDeviceId ) const; - - int switchState( int DeviceId, int newState, const std::string &value = "" ); - int sendRawCommand(const std::string &strMessage); - - int addDevice(); - bool removeDevice(int intDeviceId); - - void connectTellStickController(int vid, int pid, const std::string &serial); - void disconnectTellStickController(int vid, int pid, const std::string &serial); - - static Manager *getInstance(); - static void close(); - - int registerDeviceEvent( TDDeviceEvent eventFunction, void *context ); - int registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ); - int registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); - bool unregisterCallback( int callbackId ); - void parseMessage( const std::string &message, Controller *controller ); - - protected: - void loadAllDevices(); - void loadControllers(); - void emitDeviceChange( int deviceId, int event, int change ); - - virtual void run(); - - private: - Manager(); - void processMessage( const std::string &message, int controllerId ); - int findTellStickController(int vid, int pid, const std::string &serial); - - Settings settings; - DeviceMap devices; - ControllerMap controllers; - CallbackList callbacks; - DeviceChangeCallbackList deviceChangeCallbacks; - RawCallbackList rawCallbacks; - - mutable MUTEX mutex; - - int lastCallbackId; - int lastControllerId; - - static Manager *instance; - }; -} - -#endif diff --git a/telldus-core/driver/libtelldus-core/Resource.h b/telldus-core/driver/libtelldus-core/Resource.h deleted file mode 100644 index 0c5cdd60..00000000 --- a/telldus-core/driver/libtelldus-core/Resource.h +++ /dev/null @@ -1,31 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by testruntelldus3.rc -// - -#define IDS_APP_TITLE 103 - -#define IDR_MAINFRAME 128 -#define IDD_TESTRUNTELLDUS3_DIALOG 102 -#define IDD_ABOUTBOX 103 -#define IDM_ABOUT 104 -#define IDM_EXIT 105 -#define IDI_TESTRUNTELLDUS3 107 -#define IDI_SMALL 108 -#define IDC_TESTRUNTELLDUS3 109 -#define IDC_MYICON 2 -#ifndef IDC_STATIC -#define IDC_STATIC -1 -#endif -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS - -#define _APS_NO_MFC 130 -#define _APS_NEXT_RESOURCE_VALUE 129 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 110 -#endif -#endif diff --git a/telldus-core/driver/libtelldus-core/Settings.cpp b/telldus-core/driver/libtelldus-core/Settings.cpp deleted file mode 100644 index af4c200f..00000000 --- a/telldus-core/driver/libtelldus-core/Settings.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "Settings.h" - -/* -* Get the name of the device -*/ -std::string Settings::getName(int intDeviceId) const { - return getStringSetting(intDeviceId, "name", false); -} - -/* -* Set the name of the device -*/ -bool Settings::setName(int intDeviceId, const std::string &strNewName){ - return setStringSetting(intDeviceId, "name", strNewName, false); -} - -/* -* Get the device vendor -*/ -std::string Settings::getProtocol(int intDeviceId) const { - return getStringSetting(intDeviceId, "protocol", false); -} - -/* -* Set the device vendor -*/ -bool Settings::setProtocol(int intDeviceId, const std::string &strVendor){ - return setStringSetting(intDeviceId, "protocol", strVendor, false); -} - -/* -* Get the device model -*/ -std::string Settings::getModel(int intDeviceId) const { - return getStringSetting(intDeviceId, "model", false); -} - -/* -* Set the device model -*/ -bool Settings::setModel(int intDeviceId, const std::string &strModel){ - return setStringSetting(intDeviceId, "model", strModel, false); -} - -/* -* Set device argument -*/ -bool Settings::setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue){ - return setStringSetting(intDeviceId, strName, strValue, true); -} - -/* -* Get device argument -*/ -std::string Settings::getDeviceParameter(int intDeviceId, const std::string &strName) const { - return getStringSetting(intDeviceId, strName, true); -} - -#ifndef _CONFUSE - -bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { - bool retval = setIntSetting( intDeviceId, "state", intDeviceState, true ); - setStringSetting( intDeviceId, "stateValue", strDeviceStateValue, true ); - return retval; -} - -int Settings::getDeviceState( int intDeviceId ) const { - return getIntSetting( intDeviceId, "state", true ); -} - -std::string Settings::getDeviceStateValue( int intDeviceId ) const { - return getStringSetting( intDeviceId, "stateValue", true ); -} - -#endif diff --git a/telldus-core/driver/libtelldus-core/Settings.h b/telldus-core/driver/libtelldus-core/Settings.h deleted file mode 100644 index 977fe9d8..00000000 --- a/telldus-core/driver/libtelldus-core/Settings.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef SETTINGS_H -#define SETTINGS_H - -#include "Device.h" - -class privateVars; - -class Settings -{ -public: - Settings(void); - std::string getSetting(const std::string &strName) const; - int getNumberOfDevices(void) const; - std::string getName(int intDeviceId) const; - bool setName(int intDeviceId, const std::string &strNewName); - std::string getProtocol(int intDeviceId) const; - bool setProtocol(int intDeviceId, const std::string &strVendor); - std::string getModel(int intDeviceId) const; - bool setModel(int intDeviceId, const std::string &strModel); - std::string getDeviceParameter(int intDeviceId, const std::string &strName) const; - bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); - bool setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ); - int getDeviceState( int intDeviceId ) const; - std::string getDeviceStateValue( int intDeviceId ) const; - - int addDevice(); - int getDeviceId(int intDeviceIndex) const; - bool removeDevice(int intDeviceId); - - ~Settings(void); - -protected: - std::string getStringSetting(int intDeviceId, const std::string &name, bool parameter) const; - bool setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter); - int getIntSetting(int intDeviceId, const std::string &name, bool parameter) const; - bool setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter); - -private: - int getNextDeviceId() const; - - privateVars *d; -}; - -#endif diff --git a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp deleted file mode 100644 index 1590c9fc..00000000 --- a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp +++ /dev/null @@ -1,374 +0,0 @@ -// -// C++ Implementation: telldussettingsconfuse -// -// Description: -// -// -// Author: Micke Prag , (C) 2008 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "Settings.h" -#include -#include -#include -#include - -using namespace std; - -class privateVars { -public: - cfg_t *cfg; - cfg_t *var_cfg; -}; - -bool readConfig(cfg_t **cfg); -bool readVarConfig(cfg_t **cfg); - -const char* CONFIG_FILE = "/etc/tellstick.conf"; -#ifdef __FreeBSD__ -const char* VAR_CONFIG_FILE = "/var/spool/telldus-core.conf"; -#else -const char* VAR_CONFIG_FILE = "/var/state/telldus-core.conf"; -#endif - -/* -* Constructor -*/ -Settings::Settings(void) -{ - d = new privateVars(); - readConfig(&d->cfg); - readVarConfig(&d->var_cfg); -} - -/* -* Destructor -*/ -Settings::~Settings(void) -{ - if (d->cfg > 0) { - cfg_free(d->cfg); - } - if (d->var_cfg > 0) { - cfg_free(d->var_cfg); - } - delete d; -} - -/* -* Return a setting -*/ -std::string Settings::getSetting(const std::string &strName) const { - if (d->cfg > 0) { - return cfg_getstr(d->cfg, strName.c_str()); - } - return ""; -} - -/* -* Return the number of stored devices -*/ -int Settings::getNumberOfDevices(void) const { - if (d->cfg > 0) { - return cfg_size(d->cfg, "device"); - } - return 0; -} - -int Settings::getDeviceId(int intDeviceIndex) const { - if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds - return -1; - } - cfg_t *cfg_device = cfg_getnsec(d->cfg, "device", intDeviceIndex); - int id = cfg_getint(cfg_device, "id"); - return id; -} - -/* -* Add a new device -*/ -int Settings::addDevice(){ - int intDeviceId = getNextDeviceId(); - - FILE *fp = fopen(CONFIG_FILE, "w"); - cfg_print(d->cfg, fp); //Print the config-file - fprintf(fp, "device {\n id=%d\n}\n", intDeviceId); //Print the new device - fclose(fp); - - //Re-read config-file - cfg_free(d->cfg); - readConfig(&d->cfg); - return intDeviceId; -} - -/* -* Get next available device id -*/ -int Settings::getNextDeviceId() const { - int intDeviceId = 0; - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") >= intDeviceId) { - intDeviceId = cfg_getint(cfg_device, "id"); - } - } - intDeviceId++; - return intDeviceId; -} - -/* -* Remove a device -*/ -bool Settings::removeDevice(int intDeviceId){ - bool blnSuccess = true; - FILE *fp = fopen(CONFIG_FILE, "w"); - - // Print all opts - for(int i = 0; d->cfg->opts[i].name; i++) { - - // Check if it isn't a device section - if (strcmp(d->cfg->opts[i].name, "device") != 0) { - cfg_opt_print(&d->cfg->opts[i], fp); - } else { - // Print all sections except the one to remove - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") != intDeviceId) { //This isn't the one to skip - fprintf(fp, "device {\n"); - cfg_print_indent(cfg_device, fp, 1); - fprintf(fp, "}\n"); - } - } - } - } - fclose(fp); - - //Re-read config-file - cfg_free(d->cfg); - readConfig(&d->cfg); - - return blnSuccess; -} - -bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { - if (d->var_cfg == 0) { - return false; - } - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->var_cfg, "device", i); - int deviceId = atoi(cfg_title(cfg_device)); - if (deviceId == intDeviceId) { - cfg_setint(cfg_device, "state", intDeviceState); - cfg_setstr(cfg_device, "stateValue", strDeviceStateValue.c_str()); - - FILE *fp = fopen(VAR_CONFIG_FILE, "w"); - cfg_print(d->var_cfg, fp); - fclose(fp); - return true; - } - } - // The device is not found in the file, we must create it manualy... - FILE *fp = fopen(VAR_CONFIG_FILE, "w"); - if(!fp) { - fprintf(stderr, "Failed to write state to %s: %s\n", - VAR_CONFIG_FILE, strerror(errno)); - return false; - } - - cfg_print(d->var_cfg, fp); //Print the config-file - fprintf(fp, "device %d {\n}\n", intDeviceId); //Print the new device - fclose(fp); - - //Re-read config-file - cfg_free(d->var_cfg); - readVarConfig(&d->var_cfg); - - return false; -} - -int Settings::getDeviceState( int intDeviceId ) const { - if (d->var_cfg == 0) { - return false; - } - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->var_cfg, "device", i); - int deviceId = atoi(cfg_title(cfg_device)); - if (deviceId == intDeviceId) { - return cfg_getint(cfg_device, "state"); - } - } - return TELLSTICK_TURNOFF; -} - -std::string Settings::getDeviceStateValue( int intDeviceId ) const { - if (d->var_cfg == 0) { - return false; - } - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->var_cfg, "device", i); - int deviceId = atoi(cfg_title(cfg_device)); - if (deviceId == intDeviceId) { - char *value = cfg_getstr(cfg_device, "stateValue"); - return value; - } - } - return ""; -} - -std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { - if (d->cfg == 0) { - return ""; - } - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") == intDeviceId) { - if (parameter) { - cfg_device = cfg_getsec(cfg_device, "parameters"); - } - char *setting = cfg_getstr(cfg_device, name.c_str()); - if (setting == 0) { //The parameter does not exists - return ""; - } - return setting; - } - } - return ""; -} - -bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { - if (d->cfg == 0) { - return false; - } - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") == intDeviceId) { - if (parameter) { - cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); - cfg_setstr(cfg_parameters, name.c_str(), value.c_str()); - } else { - cfg_setstr(cfg_device, name.c_str(), value.c_str()); - } - FILE *fp = fopen(CONFIG_FILE, "w"); - cfg_print(d->cfg, fp); - fclose(fp); - return true; - } - } - return false; -} - -int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { - if (d->cfg == 0) { - return 0; - } - cfg_t *cfg_device; - for(int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") == intDeviceId) { - if (parameter) { - cfg_device = cfg_getsec(cfg_device, "parameters"); - } - return cfg_getint(cfg_device, name.c_str()); - } - } - return 0; -} - -bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { - if (d->cfg == 0) { - return false; - } - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") == intDeviceId) { - if (parameter) { - cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); - cfg_setint(cfg_parameters, name.c_str(), value); - } else { - cfg_setint(cfg_device, name.c_str(), value); - } - FILE *fp = fopen(CONFIG_FILE, "w"); - cfg_print(d->cfg, fp); - fclose(fp); - return true; - } - } - return false; -} - - -bool readConfig(cfg_t **cfg) { - cfg_opt_t controller_opts[] = { - CFG_INT("id", -1, CFGF_NONE), - }; - - cfg_opt_t device_parameter_opts[] = { - //Groups - CFG_STR("devices", 0, CFGF_NONE), - - CFG_STR("house", 0, CFGF_NONE), - CFG_STR("unit", 0, CFGF_NONE), - CFG_STR("code", 0, CFGF_NONE), - CFG_STR("system", 0, CFGF_NONE), - CFG_STR("units", 0, CFGF_NONE), - CFG_STR("fade", 0, CFGF_NONE), - - CFG_END() - }; - - cfg_opt_t device_opts[] = { - CFG_INT("id", -1, CFGF_NONE), - CFG_STR("name", "Unnamed", CFGF_NONE), - CFG_INT("controller", 0, CFGF_NONE), - CFG_STR("protocol", "arctech", CFGF_NONE), - CFG_STR("model", "", CFGF_NONE), - CFG_SEC("parameters", device_parameter_opts, CFGF_NONE), - CFG_END() - }; - - cfg_opt_t opts[] = { - CFG_STR("deviceNode", "/dev/tellstick", CFGF_NONE), - CFG_SEC("device", device_opts, CFGF_MULTI), - CFG_END() - }; - - (*cfg) = cfg_init(opts, CFGF_NOCASE); - if (cfg_parse((*cfg), CONFIG_FILE) == CFG_PARSE_ERROR) { - (*cfg) = 0; - return false; - } - - return true; -} - -bool readVarConfig(cfg_t **cfg) { - - cfg_opt_t device_opts[] = { - CFG_INT("state", 0, CFGF_NONE), - CFG_STR("stateValue", "", CFGF_NONE), - CFG_END() - }; - - cfg_opt_t opts[] = { - CFG_SEC("device", device_opts, CFGF_MULTI | CFGF_TITLE), - CFG_END() - }; - - (*cfg) = cfg_init(opts, CFGF_NOCASE); - if (cfg_parse((*cfg), VAR_CONFIG_FILE) == CFG_PARSE_ERROR) { - (*cfg) = 0; - return false; - } - - return true; -} diff --git a/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp b/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp deleted file mode 100644 index bdfa3ce1..00000000 --- a/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp +++ /dev/null @@ -1,245 +0,0 @@ -// -// C++ Implementation: telldussettingsconfuse -// -// Description: -// -// -// Author: Micke Prag , (C) 2008 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "Settings.h" -#include -#include -#include - -using namespace std; - -class privateVars { -public: - CFStringRef app_ID; - CFStringRef userName; - CFStringRef hostName; -}; - - -/* -* Constructor -*/ -Settings::Settings(void) -{ - d = new privateVars(); - d->app_ID = CFSTR( "com.telldus.core" ); - d->userName = kCFPreferencesAnyUser; - d->hostName = kCFPreferencesCurrentHost; -} - -/* -* Destructor -*/ -Settings::~Settings(void) -{ - delete d; -} - -/* -* Return a setting -*/ -std::string Settings::getSetting(const std::string &strName) const { - return ""; -} - -/* -* Return the number of stored devices -*/ -int Settings::getNumberOfDevices(void) const { - CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); - if (!cfarray) return 0; - CFIndex size = CFArrayGetCount( cfarray ); - int devices = 0; - for (CFIndex k = 0; k < size; ++k) { - CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); - if (CFStringHasPrefix( key, CFSTR("devices.") ) && - CFStringHasSuffix( key, CFSTR(".name") ) ) { - devices++; - } - } - return devices; -} - -int Settings::getDeviceId(int intDeviceIndex) const { - CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); - if (!cfarray) return 0; - CFIndex size = CFArrayGetCount( cfarray ); - int index = 0; - int id = 0; - for (CFIndex k = 0; k < size; ++k) { - CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); - if (CFStringHasPrefix( key, CFSTR("devices.") ) && - CFStringHasSuffix( key, CFSTR(".name") ) ) { - - if (index == intDeviceIndex) { - CFArrayRef split = CFStringCreateArrayBySeparatingStrings( 0, key, CFSTR(".") ); - if ( !split || CFArrayGetCount( split ) != 3 ) continue; - - // This code crashes! - //CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); - //if (cfid) - // CFNumberGetValue( cfid, kCFNumberIntType, &id); - - CFStringRef cfid = (CFStringRef) CFArrayGetValueAtIndex( split, 1 ); - char *cp = NULL; - CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1; - cp = (char *)malloc(size); - CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); - cp = (char *)realloc( cp, strlen(cp) + 1); - id = atoi(cp); - - - CFRelease(key); - CFRelease(split); - CFRelease(cfid); - break; - } - index++; - } - CFRelease( key ); - } - return id; -} - -/* -* Add a new device -*/ -int Settings::addDevice() { - int id = getNextDeviceId(); - setStringSetting( id, "name", "", false ); //Create a empty name so the device has an entry - setStringSetting( id, "model", "", false ); - return id; -} - -/* -* Get next available device id -*/ -int Settings::getNextDeviceId() const { - int id = 0, max = 0; - int numberOfDevices = getNumberOfDevices(); - for( int i = 0; i < numberOfDevices; i++) { - id = getDeviceId( i ); - if (id > max) { - max = id; - } - } - max++; - return max; -} - -/* -* Remove a device -*/ -bool Settings::removeDevice(int intDeviceId){ - CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d."), intDeviceId); // The key to search for - - CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); - if (!cfarray) return 0; - CFIndex size = CFArrayGetCount( cfarray ); - for (CFIndex k = 0; k < size; ++k) { - CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); - if (CFStringHasPrefix( key, filterKey ) ) { - CFPreferencesSetValue( key, NULL, d->app_ID, d->userName, d->hostName ); //Remove the key - } - } - - CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); - return true; -} - -std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); - - CFStringRef key; - if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); - } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); - } - - CFStringRef value; - - value = (CFStringRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName); - if (!value) { - return ""; - } - - char *cp = NULL; - CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( value ), kCFStringEncodingUTF8) + 1; - cp = (char *)malloc(size); - CFStringGetCString( value, cp, size, kCFStringEncodingUTF8 ); - cp = (char *)realloc( cp, strlen(cp) + 1); - - CFRelease(value); - return cp; -} - -bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); - CFStringRef cfvalue = CFStringCreateWithCString( 0, value.c_str(), kCFStringEncodingUTF8 ); - - CFStringRef key; - if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); - } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); - } - - CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); - CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); - return true; -} - -int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { - int retval = 0; - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); - CFNumberRef cfvalue; - - CFStringRef key; - if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); - } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); - } - - cfvalue = (CFNumberRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName); - - // If the preference exists, use it. - if (cfvalue) { - try { - // Numbers come out of preferences as CFNumber objects. - if (!CFNumberGetValue(cfvalue, kCFNumberIntType, &retval)) { - retval = 0; - } - CFRelease(cfvalue); - } catch (std::exception e) { - retval = 0; - } - } - - return retval; -} - -bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); - CFNumberRef cfvalue = CFNumberCreate(NULL, kCFNumberIntType, &value); - - CFStringRef key; - if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); - } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); - } - - CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); - CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); - return true; -} diff --git a/telldus-core/driver/libtelldus-core/SettingsQt.cpp b/telldus-core/driver/libtelldus-core/SettingsQt.cpp deleted file mode 100644 index 42c81cce..00000000 --- a/telldus-core/driver/libtelldus-core/SettingsQt.cpp +++ /dev/null @@ -1,148 +0,0 @@ -// -// C++ Implementation: telldussettingsconfuse -// -// Description: -// -// -// Author: Micke Prag , (C) 2008 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "Settings.h" -#include -#include -#include -#include -#include - -using namespace std; - -class privateVars { -public: - QSettings *settings; -}; - - -/* -* Constructor -*/ -Settings::Settings(void) -{ - d = new privateVars(); - d->settings = new QSettings("Telldus", "Core"); -} - -/* -* Destructor -*/ -Settings::~Settings(void) -{ - delete d->settings; - delete d; -} - -/* -* Return a setting -*/ -std::string Settings::getSetting(const std::string &strName) const { - return ""; -} - -/* -* Return the number of stored devices -*/ -int Settings::getNumberOfDevices(void) const { - int devices = 0; - d->settings->beginGroup("devices"); - devices = d->settings->childGroups().count(); - d->settings->endGroup(); - return devices; -} - -int Settings::getDeviceId(int intDeviceIndex) const { - int id = 0; - d->settings->beginGroup("devices"); - QString strId = d->settings->childGroups().at(intDeviceIndex); - d->settings->endGroup(); - - id = strId.toInt(); - - return id; -} - -/* -* Add a new device -*/ -int Settings::addDevice() { - int id = getNextDeviceId(); - - if (id < 0) { - return -1; - } - - setStringSetting(id, "name", "Unnamed", false); - setStringSetting(id, "protocol", "arctech", false); - - return id; -} - -/* -* Get next available device id -*/ -int Settings::getNextDeviceId() const { - int id = d->settings->value("lastUsedDeviceId", 0).toInt() + 1; - d->settings->setValue("lastUsedDeviceId", id); - return id; -} - -/* -* Remove a device -*/ -bool Settings::removeDevice(int intDeviceId) { - d->settings->remove( QString("devices/%1").arg(intDeviceId) ); - return true; -} - -std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { - QString key = QString("devices/%1/").arg(intDeviceId); - if (parameter) { - key += "parameters/"; - } - key += name.c_str(); - QString value = d->settings->value(key).toString(); - return value.toStdString(); -} - -bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { - QString key = QString("devices/%1/").arg(intDeviceId); - if (parameter) { - key += "parameters/"; - } - key += name.c_str(); - d->settings->setValue(key, value.c_str()); - d->settings->sync(); - return true; -} - -int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { - int retval = 0; - QString key = QString("devices/%1/").arg(intDeviceId); - if (parameter) { - key += "parameters/"; - } - key += name.c_str(); - retval = d->settings->value(key).toInt(); - return retval; -} - -bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { - QString key = QString("devices/%1/").arg(intDeviceId); - if (parameter) { - key += "parameters/"; - } - key += name.c_str(); - d->settings->setValue(key, value); - d->settings->sync(); - return true; -} diff --git a/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp b/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp deleted file mode 100644 index ed992e53..00000000 --- a/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#include "StdAfx.h" -#include "Settings.h" -#include -#include -#include -#include -#include - -bool storeGlobal(privateVars *d); - -const int intMaxRegValueLength = 1000; - -class privateVars { -public: - HKEY hk; - HKEY rootKey; - std::string strRegPathDevice; - std::string strRegPath; -}; - -/* -* Constructor -*/ -Settings::Settings(void) -{ - d = new privateVars(); - d->strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; - d->strRegPath = "SOFTWARE\\Telldus\\"; - //if (storeGlobal(d)) { - d->rootKey = HKEY_LOCAL_MACHINE; - //} else { - // d->rootKey = HKEY_CURRENT_USER; - //} -} - -/* -* Destructor -*/ -Settings::~Settings(void) -{ - //RegCloseKey(hk); //close all, if still open //TODO: Need some way to know if open or closed - d->strRegPath = ""; - d->strRegPathDevice = ""; - delete d; -} - -/* -* Return the number of stored devices -*/ -int Settings::getNumberOfDevices(void) const { - - int intNumberOfDevices = 0; - - try{ - - long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - - std::string strNumSubKeys; - DWORD dNumSubKeys; - RegQueryInfoKey(d->hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - intNumberOfDevices = (int)dNumSubKeys; - - RegCloseKey(d->hk); - } - else{ - throw std::exception(); //couldn't open reg key - } - } - catch(...){ - intNumberOfDevices = -1; - } - return intNumberOfDevices; -} - - -int Settings::getDeviceId(int intDeviceIndex) const { - int intReturn = -1; - - try{ - - long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_READ, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - - char* Buff = new char[intMaxRegValueLength]; - DWORD size = intMaxRegValueLength; - if (RegEnumKeyEx(d->hk, intDeviceIndex, (LPSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { - intReturn = (int)_atoi64(Buff); - } - - delete Buff; - - RegCloseKey(d->hk); - } else { - throw std::exception(); //couldn't open reg key - } - } - catch(...){ - intReturn = -1; - } - return intReturn; - - -} - -/* -* Add a new device -*/ -int Settings::addDevice(){ - - int intDeviceId = -1; - try{ - - DWORD dwDisp; - intDeviceId = getNextDeviceId(); - - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::string strCompleteRegPath = ssRegPath.str(); - - if(RegCreateKeyEx(d->rootKey, - strCompleteRegPath.c_str(), - 0, - NULL, - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &d->hk, - &dwDisp)){ - //fail - throw std::exception("Create Key failed"); - } - - RegCloseKey(d->hk); - - } - catch(...){ - intDeviceId = -1; - } - return intDeviceId; -} - -/* -* Get next available device id -*/ -int Settings::getNextDeviceId() const { - - int intReturn = -1; - try{ - DWORD dwDisp; - long lnExists = RegCreateKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, - NULL, - &d->hk, - &dwDisp); //create or open if already created - - if(lnExists == ERROR_SUCCESS){ - - DWORD dwLength; - char* Buff = new char[intMaxRegValueLength]; - - long lngStatus = RegQueryValueEx(d->hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); - - if(lngStatus == ERROR_MORE_DATA){ - //The buffer is to small, recreate it - delete Buff; - Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(d->hk, "LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); - } - - if(lngStatus == ERROR_SUCCESS){ - - int intLast = (int)Buff[0]; - intReturn = intLast + 1; - } - else{ - intReturn = 1; - } - delete Buff; - - DWORD dwVal = intReturn; - - RegSetValueEx (d->hk, "LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); - - } - RegCloseKey(d->hk); - } - catch(...){ - intReturn = -1; - } - return intReturn; -} - -/* -* Remove a device -*/ -bool Settings::removeDevice(int intDeviceId){ - - bool blnSuccess = true; - try{ - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::string strCompleteRegPath = ssRegPath.str(); - - long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); - if(lngSuccess != ERROR_SUCCESS){ - blnSuccess = false; - } - } - catch(...){ - blnSuccess = false; - } - - return blnSuccess; -} - -std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { - std::string strReturn = ""; - - try{ - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - DWORD dwLength; - char* Buff = new char[intMaxRegValueLength]; - - long lngStatus = RegQueryValueEx(d->hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - if(lngStatus == ERROR_MORE_DATA){ - //The buffer is to small, recreate it - delete Buff; - Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(d->hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - } - if (lngStatus == ERROR_SUCCESS) { - strReturn = Buff; - } - delete Buff; - } - else{ - throw std::exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - } - catch(...){ - strReturn = ""; - } - return strReturn; -} - -bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { - - bool blnSuccess = true; - try{ - - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - int length = (int)value.length(); - RegSetValueEx(d->hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length); - } - else{ - throw std::exception(); //couldn't open reg key - } - RegCloseKey(d->hk); - - } - catch(...){ - blnSuccess = false; - } - return blnSuccess; - -} - -int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { - int intReturn = 0; - - std::string strSetting = getStringSetting(intDeviceId, name, parameter); - if (strSetting.length()) { - intReturn = (int)strSetting[0]; - } - - return intReturn; -} - -bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { - bool blnReturn = false; - - std::ostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::string strCompleteRegPath = ssRegPath.str(); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); - if (lnExists == ERROR_SUCCESS) { - DWORD dwVal = value; - lnExists = RegSetValueEx (d->hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); - if (lnExists == ERROR_SUCCESS) { - blnReturn = true; - } - } - RegCloseKey(d->hk); - return blnReturn; -} - -bool storeGlobal(privateVars *d) { - bool blnReturn = false; - try{ - long lnExists = RegOpenKeyEx(HKEY_LOCAL_MACHINE, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &d->hk); - - if(lnExists == ERROR_SUCCESS){ - - DWORD dwLength; - char* Buff = new char[intMaxRegValueLength]; - - long lngStatus = RegQueryValueEx(d->hk, "SharedDevices", NULL, NULL, (LPBYTE)Buff, &dwLength); - - if(lngStatus == ERROR_MORE_DATA){ - //The buffer is to small, recreate it - delete Buff; - Buff = new char[dwLength]; - - lngStatus = RegQueryValueEx(d->hk, "SharedDevices", NULL, NULL, (LPBYTE)Buff, &dwLength); - } - - if(lngStatus == ERROR_SUCCESS){ - - int intValue = (int)Buff[0]; - blnReturn = (intValue == 1); - } - delete Buff; - } - RegCloseKey(d->hk); - } - catch(...){ - } - return blnReturn; -} diff --git a/telldus-core/driver/libtelldus-core/TellStick.cpp b/telldus-core/driver/libtelldus-core/TellStick.cpp deleted file mode 100644 index d8b93d61..00000000 --- a/telldus-core/driver/libtelldus-core/TellStick.cpp +++ /dev/null @@ -1,423 +0,0 @@ -// -// C++ Implementation: TellStick -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "TellStick.h" -#include "TellStickDuo.h" -#include "telldus-core.h" -#include -#include - -using namespace TelldusCore; - -class TelldusCore::TellStickDescriptor { -public: - bool found; - std::string serial; - int vid, pid; -}; - -class TelldusCore::PrivateVars { -public: - bool open; - TellStickHandle ftHandle; - TellStickDescriptor descriptor; -}; - -TellStick::TellStick( const TellStickDescriptor &td ) { - d = new PrivateVars; - d->open = false; - d->descriptor = td; - -#ifdef LIBFTDI - ftdi_init(&d->ftHandle); - - int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str()); - if (ret < 0) { - ftdi_deinit(&d->ftHandle); - return; - } - d->open = true; - ftdi_usb_reset( &d->ftHandle ); - ftdi_disable_bitbang( &d->ftHandle ); -#else - - char *tempSerial = new char[td.serial.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempSerial, td.serial.size()+1, td.serial.c_str()); -#else - strcpy(tempSerial, td.serial.c_str()); - FT_SetVIDPID(td.vid, td.pid); -#endif - FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); - delete tempSerial; - if (ftStatus == FT_OK) { - d->open = true; - FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); - FT_SetTimeouts(d->ftHandle,5000,0); - } -#endif - - if (d->open) { - setBaud(4800); - } -} - -TellStick::~TellStick() { - if (d->open) { -#ifdef LIBFTDI - ftdi_usb_close(&d->ftHandle); - ftdi_deinit(&d->ftHandle); -#else - FT_Close(d->ftHandle); -#endif - } - delete d; -} - -int TellStick::vid() const { - return d->descriptor.vid; -} - -int TellStick::pid() const { - return d->descriptor.pid; -} - -std::string TellStick::serial() const { - return d->descriptor.serial; -} - -bool TellStick::open() const { - return d->open; -} - -TellStick *TellStick::findFirstDevice(int vid, int pid) { - TellStick *tellstick = 0; - - if (vid == 0 && pid == 0) { - tellstick = findFirstDevice(0x1781, 0x0C30); - if (tellstick) { - return tellstick; - } -#ifdef TELLSTICK_DUO - tellstick = findFirstDevice(0x1781, 0x0C31); -#endif - return tellstick; - - } - - TellStickDescriptor d = findByVIDPID(vid, pid); - if (d.found) { -#ifdef TELLSTICK_DUO - if (pid == 0x0C31) { - return new TellStickDuo(d); - } -#endif - return new TellStick(d); - } - return 0; -} - -TellStick *TellStick::loadBy(int vid, int pid, const std::string &serial) { - if (vid != 0x1781) { - return 0; - } - - TellStick *tellstick = 0; - - if (serial.length() == 0) { - tellstick = TellStick::findFirstDevice(); - } else { - TellStickDescriptor d; - d.vid = vid; - d.pid = pid; - d.serial = serial; - - if (pid == 0x0C30) { - tellstick = new TellStick(d); -#ifdef TELLSTICK_DUO - } else if (pid == 0x0C31) { - tellstick = new TellStickDuo(d); -#endif - } - } - if (!tellstick) { - return 0; - } - if (tellstick->open()) { - return tellstick; - } - delete tellstick; - return 0; -} - -TellStickDescriptor TellStick::findByVIDPID( int vid, int pid ) { - TellStickDescriptor retval; - retval.found = false; - retval.vid = vid; - retval.pid = pid; - -#ifdef LIBFTDI - ftdi_context ftdic; - struct ftdi_device_list *devlist, *curdev; - char serialBuffer[10]; - ftdi_init(&ftdic); - - int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid); - if (ret > 0) { - for (curdev = devlist; curdev != NULL; curdev = curdev->next) { - ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); - if (ret != 0) { - continue; - } - retval.serial = serialBuffer; - break; - } - retval.found = true; - } - - ftdi_list_free(&devlist); - ftdi_deinit(&ftdic); -#else - FT_HANDLE fthHandle = 0; - FT_STATUS ftStatus = FT_OK; - - try{ - DWORD dwNumberOfDevices = 0; - -#ifndef _WINDOWS - FT_SetVIDPID(vid, pid); -#endif - ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); - if (ftStatus == FT_OK) { - for (int i = 0; i < (int)dwNumberOfDevices; i++) { - - FT_PROGRAM_DATA pData; - char ManufacturerBuf[32]; - char ManufacturerIdBuf[16]; - char DescriptionBuf[64]; - char SerialNumberBuf[16]; - - pData.Signature1 = 0x00000000; - pData.Signature2 = 0xffffffff; - pData.Version = 0x00000002; // EEPROM structure with FT232R extensions - pData.Manufacturer = ManufacturerBuf; - pData.ManufacturerId = ManufacturerIdBuf; - pData.Description = DescriptionBuf; - pData.SerialNumber = SerialNumberBuf; - - ftStatus = FT_Open(i, &fthHandle); - ftStatus = FT_EE_Read(fthHandle, &pData); - if(ftStatus == FT_OK){ - if(pData.VendorId == vid && pData.ProductId == pid){ - ftStatus = FT_Close(fthHandle); - retval.found = true; - retval.serial = pData.SerialNumber; - break; - } - } - ftStatus = FT_Close(fthHandle); - } - } - } - catch(...){ - throw; - } -#endif - return retval; -} - -int TelldusCore::TellStick::firmwareVersion() { - return 1; -} - -int TelldusCore::TellStick::send(const std::string & strMessage) { - if (!d->open) { - return TELLSTICK_ERROR_NOT_FOUND; - } - - - bool c = true; -#ifdef LIBFTDI - unsigned char *tempMessage = new unsigned char[strMessage.size()]; - memcpy(tempMessage, strMessage.c_str(), strMessage.size()); - - int ret; - ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ; - if(ret < 0) { - c = false; - } else if(ret != strMessage.length()) { - fprintf(stderr, "wierd send length? retval %i instead of %d\n", - ret, (int)strMessage.length()); - } - - delete[] tempMessage; - - int retrycnt = 500; - unsigned char in; - while(c && --retrycnt) { - ret = ftdi_read_data( &d->ftHandle, &in, 1); - if (ret > 0) { - if (in == '\n') { - break; - } - } else if(ret == 0) { // No data available - usleep(100); - } else { //Error - c = false; - } - } - if (!retrycnt) { - c = false; - } -#else - char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); -#ifdef _WINDOWS - strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str()); -#else - strcpy(tempMessage, strMessage.c_str()); -#endif - ULONG bytesWritten, bytesRead; - char in; - FT_STATUS ftStatus; - ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten); - free(tempMessage); - - while(c) { - ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead); - if (ftStatus == FT_OK) { - if (bytesRead == 1) { - if (in == '\n') { - break; - } - } else { //Timeout - c = false; - } - } else { //Error - c = false; - } - } -#endif - - if (!c) { - return TELLSTICK_ERROR_COMMUNICATION; - } - return TELLSTICK_SUCCESS; -} - -void TelldusCore::TellStick::setBaud(int baud) { -#ifdef LIBFTDI - int ret = ftdi_set_baudrate(&d->ftHandle, baud); - if(ret != 0) { - fprintf(stderr, "set Baud failed, retval %i\n", ret); - } -#else - FT_SetBaudRate(d->ftHandle, baud); -#endif -} - -TellStickHandle TelldusCore::TellStick::handle() const { - return d->ftHandle; -} - -bool TelldusCore::TellStick::stillConnected() const { - std::string serial = this->serial(); - -#ifdef LIBFTDI - ftdi_context ftdic; - struct ftdi_device_list *devlist, *curdev; - char serialBuffer[10]; - ftdi_init(&ftdic); - bool found = false; - - int ret = ftdi_usb_find_all(&ftdic, &devlist, this->vid(), this->pid()); - if (ret > 0) { - for (curdev = devlist; curdev != NULL; curdev = curdev->next) { - ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); - if (ret != 0) { - continue; - } - if (serial.compare(serialBuffer) == 0) { - found = true; - break; - } - } - } - - ftdi_list_free(&devlist); - ftdi_deinit(&ftdic); - return found; -#else - FT_STATUS ftStatus; - DWORD numDevs; - // create the device information list - ftStatus = FT_CreateDeviceInfoList(&numDevs); - if (ftStatus != FT_OK) { - return false; - } - if (numDevs <= 0) { - return false; - } - for (int i = 0; i < (int)numDevs; i++) { - FT_HANDLE ftHandleTemp; - DWORD flags; - DWORD id; - DWORD type; - DWORD locId; - char serialNumber[16]; - char description[64]; - // get information for device 0 - ftStatus = FT_GetDeviceInfoDetail(i, &flags, &type, &id, &locId, serialNumber, description, &ftHandleTemp); - if (ftStatus != FT_OK) { - continue; - } - if (serial.compare(serialNumber) == 0) { - return true; - } - } - return false; -#endif -} - -std::string TelldusCore::TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ) { - unsigned char dataByte = 0; - std::string retString = "R\1T"; - retString.append(1, t0); - retString.append(1, t1); - retString.append(1, t2); - retString.append(1, t3); - - if (data.length() > 255) { - return ""; - } - unsigned char length = (unsigned char)data.length(); - retString.append(1, length); - - for (size_t i = 0; i < data.length(); ++i) { - dataByte <<= 2; - if (data.at(i) == '1') { - dataByte |= 1; - } else if (data.at(i) == '2') { - dataByte |= 2; - } else if (data.at(i) == '3') { - dataByte |= 3; - } - if ( (i+1) % 4 == 0) { - retString.append(1, dataByte); - dataByte = 0; - } - } - if (data.length() % 4 != 0) { - retString.append(1, dataByte); - } - - retString.append("+"); - return retString; -} diff --git a/telldus-core/driver/libtelldus-core/TellStick.h b/telldus-core/driver/libtelldus-core/TellStick.h deleted file mode 100644 index 7dce4ad7..00000000 --- a/telldus-core/driver/libtelldus-core/TellStick.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// C++ Interface: TellStick -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLSTICK_H -#define TELLSTICK_H - -#include "Controller.h" - -#include "ftd2xx.h" -#ifdef LIBFTDI - typedef ftdi_context TellStickHandle; -#else - typedef FT_HANDLE TellStickHandle; -#endif - -/** - @author Micke Prag -*/ -namespace TelldusCore { - class PrivateVars; - class TellStickDescriptor; - - class TellStick : public Controller { - public: - virtual ~TellStick(); - - virtual int firmwareVersion(); - virtual int send( const std::string &message ); - - int vid() const; - int pid() const; - std::string serial() const; - bool open() const; - bool stillConnected() const; - - static TellStick *findFirstDevice(int vid = 0, int pid = 0); - static TellStick *loadBy(int vid, int pid, const std::string &serial); - - static std::string convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ); - - protected: - TellStick(const TellStickDescriptor &d); - void setBaud( int baud ); - TellStickHandle handle() const; - - private: - static TellStickDescriptor findByVIDPID( int vid, int pid ); - - PrivateVars *d; - }; -} - -#endif diff --git a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp deleted file mode 100644 index c43841aa..00000000 --- a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// -// C++ Implementation: controller -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "TellStickDuo.h" -#include "Thread.h" -#include "Manager.h" -#include -#include - -#if defined(_WINDOWS) && defined(LIBFTD2XX) -typedef HANDLE EVENT_HANDLE; -#elif defined(LIBFTDI) - #include - typedef struct _EVENT_HANDLE { - pthread_cond_t eCondVar; - pthread_mutex_t eMutex; - } EVENT_HANDLE; - typedef int DWORD; -#endif - -using namespace TelldusCore; - -namespace TelldusCore { - - class PrivateTellStickDuoListener: public Thread { - public: - PrivateTellStickDuoListener( TellStickDuo *parent ); - virtual ~PrivateTellStickDuoListener(); - void stop(); - protected: - void run(); - private: - void processData( const std::string &data ); - - TellStickDuo *parent; - EVENT_HANDLE eh; - bool running; - MUTEX mutex; - std::string message; - }; - - class TellStickDuoPrivate { - public: - PrivateTellStickDuoListener *listener; - }; -} - -TellStickDuo::TellStickDuo(const TellStickDescriptor &td) - : TellStick(td) -{ - d = new TellStickDuoPrivate; - - this->setBaud(9600); - - d->listener = new PrivateTellStickDuoListener(this); - d->listener->start(); -} - - -TellStickDuo::~TellStickDuo() { - if (d->listener) { - d->listener->stop(); - delete d->listener; - } -} - -bool TellStickDuo::connected() const { - return true; -} - -PrivateTellStickDuoListener::PrivateTellStickDuoListener( TellStickDuo *p ) - : Thread(), - parent(p), - running(false) -{ - Thread::initMutex(&mutex); -} - -PrivateTellStickDuoListener::~PrivateTellStickDuoListener() { - if (running) { - stop(); - } - Thread::destroyMutex(&mutex); -} - -void PrivateTellStickDuoListener::stop() { - if (running) { - { - MutexLocker locker(&mutex); - running = false; - } - //Unlock the wait-condition -#ifdef _WINDOWS - SetEvent(eh); -#else - pthread_cond_broadcast(&eh.eCondVar); -#endif - } - this->wait(); -} - -void PrivateTellStickDuoListener::run() { -#ifdef LIBFTD2XX - DWORD dwBytesInQueue = 0; - DWORD dwBytesRead = 0; - char *buf = 0; -#else - int dwBytesRead = 0; - unsigned char buf[100];// = 0; - TellStickHandle h = parent->handle(); -#endif - -#ifdef _WINDOWS - eh = CreateEvent( NULL, false, false, "" ); -#else - pthread_mutex_init(&eh.eMutex, NULL); - pthread_cond_init(&eh.eCondVar, NULL); -#endif - - { - MutexLocker locker(&mutex); - running = true; - } - - while(1) { -#ifdef LIBFTD2XX -#ifdef _WINDOWS - FT_SetEventNotification(parent->handle(), FT_EVENT_RXCHAR, eh); - WaitForSingleObject(eh,INFINITE); -#else - FT_SetEventNotification(parent->handle(), FT_EVENT_RXCHAR, (PVOID)&eh); - pthread_mutex_lock(&eh.eMutex); - pthread_cond_wait(&eh.eCondVar, &eh.eMutex); - pthread_mutex_unlock(&eh.eMutex); -#endif - { - MutexLocker locker(&mutex); - if (!running) { - break; - } - } - - FT_GetQueueStatus(parent->handle(), &dwBytesInQueue); - if (dwBytesInQueue < 1) { - continue; - } - - buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); - memset(buf, 0, dwBytesInQueue+1); - FT_Read(parent->handle(), buf, dwBytesInQueue, &dwBytesRead); - processData( buf ); - free(buf); -#else - usleep(1000); - dwBytesRead = ftdi_read_data(&h, buf, 100); - if (dwBytesRead < 1) { - continue; - } - processData( reinterpret_cast(&buf) ); -#endif - } -} - -void PrivateTellStickDuoListener::processData( const std::string &data ) { - for (unsigned int i = 0; i < data.length(); ++i) { - if (data[i] == 13) { // Skip \r - continue; - } else if (data[i] == 10) { // \n found - if (message.substr(0,2).compare("+V") == 0) { - //parent->fwVersion = atoi(message.substr(2).c_str()); - //printf("Firmware version: %s\n", message.substr(2).c_str()); - } else if (message.substr(0,2).compare("+R") == 0) { - Manager *manager = Manager::getInstance(); - manager->parseMessage(message.substr(2), parent); - } - message.clear(); - } else { // Append the character - message.append( 1, data[i] ); - } - } -} diff --git a/telldus-core/driver/libtelldus-core/TellStickDuo.h b/telldus-core/driver/libtelldus-core/TellStickDuo.h deleted file mode 100644 index 48486e29..00000000 --- a/telldus-core/driver/libtelldus-core/TellStickDuo.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// C++ Interface: controller -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLSTICKDUO_H -#define TELLSTICKDUO_H - -#include "TellStick.h" -#include "ftd2xx.h" - -/** - @author Micke Prag -*/ -namespace TelldusCore { - class PrivateTellStickDuoListener; - class TellStickDuoPrivate; - - class TellStickDuo : public TellStick { - friend class PrivateTellStickDuoListener; - friend class TellStick; - - public: - ~TellStickDuo(); - -// virtual int firmwareVersion(); -// virtual int send( const std::string &message ); - - bool connected() const; - - protected: - TellStickDuo(const TellStickDescriptor &d); - - private: - TellStickDuoPrivate *d; - }; -} - -#endif diff --git a/telldus-core/driver/libtelldus-core/Thread.cpp b/telldus-core/driver/libtelldus-core/Thread.cpp deleted file mode 100644 index 2420a593..00000000 --- a/telldus-core/driver/libtelldus-core/Thread.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// -// C++ Implementation: Thread -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#include "Thread.h" - -using namespace TelldusCore; - -class TelldusCore::ThreadPrivate { -public: -#ifdef _WINDOWS - HANDLE thread; - DWORD threadId; - HANDLE noEvent, noWait; -#else - pthread_t thread; - pthread_cond_t noEvent, noWait; -#endif - MUTEX mutex; - - //Must be locked by the mutex! - bool hasEvent; - std::string strMessage; - int intMessage; -}; - -Thread::Thread() { - d = new ThreadPrivate; - initMutex(&d->mutex); - - lockMutex(&d->mutex); - d->hasEvent = false; - unlockMutex(&d->mutex); - -#ifdef _WINDOWS - d->noEvent = CreateEvent(0, FALSE, FALSE, 0); - d->noWait = CreateEvent(0, FALSE, FALSE, 0); -#else - pthread_cond_init(&d->noEvent, NULL); - pthread_cond_init(&d->noWait, NULL); -#endif -} - -Thread::~Thread() { - destroyMutex(&d->mutex); -#ifdef _WINDOWS - CloseHandle(d->noEvent); - CloseHandle(d->noWait); -#else - pthread_cond_destroy(&d->noEvent); - pthread_cond_destroy(&d->noWait); -#endif - delete d; -} - -void Thread::start() { -#ifdef _WINDOWS - d->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Thread::exec, this, 0, &d->threadId); -#else - pthread_create(&d->thread, NULL, &Thread::exec, this ); -#endif -} - -bool Thread::wait() { -#ifdef _WINDOWS - WaitForSingleObject(d->thread, INFINITE); - CloseHandle(d->thread); -#else - pthread_join(d->thread, 0); -#endif - return true; -} - -void *Thread::exec( void *ptr ) { - Thread *t = reinterpret_cast(ptr); - if (t) { - t->run(); - } - return 0; -} - -std::string Thread::waitForEvent(int *intMessage) { - std::string strMessage; - lockMutex(&d->mutex); - while(!d->hasEvent) { -#ifdef _WINDOWS - unlockMutex(&d->mutex); - WaitForSingleObject(d->noWait, INFINITE); - lockMutex(&d->mutex); -#else - pthread_cond_wait(&d->noWait, &d->mutex); -#endif - } - d->hasEvent = false; - strMessage = d->strMessage; - (*intMessage) = d->intMessage; - unlockMutex(&d->mutex); -#ifdef _WINDOWS - SetEvent(d->noEvent); -#else - pthread_cond_broadcast(&d->noEvent); -#endif - return strMessage; -} - -void Thread::sendEvent(const std::string &strMessage, int intMessage) { - lockMutex(&d->mutex); - while (d->hasEvent) { //We have an unprocessed event -#ifdef _WINDOWS - unlockMutex(&d->mutex); - WaitForSingleObject(d->noEvent, INFINITE); - lockMutex(&d->mutex); -#else - pthread_cond_wait(&d->noEvent, &d->mutex); -#endif - } - d->hasEvent = true; - d->strMessage = strMessage; - d->intMessage = intMessage; - unlockMutex(&d->mutex); -#ifdef _WINDOWS - SetEvent(d->noWait); -#else - pthread_cond_broadcast(&d->noWait); -#endif -} - -void Thread::initMutex(MUTEX * m) { -#ifdef _WINDOWS - InitializeCriticalSection(m); -#else - pthread_mutex_init(m, NULL); -#endif -} - -void Thread::destroyMutex(MUTEX * m) { -#ifdef _WINDOWS - DeleteCriticalSection(m); -#else - pthread_mutex_destroy(m); -#endif -} - -void Thread::unlockMutex(MUTEX * m) { -#ifdef _WINDOWS - LeaveCriticalSection(m); -#else - pthread_mutex_unlock(m); -#endif -} - -void Thread::lockMutex(MUTEX * m) { -#ifdef _WINDOWS - EnterCriticalSection(m); -#else - pthread_mutex_lock(m); -#endif -} - - -MutexLocker::MutexLocker(MUTEX *m) - :mutex(m) { - Thread::lockMutex(mutex); -} - -MutexLocker::~MutexLocker() { - Thread::unlockMutex(mutex); -} diff --git a/telldus-core/driver/libtelldus-core/Thread.h b/telldus-core/driver/libtelldus-core/Thread.h deleted file mode 100644 index e557bce4..00000000 --- a/telldus-core/driver/libtelldus-core/Thread.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// C++ Interface: Thread -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef THREAD_H -#define THREAD_H - -#include - -#ifdef _WINDOWS - #include - typedef CRITICAL_SECTION MUTEX; -#else - #include - typedef pthread_mutex_t MUTEX; -#endif - -namespace TelldusCore { - class ThreadPrivate; - class Thread { - public: - Thread(); - virtual ~Thread(); - void start(); - bool wait(); - - void sendEvent(const std::string &string, int integer = 0); - - static void initMutex(MUTEX *m); - static void destroyMutex(MUTEX *m); - static void lockMutex(MUTEX *m); - static void unlockMutex(MUTEX *m); - - protected: - virtual void run() = 0; - std::string waitForEvent(int *intMessage); - - private: - static void* exec( void *ptr ); - ThreadPrivate *d; - }; - - class MutexLocker { - public: - MutexLocker(MUTEX *m); - ~MutexLocker(); - private: - MUTEX *mutex; - }; -} - -#endif diff --git a/telldus-core/driver/libtelldus-core/common.h b/telldus-core/driver/libtelldus-core/common.h deleted file mode 100644 index 5f90ccc1..00000000 --- a/telldus-core/driver/libtelldus-core/common.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// - -#ifdef _WINDOWS -#include "stdafx.h" -#include -#define strcasecmp _stricmp -#define strncasecmp _strnicmp - -#endif -#include -#include - -inline void msleep( const int msec) { -#ifdef _WINDOWS - Sleep(msec); -#else - usleep(msec*1000); -#endif -} - -inline char *wrapStdString( const std::string &string) { -#ifdef _WINDOWS - return (char *)SysAllocStringByteLen(string.c_str(), (unsigned int)string.size()); -#else - char *returnVal = (char *)malloc(sizeof(char) * (string.size()+1)); - strcpy(returnVal, string.c_str()); - return returnVal; -#endif -} diff --git a/telldus-core/driver/libtelldus-core/ftd2xx.h b/telldus-core/driver/libtelldus-core/ftd2xx.h deleted file mode 100644 index ce6405db..00000000 --- a/telldus-core/driver/libtelldus-core/ftd2xx.h +++ /dev/null @@ -1,15 +0,0 @@ - - -#ifdef LIBFTD2XX - #ifdef _WINDOWS - #include "stdafx.h" - #include "win\ftd2xx.h" - #else - #include "osx/WinTypes.h" - #include "osx/ftd2xx.h" - #endif -#endif - -#ifdef LIBFTDI - #include -#endif diff --git a/telldus-core/driver/libtelldus-core/libtelldus-core.def b/telldus-core/driver/libtelldus-core/libtelldus-core.def deleted file mode 100644 index 8932354c..00000000 --- a/telldus-core/driver/libtelldus-core/libtelldus-core.def +++ /dev/null @@ -1,47 +0,0 @@ -LIBRARY tellduscore -EXPORTS - tdGetNumberOfDevices @1 - tdGetDeviceId @2 - - tdGetName @3 - tdGetProtocol @4 - tdGetModel @5 - tdGetDeviceParameter @6 - - tdSetName @7 - tdSetProtocol @8 - tdSetModel @9 - tdSetDeviceParameter @10 - - tdAddDevice @11 - tdRemoveDevice @12 - - tdMethods @13 - tdTurnOn @14 - tdTurnOff @15 - tdBell @16 - tdDim @17 - - tdGetErrorString @18 - - tdClose @19 - - tdInit @20 - tdRegisterDeviceEvent @21 - tdLastSentCommand @22 - tdGetDeviceType @23 - - tdSendRawCommand @24 - tdRegisterRawDeviceEvent @25 - - tdLearn @26 - tdLastSentValue @27 - - tdReleaseString @28 - tdUnregisterCallback @29 - - tdConnectTellStickController @30 - tdDisconnectTellStickController @31 - - tdRegisterDeviceChangeEvent @32 - \ No newline at end of file diff --git a/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj b/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj deleted file mode 100644 index 74af9954..00000000 --- a/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj +++ /dev/null @@ -1,354 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/telldus-core/driver/libtelldus-core/libtelldus-core_service.def b/telldus-core/driver/libtelldus-core/libtelldus-core_service.def deleted file mode 100644 index 7e655d5b..00000000 --- a/telldus-core/driver/libtelldus-core/libtelldus-core_service.def +++ /dev/null @@ -1,43 +0,0 @@ -LIBRARY TelldusCoreLib -EXPORTS - tdGetNumberOfDevices @1 - tdGetDeviceId @2 - - tdGetName @3 - tdGetProtocol @4 - tdGetModel @5 - tdGetDeviceParameter @6 - - tdSetName @7 - tdSetProtocol @8 - tdSetModel @9 - tdSetDeviceParameter @10 - - tdAddDevice @11 - tdRemoveDevice @12 - - tdMethods @13 - tdTurnOn @14 - tdTurnOff @15 - tdBell @16 - tdDim @17 - - tdGetErrorString @18 - - tdClose @19 - - tdInit @20 - tdRegisterDeviceEvent @21 - tdLastSentCommand @22 - tdGetDeviceType @23 - - tdSendRawCommand @24 - tdRegisterRawDeviceEvent @25 - - tdLearn @26 - tdLastSentValue @27 - - tdReleaseString @28 - - tdConnectTellStickController @29 - tdDisconnectTellStickController @30 diff --git a/telldus-core/driver/libtelldus-core/linux/Device.cpp b/telldus-core/driver/libtelldus-core/linux/Device.cpp deleted file mode 100644 index b1f20648..00000000 --- a/telldus-core/driver/libtelldus-core/linux/Device.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "../Device.h" -#include -#include -#include -#include -#include - -using namespace TelldusCore; - -/* -* Send message to the USB dongle -*/ -int Device::send(const std::string &strMessage) { - int fd = -1; - struct termios tio; - char in; - - if( 0 > ( fd = open( strDevice.c_str(), O_RDWR ) ) ) { - if (errno == ENOENT) { - return TELLSTICK_ERROR_NOT_FOUND; - } else if (errno == EACCES) { - return TELLSTICK_ERROR_PERMISSION_DENIED; - } - return TELLSTICK_ERROR_UNKNOWN; - } - - /* adjust serial port parameters */ - bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ - tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ - tio.c_iflag = IGNPAR; - tio.c_oflag = 0; - tcflush(fd, TCIFLUSH); - tcsetattr(fd,TCSANOW,&tio); - - write(fd, strMessage.c_str(), strMessage.length()); - - ssize_t bytes = 0; - int c = 5000; - while(--c) { - bytes = read(fd, &in, 1); - if (bytes > 0) { - if (in == '\n') { - break; - } - } - usleep(1000); //Don't eat 100% cpu - } - - close(fd); - - if (c == 0) { - return TELLSTICK_ERROR_COMMUNICATION; - } - - return TELLSTICK_SUCCESS; -} - -void Device::setDevice(const std::string &device) { - strDevice = device; -} diff --git a/telldus-core/driver/libtelldus-core/osx/WinTypes.h b/telldus-core/driver/libtelldus-core/osx/WinTypes.h deleted file mode 100755 index c37d66ff..00000000 --- a/telldus-core/driver/libtelldus-core/osx/WinTypes.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef __WINDOWS_TYPES__ -#define __WINDOWS_TYPES__ - -#define MAX_NUM_DEVICES 50 -#include - -typedef unsigned long DWORD; -typedef unsigned long ULONG; -typedef unsigned short USHORT; -typedef short SHORT; -typedef unsigned char UCHAR; -typedef unsigned short WORD; -typedef unsigned char BYTE; -typedef unsigned char *LPBYTE; -typedef int BOOL; -typedef char BOOLEAN; -typedef char CHAR; -typedef int *LPBOOL; -typedef unsigned char *PUCHAR; -typedef const char *LPCSTR; -typedef char *PCHAR; -typedef void *PVOID; -typedef void *HANDLE; -typedef long LONG; -typedef int INT; -typedef unsigned int UINT; -typedef char *LPSTR; -typedef char *LPTSTR; -typedef DWORD *LPDWORD; -typedef WORD *LPWORD; -typedef ULONG *PULONG; -typedef PVOID LPVOID; -typedef void VOID; -typedef unsigned long long int ULONGLONG; - -typedef struct _OVERLAPPED { - DWORD Internal; - DWORD InternalHigh; - DWORD Offset; - DWORD OffsetHigh; - HANDLE hEvent; -} OVERLAPPED, *LPOVERLAPPED; - -typedef struct _SECURITY_ATTRIBUTES { - DWORD nLength; - LPVOID lpSecurityDescriptor; - BOOL bInheritHandle; -} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; - -typedef struct timeval SYSTEMTIME; -typedef struct timeval FILETIME; -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -// -// Modem Status Flags -// -#define MS_CTS_ON ((DWORD)0x0010) -#define MS_DSR_ON ((DWORD)0x0020) -#define MS_RING_ON ((DWORD)0x0040) -#define MS_RLSD_ON ((DWORD)0x0080) - -// -// Error Flags -// - -#define CE_RXOVER 0x0001 // Receive Queue overflow -#define CE_OVERRUN 0x0002 // Receive Overrun Error -#define CE_RXPARITY 0x0004 // Receive Parity Error -#define CE_FRAME 0x0008 // Receive Framing error -#define CE_BREAK 0x0010 // Break Detected -#define CE_TXFULL 0x0100 // TX Queue is full -#define CE_PTO 0x0200 // LPTx Timeout -#define CE_IOE 0x0400 // LPTx I/O Error -#define CE_DNS 0x0800 // LPTx Device not selected -#define CE_OOP 0x1000 // LPTx Out-Of-Paper -#define CE_MODE 0x8000 // Requested mode unsupported - -#ifndef INVALID_HANDLE_VALUE -#define INVALID_HANDLE_VALUE 0xFFFFFFFF -#endif - -#endif diff --git a/telldus-core/driver/libtelldus-core/osx/ftd2xx.h b/telldus-core/driver/libtelldus-core/osx/ftd2xx.h deleted file mode 100755 index 67969cfe..00000000 --- a/telldus-core/driver/libtelldus-core/osx/ftd2xx.h +++ /dev/null @@ -1,924 +0,0 @@ -/*++ - -Copyright (c) 2001-2003 Future Technology Devices International Ltd. - -Module Name: - - ftd2xx.h - -Abstract: - - Native USB interface for FTDI FT8U232/245/2232C - FTD2XX library definitions - -Environment: - - kernel & user mode - -Revision History: - - 13/03/01 awm Created. - 13/01/03 awm Added device information support. - 19/03/03 awm Added FT_W32_CancelIo. - 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. - 18/09/03 awm Added FT_SetResetPipeRetryCount. - 10/10/03 awm Added FT_ResetPort. - /03/04 st modified for linux users - 12/10/04 st added FT_SetVIDPID - - ---*/ - - -#ifndef FTD2XX_H -#define FTD2XX_H - -#ifndef _WINDOWS -#include -#define WINAPI -#endif - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// FTD2XX_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef FTD2XX_EXPORTS -#define FTD2XX_API __declspec(dllexport) -#else -#define FTD2XX_API __declspec(dllimport) -#endif - -#ifndef _WINDOWS -#include "WinTypes.h" - -#ifdef FTD2XX_API -#undef FTD2XX_API -#define FTD2XX_API -#endif -#endif -typedef struct _EVENT_HANDLE{ - pthread_cond_t eCondVar; - pthread_mutex_t eMutex; - int iVar; -} EVENT_HANDLE; - -typedef DWORD *FT_HANDLE; -//typedef unsigned int FT_HANDLE; -//typedef struct ftdi_device * FT_HANDLE; - -typedef ULONG FT_STATUS; - -// -// Device status -// -enum { - FT_OK, - FT_INVALID_HANDLE, - FT_DEVICE_NOT_FOUND, - FT_DEVICE_NOT_OPENED, - FT_IO_ERROR, - FT_INSUFFICIENT_RESOURCES, - FT_INVALID_PARAMETER, - FT_INVALID_BAUD_RATE, //7 - - FT_DEVICE_NOT_OPENED_FOR_ERASE, - FT_DEVICE_NOT_OPENED_FOR_WRITE, - FT_FAILED_TO_WRITE_DEVICE, - FT_EEPROM_READ_FAILED, - FT_EEPROM_WRITE_FAILED, - FT_EEPROM_ERASE_FAILED, - FT_EEPROM_NOT_PRESENT, - FT_EEPROM_NOT_PROGRAMMED, - FT_INVALID_ARGS, - FT_NOT_SUPPORTED, - FT_OTHER_ERROR -}; - - -#define FT_SUCCESS(status) ((status) == FT_OK) - -// -// FT_OpenEx Flags -// - -#define FT_OPEN_BY_SERIAL_NUMBER 1 -#define FT_OPEN_BY_DESCRIPTION 2 - -// -// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags -// - -#define FT_LIST_NUMBER_ONLY 0x80000000 -#define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 - -#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) - -// -// Baud Rates -// - -#define FT_BAUD_300 300 -#define FT_BAUD_600 600 -#define FT_BAUD_1200 1200 -#define FT_BAUD_2400 2400 -#define FT_BAUD_4800 4800 -#define FT_BAUD_9600 9600 -#define FT_BAUD_14400 14400 -#define FT_BAUD_19200 19200 -#define FT_BAUD_38400 38400 -#define FT_BAUD_57600 57600 -#define FT_BAUD_115200 115200 -#define FT_BAUD_230400 230400 -#define FT_BAUD_460800 460800 -#define FT_BAUD_921600 921600 - -// -// Word Lengths -// - -#define FT_BITS_8 (UCHAR) 8 -#define FT_BITS_7 (UCHAR) 7 -#define FT_BITS_6 (UCHAR) 6 -#define FT_BITS_5 (UCHAR) 5 - -// -// Stop Bits -// - -#define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_1_5 (UCHAR) 1 -#define FT_STOP_BITS_2 (UCHAR) 2 - -// -// Parity -// - -#define FT_PARITY_NONE (UCHAR) 0 -#define FT_PARITY_ODD (UCHAR) 1 -#define FT_PARITY_EVEN (UCHAR) 2 -#define FT_PARITY_MARK (UCHAR) 3 -#define FT_PARITY_SPACE (UCHAR) 4 - -// -// Flow Control -// - -#define FT_FLOW_NONE 0x0000 -#define FT_FLOW_RTS_CTS 0x0100 -#define FT_FLOW_DTR_DSR 0x0200 -#define FT_FLOW_XON_XOFF 0x0400 - -// -// Purge rx and tx buffers -// -#define FT_PURGE_RX 1 -#define FT_PURGE_TX 2 - -// -// Events -// - -typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); - -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 - -// -// Timeouts -// - -#define FT_DEFAULT_RX_TIMEOUT 300 -#define FT_DEFAULT_TX_TIMEOUT 300 - -// -// Device types -// - -typedef ULONG FT_DEVICE; - -enum { - FT_DEVICE_BM, - FT_DEVICE_AM, - FT_DEVICE_100AX, - FT_DEVICE_UNKNOWN, - FT_DEVICE_2232C, - FT_DEVICE_232R - }; - - -#ifdef __cplusplus -extern "C" { -#endif - -FTD2XX_API -FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - -FTD2XX_API -FT_STATUS FT_SetVIDPID( - DWORD dwVID, - DWORD dwPID - ); - -FTD2XX_API -FT_STATUS FT_GetVIDPID( - DWORD * pdwVID, - DWORD * pdwPID - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten - ); - -FTD2XX_API -FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); - -// -// structure to hold program data for FT_Program function -// -typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232C extensions - // 2 = FT232R extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // FT2232C extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // FT232R extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - - UCHAR RIsVCP; // zero if using VCP drivers - -} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA lpData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA lpData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - -FTD2XX_API -FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - - -// -// Win32-type functions -// - -FTD2XX_API -FT_HANDLE WINAPI FT_W32_CreateFile( - LPCSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); - - -// -// Win32 COMM API type functions -// -typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; -} FTCOMSTAT, *LPFTCOMSTAT; - -typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ -} FTDCB, *LPFTDCB; - -typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ -} FTTIMEOUTS,*LPFTTIMEOUTS; - - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - -FTD2XX_API -BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); - -// -// Device information -// - -typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; -} FT_DEVICE_LIST_INFO_NODE; - -FTD2XX_API -FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDriverVersion( - FT_HANDLE ftHandle, - LPDWORD lpdwVersion - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLibraryVersion( - LPDWORD lpdwVersion - ); - -// -// Events -// - -#define EV_RXCHAR 0x0001 // Any Character received -#define EV_RXFLAG 0x0002 // Received certain character -#define EV_TXEMPTY 0x0004 // Transmitt Queue Empty -#define EV_CTS 0x0008 // CTS changed state -#define EV_DSR 0x0010 // DSR changed state -#define EV_RLSD 0x0020 // RLSD changed state -#define EV_BREAK 0x0040 // BREAK received -#define EV_ERR 0x0080 // Line status error occurred -#define EV_RING 0x0100 // Ring signal detected -#define EV_PERR 0x0200 // Printer error occured -#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full -#define EV_EVENT1 0x0800 // Provider specific event 1 -#define EV_EVENT2 0x1000 // Provider specific event 2 - -// -// Escape Functions -// - -#define SETXOFF 1 // Simulate XOFF received -#define SETXON 2 // Simulate XON received -#define SETRTS 3 // Set RTS high -#define CLRRTS 4 // Set RTS low -#define SETDTR 5 // Set DTR high -#define CLRDTR 6 // Set DTR low -#define RESETDEV 7 // Reset device if possible -#define SETBREAK 8 // Set the device break line. -#define CLRBREAK 9 // Clear the device break line. - -// -// PURGE function flags. -// -#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. -#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. -#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. -#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. - -#ifdef __cplusplus -} -#endif - - -#endif /* FTD2XX_H */ - - - - - - diff --git a/telldus-core/driver/libtelldus-core/stdafx.cpp b/telldus-core/driver/libtelldus-core/stdafx.cpp deleted file mode 100644 index 54385d7a..00000000 --- a/telldus-core/driver/libtelldus-core/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// testruntelldus3.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/telldus-core/driver/libtelldus-core/stdafx.h b/telldus-core/driver/libtelldus-core/stdafx.h deleted file mode 100644 index 5df7bbe1..00000000 --- a/telldus-core/driver/libtelldus-core/stdafx.h +++ /dev/null @@ -1,37 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -// Modify the following defines if you have to target a platform prior to the ones specified below. -// Refer to MSDN for the latest info on corresponding values for different platforms. -#ifndef WINVER // Allow use of features specific to Windows XP or later. -#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later. -#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. -#endif - -#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later. -#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE. -#endif - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include - -// C RunTime Header Files -#include -#include -#include -#include - - -// TODO: reference additional headers your program requires here diff --git a/telldus-core/driver/libtelldus-core/telldus-core-service.h b/telldus-core/driver/libtelldus-core/telldus-core-service.h deleted file mode 100644 index e554759f..00000000 --- a/telldus-core/driver/libtelldus-core/telldus-core-service.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef TELLDUSCORESERVICE_H -#define TELLDUSCORESERVICE_H - -#define TELLDUSCORE_STATIC -#include "telldus-core.h" - -#ifdef __cplusplus -extern "C" { -#endif - TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); - TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); -#ifdef __cplusplus -} -#endif - -#endif //TELLDUSCORESERVICE_H diff --git a/telldus-core/driver/libtelldus-core/telldus-core.conf b/telldus-core/driver/libtelldus-core/telldus-core.conf deleted file mode 100644 index 71f45b3d..00000000 --- a/telldus-core/driver/libtelldus-core/telldus-core.conf +++ /dev/null @@ -1,11 +0,0 @@ -deviceNode = "/dev/tellstick" -device { - id = 1 - name = "Example device" - protocol = "arctech" - model = "codeswitch" - parameters { - house = "A" - unit = "1" - } -} diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp deleted file mode 100644 index 6c36e46b..00000000 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ /dev/null @@ -1,644 +0,0 @@ -/** - * @defgroup core telldus-core - * Telldus Core is the base module used to interface a Telldus TellStick. - * @{ - */ - -#include "telldus-core.h" -#include "Manager.h" -#include "Device.h" -#include "DeviceGroup.h" -#include "DeviceUndefined.h" -#ifdef TELLSTICK_DUO - #include "TellStickDuo.h" -#endif -#include "common.h" -#include -#include -#include -#include -#include - -void handleException(std::exception e); -using namespace std; -using namespace TelldusCore; - - -/** - * @def TELLSTICK_TURNON - * Device-flag for devices supporting the tdTurnOn() call. - * - * @def TELLSTICK_TURNOFF - * Device-flag for devices supporting the tdTurnOff() call. - * - * @def TELLSTICK_BELL - * Device-flag for devices supporting the tdBell() call. - * - * @def TELLSTICK_TOGGLE - * This method is currently unimplemented. - * - * @def TELLSTICK_DIM - * Device-flag for devices supporting the tdDim() call. - * - * @def TELLSTICK_LEARN - * Device-flag for devices supporting the tdLearn() call. - * - * @def TELLSTICK_TYPE_DEVICE - * Device type of a single device. - * - * @def TELLSTICK_TYPE_GROUP - * Device type of a device which contains other devices. - * - * @def TELLSTICK_SUCCESS - * Error code. Returned when the command succeeded. - * - * @def TELLSTICK_ERROR_NOT_FOUND - * Error code. Returned if a TellStick was not found on the system. - * - * @def TELLSTICK_ERROR_PERMISSION_DENIED - * Error code. Returned if the user doesn't have privileges to open - * the TellStick device. - * - * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND - * Error code. The supplied device id was not found. - * - * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - * Error code. The requested method is not supported by the device. - * This should be avoided by a call to tdMethods(). - * - * @def TELLSTICK_ERROR_COMMUNICATION - * Error code. An error occurred when communicating with TellStick. - * - * @def TELLSTICK_ERROR_CONNECTING_SERVICE - * Error code. The client library could not connect to the service. - * Maybe it is not running? - * - * @def TELLSTICK_ERROR_UNKNOWN_RESPONSE - * Error code. The client library received a response from the service - * it did not understand. - * - * @def TELLSTICK_ERROR_UNKNOWN - * Error code. An unkown error has occurred. - */ - -#define MAX_LOADSTRING 100 - -void WINAPI tdInit(void) { - Manager::getInstance(); //Create the manager-object -} - -int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - Manager *manager = Manager::getInstance(); - return manager->registerDeviceEvent( eventFunction, context ); -} - -int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { - Manager *manager = Manager::getInstance(); - return manager->registerRawDeviceEvent( eventFunction, context ); -} - -int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { - Manager *manager = Manager::getInstance(); - return manager->registerDeviceChangeEvent( eventFunction, context ); -} - - -/** - * Close the library and clean up the cache it uses. - * This should be called when the library is not supposed to be used anymore - **/ -void WINAPI tdClose(void) { - Manager::close(); -} - -/** - * This method releases resources allocated by telldus-core. - * It should be called on the returned value from all functions return char * - **/ -void WINAPI tdReleaseString(char *string) { -#ifdef _WINDOWS - SysFreeString((BSTR)string); -#else - free(string); -#endif -} - - -/** - * Turns a device on. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to turn on. - **/ -int WINAPI tdTurnOn(int intDeviceId){ - - try{ - Manager *manager = Manager::getInstance(); - return manager->switchState(intDeviceId, TELLSTICK_TURNON); - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Turns a device off. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to turn off. - */ -int WINAPI tdTurnOff(int intDeviceId){ - - try{ - Manager *manager = Manager::getInstance(); - return manager->switchState(intDeviceId, TELLSTICK_TURNOFF); - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Sends bell command to devices supporting this. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to send bell to - */ -int WINAPI tdBell(int intDeviceId){ - - try{ - Manager *manager = Manager::getInstance(); - return manager->switchState( intDeviceId, TELLSTICK_BELL ); - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Dims a device. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to dim - * @param level The level the device should dim to. This value should be 0-255 - */ -int WINAPI tdDim(int intDeviceId, unsigned char level){ - try{ - Manager *manager = Manager::getInstance(); - - if (level == 0) { - return manager->switchState( intDeviceId, TELLSTICK_TURNOFF ); - } else if (level == 255) { - return manager->switchState( intDeviceId, TELLSTICK_TURNON ); - } else { - return manager->switchState( intDeviceId, TELLSTICK_DIM, (char *)&level); - } - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Sends a special learn command to some devices that need a special learn-command - * to be used from TellStick - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to learn. - */ -int WINAPI tdLearn(int intDeviceId) { - - try{ - Manager *manager = Manager::getInstance(); - return manager->switchState(intDeviceId, TELLSTICK_LEARN); - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Returns the last sent command to a specific device - * @param intDeviceId The device id to query - * @param methodsSupported The methods supported by the client. See tdMethods() for more information. - * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF - */ -int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ) { - Manager *manager = Manager::getInstance(); - int lastSentCommand = Device::maskUnsupportedMethods(manager->getDeviceState( intDeviceId ), methodsSupported); - - if (lastSentCommand == TELLSTICK_BELL) { - //Bell is not a state - lastSentCommand = TELLSTICK_TURNOFF; - } - if (lastSentCommand == 0) { - lastSentCommand = TELLSTICK_TURNOFF; - } - return lastSentCommand; -} - -/** - * If the last sent command it TELLSTICK_DIM this returns the dimmed value. - * @param intDeviceId The device id to query - * @returns the the value as a human readable string, example "128" for 50% - */ -char * WINAPI tdLastSentValue( int intDeviceId ) { - Manager *manager = Manager::getInstance(); - std::string strReturn = manager->getDeviceStateValue( intDeviceId ); - return wrapStdString(strReturn); -} - -/** - * This function returns the number of devices configured - * @returns an integer of the total number of devices configured - */ -int WINAPI tdGetNumberOfDevices(void){ - int intReturn = -1; - try{ - Manager *manager = Manager::getInstance(); - intReturn = manager->getNumberOfDevices(); - } - catch(exception e){ - intReturn = -1; - handleException(e); - } - return intReturn; -} - -/** - * This function returns the unique id of a device with a specific index. - * To get all the id numbers you should loop over all the devices: - * \code - * int intNumberOfDevices = tdGetNumberOfDevices(); - * for (int i = 0; i < intNumberOfDevices; i++) { - * int id = tdGetDeviceId( i ); - * // id now contains the id number of the device with index of i - * } - * \endcode - * @param intDeviceIndex The device index to query. The index starts from 0. - * @returns the unique id for the device or -1 if the device is not found. - */ -int WINAPI tdGetDeviceId(int intDeviceIndex){ - int intReturn = -1; - try{ - Manager *manager = Manager::getInstance(); - intReturn = manager->getDeviceId(intDeviceIndex); - } - catch(exception e){ - intReturn = -1; - handleException(e); - } - return intReturn; -} - -/** - * Returns which type the device is. The device could be either - * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP - */ -int WINAPI tdGetDeviceType(int intDeviceId) { - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if (dev != NULL) { - DeviceGroup *deviceGroup = dynamic_cast(dev); - if (deviceGroup) { - return TELLSTICK_TYPE_GROUP; - } - } - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_TYPE_DEVICE; -} - -/** - * Query a device for it's name. - * @param intDeviceId The unique id of the device to query - * @returns The name of the device or an empty string if the device is not found. - */ -char * WINAPI tdGetName(int intDeviceId){ - std::string strReturn = ""; - try { - Manager *manager = Manager::getInstance(); - Device *dev = manager->getDevice( intDeviceId ); - if (dev != NULL) { - strReturn = dev->getName(); - } - } - catch(exception e){ - strReturn = ""; - handleException(e); - } - return wrapStdString(strReturn); -} - -/** - * Sets a new name for a device. The devices are global for all application, changing - * this will change the name for other applications aswell. - * @param intDeviceId The device id to change the name for - * @param strNewName The new name for the devices - * @returns \c true on success, \c false otherwise. - */ -bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ - bool blnSuccess = false; - try{ - Manager *manager = Manager::getInstance(); - Device *dev = manager->getDevice( intDeviceId ); - if (dev != NULL) { - blnSuccess = dev->setName(strNewName); - } - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -/** - * @returns the protocol used by a specific device. - * @param intDeviceId The device id to query. - */ -char* WINAPI tdGetProtocol(int intDeviceId){ - std::string strReturn = ""; - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if (dev != NULL) { - strReturn = dev->getProtocol(); - } - } - catch(exception e){ - handleException(e); - } - return wrapStdString(strReturn); -} - -/** - * This changes the current protocol used by a device. After changing the protocol, - * setting new parameters is required. - * @param intDeviceId The device to change. - * @param strProtocol The new protocol to use. - * @returns \c true on success, \c false otherwise. - * @sa tdSetModel() - * @sa tdSetDeviceParameter() - */ -bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ - bool blnSuccess = false; - try{ - Manager *manager = Manager::getInstance(); - blnSuccess = manager->setDeviceProtocol(intDeviceId, strProtocol); - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -/** - * @returns the model for a device. Not all protocols uses this. - * @param intDeviceId The device to query. - */ -char* WINAPI tdGetModel(int intDeviceId){ - std::string strReturn = ""; - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if (dev != NULL) { - strReturn = dev->getFullModel(); - } - } - catch(exception e){ - handleException(e); - } - return wrapStdString(strReturn); -} - -/** - * Sets a new model for a device. Which model to set depends on the - * current protocol. - * @param intDeviceId The device to change - * @param strModel The new model - * @returns \c true on success, \c false otherwise. - */ -bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ - bool blnSuccess = false; - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if (dev != NULL) { - blnSuccess = dev->setModel(strModel); - } - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -/** - * Sets a new protocol specific parameter. Please see the documentation of the protocols - * before setting any parameter. - * @param intDeviceId The device to change. - * @param strName The parameter to change. - * @param strValue The new value for the parameter. - * @returns \c true on success, \c false otherwise. - */ -bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ - - try{ - Manager *manager = Manager::getInstance(); - Device *dev = manager->getDevice( intDeviceId ); - if (dev != NULL) { - return dev->setParameter(strName, strValue); - } - } - catch(exception e){ - handleException(e); - } - return false; -} - -/** - * @returns any protocol specific parameter specified by \c strName - * @param intDeviceId The device to query. - * @param strName The name of the parameter to query. - * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. - */ -char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ - std::string strReturn = ""; - try{ - Manager *manager = Manager::getInstance(); - strReturn = manager->getDeviceParameter(intDeviceId, strName); - if (strReturn.empty()) { - strReturn = defaultValue; - } - } - catch(exception e){ - handleException(e); - } - return wrapStdString(strReturn); -} - -/** - * Add a new device to the global database of devices. This function must be called first before - * any call to tdSetName(), tdSetProtocol() and similar functions. - * @returns the new device id for the newly created device. If the creation fails it returnes a - * negative value. - */ -int WINAPI tdAddDevice(){ - int intNewDeviceId = -1; - try{ - Manager *manager = Manager::getInstance(); - intNewDeviceId = manager->addDevice(); - } - catch(exception e){ - intNewDeviceId = -1; - handleException(e); - } - return intNewDeviceId; -} - -/** - * Removes a device. - * @returns \c true on success, \c false otherwise. - */ -bool WINAPI tdRemoveDevice(int intDeviceId){ - bool blnSuccess = false; - try{ - Manager *manager = Manager::getInstance(); - blnSuccess = manager->removeDevice(intDeviceId); - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -/** - * Query a device for which methods it supports. By supplying the methods you support - * the library could remap the methods a device support for better fit the application. - * Example of querying a device supporting TELLSTICK_BELL: - * \code - * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); - * //methods is now TELLSTICK_BELL - * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); - * //methods is now TELLSTICK_TURNON because the client application doesn't support TELLSTICK_BELL - * \endcode - * @param id The device id to query - * @param methodsSupported The methods the client application supports - * @returns The method-flags OR'ed into an integer. - * @sa TELLSTICK_TURNON - * @sa TELLSTICK_TURNOFF - * @sa TELLSTICK_BELL - * @sa TELLSTICK_TOGGLE - * @sa TELLSTICK_DIM - */ -int WINAPI tdMethods(int id, int methodsSupported){ - - int intMethods = 0; - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(id); - if (dev != NULL) { - intMethods = dev->methods(); - } - } - catch(exception e){ - intMethods = 0; - handleException(e); - } - intMethods = Device::maskUnsupportedMethods(intMethods, methodsSupported); //Strip the methods not supported by client. - return intMethods; -} - -/** - * Get a human readable string from an error code returned - * from a function in telldus-core. - * @param intErrorNo The error code to translate. - * @returns a string ready to show to the user. - * @sa TELLSTICK_SUCCESS - * @sa TELLSTICK_ERROR_NOT_FOUND - * @sa TELLSTICK_ERROR_PERMISSION_DENIED - * @sa TELLSTICK_ERROR_DEVICE_NOT_FOUND - * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - * @sa TELLSTICK_ERROR_UNKNOWN - */ -char * WINAPI tdGetErrorString(int intErrorNo) { - const int numResponses = 8; - const char *responses[numResponses] = { - "Success", - "TellStick not found", - "Permission denied", - "Device not found", - "The method you tried to use is not supported by the device", - "An error occurred while communicating with TellStick", - "Could not connect to the Telldus Service", - "Received an unknown response" - }; - std::string strReturn; - intErrorNo = abs(intErrorNo); //We don't use negative values here. - if (intErrorNo >= numResponses) { - strReturn = "Unknown error"; - } else { - // Copy the error string to strReturn - strReturn = responses[intErrorNo]; - } - return wrapStdString(strReturn); -} - -/** - * Send a raw command to TellStick. Please read the TellStick protocol - * definition on how the command should be constructed. - * @param command The command for TellStick in its native format - * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure - */ -int WINAPI tdSendRawCommand(const char *command, int reserved) { - try{ - Manager *manager = Manager::getInstance(); - return manager->sendRawCommand(command); - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - - -void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { - Manager *manager = Manager::getInstance(); - manager->connectTellStickController(vid, pid, serial); -} - -void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { - Manager *manager = Manager::getInstance(); - manager->disconnectTellStickController(vid, pid, serial); -} - -//******** -//* Error management, set strLogName to "" to turn off -//* -void handleException(exception e){ - -// std::string strLogName = "errorlog.txt"; - std::string strLogName = ""; - - if(strLogName.length() > 0){ - ofstream errorfile(strLogName.c_str(), ios::app); - if(errorfile){ - errorfile << e.what() << endl; - errorfile.close(); - } - } -} - -/*\@}*/ diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h deleted file mode 100644 index 1fa84fe7..00000000 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef TELLDUSCORE_H -#define TELLDUSCORE_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// TELLSTICK_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef _WINDOWS - #if defined(TELLDUSCORE_STATIC) - #define TELLSTICK_API - #elif defined(TELLDUSCORE_EXPORTS) - #define TELLSTICK_API __declspec(dllexport) - #else - #define TELLSTICK_API __declspec(dllimport) - #endif - #define WINAPI __stdcall -#else - #define WINAPI - #define TELLSTICK_API -#endif - -typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); -typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); -typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); - -#ifndef __cplusplus - #define bool char -#endif - -#ifdef __cplusplus -extern "C" { -#endif - TELLSTICK_API void WINAPI tdInit(void); - TELLSTICK_API int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); - TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); - TELLSTICK_API void WINAPI tdClose(void); - TELLSTICK_API void WINAPI tdReleaseString(char *string); - - TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); - TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); - TELLSTICK_API int WINAPI tdBell(int intDeviceId); - TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); - TELLSTICK_API int WINAPI tdLearn(int intDeviceId); - TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); - TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); - TELLSTICK_API char *WINAPI tdLastSentValue( int intDeviceId ); - - TELLSTICK_API int WINAPI tdGetNumberOfDevices(); - TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); - TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); - - TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); - - TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); - TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); - TELLSTICK_API char * WINAPI tdGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, const char *intModel); - - TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); - TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); - - TELLSTICK_API int WINAPI tdAddDevice(); - TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); - - TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); - - TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); - TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); - -#ifdef __cplusplus -} -#endif - -//Device methods -#define TELLSTICK_TURNON 1 -#define TELLSTICK_TURNOFF 2 -#define TELLSTICK_BELL 4 -#define TELLSTICK_TOGGLE 8 -#define TELLSTICK_DIM 16 -#define TELLSTICK_LEARN 32 - -//Error codes -#define TELLSTICK_SUCCESS 0 -#define TELLSTICK_ERROR_NOT_FOUND -1 -#define TELLSTICK_ERROR_PERMISSION_DENIED -2 -#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 -#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 -#define TELLSTICK_ERROR_COMMUNICATION -5 -#define TELLSTICK_ERROR_CONNECTING_SERVICE -6 -#define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7 -#define TELLSTICK_ERROR_UNKNOWN -99 - -//Device typedef -#define TELLSTICK_TYPE_DEVICE 1 -#define TELLSTICK_TYPE_GROUP 2 - -//Device changes -#define TELLSTICK_DEVICE_ADDED 1 -#define TELLSTICK_DEVICE_CHANGED 2 -#define TELLSTICK_DEVICE_REMOVED 3 -#define TELLSTICK_DEVICE_STATE_CHANGED 4 - -//Change types -#define TELLSTICK_CHANGE_NAME 1 -#define TELLSTICK_CHANGE_PROTOCOL 2 -#define TELLSTICK_CHANGE_MODEL 3 - -#endif diff --git a/telldus-core/driver/libtelldus-core/tellstick.conf b/telldus-core/driver/libtelldus-core/tellstick.conf deleted file mode 100644 index 71f45b3d..00000000 --- a/telldus-core/driver/libtelldus-core/tellstick.conf +++ /dev/null @@ -1,11 +0,0 @@ -deviceNode = "/dev/tellstick" -device { - id = 1 - name = "Example device" - protocol = "arctech" - model = "codeswitch" - parameters { - house = "A" - unit = "1" - } -} diff --git a/telldus-core/driver/libtelldus-core/win/Device.cpp b/telldus-core/driver/libtelldus-core/win/Device.cpp deleted file mode 100644 index de840037..00000000 --- a/telldus-core/driver/libtelldus-core/win/Device.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "../Device.h" -#include -#include -#include -#include -#include - -#include "../ftd2xx.h" - -int getDongleIndex(); - -using namespace TelldusCore; - -/* -* Send message to the USB dongle -*/ -int Device::send(const std::string &strMessage){ - - try{ - FT_STATUS ftStatus = FT_OK; - FT_HANDLE fthHandle = 0; - char in; - - int intDongleIndex = getDongleIndex(); - if (intDongleIndex < 0) { - return TELLSTICK_ERROR_NOT_FOUND; - } - - ftStatus = FT_Open(intDongleIndex, &fthHandle); - int intBaudRate = 4800; //always 4800 - ftStatus = FT_SetBaudRate(fthHandle, intBaudRate); - FT_SetTimeouts(fthHandle,5000,0); - ULONG bytesWritten, bytesRead; - - char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); - memcpy(tempMessage, strMessage.data(), strMessage.length()); - ftStatus = FT_Write(fthHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten); - free(tempMessage); - - bool c = true; - while(c) { - ftStatus = FT_Read(fthHandle,&in,1,&bytesRead); - if (ftStatus == FT_OK) { - if (bytesRead == 1) { - if (in == '\n') { - break; - } - } else { //Timeout - c = false; - } - } else { //Error - c = false; - } - } - - ftStatus = FT_Close(fthHandle); - - if (!c) { - return TELLSTICK_ERROR_COMMUNICATION; - } - } - catch(...){ - throw; - } - return TELLSTICK_SUCCESS; -} - -/* -* Get the device index of the Telldus dongle (the first one if many are connected) -* -1 if no such device exists -*/ -int getDongleIndex(){ - int intReturn = -1; - FT_HANDLE fthHandle = 0; - FT_STATUS ftStatus = FT_OK; - - try{ - DWORD dwNumberOfDevices = 0; - -#ifndef _WINDOWS - FT_SetVIDPID(0x1781, 0x0C30); -#endif - ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); - if (ftStatus == FT_OK) { - for (int i = 0; i < (int)dwNumberOfDevices; i++) { - - FT_PROGRAM_DATA pData; - char ManufacturerBuf[32]; - char ManufacturerIdBuf[16]; - char DescriptionBuf[64]; - char SerialNumberBuf[16]; - - pData.Signature1 = 0x00000000; - pData.Signature2 = 0xffffffff; - pData.Version = 0x00000002; // EEPROM structure with FT232R extensions - pData.Manufacturer = ManufacturerBuf; - pData.ManufacturerId = ManufacturerIdBuf; - pData.Description = DescriptionBuf; - pData.SerialNumber = SerialNumberBuf; - - ftStatus = FT_Open(i, &fthHandle); - ftStatus = FT_EE_Read(fthHandle, &pData); - if(ftStatus == FT_OK){ - if(pData.VendorId == 6017 && pData.ProductId == 3120){ - intReturn = i; - ftStatus = FT_Close(fthHandle); - break; - } - } - ftStatus = FT_Close(fthHandle); - } - } - } - catch(...){ - throw; - } - return intReturn; -} - diff --git a/telldus-core/driver/libtelldus-core/win/ftd2xx.h b/telldus-core/driver/libtelldus-core/win/ftd2xx.h deleted file mode 100755 index 96a4d318..00000000 --- a/telldus-core/driver/libtelldus-core/win/ftd2xx.h +++ /dev/null @@ -1,963 +0,0 @@ -/*++ - -Copyright (c) 2001-2007 Future Technology Devices International Ltd. - -Module Name: - - ftd2xx.h - -Abstract: - - Native USB device driver for FTDI FT8U232/245 - FTD2XX library definitions - -Environment: - - kernel & user mode - -Revision History: - - 13/03/01 awm Created. - 13/01/03 awm Added device information support. - 19/03/03 awm Added FT_W32_CancelIo. - 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. - 18/09/03 awm Added FT_SetResetPipeRetryCount. - 10/10/03 awm Added FT_ResetPort. - 23/01/04 awm Added support for open-by-location. - 16/03/04 awm Added support for FT2232C. - 23/09/04 awm Added support for FT232R. - 20/10/04 awm Added FT_CyclePort. - 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. - 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. - 25/08/05 awm Added FT_SetDeadmanTimeout. - 02/12/05 awm Removed obsolete references. - 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. - 08/09/06 awm Added FT_W32_GetCommMask. - 11/09/06 awm Added FT_Rescan. - 11/07/07 awm Added support for FT2232H and FT4232H. - 10/08/07 awm Added flags definitions. - 21/11/07 mja Added FT_GetComPortNumber. - 05/06/08 mja Added EEPROM extensions for FT2232H. - - ---*/ - - -#ifndef FTD2XX_H -#define FTD2XX_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// FTD2XX_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef FTD2XX_EXPORTS -#define FTD2XX_API __declspec(dllexport) -#else -#define FTD2XX_API __declspec(dllimport) -#endif - - -typedef PVOID FT_HANDLE; -typedef ULONG FT_STATUS; - -// -// Device status -// -enum { - FT_OK, - FT_INVALID_HANDLE, - FT_DEVICE_NOT_FOUND, - FT_DEVICE_NOT_OPENED, - FT_IO_ERROR, - FT_INSUFFICIENT_RESOURCES, - FT_INVALID_PARAMETER, - FT_INVALID_BAUD_RATE, - - FT_DEVICE_NOT_OPENED_FOR_ERASE, - FT_DEVICE_NOT_OPENED_FOR_WRITE, - FT_FAILED_TO_WRITE_DEVICE, - FT_EEPROM_READ_FAILED, - FT_EEPROM_WRITE_FAILED, - FT_EEPROM_ERASE_FAILED, - FT_EEPROM_NOT_PRESENT, - FT_EEPROM_NOT_PROGRAMMED, - FT_INVALID_ARGS, - FT_NOT_SUPPORTED, - FT_OTHER_ERROR, - FT_DEVICE_LIST_NOT_READY, -}; - - -#define FT_SUCCESS(status) ((status) == FT_OK) - -// -// FT_OpenEx Flags -// - -#define FT_OPEN_BY_SERIAL_NUMBER 1 -#define FT_OPEN_BY_DESCRIPTION 2 -#define FT_OPEN_BY_LOCATION 4 - -// -// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags -// - -#define FT_LIST_NUMBER_ONLY 0x80000000 -#define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 - -#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) - -// -// Baud Rates -// - -#define FT_BAUD_300 300 -#define FT_BAUD_600 600 -#define FT_BAUD_1200 1200 -#define FT_BAUD_2400 2400 -#define FT_BAUD_4800 4800 -#define FT_BAUD_9600 9600 -#define FT_BAUD_14400 14400 -#define FT_BAUD_19200 19200 -#define FT_BAUD_38400 38400 -#define FT_BAUD_57600 57600 -#define FT_BAUD_115200 115200 -#define FT_BAUD_230400 230400 -#define FT_BAUD_460800 460800 -#define FT_BAUD_921600 921600 - -// -// Word Lengths -// - -#define FT_BITS_8 (UCHAR) 8 -#define FT_BITS_7 (UCHAR) 7 -#define FT_BITS_6 (UCHAR) 6 -#define FT_BITS_5 (UCHAR) 5 - -// -// Stop Bits -// - -#define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_1_5 (UCHAR) 1 -#define FT_STOP_BITS_2 (UCHAR) 2 - -// -// Parity -// - -#define FT_PARITY_NONE (UCHAR) 0 -#define FT_PARITY_ODD (UCHAR) 1 -#define FT_PARITY_EVEN (UCHAR) 2 -#define FT_PARITY_MARK (UCHAR) 3 -#define FT_PARITY_SPACE (UCHAR) 4 - -// -// Flow Control -// - -#define FT_FLOW_NONE 0x0000 -#define FT_FLOW_RTS_CTS 0x0100 -#define FT_FLOW_DTR_DSR 0x0200 -#define FT_FLOW_XON_XOFF 0x0400 - -// -// Purge rx and tx buffers -// -#define FT_PURGE_RX 1 -#define FT_PURGE_TX 2 - -// -// Events -// - -typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); - -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 -#define FT_EVENT_LINE_STATUS 4 - -// -// Timeouts -// - -#define FT_DEFAULT_RX_TIMEOUT 300 -#define FT_DEFAULT_TX_TIMEOUT 300 - -// -// Device types -// - -typedef ULONG FT_DEVICE; - -enum { - FT_DEVICE_BM, - FT_DEVICE_AM, - FT_DEVICE_100AX, - FT_DEVICE_UNKNOWN, - FT_DEVICE_2232C, - FT_DEVICE_232R, - FT_DEVICE_2232H, - FT_DEVICE_4232H -}; - - -#ifdef __cplusplus -extern "C" { -#endif - - -FTD2XX_API -FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToRead, - LPDWORD lpBytesReturned - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToWrite, - LPDWORD lpBytesWritten - ); - -FTD2XX_API -FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); - -// -// structure to hold program data for FT_Program function -// -typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232C extensions - // 2 = FT232R extensions - // 3 = FT2232H extensions - // 4 = FT4232H extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 (FT232B) extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // Rev 5 (FT2232) extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // Rev 6 (FT232R) extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR RIsD2XX; // non-zero if using D2XX driver - // - // Rev 7 (FT2232H) Extensions - // - UCHAR PullDownEnable7; // non-zero if pull down enabled - UCHAR SerNumEnable7; // non-zero if serial number to be used - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial - UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial - UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // - // Rev 8 (FT4232H) Extensions - // - UCHAR PullDownEnable8; // non-zero if pull down enabled - UCHAR SerNumEnable8; // non-zero if serial number to be used - UCHAR ASlowSlew; // non-zero if AL pins have slow slew - UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if AH pins have slow slew - UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if BL pins have slow slew - UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if BH pins have slow slew - UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers - -} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDeadmanTimeout( - FT_HANDLE ftHandle, - ULONG ulDeadmanTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - -FTD2XX_API -FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_CyclePort( - FT_HANDLE ftHandle - ); - - -// -// Win32-type functions -// - -FTD2XX_API -FT_HANDLE WINAPI FT_W32_CreateFile( - LPCTSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); - - -// -// Win32 COMM API type functions -// -typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; -} FTCOMSTAT, *LPFTCOMSTAT; - -typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ -} FTDCB, *LPFTDCB; - -typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ -} FTTIMEOUTS,*LPFTTIMEOUTS; - - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - -FTD2XX_API -BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommMask( - FT_HANDLE ftHandle, - LPDWORD lpdwEventMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); - - -// -// Device information -// - -typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; -} FT_DEVICE_LIST_INFO_NODE; - -// Device information flags -enum { - FT_FLAGS_OPENED = 1, - FT_FLAGS_HISPEED = 2 -}; - - -FTD2XX_API -FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); - - -// -// Version information -// - -FTD2XX_API -FT_STATUS WINAPI FT_GetDriverVersion( - FT_HANDLE ftHandle, - LPDWORD lpdwVersion - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLibraryVersion( - LPDWORD lpdwVersion - ); - - -FTD2XX_API -FT_STATUS WINAPI FT_Rescan( - void - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Reload( - WORD wVid, - WORD wPid - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetComPortNumber( - FT_HANDLE ftHandle, - LPLONG lpdwComPortNumber - ); - - - -#ifdef __cplusplus -} -#endif - - -#endif /* FTD2XX_H */ - diff --git a/telldus-core/rfcmd/CMakeLists.txt b/telldus-core/rfcmd/CMakeLists.txt deleted file mode 100644 index af4b4484..00000000 --- a/telldus-core/rfcmd/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -cmake_minimum_required(VERSION 2.4) - -INCLUDE_DIRECTORIES( - /usr/src/linux/include -) - -#### Project: rfcmd #### - -PROJECT(rfcmd) - -SET(rfcmd_DESCRIPTION - "Sends RF remote commands through a Telldus TellStick" -) - -SET(rfcmd_SRCS - rfcmd.c -) - -IF(${RFCMD_DEBUG}) - ADD_DEFINITIONS( -DRFCMD_DEBUG ) -ENDIF(${RFCMD_DEBUG}) - -IF (BUILD_RFCMD_WITH_LIBFTDI) - ADD_DEFINITIONS( -DLIBFTDI ) - - SET(rfcmd_SRCS - ${rfcmd_SRCS} - ftdi.c - ) -ENDIF (BUILD_RFCMD_WITH_LIBFTDI) -ADD_EXECUTABLE(rfcmd - ${rfcmd_SRCS} -) - -IF (BUILD_RFCMD_WITH_SEMAPHORES) - FIND_LIBRARY(SEM_LIBRARY rt) - TARGET_LINK_LIBRARIES(rfcmd - ${SEM_LIBRARY} - ) -ELSE (BUILD_RFCMD_WITH_SEMAPHORES) - ADD_DEFINITIONS( -DNO_SEMAPHORES ) -ENDIF (BUILD_RFCMD_WITH_SEMAPHORES) - - - -IF (BUILD_RFCMD_WITH_LIBFTDI) - FIND_LIBRARY(FTDI_LIBRARY ftdi) - - TARGET_LINK_LIBRARIES(rfcmd - ${FTDI_LIBRARY} - ) -ENDIF (BUILD_RFCMD_WITH_LIBFTDI) - -INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) - -IF (UNIX) - IF (GENERATE_MAN) - ADD_CUSTOM_COMMAND( - TARGET rfcmd - POST_BUILD - COMMAND help2man -n ${rfcmd_DESCRIPTION} ./rfcmd > rfcmd.1 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating man file rfcmd.1" - ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/rfcmd.1 DESTINATION share/man/man1) - ENDIF (GENERATE_MAN) -ENDIF (UNIX) - -#### Project: find_telldus #### - -IF (BUILD_RFCMD_WITH_LIBFTDI) - PROJECT(find_telldus) - - SET(find_telldus_SRCS - find_telldus.c - ) - - ADD_EXECUTABLE(find_telldus - ${find_telldus_SRCS} - ) - - TARGET_LINK_LIBRARIES(find_telldus - ${FTDI_LIBRARY} - ) - - INSTALL(TARGETS find_telldus RUNTIME DESTINATION bin) - -ENDIF (BUILD_RFCMD_WITH_LIBFTDI) diff --git a/telldus-core/rfcmd/COPYING b/telldus-core/rfcmd/COPYING deleted file mode 100644 index 60549be5..00000000 --- a/telldus-core/rfcmd/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/telldus-core/rfcmd/Makefile b/telldus-core/rfcmd/Makefile deleted file mode 100644 index 4836075a..00000000 --- a/telldus-core/rfcmd/Makefile +++ /dev/null @@ -1,22 +0,0 @@ - -SRCS= rfcmd.c ftdi.c -CFLAGS=-O2 -Wall -I/usr/local/include -LFLAGS= -L/usr/local/lib -R/usr/local/lib -#linux:LFLAGS=-Wl,-rpath,/usr/local/lib -LIBS= -lftdi -lusb -PROG= rfcmd -FT= find_telldus -OBJS= $(SRCS:.c=.o) -CC= gcc - -all: $(PROG) $(FT) - -$(PROG): $(OBJS) - $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LFLAGS) $(LIBS) - -rfcmd.o: rfcmd.c - -ftdi.o: ftdi.c - -$(FT): $(FT).c - $(CC) $(CFLAGS) -o $@ $(FT).c $(LFLAGS) $(LIBS) diff --git a/telldus-core/rfcmd/build.sh b/telldus-core/rfcmd/build.sh deleted file mode 100644 index fb5100b9..00000000 --- a/telldus-core/rfcmd/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -set -e -make clean || { echo "Warning: make clean failed"; } -make || { echo "make failed"; exit 1; } -make install || { echo "make install failed"; exit 1; } -echo rfcmd built and installed! diff --git a/telldus-core/rfcmd/find_telldus.c b/telldus-core/rfcmd/find_telldus.c deleted file mode 100644 index 5c44915e..00000000 --- a/telldus-core/rfcmd/find_telldus.c +++ /dev/null @@ -1,42 +0,0 @@ -/* find_all.c - - Example for ftdi_usb_find_all() - - This program is distributed under the GPL, version 2 -*/ - -#include -#include - -int main(int argc, char **argv) -{ - int ret, i; - struct ftdi_context ftdic; - struct ftdi_device_list *devlist, *curdev; - char manufacturer[128], description[128]; - - ftdi_init(&ftdic); - - if((ret = ftdi_usb_find_all(&ftdic, &devlist, 0x1781, 0x0c30)) < 0) { - fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); - return EXIT_FAILURE; - } - - printf("Number of FTDI devices (telldus) found: %d\n", ret); - - i = 0; - for (curdev = devlist; curdev != NULL; i++) { - printf("Checking device: %d\n", i); - if((ret = ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) { - fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); - return EXIT_FAILURE; - } - printf("Manufacturer: %s, Description: %s\n\n", manufacturer, description); - curdev = curdev->next; - } - - ftdi_list_free(&devlist); - ftdi_deinit(&ftdic); - - return EXIT_SUCCESS; -} diff --git a/telldus-core/rfcmd/ftdi.c b/telldus-core/rfcmd/ftdi.c deleted file mode 100644 index c229f2cb..00000000 --- a/telldus-core/rfcmd/ftdi.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * TellStick libftdi libusb version - * tested with 0.15 : http://www.intra2net.com/en/developer/libftdi - */ - -#include -#include -#include -#include - -#define BAUD 4800 - -void ftdiCleanup(struct ftdi_context *ctx) { - ftdi_usb_close( ctx ); - ftdi_deinit( ctx ); -} - -/* - * use libftdi and libusb to send command - * no kernel driver needed - */ -int usbWriteFtdi(char *cmdstr) -{ - struct ftdi_context ctx; - int device=0x0c30, vendor=0x1781; - int retrycnt; - int retval = 0; - - if (ftdi_init( &ctx )) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - init error: %s\n", err); - return 1; - } - - retval = ftdi_usb_open(&ctx, vendor, device); - if (retval) { - char *err = ftdi_get_error_string(&ctx); - // FreeBSD says -3 when another rfcmd is running... - // Same on other systems? - if(retval == -3) { - fprintf(stderr, "usb - open error: %s. Is it busy?\n", err); - } else { - fprintf(stderr, "usb - open error: %s\n", err); - } - - ftdi_deinit( &ctx ); - return 2; - } - - if (ftdi_usb_reset( &ctx )) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - reset error: %s\n", err); - retval = 3; - ftdiCleanup(&ctx); - return retval; - } - - if (ftdi_disable_bitbang( &ctx ) || ftdi_set_baudrate(&ctx, BAUD)) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - init failed: %s\n", err); - ftdiCleanup(&ctx); - return 4; - } - - retval = ftdi_write_data( &ctx, cmdstr, strlen(cmdstr) ); - if (retval < 0) { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - write failed: %s\n", err); - ftdiCleanup(&ctx); - return 5; - } else if(retval != strlen(cmdstr)) { - fprintf(stderr, "usb - warning: %d bytes written instead of %d\n", - retval, (int)strlen(cmdstr)); - } - - /** - * Wait for Tellstick to be done with cmd, read back until we've received - * a \n indicating end of response. - * Wait max 5000 * 1000uS. - * XXX: Can the tellstick report errors? - */ - retval = 0; - retrycnt = 5000; - while (retrycnt--) { - unsigned char inb; - int bytes; - - bytes = ftdi_read_data(&ctx, &inb, 1); - if (bytes == 0) { - usleep(1000); - } else if (bytes > 0) { - // Done when newline is received - if(inb == '\n') { - ftdiCleanup(&ctx); - return retval; - } - } else { - char *err = ftdi_get_error_string(&ctx); - fprintf(stderr, "usb - read error: %s\n", err); - ftdiCleanup(&ctx); - return 6; - } - } - - // if we get here we failed to readback - fprintf(stderr, "usb - warning: never got newline response, giving up on wait\n"); - return retval; -} - - diff --git a/telldus-core/rfcmd/rfcmd.c b/telldus-core/rfcmd/rfcmd.c deleted file mode 100644 index 608b7d67..00000000 --- a/telldus-core/rfcmd/rfcmd.c +++ /dev/null @@ -1,566 +0,0 @@ -/**************************************************************************** - ** rfcmd.c *********************************************************** - **************************************************************************** - * - * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick - * USB interface - * - * Copyright (C) 2007 Tord Andersson - * - * License: GPL v. 2 - * - * Authors: - * Tord Andersson - * Micke Prag - * Gudmund Berggren - * - * Tapani Rintala / userspace libusb / libftdi - version 02-2009 - */ - -/******************************************************************************* - * Modifications from rfcmd.c ver 0.2 done by Gudmund - * Added support for IKEA - * Note: - * 1. System code - * 2. Level 0 == Off (For dimmers and non dimmers) - * Level 1== 10%. (for dimmers) - * .... - * Level 9 == 90 % (for dimmers) - * Level 10 == 100 % (or ON for non dimmers) - * 3. Command line syntax: - * /usr/local/bin/rfcmd /dev/ttyUSB0 IKEA 0 1 10 1" - * Arg 1: device - * Arg 2: Protocoll - * Arg 3: System code - * Arg 4: Device code - * Arg 5: Level (0=off, 1 = 10%, 2=20%,...9=90%, 10=100%) - * Arg 6: DimStyle (0=instant change, 1=gradually change) - ******************************************************************************/ - -/******************************************************************************* - * Modifications to rfcmd.c ver 2.1.0 done by Tord Andersson - * Introduced semaphore protection to avoid problems with simultaneous port - * access from several processes (typically cron jobs). Note! Need rt lib. - ******************************************************************************/ - -/******************************************************************************* - * Modifications from rfcmd.c ver 2.1.0 done by Leo - * Added support for RISINGSUN - * Note: - * 1. Command line syntax: - * /usr/local/bin/rfcmd /dev/ttyUSB0 RISINGSUN 4 1 0" - * Arg 1: device - * Arg 2: protocol - * Arg 3: code - * Arg 4: device number - * Arg 5: Level (0=off, 1 = on) - ******************************************************************************/ - -/******************************************************************************* - * Modifications from rfcmd ver 2.1.1 done by Johan Ström - * Default disabled semaphores for FreeBSD. - * Added status readback in ftdi.c, instead of wasting time in sleep. - * - * FreeBSD does not have support in the GENERIC kernel semaphore. - * To enable usage of them, you'll have have the following option in your - * kernel configuration: - * - * options P1003_1B_SEMAPHORES - * - * However, on FreeBSD only libftdi seems to be working (at least on my system), - * since the device is not identified as a ucom device. And as we're accessing it - * via libftdi, libftdi makes sure simultaneous access is impossible. - ******************************************************************************/ - - -#include -#include -#include -#include -#include -#include - -#ifndef NO_SEMAPHORES -#include -#endif - -#define PROG_NAME "rfcmd" -#define PROG_VERSION "2.1.1" -/* #define RFCMD_DEBUG */ - -/* Local function declarations */ -int createNexaString(const char * pHouseStr, const char * pChannelStr, - const char * pOn_offStr, char * pTxStr, int waveman); -int createSartanoString(const char * pChannelStr, const char * pOn_offStr, - char * pTxStr); -int createIkeaString(const char * pSystemStr, const char * pChannelStr, - const char * pLevelStr, const char *pDimStyle, - char * pStrReturn); -int createRisingSunString(const char * pCodeStr, const char* pUnitStr, const char * pOn_offStr, - char * pTxStr); - -void printUsage(void); -void printVersion(void); - -#ifdef LIBFTDI -int usbWriteFtdi(char *cmdstr); -#endif - -int main( int argc, char **argv ) -{ - struct termios tio; - int fd = -1; -#ifndef NO_SEMAPHORES - sem_t * portMutex; - char SEM_NAME[]= "RFCMD_SEM"; /* Semaphore for multiple access ctrl */ -#endif - - - char txStr[100]; - - if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) { - if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) { - if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) { - printUsage(); - exit(1); - } - } else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) { - if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) { - // System, Channel, Level, DimStyle, TXString - if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc == 6) && (strcmp(*(argv+2),"RISINGSUN")==0) ) { - // Code, Unit, Power - if ( createRisingSunString(*(argv+3), *(argv+4), *(argv+5), txStr) == 0 ) { - printUsage(); - exit(1); - } - /* else - a send cmd string was created */ - } else if ( (argc >= 2) && (strcmp(*(argv+1),"--version")==0) ) { - printVersion(); - exit(1); - } else { /* protocol or parameters not recognized */ - printUsage(); - exit(1); - } - -#ifdef RFCMD_DEBUG - printf("txStr: %s\n", txStr); - -#endif - - if(strlen(txStr) > 0) { -#ifndef NO_SEMAPHORES - /* create the semaphore - will reuse an existing one if it exists */ - portMutex = sem_open(SEM_NAME,O_CREAT,0644,1); - if( portMutex == SEM_FAILED) { - fprintf(stderr, "%s - Error creating port semaphore\n", PROG_NAME); - perror("Semaphore open error"); - sem_unlink(SEM_NAME); - exit(1); - } - - /* lock semaphore to protect port from multiple access */ - if(sem_wait(portMutex) != 0) { - fprintf(stderr, "%s - Error aquiring port semaphore\n", PROG_NAME); - sem_unlink(SEM_NAME); - sem_close(portMutex); - exit(1); - } -#endif - - - if (strcmp(*(argv+1), "LIBUSB") != 0) { - if( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) { -#ifdef __FreeBSD__ - fprintf(stderr, "%s - Error opening %s; You're on a FreeBSD system, you should probably use LIBUSB.\n", PROG_NAME, *(argv+1)); -#else - fprintf(stderr, "%s - Error opening %s\n", PROG_NAME, *(argv+1)); -#endif -#ifndef NO_SEMAPHORES - if(sem_post(portMutex) != 0) { - fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME); - } - sem_unlink(SEM_NAME); - sem_close(portMutex); -#endif - exit(1); - } - - /* adjust serial port parameters */ - bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ - tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ - tio.c_iflag = IGNPAR; - tio.c_oflag = 0; - tio.c_ispeed = 4800; - tio.c_ospeed = 4800; - tcflush(fd, TCIFLUSH); - tcsetattr(fd,TCSANOW,&tio); - - write(fd, txStr, strlen(txStr)); - - sleep(1); /* one second sleep to avoid device 'choking' */ - close(fd); /* Modified : Close fd to make a clean exit */ - } else { -#ifdef LIBFTDI - usbWriteFtdi( txStr ); -#else - fprintf(stderr, "%s - Support for libftdi is not compiled in, please recompile rfcmd with support for libftdi\n", PROG_NAME); -#endif - } -#ifndef NO_SEMAPHORES - /* Unlock semaphore */ - if (sem_post(portMutex) != 0) { - fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME); - sem_unlink(SEM_NAME); - sem_close(portMutex); - exit(1); - } else { - sem_unlink(SEM_NAME); - sem_close(portMutex); - } -#endif - } - exit(0); -} - - -int createNexaString(const char * pHouseStr, const char * pChannelStr, - const char * pOn_offStr, char * pTxStr, int waveman) -{ - * pTxStr = '\0'; /* Make sure tx string is empty */ - int houseCode; - int channelCode; - int on_offCode; - int txCode = 0; - const int unknownCode = 0x6; - int bit; - int bitmask = 0x0001; - - houseCode = (int)((* pHouseStr) - 65); /* House 'A'..'P' */ - channelCode = atoi(pChannelStr) - 1; /* Channel 1..16 */ - on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ - -#ifdef RFCMD_DEBUG - printf("House: %d, channel: %d, on_off: %d\n", houseCode, channelCode, on_offCode); -#endif - - /* check converted parameters for validity */ - if((houseCode < 0) || (houseCode > 15) || // House 'A'..'P' - (channelCode < 0) || (channelCode > 15) || - (on_offCode < 0) || (on_offCode > 1)) - { - - } else { - /* b0..b11 txCode where 'X' will be represented by 1 for simplicity. - b0 will be sent first */ - txCode = houseCode; - txCode |= (channelCode << 4); - if (waveman && on_offCode == 0) { - } else { - txCode |= (unknownCode << 8); - txCode |= (on_offCode << 11); - } - - /* convert to send cmd string */ - strcat(pTxStr,"S"); - for(bit=0;bit<12;bit++) - { - if((bitmask & txCode) == 0) { - /* bit timing might need further refinement */ - strcat(pTxStr," ` `"); /* 320 us high, 960 us low, 320 us high, 960 us low */ - /* strcat(pTxStr,"$k$k"); *//* 360 us high, 1070 us low, 360 us high, 1070 us low */ - } else { /* add 'X' (floating bit) */ - strcat(pTxStr," `` "); /* 320 us high, 960 us low, 960 us high, 320 us low */ - /*strcat(pTxStr,"$kk$"); *//* 360 us high, 1070 us low, 1070 us high, 360 us low */ - } - bitmask = bitmask<<1; - } - /* add stop/sync bit and command termination char '+'*/ - strcat(pTxStr," }+"); - /* strcat(pTxStr,"$}+"); */ - } - -#ifdef RFCMD_DEBUG - printf("txCode: %04X\n", txCode); -#endif - - return strlen(pTxStr); -} - -int createSartanoString(const char * pChannelStr, const char * pOn_offStr, - char * pTxStr) -{ - * pTxStr = '\0'; /* Make sure tx string is empty */ - int on_offCode; - int bit; - - on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ - -#ifdef RFCMD_DEBUG - printf("Channel: %s, on_off: %d\n", pChannelStr, on_offCode); -#endif - - /* check converted parameters for validity */ - if((strlen(pChannelStr) != 10) || - (on_offCode < 0) || (on_offCode > 1)) { - } else { - strcat(pTxStr,"S"); - for(bit=0;bit<=9;bit++) - { - if(strncmp(pChannelStr+bit, "1", 1) == 0) { //If it is a "1" - strcat(pTxStr,"$k$k"); - } else { - strcat(pTxStr,"$kk$"); - } - } - if (on_offCode >= 1) - strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code - else - strcat(pTxStr,"$kk$$k$k"); //the "turn off"-code - - /* add stop/sync bit and command termination char '+'*/ - strcat(pTxStr,"$k+"); - } - - return strlen(pTxStr); -} - -int createIkeaString( const char * pSystemStr, const char * pChannelStr, const char * pLevelStr, const char *pDimStyle, char * pStrReturn) -{ - *pStrReturn = '\0'; /* Make sure tx string is empty */ - - const char STARTCODE[] = "STTTTTTª"; - const char TT[] = "TT"; - const char A[] = "ª"; - int systemCode = atoi(pSystemStr) - 1; /* System 1..16 */ - int channelCode = atoi(pChannelStr); /* Channel 1..10 */ - int Level = atoi(pLevelStr); /* off,10,20,..,90,on */ - int DimStyle = atoi(pDimStyle); - int intCode = 0; - int checksum1 = 0; - int checksum2 = 0; - int intFade ; - int i ; - int rawChannelCode = 0; - - /* check converted parameters for validity */ - if ( (channelCode <= 0) || (channelCode > 10) || - (systemCode < 0) || (systemCode > 15) || - (Level < 0) || (Level > 10) || - (DimStyle < 0) || (DimStyle > 1)) - { - return 0; - } - - if (channelCode == 10) { - channelCode = 0; - } - rawChannelCode = (1<<(9-channelCode)); - - strcat(pStrReturn, STARTCODE ) ; //Startcode, always like this; - intCode = (systemCode << 10) | rawChannelCode; - - for ( i = 13; i >= 0; --i) { - if ((intCode>>i) & 1) { - strcat(pStrReturn, TT ); - if (i % 2 == 0) { - checksum2++; - } else { - checksum1++; - } - } else { - strcat(pStrReturn,A); - } - } - - if (checksum1 %2 == 0) { - strcat(pStrReturn, TT ); - } else { - strcat(pStrReturn, A) ; //1st checksum - } - - if (checksum2 %2 == 0) { - strcat(pStrReturn, TT ); - } else { - strcat(pStrReturn, A ) ; //2nd checksum - } - - if (DimStyle == 1) { - intFade = 11 << 4; //Smooth - } else { - intFade = 1 << 4; //Instant - } - - switch ( Level ) - { - case 0 : - intCode = (10 | intFade) ; //Concat level and fade - break; - case 1 : - intCode = (1 | intFade) ; //Concat level and fade - break; - case 2 : - intCode = (2 | intFade) ; //Concat level and fade - break; - case 3 : - intCode = (3 | intFade) ; //Concat level and fade - break; - case 4 : - intCode = (4 | intFade) ; //Concat level and fade - break; - case 5 : - intCode = (5 | intFade) ; //Concat level and fade - break; - case 6 : - intCode = (6 | intFade) ; //Concat level and fade - break; - case 7 : - intCode = (7 | intFade) ; //Concat level and fade - break; - case 8 : - intCode = (8 | intFade) ; //Concat level and fade - break; - case 9 : - intCode = (9 | intFade) ; //Concat level and fade - break; - case 10 : - default : - intCode = (0 | intFade) ; //Concat level and fade - break; - } - - checksum1 = 0; - checksum2 = 0; - - for (i = 0; i < 6; ++i) { - if ((intCode>>i) & 1) { - strcat(pStrReturn, TT); - - if (i % 2 == 0) { - checksum1++; - } else { - checksum2++; - } - } else { - strcat(pStrReturn, A ); - } - } - - if (checksum1 %2 == 0) { - strcat(pStrReturn, TT); - } else { - strcat(pStrReturn, A ) ; //2nd checksum - } - - if (checksum2 %2 == 0) { - strcat(pStrReturn, TT ); - } else { - strcat(pStrReturn, A ) ; //2nd checksum - } - - strcat(pStrReturn, "+"); - - return strlen(pStrReturn); -} - -int createRisingSunString(const char * pCodeStr, const char * pUnitStr, const char * pOn_offStr, - char * pTxStr) -{ - * pTxStr = '\0'; /* Make sure tx string is empty */ - int on_offCode; - int unit; - int code; - int i; - - on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ - code = atoi (pCodeStr); - unit = atoi (pUnitStr); - -#ifdef RFCMD_DEBUG - printf("Code: %s, unit: %s, on_off: %d\n", pCodeStr, pUnitStr, on_offCode); -#endif - - /* check converted parameters for validity */ - if((code < 1) || (code > 4) || - (unit < 1) || (unit > 4) || - (on_offCode < 0) || (on_offCode > 1)) { - } else { - strcat(pTxStr,"S.e"); - for (i = 1; i <= 4; ++i) { - if (i == code) { - strcat (pTxStr, ".e.e"); - } else { - strcat (pTxStr, "e..e"); - } - } - for (i = 1; i <= 4; ++i) { - if (i == unit) { - strcat (pTxStr, ".e.e"); - } else { - strcat (pTxStr, "e..e"); - } - } - - if (on_offCode >= 1) { - strcat(pTxStr,"e..ee..ee..ee..e+"); //the "turn on"-code - } else { - strcat(pTxStr,"e..ee..ee..e.e.e+"); //the "turn off"-code - } - } - - return strlen(pTxStr); -} - - -void printUsage(void) -{ - printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n"); - printf("\n"); -#ifdef LIBFTDI - printf("\t DEVICE: /dev/ttyUSB[0..n] | LIBUSB\n" ); -#else - printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); -#endif - printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA, RISINGSUN\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n"); - printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - SARTANO:\n"); - printf("\t\tCHANNEL: 0000000000..1111111111\n\t\tOFF_ON: 0..1\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - IKEA:\n"); - printf("\t\tSYSTEM: 1..16\n\t\tDEVICE: 1..10\n"); - printf("\t\tDIM_LEVEL: 0..10\n\t\tDIM_STYLE: 0..1\n" ); - printf("\n"); - printf("\t PROTOCOL ARGUMENTS - RISINGSUN:\n"); - printf("\t\tCODE: 1..4\n\t\tDEVICE: 1..4\n"); - printf("\t\tOFF_ON: 0..1\n" ); - printf("\n"); - printf("Report bugs to \n"); -} - -void printVersion(void) { - printf("%s v%s\n", PROG_NAME, PROG_VERSION); - printf("\n"); - printf("Copyright (C) Tord Andersson 2007\n"); - printf("\n"); - printf("Written by:\n"); - printf("Tord Andersson, Micke Prag, Gudmund Berggren, Tapani Rintala\n"); - printf("and Johan Ström\n"); -} - diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt deleted file mode 100644 index b35b2144..00000000 --- a/telldus-core/tdtool/CMakeLists.txt +++ /dev/null @@ -1,52 +0,0 @@ -PROJECT(tdtool) - -cmake_policy(SET CMP0005 NEW) - -SET (tdtool_DESCRIPTION - "a command line utility to control a Telldus TellStick" -) - -SET(tdtool_SRCS - main.cpp -) - -ADD_EXECUTABLE(tdtool - ${tdtool_SRCS} -) - -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/driver -) - -ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) - -IF (WIN32) - FIND_LIBRARY(TELLDUSCORE_LIBRARY TelldusCore) - TARGET_LINK_LIBRARIES(tdtool - ${TELLDUSCORE_LIBRARY} - ) -ELSEIF (APPLE) - TARGET_LINK_LIBRARIES(tdtool - TelldusCore - ) -ELSE (WIN32) - TARGET_LINK_LIBRARIES(tdtool - telldus-core - ) -ENDIF (WIN32) - -IF (UNIX) - IF (GENERATE_MAN) - ADD_CUSTOM_COMMAND( - TARGET tdtool - POST_BUILD - COMMAND help2man -n ${tdtool_DESCRIPTION} ./tdtool > tdtool.1 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating man file tdtool.1" - ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tdtool.1 DESTINATION share/man/man1) - ENDIF (GENERATE_MAN) -ENDIF (UNIX) - -INSTALL(TARGETS tdtool RUNTIME DESTINATION bin) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp deleted file mode 100644 index 583e3b72..00000000 --- a/telldus-core/tdtool/main.cpp +++ /dev/null @@ -1,300 +0,0 @@ -#include -#include -#include -#include -#include "../driver/libtelldus-core/telldus-core.h" - -const int SUPPORTED_METHODS = - TELLSTICK_TURNON | - TELLSTICK_TURNOFF | - TELLSTICK_BELL | - TELLSTICK_DIM; - -void print_usage( char *name ) { - printf("Usage: %s [ options ]\n", name); - printf("\n"); - printf("Options:\n"); - printf(" -[bdefhlnrv] [ --list ] [ --help ]\n"); - printf(" [ --on device ] [ --off device ] [ --bell device ]\n"); - printf(" [ --learn device ]\n"); - printf(" [ --dimlevel level --dim device ]\n"); - printf(" [ --raw input ]\n"); - printf("\n"); - printf(" --list (-l short option)\n"); - printf(" List currently configured devices.\n"); - printf("\n"); - printf(" --help (-h short option)\n"); - printf(" Shows this screen.\n"); - printf("\n"); - printf(" --on device (-n short option)\n"); - printf(" Turns on device. 'device' could either be an integer of the\n"); - printf(" device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --off device (-f short option)\n"); - printf(" Turns off device. 'device' could either be an integer of the\n"); - printf(" device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --dim device (-d short option)\n"); - printf(" Dims device. 'device' could either be an integer of the device-id,\n"); - printf(" or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf(" Note: The dimlevel parameter must be set before using this option.\n"); - printf("\n"); - printf(" --dimlevel level (-v short option)\n"); - printf(" Set dim level. 'level' should an integer, 0-255.\n"); - printf(" Note: This parameter must be set before using dim.\n"); - printf("\n"); - printf(" --bell device (-b short option)\n"); - printf(" Sends bell command to devices supporting this. 'device' could\n"); - printf(" either be an integer of the device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --learn device (-e short option)\n"); - printf(" Sends a special learn command to devices supporting this. This is normaly\n"); - printf(" devices of 'selflearning' type. 'device' could either be an integer\n"); - printf(" of the device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --raw input (-r short option)\n"); - printf(" This command sends a raw command to TellStick.\n"); - printf(" input can be either - or a filename. If input is - the data is\n"); - printf(" taken from stdin, otherwise the data is taken from the supplied filename.\n"); - printf("\n"); - printf(" Example to turn on an ArcTech codeswitch A1:\n"); - printf(" echo 'S$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$kk$$kk$$kk$$}+' | tdtool --raw -\n"); - printf("\n"); - printf("Report bugs to \n"); -} - -void print_version() { - printf("tdtool " VERSION "\n"); - printf("\n"); - printf("Copyright (C) 2009 Telldus Technologies AB\n"); - printf("\n"); - printf("Written by Micke Prag \n"); -} - -void print_device( int index ) { - int intId = tdGetDeviceId(index); - char *name = tdGetName(intId); - printf("%i\t%s\t", intId, name); - tdReleaseString(name); - int lastSentCommand = tdLastSentCommand(intId, SUPPORTED_METHODS); - char *level = 0; - switch(lastSentCommand) { - case TELLSTICK_TURNON: - printf("ON"); - break; - case TELLSTICK_TURNOFF: - printf("OFF"); - break; - case TELLSTICK_DIM: - level = tdLastSentValue(intId); - printf("DIMMED:%s", level); - tdReleaseString(level); - break; - default: - printf("Unknown state"); - } - printf("\n"); -} - -void list_devices() { - int intNum = tdGetNumberOfDevices(); - if (intNum < 0) { - char *errorString = tdGetErrorString(intNum); - fprintf(stderr, "Error fetching devices: %s\n", errorString); - tdReleaseString(errorString); - return; - } - printf("Number of devices: %i\n", intNum); - int i = 0; - while (i < intNum) { - print_device( i ); - i++; - } -} - -int find_device( char *device ) { - int deviceId = atoi(device); - if (deviceId == 0) { //Try to find the id from the name - int intNum = tdGetNumberOfDevices(); - int index = 0; - while (index < intNum) { - int id = tdGetDeviceId(index); - char *name = tdGetName( id ); - if (strcasecmp(name, device) == 0) { - deviceId = id; - tdReleaseString(name); - break; - } - tdReleaseString(name); - index++; - } - } - return deviceId; -} - -void switch_device( bool turnOn, char *device ) { - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } - - char *name = tdGetName( deviceId ); - int deviceType = tdGetDeviceType( deviceId ); - printf("Turning %s %s %i, %s", - (turnOn ? "on" : "off"), - (deviceType == TELLSTICK_TYPE_DEVICE ? "device" : "group"), - deviceId, - name); - tdReleaseString(name); - - int retval = (turnOn ? tdTurnOn( deviceId ) : tdTurnOff( deviceId )); - char *errorString = tdGetErrorString(retval); - - printf(" - %s\n", errorString); - tdReleaseString(errorString); -} - -void dim_device( char *device, int level ) { - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } - if (level < 0 || level > 255) { - printf("Level %i out of range!\n", level); - return; - } - - char *name = tdGetName( deviceId ); - int retval = tdDim( deviceId, (unsigned char)level ); - char *errorString = tdGetErrorString(retval); - printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); - tdReleaseString(name); - tdReleaseString(errorString); -} - -void bell_device( char *device ) { - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } - - char *name = tdGetName( deviceId ); - int retval = tdBell( deviceId ); - char *errorString = tdGetErrorString(retval); - printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); - tdReleaseString(name); - tdReleaseString(errorString); -} - -void learn_device( char *device ) { - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return; - } - - char *name = tdGetName( deviceId ); - int retval = tdLearn( deviceId ); - char *errorString = tdGetErrorString(retval); - printf("Learning device: %i %s - %s\n", deviceId, name, errorString); - tdReleaseString(name); - tdReleaseString(errorString); -} - -void send_raw_command( char *command ) { - const int MAX_LENGTH = 100; - char msg[MAX_LENGTH]; - - if (strcmp(command, "-") == 0) { - fgets(msg, MAX_LENGTH, stdin); - } else { - FILE *fd; - - fd = fopen(command, "r"); - if (fd == NULL) { - printf("Error opening file %s\n", command); - return; - } - fgets(msg, MAX_LENGTH, fd); - } - - int retval = tdSendRawCommand( msg, 0 ); - char *errorString = tdGetErrorString(retval); - printf("Sending raw command: %s\n", errorString); - tdReleaseString(errorString); -} - -int main(int argc, char **argv) -{ - int optch, longindex; - static char optstring[] = "ln:f:d:b:v:e:r:hi"; - static struct option long_opts[] = { - { "list", 0, 0, 'l' }, - { "on", 1, 0, 'n' }, - { "off", 1, 0, 'f' }, - { "dim", 1, 0, 'd' }, - { "bell", 1, 0, 'b' }, - { "dimlevel", 1, 0, 'v' }, - { "learn", 1, 0, 'e' }, - { "raw", 1, 0, 'r' }, - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'i'}, - { 0, 0, 0, 0} - }; - int level = -1; - - if (argc < 2) { - print_usage( argv[0] ); - return -1; - } - - while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) - switch (optch) { - case 'b' : - bell_device( &optarg[0] ); - break; - case 'd' : - if (level >= 0) { - dim_device( &optarg[0], level ); - } - break; - case 'f' : - switch_device(false, &optarg[0]); - break; - case 'h' : - print_usage( argv[0] ); - break; - case 'i' : - print_version( ); - break; - case 'l' : - list_devices(); - break; - case 'n' : - switch_device(true, &optarg[0]); - break; - case 'e' : - learn_device(&optarg[0]); - break; - case 'r' : - send_raw_command(&optarg[0]); - break; - case 'v' : - level = atoi( &optarg[0] ); - break; - default : - print_usage( argv[0] ); - return -1; - } - - tdClose(); //Cleaning up - return 0; -} diff --git a/telldus-core/telldus-service/CMakeLists.txt b/telldus-core/telldus-service/CMakeLists.txt deleted file mode 100644 index 37ae61e2..00000000 --- a/telldus-core/telldus-service/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -PROJECT( telldus-service ) - -CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) - -SET(BUILD_SERVICE TRUE CACHE BOOL "Build the service") -SET(BUILD_CLIENT FALSE CACHE BOOL "Build the client") - -if(BUILD_SERVICE) - ADD_SUBDIRECTORY(service) -endif(BUILD_SERVICE) - -IF (BUILD_CLIENT) - ADD_SUBDIRECTORY(client) -ENDIF (BUILD_CLIENT) - diff --git a/telldus-core/telldus-service/client/CMakeLists.txt b/telldus-core/telldus-service/client/CMakeLists.txt deleted file mode 100644 index e2aa97f9..00000000 --- a/telldus-core/telldus-service/client/CMakeLists.txt +++ /dev/null @@ -1,129 +0,0 @@ -IF(COMMAND cmake_policy) - CMAKE_POLICY(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - -######## Non configurable options ######## -SET( telldus-client_SRCS - main.cpp - Manager.cpp - ../common/Message.cpp - ${CMAKE_SOURCE_DIR}/driver/libtelldus-core/Thread.cpp -) - -SET( telldus-client_HDRS - ${CMAKE_SOURCE_DIR}/driver/libtelldus-core/telldus-core.h - ${CMAKE_SOURCE_DIR}/driver/libtelldus-core/Thread.h -) - -SET( telldus-client_LIBRARIES -) - -INCLUDE_DIRECTORIES( - ${CMAKE_SOURCE_DIR}/driver - ${CMAKE_CURRENT_SOURCE_DIR}/../common -) - -FIND_PACKAGE(Threads) -LIST(APPEND telldus-client_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - - -######## Configurable options for the platform ######## - - -######## Platforms-specific, non configurable ######## - -IF (APPLE) #### Mac OS X #### - SET( telldus-client_TARGET TelldusCore ) - -ELSEIF (WIN32) #### Windows #### - SET( telldus-client_TARGET TelldusCore ) - - CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in - ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc - ) - - SET( telldus-client_SRCS - ${telldus-client_SRCS} - ../../driver/libtelldus-core/libtelldus-core.def - ../common/Socket_win.cpp - ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc - ) - ADD_DEFINITIONS( - -D_WINDOWS - -DTELLDUSCORE_EXPORTS - ) - INCLUDE_DIRECTORIES( - ${CMAKE_SOURCE_DIR}/driver - ${CMAKE_CURRENT_SOURCE_DIR}/../common - ) - ADD_DEFINITIONS( -DUNICODE ) - SET(CMAKE_EXE_LINKER_FLAGS - "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" - ) - -ELSE (APPLE) #### Linux #### - SET( telldus-client_TARGET telldus-core ) - -ENDIF (APPLE) - -IF (NOT WIN32) - SET( telldus-client_SRCS - ${telldus-client_SRCS} - ../common/Socket_unix.cpp - ) - -ENDIF (NOT WIN32) - - -######## Configuring ######## - -ADD_LIBRARY(${telldus-client_TARGET} SHARED - ${telldus-client_SRCS} - ${telldus-client_HDRS} -) -SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - -IF (SIGN_FILE) - #This doesn't work for some reason - ADD_CUSTOM_COMMAND(TARGET ${telldus-client_TARGET} - POST_BUILD - COMMAND signtool.exe - ARGS sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${telldus-client_TARGET}.dll - WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR} - COMMENT "Signing file TelldusCore.dll" - ) -ENDIF (SIGN_FILE) - - -SET_PROPERTY(TARGET ${telldus-client_TARGET} - PROPERTY FRAMEWORK TRUE -) -SET_PROPERTY(TARGET ${telldus-client_TARGET} - PROPERTY PUBLIC_HEADER ${telldus-client_HDRS} -) - -SET_PROPERTY(TARGET ${telldus-client_TARGET} - PROPERTY VERSION ${PACKAGE_VERSION} -) -SET_PROPERTY(TARGET ${telldus-client_TARGET} - PROPERTY SOVERSION ${PACKAGE_SOVERSION} -) - - -TARGET_LINK_LIBRARIES( ${telldus-client_TARGET} ${telldus-client_LIBRARIES} ) - - -SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist -) -IF (APPLE) - SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} - ) -ELSEIF (UNIX) - SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/TelldusClient - ) -ENDIF (APPLE) - diff --git a/telldus-core/telldus-service/client/Manager.cpp b/telldus-core/telldus-service/client/Manager.cpp deleted file mode 100644 index 6f4d3258..00000000 --- a/telldus-core/telldus-service/client/Manager.cpp +++ /dev/null @@ -1,244 +0,0 @@ - -#include "Manager.h" -#include "Message.h" -#include "../common/Socket.h" -#include - -using namespace TelldusService; - -typedef std::list CallbackList; -typedef std::list DeviceChangeCallbackList; -typedef std::list RawCallbackList; - -class ManagerPrivate { -public: - int numberOfDevices; - int lastCallbackId; - Socket s, eventSocket; - MUTEX sMutex; - CallbackList callbacks; - DeviceChangeCallbackList deviceChangeCallbacks; - RawCallbackList rawCallbacks; -}; - -Manager *Manager::instance = 0; - -Manager::Manager(void) - :Thread() -{ - d = new ManagerPrivate; - Thread::initMutex(&d->sMutex); - d->numberOfDevices = -1; - d->lastCallbackId = 0; - -#ifdef _WINDOWS - d->s.connectToServer( "TelldusCoreClient" ); - d->eventSocket.connectToServer( "TelldusCoreEvents" ); -#else - d->s.connectToServer( "/tmp/TelldusCoreClient" ); - d->eventSocket.connectToServer( "/tmp/TelldusCoreEvents" ); -#endif - - start(); -} - -Manager::~Manager(void) { - d->eventSocket.disconnect(); - this->wait(); - Thread::destroyMutex(&d->sMutex); - delete d; -} - -Manager *Manager::getInstance() { - if (Manager::instance == 0) { - Manager::instance = new Manager(); - } - return Manager::instance; -} - - -void Manager::close() { - if (Manager::instance != 0) { - delete Manager::instance; - } -} - -int Manager::numberOfDevices() { - bool ok; - if (d->numberOfDevices >= 0) { - return d->numberOfDevices; - } - Message message("tdGetNumberOfDevices"); - d->numberOfDevices = this->sendAndReceiveInt(message, &ok); - return d->numberOfDevices; -} - -std::string Manager::deviceName(int deviceId) { - bool ok; - Message message("tdGetName"); - message.addArgument(deviceId); - std::string retval = this->sendAndReceiveString(message, &ok); - if (!ok) { - retval = ""; - } - return retval; -} - -int Manager::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - int id = ++d->lastCallbackId; - CallbackStruct callback = {eventFunction, id, context}; - d->callbacks.push_back(callback); - return id; -} - -int Manager::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { - int id = ++d->lastCallbackId; - DeviceChangeCallbackStruct callback = {eventFunction, id, context}; - d->deviceChangeCallbacks.push_back(callback); - return id; -} - -int Manager::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { - int id = ++d->lastCallbackId; - RawCallbackStruct callback = {eventFunction, id, context}; - d->rawCallbacks.push_back(callback); - return id; -} - -bool Manager::unregisterCallback( int callbackId ) { - for(CallbackList::iterator callback_it = d->callbacks.begin(); callback_it != d->callbacks.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - d->callbacks.erase(callback_it); - return true; - } - - for(DeviceChangeCallbackList::iterator callback_it = d->deviceChangeCallbacks.begin(); callback_it != d->deviceChangeCallbacks.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - d->deviceChangeCallbacks.erase(callback_it); - return true; - } - - for(RawCallbackList::iterator callback_it = d->rawCallbacks.begin(); callback_it != d->rawCallbacks.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - d->rawCallbacks.erase(callback_it); - return true; - } - - return false; -} - -void Manager::run() { - while( d->eventSocket.connected() ) { - logMessage("-> OVERLAPPED read"); - std::string data(d->eventSocket.read()); - Message message("Tack"); - d->eventSocket.write(message); - logMessage("<- OVERLAPPED result:"); - logMessage(data); - if (data.length() == 0) { - continue; - } - this->dataReceived(data); - } -} - -void Manager::dataReceived(const std::string &message) { - std::string msg(message); //Copy -// logMessage(QString::fromStdString(msg)); - std::string funcName = Message::takeString(&msg); -// logMessage(QString::fromStdString(funcName)); - if (funcName == "TDDeviceEvent") { - int intDeviceId = Message::takeInt(&msg); - int intDeviceState = Message::takeInt(&msg); - std::string strDeviceStateValue = Message::takeString(&msg); -// logMessage(QString("Sending %1 callbacks").arg(d->callbacks.size())); - for(CallbackList::const_iterator callback_it = d->callbacks.begin(); callback_it != d->callbacks.end(); ++callback_it) { - //logMessage("StartSend"); - (*callback_it).event(intDeviceId, intDeviceState, strDeviceStateValue.c_str(), (*callback_it).id, (*callback_it).context); - //logMessage("SendDone"); - } - } else if (funcName == "TDDeviceChangeEvent") { - int intDeviceId = Message::takeInt(&msg); - int intEvent = Message::takeInt(&msg); - int intChange = Message::takeInt(&msg); - //Clear the cache - d->numberOfDevices = -1; -// logMessage(QString("Number of callbacks %1").arg(d->deviceChangeCallbacks.size())); - for(DeviceChangeCallbackList::const_iterator callback_it = d->deviceChangeCallbacks.begin(); callback_it != d->deviceChangeCallbacks.end(); ++callback_it) { - (*callback_it).event(intDeviceId, intEvent, intChange, (*callback_it).id, (*callback_it).context); - } - } else if (funcName == "TDRawDeviceEvent") { - std::string strData = Message::takeString(&msg); - //logMessage(strData); - int controllerId = Message::takeInt(&msg); - for(RawCallbackList::const_iterator callback_it = d->rawCallbacks.begin(); callback_it != d->rawCallbacks.end(); ++callback_it) { - (*callback_it).event(strData.c_str(), controllerId, (*callback_it).id, (*callback_it).context); - } - } -} - -std::string Manager::send(const Message &message, bool *success) { - (*success) = false; - if (!d->s.connected()) { - Message msg; - msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); - return msg; - } - std::string response; - { - TelldusCore::MutexLocker l(&d->sMutex); -// logMessage(QString("Sending: %1").arg(QString::fromStdString(message))); - response = d->s.readWriteOverlapped(message); - } - if (response.length() > 0) { -// logMessage(QString("Received: %1 from: %2").arg(QString::fromStdString(response).trimmed()).arg(QString::fromStdString(message))); - (*success) = true; - return response; - } - logMessage("Received: empty result"); - Message msg; - msg.addArgument(TELLSTICK_ERROR_UNKNOWN_RESPONSE); - return msg; -} - -std::string Manager::sendAndReceiveString(const TelldusService::Message &msg, bool *success) { - std::string message(send(msg, success)); - return Message::takeString(&message); -} - -int Manager::sendAndReceiveInt(const TelldusService::Message &msg, bool *success) { - std::string message(send(msg, success)); - return Message::takeInt(&message); -} - -//#include -#include -#include -#include -//#include -void Manager::logMessage( const std::string &message) { -#ifdef _WINDOWS - return; - static bool firstRun = true; - std::ofstream file; - std::string filename("C:/log_client.txt"); - if (firstRun) { - file.open(filename.c_str(), std::ios::out); - firstRun = false; - } else { - file.open(filename.c_str(), std::ios::out | std::ios::app); - } - - file << message << "\n"; - file.flush(); - file.close(); -#else - qDebug() << message; -#endif -} diff --git a/telldus-core/telldus-service/client/Manager.h b/telldus-core/telldus-service/client/Manager.h deleted file mode 100644 index e3c8bf4f..00000000 --- a/telldus-core/telldus-service/client/Manager.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef MANAGER_H -#define MANAGER_H - -#include "Message.h" -#include -#include - -class ManagerPrivate; - -struct CallbackStruct { - TDDeviceEvent event; - int id; - void *context; -}; -struct DeviceChangeCallbackStruct { - TDDeviceChangeEvent event; - int id; - void *context; -}; -struct RawCallbackStruct { - TDRawDeviceEvent event; - int id; - void *context; -}; - - -class Manager : public TelldusCore::Thread { -public: - ~Manager(void); - - static Manager *getInstance(); - static void close(); - - std::string send(const TelldusService::Message &msg, bool *success); - std::string sendAndReceiveString(const TelldusService::Message &msg, bool *success); - int sendAndReceiveInt(const TelldusService::Message &msg, bool *success); - - int numberOfDevices(); - std::string deviceName(int deviceId); - - int registerDeviceEvent( TDDeviceEvent eventFunction, void *context ); - int registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ); - int registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); - bool unregisterCallback( int callbackId ); - - static void logMessage( const std::string &message); - -protected: - void run(); - -private: - Manager(void); - void dataReceived(const std::string &msg); - - ManagerPrivate *d; - static Manager *instance; -}; - -#endif //MANAGER_H diff --git a/telldus-core/telldus-service/client/main.cpp b/telldus-core/telldus-service/client/main.cpp deleted file mode 100644 index 49b8963e..00000000 --- a/telldus-core/telldus-service/client/main.cpp +++ /dev/null @@ -1,295 +0,0 @@ - -#include -#include -#include -#include - -#include "Manager.h" - -using namespace TelldusService; - -void WINAPI tdInit(void) { - Manager::getInstance(); //Create the manager-object -} - -int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - Manager *manager = Manager::getInstance(); - return manager->registerDeviceEvent( eventFunction, context ); -} - -int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { - Manager *manager = Manager::getInstance(); - return manager->registerDeviceChangeEvent( eventFunction, context ); -} - -int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { - Manager *manager = Manager::getInstance(); - return manager->registerRawDeviceEvent( eventFunction, context ); -} - -int WINAPI tdUnregisterCallback( int callbackId ) { - Manager *manager = Manager::getInstance(); - return manager->unregisterCallback( callbackId ); -} - -void WINAPI tdClose(void) { - Manager::close(); -} - -void WINAPI tdReleaseString(char *string) { -#ifdef _WINDOWS - SysFreeString((BSTR)string); -#else - free(string); -#endif -} - -int WINAPI tdTurnOn(int intDeviceId){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdTurnOn"); - message.addArgument(intDeviceId); - return manager->sendAndReceiveInt(message, &ok); -} - -int WINAPI tdTurnOff(int intDeviceId){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdTurnOff"); - message.addArgument(intDeviceId); - return manager->sendAndReceiveInt(message, &ok); -} - -int WINAPI tdBell(int intDeviceId){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdBell"); - message.addArgument(intDeviceId); - return manager->sendAndReceiveInt(message, &ok); -} - -int WINAPI tdDim(int intDeviceId, unsigned char level){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdDim"); - message.addArgument(intDeviceId); - message.addArgument(level); - return manager->sendAndReceiveInt(message, &ok); -} - -int WINAPI tdLearn(int intDeviceId) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdLearn"); - message.addArgument(intDeviceId); - return manager->sendAndReceiveInt(message, &ok); -} - -int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdLastSentCommand"); - message.addArgument(intDeviceId); - message.addArgument(methodsSupported); - return manager->sendAndReceiveInt(message, &ok); -} - -char * WINAPI tdLastSentValue( int intDeviceId ) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdLastSentValue"); - message.addArgument(intDeviceId); - std::string retval = manager->sendAndReceiveString(message, &ok); - if (!ok) { - return wrapStdString("0"); - } - return wrapStdString(retval); -} - -int WINAPI tdGetNumberOfDevices(void){ - //We go through the Manager so we can cache the value - Manager *manager = Manager::getInstance(); - return manager->numberOfDevices(); -} - -int WINAPI tdGetDeviceId(int intDeviceIndex){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdGetDeviceId"); - message.addArgument(intDeviceIndex); - return manager->sendAndReceiveInt(message, &ok); -} - -int WINAPI tdGetDeviceType(int intDeviceId) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdGetDeviceType"); - message.addArgument(intDeviceId); - return manager->sendAndReceiveInt(message, &ok); -} - -char * WINAPI tdGetName(int intDeviceId){ - Manager *manager = Manager::getInstance(); - std::string name = manager->deviceName(intDeviceId); - return wrapStdString(name); -} - -bool WINAPI tdSetName(int intDeviceId, const char* strNewName) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdSetName"); - message.addArgument(intDeviceId); - message.addArgument(strNewName); - int retval = manager->sendAndReceiveInt(message, &ok); - if (!ok) { - return false; - } - return (retval == 1); -} - -char* WINAPI tdGetProtocol(int intDeviceId){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdGetProtocol"); - message.addArgument(intDeviceId); - std::string retval = manager->sendAndReceiveString(message, &ok); - if (!ok) { - retval = "arctech"; - } - return wrapStdString(retval); -} - -bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdSetProtocol"); - message.addArgument(intDeviceId); - message.addArgument(strProtocol); - int retval = manager->sendAndReceiveInt(message, &ok); - if (!ok) { - return false; - } - return (retval == 1); -} - -char* WINAPI tdGetModel(int intDeviceId) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdGetModel"); - message.addArgument(intDeviceId); - std::string retval = manager->sendAndReceiveString(message, &ok); - if (!ok) { - retval = ""; - } - return wrapStdString(retval); -} - -bool WINAPI tdSetModel(int intDeviceId, const char *strModel) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdSetModel"); - message.addArgument(intDeviceId); - message.addArgument(strModel); - int retval = manager->sendAndReceiveInt(message, &ok); - if (!ok) { - return false; - } - return (retval == 1); -} - -bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdSetDeviceParameter"); - message.addArgument(intDeviceId); - message.addArgument(strName); - message.addArgument(strValue); - int retval = manager->sendAndReceiveInt(message, &ok); - if (!ok) { - return false; - } - return (retval == 1); -} - -char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdGetDeviceParameter"); - message.addArgument(intDeviceId); - message.addArgument(strName); - message.addArgument(defaultValue); - std::string retval = manager->sendAndReceiveString(message, &ok); - if (!ok) { - retval = defaultValue; - } - return wrapStdString(retval); -} - -int WINAPI tdAddDevice(){ - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdAddDevice"); - return manager->sendAndReceiveInt(message, &ok); -} - -bool WINAPI tdRemoveDevice(int intDeviceId) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdRemoveDevice"); - message.addArgument(intDeviceId); - return (manager->sendAndReceiveInt(message, &ok) == 1); -} - -int WINAPI tdMethods(int id, int methodsSupported) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdMethods"); - message.addArgument(id); - message.addArgument(methodsSupported); - return manager->sendAndReceiveInt(message, &ok); -} - -char * WINAPI tdGetErrorString(int intErrorNo) { - bool ok; - if (intErrorNo == TELLSTICK_ERROR_CONNECTING_SERVICE) { - //This error cannot be fetched from the service, obviously - return wrapStdString("Could not connect to the Telldus Service"); - } - Manager *manager = Manager::getInstance(); - Message message("tdGetErrorString"); - message.addArgument(intErrorNo); - std::string retval = manager->sendAndReceiveString(message, &ok); - if (!ok) { - retval = "Unknown error"; - } - return wrapStdString(retval); -} - -int WINAPI tdSendRawCommand(const char *command, int reserved) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdSendRawCommand"); - message.addArgument(command); - message.addArgument(reserved); - return manager->sendAndReceiveInt(message, &ok); -} - -void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdConnectTellStickController"); - message.addArgument(vid); - message.addArgument(pid); - message.addArgument(serial); - manager->send(message, &ok); -} - -void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { - bool ok; - Manager *manager = Manager::getInstance(); - Message message("tdDisconnectTellStickController"); - message.addArgument(vid); - message.addArgument(pid); - message.addArgument(serial); - manager->send(message, &ok); -} diff --git a/telldus-core/telldus-service/client/telldus-core.rc.in b/telldus-core/telldus-service/client/telldus-core.rc.in deleted file mode 100644 index 23b37639..00000000 --- a/telldus-core/telldus-service/client/telldus-core.rc.in +++ /dev/null @@ -1,18 +0,0 @@ -#include - -VS_VERSION_INFO VERSIONINFO - FILEVERSION ${PACKAGE_MAJOR_VERSION},${PACKAGE_MINOR_VERSION},${PACKAGE_PATCH_VERSION},0 -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "04090000" - BEGIN - VALUE "FileDescription", "Utilities and driver to control wireless receivers through a TellStick" - VALUE "FileVersion", "${PACKAGE_VERSION}" - VALUE "LegalCopyright", "Copyright (C) 2010 Telldus Technologies AB" - VALUE "OriginalFilename", "TelldusCore.dll" - VALUE "ProductName", "TelldusCore" - VALUE "ProductVersion", "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}" - END - END -END \ No newline at end of file diff --git a/telldus-core/telldus-service/common/Message.cpp b/telldus-core/telldus-service/common/Message.cpp deleted file mode 100644 index 0da67ee5..00000000 --- a/telldus-core/telldus-service/common/Message.cpp +++ /dev/null @@ -1,89 +0,0 @@ - -#include "Message.h" -using namespace TelldusService; -#include -#include -#include - - -/*class MesssagePrivate { -public: -};*/ - -Message::Message() - : std::string() -{ -} - -Message::Message(const std::string &functionName) - :std::string() -{ - this->addArgument(functionName); -} - -Message::~Message(void) { - //delete d; -} - -void Message::addArgument(const std::string &value) { - std::stringstream st; - st << (int)value.size(); - this->append(st.str()); - this->append(":"); - this->append(value); -} - -void Message::addArgument(int value) { - std::stringstream st; - st << (int)value; - this->append("i"); - this->append(st.str()); - this->append("e"); -} - -/*void Message::addArgument(const QVariant &value) { - if (value.type() == QVariant::Int) { - this->addArgument(value.toInt()); - } else { - this->addArgument(value.toByteArray()); - } -}*/ - -void Message::addArgument(const char *value) { - this->addArgument(std::string(value)); -} - -bool Message::nextIsInt(const std::string &message) { - if (message.length() == 0) { - return false; - } - return (message.at(0) == 'i'); -} - -bool Message::nextIsString(const std::string &message) { - if (message.length() == 0) { - return false; - } - return (isdigit(message.at(0)) != 0); -} - -std::string Message::takeString(std::string *message) { - if (!Message::nextIsString(*message)) { - return ""; - } - int index = message->find(':'); - int length = atoi(message->substr(0, index).c_str()); - std::string retval(message->substr(index+1, length)); - message->erase(0, index+length+1); - return retval; -} - -int Message::takeInt(std::string *message) { - if (!Message::nextIsInt(*message)) { - return 0; - } - int index = message->find('e'); - int value = atoi(message->substr(1, index - 1).c_str()); - message->erase(0, index+1); - return value; -} \ No newline at end of file diff --git a/telldus-core/telldus-service/common/Message.h b/telldus-core/telldus-service/common/Message.h deleted file mode 100644 index 38847412..00000000 --- a/telldus-core/telldus-service/common/Message.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MESSAGE_H -#define MESSAGE_H - -#include - -//class MessagePrivate; -namespace TelldusService { - class Message : public std::string { - public: - Message(); - Message(const std::string &); - ~Message(void); - - void addArgument(const std::string &); - void addArgument(int); - //void addArgument(const QVariant &); - void addArgument(const char *); - - static bool nextIsInt(const std::string &); - static bool nextIsString(const std::string &); - - static std::string takeString(std::string *); - static int takeInt(std::string *); - - //MessagePrivate *d; - }; -} - -#endif //MESSAGE_H diff --git a/telldus-core/telldus-service/common/Socket.h b/telldus-core/telldus-service/common/Socket.h deleted file mode 100644 index d74424bf..00000000 --- a/telldus-core/telldus-service/common/Socket.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SOCKET_H -#define SOCKET_H - -#include "Message.h" - -#define BUFSIZE 512 - -#ifdef _WINDOWS - #include - typedef HANDLE SOCKET_T; -#else - typedef unsigned int SOCKET_T; -#endif - -class Socket { -public: - Socket(SOCKET_T socket); - Socket(); - ~Socket(void); - - void connectToServer(const std::string &serverName); - void disconnect(); - void write(const TelldusService::Message &msg); - void writeOverlapped(const TelldusService::Message &msg); - std::string readWriteOverlapped(const TelldusService::Message &msg); - std::string readOverlapped(int timeout = 10000); - std::string read(); - - bool connected() const; - -private: - class PrivateData; - PrivateData *d; -}; - -#endif //SOCKET_H diff --git a/telldus-core/telldus-service/common/Socket_unix.cpp b/telldus-core/telldus-service/common/Socket_unix.cpp deleted file mode 100644 index d6be3efb..00000000 --- a/telldus-core/telldus-service/common/Socket_unix.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "Socket.h" -#include -#include -#include - -// #include - -//Not needed when the class Socket isn't derived from QObject anymore -int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - connect(sockfd, addr, addrlen); -} - -class Socket::PrivateData { -public: - SOCKET_T socket; - bool connected; -}; - -Socket::Socket(SOCKET_T socket) -{ - d = new PrivateData; - d->socket = socket; - d->connected = true; -} - -Socket::Socket() { - d = new PrivateData; - d->socket = -1; - d->connected = false; -} - -Socket::~Socket(void) { - if (d->connected) { - disconnect(); - } - delete d; -} - -void Socket::connectToServer(const std::string &server) { - struct sockaddr_un remote; - socklen_t len; - //QString name = QString("/tmp/%1").arg(server); - - if ((d->socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - return; - } - remote.sun_family = AF_UNIX; - strcpy(remote.sun_path, server.c_str()); - len = SUN_LEN(&remote); - - if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { - return; - } - d->connected = true; -} - -void Socket::disconnect() { - d->connected = false; - close(d->socket); -// emit disconnected(); //TODO:! -} - -void Socket::write(const TelldusService::Message &msg) { - send(d->socket, msg.c_str(), msg.length(), 0); -} - -void Socket::writeOverlapped(const TelldusService::Message &msg) { - this->write(msg); -} - -std::string Socket::readOverlapped(int timeout) { - return this->read(); -} - -std::string Socket::read() { - ssize_t len; - char buf[BUFSIZE]; - - len = recv(d->socket, buf, BUFSIZE, 0); - if (len <= 0) { - return ""; - } - return buf; -} - -std::string Socket::readWriteOverlapped(const TelldusService::Message &msg) { - this->writeOverlapped(msg); - return this->readOverlapped(); -} - -bool Socket::connected() const { - return d->connected; -} diff --git a/telldus-core/telldus-service/common/Socket_win.cpp b/telldus-core/telldus-service/common/Socket_win.cpp deleted file mode 100644 index 56740335..00000000 --- a/telldus-core/telldus-service/common/Socket_win.cpp +++ /dev/null @@ -1,189 +0,0 @@ -#include "Socket.h" -#include -//#include "TelldusCore.h" - -class Socket::PrivateData { -public: - SOCKET_T hPipe; - HANDLE readEvent; - bool connected; -}; - -Socket::Socket(SOCKET_T socket) -{ - d = new PrivateData; - d->hPipe = socket; - d->readEvent = INVALID_HANDLE_VALUE; - d->connected = true; -} - -Socket::Socket() { - d = new PrivateData; - d->hPipe = INVALID_HANDLE_VALUE; - d->readEvent = INVALID_HANDLE_VALUE; - d->connected = false; -} - -Socket::~Socket(void) { - if (d->connected) { - disconnect(); - } - if (d->hPipe != INVALID_HANDLE_VALUE) { - /*TelldusCore::logMessage("Flush file"); - //FlushFileBuffers(d->hPipe); - TelldusCore::logMessage("Cancel Sync"); - CancelSynchronousIo(d->thread); - TelldusCore::logMessage("Disconnect named pipe");*/ - //DisconnectNamedPipe(d->hPipe); - //TelldusCore::logMessage("CloseHandle"); - CloseHandle(d->hPipe); - //TelldusCore::logMessage("Done"); - } - delete d; -} - -void Socket::connectToServer(const std::string &server) { - DWORD dwMode; - bool fSuccess = false; - - //Convert our std::string to std::wstring since we build agains win32 with unicode support - std::string strName = "\\\\.\\pipe\\" + server; - std::wstring name(strName.begin(), strName.end()); - d->hPipe = CreateFile( - name.c_str(), // pipe name - GENERIC_READ | // read and write access - GENERIC_WRITE, - 0, // no sharing - NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - FILE_FLAG_OVERLAPPED, // default attributes - NULL); // no template file - - if (d->hPipe == INVALID_HANDLE_VALUE) { - return; - } - - dwMode = PIPE_READMODE_MESSAGE; - fSuccess = SetNamedPipeHandleState( - d->hPipe, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time - - if (!fSuccess) { - return; - } - - d->connected = true; -} - -void Socket::disconnect() { - d->connected = false; - if (d->readEvent != INVALID_HANDLE_VALUE) { - SetEvent(d->readEvent); - } -} - -void Socket::write(const TelldusService::Message &msg) { - this->writeOverlapped(msg); - /*DWORD bytesWritten = 0; - if (WriteFile(d->hPipe, msg.data(), (DWORD)msg.length(), &bytesWritten, NULL)) { - FlushFileBuffers(d->hPipe); - } else { - d->connected = false; - }*/ -} - -void Socket::writeOverlapped(const TelldusService::Message &msg) { - OVERLAPPED oOverlap; - DWORD bytesWritten = 0; - int result; - bool fSuccess; - - oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - WriteFile(d->hPipe, msg.data(), (DWORD)msg.length(), &bytesWritten, &oOverlap); - - result = WaitForSingleObject(oOverlap.hEvent, 10000); - if (result == WAIT_TIMEOUT) { - CloseHandle(oOverlap.hEvent); - d->connected = false; - return; - } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, false); - CloseHandle(oOverlap.hEvent); - if (!fSuccess) { - d->connected = false; - return; - } -} - -std::string Socket::readOverlapped(int timeout) { - char buf[BUFSIZE]; - int result; - DWORD cbBytesRead = 0; - OVERLAPPED oOverlap; - d->readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - oOverlap.hEvent = d->readEvent; - bool fSuccess = false; - - memset(&buf, 0, BUFSIZE); - - if (!d->connected) { - return ""; - } - - ReadFile( d->hPipe, &buf, sizeof(char)*BUFSIZE, &cbBytesRead, &oOverlap); - - result = WaitForSingleObject(oOverlap.hEvent, timeout); - if (result == WAIT_TIMEOUT) { - CloseHandle(d->readEvent); - d->readEvent = INVALID_HANDLE_VALUE; - return ""; - } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); - if (!fSuccess) { - DWORD err = GetLastError(); - if (err == ERROR_BROKEN_PIPE) { - d->connected = false; - } - buf[0] = 0; - } - CloseHandle(d->readEvent); - d->readEvent = INVALID_HANDLE_VALUE; - return buf; -} - -std::string Socket::readWriteOverlapped(const TelldusService::Message &msg) { - int result; - bool fSuccess = false; - char buf[BUFSIZE]; - DWORD cbBytesRead = 0; - OVERLAPPED oOverlap; - oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - - char *temp = new char[msg.size()+1]; - strcpy_s(temp, msg.size()+1, msg.data()); - - TransactNamedPipe( d->hPipe, temp, (DWORD)msg.length(), &buf, sizeof(char)*BUFSIZE, &cbBytesRead, &oOverlap ); - - result = WaitForSingleObject(oOverlap.hEvent, 10000); - delete temp; - if (result == WAIT_TIMEOUT) { - CloseHandle(oOverlap.hEvent); - return ""; - } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); - CloseHandle(oOverlap.hEvent); - if (!fSuccess) { - return ""; - } - return buf; -} - -std::string Socket::read() { - return this->readOverlapped(INFINITE); -} - -bool Socket::connected() const { - return d->connected; -} \ No newline at end of file diff --git a/telldus-core/telldus-service/service/CMakeLists.txt b/telldus-core/telldus-service/service/CMakeLists.txt deleted file mode 100644 index 1676cee7..00000000 --- a/telldus-core/telldus-service/service/CMakeLists.txt +++ /dev/null @@ -1,138 +0,0 @@ -FIND_PACKAGE( Qt4 REQUIRED ) -SET(QT_USE_QTNETWORK TRUE) -INCLUDE( ${QT_USE_FILE} ) - -IF(COMMAND cmake_policy) - CMAKE_POLICY(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - -######## Non configurable options ######## -SET( telldus-service_SRCS - TelldusCore.cpp - Manager.cpp - ../common/Message.cpp -) -SET( telldus-service_HDRS - ../common/Socket.h -) -SET( telldus-service_MOC_HDRS - TelldusCore.h - Manager.h - MessageReceiver.h - Pipe.h -) - -SET( telldus-service_LIBRARIES - ${QT_LIBRARIES} -) - -INCLUDE_DIRECTORIES( - ${CMAKE_SOURCE_DIR}/driver - ${CMAKE_CURRENT_SOURCE_DIR}/../common -) - -FIND_PACKAGE(Threads) -LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - - -######## Configurable options for the platform ######## - -######## Platforms-specific, non configurable ######## - -IF (APPLE) #### Mac OS X #### - SET( telldus-service_TARGET TelldusService ) - FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) - FIND_LIBRARY(IOKIT_LIBRARY IOKit) - - SET( telldus-service_LIBRARIES - ${telldus-service_LIBRARIES} - ${COREFOUNDATION_LIBRARY} - ${IOKIT_LIBRARY} - TelldusCoreLib - ) - SET( telldus-service_SRCS - ${telldus-service_SRCS} - main_unix.cpp - MessageReceiver_mac.cpp - MessageReceiverPrivate_mac.cpp - ../common/Socket_unix.cpp - Pipe_unix.cpp - ) - SET( telldus-service_MOC_HDRS - ${telldus-service_MOC_HDRS} - MessageReceiverPrivate_mac.h - ) - -ELSEIF (WIN32) #### Windows #### - SET( telldus-service_TARGET TelldusService ) - ADD_DEFINITIONS( -DUNICODE ) - ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No - SET(CMAKE_EXE_LINKER_FLAGS - "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" - ) - SET( telldus-service_LIBRARIES - ${telldus-service_LIBRARIES} - ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCoreLib.lib - ) - SET( telldus-service_SRCS - ${telldus-service_SRCS} - MessageReceiver_win.cpp - Pipe_win.cpp - ../common/Socket_win.cpp - main_win.cpp - TelldusWinService_win.cpp - ) - - SET( telldus-service_MOC_HDRS - ${telldus-service_MOC_HDRS} - TelldusWinService_win.h - ) - -ELSE (APPLE) #### Linux #### - - SET( telldus-service_TARGET telldusd ) - SET( telldus-service_SRCS - ${telldus-service_SRCS} - MessageReceiver_unix.cpp - main_unix.cpp - ../common/Socket_unix.cpp - Pipe_unix.cpp - ) - SET( telldus-service_LIBRARIES - ${telldus-service_LIBRARIES} - telldus-core-lib - ) -ENDIF (APPLE) - -######## QtService ######## - -IF (WIN32) - INCLUDE( ../../3rdparty/qtservice.cmake NO_POLICY_SCOPE ) - SET( telldus-service_SRCS - ${telldus-service_SRCS} - ${qtservice_SRCS} - ) -ENDIF(WIN32) - -######## Configuring ######## - -QT4_WRAP_CPP( telldus-service_MOC_SRCS ${telldus-service_MOC_HDRS} ) - -ADD_EXECUTABLE(${telldus-service_TARGET} - ${telldus-service_SRCS} - ${telldus-service_MOC_SRCS} - ${telldus-service_MOC_HDRS} -) -SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - -TARGET_LINK_LIBRARIES( ${telldus-service_TARGET} ${telldus-service_LIBRARIES} ) - -SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist -) -IF (APPLE) - SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} - ) -ENDIF (APPLE) - diff --git a/telldus-core/telldus-service/service/Manager.cpp b/telldus-core/telldus-service/service/Manager.cpp deleted file mode 100644 index 149fe5b0..00000000 --- a/telldus-core/telldus-service/service/Manager.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include -#include -#include "Manager.h" -#include "Message.h" -#include "Socket.h" - -#include "TelldusCore.h" - -#include - -using namespace TelldusService; - -class ManagerPrivate { -public: - Socket *s; - bool running; -}; - -Manager::Manager(Socket *s, QObject *parent) - :QThread(parent) -{ - //connect(this, SIGNAL(send(const Message &)), this, SLOT(sendMessage())); - d = new ManagerPrivate; - d->s = s; - d->running = true; - connect(this, SIGNAL(finished()), this, SIGNAL(done())); -// connect(d->s, SIGNAL(dataArrived(const QByteArray &)), this, SLOT(dataArrived(const QByteArray &))); - //TelldusCore::logMessage(" Manager created"); - this->start(); -} - -Manager::~Manager(void) { - //TelldusCore::logMessage(" Destroying Manager"); - d->s->disconnect(); - //TelldusCore::logMessage(" Disconnected, waiting"); - wait(); - //TelldusCore::logMessage(" Waited, deleting"); - delete d->s; - delete d; - //TelldusCore::logMessage(" Manager destroyed"); -} - -QVariant Manager::parseMessage(const std::string &message) { - std::string msg(message); //Copy - std::string function(Message::takeString(&msg)); - if (function == "tdTurnOn") { - int intDeviceId = Message::takeInt(&msg); - return tdTurnOn(intDeviceId); - - } else if (function == "tdTurnOff") { - int intDeviceId = Message::takeInt(&msg); - return tdTurnOff(intDeviceId); - - } else if (function == "tdBell") { - int intDeviceId = Message::takeInt(&msg); - return tdBell(intDeviceId); - - } else if (function == "tdDim") { - int intDeviceId = Message::takeInt(&msg); - int level = Message::takeInt(&msg); - return tdDim(intDeviceId, level); - - } else if (function == "tdLearn") { - int intDeviceId = Message::takeInt(&msg); - return tdLearn(intDeviceId); - - } else if (function == "tdLastSentCommand") { - int intDeviceId = Message::takeInt(&msg); - int methodsSupported = Message::takeInt(&msg); - return tdLastSentCommand(intDeviceId, methodsSupported); - - } else if (function == "tdLastSentValue") { - int intDeviceId = Message::takeInt(&msg); - char *value = tdLastSentValue(intDeviceId); - QByteArray retval(value); - tdReleaseString(value); - return retval; - - } else if (function == "tdGetNumberOfDevices") { - return tdGetNumberOfDevices(); - - } else if (function == "tdGetDeviceId") { - int intDeviceIndex = Message::takeInt(&msg); - return tdGetDeviceId(intDeviceIndex); - - } else if (function == "tdGetDeviceType") { - int intDeviceId = Message::takeInt(&msg); - return tdGetDeviceType(intDeviceId); - - } else if (function == "tdGetName") { - int intDeviceId = Message::takeInt(&msg); - char *name = tdGetName(intDeviceId); - QByteArray retval(name); - tdReleaseString(name); - return retval; - - } else if (function == "tdSetName") { - int intDeviceId = Message::takeInt(&msg); - std::string name = Message::takeString(&msg); - return tdSetName(intDeviceId, name.c_str()); - - } else if (function == "tdGetProtocol") { - int intDeviceId = Message::takeInt(&msg); - char *protocol = tdGetProtocol(intDeviceId); - QByteArray retval(protocol); - tdReleaseString(protocol); - return retval; - - } else if (function == "tdSetProtocol") { - int intDeviceId = Message::takeInt(&msg); - std::string protocol = Message::takeString(&msg); - return tdSetProtocol(intDeviceId, protocol.c_str()); - - } else if (function == "tdGetModel") { - int intDeviceId = Message::takeInt(&msg); - char *model = tdGetModel(intDeviceId); - QByteArray retval(model); - tdReleaseString(model); - return retval; - - } else if (function == "tdSetModel") { - int intDeviceId = Message::takeInt(&msg); - std::string model = Message::takeString(&msg); - return tdSetModel(intDeviceId, model.c_str()); - - } else if (function == "tdSetDeviceParameter") { - int intDeviceId = Message::takeInt(&msg); - std::string name = Message::takeString(&msg); - std::string value = Message::takeString(&msg); - return tdSetDeviceParameter(intDeviceId, name.c_str(), value.c_str()); - - } else if (function == "tdGetDeviceParameter") { - int intDeviceId = Message::takeInt(&msg); - std::string name = Message::takeString(&msg); - std::string defaultValue = Message::takeString(&msg); - char *value = tdGetDeviceParameter(intDeviceId, name.c_str(), defaultValue.c_str()); - QByteArray retval(value); - tdReleaseString(value); - return retval; - - } else if (function == "tdAddDevice") { - return tdAddDevice(); - - } else if (function == "tdRemoveDevice") { - int intDeviceId = Message::takeInt(&msg); - return tdRemoveDevice(intDeviceId); - - } else if (function == "tdMethods") { - int intDeviceId = Message::takeInt(&msg); - int intMethodsSupported = Message::takeInt(&msg); - return tdMethods(intDeviceId, intMethodsSupported); - - } else if (function == "tdGetErrorString") { - int intErrorNo = Message::takeInt(&msg); - char *response = tdGetErrorString(intErrorNo); - QByteArray retval(response); - tdReleaseString(response); - return retval; - - } else if (function == "tdSendRawCommand") { - std::string command = Message::takeString(&msg); - int reserved = Message::takeInt(&msg); - return tdSendRawCommand(command.c_str(), reserved); - - } else if (function == "tdConnectTellStickController") { - int vid = Message::takeInt(&msg); - int pid = Message::takeInt(&msg); - std::string serial = Message::takeString(&msg); - tdConnectTellStickController(vid, pid, serial.c_str()); - return ""; - - } else if (function == "tdDisconnectTellStickController") { - int vid = Message::takeInt(&msg); - int pid = Message::takeInt(&msg); - std::string serial = Message::takeString(&msg); - tdDisconnectTellStickController(vid, pid, serial.c_str()); - return ""; - - } - - return 0; -} - -void Manager::run() { - while(1) { - std::string data(d->s->read()); - if (data.length() == 0) { - if (!d->s->connected()) { - return; - } - continue; - } - //TelldusCore::logMessage(data); - QVariant response(this->parseMessage(data)); - Message msg; - if (response.type() == QVariant::Int) { - msg.addArgument(response.toInt()); - } else { - msg.addArgument(response.toString().toStdString()); - } - msg.append("\n"); - d->s->write(msg); - } -} diff --git a/telldus-core/telldus-service/service/Manager.h b/telldus-core/telldus-service/service/Manager.h deleted file mode 100644 index 5c822bbb..00000000 --- a/telldus-core/telldus-service/service/Manager.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef MANAGER_H -#define MANAGER_H - -#include "Message.h" -#include -#include - -class ManagerPrivate; -class Socket; - -class Manager : public QThread { - Q_OBJECT -public: - Manager(Socket *s, QObject *parent); - ~Manager(void); - -protected: - QVariant parseMessage(const std::string &message); - void run(); - -signals: - void done(); - -private: - ManagerPrivate *d; -}; - -#endif //MANAGER_H diff --git a/telldus-core/telldus-service/service/MessageReceiver.h b/telldus-core/telldus-service/service/MessageReceiver.h deleted file mode 100644 index ca9f103a..00000000 --- a/telldus-core/telldus-service/service/MessageReceiver.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MESSAGERECEIVER_H -#define MESSAGERECEIVER_H - -#include - -class MessageReceiverPrivate; - -class MessageReceiver : public QObject { - Q_OBJECT -public: - MessageReceiver(QObject *parent); - ~MessageReceiver(void); - -signals: - void deviceInserted(int vid, int pid, const QString &serial); - void deviceRemoved(int vid, int pid, const QString &serial); - -private: - MessageReceiverPrivate *d; -}; - -#endif //MESSAGERECEIVER_H diff --git a/telldus-core/telldus-service/service/MessageReceiverPrivate_mac.cpp b/telldus-core/telldus-service/service/MessageReceiverPrivate_mac.cpp deleted file mode 100644 index 3c0a45b0..00000000 --- a/telldus-core/telldus-service/service/MessageReceiverPrivate_mac.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "MessageReceiverPrivate_mac.h" - -struct PrivateTellStickData { - io_object_t notification; - CFStringRef serialNumber; - MessageReceiverPrivate *parent; - UInt32 vid; - UInt32 pid; -}; - -MessageReceiverPrivate::MessageReceiverPrivate(QObject *parent) : QThread(parent) { - this->start(); -} - -MessageReceiverPrivate::~MessageReceiverPrivate() { - printf("msgRecieverP cleanup\n"); - CFRunLoopStop(gRunLoop); - printf("Stopped runloop, waiting\n"); - this->wait(); - printf("Wait done\n"); -} - -void MessageReceiverPrivate::run() { - CFMutableDictionaryRef matchingDict; - CFRunLoopSourceRef runLoopSource; - CFNumberRef numberRef; - kern_return_t kr; - long usbVendor = 0x1781; - long usbProduct = 0x0c30; - - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class - // IOUSBDevice and its subclasses - - if (matchingDict == NULL) { - return; - } - - // Create a CFNumber for the idVendor and set the value in the dictionary - numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor); - CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); - CFRelease(numberRef); - - // Create a CFNumber for the idProduct and set the value in the dictionary - numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct); - CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); - CFRelease(numberRef); - numberRef = NULL; - - gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); - runLoopSource = IONotificationPortGetRunLoopSource(gNotifyPort); - - gRunLoop = CFRunLoopGetCurrent(); - CFRunLoopAddSource(gRunLoop, runLoopSource, kCFRunLoopDefaultMode); - - // Now set up a notification to be called when a device is first matched by I/O Kit. - kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort - kIOFirstMatchNotification, // notificationType - matchingDict, // matching - DeviceAdded, // callback - this, // refCon - &gAddedIter // notification - ); - - - // Iterate once to get already-present devices and arm the notification - DeviceAdded(this, gAddedIter); - printf("Starting RunLoop\n"); - CFRunLoopRun(); - printf("Runloop done\n"); -} - -void MessageReceiverPrivate::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { - kern_return_t kr; - - if (messageType != kIOMessageServiceIsTerminated) { - return; - } - - PrivateTellStickData *tsd = reinterpret_cast (refCon); - if (!tsd) { - return; - } - - CFIndex size = CFStringGetLength(tsd->serialNumber); - char *s = new char[size+1]; - CFStringGetCString(tsd->serialNumber, s, size+1, kCFStringEncodingASCII); - QString serial(s); //Copy the string to the stack - delete[] s; - - emit tsd->parent->deviceRemoved(tsd->vid, tsd->pid, serial); - - // Free the data we're no longer using now that the device is going away - CFRelease(tsd->serialNumber); - - kr = IOObjectRelease(tsd->notification); - - delete tsd; -} - -void MessageReceiverPrivate::DeviceAdded(void *refCon, io_iterator_t iterator) { - io_service_t usbDevice; - kern_return_t kr; - - MessageReceiverPrivate *parent = reinterpret_cast (refCon); - - while ((usbDevice = IOIteratorNext(iterator))) { - PrivateTellStickData *tsd = new PrivateTellStickData; - tsd->parent = parent; - - // Get the serial number - CFStringRef serialRef = reinterpret_cast(IORegistryEntryCreateCFProperty( usbDevice, CFSTR("USB Serial Number" ), kCFAllocatorDefault, 0 )); - if (serialRef == NULL) { - //No serial number, we cannot continue. Sorry - continue; - } - - - CFNumberRef vidRef = reinterpret_cast (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idVendor"), kCFAllocatorDefault, 0)); - if (vidRef) { - CFNumberGetValue(vidRef, kCFNumberIntType, &(tsd->vid)); - CFRelease(vidRef); - } - - CFNumberRef pidRef = reinterpret_cast (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idProduct"), kCFAllocatorDefault, 0)); - if (pidRef) { - CFNumberGetValue(pidRef, kCFNumberIntType, &(tsd->pid)); - CFRelease(pidRef); - } - - CFStringRef serialNumberAsCFString = CFStringCreateCopy(kCFAllocatorDefault, serialRef); - tsd->serialNumber = serialNumberAsCFString; - CFRelease(serialRef); - - // Register for an interest notification of this device being removed. Use a reference to our - // private data as the refCon which will be passed to the notification callback. - kr = IOServiceAddInterestNotification(parent->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); - - CFIndex size = CFStringGetLength(serialNumberAsCFString); - char *s = new char[size+1]; - CFStringGetCString(serialNumberAsCFString, s, size+1, kCFStringEncodingASCII); - QString serial(s); //Copy the string to the stack - delete[] s; - - kr = IOObjectRelease(usbDevice); - - emit parent->deviceInserted(tsd->vid, tsd->pid, serial ); - } -} diff --git a/telldus-core/telldus-service/service/MessageReceiverPrivate_mac.h b/telldus-core/telldus-service/service/MessageReceiverPrivate_mac.h deleted file mode 100644 index ecae3b05..00000000 --- a/telldus-core/telldus-service/service/MessageReceiverPrivate_mac.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef MESSAGERECEIVERPRIVATE_H -#define MESSAGERECEIVERPRIVATE_H - -#include - -#include -#include -#include -#include - -#include - -class MessageReceiverPrivate : public QThread { - Q_OBJECT -public: - MessageReceiverPrivate(QObject *parent = 0); - virtual ~MessageReceiverPrivate(); - -signals: - void deviceInserted(int vid, int pid, const QString &serial); - void deviceRemoved(int vid, int pid, const QString &serial); - -protected: - virtual void run(); - -private: - static void DeviceAdded(void *refCon, io_iterator_t iterator); - static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); - - IONotificationPortRef gNotifyPort; - CFRunLoopRef gRunLoop; - io_iterator_t gAddedIter; -}; - -#endif //MESSAGERECEIVERPRIVATE_H diff --git a/telldus-core/telldus-service/service/MessageReceiver_mac.cpp b/telldus-core/telldus-service/service/MessageReceiver_mac.cpp deleted file mode 100644 index dfcd7f6a..00000000 --- a/telldus-core/telldus-service/service/MessageReceiver_mac.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "MessageReceiver.h" -#include "TelldusCore.h" - -#include "MessageReceiverPrivate_mac.h" - -MessageReceiver::MessageReceiver(QObject *parent) - :QObject(parent) -{ - - d = new MessageReceiverPrivate(this); - connect(d, SIGNAL(deviceInserted(int, int, const QString &)), this, SIGNAL(deviceInserted(int, int, const QString &))); - connect(d, SIGNAL(deviceRemoved(int, int, const QString &)), this, SIGNAL(deviceRemoved(int, int, const QString &))); - TelldusCore::logMessage("MessageReceiver"); -} - -MessageReceiver::~MessageReceiver(void) { - TelldusCore::logMessage("MessageReceiver shutdown"); -} - diff --git a/telldus-core/telldus-service/service/MessageReceiver_unix.cpp b/telldus-core/telldus-service/service/MessageReceiver_unix.cpp deleted file mode 100644 index ce380b0c..00000000 --- a/telldus-core/telldus-service/service/MessageReceiver_unix.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "MessageReceiver.h" -#include "TelldusCore.h" - - -MessageReceiver::MessageReceiver(QObject *parent) - :QObject(parent) -{ - -/* d = new MessageReceiverPrivate(this); - connect(d, SIGNAL(deviceInserted(int, int, const QString &)), this, SIGNAL(deviceInserted(int, int, const QString &))); - connect(d, SIGNAL(deviceRemoved(int, int, const QString &)), this, SIGNAL(deviceRemoved(int, int, const QString &)));*/ - TelldusCore::logMessage("MessageReceiver"); -} - -MessageReceiver::~MessageReceiver(void) { - TelldusCore::logMessage("MessageReceiver shutdown"); -} - diff --git a/telldus-core/telldus-service/service/MessageReceiver_win.cpp b/telldus-core/telldus-service/service/MessageReceiver_win.cpp deleted file mode 100644 index 948ba423..00000000 --- a/telldus-core/telldus-service/service/MessageReceiver_win.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "MessageReceiver.h" -#include - -MessageReceiver::MessageReceiver(QObject *parent) - :QObject(parent) -{ -} - -MessageReceiver::~MessageReceiver(void) { -} diff --git a/telldus-core/telldus-service/service/Pipe.h b/telldus-core/telldus-service/service/Pipe.h deleted file mode 100644 index fd53e746..00000000 --- a/telldus-core/telldus-service/service/Pipe.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PIPE_H -#define PIPE_H - -#include -class PipePrivate; -class Socket; - -class Pipe : public QThread { - Q_OBJECT -public: - Pipe(QObject *parent = 0); - ~Pipe(void); - - void listen(const QString &name); - -signals: - void newConnection(Socket *); - -protected: - void run(); - -private: - PipePrivate *d; -}; - -#endif //PIPE_H diff --git a/telldus-core/telldus-service/service/Pipe_unix.cpp b/telldus-core/telldus-service/service/Pipe_unix.cpp deleted file mode 100644 index 223546c2..00000000 --- a/telldus-core/telldus-service/service/Pipe_unix.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "Pipe.h" -#include "Socket.h" - -#include -#include - -#include - -//using namespace TelldusService; - -inline int listenWrapper(int sockfd, int backlog) { //To not collide with Pipe::listen - return listen(sockfd, backlog); -} - -class PipePrivate { -public: - SOCKET_T socket; - QString name; -}; - -Pipe::Pipe(QObject *parent) - :QThread(parent) -{ - d = new PipePrivate; - d->socket = -1; -} - -Pipe::~Pipe(void) { - qDebug() << "Closing pipe" << d->name; - close(d->socket); - qDebug() << "Waiting!"; - this->wait(); - delete d; -} - -void Pipe::listen(const QString &name) { - d->name = QString("/tmp/%1").arg(name); - this->start(); -} - -void Pipe::run() { - SOCKET_T s; - struct sockaddr_un remote, name; - socklen_t len; - - d->socket = socket(PF_LOCAL, SOCK_STREAM, 0); - if (d->socket < 0) { - return; - } - name.sun_family = AF_LOCAL; - memset(name.sun_path, '\0', sizeof(name.sun_path)); - strncpy(name.sun_path, d->name.toLocal8Bit(), sizeof(name.sun_path)); - unlink(name.sun_path); - int size = SUN_LEN(&name); - bind(d->socket, (struct sockaddr *)&name, size); - qDebug() << "Running" << d->name; - listenWrapper(d->socket, 5); - qDebug() << "Listen"; - len = sizeof(struct sockaddr_un); - while(1) { - qDebug() << "Accepting" << d->name; - s = accept(d->socket, (struct sockaddr *)&remote, &len); - qDebug() << "Accepted" << d->name; - emit newConnection(new Socket(s)); - } -} diff --git a/telldus-core/telldus-service/service/Pipe_win.cpp b/telldus-core/telldus-service/service/Pipe_win.cpp deleted file mode 100644 index a7be9767..00000000 --- a/telldus-core/telldus-service/service/Pipe_win.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "Pipe.h" -#include "Socket.h" -#include "TelldusCore.h" - -#include -#include -#include - -//using namespace TelldusService; - -class PipePrivate { -public: - QString name; - HANDLE event; - bool closing; -}; - -Pipe::Pipe(QObject *parent) - :QThread(parent) -{ - d = new PipePrivate; - d->event = INVALID_HANDLE_VALUE; - d->closing = false; -} - -Pipe::~Pipe(void) { - //TelldusCore::logMessage(QString("Stopping pipe %1").arg(d->name)); - d->closing = true; - if (d->event != INVALID_HANDLE_VALUE) { - SetEvent(d->event); - } - //TelldusCore::logMessage("Waiting for thread to close"); - this->wait(); - delete d; -} - -void Pipe::listen(const QString &name) { - d->name = QString("\\\\.\\pipe\\%1").arg(name); - this->start(); -} - -void Pipe::run() { - SECURITY_ATTRIBUTES sa; - PSECURITY_DESCRIPTOR pSD = NULL; - PACL pACL = NULL; - EXPLICIT_ACCESS ea; - PSID pEveryoneSID = NULL; - SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; - DWORD cbBytesRead; - - pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); - if (pSD == NULL) { - return; - } - - if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { - LocalFree(pSD); - return; - } - - if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) { - LocalFree(pSD); - } - - ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); - ea.grfAccessPermissions = STANDARD_RIGHTS_ALL; - ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance= NO_INHERITANCE; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; - - - // Add the ACL to the security descriptor. - if (!SetSecurityDescriptorDacl(pSD, - TRUE, // bDaclPresent flag - pACL, - FALSE)) // not a default DACL - { - LocalFree(pSD); - FreeSid(pEveryoneSID); - } - - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = pSD; - sa.bInheritHandle = false; - - OVERLAPPED oOverlap; - oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - d->event = oOverlap.hEvent; - - while(!d->closing) { - //TelldusCore::logMessage(QString("Starting listening in pipe %1").arg(d->name)); - HANDLE hPipe = CreateNamedPipe( - (const wchar_t *)d->name.utf16(), // pipe name - PIPE_ACCESS_DUPLEX | // read/write access - FILE_FLAG_OVERLAPPED, //Overlapped mode - PIPE_TYPE_MESSAGE | // message type pipe - PIPE_READMODE_MESSAGE | // message-read mode - PIPE_WAIT, // blocking mode - PIPE_UNLIMITED_INSTANCES, // max. instances - BUFSIZE, // output buffer size - BUFSIZE, // input buffer size - 0, // client time-out - &sa); // default security attribute - - if (hPipe == INVALID_HANDLE_VALUE) { - TelldusCore::logMessage("Could not create named pipe"); - return; - } - - ConnectNamedPipe(hPipe, &oOverlap); - int result = WaitForSingleObject(oOverlap.hEvent, INFINITE); - if (result == WAIT_TIMEOUT) { - continue; - } - bool connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); - if (d->closing || !connected) { - CloseHandle(hPipe); - //TelldusCore::logMessage("Closing or no connection, restart"); - continue; - } - //TelldusCore::logMessage("Connected"); - emit newConnection(new Socket(hPipe)); - } - - CloseHandle(oOverlap.hEvent); - d->event = INVALID_HANDLE_VALUE; - - LocalFree(pSD); - FreeSid(pEveryoneSID); - LocalFree(pACL); -} \ No newline at end of file diff --git a/telldus-core/telldus-service/service/TelldusCore.cpp b/telldus-core/telldus-service/service/TelldusCore.cpp deleted file mode 100644 index 88aa577b..00000000 --- a/telldus-core/telldus-service/service/TelldusCore.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "TelldusCore.h" -#include "Manager.h" -#include "MessageReceiver.h" -#include "Socket.h" -#include -#include - -//Debug -#include -#include -#include - -using namespace TelldusService; - -class TelldusCorePrivate { -public: - Pipe server, eventServer; - QList eventSockets; - MessageReceiver *messageReceiver; -}; - -TelldusCore::TelldusCore(void) - :QObject(), - d(new TelldusCorePrivate) -{ - connect(this, SIGNAL(deviceEventSignal(int, int, const char *)), this, SLOT(deviceEventSlot(int, int, const char *))); - connect(this, SIGNAL(deviceChangeEventSignal(int, int, int)), this, SLOT(deviceChangeEventSlot(int, int, int))); - connect(this, SIGNAL(rawDeviceEventSignal(const QString &, int)), this, SLOT(rawDeviceEventSlot(const QString &, int))); - - tdInit(); - - connect(&d->server, SIGNAL(newConnection(Socket *)), this, SLOT(newConnection(Socket *))); - d->server.listen("TelldusCoreClient"); - - connect(&d->eventServer, SIGNAL(newConnection(Socket *)), this, SLOT(newEventConnection(Socket *))); - d->eventServer.listen("TelldusCoreEvents"); - -#ifndef _WINDOWS //Handled differently on Windows - d->messageReceiver = new MessageReceiver(this); - connect(d->messageReceiver, SIGNAL(deviceInserted(int,int,const QString &)), this, SLOT(deviceInserted(int,int,const QString &))); - connect(d->messageReceiver, SIGNAL(deviceRemoved(int,int,const QString &)), this, SLOT(deviceRemoved(int,int,const QString &))); -#endif - - tdRegisterDeviceEvent( reinterpret_cast(&deviceEvent), this); - tdRegisterDeviceChangeEvent(reinterpret_cast(&deviceChangeEvent), this); - tdRegisterRawDeviceEvent(reinterpret_cast(&rawDeviceEvent), this); -} - -TelldusCore::~TelldusCore(void) { - tdClose(); - logMessage("Shutting down"); - delete d; -} - -void TelldusCore::managerDone() { - //Cleanup our manager after us - Manager *m = qobject_cast(sender()); - if (m) { - delete m; - } -} - -void TelldusCore::newConnection(Socket *socket) { - //logMessage(" New normal Connection"); - //QLocalSocket *s = d->server.nextPendingConnection(); - Manager *m = new Manager(socket, this); - connect(m, SIGNAL(done()), this, SLOT(managerDone())); -} - -void TelldusCore::newEventConnection(Socket *socket) { - //logMessage(" New eventConnection"); -// QLocalSocket *s = d->eventServer.nextPendingConnection(); - //connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected())); //TODO: Must check for disconnect somehow - d->eventSockets.append(socket); -} - -void TelldusCore::disconnected(Socket *s) { - logMessage(" Event disconnection"); - d->eventSockets.removeOne(s); - //if (d->eventServer.isListening()) { - delete s; - //} -} - -void TelldusCore::deviceInserted(int vid, int pid, const QString &serial) { - if (vid != 0x1781) { - return; - } - if (pid == 0x0c30) { - logMessage("TellStick Uno found " + serial); - } else if (pid == 0x0c31) { - logMessage("TellStick Duo found " + serial); - } - tdConnectTellStickController(vid, pid, serial.toLocal8Bit()); -} - -void TelldusCore::deviceRemoved(int vid, int pid, const QString &serial) { - if (pid == 0x0c30) { - logMessage("TellStick Uno disconnected " + serial); - } else if (pid == 0x0c31) { - logMessage("TellStick Duo disconnected " + serial); - } - tdDisconnectTellStickController(vid, pid, serial.toLocal8Bit()); -} - - -void TelldusCore::deviceEventSlot(int deviceId, int method, const char *data) { - Message msg("TDDeviceEvent"); - msg.addArgument(deviceId); - msg.addArgument(method); - msg.addArgument(data); - sendEventMessage(msg); -} - -void TelldusCore::deviceChangeEventSlot(int deviceId, int eventId, int changeType) { - Message msg("TDDeviceChangeEvent"); - msg.addArgument(deviceId); - msg.addArgument(eventId); - msg.addArgument(changeType); - sendEventMessage(msg); -} - -void TelldusCore::rawDeviceEventSlot(const QString &data, int controllerId) { - logMessage(data); - Message msg("TDRawDeviceEvent"); - msg.addArgument(data.toStdString()); - msg.addArgument(controllerId); - sendEventMessage(msg); -} - -void TelldusCore::sendEventMessage(const Message &msg) { - foreach(Socket *s, d->eventSockets) { - std::string ret = s->readWriteOverlapped(msg); - } -} - -void TelldusCore::logMessage( const QString &message) { -#ifdef _WINDOWS - return; - static bool firstRun = true; - QFile file("C:/log_server.txt"); - if (firstRun) { - file.open(QIODevice::WriteOnly | QIODevice::Text); - firstRun = false; - } else { - file.open(QIODevice::Append | QIODevice::Text); - } - QTextStream out(&file); - out << QTime::currentTime().toString() << ": " << message << "\n"; - file.close(); -#else - qDebug() << message; -#endif -} - -void TelldusCore::logMessage( const std::string &message) { - logMessage( QString::fromStdString( message ) ); -} - -void TelldusCore::logMessage( const char *message) { - logMessage( QString(message) ); -} - -void TelldusCore::logMessage( int message) { - logMessage( QString::number(message) ); -} - -void TelldusCore::logWinError( int errorNo) { - logMessage("WinError:"); - logMessage(errorNo); - /*LPVOID lpMsgBuf; - - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - errorNo, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL ); - logMessage( QString(reinterpret_cast(lpMsgBuf)) );*/ -} - - - -void WINAPI TelldusCore::deviceEvent(int deviceId, int method, const char *data, int, void *context) { - TelldusCore *tc = reinterpret_cast(context); - if (tc) { - //The reason we emit the signal here and don't just call the function is because this - //deviceEvent could be called by any thread. Qts signals makes sure our normal thread - //runs the function instead. - emit tc->deviceEventSignal(deviceId, method, data); - } -} - -void WINAPI TelldusCore::deviceChangeEvent(int deviceId, int eventId, int changeType, int, void *context) { - TelldusCore *tc = reinterpret_cast(context); - if (tc) { - emit tc->deviceChangeEventSignal(deviceId, eventId, changeType); - } -} - -void WINAPI TelldusCore::rawDeviceEvent(const char *data, int controllerId, int, void *context) { - TelldusCore *tc = reinterpret_cast(context); - if (tc) { - //Copy the data so we own it since we will hand it over to another thread. - QString msg(data); - emit tc->rawDeviceEventSignal(msg, controllerId); - } -} diff --git a/telldus-core/telldus-service/service/TelldusCore.h b/telldus-core/telldus-service/service/TelldusCore.h deleted file mode 100644 index 895b4180..00000000 --- a/telldus-core/telldus-service/service/TelldusCore.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef TELLDUS_CORE_H -#define TELLDUS_CORE_H - -#include -#include "Pipe.h" -#include "Message.h" -#include - -class TelldusCorePrivate; -class Socket; - -class TelldusCore : public QObject { - Q_OBJECT -public: - TelldusCore(void); - ~TelldusCore(void); - - static void logMessage( const QString &message); - static void logMessage( const std::string &message); - static void logMessage( const char *message); - static void logMessage( int message); - static void logWinError( int errorNo); - -public slots: - void deviceInserted(int, int, const QString &); - void deviceRemoved(int, int, const QString &); - -private slots: - void newConnection(Socket *); - void newEventConnection(Socket *); - void deviceEventSlot(int, int, const char *); - void deviceChangeEventSlot(int, int, int); - void rawDeviceEventSlot(const QString &, int); - void managerDone(); - -signals: - void deviceEventSignal(int, int, const char *); - void deviceChangeEventSignal(int, int, int); - void rawDeviceEventSignal(const QString &, int); - -private: - void disconnected(Socket *); - void sendEventMessage(const TelldusService::Message &msg); - TelldusCorePrivate * const d; - - static void WINAPI deviceEvent(int deviceId, int, const char *, int, void *); - static void WINAPI deviceChangeEvent(int deviceId, int eventId, int changeType, int, void *); - static void WINAPI rawDeviceEvent(const char *data, int controllerId, int, void *); - static int callbackId; -}; - -#endif diff --git a/telldus-core/telldus-service/service/TelldusWinService_win.cpp b/telldus-core/telldus-service/service/TelldusWinService_win.cpp deleted file mode 100644 index b1b1fad8..00000000 --- a/telldus-core/telldus-service/service/TelldusWinService_win.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include "TelldusWinService_win.h" -#include "TelldusCore.h" -#include -#include - -#include - -int g_argc; -char **g_argv; - - -static const GUID GUID_DEVINTERFACE_USBRAW = -{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; - -TelldusWinService::TelldusWinService() - :tc(0) -{ - - //setServiceDescription("A Telldus service for managing TellStick Duo."); -} - -TelldusWinService::~TelldusWinService() { -} - -void TelldusWinService::start() { - tc = new TelldusCore(); - - connect(this, SIGNAL(deviceInserted(int,int,const QString &)), tc, SLOT(deviceInserted(int,int,const QString &))); - connect(this, SIGNAL(deviceRemoved(int,int,const QString &)), tc, SLOT(deviceRemoved(int,int,const QString &))); - - //app->quit(); - -} - - -void TelldusWinService::stop() { - if (tc) { - delete tc; - } - tc = 0; -} - -DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { - switch ( controlCode ) { - case SERVICE_CONTROL_INTERROGATE: - SetServiceStatus( serviceStatusHandle, &serviceStatus ); - return NO_ERROR; - - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - stop(); - serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus( serviceStatusHandle, &serviceStatus ); - - QCoreApplication::quit(); - return NO_ERROR; - - case SERVICE_CONTROL_DEVICEEVENT: - if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - - PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast(lpEventData); - if (!pDevInf) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - - TelldusCore::logMessage(QString::fromWCharArray(pDevInf->dbcc_name)); - - //QRegExp rx("USB#VID_([0-9A-Fa-f]+)&PID_([0-9A-Fa-f]+)#(\\.+)#"); - QRegExp rx("USB#VID_([0-9A-Fa-f]+)&PID_([0-9A-Fa-f]+)", Qt::CaseInsensitive); - if (rx.indexIn(QString::fromWCharArray(pDevInf->dbcc_name)) < 0) { - TelldusCore::logMessage("No match"); - return 0; - } - - int vid = strtol(rx.cap(1).toLocal8Bit(), 0, 16); - int pid = strtol(rx.cap(2).toLocal8Bit(), 0, 16); - - if (dwEventType == DBT_DEVICEARRIVAL) { - TelldusCore::logMessage(QString("Insert %1 %2").arg(vid).arg(pid)); - emit deviceInserted(vid, pid, ""); - } else { - TelldusCore::logMessage(QString("Remove %1").arg(rx.cap(3))); - emit deviceRemoved(vid, pid, ""); - } - - return NO_ERROR; - } - return ERROR_CALL_NOT_IMPLEMENTED; -} - -DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { - TelldusWinService *instance = reinterpret_cast(lpContext); - if (!instance) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - return instance->serviceControlHandler(controlCode, dwEventType, lpEventData); -} - -void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { - TelldusWinService instance; - QCoreApplication app(g_argc, g_argv); - - - // initialise service status - instance.serviceStatus.dwServiceType = SERVICE_WIN32; - instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; - instance.serviceStatus.dwControlsAccepted = 0; - instance.serviceStatus.dwWin32ExitCode = NO_ERROR; - instance.serviceStatus.dwServiceSpecificExitCode = NO_ERROR; - instance.serviceStatus.dwCheckPoint = 0; - instance.serviceStatus.dwWaitHint = 0; - - instance.serviceStatusHandle = RegisterServiceCtrlHandlerEx( serviceName, TelldusWinService::serviceControlHandler, &instance ); - - if ( instance.serviceStatusHandle ) { - // service is starting - instance.serviceStatus.dwCurrentState = SERVICE_START_PENDING; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - - // running - instance.start(); - instance.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - instance.serviceStatus.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - - DEV_BROADCAST_DEVICEINTERFACE devInterface; - ZeroMemory( &devInterface, sizeof(devInterface) ); - devInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); - devInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW; - - HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE); - - if (!deviceNotificationHandle) { - TelldusCore::logMessage(QString("Fail RegisterDeviceNotification")); - } - - //TelldusCore::logMessage(QString("Main thread waiting for service to stop")); - app.exec(); - //TelldusCore::logMessage(QString("Main thread waited, shutting down")); - - // service was stopped - instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - - // service is now stopped - instance.serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - } -} diff --git a/telldus-core/telldus-service/service/TelldusWinService_win.h b/telldus-core/telldus-service/service/TelldusWinService_win.h deleted file mode 100644 index fb86f07c..00000000 --- a/telldus-core/telldus-service/service/TelldusWinService_win.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef TELLDUSSERVICE_WIN_H -#define TELLDUSSERVICE_WIN_H - -#include -#include - -extern int g_argc; -extern char **g_argv; - -class TelldusCore; - -#define serviceName TEXT("TelldusCore") - -class TelldusWinService : public QObject { - Q_OBJECT -public: - TelldusWinService(); - ~TelldusWinService(); - - static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); - -signals: - void deviceInserted(int vid, int pid, const QString &serial); - void deviceRemoved(int vid, int pid, const QString &serial); - -protected: - - void start(); - void stop(); - - DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); - -private: - TelldusCore *tc; - SERVICE_STATUS serviceStatus; - SERVICE_STATUS_HANDLE serviceStatusHandle; - - static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); - -}; -#endif TELLDUSSERVICE_WIN_H \ No newline at end of file diff --git a/telldus-core/telldus-service/service/main_unix.cpp b/telldus-core/telldus-service/service/main_unix.cpp deleted file mode 100644 index cc6c932d..00000000 --- a/telldus-core/telldus-service/service/main_unix.cpp +++ /dev/null @@ -1,22 +0,0 @@ - -#include -#include - -#include "TelldusCore.h" -#include - -void shutdownHandler(int onSignal) { - qApp->quit(); -} - -int main(int argc, char **argv) { - QCoreApplication app(argc, argv); - - /* Install signal traps for proper shutdown */ - signal(SIGTERM, shutdownHandler); - signal(SIGINT, shutdownHandler); - - TelldusCore telldusCore; - - return app.exec(); -} diff --git a/telldus-core/telldus-service/service/main_win.cpp b/telldus-core/telldus-service/service/main_win.cpp deleted file mode 100644 index ec325075..00000000 --- a/telldus-core/telldus-service/service/main_win.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "TelldusWinService_win.h" -#include - -#include -#include - - -int main(int argc, char **argv) { - g_argc = argc; - g_argv = argv; - - SERVICE_TABLE_ENTRY serviceTable[] = { - {serviceName, TelldusWinService::serviceMain }, - { 0, 0 } - }; - - StartServiceCtrlDispatcher( serviceTable ); - - return 0; -} From 3d8490f9258107afccd030317dc1dc7d50544127 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 05:59:32 +0000 Subject: [PATCH 0168/2215] Added initial directory structure for telldus-core rewrite --- .../qtservice-2.6-opensource/INSTALL.TXT | 254 ++++ .../LGPL_EXCEPTION.txt | 10 + .../qtservice-2.6-opensource/LICENSE.GPL3 | 674 ++++++++++ .../qtservice-2.6-opensource/LICENSE.LGPL | 504 ++++++++ .../qtservice-2.6-opensource/README.TXT | 7 + .../buildlib/buildlib.pro | 13 + .../qtservice-2.6-opensource/common.pri | 6 + .../qtservice-2.6-opensource/configure | 112 ++ .../doc/html/classic.css | 131 ++ .../doc/html/images/qt-logo.png | Bin 0 -> 4075 bytes .../doc/html/index.html | 50 + .../html/qtservice-example-controller.html | 195 +++ .../html/qtservice-example-interactive.html | 161 +++ .../doc/html/qtservice-example-server.html | 159 +++ .../doc/html/qtservice-members.html | 52 + .../doc/html/qtservice.dcf | 76 ++ .../doc/html/qtservice.html | 92 ++ .../doc/html/qtservice.index | 111 ++ .../doc/html/qtservice.qch | Bin 0 -> 57344 bytes .../doc/html/qtservice.qhp | 90 ++ .../doc/html/qtservicebase-members.html | 51 + .../doc/html/qtservicebase.html | 199 +++ .../doc/html/qtservicecontroller-members.html | 46 + .../doc/html/qtservicecontroller.html | 155 +++ .../doc/images/qt-logo.png | Bin 0 -> 4075 bytes .../qtservice-2.6-opensource/doc/index.qdoc | 46 + .../examples/controller/controller.pro | 7 + .../examples/controller/controller.qdoc | 81 ++ .../examples/controller/main.cpp | 169 +++ .../examples/examples.pro | 4 + .../examples/interactive/interactive.pro | 6 + .../examples/interactive/interactive.qdoc | 76 ++ .../examples/interactive/main.cpp | 133 ++ .../examples/server/main.cpp | 190 +++ .../examples/server/server.pro | 8 + .../examples/server/server.qdoc | 87 ++ .../qtservice-2.6-opensource/qtservice.pro | 5 + .../src/QtServiceBase | 1 + .../src/QtServiceController | 1 + .../src/qtservice.cpp | 1117 +++++++++++++++++ .../qtservice-2.6-opensource/src/qtservice.h | 197 +++ .../src/qtservice.pri | 21 + .../src/qtservice_p.h | 93 ++ .../src/qtservice_unix.cpp | 480 +++++++ .../src/qtservice_win.cpp | 903 +++++++++++++ .../src/qtunixserversocket.cpp | 98 ++ .../src/qtunixserversocket.h | 67 + .../src/qtunixsocket.cpp | 84 ++ .../src/qtunixsocket.h | 61 + telldus-core/3rdparty/qtservice.cmake | 39 + 50 files changed, 7122 insertions(+) create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/common.pri create mode 100755 telldus-core/3rdparty/qtservice-2.6-opensource/configure create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/images/qt-logo.png create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp create mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h create mode 100644 telldus-core/3rdparty/qtservice.cmake diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT b/telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT new file mode 100644 index 00000000..8d41864d --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT @@ -0,0 +1,254 @@ +INSTALLATION INSTRUCTIONS + +These instructions refer to the package you are installing as +some-package.tar.gz or some-package.zip. The .zip file is intended for use +on Windows. + +The directory you choose for the installation will be referred to as +your-install-dir. + +Note to Qt Visual Studio Integration users: In the instructions below, +instead of building from command line with nmake, you can use the menu +command 'Qt->Open Solution from .pro file' on the .pro files in the +example and plugin directories, and then build from within Visual +Studio. + +Unpacking and installation +-------------------------- + +1. Unpacking the archive (if you have not done so already). + + On Unix and Mac OS X (in a terminal window): + + cd your-install-dir + gunzip some-package.tar.gz + tar xvf some-package.tar + + This creates the subdirectory some-package containing the files. + + On Windows: + + Unpack the .zip archive by right-clicking it in explorer and + choosing "Extract All...". If your version of Windows does not + have zip support, you can use the infozip tools available + from www.info-zip.org. + + If you are using the infozip tools (in a command prompt window): + cd your-install-dir + unzip some-package.zip + +2. Configuring the package. + + The configure script is called "configure" on unix/mac and + "configure.bat" on Windows. It should be run from a command line + after cd'ing to the package directory. + + You can choose whether you want to use the component by including + its source code directly into your project, or build the component + as a dynamic shared library (DLL) that is loaded into the + application at run-time. The latter may be preferable for + technical or licensing (LGPL) reasons. If you want to build a DLL, + run the configure script with the argument "-library". Also see + the note about usage below. + + (Components that are Qt plugins, e.g. styles and image formats, + are by default built as a plugin DLL.) + + The configure script will prompt you in some cases for further + information. Answer these questions and carefully read the license text + before accepting the license conditions. The package cannot be used if + you do not accept the license conditions. + +3. Building the component and examples (when required). + + If a DLL is to be built, or if you would like to build the + examples, next give the commands + + qmake + make [or nmake if your are using Microsoft Visual C++] + + The example program(s) can be found in the directory called + "examples" or "example". + + Components that are Qt plugins, e.g. styles and image formats, are + ready to be used as soon as they are built, so the rest of this + installation instruction can be skipped. + +4. Building the Qt Designer plugin (optional). + + Some of the widget components are provided with plugins for Qt + Designer. To build and install the plugin, cd into the + some-package/plugin directory and give the commands + + qmake + make [or nmake if your are using Microsoft Visual C++] + + Restart Qt Designer to make it load the new widget plugin. + + Note: If you are using the built-in Qt Designer from the Qt Visual + Studio Integration, you will need to manually copy the plugin DLL + file, i.e. copy + %QTDIR%\plugins\designer\some-component.dll + to the Qt Visual Studio Integration plugin path, typically: + C:\Program Files\Trolltech\Qt VS Integration\plugins + + Note: If you for some reason are using a Qt Designer that is built + in debug mode, you will need to build the plugin in debug mode + also. Edit the file plugin.pro in the plugin directory, changing + 'release' to 'debug' in the CONFIG line, before running qmake. + + + +Solutions components are intended to be used directly from the package +directory during development, so there is no 'make install' procedure. + + +Using a component in your project +--------------------------------- + +To use this component in your project, add the following line to the +project's .pro file (or do the equivalent in your IDE): + + include(your-install-dir/some-package/src/some-package.pri) + +This adds the package's sources and headers to the SOURCES and HEADERS +project variables respectively (or, if the component has been +configured as a DLL, it adds that library to the LIBS variable), and +updates INCLUDEPATH to contain the package's src +directory. Additionally, the .pri file may include some dependencies +needed by the package. + +To include a header file from the package in your sources, you can now +simply use: + + #include + +or alternatively, in pre-Qt 4 style: + + #include + +Refer to the documentation to see the classes and headers this +components provides. + + + +Install documentation (optional) +-------------------------------- + +The HTML documentation for the package's classes is located in the +your-install-dir/some-package/doc/html/index.html. You can open this +file and read the documentation with any web browser. + +To install the documentation into Qt Assistant (for Qt version 4.4 and +later): + +1. In Assistant, open the Edit->Preferences dialog and choose the + Documentation tab. Click the Add... button and select the file + your-install-dir/some-package/doc/html/some-package.qch + +For Qt versions prior to 4.4, do instead the following: + +1. The directory your-install-dir/some-package/doc/html contains a + file called some-package.dcf. Execute the following commands in a + shell, command prompt or terminal window: + + cd your-install-dir/some-package/doc/html/ + assistant -addContentFile some-package.dcf + +The next time you start Qt Assistant, you can access the package's +documentation. + + +Removing the documentation from assistant +----------------------------------------- + +If you have installed the documentation into Qt Assistant, and want to uninstall it, do as follows, for Qt version 4.4 and later: + +1. In Assistant, open the Edit->Preferences dialog and choose the + Documentation tab. In the list of Registered Documentation, select + the item com.trolltech.qtsolutions.some-package_version, and click + the Remove button. + +For Qt versions prior to 4.4, do instead the following: + +1. The directory your-install-dir/some-package/doc/html contains a + file called some-package.dcf. Execute the following commands in a + shell, command prompt or terminal window: + + cd your-install-dir/some-package/doc/html/ + assistant -removeContentFile some-package.dcf + + + +Using the component as a DLL +---------------------------- + +1. Normal components + + The shared library (DLL) is built and placed in the + some-package/lib directory. It is intended to be used directly + from there during development. When appropriate, both debug and + release versions are built, since the run-time linker will in some + cases refuse to load a debug-built DLL into a release-built + application or vice versa. + + The following steps are taken by default to help the dynamic + linker to locate the DLL at run-time (during development): + + Unix: The some-package.pri file will add linker instructions to + add the some-package/lib directory to the rpath of the + executable. (When distributing, or if your system does not support + rpath, you can copy the shared library to another place that is + searched by the dynamic linker, e.g. the "lib" directory of your + Qt installation.) + + Mac: The full path to the library is hardcoded into the library + itself, from where it is copied into the executable at link time, + and ready by the dynamic linker at run-time. (When distributing, + you will want to edit these hardcoded paths in the same way as for + the Qt DLLs. Refer to the document "Deploying an Application on + Mac OS X" in the Qt Reference Documentation.) + + Windows: the .dll file(s) are copied into the "bin" directory of + your Qt installation. The Qt installation will already have set up + that directory to be searched by the dynamic linker. + + +2. Plugins + + For Qt Solutions plugins (e.g. image formats), both debug and + release versions of the plugin are built by default when + appropriate, since in some cases the release Qt library will not + load a debug plugin, and vice versa. The plugins are automatically + copied into the plugins directory of your Qt installation when + built, so no further setup is required. + + Plugins may also be built statically, i.e. as a library that will be + linked into your application executable, and so will not need to + be redistributed as a separate plugin DLL to end users. Static + building is required if Qt itself is built statically. To do it, + just add "static" to the CONFIG variable in the plugin/plugin.pro + file before building. Refer to the "Static Plugins" section in the + chapter "How to Create Qt Plugins" for explanation of how to use a + static plugin in your application. The source code of the example + program(s) will also typically contain the relevant instructions + as comments. + + + +Uninstalling +------------ + + The following command will remove any fils that have been + automatically placed outside the package directory itself during + installation and building + + make distclean [or nmake if your are using Microsoft Visual C++] + + If Qt Assistant documentation or Qt Designer plugins have been + installed, they can be uninstalled manually, ref. above. + + +Enjoy! :) + +- The Qt Solutions Team. diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt b/telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt new file mode 100644 index 00000000..0b56ff1e --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt @@ -0,0 +1,10 @@ +Nokia Qt LGPL Exception version 1.0 + +As a special exception to the GNU Lesser General Public License +version 2.1, the object code form of a "work that uses the Library" +may incorporate material from a header file that is part of the +Library. You may distribute such object code under terms of your +choice, provided that the incorporated material (i) does not exceed +more than 5% of the total size of the Library; and (ii) is limited to +numerical parameters, data structure layouts, accessors, macros, +inline functions and templates. diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 b/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 new file mode 100644 index 00000000..94a9ed02 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL b/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL new file mode 100644 index 00000000..5ab7695a --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT b/telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT new file mode 100644 index 00000000..d8a55f89 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT @@ -0,0 +1,7 @@ +Service v2.6 + +The QtService component is useful for developing Windows services +and Unix daemons. + + + diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro new file mode 100644 index 00000000..1e51cc1d --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro @@ -0,0 +1,13 @@ +TEMPLATE=lib +CONFIG += qt dll qtservice-buildlib +mac:CONFIG += absolute_library_soname +win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all +include(../src/qtservice.pri) +TARGET = $$QTSERVICE_LIBNAME +DESTDIR = $$QTSERVICE_LIBDIR +win32 { + DLLDESTDIR = $$[QT_INSTALL_BINS] + QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTSERVICE_LIBNAME}.dll +} +target.path = $$DESTDIR +INSTALLS += target diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/common.pri b/telldus-core/3rdparty/qtservice-2.6-opensource/common.pri new file mode 100644 index 00000000..b9456796 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/common.pri @@ -0,0 +1,6 @@ +infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtservice-uselib +TEMPLATE += fakelib +QTSERVICE_LIBNAME = $$qtLibraryTarget(QtSolutions_Service-2.6) +TEMPLATE -= fakelib +QTSERVICE_LIBDIR = $$PWD/lib +unix:qtservice-uselib:!qtservice-buildlib:QMAKE_RPATHDIR += $$QTSERVICE_LIBDIR diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/configure b/telldus-core/3rdparty/qtservice-2.6-opensource/configure new file mode 100755 index 00000000..674d286a --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/configure @@ -0,0 +1,112 @@ +#!/bin/sh + +if [ "x$1" != "x" -a "x$1" != "x-library" ]; then + echo "Usage: $0 [-library]" + echo + echo "-library: Build the component as a dynamic library (DLL). Default is to" + echo " include the component source code directly in the application." + echo " A DLL may be preferable for technical or licensing (LGPL) reasons." + echo + exit 0 +fi + + +# only ask to accept the license text once +if [ ! -f .licenseAccepted ]; then +# determine if opensource or commercial package + if [ -f LICENSE.LGPL ]; then + # opensource edition + while true; do + echo + echo "You are licensed to use this software under the terms of" + echo "the GNU General Public License (GPL) version 3, or" + echo "the GNU Lesser General Public License (LGPL) version 2.1" + echo "with certain additional extra rights as specified in the" + echo "Nokia Qt LGPL Exception version 1.0." + echo + echo "Type 'G' to view the GNU General Public License (GPL) version 3." + echo "Type 'L' to view the GNU Lesser General Public License (LGPL) version 2.1." + echo "Type 'E' to view the Nokia Qt LGPL Exception version 1.0." + echo "Type 'yes' to accept this license offer." + echo "Type 'no' to decline this license offer." + echo + echo "Do you accept the terms of this license? " + read answer + echo + + if [ "x$answer" = "xno" ]; then + echo "You are not licensed to use this software." + echo + exit 1 + elif [ "x$answer" = "xyes" ]; then + echo license accepted > .licenseAccepted + break + elif [ "x$answer" = "xe" -o "x$answer" = "xE" ]; then + more LGPL_EXCEPTION.txt + elif [ "x$answer" = "xl" -o "x$answer" = "xL" ]; then + more LICENSE.LGPL + elif [ "x$answer" = "xg" -o "x$answer" = "xG" ]; then + more LICENSE.GPL3 + fi + done + else + while true; do + echo + echo "Please choose your region." + echo + echo "Type 1 for North or South America." + echo "Type 2 for anywhere outside North and South America." + echo + echo "Select: " + read region + if [ "x$region" = "x1" ]; then + licenseFile=LICENSE.US + break; + elif [ "x$region" = "x2" ]; then + licenseFile=LICENSE.NO + break; + fi + done + while true; do + echo + echo "License Agreement" + echo + echo "Type '?' to view the Qt Solutions Commercial License." + echo "Type 'yes' to accept this license offer." + echo "Type 'no' to decline this license offer." + echo + echo "Do you accept the terms of this license? " + read answer + echo + + if [ "x$answer" = "xno" ]; then + echo "You are not licensed to use this software." + echo + exit 1 + elif [ "x$answer" = "xyes" ]; then + echo license accepted > .licenseAccepted + cp "$licenseFile" LICENSE + rm LICENSE.US + rm LICENSE.NO + break + elif [ "x$answer" = "x?" ]; then + more "$licenseFile" + fi + done + fi +fi + +rm -f config.pri +if [ "x$1" = "x-library" ]; then + echo "Configuring to build this component as a dynamic library." + echo "SOLUTIONS_LIBRARY = yes" > config.pri +fi + +echo +echo "This component is now configured." +echo +echo "To build the component library (if requested) and example(s)," +echo "run qmake and your make command." +echo +echo "To remove or reconfigure, run make distclean." +echo diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css new file mode 100644 index 00000000..0ff9e7db --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css @@ -0,0 +1,131 @@ +h3.fn,span.fn +{ + margin-left: 1cm; + text-indent: -1cm; +} + +a:link +{ + color: #004faf; + text-decoration: none +} + +a:visited +{ + color: #672967; + text-decoration: none +} + +a.obsolete +{ + color: #661100; + text-decoration: none +} + +a.compat +{ + color: #661100; + text-decoration: none +} + +a.obsolete:visited +{ + color: #995500; + text-decoration: none +} + +a.compat:visited +{ + color: #995500; + text-decoration: none +} + +td.postheader +{ + font-family: sans-serif +} + +tr.address +{ + font-family: sans-serif +} + +body +{ + background: #ffffff; + color: black +} + +table tr.odd { + background: #f0f0f0; + color: black; +} + +table tr.even { + background: #e4e4e4; + color: black; +} + +table.annotated th { + padding: 3px; + text-align: left +} + +table.annotated td { + padding: 3px; +} + +table tr pre +{ + padding-top: none; + padding-bottom: none; + padding-left: none; + padding-right: none; + border: none; + background: none +} + +tr.qt-style +{ + background: #a2c511; + color: black +} + +body pre +{ + padding: 0.2em; + border: #e7e7e7 1px solid; + background: #f1f1f1; + color: black +} + +span.preprocessor, span.preprocessor a +{ + color: darkblue; +} + +span.comment +{ + color: darkred; + font-style: italic +} + +span.string,span.char +{ + color: darkgreen; +} + +.title +{ + text-align: center +} + +.subtitle +{ + font-size: 0.8em +} + +.small-subtitle +{ + font-size: 0.65em +} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/images/qt-logo.png b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/images/qt-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..794162f5af58e7b38beebf472842fc9703ede19b GIT binary patch literal 4075 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 literal 0 HcmV?d00001 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html new file mode 100644 index 00000000..d7d27464 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html @@ -0,0 +1,50 @@ + + + + + + Service + + + + + + + +
  Home

Service
+

+ +

Description

+

The QtService component is useful for developing Windows services and Unix daemons.

+

The project provides a QtService template class that can be used to implement service applications, and a QtServiceController class to control a service.

+

On Windows systems the implementation uses the Service Control Manager.

+

On Unix systems services are implemented as daemons.

+ +

Classes

+ + +

Examples

+ + +

Tested platforms

+
    +
  • Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005
  • +
  • Qt 4.4, 4.5 / Linux / gcc
  • +
  • Qt 4.4, 4.5 / MacOS X 10.5 / gcc
  • +
+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html new file mode 100644 index 00000000..8462fe78 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html @@ -0,0 +1,195 @@ + + + + + + A simple Service Controller + + + + + + + +
  Home

A simple Service Controller
+

+

It is a very simple implementation of universal command-line controller. This controller can install and control any service written using QtService component. It demonstrates how to use QtServiceController class. On Windows, this is an alternative to using the "Services" Administrative Tool or the built-in sc.exe command-line tool to control services.

+

A note about services on Windows Vista: Installing/uninstalling and starting/stopping services requires security privileges. The simplest way to achieve this is to set the "Run as Administrator" property on the executable (right-click the executable file, select Properties, and choose the Compatibilty tab in the Properties dialog). This applies even if you are logged in as Administrator. Also, the command-line shell should be started with "Run as Administrator". Note that the service itself does not need special privileges to run. Only if you want the service to be able to install itself (the -i option) or similar, then the service will need to be run as Administrator. Otherwise, the recommended procedure is to use a controller such as this example and/or the "Services" Administrative Tool to manage the service.

+

A usability hint: in some circumstances, e.g. when running this example on Windows Vista with the "Run as Administrator" property set, output will be sent to a shell window which will close immediately upon termination, not leaving the user enough time to read the output. In such cases, append the -w(ait) argument, which will make the controller wait for a keypress before terminating.

+

Here is the complete source code:

+
 /****************************************************************************
+ **
+ ** This file is part of a Qt Solutions component.
+ **
+ ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ **
+ ** Contact:  Qt Software Information (qt-info@nokia.com)
+ **
+ ** Commercial Usage
+ ** Licensees holding valid Qt Commercial licenses may use this file in
+ ** accordance with the Qt Solutions Commercial License Agreement provided
+ ** with the Software or, alternatively, in accordance with the terms
+ ** contained in a written agreement between you and Nokia.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file.  Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain
+ ** additional rights. These rights are described in the Nokia Qt LGPL
+ ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+ ** package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file.  Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Please note Third Party Software included with Qt Solutions may impose
+ ** additional restrictions and it is the user's responsibility to ensure
+ ** that they have met the licensing requirements of the GPL, LGPL, or Qt
+ ** Solutions Commercial license and the relevant license of the Third
+ ** Party Software they are using.
+ **
+ ** If you are unsure which license is appropriate for your use, please
+ ** contact the sales department at qt-sales@nokia.com.
+ **
+ ****************************************************************************/
+
+ #include <QtCore/QStringList>
+ #include <QtCore/QDir>
+ #include <QtCore/QSettings>
+ #include "qtservice.h"
+
+ int processArgs(int argc, char **argv)
+ {
+     if (argc > 2) {
+         QString arg1(argv[1]);
+         if (arg1 == QLatin1String("-i") ||
+             arg1 == QLatin1String("-install")) {
+             if (argc > 2) {
+                 QString account;
+                 QString password;
+                 QString path(argv[2]);
+                 if (argc > 3)
+                     account = argv[3];
+                 if (argc > 4)
+                     password = argv[4];
+                 printf("The service %s installed.\n",
+                        (QtServiceController::install(path, account, password) ? "was" : "was not"));
+                 return 0;
+             }
+         } else {
+             QString serviceName(argv[1]);
+             QtServiceController controller(serviceName);
+             QString option(argv[2]);
+             if (option == QLatin1String("-u") ||
+                 option == QLatin1String("-uninstall")) {
+                 printf("The service \"%s\" %s uninstalled.\n",
+                             controller.serviceName().toLatin1().constData(),
+                             (controller.uninstall() ? "was" : "was not"));
+                 return 0;
+             } else if (option == QLatin1String("-s") ||
+                        option == QLatin1String("-start")) {
+                 QStringList args;
+                 for (int i = 3; i < argc; ++i)
+                     args.append(QString::fromLocal8Bit(argv[i]));
+                 printf("The service \"%s\" %s started.\n",
+                        controller.serviceName().toLatin1().constData(),
+                             (controller.start(args) ? "was" : "was not"));
+                 return 0;
+             } else if (option == QLatin1String("-t") ||
+                        option == QLatin1String("-terminate")) {
+                 printf("The service \"%s\" %s stopped.\n",
+                        controller.serviceName().toLatin1().constData(),
+                        (controller.stop() ? "was" : "was not"));
+                 return 0;
+             } else if (option == QLatin1String("-p") ||
+                     option == QLatin1String("-pause")) {
+                 printf("The service \"%s\" %s paused.\n",
+                        controller.serviceName().toLatin1().constData(),
+                        (controller.pause() ? "was" : "was not"));
+                 return 0;
+             } else if (option == QLatin1String("-r") ||
+                        option == QLatin1String("-resume")) {
+                 printf("The service \"%s\" %s resumed.\n",
+                        controller.serviceName().toLatin1().constData(),
+                        (controller.resume() ? "was" : "was not"));
+                 return 0;
+             } else if (option == QLatin1String("-c") ||
+                        option == QLatin1String("-command")) {
+                 if (argc > 3) {
+                     QString codestr(argv[3]);
+                     int code = codestr.toInt();
+                     printf("The command %s sent to the service \"%s\".\n",
+                            (controller.sendCommand(code) ? "was" : "was not"),
+                            controller.serviceName().toLatin1().constData());
+                     return 0;
+                 }
+             } else if (option == QLatin1String("-v") ||
+                     option == QLatin1String("-version")) {
+                 bool installed = controller.isInstalled();
+                 printf("The service\n"
+                         "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData());
+                 printf("is %s", (installed ? "installed" : "not installed"));
+                 printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running"));
+                 if (installed) {
+                     printf("path: %s\n", controller.serviceFilePath().toLatin1().data());
+                     printf("description: %s\n", controller.serviceDescription().toLatin1().data());
+                     printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual");
+                 }
+                 return 0;
+             }
+         }
+     }
+     printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n"
+             "\t-i(nstall) PATH\t: Install the service\n"
+             "\t-v(ersion)\t: Print status of the service\n"
+             "\t-u(ninstall)\t: Uninstall the service\n"
+             "\t-s(tart)\t: Start the service\n"
+             "\t-t(erminate)\t: Stop the service\n"
+             "\t-p(ause)\t: Pause the service\n"
+             "\t-r(esume)\t: Resume the service\n"
+             "\t-c(ommand) CODE\t: Send a command to the service\n"
+             "\t-h(elp)\t\t: Print this help info\n"
+             "\t-w(ait)\t\t: Wait for keypress when done\n");
+     return 0;
+ }
+
+ int main(int argc, char **argv)
+ {
+ #if !defined(Q_WS_WIN)
+     // QtService stores service settings in SystemScope, which normally require root privileges.
+     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
+     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
+     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
+ #endif
+
+     int result = processArgs(argc, argv);
+
+     if (QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-w") ||
+         QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-wait")) {
+         printf("\nPress Enter to continue...");
+         QFile input;
+         input.open(stdin, QIODevice::ReadOnly);
+         input.readLine();
+         printf("\n");
+     }
+
+     return result;
+ }
+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html new file mode 100644 index 00000000..34928841 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html @@ -0,0 +1,161 @@ + + + + + + An Interactive Service + + + + + + + +
  Home

An Interactive Service
+

+

This example implements a service with a simple user interface.

+

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes.

+

However, although not recommended in the general case, in certain circumstances a service may provide a GUI itself. This is typically only possible if the service process is run as the same user as the one that is logged in, so that it will have access to the screen. Note however that on Windows Vista, service GUIs are not allowed at all, since services run in a diferent session than all user sessions, for security reasons.

+

This example demonstrates how to subclass the QtService class, the use of start(), stop(), pause(), resume(), and how to use processCommand() to receive control commands while running.

+

Here is the complete source code:

+
 /****************************************************************************
+ **
+ ** This file is part of a Qt Solutions component.
+ **
+ ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ **
+ ** Contact:  Qt Software Information (qt-info@nokia.com)
+ **
+ ** Commercial Usage
+ ** Licensees holding valid Qt Commercial licenses may use this file in
+ ** accordance with the Qt Solutions Commercial License Agreement provided
+ ** with the Software or, alternatively, in accordance with the terms
+ ** contained in a written agreement between you and Nokia.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 2.1 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL included in the
+ ** packaging of this file.  Please review the following information to
+ ** ensure the GNU Lesser General Public License version 2.1 requirements
+ ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ **
+ ** In addition, as a special exception, Nokia gives you certain
+ ** additional rights. These rights are described in the Nokia Qt LGPL
+ ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+ ** package.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 3.0 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL included in the
+ ** packaging of this file.  Please review the following information to
+ ** ensure the GNU General Public License version 3.0 requirements will be
+ ** met: http://www.gnu.org/copyleft/gpl.html.
+ **
+ ** Please note Third Party Software included with Qt Solutions may impose
+ ** additional restrictions and it is the user's responsibility to ensure
+ ** that they have met the licensing requirements of the GPL, LGPL, or Qt
+ ** Solutions Commercial license and the relevant license of the Third
+ ** Party Software they are using.
+ **
+ ** If you are unsure which license is appropriate for your use, please
+ ** contact the sales department at qt-sales@nokia.com.
+ **
+ ****************************************************************************/
+
+ #include <QtGui/QApplication>
+ #include <QtGui/QDesktopWidget>
+ #include <QtGui/QLabel>
+ #include <QtCore/QDir>
+ #include <QtCore/QSettings>
+ #include "qtservice.h"
+
+ class InteractiveService : public QtService<QApplication>
+ {
+ public:
+     InteractiveService(int argc, char **argv);
+     ~InteractiveService();
+
+ protected:
+
+     void start();
+     void stop();
+     void pause();
+     void resume();
+     void processCommand(int code);
+
+ private:
+     QLabel *gui;
+ };
+
+ InteractiveService::InteractiveService(int argc, char **argv)
+     : QtService<QApplication>(argc, argv, "Qt Interactive Service"), gui(0)
+ {
+     setServiceDescription("A Qt service with user interface.");
+     setServiceFlags(QtServiceBase::CanBeSuspended);
+ }
+
+ InteractiveService::~InteractiveService()
+ {
+ }
+
+ void InteractiveService::start()
+ {
+ #if defined(Q_OS_WIN)
+     if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) &&
+         (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) {
+         logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error );
+         return;
+     }
+ #endif
+
+     qApp->setQuitOnLastWindowClosed(false);
+
+     gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
+     gui->move(QApplication::desktop()->availableGeometry().topLeft());
+     gui->show();
+ }
+
+ void InteractiveService::stop()
+ {
+     delete gui;
+ }
+
+ void InteractiveService::pause()
+ {
+     if (gui)
+         gui->hide();
+ }
+
+ void InteractiveService::resume()
+ {
+     if (gui)
+         gui->show();
+ }
+
+ void InteractiveService::processCommand(int code)
+ {
+     gui->setText("Command code " + QString::number(code));
+     gui->adjustSize();
+ }
+
+ int main(int argc, char **argv)
+ {
+ #if !defined(Q_WS_WIN)
+     // QtService stores service settings in SystemScope, which normally require root privileges.
+     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
+     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
+     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
+ #endif
+     InteractiveService service(argc, argv);
+     return service.exec();
+ }
+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html new file mode 100644 index 00000000..00cfb826 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html @@ -0,0 +1,159 @@ + + + + + + A simple HTTP Server + + + + + + + +
  Home

A simple HTTP Server
+

+

It is a very simple implementation of a HTTP daemon that listens on chosen port (defaultly 8080) and sends back a simple HTML page back for every GET request it gets. After sending the page, it closes the connection.

+
 // HttpDaemon is the the class that implements the simple HTTP server.
+ class HttpDaemon : public QTcpServer
+ {
+     Q_OBJECT
+ public:
+     HttpDaemon(quint16 port, QObject* parent = 0)
+         : QTcpServer(parent), disabled(false)
+     {
+         listen(QHostAddress::Any, port);
+     }
+
+     void incomingConnection(int socket)
+     {
+         if (disabled)
+             return;
+
+         // When a new client connects, the server constructs a QTcpSocket and all
+         // communication with the client is done over this QTcpSocket. QTcpSocket
+         // works asynchronously, this means that all the communication is done
+         // in the two slots readClient() and discardClient().
+         QTcpSocket* s = new QTcpSocket(this);
+         connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
+         connect(s, SIGNAL(disconnected()), this, SLOT(discardClient()));
+         s->setSocketDescriptor(socket);
+
+         QtServiceBase::instance()->logMessage("New Connection");
+     }
+
+     void pause()
+     {
+         disabled = true;
+     }
+
+     void resume()
+     {
+         disabled = false;
+     }
+
+ private slots:
+     void readClient()
+     {
+         if (disabled)
+             return;
+
+         // This slot is called when the client sent data to the server. The
+         // server looks if it was a get request and sends a very simple HTML
+         // document back.
+         QTcpSocket* socket = (QTcpSocket*)sender();
+         if (socket->canReadLine()) {
+             QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*"));
+             if (tokens[0] == "GET") {
+                 QTextStream os(socket);
+                 os.setAutoDetectUnicode(true);
+                 os << "HTTP/1.0 200 Ok\r\n"
+                     "Content-Type: text/html; charset=\"utf-8\"\r\n"
+                     "\r\n"
+                     "<h1>Nothing to see here</h1>\n"
+                     << QDateTime::currentDateTime().toString() << "\n";
+                 socket->close();
+
+                 QtServiceBase::instance()->logMessage("Wrote to client");
+
+                 if (socket->state() == QTcpSocket::UnconnectedState) {
+                     delete socket;
+                     QtServiceBase::instance()->logMessage("Connection closed");
+                 }
+             }
+         }
+     }
+     void discardClient()
+     {
+         QTcpSocket* socket = (QTcpSocket*)sender();
+         socket->deleteLater();
+
+         QtServiceBase::instance()->logMessage("Connection closed");
+     }
+
+ private:
+     bool disabled;
+ };
+

The server implementation uses the QtService::logMessage() function to send messages and status reports to the system event log. The server also supports a paused state in which case incoming requests are ignored.

+

The HttpService class subclasses QtService to implement the service functionality.

+
 class HttpService : public QtService<QCoreApplication>
+ {
+ public:
+     HttpService(int argc, char **argv)
+         : QtService<QCoreApplication>(argc, argv, "Qt HTTP Daemon")
+     {
+         setServiceDescription("A dummy HTTP service implemented with Qt");
+         setServiceFlags(QtServiceBase::CanBeSuspended);
+     }
+

The constructor calls the QtService constructor instantiated with QCoreApplication since our service will not use GUI. The first two parameters of our constructor are passed to QtService. The last parameter, "Qt HTTP Daemon", is the name of the service.

+
 protected:
+     void start()
+     {
+         QCoreApplication *app = application();
+
+         quint16 port = (app->argc() > 1) ?
+                 QString::fromLocal8Bit(app->argv()[1]).toUShort() : 8080;
+         daemon = new HttpDaemon(port, app);
+
+         if (!daemon->isListening()) {
+             logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error);
+             app->quit();
+         }
+     }
+

The implementation of start() first checks if the user passed a port number. If yes that port is used by server to listen on. Otherwise default 8080 port is used. Then creates an instance of the HTTP server using operator new, passing the application object as the parent to ensure that the object gets destroyed.

+
     void pause()
+     {
+         daemon->pause();
+     }
+
+     void resume()
+     {
+         daemon->resume();
+     }
+
+ private:
+     HttpDaemon *daemon;
+ };
+

The implementations of pause() and resume() forward the request to the server object.

+
 #include "main.moc"
+
+ int main(int argc, char **argv)
+ {
+ #if !defined(Q_WS_WIN)
+     // QtService stores service settings in SystemScope, which normally require root privileges.
+     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
+     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
+     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
+ #endif
+     HttpService service(argc, argv);
+     return service.exec();
+ }
+

The main entry point function creates the service object and uses the exec() function to execute the service.

+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html new file mode 100644 index 00000000..781a154b --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html @@ -0,0 +1,52 @@ + + + + + + List of All Members for QtService + + + + + + + +
  Home

List of All Members for QtService

+

This is the complete list of members for QtService, including inherited members.

+

+ +
+

+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf new file mode 100644 index 00000000..3ba64c80 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf @@ -0,0 +1,76 @@ + + +
+
+ QtService + application +
+
+
+ QtServiceBase + MessageType + QtServiceBase::Warning + QtServiceBase::Error + QtServiceBase::Success + QtServiceBase::Information + ServiceFlag + ServiceFlags + QtServiceBase::Default + QtServiceBase::CannotBeStopped + QtServiceBase::CanBeSuspended + createApplication + exec + executeApplication + instance + logMessage + pause + processCommand + resume + serviceDescription + serviceFlags + serviceName + setServiceDescription + setServiceFlags + setStartupType + start + startupType + stop +
+
+
+ QtServiceController + StartupType + QtServiceController::AutoStartup + QtServiceController::ManualStartup + install + isInstalled + isRunning + pause + resume + sendCommand + serviceDescription + serviceFilePath + serviceName + start + startupType + stop + uninstall +
+
+
+
+
+ A simple HTTP Server +
+
+ A simple Service Controller +
+
+ An Interactive Service +
+
+ Service +
+
+
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html new file mode 100644 index 00000000..370c8ee6 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html @@ -0,0 +1,92 @@ + + + + + + QtService Class Reference + + + + + + + +
  Home

QtService Class Reference

+

The QtService is a convenient template class that allows you to create a service for a particular application type. More...

+
 #include <QtService>

Inherits QtServiceBase.

+ + +

Public Functions

+ + + +

Protected Functions

+ + +

Additional Inherited Members

+ + +
+

Detailed Description

+

The QtService is a convenient template class that allows you to create a service for a particular application type.

+

A Windows service or Unix daemon (a "service"), is a program that runs "in the background" independently of whether a user is logged in or not. A service is often set up to start when the machine boots up, and will typically run continuously as long as the machine is on.

+

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes. (In certain circumstances, a service may provide a GUI itself, ref. the "interactive" example documentation).

+

Note: On Unix systems, this class relies on facilities provided by the QtNetwork module, provided as part of the Qt Open Source Edition and certain Qt Commercial Editions.

+

The QtService class functionality is inherited from QtServiceBase, but in addition the QtService class binds an instance of QtServiceBase with an application type.

+

Typically, you will create a service by subclassing the QtService template class. For example:

+
 class MyService : public QtService<QApplication>
+ {
+ public:
+     MyService(int argc, char **argv);
+     ~MyService();
+
+ protected:
+     void start();
+     void stop();
+     void pause();
+     void resume();
+     void processCommand(int code);
+ };
+

The application type can be QCoreApplication for services without GUI, QApplication for services with GUI or you can use your own custom application type.

+

You must reimplement the QtServiceBase::start() function to perform the service's work. Usually you create some main object on the heap which is the heart of your service.

+

In addition, you might want to reimplement the QtServiceBase::pause(), QtServiceBase::processCommand(), QtServiceBase::resume() and QtServiceBase::stop() to intervene the service's process on controller requests. You can control any given service using an instance of the QtServiceController class which also allows you to control services from separate applications. The mentioned functions are all virtual and won't do anything unless they are reimplemented.

+

Your custom service is typically instantiated in the application's main function. Then the main function will call your service's exec() function, and return the result of that call. For example:

+
     int main(int argc, char **argv)
+     {
+         MyService service(argc, argv);
+         return service.exec();
+     }
+

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and exit.

+

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

+

See also QtServiceBase and QtServiceController.

+
+

Member Function Documentation

+

QtService::QtService ( int argc, char ** argv, const QString & name )

+

Constructs a QtService object called name. The argc and argv parameters are parsed after the exec() function has been called. Then they are passed to the application's constructor.

+

There can only be one QtService object in a process.

+

See also QtServiceBase().

+

QtService::~QtService ()

+

Destroys the service object.

+

Application * QtService::application () const   [protected]

+

Returns a pointer to the application object.

+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index new file mode 100644 index 00000000..494e0060 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch new file mode 100644 index 0000000000000000000000000000000000000000..2757197b7792d8ff6d6d45bcd457126e03c97151 GIT binary patch literal 57344 zcmeEv1zc54yYJp?x*JJpq`N~vLb|)VyHmQm8$KDJ4W2=~SfS?ybk;`<>VK zJMX!_d++a@`?>bsYt4Elpa0CPnfcGdLPbf|%GHe2+`-w-$d!~G01W^F0m7uD004j* z{QKj92EGCQK>+m!_dj*QfPF!rV@McG&=u(PyYrt$`R(}|f!_%HUqS!{37jxIJop3$ zjRHOcK@|Y-_xJG|f!_%HH%34i2n`6NH32vP>;OyvSAa9vWefhe0?Ys=086mU3G8ee(00#sD zu>QI4<3NGM-yaKq?EY{-5C8`v{yzRs06-J}6P5m5=HCeXM&KV1U${556zWr}_1U?4Bk%@}~gAiN+MgU_l=V1nr2fOURR~LXI*ahJ3SbJ3AqCDF5?2!ZQwHBFg3nR_IdD4404?yn z3|OuOVEFd}Lh=v?XoAnA09rtxJro?7o*poW>Zd9aU{dBgjpGbX#TEQ<21|?q5EAE) zYW>}Cpubk}?`*4`h>_-9|}zo*=vBmN&$=`l1M z880s|i0s!Y{aTfuQkcJ|!p{hhqW@6nSB;PX+_e6P+MgTIuVO)(RfgykBfl^?0(G=W3J;6=;N3Z;q4EC?p{Z;V)GxY?41fsMVxR4Mk z)ExYSEPQ_UMo5Ssp#FS_{0gX_@S6Sd836GY0p|lDVIBS*IF6gz(RP2!994KS%p3NWX*hqZWUq`ZonE;o!*ROme!0+QX0>2UX7eoNE{s)4tAe!@hzx)e=@LT2I2>eST z!0q^L{}1>T0RH|y{#6hNfd})xzzB5UzbT9jUK{;b1TcZuFs@)?#TM)*0r>kHNu&TV z@I2WB%vnH48OTf-GTr=cg7V#Nl<(inQ~tR9#0U=S2@YuoCUGF74kLJe{oNmO{$p7l zfLBLVDb$!cktaGb!Ygtx`eD}e--kl_TNkNJ@3D&Q`CRQ z>RagF`+xr`o&L9;|KbRI+y4UrzwQ4)0sn3P?_2)|asz*FR8ae?KJZUqkWt6ZtD@?I*MQeFXk-$n z0`LV25e6S(SBnU94!Gj19U~nNq1Q;BM5FQ2_B7}#*f(YSZFd;%X7z~II4h9_} zgo8nY2w`DRAwpOf6o?QO1{orRfkA=@VPFs;LKqkXh!7eE9wLN>frAL4VPGLba8QU4 z1Op8bg1)c+p}w#G|IPjv3ex`(0ke?5|8oUNK`lU;0Iz`0fs|l^c=msC#nL0f0M&p1 zAcQV90$6}opDqCAZ*(jpm}qtYOB}!yt0S0DwE!RzBftQ8!GTS{UPj=65SG~l>}~SR zjo=Rt3$z0U;sgKucU1qJKZb|U=l@6-|5#oBkt~K#$UibB1sf5XfsK_QbTEV>fY>#v z!NCBP06=)b$`KnsEaasp|=4erl7 zDWHFB1Azc2aJevmUVp1x|GbGo{keSqm>HyY{=CNl2j>4!fG7a)7h?aL1%RRhp#UYp zj{i1CARXE_f+bMxC&eZQt{uqT4=&>;!SdHW*nds1{B@+C=9Un9LC7AJE7+o!6rc{y z+!nmYWd?RbtcHJ>Q3V>Jezyqy10N^>#@+Ut1)}pm5MRHNV*Pa?f1S*K)foAwrPx0z z^eY2Mv2PvhAB~*BhRcS?aNq2BS%22Y4_fQ{^*e?3vrhiGFZw@I8DbA@_77HmKa>66 zr#62S=r1`vN0jfJp3$FG`~lR@a{Nf`&psIcxoUro^j)o=jpJ8^gfzh)G5^t!^+#d; zDwZmENOS!L>d$yT?Eiq^7xMgmC(nPI2jB04{6^sa9s(%fmxvI9CmyEY(aGfd_zwlj z1Atb*r{BkK1b!p%-v|K_D3GAmqi;*WpVn00C%0mM z!GvAQ>P;f8iPMQFvucc(^-9aq+F~JFY_DAS$E8D*&RYiMNT|g4#-@DKi<*fiPpJ#> zjIk^`kQha4pnae6UbP>~lO?~Jp52-Y?5hokoeCOQ2Pw=T9SgSD!M(1(jWnBNi34&l zdrqD~!*((DV5>YzE5W3Qp((gF?V4&v$-t-x5^?8*6^h1VfI4R5Ort>n1r;Lr2NPAF z$jaD=4>^M@4T}bcc#h25YW!0yN#2pF&|1zI75FkxBR;pZ4>dC3G*Jig*9K{c&rvnL ze<2LCe2MClS;xIBz{$>N?&N4$f~^R1E7!@UvSRvl2LL)fe^j-XXJPdbi$8*fE%o_* zOkLWVfXR1H5{7#k%@8}Suc&t-2=Cp$uE?GxhZ&$9*@QFUYiFT=BdJl<>O2?z)M#r~ zrkZzyy6Tml%VQAGNak7ZOS;q%+&F7Y+QsIp!#274h>7!>g?y+}&n3-@H#IWA@lgp9 z8iC1N%$Sl2NoF!%%#J7i> zYuo=3zYd-hVOc(mLA`*YBcKS1Creh0B`WIKI2@k>#?;`ed;KvbZsy}w0m9N-78q^% zVgZ8lNu|gxqF5rxap?#%9MdoRtf&JMT%82IMg<142^U&S!doyhj_X5Bn#J%$h~)$q z5eKjodU3X82oO-nKxO8WOw2z;tMY-PV1c{exvoSkOx5h%4P=VAs+G0F)3YZvsDHfk zAU_~-5ny`+=u@a}bNP$&MRuYuW1MrOwblHnueHzNX$AR$4{YHN*7meV*dO!4 z!oo54h>p3cdT)dtEjv2Fo`#+~e!>*!FWlv~R?0^t?z4S1*7f8`-x#jT6DB)DA<<84 z@J=~Gylpjm%2d2rA5_h2lJ*qMT%;WtBC_@dPfyt+&TR&tidaauMb54fl4Di~v0&zu zZi*0Ms@4x7Z0y4)?3kkNBV$cVA*SW|3+bM02jS3FfbHkO zuIV>xLoiWVZQEsB`6!DvXl@_W`= z{wO_puI?=Hrn89nK=W)~Coj}zbo=5ldGzR-#?f8rHYe5jcv25FNr?0HNIc}92tEuA zdoXBX!LlWyTafW)gMyO6?WUQprZLFZn59;sD1$c)eb;(}k^x|aa~vpQ*jJ5qE)@Kg z6VZFb)3teo2Ll~06=&|jsFjquFefxm({Q+H3RTVL4^KZku9yxuHTybgC7D#}%GRt> zV`lms2Dw4M<%CXyuj6DkJS+_i68-pI&hnmjVGubk^`x^R!8CiwmT)~*_L`_Rue;{c z#x%iIKUlHD_&Xi}p*MV9UemSQ)0{FY#~Cj`7cvy*LgNdeoM(6e2M=RD`XJXK&Ouf6 zSQDF4WRN;i5kfsq2kfL4nE_-U@|kZE*@S{0e~(JAHHVwG_+BhM6=;T0TjAn;L71ia z!T5FW`1YlAe2$fdf~vNFH^WiO`%^ug;L4W zm%!bB`8XprQsv|Dz9^?5L^W2&VA_C?E=vT_~7*Y-+)PZ@pEQHZ!( z)f3c=X^AwrDl+Rxwt34#qK3S}Q-~R`8;0KP86h&nLQ6CZX;(UXiEu!loY{6HB(qR> zW=9`-;#|?%3s2LtX;;1^??<~uHJa&}pO{pe)Nwx_z&s#dP(@X%=N+fOT4u+NR6@eF z*6lu8F+zkHytDK{#iIvuv151SaYUb;A74^jpt@(>wtT5-X|gz&-`i~$newQaF8J%xhK)D}~$gB9v0sk{&EUj^A-Xj>?D+3p$l+n*~~cNtDy{E0XTr;%u`qr1tp4S6nP%XxT z$DwboACH}jRfsaWwF|x&(x!dk*et#s+U$18r&&Ou7vJz;Y^E31|DaIrFaqPcLcBxg zY)5D92`Qy?+!+*%AKjIoS~NGmI&bcZMTk$hd7 z#?)S-Gz`k6NuDtx#H6R_=orJn2L+@Gkk6~-ck#r9K9-KFd4in;(g9b zOP~&Aq?h!-w{3B+>ZVdJtatupPw(cDjGTxSAP44)A?rGn_@`_th86sG%JU0d8PTCT zon9i0AGTk&BoY zp-xz&+O?ec>Ja_Rm}_i0+Ie5&3vvlkOqSa2N$|%qnVEW5)Ym$nM;ru3y=pUF@$VeF z#EW05e>JdkOf?yNIG>bzU$@=xN$v2O#+!U1k~a_e&-d>wDy*pS_cI3@;J#tIo;=5? z?M|2MKRntzCqBt**8#k&QpPB-!{^cDlv>u&S)6-Oe8%r73rY{qdh8!((p3~cI?OnI zRXZ4L94Ql{kEeiUXasdapO_qeU)Va>*llG{?G&)X&@nlIAFwGQ5TFXDx`e(@e|Z5| zec;G$o-CjcwPwV_yt#WR;0M>_M4E(*t#zLGmZtA0O`i0C)T87u?pn^NPCu`Fia1oW zs0dSBQLS*}*;09~W2XIw=YG%#$Jv_5$M-m!J?}O?-()AVzgac#`%DrRZ5l8vke)g{aY)R`hqO02oiY=z1WuOTteiV33gvKgwHkZPGpC#3ok7!qm7+*; zV#=RsQnh`ZdVqb8 zN83?Oi&x>%TsXIGNwhR2&uRC-F@w-snq)6McG)>Ho{s#GT_vZETDc#ABz&S;k&d0ZXLg>- z3DFwL*s6S0?8Um{%l0$(KdrT3X8H5@ih@iYub*2p&XKb;O&BDE;cziYDpaH%q-DNdZ# zUK!EnS%a%RYQnm5`Qbb}U*l8sQ0V-7z9jS5EUWAC9bRkZkkeFd55GrNTjNW~s7lGV z(|5o|z3^}E_#W`*Z^Ku(eJvP1sj&k%^0>Mg{xrjy5HfjR(nNZU+QRV(YfCHi3AD$e z^Z~8l8*1UBh^pWf7N=MNMqiO}n*?CtxV@P4;VxQAm3q0WTM7YxN%z#$)N~wl5n2?C zp(xhY5>y>!pyXkQo-|WZ_lcgd_0wD}O(shtp43+K-4hH0GAU8T&L|?4fmbKe>mHS6 z67zOEipmd#t$J<6nvLH|>%{_-!x3G^mUumx?4z_L#O9eutgK z<*kJE%!-X=hW^iLwoF8RCy{I}$lLJy>hMWvW?2(vIQ3mi# z0hiF96wCY*X{%F*D{!en_fe;q*-IIA?K3AEn_G;J;hW01B3Exjj|uBsrsDB(}2zO+dA~CA3jG zoP;IPgcpERYXheZ5h8TFVnD3ux~#Fp4owT3y6&&J80HyEGK5^l&JQjNI~hKzE5ztX z?S+SSi4R`iO(iLD+=a%|y7+v$4yv2k)3*+Mp+MN9=WRR+g*1PWD>+e)Ks~{exUy#c zao7y+ygsa&kZkYSxktFs($p!wt_p2)hO9lIM)j9zpAYn+hx=N)d$=a)l*~0gQIx(9 z&%dhAo62QTY{lm#o{n}qd0*qEV-@&WEG?~W>>N}(dHV?kc6TnDCJ$Hj7QKt+6xz(W zll~NSoXy`HzEUt}&oNK5u#I7_<0Uo_XG`K8S)7oZvw9CrDU_dk8!oCa8f7 z&HpbBf+-3vf9@MBU*aGu80*;tVvmow-j|HnPjx1Ejit&4Et4Gk*cq=szsb^*f3k9p zQgOy0l``JC^l*4a64zq$UFEgw^6kB*7Ut)N)xAVP(#2-J^dn4RuCO*osxJqM zBoS1~u1^Z^7pkcqY_CBT_i8bzXUK)R5k>3Y=PlBFZH2zl)Wd?S)G+@qsR*)=%Aa_5UvlGSU^4zbhbdx94H!Zp|!ZUh&OFv0a~`(uu^ z5m5u4Xg?iejOtVF)kdkf(O8*R)h)O;{)nJ8FNUr-m>}pc?7px{4}85fq+PsGL^$$R z`c7MwI%QBE@ZTz5Aci2y;9fO$$qaw8IMsgQV8^8DJr?VTc<2DIS-*MWyoiv=N=B^` zYt&QVD2}?|Oe^;gfjb9(?(-H2*OO4QE0zQ)1P7?&$H?^ZwSbFf@-%WxA7njKqF)o? z?35=7*{)v31UHj%m>Su(Z1`m#?=cSuBj~wdk>gXnk(hTCCSag%Q>?Rc7 zgxP)0L02RWBJWI>-RWy{$CX|P=Fdx&(1!=jTm&prV__u0?HP>anQx@r3XrA5QP2(N z6W_1*XzGd1o?VcQ&klY@ewBFuU1Xa-r<`V8ukwyfH?UyE!CueGd?EezW|;KJ99`iP zCsFCvvT zE(yAtuGn!+K?8j9hjfv`(DJ#vGpx>dM`;fM6+qRx*L{hXH)vkDF!q+c`YO+9Fft3! zEzbnWN2=G05WZGH$#GHmUtPE!&2E+ipFSi^ZJL~sH@vOxl95S~$JR(lL%d6OJ;T4% z$?V_EDNWJJEvebTBA_iBD@DrW2>q!3MM=HEZ$aw)%@MZihqxW7N4hL!b6aQGM%FJ3 zh3eTnuyrgRv1zti?X!Ut(^N5)fEBy8FC}tcJzs>zxQ}k9Ult)=2J^hmk-u4HA2q4K z*rws}8VqJWuG_IL6$OLFz1&UZ$miA?6{N6zF)whAd<(AFDV7Wh66=`@JT*vOw^hIh z%VOa*i0$r04Qk_BYL2$PXKLWXM=N#%-x(UCS*l5sjn^9O z`=f77_QyNsf!D6A8F%f}a(7?M_ej|+0`vIgN0*|tI$z7A)&-!m*K2Htw~ zIjXvy@lIo6FmhWG`ism(I!m=Z4txB5k>wQ?u{%5hIcC#(Grs;jv7opu!^^-_so8vm7` zSvk@m0~$pbKP@?Y#EqtWuW|aSBMpP!sxg(QjO|_Itz@3Le8Ut+(;eg0Ql6*APT+Y> zXkY02vosi2H=P65(iGKsghouzx(%1}VoCdAqfevw%CyZ~sJ2Dhv1m_KDyd7LQ~8i$ ziwQY%x{9^R;@es6bFKyXjt{oD8CB&Rz}E{-NWmVp9)K6>v>$u(Q?=CW_8O?;dJx}m zaPimD5o?^z^M!Pw4$;@4MF;lv(PxT3Eo=xURU{+b=3}5>$KNtg!ErW`$;iHk>%1<5sY)!fp4IS)C3H1a z44$U6%SZ{`uCXEh>?}#XcpZ^Ah3oA{!_Hgdpcsa5LNEdYj#SE!?o_4c(ub8t&qy6HZM-~uOGjfD79j*B?~+jFT3>f#dCkMaJ1;RPUm2( z;ki9mL-nE@o$JAFy@MMx%s^&fC;a-9?{um1TQ1BV^LHPu{DU;I0TTsI;a3Q`)?@BN zMbfF2NhO8vay#Df$_hlxdiSeWP(%lt5I$~6F!ge~(Sb>G7ts`lJr`ARr6A$k65?n? zv?O4TolTe9z71?+|1@D}R85g|l4rLNtJ);CU!I@q^K`@9oP(vTP6SP0wz=3#{%XES z@R^HN1vsNjbPf-+jSId`o$_ zl%GTW=rip@a31%vIiR2cjo=pqFunH7>D9J#ndid1JunEQn<8>c72}upiDf8vvnx4{ z*`2MOIw>ABCB;l)DTapyP}x*n95%H9XqD4U+oT9aHE|L4klge281%g#F34hX;e2?U zdcf_@H;+O+`M8&jc%S>Z(*FG?*SA_eCC4gH%Fjk8hP%t}^6uBy=2Ge)3vE_E;T7aH zjdj2GdQK3z`&l`~X@7M2l03enak~2OK-kK$RxoD)?JJS4+{UM8xwCyJ%Tb5-EEBVC z`er{=5Qf#yRj|+RKM+Lp$P@J0*dmxM&306keU74jD?0kY?zEHOX$c$VK27fZ4|G_i zN-c3>5A4q=WkL`rQnf3S#I}aU-iB+6S1d@#LC0UQROO{|VcdYsDKYD0`qPQi#M;N* zI^RahR?lfhulQ3)H?y+si1l$~;12qC&+~*J@qDpK#&FM{Q=t?BBa?Y`(45FP)88oXWWj#GE?}0`Jf6tZHf#p4BcmTm#ULVr%p05~X*7`hk zrTb#!ILVKiF<_GU{KEI%b8UBn*VhMXXO!ngt}N#ps|y$FONY#JT@3Z0u+5wB84ZUq zt?}5x__48PTgJ|vw_nXaf58D!x|^sHWIt$qg{m1)x)sQk=h{GgNJWhRNbS4#V&E%_ z<~@~@XO<1xU)9Halt-T>YgFsE_yHMrEOOwnygGKc3oGW$JS33Z^7{&}D$e{gaLH%t zRBI!8KnA#(;~1kzpYFaMVB*)?r$0a!zz@t1l#-*Cu#hcz8Q7jFyI4=y=8fLMtDRbO z!Km|ql@QjcuR(rIzrw8}Wgsk&%cejZ-U!NkI`kf_gh0jsQ$zs0^8l<$X2tQ?5iPo0 zk#qKy(R-YLW)9Myurvh z!@c%I8P*6(MC_xeDEOofv`7~Y%^X#p%ITmRx?DPAsIJlS_pLdXD8UhZm9OQGbYd0> z(yaRi)uwS+uG*mCK6dzI+}2Hm#@>0JUFN56CWGD-ABJTwtmtKKY^?jx zgF8Gv_(yWdetH^#Qw*Heaid9iS1V$!@m49cE&$FBjnJDi;bD4VfGxgEhu886_6O%n zdN<`yeV@Bl>YW7e;nQ@6u_Igu5^KC0@3G=xorlZ9-N1X5b!e~@lKQ%1V2>!!yTWJ^ zJRJUl&S)fz)3t`-I-np!a~Xh-BfosPTfmA61VVPt&ACrj#u!xILor+ zIrzmt#H;laITj99HLkrA^Wi_;wA5gKO5&D2s7)e;-CEc9ViL~kwP<3)Z-A2!l zKq4-6H{A}J*8*$2IBUW$dfgFEJsT!cdY5kF@lN<-4(qwxu^lgjlhKjUl zm=!f=mFo9YQwil#6TT)1`M7(YLp``+;H7pgeL057B8ePMAu!-3QJl0Z=kOqO+k+Pe zx729lIuFT5a*LlCHzkuen*_1G=gSh}2P0^!%iQ-Y@$!^V=j|dm9>I8y{zf4nd5QL5 z`Wjlh@uy<~sZKyS{l-dK#D2Jm5JZLJrQ$orZrA2e!MR~7<2V8J&4_ok*3;YsbotpK z#VM`0bA43#emX(a+;K=oD5a%LCLZt<^hf1$E^#3d2^NHEyvY3dFB|<`F7osM0}+GV zWczw*F82yC-f*rC+s$dOxgtWBCrG)`QyPVneDJ$&ygEY^E7aAPWbhVWzlmM@ zOrXtq>Kvm_Z#!!kP1m@bbxr8pl8m;0KKE(Q*7bN}2MS9{yRRPjBB>J@)G&$fe4&Nr|ZH>%aH^Ne3!ELbldI^Srbq~1VbtjhlFl3v_i z``4*SR{`qAz-vj0bDM%IB8yiK0j+ly>;9ohdIQsrZWScKwn0!L;U)J-7l4-NjRjTE zpCn865Zx@Miu)wo(xIBzm|9Rr8`xHXs-X{6`PtZNU%IsyQA00~KTzx&j~a~mfcDPO z0j__rL7a5)TmsR$rATOYAVvrGg_5%ytK%#&Y3?J%ek%trc#&P`XQ@2I(VUWfRWwkN z7HAGdcG)}=*JP0&qPRZb3C&H#oY7szo4!8^MF`-mlxCceZh=KU$+8W4+YcG^y$Tr_ zBT*P1pzgyvS;OgS1zITvFF5Li5aRp4QP925jy9VNfI8)<@1Hr9qgvZd-$&Tro+LS> z@unKF;Bdch){1@VREH#lH@9fz$^vEk{I+Y4A;;5Q%AVdVo*$+3egNNVhy9$^NAW{_ zLSB>=RyqqpXsS0eBBVrZHYI`;-bn&Q>4O1pl?dWGyIY^^ZQs>fh~!g(xGEkya**8j z9BL3P$Ie<`t0c2dZ=-nXbb$Jv@dS6y{fuFOQG%}Pz!^msw&<0{Y}2rGP^W{~k>cL* zdAZw}ZofgJ-B|TAnBZlR=Q)CSl>VqCpokg%J^uW0xc(*K;~_P1jT7&@ORA#kO2Wk4 z=!A|F&-C}ZG0bw+7}pj(+n&Bd(fPdq(SU=y>Z!wcoZH zM7Y~4Fsiscxfo>8*N@}}c<3+jUrNASIgcLB<0PzYQuB4EWtGRY!m|b zuEhu+LL$N~V!ICRE2N+<_wA|^ zUzMXz`wl7b&L_uVjq`B^9NVttvK6(}j@+@s=oho>fj!x+aJvJ|E)6YIQd7|5l@;x) z?(cVz^;%u}ZPMvs^*%5nDQ2^hthKoA65cKNuV+=oLqU04h{Q%6&`;8hanC2k&T&(R zfkc}kPAfD|vQJ*tBS4)%P2xzNOKI$$;xv6cB*vVgAePvlkngR4ImNG{z8C3}=-DG@ z+&amZk#b@W+~*50Do#%Id7m)EIq&sF=?!S-^{m&?bcx>~Tdt;FFd0jHqkfk_$=3xB z-l@}#9ok%_IR11EH2oFd8LgY;1zDbx0>_w-Uj~irIW_D2F%&Tu&l&~}^dCSuE9;*^1U25-V$|MPt zC)dYUc-_yoO13-K6{;6=7q4%2Vk&L(h*^BA7VmtW{D%sSh@SZR6ZBWx>(?4AEnYi! zc0`U=q(#QA)elFAXG9%ZtxSwJA1hf;!RuPZh(vYeh|${&I}t4{EW{q<#i!`^Niyrd zI@%>CC$PwY#uD$zGN7Du9I&s%@Mgqf_2s%WdLgZJPi!fxQbHE^YGKwS1EJu&< z=2pb*2Ku^8RAAS_(gv$cYK8qvR zDy43e!8^d{NiLDx>}uP!s96$OysFh`6iOFH>?&#jz!&h;GG|-C4YZcn^XpC=P-QiA z2EJQRSB}O;D_)t2piyRUBu~?Ip@*H7-V`u#Sj_imVQ*VC-4UopBna}AC*-M68moF) zmNt&w_lnPKFbXepKw__9vf(Wwh(>?yJ+=JPjQ4cIA?`x{#$t(i#u&^AcvW^RZ>=72 zl6X8ASZEhIRXB6ZbDLGt5isQ^aZrHq=Uu94`GOY%pFqG%gN6HiR2O$qsKG(Q zQ3o+uGdhC9mW+LcF@b*nBpm+$&UQXiM`DGcG)B#9CStj~jKQuK{n@7}nzOMUR*H6I zScIzmd=&bSb`@}cCkFq>I$fxw@xRn29nU@_>J{&di*wW?p~9N&&6IcRqj|G!!@j!t z*vUOnT)H;iw~wkII6rojlqj$0!lE(3*Ig*WNtGbpxCmDE^PX?P3Ei4?XA22SJKgz( z@E0G!VxWnptF5|Vc9bd1-L_?x6BiEK%4c6dbG%m?j*{`XL$w-4@4+RL+zHf{tM7Gn zvjgL?LRTR}F6e?yDA>(mKNUCh33yT1xz3>X7M~Qf)f%&*3sjC{W5s($o{zSpGTWqo zZPbA)kjs2>u}pJL4B*QH$Ya*Gf~;A*vJ}*ghpvk@&ogRVg&u@VHv2HqqnqT}H0R}r z<36*>JG#P1^l|3GYB8@JfM&Q@KR@r+;vkg0Wk?f7^@T#k_@sWY2JpQ?sCRwjtmSb;WPW!E6ueoTQtCp!R!Z^ri_7Kp}tTIw}4^?)y zM4;V5swbUXgJOgGoN|Rvnw>M_6;@Kb1Vw!$6j_3ASKf24oKyr01@@aV*wLvL*ql|; zfUk50j+xeZHQQxbuU4IdMec-{*x1Tb@UI6a2QOt*G}kQ$(^bY{-GiD+CuK(hc-hSJ zkuw9)x%0dq>^-W-&mevviX_eupGFD;SqYxQi$gWWbqfRX6@6u^#izbYu?oEvcd9o>MuT~T~D|n86@K3 zFxB8y^uV_o58FF*r@4YMak`Vi9c5(c%mrk~2t^OcqRok?+>KPrz?9LiAn0w1b~7fd zLnVBK8AskwMGJb&o6ri+L;vMoVtru5n`X&*_!gJ}f+=p(8Iyg0r$T+bE9Rh=FPA*c zBV15dYmmJ!-)sBDz1h|@R)Re_y<#eS+l+s9C=XZe1`;3Yn zjFN;q`cX??JXt#5+!VjUv8uC^uK}n_z$Wi_1Z?4AGc5>8I)*IFP8_FLCML^|*_6`;;lti!O zJUxQmn&>$wM*x&^lS-AE;$cJLgr~3{2*QT#@Buo@Q;?4Qo)54wDJTR#k%lGpR4Nk4Q|F)D4n%jy!dk7n+);~{zxpD>AhG>hHa50ZpWJ}$Lvfdbac z#Ki4xpIoCPA?qmJ@gsG0 z{1KcOQ#cHt%OdQ{R6lzr)Xpz~S{O+!F=?{Q%rrQVaQgy9<*ZKhT_7y?3#E0aW&KzbmFDU5+TD-i_3S8n7T}7FIrCrQiuu| zt;%%QC21wDFdhu($m5Ed=7^^{2k=~A?T?~h@ftexQQj#RV^WZ7_K$83S}LM<%11vA zQYPwBM(;A)TN2U>ttWifPugG>*93Uorpj!2AJxtq$dSREpjRcNTQD@@k{3J69AG3) z4~vEFxvP8Mr+f$5H_vmScH$J4B4JnLa{_kT3(AN4+uN<~K^JMuq6&$)5j~<0Qsps1 zAAkJBF^b|3PZ%IsgB74+NR)!!YfkD03z8wTx(f)qA}hzL4@-&YrGmd=6C)p?A7Uu& zSblZ^dDx%Rhh0er1PX_|(O}rTlph#-kW1M^G`qTtDEtYN18|)`)T~QTUl}Im`AFd7 za~#j+=ywW0mpNN_WDY`%+}shbfy$T1R}m4}@EHW2QKwE@_?LYMJqeX!Rv|r_%Z3-* zQKin-%0U2rrWt0|ZjSI?C$?uV4{)tsIkw=uAGaC62O#W_LBp(jqoAug7dQ%km}(yB z*qR9e5H(mE0G>@*>*tN|6eMCCpK-svFiW$TYkLrGs6Y@KXwn5^oRCW!*|c)lgM@?d zLAujkD}`Z7Kuue_AY>q5i14cfZlFv(JbXuDTyv4ntHGOY^p`^ zx#bb4^kbvM7kW`AF`D+yvtf&3Nll^NLzm)Z0g$m}3?uK6-=?Yrx_=;}GkO+|>?-~o zk7VM_MxUzK(;!q%%@D4xdzg2V1_7@l5|!2=UA4BbSPY3%$9znFV3xMa_hNh?~V;+Q7wDHrao zz7s?}iWY_#>^f@2Z=sF4$@Xp^x^LdwVT`{4dh(JjW(1Jm*N zyq`2jt&b88h2JdjxQdH4`pX9be?z^29pCV>1(^Hm^-Aow_I^ByV{J<04xh|-xEeL;&AUd=dZCtRTQUW7(nThibqk%cmeeedK&jt z4d}$F@7eVW2J9Cx_r;FTVIqQ8}?st7>g!;OpW+b)k*3wNUS=hY>kNHnA3Lmo9uro_=ai!Q`#j5~2FK z;iXFSK4q@bC&lE@UY_VV-Dbp7+tYIED)sK(uGXyk29igZ#Ci%@bR_JrNkZ#|5OZ&F zQrJ5lh;$@Nei23RVp2v9WPQs#L^_a#xc>CX3VFfA_z<2mF=JR^n$@#d7Tw@b*&`#p zlc@srs0&=^1Hco*!eN>gmQJ^G;wwT<+8Ph~%}(tO)Dc61uR}4lq&(1MFW}Di4vW{L zD6bdDOsjJX`HdNiJktkws5EAl`Nqkt>d|HFNO$e_@T>s$4j;dlmK^GYi^-+J z!P_b%)s8RL{@sbEJF$bq(>(Fy=&I{dDS;D}y{>SEqvmE3iDq3TpK@@D7@$KU!e7v^ zq;)oxptEE)6Bm$7o71@Gw=N?!)5ttD8L?L3>@+qNf84+T1N~WO@oi`yLPYgI_K{c4 zSB^N3M-!VYRm1in6F92@F6kL$rH+xG&Tp)gRaJCmru6+uJxrdMC%x}^`}F0^{n#r^ z{CMg)w1W)gc^SGTb$Tr{i>Z1W`+CqiB9(7iA^oO)2c_3h+8O-x=t`Vrb7erio!xDp zS(z|?g>GARbebE&wa!<+chfG6;_B6Uqc3~_>%jqyLM}z*Dh=X~+$G0s`ht0$q)8X$ z4(>M!`O%AWB2`RO3Cdgb!=4LUJ8Lw;mfAekS$?I5Z-S)zl43Fk4T;1~ea49^bu@7? zgUEE*%qRYaNqX?B1l1<7N3~QJ?Q<1cCf7!JF9k^(7sTfd8D{B~h!n+Q(t@gcY$FCA zb_Q0x6dN-=xeXW2dglh0DqGGt8ST_vJ_w@LA$x)iKl>O!KZcYHHxTJe?CCPidZ)&+|Ai zHB;^(Ei{Tn_0%(YIX6ZLJJkE!x7}Y$p`>v;on@3yyusWXe_pbb_#JvtkQ(Fk?NW)U zE!=jT^u}$o%-F{eiLrOCDcg^T>#Rx#?`u?PxZSU+@@P9i_DN5ggT4ZZpb$EFgf+-K z<1lP6iW7HBXO3bH6E%9C3B`I1gUa2)mRcfW{3!>?Ah}cMiy^@t8{85SjO62FtIMw@ zm9of%*fIU10gv8qq&EA%&=W|OU}l7xE07etYt~_|=?@pQNs90kJ4oF)Hijl7zT>%c zx)xVDeA=D1Ek=20XM$F%CW*%+s4=IXuHV#~v@DpNSJ7e4mGF5%D+Axad6_QR=cz5m z(R|EgozLdeaf=M+Je`Cxv8ACZ(QWG8toKt%AtGAFH&en(6%5%~*$A0!W%h(O#_3HJ zpJYKa)SI+!9kVatNAgW{!rbiON$3(7Wz61TwZ6+}>-h}FHTxjLFR)LzFv93Q5*eoE z^;|Sw54+*BHF{gt{H~O!Idz!k73fG=m!WIQ{8-O7C%s5IZeiOxVcP)jljH?7!5^<(+8QbLp;Zi*i(ojD6bO8I1 z@6)2KXDv)df#Z9bA~>&hz+LBM6$ZAyq{_M zel`9QSdZFmB9mPzWmKx4W>aE2m4{#4nyY0}Cb3;SVLvXUh4Vm})pGI&|;@?-M zsKH^?NuRBF<##dqZo?aQ`gPQ@Kmld{p^6~l{+aWYxs)_Iuon>K3K z`A;R0bEsBygkeqwCK|~-if}kdOU1=_ACKgeQF;{C&)BUyLJbGuKv=r}%H~M1j z8cIn~`9Z~7#xN8$JAV((zWWotFHNQQIgY{oAJDDcc$xq30HHn4!kEB}Yb($z&eq?K zrIWtNa-Mc0uUu9mOVTrA?&)B@eU(Ys8sOz7jf!5h?)K;fUNHEb~xoG`c`2n2pMWy*RjL5jjfnx(Omfmq;eoji#Mv)JyNBt%!N$8e-O? zjO;OQyN~sYc+@#xmB=!^gw@6(!kd_1l%8C}K|Q_~!*9JTAuXf;q-W!yFsv~p8F)Y7 zYu;n@dEx6PAE*%dNoW{cTsasqL?oy1M_5J#hRd%7b8E8;KhjYww03YwG?fCUaOV^I zt=#B@rZ4RtfmYk>bhK^fM9|4IqezRK5YZ_R+oq`UBr!s^UGr3!D9ly$qW znc3M(+m&slMs>`5S=bL_#!|7d;&P!5GC_>GjQ4mpUCeZphks9|GJa?{`lpvokx!tPUHZJjw#`UU9MB#7q z^1Z3(H%^LQy<bNRXf)ND>4=Ns>WSKolei%61>G>p54>(fjT0v->>zH8REgy29I4^{=<8o#|qk z(RU6?Skml%b&OII2Ndzv~jIYpR6A( zok@Q8>a*>mHH8B95rZ#Wv6YEk&SI~p{d!ySCR78Syw%pzz4$gxWxs^UWr%+&jJ&=m zVe9TK#?u#H8QLX1=Ve|YzZeP1OcN|7nU!8~9524sB;4Aw)~dm<-CP-ZO;WV_s{Q5( zvWXr?!oxu5n_ywPX&-woaT+AkTIW6aut^c@7jlr?LX|)4u(mKSgXvxwD%>nQF({z2 zE0COjer7ZNp{2CKs1aLK(s8;GEo=8Lx5n>xbMg}mKiZ5pXR0TXEbQ9OUbl|2*_e_6 zu5qdSasMBQFhwB0KrjD$k2EqY3`7|>^t{nr=wo8W(1+4QNudv=S-dsr%6#6LAV@VS za9h&Pu1mjBBd1rxbq%F>hMAqU4N>5_HnKRmBXp9St0zHn|6W)k8$!W9|Go4SfGuWPTaO(tlZgd)%SIO`$jX z+1VKa+kPHiy0ncdgSQR2^u@l=+2p>I6PGE-Sk&4U{9m`2ww;VsaNg$0_XIh2ZB{7< zpP$joH>%iOJ)z>5rgX0KC5djc=+#BNYc8GfKyoZdA* z`*IC+?pa{~bFUbR_=98S(?-nWkIxJ&l~lae4#ztjsh>G_V%aJ$yXK8V$U3KZ0$Ta? zO|0U=fXb|QpGQI`0<-Eka~1E8TrOXBDz)n6iJbY!`Y|S!d%>S&s9r!UxcaMuMD2Gwom{ckf?Fq|t4Eu)Ude@n;38@}$crcfC z@$%CT)h9_GPt`qLyaHUf)cnGQiO!BymE!hZ)E=?5VCjcD8mT0Xx~#j}qnDJ(BI#?A z_^s{^HPMJ%;q)PYm>dh;NVPXo&*EaJIj>!;nBrMym@#b7*U|_)sYQG?*B3Kvf3tMU zwN{g?U#f7eM#eHODlRAW)}wPw@Q(NFr4E=Fh+#bh!aOJ-XH63Bq3P>iD2$3vyZZMe z=lTS(C)_Qq&7JntPuA!f*#6c>Njb>B_0gyG&&05(B2tyKt97#{rX)p~agbQcVW?+c zeI7m?P|vJp%KE_9rH#?6*$+bk9#aNo zhIY-)L~F`CYeBABd2k0IZeUxeq@Vfct zE9X!T!mcwIzo7fYp2ZDcPjQBS{kKw7&Na;ots#!nbh8D+C(b+ykhb_rb;i%9qt&5v z$(44q$i65)K>@0Q~0ak_WDtxIc|fK@0unj zCi$mIh2qDhM}%FN=N0;gdyG0z>90LTL}qr|=wz^u;Rl~nz$DvAu9hwaZLoMPG+WTu zMtB8v;>B^p#tY_#8T@vbJ)Y9%lwYb@xRRN?B(Gi7^gj0fsqxh_Yy_H2Ry9Iu5T`OI>-gyvo9j zw?>iIS;WZg*;O5N-KZu1Udyw1q1$28UjoEEoZ8#G(^56KUK|&H)qIhfT3G$LrZ-zQ zxA)_?GU}jf_*!)=Z9*4jUmOK}4B%IuvM|z3S@XCq zP#d3O#O`>K`yD;2=)+R16Qw1Dk?EEq$2pHv#gaZcs~7Jggh@(@N2u!KPDW~YUn}tN zkxS;?wkHW%22nc`OHfKs~oe=7j!<> z6DO+9oel6uXqPFd94tK6pUK4t7WSW3o4YLp|tvJC!QomfJBeyP=&bI+wuYz#8x6t>lvy?hL!HYUeEJ4 z_S1SI)O)Bfm>+QR-ojuKtIvt;owFW7B$QY@B1fa@p9yC((H%pwncxK>PrV{An#q*X zN=%DCU2u&sX3X%kVx3;(wb#K-{?B%~SegVdh;{a_*ineo>x34nIBsUJoY<}`;5M|t zJfPxsRZ$Sk;*)x_C_sa=;;wL(Mq~P%$m6Ty2tbI=SSC8hS$Jps$vWxED>Wh_`*Zq+jS;E^|xv zP4^Qdx2!ZWbz!+^`AxYLvFpOt#25DK?G(nk$44exk`g;ycjPl$Xcv$bA*v8ad zZOOIfgKn*=CDBM$M&(&(@pK|J-A%W!Ynk{*}!b9l}1vtz9`uACaE z)2?xB#OA8JA$J6lSTflSh|};S+xI*pLW1;n3^P__n^2||Cnzc@PIM%?-FiO~ga4Li zlJDY4$54lSA41f?EyJrH#+2Ux=~yUnHlHjman99yGJXf`WWi46@9$~4p4xikdZ^m6 zKCD~6+UIrbGQ9prq~A@Rd3`qass8ORA7U7jeZy~R$R7K`)F~|BXKQ>7dDpA-sp#Fk z;e7uy9(Tnfi$4tdtkA2s#pLovtn-};nRe%Py?sO8@}^N@j6~vyg{d*!Vu=1_TRD6k z$t2s0*IIel-S0da+Ih0z9#GOjYw?P5Qo7N_4L8jgCtOdIcI!UpBHtFPu;F0i>Prhf zL|>2tXm+FiL6gv+XhY=d(uK^g3B*>?=eY@tQ zU-MLK;-*-qhbFqtHk`J&ITLdHvvNtbh4;u@8C%1XjS1WrZrklDx9?XqRR_*tKLeF? z92$eTKlIj?TCXU*;V=}}vm%JaKX`X+yJWOjBA)IBK62D|xH`ycP%km_4XK5pF2ySb z_1$*qAspd6UqQ`FpH_W7^|ijTv{smJG9SJzAlh!HJUHNVY~t%cLnZ%BKM~D5$pEa{ zzV!gw&QFcWL+`O~G&rV`oz*tn&5H_h$9_=HImE~>%oU(1lAe$k;@9t6%2g^eKJI_L95@DEcUUdM_7i{ zT2A~*)`T@3g3S6Ll&lp$sF_wn^J#8L?I!6%GP|B=LGir%nJ;mfQplgXT)1-Bz~HTa zBf7_dfCsNvjdLwx?oPMpw9NX2m*oU^!5d5>Vd{77Y$vy>2#p6k6bfr6t9M! ztnlnx&PBW~9NjP+TA1_@S{^|STXv;y$+p#BDM018;_4X6O4i(Un-lX13|UTKV;rA# zJIOPdTub$^8QW{eXl;tIX*I9^AYLnMq;WWQvafg`m(z7h>=n;RC0+lkem;APfmH%WCjtT~~` zRBunc$Jot>C8j1u`mD6JTojM5Q-C6NEvQr_@{5iyQCP3=LN)j56!>v?;Zarn8EHBO zidRi7W7EX%_UD{t^L9;JGR$$>`EohUF1N9Xv$9b=xSltV8eP2gzFJxDkg}PjVe(xx z-uvnO)8s_kmD?fP?xyM{VEC3KhF0;~;pv8&N)Pq*-9g79qQNRv*I=TSjdv%TJ62mW z&4OJULp-T9<8Wnn`-`ScJ6M8R_XS9~4ER#lKJMs*NZCFkBup50-cx3EUO%4ipLZd+ zF~I#ZU7Ag^+Q@B>CeJBCpJ{%#mqSjJTLmBG*YSh-u0Ao3vj|)0Q;``$N^MtO?z*Ym zylFl$x5@&^pUWWmYMhF4n2ohTgw~jc#e?~RxaIYpTAPJU&bAAZZ#i_%-n1DHWPQPG z?bVwR8)HJgDyg$-K;RP%Br;G>JWf)g`fzSY`$@M_Di_Z)mOhgk8?T9bDcv%fI z-g#wQ4l5r%2%5EUe`H}3S|HQ1dh$ee=gC){!Vf5ogrb0Mdom<5ur}}}N|{)lkBn@H zZ$nuxzdhmed?iVyfOKZr<{Q;rhEw7(a_pry-e<(lbL=Tm+P~JVx2{Ql9;k<1>akUB zR-JLrtZh9&>8?UxUiD=`k}IbXGBt4Jr_@-RjISkQ-FZDn*E%zhP}m@ zqHx5Et-)SPt}z1171ppK#uVoe{4-MM+j)JdGot-*n-0V^%~?rv4lMgwYh8x1>1Es= zFBuYI=Vz~2dXlGvC%JR8x%2^nikq=^+Z=nL!`x5w^Bkn^RxDm}o~X;xz;hh3zZ3dd zc2gV%`VM(&@`&qh5PI(wf^gqB6(=S}D7ua2or+2fmU{yHx z&a5@cH^NvziLmY3#RQU0Dee8LUTeOULCZokF)g+ z6tV7sKqM`4;`jNO}}%mw{#-eoiw$V_dPJ(Q=+dgeDYcE0=JEKRWdi;-bJ zB8IFF&aqAeVUlsKDsl0$Scm0TMa3<5OXT}-j7%yP4Sd(T71skUT~n{YnhVEbw!6qS zqQtOs!U$o`A2waDYd~D;V-sg}=$m#{sz;6kR33OOo;?<+=3hK{MLnR>YH_l1vb4_bwk71DTIuPs*ux`(?SBGXS{9iOC^ov>YQ%StmS^*s0_+B!mj zNOk&%P0K*4Xp%7&>u^=))d%t?x)}X5!zJL2JS-6f^-^XU-OF|QSm;EJUhZhmbg)b3 z775cQyZRHQ9{V zqqoHt!>JXT?gUmLj=0CK*kaGrAZl)>oi^#q^@%Y^wUM^v)Y3Yg5i6ul%8}(*o6Xw{ z>7Sc2?4qlBf$quc5fv+dF=E0**8(@}SZTgDN25pz?&tXmlA6g3_S$!+ohXFR`WJ0v z2#LXTFuTS4QHxgjtecQIai{&$2Yu9>VEf@Kv1e|#S^yptOG#&w{HzDt#3H31ziK$v z3Xf5#=w$rb`+|z1ejiy!iT)AXCUHC;vW}AMF1$qUrb}_DRl^p`hfbD74{8zwt-gNw z%(E+{dCM*M#O!SGGeWR4{l0`t-tKf|rr0<^gEUN5Z39JkM z5aV*Ne9k)YaFsJI;`Eb=E1xeq$V;zO54OMA+5cc{dXsazfGgy6TZY^26uHAG{P2|Q zhO0x=$)3C)Fin6%QZWUSXiNpdFS2Ht>x4Kw7` zCey8XK1Edu>aZIQ%=}srQ-#D05m7N6lB!J9o@j#S=gw`c4Eo3LRRz+njD8Ar~Vid-m>xw_Kt8K~@QgZA4+mBQq zKAdr=L}3@+vRoiJ{Wac>!nrQwiuVgrk~$)_q?VEUtM}>%iS+1*Wuyqo5>J_Rwvu1q z3$7gSGg`mk{E!gYB@la`rL#42p0Iq>=~fee_()RVa)}$rV3RdhMu1 zLlxYtDdywLk26k+`Fvti)=xi9-_BndJi067j*;1UK8)*!^c4}=U=eB)~ZT$J_WdG zwT0B*8nt-%+UwG@>BCWDzm>8FZJ#e@8}K;XYZ&i6&>J(pK4`M+W7X`xJfUUWBtmP- z?X`2(K9tS<1xg*KcJ3mdyod>-jERk%lbxDAo573T*g3y*F9bhTmxHB9?}>(p5zn(2 z4>ofmMH+CPSUfsWGMShkkY{!2o^PG6qCmayMOLt>tlF08hE?s_s4cbEhm*_o@ce)7 zskL;eO0H&Nrr4?+#nVy+dsl&CS+VEoPe|u(yq@Hl#AwjrQxWb?}jRo6Xn8cGT(9L%y?FzDw!F#Ux|8Zm0`O z=i3)9mo&+LDKgldB*lBo{W3kEVU?DC#7N|8RT1O+#UL}w_T*eM*G|uS6%w{R!Q&pe zhb9jjBO7b4kJdZBx=vsJcGB;a@nkVg{e@B0h8ZsezZHTb^G@GnVFQVMjMRGETj%Ma zMvbP@u_oi$x-+fDV-HfKB|b5K)dEfnKXC^iC?rO_0YW#tUg`9_R2kFy7~nz^kTi6q zX7L_|S5T1L=JIM;a=<4mgTO(hK|~yJc!gYws*c}Q{9fcj#A^d}cQ&b)oz(aj=~kRl zC{-gVIq2Pq)E92@%x6a)UJ7`GT_f)@(Ka%nAv#euE1~qxBEIT4|5cQ8*QM+=(Ki!e zcX~~BC_V|^BJgUfp%-LbT}`}ESv$k)lO>R2|B!~psXxD$^1dqF;c0^yBl?$3Rz-}q zv5ag{u9Q_lh%)!bA&cn&@#?}?ToJkrEjZ#6k!1wM#n;Zpo)@8@)3lSg5*#RfFj(!E zdKxbXzvcMa!h5rWD;+LRq-$f6dhI?k>+U!|YBHOc)}PNkDesc>aNO9X=hSDf;oNsu zXs(x4ur-rSls%pZM;kgx&~%1Ja}AoE(Tbh4i0}xsYZ+0?%}(9 z>c!euJA2=d4Oc_0u4$K=zTw_S9y2e940Ags2ZGaS8&+;4EF&s8cJ&&(8w1zG)RXy5 zJ~uK}FP0N!f9;O-Mpxc^E_CVG!?^w_>@U4%7Swfj23!Ne9hP_}mx3!kYNZWyuP$n@ z6_1k9Gqy_5na5aZ&r8%S;wagBo=qSk%1;`dm%7bU`Ba+VY-KZElYwekRJml)Qt*z( z^8Ik)X41)lqSq(Nt~`+ry3?K3&Ang7Qd{3@>P**MfVHju8t@{O`Aj6AK1>3C{vX;5 z7=fIEUjBbQBK2`F5YZ7wobDZi*7o5C!Y9N!`aCWi~dX9wuYFD3u$Do6ce+m zg_~V=s7piJ^i0Z^&6w(pw{_%0&ylNmJ<4)nI$=y-YPcp`6oeq^ntJPTK(AK1VUzeV zNpdkTJycHRUC?a!a+so7|DMmp`k}za;YRuMJjr@&-1AY+)j1=Bj@~>`SSw`LG)A>o zb+meK?3i=$=+u{#%I49Xqq=iO+Bc+khQ@&XAc05TRx4^tnX78Cy6v?Y^bA0r3AQVI zkzX>^+DxplFOj`E+e{=eQpeTd9o}L{80U6o=yK9|#TU5Z${L^C=u3$d+efbPa&ipB zW|W$K?ur!H5ud6h^H)46 z|0tT#y?+N=@a_xAc-LH_I!fjXL`(|nN|)a<@32yy1ct{AW(U$5Edsk9i@j;z;-?ae zyV7ACZ^{?-dQdYEORDK!(Z|?i-iAHgc==j>jovI7ryWsh0Sv+}`@~&UVf}c|EjmJq z{mWA&Zy#kW3NBeP7Rvw^bjwV$h_NvcwX6t)v_U}5lIaTkpn}7^hsZ89-QXw52TH;5 zyfwpP{X&B3StA4Yb5}wyDk+_jC&33yUQT`bx;@#cdR$RC)%v!7i`v=rn68uCdykRy zVWARz-2^;rRC|FwBQkN=ePl@+AzlogTtVicTb(u2+Mj$69CokwF`ldl58ULY6!;0RY@{`rSp2Zl0>9Z zy>XeN-2c^KH3x3Gs&*Ox+F4TCw?RC^Pshr za!A@5Dav!IxOUyKU_|I6Q6@RPDvEV7&*<7%hsX;8VdJcoffM|}1=IU4WN}FR{e09? z=RoGF(reN~UC|CA`4S(h+U0eu7H^H6E6O745^4bhR(eS z0VEnv^@Oo(7HUuG&f3&z@mvSTK-V%I2k#P_%%-LHGpf&2D7ABQNGYn{c4ZK3^A9ZO zHj`W`+__tm7ATPUYDV)lt5qyNKdGAe!@RH)qke9b{Sr<-&pmD3QQ}E%LtmautYMi> zUd-X(!hiB)vHyng+%x~oFT)eZ^cPI)Mc(Qe+TYQ^Zx0Q5E=pg$d-p(o@t$jq>}knV zogT{NA^O+EJbe?pA!ABcu=1_&bOUUBCF~HZ4lXMAiM!ceYA5W9IIkF5?;Up=9}F~O z|B`-Y(7SF<8W+HdQw+I&t*ZWUe*9PM)T}+4%l&wc8LCZteYB!;^@L*Y74P-$g$*SI zi$KD{y)<9Gyjm_I%tTmAem$Hl(wB*|VJU!4V{oUjRb9%L7?pcWB4`mOvv9-maq+9B zI*c=qFNco{e*J8oghDFiuyb#CJQ-;74IX$8pox2o`O3-&nsxbB=Avp|otLCDxZd7N zVG~B|P5e2b{H>Abd9hnxJCvqJpAJ;C03O1-Ld971jcNYuHOHHK= z*-?Ks^Ol%dP?sHp6M77C#nc4$hkYu6_qT4!G~KFwD;PLF@v8jE=h`o3Lb;bUDPu5- zyMz2ybNdpLPc;|m#bT2ULrpH5rHy1dA_bB@zE(u#^KPj0FJ0oK72F?wE*vhvXBe397bu0y}hp*;`aizjByz! zx5oxZ4Sa06H#qheU*S&Dk*c|5RUI3cU5hRSo+4bIi7*Ico%YRL$pLFl8C{R*?#_HB zk3HIHf9-SSsG+AeGrv0Bo&=8WExYO`N#ifEbW{9k=i4~zHM3K7D>RfWb3%bYNdG7M zT)_Mi6(QmBu~S?mWJ+Ul!H-p_H+{AM)>!sSA(&(m4q$jrvC?q|H%HxW@z2$dN%|wR zE_|g#x5iU3l>6;IoAJ|Ua~koNAAdf>fR*q(I<>**nypJ=yPs)cqGmNsr<{Ge;OiFL zG@Pt#HWfKWo3}4Vx2vku$T=4`m{`u-XEm?X`ikS6J+ex@%Opm)RqklSL2I3DfYs4@ z#dUVeIkc_sS&%@G-%jxANy}ehOMKt?Ay)#!S zUcVL6>U;#I(A>g(T>Irt>40xSg2r8cyVg(KDG$wdRIXC31XnvPWYxbobtw5UTj^Gdn;cU43H1uQ9z< zYVl*7ga^)os2XqOeZjT-B;DO*<%X{rYIf4zmp}L_&6r!XGn{Z&bI{(u*FJ>9zW#FY zSeFD{QLJ%FDDqS2R`4}EORQ&|p0pJA-j&L4b7%7ki(N}{7v{uJGs<#(DS_{`eXWBU z|G7c~dB$@G#;TxNrl&0Y<#M-4D?lP+X4$V2Y5fO=TMy2&B=`!|Yt%$0pCh-`uj#SC zd_&#F8~$WV;-a-`Sg-6-^3>t@6E#g5`LaHZn6#BQ(w`r%G!3pORWUV+Mv~u-a9X{R zYHIAAa?3nU_OhqnEgcGeL7mxxQbT?JkBYp#T-*Xtf_}*E8X8}P3@Ik8OFHekV%{EV zjR(|Hcmgz|4swVZEH(}_^}!|OvpjB}+fT zeA6zpU+MG2CRuAF(DJhGl(Fr2B!&PVwEKX*PP)@?Ys<DC8Q|Dvqn>{;IX)fCopi@;m4Rg6`3<8V%ef(Rn(3BIA!3y6QdmF9?YqXz6qnt< zHkQ^ed_DJUL9Db>fXlSR`|+2dfOUs7RVA060sCAJ>@HdQn@uH;tl2qMHhPWF)An7( zE>tXci5%Gy&rOxYlsRrJK=ETUy zB;(2anNd9FqH(nw@+GY(YP@S>G8?ozKWRGqFnDTNSdZWT?6rB$LrQjVwc>STqSaL_yH zXrH$g)mOVx;&8OeOq+1Myjpj{MlJ%9XhecyQSR}#cr#OVD*Zc*7% ziR5gFT5t1B^YCY-*{a!o)@Pzh!WlzFa|7Pl2L;NL-Z^n!Ey^cv-*{%Z71cHDy7u&j zDOQ^6(dDeH?IQ1+BJIqO`dPwpe*~xR^nwG_Ob%Fl+&Ei$mxMy}7ixtsPH%ad@MhLzWBq|>Z zxslx^Qhz#HN8`;Sxq`y{Eyl<*X^-WYl672&?_~R({9?B2I5Yby@vbpiZfQ;~Y|_u| z{WEkd?p&dzi56aotVon9zF)cLb19c|DT0E=A2K>gnangqS1~jFJaJBUQZk(mI(zc0 z%c#pO#qCRJt2G2YY#*GoC-2?!Lf^_$zY|PL`_OSbgkrYIf>8;J9c%j*6TJu4wTRnP zmHs&Wn%zOo!yeY{O8kJN^xQ?lt?t(D8=)+H(Hp}^24mH-2kdtaIQFv69n1>pJ2*%- zT4BC$SH1F@{+@kT;d~35KiM{WCoi{|Za7gDG*~ri%JKHpUxS_ohWYBv>SrJ8{`QsJ z6p=c$it_;-GV@iRI~lEVa&o-P&*$>EIg620b4f0fC!}qNo8XqNu%~Y6Od8n{mC_Ps zHb%Qubj>~JxSvmcC{=E>-(g)9X!JfpYE7$eV{baP2>K}R@$==6GRE}s!&*gd@;XIbRfkP%1{fC-z~xu93aMvDu(cwUE6 zMw|G|J@e8AeYqqi=InS`BO5YiHwQr5tOOTB>EgZ2mjth9+f5YI6IGPhGk02*nh$5P zy#+E;#5NDMmv@>oC+j|+G;X%4%F2SC!pb`>F6 zB_$AnZD`LBQh+JD82g1*%*lI)=YXi>aK`<;^c|y$y4a5WO*JexJtK-X&LsO0hPsJq zPLZq&HDga#=eKI6OjE9y$9-%kAkPrWhQ97oO{jvv?7*gCBE2H5(1#ztQY3xZJE1nA zMHcY5B|ayhCa!gA(fOH1V%VvQ)t&nX5_G`rvxQx_(PwZk`%%XDy(Y||>ZDfKV4Y|r zvk_?QPER+M=Y$<02mGT64jm`m+`Q1sU4f?E0l3314YGtmr+*^aM2X4{W3-yjAR zFL!=vGPD2u;$g6br*IgJI;GGFyx0W3doj05n*tx-ws~AA6WmPXUO+4$DE#`Kx*HN< zh33C{o^1) z5vXF+Nn{@~2Pp=O0BHaKq5ty-8o+&gY+PIXca+ZIZ&mLdeNM zjqvx`|NR*N(;5>CA#4c%ieX1&@N+`AhL4H~VA()h#=1jW#+^JOA4?DmAqF*_m?c!9 z9?;IR@RsR6HmN(hn4{wYSVwbS3@ijc|B==3bM{assBfJK@tmQd6?*{!lyKev2QUOR~01I*c{E@{fL0kUmA+-Kv0KCWF&jlSF55R!+ zkBO*3pe~^Rq$@BE=tFP*-#*ZcL^udE0B!94t8qgf>X2^GKHau|j3C~BDF55;>^4XA z=(e0%VyTl-3u@!RHqi{Wb1y*g!(?TjSc% z*YdNz{#-jpr}-V5@PErDWvJEc{up^&|8Yq9vrR{*`Sn+;95+g&S0a4DkA+TK>6te#HBA(Xjrpp%DaSf^0|f10Mim0D;Jc!2iOb zNQH%9f`%(5k3aghH`L4j+29}X0L&kMTT?=A%o6~FU7%~WNBq^9{&R*$r2sIGqJ|V$ z2wq13;Dy`O8&V-WVp#vu;(w0~VE#Knlapg3^wA^$pl^!^fHJg(WbOlna=+;>|J=EM zCkFuYcVfwqVIhtg1HiHGk^i|OzsLHKIhv3Z8=;LR003=ks5jdFA<+NYRsA|WG?)2h z8E6WUZ%+9a>N$GQ`t@`Y_NRV-%x-KE--mi{=y};k=l3Tkz(NeUDG&|*rkiqudb!WP zoE1Fnf@f8>&^F!w+(6$P)!(K4wUw~`u@I>UR0K*GnTO;B+5sBq?f=ySjby+^D8m(} z438Z?|2DV!(Fp%sHUFFz!2IX)X!c{+2ut)a0I)nNBJ7U6Ax(QhJ;MVs@!Out|G7a& z=X11iN5^%fhbH3C`b7*j^G8?JfQ0D^kzbqibDD3(|IFR#un?DpDl;I0=gCqkRhD&=6A#$03Npgg0)BI`uo-%o&ML>>a$`Yj3Ed9n-%kW1_9V;43>X&L;a)f z1$>{3{G8qQGkzsG`Q`z^jB)BhX||J;kd zxB9QM`_c2hr}>uo&s_2Nzoxlx+22n8ZuWo9GKBHF{=fT~@43O<|GN>t%K4j{JSye4 zAq{q-N1gqqe^~@d1-XLsMq&ZAfGJ`DA^W@fM;|{4kI-DuH21$YLjRqbeLn5|Fq2g_rod!v5?d0PH`%)8>IX9^~== zaeei7+5T8x0oXtOcH+iH@WV4Men-gl=s+W{8}##cYu&%g`{%R(_Rq|Z>w9~^=aivx zz6t1?FF4B8{Zn~Ar~g*w&-^?m7J@4j0Jz}G`cdT1%KH1_{+tdj=FjiZf*g<=p+Hmo zM@~=u5C859y}JCHLVw?`zt7{>?&O>P(-0_k=l)%@M%gLbPwei+~1G(r$?CxJM-@;;Nk6CT0epB!u_V6?^CqD_fh|p_s0SY2dElUIrRU6d8q5CMAQ{%g%FJLLAj#rQ06Ejlr~BQC6AIs38PM;I8et?G$>LO z9ts2b1-Xq}N4`PMAt#W-$fw9oWGk{B+GDyDS%}O=rXu5!myzMf0Hi0<32BWqL+T?n zkmr!HNHL@Uk_X9(Jcgu15+SjX0Pq>u1Xh71U>X<&27w;v&O{S5JGl$o0`h?jAPI;C zB7qRV7jOgY0SoB9r4FD9C;(ExX@C#l1egF?fDFKgzSZy*u>)P;zYfp?1ueDML3b!X zv4L(-fMf$*VaNu$z>pPmh9N8H1VdKP5r!WsWCTrM$N(C{kO4G;Ap>X#!(*TU z43B~OFgyn8!H^!*g&{qt14DXH8-{eC77Xb?O&HRF8Ze{<)nP~rs=<&JRD~f8r~*S8 zP#K0apb`wJ!E-RA2G7Ef8dQWK6{rA1Do`GVRNxsHQi5_Yqy%MQND0cokOGv3Aq6M} zLkdt5hUB0G49P)p7?OixFeC#-VMqpwz>o|)4MS2;7>1;v5DZB{K^T&N0x%>2`C&)` zo`NAU$Ol7W@FWb0L0%XVfhS-{1oFU;2;_z#A;<+oLXZ=NgdhhD2|#uj5`b(lBmh}q zh!3*B5FccQAwI|iLp<;}4Dmol7~+8pFvJCq!4MauhaoOV2SXf?7KS(=4GeKWY8YaJ zR4~K_DPf2WQos-kB!?juNCrbJkQ9cPAPEdHL1GwUfJx zlt0QHWe=&}5T%Jahmt{wp!gu|Goq+aL?|reAvA+nM=m30kfX?F$S&kVNcWY<+sJ(6 zb?ClAG*rlcAOBqgf2{!!4XX`x8brf#LqZ{}HvkG@!J&jfG^{uz6vC1Npb*v^N(e;5 zqC-L02IO!MDc-WSc6C?ghdEIA*@2wNe~Uo5DA5_4gn~Hg^1z>(XbMc zPzXyAfI?V{s1qO>79$c0VKo9!2+I-01ELWy=K;fE%maqOlp73%AvYKTLvAn_hFo9} s47tES7;=FDFysXNVaN&k!H^U5g&_y%149nb8-^U97Yx}!PZ+ZQ53~s;U;qFB literal 0 HcmV?d00001 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp new file mode 100644 index 00000000..96d058f5 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp @@ -0,0 +1,90 @@ + + + com.trolltech.qtsolutions.qtservice_2.6 + qdoc + + qt + qtservice + solutions + + + qt + qtservice + solutions + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + qtservice-example-controller.html + index.html + qtservice-example-server.html + qtservice-example-interactive.html + qtservicebase.html + qtservice.html + qtservicecontroller.html + classic.css + images/qt-logo.png + +
+
diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html new file mode 100644 index 00000000..909b555c --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html @@ -0,0 +1,51 @@ + + + + + + List of All Members for QtServiceBase + + + + + + + +
  Home

List of All Members for QtServiceBase

+

This is the complete list of members for QtServiceBase, including inherited members.

+

+ +
+

+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html new file mode 100644 index 00000000..680a1df9 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html @@ -0,0 +1,199 @@ + + + + + + QtServiceBase Class Reference + + + + + + + +
  Home

QtServiceBase Class Reference

+

The QtServiceBase class provides an API for implementing Windows services and Unix daemons. More...

+
 #include <QtServiceBase>

Inherited by QtService.

+ + +

Public Types

+ + +

Public Functions

+ + +

Static Public Members

+ + +

Protected Functions

+ + +
+

Detailed Description

+

The QtServiceBase class provides an API for implementing Windows services and Unix daemons.

+

A Windows service or Unix daemon (a "service"), is a program that runs "in the background" independently of whether a user is logged in or not. A service is often set up to start when the machine boots up, and will typically run continuously as long as the machine is on.

+

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes. (In certain circumstances, a service may provide a GUI itself, ref. the "interactive" example documentation).

+

Typically, you will create a service by subclassing the QtService template class which inherits QtServiceBase and allows you to create a service for a particular application type.

+

The Windows implementation uses the NT Service Control Manager, and the application can be controlled through the system administration tools. Services are usually launched using the system account, which requires that all DLLs that the service executable depends on (i.e. Qt), are located in the same directory as the service, or in a system path.

+

On Unix a service is implemented as a daemon.

+

You can retrieve the service's description, state, and startup type using the serviceDescription(), serviceFlags() and startupType() functions respectively. The service's state is decribed by the ServiceFlag enum. The mentioned properites can also be set using the corresponding set functions. In addition you can retrieve the service's name using the serviceName() function.

+

Several of QtServiceBase's protected functions are called on requests from the QtServiceController class:

+ +

You can control any given service using an instance of the QtServiceController class which also allows you to control services from separate applications. The mentioned functions are all virtual and won't do anything unless they are reimplemented. You can reimplement these functions to pause and resume the service's execution, as well as process user commands and perform additional clean-ups before shutting down.

+

QtServiceBase also provides the static instance() function which returns a pointer to an application's QtServiceBase instance. In addition, a service can report events to the system's event log using the logMessage() function. The MessageType enum describes the different types of messages a service reports.

+

The implementation of a service application's main function typically creates an service object derived by subclassing the QtService template class. Then the main function will call this service's exec() function, and return the result of that call. For example:

+
 int main(int argc, char **argv)
+ {
+     MyService service(argc, argv);
+     return service.exec();
+ }
+

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and return.

+

The following arguments are recognized as service specific:

+

+ + + + + + + + + +
ShortLongExplanation
-i-installInstall the service.
-u-uninstallUninstall the service.
-e-execExecute the service as a standalone application (useful for debug purposes). This is a blocking call, the service will be executed like a normal application. In this mode you will not be able to communicate with the service from the contoller.
-t-terminateStop the service.
-p-pausePause the service.
-r-resumeResume a paused service.
-c cmd-command cmdSend the user defined command code cmd to the service application.
-v-versionDisplay version and status information.

+

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

+

See also QtService and QtServiceController.

+
+

Member Type Documentation

+

enum QtServiceBase::MessageType

+

This enum describes the different types of messages a service reports to the system log.

+

+ + + + + +
ConstantValueDescription
QtServiceBase::Success0An operation has succeeded, e.g. the service is started.
QtServiceBase::Error1An operation failed, e.g. the service failed to start.
QtServiceBase::Warning2An operation caused a warning that might require user interaction.
QtServiceBase::Information3Any type of usually non-critical information.

+

enum QtServiceBase::ServiceFlag
flags QtServiceBase::ServiceFlags

+

This enum describes the different states of a service.

+

+ + + + +
ConstantValueDescription
QtServiceBase::Default0x00The service can be stopped, but not suspended.
QtServiceBase::CanBeSuspended0x01The service can be suspended.
QtServiceBase::CannotBeStopped0x02The service cannot be stopped.

+

The ServiceFlags type is a typedef for QFlags<ServiceFlag>. It stores an OR combination of ServiceFlag values.

+
+

Member Function Documentation

+

QtServiceBase::QtServiceBase ( int argc, char ** argv, const QString & name )

+

Creates a service instance called name. The argc and argv parameters are parsed after the exec() function has been called. Then they are passed to the application's constructor. The application type is determined by the QtService subclass.

+

The service is neither installed nor started. The name must not contain any backslashes or be longer than 255 characters. In addition, the name must be unique in the system's service database.

+

See also exec(), start(), and QtServiceController::install().

+

QtServiceBase::~QtServiceBase ()   [virtual]

+

Destroys the service object. This neither stops nor uninstalls the service.

+

To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the QtServiceController::uninstall() function.

+

See also stop() and QtServiceController::uninstall().

+

void QtServiceBase::createApplication ( int & argc, char ** argv )   [pure virtual protected]

+

Creates the application object using the argc and argv parameters.

+

This function is only called when no service specific arguments were passed to the service constructor, and is called by exec() before it calls the executeApplication() and start() functions.

+

The createApplication() function is implemented in QtService, but you might want to reimplement it, for example, if the chosen application type's constructor needs additional arguments.

+

See also exec() and QtService.

+

int QtServiceBase::exec ()

+

Executes the service.

+

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and exit.

+

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

+

See also QtServiceController.

+

int QtServiceBase::executeApplication ()   [pure virtual protected]

+

Executes the application previously created with the createApplication() function.

+

This function is only called when no service specific arguments were passed to the service constructor, and is called by exec() after it has called the createApplication() function and before start() function.

+

This function is implemented in QtService.

+

See also exec() and createApplication().

+

QtServiceBase * QtServiceBase::instance ()   [static]

+

Returns a pointer to the current application's QtServiceBase instance.

+

void QtServiceBase::logMessage ( const QString & message, MessageType type = Success, int id = 0, uint category = 0, const QByteArray & data = QByteArray() )

+

Reports a message of the given type with the given message to the local system event log. The message identifier id and the message category are user defined values. The data parameter can contain arbitrary binary data.

+

Message strings for id and category must be provided by a message file, which must be registered in the system registry. Refer to the MSDN for more information about how to do this on Windows.

+

See also MessageType.

+

void QtServiceBase::pause ()   [virtual protected]

+

Reimplement this function to pause the service's execution (for example to stop a polling timer, or to ignore socket notifiers).

+

This function is called in reply to controller requests. The default implementation does nothing.

+

See also resume() and QtServiceController::pause().

+

void QtServiceBase::processCommand ( int code )   [virtual protected]

+

Reimplement this function to process the user command code.

+

This function is called in reply to controller requests. The default implementation does nothing.

+

See also QtServiceController::sendCommand().

+

void QtServiceBase::resume ()   [virtual protected]

+

Reimplement this function to continue the service after a call to pause().

+

This function is called in reply to controller requests. The default implementation does nothing.

+

See also pause() and QtServiceController::resume().

+

QString QtServiceBase::serviceDescription () const

+

Returns the description of the service.

+

See also setServiceDescription() and serviceName().

+

ServiceFlags QtServiceBase::serviceFlags () const

+

Returns the service's state which is decribed using the ServiceFlag enum.

+

See also ServiceFlags and setServiceFlags().

+

QString QtServiceBase::serviceName () const

+

Returns the name of the service.

+

See also QtServiceBase() and serviceDescription().

+

void QtServiceBase::setServiceDescription ( const QString & description )

+

Sets the description of the service to the given description.

+

See also serviceDescription().

+

void QtServiceBase::setServiceFlags ( ServiceFlags flags )

+

Sets the service's state to the state described by the given flags.

+

See also ServiceFlags and serviceFlags().

+

void QtServiceBase::setStartupType ( QtServiceController::StartupType type )

+

Sets the service's startup type to the given type.

+

See also QtServiceController::StartupType and startupType().

+

void QtServiceBase::start ()   [pure virtual protected]

+

This function must be implemented in QtServiceBase subclasses in order to perform the service's work. Usually you create some main object on the heap which is the heart of your service.

+

The function is only called when no service specific arguments were passed to the service constructor, and is called by exec() after it has called the executeApplication() function.

+

Note that you don't need to create an application object or call its exec() function explicitly.

+

See also exec(), stop(), and QtServiceController::start().

+

QtServiceController::StartupType QtServiceBase::startupType () const

+

Returns the service's startup type.

+

See also QtServiceController::StartupType and setStartupType().

+

void QtServiceBase::stop ()   [virtual protected]

+

Reimplement this function to perform additional cleanups before shutting down (for example deleting a main object if it was created in the start() function).

+

This function is called in reply to controller requests. The default implementation does nothing.

+

See also start() and QtServiceController::stop().

+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html new file mode 100644 index 00000000..1ea83044 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html @@ -0,0 +1,46 @@ + + + + + + List of All Members for QtServiceController + + + + + + + +
  Home

List of All Members for QtServiceController

+

This is the complete list of members for QtServiceController, including inherited members.

+

+ +
+

+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html new file mode 100644 index 00000000..6ec6d338 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html @@ -0,0 +1,155 @@ + + + + + + QtServiceController Class Reference + + + + + + + +
  Home

QtServiceController Class Reference

+

The QtServiceController class allows you to control services from separate applications. More...

+
 #include <QtServiceController>
+ +

Public Types

+ + +

Public Functions

+ + +

Static Public Members

+
    +
  • bool install ( const QString & serviceFilePath, const QString & account = QString(), const QString & password = QString() )
  • +
+ +
+

Detailed Description

+

The QtServiceController class allows you to control services from separate applications.

+

QtServiceController provides a collection of functions that lets you install and run a service controlling its execution, as well as query its status.

+

In order to run a service, the service must be installed in the system's service database using the install() function. The system will start the service depending on the specified StartupType; it can either be started during system startup, or when a process starts it manually.

+

Once a service is installed, the service can be run and controlled manually using the start(), stop(), pause(), resume() or sendCommand() functions. You can at any time query for the service's status using the isInstalled() and isRunning() functions, or you can query its properties using the serviceDescription(), serviceFilePath(), serviceName() and startupType() functions. For example:

+
 MyService service;       \\ which inherits QtService
+ QString serviceFilePath;
+
+ QtServiceController controller(service.serviceName());
+
+ if (controller.install(serviceFilePath))
+     controller.start()
+
+ if (controller.isRunning())
+     QMessageBox::information(this, tr("Service Status"),
+                              tr("The %1 service is started").arg(controller.serviceName()));
+
+ ...
+
+ controller.stop();
+ controller.uninstall();
+ }
+

An instance of the service controller can only control one single service. To control several services within one application, you must create en equal number of service controllers.

+

The QtServiceController destructor neither stops nor uninstalls the associated service. To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the uninstall() function.

+

See also QtServiceBase and QtService.

+
+

Member Type Documentation

+

enum QtServiceController::StartupType

+

This enum describes when a service should be started.

+

+ + + +
ConstantValueDescription
QtServiceController::AutoStartup0The service is started during system startup.
QtServiceController::ManualStartup1The service must be started manually by a process.

+

Warning: The StartupType enum is ignored under UNIX-like systems. A service, or daemon, can only be started manually on such systems with current implementation.

+

See also startupType().

+
+

Member Function Documentation

+

QtServiceController::QtServiceController ( const QString & name )

+

Creates a controller object for the service with the given name.

+

QtServiceController::~QtServiceController ()   [virtual]

+

Destroys the service controller. This neither stops nor uninstalls the controlled service.

+

To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the uninstall() function.

+

See also stop() and QtServiceController::uninstall().

+

bool QtServiceController::install ( const QString & serviceFilePath, const QString & account = QString(), const QString & password = QString() )   [static]

+

Installs the service with the given serviceFilePath and returns true if the service is installed successfully; otherwise returns false.

+

On Windows service is installed in the system's service control manager with the given account and password.

+

On Unix service configuration is written to QSettings::SystemScope using "QtSoftware" as organization name. account and password arguments are ignored.

+

Warning: Due to the different implementations of how services (daemons) are installed on various UNIX-like systems, this method doesn't integrate the service into the system's startup scripts.

+

See also uninstall() and start().

+

bool QtServiceController::isInstalled () const

+

Returns true if the service is installed; otherwise returns false.

+

On Windows it uses the system's service control manager.

+

On Unix it checks configuration written to QSettings::SystemScope using "QtSoftware" as organization name.

+

See also install().

+

bool QtServiceController::isRunning () const

+

Returns true if the service is running; otherwise returns false. A service must be installed before it can be run using a controller.

+

See also start() and isInstalled().

+

bool QtServiceController::pause ()

+

Requests the running service to pause. If the service's state is QtServiceBase::CanBeSuspended, the service will call the QtServiceBase::pause() implementation. The function does nothing if the service is not running.

+

Returns true if a running service was successfully paused; otherwise returns false.

+

See also resume(), QtServiceBase::pause(), and QtServiceBase::ServiceFlags.

+

bool QtServiceController::resume ()

+

Requests the running service to continue. If the service's state is QtServiceBase::CanBeSuspended, the service will call the QtServiceBase::resume() implementation. This function does nothing if the service is not running.

+

Returns true if a running service was successfully resumed; otherwise returns false.

+

See also pause(), QtServiceBase::resume(), and QtServiceBase::ServiceFlags.

+

bool QtServiceController::sendCommand ( int code )

+

Sends the user command code to the service. The service will call the QtServiceBase::processCommand() implementation. This function does nothing if the service is not running.

+

Returns true if the request was sent to a running service; otherwise returns false.

+

See also QtServiceBase::processCommand().

+

QString QtServiceController::serviceDescription () const

+

Returns the description of the controlled service.

+

See also install() and serviceName().

+

QString QtServiceController::serviceFilePath () const

+

Returns the file path to the controlled service.

+

See also install() and serviceName().

+

QString QtServiceController::serviceName () const

+

Returns the name of the controlled service.

+

See also QtServiceController() and serviceDescription().

+

bool QtServiceController::start ( const QStringList & arguments )

+

Starts the installed service passing the given arguments to the service. A service must be installed before a controller can run it.

+

Returns true if the service could be started; otherwise returns false.

+

See also install() and stop().

+

bool QtServiceController::start ()

+

This is an overloaded member function, provided for convenience.

+

Starts the installed service without passing any arguments to the service.

+

StartupType QtServiceController::startupType () const

+

Returns the startup type of the controlled service.

+

See also install() and serviceName().

+

bool QtServiceController::stop ()

+

Requests the running service to stop. The service will call the QtServiceBase::stop() implementation unless the service's state is QtServiceBase::CannotBeStopped. This function does nothing if the service is not running.

+

Returns true if a running service was successfully stopped; otherwise false.

+

See also start(), QtServiceBase::stop(), and QtServiceBase::ServiceFlags.

+

bool QtServiceController::uninstall ()

+

Uninstalls the service and returns true if successful; otherwise returns false.

+

On Windows service is uninstalled using the system's service control manager.

+

On Unix service configuration is cleared using QSettings::SystemScope with "QtSoftware" as organization name.

+

See also install().

+


+ + + + +
Copyright © 2009 NokiaTrademarks
Qt Solutions
+ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..794162f5af58e7b38beebf472842fc9703ede19b GIT binary patch literal 4075 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 literal 0 HcmV?d00001 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc new file mode 100644 index 00000000..31c3e87b --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc @@ -0,0 +1,46 @@ +/*! + \page index.html + \title Service + + \section1 Description + + The QtService component is useful for developing Windows + services and Unix daemons. + + + + The project provides a QtService template class that can be used to + implement service applications, and a QtServiceController class + to control a service. + + On Windows systems the implementation uses the Service Control + Manager. + + On Unix systems services are implemented as daemons. + + + + \section1 Classes + \list + \i QtServiceController \i QtServiceBase \i QtService\endlist + + \section1 Examples + \list + \i \link qtservice-example-interactive.html An Interactive Service \endlink \i \link qtservice-example-server.html A simple HTTP Server \endlink \i \link qtservice-example-controller.html A simple Service Controller \endlink \endlist + + + + + + + \section1 Tested platforms + \list + \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005 + \i Qt 4.4, 4.5 / Linux / gcc + \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc + \endlist + + + + + */ \ No newline at end of file diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro new file mode 100644 index 00000000..722084b8 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += console qt +QT = core + +SOURCES = main.cpp + +include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc new file mode 100644 index 00000000..7de827bd --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +/*! \page qtservice-example-controller.html + \title A simple Service Controller + + It is a very simple implementation of universal command-line + controller. This controller can install and control any service + written using QtService component. It demonstrates how to use + QtServiceController class. On Windows, this is an alternative to + using the "Services" Administrative Tool or the built-in \c sc.exe + command-line tool to control services. + + A note about services on Windows Vista: Installing/uninstalling + and starting/stopping services requires security privileges. The + simplest way to achieve this is to set the "Run as Administrator" + property on the executable (right-click the executable file, + select Properties, and choose the Compatibilty tab in the + Properties dialog). This applies even if you are logged in as + Administrator. Also, the command-line shell should be started with + "Run as Administrator". Note that the service itself does not need + special privileges to run. Only if you want the service to be able + to install itself (the -i option) or similar, then the service + will need to be run as Administrator. Otherwise, the recommended + procedure is to use a controller such as this example and/or the + "Services" Administrative Tool to manage the service. + + A usability hint: in some circumstances, e.g. when running this + example on Windows Vista with the "Run as Administrator" property + set, output will be sent to a shell window which will close + immediately upon termination, not leaving the user enough time to + read the output. In such cases, append the -w(ait) argument, which + will make the controller wait for a keypress before terminating. + + Here is the complete source code: + + \quotefile controller/main.cpp +*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp new file mode 100644 index 00000000..a64edc15 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include +#include +#include +#include "qtservice.h" + +int processArgs(int argc, char **argv) +{ + if (argc > 2) { + QString arg1(argv[1]); + if (arg1 == QLatin1String("-i") || + arg1 == QLatin1String("-install")) { + if (argc > 2) { + QString account; + QString password; + QString path(argv[2]); + if (argc > 3) + account = argv[3]; + if (argc > 4) + password = argv[4]; + printf("The service %s installed.\n", + (QtServiceController::install(path, account, password) ? "was" : "was not")); + return 0; + } + } else { + QString serviceName(argv[1]); + QtServiceController controller(serviceName); + QString option(argv[2]); + if (option == QLatin1String("-u") || + option == QLatin1String("-uninstall")) { + printf("The service \"%s\" %s uninstalled.\n", + controller.serviceName().toLatin1().constData(), + (controller.uninstall() ? "was" : "was not")); + return 0; + } else if (option == QLatin1String("-s") || + option == QLatin1String("-start")) { + QStringList args; + for (int i = 3; i < argc; ++i) + args.append(QString::fromLocal8Bit(argv[i])); + printf("The service \"%s\" %s started.\n", + controller.serviceName().toLatin1().constData(), + (controller.start(args) ? "was" : "was not")); + return 0; + } else if (option == QLatin1String("-t") || + option == QLatin1String("-terminate")) { + printf("The service \"%s\" %s stopped.\n", + controller.serviceName().toLatin1().constData(), + (controller.stop() ? "was" : "was not")); + return 0; + } else if (option == QLatin1String("-p") || + option == QLatin1String("-pause")) { + printf("The service \"%s\" %s paused.\n", + controller.serviceName().toLatin1().constData(), + (controller.pause() ? "was" : "was not")); + return 0; + } else if (option == QLatin1String("-r") || + option == QLatin1String("-resume")) { + printf("The service \"%s\" %s resumed.\n", + controller.serviceName().toLatin1().constData(), + (controller.resume() ? "was" : "was not")); + return 0; + } else if (option == QLatin1String("-c") || + option == QLatin1String("-command")) { + if (argc > 3) { + QString codestr(argv[3]); + int code = codestr.toInt(); + printf("The command %s sent to the service \"%s\".\n", + (controller.sendCommand(code) ? "was" : "was not"), + controller.serviceName().toLatin1().constData()); + return 0; + } + } else if (option == QLatin1String("-v") || + option == QLatin1String("-version")) { + bool installed = controller.isInstalled(); + printf("The service\n" + "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData()); + printf("is %s", (installed ? "installed" : "not installed")); + printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running")); + if (installed) { + printf("path: %s\n", controller.serviceFilePath().toLatin1().data()); + printf("description: %s\n", controller.serviceDescription().toLatin1().data()); + printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual"); + } + return 0; + } + } + } + printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n" + "\t-i(nstall) PATH\t: Install the service\n" + "\t-v(ersion)\t: Print status of the service\n" + "\t-u(ninstall)\t: Uninstall the service\n" + "\t-s(tart)\t: Start the service\n" + "\t-t(erminate)\t: Stop the service\n" + "\t-p(ause)\t: Pause the service\n" + "\t-r(esume)\t: Resume the service\n" + "\t-c(ommand) CODE\t: Send a command to the service\n" + "\t-h(elp)\t\t: Print this help info\n" + "\t-w(ait)\t\t: Wait for keypress when done\n"); + return 0; +} + + +int main(int argc, char **argv) +{ +#if !defined(Q_WS_WIN) + // QtService stores service settings in SystemScope, which normally require root privileges. + // To allow testing this example as non-root, we change the directory of the SystemScope settings file. + QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); + qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); +#endif + + int result = processArgs(argc, argv); + + if (QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-w") || + QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-wait")) { + printf("\nPress Enter to continue..."); + QFile input; + input.open(stdin, QIODevice::ReadOnly); + input.readLine(); + printf("\n"); + } + + return result; +} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro new file mode 100644 index 00000000..109b9294 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs +SUBDIRS = interactive \ + server \ + controller diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro new file mode 100644 index 00000000..6dba6f80 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +CONFIG += console qt + +SOURCES = main.cpp + +include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc new file mode 100644 index 00000000..dcb57e9a --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +/*! \page qtservice-example-interactive.html + \title An Interactive Service + + This example implements a service with a simple user interface. + + Services are usually non-interactive console applications. User + interaction, if required, is usually implemented in a separate, + normal GUI application that communicates with the service through + an IPC channel. For simple communication, + QtServiceController::sendCommand() and QtService::processCommand() + may be used, possibly in combination with a shared settings + file. For more complex, interactive communication, a custom IPC + channel should be used, e.g. based on Qt's networking classes. + + However, although not recommended in the general case, in certain + circumstances a service may provide a GUI + itself. This is typically only possible if the service process is run as + the same user as the one that is logged in, so that it will have + access to the screen. Note however that on Windows Vista, service + GUIs are not allowed at all, since services run in a + diferent session than all user sessions, for security reasons. + + This example demonstrates how to subclass the QtService class, the use of + start(), stop(), pause(), resume(), and how to use + processCommand() to receive control commands while running. + + Here is the complete source code: + + \quotefile interactive/main.cpp +*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp new file mode 100644 index 00000000..4a99af57 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include "qtservice.h" + +class InteractiveService : public QtService +{ +public: + InteractiveService(int argc, char **argv); + ~InteractiveService(); + +protected: + + void start(); + void stop(); + void pause(); + void resume(); + void processCommand(int code); + +private: + QLabel *gui; +}; + +InteractiveService::InteractiveService(int argc, char **argv) + : QtService(argc, argv, "Qt Interactive Service"), gui(0) +{ + setServiceDescription("A Qt service with user interface."); + setServiceFlags(QtServiceBase::CanBeSuspended); +} + +InteractiveService::~InteractiveService() +{ +} + +void InteractiveService::start() +{ +#if defined(Q_OS_WIN) + if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) && + (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) { + logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error ); + return; + } +#endif + + qApp->setQuitOnLastWindowClosed(false); + + gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); + gui->move(QApplication::desktop()->availableGeometry().topLeft()); + gui->show(); +} + +void InteractiveService::stop() +{ + delete gui; +} + +void InteractiveService::pause() +{ + if (gui) + gui->hide(); +} + +void InteractiveService::resume() +{ + if (gui) + gui->show(); +} + +void InteractiveService::processCommand(int code) +{ + gui->setText("Command code " + QString::number(code)); + gui->adjustSize(); +} + +int main(int argc, char **argv) +{ +#if !defined(Q_WS_WIN) + // QtService stores service settings in SystemScope, which normally require root privileges. + // To allow testing this example as non-root, we change the directory of the SystemScope settings file. + QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); + qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); +#endif + InteractiveService service(argc, argv); + return service.exec(); +} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp new file mode 100644 index 00000000..43d2d501 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qtservice.h" + +// HttpDaemon is the the class that implements the simple HTTP server. +class HttpDaemon : public QTcpServer +{ + Q_OBJECT +public: + HttpDaemon(quint16 port, QObject* parent = 0) + : QTcpServer(parent), disabled(false) + { + listen(QHostAddress::Any, port); + } + + void incomingConnection(int socket) + { + if (disabled) + return; + + // When a new client connects, the server constructs a QTcpSocket and all + // communication with the client is done over this QTcpSocket. QTcpSocket + // works asynchronously, this means that all the communication is done + // in the two slots readClient() and discardClient(). + QTcpSocket* s = new QTcpSocket(this); + connect(s, SIGNAL(readyRead()), this, SLOT(readClient())); + connect(s, SIGNAL(disconnected()), this, SLOT(discardClient())); + s->setSocketDescriptor(socket); + + QtServiceBase::instance()->logMessage("New Connection"); + } + + void pause() + { + disabled = true; + } + + void resume() + { + disabled = false; + } + +private slots: + void readClient() + { + if (disabled) + return; + + // This slot is called when the client sent data to the server. The + // server looks if it was a get request and sends a very simple HTML + // document back. + QTcpSocket* socket = (QTcpSocket*)sender(); + if (socket->canReadLine()) { + QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*")); + if (tokens[0] == "GET") { + QTextStream os(socket); + os.setAutoDetectUnicode(true); + os << "HTTP/1.0 200 Ok\r\n" + "Content-Type: text/html; charset=\"utf-8\"\r\n" + "\r\n" + "

Nothing to see here

\n" + << QDateTime::currentDateTime().toString() << "\n"; + socket->close(); + + QtServiceBase::instance()->logMessage("Wrote to client"); + + if (socket->state() == QTcpSocket::UnconnectedState) { + delete socket; + QtServiceBase::instance()->logMessage("Connection closed"); + } + } + } + } + void discardClient() + { + QTcpSocket* socket = (QTcpSocket*)sender(); + socket->deleteLater(); + + QtServiceBase::instance()->logMessage("Connection closed"); + } + +private: + bool disabled; +}; + +class HttpService : public QtService +{ +public: + HttpService(int argc, char **argv) + : QtService(argc, argv, "Qt HTTP Daemon") + { + setServiceDescription("A dummy HTTP service implemented with Qt"); + setServiceFlags(QtServiceBase::CanBeSuspended); + } + +protected: + void start() + { + QCoreApplication *app = application(); + + quint16 port = (app->argc() > 1) ? + QString::fromLocal8Bit(app->argv()[1]).toUShort() : 8080; + daemon = new HttpDaemon(port, app); + + if (!daemon->isListening()) { + logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error); + app->quit(); + } + } + + void pause() + { + daemon->pause(); + } + + void resume() + { + daemon->resume(); + } + +private: + HttpDaemon *daemon; +}; + +#include "main.moc" + +int main(int argc, char **argv) +{ +#if !defined(Q_WS_WIN) + // QtService stores service settings in SystemScope, which normally require root privileges. + // To allow testing this example as non-root, we change the directory of the SystemScope settings file. + QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); + qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); +#endif + HttpService service(argc, argv); + return service.exec(); +} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro new file mode 100644 index 00000000..608b4d55 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro @@ -0,0 +1,8 @@ +TARGET = httpservice +TEMPLATE = app +CONFIG += console qt +QT = core network + +SOURCES = main.cpp + +include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc new file mode 100644 index 00000000..1728210f --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +/*! \page qtservice-example-server.html + \title A simple HTTP Server + + It is a very simple implementation of a HTTP daemon that listens on + chosen port (defaultly 8080) and sends back a simple HTML page back for every GET + request it gets. After sending the page, it closes the connection. + + \quotefromfile server/main.cpp + \skipto HttpDaemon + + \printuntil }; + The server implementation uses + the QtService::logMessage() function to send messages and status + reports to the system event log. The server also supports + a paused state in which case incoming requests are ignored. + + The \c HttpService class subclasses QtService to implement the + service functionality. + + \printto protected: + The constructor calls the QtService constructor instantiated with QCoreApplication + since our service will not use GUI. + The first two parameters of our constructor are passed to QtService. + The last parameter, "Qt HTTP Daemon", is the name of the service. + + \printto pause() + The implementation of \c start() first checks if the user passed a port number. + If yes that port is used by server to listen on. Otherwise default 8080 port is used. + Then creates an instance of the HTTP server using operator + new, passing the application object as the parent to ensure that the object + gets destroyed. + + \printto private: + \printuntil }; + The implementations of pause() and resume() forward the request to the + server object. + + \printuntil } + The main entry point function creates the service object and uses + the \c exec() function to execute the service. +*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro new file mode 100644 index 00000000..5aa57569 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro @@ -0,0 +1,5 @@ +TEMPLATE=subdirs +CONFIG += ordered +include(common.pri) +qtservice-uselib:SUBDIRS=buildlib +SUBDIRS+=examples diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase new file mode 100644 index 00000000..57e17a52 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase @@ -0,0 +1 @@ +#include "qtservice.h" diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController new file mode 100644 index 00000000..57e17a52 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController @@ -0,0 +1 @@ +#include "qtservice.h" diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp new file mode 100644 index 00000000..e0084f1f --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp @@ -0,0 +1,1117 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include "qtservice.h" +#include "qtservice_p.h" +#include +#include +#include +#include +#include + +#if defined(QTSERVICE_DEBUG) +#include +#include +#include +#include +#if defined(Q_OS_WIN32) +#include +#else +#include +#include +#endif + +static QFile* f = 0; + +static void qtServiceCloseDebugLog() +{ + if (!f) + return; + QString ps(QTime::currentTime().toString("HH:mm:ss.zzz ") + QLatin1String("--- DEBUG LOG CLOSED ---\n\n")); + f->write(ps.toAscii()); + f->flush(); + f->close(); + delete f; + f = 0; +} + +void qtServiceLogDebug(QtMsgType type, const char* msg) +{ + static QMutex mutex; + QMutexLocker locker(&mutex); + QString s(QTime::currentTime().toString("HH:mm:ss.zzz ")); + s += QString("[%1] ").arg( +#if defined(Q_OS_WIN32) + GetCurrentProcessId()); +#else + getpid()); +#endif + + if (!f) { +#if defined(Q_OS_WIN32) + f = new QFile("c:/service-debuglog.txt"); +#else + f = new QFile("/tmp/service-debuglog.txt"); +#endif + if (!f->open(QIODevice::WriteOnly | QIODevice::Append)) { + delete f; + f = 0; + return; + } + QString ps(QLatin1String("\n") + s + QLatin1String("--- DEBUG LOG OPENED ---\n")); + f->write(ps.toAscii()); + } + + switch (type) { + case QtWarningMsg: + s += QLatin1String("WARNING: "); + break; + case QtCriticalMsg: + s += QLatin1String("CRITICAL: "); + break; + case QtFatalMsg: + s+= QLatin1String("FATAL: "); + break; + case QtDebugMsg: + s += QLatin1String("DEBUG: "); + break; + default: + // Nothing + break; + } + + s += msg; + s += QLatin1String("\n"); + + f->write(s.toAscii()); + f->flush(); + + if (type == QtFatalMsg) { + qtServiceCloseDebugLog(); + exit(1); + } +} + +#endif + +/*! + \class QtServiceController + + \brief The QtServiceController class allows you to control + services from separate applications. + + QtServiceController provides a collection of functions that lets + you install and run a service controlling its execution, as well + as query its status. + + In order to run a service, the service must be installed in the + system's service database using the install() function. The system + will start the service depending on the specified StartupType; it + can either be started during system startup, or when a process + starts it manually. + + Once a service is installed, the service can be run and controlled + manually using the start(), stop(), pause(), resume() or + sendCommand() functions. You can at any time query for the + service's status using the isInstalled() and isRunning() + functions, or you can query its properties using the + serviceDescription(), serviceFilePath(), serviceName() and + startupType() functions. For example: + + \code + MyService service; \\ which inherits QtService + QString serviceFilePath; + + QtServiceController controller(service.serviceName()); + + if (controller.install(serviceFilePath)) + controller.start() + + if (controller.isRunning()) + QMessageBox::information(this, tr("Service Status"), + tr("The %1 service is started").arg(controller.serviceName())); + + ... + + controller.stop(); + controller.uninstall(); + } + \endcode + + An instance of the service controller can only control one single + service. To control several services within one application, you + must create en equal number of service controllers. + + The QtServiceController destructor neither stops nor uninstalls + the associated service. To stop a service the stop() function must + be called explicitly. To uninstall a service, you can use the + uninstall() function. + + \sa QtServiceBase, QtService +*/ + +/*! + \enum QtServiceController::StartupType + This enum describes when a service should be started. + + \value AutoStartup The service is started during system startup. + \value ManualStartup The service must be started manually by a process. + + \warning The \a StartupType enum is ignored under UNIX-like + systems. A service, or daemon, can only be started manually on such + systems with current implementation. + + \sa startupType() +*/ + + +/*! + Creates a controller object for the service with the given + \a name. +*/ +QtServiceController::QtServiceController(const QString &name) + : d_ptr(new QtServiceControllerPrivate()) +{ + Q_D(QtServiceController); + d->q_ptr = this; + d->serviceName = name; +} +/*! + Destroys the service controller. This neither stops nor uninstalls + the controlled service. + + To stop a service the stop() function must be called + explicitly. To uninstall a service, you can use the uninstall() + function. + + \sa stop(), QtServiceController::uninstall() +*/ +QtServiceController::~QtServiceController() +{ + delete d_ptr; +} +/*! + \fn bool QtServiceController::isInstalled() const + + Returns true if the service is installed; otherwise returns false. + + On Windows it uses the system's service control manager. + + On Unix it checks configuration written to QSettings::SystemScope + using "QtSoftware" as organization name. + + \sa install() +*/ + +/*! + \fn bool QtServiceController::isRunning() const + + Returns true if the service is running; otherwise returns false. A + service must be installed before it can be run using a controller. + + \sa start(), isInstalled() +*/ + +/*! + Returns the name of the controlled service. + + \sa QtServiceController(), serviceDescription() +*/ +QString QtServiceController::serviceName() const +{ + Q_D(const QtServiceController); + return d->serviceName; +} +/*! + \fn QString QtServiceController::serviceDescription() const + + Returns the description of the controlled service. + + \sa install(), serviceName() +*/ + +/*! + \fn QtServiceController::StartupType QtServiceController::startupType() const + + Returns the startup type of the controlled service. + + \sa install(), serviceName() +*/ + +/*! + \fn QString QtServiceController::serviceFilePath() const + + Returns the file path to the controlled service. + + \sa install(), serviceName() +*/ + +/*! + Installs the service with the given \a serviceFilePath + and returns true if the service is installed + successfully; otherwise returns false. + + On Windows service is installed in the system's service control manager with the given + \a account and \a password. + + On Unix service configuration is written to QSettings::SystemScope + using "QtSoftware" as organization name. \a account and \a password + arguments are ignored. + + \warning Due to the different implementations of how services (daemons) + are installed on various UNIX-like systems, this method doesn't + integrate the service into the system's startup scripts. + + \sa uninstall(), start() +*/ +bool QtServiceController::install(const QString &serviceFilePath, const QString &account, + const QString &password) +{ + QStringList arguments; + arguments << QLatin1String("-i"); + arguments << account; + arguments << password; + return (QProcess::execute(serviceFilePath, arguments) == 0); +} + + +/*! + \fn bool QtServiceController::uninstall() + + Uninstalls the service and returns true if successful; otherwise returns false. + + On Windows service is uninstalled using the system's service control manager. + + On Unix service configuration is cleared using QSettings::SystemScope + with "QtSoftware" as organization name. + + + \sa install() +*/ + +/*! + \fn bool QtServiceController::start(const QStringList &arguments) + + Starts the installed service passing the given \a arguments to the + service. A service must be installed before a controller can run it. + + Returns true if the service could be started; otherwise returns + false. + + \sa install(), stop() +*/ + +/*! + \overload + + Starts the installed service without passing any arguments to the service. +*/ +bool QtServiceController::start() +{ + return start(QStringList()); +} + +/*! + \fn bool QtServiceController::stop() + + Requests the running service to stop. The service will call the + QtServiceBase::stop() implementation unless the service's state + is QtServiceBase::CannotBeStopped. This function does nothing if + the service is not running. + + Returns true if a running service was successfully stopped; + otherwise false. + + \sa start(), QtServiceBase::stop(), QtServiceBase::ServiceFlags +*/ + +/*! + \fn bool QtServiceController::pause() + + Requests the running service to pause. If the service's state is + QtServiceBase::CanBeSuspended, the service will call the + QtServiceBase::pause() implementation. The function does nothing + if the service is not running. + + Returns true if a running service was successfully paused; + otherwise returns false. + + \sa resume(), QtServiceBase::pause(), QtServiceBase::ServiceFlags +*/ + +/*! + \fn bool QtServiceController::resume() + + Requests the running service to continue. If the service's state + is QtServiceBase::CanBeSuspended, the service will call the + QtServiceBase::resume() implementation. This function does nothing + if the service is not running. + + Returns true if a running service was successfully resumed; + otherwise returns false. + + \sa pause(), QtServiceBase::resume(), QtServiceBase::ServiceFlags +*/ + +/*! + \fn bool QtServiceController::sendCommand(int code) + + Sends the user command \a code to the service. The service will + call the QtServiceBase::processCommand() implementation. This + function does nothing if the service is not running. + + Returns true if the request was sent to a running service; + otherwise returns false. + + \sa QtServiceBase::processCommand() +*/ + +class QtServiceStarter : public QObject +{ + Q_OBJECT +public: + QtServiceStarter(QtServiceBasePrivate *service) + : QObject(), d_ptr(service) {} +public slots: + void slotStart() + { + d_ptr->startService(); + } +private: + QtServiceBasePrivate *d_ptr; +}; +#include "qtservice.moc" + +QtServiceBase *QtServiceBasePrivate::instance = 0; + +QtServiceBasePrivate::QtServiceBasePrivate(const QString &name) + : startupType(QtServiceController::ManualStartup), serviceFlags(0), controller(name) +{ + +} + +QtServiceBasePrivate::~QtServiceBasePrivate() +{ + +} + +void QtServiceBasePrivate::startService() +{ + q_ptr->start(); +} + +int QtServiceBasePrivate::run(bool asService, const QStringList &argList) +{ + int argc = argList.size(); + QVector argv(argc); + QList argvData; + for (int i = 0; i < argc; ++i) + argvData.append(argList.at(i).toLocal8Bit()); + for (int i = 0; i < argc; ++i) + argv[i] = argvData[i].data(); + + if (asService && !sysInit()) + return -1; + + q_ptr->createApplication(argc, argv.data()); + QCoreApplication *app = QCoreApplication::instance(); + if (!app) + return -1; + + if (asService) + sysSetPath(); + + QtServiceStarter starter(this); + QTimer::singleShot(0, &starter, SLOT(slotStart())); + int res = q_ptr->executeApplication(); + delete app; + + if (asService) + sysCleanup(); + return res; +} + + +/*! + \class QtServiceBase + + \brief The QtServiceBase class provides an API for implementing + Windows services and Unix daemons. + + A Windows service or Unix daemon (a "service"), is a program that + runs "in the background" independently of whether a user is logged + in or not. A service is often set up to start when the machine + boots up, and will typically run continuously as long as the + machine is on. + + Services are usually non-interactive console applications. User + interaction, if required, is usually implemented in a separate, + normal GUI application that communicates with the service through + an IPC channel. For simple communication, + QtServiceController::sendCommand() and QtService::processCommand() + may be used, possibly in combination with a shared settings + file. For more complex, interactive communication, a custom IPC + channel should be used, e.g. based on Qt's networking classes. (In + certain circumstances, a service may provide a GUI itself, + ref. the "interactive" example documentation). + + Typically, you will create a service by subclassing the QtService + template class which inherits QtServiceBase and allows you to + create a service for a particular application type. + + The Windows implementation uses the NT Service Control Manager, + and the application can be controlled through the system + administration tools. Services are usually launched using the + system account, which requires that all DLLs that the service + executable depends on (i.e. Qt), are located in the same directory + as the service, or in a system path. + + On Unix a service is implemented as a daemon. + + You can retrieve the service's description, state, and startup + type using the serviceDescription(), serviceFlags() and + startupType() functions respectively. The service's state is + decribed by the ServiceFlag enum. The mentioned properites can + also be set using the corresponding set functions. In addition you + can retrieve the service's name using the serviceName() function. + + Several of QtServiceBase's protected functions are called on + requests from the QtServiceController class: + + \list + \o start() + \o pause() + \o processCommand() + \o resume() + \o stop() + \endlist + + You can control any given service using an instance of the + QtServiceController class which also allows you to control + services from separate applications. The mentioned functions are + all virtual and won't do anything unless they are + reimplemented. You can reimplement these functions to pause and + resume the service's execution, as well as process user commands + and perform additional clean-ups before shutting down. + + QtServiceBase also provides the static instance() function which + returns a pointer to an application's QtServiceBase instance. In + addition, a service can report events to the system's event log + using the logMessage() function. The MessageType enum describes + the different types of messages a service reports. + + The implementation of a service application's main function + typically creates an service object derived by subclassing the + QtService template class. Then the main function will call this + service's exec() function, and return the result of that call. For + example: + + \code + int main(int argc, char **argv) + { + MyService service(argc, argv); + return service.exec(); + } + \endcode + + When the exec() function is called, it will parse the service + specific arguments passed in \c argv, perform the required + actions, and return. + + \target serviceSpecificArguments + + The following arguments are recognized as service specific: + + \table + \header \i Short \i Long \i Explanation + \row \i -i \i -install \i Install the service. + \row \i -u \i -uninstall \i Uninstall the service. + \row \i -e \i -exec + \i Execute the service as a standalone application (useful for debug purposes). + This is a blocking call, the service will be executed like a normal application. + In this mode you will not be able to communicate with the service from the contoller. + \row \i -t \i -terminate \i Stop the service. + \row \i -p \i -pause \i Pause the service. + \row \i -r \i -resume \i Resume a paused service. + \row \i -c \e{cmd} \i -command \e{cmd} + \i Send the user defined command code \e{cmd} to the service application. + \row \i -v \i -version \i Display version and status information. + \endtable + + If \e none of the arguments is recognized as service specific, + exec() will first call the createApplication() function, then + executeApplication() and finally the start() function. In the end, + exec() returns while the service continues in its own process + waiting for commands from the service controller. + + \sa QtService, QtServiceController +*/ + +/*! + \enum QtServiceBase::MessageType + + This enum describes the different types of messages a service + reports to the system log. + + \value Success An operation has succeeded, e.g. the service + is started. + \value Error An operation failed, e.g. the service failed to start. + \value Warning An operation caused a warning that might require user + interaction. + \value Information Any type of usually non-critical information. +*/ + +/*! + \enum QtServiceBase::ServiceFlag + + This enum describes the different states of a service. + + \value Default The service can be stopped, but not suspended. + \value CanBeSuspended The service can be suspended. + \value CannotBeStopped The service cannot be stopped. +*/ + +/*! + Creates a service instance called \a name. The \a argc and \a argv + parameters are parsed after the exec() function has been + called. Then they are passed to the application's constructor. + The application type is determined by the QtService subclass. + + The service is neither installed nor started. The name must not + contain any backslashes or be longer than 255 characters. In + addition, the name must be unique in the system's service + database. + + \sa exec(), start(), QtServiceController::install() +*/ +QtServiceBase::QtServiceBase(int argc, char **argv, const QString &name) +{ +#if defined(QTSERVICE_DEBUG) + qInstallMsgHandler(qtServiceLogDebug); + qAddPostRoutine(qtServiceCloseDebugLog); +#endif + + Q_ASSERT(!QtServiceBasePrivate::instance); + QtServiceBasePrivate::instance = this; + + QString nm(name); + if (nm.length() > 255) { + qWarning("QtService: 'name' is longer than 255 characters."); + nm.truncate(255); + } + if (nm.contains('\\')) { + qWarning("QtService: 'name' contains backslashes '\\'."); + nm.replace((QChar)'\\', (QChar)'\0'); + } + + d_ptr = new QtServiceBasePrivate(nm); + d_ptr->q_ptr = this; + + d_ptr->serviceFlags = 0; + d_ptr->sysd = 0; + for (int i = 0; i < argc; ++i) + d_ptr->args.append(QString::fromLocal8Bit(argv[i])); +} + +/*! + Destroys the service object. This neither stops nor uninstalls the + service. + + To stop a service the stop() function must be called + explicitly. To uninstall a service, you can use the + QtServiceController::uninstall() function. + + \sa stop(), QtServiceController::uninstall() +*/ +QtServiceBase::~QtServiceBase() +{ + delete d_ptr; + QtServiceBasePrivate::instance = 0; +} + +/*! + Returns the name of the service. + + \sa QtServiceBase(), serviceDescription() +*/ +QString QtServiceBase::serviceName() const +{ + return d_ptr->controller.serviceName(); +} + +/*! + Returns the description of the service. + + \sa setServiceDescription(), serviceName() +*/ +QString QtServiceBase::serviceDescription() const +{ + return d_ptr->serviceDescription; +} + +/*! + Sets the description of the service to the given \a description. + + \sa serviceDescription() +*/ +void QtServiceBase::setServiceDescription(const QString &description) +{ + d_ptr->serviceDescription = description; +} + +/*! + Returns the service's startup type. + + \sa QtServiceController::StartupType, setStartupType() +*/ +QtServiceController::StartupType QtServiceBase::startupType() const +{ + return d_ptr->startupType; +} + +/*! + Sets the service's startup type to the given \a type. + + \sa QtServiceController::StartupType, startupType() +*/ +void QtServiceBase::setStartupType(QtServiceController::StartupType type) +{ + d_ptr->startupType = type; +} + +/*! + Returns the service's state which is decribed using the + ServiceFlag enum. + + \sa ServiceFlags, setServiceFlags() +*/ +QtServiceBase::ServiceFlags QtServiceBase::serviceFlags() const +{ + return d_ptr->serviceFlags; +} + +/*! + \fn void QtServiceBase::setServiceFlags(ServiceFlags flags) + + Sets the service's state to the state described by the given \a + flags. + + \sa ServiceFlags, serviceFlags() +*/ + +/*! + Executes the service. + + When the exec() function is called, it will parse the \l + {serviceSpecificArguments} {service specific arguments} passed in + \c argv, perform the required actions, and exit. + + If none of the arguments is recognized as service specific, exec() + will first call the createApplication() function, then executeApplication() and + finally the start() function. In the end, exec() + returns while the service continues in its own process waiting for + commands from the service controller. + + \sa QtServiceController +*/ +int QtServiceBase::exec() +{ + if (d_ptr->args.size() > 1) { + QString a = d_ptr->args.at(1); + if (a == QLatin1String("-i") || a == QLatin1String("-install")) { + if (!d_ptr->controller.isInstalled()) { + QString account; + QString password; + if (d_ptr->args.size() > 2) + account = d_ptr->args.at(2); + if (d_ptr->args.size() > 3) + password = d_ptr->args.at(3); + if (!d_ptr->install(account, password)) { + fprintf(stderr, "The service %s could not be installed\n", serviceName().toLatin1().constData()); + return -1; + } else { + printf("The service %s has been installed under: %s\n", + serviceName().toLatin1().constData(), d_ptr->filePath().toLatin1().constData()); + } + } else { + fprintf(stderr, "The service %s is already installed\n", serviceName().toLatin1().constData()); + } + return 0; + } else if (a == QLatin1String("-u") || a == QLatin1String("-uninstall")) { + if (d_ptr->controller.isInstalled()) { + if (!d_ptr->controller.uninstall()) { + fprintf(stderr, "The service %s could not be uninstalled\n", serviceName().toLatin1().constData()); + return -1; + } else { + printf("The service %s has been uninstalled.\n", + serviceName().toLatin1().constData()); + } + } else { + fprintf(stderr, "The service %s is not installed\n", serviceName().toLatin1().constData()); + } + return 0; + } else if (a == QLatin1String("-v") || a == QLatin1String("-version")) { + printf("The service\n" + "\t%s\n\t%s\n\n", serviceName().toLatin1().constData(), d_ptr->args.at(0).toLatin1().constData()); + printf("is %s", (d_ptr->controller.isInstalled() ? "installed" : "not installed")); + printf(" and %s\n\n", (d_ptr->controller.isRunning() ? "running" : "not running")); + return 0; + } else if (a == QLatin1String("-e") || a == QLatin1String("-exec")) { + d_ptr->args.removeAt(1); + int ec = d_ptr->run(false, d_ptr->args); + if (ec == -1) + qErrnoWarning("The service could not be executed."); + return ec; + } else if (a == QLatin1String("-t") || a == QLatin1String("-terminate")) { + if (!d_ptr->controller.stop()) + qErrnoWarning("The service could not be stopped."); + return 0; + } else if (a == QLatin1String("-p") || a == QLatin1String("-pause")) { + d_ptr->controller.pause(); + return 0; + } else if (a == QLatin1String("-r") || a == QLatin1String("-resume")) { + d_ptr->controller.resume(); + return 0; + } else if (a == QLatin1String("-c") || a == QLatin1String("-command")) { + int code = 0; + if (d_ptr->args.size() > 2) + code = d_ptr->args.at(2).toInt(); + d_ptr->controller.sendCommand(code); + return 0; + } else if (a == QLatin1String("-h") || a == QLatin1String("-help")) { + printf("\n%s -[i|u|e|s|v|h]\n" + "\t-i(nstall) [account] [password]\t: Install the service, optionally using given account and password\n" + "\t-u(ninstall)\t: Uninstall the service.\n" + "\t-e(xec)\t\t: Run as a regular application. Useful for debugging.\n" + "\t-t(erminate)\t: Stop the service.\n" + "\t-c(ommand) num\t: Send command code num to the service.\n" + "\t-v(ersion)\t: Print version and status information.\n" + "\t-h(elp) \t: Show this help\n" + "\tNo arguments\t: Start the service.\n", + d_ptr->args.at(0).toLatin1().constData()); + return 0; + } + } +#if defined(Q_OS_UNIX) + if (::getenv("QTSERVICE_RUN")) { + // Means we're the detached, real service process. + int ec = d_ptr->run(true, d_ptr->args); + if (ec == -1) + qErrnoWarning("The service failed to run."); + return ec; + } +#endif + if (!d_ptr->start()) { + fprintf(stderr, "The service %s could not start\n", serviceName().toLatin1().constData()); + return -4; + } + return 0; +} + +/*! + \fn void QtServiceBase::logMessage(const QString &message, MessageType type, + int id, uint category, const QByteArray &data) + + Reports a message of the given \a type with the given \a message + to the local system event log. The message identifier \a id and + the message \a category are user defined values. The \a data + parameter can contain arbitrary binary data. + + Message strings for \a id and \a category must be provided by a + message file, which must be registered in the system registry. + Refer to the MSDN for more information about how to do this on + Windows. + + \sa MessageType +*/ + +/*! + Returns a pointer to the current application's QtServiceBase + instance. +*/ +QtServiceBase *QtServiceBase::instance() +{ + return QtServiceBasePrivate::instance; +} + +/*! + \fn void QtServiceBase::start() + + This function must be implemented in QtServiceBase subclasses in + order to perform the service's work. Usually you create some main + object on the heap which is the heart of your service. + + The function is only called when no service specific arguments + were passed to the service constructor, and is called by exec() + after it has called the executeApplication() function. + + Note that you \e don't need to create an application object or + call its exec() function explicitly. + + \sa exec(), stop(), QtServiceController::start() +*/ + +/*! + Reimplement this function to perform additional cleanups before + shutting down (for example deleting a main object if it was + created in the start() function). + + This function is called in reply to controller requests. The + default implementation does nothing. + + \sa start(), QtServiceController::stop() +*/ +void QtServiceBase::stop() +{ +} + +/*! + Reimplement this function to pause the service's execution (for + example to stop a polling timer, or to ignore socket notifiers). + + This function is called in reply to controller requests. The + default implementation does nothing. + + \sa resume(), QtServiceController::pause() +*/ +void QtServiceBase::pause() +{ +} + +/*! + Reimplement this function to continue the service after a call to + pause(). + + This function is called in reply to controller requests. The + default implementation does nothing. + + \sa pause(), QtServiceController::resume() +*/ +void QtServiceBase::resume() +{ +} + +/*! + Reimplement this function to process the user command \a code. + + + This function is called in reply to controller requests. The + default implementation does nothing. + + \sa QtServiceController::sendCommand() +*/ +void QtServiceBase::processCommand(int /*code*/) +{ +} + +/*! + \fn void QtServiceBase::createApplication(int &argc, char **argv) + + Creates the application object using the \a argc and \a argv + parameters. + + This function is only called when no \l + {serviceSpecificArguments}{service specific arguments} were + passed to the service constructor, and is called by exec() before + it calls the executeApplication() and start() functions. + + The createApplication() function is implemented in QtService, but + you might want to reimplement it, for example, if the chosen + application type's constructor needs additional arguments. + + \sa exec(), QtService +*/ + +/*! + \fn int QtServiceBase::executeApplication() + + Executes the application previously created with the + createApplication() function. + + This function is only called when no \l + {serviceSpecificArguments}{service specific arguments} were + passed to the service constructor, and is called by exec() after + it has called the createApplication() function and before start() function. + + This function is implemented in QtService. + + \sa exec(), createApplication() +*/ + +/*! + \class QtService + + \brief The QtService is a convenient template class that allows + you to create a service for a particular application type. + + A Windows service or Unix daemon (a "service"), is a program that + runs "in the background" independently of whether a user is logged + in or not. A service is often set up to start when the machine + boots up, and will typically run continuously as long as the + machine is on. + + Services are usually non-interactive console applications. User + interaction, if required, is usually implemented in a separate, + normal GUI application that communicates with the service through + an IPC channel. For simple communication, + QtServiceController::sendCommand() and QtService::processCommand() + may be used, possibly in combination with a shared settings file. For + more complex, interactive communication, a custom IPC channel + should be used, e.g. based on Qt's networking classes. (In certain + circumstances, a service may provide a GUI itself, ref. the + "interactive" example documentation). + + \bold{Note:} On Unix systems, this class relies on facilities + provided by the QtNetwork module, provided as part of the + \l{Qt Open Source Edition} and certain \l{Qt Commercial Editions}. + + The QtService class functionality is inherited from QtServiceBase, + but in addition the QtService class binds an instance of + QtServiceBase with an application type. + + Typically, you will create a service by subclassing the QtService + template class. For example: + + \code + class MyService : public QtService + { + public: + MyService(int argc, char **argv); + ~MyService(); + + protected: + void start(); + void stop(); + void pause(); + void resume(); + void processCommand(int code); + }; + \endcode + + The application type can be QCoreApplication for services without + GUI, QApplication for services with GUI or you can use your own + custom application type. + + You must reimplement the QtServiceBase::start() function to + perform the service's work. Usually you create some main object on + the heap which is the heart of your service. + + In addition, you might want to reimplement the + QtServiceBase::pause(), QtServiceBase::processCommand(), + QtServiceBase::resume() and QtServiceBase::stop() to intervene the + service's process on controller requests. You can control any + given service using an instance of the QtServiceController class + which also allows you to control services from separate + applications. The mentioned functions are all virtual and won't do + anything unless they are reimplemented. + + Your custom service is typically instantiated in the application's + main function. Then the main function will call your service's + exec() function, and return the result of that call. For example: + + \code + int main(int argc, char **argv) + { + MyService service(argc, argv); + return service.exec(); + } + \endcode + + When the exec() function is called, it will parse the \l + {serviceSpecificArguments} {service specific arguments} passed in + \c argv, perform the required actions, and exit. + + If none of the arguments is recognized as service specific, exec() + will first call the createApplication() function, then executeApplication() and + finally the start() function. In the end, exec() + returns while the service continues in its own process waiting for + commands from the service controller. + + \sa QtServiceBase, QtServiceController +*/ + +/*! + \fn QtService::QtService(int argc, char **argv, const QString &name) + + Constructs a QtService object called \a name. The \a argc and \a + argv parameters are parsed after the exec() function has been + called. Then they are passed to the application's constructor. + + There can only be one QtService object in a process. + + \sa QtServiceBase() +*/ + +/*! + \fn QtService::~QtService() + + Destroys the service object. +*/ + +/*! + \fn Application *QtService::application() const + + Returns a pointer to the application object. +*/ + +/*! + \fn void QtService::createApplication(int &argc, char **argv) + + Creates application object of type Application passing \a argc and + \a argv to its constructor. + + \reimp + +*/ + +/*! + \fn int QtService::executeApplication() + + \reimp +*/ + + + diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h new file mode 100644 index 00000000..a0230e28 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef QTSERVICE_H +#define QTSERVICE_H + +#include + +#if defined(Q_WS_WIN) +# if !defined(QT_QTSERVICE_EXPORT) && !defined(QT_QTSERVICE_IMPORT) +# define QT_QTSERVICE_EXPORT +# elif defined(QT_QTSERVICE_IMPORT) +# if defined(QT_QTSERVICE_EXPORT) +# undef QT_QTSERVICE_EXPORT +# endif +# define QT_QTSERVICE_EXPORT __declspec(dllimport) +# elif defined(QT_QTSERVICE_EXPORT) +# undef QT_QTSERVICE_EXPORT +# define QT_QTSERVICE_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTSERVICE_EXPORT +#endif + +class QStringList; +class QtServiceControllerPrivate; + +class QT_QTSERVICE_EXPORT QtServiceController +{ + Q_DECLARE_PRIVATE(QtServiceController) +public: + enum StartupType + { + AutoStartup = 0, ManualStartup + }; + + QtServiceController(const QString &name); + virtual ~QtServiceController(); + + bool isInstalled() const; + bool isRunning() const; + + QString serviceName() const; + QString serviceDescription() const; + StartupType startupType() const; + QString serviceFilePath() const; + + static bool install(const QString &serviceFilePath, const QString &account = QString(), + const QString &password = QString()); + bool uninstall(); + + bool start(const QStringList &arguments); + bool start(); + bool stop(); + bool pause(); + bool resume(); + bool sendCommand(int code); + +private: + QtServiceControllerPrivate *d_ptr; +}; + +class QtServiceBasePrivate; + +class QT_QTSERVICE_EXPORT QtServiceBase +{ + Q_DECLARE_PRIVATE(QtServiceBase) +public: + + enum MessageType + { + Success = 0, Error, Warning, Information + }; + + enum ServiceFlag + { + Default = 0x00, + CanBeSuspended = 0x01, + CannotBeStopped = 0x02 + }; + + Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag) + + QtServiceBase(int argc, char **argv, const QString &name); + virtual ~QtServiceBase(); + + QString serviceName() const; + + QString serviceDescription() const; + void setServiceDescription(const QString &description); + + QtServiceController::StartupType startupType() const; + void setStartupType(QtServiceController::StartupType startupType); + + ServiceFlags serviceFlags() const; + void setServiceFlags(ServiceFlags flags); + + int exec(); + + void logMessage(const QString &message, MessageType type = Success, + int id = 0, uint category = 0, const QByteArray &data = QByteArray()); + + static QtServiceBase *instance(); + +protected: + + virtual void start() = 0; + virtual void stop(); + virtual void pause(); + virtual void resume(); + virtual void processCommand(int code); + + virtual void createApplication(int &argc, char **argv) = 0; + + virtual int executeApplication() = 0; + +private: + + friend class QtServiceSysPrivate; + QtServiceBasePrivate *d_ptr; +}; + +template +class QtService : public QtServiceBase +{ +public: + QtService(int argc, char **argv, const QString &name) + : QtServiceBase(argc, argv, name), app(0) + { } + ~QtService() + { + } + +protected: + Application *application() const + { return app; } + + virtual void createApplication(int &argc, char **argv) + { + app = new Application(argc, argv); + QCoreApplication *a = app; + Q_UNUSED(a); + } + + virtual int executeApplication() + { return Application::exec(); } + +private: + Application *app; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QtServiceBase::ServiceFlags) + +#endif // QTSERVICE_H diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri new file mode 100644 index 00000000..658a3288 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri @@ -0,0 +1,21 @@ +include(../common.pri) +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD +!win32:QT += network +win32:LIBS += -luser32 + +qtservice-uselib:!qtservice-buildlib { + LIBS += -L$$QTSERVICE_LIBDIR -l$$QTSERVICE_LIBNAME +} else { + HEADERS += $$PWD/qtservice.h \ + $$PWD/qtservice_p.h + SOURCES += $$PWD/qtservice.cpp + win32:SOURCES += $$PWD/qtservice_win.cpp + unix:HEADERS += $$PWD/qtunixsocket.h $$PWD/qtunixserversocket.h + unix:SOURCES += $$PWD/qtservice_unix.cpp $$PWD/qtunixsocket.cpp $$PWD/qtunixserversocket.cpp +} + +win32 { + contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSERVICE_EXPORT + else:qtservice-uselib:DEFINES += QT_QTSERVICE_IMPORT +} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h new file mode 100644 index 00000000..fc5e6b82 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef QTSERVICE_P_H +#define QTSERVICE_P_H + +#include +#include "qtservice.h" + +class QtServiceControllerPrivate +{ + Q_DECLARE_PUBLIC(QtServiceController) +public: + QString serviceName; + QtServiceController *q_ptr; +}; + +class QtServiceBasePrivate +{ + Q_DECLARE_PUBLIC(QtServiceBase) +public: + + QtServiceBasePrivate(const QString &name); + ~QtServiceBasePrivate(); + + QtServiceBase *q_ptr; + + QString serviceDescription; + QtServiceController::StartupType startupType; + QtServiceBase::ServiceFlags serviceFlags; + QStringList args; + + static class QtServiceBase *instance; + + QtServiceController controller; + + void startService(); + int run(bool asService, const QStringList &argList); + bool install(const QString &account, const QString &password); + + bool start(); + + QString filePath() const; + bool sysInit(); + void sysSetPath(); + void sysCleanup(); + class QtServiceSysPrivate *sysd; +}; + +#endif diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp new file mode 100644 index 00000000..7e4ec700 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp @@ -0,0 +1,480 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include "qtservice.h" +#include "qtservice_p.h" +#include "qtunixsocket.h" +#include "qtunixserversocket.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static QString encodeName(const QString &name, bool allowUpper = false) +{ + QString n = name.toLower(); + QString legal = QLatin1String("abcdefghijklmnopqrstuvwxyz1234567890"); + if (allowUpper) + legal += QLatin1String("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + int pos = 0; + while (pos < n.size()) { + if (legal.indexOf(n[pos]) == -1) + n.remove(pos, 1); + else + ++pos; + } + return n; +} + +static QString login() +{ + QString l; + uid_t uid = getuid(); + passwd *pw = getpwuid(uid); + if (pw) + l = QString(pw->pw_name); + return l; +} + +static QString socketPath(const QString &serviceName) +{ + QString sn = encodeName(serviceName); + return QString(QLatin1String("/var/tmp/") + sn + QLatin1String(".") + login()); +} + +static bool sendCmd(const QString &serviceName, const QString &cmd) +{ + bool retValue = false; + QtUnixSocket sock; + if (sock.connectTo(socketPath(serviceName))) { + sock.write(QString(cmd+"\r\n").toLatin1().constData()); + sock.flush(); + sock.waitForReadyRead(-1); + QString reply = sock.readAll(); + if (reply == QLatin1String("true")) + retValue = true; + sock.close(); + } + return retValue; +} + +static QString absPath(const QString &path) +{ + QString ret; + if (path[0] != QChar('/')) { // Not an absolute path + int slashpos; + if ((slashpos = path.lastIndexOf('/')) != -1) { // Relative path + QDir dir = QDir::current(); + dir.cd(path.left(slashpos)); + ret = dir.absolutePath(); + } else { // Need to search $PATH + char *envPath = ::getenv("PATH"); + if (envPath) { + QStringList envPaths = QString::fromLocal8Bit(envPath).split(':'); + for (int i = 0; i < envPaths.size(); ++i) { + if (QFile::exists(envPaths.at(i) + QLatin1String("/") + QString(path))) { + QDir dir(envPaths.at(i)); + ret = dir.absolutePath(); + break; + } + } + } + } + } else { + QFileInfo fi(path); + ret = fi.absolutePath(); + } + return ret; +} + +QString QtServiceBasePrivate::filePath() const +{ + QString ret; + if (args.isEmpty()) + return ret; + QFileInfo fi(args[0]); + QDir dir(absPath(args[0])); + return dir.absoluteFilePath(fi.fileName()); +} + + +QString QtServiceController::serviceDescription() const +{ + QSettings settings(QSettings::SystemScope, "QtSoftware"); + settings.beginGroup("services"); + settings.beginGroup(serviceName()); + + QString desc = settings.value("description").toString(); + + settings.endGroup(); + settings.endGroup(); + + return desc; +} + +QtServiceController::StartupType QtServiceController::startupType() const +{ + QSettings settings(QSettings::SystemScope, "QtSoftware"); + settings.beginGroup("services"); + settings.beginGroup(serviceName()); + + StartupType startupType = (StartupType)settings.value("startupType").toInt(); + + settings.endGroup(); + settings.endGroup(); + + return startupType; +} + +QString QtServiceController::serviceFilePath() const +{ + QSettings settings(QSettings::SystemScope, "QtSoftware"); + settings.beginGroup("services"); + settings.beginGroup(serviceName()); + + QString path = settings.value("path").toString(); + + settings.endGroup(); + settings.endGroup(); + + return path; +} + +bool QtServiceController::uninstall() +{ + QSettings settings(QSettings::SystemScope, "QtSoftware"); + settings.beginGroup("services"); + + settings.remove(serviceName()); + + settings.endGroup(); + settings.sync(); + + QSettings::Status ret = settings.status(); + if (ret == QSettings::AccessError) { + fprintf(stderr, "Cannot uninstall \"%s\". Cannot write to: %s. Check permissions.\n", + serviceName().toLatin1().constData(), + settings.fileName().toLatin1().constData()); + } + return (ret == QSettings::NoError); +} + + +bool QtServiceController::start(const QStringList &arguments) +{ + if (!isInstalled()) + return false; + if (isRunning()) + return false; + return QProcess::startDetached(serviceFilePath(), arguments); +} + +bool QtServiceController::stop() +{ + return sendCmd(serviceName(), QLatin1String("terminate")); +} + +bool QtServiceController::pause() +{ + return sendCmd(serviceName(), QLatin1String("pause")); +} + +bool QtServiceController::resume() +{ + return sendCmd(serviceName(), QLatin1String("resume")); +} + +bool QtServiceController::sendCommand(int code) +{ + return sendCmd(serviceName(), QString(QLatin1String("num:") + QString::number(code))); +} + +bool QtServiceController::isInstalled() const +{ + QSettings settings(QSettings::SystemScope, "QtSoftware"); + settings.beginGroup("services"); + + QStringList list = settings.childGroups(); + + settings.endGroup(); + + QStringListIterator it(list); + while (it.hasNext()) { + if (it.next() == serviceName()) + return true; + } + + return false; +} + +bool QtServiceController::isRunning() const +{ + QtUnixSocket sock; + if (sock.connectTo(socketPath(serviceName()))) + return true; + return false; +} + + + + +/////////////////////////////////// + +class QtServiceSysPrivate : public QtUnixServerSocket +{ + Q_OBJECT +public: + QtServiceSysPrivate(); + ~QtServiceSysPrivate(); + + char *ident; + + QtServiceBase::ServiceFlags serviceFlags; + +protected: + void incomingConnection(int socketDescriptor); + +private slots: + void slotReady(); + void slotClosed(); + +private: + QString getCommand(const QTcpSocket *socket); + QMap cache; +}; + +QtServiceSysPrivate::QtServiceSysPrivate() + : QtUnixServerSocket(), ident(0), serviceFlags(0) +{ +} + +QtServiceSysPrivate::~QtServiceSysPrivate() +{ + if (ident) + delete[] ident; +} + +void QtServiceSysPrivate::incomingConnection(int socketDescriptor) +{ + QTcpSocket *s = new QTcpSocket(this); + s->setSocketDescriptor(socketDescriptor); + connect(s, SIGNAL(readyRead()), this, SLOT(slotReady())); + connect(s, SIGNAL(disconnected()), this, SLOT(slotClosed())); +} + +void QtServiceSysPrivate::slotReady() +{ + QTcpSocket *s = (QTcpSocket *)sender(); + cache[s] += QString(s->readAll()); + QString cmd = getCommand(s); + while (!cmd.isEmpty()) { + bool retValue = false; + if (cmd == QLatin1String("terminate")) { + if (!(serviceFlags & QtServiceBase::CannotBeStopped)) { + QtServiceBase::instance()->stop(); + QCoreApplication::instance()->quit(); + retValue = true; + } + } else if (cmd == QLatin1String("pause")) { + if (serviceFlags & QtServiceBase::CanBeSuspended) { + QtServiceBase::instance()->pause(); + retValue = true; + } + } else if (cmd == QLatin1String("resume")) { + if (serviceFlags & QtServiceBase::CanBeSuspended) { + QtServiceBase::instance()->resume(); + retValue = true; + } + } else if (cmd == QLatin1String("alive")) { + retValue = true; + } else if (cmd.length() > 4 && cmd.left(4) == QLatin1String("num:")) { + cmd = cmd.mid(4); + QtServiceBase::instance()->processCommand(cmd.toInt()); + retValue = true; + } + QString retString; + if (retValue) + retString = QLatin1String("true"); + else + retString = QLatin1String("false"); + s->write(retString.toLatin1().constData()); + s->flush(); + cmd = getCommand(s); + } +} + +void QtServiceSysPrivate::slotClosed() +{ + QTcpSocket *s = (QTcpSocket *)sender(); + s->deleteLater(); +} + +QString QtServiceSysPrivate::getCommand(const QTcpSocket *socket) +{ + int pos = cache[socket].indexOf("\r\n"); + if (pos >= 0) { + QString ret = cache[socket].left(pos); + cache[socket].remove(0, pos+2); + return ret; + } + return ""; +} + +#include "qtservice_unix.moc" + +bool QtServiceBasePrivate::sysInit() +{ + sysd = new QtServiceSysPrivate; + sysd->serviceFlags = serviceFlags; + // Restrict permissions on files that are created by the service + ::umask(027); + + return true; +} + +void QtServiceBasePrivate::sysSetPath() +{ + if (sysd) + sysd->setPath(socketPath(controller.serviceName())); +} + +void QtServiceBasePrivate::sysCleanup() +{ + if (sysd) { + sysd->close(); + delete sysd; + sysd = 0; + } +} + +bool QtServiceBasePrivate::start() +{ + if (sendCmd(controller.serviceName(), "alive")) { + // Already running + return false; + } + // Could just call controller.start() here, but that would fail if + // we're not installed. We do not want to strictly require installation. + ::setenv("QTSERVICE_RUN", "1", 1); // Tell the detached process it's it + return QProcess::startDetached(filePath(), args.mid(1), "/"); +} + +bool QtServiceBasePrivate::install(const QString &account, const QString &password) +{ + Q_UNUSED(account) + Q_UNUSED(password) + QSettings settings(QSettings::SystemScope, "QtSoftware"); + + settings.beginGroup("services"); + settings.beginGroup(controller.serviceName()); + + settings.setValue("path", filePath()); + settings.setValue("description", serviceDescription); + settings.setValue("automaticStartup", startupType); + + settings.endGroup(); + settings.endGroup(); + settings.sync(); + + QSettings::Status ret = settings.status(); + if (ret == QSettings::AccessError) { + fprintf(stderr, "Cannot install \"%s\". Cannot write to: %s. Check permissions.\n", + controller.serviceName().toLatin1().constData(), + settings.fileName().toLatin1().constData()); + } + return (ret == QSettings::NoError); +} + +void QtServiceBase::logMessage(const QString &message, QtServiceBase::MessageType type, + int, uint, const QByteArray &) +{ + if (!d_ptr->sysd) + return; + int st; + switch(type) { + case QtServiceBase::Error: + st = LOG_ERR; + break; + case QtServiceBase::Warning: + st = LOG_WARNING; + break; + default: + st = LOG_INFO; + } + if (!d_ptr->sysd->ident) { + QString tmp = encodeName(serviceName(), TRUE); + int len = tmp.toLocal8Bit().size(); + d_ptr->sysd->ident = new char[len+1]; + d_ptr->sysd->ident[len] = '\0'; + ::memcpy(d_ptr->sysd->ident, tmp.toLocal8Bit().constData(), len); + } + openlog(d_ptr->sysd->ident, LOG_PID, LOG_DAEMON); + foreach(QString line, message.split('\n')) + syslog(st, "%s", line.toLocal8Bit().constData()); + closelog(); +} + +void QtServiceBase::setServiceFlags(QtServiceBase::ServiceFlags flags) +{ + if (d_ptr->serviceFlags == flags) + return; + d_ptr->serviceFlags = flags; + if (d_ptr->sysd) + d_ptr->sysd->serviceFlags = flags; +} + diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp new file mode 100644 index 00000000..7a737af1 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp @@ -0,0 +1,903 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include "qtservice.h" +#include "qtservice_p.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(QTSERVICE_DEBUG) +#include +#endif + +typedef SERVICE_STATUS_HANDLE(WINAPI*PRegisterServiceCtrlHandler)(const wchar_t*,LPHANDLER_FUNCTION); +static PRegisterServiceCtrlHandler pRegisterServiceCtrlHandler = 0; +typedef BOOL(WINAPI*PSetServiceStatus)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS); +static PSetServiceStatus pSetServiceStatus = 0; +typedef BOOL(WINAPI*PChangeServiceConfig2)(SC_HANDLE,DWORD,LPVOID); +static PChangeServiceConfig2 pChangeServiceConfig2 = 0; +typedef BOOL(WINAPI*PCloseServiceHandle)(SC_HANDLE); +static PCloseServiceHandle pCloseServiceHandle = 0; +typedef SC_HANDLE(WINAPI*PCreateService)(SC_HANDLE,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPCTSTR,LPDWORD,LPCTSTR,LPCTSTR,LPCTSTR); +static PCreateService pCreateService = 0; +typedef SC_HANDLE(WINAPI*POpenSCManager)(LPCTSTR,LPCTSTR,DWORD); +static POpenSCManager pOpenSCManager = 0; +typedef BOOL(WINAPI*PDeleteService)(SC_HANDLE); +static PDeleteService pDeleteService = 0; +typedef SC_HANDLE(WINAPI*POpenService)(SC_HANDLE,LPCTSTR,DWORD); +static POpenService pOpenService = 0; +typedef BOOL(WINAPI*PQueryServiceStatus)(SC_HANDLE,LPSERVICE_STATUS); +static PQueryServiceStatus pQueryServiceStatus = 0; +typedef BOOL(WINAPI*PStartServiceCtrlDispatcher)(CONST SERVICE_TABLE_ENTRY*); +static PStartServiceCtrlDispatcher pStartServiceCtrlDispatcher = 0; +typedef BOOL(WINAPI*PStartService)(SC_HANDLE,DWORD,const wchar_t**); +static PStartService pStartService = 0; +typedef BOOL(WINAPI*PControlService)(SC_HANDLE,DWORD,LPSERVICE_STATUS); +static PControlService pControlService = 0; +typedef HANDLE(WINAPI*PDeregisterEventSource)(HANDLE); +static PDeregisterEventSource pDeregisterEventSource = 0; +typedef BOOL(WINAPI*PReportEvent)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCTSTR*,LPVOID); +static PReportEvent pReportEvent = 0; +typedef HANDLE(WINAPI*PRegisterEventSource)(LPCTSTR,LPCTSTR); +static PRegisterEventSource pRegisterEventSource = 0; +typedef DWORD(WINAPI*PRegisterServiceProcess)(DWORD,DWORD); +static PRegisterServiceProcess pRegisterServiceProcess = 0; +typedef BOOL(WINAPI*PQueryServiceConfig)(SC_HANDLE,LPQUERY_SERVICE_CONFIG,DWORD,LPDWORD); +static PQueryServiceConfig pQueryServiceConfig = 0; +typedef BOOL(WINAPI*PQueryServiceConfig2)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD); +static PQueryServiceConfig2 pQueryServiceConfig2 = 0; + + +#define RESOLVE(name) p##name = (P##name)lib.resolve(#name); +#define RESOLVEA(name) p##name = (P##name)lib.resolve(#name"A"); +#define RESOLVEW(name) p##name = (P##name)lib.resolve(#name"W"); + +static bool winServiceInit() +{ + if (!pOpenSCManager) { + QLibrary lib("advapi32"); + + // only resolve unicode versions + RESOLVEW(RegisterServiceCtrlHandler); + RESOLVE(SetServiceStatus); + RESOLVEW(ChangeServiceConfig2); + RESOLVE(CloseServiceHandle); + RESOLVEW(CreateService); + RESOLVEW(OpenSCManager); + RESOLVE(DeleteService); + RESOLVEW(OpenService); + RESOLVE(QueryServiceStatus); + RESOLVEW(StartServiceCtrlDispatcher); + RESOLVEW(StartService); // need only Ansi version + RESOLVE(ControlService); + RESOLVE(DeregisterEventSource); + RESOLVEW(ReportEvent); + RESOLVEW(RegisterEventSource); + RESOLVEW(QueryServiceConfig); + RESOLVEW(QueryServiceConfig2); + } + return pOpenSCManager != 0; +} + +bool QtServiceController::isInstalled() const +{ + Q_D(const QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); + if (hSCM) { + // Try to open the service + SC_HANDLE hService = pOpenService(hSCM, (wchar_t*)d->serviceName.utf16(), + SERVICE_QUERY_CONFIG); + + if (hService) { + result = true; + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +bool QtServiceController::isRunning() const +{ + Q_D(const QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); + if (hSCM) { + // Try to open the service + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), + SERVICE_QUERY_STATUS); + if (hService) { + SERVICE_STATUS info; + int res = pQueryServiceStatus(hService, &info); + if (res) + result = info.dwCurrentState != SERVICE_STOPPED; + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + + +QString QtServiceController::serviceFilePath() const +{ + Q_D(const QtServiceController); + QString result; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); + if (hSCM) { + // Try to open the service + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), + SERVICE_QUERY_CONFIG); + if (hService) { + DWORD sizeNeeded = 0; + char data[8 * 1024]; + if (pQueryServiceConfig(hService, (LPQUERY_SERVICE_CONFIG)data, 8 * 1024, &sizeNeeded)) { + LPQUERY_SERVICE_CONFIG config = (LPQUERY_SERVICE_CONFIG)data; + result = QString::fromUtf16((const ushort*)config->lpBinaryPathName); + } + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +QString QtServiceController::serviceDescription() const +{ + Q_D(const QtServiceController); + QString result; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); + if (hSCM) { + // Try to open the service + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), + SERVICE_QUERY_CONFIG); + if (hService) { + DWORD dwBytesNeeded; + char data[8 * 1024]; + if (pQueryServiceConfig2( + hService, + SERVICE_CONFIG_DESCRIPTION, + (unsigned char *)data, + 8096, + &dwBytesNeeded)) { + LPSERVICE_DESCRIPTION desc = (LPSERVICE_DESCRIPTION)data; + if (desc->lpDescription) + result = QString::fromUtf16((const ushort*)desc->lpDescription); + } + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +QtServiceController::StartupType QtServiceController::startupType() const +{ + Q_D(const QtServiceController); + StartupType result = ManualStartup; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); + if (hSCM) { + // Try to open the service + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), + SERVICE_QUERY_CONFIG); + if (hService) { + DWORD sizeNeeded = 0; + char data[8 * 1024]; + if (pQueryServiceConfig(hService, (QUERY_SERVICE_CONFIG *)data, 8 * 1024, &sizeNeeded)) { + QUERY_SERVICE_CONFIG *config = (QUERY_SERVICE_CONFIG *)data; + result = config->dwStartType == SERVICE_DEMAND_START ? ManualStartup : AutoStartup; + } + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +bool QtServiceController::uninstall() +{ + Q_D(QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); + if (hSCM) { + // Try to open the service + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), DELETE); + if (hService) { + if (pDeleteService(hService)) + result = true; + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +bool QtServiceController::start(const QStringList &args) +{ + Q_D(QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); + if (hSCM) { + // Try to open the service + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), SERVICE_START); + if (hService) { + QVector argv(args.size()); + for (int i = 0; i < args.size(); ++i) + argv[i] = (const wchar_t*)args.at(i).utf16(); + + if (pStartService(hService, args.size(), argv.data())) + result = true; + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +bool QtServiceController::stop() +{ + Q_D(QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); + if (hSCM) { + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), SERVICE_STOP|SERVICE_QUERY_STATUS); + if (hService) { + SERVICE_STATUS status; + if (pControlService(hService, SERVICE_CONTROL_STOP, &status)) { + bool stopped = status.dwCurrentState == SERVICE_STOPPED; + int i = 0; + while(!stopped && i < 10) { + Sleep(200); + if (!pQueryServiceStatus(hService, &status)) + break; + stopped = status.dwCurrentState == SERVICE_STOPPED; + ++i; + } + result = stopped; + } else { + qErrnoWarning(GetLastError(), "stopping"); + } + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +bool QtServiceController::pause() +{ + Q_D(QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); + if (hSCM) { + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), + SERVICE_PAUSE_CONTINUE); + if (hService) { + SERVICE_STATUS status; + if (pControlService(hService, SERVICE_CONTROL_PAUSE, &status)) + result = true; + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +bool QtServiceController::resume() +{ + Q_D(QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); + if (hSCM) { + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), + SERVICE_PAUSE_CONTINUE); + if (hService) { + SERVICE_STATUS status; + if (pControlService(hService, SERVICE_CONTROL_CONTINUE, &status)) + result = true; + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +bool QtServiceController::sendCommand(int code) +{ + Q_D(QtServiceController); + bool result = false; + if (!winServiceInit()) + return result; + + if (code < 0 || code > 127 || !isRunning()) + return result; + + SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); + if (hSCM) { + SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), + SERVICE_USER_DEFINED_CONTROL); + if (hService) { + SERVICE_STATUS status; + if (pControlService(hService, 128 + code, &status)) + result = true; + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +#if defined(QTSERVICE_DEBUG) +extern void qtServiceLogDebug(QtMsgType type, const char* msg); +#endif + +void QtServiceBase::logMessage(const QString &message, MessageType type, + int id, uint category, const QByteArray &data) +{ +#if defined(QTSERVICE_DEBUG) + QByteArray dbgMsg("[LOGGED "); + switch (type) { + case Error: dbgMsg += "Error] " ; break; + case Warning: dbgMsg += "Warning] "; break; + case Success: dbgMsg += "Success] "; break; + case Information: //fall through + default: dbgMsg += "Information] "; break; + } + dbgMsg += message.toAscii(); + qtServiceLogDebug((QtMsgType)-1, dbgMsg.constData()); +#endif + + Q_D(QtServiceBase); + if (!winServiceInit()) + return; + WORD wType; + switch (type) { + case Error: wType = EVENTLOG_ERROR_TYPE; break; + case Warning: wType = EVENTLOG_WARNING_TYPE; break; + case Information: wType = EVENTLOG_INFORMATION_TYPE; break; + default: wType = EVENTLOG_SUCCESS; break; + } + HANDLE h = pRegisterEventSource(0, (wchar_t *)d->controller.serviceName().utf16()); + if (h) { + const wchar_t *msg = (wchar_t*)message.utf16(); + const char *bindata = data.size() ? data.constData() : 0; + pReportEvent(h, wType, category, id, 0, 1, data.size(),(const wchar_t **)&msg, + const_cast(bindata)); + pDeregisterEventSource(h); + } +} + +class QtServiceControllerHandler : public QObject +{ + Q_OBJECT +public: + QtServiceControllerHandler(QtServiceSysPrivate *sys); + +protected: + void customEvent(QEvent *e); + +private: + QtServiceSysPrivate *d_sys; +}; + +class QtServiceSysPrivate +{ +public: + enum { + QTSERVICE_STARTUP = 256 + }; + QtServiceSysPrivate(); + + void setStatus( DWORD dwState ); + void setServiceFlags(QtServiceBase::ServiceFlags flags); + DWORD serviceFlags(QtServiceBase::ServiceFlags flags) const; + inline bool available() const; + static void WINAPI serviceMain( DWORD dwArgc, wchar_t** lpszArgv ); + static void WINAPI handler( DWORD dwOpcode ); + + SERVICE_STATUS status; + SERVICE_STATUS_HANDLE serviceStatus; + QStringList serviceArgs; + + static QtServiceSysPrivate *instance; + static QCoreApplication::EventFilter nextFilter; + + QWaitCondition condition; + QMutex mutex; + QSemaphore startSemaphore; + QSemaphore startSemaphore2; + + QtServiceControllerHandler *controllerHandler; + + void handleCustomEvent(QEvent *e); +}; + +QtServiceControllerHandler::QtServiceControllerHandler(QtServiceSysPrivate *sys) + : QObject(), d_sys(sys) +{ + +} + +void QtServiceControllerHandler::customEvent(QEvent *e) +{ + d_sys->handleCustomEvent(e); +} + + +QtServiceSysPrivate *QtServiceSysPrivate::instance = 0; +QCoreApplication::EventFilter QtServiceSysPrivate::nextFilter = 0; + +QtServiceSysPrivate::QtServiceSysPrivate() +{ + instance = this; +} + +inline bool QtServiceSysPrivate::available() const +{ + return 0 != pOpenSCManager; +} + +void WINAPI QtServiceSysPrivate::serviceMain(DWORD dwArgc, wchar_t** lpszArgv) +{ + if (!instance || !QtServiceBase::instance()) + return; + + // Windows spins off a random thread to call this function on + // startup, so here we just signal to the QApplication event loop + // in the main thread to go ahead with start()'ing the service. + + for (DWORD i = 0; i < dwArgc; i++) + instance->serviceArgs.append(QString::fromUtf16((unsigned short*)lpszArgv[i])); + + instance->startSemaphore.release(); // let the qapp creation start + instance->startSemaphore2.acquire(); // wait until its done + // Register the control request handler + instance->serviceStatus = pRegisterServiceCtrlHandler((TCHAR*)QtServiceBase::instance()->serviceName().utf16(), handler); + + if (!instance->serviceStatus) // cannot happen - something is utterly wrong + return; + + handler(QTSERVICE_STARTUP); // Signal startup to the application - + // causes QtServiceBase::start() to be called in the main thread + + // The MSDN doc says that this thread should just exit - the service is + // running in the main thread (here, via callbacks in the handler thread). +} + + +// The handler() is called from the thread that called +// StartServiceCtrlDispatcher, i.e. our HandlerThread, and +// not from the main thread that runs the event loop, so we +// have to post an event to ourselves, and use a QWaitCondition +// and a QMutex to synchronize. +void QtServiceSysPrivate::handleCustomEvent(QEvent *e) +{ + int code = e->type() - QEvent::User; + + switch(code) { + case QTSERVICE_STARTUP: // Startup + QtServiceBase::instance()->start(); + break; + case SERVICE_CONTROL_STOP: + QtServiceBase::instance()->stop(); + QCoreApplication::instance()->quit(); + break; + case SERVICE_CONTROL_PAUSE: + QtServiceBase::instance()->pause(); + break; + case SERVICE_CONTROL_CONTINUE: + QtServiceBase::instance()->resume(); + break; + default: + if (code >= 128 && code <= 255) + QtServiceBase::instance()->processCommand(code - 128); + break; + } + + mutex.lock(); + condition.wakeAll(); + mutex.unlock(); +} + +void WINAPI QtServiceSysPrivate::handler( DWORD code ) +{ + if (!instance) + return; + + instance->mutex.lock(); + switch (code) { + case QTSERVICE_STARTUP: // QtService startup (called from WinMain when started) + instance->setStatus(SERVICE_START_PENDING); + QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); + instance->condition.wait(&instance->mutex); + instance->setStatus(SERVICE_RUNNING); + break; + case SERVICE_CONTROL_STOP: // 1 + instance->setStatus(SERVICE_STOP_PENDING); + QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); + instance->condition.wait(&instance->mutex); + // status will be reported as stopped in start() when qapp::exec returns + break; + + case SERVICE_CONTROL_PAUSE: // 2 + instance->setStatus(SERVICE_PAUSE_PENDING); + QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); + instance->condition.wait(&instance->mutex); + instance->setStatus(SERVICE_PAUSED); + break; + + case SERVICE_CONTROL_CONTINUE: // 3 + instance->setStatus(SERVICE_CONTINUE_PENDING); + QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); + instance->condition.wait(&instance->mutex); + instance->setStatus(SERVICE_RUNNING); + break; + + case SERVICE_CONTROL_INTERROGATE: // 4 + break; + + default: + if ( code >= 128 && code <= 255 ) { + QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); + instance->condition.wait(&instance->mutex); + } + break; + } + + instance->mutex.unlock(); + + // Report current status + if (instance->available() && instance->status.dwCurrentState != SERVICE_STOPPED) + pSetServiceStatus(instance->serviceStatus, &instance->status); +} + +void QtServiceSysPrivate::setStatus(DWORD state) +{ + if (!available()) + return; + status.dwCurrentState = state; + pSetServiceStatus(serviceStatus, &status); +} + +void QtServiceSysPrivate::setServiceFlags(QtServiceBase::ServiceFlags flags) +{ + if (!available()) + return; + status.dwControlsAccepted = serviceFlags(flags); + pSetServiceStatus(serviceStatus, &status); +} + +DWORD QtServiceSysPrivate::serviceFlags(QtServiceBase::ServiceFlags flags) const +{ + DWORD control = 0; + if (flags & QtServiceBase::CanBeSuspended) + control |= SERVICE_ACCEPT_PAUSE_CONTINUE; + if (!(flags & QtServiceBase::CannotBeStopped)) + control |= SERVICE_ACCEPT_STOP; + return control; +} + +#include "qtservice_win.moc" + + +class HandlerThread : public QThread +{ +public: + HandlerThread() + : success(true), console(false), QThread() + {} + + bool calledOk() { return success; } + bool runningAsConsole() { return console; } + +protected: + bool success, console; + void run() + { + SERVICE_TABLE_ENTRYW st [2]; + st[0].lpServiceName = (wchar_t*)QtServiceBase::instance()->serviceName().utf16(); + st[0].lpServiceProc = QtServiceSysPrivate::serviceMain; + st[1].lpServiceName = 0; + st[1].lpServiceProc = 0; + + success = (pStartServiceCtrlDispatcher(st) != 0); // should block + + if (!success) { + if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { + // Means we're started from console, not from service mgr + // start() will ask the mgr to start another instance of us as a service instead + console = true; + } + else { + QtServiceBase::instance()->logMessage(QString("The Service failed to start [%1]").arg(qt_error_string(GetLastError())), QtServiceBase::Error); + } + QtServiceSysPrivate::instance->startSemaphore.release(); // let start() continue, since serviceMain won't be doing it + } + } +}; + +/* + Ignore WM_ENDSESSION system events, since they make the Qt kernel quit +*/ +bool myEventFilter(void* message, long* result) +{ + MSG* msg = reinterpret_cast(message); + if (!msg || (msg->message != WM_ENDSESSION) || !(msg->lParam & ENDSESSION_LOGOFF)) + return QtServiceSysPrivate::nextFilter ? QtServiceSysPrivate::nextFilter(message, result) : false; + + if (QtServiceSysPrivate::nextFilter) + QtServiceSysPrivate::nextFilter(message, result); + if (result) + *result = TRUE; + return true; +} + +/* There are three ways we can be started: + + - By a service controller (e.g. the Services control panel), with + no (service-specific) arguments. ServiceBase::exec() will then call + start() below, and the service will start. + + - From the console, but with no (service-specific) arguments. This + means we should ask a controller to start the service (i.e. another + instance of this executable), and then just terminate. We discover + this case (as different from the above) by the fact that + StartServiceCtrlDispatcher will return an error, instead of blocking. + + - From the console, with -e(xec) argument. ServiceBase::exec() will + then call ServiceBasePrivate::exec(), which calls + ServiceBasePrivate::run(), which runs the application as a normal + program. +*/ + +bool QtServiceBasePrivate::start() +{ + sysInit(); + if (!winServiceInit()) + return false; + + // Since StartServiceCtrlDispatcher() blocks waiting for service + // control events, we need to call it in another thread, so that + // the main thread can run the QApplication event loop. + HandlerThread* ht = new HandlerThread(); + ht->start(); + + QtServiceSysPrivate* sys = QtServiceSysPrivate::instance; + + // Wait until service args have been received by serviceMain. + // If Windows doesn't call serviceMain (or + // StartServiceControlDispatcher doesn't return an error) within + // a timeout of 20 secs, something is very wrong; give up + if (!sys->startSemaphore.tryAcquire(1, 20000)) + return false; + + if (!ht->calledOk()) { + if (ht->runningAsConsole()) + return controller.start(args.mid(1)); + else + return false; + } + + int argc = sys->serviceArgs.size(); + QVector argv(argc); + QList argvData; + for (int i = 0; i < argc; ++i) + argvData.append(sys->serviceArgs.at(i).toLocal8Bit()); + for (int i = 0; i < argc; ++i) + argv[i] = argvData[i].data(); + + q_ptr->createApplication(argc, argv.data()); + QCoreApplication *app = QCoreApplication::instance(); + if (!app) + return false; + QtServiceSysPrivate::nextFilter = app->setEventFilter(myEventFilter); + + sys->controllerHandler = new QtServiceControllerHandler(sys); + + sys->startSemaphore2.release(); // let serviceMain continue (and end) + + sys->status.dwWin32ExitCode = q_ptr->executeApplication(); + sys->setStatus(SERVICE_STOPPED); + + if (ht->isRunning()) + ht->wait(1000); // let the handler thread finish + delete sys->controllerHandler; + sys->controllerHandler = 0; + if (ht->isFinished()) + delete ht; + delete app; + sysCleanup(); + return true; +} + +bool QtServiceBasePrivate::install(const QString &account, const QString &password) +{ + bool result = false; + if (!winServiceInit()) + return result; + + // Open the Service Control Manager + SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); + if (hSCM) { + QString acc = account; + DWORD dwStartType = startupType == QtServiceController::AutoStartup ? SERVICE_AUTO_START : SERVICE_DEMAND_START; + DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS; + wchar_t *act = 0; + wchar_t *pwd = 0; + if (!acc.isEmpty()) { + // The act string must contain a string of the format "Domain\UserName", + // so if only a username was specified without a domain, default to the local machine domain. + if (!acc.contains(QChar('\\'))) { + acc.prepend(QLatin1String(".\\")); + } + if (!acc.endsWith(QLatin1String("\\LocalSystem"))) + act = (wchar_t*)acc.utf16(); + } + if (!password.isEmpty() && act) { + pwd = (wchar_t*)password.utf16(); + } + + // Only set INTERACTIVE if act is LocalSystem. (and act should be 0 if it is LocalSystem). + if (!act) dwServiceType |= SERVICE_INTERACTIVE_PROCESS; + + // Create the service + SC_HANDLE hService = pCreateService(hSCM, (wchar_t *)controller.serviceName().utf16(), + (wchar_t *)controller.serviceName().utf16(), + SERVICE_ALL_ACCESS, + dwServiceType, // QObject::inherits ( const char * className ) for no inter active ???? + dwStartType, SERVICE_ERROR_NORMAL, (wchar_t *)filePath().utf16(), + 0, 0, 0, + act, pwd); + if (hService) { + result = true; + if (!serviceDescription.isEmpty()) { + SERVICE_DESCRIPTION sdesc; + sdesc.lpDescription = (wchar_t *)serviceDescription.utf16(); + pChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sdesc); + } + pCloseServiceHandle(hService); + } + pCloseServiceHandle(hSCM); + } + return result; +} + +QString QtServiceBasePrivate::filePath() const +{ + wchar_t path[_MAX_PATH]; + ::GetModuleFileNameW( 0, path, sizeof(path) ); + return QString::fromUtf16((unsigned short*)path); +} + +bool QtServiceBasePrivate::sysInit() +{ + sysd = new QtServiceSysPrivate(); + + sysd->serviceStatus = 0; + sysd->status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS; + sysd->status.dwCurrentState = SERVICE_STOPPED; + sysd->status.dwControlsAccepted = sysd->serviceFlags(serviceFlags); + sysd->status.dwWin32ExitCode = NO_ERROR; + sysd->status.dwServiceSpecificExitCode = 0; + sysd->status.dwCheckPoint = 0; + sysd->status.dwWaitHint = 0; + + return true; +} + +void QtServiceBasePrivate::sysSetPath() +{ + +} + +void QtServiceBasePrivate::sysCleanup() +{ + if (sysd) { + delete sysd; + sysd = 0; + } +} + +void QtServiceBase::setServiceFlags(QtServiceBase::ServiceFlags flags) +{ + if (d_ptr->serviceFlags == flags) + return; + d_ptr->serviceFlags = flags; + if (d_ptr->sysd) + d_ptr->sysd->setServiceFlags(flags); +} + + diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp new file mode 100644 index 00000000..a04f0f4c --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include "qtunixserversocket.h" +#include +#include +#include +#include +#include + +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ + +strlen ((ptr)->sun_path)) +#endif + +QtUnixServerSocket::QtUnixServerSocket(const QString &path, QObject *parent) + : QTcpServer(parent) +{ + setPath(path); +} + +QtUnixServerSocket::QtUnixServerSocket(QObject *parent) + : QTcpServer(parent) +{ +} + +void QtUnixServerSocket::setPath(const QString &path) +{ + path_.clear(); + + int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); + if (sock != -1) { + struct sockaddr_un addr; + ::memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + ::unlink(path.toLatin1().constData()); // ### This might need to be changed + unsigned int pathlen = strlen(path.toLatin1().constData()); + if (pathlen > sizeof(addr.sun_path)) pathlen = sizeof(addr.sun_path); + ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); + if ((::bind(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)) != -1) && + (::listen(sock, 5) != -1)) { + setSocketDescriptor(sock); + path_ = path; + } + } +} + +void QtUnixServerSocket::close() +{ + QTcpServer::close(); + if (!path_.isEmpty()) { + ::unlink(path_.toLatin1().constData()); + path_.clear(); + } +} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h new file mode 100644 index 00000000..2ba2fd12 --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef QTUNIXSERVERSOCKET_H +#define QTUNIXSERVERSOCKET_H + +#include + +class QtUnixServerSocket : public QTcpServer +{ + Q_OBJECT +public: + QtUnixServerSocket(const QString &path, QObject *parent = 0); + QtUnixServerSocket(QObject *parent = 0); + + void setPath(const QString &path); + void close(); + +private: + QString path_; +}; + + +#endif diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp new file mode 100644 index 00000000..fae5ac1b --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include "qtunixsocket.h" +#include +#include +#include +#include +#include + +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ + +strlen ((ptr)->sun_path)) +#endif + +QtUnixSocket::QtUnixSocket(QObject *parent) + : QTcpSocket(parent) +{ +} + +bool QtUnixSocket::connectTo(const QString &path) +{ + bool ret = false; + int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); + if (sock != -1) { + struct sockaddr_un addr; + ::memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + size_t pathlen = strlen(path.toLatin1().constData()); + pathlen = qMin(pathlen, sizeof(addr.sun_path)); + ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); + int err = ::connect(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)); + if (err != -1) { + setSocketDescriptor(sock); + ret = true; + } else { + ::close(sock); + } + } + return ret; +} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h new file mode 100644 index 00000000..b7aaebde --- /dev/null +++ b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef QTUNIXSOCKET_H +#define QTUNIXSOCKET_H + +#include + +class QtUnixSocket : public QTcpSocket +{ + Q_OBJECT +public: + QtUnixSocket(QObject *parent = 0); + + bool connectTo(const QString &path); +}; + +#endif diff --git a/telldus-core/3rdparty/qtservice.cmake b/telldus-core/3rdparty/qtservice.cmake new file mode 100644 index 00000000..652b0127 --- /dev/null +++ b/telldus-core/3rdparty/qtservice.cmake @@ -0,0 +1,39 @@ + +QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice.moc ) + +SET( qtservice_SRCS + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp + ${CMAKE_CURRENT_BINARY_DIR}/qtservice.moc +) + +IF (UNIX) + QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice_unix.moc ) + + SET( qtservice_MOC_HDRS + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h + ) + + QT4_WRAP_CPP( qtservice_MOC_SRCS ${qtservice_MOC_HDRS} ) + + SET( qtservice_SRCS + ${qtservice_SRCS} + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp + ${CMAKE_CURRENT_BINARY_DIR}/qtservice_unix.moc + ${qtservice_MOC_SRCS} + ) +ELSEIF (WIN32) + QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice_win.moc ) + SET(qtservice_SRCS + ${qtservice_SRCS} + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp + ${CMAKE_CURRENT_BINARY_DIR}/qtservice_win.moc + ) +ENDIF (UNIX) + +INCLUDE_DIRECTORIES( + ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/ + ${CMAKE_CURRENT_BINARY_DIR} +) From 5b4700ef4f82115f9cdd546c0a1e396967a91add Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 06:28:43 +0000 Subject: [PATCH 0169/2215] Added som initial CMakeList.txt files --- telldus-core/CMakeLists.txt | 48 ++++++++++++ telldus-core/client/CMakeLists.txt | 117 ++++++++++++++++++++++++++++ telldus-core/common/CMakeLists.txt | 40 ++++++++++ telldus-core/service/CMakeLists.txt | 79 +++++++++++++++++++ telldus-core/service/main_unix.cpp | 22 ++++++ telldus-core/service/main_win.cpp | 20 +++++ 6 files changed, 326 insertions(+) create mode 100644 telldus-core/CMakeLists.txt create mode 100644 telldus-core/client/CMakeLists.txt create mode 100644 telldus-core/common/CMakeLists.txt create mode 100644 telldus-core/service/CMakeLists.txt create mode 100644 telldus-core/service/main_unix.cpp create mode 100644 telldus-core/service/main_win.cpp diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt new file mode 100644 index 00000000..4cd9b039 --- /dev/null +++ b/telldus-core/CMakeLists.txt @@ -0,0 +1,48 @@ +PROJECT( telldus-core ) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) + +CMAKE_POLICY(SET CMP0003 NEW) + +SET(PACKAGE_MAJOR_VERSION 2) +SET(PACKAGE_MINOR_VERSION 0) +SET(PACKAGE_PATCH_VERSION 200) +SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") +SET(PACKAGE_SUBVERSION) +SET(PACKAGE_SOVERSION 2) + +IF (PACKAGE_SUBVERSION) + SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_${PACKAGE_SUBVERSION}") +ELSE (PACKAGE_SUBVERSION) + SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) +ENDIF(PACKAGE_SUBVERSION) + +SET(BUILD_LIBTELLDUS-CORE TRUE CACHE BOOL "Build libtelldus-core") + +SET(USE_QT_SETTINGS_BACKEND FALSE CACHE BOOL "Use QT as settings backend instead of the native one") +IF (WIN32) + SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") +ENDIF (WIN32) + +SET(BUILD_RFCMD FALSE CACHE BOOL "Build rfcmd") + +SET(BUILD_TDTOOL TRUE CACHE BOOL "Build tdtool") + +SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") + +# Lets figure if we need to build against Qt or not +IF(USE_QT_SETTINGS_BACKEND) + SET(BUILD_WITH_QT TRUE) +ENDIF(USE_QT_SETTINGS_BACKEND) + +# ADD_SUBDIRECTORY(common) +# ADD_SUBDIRECTORY(service) +# ADD_SUBDIRECTORY(client) + +IF(BUILD_TDTOOL) +# ADD_SUBDIRECTORY(tdtool) +ENDIF(BUILD_TDTOOL) + +IF(BUILD_RFCMD) +# ADD_SUBDIRECTORY(rfcmd) +ENDIF(BUILD_RFCMD) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt new file mode 100644 index 00000000..398df729 --- /dev/null +++ b/telldus-core/client/CMakeLists.txt @@ -0,0 +1,117 @@ +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +######## Non configurable options ######## +SET( telldus-core_SRCS + telldus-core.cpp + ) + +SET( telldus-core_HDRS + telldus-core.h +) + + +OPTION(USE_FTD2XX_RATHER_THEN_LIBFTDI "Link against ftd2xx even if libftdi is the preferred one" OFF) +IF (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) + FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) + SET( telldus-core_LIBRARIES + ${telldus-core_LIBRARIES} + ${FTD2XX_LIBRARY} + ) + ADD_DEFINITIONS( -DLIBFTD2XX ) +ELSE (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) + FIND_LIBRARY(FTDI_LIBRARY ftdi) + SET( telldus-core_LIBRARIES + ${telldus-core_LIBRARIES} + ${FTDI_LIBRARY} + ) + ADD_DEFINITIONS( -DLIBFTDI ) +ENDIF (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) + + +######## Configurable options for the platform ######## + + + +######## Platforms-specific, non configurable ######## + +IF (APPLE) + #### Mac OS X #### + SET( telldus-core_TARGET TelldusCore ) + ADD_DEFINITIONS( + -D_MACOSX + ) +ELSEIF (WIN32) + #### Windows #### + SET( telldus-core_TARGET TelldusCore ) + SET( telldus-core_SRCS + ${telldus-core_SRCS} + libtelldus-core.def + ) + ADD_DEFINITIONS( + -D_WINDOWS + -DTELLDUSCORE_EXPORTS + ) +ELSE (APPLE) + #### Linux #### + SET( telldus-core_TARGET telldus-core ) + ADD_DEFINITIONS( + -D_LINUX + ) +ENDIF (APPLE) + + + +######## Configuring ######## + +ADD_LIBRARY(${telldus-core_TARGET} SHARED + ${telldus-core_SRCS} + ${telldus-core_HDRS} +) + +TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) + +SET_PROPERTY(TARGET ${telldus-core_TARGET} + PROPERTY FRAMEWORK TRUE +) +SET_PROPERTY(TARGET ${telldus-core_TARGET} + PROPERTY PUBLIC_HEADER ${telldus-core_HDRS} +) + +SET_PROPERTY(TARGET ${telldus-core_TARGET} + PROPERTY VERSION ${PACKAGE_VERSION} +) +SET_PROPERTY(TARGET ${telldus-core_TARGET} + PROPERTY SOVERSION ${PACKAGE_SOVERSION} +) + +IF (NOT LIBRARY_DIR) + SET(LIBRARY_DIR "lib") +ENDIF (NOT LIBRARY_DIR) + +IF (UNIX) + INSTALL(TARGETS ${telldus-core_TARGET} + LIBRARY DESTINATION ${LIBRARY_DIR} + ARCHIVE DESTINATION ${LIBRARY_DIR} + FRAMEWORK DESTINATION "/Library/Frameworks" + PUBLIC_HEADER DESTINATION include + ) +ENDIF (UNIX) + +IF (UNIX AND NOT APPLE) + SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) + SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) + SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) + + INSTALL(FILES tellstick.conf + DESTINATION ${SYSCONF_INSTALL_DIR} + ) + INSTALL(FILES telldus-core.conf + DESTINATION ${STATE_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE + ) + INSTALL(FILES 99-tellstick.rules + DESTINATION ${UDEV_RULES_DIR} + ) +ENDIF (UNIX AND NOT APPLE) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt new file mode 100644 index 00000000..195ea3aa --- /dev/null +++ b/telldus-core/common/CMakeLists.txt @@ -0,0 +1,40 @@ +IF(COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +######## Non configurable options ######## +SET( common_SRCS + ) + +SET( common_HDRS +) + +######## Configurable options for the platform ######## + + +######## Platforms-specific, non configurable ######## + +IF (APPLE) + #### Mac OS X #### + SET( telldus-common_TARGET TelldusCommon ) + ADD_DEFINITIONS( -D_MACOSX ) +ELSEIF (WIN32) + #### Windows #### + SET( telldus-common_TARGET TelldusCommon ) + ADD_DEFINITIONS( -D_WINDOWS ) +ELSE (APPLE) + #### Linux #### + SET( telldus-common_TARGET telldus-common ) + ADD_DEFINITIONS( -D_LINUX ) +ENDIF (APPLE) + + +######## Configuring ######## + + +ADD_LIBRARY(${telldus-common_TARGET} STATIC + ${telldus-common_SRCS} + ${telldus-common_HDRS} +) + +TARGET_LINK_LIBRARIES( ${telldus-common_TARGET} ${telldus-common_LIBRARIES} ) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt new file mode 100644 index 00000000..d0ed9d62 --- /dev/null +++ b/telldus-core/service/CMakeLists.txt @@ -0,0 +1,79 @@ +IF(COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +######## Non configurable options ######## +SET( telldus-service_SRCS +) +SET( telldus-service_HDRS +) + +FIND_PACKAGE(Threads) +LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) + + +######## Configurable options for the platform ######## + +######## Platforms-specific, non configurable ######## + +IF (APPLE) #### Mac OS X #### + SET( telldus-service_TARGET TelldusService ) + FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) + FIND_LIBRARY(IOKIT_LIBRARY IOKit) + + SET( telldus-service_LIBRARIES + ${telldus-service_LIBRARIES} + ${COREFOUNDATION_LIBRARY} + ${IOKIT_LIBRARY} + TelldusCommon + ) + LIST(APPEND telldus-service_SRCS + main_unix.cpp + ) + +ELSEIF (WIN32) #### Windows #### + SET( telldus-service_TARGET TelldusService ) + ADD_DEFINITIONS( -DUNICODE ) + ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No + SET(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" + ) + SET( telldus-service_LIBRARIES + ${telldus-service_LIBRARIES} + ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib + ) + LIST(APPEND telldus-service_SRCS + main_win.cpp + ) + +ELSE (APPLE) #### Linux #### + + SET( telldus-service_TARGET telldusd ) + LIST(APPEND telldus-service_SRCS + main_unix.cpp + ) + LIST(APPEND telldus-service_LIBRARIES + ${telldus-service_LIBRARIES} + telldus-common + ) +ENDIF (APPLE) + +######## Configuring ######## + + +ADD_EXECUTABLE(${telldus-service_TARGET} + ${telldus-service_SRCS} +) +SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + +TARGET_LINK_LIBRARIES( ${telldus-service_TARGET} ${telldus-service_LIBRARIES} ) + +SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist +) +IF (APPLE) + SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} + ) +ENDIF (APPLE) + diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp new file mode 100644 index 00000000..cc6c932d --- /dev/null +++ b/telldus-core/service/main_unix.cpp @@ -0,0 +1,22 @@ + +#include +#include + +#include "TelldusCore.h" +#include + +void shutdownHandler(int onSignal) { + qApp->quit(); +} + +int main(int argc, char **argv) { + QCoreApplication app(argc, argv); + + /* Install signal traps for proper shutdown */ + signal(SIGTERM, shutdownHandler); + signal(SIGINT, shutdownHandler); + + TelldusCore telldusCore; + + return app.exec(); +} diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp new file mode 100644 index 00000000..ec325075 --- /dev/null +++ b/telldus-core/service/main_win.cpp @@ -0,0 +1,20 @@ +#include "TelldusWinService_win.h" +#include + +#include +#include + + +int main(int argc, char **argv) { + g_argc = argc; + g_argv = argv; + + SERVICE_TABLE_ENTRY serviceTable[] = { + {serviceName, TelldusWinService::serviceMain }, + { 0, 0 } + }; + + StartServiceCtrlDispatcher( serviceTable ); + + return 0; +} From 9fedd898e28eab43941022e4f9fe39913d119100 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 06:54:47 +0000 Subject: [PATCH 0170/2215] Added function-stubs for the client library --- telldus-core/client/common.h | 36 +++ telldus-core/client/libtelldus-core.def | 47 +++ telldus-core/client/telldus-core.cpp | 397 ++++++++++++++++++++++++ telldus-core/client/telldus-core.h | 116 +++++++ 4 files changed, 596 insertions(+) create mode 100644 telldus-core/client/common.h create mode 100644 telldus-core/client/libtelldus-core.def create mode 100644 telldus-core/client/telldus-core.cpp create mode 100644 telldus-core/client/telldus-core.h diff --git a/telldus-core/client/common.h b/telldus-core/client/common.h new file mode 100644 index 00000000..886f94e1 --- /dev/null +++ b/telldus-core/client/common.h @@ -0,0 +1,36 @@ +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#ifdef _WINDOWS +#include "stdafx.h" +#include +#define strcasecmp _stricmp +#define strncasecmp _strnicmp + +#endif +#include +#include +#include +#include + +inline void msleep( const int msec) { +#ifdef _WINDOWS + Sleep(msec); +#else + usleep(msec*1000); +#endif +} + +inline char *wrapStdString( const std::string &string) { +#ifdef _WINDOWS + return (char *)SysAllocStringByteLen(string.c_str(), (unsigned int)string.size()); +#else + char *returnVal = (char *)malloc(sizeof(char) * (string.size()+1)); + strcpy(returnVal, string.c_str()); + return returnVal; +#endif +} diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def new file mode 100644 index 00000000..8932354c --- /dev/null +++ b/telldus-core/client/libtelldus-core.def @@ -0,0 +1,47 @@ +LIBRARY tellduscore +EXPORTS + tdGetNumberOfDevices @1 + tdGetDeviceId @2 + + tdGetName @3 + tdGetProtocol @4 + tdGetModel @5 + tdGetDeviceParameter @6 + + tdSetName @7 + tdSetProtocol @8 + tdSetModel @9 + tdSetDeviceParameter @10 + + tdAddDevice @11 + tdRemoveDevice @12 + + tdMethods @13 + tdTurnOn @14 + tdTurnOff @15 + tdBell @16 + tdDim @17 + + tdGetErrorString @18 + + tdClose @19 + + tdInit @20 + tdRegisterDeviceEvent @21 + tdLastSentCommand @22 + tdGetDeviceType @23 + + tdSendRawCommand @24 + tdRegisterRawDeviceEvent @25 + + tdLearn @26 + tdLastSentValue @27 + + tdReleaseString @28 + tdUnregisterCallback @29 + + tdConnectTellStickController @30 + tdDisconnectTellStickController @31 + + tdRegisterDeviceChangeEvent @32 + \ No newline at end of file diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp new file mode 100644 index 00000000..13907d44 --- /dev/null +++ b/telldus-core/client/telldus-core.cpp @@ -0,0 +1,397 @@ +/** + * @defgroup core telldus-core + * Telldus Core is the base module used to interface a Telldus TellStick. + * @{ + */ + +#include "telldus-core.h" +#include "common.h" +#include + + +/** + * @def TELLSTICK_TURNON + * Device-flag for devices supporting the tdTurnOn() call. + * + * @def TELLSTICK_TURNOFF + * Device-flag for devices supporting the tdTurnOff() call. + * + * @def TELLSTICK_BELL + * Device-flag for devices supporting the tdBell() call. + * + * @def TELLSTICK_TOGGLE + * This method is currently unimplemented. + * + * @def TELLSTICK_DIM + * Device-flag for devices supporting the tdDim() call. + * + * @def TELLSTICK_LEARN + * Device-flag for devices supporting the tdLearn() call. + * + * @def TELLSTICK_TYPE_DEVICE + * Device type of a single device. + * + * @def TELLSTICK_TYPE_GROUP + * Device type of a device which contains other devices. + * + * @def TELLSTICK_SUCCESS + * Error code. Returned when the command succeeded. + * + * @def TELLSTICK_ERROR_NOT_FOUND + * Error code. Returned if a TellStick was not found on the system. + * + * @def TELLSTICK_ERROR_PERMISSION_DENIED + * Error code. Returned if the user doesn't have privileges to open + * the TellStick device. + * + * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND + * Error code. The supplied device id was not found. + * + * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + * Error code. The requested method is not supported by the device. + * This should be avoided by a call to tdMethods(). + * + * @def TELLSTICK_ERROR_COMMUNICATION + * Error code. An error occurred when communicating with TellStick. + * + * @def TELLSTICK_ERROR_CONNECTING_SERVICE + * Error code. The client library could not connect to the service. + * Maybe it is not running? + * + * @def TELLSTICK_ERROR_UNKNOWN_RESPONSE + * Error code. The client library received a response from the service + * it did not understand. + * + * @def TELLSTICK_ERROR_UNKNOWN + * Error code. An unkown error has occurred. + */ + +#define MAX_LOADSTRING 100 + +void WINAPI tdInit(void) { +} + +int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { + return 0; +} + +int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { + return 0; +} + +int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { + return 0; +} + + +/** + * Close the library and clean up the cache it uses. + * This should be called when the library is not supposed to be used anymore + **/ +void WINAPI tdClose(void) { +} + +/** + * This method releases resources allocated by telldus-core. + * It should be called on the returned value from all functions return char * + **/ +void WINAPI tdReleaseString(char *string) { +#ifdef _WINDOWS + SysFreeString((BSTR)string); +#else + free(string); +#endif +} + + +/** + * Turns a device on. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to turn on. + **/ +int WINAPI tdTurnOn(int intDeviceId){ + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Turns a device off. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to turn off. + */ +int WINAPI tdTurnOff(int intDeviceId){ + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Sends bell command to devices supporting this. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to send bell to + */ +int WINAPI tdBell(int intDeviceId){ + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Dims a device. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to dim + * @param level The level the device should dim to. This value should be 0-255 + */ +int WINAPI tdDim(int intDeviceId, unsigned char level){ + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Sends a special learn command to some devices that need a special learn-command + * to be used from TellStick + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to learn. + */ +int WINAPI tdLearn(int intDeviceId) { + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Returns the last sent command to a specific device + * @param intDeviceId The device id to query + * @param methodsSupported The methods supported by the client. See tdMethods() for more information. + * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF + */ +int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ) { + return TELLSTICK_TURNOFF; +} + +/** + * If the last sent command it TELLSTICK_DIM this returns the dimmed value. + * @param intDeviceId The device id to query + * @returns the the value as a human readable string, example "128" for 50% + */ +char * WINAPI tdLastSentValue( int intDeviceId ) { + return wrapStdString("255"); +} + +/** + * This function returns the number of devices configured + * @returns an integer of the total number of devices configured + */ +int WINAPI tdGetNumberOfDevices(void){ + return 1; +} + +/** + * This function returns the unique id of a device with a specific index. + * To get all the id numbers you should loop over all the devices: + * \code + * int intNumberOfDevices = tdGetNumberOfDevices(); + * for (int i = 0; i < intNumberOfDevices; i++) { + * int id = tdGetDeviceId( i ); + * // id now contains the id number of the device with index of i + * } + * \endcode + * @param intDeviceIndex The device index to query. The index starts from 0. + * @returns the unique id for the device or -1 if the device is not found. + */ +int WINAPI tdGetDeviceId(int intDeviceIndex){ + return 1; +} + +/** + * Returns which type the device is. The device could be either + * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP + */ +int WINAPI tdGetDeviceType(int intDeviceId) { + return TELLSTICK_TYPE_DEVICE; +} + +/** + * Query a device for it's name. + * @param intDeviceId The unique id of the device to query + * @returns The name of the device or an empty string if the device is not found. + */ +char * WINAPI tdGetName(int intDeviceId){ + std::string strReturn = "Hardcoded device"; + return wrapStdString(strReturn); +} + +/** + * Sets a new name for a device. The devices are global for all application, changing + * this will change the name for other applications aswell. + * @param intDeviceId The device id to change the name for + * @param strNewName The new name for the devices + * @returns \c true on success, \c false otherwise. + */ +bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ + bool blnSuccess = false; + return blnSuccess; +} + +/** + * @returns the protocol used by a specific device. + * @param intDeviceId The device id to query. + */ +char* WINAPI tdGetProtocol(int intDeviceId){ + std::string strReturn = ""; + return wrapStdString(strReturn); +} + +/** + * This changes the current protocol used by a device. After changing the protocol, + * setting new parameters is required. + * @param intDeviceId The device to change. + * @param strProtocol The new protocol to use. + * @returns \c true on success, \c false otherwise. + * @sa tdSetModel() + * @sa tdSetDeviceParameter() + */ +bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ + bool blnSuccess = false; + return blnSuccess; +} + +/** + * @returns the model for a device. Not all protocols uses this. + * @param intDeviceId The device to query. + */ +char* WINAPI tdGetModel(int intDeviceId){ + std::string strReturn = ""; + return wrapStdString(strReturn); +} + +/** + * Sets a new model for a device. Which model to set depends on the + * current protocol. + * @param intDeviceId The device to change + * @param strModel The new model + * @returns \c true on success, \c false otherwise. + */ +bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ + bool blnSuccess = false; + return blnSuccess; +} + +/** + * Sets a new protocol specific parameter. Please see the documentation of the protocols + * before setting any parameter. + * @param intDeviceId The device to change. + * @param strName The parameter to change. + * @param strValue The new value for the parameter. + * @returns \c true on success, \c false otherwise. + */ +bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ + return false; +} + +/** + * @returns any protocol specific parameter specified by \c strName + * @param intDeviceId The device to query. + * @param strName The name of the parameter to query. + * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. + */ +char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ + std::string strReturn = ""; + return wrapStdString(strReturn); +} + +/** + * Add a new device to the global database of devices. This function must be called first before + * any call to tdSetName(), tdSetProtocol() and similar functions. + * @returns the new device id for the newly created device. If the creation fails it returnes a + * negative value. + */ +int WINAPI tdAddDevice(){ + int intNewDeviceId = -1; + return intNewDeviceId; +} + +/** + * Removes a device. + * @returns \c true on success, \c false otherwise. + */ +bool WINAPI tdRemoveDevice(int intDeviceId){ + bool blnSuccess = false; + return blnSuccess; +} + +/** + * Query a device for which methods it supports. By supplying the methods you support + * the library could remap the methods a device support for better fit the application. + * Example of querying a device supporting TELLSTICK_BELL: + * \code + * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); + * //methods is now TELLSTICK_BELL + * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); + * //methods is now TELLSTICK_TURNON because the client application doesn't support TELLSTICK_BELL + * \endcode + * @param id The device id to query + * @param methodsSupported The methods the client application supports + * @returns The method-flags OR'ed into an integer. + * @sa TELLSTICK_TURNON + * @sa TELLSTICK_TURNOFF + * @sa TELLSTICK_BELL + * @sa TELLSTICK_TOGGLE + * @sa TELLSTICK_DIM + */ +int WINAPI tdMethods(int id, int methodsSupported){ + + return TELLSTICK_TURNON; +} + +/** + * Get a human readable string from an error code returned + * from a function in telldus-core. + * @param intErrorNo The error code to translate. + * @returns a string ready to show to the user. + * @sa TELLSTICK_SUCCESS + * @sa TELLSTICK_ERROR_NOT_FOUND + * @sa TELLSTICK_ERROR_PERMISSION_DENIED + * @sa TELLSTICK_ERROR_DEVICE_NOT_FOUND + * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + * @sa TELLSTICK_ERROR_UNKNOWN + */ +char * WINAPI tdGetErrorString(int intErrorNo) { + const int numResponses = 8; + const char *responses[numResponses] = { + "Success", + "TellStick not found", + "Permission denied", + "Device not found", + "The method you tried to use is not supported by the device", + "An error occurred while communicating with TellStick", + "Could not connect to the Telldus Service", + "Received an unknown response" + }; + std::string strReturn; + intErrorNo = abs(intErrorNo); //We don't use negative values here. + if (intErrorNo >= numResponses) { + strReturn = "Unknown error"; + } else { + // Copy the error string to strReturn + strReturn = responses[intErrorNo]; + } + return wrapStdString(strReturn); +} + +/** + * Send a raw command to TellStick. Please read the TellStick protocol + * definition on how the command should be constructed. + * @param command The command for TellStick in its native format + * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure + */ +int WINAPI tdSendRawCommand(const char *command, int reserved) { + return TELLSTICK_ERROR_UNKNOWN; +} + + +void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { +} + +void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { +} + + +/*\@}*/ diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h new file mode 100644 index 00000000..1fa84fe7 --- /dev/null +++ b/telldus-core/client/telldus-core.h @@ -0,0 +1,116 @@ +#ifndef TELLDUSCORE_H +#define TELLDUSCORE_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLSTICK_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef _WINDOWS + #if defined(TELLDUSCORE_STATIC) + #define TELLSTICK_API + #elif defined(TELLDUSCORE_EXPORTS) + #define TELLSTICK_API __declspec(dllexport) + #else + #define TELLSTICK_API __declspec(dllimport) + #endif + #define WINAPI __stdcall +#else + #define WINAPI + #define TELLSTICK_API +#endif + +typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); +typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); +typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); + +#ifndef __cplusplus + #define bool char +#endif + +#ifdef __cplusplus +extern "C" { +#endif + TELLSTICK_API void WINAPI tdInit(void); + TELLSTICK_API int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); + TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); + TELLSTICK_API void WINAPI tdClose(void); + TELLSTICK_API void WINAPI tdReleaseString(char *string); + + TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); + TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); + TELLSTICK_API int WINAPI tdBell(int intDeviceId); + TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI tdLearn(int intDeviceId); + TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); + TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); + TELLSTICK_API char *WINAPI tdLastSentValue( int intDeviceId ); + + TELLSTICK_API int WINAPI tdGetNumberOfDevices(); + TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); + TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); + + TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); + + TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); + TELLSTICK_API char * WINAPI tdGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, const char *intModel); + + TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); + + TELLSTICK_API int WINAPI tdAddDevice(); + TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); + + TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); + + TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); + TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); + +#ifdef __cplusplus +} +#endif + +//Device methods +#define TELLSTICK_TURNON 1 +#define TELLSTICK_TURNOFF 2 +#define TELLSTICK_BELL 4 +#define TELLSTICK_TOGGLE 8 +#define TELLSTICK_DIM 16 +#define TELLSTICK_LEARN 32 + +//Error codes +#define TELLSTICK_SUCCESS 0 +#define TELLSTICK_ERROR_NOT_FOUND -1 +#define TELLSTICK_ERROR_PERMISSION_DENIED -2 +#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 +#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 +#define TELLSTICK_ERROR_COMMUNICATION -5 +#define TELLSTICK_ERROR_CONNECTING_SERVICE -6 +#define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7 +#define TELLSTICK_ERROR_UNKNOWN -99 + +//Device typedef +#define TELLSTICK_TYPE_DEVICE 1 +#define TELLSTICK_TYPE_GROUP 2 + +//Device changes +#define TELLSTICK_DEVICE_ADDED 1 +#define TELLSTICK_DEVICE_CHANGED 2 +#define TELLSTICK_DEVICE_REMOVED 3 +#define TELLSTICK_DEVICE_STATE_CHANGED 4 + +//Change types +#define TELLSTICK_CHANGE_NAME 1 +#define TELLSTICK_CHANGE_PROTOCOL 2 +#define TELLSTICK_CHANGE_MODEL 3 + +#endif From c374f416fe516edef78dab075e5b64a2655d4205 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 07:01:39 +0000 Subject: [PATCH 0171/2215] Added diretory client to build --- telldus-core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 4cd9b039..e51fcf83 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -37,7 +37,7 @@ ENDIF(USE_QT_SETTINGS_BACKEND) # ADD_SUBDIRECTORY(common) # ADD_SUBDIRECTORY(service) -# ADD_SUBDIRECTORY(client) +ADD_SUBDIRECTORY(client) IF(BUILD_TDTOOL) # ADD_SUBDIRECTORY(tdtool) From 2d390899925ab8add889ca254ac872ea0d723825 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 07:06:59 +0000 Subject: [PATCH 0172/2215] Build-fixes for windows --- telldus-core/client/common.h | 6 +++--- telldus-core/client/telldus-core.cpp | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/telldus-core/client/common.h b/telldus-core/client/common.h index 886f94e1..37cd9965 100644 --- a/telldus-core/client/common.h +++ b/telldus-core/client/common.h @@ -6,16 +6,16 @@ // #ifdef _WINDOWS -#include "stdafx.h" +#include #include #define strcasecmp _stricmp #define strncasecmp _strnicmp - +#else +#include #endif #include #include #include -#include inline void msleep( const int msec) { #ifdef _WINDOWS diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 13907d44..0afac2e4 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -83,6 +83,10 @@ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void return 0; } +int WINAPI tdUnregisterCallback( int callbackId ) { + return TELLSTICK_SUCCESS; +} + /** * Close the library and clean up the cache it uses. From 697f7221cf08c34da4a86a7937fab56d39f10ecf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 07:42:46 +0000 Subject: [PATCH 0173/2215] Added very basic service implementation. It lacks an event-loop so it shut itself down immediately. --- telldus-core/CMakeLists.txt | 2 +- telldus-core/service/CMakeLists.txt | 10 +- .../service/TelldusWinService_win.cpp | 152 ++++++++++++++++++ telldus-core/service/TelldusWinService_win.h | 35 ++++ telldus-core/service/main_win.cpp | 2 +- 5 files changed, 195 insertions(+), 6 deletions(-) create mode 100644 telldus-core/service/TelldusWinService_win.cpp create mode 100644 telldus-core/service/TelldusWinService_win.h diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index e51fcf83..e044f326 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -36,7 +36,7 @@ IF(USE_QT_SETTINGS_BACKEND) ENDIF(USE_QT_SETTINGS_BACKEND) # ADD_SUBDIRECTORY(common) -# ADD_SUBDIRECTORY(service) +ADD_SUBDIRECTORY(service) ADD_SUBDIRECTORY(client) IF(BUILD_TDTOOL) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index d0ed9d62..37f69211 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -6,6 +6,7 @@ ENDIF(COMMAND cmake_policy) SET( telldus-service_SRCS ) SET( telldus-service_HDRS + TelldusWinService_win.h ) FIND_PACKAGE(Threads) @@ -38,12 +39,13 @@ ELSEIF (WIN32) #### Windows #### SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" ) - SET( telldus-service_LIBRARIES - ${telldus-service_LIBRARIES} - ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib - ) + #SET( telldus-service_LIBRARIES + # ${telldus-service_LIBRARIES} + # ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib + #) LIST(APPEND telldus-service_SRCS main_win.cpp + TelldusWinService_win.cpp ) ELSE (APPLE) #### Linux #### diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp new file mode 100644 index 00000000..0f928a64 --- /dev/null +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -0,0 +1,152 @@ +#include "TelldusWinService_win.h" +//#include "TelldusCore.h" +//#include +//#include + +#include + +int g_argc; +char **g_argv; + + +static const GUID GUID_DEVINTERFACE_USBRAW = +{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; + +TelldusWinService::TelldusWinService() + :tc(0) +{ + + //setServiceDescription("A Telldus service for managing TellStick Duo."); +} + +TelldusWinService::~TelldusWinService() { +} + +void TelldusWinService::start() { +// tc = new TelldusCore(); + +// connect(this, SIGNAL(deviceInserted(int,int,const QString &)), tc, SLOT(deviceInserted(int,int,const QString &))); +// connect(this, SIGNAL(deviceRemoved(int,int,const QString &)), tc, SLOT(deviceRemoved(int,int,const QString &))); + + //app->quit(); + +} + + +void TelldusWinService::stop() { +// if (tc) { +// delete tc; +// } +// tc = 0; +} + +DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { + switch ( controlCode ) { + case SERVICE_CONTROL_INTERROGATE: + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + return NO_ERROR; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + stop(); + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + +// QCoreApplication::quit(); + return NO_ERROR; + + case SERVICE_CONTROL_DEVICEEVENT: + if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast(lpEventData); + if (!pDevInf) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + +// TelldusCore::logMessage(QString::fromWCharArray(pDevInf->dbcc_name)); + +/* QRegExp rx("USB#VID_([0-9A-Fa-f]+)&PID_([0-9A-Fa-f]+)", Qt::CaseInsensitive); + if (rx.indexIn(QString::fromWCharArray(pDevInf->dbcc_name)) < 0) { + TelldusCore::logMessage("No match"); + return 0; + } + + int vid = strtol(rx.cap(1).toLocal8Bit(), 0, 16); + int pid = strtol(rx.cap(2).toLocal8Bit(), 0, 16); + + if (dwEventType == DBT_DEVICEARRIVAL) { + TelldusCore::logMessage(QString("Insert %1 %2").arg(vid).arg(pid)); + emit deviceInserted(vid, pid, ""); + } else { + TelldusCore::logMessage(QString("Remove %1").arg(rx.cap(3))); + emit deviceRemoved(vid, pid, ""); + }*/ + + return NO_ERROR; + } + return ERROR_CALL_NOT_IMPLEMENTED; +} + +DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { + TelldusWinService *instance = reinterpret_cast(lpContext); + if (!instance) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + return instance->serviceControlHandler(controlCode, dwEventType, lpEventData); +} + +void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { + TelldusWinService instance; +// QCoreApplication app(g_argc, g_argv); + + + // initialise service status + instance.serviceStatus.dwServiceType = SERVICE_WIN32; + instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; + instance.serviceStatus.dwControlsAccepted = 0; + instance.serviceStatus.dwWin32ExitCode = NO_ERROR; + instance.serviceStatus.dwServiceSpecificExitCode = NO_ERROR; + instance.serviceStatus.dwCheckPoint = 0; + instance.serviceStatus.dwWaitHint = 0; + + instance.serviceStatusHandle = RegisterServiceCtrlHandlerEx( serviceName, TelldusWinService::serviceControlHandler, &instance ); + + if ( instance.serviceStatusHandle ) { + // service is starting + instance.serviceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + + // running + instance.start(); + instance.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + instance.serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + + DEV_BROADCAST_DEVICEINTERFACE devInterface; + ZeroMemory( &devInterface, sizeof(devInterface) ); + devInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + devInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW; + + HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE); + + if (!deviceNotificationHandle) { +// TelldusCore::logMessage(QString("Fail RegisterDeviceNotification")); + } + + //TelldusCore::logMessage(QString("Main thread waiting for service to stop")); +// app.exec(); + //TelldusCore::logMessage(QString("Main thread waited, shutting down")); + + // service was stopped + instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + + // service is now stopped + instance.serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + } +} diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h new file mode 100644 index 00000000..37ea8565 --- /dev/null +++ b/telldus-core/service/TelldusWinService_win.h @@ -0,0 +1,35 @@ +#ifndef TELLDUSSERVICE_WIN_H +#define TELLDUSSERVICE_WIN_H + +#include + +extern int g_argc; +extern char **g_argv; + +class TelldusCore; + +#define serviceName TEXT("TelldusCore") + +class TelldusWinService { +public: + TelldusWinService(); + ~TelldusWinService(); + + static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); + +protected: + + void start(); + void stop(); + + DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); + +private: + TelldusCore *tc; + SERVICE_STATUS serviceStatus; + SERVICE_STATUS_HANDLE serviceStatusHandle; + + static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); + +}; +#endif TELLDUSSERVICE_WIN_H \ No newline at end of file diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp index ec325075..95257b1e 100644 --- a/telldus-core/service/main_win.cpp +++ b/telldus-core/service/main_win.cpp @@ -1,5 +1,5 @@ #include "TelldusWinService_win.h" -#include +//#include #include #include From 387f997816df66efa539cb61fae207acea097031 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 07:44:00 +0000 Subject: [PATCH 0174/2215] Added public headers --- telldus-core/client/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 398df729..761c5acc 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -8,6 +8,8 @@ SET( telldus-core_SRCS ) SET( telldus-core_HDRS +) +SET( telldus-core_PUB_HDRS telldus-core.h ) @@ -68,6 +70,7 @@ ENDIF (APPLE) ADD_LIBRARY(${telldus-core_TARGET} SHARED ${telldus-core_SRCS} ${telldus-core_HDRS} + ${telldus-core_PUB_HDRS} ) TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) @@ -76,7 +79,7 @@ SET_PROPERTY(TARGET ${telldus-core_TARGET} PROPERTY FRAMEWORK TRUE ) SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY PUBLIC_HEADER ${telldus-core_HDRS} + PROPERTY PUBLIC_HEADER ${telldus-core_PUB_HDRS} ) SET_PROPERTY(TARGET ${telldus-core_TARGET} From 05b4837d26242b63503a1659c49860bd10586198 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 07:56:59 +0000 Subject: [PATCH 0175/2215] Excluding redundant .def-file when compiling with 64 bit compiler from microsoft. --- telldus-core/client/CMakeLists.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 761c5acc..00b238fc 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -47,10 +47,11 @@ IF (APPLE) ELSEIF (WIN32) #### Windows #### SET( telldus-core_TARGET TelldusCore ) - SET( telldus-core_SRCS - ${telldus-core_SRCS} - libtelldus-core.def - ) + IF (NOT CMAKE_CL_64) + LIST(APPEND telldus-core_SRCS + libtelldus-core.def + ) + ENDIF(NOT CMAKE_CL_64) ADD_DEFINITIONS( -D_WINDOWS -DTELLDUSCORE_EXPORTS From bb17f275874a56cd935fa0747b71202625b59570 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 09:53:20 +0000 Subject: [PATCH 0176/2215] Added the headers to the project --- telldus-core/service/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 37f69211..7859bb34 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -12,7 +12,6 @@ SET( telldus-service_HDRS FIND_PACKAGE(Threads) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - ######## Configurable options for the platform ######## ######## Platforms-specific, non configurable ######## @@ -65,6 +64,7 @@ ENDIF (APPLE) ADD_EXECUTABLE(${telldus-service_TARGET} ${telldus-service_SRCS} + ${telldus-service_HDRS} ) SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) From 4a94bce2ada7062ef957355a1a94b1a7057066ec Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 10:10:56 +0000 Subject: [PATCH 0177/2215] Added common library with a thread-implementation --- telldus-core/CMakeLists.txt | 2 +- telldus-core/common/CMakeLists.txt | 8 +- telldus-core/common/Thread.cpp | 176 ++++++++++++++++++++++++++++ telldus-core/common/Thread.h | 59 ++++++++++ telldus-core/service/CMakeLists.txt | 11 +- 5 files changed, 248 insertions(+), 8 deletions(-) create mode 100644 telldus-core/common/Thread.cpp create mode 100644 telldus-core/common/Thread.h diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index e044f326..de510bfc 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -35,7 +35,7 @@ IF(USE_QT_SETTINGS_BACKEND) SET(BUILD_WITH_QT TRUE) ENDIF(USE_QT_SETTINGS_BACKEND) -# ADD_SUBDIRECTORY(common) +ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(service) ADD_SUBDIRECTORY(client) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 195ea3aa..5898c92a 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -3,10 +3,12 @@ IF(COMMAND cmake_policy) ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## -SET( common_SRCS - ) +SET( telldus-common_SRCS + Thread.cpp +) -SET( common_HDRS +SET( telldus-common_HDRS + Thread.h ) ######## Configurable options for the platform ######## diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp new file mode 100644 index 00000000..2420a593 --- /dev/null +++ b/telldus-core/common/Thread.cpp @@ -0,0 +1,176 @@ +// +// C++ Implementation: Thread +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "Thread.h" + +using namespace TelldusCore; + +class TelldusCore::ThreadPrivate { +public: +#ifdef _WINDOWS + HANDLE thread; + DWORD threadId; + HANDLE noEvent, noWait; +#else + pthread_t thread; + pthread_cond_t noEvent, noWait; +#endif + MUTEX mutex; + + //Must be locked by the mutex! + bool hasEvent; + std::string strMessage; + int intMessage; +}; + +Thread::Thread() { + d = new ThreadPrivate; + initMutex(&d->mutex); + + lockMutex(&d->mutex); + d->hasEvent = false; + unlockMutex(&d->mutex); + +#ifdef _WINDOWS + d->noEvent = CreateEvent(0, FALSE, FALSE, 0); + d->noWait = CreateEvent(0, FALSE, FALSE, 0); +#else + pthread_cond_init(&d->noEvent, NULL); + pthread_cond_init(&d->noWait, NULL); +#endif +} + +Thread::~Thread() { + destroyMutex(&d->mutex); +#ifdef _WINDOWS + CloseHandle(d->noEvent); + CloseHandle(d->noWait); +#else + pthread_cond_destroy(&d->noEvent); + pthread_cond_destroy(&d->noWait); +#endif + delete d; +} + +void Thread::start() { +#ifdef _WINDOWS + d->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Thread::exec, this, 0, &d->threadId); +#else + pthread_create(&d->thread, NULL, &Thread::exec, this ); +#endif +} + +bool Thread::wait() { +#ifdef _WINDOWS + WaitForSingleObject(d->thread, INFINITE); + CloseHandle(d->thread); +#else + pthread_join(d->thread, 0); +#endif + return true; +} + +void *Thread::exec( void *ptr ) { + Thread *t = reinterpret_cast(ptr); + if (t) { + t->run(); + } + return 0; +} + +std::string Thread::waitForEvent(int *intMessage) { + std::string strMessage; + lockMutex(&d->mutex); + while(!d->hasEvent) { +#ifdef _WINDOWS + unlockMutex(&d->mutex); + WaitForSingleObject(d->noWait, INFINITE); + lockMutex(&d->mutex); +#else + pthread_cond_wait(&d->noWait, &d->mutex); +#endif + } + d->hasEvent = false; + strMessage = d->strMessage; + (*intMessage) = d->intMessage; + unlockMutex(&d->mutex); +#ifdef _WINDOWS + SetEvent(d->noEvent); +#else + pthread_cond_broadcast(&d->noEvent); +#endif + return strMessage; +} + +void Thread::sendEvent(const std::string &strMessage, int intMessage) { + lockMutex(&d->mutex); + while (d->hasEvent) { //We have an unprocessed event +#ifdef _WINDOWS + unlockMutex(&d->mutex); + WaitForSingleObject(d->noEvent, INFINITE); + lockMutex(&d->mutex); +#else + pthread_cond_wait(&d->noEvent, &d->mutex); +#endif + } + d->hasEvent = true; + d->strMessage = strMessage; + d->intMessage = intMessage; + unlockMutex(&d->mutex); +#ifdef _WINDOWS + SetEvent(d->noWait); +#else + pthread_cond_broadcast(&d->noWait); +#endif +} + +void Thread::initMutex(MUTEX * m) { +#ifdef _WINDOWS + InitializeCriticalSection(m); +#else + pthread_mutex_init(m, NULL); +#endif +} + +void Thread::destroyMutex(MUTEX * m) { +#ifdef _WINDOWS + DeleteCriticalSection(m); +#else + pthread_mutex_destroy(m); +#endif +} + +void Thread::unlockMutex(MUTEX * m) { +#ifdef _WINDOWS + LeaveCriticalSection(m); +#else + pthread_mutex_unlock(m); +#endif +} + +void Thread::lockMutex(MUTEX * m) { +#ifdef _WINDOWS + EnterCriticalSection(m); +#else + pthread_mutex_lock(m); +#endif +} + + +MutexLocker::MutexLocker(MUTEX *m) + :mutex(m) { + Thread::lockMutex(mutex); +} + +MutexLocker::~MutexLocker() { + Thread::unlockMutex(mutex); +} diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h new file mode 100644 index 00000000..e557bce4 --- /dev/null +++ b/telldus-core/common/Thread.h @@ -0,0 +1,59 @@ +// +// C++ Interface: Thread +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef THREAD_H +#define THREAD_H + +#include + +#ifdef _WINDOWS + #include + typedef CRITICAL_SECTION MUTEX; +#else + #include + typedef pthread_mutex_t MUTEX; +#endif + +namespace TelldusCore { + class ThreadPrivate; + class Thread { + public: + Thread(); + virtual ~Thread(); + void start(); + bool wait(); + + void sendEvent(const std::string &string, int integer = 0); + + static void initMutex(MUTEX *m); + static void destroyMutex(MUTEX *m); + static void lockMutex(MUTEX *m); + static void unlockMutex(MUTEX *m); + + protected: + virtual void run() = 0; + std::string waitForEvent(int *intMessage); + + private: + static void* exec( void *ptr ); + ThreadPrivate *d; + }; + + class MutexLocker { + public: + MutexLocker(MUTEX *m); + ~MutexLocker(); + private: + MUTEX *mutex; + }; +} + +#endif diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 7859bb34..92d18866 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -12,6 +12,10 @@ SET( telldus-service_HDRS FIND_PACKAGE(Threads) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/../common +) + ######## Configurable options for the platform ######## ######## Platforms-specific, non configurable ######## @@ -38,10 +42,9 @@ ELSEIF (WIN32) #### Windows #### SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" ) - #SET( telldus-service_LIBRARIES - # ${telldus-service_LIBRARIES} - # ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib - #) + LIST(APPEND telldus-service_LIBRARIES + ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib + ) LIST(APPEND telldus-service_SRCS main_win.cpp TelldusWinService_win.cpp From 622fe620fb312acabd8ce6468fe0cfe4a7c911a9 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 14:24:30 +0000 Subject: [PATCH 0178/2215] Socket.h added --- telldus-core/common/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 5898c92a..01528e74 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -9,6 +9,7 @@ SET( telldus-common_SRCS SET( telldus-common_HDRS Thread.h + Socket.h ) ######## Configurable options for the platform ######## @@ -24,6 +25,9 @@ ELSEIF (WIN32) #### Windows #### SET( telldus-common_TARGET TelldusCommon ) ADD_DEFINITIONS( -D_WINDOWS ) + LIST(APPEND telldus-common_SRCS + Socket_win.cpp + ) ELSE (APPLE) #### Linux #### SET( telldus-common_TARGET telldus-common ) From 3a0a130b456deaeccf26446d92f2f6c624b8f7cd Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 14:25:30 +0000 Subject: [PATCH 0179/2215] A bit further --- telldus-core/client/telldus-core.cpp | 51 ++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 0afac2e4..ae12b92a 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -179,11 +179,62 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { return wrapStdString("255"); } + /** * This function returns the number of devices configured * @returns an integer of the total number of devices configured */ int WINAPI tdGetNumberOfDevices(void){ + DWORD dwMode; + bool fSuccess = false; + + //Convert our std::string to std::wstring since we build agains win32 with unicode support + //std::string strName = "\\\\.\\pipe\\" + server; + std::wstring name(L"\\\\.\\pipe\\TelldusClient"); + HANDLE hPipe = CreateFile( + (const wchar_t *)name.c_str(), // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, // default attributes + NULL); // no template file + + if (hPipe == INVALID_HANDLE_VALUE) { + return 2; + } + + dwMode = PIPE_READMODE_MESSAGE; + fSuccess = SetNamedPipeHandleState( + hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time + + if (!fSuccess) { + return 3; + } + + OVERLAPPED oOverlap; + DWORD bytesWritten = 0; + + oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + std::string msg = "tdGetNumberOfDevices"; + WriteFile(hPipe, msg.data(), (DWORD)msg.length(), &bytesWritten, &oOverlap); + + /*result = WaitForSingleObject(oOverlap.hEvent, 10000); + if (result == WAIT_TIMEOUT) { + CloseHandle(oOverlap.hEvent); + return; + } + + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, false); + CloseHandle(oOverlap.hEvent); + if (!fSuccess) { + return; + } +*/ return 1; } From bb5fd10c2c3ee5ce9ae146230542c97509471319 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 14:26:32 +0000 Subject: [PATCH 0180/2215] Definitions added --- telldus-core/client/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 00b238fc..622f5647 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -46,12 +46,14 @@ IF (APPLE) ) ELSEIF (WIN32) #### Windows #### + ADD_DEFINITIONS( -DUNICODE ) + ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No SET( telldus-core_TARGET TelldusCore ) - IF (NOT CMAKE_CL_64) + #IF (NOT CMAKE_CL_64) LIST(APPEND telldus-core_SRCS libtelldus-core.def ) - ENDIF(NOT CMAKE_CL_64) + #ENDIF(NOT CMAKE_CL_64) ADD_DEFINITIONS( -D_WINDOWS -DTELLDUSCORE_EXPORTS From 3c0eee8c540b5486a0bf1b186dcd985b27764c62 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 14:27:06 +0000 Subject: [PATCH 0181/2215] TelldusMain added --- .../service/TelldusWinService_win.cpp | 25 ++++++++++++++++--- telldus-core/service/TelldusWinService_win.h | 4 ++- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 0f928a64..e5213ce9 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -1,4 +1,5 @@ #include "TelldusWinService_win.h" +#include "TelldusMain.h" //#include "TelldusCore.h" //#include //#include @@ -13,10 +14,11 @@ static const GUID GUID_DEVINTERFACE_USBRAW = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; TelldusWinService::TelldusWinService() - :tc(0) + :tm(0) { - - //setServiceDescription("A Telldus service for managing TellStick Duo."); + tm = new TelldusMain(); + + //setServiceDescription("A Telldus service for managing TellStick Duo."); } TelldusWinService::~TelldusWinService() { @@ -34,6 +36,12 @@ void TelldusWinService::start() { void TelldusWinService::stop() { + //running = false; + tm->stop(); + //if(tm){ + // delete tm; + //} + //tm = 0; // if (tc) { // delete tc; // } @@ -137,6 +145,17 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { } //TelldusCore::logMessage(QString("Main thread waiting for service to stop")); + + //TelldusMain tm; + //tm = new TelldusMain(); + //tm.start(); + instance.tm->start(); + + //while(instance.running) { + // Sleep(1000); + //} + + // app.exec(); //TelldusCore::logMessage(QString("Main thread waited, shutting down")); diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index 37ea8565..482f66f1 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -7,6 +7,7 @@ extern int g_argc; extern char **g_argv; class TelldusCore; +class TelldusMain; #define serviceName TEXT("TelldusCore") @@ -16,7 +17,7 @@ public: ~TelldusWinService(); static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); - + protected: void start(); @@ -26,6 +27,7 @@ protected: private: TelldusCore *tc; + TelldusMain *tm; SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE serviceStatusHandle; From 5a653c3d60166923234e199b92c1cb4f4be1b1cb Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 14:28:20 +0000 Subject: [PATCH 0182/2215] Classes added --- telldus-core/service/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 92d18866..acabc9c3 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -4,9 +4,12 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-service_SRCS + TelldusMain.cpp ) SET( telldus-service_HDRS - TelldusWinService_win.h + TelldusMain.h + ConnectionListener.h + Event.h ) FIND_PACKAGE(Threads) @@ -48,6 +51,10 @@ ELSEIF (WIN32) #### Windows #### LIST(APPEND telldus-service_SRCS main_win.cpp TelldusWinService_win.cpp + ConnectionListener_win.cpp + ) + LIST(APPEND telldus-service_HDRS + TelldusWinService_win.h ) ELSE (APPLE) #### Linux #### From 1cc0a9496dbcbd0f7533394654947191f1677bfb Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 14:30:11 +0000 Subject: [PATCH 0183/2215] New files --- telldus-core/common/Socket.h | 20 ++++ telldus-core/common/Socket_win.cpp | 54 +++++++++ telldus-core/service/ConnectionListener.h | 21 ++++ .../service/ConnectionListener_win.cpp | 111 ++++++++++++++++++ telldus-core/service/Event.h | 12 ++ telldus-core/service/TelldusMain.cpp | 42 +++++++ telldus-core/service/TelldusMain.h | 20 ++++ 7 files changed, 280 insertions(+) create mode 100644 telldus-core/common/Socket.h create mode 100644 telldus-core/common/Socket_win.cpp create mode 100644 telldus-core/service/ConnectionListener.h create mode 100644 telldus-core/service/ConnectionListener_win.cpp create mode 100644 telldus-core/service/Event.h create mode 100644 telldus-core/service/TelldusMain.cpp create mode 100644 telldus-core/service/TelldusMain.h diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h new file mode 100644 index 00000000..436c5035 --- /dev/null +++ b/telldus-core/common/Socket.h @@ -0,0 +1,20 @@ +#ifndef SOCKET_H +#define SOCKET_H + +#include +#include "Event.h" + +class Socket +{ +public: + Socket(HANDLE hPipe); + virtual ~Socket(void); + + std::string read(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //SOCKET_H diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp new file mode 100644 index 00000000..fc636c6d --- /dev/null +++ b/telldus-core/common/Socket_win.cpp @@ -0,0 +1,54 @@ +#include "Socket.h" +#include "Event.h" + +#include +#include +#include + +#define BUFSIZE 512 + +class Socket::PrivateData { +public: + HANDLE hPipe; +}; + +Socket::Socket(HANDLE hPipe) +{ + d = new PrivateData; + d->hPipe = hPipe; + +} + +Socket::~Socket(void){ + delete d; +} + +std::string Socket::read() { + char buf[BUFSIZE]; + int result; + DWORD cbBytesRead = 0; + OVERLAPPED oOverlap; + HANDLE readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + oOverlap.hEvent = readEvent; + bool fSuccess = false; + + memset(&buf, 0, BUFSIZE); + + ReadFile( d->hPipe, &buf, sizeof(char)*BUFSIZE, &cbBytesRead, &oOverlap); + + result = WaitForSingleObject(oOverlap.hEvent, 10000); + if (result == WAIT_TIMEOUT) { + CloseHandle(readEvent); + return ""; + } + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); + if (!fSuccess) { + DWORD err = GetLastError(); + if (err == ERROR_BROKEN_PIPE) { + //TODO: Connection closed + } + buf[0] = 0; + } + CloseHandle(readEvent); + return buf; +} \ No newline at end of file diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h new file mode 100644 index 00000000..75674f39 --- /dev/null +++ b/telldus-core/service/ConnectionListener.h @@ -0,0 +1,21 @@ +#ifndef CONNECTIONLISTENER_H +#define CONNECTIONLISTENER_H + +#include +#include "Event.h" +#include "Socket.h" + +class ConnectionListener +{ +public: + ConnectionListener(const std::wstring &name); + virtual ~ConnectionListener(void); + void listen(EVENT waitEvent); + Socket *retrieveClientSocket(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CONNECTIONLISTENER_H diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp new file mode 100644 index 00000000..b800ec22 --- /dev/null +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -0,0 +1,111 @@ +#include "ConnectionListener.h" + +#include +#include +#include + +#define BUFSIZE 512 + +class ConnectionListener::PrivateData { +public: + std::wstring pipename; + SECURITY_ATTRIBUTES sa; + HANDLE hPipe; + OVERLAPPED oOverlap; +}; + +ConnectionListener::ConnectionListener(const std::wstring &name) +{ + d = new PrivateData; + + d->pipename = L"\\\\.\\pipe\\" + name; + + + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + EXPLICIT_ACCESS ea; + PSID pEveryoneSID = NULL; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + + pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD == NULL) { + return; + } + + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { + LocalFree(pSD); + return; + } + + if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) { + LocalFree(pSD); + } + + ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); + ea.grfAccessPermissions = STANDARD_RIGHTS_ALL; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance= NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; + + + // Add the ACL to the security descriptor. + if (!SetSecurityDescriptorDacl(pSD, + TRUE, // bDaclPresent flag + pACL, + FALSE)) // not a default DACL + { + LocalFree(pSD); + FreeSid(pEveryoneSID); + } + + + d->sa.nLength = sizeof(SECURITY_ATTRIBUTES); + d->sa.lpSecurityDescriptor = pSD; + d->sa.bInheritHandle = false; + +} + +ConnectionListener::~ConnectionListener(void) +{ + delete d; +} + +void ConnectionListener::listen(EVENT waitEvent){ + + d->oOverlap.hEvent = waitEvent; + + d->hPipe = CreateNamedPipe( + (const wchar_t *)d->pipename.c_str(), // pipe name + PIPE_ACCESS_DUPLEX | // read/write access + FILE_FLAG_OVERLAPPED, //Overlapped mode + PIPE_TYPE_MESSAGE | // message type pipe + PIPE_READMODE_MESSAGE | // message-read mode + PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max. instances + BUFSIZE, // output buffer size + BUFSIZE, // input buffer size + 0, // client time-out + &d->sa); // default security attribute + + if (d->hPipe == INVALID_HANDLE_VALUE) { + //TelldusCore::logMessage("Could not create named pipe"); + return; + } + + ConnectNamedPipe(d->hPipe, &d->oOverlap); +} + +Socket *ConnectionListener::retrieveClientSocket(){ + DWORD cbBytesRead; + + bool connected = GetOverlappedResult(d->hPipe, &d->oOverlap, &cbBytesRead, false); + if (!connected) { + CloseHandle(d->hPipe); + return 0; + } + Socket *s = new Socket(d->hPipe); + return s; + +} diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h new file mode 100644 index 00000000..de599867 --- /dev/null +++ b/telldus-core/service/Event.h @@ -0,0 +1,12 @@ +#ifndef EVENT_H +#define EVENT_H + +#ifdef _WINDOWS + #include + typedef HANDLE EVENT; +#else + //#include + //typedef pthread_mutex_t MUTEX; +#endif + +#endif //EVENT_H \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp new file mode 100644 index 00000000..235472ed --- /dev/null +++ b/telldus-core/service/TelldusMain.cpp @@ -0,0 +1,42 @@ +#include "TelldusMain.h" +#include "ConnectionListener.h" + +TelldusMain::TelldusMain(void) +{ + running = true; +} + +TelldusMain::~TelldusMain(void) +{ +} + +void TelldusMain::start(void){ + ConnectionListener clientListener(L"TelldusClient"); + EVENT clientEvent = CreateEvent(NULL, true, true, NULL);//EventHandler::createEvent(); + //TODO: eventlistener + + clientListener.listen(clientEvent); + //TODO: listen on eventListener + + //EventHandler eventHandler; + while(running) { + + +// int eventId = eventHandler.waitForAny(); + int result = WaitForSingleObject(clientEvent, 3000); + if (result != WAIT_TIMEOUT) { +// if (eventId == clientEvent.id()) { + //New client connection + Socket *s = clientListener.retrieveClientSocket(); + s->read(); + delete s; + clientListener.listen(clientEvent); + } + + Sleep(1000); + } +} + +void TelldusMain::stop(void){ + running = false; +} diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h new file mode 100644 index 00000000..8f836a3c --- /dev/null +++ b/telldus-core/service/TelldusMain.h @@ -0,0 +1,20 @@ +#ifndef TELLDUSMAIN_H +#define TELLDUSMAIN_H + +#include + +class TelldusMain +{ +public: + TelldusMain(void); + ~TelldusMain(void); + + void start(); + void stop(); + +private: + bool running; + +}; + +#endif //TELLDUSMAIN_H \ No newline at end of file From 07a7046a637a02edce34b10e1fceb33c036c4aa9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 14:55:06 +0000 Subject: [PATCH 0184/2215] Added class EventHandler and moved windows-specific code from TelldusMain to it. --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/EventHandler.h | 21 ++++++++++++++ telldus-core/service/EventHandler_win.cpp | 34 +++++++++++++++++++++++ telldus-core/service/TelldusMain.cpp | 11 ++++---- 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 telldus-core/service/EventHandler.h create mode 100644 telldus-core/service/EventHandler_win.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index acabc9c3..edcbcd6f 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -10,6 +10,7 @@ SET( telldus-service_HDRS TelldusMain.h ConnectionListener.h Event.h + EventHandler.h ) FIND_PACKAGE(Threads) @@ -52,6 +53,7 @@ ELSEIF (WIN32) #### Windows #### main_win.cpp TelldusWinService_win.cpp ConnectionListener_win.cpp + EventHandler_win.cpp ) LIST(APPEND telldus-service_HDRS TelldusWinService_win.h diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h new file mode 100644 index 00000000..d9aeeb91 --- /dev/null +++ b/telldus-core/service/EventHandler.h @@ -0,0 +1,21 @@ +#ifndef EVENTHANDLER_H +#define EVENTHANDLER_H + +#include "Event.h" + +class EventHandler { +public: + EventHandler(); + virtual ~EventHandler(void); + + void addEvent(EVENT event); + + int waitForAny(); + + static EVENT createEvent(); +private: + class PrivateData; + PrivateData *d; +}; + +#endif //EVENTHANDLER_H \ No newline at end of file diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp new file mode 100644 index 00000000..0534ca97 --- /dev/null +++ b/telldus-core/service/EventHandler_win.cpp @@ -0,0 +1,34 @@ +#include "EventHandler.h" + +class EventHandler::PrivateData { +public: + EVENT event; +}; + +EventHandler::EventHandler() +{ + d = new PrivateData; + +} + +EventHandler::~EventHandler(void) +{ + delete d; +} + +void EventHandler::addEvent(EVENT event) { + d->event = event; +} + +int EventHandler::waitForAny() { + int result = WaitForSingleObject(d->event, 3000); + if (result == WAIT_TIMEOUT) { + return 0; + } + return 1; + +} + +EVENT EventHandler::createEvent() { + return CreateEvent(NULL, true, true, NULL); +} \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 235472ed..7bf9856f 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -1,5 +1,6 @@ #include "TelldusMain.h" #include "ConnectionListener.h" +#include "EventHandler.h" TelldusMain::TelldusMain(void) { @@ -12,19 +13,19 @@ TelldusMain::~TelldusMain(void) void TelldusMain::start(void){ ConnectionListener clientListener(L"TelldusClient"); - EVENT clientEvent = CreateEvent(NULL, true, true, NULL);//EventHandler::createEvent(); + EVENT clientEvent = EventHandler::createEvent(); //TODO: eventlistener clientListener.listen(clientEvent); //TODO: listen on eventListener - //EventHandler eventHandler; + EventHandler eventHandler; + eventHandler.addEvent(clientEvent); while(running) { -// int eventId = eventHandler.waitForAny(); - int result = WaitForSingleObject(clientEvent, 3000); - if (result != WAIT_TIMEOUT) { + int eventId = eventHandler.waitForAny(); + if (eventId) { // if (eventId == clientEvent.id()) { //New client connection Socket *s = clientListener.retrieveClientSocket(); From 08d838ba8d6b35f5e08c631b56b54a20fde3f7f6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 7 Oct 2010 15:35:11 +0000 Subject: [PATCH 0185/2215] ClientMessageHandler added, and changed to wstring in some places. --- telldus-core/common/CMakeLists.txt | 2 ++ telldus-core/common/Socket.h | 2 +- telldus-core/common/Socket_win.cpp | 10 +++--- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/ClientMessageHandler.cpp | 34 +++++++++++++++++++ telldus-core/service/ClientMessageHandler.h | 21 ++++++++++++ telldus-core/service/TelldusMain.cpp | 5 +-- 7 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 telldus-core/service/ClientMessageHandler.cpp create mode 100644 telldus-core/service/ClientMessageHandler.h diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 01528e74..74a383c9 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -23,6 +23,8 @@ IF (APPLE) ADD_DEFINITIONS( -D_MACOSX ) ELSEIF (WIN32) #### Windows #### + ADD_DEFINITIONS( -DUNICODE ) + ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No SET( telldus-common_TARGET TelldusCommon ) ADD_DEFINITIONS( -D_WINDOWS ) LIST(APPEND telldus-common_SRCS diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 436c5035..9d14954a 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -10,7 +10,7 @@ public: Socket(HANDLE hPipe); virtual ~Socket(void); - std::string read(); + std::wstring read(); private: class PrivateData; diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index fc636c6d..cecc3d0d 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -7,6 +7,8 @@ #define BUFSIZE 512 +//TODO: using namespace TelldusCore; + class Socket::PrivateData { public: HANDLE hPipe; @@ -23,8 +25,8 @@ Socket::~Socket(void){ delete d; } -std::string Socket::read() { - char buf[BUFSIZE]; +std::wstring Socket::read() { + wchar_t buf[BUFSIZE]; int result; DWORD cbBytesRead = 0; OVERLAPPED oOverlap; @@ -34,12 +36,12 @@ std::string Socket::read() { memset(&buf, 0, BUFSIZE); - ReadFile( d->hPipe, &buf, sizeof(char)*BUFSIZE, &cbBytesRead, &oOverlap); + ReadFile( d->hPipe, &buf, sizeof(wchar_t)*BUFSIZE, &cbBytesRead, &oOverlap); result = WaitForSingleObject(oOverlap.hEvent, 10000); if (result == WAIT_TIMEOUT) { CloseHandle(readEvent); - return ""; + return L""; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); if (!fSuccess) { diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index edcbcd6f..c5622f9e 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -5,11 +5,13 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-service_SRCS TelldusMain.cpp + ClientMessageHandler.cpp ) SET( telldus-service_HDRS TelldusMain.h ConnectionListener.h Event.h + ClientMessageHandler.h EventHandler.h ) diff --git a/telldus-core/service/ClientMessageHandler.cpp b/telldus-core/service/ClientMessageHandler.cpp new file mode 100644 index 00000000..1cb960da --- /dev/null +++ b/telldus-core/service/ClientMessageHandler.cpp @@ -0,0 +1,34 @@ +#include "ClientMessageHandler.h" + +#include + +class ClientMessageHandler::PrivateData { +public: + std::wstring clientMessage; +}; + +ClientMessageHandler::ClientMessageHandler(const std::wstring &clientMessage) + :Thread() +{ + d = new PrivateData; + d->clientMessage = clientMessage; + +} + +ClientMessageHandler::~ClientMessageHandler(void) +{ + delete d; +} + +void ClientMessageHandler::run(){ + //run thread + if(d->clientMessage == L"tdGetNumberOfDevices"){ + //starta ny tråd (ny klass, ärv från Thread) + //skicka in meddelandet i denna tråd + //kolla där vad det är för meddelande + //do stuff + //TODO + } +} + + diff --git a/telldus-core/service/ClientMessageHandler.h b/telldus-core/service/ClientMessageHandler.h new file mode 100644 index 00000000..aacb8826 --- /dev/null +++ b/telldus-core/service/ClientMessageHandler.h @@ -0,0 +1,21 @@ +#ifndef CLIENTMESSAGEHANDLER_H +#define CLIENTMESSAGEHANDLER_H + +#include +#include "Thread.h" + +class ClientMessageHandler : public TelldusCore::Thread +{ +public: + ClientMessageHandler(const std::wstring &clientMessage); + ~ClientMessageHandler(void); + +protected: + void run(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CLIENTMESSAGEHANDLER_H \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 7bf9856f..7c92b2af 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -29,8 +29,9 @@ void TelldusMain::start(void){ // if (eventId == clientEvent.id()) { //New client connection Socket *s = clientListener.retrieveClientSocket(); - s->read(); - delete s; + std::wstring clientMessage = s->read(); + + delete s; //TODO: Cleanup clientListener.listen(clientEvent); } From 86a3cd73a2c6562b2175c5cfdefcee41b5cdabbf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 15:41:19 +0000 Subject: [PATCH 0186/2215] Made EventHandler handle multiple events. --- telldus-core/service/EventHandler.h | 2 +- telldus-core/service/EventHandler_win.cpp | 32 ++++++++++++++++------- telldus-core/service/TelldusMain.cpp | 5 ++-- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index d9aeeb91..c006357d 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -10,7 +10,7 @@ public: void addEvent(EVENT event); - int waitForAny(); + EVENT waitForAny(); static EVENT createEvent(); private: diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 0534ca97..6a411b23 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -2,30 +2,42 @@ class EventHandler::PrivateData { public: - EVENT event; + EVENT *events; + int eventCount; }; -EventHandler::EventHandler() -{ +EventHandler::EventHandler() { d = new PrivateData; - + d->eventCount = 0; + d->events = new EVENT[0]; } -EventHandler::~EventHandler(void) -{ +EventHandler::~EventHandler(void) { + delete[] d->events; delete d; } void EventHandler::addEvent(EVENT event) { - d->event = event; + EVENT *newArray = new EVENT[d->eventCount+1]; + for (int i = 0; i < d->eventCount; ++i) { + newArray[i] = d->events[i]; + } + delete[] d->events; + d->events = newArray; + d->events[d->eventCount] = event; + ++d->eventCount; } -int EventHandler::waitForAny() { - int result = WaitForSingleObject(d->event, 3000); +EVENT EventHandler::waitForAny() { + int result = WaitForMultipleObjects(d->eventCount, d->events, FALSE, 3000); if (result == WAIT_TIMEOUT) { return 0; } - return 1; + int eventIndex = result - WAIT_OBJECT_0; + if (eventIndex >= d->eventCount) { + return 0; + } + return d->events[eventIndex]; } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 7c92b2af..46bd5b4f 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -24,9 +24,8 @@ void TelldusMain::start(void){ while(running) { - int eventId = eventHandler.waitForAny(); - if (eventId) { -// if (eventId == clientEvent.id()) { + EVENT signaledEvent = eventHandler.waitForAny(); + if (signaledEvent == clientEvent) { //New client connection Socket *s = clientListener.retrieveClientSocket(); std::wstring clientMessage = s->read(); From 34bb8fc81216b7a4a3cb8e6c4bfb7c3113734b2e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:26:58 +0000 Subject: [PATCH 0187/2215] Removed Qt from main_unix.cpp --- telldus-core/service/main_unix.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index cc6c932d..987464fa 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -1,22 +1,11 @@ -#include -#include - -#include "TelldusCore.h" #include void shutdownHandler(int onSignal) { - qApp->quit(); } int main(int argc, char **argv) { - QCoreApplication app(argc, argv); - /* Install signal traps for proper shutdown */ signal(SIGTERM, shutdownHandler); - signal(SIGINT, shutdownHandler); - - TelldusCore telldusCore; - - return app.exec(); + signal(SIGINT, shutdownHandler); } From fc7a28e5095c8b93d1a3cd390fe22cfef73ab3b4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:27:33 +0000 Subject: [PATCH 0188/2215] Added type EVENT for unix --- telldus-core/service/Event.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index de599867..1b0c0f0b 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -1,12 +1,12 @@ -#ifndef EVENT_H +#ifndef EVENT_H #define EVENT_H #ifdef _WINDOWS #include typedef HANDLE EVENT; #else - //#include - //typedef pthread_mutex_t MUTEX; + #include + typedef pthread_cond_t EVENT; #endif -#endif //EVENT_H \ No newline at end of file +#endif //EVENT_H From 852f65c9414b99aad3eed25748b706dfff7169f6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:28:04 +0000 Subject: [PATCH 0189/2215] Removed windows.h from platform independent code --- telldus-core/service/ClientMessageHandler.cpp | 2 -- telldus-core/service/TelldusMain.h | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/ClientMessageHandler.cpp b/telldus-core/service/ClientMessageHandler.cpp index 1cb960da..64194d64 100644 --- a/telldus-core/service/ClientMessageHandler.cpp +++ b/telldus-core/service/ClientMessageHandler.cpp @@ -1,7 +1,5 @@ #include "ClientMessageHandler.h" -#include - class ClientMessageHandler::PrivateData { public: std::wstring clientMessage; diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index 8f836a3c..2cb17843 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -1,7 +1,5 @@ -#ifndef TELLDUSMAIN_H -#define TELLDUSMAIN_H - -#include +#ifndef TELLDUSMAIN_H +#define TELLDUSMAIN_H class TelldusMain { From caf9fe34a609f263021e9133828ec4efbaaeec9d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:28:59 +0000 Subject: [PATCH 0190/2215] Event.h cannot be included in Socket.h since the belongs to different projects --- telldus-core/common/Socket.h | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 9d14954a..774c7bb3 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -2,7 +2,6 @@ #define SOCKET_H #include -#include "Event.h" class Socket { From 047f162947ca4b0c8c3140fed43ead744a7b3320 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:31:15 +0000 Subject: [PATCH 0191/2215] Added the new type SOCKET --- telldus-core/common/Socket.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 774c7bb3..c4e312fa 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -3,10 +3,17 @@ #include +#ifdef _WINDOWS + #include + typedef HANDLE SOCKET; +#else + typedef unsigned int SOCKET; +#endif + class Socket { public: - Socket(HANDLE hPipe); + Socket(SOCKET hPipe); virtual ~Socket(void); std::wstring read(); From b686378df286185ecf1d3ba214c41e4316b88784 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:42:37 +0000 Subject: [PATCH 0192/2215] Added new overloaded function EventHandler::add() --- telldus-core/service/EventHandler.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index c006357d..b12e1e2a 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -1,14 +1,15 @@ #ifndef EVENTHANDLER_H -#define EVENTHANDLER_H - -#include "Event.h" - +#define EVENTHANDLER_H + +#include "Event.h" + class EventHandler { public: EventHandler(); virtual ~EventHandler(void); void addEvent(EVENT event); + EVENT addEvent(); EVENT waitForAny(); @@ -16,6 +17,6 @@ public: private: class PrivateData; PrivateData *d; -}; - -#endif //EVENTHANDLER_H \ No newline at end of file +}; + +#endif //EVENTHANDLER_H From a756393a88381c68b83108ea753400697bbc7a66 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:45:19 +0000 Subject: [PATCH 0193/2215] Use our new overloaded function EventHandler::add() --- telldus-core/service/TelldusMain.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 46bd5b4f..3b39ddd2 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -12,15 +12,15 @@ TelldusMain::~TelldusMain(void) } void TelldusMain::start(void){ + EventHandler eventHandler; + EVENT clientEvent = eventHandler.addEvent(); + ConnectionListener clientListener(L"TelldusClient"); - EVENT clientEvent = EventHandler::createEvent(); //TODO: eventlistener clientListener.listen(clientEvent); //TODO: listen on eventListener - EventHandler eventHandler; - eventHandler.addEvent(clientEvent); while(running) { @@ -33,8 +33,11 @@ void TelldusMain::start(void){ delete s; //TODO: Cleanup clientListener.listen(clientEvent); } - +#ifdef _WINDOWS Sleep(1000); +#else + sleep(1); +#endif } } From 3be92d58df6786ef70f3757de96b5dd0b9f8a234 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 18:45:45 +0000 Subject: [PATCH 0194/2215] Added unix version of EventHandler --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/EventHandler_unix.cpp | 28 ++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 telldus-core/service/EventHandler_unix.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index c5622f9e..954652ab 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -39,6 +39,7 @@ IF (APPLE) #### Mac OS X #### ) LIST(APPEND telldus-service_SRCS main_unix.cpp + EventHandler_unix.cpp ) ELSEIF (WIN32) #### Windows #### @@ -66,6 +67,7 @@ ELSE (APPLE) #### Linux #### SET( telldus-service_TARGET telldusd ) LIST(APPEND telldus-service_SRCS main_unix.cpp + EventHandler_unix.cpp ) LIST(APPEND telldus-service_LIBRARIES ${telldus-service_LIBRARIES} diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp new file mode 100644 index 00000000..480ac778 --- /dev/null +++ b/telldus-core/service/EventHandler_unix.cpp @@ -0,0 +1,28 @@ +#include "EventHandler.h" + +class EventHandler::PrivateData { +public: +}; + +EventHandler::EventHandler() { + d = new PrivateData; +} + +EventHandler::~EventHandler(void) { + delete d; +} + +void EventHandler::addEvent(EVENT event) { +} + +EVENT EventHandler::addEvent() { + EVENT event = EventHandler::createEvent(); + this->addEvent(event); + return event; +} + +EVENT EventHandler::waitForAny() { +} + +EVENT EventHandler::createEvent() { +} \ No newline at end of file From 801ac343cc25d08a130e98c4a25460d3e0fee9df Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Oct 2010 20:07:15 +0000 Subject: [PATCH 0195/2215] Converted type EVENT to a class instead --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/ConnectionListener.h | 2 +- telldus-core/service/Event.h | 26 +++++++++++----- telldus-core/service/EventHandler.h | 11 +++---- telldus-core/service/EventHandler_unix.cpp | 36 ++++++++++++++++------ telldus-core/service/Event_unix.cpp | 29 +++++++++++++++++ telldus-core/service/TelldusMain.cpp | 8 ++--- 7 files changed, 87 insertions(+), 27 deletions(-) create mode 100644 telldus-core/service/Event_unix.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 954652ab..33113056 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -39,6 +39,7 @@ IF (APPLE) #### Mac OS X #### ) LIST(APPEND telldus-service_SRCS main_unix.cpp + Event_unix.cpp EventHandler_unix.cpp ) @@ -67,6 +68,7 @@ ELSE (APPLE) #### Linux #### SET( telldus-service_TARGET telldusd ) LIST(APPEND telldus-service_SRCS main_unix.cpp + Event_unix.cpp EventHandler_unix.cpp ) LIST(APPEND telldus-service_LIBRARIES diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index 75674f39..f93deb7a 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -10,7 +10,7 @@ class ConnectionListener public: ConnectionListener(const std::wstring &name); virtual ~ConnectionListener(void); - void listen(EVENT waitEvent); + void listen(Event *waitEvent); Socket *retrieveClientSocket(); private: diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 1b0c0f0b..dcc7c7fb 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -1,12 +1,24 @@ #ifndef EVENT_H #define EVENT_H -#ifdef _WINDOWS - #include - typedef HANDLE EVENT; -#else - #include - typedef pthread_cond_t EVENT; -#endif +class EventHandler; + +class Event { +public: + Event(EventHandler *handler); + virtual ~Event(); + + bool isSignaled(); + void signal(); + +protected: + void setSignaled(); + +private: + class PrivateData; + PrivateData *d; + +friend class EventHandler; +}; #endif //EVENT_H diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index b12e1e2a..14c0d4f9 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -1,19 +1,18 @@ #ifndef EVENTHANDLER_H #define EVENTHANDLER_H -#include "Event.h" +class Event; class EventHandler { public: EventHandler(); virtual ~EventHandler(void); - void addEvent(EVENT event); - EVENT addEvent(); + Event *addEvent(); + + void signal(Event *event); + void waitForAny(); - EVENT waitForAny(); - - static EVENT createEvent(); private: class PrivateData; PrivateData *d; diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index 480ac778..8ff9689a 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -1,28 +1,46 @@ #include "EventHandler.h" +#include "Event.h" +#include class EventHandler::PrivateData { public: + pthread_cond_t event; + pthread_mutex_t mutex; + bool hasEvent; }; EventHandler::EventHandler() { d = new PrivateData; + pthread_cond_init(&d->event, NULL); + pthread_mutex_init(&d->mutex, NULL); } EventHandler::~EventHandler(void) { + pthread_mutex_destroy(&d->mutex); + pthread_cond_destroy(&d->event); delete d; } -void EventHandler::addEvent(EVENT event) { -} - -EVENT EventHandler::addEvent() { - EVENT event = EventHandler::createEvent(); - this->addEvent(event); +Event *EventHandler::addEvent() { + Event *event = new Event(this); return event; } -EVENT EventHandler::waitForAny() { +void EventHandler::signal(Event *event) { + pthread_mutex_lock(&d->mutex); + event->setSignaled(); + d->hasEvent = true; + pthread_cond_signal(&d->event); + pthread_mutex_unlock(&d->mutex); } -EVENT EventHandler::createEvent() { -} \ No newline at end of file +void EventHandler::waitForAny() { + pthread_mutex_lock(&d->mutex); + while(!d->hasEvent) { + pthread_cond_wait(&d->event, &d->mutex); + } + d->hasEvent = false; + pthread_mutex_unlock(&d->mutex); + + return; +} diff --git a/telldus-core/service/Event_unix.cpp b/telldus-core/service/Event_unix.cpp new file mode 100644 index 00000000..0480223f --- /dev/null +++ b/telldus-core/service/Event_unix.cpp @@ -0,0 +1,29 @@ +#include "Event.h" +#include "EventHandler.h" + +class Event::PrivateData { +public: + bool signaled; + EventHandler *handler; +}; + +Event::Event(EventHandler *handler) { + d = new PrivateData; + d->signaled = false; +} + +Event::~Event(void) { + delete d; +} + +bool Event::isSignaled() { + return d->signaled; +} + +void Event::signal() { + d->handler->signal(this); +} + +void Event::setSignaled() { + d->signaled = true; +} \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 3b39ddd2..1e71e817 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -13,7 +13,7 @@ TelldusMain::~TelldusMain(void) void TelldusMain::start(void){ EventHandler eventHandler; - EVENT clientEvent = eventHandler.addEvent(); + Event *clientEvent = eventHandler.addEvent(); ConnectionListener clientListener(L"TelldusClient"); //TODO: eventlistener @@ -24,15 +24,15 @@ void TelldusMain::start(void){ while(running) { - EVENT signaledEvent = eventHandler.waitForAny(); - if (signaledEvent == clientEvent) { + //Event *signaledEvent = eventHandler.waitForAny(); + /*if (signaledEvent == clientEvent) { //New client connection Socket *s = clientListener.retrieveClientSocket(); std::wstring clientMessage = s->read(); delete s; //TODO: Cleanup clientListener.listen(clientEvent); - } + }*/ #ifdef _WINDOWS Sleep(1000); #else From 476251894eaac9d5633a47315421a3ee048524e3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 06:31:27 +0000 Subject: [PATCH 0196/2215] Added function-stub for ConnectionListener in Linux --- telldus-core/service/CMakeLists.txt | 2 ++ .../service/ConnectionListener_unix.cpp | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 telldus-core/service/ConnectionListener_unix.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 33113056..4d42d81f 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -41,6 +41,7 @@ IF (APPLE) #### Mac OS X #### main_unix.cpp Event_unix.cpp EventHandler_unix.cpp + ConnectionListener_unix.cpp ) ELSEIF (WIN32) #### Windows #### @@ -70,6 +71,7 @@ ELSE (APPLE) #### Linux #### main_unix.cpp Event_unix.cpp EventHandler_unix.cpp + ConnectionListener_unix.cpp ) LIST(APPEND telldus-service_LIBRARIES ${telldus-service_LIBRARIES} diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp new file mode 100644 index 00000000..168cb9b1 --- /dev/null +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -0,0 +1,23 @@ +#include "ConnectionListener.h" + + +class ConnectionListener::PrivateData { +public: +}; + +ConnectionListener::ConnectionListener(const std::wstring &name) +{ + d = new PrivateData; +} + +ConnectionListener::~ConnectionListener(void) { + delete d; +} + +void ConnectionListener::listen(Event *waitEvent){ + +} + +Socket *ConnectionListener::retrieveClientSocket(){ + +} From 0859f868d6037efeb155436a4513b129a801f814 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 06:45:49 +0000 Subject: [PATCH 0197/2215] Compile fixes for Windows. Code not working though. --- telldus-core/common/Socket.h | 4 +-- telldus-core/common/Socket_win.cpp | 2 +- .../service/ConnectionListener_win.cpp | 2 +- telldus-core/service/EventHandler_win.cpp | 25 +++++++++++-------- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index c4e312fa..f377eada 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -5,7 +5,7 @@ #ifdef _WINDOWS #include - typedef HANDLE SOCKET; + typedef HANDLE SOCKET_T; #else typedef unsigned int SOCKET; #endif @@ -13,7 +13,7 @@ class Socket { public: - Socket(SOCKET hPipe); + Socket(SOCKET_T hPipe); virtual ~Socket(void); std::wstring read(); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index cecc3d0d..f395e4db 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -14,7 +14,7 @@ public: HANDLE hPipe; }; -Socket::Socket(HANDLE hPipe) +Socket::Socket(SOCKET_T hPipe) { d = new PrivateData; d->hPipe = hPipe; diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index b800ec22..8b281a3a 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -72,7 +72,7 @@ ConnectionListener::~ConnectionListener(void) delete d; } -void ConnectionListener::listen(EVENT waitEvent){ +void ConnectionListener::listen(Event *waitEvent){ d->oOverlap.hEvent = waitEvent; diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 6a411b23..e5e48c20 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -1,15 +1,17 @@ #include "EventHandler.h" +#include + class EventHandler::PrivateData { public: - EVENT *events; + HANDLE *events; int eventCount; }; EventHandler::EventHandler() { d = new PrivateData; d->eventCount = 0; - d->events = new EVENT[0]; + d->events = new HANDLE[0]; } EventHandler::~EventHandler(void) { @@ -17,30 +19,31 @@ EventHandler::~EventHandler(void) { delete d; } -void EventHandler::addEvent(EVENT event) { - EVENT *newArray = new EVENT[d->eventCount+1]; +Event *EventHandler::addEvent() { +/* EVENT *newArray = new EVENT[d->eventCount+1]; for (int i = 0; i < d->eventCount; ++i) { newArray[i] = d->events[i]; } delete[] d->events; d->events = newArray; d->events[d->eventCount] = event; - ++d->eventCount; + ++d->eventCount;*/ + return 0; } -EVENT EventHandler::waitForAny() { +void EventHandler::waitForAny() { int result = WaitForMultipleObjects(d->eventCount, d->events, FALSE, 3000); if (result == WAIT_TIMEOUT) { - return 0; + return; } int eventIndex = result - WAIT_OBJECT_0; if (eventIndex >= d->eventCount) { - return 0; + return; } - return d->events[eventIndex]; + return; } -EVENT EventHandler::createEvent() { +/*EVENT EventHandler::createEvent() { return CreateEvent(NULL, true, true, NULL); -} \ No newline at end of file +}*/ \ No newline at end of file From aa05e17676b2a86e2d2e8841e04b9d70bb7ea47d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 07:43:17 +0000 Subject: [PATCH 0198/2215] Renamed ClientMessageHandler to ClientCommunicationHandler --- telldus-core/service/CMakeLists.txt | 4 +- .../service/ClientCommunicationHandler.cpp | 37 +++++++++++++++++++ .../service/ClientCommunicationHandler.h | 21 +++++++++++ telldus-core/service/ClientMessageHandler.cpp | 32 ---------------- telldus-core/service/ClientMessageHandler.h | 21 ----------- telldus-core/service/TelldusMain.cpp | 2 + 6 files changed, 62 insertions(+), 55 deletions(-) create mode 100644 telldus-core/service/ClientCommunicationHandler.cpp create mode 100644 telldus-core/service/ClientCommunicationHandler.h delete mode 100644 telldus-core/service/ClientMessageHandler.cpp delete mode 100644 telldus-core/service/ClientMessageHandler.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 4d42d81f..88fb8dba 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -5,13 +5,13 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-service_SRCS TelldusMain.cpp - ClientMessageHandler.cpp + ClientCommunicationHandler.cpp ) SET( telldus-service_HDRS TelldusMain.h ConnectionListener.h Event.h - ClientMessageHandler.h + ClientCommunicationHandler.h EventHandler.h ) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp new file mode 100644 index 00000000..6c7a0aa0 --- /dev/null +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -0,0 +1,37 @@ +#include "ClientCommunicationHandler.h" + +class ClientCommunicationHandler::PrivateData { +public: + std::wstring clientMessage; +}; + +ClientCommunicationHandler::ClientCommunicationHandler(const std::wstring &clientMessage) + :Thread() +{ + d = new PrivateData; + d->clientMessage = clientMessage; + +} + +ClientCommunicationHandler::~ClientCommunicationHandler(void) +{ + delete d; +} + +void ClientCommunicationHandler::run(){ + //run thread + +// std::wstring clientMessage = s->read(); + + if(d->clientMessage == L"tdGetNumberOfDevices"){ + //starta ny tråd (ny klass, ärv från Thread) + //skicka in meddelandet i denna tråd + //kolla där vad det är för meddelande + //do stuff + //TODO + } + +// delete s; //TODO: Cleanup +} + + diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h new file mode 100644 index 00000000..4423cd6e --- /dev/null +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -0,0 +1,21 @@ +#ifndef CLIENTCOMMUNICATIONHANDLER_H +#define CLIENTCOMMUNICATIONHANDLER_H + +#include +#include "Thread.h" + +class ClientCommunicationHandler : public TelldusCore::Thread +{ +public: + ClientCommunicationHandler(const std::wstring &clientMessage); + ~ClientCommunicationHandler(void); + +protected: + void run(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CLIENTCOMMUNICATIONHANDLER_H \ No newline at end of file diff --git a/telldus-core/service/ClientMessageHandler.cpp b/telldus-core/service/ClientMessageHandler.cpp deleted file mode 100644 index 64194d64..00000000 --- a/telldus-core/service/ClientMessageHandler.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "ClientMessageHandler.h" - -class ClientMessageHandler::PrivateData { -public: - std::wstring clientMessage; -}; - -ClientMessageHandler::ClientMessageHandler(const std::wstring &clientMessage) - :Thread() -{ - d = new PrivateData; - d->clientMessage = clientMessage; - -} - -ClientMessageHandler::~ClientMessageHandler(void) -{ - delete d; -} - -void ClientMessageHandler::run(){ - //run thread - if(d->clientMessage == L"tdGetNumberOfDevices"){ - //starta ny tråd (ny klass, ärv från Thread) - //skicka in meddelandet i denna tråd - //kolla där vad det är för meddelande - //do stuff - //TODO - } -} - - diff --git a/telldus-core/service/ClientMessageHandler.h b/telldus-core/service/ClientMessageHandler.h deleted file mode 100644 index aacb8826..00000000 --- a/telldus-core/service/ClientMessageHandler.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef CLIENTMESSAGEHANDLER_H -#define CLIENTMESSAGEHANDLER_H - -#include -#include "Thread.h" - -class ClientMessageHandler : public TelldusCore::Thread -{ -public: - ClientMessageHandler(const std::wstring &clientMessage); - ~ClientMessageHandler(void); - -protected: - void run(); - -private: - class PrivateData; - PrivateData *d; -}; - -#endif //CLIENTMESSAGEHANDLER_H \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 1e71e817..de734d88 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -22,7 +22,9 @@ void TelldusMain::start(void){ //TODO: listen on eventListener while(running) { + Socket *s = clientListener.retrieveClientSocket(); + //Event *signaledEvent = eventHandler.waitForAny(); /*if (signaledEvent == clientEvent) { From 4e59948628af4c4e204abb6b42f235e352cb2603 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 08:05:53 +0000 Subject: [PATCH 0199/2215] Added Event for Windows --- telldus-core/service/CMakeLists.txt | 1 + .../service/ConnectionListener_win.cpp | 2 +- telldus-core/service/Event.h | 8 ++++ telldus-core/service/EventHandler.h | 2 +- telldus-core/service/EventHandler_win.cpp | 43 +++++++++++-------- telldus-core/service/Event_win.cpp | 35 +++++++++++++++ 6 files changed, 70 insertions(+), 21 deletions(-) create mode 100644 telldus-core/service/Event_win.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 88fb8dba..fa2ec19c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -58,6 +58,7 @@ ELSEIF (WIN32) #### Windows #### main_win.cpp TelldusWinService_win.cpp ConnectionListener_win.cpp + Event_win.cpp EventHandler_win.cpp ) LIST(APPEND telldus-service_HDRS diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 8b281a3a..9de555cf 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -74,7 +74,7 @@ ConnectionListener::~ConnectionListener(void) void ConnectionListener::listen(Event *waitEvent){ - d->oOverlap.hEvent = waitEvent; + d->oOverlap.hEvent = waitEvent->retrieveNative(); d->hPipe = CreateNamedPipe( (const wchar_t *)d->pipename.c_str(), // pipe name diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index dcc7c7fb..63a89435 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -3,12 +3,20 @@ class EventHandler; +#ifdef _WINDOWS + #include + typedef HANDLE EVENT_T; +#else + typedef void* EVENT_T; +#endif + class Event { public: Event(EventHandler *handler); virtual ~Event(); bool isSignaled(); + EVENT_T retrieveNative(); void signal(); protected: diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index 14c0d4f9..323ae9d7 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -11,7 +11,7 @@ public: Event *addEvent(); void signal(Event *event); - void waitForAny(); + bool waitForAny(); private: class PrivateData; diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index e5e48c20..1d254549 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -1,49 +1,54 @@ #include "EventHandler.h" +#include "Event.h" #include +#include class EventHandler::PrivateData { public: - HANDLE *events; + HANDLE *eventArray; + std::list eventList; int eventCount; }; EventHandler::EventHandler() { d = new PrivateData; d->eventCount = 0; - d->events = new HANDLE[0]; + d->eventArray = new HANDLE[0]; } EventHandler::~EventHandler(void) { - delete[] d->events; + delete[] d->eventArray; delete d; } Event *EventHandler::addEvent() { -/* EVENT *newArray = new EVENT[d->eventCount+1]; + Event *event = new Event(this); + HANDLE *newArray = new HANDLE[d->eventCount+1]; for (int i = 0; i < d->eventCount; ++i) { - newArray[i] = d->events[i]; + newArray[i] = d->eventArray[i]; } - delete[] d->events; - d->events = newArray; - d->events[d->eventCount] = event; - ++d->eventCount;*/ - return 0; + delete[] d->eventArray; + d->eventArray = newArray; + d->eventArray[d->eventCount] = event->retrieveNative(); + d->eventList.push_back(event); + ++d->eventCount; + return event; } -void EventHandler::waitForAny() { - int result = WaitForMultipleObjects(d->eventCount, d->events, FALSE, 3000); +void EventHandler::signal(Event *event) { +} + +bool EventHandler::waitForAny() { + int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 3000); if (result == WAIT_TIMEOUT) { - return; + return false; } int eventIndex = result - WAIT_OBJECT_0; if (eventIndex >= d->eventCount) { - return; + return false; } - return; + + return true; } - -/*EVENT EventHandler::createEvent() { - return CreateEvent(NULL, true, true, NULL); -}*/ \ No newline at end of file diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp new file mode 100644 index 00000000..add99a98 --- /dev/null +++ b/telldus-core/service/Event_win.cpp @@ -0,0 +1,35 @@ +#include "Event.h" +#include "EventHandler.h" + +class Event::PrivateData { +public: + bool signaled; + EventHandler *handler; + EVENT_T event; +}; + +Event::Event(EventHandler *handler) { + d = new PrivateData; + d->signaled = false; + d->event = CreateEvent(NULL, true, true, NULL); +} + +Event::~Event(void) { + delete d; +} + +bool Event::isSignaled() { + return d->signaled; +} + +void Event::signal() { + //d->handler->signal(this); +} + +void Event::setSignaled() { + d->signaled = true; +} + +EVENT_T Event::retrieveNative() { + return d->event; +} \ No newline at end of file From 4bb47a941392ceb72ca5725538abdfb2ccd0b30f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 08:10:32 +0000 Subject: [PATCH 0200/2215] Acctual, working, non crashing, code. --- telldus-core/service/TelldusMain.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index de734d88..ffa26c45 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -22,19 +22,17 @@ void TelldusMain::start(void){ //TODO: listen on eventListener while(running) { - Socket *s = clientListener.retrieveClientSocket(); - - - - //Event *signaledEvent = eventHandler.waitForAny(); - /*if (signaledEvent == clientEvent) { + if (!eventHandler.waitForAny()) { + continue; + } + //if (signaledEvent == clientEvent) { //New client connection Socket *s = clientListener.retrieveClientSocket(); std::wstring clientMessage = s->read(); delete s; //TODO: Cleanup clientListener.listen(clientEvent); - }*/ + //} #ifdef _WINDOWS Sleep(1000); #else From 817baffe4d7c53ba7fe9fe47c0b284df22fca080 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 09:25:50 +0000 Subject: [PATCH 0201/2215] Renamed MUTEX to MUTEX_T --- telldus-core/common/Thread.cpp | 12 ++++++------ telldus-core/common/Thread.h | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index 2420a593..404ea95b 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -24,7 +24,7 @@ public: pthread_t thread; pthread_cond_t noEvent, noWait; #endif - MUTEX mutex; + MUTEX_T mutex; //Must be locked by the mutex! bool hasEvent; @@ -133,7 +133,7 @@ void Thread::sendEvent(const std::string &strMessage, int intMessage) { #endif } -void Thread::initMutex(MUTEX * m) { +void Thread::initMutex(MUTEX_T * m) { #ifdef _WINDOWS InitializeCriticalSection(m); #else @@ -141,7 +141,7 @@ void Thread::initMutex(MUTEX * m) { #endif } -void Thread::destroyMutex(MUTEX * m) { +void Thread::destroyMutex(MUTEX_T * m) { #ifdef _WINDOWS DeleteCriticalSection(m); #else @@ -149,7 +149,7 @@ void Thread::destroyMutex(MUTEX * m) { #endif } -void Thread::unlockMutex(MUTEX * m) { +void Thread::unlockMutex(MUTEX_T * m) { #ifdef _WINDOWS LeaveCriticalSection(m); #else @@ -157,7 +157,7 @@ void Thread::unlockMutex(MUTEX * m) { #endif } -void Thread::lockMutex(MUTEX * m) { +void Thread::lockMutex(MUTEX_T * m) { #ifdef _WINDOWS EnterCriticalSection(m); #else @@ -166,7 +166,7 @@ void Thread::lockMutex(MUTEX * m) { } -MutexLocker::MutexLocker(MUTEX *m) +MutexLocker::MutexLocker(MUTEX_T *m) :mutex(m) { Thread::lockMutex(mutex); } diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index e557bce4..7f30052f 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -16,10 +16,10 @@ #ifdef _WINDOWS #include - typedef CRITICAL_SECTION MUTEX; + typedef CRITICAL_SECTION MUTEX_T; #else #include - typedef pthread_mutex_t MUTEX; + typedef pthread_mutex_t MUTEX_T; #endif namespace TelldusCore { @@ -33,10 +33,10 @@ namespace TelldusCore { void sendEvent(const std::string &string, int integer = 0); - static void initMutex(MUTEX *m); - static void destroyMutex(MUTEX *m); - static void lockMutex(MUTEX *m); - static void unlockMutex(MUTEX *m); + static void initMutex(MUTEX_T *m); + static void destroyMutex(MUTEX_T *m); + static void lockMutex(MUTEX_T *m); + static void unlockMutex(MUTEX_T *m); protected: virtual void run() = 0; @@ -49,10 +49,10 @@ namespace TelldusCore { class MutexLocker { public: - MutexLocker(MUTEX *m); + MutexLocker(MUTEX_T *m); ~MutexLocker(); private: - MUTEX *mutex; + MUTEX_T *mutex; }; } From 3b1f4d197ee4e4542dc0cd5ac823417fd651e714 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 09:27:39 +0000 Subject: [PATCH 0202/2215] Added locks to Event functions --- telldus-core/service/Event_win.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index add99a98..07426937 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -1,24 +1,29 @@ #include "Event.h" #include "EventHandler.h" +#include "Thread.h" class Event::PrivateData { public: bool signaled; EventHandler *handler; EVENT_T event; + MUTEX_T mutex; }; Event::Event(EventHandler *handler) { d = new PrivateData; d->signaled = false; d->event = CreateEvent(NULL, true, true, NULL); + TelldusCore::Thread::initMutex(&d->mutex); } Event::~Event(void) { + TelldusCore::Thread::destroyMutex(&d->mutex); delete d; } bool Event::isSignaled() { + TelldusCore::MutexLocker locker(&d->mutex); return d->signaled; } @@ -27,9 +32,11 @@ void Event::signal() { } void Event::setSignaled() { + TelldusCore::MutexLocker locker(&d->mutex); d->signaled = true; } EVENT_T Event::retrieveNative() { + TelldusCore::MutexLocker locker(&d->mutex); return d->event; } \ No newline at end of file From b0e324a9f7aea7e289b14e40212c22c2b983e2aa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 09:28:24 +0000 Subject: [PATCH 0203/2215] Implemented Event::signal() on Windows --- telldus-core/service/Event_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index 07426937..1ff0b2f6 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -28,7 +28,7 @@ bool Event::isSignaled() { } void Event::signal() { - //d->handler->signal(this); + SetEvent(d->event); } void Event::setSignaled() { From 747c3a21158aa8cb5808f53b3faf24f6e4c193cd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 09:29:15 +0000 Subject: [PATCH 0204/2215] Store the eventObjects and mark an event as signaled when needed. --- telldus-core/service/EventHandler_win.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 1d254549..c0cb1793 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -7,7 +7,7 @@ class EventHandler::PrivateData { public: HANDLE *eventArray; - std::list eventList; + Event **eventObjectArray; int eventCount; }; @@ -15,28 +15,36 @@ EventHandler::EventHandler() { d = new PrivateData; d->eventCount = 0; d->eventArray = new HANDLE[0]; + d->eventObjectArray = new Event*[0]; } EventHandler::~EventHandler(void) { + delete[] d->eventObjectArray; delete[] d->eventArray; delete d; } Event *EventHandler::addEvent() { Event *event = new Event(this); + HANDLE *newArray = new HANDLE[d->eventCount+1]; + Event **newObjectArray = new Event*[d->eventCount+1]; for (int i = 0; i < d->eventCount; ++i) { newArray[i] = d->eventArray[i]; + newObjectArray[i] = d->eventObjectArray[i]; } delete[] d->eventArray; + delete[] d->eventObjectArray; d->eventArray = newArray; + d->eventObjectArray = newObjectArray; d->eventArray[d->eventCount] = event->retrieveNative(); - d->eventList.push_back(event); + d->eventObjectArray[d->eventCount] = event; ++d->eventCount; return event; } void EventHandler::signal(Event *event) { + event->signal(); } bool EventHandler::waitForAny() { @@ -48,7 +56,7 @@ bool EventHandler::waitForAny() { if (eventIndex >= d->eventCount) { return false; } - + d->eventObjectArray[eventIndex]->setSignaled(); return true; } From 5a3d66f42eb776a4fd225292b5f8eb48c881716f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 09:29:42 +0000 Subject: [PATCH 0205/2215] Use the functions Event::isSignaled() --- telldus-core/service/TelldusMain.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index ffa26c45..faf39c8a 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -25,14 +25,14 @@ void TelldusMain::start(void){ if (!eventHandler.waitForAny()) { continue; } - //if (signaledEvent == clientEvent) { + if (clientEvent->isSignaled()) { //New client connection Socket *s = clientListener.retrieveClientSocket(); std::wstring clientMessage = s->read(); delete s; //TODO: Cleanup clientListener.listen(clientEvent); - //} + } #ifdef _WINDOWS Sleep(1000); #else From 5c00ca822374ea2e582800b36b4fc6071b7eb501 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 09:37:11 +0000 Subject: [PATCH 0206/2215] Clean the event when we are done with it. --- telldus-core/service/Event_win.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index 1ff0b2f6..dc8709db 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -19,6 +19,7 @@ Event::Event(EventHandler *handler) { Event::~Event(void) { TelldusCore::Thread::destroyMutex(&d->mutex); + CloseHandle(d->event); delete d; } From 7eb9754ebd1bcb507d05353aa922c2489dc5c75f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 09:41:11 +0000 Subject: [PATCH 0207/2215] Close handle (hPipe) in destructor --- telldus-core/common/Socket_win.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index f395e4db..c80514fd 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -22,6 +22,9 @@ Socket::Socket(SOCKET_T hPipe) } Socket::~Socket(void){ + if (d->hPipe != INVALID_HANDLE_VALUE) { + CloseHandle(d->hPipe); + } delete d; } From 5514c8931b46eb9b9f8b94d45eec3354b984eb9c Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 09:42:15 +0000 Subject: [PATCH 0208/2215] CommunicationHandler uses socket instead of string message --- telldus-core/service/ClientCommunicationHandler.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 4423cd6e..a43e872c 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -3,13 +3,17 @@ #include #include "Thread.h" +#include "Socket.h" +#include "Event.h" class ClientCommunicationHandler : public TelldusCore::Thread { public: - ClientCommunicationHandler(const std::wstring &clientMessage); + ClientCommunicationHandler(Socket *clientSocket, Event *event); ~ClientCommunicationHandler(void); + bool isDone(); + protected: void run(); From 89112125ac2463567abee903c7fdc2584ea82c42 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 09:43:37 +0000 Subject: [PATCH 0209/2215] Socket instead of message. Better thread cleanup. --- .../service/ClientCommunicationHandler.cpp | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 6c7a0aa0..529c0174 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -2,36 +2,48 @@ class ClientCommunicationHandler::PrivateData { public: - std::wstring clientMessage; + Socket *clientSocket; + Event *event; + bool done; }; -ClientCommunicationHandler::ClientCommunicationHandler(const std::wstring &clientMessage) +ClientCommunicationHandler::ClientCommunicationHandler(Socket *clientSocket, Event *event) :Thread() { d = new PrivateData; - d->clientMessage = clientMessage; + d->clientSocket = clientSocket; + d->event = event; + d->done = false; } ClientCommunicationHandler::~ClientCommunicationHandler(void) { + wait(); + delete(d->clientSocket); delete d; } void ClientCommunicationHandler::run(){ //run thread -// std::wstring clientMessage = s->read(); + + std::wstring clientMessage = d->clientSocket->read(); - if(d->clientMessage == L"tdGetNumberOfDevices"){ + if(clientMessage == L"tdGetNumberOfDevices"){ //starta ny tråd (ny klass, ärv från Thread) //skicka in meddelandet i denna tråd //kolla där vad det är för meddelande //do stuff //TODO } + -// delete s; //TODO: Cleanup + //We are done, signal for removal + d->done = true; + d->event->signal(); } - +bool ClientCommunicationHandler::isDone(){ + return d->done; +} From 0586fe6d2b6dc9fdc724cb9512bc85a364a94321 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 09:45:25 +0000 Subject: [PATCH 0210/2215] Now using ClientCommunicationHandler, including thread management. --- telldus-core/service/TelldusMain.cpp | 29 +++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index faf39c8a..8edf325b 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -1,6 +1,9 @@ #include "TelldusMain.h" #include "ConnectionListener.h" #include "EventHandler.h" +#include "ClientCommunicationHandler.h" + +#include TelldusMain::TelldusMain(void) { @@ -21,18 +24,38 @@ void TelldusMain::start(void){ clientListener.listen(clientEvent); //TODO: listen on eventListener + std::list clientCommunicationHandlerList; + while(running) { if (!eventHandler.waitForAny()) { continue; } if (clientEvent->isSignaled()) { //New client connection + + Socket *s = clientListener.retrieveClientSocket(); - std::wstring clientMessage = s->read(); - - delete s; //TODO: Cleanup + if(s){ + Event *handlerEvent = eventHandler.addEvent(); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(s, handlerEvent); + clientCommunication->start(); + clientCommunicationHandlerList.push_back(clientCommunication); + } + clientListener.listen(clientEvent); } + + + for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ + if ((*it)->isDone()){ + delete *it; + it = clientCommunicationHandlerList.erase(it); + } + else{ + ++it; + } + } + #ifdef _WINDOWS Sleep(1000); #else From 549568df4f2f6c6deb811b197f3ba1619793a8b6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 10:08:31 +0000 Subject: [PATCH 0211/2215] Unicode support in tdGetNumberOfDevices-event. --- telldus-core/client/telldus-core.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index ae12b92a..d955df5e 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -220,8 +220,8 @@ int WINAPI tdGetNumberOfDevices(void){ DWORD bytesWritten = 0; oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - std::string msg = "tdGetNumberOfDevices"; - WriteFile(hPipe, msg.data(), (DWORD)msg.length(), &bytesWritten, &oOverlap); + std::wstring msg = L"tdGetNumberOfDevices"; + WriteFile(hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); /*result = WaitForSingleObject(oOverlap.hEvent, 10000); if (result == WAIT_TIMEOUT) { From 801d394cd9d3af967b092c681bc598cae3910b61 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 10:20:08 +0000 Subject: [PATCH 0212/2215] Added function Event::clearSignal() --- telldus-core/service/Event.h | 1 + telldus-core/service/Event_win.cpp | 5 +++++ telldus-core/service/TelldusMain.cpp | 1 + 3 files changed, 7 insertions(+) diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 63a89435..3d8fd1c2 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -15,6 +15,7 @@ public: Event(EventHandler *handler); virtual ~Event(); + void clearSignal(); bool isSignaled(); EVENT_T retrieveNative(); void signal(); diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index dc8709db..817a493e 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -23,6 +23,11 @@ Event::~Event(void) { delete d; } +void Event::clearSignal() { + TelldusCore::MutexLocker locker(&d->mutex); + d->signaled = false; +} + bool Event::isSignaled() { TelldusCore::MutexLocker locker(&d->mutex); return d->signaled; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 8edf325b..2fc5ef47 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -31,6 +31,7 @@ void TelldusMain::start(void){ continue; } if (clientEvent->isSignaled()) { + clientEvent->clearSignal(); //New client connection From 47b0e19de094398c1cab689dd68c8959be973782 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 10:36:37 +0000 Subject: [PATCH 0213/2215] Added Socket to namespace TelldusCore. --- telldus-core/common/Socket.h | 25 ++++++++--------- telldus-core/common/Socket_win.cpp | 2 +- .../service/ClientCommunicationHandler.cpp | 27 ++++++++++++------- .../service/ClientCommunicationHandler.h | 3 ++- telldus-core/service/ConnectionListener.h | 2 +- .../service/ConnectionListener_win.cpp | 4 +-- telldus-core/service/TelldusMain.cpp | 2 +- 7 files changed, 38 insertions(+), 27 deletions(-) diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index f377eada..6ac8e354 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -10,17 +10,18 @@ typedef unsigned int SOCKET; #endif -class Socket -{ -public: - Socket(SOCKET_T hPipe); - virtual ~Socket(void); - - std::wstring read(); - -private: - class PrivateData; - PrivateData *d; -}; +namespace TelldusCore { + class Socket + { + public: + Socket(SOCKET_T hPipe); + virtual ~Socket(void); + std::wstring read(); + + private: + class PrivateData; + PrivateData *d; + }; +} #endif //SOCKET_H diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index c80514fd..d39c2e1e 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -7,7 +7,7 @@ #define BUFSIZE 512 -//TODO: using namespace TelldusCore; +using namespace TelldusCore; class Socket::PrivateData { public: diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 529c0174..2f865280 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -2,12 +2,12 @@ class ClientCommunicationHandler::PrivateData { public: - Socket *clientSocket; + TelldusCore::Socket *clientSocket; Event *event; bool done; }; -ClientCommunicationHandler::ClientCommunicationHandler(Socket *clientSocket, Event *event) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event) :Thread() { d = new PrivateData; @@ -30,13 +30,8 @@ void ClientCommunicationHandler::run(){ std::wstring clientMessage = d->clientSocket->read(); - if(clientMessage == L"tdGetNumberOfDevices"){ - //starta ny tråd (ny klass, ärv från Thread) - //skicka in meddelandet i denna tråd - //kolla där vad det är för meddelande - //do stuff - //TODO - } + //parseMessage(clientMessage); + //We are done, signal for removal @@ -47,3 +42,17 @@ void ClientCommunicationHandler::run(){ bool ClientCommunicationHandler::isDone(){ return d->done; } + +/* +std::wstring parseMessage(std::wstring &clientMessage){ + + if(clientMessage == L"tdGetNumberOfDevices"){ + //starta ny tråd (ny klass, ärv från Thread) + //skicka in meddelandet i denna tråd + //kolla där vad det är för meddelande + //do stuff + //TODO + } + +} +*/ \ No newline at end of file diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index a43e872c..724ee789 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -9,7 +9,7 @@ class ClientCommunicationHandler : public TelldusCore::Thread { public: - ClientCommunicationHandler(Socket *clientSocket, Event *event); + ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event); ~ClientCommunicationHandler(void); bool isDone(); @@ -20,6 +20,7 @@ protected: private: class PrivateData; PrivateData *d; + //std::wstring parseMessage(std::wstring); }; #endif //CLIENTCOMMUNICATIONHANDLER_H \ No newline at end of file diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index f93deb7a..adc9fc5d 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -11,7 +11,7 @@ public: ConnectionListener(const std::wstring &name); virtual ~ConnectionListener(void); void listen(Event *waitEvent); - Socket *retrieveClientSocket(); + TelldusCore::Socket *retrieveClientSocket(); private: class PrivateData; diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 9de555cf..7dafc25a 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -97,7 +97,7 @@ void ConnectionListener::listen(Event *waitEvent){ ConnectNamedPipe(d->hPipe, &d->oOverlap); } -Socket *ConnectionListener::retrieveClientSocket(){ +TelldusCore::Socket *ConnectionListener::retrieveClientSocket(){ DWORD cbBytesRead; bool connected = GetOverlappedResult(d->hPipe, &d->oOverlap, &cbBytesRead, false); @@ -105,7 +105,7 @@ Socket *ConnectionListener::retrieveClientSocket(){ CloseHandle(d->hPipe); return 0; } - Socket *s = new Socket(d->hPipe); + TelldusCore::Socket *s = new TelldusCore::Socket(d->hPipe); return s; } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 2fc5ef47..87a37a45 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -35,7 +35,7 @@ void TelldusMain::start(void){ //New client connection - Socket *s = clientListener.retrieveClientSocket(); + TelldusCore::Socket *s = clientListener.retrieveClientSocket(); if(s){ Event *handlerEvent = eventHandler.addEvent(); ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(s, handlerEvent); From 1ae53d50104598f256478edd25346a8fac41f218 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 10:40:25 +0000 Subject: [PATCH 0214/2215] Code cleanup --- telldus-core/common/Socket_win.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index d39c2e1e..32277c6e 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -1,5 +1,4 @@ #include "Socket.h" -#include "Event.h" #include #include From 8ef882a59f382dc38470e5c9242db8bfd54f6abb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 10:54:30 +0000 Subject: [PATCH 0215/2215] Removed the 3rdparty-lib. Not used anymore --- .../qtservice-2.6-opensource/INSTALL.TXT | 254 ---- .../LGPL_EXCEPTION.txt | 10 - .../qtservice-2.6-opensource/LICENSE.GPL3 | 674 ---------- .../qtservice-2.6-opensource/LICENSE.LGPL | 504 -------- .../qtservice-2.6-opensource/README.TXT | 7 - .../buildlib/buildlib.pro | 13 - .../qtservice-2.6-opensource/common.pri | 6 - .../qtservice-2.6-opensource/configure | 112 -- .../doc/html/classic.css | 131 -- .../doc/html/images/qt-logo.png | Bin 4075 -> 0 bytes .../doc/html/index.html | 50 - .../html/qtservice-example-controller.html | 195 --- .../html/qtservice-example-interactive.html | 161 --- .../doc/html/qtservice-example-server.html | 159 --- .../doc/html/qtservice-members.html | 52 - .../doc/html/qtservice.dcf | 76 -- .../doc/html/qtservice.html | 92 -- .../doc/html/qtservice.index | 111 -- .../doc/html/qtservice.qch | Bin 57344 -> 0 bytes .../doc/html/qtservice.qhp | 90 -- .../doc/html/qtservicebase-members.html | 51 - .../doc/html/qtservicebase.html | 199 --- .../doc/html/qtservicecontroller-members.html | 46 - .../doc/html/qtservicecontroller.html | 155 --- .../doc/images/qt-logo.png | Bin 4075 -> 0 bytes .../qtservice-2.6-opensource/doc/index.qdoc | 46 - .../examples/controller/controller.pro | 7 - .../examples/controller/controller.qdoc | 81 -- .../examples/controller/main.cpp | 169 --- .../examples/examples.pro | 4 - .../examples/interactive/interactive.pro | 6 - .../examples/interactive/interactive.qdoc | 76 -- .../examples/interactive/main.cpp | 133 -- .../examples/server/main.cpp | 190 --- .../examples/server/server.pro | 8 - .../examples/server/server.qdoc | 87 -- .../qtservice-2.6-opensource/qtservice.pro | 5 - .../src/QtServiceBase | 1 - .../src/QtServiceController | 1 - .../src/qtservice.cpp | 1117 ----------------- .../qtservice-2.6-opensource/src/qtservice.h | 197 --- .../src/qtservice.pri | 21 - .../src/qtservice_p.h | 93 -- .../src/qtservice_unix.cpp | 480 ------- .../src/qtservice_win.cpp | 903 ------------- .../src/qtunixserversocket.cpp | 98 -- .../src/qtunixserversocket.h | 67 - .../src/qtunixsocket.cpp | 84 -- .../src/qtunixsocket.h | 61 - telldus-core/3rdparty/qtservice.cmake | 39 - 50 files changed, 7122 deletions(-) delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/common.pri delete mode 100755 telldus-core/3rdparty/qtservice-2.6-opensource/configure delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/images/qt-logo.png delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp delete mode 100644 telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h delete mode 100644 telldus-core/3rdparty/qtservice.cmake diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT b/telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT deleted file mode 100644 index 8d41864d..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/INSTALL.TXT +++ /dev/null @@ -1,254 +0,0 @@ -INSTALLATION INSTRUCTIONS - -These instructions refer to the package you are installing as -some-package.tar.gz or some-package.zip. The .zip file is intended for use -on Windows. - -The directory you choose for the installation will be referred to as -your-install-dir. - -Note to Qt Visual Studio Integration users: In the instructions below, -instead of building from command line with nmake, you can use the menu -command 'Qt->Open Solution from .pro file' on the .pro files in the -example and plugin directories, and then build from within Visual -Studio. - -Unpacking and installation --------------------------- - -1. Unpacking the archive (if you have not done so already). - - On Unix and Mac OS X (in a terminal window): - - cd your-install-dir - gunzip some-package.tar.gz - tar xvf some-package.tar - - This creates the subdirectory some-package containing the files. - - On Windows: - - Unpack the .zip archive by right-clicking it in explorer and - choosing "Extract All...". If your version of Windows does not - have zip support, you can use the infozip tools available - from www.info-zip.org. - - If you are using the infozip tools (in a command prompt window): - cd your-install-dir - unzip some-package.zip - -2. Configuring the package. - - The configure script is called "configure" on unix/mac and - "configure.bat" on Windows. It should be run from a command line - after cd'ing to the package directory. - - You can choose whether you want to use the component by including - its source code directly into your project, or build the component - as a dynamic shared library (DLL) that is loaded into the - application at run-time. The latter may be preferable for - technical or licensing (LGPL) reasons. If you want to build a DLL, - run the configure script with the argument "-library". Also see - the note about usage below. - - (Components that are Qt plugins, e.g. styles and image formats, - are by default built as a plugin DLL.) - - The configure script will prompt you in some cases for further - information. Answer these questions and carefully read the license text - before accepting the license conditions. The package cannot be used if - you do not accept the license conditions. - -3. Building the component and examples (when required). - - If a DLL is to be built, or if you would like to build the - examples, next give the commands - - qmake - make [or nmake if your are using Microsoft Visual C++] - - The example program(s) can be found in the directory called - "examples" or "example". - - Components that are Qt plugins, e.g. styles and image formats, are - ready to be used as soon as they are built, so the rest of this - installation instruction can be skipped. - -4. Building the Qt Designer plugin (optional). - - Some of the widget components are provided with plugins for Qt - Designer. To build and install the plugin, cd into the - some-package/plugin directory and give the commands - - qmake - make [or nmake if your are using Microsoft Visual C++] - - Restart Qt Designer to make it load the new widget plugin. - - Note: If you are using the built-in Qt Designer from the Qt Visual - Studio Integration, you will need to manually copy the plugin DLL - file, i.e. copy - %QTDIR%\plugins\designer\some-component.dll - to the Qt Visual Studio Integration plugin path, typically: - C:\Program Files\Trolltech\Qt VS Integration\plugins - - Note: If you for some reason are using a Qt Designer that is built - in debug mode, you will need to build the plugin in debug mode - also. Edit the file plugin.pro in the plugin directory, changing - 'release' to 'debug' in the CONFIG line, before running qmake. - - - -Solutions components are intended to be used directly from the package -directory during development, so there is no 'make install' procedure. - - -Using a component in your project ---------------------------------- - -To use this component in your project, add the following line to the -project's .pro file (or do the equivalent in your IDE): - - include(your-install-dir/some-package/src/some-package.pri) - -This adds the package's sources and headers to the SOURCES and HEADERS -project variables respectively (or, if the component has been -configured as a DLL, it adds that library to the LIBS variable), and -updates INCLUDEPATH to contain the package's src -directory. Additionally, the .pri file may include some dependencies -needed by the package. - -To include a header file from the package in your sources, you can now -simply use: - - #include - -or alternatively, in pre-Qt 4 style: - - #include - -Refer to the documentation to see the classes and headers this -components provides. - - - -Install documentation (optional) --------------------------------- - -The HTML documentation for the package's classes is located in the -your-install-dir/some-package/doc/html/index.html. You can open this -file and read the documentation with any web browser. - -To install the documentation into Qt Assistant (for Qt version 4.4 and -later): - -1. In Assistant, open the Edit->Preferences dialog and choose the - Documentation tab. Click the Add... button and select the file - your-install-dir/some-package/doc/html/some-package.qch - -For Qt versions prior to 4.4, do instead the following: - -1. The directory your-install-dir/some-package/doc/html contains a - file called some-package.dcf. Execute the following commands in a - shell, command prompt or terminal window: - - cd your-install-dir/some-package/doc/html/ - assistant -addContentFile some-package.dcf - -The next time you start Qt Assistant, you can access the package's -documentation. - - -Removing the documentation from assistant ------------------------------------------ - -If you have installed the documentation into Qt Assistant, and want to uninstall it, do as follows, for Qt version 4.4 and later: - -1. In Assistant, open the Edit->Preferences dialog and choose the - Documentation tab. In the list of Registered Documentation, select - the item com.trolltech.qtsolutions.some-package_version, and click - the Remove button. - -For Qt versions prior to 4.4, do instead the following: - -1. The directory your-install-dir/some-package/doc/html contains a - file called some-package.dcf. Execute the following commands in a - shell, command prompt or terminal window: - - cd your-install-dir/some-package/doc/html/ - assistant -removeContentFile some-package.dcf - - - -Using the component as a DLL ----------------------------- - -1. Normal components - - The shared library (DLL) is built and placed in the - some-package/lib directory. It is intended to be used directly - from there during development. When appropriate, both debug and - release versions are built, since the run-time linker will in some - cases refuse to load a debug-built DLL into a release-built - application or vice versa. - - The following steps are taken by default to help the dynamic - linker to locate the DLL at run-time (during development): - - Unix: The some-package.pri file will add linker instructions to - add the some-package/lib directory to the rpath of the - executable. (When distributing, or if your system does not support - rpath, you can copy the shared library to another place that is - searched by the dynamic linker, e.g. the "lib" directory of your - Qt installation.) - - Mac: The full path to the library is hardcoded into the library - itself, from where it is copied into the executable at link time, - and ready by the dynamic linker at run-time. (When distributing, - you will want to edit these hardcoded paths in the same way as for - the Qt DLLs. Refer to the document "Deploying an Application on - Mac OS X" in the Qt Reference Documentation.) - - Windows: the .dll file(s) are copied into the "bin" directory of - your Qt installation. The Qt installation will already have set up - that directory to be searched by the dynamic linker. - - -2. Plugins - - For Qt Solutions plugins (e.g. image formats), both debug and - release versions of the plugin are built by default when - appropriate, since in some cases the release Qt library will not - load a debug plugin, and vice versa. The plugins are automatically - copied into the plugins directory of your Qt installation when - built, so no further setup is required. - - Plugins may also be built statically, i.e. as a library that will be - linked into your application executable, and so will not need to - be redistributed as a separate plugin DLL to end users. Static - building is required if Qt itself is built statically. To do it, - just add "static" to the CONFIG variable in the plugin/plugin.pro - file before building. Refer to the "Static Plugins" section in the - chapter "How to Create Qt Plugins" for explanation of how to use a - static plugin in your application. The source code of the example - program(s) will also typically contain the relevant instructions - as comments. - - - -Uninstalling ------------- - - The following command will remove any fils that have been - automatically placed outside the package directory itself during - installation and building - - make distclean [or nmake if your are using Microsoft Visual C++] - - If Qt Assistant documentation or Qt Designer plugins have been - installed, they can be uninstalled manually, ref. above. - - -Enjoy! :) - -- The Qt Solutions Team. diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt b/telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt deleted file mode 100644 index 0b56ff1e..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/LGPL_EXCEPTION.txt +++ /dev/null @@ -1,10 +0,0 @@ -Nokia Qt LGPL Exception version 1.0 - -As a special exception to the GNU Lesser General Public License -version 2.1, the object code form of a "work that uses the Library" -may incorporate material from a header file that is part of the -Library. You may distribute such object code under terms of your -choice, provided that the incorporated material (i) does not exceed -more than 5% of the total size of the Library; and (ii) is limited to -numerical parameters, data structure layouts, accessors, macros, -inline functions and templates. diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 b/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 deleted file mode 100644 index 94a9ed02..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.GPL3 +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL b/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL deleted file mode 100644 index 5ab7695a..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/LICENSE.LGPL +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT b/telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT deleted file mode 100644 index d8a55f89..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/README.TXT +++ /dev/null @@ -1,7 +0,0 @@ -Service v2.6 - -The QtService component is useful for developing Windows services -and Unix daemons. - - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro deleted file mode 100644 index 1e51cc1d..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/buildlib/buildlib.pro +++ /dev/null @@ -1,13 +0,0 @@ -TEMPLATE=lib -CONFIG += qt dll qtservice-buildlib -mac:CONFIG += absolute_library_soname -win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all -include(../src/qtservice.pri) -TARGET = $$QTSERVICE_LIBNAME -DESTDIR = $$QTSERVICE_LIBDIR -win32 { - DLLDESTDIR = $$[QT_INSTALL_BINS] - QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTSERVICE_LIBNAME}.dll -} -target.path = $$DESTDIR -INSTALLS += target diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/common.pri b/telldus-core/3rdparty/qtservice-2.6-opensource/common.pri deleted file mode 100644 index b9456796..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/common.pri +++ /dev/null @@ -1,6 +0,0 @@ -infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtservice-uselib -TEMPLATE += fakelib -QTSERVICE_LIBNAME = $$qtLibraryTarget(QtSolutions_Service-2.6) -TEMPLATE -= fakelib -QTSERVICE_LIBDIR = $$PWD/lib -unix:qtservice-uselib:!qtservice-buildlib:QMAKE_RPATHDIR += $$QTSERVICE_LIBDIR diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/configure b/telldus-core/3rdparty/qtservice-2.6-opensource/configure deleted file mode 100755 index 674d286a..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/configure +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/sh - -if [ "x$1" != "x" -a "x$1" != "x-library" ]; then - echo "Usage: $0 [-library]" - echo - echo "-library: Build the component as a dynamic library (DLL). Default is to" - echo " include the component source code directly in the application." - echo " A DLL may be preferable for technical or licensing (LGPL) reasons." - echo - exit 0 -fi - - -# only ask to accept the license text once -if [ ! -f .licenseAccepted ]; then -# determine if opensource or commercial package - if [ -f LICENSE.LGPL ]; then - # opensource edition - while true; do - echo - echo "You are licensed to use this software under the terms of" - echo "the GNU General Public License (GPL) version 3, or" - echo "the GNU Lesser General Public License (LGPL) version 2.1" - echo "with certain additional extra rights as specified in the" - echo "Nokia Qt LGPL Exception version 1.0." - echo - echo "Type 'G' to view the GNU General Public License (GPL) version 3." - echo "Type 'L' to view the GNU Lesser General Public License (LGPL) version 2.1." - echo "Type 'E' to view the Nokia Qt LGPL Exception version 1.0." - echo "Type 'yes' to accept this license offer." - echo "Type 'no' to decline this license offer." - echo - echo "Do you accept the terms of this license? " - read answer - echo - - if [ "x$answer" = "xno" ]; then - echo "You are not licensed to use this software." - echo - exit 1 - elif [ "x$answer" = "xyes" ]; then - echo license accepted > .licenseAccepted - break - elif [ "x$answer" = "xe" -o "x$answer" = "xE" ]; then - more LGPL_EXCEPTION.txt - elif [ "x$answer" = "xl" -o "x$answer" = "xL" ]; then - more LICENSE.LGPL - elif [ "x$answer" = "xg" -o "x$answer" = "xG" ]; then - more LICENSE.GPL3 - fi - done - else - while true; do - echo - echo "Please choose your region." - echo - echo "Type 1 for North or South America." - echo "Type 2 for anywhere outside North and South America." - echo - echo "Select: " - read region - if [ "x$region" = "x1" ]; then - licenseFile=LICENSE.US - break; - elif [ "x$region" = "x2" ]; then - licenseFile=LICENSE.NO - break; - fi - done - while true; do - echo - echo "License Agreement" - echo - echo "Type '?' to view the Qt Solutions Commercial License." - echo "Type 'yes' to accept this license offer." - echo "Type 'no' to decline this license offer." - echo - echo "Do you accept the terms of this license? " - read answer - echo - - if [ "x$answer" = "xno" ]; then - echo "You are not licensed to use this software." - echo - exit 1 - elif [ "x$answer" = "xyes" ]; then - echo license accepted > .licenseAccepted - cp "$licenseFile" LICENSE - rm LICENSE.US - rm LICENSE.NO - break - elif [ "x$answer" = "x?" ]; then - more "$licenseFile" - fi - done - fi -fi - -rm -f config.pri -if [ "x$1" = "x-library" ]; then - echo "Configuring to build this component as a dynamic library." - echo "SOLUTIONS_LIBRARY = yes" > config.pri -fi - -echo -echo "This component is now configured." -echo -echo "To build the component library (if requested) and example(s)," -echo "run qmake and your make command." -echo -echo "To remove or reconfigure, run make distclean." -echo diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css deleted file mode 100644 index 0ff9e7db..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/classic.css +++ /dev/null @@ -1,131 +0,0 @@ -h3.fn,span.fn -{ - margin-left: 1cm; - text-indent: -1cm; -} - -a:link -{ - color: #004faf; - text-decoration: none -} - -a:visited -{ - color: #672967; - text-decoration: none -} - -a.obsolete -{ - color: #661100; - text-decoration: none -} - -a.compat -{ - color: #661100; - text-decoration: none -} - -a.obsolete:visited -{ - color: #995500; - text-decoration: none -} - -a.compat:visited -{ - color: #995500; - text-decoration: none -} - -td.postheader -{ - font-family: sans-serif -} - -tr.address -{ - font-family: sans-serif -} - -body -{ - background: #ffffff; - color: black -} - -table tr.odd { - background: #f0f0f0; - color: black; -} - -table tr.even { - background: #e4e4e4; - color: black; -} - -table.annotated th { - padding: 3px; - text-align: left -} - -table.annotated td { - padding: 3px; -} - -table tr pre -{ - padding-top: none; - padding-bottom: none; - padding-left: none; - padding-right: none; - border: none; - background: none -} - -tr.qt-style -{ - background: #a2c511; - color: black -} - -body pre -{ - padding: 0.2em; - border: #e7e7e7 1px solid; - background: #f1f1f1; - color: black -} - -span.preprocessor, span.preprocessor a -{ - color: darkblue; -} - -span.comment -{ - color: darkred; - font-style: italic -} - -span.string,span.char -{ - color: darkgreen; -} - -.title -{ - text-align: center -} - -.subtitle -{ - font-size: 0.8em -} - -.small-subtitle -{ - font-size: 0.65em -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/images/qt-logo.png b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/images/qt-logo.png deleted file mode 100644 index 794162f5af58e7b38beebf472842fc9703ede19b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4075 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 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html deleted file mode 100644 index d7d27464..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - Service - - - - - - - -
  Home

Service
-

- -

Description

-

The QtService component is useful for developing Windows services and Unix daemons.

-

The project provides a QtService template class that can be used to implement service applications, and a QtServiceController class to control a service.

-

On Windows systems the implementation uses the Service Control Manager.

-

On Unix systems services are implemented as daemons.

- -

Classes

- - -

Examples

- - -

Tested platforms

-
    -
  • Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005
  • -
  • Qt 4.4, 4.5 / Linux / gcc
  • -
  • Qt 4.4, 4.5 / MacOS X 10.5 / gcc
  • -
-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html deleted file mode 100644 index 8462fe78..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-controller.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - A simple Service Controller - - - - - - - -
  Home

A simple Service Controller
-

-

It is a very simple implementation of universal command-line controller. This controller can install and control any service written using QtService component. It demonstrates how to use QtServiceController class. On Windows, this is an alternative to using the "Services" Administrative Tool or the built-in sc.exe command-line tool to control services.

-

A note about services on Windows Vista: Installing/uninstalling and starting/stopping services requires security privileges. The simplest way to achieve this is to set the "Run as Administrator" property on the executable (right-click the executable file, select Properties, and choose the Compatibilty tab in the Properties dialog). This applies even if you are logged in as Administrator. Also, the command-line shell should be started with "Run as Administrator". Note that the service itself does not need special privileges to run. Only if you want the service to be able to install itself (the -i option) or similar, then the service will need to be run as Administrator. Otherwise, the recommended procedure is to use a controller such as this example and/or the "Services" Administrative Tool to manage the service.

-

A usability hint: in some circumstances, e.g. when running this example on Windows Vista with the "Run as Administrator" property set, output will be sent to a shell window which will close immediately upon termination, not leaving the user enough time to read the output. In such cases, append the -w(ait) argument, which will make the controller wait for a keypress before terminating.

-

Here is the complete source code:

-
 /****************************************************************************
- **
- ** This file is part of a Qt Solutions component.
- **
- ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
- **
- ** Contact:  Qt Software Information (qt-info@nokia.com)
- **
- ** Commercial Usage
- ** Licensees holding valid Qt Commercial licenses may use this file in
- ** accordance with the Qt Solutions Commercial License Agreement provided
- ** with the Software or, alternatively, in accordance with the terms
- ** contained in a written agreement between you and Nokia.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain
- ** additional rights. These rights are described in the Nokia Qt LGPL
- ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
- ** package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- ** Please note Third Party Software included with Qt Solutions may impose
- ** additional restrictions and it is the user's responsibility to ensure
- ** that they have met the licensing requirements of the GPL, LGPL, or Qt
- ** Solutions Commercial license and the relevant license of the Third
- ** Party Software they are using.
- **
- ** If you are unsure which license is appropriate for your use, please
- ** contact the sales department at qt-sales@nokia.com.
- **
- ****************************************************************************/
-
- #include <QtCore/QStringList>
- #include <QtCore/QDir>
- #include <QtCore/QSettings>
- #include "qtservice.h"
-
- int processArgs(int argc, char **argv)
- {
-     if (argc > 2) {
-         QString arg1(argv[1]);
-         if (arg1 == QLatin1String("-i") ||
-             arg1 == QLatin1String("-install")) {
-             if (argc > 2) {
-                 QString account;
-                 QString password;
-                 QString path(argv[2]);
-                 if (argc > 3)
-                     account = argv[3];
-                 if (argc > 4)
-                     password = argv[4];
-                 printf("The service %s installed.\n",
-                        (QtServiceController::install(path, account, password) ? "was" : "was not"));
-                 return 0;
-             }
-         } else {
-             QString serviceName(argv[1]);
-             QtServiceController controller(serviceName);
-             QString option(argv[2]);
-             if (option == QLatin1String("-u") ||
-                 option == QLatin1String("-uninstall")) {
-                 printf("The service \"%s\" %s uninstalled.\n",
-                             controller.serviceName().toLatin1().constData(),
-                             (controller.uninstall() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-s") ||
-                        option == QLatin1String("-start")) {
-                 QStringList args;
-                 for (int i = 3; i < argc; ++i)
-                     args.append(QString::fromLocal8Bit(argv[i]));
-                 printf("The service \"%s\" %s started.\n",
-                        controller.serviceName().toLatin1().constData(),
-                             (controller.start(args) ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-t") ||
-                        option == QLatin1String("-terminate")) {
-                 printf("The service \"%s\" %s stopped.\n",
-                        controller.serviceName().toLatin1().constData(),
-                        (controller.stop() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-p") ||
-                     option == QLatin1String("-pause")) {
-                 printf("The service \"%s\" %s paused.\n",
-                        controller.serviceName().toLatin1().constData(),
-                        (controller.pause() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-r") ||
-                        option == QLatin1String("-resume")) {
-                 printf("The service \"%s\" %s resumed.\n",
-                        controller.serviceName().toLatin1().constData(),
-                        (controller.resume() ? "was" : "was not"));
-                 return 0;
-             } else if (option == QLatin1String("-c") ||
-                        option == QLatin1String("-command")) {
-                 if (argc > 3) {
-                     QString codestr(argv[3]);
-                     int code = codestr.toInt();
-                     printf("The command %s sent to the service \"%s\".\n",
-                            (controller.sendCommand(code) ? "was" : "was not"),
-                            controller.serviceName().toLatin1().constData());
-                     return 0;
-                 }
-             } else if (option == QLatin1String("-v") ||
-                     option == QLatin1String("-version")) {
-                 bool installed = controller.isInstalled();
-                 printf("The service\n"
-                         "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData());
-                 printf("is %s", (installed ? "installed" : "not installed"));
-                 printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running"));
-                 if (installed) {
-                     printf("path: %s\n", controller.serviceFilePath().toLatin1().data());
-                     printf("description: %s\n", controller.serviceDescription().toLatin1().data());
-                     printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual");
-                 }
-                 return 0;
-             }
-         }
-     }
-     printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n"
-             "\t-i(nstall) PATH\t: Install the service\n"
-             "\t-v(ersion)\t: Print status of the service\n"
-             "\t-u(ninstall)\t: Uninstall the service\n"
-             "\t-s(tart)\t: Start the service\n"
-             "\t-t(erminate)\t: Stop the service\n"
-             "\t-p(ause)\t: Pause the service\n"
-             "\t-r(esume)\t: Resume the service\n"
-             "\t-c(ommand) CODE\t: Send a command to the service\n"
-             "\t-h(elp)\t\t: Print this help info\n"
-             "\t-w(ait)\t\t: Wait for keypress when done\n");
-     return 0;
- }
-
- int main(int argc, char **argv)
- {
- #if !defined(Q_WS_WIN)
-     // QtService stores service settings in SystemScope, which normally require root privileges.
-     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
-     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
-     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
- #endif
-
-     int result = processArgs(argc, argv);
-
-     if (QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-w") ||
-         QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-wait")) {
-         printf("\nPress Enter to continue...");
-         QFile input;
-         input.open(stdin, QIODevice::ReadOnly);
-         input.readLine();
-         printf("\n");
-     }
-
-     return result;
- }
-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html deleted file mode 100644 index 34928841..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-interactive.html +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - An Interactive Service - - - - - - - -
  Home

An Interactive Service
-

-

This example implements a service with a simple user interface.

-

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes.

-

However, although not recommended in the general case, in certain circumstances a service may provide a GUI itself. This is typically only possible if the service process is run as the same user as the one that is logged in, so that it will have access to the screen. Note however that on Windows Vista, service GUIs are not allowed at all, since services run in a diferent session than all user sessions, for security reasons.

-

This example demonstrates how to subclass the QtService class, the use of start(), stop(), pause(), resume(), and how to use processCommand() to receive control commands while running.

-

Here is the complete source code:

-
 /****************************************************************************
- **
- ** This file is part of a Qt Solutions component.
- **
- ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
- **
- ** Contact:  Qt Software Information (qt-info@nokia.com)
- **
- ** Commercial Usage
- ** Licensees holding valid Qt Commercial licenses may use this file in
- ** accordance with the Qt Solutions Commercial License Agreement provided
- ** with the Software or, alternatively, in accordance with the terms
- ** contained in a written agreement between you and Nokia.
- **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain
- ** additional rights. These rights are described in the Nokia Qt LGPL
- ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
- ** package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- ** Please note Third Party Software included with Qt Solutions may impose
- ** additional restrictions and it is the user's responsibility to ensure
- ** that they have met the licensing requirements of the GPL, LGPL, or Qt
- ** Solutions Commercial license and the relevant license of the Third
- ** Party Software they are using.
- **
- ** If you are unsure which license is appropriate for your use, please
- ** contact the sales department at qt-sales@nokia.com.
- **
- ****************************************************************************/
-
- #include <QtGui/QApplication>
- #include <QtGui/QDesktopWidget>
- #include <QtGui/QLabel>
- #include <QtCore/QDir>
- #include <QtCore/QSettings>
- #include "qtservice.h"
-
- class InteractiveService : public QtService<QApplication>
- {
- public:
-     InteractiveService(int argc, char **argv);
-     ~InteractiveService();
-
- protected:
-
-     void start();
-     void stop();
-     void pause();
-     void resume();
-     void processCommand(int code);
-
- private:
-     QLabel *gui;
- };
-
- InteractiveService::InteractiveService(int argc, char **argv)
-     : QtService<QApplication>(argc, argv, "Qt Interactive Service"), gui(0)
- {
-     setServiceDescription("A Qt service with user interface.");
-     setServiceFlags(QtServiceBase::CanBeSuspended);
- }
-
- InteractiveService::~InteractiveService()
- {
- }
-
- void InteractiveService::start()
- {
- #if defined(Q_OS_WIN)
-     if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) &&
-         (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) {
-         logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error );
-         return;
-     }
- #endif
-
-     qApp->setQuitOnLastWindowClosed(false);
-
-     gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
-     gui->move(QApplication::desktop()->availableGeometry().topLeft());
-     gui->show();
- }
-
- void InteractiveService::stop()
- {
-     delete gui;
- }
-
- void InteractiveService::pause()
- {
-     if (gui)
-         gui->hide();
- }
-
- void InteractiveService::resume()
- {
-     if (gui)
-         gui->show();
- }
-
- void InteractiveService::processCommand(int code)
- {
-     gui->setText("Command code " + QString::number(code));
-     gui->adjustSize();
- }
-
- int main(int argc, char **argv)
- {
- #if !defined(Q_WS_WIN)
-     // QtService stores service settings in SystemScope, which normally require root privileges.
-     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
-     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
-     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
- #endif
-     InteractiveService service(argc, argv);
-     return service.exec();
- }
-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html deleted file mode 100644 index 00cfb826..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-example-server.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - A simple HTTP Server - - - - - - - -
  Home

A simple HTTP Server
-

-

It is a very simple implementation of a HTTP daemon that listens on chosen port (defaultly 8080) and sends back a simple HTML page back for every GET request it gets. After sending the page, it closes the connection.

-
 // HttpDaemon is the the class that implements the simple HTTP server.
- class HttpDaemon : public QTcpServer
- {
-     Q_OBJECT
- public:
-     HttpDaemon(quint16 port, QObject* parent = 0)
-         : QTcpServer(parent), disabled(false)
-     {
-         listen(QHostAddress::Any, port);
-     }
-
-     void incomingConnection(int socket)
-     {
-         if (disabled)
-             return;
-
-         // When a new client connects, the server constructs a QTcpSocket and all
-         // communication with the client is done over this QTcpSocket. QTcpSocket
-         // works asynchronously, this means that all the communication is done
-         // in the two slots readClient() and discardClient().
-         QTcpSocket* s = new QTcpSocket(this);
-         connect(s, SIGNAL(readyRead()), this, SLOT(readClient()));
-         connect(s, SIGNAL(disconnected()), this, SLOT(discardClient()));
-         s->setSocketDescriptor(socket);
-
-         QtServiceBase::instance()->logMessage("New Connection");
-     }
-
-     void pause()
-     {
-         disabled = true;
-     }
-
-     void resume()
-     {
-         disabled = false;
-     }
-
- private slots:
-     void readClient()
-     {
-         if (disabled)
-             return;
-
-         // This slot is called when the client sent data to the server. The
-         // server looks if it was a get request and sends a very simple HTML
-         // document back.
-         QTcpSocket* socket = (QTcpSocket*)sender();
-         if (socket->canReadLine()) {
-             QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*"));
-             if (tokens[0] == "GET") {
-                 QTextStream os(socket);
-                 os.setAutoDetectUnicode(true);
-                 os << "HTTP/1.0 200 Ok\r\n"
-                     "Content-Type: text/html; charset=\"utf-8\"\r\n"
-                     "\r\n"
-                     "<h1>Nothing to see here</h1>\n"
-                     << QDateTime::currentDateTime().toString() << "\n";
-                 socket->close();
-
-                 QtServiceBase::instance()->logMessage("Wrote to client");
-
-                 if (socket->state() == QTcpSocket::UnconnectedState) {
-                     delete socket;
-                     QtServiceBase::instance()->logMessage("Connection closed");
-                 }
-             }
-         }
-     }
-     void discardClient()
-     {
-         QTcpSocket* socket = (QTcpSocket*)sender();
-         socket->deleteLater();
-
-         QtServiceBase::instance()->logMessage("Connection closed");
-     }
-
- private:
-     bool disabled;
- };
-

The server implementation uses the QtService::logMessage() function to send messages and status reports to the system event log. The server also supports a paused state in which case incoming requests are ignored.

-

The HttpService class subclasses QtService to implement the service functionality.

-
 class HttpService : public QtService<QCoreApplication>
- {
- public:
-     HttpService(int argc, char **argv)
-         : QtService<QCoreApplication>(argc, argv, "Qt HTTP Daemon")
-     {
-         setServiceDescription("A dummy HTTP service implemented with Qt");
-         setServiceFlags(QtServiceBase::CanBeSuspended);
-     }
-

The constructor calls the QtService constructor instantiated with QCoreApplication since our service will not use GUI. The first two parameters of our constructor are passed to QtService. The last parameter, "Qt HTTP Daemon", is the name of the service.

-
 protected:
-     void start()
-     {
-         QCoreApplication *app = application();
-
-         quint16 port = (app->argc() > 1) ?
-                 QString::fromLocal8Bit(app->argv()[1]).toUShort() : 8080;
-         daemon = new HttpDaemon(port, app);
-
-         if (!daemon->isListening()) {
-             logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error);
-             app->quit();
-         }
-     }
-

The implementation of start() first checks if the user passed a port number. If yes that port is used by server to listen on. Otherwise default 8080 port is used. Then creates an instance of the HTTP server using operator new, passing the application object as the parent to ensure that the object gets destroyed.

-
     void pause()
-     {
-         daemon->pause();
-     }
-
-     void resume()
-     {
-         daemon->resume();
-     }
-
- private:
-     HttpDaemon *daemon;
- };
-

The implementations of pause() and resume() forward the request to the server object.

-
 #include "main.moc"
-
- int main(int argc, char **argv)
- {
- #if !defined(Q_WS_WIN)
-     // QtService stores service settings in SystemScope, which normally require root privileges.
-     // To allow testing this example as non-root, we change the directory of the SystemScope settings file.
-     QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
-     qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
- #endif
-     HttpService service(argc, argv);
-     return service.exec();
- }
-

The main entry point function creates the service object and uses the exec() function to execute the service.

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html deleted file mode 100644 index 781a154b..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice-members.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - List of All Members for QtService - - - - - - - -
  Home

List of All Members for QtService

-

This is the complete list of members for QtService, including inherited members.

-

- -
-

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf deleted file mode 100644 index 3ba64c80..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.dcf +++ /dev/null @@ -1,76 +0,0 @@ - - -
-
- QtService - application -
-
-
- QtServiceBase - MessageType - QtServiceBase::Warning - QtServiceBase::Error - QtServiceBase::Success - QtServiceBase::Information - ServiceFlag - ServiceFlags - QtServiceBase::Default - QtServiceBase::CannotBeStopped - QtServiceBase::CanBeSuspended - createApplication - exec - executeApplication - instance - logMessage - pause - processCommand - resume - serviceDescription - serviceFlags - serviceName - setServiceDescription - setServiceFlags - setStartupType - start - startupType - stop -
-
-
- QtServiceController - StartupType - QtServiceController::AutoStartup - QtServiceController::ManualStartup - install - isInstalled - isRunning - pause - resume - sendCommand - serviceDescription - serviceFilePath - serviceName - start - startupType - stop - uninstall -
-
-
-
-
- A simple HTTP Server -
-
- A simple Service Controller -
-
- An Interactive Service -
-
- Service -
-
-
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html deleted file mode 100644 index 370c8ee6..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - QtService Class Reference - - - - - - - -
  Home

QtService Class Reference

-

The QtService is a convenient template class that allows you to create a service for a particular application type. More...

-
 #include <QtService>

Inherits QtServiceBase.

- - -

Public Functions

- - - -

Protected Functions

- - -

Additional Inherited Members

- - -
-

Detailed Description

-

The QtService is a convenient template class that allows you to create a service for a particular application type.

-

A Windows service or Unix daemon (a "service"), is a program that runs "in the background" independently of whether a user is logged in or not. A service is often set up to start when the machine boots up, and will typically run continuously as long as the machine is on.

-

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes. (In certain circumstances, a service may provide a GUI itself, ref. the "interactive" example documentation).

-

Note: On Unix systems, this class relies on facilities provided by the QtNetwork module, provided as part of the Qt Open Source Edition and certain Qt Commercial Editions.

-

The QtService class functionality is inherited from QtServiceBase, but in addition the QtService class binds an instance of QtServiceBase with an application type.

-

Typically, you will create a service by subclassing the QtService template class. For example:

-
 class MyService : public QtService<QApplication>
- {
- public:
-     MyService(int argc, char **argv);
-     ~MyService();
-
- protected:
-     void start();
-     void stop();
-     void pause();
-     void resume();
-     void processCommand(int code);
- };
-

The application type can be QCoreApplication for services without GUI, QApplication for services with GUI or you can use your own custom application type.

-

You must reimplement the QtServiceBase::start() function to perform the service's work. Usually you create some main object on the heap which is the heart of your service.

-

In addition, you might want to reimplement the QtServiceBase::pause(), QtServiceBase::processCommand(), QtServiceBase::resume() and QtServiceBase::stop() to intervene the service's process on controller requests. You can control any given service using an instance of the QtServiceController class which also allows you to control services from separate applications. The mentioned functions are all virtual and won't do anything unless they are reimplemented.

-

Your custom service is typically instantiated in the application's main function. Then the main function will call your service's exec() function, and return the result of that call. For example:

-
     int main(int argc, char **argv)
-     {
-         MyService service(argc, argv);
-         return service.exec();
-     }
-

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and exit.

-

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

-

See also QtServiceBase and QtServiceController.

-
-

Member Function Documentation

-

QtService::QtService ( int argc, char ** argv, const QString & name )

-

Constructs a QtService object called name. The argc and argv parameters are parsed after the exec() function has been called. Then they are passed to the application's constructor.

-

There can only be one QtService object in a process.

-

See also QtServiceBase().

-

QtService::~QtService ()

-

Destroys the service object.

-

Application * QtService::application () const   [protected]

-

Returns a pointer to the application object.

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index deleted file mode 100644 index 494e0060..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.index +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qch deleted file mode 100644 index 2757197b7792d8ff6d6d45bcd457126e03c97151..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57344 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 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp deleted file mode 100644 index 96d058f5..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservice.qhp +++ /dev/null @@ -1,90 +0,0 @@ - - - com.trolltech.qtsolutions.qtservice_2.6 - qdoc - - qt - qtservice - solutions - - - qt - qtservice - solutions - -
-
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - qtservice-example-controller.html - index.html - qtservice-example-server.html - qtservice-example-interactive.html - qtservicebase.html - qtservice.html - qtservicecontroller.html - classic.css - images/qt-logo.png - -
-
diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html deleted file mode 100644 index 909b555c..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase-members.html +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - List of All Members for QtServiceBase - - - - - - - -
  Home

List of All Members for QtServiceBase

-

This is the complete list of members for QtServiceBase, including inherited members.

-

- -
-

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html deleted file mode 100644 index 680a1df9..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicebase.html +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - QtServiceBase Class Reference - - - - - - - -
  Home

QtServiceBase Class Reference

-

The QtServiceBase class provides an API for implementing Windows services and Unix daemons. More...

-
 #include <QtServiceBase>

Inherited by QtService.

- - -

Public Types

- - -

Public Functions

- - -

Static Public Members

- - -

Protected Functions

- - -
-

Detailed Description

-

The QtServiceBase class provides an API for implementing Windows services and Unix daemons.

-

A Windows service or Unix daemon (a "service"), is a program that runs "in the background" independently of whether a user is logged in or not. A service is often set up to start when the machine boots up, and will typically run continuously as long as the machine is on.

-

Services are usually non-interactive console applications. User interaction, if required, is usually implemented in a separate, normal GUI application that communicates with the service through an IPC channel. For simple communication, QtServiceController::sendCommand() and QtService::processCommand() may be used, possibly in combination with a shared settings file. For more complex, interactive communication, a custom IPC channel should be used, e.g. based on Qt's networking classes. (In certain circumstances, a service may provide a GUI itself, ref. the "interactive" example documentation).

-

Typically, you will create a service by subclassing the QtService template class which inherits QtServiceBase and allows you to create a service for a particular application type.

-

The Windows implementation uses the NT Service Control Manager, and the application can be controlled through the system administration tools. Services are usually launched using the system account, which requires that all DLLs that the service executable depends on (i.e. Qt), are located in the same directory as the service, or in a system path.

-

On Unix a service is implemented as a daemon.

-

You can retrieve the service's description, state, and startup type using the serviceDescription(), serviceFlags() and startupType() functions respectively. The service's state is decribed by the ServiceFlag enum. The mentioned properites can also be set using the corresponding set functions. In addition you can retrieve the service's name using the serviceName() function.

-

Several of QtServiceBase's protected functions are called on requests from the QtServiceController class:

- -

You can control any given service using an instance of the QtServiceController class which also allows you to control services from separate applications. The mentioned functions are all virtual and won't do anything unless they are reimplemented. You can reimplement these functions to pause and resume the service's execution, as well as process user commands and perform additional clean-ups before shutting down.

-

QtServiceBase also provides the static instance() function which returns a pointer to an application's QtServiceBase instance. In addition, a service can report events to the system's event log using the logMessage() function. The MessageType enum describes the different types of messages a service reports.

-

The implementation of a service application's main function typically creates an service object derived by subclassing the QtService template class. Then the main function will call this service's exec() function, and return the result of that call. For example:

-
 int main(int argc, char **argv)
- {
-     MyService service(argc, argv);
-     return service.exec();
- }
-

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and return.

-

The following arguments are recognized as service specific:

-

- - - - - - - - - -
ShortLongExplanation
-i-installInstall the service.
-u-uninstallUninstall the service.
-e-execExecute the service as a standalone application (useful for debug purposes). This is a blocking call, the service will be executed like a normal application. In this mode you will not be able to communicate with the service from the contoller.
-t-terminateStop the service.
-p-pausePause the service.
-r-resumeResume a paused service.
-c cmd-command cmdSend the user defined command code cmd to the service application.
-v-versionDisplay version and status information.

-

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

-

See also QtService and QtServiceController.

-
-

Member Type Documentation

-

enum QtServiceBase::MessageType

-

This enum describes the different types of messages a service reports to the system log.

-

- - - - - -
ConstantValueDescription
QtServiceBase::Success0An operation has succeeded, e.g. the service is started.
QtServiceBase::Error1An operation failed, e.g. the service failed to start.
QtServiceBase::Warning2An operation caused a warning that might require user interaction.
QtServiceBase::Information3Any type of usually non-critical information.

-

enum QtServiceBase::ServiceFlag
flags QtServiceBase::ServiceFlags

-

This enum describes the different states of a service.

-

- - - - -
ConstantValueDescription
QtServiceBase::Default0x00The service can be stopped, but not suspended.
QtServiceBase::CanBeSuspended0x01The service can be suspended.
QtServiceBase::CannotBeStopped0x02The service cannot be stopped.

-

The ServiceFlags type is a typedef for QFlags<ServiceFlag>. It stores an OR combination of ServiceFlag values.

-
-

Member Function Documentation

-

QtServiceBase::QtServiceBase ( int argc, char ** argv, const QString & name )

-

Creates a service instance called name. The argc and argv parameters are parsed after the exec() function has been called. Then they are passed to the application's constructor. The application type is determined by the QtService subclass.

-

The service is neither installed nor started. The name must not contain any backslashes or be longer than 255 characters. In addition, the name must be unique in the system's service database.

-

See also exec(), start(), and QtServiceController::install().

-

QtServiceBase::~QtServiceBase ()   [virtual]

-

Destroys the service object. This neither stops nor uninstalls the service.

-

To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the QtServiceController::uninstall() function.

-

See also stop() and QtServiceController::uninstall().

-

void QtServiceBase::createApplication ( int & argc, char ** argv )   [pure virtual protected]

-

Creates the application object using the argc and argv parameters.

-

This function is only called when no service specific arguments were passed to the service constructor, and is called by exec() before it calls the executeApplication() and start() functions.

-

The createApplication() function is implemented in QtService, but you might want to reimplement it, for example, if the chosen application type's constructor needs additional arguments.

-

See also exec() and QtService.

-

int QtServiceBase::exec ()

-

Executes the service.

-

When the exec() function is called, it will parse the service specific arguments passed in argv, perform the required actions, and exit.

-

If none of the arguments is recognized as service specific, exec() will first call the createApplication() function, then executeApplication() and finally the start() function. In the end, exec() returns while the service continues in its own process waiting for commands from the service controller.

-

See also QtServiceController.

-

int QtServiceBase::executeApplication ()   [pure virtual protected]

-

Executes the application previously created with the createApplication() function.

-

This function is only called when no service specific arguments were passed to the service constructor, and is called by exec() after it has called the createApplication() function and before start() function.

-

This function is implemented in QtService.

-

See also exec() and createApplication().

-

QtServiceBase * QtServiceBase::instance ()   [static]

-

Returns a pointer to the current application's QtServiceBase instance.

-

void QtServiceBase::logMessage ( const QString & message, MessageType type = Success, int id = 0, uint category = 0, const QByteArray & data = QByteArray() )

-

Reports a message of the given type with the given message to the local system event log. The message identifier id and the message category are user defined values. The data parameter can contain arbitrary binary data.

-

Message strings for id and category must be provided by a message file, which must be registered in the system registry. Refer to the MSDN for more information about how to do this on Windows.

-

See also MessageType.

-

void QtServiceBase::pause ()   [virtual protected]

-

Reimplement this function to pause the service's execution (for example to stop a polling timer, or to ignore socket notifiers).

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also resume() and QtServiceController::pause().

-

void QtServiceBase::processCommand ( int code )   [virtual protected]

-

Reimplement this function to process the user command code.

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also QtServiceController::sendCommand().

-

void QtServiceBase::resume ()   [virtual protected]

-

Reimplement this function to continue the service after a call to pause().

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also pause() and QtServiceController::resume().

-

QString QtServiceBase::serviceDescription () const

-

Returns the description of the service.

-

See also setServiceDescription() and serviceName().

-

ServiceFlags QtServiceBase::serviceFlags () const

-

Returns the service's state which is decribed using the ServiceFlag enum.

-

See also ServiceFlags and setServiceFlags().

-

QString QtServiceBase::serviceName () const

-

Returns the name of the service.

-

See also QtServiceBase() and serviceDescription().

-

void QtServiceBase::setServiceDescription ( const QString & description )

-

Sets the description of the service to the given description.

-

See also serviceDescription().

-

void QtServiceBase::setServiceFlags ( ServiceFlags flags )

-

Sets the service's state to the state described by the given flags.

-

See also ServiceFlags and serviceFlags().

-

void QtServiceBase::setStartupType ( QtServiceController::StartupType type )

-

Sets the service's startup type to the given type.

-

See also QtServiceController::StartupType and startupType().

-

void QtServiceBase::start ()   [pure virtual protected]

-

This function must be implemented in QtServiceBase subclasses in order to perform the service's work. Usually you create some main object on the heap which is the heart of your service.

-

The function is only called when no service specific arguments were passed to the service constructor, and is called by exec() after it has called the executeApplication() function.

-

Note that you don't need to create an application object or call its exec() function explicitly.

-

See also exec(), stop(), and QtServiceController::start().

-

QtServiceController::StartupType QtServiceBase::startupType () const

-

Returns the service's startup type.

-

See also QtServiceController::StartupType and setStartupType().

-

void QtServiceBase::stop ()   [virtual protected]

-

Reimplement this function to perform additional cleanups before shutting down (for example deleting a main object if it was created in the start() function).

-

This function is called in reply to controller requests. The default implementation does nothing.

-

See also start() and QtServiceController::stop().

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html deleted file mode 100644 index 1ea83044..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller-members.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - List of All Members for QtServiceController - - - - - - - -
  Home

List of All Members for QtServiceController

-

This is the complete list of members for QtServiceController, including inherited members.

-

- -
-

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html deleted file mode 100644 index 6ec6d338..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/html/qtservicecontroller.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - - QtServiceController Class Reference - - - - - - - -
  Home

QtServiceController Class Reference

-

The QtServiceController class allows you to control services from separate applications. More...

-
 #include <QtServiceController>
- -

Public Types

- - -

Public Functions

- - -

Static Public Members

-
    -
  • bool install ( const QString & serviceFilePath, const QString & account = QString(), const QString & password = QString() )
  • -
- -
-

Detailed Description

-

The QtServiceController class allows you to control services from separate applications.

-

QtServiceController provides a collection of functions that lets you install and run a service controlling its execution, as well as query its status.

-

In order to run a service, the service must be installed in the system's service database using the install() function. The system will start the service depending on the specified StartupType; it can either be started during system startup, or when a process starts it manually.

-

Once a service is installed, the service can be run and controlled manually using the start(), stop(), pause(), resume() or sendCommand() functions. You can at any time query for the service's status using the isInstalled() and isRunning() functions, or you can query its properties using the serviceDescription(), serviceFilePath(), serviceName() and startupType() functions. For example:

-
 MyService service;       \\ which inherits QtService
- QString serviceFilePath;
-
- QtServiceController controller(service.serviceName());
-
- if (controller.install(serviceFilePath))
-     controller.start()
-
- if (controller.isRunning())
-     QMessageBox::information(this, tr("Service Status"),
-                              tr("The %1 service is started").arg(controller.serviceName()));
-
- ...
-
- controller.stop();
- controller.uninstall();
- }
-

An instance of the service controller can only control one single service. To control several services within one application, you must create en equal number of service controllers.

-

The QtServiceController destructor neither stops nor uninstalls the associated service. To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the uninstall() function.

-

See also QtServiceBase and QtService.

-
-

Member Type Documentation

-

enum QtServiceController::StartupType

-

This enum describes when a service should be started.

-

- - - -
ConstantValueDescription
QtServiceController::AutoStartup0The service is started during system startup.
QtServiceController::ManualStartup1The service must be started manually by a process.

-

Warning: The StartupType enum is ignored under UNIX-like systems. A service, or daemon, can only be started manually on such systems with current implementation.

-

See also startupType().

-
-

Member Function Documentation

-

QtServiceController::QtServiceController ( const QString & name )

-

Creates a controller object for the service with the given name.

-

QtServiceController::~QtServiceController ()   [virtual]

-

Destroys the service controller. This neither stops nor uninstalls the controlled service.

-

To stop a service the stop() function must be called explicitly. To uninstall a service, you can use the uninstall() function.

-

See also stop() and QtServiceController::uninstall().

-

bool QtServiceController::install ( const QString & serviceFilePath, const QString & account = QString(), const QString & password = QString() )   [static]

-

Installs the service with the given serviceFilePath and returns true if the service is installed successfully; otherwise returns false.

-

On Windows service is installed in the system's service control manager with the given account and password.

-

On Unix service configuration is written to QSettings::SystemScope using "QtSoftware" as organization name. account and password arguments are ignored.

-

Warning: Due to the different implementations of how services (daemons) are installed on various UNIX-like systems, this method doesn't integrate the service into the system's startup scripts.

-

See also uninstall() and start().

-

bool QtServiceController::isInstalled () const

-

Returns true if the service is installed; otherwise returns false.

-

On Windows it uses the system's service control manager.

-

On Unix it checks configuration written to QSettings::SystemScope using "QtSoftware" as organization name.

-

See also install().

-

bool QtServiceController::isRunning () const

-

Returns true if the service is running; otherwise returns false. A service must be installed before it can be run using a controller.

-

See also start() and isInstalled().

-

bool QtServiceController::pause ()

-

Requests the running service to pause. If the service's state is QtServiceBase::CanBeSuspended, the service will call the QtServiceBase::pause() implementation. The function does nothing if the service is not running.

-

Returns true if a running service was successfully paused; otherwise returns false.

-

See also resume(), QtServiceBase::pause(), and QtServiceBase::ServiceFlags.

-

bool QtServiceController::resume ()

-

Requests the running service to continue. If the service's state is QtServiceBase::CanBeSuspended, the service will call the QtServiceBase::resume() implementation. This function does nothing if the service is not running.

-

Returns true if a running service was successfully resumed; otherwise returns false.

-

See also pause(), QtServiceBase::resume(), and QtServiceBase::ServiceFlags.

-

bool QtServiceController::sendCommand ( int code )

-

Sends the user command code to the service. The service will call the QtServiceBase::processCommand() implementation. This function does nothing if the service is not running.

-

Returns true if the request was sent to a running service; otherwise returns false.

-

See also QtServiceBase::processCommand().

-

QString QtServiceController::serviceDescription () const

-

Returns the description of the controlled service.

-

See also install() and serviceName().

-

QString QtServiceController::serviceFilePath () const

-

Returns the file path to the controlled service.

-

See also install() and serviceName().

-

QString QtServiceController::serviceName () const

-

Returns the name of the controlled service.

-

See also QtServiceController() and serviceDescription().

-

bool QtServiceController::start ( const QStringList & arguments )

-

Starts the installed service passing the given arguments to the service. A service must be installed before a controller can run it.

-

Returns true if the service could be started; otherwise returns false.

-

See also install() and stop().

-

bool QtServiceController::start ()

-

This is an overloaded member function, provided for convenience.

-

Starts the installed service without passing any arguments to the service.

-

StartupType QtServiceController::startupType () const

-

Returns the startup type of the controlled service.

-

See also install() and serviceName().

-

bool QtServiceController::stop ()

-

Requests the running service to stop. The service will call the QtServiceBase::stop() implementation unless the service's state is QtServiceBase::CannotBeStopped. This function does nothing if the service is not running.

-

Returns true if a running service was successfully stopped; otherwise false.

-

See also start(), QtServiceBase::stop(), and QtServiceBase::ServiceFlags.

-

bool QtServiceController::uninstall ()

-

Uninstalls the service and returns true if successful; otherwise returns false.

-

On Windows service is uninstalled using the system's service control manager.

-

On Unix service configuration is cleared using QSettings::SystemScope with "QtSoftware" as organization name.

-

See also install().

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/images/qt-logo.png deleted file mode 100644 index 794162f5af58e7b38beebf472842fc9703ede19b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4075 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 diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc deleted file mode 100644 index 31c3e87b..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/doc/index.qdoc +++ /dev/null @@ -1,46 +0,0 @@ -/*! - \page index.html - \title Service - - \section1 Description - - The QtService component is useful for developing Windows - services and Unix daemons. - - - - The project provides a QtService template class that can be used to - implement service applications, and a QtServiceController class - to control a service. - - On Windows systems the implementation uses the Service Control - Manager. - - On Unix systems services are implemented as daemons. - - - - \section1 Classes - \list - \i QtServiceController \i QtServiceBase \i QtService\endlist - - \section1 Examples - \list - \i \link qtservice-example-interactive.html An Interactive Service \endlink \i \link qtservice-example-server.html A simple HTTP Server \endlink \i \link qtservice-example-controller.html A simple Service Controller \endlink \endlist - - - - - - - \section1 Tested platforms - \list - \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005 - \i Qt 4.4, 4.5 / Linux / gcc - \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc - \endlist - - - - - */ \ No newline at end of file diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro deleted file mode 100644 index 722084b8..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.pro +++ /dev/null @@ -1,7 +0,0 @@ -TEMPLATE = app -CONFIG += console qt -QT = core - -SOURCES = main.cpp - -include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc deleted file mode 100644 index 7de827bd..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/controller.qdoc +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -/*! \page qtservice-example-controller.html - \title A simple Service Controller - - It is a very simple implementation of universal command-line - controller. This controller can install and control any service - written using QtService component. It demonstrates how to use - QtServiceController class. On Windows, this is an alternative to - using the "Services" Administrative Tool or the built-in \c sc.exe - command-line tool to control services. - - A note about services on Windows Vista: Installing/uninstalling - and starting/stopping services requires security privileges. The - simplest way to achieve this is to set the "Run as Administrator" - property on the executable (right-click the executable file, - select Properties, and choose the Compatibilty tab in the - Properties dialog). This applies even if you are logged in as - Administrator. Also, the command-line shell should be started with - "Run as Administrator". Note that the service itself does not need - special privileges to run. Only if you want the service to be able - to install itself (the -i option) or similar, then the service - will need to be run as Administrator. Otherwise, the recommended - procedure is to use a controller such as this example and/or the - "Services" Administrative Tool to manage the service. - - A usability hint: in some circumstances, e.g. when running this - example on Windows Vista with the "Run as Administrator" property - set, output will be sent to a shell window which will close - immediately upon termination, not leaving the user enough time to - read the output. In such cases, append the -w(ait) argument, which - will make the controller wait for a keypress before terminating. - - Here is the complete source code: - - \quotefile controller/main.cpp -*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp deleted file mode 100644 index a64edc15..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/controller/main.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include -#include -#include -#include "qtservice.h" - -int processArgs(int argc, char **argv) -{ - if (argc > 2) { - QString arg1(argv[1]); - if (arg1 == QLatin1String("-i") || - arg1 == QLatin1String("-install")) { - if (argc > 2) { - QString account; - QString password; - QString path(argv[2]); - if (argc > 3) - account = argv[3]; - if (argc > 4) - password = argv[4]; - printf("The service %s installed.\n", - (QtServiceController::install(path, account, password) ? "was" : "was not")); - return 0; - } - } else { - QString serviceName(argv[1]); - QtServiceController controller(serviceName); - QString option(argv[2]); - if (option == QLatin1String("-u") || - option == QLatin1String("-uninstall")) { - printf("The service \"%s\" %s uninstalled.\n", - controller.serviceName().toLatin1().constData(), - (controller.uninstall() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-s") || - option == QLatin1String("-start")) { - QStringList args; - for (int i = 3; i < argc; ++i) - args.append(QString::fromLocal8Bit(argv[i])); - printf("The service \"%s\" %s started.\n", - controller.serviceName().toLatin1().constData(), - (controller.start(args) ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-t") || - option == QLatin1String("-terminate")) { - printf("The service \"%s\" %s stopped.\n", - controller.serviceName().toLatin1().constData(), - (controller.stop() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-p") || - option == QLatin1String("-pause")) { - printf("The service \"%s\" %s paused.\n", - controller.serviceName().toLatin1().constData(), - (controller.pause() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-r") || - option == QLatin1String("-resume")) { - printf("The service \"%s\" %s resumed.\n", - controller.serviceName().toLatin1().constData(), - (controller.resume() ? "was" : "was not")); - return 0; - } else if (option == QLatin1String("-c") || - option == QLatin1String("-command")) { - if (argc > 3) { - QString codestr(argv[3]); - int code = codestr.toInt(); - printf("The command %s sent to the service \"%s\".\n", - (controller.sendCommand(code) ? "was" : "was not"), - controller.serviceName().toLatin1().constData()); - return 0; - } - } else if (option == QLatin1String("-v") || - option == QLatin1String("-version")) { - bool installed = controller.isInstalled(); - printf("The service\n" - "\t\"%s\"\n\n", controller.serviceName().toLatin1().constData()); - printf("is %s", (installed ? "installed" : "not installed")); - printf(" and %s\n\n", (controller.isRunning() ? "running" : "not running")); - if (installed) { - printf("path: %s\n", controller.serviceFilePath().toLatin1().data()); - printf("description: %s\n", controller.serviceDescription().toLatin1().data()); - printf("startup: %s\n", controller.startupType() == QtServiceController::AutoStartup ? "Auto" : "Manual"); - } - return 0; - } - } - } - printf("controller [-i PATH | SERVICE_NAME [-v | -u | -s | -t | -p | -r | -c CODE] | -h] [-w]\n\n" - "\t-i(nstall) PATH\t: Install the service\n" - "\t-v(ersion)\t: Print status of the service\n" - "\t-u(ninstall)\t: Uninstall the service\n" - "\t-s(tart)\t: Start the service\n" - "\t-t(erminate)\t: Stop the service\n" - "\t-p(ause)\t: Pause the service\n" - "\t-r(esume)\t: Resume the service\n" - "\t-c(ommand) CODE\t: Send a command to the service\n" - "\t-h(elp)\t\t: Print this help info\n" - "\t-w(ait)\t\t: Wait for keypress when done\n"); - return 0; -} - - -int main(int argc, char **argv) -{ -#if !defined(Q_WS_WIN) - // QtService stores service settings in SystemScope, which normally require root privileges. - // To allow testing this example as non-root, we change the directory of the SystemScope settings file. - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); - qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); -#endif - - int result = processArgs(argc, argv); - - if (QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-w") || - QString::fromLocal8Bit(argv[argc-1]) == QLatin1String("-wait")) { - printf("\nPress Enter to continue..."); - QFile input; - input.open(stdin, QIODevice::ReadOnly); - input.readLine(); - printf("\n"); - } - - return result; -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro deleted file mode 100644 index 109b9294..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/examples.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = interactive \ - server \ - controller diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro deleted file mode 100644 index 6dba6f80..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.pro +++ /dev/null @@ -1,6 +0,0 @@ -TEMPLATE = app -CONFIG += console qt - -SOURCES = main.cpp - -include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc deleted file mode 100644 index dcb57e9a..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/interactive.qdoc +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -/*! \page qtservice-example-interactive.html - \title An Interactive Service - - This example implements a service with a simple user interface. - - Services are usually non-interactive console applications. User - interaction, if required, is usually implemented in a separate, - normal GUI application that communicates with the service through - an IPC channel. For simple communication, - QtServiceController::sendCommand() and QtService::processCommand() - may be used, possibly in combination with a shared settings - file. For more complex, interactive communication, a custom IPC - channel should be used, e.g. based on Qt's networking classes. - - However, although not recommended in the general case, in certain - circumstances a service may provide a GUI - itself. This is typically only possible if the service process is run as - the same user as the one that is logged in, so that it will have - access to the screen. Note however that on Windows Vista, service - GUIs are not allowed at all, since services run in a - diferent session than all user sessions, for security reasons. - - This example demonstrates how to subclass the QtService class, the use of - start(), stop(), pause(), resume(), and how to use - processCommand() to receive control commands while running. - - Here is the complete source code: - - \quotefile interactive/main.cpp -*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp deleted file mode 100644 index 4a99af57..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/interactive/main.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include "qtservice.h" - -class InteractiveService : public QtService -{ -public: - InteractiveService(int argc, char **argv); - ~InteractiveService(); - -protected: - - void start(); - void stop(); - void pause(); - void resume(); - void processCommand(int code); - -private: - QLabel *gui; -}; - -InteractiveService::InteractiveService(int argc, char **argv) - : QtService(argc, argv, "Qt Interactive Service"), gui(0) -{ - setServiceDescription("A Qt service with user interface."); - setServiceFlags(QtServiceBase::CanBeSuspended); -} - -InteractiveService::~InteractiveService() -{ -} - -void InteractiveService::start() -{ -#if defined(Q_OS_WIN) - if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) && - (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)) { - logMessage( "Service GUI not allowed on Windows Vista. See the documentation for this example for more information.", QtServiceBase::Error ); - return; - } -#endif - - qApp->setQuitOnLastWindowClosed(false); - - gui = new QLabel("Service", 0, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); - gui->move(QApplication::desktop()->availableGeometry().topLeft()); - gui->show(); -} - -void InteractiveService::stop() -{ - delete gui; -} - -void InteractiveService::pause() -{ - if (gui) - gui->hide(); -} - -void InteractiveService::resume() -{ - if (gui) - gui->show(); -} - -void InteractiveService::processCommand(int code) -{ - gui->setText("Command code " + QString::number(code)); - gui->adjustSize(); -} - -int main(int argc, char **argv) -{ -#if !defined(Q_WS_WIN) - // QtService stores service settings in SystemScope, which normally require root privileges. - // To allow testing this example as non-root, we change the directory of the SystemScope settings file. - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); - qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); -#endif - InteractiveService service(argc, argv); - return service.exec(); -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp deleted file mode 100644 index 43d2d501..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/main.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "qtservice.h" - -// HttpDaemon is the the class that implements the simple HTTP server. -class HttpDaemon : public QTcpServer -{ - Q_OBJECT -public: - HttpDaemon(quint16 port, QObject* parent = 0) - : QTcpServer(parent), disabled(false) - { - listen(QHostAddress::Any, port); - } - - void incomingConnection(int socket) - { - if (disabled) - return; - - // When a new client connects, the server constructs a QTcpSocket and all - // communication with the client is done over this QTcpSocket. QTcpSocket - // works asynchronously, this means that all the communication is done - // in the two slots readClient() and discardClient(). - QTcpSocket* s = new QTcpSocket(this); - connect(s, SIGNAL(readyRead()), this, SLOT(readClient())); - connect(s, SIGNAL(disconnected()), this, SLOT(discardClient())); - s->setSocketDescriptor(socket); - - QtServiceBase::instance()->logMessage("New Connection"); - } - - void pause() - { - disabled = true; - } - - void resume() - { - disabled = false; - } - -private slots: - void readClient() - { - if (disabled) - return; - - // This slot is called when the client sent data to the server. The - // server looks if it was a get request and sends a very simple HTML - // document back. - QTcpSocket* socket = (QTcpSocket*)sender(); - if (socket->canReadLine()) { - QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*")); - if (tokens[0] == "GET") { - QTextStream os(socket); - os.setAutoDetectUnicode(true); - os << "HTTP/1.0 200 Ok\r\n" - "Content-Type: text/html; charset=\"utf-8\"\r\n" - "\r\n" - "

Nothing to see here

\n" - << QDateTime::currentDateTime().toString() << "\n"; - socket->close(); - - QtServiceBase::instance()->logMessage("Wrote to client"); - - if (socket->state() == QTcpSocket::UnconnectedState) { - delete socket; - QtServiceBase::instance()->logMessage("Connection closed"); - } - } - } - } - void discardClient() - { - QTcpSocket* socket = (QTcpSocket*)sender(); - socket->deleteLater(); - - QtServiceBase::instance()->logMessage("Connection closed"); - } - -private: - bool disabled; -}; - -class HttpService : public QtService -{ -public: - HttpService(int argc, char **argv) - : QtService(argc, argv, "Qt HTTP Daemon") - { - setServiceDescription("A dummy HTTP service implemented with Qt"); - setServiceFlags(QtServiceBase::CanBeSuspended); - } - -protected: - void start() - { - QCoreApplication *app = application(); - - quint16 port = (app->argc() > 1) ? - QString::fromLocal8Bit(app->argv()[1]).toUShort() : 8080; - daemon = new HttpDaemon(port, app); - - if (!daemon->isListening()) { - logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error); - app->quit(); - } - } - - void pause() - { - daemon->pause(); - } - - void resume() - { - daemon->resume(); - } - -private: - HttpDaemon *daemon; -}; - -#include "main.moc" - -int main(int argc, char **argv) -{ -#if !defined(Q_WS_WIN) - // QtService stores service settings in SystemScope, which normally require root privileges. - // To allow testing this example as non-root, we change the directory of the SystemScope settings file. - QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath()); - qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData()); -#endif - HttpService service(argc, argv); - return service.exec(); -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro deleted file mode 100644 index 608b4d55..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.pro +++ /dev/null @@ -1,8 +0,0 @@ -TARGET = httpservice -TEMPLATE = app -CONFIG += console qt -QT = core network - -SOURCES = main.cpp - -include(../../src/qtservice.pri) diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc b/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc deleted file mode 100644 index 1728210f..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/examples/server/server.qdoc +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -/*! \page qtservice-example-server.html - \title A simple HTTP Server - - It is a very simple implementation of a HTTP daemon that listens on - chosen port (defaultly 8080) and sends back a simple HTML page back for every GET - request it gets. After sending the page, it closes the connection. - - \quotefromfile server/main.cpp - \skipto HttpDaemon - - \printuntil }; - The server implementation uses - the QtService::logMessage() function to send messages and status - reports to the system event log. The server also supports - a paused state in which case incoming requests are ignored. - - The \c HttpService class subclasses QtService to implement the - service functionality. - - \printto protected: - The constructor calls the QtService constructor instantiated with QCoreApplication - since our service will not use GUI. - The first two parameters of our constructor are passed to QtService. - The last parameter, "Qt HTTP Daemon", is the name of the service. - - \printto pause() - The implementation of \c start() first checks if the user passed a port number. - If yes that port is used by server to listen on. Otherwise default 8080 port is used. - Then creates an instance of the HTTP server using operator - new, passing the application object as the parent to ensure that the object - gets destroyed. - - \printto private: - \printuntil }; - The implementations of pause() and resume() forward the request to the - server object. - - \printuntil } - The main entry point function creates the service object and uses - the \c exec() function to execute the service. -*/ diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro b/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro deleted file mode 100644 index 5aa57569..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/qtservice.pro +++ /dev/null @@ -1,5 +0,0 @@ -TEMPLATE=subdirs -CONFIG += ordered -include(common.pri) -qtservice-uselib:SUBDIRS=buildlib -SUBDIRS+=examples diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase deleted file mode 100644 index 57e17a52..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceBase +++ /dev/null @@ -1 +0,0 @@ -#include "qtservice.h" diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController b/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController deleted file mode 100644 index 57e17a52..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/QtServiceController +++ /dev/null @@ -1 +0,0 @@ -#include "qtservice.h" diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp deleted file mode 100644 index e0084f1f..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp +++ /dev/null @@ -1,1117 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtservice.h" -#include "qtservice_p.h" -#include -#include -#include -#include -#include - -#if defined(QTSERVICE_DEBUG) -#include -#include -#include -#include -#if defined(Q_OS_WIN32) -#include -#else -#include -#include -#endif - -static QFile* f = 0; - -static void qtServiceCloseDebugLog() -{ - if (!f) - return; - QString ps(QTime::currentTime().toString("HH:mm:ss.zzz ") + QLatin1String("--- DEBUG LOG CLOSED ---\n\n")); - f->write(ps.toAscii()); - f->flush(); - f->close(); - delete f; - f = 0; -} - -void qtServiceLogDebug(QtMsgType type, const char* msg) -{ - static QMutex mutex; - QMutexLocker locker(&mutex); - QString s(QTime::currentTime().toString("HH:mm:ss.zzz ")); - s += QString("[%1] ").arg( -#if defined(Q_OS_WIN32) - GetCurrentProcessId()); -#else - getpid()); -#endif - - if (!f) { -#if defined(Q_OS_WIN32) - f = new QFile("c:/service-debuglog.txt"); -#else - f = new QFile("/tmp/service-debuglog.txt"); -#endif - if (!f->open(QIODevice::WriteOnly | QIODevice::Append)) { - delete f; - f = 0; - return; - } - QString ps(QLatin1String("\n") + s + QLatin1String("--- DEBUG LOG OPENED ---\n")); - f->write(ps.toAscii()); - } - - switch (type) { - case QtWarningMsg: - s += QLatin1String("WARNING: "); - break; - case QtCriticalMsg: - s += QLatin1String("CRITICAL: "); - break; - case QtFatalMsg: - s+= QLatin1String("FATAL: "); - break; - case QtDebugMsg: - s += QLatin1String("DEBUG: "); - break; - default: - // Nothing - break; - } - - s += msg; - s += QLatin1String("\n"); - - f->write(s.toAscii()); - f->flush(); - - if (type == QtFatalMsg) { - qtServiceCloseDebugLog(); - exit(1); - } -} - -#endif - -/*! - \class QtServiceController - - \brief The QtServiceController class allows you to control - services from separate applications. - - QtServiceController provides a collection of functions that lets - you install and run a service controlling its execution, as well - as query its status. - - In order to run a service, the service must be installed in the - system's service database using the install() function. The system - will start the service depending on the specified StartupType; it - can either be started during system startup, or when a process - starts it manually. - - Once a service is installed, the service can be run and controlled - manually using the start(), stop(), pause(), resume() or - sendCommand() functions. You can at any time query for the - service's status using the isInstalled() and isRunning() - functions, or you can query its properties using the - serviceDescription(), serviceFilePath(), serviceName() and - startupType() functions. For example: - - \code - MyService service; \\ which inherits QtService - QString serviceFilePath; - - QtServiceController controller(service.serviceName()); - - if (controller.install(serviceFilePath)) - controller.start() - - if (controller.isRunning()) - QMessageBox::information(this, tr("Service Status"), - tr("The %1 service is started").arg(controller.serviceName())); - - ... - - controller.stop(); - controller.uninstall(); - } - \endcode - - An instance of the service controller can only control one single - service. To control several services within one application, you - must create en equal number of service controllers. - - The QtServiceController destructor neither stops nor uninstalls - the associated service. To stop a service the stop() function must - be called explicitly. To uninstall a service, you can use the - uninstall() function. - - \sa QtServiceBase, QtService -*/ - -/*! - \enum QtServiceController::StartupType - This enum describes when a service should be started. - - \value AutoStartup The service is started during system startup. - \value ManualStartup The service must be started manually by a process. - - \warning The \a StartupType enum is ignored under UNIX-like - systems. A service, or daemon, can only be started manually on such - systems with current implementation. - - \sa startupType() -*/ - - -/*! - Creates a controller object for the service with the given - \a name. -*/ -QtServiceController::QtServiceController(const QString &name) - : d_ptr(new QtServiceControllerPrivate()) -{ - Q_D(QtServiceController); - d->q_ptr = this; - d->serviceName = name; -} -/*! - Destroys the service controller. This neither stops nor uninstalls - the controlled service. - - To stop a service the stop() function must be called - explicitly. To uninstall a service, you can use the uninstall() - function. - - \sa stop(), QtServiceController::uninstall() -*/ -QtServiceController::~QtServiceController() -{ - delete d_ptr; -} -/*! - \fn bool QtServiceController::isInstalled() const - - Returns true if the service is installed; otherwise returns false. - - On Windows it uses the system's service control manager. - - On Unix it checks configuration written to QSettings::SystemScope - using "QtSoftware" as organization name. - - \sa install() -*/ - -/*! - \fn bool QtServiceController::isRunning() const - - Returns true if the service is running; otherwise returns false. A - service must be installed before it can be run using a controller. - - \sa start(), isInstalled() -*/ - -/*! - Returns the name of the controlled service. - - \sa QtServiceController(), serviceDescription() -*/ -QString QtServiceController::serviceName() const -{ - Q_D(const QtServiceController); - return d->serviceName; -} -/*! - \fn QString QtServiceController::serviceDescription() const - - Returns the description of the controlled service. - - \sa install(), serviceName() -*/ - -/*! - \fn QtServiceController::StartupType QtServiceController::startupType() const - - Returns the startup type of the controlled service. - - \sa install(), serviceName() -*/ - -/*! - \fn QString QtServiceController::serviceFilePath() const - - Returns the file path to the controlled service. - - \sa install(), serviceName() -*/ - -/*! - Installs the service with the given \a serviceFilePath - and returns true if the service is installed - successfully; otherwise returns false. - - On Windows service is installed in the system's service control manager with the given - \a account and \a password. - - On Unix service configuration is written to QSettings::SystemScope - using "QtSoftware" as organization name. \a account and \a password - arguments are ignored. - - \warning Due to the different implementations of how services (daemons) - are installed on various UNIX-like systems, this method doesn't - integrate the service into the system's startup scripts. - - \sa uninstall(), start() -*/ -bool QtServiceController::install(const QString &serviceFilePath, const QString &account, - const QString &password) -{ - QStringList arguments; - arguments << QLatin1String("-i"); - arguments << account; - arguments << password; - return (QProcess::execute(serviceFilePath, arguments) == 0); -} - - -/*! - \fn bool QtServiceController::uninstall() - - Uninstalls the service and returns true if successful; otherwise returns false. - - On Windows service is uninstalled using the system's service control manager. - - On Unix service configuration is cleared using QSettings::SystemScope - with "QtSoftware" as organization name. - - - \sa install() -*/ - -/*! - \fn bool QtServiceController::start(const QStringList &arguments) - - Starts the installed service passing the given \a arguments to the - service. A service must be installed before a controller can run it. - - Returns true if the service could be started; otherwise returns - false. - - \sa install(), stop() -*/ - -/*! - \overload - - Starts the installed service without passing any arguments to the service. -*/ -bool QtServiceController::start() -{ - return start(QStringList()); -} - -/*! - \fn bool QtServiceController::stop() - - Requests the running service to stop. The service will call the - QtServiceBase::stop() implementation unless the service's state - is QtServiceBase::CannotBeStopped. This function does nothing if - the service is not running. - - Returns true if a running service was successfully stopped; - otherwise false. - - \sa start(), QtServiceBase::stop(), QtServiceBase::ServiceFlags -*/ - -/*! - \fn bool QtServiceController::pause() - - Requests the running service to pause. If the service's state is - QtServiceBase::CanBeSuspended, the service will call the - QtServiceBase::pause() implementation. The function does nothing - if the service is not running. - - Returns true if a running service was successfully paused; - otherwise returns false. - - \sa resume(), QtServiceBase::pause(), QtServiceBase::ServiceFlags -*/ - -/*! - \fn bool QtServiceController::resume() - - Requests the running service to continue. If the service's state - is QtServiceBase::CanBeSuspended, the service will call the - QtServiceBase::resume() implementation. This function does nothing - if the service is not running. - - Returns true if a running service was successfully resumed; - otherwise returns false. - - \sa pause(), QtServiceBase::resume(), QtServiceBase::ServiceFlags -*/ - -/*! - \fn bool QtServiceController::sendCommand(int code) - - Sends the user command \a code to the service. The service will - call the QtServiceBase::processCommand() implementation. This - function does nothing if the service is not running. - - Returns true if the request was sent to a running service; - otherwise returns false. - - \sa QtServiceBase::processCommand() -*/ - -class QtServiceStarter : public QObject -{ - Q_OBJECT -public: - QtServiceStarter(QtServiceBasePrivate *service) - : QObject(), d_ptr(service) {} -public slots: - void slotStart() - { - d_ptr->startService(); - } -private: - QtServiceBasePrivate *d_ptr; -}; -#include "qtservice.moc" - -QtServiceBase *QtServiceBasePrivate::instance = 0; - -QtServiceBasePrivate::QtServiceBasePrivate(const QString &name) - : startupType(QtServiceController::ManualStartup), serviceFlags(0), controller(name) -{ - -} - -QtServiceBasePrivate::~QtServiceBasePrivate() -{ - -} - -void QtServiceBasePrivate::startService() -{ - q_ptr->start(); -} - -int QtServiceBasePrivate::run(bool asService, const QStringList &argList) -{ - int argc = argList.size(); - QVector argv(argc); - QList argvData; - for (int i = 0; i < argc; ++i) - argvData.append(argList.at(i).toLocal8Bit()); - for (int i = 0; i < argc; ++i) - argv[i] = argvData[i].data(); - - if (asService && !sysInit()) - return -1; - - q_ptr->createApplication(argc, argv.data()); - QCoreApplication *app = QCoreApplication::instance(); - if (!app) - return -1; - - if (asService) - sysSetPath(); - - QtServiceStarter starter(this); - QTimer::singleShot(0, &starter, SLOT(slotStart())); - int res = q_ptr->executeApplication(); - delete app; - - if (asService) - sysCleanup(); - return res; -} - - -/*! - \class QtServiceBase - - \brief The QtServiceBase class provides an API for implementing - Windows services and Unix daemons. - - A Windows service or Unix daemon (a "service"), is a program that - runs "in the background" independently of whether a user is logged - in or not. A service is often set up to start when the machine - boots up, and will typically run continuously as long as the - machine is on. - - Services are usually non-interactive console applications. User - interaction, if required, is usually implemented in a separate, - normal GUI application that communicates with the service through - an IPC channel. For simple communication, - QtServiceController::sendCommand() and QtService::processCommand() - may be used, possibly in combination with a shared settings - file. For more complex, interactive communication, a custom IPC - channel should be used, e.g. based on Qt's networking classes. (In - certain circumstances, a service may provide a GUI itself, - ref. the "interactive" example documentation). - - Typically, you will create a service by subclassing the QtService - template class which inherits QtServiceBase and allows you to - create a service for a particular application type. - - The Windows implementation uses the NT Service Control Manager, - and the application can be controlled through the system - administration tools. Services are usually launched using the - system account, which requires that all DLLs that the service - executable depends on (i.e. Qt), are located in the same directory - as the service, or in a system path. - - On Unix a service is implemented as a daemon. - - You can retrieve the service's description, state, and startup - type using the serviceDescription(), serviceFlags() and - startupType() functions respectively. The service's state is - decribed by the ServiceFlag enum. The mentioned properites can - also be set using the corresponding set functions. In addition you - can retrieve the service's name using the serviceName() function. - - Several of QtServiceBase's protected functions are called on - requests from the QtServiceController class: - - \list - \o start() - \o pause() - \o processCommand() - \o resume() - \o stop() - \endlist - - You can control any given service using an instance of the - QtServiceController class which also allows you to control - services from separate applications. The mentioned functions are - all virtual and won't do anything unless they are - reimplemented. You can reimplement these functions to pause and - resume the service's execution, as well as process user commands - and perform additional clean-ups before shutting down. - - QtServiceBase also provides the static instance() function which - returns a pointer to an application's QtServiceBase instance. In - addition, a service can report events to the system's event log - using the logMessage() function. The MessageType enum describes - the different types of messages a service reports. - - The implementation of a service application's main function - typically creates an service object derived by subclassing the - QtService template class. Then the main function will call this - service's exec() function, and return the result of that call. For - example: - - \code - int main(int argc, char **argv) - { - MyService service(argc, argv); - return service.exec(); - } - \endcode - - When the exec() function is called, it will parse the service - specific arguments passed in \c argv, perform the required - actions, and return. - - \target serviceSpecificArguments - - The following arguments are recognized as service specific: - - \table - \header \i Short \i Long \i Explanation - \row \i -i \i -install \i Install the service. - \row \i -u \i -uninstall \i Uninstall the service. - \row \i -e \i -exec - \i Execute the service as a standalone application (useful for debug purposes). - This is a blocking call, the service will be executed like a normal application. - In this mode you will not be able to communicate with the service from the contoller. - \row \i -t \i -terminate \i Stop the service. - \row \i -p \i -pause \i Pause the service. - \row \i -r \i -resume \i Resume a paused service. - \row \i -c \e{cmd} \i -command \e{cmd} - \i Send the user defined command code \e{cmd} to the service application. - \row \i -v \i -version \i Display version and status information. - \endtable - - If \e none of the arguments is recognized as service specific, - exec() will first call the createApplication() function, then - executeApplication() and finally the start() function. In the end, - exec() returns while the service continues in its own process - waiting for commands from the service controller. - - \sa QtService, QtServiceController -*/ - -/*! - \enum QtServiceBase::MessageType - - This enum describes the different types of messages a service - reports to the system log. - - \value Success An operation has succeeded, e.g. the service - is started. - \value Error An operation failed, e.g. the service failed to start. - \value Warning An operation caused a warning that might require user - interaction. - \value Information Any type of usually non-critical information. -*/ - -/*! - \enum QtServiceBase::ServiceFlag - - This enum describes the different states of a service. - - \value Default The service can be stopped, but not suspended. - \value CanBeSuspended The service can be suspended. - \value CannotBeStopped The service cannot be stopped. -*/ - -/*! - Creates a service instance called \a name. The \a argc and \a argv - parameters are parsed after the exec() function has been - called. Then they are passed to the application's constructor. - The application type is determined by the QtService subclass. - - The service is neither installed nor started. The name must not - contain any backslashes or be longer than 255 characters. In - addition, the name must be unique in the system's service - database. - - \sa exec(), start(), QtServiceController::install() -*/ -QtServiceBase::QtServiceBase(int argc, char **argv, const QString &name) -{ -#if defined(QTSERVICE_DEBUG) - qInstallMsgHandler(qtServiceLogDebug); - qAddPostRoutine(qtServiceCloseDebugLog); -#endif - - Q_ASSERT(!QtServiceBasePrivate::instance); - QtServiceBasePrivate::instance = this; - - QString nm(name); - if (nm.length() > 255) { - qWarning("QtService: 'name' is longer than 255 characters."); - nm.truncate(255); - } - if (nm.contains('\\')) { - qWarning("QtService: 'name' contains backslashes '\\'."); - nm.replace((QChar)'\\', (QChar)'\0'); - } - - d_ptr = new QtServiceBasePrivate(nm); - d_ptr->q_ptr = this; - - d_ptr->serviceFlags = 0; - d_ptr->sysd = 0; - for (int i = 0; i < argc; ++i) - d_ptr->args.append(QString::fromLocal8Bit(argv[i])); -} - -/*! - Destroys the service object. This neither stops nor uninstalls the - service. - - To stop a service the stop() function must be called - explicitly. To uninstall a service, you can use the - QtServiceController::uninstall() function. - - \sa stop(), QtServiceController::uninstall() -*/ -QtServiceBase::~QtServiceBase() -{ - delete d_ptr; - QtServiceBasePrivate::instance = 0; -} - -/*! - Returns the name of the service. - - \sa QtServiceBase(), serviceDescription() -*/ -QString QtServiceBase::serviceName() const -{ - return d_ptr->controller.serviceName(); -} - -/*! - Returns the description of the service. - - \sa setServiceDescription(), serviceName() -*/ -QString QtServiceBase::serviceDescription() const -{ - return d_ptr->serviceDescription; -} - -/*! - Sets the description of the service to the given \a description. - - \sa serviceDescription() -*/ -void QtServiceBase::setServiceDescription(const QString &description) -{ - d_ptr->serviceDescription = description; -} - -/*! - Returns the service's startup type. - - \sa QtServiceController::StartupType, setStartupType() -*/ -QtServiceController::StartupType QtServiceBase::startupType() const -{ - return d_ptr->startupType; -} - -/*! - Sets the service's startup type to the given \a type. - - \sa QtServiceController::StartupType, startupType() -*/ -void QtServiceBase::setStartupType(QtServiceController::StartupType type) -{ - d_ptr->startupType = type; -} - -/*! - Returns the service's state which is decribed using the - ServiceFlag enum. - - \sa ServiceFlags, setServiceFlags() -*/ -QtServiceBase::ServiceFlags QtServiceBase::serviceFlags() const -{ - return d_ptr->serviceFlags; -} - -/*! - \fn void QtServiceBase::setServiceFlags(ServiceFlags flags) - - Sets the service's state to the state described by the given \a - flags. - - \sa ServiceFlags, serviceFlags() -*/ - -/*! - Executes the service. - - When the exec() function is called, it will parse the \l - {serviceSpecificArguments} {service specific arguments} passed in - \c argv, perform the required actions, and exit. - - If none of the arguments is recognized as service specific, exec() - will first call the createApplication() function, then executeApplication() and - finally the start() function. In the end, exec() - returns while the service continues in its own process waiting for - commands from the service controller. - - \sa QtServiceController -*/ -int QtServiceBase::exec() -{ - if (d_ptr->args.size() > 1) { - QString a = d_ptr->args.at(1); - if (a == QLatin1String("-i") || a == QLatin1String("-install")) { - if (!d_ptr->controller.isInstalled()) { - QString account; - QString password; - if (d_ptr->args.size() > 2) - account = d_ptr->args.at(2); - if (d_ptr->args.size() > 3) - password = d_ptr->args.at(3); - if (!d_ptr->install(account, password)) { - fprintf(stderr, "The service %s could not be installed\n", serviceName().toLatin1().constData()); - return -1; - } else { - printf("The service %s has been installed under: %s\n", - serviceName().toLatin1().constData(), d_ptr->filePath().toLatin1().constData()); - } - } else { - fprintf(stderr, "The service %s is already installed\n", serviceName().toLatin1().constData()); - } - return 0; - } else if (a == QLatin1String("-u") || a == QLatin1String("-uninstall")) { - if (d_ptr->controller.isInstalled()) { - if (!d_ptr->controller.uninstall()) { - fprintf(stderr, "The service %s could not be uninstalled\n", serviceName().toLatin1().constData()); - return -1; - } else { - printf("The service %s has been uninstalled.\n", - serviceName().toLatin1().constData()); - } - } else { - fprintf(stderr, "The service %s is not installed\n", serviceName().toLatin1().constData()); - } - return 0; - } else if (a == QLatin1String("-v") || a == QLatin1String("-version")) { - printf("The service\n" - "\t%s\n\t%s\n\n", serviceName().toLatin1().constData(), d_ptr->args.at(0).toLatin1().constData()); - printf("is %s", (d_ptr->controller.isInstalled() ? "installed" : "not installed")); - printf(" and %s\n\n", (d_ptr->controller.isRunning() ? "running" : "not running")); - return 0; - } else if (a == QLatin1String("-e") || a == QLatin1String("-exec")) { - d_ptr->args.removeAt(1); - int ec = d_ptr->run(false, d_ptr->args); - if (ec == -1) - qErrnoWarning("The service could not be executed."); - return ec; - } else if (a == QLatin1String("-t") || a == QLatin1String("-terminate")) { - if (!d_ptr->controller.stop()) - qErrnoWarning("The service could not be stopped."); - return 0; - } else if (a == QLatin1String("-p") || a == QLatin1String("-pause")) { - d_ptr->controller.pause(); - return 0; - } else if (a == QLatin1String("-r") || a == QLatin1String("-resume")) { - d_ptr->controller.resume(); - return 0; - } else if (a == QLatin1String("-c") || a == QLatin1String("-command")) { - int code = 0; - if (d_ptr->args.size() > 2) - code = d_ptr->args.at(2).toInt(); - d_ptr->controller.sendCommand(code); - return 0; - } else if (a == QLatin1String("-h") || a == QLatin1String("-help")) { - printf("\n%s -[i|u|e|s|v|h]\n" - "\t-i(nstall) [account] [password]\t: Install the service, optionally using given account and password\n" - "\t-u(ninstall)\t: Uninstall the service.\n" - "\t-e(xec)\t\t: Run as a regular application. Useful for debugging.\n" - "\t-t(erminate)\t: Stop the service.\n" - "\t-c(ommand) num\t: Send command code num to the service.\n" - "\t-v(ersion)\t: Print version and status information.\n" - "\t-h(elp) \t: Show this help\n" - "\tNo arguments\t: Start the service.\n", - d_ptr->args.at(0).toLatin1().constData()); - return 0; - } - } -#if defined(Q_OS_UNIX) - if (::getenv("QTSERVICE_RUN")) { - // Means we're the detached, real service process. - int ec = d_ptr->run(true, d_ptr->args); - if (ec == -1) - qErrnoWarning("The service failed to run."); - return ec; - } -#endif - if (!d_ptr->start()) { - fprintf(stderr, "The service %s could not start\n", serviceName().toLatin1().constData()); - return -4; - } - return 0; -} - -/*! - \fn void QtServiceBase::logMessage(const QString &message, MessageType type, - int id, uint category, const QByteArray &data) - - Reports a message of the given \a type with the given \a message - to the local system event log. The message identifier \a id and - the message \a category are user defined values. The \a data - parameter can contain arbitrary binary data. - - Message strings for \a id and \a category must be provided by a - message file, which must be registered in the system registry. - Refer to the MSDN for more information about how to do this on - Windows. - - \sa MessageType -*/ - -/*! - Returns a pointer to the current application's QtServiceBase - instance. -*/ -QtServiceBase *QtServiceBase::instance() -{ - return QtServiceBasePrivate::instance; -} - -/*! - \fn void QtServiceBase::start() - - This function must be implemented in QtServiceBase subclasses in - order to perform the service's work. Usually you create some main - object on the heap which is the heart of your service. - - The function is only called when no service specific arguments - were passed to the service constructor, and is called by exec() - after it has called the executeApplication() function. - - Note that you \e don't need to create an application object or - call its exec() function explicitly. - - \sa exec(), stop(), QtServiceController::start() -*/ - -/*! - Reimplement this function to perform additional cleanups before - shutting down (for example deleting a main object if it was - created in the start() function). - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa start(), QtServiceController::stop() -*/ -void QtServiceBase::stop() -{ -} - -/*! - Reimplement this function to pause the service's execution (for - example to stop a polling timer, or to ignore socket notifiers). - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa resume(), QtServiceController::pause() -*/ -void QtServiceBase::pause() -{ -} - -/*! - Reimplement this function to continue the service after a call to - pause(). - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa pause(), QtServiceController::resume() -*/ -void QtServiceBase::resume() -{ -} - -/*! - Reimplement this function to process the user command \a code. - - - This function is called in reply to controller requests. The - default implementation does nothing. - - \sa QtServiceController::sendCommand() -*/ -void QtServiceBase::processCommand(int /*code*/) -{ -} - -/*! - \fn void QtServiceBase::createApplication(int &argc, char **argv) - - Creates the application object using the \a argc and \a argv - parameters. - - This function is only called when no \l - {serviceSpecificArguments}{service specific arguments} were - passed to the service constructor, and is called by exec() before - it calls the executeApplication() and start() functions. - - The createApplication() function is implemented in QtService, but - you might want to reimplement it, for example, if the chosen - application type's constructor needs additional arguments. - - \sa exec(), QtService -*/ - -/*! - \fn int QtServiceBase::executeApplication() - - Executes the application previously created with the - createApplication() function. - - This function is only called when no \l - {serviceSpecificArguments}{service specific arguments} were - passed to the service constructor, and is called by exec() after - it has called the createApplication() function and before start() function. - - This function is implemented in QtService. - - \sa exec(), createApplication() -*/ - -/*! - \class QtService - - \brief The QtService is a convenient template class that allows - you to create a service for a particular application type. - - A Windows service or Unix daemon (a "service"), is a program that - runs "in the background" independently of whether a user is logged - in or not. A service is often set up to start when the machine - boots up, and will typically run continuously as long as the - machine is on. - - Services are usually non-interactive console applications. User - interaction, if required, is usually implemented in a separate, - normal GUI application that communicates with the service through - an IPC channel. For simple communication, - QtServiceController::sendCommand() and QtService::processCommand() - may be used, possibly in combination with a shared settings file. For - more complex, interactive communication, a custom IPC channel - should be used, e.g. based on Qt's networking classes. (In certain - circumstances, a service may provide a GUI itself, ref. the - "interactive" example documentation). - - \bold{Note:} On Unix systems, this class relies on facilities - provided by the QtNetwork module, provided as part of the - \l{Qt Open Source Edition} and certain \l{Qt Commercial Editions}. - - The QtService class functionality is inherited from QtServiceBase, - but in addition the QtService class binds an instance of - QtServiceBase with an application type. - - Typically, you will create a service by subclassing the QtService - template class. For example: - - \code - class MyService : public QtService - { - public: - MyService(int argc, char **argv); - ~MyService(); - - protected: - void start(); - void stop(); - void pause(); - void resume(); - void processCommand(int code); - }; - \endcode - - The application type can be QCoreApplication for services without - GUI, QApplication for services with GUI or you can use your own - custom application type. - - You must reimplement the QtServiceBase::start() function to - perform the service's work. Usually you create some main object on - the heap which is the heart of your service. - - In addition, you might want to reimplement the - QtServiceBase::pause(), QtServiceBase::processCommand(), - QtServiceBase::resume() and QtServiceBase::stop() to intervene the - service's process on controller requests. You can control any - given service using an instance of the QtServiceController class - which also allows you to control services from separate - applications. The mentioned functions are all virtual and won't do - anything unless they are reimplemented. - - Your custom service is typically instantiated in the application's - main function. Then the main function will call your service's - exec() function, and return the result of that call. For example: - - \code - int main(int argc, char **argv) - { - MyService service(argc, argv); - return service.exec(); - } - \endcode - - When the exec() function is called, it will parse the \l - {serviceSpecificArguments} {service specific arguments} passed in - \c argv, perform the required actions, and exit. - - If none of the arguments is recognized as service specific, exec() - will first call the createApplication() function, then executeApplication() and - finally the start() function. In the end, exec() - returns while the service continues in its own process waiting for - commands from the service controller. - - \sa QtServiceBase, QtServiceController -*/ - -/*! - \fn QtService::QtService(int argc, char **argv, const QString &name) - - Constructs a QtService object called \a name. The \a argc and \a - argv parameters are parsed after the exec() function has been - called. Then they are passed to the application's constructor. - - There can only be one QtService object in a process. - - \sa QtServiceBase() -*/ - -/*! - \fn QtService::~QtService() - - Destroys the service object. -*/ - -/*! - \fn Application *QtService::application() const - - Returns a pointer to the application object. -*/ - -/*! - \fn void QtService::createApplication(int &argc, char **argv) - - Creates application object of type Application passing \a argc and - \a argv to its constructor. - - \reimp - -*/ - -/*! - \fn int QtService::executeApplication() - - \reimp -*/ - - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h deleted file mode 100644 index a0230e28..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.h +++ /dev/null @@ -1,197 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTSERVICE_H -#define QTSERVICE_H - -#include - -#if defined(Q_WS_WIN) -# if !defined(QT_QTSERVICE_EXPORT) && !defined(QT_QTSERVICE_IMPORT) -# define QT_QTSERVICE_EXPORT -# elif defined(QT_QTSERVICE_IMPORT) -# if defined(QT_QTSERVICE_EXPORT) -# undef QT_QTSERVICE_EXPORT -# endif -# define QT_QTSERVICE_EXPORT __declspec(dllimport) -# elif defined(QT_QTSERVICE_EXPORT) -# undef QT_QTSERVICE_EXPORT -# define QT_QTSERVICE_EXPORT __declspec(dllexport) -# endif -#else -# define QT_QTSERVICE_EXPORT -#endif - -class QStringList; -class QtServiceControllerPrivate; - -class QT_QTSERVICE_EXPORT QtServiceController -{ - Q_DECLARE_PRIVATE(QtServiceController) -public: - enum StartupType - { - AutoStartup = 0, ManualStartup - }; - - QtServiceController(const QString &name); - virtual ~QtServiceController(); - - bool isInstalled() const; - bool isRunning() const; - - QString serviceName() const; - QString serviceDescription() const; - StartupType startupType() const; - QString serviceFilePath() const; - - static bool install(const QString &serviceFilePath, const QString &account = QString(), - const QString &password = QString()); - bool uninstall(); - - bool start(const QStringList &arguments); - bool start(); - bool stop(); - bool pause(); - bool resume(); - bool sendCommand(int code); - -private: - QtServiceControllerPrivate *d_ptr; -}; - -class QtServiceBasePrivate; - -class QT_QTSERVICE_EXPORT QtServiceBase -{ - Q_DECLARE_PRIVATE(QtServiceBase) -public: - - enum MessageType - { - Success = 0, Error, Warning, Information - }; - - enum ServiceFlag - { - Default = 0x00, - CanBeSuspended = 0x01, - CannotBeStopped = 0x02 - }; - - Q_DECLARE_FLAGS(ServiceFlags, ServiceFlag) - - QtServiceBase(int argc, char **argv, const QString &name); - virtual ~QtServiceBase(); - - QString serviceName() const; - - QString serviceDescription() const; - void setServiceDescription(const QString &description); - - QtServiceController::StartupType startupType() const; - void setStartupType(QtServiceController::StartupType startupType); - - ServiceFlags serviceFlags() const; - void setServiceFlags(ServiceFlags flags); - - int exec(); - - void logMessage(const QString &message, MessageType type = Success, - int id = 0, uint category = 0, const QByteArray &data = QByteArray()); - - static QtServiceBase *instance(); - -protected: - - virtual void start() = 0; - virtual void stop(); - virtual void pause(); - virtual void resume(); - virtual void processCommand(int code); - - virtual void createApplication(int &argc, char **argv) = 0; - - virtual int executeApplication() = 0; - -private: - - friend class QtServiceSysPrivate; - QtServiceBasePrivate *d_ptr; -}; - -template -class QtService : public QtServiceBase -{ -public: - QtService(int argc, char **argv, const QString &name) - : QtServiceBase(argc, argv, name), app(0) - { } - ~QtService() - { - } - -protected: - Application *application() const - { return app; } - - virtual void createApplication(int &argc, char **argv) - { - app = new Application(argc, argv); - QCoreApplication *a = app; - Q_UNUSED(a); - } - - virtual int executeApplication() - { return Application::exec(); } - -private: - Application *app; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QtServiceBase::ServiceFlags) - -#endif // QTSERVICE_H diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri deleted file mode 100644 index 658a3288..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice.pri +++ /dev/null @@ -1,21 +0,0 @@ -include(../common.pri) -INCLUDEPATH += $$PWD -DEPENDPATH += $$PWD -!win32:QT += network -win32:LIBS += -luser32 - -qtservice-uselib:!qtservice-buildlib { - LIBS += -L$$QTSERVICE_LIBDIR -l$$QTSERVICE_LIBNAME -} else { - HEADERS += $$PWD/qtservice.h \ - $$PWD/qtservice_p.h - SOURCES += $$PWD/qtservice.cpp - win32:SOURCES += $$PWD/qtservice_win.cpp - unix:HEADERS += $$PWD/qtunixsocket.h $$PWD/qtunixserversocket.h - unix:SOURCES += $$PWD/qtservice_unix.cpp $$PWD/qtunixsocket.cpp $$PWD/qtunixserversocket.cpp -} - -win32 { - contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSERVICE_EXPORT - else:qtservice-uselib:DEFINES += QT_QTSERVICE_IMPORT -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h deleted file mode 100644 index fc5e6b82..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_p.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTSERVICE_P_H -#define QTSERVICE_P_H - -#include -#include "qtservice.h" - -class QtServiceControllerPrivate -{ - Q_DECLARE_PUBLIC(QtServiceController) -public: - QString serviceName; - QtServiceController *q_ptr; -}; - -class QtServiceBasePrivate -{ - Q_DECLARE_PUBLIC(QtServiceBase) -public: - - QtServiceBasePrivate(const QString &name); - ~QtServiceBasePrivate(); - - QtServiceBase *q_ptr; - - QString serviceDescription; - QtServiceController::StartupType startupType; - QtServiceBase::ServiceFlags serviceFlags; - QStringList args; - - static class QtServiceBase *instance; - - QtServiceController controller; - - void startService(); - int run(bool asService, const QStringList &argList); - bool install(const QString &account, const QString &password); - - bool start(); - - QString filePath() const; - bool sysInit(); - void sysSetPath(); - void sysCleanup(); - class QtServiceSysPrivate *sysd; -}; - -#endif diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp deleted file mode 100644 index 7e4ec700..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp +++ /dev/null @@ -1,480 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtservice.h" -#include "qtservice_p.h" -#include "qtunixsocket.h" -#include "qtunixserversocket.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static QString encodeName(const QString &name, bool allowUpper = false) -{ - QString n = name.toLower(); - QString legal = QLatin1String("abcdefghijklmnopqrstuvwxyz1234567890"); - if (allowUpper) - legal += QLatin1String("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - int pos = 0; - while (pos < n.size()) { - if (legal.indexOf(n[pos]) == -1) - n.remove(pos, 1); - else - ++pos; - } - return n; -} - -static QString login() -{ - QString l; - uid_t uid = getuid(); - passwd *pw = getpwuid(uid); - if (pw) - l = QString(pw->pw_name); - return l; -} - -static QString socketPath(const QString &serviceName) -{ - QString sn = encodeName(serviceName); - return QString(QLatin1String("/var/tmp/") + sn + QLatin1String(".") + login()); -} - -static bool sendCmd(const QString &serviceName, const QString &cmd) -{ - bool retValue = false; - QtUnixSocket sock; - if (sock.connectTo(socketPath(serviceName))) { - sock.write(QString(cmd+"\r\n").toLatin1().constData()); - sock.flush(); - sock.waitForReadyRead(-1); - QString reply = sock.readAll(); - if (reply == QLatin1String("true")) - retValue = true; - sock.close(); - } - return retValue; -} - -static QString absPath(const QString &path) -{ - QString ret; - if (path[0] != QChar('/')) { // Not an absolute path - int slashpos; - if ((slashpos = path.lastIndexOf('/')) != -1) { // Relative path - QDir dir = QDir::current(); - dir.cd(path.left(slashpos)); - ret = dir.absolutePath(); - } else { // Need to search $PATH - char *envPath = ::getenv("PATH"); - if (envPath) { - QStringList envPaths = QString::fromLocal8Bit(envPath).split(':'); - for (int i = 0; i < envPaths.size(); ++i) { - if (QFile::exists(envPaths.at(i) + QLatin1String("/") + QString(path))) { - QDir dir(envPaths.at(i)); - ret = dir.absolutePath(); - break; - } - } - } - } - } else { - QFileInfo fi(path); - ret = fi.absolutePath(); - } - return ret; -} - -QString QtServiceBasePrivate::filePath() const -{ - QString ret; - if (args.isEmpty()) - return ret; - QFileInfo fi(args[0]); - QDir dir(absPath(args[0])); - return dir.absoluteFilePath(fi.fileName()); -} - - -QString QtServiceController::serviceDescription() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - settings.beginGroup(serviceName()); - - QString desc = settings.value("description").toString(); - - settings.endGroup(); - settings.endGroup(); - - return desc; -} - -QtServiceController::StartupType QtServiceController::startupType() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - settings.beginGroup(serviceName()); - - StartupType startupType = (StartupType)settings.value("startupType").toInt(); - - settings.endGroup(); - settings.endGroup(); - - return startupType; -} - -QString QtServiceController::serviceFilePath() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - settings.beginGroup(serviceName()); - - QString path = settings.value("path").toString(); - - settings.endGroup(); - settings.endGroup(); - - return path; -} - -bool QtServiceController::uninstall() -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - - settings.remove(serviceName()); - - settings.endGroup(); - settings.sync(); - - QSettings::Status ret = settings.status(); - if (ret == QSettings::AccessError) { - fprintf(stderr, "Cannot uninstall \"%s\". Cannot write to: %s. Check permissions.\n", - serviceName().toLatin1().constData(), - settings.fileName().toLatin1().constData()); - } - return (ret == QSettings::NoError); -} - - -bool QtServiceController::start(const QStringList &arguments) -{ - if (!isInstalled()) - return false; - if (isRunning()) - return false; - return QProcess::startDetached(serviceFilePath(), arguments); -} - -bool QtServiceController::stop() -{ - return sendCmd(serviceName(), QLatin1String("terminate")); -} - -bool QtServiceController::pause() -{ - return sendCmd(serviceName(), QLatin1String("pause")); -} - -bool QtServiceController::resume() -{ - return sendCmd(serviceName(), QLatin1String("resume")); -} - -bool QtServiceController::sendCommand(int code) -{ - return sendCmd(serviceName(), QString(QLatin1String("num:") + QString::number(code))); -} - -bool QtServiceController::isInstalled() const -{ - QSettings settings(QSettings::SystemScope, "QtSoftware"); - settings.beginGroup("services"); - - QStringList list = settings.childGroups(); - - settings.endGroup(); - - QStringListIterator it(list); - while (it.hasNext()) { - if (it.next() == serviceName()) - return true; - } - - return false; -} - -bool QtServiceController::isRunning() const -{ - QtUnixSocket sock; - if (sock.connectTo(socketPath(serviceName()))) - return true; - return false; -} - - - - -/////////////////////////////////// - -class QtServiceSysPrivate : public QtUnixServerSocket -{ - Q_OBJECT -public: - QtServiceSysPrivate(); - ~QtServiceSysPrivate(); - - char *ident; - - QtServiceBase::ServiceFlags serviceFlags; - -protected: - void incomingConnection(int socketDescriptor); - -private slots: - void slotReady(); - void slotClosed(); - -private: - QString getCommand(const QTcpSocket *socket); - QMap cache; -}; - -QtServiceSysPrivate::QtServiceSysPrivate() - : QtUnixServerSocket(), ident(0), serviceFlags(0) -{ -} - -QtServiceSysPrivate::~QtServiceSysPrivate() -{ - if (ident) - delete[] ident; -} - -void QtServiceSysPrivate::incomingConnection(int socketDescriptor) -{ - QTcpSocket *s = new QTcpSocket(this); - s->setSocketDescriptor(socketDescriptor); - connect(s, SIGNAL(readyRead()), this, SLOT(slotReady())); - connect(s, SIGNAL(disconnected()), this, SLOT(slotClosed())); -} - -void QtServiceSysPrivate::slotReady() -{ - QTcpSocket *s = (QTcpSocket *)sender(); - cache[s] += QString(s->readAll()); - QString cmd = getCommand(s); - while (!cmd.isEmpty()) { - bool retValue = false; - if (cmd == QLatin1String("terminate")) { - if (!(serviceFlags & QtServiceBase::CannotBeStopped)) { - QtServiceBase::instance()->stop(); - QCoreApplication::instance()->quit(); - retValue = true; - } - } else if (cmd == QLatin1String("pause")) { - if (serviceFlags & QtServiceBase::CanBeSuspended) { - QtServiceBase::instance()->pause(); - retValue = true; - } - } else if (cmd == QLatin1String("resume")) { - if (serviceFlags & QtServiceBase::CanBeSuspended) { - QtServiceBase::instance()->resume(); - retValue = true; - } - } else if (cmd == QLatin1String("alive")) { - retValue = true; - } else if (cmd.length() > 4 && cmd.left(4) == QLatin1String("num:")) { - cmd = cmd.mid(4); - QtServiceBase::instance()->processCommand(cmd.toInt()); - retValue = true; - } - QString retString; - if (retValue) - retString = QLatin1String("true"); - else - retString = QLatin1String("false"); - s->write(retString.toLatin1().constData()); - s->flush(); - cmd = getCommand(s); - } -} - -void QtServiceSysPrivate::slotClosed() -{ - QTcpSocket *s = (QTcpSocket *)sender(); - s->deleteLater(); -} - -QString QtServiceSysPrivate::getCommand(const QTcpSocket *socket) -{ - int pos = cache[socket].indexOf("\r\n"); - if (pos >= 0) { - QString ret = cache[socket].left(pos); - cache[socket].remove(0, pos+2); - return ret; - } - return ""; -} - -#include "qtservice_unix.moc" - -bool QtServiceBasePrivate::sysInit() -{ - sysd = new QtServiceSysPrivate; - sysd->serviceFlags = serviceFlags; - // Restrict permissions on files that are created by the service - ::umask(027); - - return true; -} - -void QtServiceBasePrivate::sysSetPath() -{ - if (sysd) - sysd->setPath(socketPath(controller.serviceName())); -} - -void QtServiceBasePrivate::sysCleanup() -{ - if (sysd) { - sysd->close(); - delete sysd; - sysd = 0; - } -} - -bool QtServiceBasePrivate::start() -{ - if (sendCmd(controller.serviceName(), "alive")) { - // Already running - return false; - } - // Could just call controller.start() here, but that would fail if - // we're not installed. We do not want to strictly require installation. - ::setenv("QTSERVICE_RUN", "1", 1); // Tell the detached process it's it - return QProcess::startDetached(filePath(), args.mid(1), "/"); -} - -bool QtServiceBasePrivate::install(const QString &account, const QString &password) -{ - Q_UNUSED(account) - Q_UNUSED(password) - QSettings settings(QSettings::SystemScope, "QtSoftware"); - - settings.beginGroup("services"); - settings.beginGroup(controller.serviceName()); - - settings.setValue("path", filePath()); - settings.setValue("description", serviceDescription); - settings.setValue("automaticStartup", startupType); - - settings.endGroup(); - settings.endGroup(); - settings.sync(); - - QSettings::Status ret = settings.status(); - if (ret == QSettings::AccessError) { - fprintf(stderr, "Cannot install \"%s\". Cannot write to: %s. Check permissions.\n", - controller.serviceName().toLatin1().constData(), - settings.fileName().toLatin1().constData()); - } - return (ret == QSettings::NoError); -} - -void QtServiceBase::logMessage(const QString &message, QtServiceBase::MessageType type, - int, uint, const QByteArray &) -{ - if (!d_ptr->sysd) - return; - int st; - switch(type) { - case QtServiceBase::Error: - st = LOG_ERR; - break; - case QtServiceBase::Warning: - st = LOG_WARNING; - break; - default: - st = LOG_INFO; - } - if (!d_ptr->sysd->ident) { - QString tmp = encodeName(serviceName(), TRUE); - int len = tmp.toLocal8Bit().size(); - d_ptr->sysd->ident = new char[len+1]; - d_ptr->sysd->ident[len] = '\0'; - ::memcpy(d_ptr->sysd->ident, tmp.toLocal8Bit().constData(), len); - } - openlog(d_ptr->sysd->ident, LOG_PID, LOG_DAEMON); - foreach(QString line, message.split('\n')) - syslog(st, "%s", line.toLocal8Bit().constData()); - closelog(); -} - -void QtServiceBase::setServiceFlags(QtServiceBase::ServiceFlags flags) -{ - if (d_ptr->serviceFlags == flags) - return; - d_ptr->serviceFlags = flags; - if (d_ptr->sysd) - d_ptr->sysd->serviceFlags = flags; -} - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp deleted file mode 100644 index 7a737af1..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp +++ /dev/null @@ -1,903 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtservice.h" -#include "qtservice_p.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(QTSERVICE_DEBUG) -#include -#endif - -typedef SERVICE_STATUS_HANDLE(WINAPI*PRegisterServiceCtrlHandler)(const wchar_t*,LPHANDLER_FUNCTION); -static PRegisterServiceCtrlHandler pRegisterServiceCtrlHandler = 0; -typedef BOOL(WINAPI*PSetServiceStatus)(SERVICE_STATUS_HANDLE,LPSERVICE_STATUS); -static PSetServiceStatus pSetServiceStatus = 0; -typedef BOOL(WINAPI*PChangeServiceConfig2)(SC_HANDLE,DWORD,LPVOID); -static PChangeServiceConfig2 pChangeServiceConfig2 = 0; -typedef BOOL(WINAPI*PCloseServiceHandle)(SC_HANDLE); -static PCloseServiceHandle pCloseServiceHandle = 0; -typedef SC_HANDLE(WINAPI*PCreateService)(SC_HANDLE,LPCTSTR,LPCTSTR,DWORD,DWORD,DWORD,DWORD,LPCTSTR,LPCTSTR,LPDWORD,LPCTSTR,LPCTSTR,LPCTSTR); -static PCreateService pCreateService = 0; -typedef SC_HANDLE(WINAPI*POpenSCManager)(LPCTSTR,LPCTSTR,DWORD); -static POpenSCManager pOpenSCManager = 0; -typedef BOOL(WINAPI*PDeleteService)(SC_HANDLE); -static PDeleteService pDeleteService = 0; -typedef SC_HANDLE(WINAPI*POpenService)(SC_HANDLE,LPCTSTR,DWORD); -static POpenService pOpenService = 0; -typedef BOOL(WINAPI*PQueryServiceStatus)(SC_HANDLE,LPSERVICE_STATUS); -static PQueryServiceStatus pQueryServiceStatus = 0; -typedef BOOL(WINAPI*PStartServiceCtrlDispatcher)(CONST SERVICE_TABLE_ENTRY*); -static PStartServiceCtrlDispatcher pStartServiceCtrlDispatcher = 0; -typedef BOOL(WINAPI*PStartService)(SC_HANDLE,DWORD,const wchar_t**); -static PStartService pStartService = 0; -typedef BOOL(WINAPI*PControlService)(SC_HANDLE,DWORD,LPSERVICE_STATUS); -static PControlService pControlService = 0; -typedef HANDLE(WINAPI*PDeregisterEventSource)(HANDLE); -static PDeregisterEventSource pDeregisterEventSource = 0; -typedef BOOL(WINAPI*PReportEvent)(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCTSTR*,LPVOID); -static PReportEvent pReportEvent = 0; -typedef HANDLE(WINAPI*PRegisterEventSource)(LPCTSTR,LPCTSTR); -static PRegisterEventSource pRegisterEventSource = 0; -typedef DWORD(WINAPI*PRegisterServiceProcess)(DWORD,DWORD); -static PRegisterServiceProcess pRegisterServiceProcess = 0; -typedef BOOL(WINAPI*PQueryServiceConfig)(SC_HANDLE,LPQUERY_SERVICE_CONFIG,DWORD,LPDWORD); -static PQueryServiceConfig pQueryServiceConfig = 0; -typedef BOOL(WINAPI*PQueryServiceConfig2)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD); -static PQueryServiceConfig2 pQueryServiceConfig2 = 0; - - -#define RESOLVE(name) p##name = (P##name)lib.resolve(#name); -#define RESOLVEA(name) p##name = (P##name)lib.resolve(#name"A"); -#define RESOLVEW(name) p##name = (P##name)lib.resolve(#name"W"); - -static bool winServiceInit() -{ - if (!pOpenSCManager) { - QLibrary lib("advapi32"); - - // only resolve unicode versions - RESOLVEW(RegisterServiceCtrlHandler); - RESOLVE(SetServiceStatus); - RESOLVEW(ChangeServiceConfig2); - RESOLVE(CloseServiceHandle); - RESOLVEW(CreateService); - RESOLVEW(OpenSCManager); - RESOLVE(DeleteService); - RESOLVEW(OpenService); - RESOLVE(QueryServiceStatus); - RESOLVEW(StartServiceCtrlDispatcher); - RESOLVEW(StartService); // need only Ansi version - RESOLVE(ControlService); - RESOLVE(DeregisterEventSource); - RESOLVEW(ReportEvent); - RESOLVEW(RegisterEventSource); - RESOLVEW(QueryServiceConfig); - RESOLVEW(QueryServiceConfig2); - } - return pOpenSCManager != 0; -} - -bool QtServiceController::isInstalled() const -{ - Q_D(const QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t*)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - - if (hService) { - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::isRunning() const -{ - Q_D(const QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_STATUS); - if (hService) { - SERVICE_STATUS info; - int res = pQueryServiceStatus(hService, &info); - if (res) - result = info.dwCurrentState != SERVICE_STOPPED; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - - -QString QtServiceController::serviceFilePath() const -{ - Q_D(const QtServiceController); - QString result; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - if (hService) { - DWORD sizeNeeded = 0; - char data[8 * 1024]; - if (pQueryServiceConfig(hService, (LPQUERY_SERVICE_CONFIG)data, 8 * 1024, &sizeNeeded)) { - LPQUERY_SERVICE_CONFIG config = (LPQUERY_SERVICE_CONFIG)data; - result = QString::fromUtf16((const ushort*)config->lpBinaryPathName); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -QString QtServiceController::serviceDescription() const -{ - Q_D(const QtServiceController); - QString result; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - if (hService) { - DWORD dwBytesNeeded; - char data[8 * 1024]; - if (pQueryServiceConfig2( - hService, - SERVICE_CONFIG_DESCRIPTION, - (unsigned char *)data, - 8096, - &dwBytesNeeded)) { - LPSERVICE_DESCRIPTION desc = (LPSERVICE_DESCRIPTION)data; - if (desc->lpDescription) - result = QString::fromUtf16((const ushort*)desc->lpDescription); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -QtServiceController::StartupType QtServiceController::startupType() const -{ - Q_D(const QtServiceController); - StartupType result = ManualStartup; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, 0); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_QUERY_CONFIG); - if (hService) { - DWORD sizeNeeded = 0; - char data[8 * 1024]; - if (pQueryServiceConfig(hService, (QUERY_SERVICE_CONFIG *)data, 8 * 1024, &sizeNeeded)) { - QUERY_SERVICE_CONFIG *config = (QUERY_SERVICE_CONFIG *)data; - result = config->dwStartType == SERVICE_DEMAND_START ? ManualStartup : AutoStartup; - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::uninstall() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), DELETE); - if (hService) { - if (pDeleteService(hService)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::start(const QStringList &args) -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - // Try to open the service - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), SERVICE_START); - if (hService) { - QVector argv(args.size()); - for (int i = 0; i < args.size(); ++i) - argv[i] = (const wchar_t*)args.at(i).utf16(); - - if (pStartService(hService, args.size(), argv.data())) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::stop() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), SERVICE_STOP|SERVICE_QUERY_STATUS); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, SERVICE_CONTROL_STOP, &status)) { - bool stopped = status.dwCurrentState == SERVICE_STOPPED; - int i = 0; - while(!stopped && i < 10) { - Sleep(200); - if (!pQueryServiceStatus(hService, &status)) - break; - stopped = status.dwCurrentState == SERVICE_STOPPED; - ++i; - } - result = stopped; - } else { - qErrnoWarning(GetLastError(), "stopping"); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::pause() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_PAUSE_CONTINUE); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, SERVICE_CONTROL_PAUSE, &status)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::resume() -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_PAUSE_CONTINUE); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, SERVICE_CONTROL_CONTINUE, &status)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -bool QtServiceController::sendCommand(int code) -{ - Q_D(QtServiceController); - bool result = false; - if (!winServiceInit()) - return result; - - if (code < 0 || code > 127 || !isRunning()) - return result; - - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_CONNECT); - if (hSCM) { - SC_HANDLE hService = pOpenService(hSCM, (wchar_t *)d->serviceName.utf16(), - SERVICE_USER_DEFINED_CONTROL); - if (hService) { - SERVICE_STATUS status; - if (pControlService(hService, 128 + code, &status)) - result = true; - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -#if defined(QTSERVICE_DEBUG) -extern void qtServiceLogDebug(QtMsgType type, const char* msg); -#endif - -void QtServiceBase::logMessage(const QString &message, MessageType type, - int id, uint category, const QByteArray &data) -{ -#if defined(QTSERVICE_DEBUG) - QByteArray dbgMsg("[LOGGED "); - switch (type) { - case Error: dbgMsg += "Error] " ; break; - case Warning: dbgMsg += "Warning] "; break; - case Success: dbgMsg += "Success] "; break; - case Information: //fall through - default: dbgMsg += "Information] "; break; - } - dbgMsg += message.toAscii(); - qtServiceLogDebug((QtMsgType)-1, dbgMsg.constData()); -#endif - - Q_D(QtServiceBase); - if (!winServiceInit()) - return; - WORD wType; - switch (type) { - case Error: wType = EVENTLOG_ERROR_TYPE; break; - case Warning: wType = EVENTLOG_WARNING_TYPE; break; - case Information: wType = EVENTLOG_INFORMATION_TYPE; break; - default: wType = EVENTLOG_SUCCESS; break; - } - HANDLE h = pRegisterEventSource(0, (wchar_t *)d->controller.serviceName().utf16()); - if (h) { - const wchar_t *msg = (wchar_t*)message.utf16(); - const char *bindata = data.size() ? data.constData() : 0; - pReportEvent(h, wType, category, id, 0, 1, data.size(),(const wchar_t **)&msg, - const_cast(bindata)); - pDeregisterEventSource(h); - } -} - -class QtServiceControllerHandler : public QObject -{ - Q_OBJECT -public: - QtServiceControllerHandler(QtServiceSysPrivate *sys); - -protected: - void customEvent(QEvent *e); - -private: - QtServiceSysPrivate *d_sys; -}; - -class QtServiceSysPrivate -{ -public: - enum { - QTSERVICE_STARTUP = 256 - }; - QtServiceSysPrivate(); - - void setStatus( DWORD dwState ); - void setServiceFlags(QtServiceBase::ServiceFlags flags); - DWORD serviceFlags(QtServiceBase::ServiceFlags flags) const; - inline bool available() const; - static void WINAPI serviceMain( DWORD dwArgc, wchar_t** lpszArgv ); - static void WINAPI handler( DWORD dwOpcode ); - - SERVICE_STATUS status; - SERVICE_STATUS_HANDLE serviceStatus; - QStringList serviceArgs; - - static QtServiceSysPrivate *instance; - static QCoreApplication::EventFilter nextFilter; - - QWaitCondition condition; - QMutex mutex; - QSemaphore startSemaphore; - QSemaphore startSemaphore2; - - QtServiceControllerHandler *controllerHandler; - - void handleCustomEvent(QEvent *e); -}; - -QtServiceControllerHandler::QtServiceControllerHandler(QtServiceSysPrivate *sys) - : QObject(), d_sys(sys) -{ - -} - -void QtServiceControllerHandler::customEvent(QEvent *e) -{ - d_sys->handleCustomEvent(e); -} - - -QtServiceSysPrivate *QtServiceSysPrivate::instance = 0; -QCoreApplication::EventFilter QtServiceSysPrivate::nextFilter = 0; - -QtServiceSysPrivate::QtServiceSysPrivate() -{ - instance = this; -} - -inline bool QtServiceSysPrivate::available() const -{ - return 0 != pOpenSCManager; -} - -void WINAPI QtServiceSysPrivate::serviceMain(DWORD dwArgc, wchar_t** lpszArgv) -{ - if (!instance || !QtServiceBase::instance()) - return; - - // Windows spins off a random thread to call this function on - // startup, so here we just signal to the QApplication event loop - // in the main thread to go ahead with start()'ing the service. - - for (DWORD i = 0; i < dwArgc; i++) - instance->serviceArgs.append(QString::fromUtf16((unsigned short*)lpszArgv[i])); - - instance->startSemaphore.release(); // let the qapp creation start - instance->startSemaphore2.acquire(); // wait until its done - // Register the control request handler - instance->serviceStatus = pRegisterServiceCtrlHandler((TCHAR*)QtServiceBase::instance()->serviceName().utf16(), handler); - - if (!instance->serviceStatus) // cannot happen - something is utterly wrong - return; - - handler(QTSERVICE_STARTUP); // Signal startup to the application - - // causes QtServiceBase::start() to be called in the main thread - - // The MSDN doc says that this thread should just exit - the service is - // running in the main thread (here, via callbacks in the handler thread). -} - - -// The handler() is called from the thread that called -// StartServiceCtrlDispatcher, i.e. our HandlerThread, and -// not from the main thread that runs the event loop, so we -// have to post an event to ourselves, and use a QWaitCondition -// and a QMutex to synchronize. -void QtServiceSysPrivate::handleCustomEvent(QEvent *e) -{ - int code = e->type() - QEvent::User; - - switch(code) { - case QTSERVICE_STARTUP: // Startup - QtServiceBase::instance()->start(); - break; - case SERVICE_CONTROL_STOP: - QtServiceBase::instance()->stop(); - QCoreApplication::instance()->quit(); - break; - case SERVICE_CONTROL_PAUSE: - QtServiceBase::instance()->pause(); - break; - case SERVICE_CONTROL_CONTINUE: - QtServiceBase::instance()->resume(); - break; - default: - if (code >= 128 && code <= 255) - QtServiceBase::instance()->processCommand(code - 128); - break; - } - - mutex.lock(); - condition.wakeAll(); - mutex.unlock(); -} - -void WINAPI QtServiceSysPrivate::handler( DWORD code ) -{ - if (!instance) - return; - - instance->mutex.lock(); - switch (code) { - case QTSERVICE_STARTUP: // QtService startup (called from WinMain when started) - instance->setStatus(SERVICE_START_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - instance->setStatus(SERVICE_RUNNING); - break; - case SERVICE_CONTROL_STOP: // 1 - instance->setStatus(SERVICE_STOP_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - // status will be reported as stopped in start() when qapp::exec returns - break; - - case SERVICE_CONTROL_PAUSE: // 2 - instance->setStatus(SERVICE_PAUSE_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - instance->setStatus(SERVICE_PAUSED); - break; - - case SERVICE_CONTROL_CONTINUE: // 3 - instance->setStatus(SERVICE_CONTINUE_PENDING); - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - instance->setStatus(SERVICE_RUNNING); - break; - - case SERVICE_CONTROL_INTERROGATE: // 4 - break; - - default: - if ( code >= 128 && code <= 255 ) { - QCoreApplication::postEvent(instance->controllerHandler, new QEvent(QEvent::Type(QEvent::User + code))); - instance->condition.wait(&instance->mutex); - } - break; - } - - instance->mutex.unlock(); - - // Report current status - if (instance->available() && instance->status.dwCurrentState != SERVICE_STOPPED) - pSetServiceStatus(instance->serviceStatus, &instance->status); -} - -void QtServiceSysPrivate::setStatus(DWORD state) -{ - if (!available()) - return; - status.dwCurrentState = state; - pSetServiceStatus(serviceStatus, &status); -} - -void QtServiceSysPrivate::setServiceFlags(QtServiceBase::ServiceFlags flags) -{ - if (!available()) - return; - status.dwControlsAccepted = serviceFlags(flags); - pSetServiceStatus(serviceStatus, &status); -} - -DWORD QtServiceSysPrivate::serviceFlags(QtServiceBase::ServiceFlags flags) const -{ - DWORD control = 0; - if (flags & QtServiceBase::CanBeSuspended) - control |= SERVICE_ACCEPT_PAUSE_CONTINUE; - if (!(flags & QtServiceBase::CannotBeStopped)) - control |= SERVICE_ACCEPT_STOP; - return control; -} - -#include "qtservice_win.moc" - - -class HandlerThread : public QThread -{ -public: - HandlerThread() - : success(true), console(false), QThread() - {} - - bool calledOk() { return success; } - bool runningAsConsole() { return console; } - -protected: - bool success, console; - void run() - { - SERVICE_TABLE_ENTRYW st [2]; - st[0].lpServiceName = (wchar_t*)QtServiceBase::instance()->serviceName().utf16(); - st[0].lpServiceProc = QtServiceSysPrivate::serviceMain; - st[1].lpServiceName = 0; - st[1].lpServiceProc = 0; - - success = (pStartServiceCtrlDispatcher(st) != 0); // should block - - if (!success) { - if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { - // Means we're started from console, not from service mgr - // start() will ask the mgr to start another instance of us as a service instead - console = true; - } - else { - QtServiceBase::instance()->logMessage(QString("The Service failed to start [%1]").arg(qt_error_string(GetLastError())), QtServiceBase::Error); - } - QtServiceSysPrivate::instance->startSemaphore.release(); // let start() continue, since serviceMain won't be doing it - } - } -}; - -/* - Ignore WM_ENDSESSION system events, since they make the Qt kernel quit -*/ -bool myEventFilter(void* message, long* result) -{ - MSG* msg = reinterpret_cast(message); - if (!msg || (msg->message != WM_ENDSESSION) || !(msg->lParam & ENDSESSION_LOGOFF)) - return QtServiceSysPrivate::nextFilter ? QtServiceSysPrivate::nextFilter(message, result) : false; - - if (QtServiceSysPrivate::nextFilter) - QtServiceSysPrivate::nextFilter(message, result); - if (result) - *result = TRUE; - return true; -} - -/* There are three ways we can be started: - - - By a service controller (e.g. the Services control panel), with - no (service-specific) arguments. ServiceBase::exec() will then call - start() below, and the service will start. - - - From the console, but with no (service-specific) arguments. This - means we should ask a controller to start the service (i.e. another - instance of this executable), and then just terminate. We discover - this case (as different from the above) by the fact that - StartServiceCtrlDispatcher will return an error, instead of blocking. - - - From the console, with -e(xec) argument. ServiceBase::exec() will - then call ServiceBasePrivate::exec(), which calls - ServiceBasePrivate::run(), which runs the application as a normal - program. -*/ - -bool QtServiceBasePrivate::start() -{ - sysInit(); - if (!winServiceInit()) - return false; - - // Since StartServiceCtrlDispatcher() blocks waiting for service - // control events, we need to call it in another thread, so that - // the main thread can run the QApplication event loop. - HandlerThread* ht = new HandlerThread(); - ht->start(); - - QtServiceSysPrivate* sys = QtServiceSysPrivate::instance; - - // Wait until service args have been received by serviceMain. - // If Windows doesn't call serviceMain (or - // StartServiceControlDispatcher doesn't return an error) within - // a timeout of 20 secs, something is very wrong; give up - if (!sys->startSemaphore.tryAcquire(1, 20000)) - return false; - - if (!ht->calledOk()) { - if (ht->runningAsConsole()) - return controller.start(args.mid(1)); - else - return false; - } - - int argc = sys->serviceArgs.size(); - QVector argv(argc); - QList argvData; - for (int i = 0; i < argc; ++i) - argvData.append(sys->serviceArgs.at(i).toLocal8Bit()); - for (int i = 0; i < argc; ++i) - argv[i] = argvData[i].data(); - - q_ptr->createApplication(argc, argv.data()); - QCoreApplication *app = QCoreApplication::instance(); - if (!app) - return false; - QtServiceSysPrivate::nextFilter = app->setEventFilter(myEventFilter); - - sys->controllerHandler = new QtServiceControllerHandler(sys); - - sys->startSemaphore2.release(); // let serviceMain continue (and end) - - sys->status.dwWin32ExitCode = q_ptr->executeApplication(); - sys->setStatus(SERVICE_STOPPED); - - if (ht->isRunning()) - ht->wait(1000); // let the handler thread finish - delete sys->controllerHandler; - sys->controllerHandler = 0; - if (ht->isFinished()) - delete ht; - delete app; - sysCleanup(); - return true; -} - -bool QtServiceBasePrivate::install(const QString &account, const QString &password) -{ - bool result = false; - if (!winServiceInit()) - return result; - - // Open the Service Control Manager - SC_HANDLE hSCM = pOpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); - if (hSCM) { - QString acc = account; - DWORD dwStartType = startupType == QtServiceController::AutoStartup ? SERVICE_AUTO_START : SERVICE_DEMAND_START; - DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS; - wchar_t *act = 0; - wchar_t *pwd = 0; - if (!acc.isEmpty()) { - // The act string must contain a string of the format "Domain\UserName", - // so if only a username was specified without a domain, default to the local machine domain. - if (!acc.contains(QChar('\\'))) { - acc.prepend(QLatin1String(".\\")); - } - if (!acc.endsWith(QLatin1String("\\LocalSystem"))) - act = (wchar_t*)acc.utf16(); - } - if (!password.isEmpty() && act) { - pwd = (wchar_t*)password.utf16(); - } - - // Only set INTERACTIVE if act is LocalSystem. (and act should be 0 if it is LocalSystem). - if (!act) dwServiceType |= SERVICE_INTERACTIVE_PROCESS; - - // Create the service - SC_HANDLE hService = pCreateService(hSCM, (wchar_t *)controller.serviceName().utf16(), - (wchar_t *)controller.serviceName().utf16(), - SERVICE_ALL_ACCESS, - dwServiceType, // QObject::inherits ( const char * className ) for no inter active ???? - dwStartType, SERVICE_ERROR_NORMAL, (wchar_t *)filePath().utf16(), - 0, 0, 0, - act, pwd); - if (hService) { - result = true; - if (!serviceDescription.isEmpty()) { - SERVICE_DESCRIPTION sdesc; - sdesc.lpDescription = (wchar_t *)serviceDescription.utf16(); - pChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sdesc); - } - pCloseServiceHandle(hService); - } - pCloseServiceHandle(hSCM); - } - return result; -} - -QString QtServiceBasePrivate::filePath() const -{ - wchar_t path[_MAX_PATH]; - ::GetModuleFileNameW( 0, path, sizeof(path) ); - return QString::fromUtf16((unsigned short*)path); -} - -bool QtServiceBasePrivate::sysInit() -{ - sysd = new QtServiceSysPrivate(); - - sysd->serviceStatus = 0; - sysd->status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS; - sysd->status.dwCurrentState = SERVICE_STOPPED; - sysd->status.dwControlsAccepted = sysd->serviceFlags(serviceFlags); - sysd->status.dwWin32ExitCode = NO_ERROR; - sysd->status.dwServiceSpecificExitCode = 0; - sysd->status.dwCheckPoint = 0; - sysd->status.dwWaitHint = 0; - - return true; -} - -void QtServiceBasePrivate::sysSetPath() -{ - -} - -void QtServiceBasePrivate::sysCleanup() -{ - if (sysd) { - delete sysd; - sysd = 0; - } -} - -void QtServiceBase::setServiceFlags(QtServiceBase::ServiceFlags flags) -{ - if (d_ptr->serviceFlags == flags) - return; - d_ptr->serviceFlags = flags; - if (d_ptr->sysd) - d_ptr->sysd->setServiceFlags(flags); -} - - diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp deleted file mode 100644 index a04f0f4c..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtunixserversocket.h" -#include -#include -#include -#include -#include - -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ - +strlen ((ptr)->sun_path)) -#endif - -QtUnixServerSocket::QtUnixServerSocket(const QString &path, QObject *parent) - : QTcpServer(parent) -{ - setPath(path); -} - -QtUnixServerSocket::QtUnixServerSocket(QObject *parent) - : QTcpServer(parent) -{ -} - -void QtUnixServerSocket::setPath(const QString &path) -{ - path_.clear(); - - int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); - if (sock != -1) { - struct sockaddr_un addr; - ::memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - ::unlink(path.toLatin1().constData()); // ### This might need to be changed - unsigned int pathlen = strlen(path.toLatin1().constData()); - if (pathlen > sizeof(addr.sun_path)) pathlen = sizeof(addr.sun_path); - ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); - if ((::bind(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)) != -1) && - (::listen(sock, 5) != -1)) { - setSocketDescriptor(sock); - path_ = path; - } - } -} - -void QtUnixServerSocket::close() -{ - QTcpServer::close(); - if (!path_.isEmpty()) { - ::unlink(path_.toLatin1().constData()); - path_.clear(); - } -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h deleted file mode 100644 index 2ba2fd12..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTUNIXSERVERSOCKET_H -#define QTUNIXSERVERSOCKET_H - -#include - -class QtUnixServerSocket : public QTcpServer -{ - Q_OBJECT -public: - QtUnixServerSocket(const QString &path, QObject *parent = 0); - QtUnixServerSocket(QObject *parent = 0); - - void setPath(const QString &path); - void close(); - -private: - QString path_; -}; - - -#endif diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp deleted file mode 100644 index fae5ac1b..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#include "qtunixsocket.h" -#include -#include -#include -#include -#include - -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t)(((struct sockaddr_un *) 0)->sun_path) \ - +strlen ((ptr)->sun_path)) -#endif - -QtUnixSocket::QtUnixSocket(QObject *parent) - : QTcpSocket(parent) -{ -} - -bool QtUnixSocket::connectTo(const QString &path) -{ - bool ret = false; - int sock = ::socket(PF_UNIX, SOCK_STREAM, 0); - if (sock != -1) { - struct sockaddr_un addr; - ::memset(&addr, 0, sizeof(struct sockaddr_un)); - addr.sun_family = AF_UNIX; - size_t pathlen = strlen(path.toLatin1().constData()); - pathlen = qMin(pathlen, sizeof(addr.sun_path)); - ::memcpy(addr.sun_path, path.toLatin1().constData(), pathlen); - int err = ::connect(sock, (struct sockaddr *)&addr, SUN_LEN(&addr)); - if (err != -1) { - setSocketDescriptor(sock); - ret = true; - } else { - ::close(sock); - } - } - return ret; -} diff --git a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h b/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h deleted file mode 100644 index b7aaebde..00000000 --- a/telldus-core/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** -****************************************************************************/ - -#ifndef QTUNIXSOCKET_H -#define QTUNIXSOCKET_H - -#include - -class QtUnixSocket : public QTcpSocket -{ - Q_OBJECT -public: - QtUnixSocket(QObject *parent = 0); - - bool connectTo(const QString &path); -}; - -#endif diff --git a/telldus-core/3rdparty/qtservice.cmake b/telldus-core/3rdparty/qtservice.cmake deleted file mode 100644 index 652b0127..00000000 --- a/telldus-core/3rdparty/qtservice.cmake +++ /dev/null @@ -1,39 +0,0 @@ - -QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice.moc ) - -SET( qtservice_SRCS - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice.cpp - ${CMAKE_CURRENT_BINARY_DIR}/qtservice.moc -) - -IF (UNIX) - QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice_unix.moc ) - - SET( qtservice_MOC_HDRS - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.h - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.h - ) - - QT4_WRAP_CPP( qtservice_MOC_SRCS ${qtservice_MOC_HDRS} ) - - SET( qtservice_SRCS - ${qtservice_SRCS} - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_unix.cpp - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixsocket.cpp - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtunixserversocket.cpp - ${CMAKE_CURRENT_BINARY_DIR}/qtservice_unix.moc - ${qtservice_MOC_SRCS} - ) -ELSEIF (WIN32) - QT4_GENERATE_MOC( ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp ${CMAKE_CURRENT_BINARY_DIR}/qtservice_win.moc ) - SET(qtservice_SRCS - ${qtservice_SRCS} - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/qtservice_win.cpp - ${CMAKE_CURRENT_BINARY_DIR}/qtservice_win.moc - ) -ENDIF (UNIX) - -INCLUDE_DIRECTORIES( - ${CMAKE_HOME_DIRECTORY}/3rdparty/qtservice-2.6-opensource/src/ - ${CMAKE_CURRENT_BINARY_DIR} -) From db1c3dfc7fca92460a578f477726602c6ae57e3b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 11:02:35 +0000 Subject: [PATCH 0216/2215] Renamed SOCKET to SOCKET_T on unix --- telldus-core/common/Socket.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 6ac8e354..b84ee33f 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -7,7 +7,7 @@ #include typedef HANDLE SOCKET_T; #else - typedef unsigned int SOCKET; + typedef unsigned int SOCKET_T; #endif namespace TelldusCore { From 2c14c779afe6e4d4c7e4c4d78352f8cd6d645245 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 12:25:46 +0000 Subject: [PATCH 0217/2215] Message-class added (will compile, but untested) --- telldus-core/common/CMakeLists.txt | 2 ++ .../service/ClientCommunicationHandler.cpp | 15 +++++++++++---- telldus-core/service/ClientCommunicationHandler.h | 3 ++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 74a383c9..a9ba57ae 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -5,11 +5,13 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-common_SRCS Thread.cpp + Message.cpp ) SET( telldus-common_HDRS Thread.h Socket.h + Message.h ) ######## Configurable options for the platform ######## diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 2f865280..18938798 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -1,4 +1,5 @@ #include "ClientCommunicationHandler.h" +#include "Message.h" class ClientCommunicationHandler::PrivateData { public: @@ -7,6 +8,10 @@ public: bool done; }; +ClientCommunicationHandler::ClientCommunicationHandler(){ + +} + ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event) :Thread() { @@ -30,7 +35,7 @@ void ClientCommunicationHandler::run(){ std::wstring clientMessage = d->clientSocket->read(); - //parseMessage(clientMessage); + //std::wstring temp = parseMessage(clientMessage); @@ -43,9 +48,11 @@ bool ClientCommunicationHandler::isDone(){ return d->done; } -/* -std::wstring parseMessage(std::wstring &clientMessage){ +std::wstring parseMessage(const std::wstring &clientMessage){ + + std::wstring msg(clientMessage); //Copy + //std::wstring function(TelldusCore::Message::takeString(&msg)); if(clientMessage == L"tdGetNumberOfDevices"){ //starta ny tråd (ny klass, ärv från Thread) //skicka in meddelandet i denna tråd @@ -54,5 +61,5 @@ std::wstring parseMessage(std::wstring &clientMessage){ //TODO } + return L"Dummy"; } -*/ \ No newline at end of file diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 724ee789..50305194 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -9,6 +9,7 @@ class ClientCommunicationHandler : public TelldusCore::Thread { public: + ClientCommunicationHandler(); ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event); ~ClientCommunicationHandler(void); @@ -20,7 +21,7 @@ protected: private: class PrivateData; PrivateData *d; - //std::wstring parseMessage(std::wstring); + std::wstring parseMessage(std::wstring &clientMessage); }; #endif //CLIENTCOMMUNICATIONHANDLER_H \ No newline at end of file From b806913cea7113b09bd5ed093b647b730c6f0be9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 12:28:07 +0000 Subject: [PATCH 0218/2215] Added function stubs to Socket in unix --- telldus-core/common/CMakeLists.txt | 6 ++++++ telldus-core/common/Socket_unix.cpp | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 telldus-core/common/Socket_unix.cpp diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index a9ba57ae..559343cd 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -23,6 +23,9 @@ IF (APPLE) #### Mac OS X #### SET( telldus-common_TARGET TelldusCommon ) ADD_DEFINITIONS( -D_MACOSX ) + LIST(APPEND telldus-common_SRCS + Socket_unix.cpp + ) ELSEIF (WIN32) #### Windows #### ADD_DEFINITIONS( -DUNICODE ) @@ -36,6 +39,9 @@ ELSE (APPLE) #### Linux #### SET( telldus-common_TARGET telldus-common ) ADD_DEFINITIONS( -D_LINUX ) + LIST(APPEND telldus-common_SRCS + Socket_unix.cpp + ) ENDIF (APPLE) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp new file mode 100644 index 00000000..aa724b45 --- /dev/null +++ b/telldus-core/common/Socket_unix.cpp @@ -0,0 +1,20 @@ +#include "Socket.h" + +using namespace TelldusCore; + +class Socket::PrivateData { +public: +}; + +Socket::Socket(SOCKET_T hPipe) +{ + d = new PrivateData; +} + +Socket::~Socket(void){ + delete d; +} + +std::wstring Socket::read() { + return L""; +} From 64439e7b0c16216d1febf65fd3a1ad3c1ceaa615 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 12:31:35 +0000 Subject: [PATCH 0219/2215] Class added --- telldus-core/common/Message.cpp | 87 +++++++++++++++++++++++++++++++++ telldus-core/common/Message.h | 28 +++++++++++ 2 files changed, 115 insertions(+) create mode 100644 telldus-core/common/Message.cpp create mode 100644 telldus-core/common/Message.h diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp new file mode 100644 index 00000000..5dd7488f --- /dev/null +++ b/telldus-core/common/Message.cpp @@ -0,0 +1,87 @@ +#include "Message.h" +using namespace TelldusCore; +#include +#include +#include + +Message::Message() + : std::wstring() +{ +} + +Message::Message(const std::wstring &functionName) + :std::wstring() +{ + this->addArgument(functionName); +} + +Message::~Message(void) { +} + +void Message::addArgument(const std::wstring &value) { + std::wstringstream st; + st << (int)value.size(); + this->append(st.str()); + this->append(L":"); + this->append(value); +} + + +void Message::addArgument(int value) { + std::wstringstream st; + st << (int)value; + this->append(L"i"); + this->append(st.str()); + this->append(L"e"); //TODO s? +} + +/* +void Message::addArgument(const char *value) { + this->addArgument(std::wstring(value)); +} +*/ + + + +bool Message::nextIsInt(const std::wstring &message) { + if (message.length() == 0) { + return false; + } + return (message.at(0) == 'i'); +} + +bool Message::nextIsString(const std::wstring &message) { + if (message.length() == 0) { + return false; + } + return (isdigit(message.at(0)) != 0); +} + +std::wstring Message::takeString(std::wstring *message) { + if (!Message::nextIsString(*message)) { + return L""; + } + int index = message->find(':'); + int length = wideToInteger(&message->substr(0, index)); + std::wstring retval(message->substr(index+1, length)); + message->erase(0, index+length+1); + return retval; +} + +int Message::takeInt(std::wstring *message) { + if (!Message::nextIsInt(*message)) { + return 0; + } + int index = message->find('e'); //TODO s? + int value = wideToInteger(&message->substr(1, index - 1)); + message->erase(0, index+1); + return value; +} + +int wideToInteger(std::wstring *input){ + std::wstringstream inputstream; + inputstream << input; + int retval; + inputstream >> retval; + return retval; +} diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h new file mode 100644 index 00000000..363d5359 --- /dev/null +++ b/telldus-core/common/Message.h @@ -0,0 +1,28 @@ +#ifndef MESSAGE_H +#define MESSAGE_H + +#include + +namespace TelldusCore { + class Message : public std::wstring { + public: + Message(); + Message(const std::wstring &); + ~Message(void); + + void addArgument(const std::wstring &); + void addArgument(int); + //void addArgument(const char *); + + static bool nextIsInt(const std::wstring &); + static bool nextIsString(const std::wstring &); + + static std::wstring takeString(std::wstring *); + static int takeInt(std::wstring *); + + private: + static int wideToInteger(std::wstring *input); + }; +} + +#endif //MESSAGE_H \ No newline at end of file From 9919c2805a5daa7d378500a1a3bde6f5f3b76f69 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 13:01:38 +0000 Subject: [PATCH 0220/2215] Only use forward-declaration for class Socket in ConnectionListener --- telldus-core/service/ConnectionListener.h | 7 +++++-- telldus-core/service/ConnectionListener_unix.cpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index adc9fc5d..2a9a9fec 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -2,8 +2,11 @@ #define CONNECTIONLISTENER_H #include -#include "Event.h" -#include "Socket.h" + +class Event; +namespace TelldusCore { + class Socket; +}; class ConnectionListener { diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 168cb9b1..08d9e9c5 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -18,6 +18,6 @@ void ConnectionListener::listen(Event *waitEvent){ } -Socket *ConnectionListener::retrieveClientSocket(){ +TelldusCore::Socket *ConnectionListener::retrieveClientSocket(){ } From 1e43b60572ca23bc9c2cdfbe4c186935feb67cdd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 13:07:38 +0000 Subject: [PATCH 0221/2215] Added our TelldusMain class in the main-function --- telldus-core/service/main_unix.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 987464fa..2bd30833 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -1,11 +1,19 @@ - +#include "TelldusMain.h" #include +#include + +TelldusMain tm; void shutdownHandler(int onSignal) { + printf("Shutting down\n"); + tm.stop(); } int main(int argc, char **argv) { /* Install signal traps for proper shutdown */ signal(SIGTERM, shutdownHandler); - signal(SIGINT, shutdownHandler); + signal(SIGINT, shutdownHandler); + + tm.start(); + return 0; } From 9746d6289894495cfde017858772289498cebe62 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 13:10:34 +0000 Subject: [PATCH 0222/2215] Added locks for the unix-implementation of class Event --- telldus-core/service/Event_unix.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Event_unix.cpp b/telldus-core/service/Event_unix.cpp index 0480223f..d2bfb34a 100644 --- a/telldus-core/service/Event_unix.cpp +++ b/telldus-core/service/Event_unix.cpp @@ -1,22 +1,32 @@ #include "Event.h" #include "EventHandler.h" +#include "Thread.h" class Event::PrivateData { public: bool signaled; EventHandler *handler; + MUTEX_T mutex; }; Event::Event(EventHandler *handler) { d = new PrivateData; d->signaled = false; + TelldusCore::Thread::initMutex(&d->mutex); } Event::~Event(void) { + TelldusCore::Thread::destroyMutex(&d->mutex); delete d; } +void Event::clearSignal() { + TelldusCore::MutexLocker locker(&d->mutex); + d->signaled = false; +} + bool Event::isSignaled() { + TelldusCore::MutexLocker locker(&d->mutex); return d->signaled; } @@ -25,5 +35,6 @@ void Event::signal() { } void Event::setSignaled() { + TelldusCore::MutexLocker locker(&d->mutex); d->signaled = true; -} \ No newline at end of file +} From b32048b4e77fca03717968a71394bbcf55bd7738 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 13:11:59 +0000 Subject: [PATCH 0223/2215] Fixed the return-value from EventHandler::waitForAny() --- telldus-core/service/EventHandler_unix.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index 8ff9689a..eecaeb6e 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -1,6 +1,8 @@ #include "EventHandler.h" #include "Event.h" +#include "Thread.h" #include +#include class EventHandler::PrivateData { public: @@ -31,10 +33,10 @@ void EventHandler::signal(Event *event) { event->setSignaled(); d->hasEvent = true; pthread_cond_signal(&d->event); - pthread_mutex_unlock(&d->mutex); + pthread_mutex_unlock(&d->mutex); } -void EventHandler::waitForAny() { +bool EventHandler::waitForAny() { pthread_mutex_lock(&d->mutex); while(!d->hasEvent) { pthread_cond_wait(&d->event, &d->mutex); @@ -42,5 +44,5 @@ void EventHandler::waitForAny() { d->hasEvent = false; pthread_mutex_unlock(&d->mutex); - return; + return true; } From 861bac30f49eb904a9dbb9ee698932bb6c20f057 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 13:12:40 +0000 Subject: [PATCH 0224/2215] Added a stop event to our main-loop --- telldus-core/service/TelldusMain.cpp | 24 ++++++++++++++++-------- telldus-core/service/TelldusMain.h | 6 +++--- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 87a37a45..5f3f5f6d 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -3,20 +3,28 @@ #include "EventHandler.h" #include "ClientCommunicationHandler.h" +#include #include +class TelldusMain::PrivateData { +public: + EventHandler eventHandler; + Event *stopEvent; +}; + TelldusMain::TelldusMain(void) { - running = true; + d = new PrivateData; + d->stopEvent = d->eventHandler.addEvent(); } TelldusMain::~TelldusMain(void) { + delete d; } -void TelldusMain::start(void){ - EventHandler eventHandler; - Event *clientEvent = eventHandler.addEvent(); +void TelldusMain::start(void) { + Event *clientEvent = d->eventHandler.addEvent(); ConnectionListener clientListener(L"TelldusClient"); //TODO: eventlistener @@ -26,8 +34,8 @@ void TelldusMain::start(void){ std::list clientCommunicationHandlerList; - while(running) { - if (!eventHandler.waitForAny()) { + while(!d->stopEvent->isSignaled()) { + if (!d->eventHandler.waitForAny()) { continue; } if (clientEvent->isSignaled()) { @@ -37,7 +45,7 @@ void TelldusMain::start(void){ TelldusCore::Socket *s = clientListener.retrieveClientSocket(); if(s){ - Event *handlerEvent = eventHandler.addEvent(); + Event *handlerEvent = d->eventHandler.addEvent(); ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(s, handlerEvent); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); @@ -66,5 +74,5 @@ void TelldusMain::start(void){ } void TelldusMain::stop(void){ - running = false; + d->eventHandler.signal(d->stopEvent); } diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index 2cb17843..3dcddd75 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -11,8 +11,8 @@ public: void stop(); private: - bool running; - + class PrivateData; + PrivateData *d; }; -#endif //TELLDUSMAIN_H \ No newline at end of file +#endif //TELLDUSMAIN_H From 6f52da0d125f638fa2a2fabfb78fe774706cdf7a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 13:16:33 +0000 Subject: [PATCH 0225/2215] Compile-fix for Windows --- telldus-core/service/ConnectionListener_win.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 7dafc25a..01bce0ec 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -1,4 +1,6 @@ #include "ConnectionListener.h" +#include "Event.h" +#include "Socket.h" #include #include From f1423aab220a25996c99a441fa7aa13a8f8c04b5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 14:00:18 +0000 Subject: [PATCH 0226/2215] Our closeEvent-object crashed for some reason. Return of the "running"-variable! --- telldus-core/service/TelldusMain.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 5f3f5f6d..ef12bc28 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -10,16 +10,19 @@ class TelldusMain::PrivateData { public: EventHandler eventHandler; Event *stopEvent; + bool running; }; TelldusMain::TelldusMain(void) { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); + d->running = true; } TelldusMain::~TelldusMain(void) { + delete d->stopEvent; delete d; } @@ -34,10 +37,14 @@ void TelldusMain::start(void) { std::list clientCommunicationHandlerList; - while(!d->stopEvent->isSignaled()) { + while(d->running) { if (!d->eventHandler.waitForAny()) { continue; } + /*if (d->stopEvent->isSignaled()) { + printf("Stopped\n"); + break; + }*/ if (clientEvent->isSignaled()) { clientEvent->clearSignal(); //New client connection @@ -74,5 +81,6 @@ void TelldusMain::start(void) { } void TelldusMain::stop(void){ - d->eventHandler.signal(d->stopEvent); + //d->eventHandler.signal(d->stopEvent); + d->running = false; } From ec1f5ee6e6a1b45c1979514ba420e3c34384cccd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:15:58 +0000 Subject: [PATCH 0227/2215] Fixed bug where the handler wasn't saved --- telldus-core/service/Event_win.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index 817a493e..e4a97f9b 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -13,7 +13,8 @@ public: Event::Event(EventHandler *handler) { d = new PrivateData; d->signaled = false; - d->event = CreateEvent(NULL, true, true, NULL); + d->handler = handler; + d->event = CreateEvent(NULL, true, false, NULL); TelldusCore::Thread::initMutex(&d->mutex); } @@ -45,4 +46,4 @@ void Event::setSignaled() { EVENT_T Event::retrieveNative() { TelldusCore::MutexLocker locker(&d->mutex); return d->event; -} \ No newline at end of file +} From 7c94f955f88742df1966255b8b8d7ef390f3c772 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:17:44 +0000 Subject: [PATCH 0228/2215] Made the constructor in Event protected, preventing instances created outside EventHandler. --- telldus-core/service/Event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 3d8fd1c2..203d1275 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -12,7 +12,6 @@ class EventHandler; class Event { public: - Event(EventHandler *handler); virtual ~Event(); void clearSignal(); @@ -21,6 +20,7 @@ public: void signal(); protected: + Event(EventHandler *handler); void setSignaled(); private: From 0895de3f70beb4971ed1736fe63fc4aa97d58c62 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:18:43 +0000 Subject: [PATCH 0229/2215] Added function Event::clearHandler() --- telldus-core/service/Event.h | 1 + telldus-core/service/Event_win.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 203d1275..99ec1674 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -22,6 +22,7 @@ public: protected: Event(EventHandler *handler); void setSignaled(); + void clearHandler(); private: class PrivateData; diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index e4a97f9b..5a08b5e3 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -19,6 +19,9 @@ Event::Event(EventHandler *handler) { } Event::~Event(void) { + if (d->handler) { + d->handler->removeEvent(this); + } TelldusCore::Thread::destroyMutex(&d->mutex); CloseHandle(d->event); delete d; @@ -38,6 +41,11 @@ void Event::signal() { SetEvent(d->event); } +void Event::clearHandler() { + TelldusCore::MutexLocker locker(&d->mutex); + d->handler = 0; +} + void Event::setSignaled() { TelldusCore::MutexLocker locker(&d->mutex); d->signaled = true; From 2588bed12a654ff8c0ed09d5658143de9cfe6a57 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:19:30 +0000 Subject: [PATCH 0230/2215] Clear the event in Event::clearSignal() --- telldus-core/service/Event_win.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index 5a08b5e3..c575c92a 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -29,6 +29,7 @@ Event::~Event(void) { void Event::clearSignal() { TelldusCore::MutexLocker locker(&d->mutex); + ResetEvent(d->event); d->signaled = false; } @@ -37,6 +38,11 @@ bool Event::isSignaled() { return d->signaled; } +EVENT_T Event::retrieveNative() { + TelldusCore::MutexLocker locker(&d->mutex); + return d->event; +} + void Event::signal() { SetEvent(d->event); } @@ -51,7 +57,3 @@ void Event::setSignaled() { d->signaled = true; } -EVENT_T Event::retrieveNative() { - TelldusCore::MutexLocker locker(&d->mutex); - return d->event; -} From 4d3f24d25c10b00c14677ce0b49b500e8c8d208d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:20:09 +0000 Subject: [PATCH 0231/2215] Added function EventHandler::removeEvent() --- telldus-core/service/EventHandler.h | 1 + telldus-core/service/EventHandler_win.cpp | 31 ++++++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index 323ae9d7..0302357b 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -9,6 +9,7 @@ public: virtual ~EventHandler(void); Event *addEvent(); + bool removeEvent(Event *event); void signal(Event *event); bool waitForAny(); diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index c0cb1793..6888f218 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -1,5 +1,6 @@ #include "EventHandler.h" #include "Event.h" +#include "Thread.h" #include #include @@ -8,6 +9,7 @@ class EventHandler::PrivateData { public: HANDLE *eventArray; Event **eventObjectArray; + MUTEX_T mutex; int eventCount; }; @@ -16,9 +18,11 @@ EventHandler::EventHandler() { d->eventCount = 0; d->eventArray = new HANDLE[0]; d->eventObjectArray = new Event*[0]; + TelldusCore::Thread::initMutex(&d->mutex); } EventHandler::~EventHandler(void) { + TelldusCore::Thread::destroyMutex(&d->mutex); delete[] d->eventObjectArray; delete[] d->eventArray; delete d; @@ -27,6 +31,8 @@ EventHandler::~EventHandler(void) { Event *EventHandler::addEvent() { Event *event = new Event(this); + TelldusCore::MutexLocker locker(&d->mutex); + HANDLE *newArray = new HANDLE[d->eventCount+1]; Event **newObjectArray = new Event*[d->eventCount+1]; for (int i = 0; i < d->eventCount; ++i) { @@ -43,12 +49,36 @@ Event *EventHandler::addEvent() { return event; } +bool EventHandler::removeEvent(Event *event) { + TelldusCore::MutexLocker locker(&d->mutex); + HANDLE *newArray = new HANDLE[d->eventCount-1]; + Event **newObjectArray = new Event*[d->eventCount-1]; + int index = 0; + int i = 0; + for (; i < d->eventCount; ++i) { + if ( d->eventObjectArray[i] == event ) { + continue; + } + newArray[index] = d->eventArray[i]; + newObjectArray[index] = d->eventObjectArray[i]; + ++index; + } + delete[] d->eventArray; + delete[] d->eventObjectArray; + d->eventArray = newArray; + d->eventObjectArray = newObjectArray; + --d->eventCount; + return (i != index); +} + void EventHandler::signal(Event *event) { event->signal(); } bool EventHandler::waitForAny() { int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 3000); + + TelldusCore::MutexLocker locker(&d->mutex); if (result == WAIT_TIMEOUT) { return false; } @@ -58,5 +88,4 @@ bool EventHandler::waitForAny() { } d->eventObjectArray[eventIndex]->setSignaled(); return true; - } From e82bdd8c9d5cacb368c0c669cf8abc55f63d961f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:20:42 +0000 Subject: [PATCH 0232/2215] Delete our event in the destructor --- telldus-core/service/ClientCommunicationHandler.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 18938798..10987384 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -25,6 +25,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie ClientCommunicationHandler::~ClientCommunicationHandler(void) { wait(); + delete(d->event); delete(d->clientSocket); delete d; } From 29db3d6e9a045683f188bc3367e105904f8add15 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:27:29 +0000 Subject: [PATCH 0233/2215] Our stopEvent is working again, away with the running-variable! --- telldus-core/service/TelldusMain.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index ef12bc28..ea532c22 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -10,14 +10,12 @@ class TelldusMain::PrivateData { public: EventHandler eventHandler; Event *stopEvent; - bool running; }; TelldusMain::TelldusMain(void) { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); - d->running = true; } TelldusMain::~TelldusMain(void) @@ -37,19 +35,14 @@ void TelldusMain::start(void) { std::list clientCommunicationHandlerList; - while(d->running) { + while(!d->stopEvent->isSignaled()) { if (!d->eventHandler.waitForAny()) { continue; } - /*if (d->stopEvent->isSignaled()) { - printf("Stopped\n"); - break; - }*/ if (clientEvent->isSignaled()) { clientEvent->clearSignal(); //New client connection - TelldusCore::Socket *s = clientListener.retrieveClientSocket(); if(s){ Event *handlerEvent = d->eventHandler.addEvent(); @@ -66,8 +59,7 @@ void TelldusMain::start(void) { if ((*it)->isDone()){ delete *it; it = clientCommunicationHandlerList.erase(it); - } - else{ + } else { ++it; } } @@ -81,6 +73,5 @@ void TelldusMain::start(void) { } void TelldusMain::stop(void){ - //d->eventHandler.signal(d->stopEvent); - d->running = false; + d->stopEvent->signal(); } From f581f879b2b4385f418d74abf36fcfe885126403 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:28:34 +0000 Subject: [PATCH 0234/2215] Saved the handler in Event under unix --- telldus-core/service/Event_unix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/Event_unix.cpp b/telldus-core/service/Event_unix.cpp index d2bfb34a..5873c798 100644 --- a/telldus-core/service/Event_unix.cpp +++ b/telldus-core/service/Event_unix.cpp @@ -12,6 +12,7 @@ public: Event::Event(EventHandler *handler) { d = new PrivateData; d->signaled = false; + d->handler = handler; TelldusCore::Thread::initMutex(&d->mutex); } From 93aed2099e433e4549255ac72b953301d474c76f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 15:34:42 +0000 Subject: [PATCH 0235/2215] Removed sleeps and timeouts. Now we waits forever. --- telldus-core/service/EventHandler_win.cpp | 2 +- telldus-core/service/TelldusMain.cpp | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 6888f218..35c75953 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -76,7 +76,7 @@ void EventHandler::signal(Event *event) { } bool EventHandler::waitForAny() { - int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 3000); + int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, INFINITE); TelldusCore::MutexLocker locker(&d->mutex); if (result == WAIT_TIMEOUT) { diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index ea532c22..09411df3 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -63,12 +63,6 @@ void TelldusMain::start(void) { ++it; } } - -#ifdef _WINDOWS - Sleep(1000); -#else - sleep(1); -#endif } } From 24426da77ad6b8bdbba0c7202480faa65dce3ea6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 8 Oct 2010 15:47:19 +0000 Subject: [PATCH 0236/2215] Client/service communication --- telldus-core/client/telldus-core.cpp | 54 ++++++++++++-- telldus-core/common/Message.cpp | 74 +++++++++---------- telldus-core/common/Message.h | 2 +- telldus-core/common/Socket.h | 1 + telldus-core/common/Socket_win.cpp | 26 +++++++ .../service/ClientCommunicationHandler.cpp | 39 +++++++--- .../service/ClientCommunicationHandler.h | 3 +- 7 files changed, 141 insertions(+), 58 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index d955df5e..ea433272 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -218,24 +218,62 @@ int WINAPI tdGetNumberOfDevices(void){ OVERLAPPED oOverlap; DWORD bytesWritten = 0; - + int result; + char buf[512]; //TODO #define BUFSIZE 512 + DWORD cbBytesRead = 0; + oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - std::wstring msg = L"tdGetNumberOfDevices"; + std::wstring msg = L"20:tdGetNumberOfDevices"; WriteFile(hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); - /*result = WaitForSingleObject(oOverlap.hEvent, 10000); + result = WaitForSingleObject(oOverlap.hEvent, 10000); if (result == WAIT_TIMEOUT) { CloseHandle(oOverlap.hEvent); - return; + return 16; } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, false); + fSuccess = GetOverlappedResult(hPipe, &oOverlap, &bytesWritten, false); CloseHandle(oOverlap.hEvent); if (!fSuccess) { - return; + return 8; } -*/ - return 1; + + + //READ //debug + HANDLE writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + oOverlap.hEvent = writeEvent; //TODO: correct? + fSuccess = false; + + memset(&buf, 0, 512); //#define BUFSIZE 512 + + /* + if (!d->connected) { + return ""; + } + */ + + ReadFile(hPipe, &buf, sizeof(char)*512, &cbBytesRead, &oOverlap); //#define BUFSIZE 512 + + result = WaitForSingleObject(writeEvent, 10000); //TODO timeout + if (result == WAIT_TIMEOUT) { + //CloseHandle(d->readEvent); + //d->readEvent = INVALID_HANDLE_VALUE; + return 9; + } + fSuccess = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); + if (!fSuccess) { + DWORD err = GetLastError(); + if (err == ERROR_BROKEN_PIPE) { + //d->connected = false; + } + buf[0] = 0; + } + //CloseHandle(d->readEvent); + //d->readEvent = INVALID_HANDLE_VALUE; + //return buf; + + return 2; //TODO, decode:a buf-en + //return buf[0]; //TODO } /** diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 5dd7488f..4582a55e 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -1,7 +1,7 @@ #include "Message.h" using namespace TelldusCore; #include -#include +#include #include Message::Message() @@ -19,66 +19,66 @@ Message::~Message(void) { } void Message::addArgument(const std::wstring &value) { - std::wstringstream st; - st << (int)value.size(); - this->append(st.str()); - this->append(L":"); - this->append(value); + std::wstringstream st; + st << (int)value.size(); + this->append(st.str()); + this->append(L":"); + this->append(value); } - void Message::addArgument(int value) { - std::wstringstream st; - st << (int)value; - this->append(L"i"); - this->append(st.str()); - this->append(L"e"); //TODO s? + std::wstringstream st; + st << (int)value; + this->append(L"i"); + this->append(st.str()); + this->append(L"s"); } /* void Message::addArgument(const char *value) { - this->addArgument(std::wstring(value)); + this->addArgument(std::wstring(value)); } */ bool Message::nextIsInt(const std::wstring &message) { - if (message.length() == 0) { - return false; - } - return (message.at(0) == 'i'); + if (message.length() == 0) { + return false; + } + return (message.at(0) == 'i'); } bool Message::nextIsString(const std::wstring &message) { - if (message.length() == 0) { - return false; - } - return (isdigit(message.at(0)) != 0); + if (message.length() == 0) { + return false; + } + return (iswdigit(message.at(0)) != 0); } std::wstring Message::takeString(std::wstring *message) { - if (!Message::nextIsString(*message)) { - return L""; - } - int index = message->find(':'); - int length = wideToInteger(&message->substr(0, index)); - std::wstring retval(message->substr(index+1, length)); - message->erase(0, index+length+1); - return retval; + + if (!Message::nextIsString(*message)) { + return L""; + } + int index = message->find(':'); + int length = wideToInteger(message->substr(0, index)); + std::wstring retval(message->substr(index+1, length)); + message->erase(0, index+length+1); + return retval; } int Message::takeInt(std::wstring *message) { - if (!Message::nextIsInt(*message)) { - return 0; - } - int index = message->find('e'); //TODO s? - int value = wideToInteger(&message->substr(1, index - 1)); - message->erase(0, index+1); - return value; + if (!Message::nextIsInt(*message)) { + return 0; + } + int index = message->find('s'); + int value = wideToInteger(message->substr(1, index - 1)); + message->erase(0, index+1); + return value; } -int wideToInteger(std::wstring *input){ +int Message::wideToInteger(const std::wstring &input){ std::wstringstream inputstream; inputstream << input; int retval; diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 363d5359..c205f793 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -21,7 +21,7 @@ namespace TelldusCore { static int takeInt(std::wstring *); private: - static int wideToInteger(std::wstring *input); + static int wideToInteger(const std::wstring &input); }; } diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index b84ee33f..4ef58824 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -18,6 +18,7 @@ namespace TelldusCore { virtual ~Socket(void); std::wstring read(); + void write(const std::wstring &msg); private: class PrivateData; diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 32277c6e..0954cdae 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -55,4 +55,30 @@ std::wstring Socket::read() { } CloseHandle(readEvent); return buf; +} + +void Socket::write(const std::wstring &msg){ + + OVERLAPPED oOverlap; + DWORD bytesWritten = 0; + int result; + bool fSuccess; + + HANDLE writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + oOverlap.hEvent = writeEvent; + + WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); + + result = WaitForSingleObject(writeEvent, 10000); + if (result == WAIT_TIMEOUT) { + CloseHandle(writeEvent); + //d->connected = false; + return; + } + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, false); + CloseHandle(writeEvent); + if (!fSuccess) { + //d->connected = false; + return; + } } \ No newline at end of file diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 10987384..173e8a8d 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -36,9 +36,25 @@ void ClientCommunicationHandler::run(){ std::wstring clientMessage = d->clientSocket->read(); - //std::wstring temp = parseMessage(clientMessage); - + int intTemp; + std::wstring strReturn; + strReturn = L""; + parseMessage(clientMessage, intTemp, strReturn); + TelldusCore::Message msg; + /* TODO + if (response.type() == QVariant::Int) { + msg.addArgument(response.toInt()); + } else { + */ + //allt som wstring ? + if(strReturn == L""){ + msg.addArgument(intTemp); + } + // msg.addArgument(temp); //temp.toString().toStdString()); + //} + msg.append(L"\n"); + d->clientSocket->write(msg); //We are done, signal for removal d->done = true; @@ -50,17 +66,18 @@ bool ClientCommunicationHandler::isDone(){ } -std::wstring parseMessage(const std::wstring &clientMessage){ +void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int &intReturn, std::wstring &wstringReturn){ std::wstring msg(clientMessage); //Copy - //std::wstring function(TelldusCore::Message::takeString(&msg)); - if(clientMessage == L"tdGetNumberOfDevices"){ - //starta ny tråd (ny klass, ärv från Thread) - //skicka in meddelandet i denna tråd - //kolla där vad det är för meddelande - //do stuff - //TODO + std::wstring function(TelldusCore::Message::takeString(&msg)); + + if(function == L"tdGetNumberOfDevices"){ + + //return L"12"; + intReturn = 12; } + + intReturn = 5; - return L"Dummy"; + //return L"5"; } diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 50305194..31f92858 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -21,7 +21,8 @@ protected: private: class PrivateData; PrivateData *d; - std::wstring parseMessage(std::wstring &clientMessage); + //std::wstring parseMessage(const std::wstring &clientMessage); + void parseMessage(const std::wstring &clientMessage, int &intReturn, std::wstring &wstringReturn); }; #endif //CLIENTCOMMUNICATIONHANDLER_H \ No newline at end of file From 9100a0bdcf59643bc02d6abe34366aa2a6a5813e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 16:36:39 +0000 Subject: [PATCH 0237/2215] Added our common library in TelldusCore --- telldus-core/client/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 622f5647..dba24a24 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -31,6 +31,9 @@ ELSE (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) ADD_DEFINITIONS( -DLIBFTDI ) ENDIF (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/../common +) ######## Configurable options for the platform ######## @@ -49,6 +52,9 @@ ELSEIF (WIN32) ADD_DEFINITIONS( -DUNICODE ) ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No SET( telldus-core_TARGET TelldusCore ) + LIST(APPEND telldus-core_LIBRARIES + ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib + ) #IF (NOT CMAKE_CL_64) LIST(APPEND telldus-core_SRCS libtelldus-core.def From 56ae5048aa1d6fb0c620a51a3a057cfd21a466d3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 16:37:27 +0000 Subject: [PATCH 0238/2215] Move the communication to Socket. --- telldus-core/client/telldus-core.cpp | 92 ++-------------------------- telldus-core/common/Socket.h | 1 + telldus-core/common/Socket_win.cpp | 35 +++++++++++ 3 files changed, 41 insertions(+), 87 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index ea433272..3f8c5d93 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -6,6 +6,7 @@ #include "telldus-core.h" #include "common.h" +#include "Socket.h" #include @@ -185,95 +186,12 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * @returns an integer of the total number of devices configured */ int WINAPI tdGetNumberOfDevices(void){ - DWORD dwMode; - bool fSuccess = false; - - //Convert our std::string to std::wstring since we build agains win32 with unicode support - //std::string strName = "\\\\.\\pipe\\" + server; - std::wstring name(L"\\\\.\\pipe\\TelldusClient"); - HANDLE hPipe = CreateFile( - (const wchar_t *)name.c_str(), // pipe name - GENERIC_READ | // read and write access - GENERIC_WRITE, - 0, // no sharing - NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - FILE_FLAG_OVERLAPPED, // default attributes - NULL); // no template file - - if (hPipe == INVALID_HANDLE_VALUE) { - return 2; - } - - dwMode = PIPE_READMODE_MESSAGE; - fSuccess = SetNamedPipeHandleState( - hPipe, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time - - if (!fSuccess) { - return 3; - } - - OVERLAPPED oOverlap; - DWORD bytesWritten = 0; - int result; - char buf[512]; //TODO #define BUFSIZE 512 - DWORD cbBytesRead = 0; - - oOverlap.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + TelldusCore::Socket s(L"TelldusClient"); std::wstring msg = L"20:tdGetNumberOfDevices"; - WriteFile(hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); - - result = WaitForSingleObject(oOverlap.hEvent, 10000); - if (result == WAIT_TIMEOUT) { - CloseHandle(oOverlap.hEvent); - return 16; - } - - fSuccess = GetOverlappedResult(hPipe, &oOverlap, &bytesWritten, false); - CloseHandle(oOverlap.hEvent); - if (!fSuccess) { - return 8; - } + s.write(msg); - - //READ //debug - HANDLE writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - oOverlap.hEvent = writeEvent; //TODO: correct? - fSuccess = false; - - memset(&buf, 0, 512); //#define BUFSIZE 512 - - /* - if (!d->connected) { - return ""; - } - */ - - ReadFile(hPipe, &buf, sizeof(char)*512, &cbBytesRead, &oOverlap); //#define BUFSIZE 512 - - result = WaitForSingleObject(writeEvent, 10000); //TODO timeout - if (result == WAIT_TIMEOUT) { - //CloseHandle(d->readEvent); - //d->readEvent = INVALID_HANDLE_VALUE; - return 9; - } - fSuccess = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); - if (!fSuccess) { - DWORD err = GetLastError(); - if (err == ERROR_BROKEN_PIPE) { - //d->connected = false; - } - buf[0] = 0; - } - //CloseHandle(d->readEvent); - //d->readEvent = INVALID_HANDLE_VALUE; - //return buf; - - return 2; //TODO, decode:a buf-en - //return buf[0]; //TODO + std::wstring response = s.read(); + return 1; } /** diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 4ef58824..9a8ce2f5 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -14,6 +14,7 @@ namespace TelldusCore { class Socket { public: + Socket(const std::wstring &server); Socket(SOCKET_T hPipe); virtual ~Socket(void); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 0954cdae..1cc48376 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -11,8 +11,43 @@ using namespace TelldusCore; class Socket::PrivateData { public: HANDLE hPipe; + bool connected; }; +Socket::Socket(const std::wstring &server) { + d = new PrivateData; + d->connected = false; + + bool fSuccess = false; + + std::wstring name(L"\\\\.\\pipe\\" + server); + d->hPipe = CreateFile( + (const wchar_t *)name.c_str(), // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, // default attributes + NULL); // no template file + + if (d->hPipe == INVALID_HANDLE_VALUE) { + return; + } + + DWORD dwMode = PIPE_READMODE_MESSAGE; + fSuccess = SetNamedPipeHandleState( + d->hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time + + if (!fSuccess) { + return; + } + d->connected = true; +} + Socket::Socket(SOCKET_T hPipe) { d = new PrivateData; From 53cce71b751ceb73e9bbb4714074766243191edb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 18:55:02 +0000 Subject: [PATCH 0239/2215] Build client library against telldus-common on Mac OS X --- telldus-core/client/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index dba24a24..543afd26 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -47,6 +47,9 @@ IF (APPLE) ADD_DEFINITIONS( -D_MACOSX ) + LIST(APPEND telldus-core_LIBRARIES + TelldusCommon + ) ELSEIF (WIN32) #### Windows #### ADD_DEFINITIONS( -DUNICODE ) From a2431533bdc42e4775bd2ef57859e613cecf9249 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 18:55:41 +0000 Subject: [PATCH 0240/2215] Added function stubs Socket::Socket() and Socket::write() --- telldus-core/common/Socket_unix.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index aa724b45..83c45d2e 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -6,6 +6,10 @@ class Socket::PrivateData { public: }; +Socket::Socket(const std::wstring &server) { + +} + Socket::Socket(SOCKET_T hPipe) { d = new PrivateData; @@ -18,3 +22,7 @@ Socket::~Socket(void){ std::wstring Socket::read() { return L""; } + +void Socket::write(const std::wstring &msg) { + +} From 3890e491c2d65c26e6655ef342336183c944047e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Oct 2010 21:06:49 +0000 Subject: [PATCH 0241/2215] Fixed typedef for SOCKET_T in unix. It it signed --- telldus-core/common/Socket.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 9a8ce2f5..02f0961c 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -7,7 +7,7 @@ #include typedef HANDLE SOCKET_T; #else - typedef unsigned int SOCKET_T; + typedef int SOCKET_T; #endif namespace TelldusCore { From 407cf1584a079c65d91b658858fd64fdd94daa7d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 11 Oct 2010 08:08:08 +0000 Subject: [PATCH 0242/2215] tdGetNumberOfDevices now communicates as expected. --- telldus-core/client/telldus-core.cpp | 6 ++-- telldus-core/common/Socket.h | 3 +- telldus-core/common/Socket_win.cpp | 33 ++++++++++--------- .../service/ClientCommunicationHandler.cpp | 11 ++++--- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 3f8c5d93..ab2b1df4 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -6,6 +6,7 @@ #include "telldus-core.h" #include "common.h" +#include "Message.h" #include "Socket.h" #include @@ -186,12 +187,13 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * @returns an integer of the total number of devices configured */ int WINAPI tdGetNumberOfDevices(void){ - TelldusCore::Socket s(L"TelldusClient"); + TelldusCore::Socket s; + s.connect(L"TelldusClient"); std::wstring msg = L"20:tdGetNumberOfDevices"; s.write(msg); std::wstring response = s.read(); - return 1; + return TelldusCore::Message::takeInt(&response); } /** diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 02f0961c..5c95a64a 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -14,10 +14,11 @@ namespace TelldusCore { class Socket { public: - Socket(const std::wstring &server); + Socket(); Socket(SOCKET_T hPipe); virtual ~Socket(void); + void connect(const std::wstring &server); std::wstring read(); void write(const std::wstring &msg); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 1cc48376..b4051cb2 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -14,10 +14,27 @@ public: bool connected; }; -Socket::Socket(const std::wstring &server) { +Socket::Socket() { d = new PrivateData; d->connected = false; +} +Socket::Socket(SOCKET_T hPipe) +{ + d = new PrivateData; + d->hPipe = hPipe; + +} + + +Socket::~Socket(void){ + if (d->hPipe != INVALID_HANDLE_VALUE) { + CloseHandle(d->hPipe); + } + delete d; +} + +void Socket::connect(const std::wstring &server){ bool fSuccess = false; std::wstring name(L"\\\\.\\pipe\\" + server); @@ -48,20 +65,6 @@ Socket::Socket(const std::wstring &server) { d->connected = true; } -Socket::Socket(SOCKET_T hPipe) -{ - d = new PrivateData; - d->hPipe = hPipe; - -} - -Socket::~Socket(void){ - if (d->hPipe != INVALID_HANDLE_VALUE) { - CloseHandle(d->hPipe); - } - delete d; -} - std::wstring Socket::read() { wchar_t buf[BUFSIZE]; int result; diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 173e8a8d..cf0585a5 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -51,8 +51,9 @@ void ClientCommunicationHandler::run(){ if(strReturn == L""){ msg.addArgument(intTemp); } - // msg.addArgument(temp); //temp.toString().toStdString()); - //} + else{ + msg.addArgument(strReturn); //temp.toString().toStdString()); + } msg.append(L"\n"); d->clientSocket->write(msg); @@ -76,8 +77,8 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, //return L"12"; intReturn = 12; } - - intReturn = 5; - + else{ + intReturn = 5; + } //return L"5"; } From f808fb2a5e2f915732214c9acc7493bd1a5850d1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 08:34:53 +0000 Subject: [PATCH 0243/2215] Check so the thread is running in Thread::wait() --- telldus-core/common/Thread.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index 404ea95b..7f90215b 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -34,6 +34,7 @@ public: Thread::Thread() { d = new ThreadPrivate; + d->thread = 0; initMutex(&d->mutex); lockMutex(&d->mutex); @@ -70,6 +71,9 @@ void Thread::start() { } bool Thread::wait() { + if (!d->thread) { + return true; + } #ifdef _WINDOWS WaitForSingleObject(d->thread, INFINITE); CloseHandle(d->thread); From cfbfc1a5dbd499cd632cabf99ead7c42c7be7618 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 08:50:16 +0000 Subject: [PATCH 0244/2215] ConnectionListener now runs in its own loop. --- telldus-core/service/ConnectionListener.h | 10 +-- .../service/ConnectionListener_win.cpp | 67 +++++++++++++------ telldus-core/service/TelldusMain.cpp | 9 +-- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index 2a9a9fec..18db5f0a 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -2,20 +2,22 @@ #define CONNECTIONLISTENER_H #include +#include "Thread.h" class Event; namespace TelldusCore { class Socket; }; -class ConnectionListener -{ +class ConnectionListener : public TelldusCore::Thread { public: - ConnectionListener(const std::wstring &name); + ConnectionListener(const std::wstring &name, Event *waitEvent); virtual ~ConnectionListener(void); - void listen(Event *waitEvent); TelldusCore::Socket *retrieveClientSocket(); +protected: + void run(); + private: class PrivateData; PrivateData *d; diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 01bce0ec..8f3e0ac9 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -12,16 +12,20 @@ class ConnectionListener::PrivateData { public: std::wstring pipename; SECURITY_ATTRIBUTES sa; - HANDLE hPipe; - OVERLAPPED oOverlap; + TelldusCore::Socket *socket; + HANDLE hEvent; + bool running; + Event *waitEvent; }; -ConnectionListener::ConnectionListener(const std::wstring &name) +ConnectionListener::ConnectionListener(const std::wstring &name, Event *waitEvent) { d = new PrivateData; + d->hEvent = 0; + d->running = true; + d->waitEvent = waitEvent; d->pipename = L"\\\\.\\pipe\\" + name; - PSECURITY_DESCRIPTOR pSD = NULL; PACL pACL = NULL; @@ -67,18 +71,29 @@ ConnectionListener::ConnectionListener(const std::wstring &name) d->sa.lpSecurityDescriptor = pSD; d->sa.bInheritHandle = false; + start(); } -ConnectionListener::~ConnectionListener(void) -{ +ConnectionListener::~ConnectionListener(void) { + d->running = false; + if (d->hEvent) { + SetEvent(d->hEvent); + } + wait(); + delete d->waitEvent; delete d; } -void ConnectionListener::listen(Event *waitEvent){ +void ConnectionListener::run() { + HANDLE hPipe; + OVERLAPPED oOverlap; + DWORD cbBytesRead; + + d->hEvent = CreateEvent(NULL, true, false, NULL); + oOverlap.hEvent = d->hEvent; - d->oOverlap.hEvent = waitEvent->retrieveNative(); - - d->hPipe = CreateNamedPipe( + while (1) { + hPipe = CreateNamedPipe( (const wchar_t *)d->pipename.c_str(), // pipe name PIPE_ACCESS_DUPLEX | // read/write access FILE_FLAG_OVERLAPPED, //Overlapped mode @@ -91,23 +106,33 @@ void ConnectionListener::listen(Event *waitEvent){ 0, // client time-out &d->sa); // default security attribute - if (d->hPipe == INVALID_HANDLE_VALUE) { + if (hPipe == INVALID_HANDLE_VALUE) { //TelldusCore::logMessage("Could not create named pipe"); return; } - ConnectNamedPipe(d->hPipe, &d->oOverlap); + ConnectNamedPipe(hPipe, &oOverlap); + + WaitForSingleObject(oOverlap.hEvent, INFINITE); + + if (!d->running) { + break; + } + + BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); + if (!connected) { + CloseHandle(hPipe); + return; + } + d->socket = new TelldusCore::Socket(hPipe); + d->waitEvent->signal(); + } + + CloseHandle(d->hEvent); + CloseHandle(hPipe); } TelldusCore::Socket *ConnectionListener::retrieveClientSocket(){ - DWORD cbBytesRead; - - bool connected = GetOverlappedResult(d->hPipe, &d->oOverlap, &cbBytesRead, false); - if (!connected) { - CloseHandle(d->hPipe); - return 0; - } - TelldusCore::Socket *s = new TelldusCore::Socket(d->hPipe); - return s; + return d->socket; } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 09411df3..a79a075f 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -27,12 +27,9 @@ TelldusMain::~TelldusMain(void) void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); - ConnectionListener clientListener(L"TelldusClient"); + ConnectionListener clientListener(L"TelldusClient", clientEvent); //TODO: eventlistener - clientListener.listen(clientEvent); - //TODO: listen on eventListener - std::list clientCommunicationHandlerList; while(!d->stopEvent->isSignaled()) { @@ -44,14 +41,12 @@ void TelldusMain::start(void) { //New client connection TelldusCore::Socket *s = clientListener.retrieveClientSocket(); - if(s){ + if (s){ Event *handlerEvent = d->eventHandler.addEvent(); ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(s, handlerEvent); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } - - clientListener.listen(clientEvent); } From 0b5f5faaccf0d974b0c36f4eef02b947d7c05d30 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 08:50:36 +0000 Subject: [PATCH 0245/2215] Made Event::retrieveNative() protected. --- telldus-core/service/Event.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 99ec1674..a510e568 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -16,13 +16,13 @@ public: void clearSignal(); bool isSignaled(); - EVENT_T retrieveNative(); void signal(); protected: Event(EventHandler *handler); - void setSignaled(); void clearHandler(); + void setSignaled(); + EVENT_T retrieveNative(); private: class PrivateData; From e9195b9de641f1be54bd2fedeb0f57d89b2cc109 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 10:12:09 +0000 Subject: [PATCH 0246/2215] Added Settings-class. Untested! --- telldus-core/service/CMakeLists.txt | 13 +- telldus-core/service/Settings.cpp | 75 ++++++ telldus-core/service/Settings.h | 42 ++++ telldus-core/service/SettingsWinRegistry.cpp | 240 +++++++++++++++++++ 4 files changed, 365 insertions(+), 5 deletions(-) create mode 100644 telldus-core/service/Settings.cpp create mode 100644 telldus-core/service/Settings.h create mode 100644 telldus-core/service/SettingsWinRegistry.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index fa2ec19c..96754d7e 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -4,15 +4,17 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-service_SRCS - TelldusMain.cpp ClientCommunicationHandler.cpp + Settings.cpp + TelldusMain.cpp ) SET( telldus-service_HDRS - TelldusMain.h + ClientCommunicationHandler.h ConnectionListener.h Event.h - ClientCommunicationHandler.h EventHandler.h + Settings.h + TelldusMain.h ) FIND_PACKAGE(Threads) @@ -55,11 +57,12 @@ ELSEIF (WIN32) #### Windows #### ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib ) LIST(APPEND telldus-service_SRCS - main_win.cpp - TelldusWinService_win.cpp ConnectionListener_win.cpp Event_win.cpp EventHandler_win.cpp + main_win.cpp + SettingsWinRegistry.cpp + TelldusWinService_win.cpp ) LIST(APPEND telldus-service_HDRS TelldusWinService_win.h diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp new file mode 100644 index 00000000..d6c32039 --- /dev/null +++ b/telldus-core/service/Settings.cpp @@ -0,0 +1,75 @@ +#include "Settings.h" + +/* +* Get the name of the device +*/ +std::wstring Settings::getName(int intDeviceId) const { + return getStringSetting(intDeviceId, L"name", false); +} + +/* +* Set the name of the device +*/ +bool Settings::setName(int intDeviceId, const std::wstring &strNewName){ + return setStringSetting(intDeviceId, L"name", strNewName, false); +} + +/* +* Get the device vendor +*/ +std::wstring Settings::getProtocol(int intDeviceId) const { + return getStringSetting(intDeviceId, L"protocol", false); +} + +/* +* Set the device vendor +*/ +bool Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ + return setStringSetting(intDeviceId, L"protocol", strVendor, false); +} + +/* +* Get the device model +*/ +std::wstring Settings::getModel(int intDeviceId) const { + return getStringSetting(intDeviceId, L"model", false); +} + +/* +* Set the device model +*/ +bool Settings::setModel(int intDeviceId, const std::wstring &strModel){ + return setStringSetting(intDeviceId, L"model", strModel, false); +} + +/* +* Set device argument +*/ +bool Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue){ + return setStringSetting(intDeviceId, strName, strValue, true); +} + +/* +* Get device argument +*/ +std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &strName) const { + return getStringSetting(intDeviceId, strName, true); +} + +#ifndef _CONFUSE + +bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { + bool retval = setIntSetting( intDeviceId, L"state", intDeviceState, true ); + setStringSetting( intDeviceId, L"stateValue", strDeviceStateValue, true ); + return retval; +} + +int Settings::getDeviceState( int intDeviceId ) const { + return getIntSetting( intDeviceId, L"state", true ); +} + +std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { + return getStringSetting( intDeviceId, L"stateValue", true ); +} + +#endif diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h new file mode 100644 index 00000000..837aaa8b --- /dev/null +++ b/telldus-core/service/Settings.h @@ -0,0 +1,42 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include + +class Settings { +public: + Settings(void); + std::wstring getSetting(const std::wstring &strName) const; + int getNumberOfDevices(void) const; + std::wstring getName(int intDeviceId) const; + bool setName(int intDeviceId, const std::wstring &strNewName); + std::wstring getProtocol(int intDeviceId) const; + bool setProtocol(int intDeviceId, const std::wstring &strVendor); + std::wstring getModel(int intDeviceId) const; + bool setModel(int intDeviceId, const std::wstring &strModel); + std::wstring getDeviceParameter(int intDeviceId, const std::wstring &strName) const; + bool setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue); + bool setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); + int getDeviceState( int intDeviceId ) const; + std::wstring getDeviceStateValue( int intDeviceId ) const; + + int addDevice(); + int getDeviceId(int intDeviceIndex) const; + bool removeDevice(int intDeviceId); + + ~Settings(void); + +protected: + std::wstring getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const; + bool setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter); + int getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const; + bool setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter); + +private: + int getNextDeviceId() const; + + class PrivateData; + PrivateData *d; +}; + +#endif diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp new file mode 100644 index 00000000..e7360fc9 --- /dev/null +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -0,0 +1,240 @@ +#include "Settings.h" +#include +#include +#include +#include +#include +#include + +const int intMaxRegValueLength = 1000; + +class Settings::PrivateData { +public: + HKEY rootKey; + std::wstring strRegPathDevice; + std::wstring strRegPath; +}; + +/* +* Constructor +*/ +Settings::Settings(void) { + d = new PrivateData(); + d->strRegPathDevice = L"SOFTWARE\\Telldus\\Devices\\"; + d->strRegPath = L"SOFTWARE\\Telldus\\"; + d->rootKey = HKEY_LOCAL_MACHINE; +} + +/* +* Destructor +*/ +Settings::~Settings(void) { + delete d; +} + +/* +* Return the number of stored devices +*/ +int Settings::getNumberOfDevices(void) const { + + int intNumberOfDevices = 0; + HKEY hk; + + long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + + std::wstring strNumSubKeys; + DWORD dNumSubKeys; + RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + intNumberOfDevices = (int)dNumSubKeys; + + RegCloseKey(hk); + } + return intNumberOfDevices; +} + + +int Settings::getDeviceId(int intDeviceIndex) const { + int intReturn = -1; + HKEY hk; + + long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_READ, &hk); + + if(lnExists == ERROR_SUCCESS){ + + wchar_t* Buff = new wchar_t[intMaxRegValueLength]; + DWORD size = intMaxRegValueLength; + if (RegEnumKeyEx(hk, intDeviceIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + intReturn = _wtoi(Buff); + } + + delete Buff; + RegCloseKey(hk); + } + return intReturn; +} + +/* +* Add a new device +*/ +int Settings::addDevice(){ + + int intDeviceId = -1; + HKEY hk; + + DWORD dwDisp; + intDeviceId = getNextDeviceId(); + + std::wostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + std::wstring strCompleteRegPath = ssRegPath.str(); + + if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) { + //fail + intDeviceId = -1; + } + + RegCloseKey(hk); + return intDeviceId; +} + +/* +* Get next available device id +*/ +int Settings::getNextDeviceId() const { + int intReturn = -1; + HKEY hk; + DWORD dwDisp; + + long lnExists = RegCreateKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created + + if(lnExists == ERROR_SUCCESS){ + + DWORD dwLength; + char *Buff = new char[intMaxRegValueLength]; + + long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + //The buffer is to small, recreate it + delete Buff; + Buff = new char[dwLength]; + lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); + } + + if(lngStatus == ERROR_SUCCESS){ + + int intLast = (int)Buff[0]; + intReturn = intLast + 1; + } else { + intReturn = 1; + } + delete Buff; + + DWORD dwVal = intReturn; + + RegSetValueEx (hk, L"LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + + } + RegCloseKey(hk); + return intReturn; +} + +/* +* Remove a device +*/ +bool Settings::removeDevice(int intDeviceId){ + bool blnSuccess = true; + + std::wostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + std::wstring strCompleteRegPath = ssRegPath.str(); + + long lngSuccess = RegDeleteKeyEx(d->rootKey, strCompleteRegPath.c_str(), KEY_WOW64_32KEY|KEY_WOW64_64KEY, 0); + if(lngSuccess != ERROR_SUCCESS){ + blnSuccess = false; + } + + return blnSuccess; +} + +std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const { + std::wstring strReturn; + HKEY hk; + + std::wostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + std::wstring strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + wchar_t* Buff = new wchar_t[intMaxRegValueLength]; + DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; + long lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + //The buffer is to small, recreate it + delete Buff; + Buff = new wchar_t[dwLength]; + lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + } + if (lngStatus == ERROR_SUCCESS) { + strReturn = Buff; + } + delete Buff; + } + RegCloseKey(hk); + return strReturn; +} + +bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { + + bool blnSuccess = false; + HKEY hk; + + std::wostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + std::wstring strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if (lnExists == ERROR_SUCCESS){ + int length = (int)value.length(); + RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); + } + RegCloseKey(hk); + + return blnSuccess; + +} + +int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const { + int intReturn = 0; + + std::wstring strSetting = getStringSetting(intDeviceId, name, parameter); + if (strSetting.length()) { + intReturn = (int)strSetting[0]; + } + + return intReturn; +} + +bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { + bool blnReturn = false; + HKEY hk; + + std::wostringstream ssRegPath; + ssRegPath << d->strRegPathDevice << intDeviceId; + std::wstring strCompleteRegPath = ssRegPath.str(); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + if (lnExists == ERROR_SUCCESS) { + DWORD dwVal = value; + lnExists = RegSetValueEx (hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + if (lnExists == ERROR_SUCCESS) { + blnReturn = true; + } + } + RegCloseKey(hk); + return blnReturn; +} From cfee7a5f9a7d0c58db657c344a54603bacb0693d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 10:29:37 +0000 Subject: [PATCH 0247/2215] Removed the thread event system. This is obsolete by our new standalone event system --- telldus-core/common/Thread.cpp | 73 ---------------------------------- telldus-core/common/Thread.h | 3 -- 2 files changed, 76 deletions(-) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index 7f90215b..a13cd1d4 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -24,41 +24,14 @@ public: pthread_t thread; pthread_cond_t noEvent, noWait; #endif - MUTEX_T mutex; - - //Must be locked by the mutex! - bool hasEvent; - std::string strMessage; - int intMessage; }; Thread::Thread() { d = new ThreadPrivate; d->thread = 0; - initMutex(&d->mutex); - - lockMutex(&d->mutex); - d->hasEvent = false; - unlockMutex(&d->mutex); - -#ifdef _WINDOWS - d->noEvent = CreateEvent(0, FALSE, FALSE, 0); - d->noWait = CreateEvent(0, FALSE, FALSE, 0); -#else - pthread_cond_init(&d->noEvent, NULL); - pthread_cond_init(&d->noWait, NULL); -#endif } Thread::~Thread() { - destroyMutex(&d->mutex); -#ifdef _WINDOWS - CloseHandle(d->noEvent); - CloseHandle(d->noWait); -#else - pthread_cond_destroy(&d->noEvent); - pthread_cond_destroy(&d->noWait); -#endif delete d; } @@ -91,52 +64,6 @@ void *Thread::exec( void *ptr ) { return 0; } -std::string Thread::waitForEvent(int *intMessage) { - std::string strMessage; - lockMutex(&d->mutex); - while(!d->hasEvent) { -#ifdef _WINDOWS - unlockMutex(&d->mutex); - WaitForSingleObject(d->noWait, INFINITE); - lockMutex(&d->mutex); -#else - pthread_cond_wait(&d->noWait, &d->mutex); -#endif - } - d->hasEvent = false; - strMessage = d->strMessage; - (*intMessage) = d->intMessage; - unlockMutex(&d->mutex); -#ifdef _WINDOWS - SetEvent(d->noEvent); -#else - pthread_cond_broadcast(&d->noEvent); -#endif - return strMessage; -} - -void Thread::sendEvent(const std::string &strMessage, int intMessage) { - lockMutex(&d->mutex); - while (d->hasEvent) { //We have an unprocessed event -#ifdef _WINDOWS - unlockMutex(&d->mutex); - WaitForSingleObject(d->noEvent, INFINITE); - lockMutex(&d->mutex); -#else - pthread_cond_wait(&d->noEvent, &d->mutex); -#endif - } - d->hasEvent = true; - d->strMessage = strMessage; - d->intMessage = intMessage; - unlockMutex(&d->mutex); -#ifdef _WINDOWS - SetEvent(d->noWait); -#else - pthread_cond_broadcast(&d->noWait); -#endif -} - void Thread::initMutex(MUTEX_T * m) { #ifdef _WINDOWS InitializeCriticalSection(m); diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index 7f30052f..35fbe1f3 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -31,8 +31,6 @@ namespace TelldusCore { void start(); bool wait(); - void sendEvent(const std::string &string, int integer = 0); - static void initMutex(MUTEX_T *m); static void destroyMutex(MUTEX_T *m); static void lockMutex(MUTEX_T *m); @@ -40,7 +38,6 @@ namespace TelldusCore { protected: virtual void run() = 0; - std::string waitForEvent(int *intMessage); private: static void* exec( void *ptr ); From 5469671079b42558bb485c6a220a5db20ef66e79 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 10:30:39 +0000 Subject: [PATCH 0248/2215] Removed unused variables. --- telldus-core/common/Thread.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index a13cd1d4..ef70dc27 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -19,10 +19,8 @@ public: #ifdef _WINDOWS HANDLE thread; DWORD threadId; - HANDLE noEvent, noWait; #else pthread_t thread; - pthread_cond_t noEvent, noWait; #endif }; From 509541f29cd23311fb20d3138a7cab2ea2104104 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 12:37:08 +0000 Subject: [PATCH 0249/2215] Rewrite of the class Event, now with signal data. This probably breaks Unix big-time... --- telldus-core/service/CMakeLists.txt | 1 + telldus-core/service/Event.cpp | 68 ++++++++++++++++++++++ telldus-core/service/Event.h | 39 +++++++++++-- telldus-core/service/EventHandler.h | 7 ++- telldus-core/service/EventHandler_unix.cpp | 2 +- telldus-core/service/EventHandler_win.cpp | 6 +- telldus-core/service/Event_unix.cpp | 29 ++------- telldus-core/service/Event_win.cpp | 42 +++---------- telldus-core/service/TelldusMain.cpp | 2 +- 9 files changed, 124 insertions(+), 72 deletions(-) create mode 100644 telldus-core/service/Event.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 96754d7e..585e895b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -5,6 +5,7 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-service_SRCS ClientCommunicationHandler.cpp + Event.cpp Settings.cpp TelldusMain.cpp ) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp new file mode 100644 index 00000000..f82e06d5 --- /dev/null +++ b/telldus-core/service/Event.cpp @@ -0,0 +1,68 @@ +#include "Event.h" +#include "EventHandler.h" + +#include + +bool EventData::isValid() const { + return false; +}; + +bool EventDataBase::isValid() const { + return true; +}; + +class EventBase::PrivateData { +public: + MUTEX_T mutex; + EventHandler *handler; + std::list eventDataList; +}; + +EventBase::EventBase(EventHandler *handler) { + d = new PrivateData; + d->handler = handler; + TelldusCore::Thread::initMutex(&d->mutex); +} + +EventBase::~EventBase(void) { + if (d->handler) { + d->handler->removeEvent(this); + } + TelldusCore::Thread::destroyMutex(&d->mutex); + delete d; +} + +void EventBase::clearHandler() { + TelldusCore::MutexLocker locker(&d->mutex); + d->handler = 0; +} + +bool EventBase::isSignaled() { + TelldusCore::MutexLocker locker(&d->mutex); + return (d->eventDataList.size() > 0); +} + +void EventBase::signal() { + signal(EventData()); +} + +void EventBase::signal(const EventData &eventData) { + { + TelldusCore::MutexLocker locker(&d->mutex); + d->eventDataList.push_back(eventData); + } + sendSignal(); +} + +EventData EventBase::takeSignal() { + TelldusCore::MutexLocker locker(&d->mutex); + if (d->eventDataList.size() == 0) { + return EventData(); + } + EventData data = d->eventDataList.front(); + d->eventDataList.pop_front(); + if (d->eventDataList.size() == 0) { + this->clearSignal(); + } + return data; +} \ No newline at end of file diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index a510e568..cbd5ba94 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -2,6 +2,7 @@ #define EVENT_H class EventHandler; +#include "Thread.h" #ifdef _WINDOWS #include @@ -10,19 +11,45 @@ class EventHandler; typedef void* EVENT_T; #endif -class Event { +class EventData { public: - virtual ~Event(); + bool isValid() const; +}; + +class EventDataBase : public EventData { +public: + bool isValid() const; +}; + +class EventBase { +public: + virtual ~EventBase(); - void clearSignal(); bool isSignaled(); void signal(); - + virtual void signal(const EventData &); + EventData takeSignal(); + +protected: + EventBase(EventHandler *handler); + void clearHandler(); + virtual void clearSignal() = 0; + virtual void sendSignal() = 0; + +private: + class PrivateData; + PrivateData *d; +}; + +class Event : public EventBase { +public: + virtual ~Event(); + protected: Event(EventHandler *handler); - void clearHandler(); - void setSignaled(); EVENT_T retrieveNative(); + virtual void clearSignal(); + virtual void sendSignal(); private: class PrivateData; diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index 0302357b..5a396b40 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -2,6 +2,7 @@ #define EVENTHANDLER_H class Event; +class EventBase; class EventHandler { public: @@ -9,11 +10,13 @@ public: virtual ~EventHandler(void); Event *addEvent(); - bool removeEvent(Event *event); + bool removeEvent(EventBase *event); - void signal(Event *event); bool waitForAny(); +protected: + void signal(Event *event); + private: class PrivateData; PrivateData *d; diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index eecaeb6e..fbf577f3 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -30,7 +30,7 @@ Event *EventHandler::addEvent() { void EventHandler::signal(Event *event) { pthread_mutex_lock(&d->mutex); - event->setSignaled(); + //event->setSignaled(); d->hasEvent = true; pthread_cond_signal(&d->event); pthread_mutex_unlock(&d->mutex); diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 35c75953..3a9b653f 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -49,7 +49,7 @@ Event *EventHandler::addEvent() { return event; } -bool EventHandler::removeEvent(Event *event) { +bool EventHandler::removeEvent(EventBase *event) { TelldusCore::MutexLocker locker(&d->mutex); HANDLE *newArray = new HANDLE[d->eventCount-1]; Event **newObjectArray = new Event*[d->eventCount-1]; @@ -71,8 +71,7 @@ bool EventHandler::removeEvent(Event *event) { return (i != index); } -void EventHandler::signal(Event *event) { - event->signal(); +void EventHandler::signal(Event *) { } bool EventHandler::waitForAny() { @@ -86,6 +85,5 @@ bool EventHandler::waitForAny() { if (eventIndex >= d->eventCount) { return false; } - d->eventObjectArray[eventIndex]->setSignaled(); return true; } diff --git a/telldus-core/service/Event_unix.cpp b/telldus-core/service/Event_unix.cpp index 5873c798..a5f4c074 100644 --- a/telldus-core/service/Event_unix.cpp +++ b/telldus-core/service/Event_unix.cpp @@ -4,38 +4,19 @@ class Event::PrivateData { public: - bool signaled; - EventHandler *handler; - MUTEX_T mutex; }; Event::Event(EventHandler *handler) { d = new PrivateData; - d->signaled = false; - d->handler = handler; - TelldusCore::Thread::initMutex(&d->mutex); } Event::~Event(void) { - TelldusCore::Thread::destroyMutex(&d->mutex); delete d; } -void Event::clearSignal() { - TelldusCore::MutexLocker locker(&d->mutex); - d->signaled = false; -} - -bool Event::isSignaled() { - TelldusCore::MutexLocker locker(&d->mutex); - return d->signaled; -} - -void Event::signal() { - d->handler->signal(this); -} - -void Event::setSignaled() { - TelldusCore::MutexLocker locker(&d->mutex); - d->signaled = true; +void Event::sendSignal() { + EventHandler *handler = this->handler(); + if (handler) { + handler->signal(this); + } } diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/service/Event_win.cpp index c575c92a..c40a37d5 100644 --- a/telldus-core/service/Event_win.cpp +++ b/telldus-core/service/Event_win.cpp @@ -1,59 +1,33 @@ #include "Event.h" -#include "EventHandler.h" #include "Thread.h" class Event::PrivateData { public: - bool signaled; - EventHandler *handler; EVENT_T event; - MUTEX_T mutex; }; -Event::Event(EventHandler *handler) { +Event::Event(EventHandler *handler) + :EventBase(handler) +{ d = new PrivateData; - d->signaled = false; - d->handler = handler; d->event = CreateEvent(NULL, true, false, NULL); - TelldusCore::Thread::initMutex(&d->mutex); } Event::~Event(void) { - if (d->handler) { - d->handler->removeEvent(this); - } - TelldusCore::Thread::destroyMutex(&d->mutex); CloseHandle(d->event); delete d; } -void Event::clearSignal() { - TelldusCore::MutexLocker locker(&d->mutex); - ResetEvent(d->event); - d->signaled = false; -} - -bool Event::isSignaled() { - TelldusCore::MutexLocker locker(&d->mutex); - return d->signaled; -} - EVENT_T Event::retrieveNative() { - TelldusCore::MutexLocker locker(&d->mutex); return d->event; } -void Event::signal() { +void Event::clearSignal() { + ResetEvent(d->event); +} + +void Event::sendSignal() { SetEvent(d->event); } -void Event::clearHandler() { - TelldusCore::MutexLocker locker(&d->mutex); - d->handler = 0; -} - -void Event::setSignaled() { - TelldusCore::MutexLocker locker(&d->mutex); - d->signaled = true; -} diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index a79a075f..25847642 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -37,7 +37,7 @@ void TelldusMain::start(void) { continue; } if (clientEvent->isSignaled()) { - clientEvent->clearSignal(); + EventData data = clientEvent->takeSignal(); //New client connection TelldusCore::Socket *s = clientListener.retrieveClientSocket(); From 5cb709e4e6319c704f7e56cc8c73c268fb7b7703 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 11 Oct 2010 13:41:22 +0000 Subject: [PATCH 0250/2215] More communication method-stubs --- telldus-core/client/telldus-core.cpp | 132 +++++++++++----- telldus-core/common/Message.cpp | 36 ++++- telldus-core/common/Message.h | 11 +- .../service/ClientCommunicationHandler.cpp | 147 +++++++++++++++--- 4 files changed, 261 insertions(+), 65 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index ab2b1df4..f65d4206 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -117,7 +117,9 @@ void WINAPI tdReleaseString(char *string) { * @param intDeviceId The device id to turn on. **/ int WINAPI tdTurnOn(int intDeviceId){ - return TELLSTICK_ERROR_UNKNOWN; + TelldusCore::Message msg(L"tdTurnOn"); + msg.addArgument(intDeviceId); + return msg.getClientIntegerFromSocket(); } /** @@ -127,7 +129,9 @@ int WINAPI tdTurnOn(int intDeviceId){ * @param intDeviceId The device id to turn off. */ int WINAPI tdTurnOff(int intDeviceId){ - return TELLSTICK_ERROR_UNKNOWN; + TelldusCore::Message msg(L"tdTurnOff"); + msg.addArgument(intDeviceId); + return msg.getClientIntegerFromSocket(); } /** @@ -137,7 +141,9 @@ int WINAPI tdTurnOff(int intDeviceId){ * @param intDeviceId The device id to send bell to */ int WINAPI tdBell(int intDeviceId){ - return TELLSTICK_ERROR_UNKNOWN; + TelldusCore::Message msg(L"tdBell"); + msg.addArgument(intDeviceId); + return msg.getClientIntegerFromSocket(); } /** @@ -148,7 +154,10 @@ int WINAPI tdBell(int intDeviceId){ * @param level The level the device should dim to. This value should be 0-255 */ int WINAPI tdDim(int intDeviceId, unsigned char level){ - return TELLSTICK_ERROR_UNKNOWN; + TelldusCore::Message msg(L"tdDim"); + msg.addArgument(intDeviceId); + msg.addArgument(level); + return msg.getClientIntegerFromSocket(); } /** @@ -159,7 +168,9 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ * @param intDeviceId The device id to learn. */ int WINAPI tdLearn(int intDeviceId) { - return TELLSTICK_ERROR_UNKNOWN; + TelldusCore::Message msg(L"tdLearn"); + msg.addArgument(intDeviceId); + return msg.getClientIntegerFromSocket(); } /** @@ -168,8 +179,11 @@ int WINAPI tdLearn(int intDeviceId) { * @param methodsSupported The methods supported by the client. See tdMethods() for more information. * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF */ -int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ) { - return TELLSTICK_TURNOFF; +int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { + TelldusCore::Message msg(L"tdLearn"); + msg.addArgument(intDeviceId); + msg.addArgument(methodsSupported); + return msg.getClientIntegerFromSocket(); } /** @@ -178,22 +192,20 @@ int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ) { * @returns the the value as a human readable string, example "128" for 50% */ char * WINAPI tdLastSentValue( int intDeviceId ) { - return wrapStdString("255"); + TelldusCore::Message msg(L"tdLastSentValue"); + msg.addArgument(intDeviceId); + std::wstring strReturn = msg.getClientWStringFromSocket(); + return wrapStdWstring(strReturn); } - /** * This function returns the number of devices configured * @returns an integer of the total number of devices configured */ int WINAPI tdGetNumberOfDevices(void){ - TelldusCore::Socket s; - s.connect(L"TelldusClient"); - std::wstring msg = L"20:tdGetNumberOfDevices"; - s.write(msg); - - std::wstring response = s.read(); - return TelldusCore::Message::takeInt(&response); + + TelldusCore::Message msg(L"tdGetNumberOfDevices"); + return msg.getClientIntegerFromSocket(); } /** @@ -210,7 +222,9 @@ int WINAPI tdGetNumberOfDevices(void){ * @returns the unique id for the device or -1 if the device is not found. */ int WINAPI tdGetDeviceId(int intDeviceIndex){ - return 1; + TelldusCore::Message msg(L"tdGetDeviceId"); + msg.addArgument(intDeviceIndex); + return msg.getClientIntegerFromSocket(); } /** @@ -218,7 +232,9 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP */ int WINAPI tdGetDeviceType(int intDeviceId) { - return TELLSTICK_TYPE_DEVICE; + TelldusCore::Message msg(L"tdGetDeviceType"); + msg.addArgument(intDeviceId); + return msg.getClientIntegerFromSocket(); } /** @@ -227,8 +243,10 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * @returns The name of the device or an empty string if the device is not found. */ char * WINAPI tdGetName(int intDeviceId){ - std::string strReturn = "Hardcoded device"; - return wrapStdString(strReturn); + TelldusCore::Message msg(L"tdGetName"); + msg.addArgument(intDeviceId); + std::wstring strReturn = msg.getClientWStringFromSocket(); + return wrapStdWstring(strReturn); } /** @@ -239,8 +257,10 @@ char * WINAPI tdGetName(int intDeviceId){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ - bool blnSuccess = false; - return blnSuccess; + TelldusCore::Message msg(L"tdSetName"); + msg.addArgument(intDeviceId); + msg.addArgument(strNewName); + return msg.getClientBoolFromSocket(); } /** @@ -248,8 +268,10 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ * @param intDeviceId The device id to query. */ char* WINAPI tdGetProtocol(int intDeviceId){ - std::string strReturn = ""; - return wrapStdString(strReturn); + TelldusCore::Message msg(L"tdGetProtocol"); + msg.addArgument(intDeviceId); + std::wstring strReturn = msg.getClientWStringFromSocket(); + return wrapStdWstring(strReturn); } /** @@ -262,8 +284,10 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * @sa tdSetDeviceParameter() */ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ - bool blnSuccess = false; - return blnSuccess; + TelldusCore::Message msg(L"tdSetProtocol"); + msg.addArgument(intDeviceId); + msg.addArgument(strProtocol); + return msg.getClientBoolFromSocket(); } /** @@ -271,8 +295,10 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ * @param intDeviceId The device to query. */ char* WINAPI tdGetModel(int intDeviceId){ - std::string strReturn = ""; - return wrapStdString(strReturn); + TelldusCore::Message msg(L"tdGetModel"); + msg.addArgument(intDeviceId); + std::wstring strReturn = msg.getClientWStringFromSocket(); + return wrapStdWstring(strReturn); } /** @@ -283,8 +309,10 @@ char* WINAPI tdGetModel(int intDeviceId){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ - bool blnSuccess = false; - return blnSuccess; + TelldusCore::Message msg(L"tdSetModel"); + msg.addArgument(intDeviceId); + msg.addArgument(strModel); + return msg.getClientBoolFromSocket(); } /** @@ -296,7 +324,11 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ - return false; + TelldusCore::Message msg(L"tdSetDeviceParameter"); + msg.addArgument(intDeviceId); + msg.addArgument(strName); + msg.addArgument(strValue); + return msg.getClientBoolFromSocket(); } /** @@ -306,8 +338,12 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. */ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ - std::string strReturn = ""; - return wrapStdString(strReturn); + TelldusCore::Message msg(L"tdGetDeviceParameter"); + msg.addArgument(intDeviceId); + msg.addArgument(strName); + msg.addArgument(defaultValue); + std::wstring strReturn = msg.getClientWStringFromSocket(); + return wrapStdWstring(strReturn); } /** @@ -317,8 +353,8 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c * negative value. */ int WINAPI tdAddDevice(){ - int intNewDeviceId = -1; - return intNewDeviceId; + TelldusCore::Message msg(L"tdAddDevice"); + return msg.getClientIntegerFromSocket(); } /** @@ -326,8 +362,9 @@ int WINAPI tdAddDevice(){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdRemoveDevice(int intDeviceId){ - bool blnSuccess = false; - return blnSuccess; + TelldusCore::Message msg(L"tdRemoveDevice"); + msg.addArgument(intDeviceId); + return msg.getClientBoolFromSocket(); } /** @@ -350,8 +387,10 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_DIM */ int WINAPI tdMethods(int id, int methodsSupported){ - - return TELLSTICK_TURNON; + TelldusCore::Message msg(L"tdMethods"); + msg.addArgument(id); + msg.addArgument(methodsSupported); + return msg.getClientIntegerFromSocket(); } /** @@ -396,14 +435,27 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure */ int WINAPI tdSendRawCommand(const char *command, int reserved) { - return TELLSTICK_ERROR_UNKNOWN; + TelldusCore::Message msg(L"tdSendRawCommand"); + msg.addArgument(command); + msg.addArgument(reserved); + return msg.getClientIntegerFromSocket(); } void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { + TelldusCore::Message msg(L"tdConnectTellStickController"); + msg.addArgument(vid); + msg.addArgument(pid); + msg.addArgument(serial); + msg.getClientWStringFromSocket(); } void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { + TelldusCore::Message msg(L"tdDisconnectTellStickController"); + msg.addArgument(vid); + msg.addArgument(pid); + msg.addArgument(serial); + msg.getClientWStringFromSocket(); } diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 4582a55e..a3dd0790 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -1,4 +1,5 @@ #include "Message.h" +#include "Socket.h" using namespace TelldusCore; #include #include @@ -34,13 +35,15 @@ void Message::addArgument(int value) { this->append(L"s"); } -/* void Message::addArgument(const char *value) { - this->addArgument(std::wstring(value)); + this->addArgument(charToWstring(value)); } -*/ - +std::wstring Message::charToWstring(const char *value) { + std::wstringstream st; + st << value; + return st.str(); +} bool Message::nextIsInt(const std::wstring &message) { if (message.length() == 0) { @@ -85,3 +88,28 @@ int Message::wideToInteger(const std::wstring &input){ inputstream >> retval; return retval; } + +bool Message::getClientBoolFromSocket(){ + //TODO: move + return getClientIntegerFromSocket() == 1; +} + +int Message::getClientIntegerFromSocket(){ + //TODO: move + Socket s; + s.connect(L"TelldusClient"); + s.write(this->data()); + + std::wstring response = s.read(); + return takeInt(&response); +} + +std::wstring Message::getClientWStringFromSocket(){ + //TODO: move + Socket s; + s.connect(L"TelldusClient"); + s.write(this->data()); + + std::wstring response = s.read(); + return takeString(&response); +} diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index c205f793..9b3cecba 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -12,9 +12,14 @@ namespace TelldusCore { void addArgument(const std::wstring &); void addArgument(int); - //void addArgument(const char *); - - static bool nextIsInt(const std::wstring &); + void addArgument(const char *); + + bool getClientBoolFromSocket(); + int getClientIntegerFromSocket(); + std::wstring getClientWStringFromSocket(); + + static std::wstring charToWstring(const char *value); + static bool nextIsInt(const std::wstring &); static bool nextIsString(const std::wstring &); static std::wstring takeString(std::wstring *); diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index cf0585a5..f8ca326f 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -32,27 +32,21 @@ ClientCommunicationHandler::~ClientCommunicationHandler(void) void ClientCommunicationHandler::run(){ //run thread - std::wstring clientMessage = d->clientSocket->read(); - int intTemp; + int intReturn; std::wstring strReturn; strReturn = L""; - parseMessage(clientMessage, intTemp, strReturn); + parseMessage(clientMessage, intReturn, strReturn); TelldusCore::Message msg; - /* TODO - if (response.type() == QVariant::Int) { - msg.addArgument(response.toInt()); - } else { - */ - //allt som wstring ? + if(strReturn == L""){ - msg.addArgument(intTemp); + msg.addArgument(intReturn); } else{ - msg.addArgument(strReturn); //temp.toString().toStdString()); + msg.addArgument(strReturn); } msg.append(L"\n"); d->clientSocket->write(msg); @@ -69,16 +63,133 @@ bool ClientCommunicationHandler::isDone(){ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int &intReturn, std::wstring &wstringReturn){ + intReturn = 0; + wstringReturn = L""; std::wstring msg(clientMessage); //Copy std::wstring function(TelldusCore::Message::takeString(&msg)); - if(function == L"tdGetNumberOfDevices"){ - - //return L"12"; - intReturn = 12; - } + if (function == L"tdTurnOn") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + intReturn = 0; //tdTurnOn(intDeviceId); + + } else if (function == L"tdTurnOff") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + intReturn = 0; //tdTurnOff(intDeviceId); + + } else if (function == L"tdBell") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + intReturn = 0; // tdBell(intDeviceId); + + } else if (function == L"tdDim") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + int level = TelldusCore::Message::takeInt(&msg); + intReturn = 0; // tdDim(intDeviceId, level); + + } else if (function == L"tdLearn") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + intReturn = 0; //tdLearn(intDeviceId); + + } else if (function == L"tdLastSentCommand") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + int methodsSupported = TelldusCore::Message::takeInt(&msg); + intReturn = 0; // tdLastSentCommand(intDeviceId, methodsSupported); + + } else if (function == L"tdLastSentValue") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + char *value = ""; //tdLastSentValue(intDeviceId); + wstringReturn = TelldusCore::Message::charToWstring(value); + + } else if(function == L"tdGetNumberOfDevices"){ + intReturn = 12; //tdGetNumberOfDevices(); + + } else if (function == L"tdGetDeviceId") { + int intDeviceIndex = TelldusCore::Message::takeInt(&msg); + intReturn = 1; //tdGetDeviceId(intDeviceIndex); + + } else if (function == L"tdGetDeviceType") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + intReturn = 11; // tdGetDeviceType(intDeviceId); + + } else if (function == L"tdGetName") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + char *name = "Default name"; //tdGetName(intDeviceId); + wstringReturn = TelldusCore::Message::charToWstring(name); + + } else if (function == L"tdSetName") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + intReturn = 0; //tdSetName(intDeviceId, name.c_str()); + + } else if (function == L"tdGetProtocol") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + char *protocol = "Default protocol"; //tdGetProtocol(intDeviceId); + + } else if (function == L"tdSetProtocol") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + std::wstring protocol = TelldusCore::Message::takeString(&msg); + intReturn = 0; // tdSetProtocol(intDeviceId, protocol.c_str()); + + } else if (function == L"tdGetModel") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + char *model = "Default model"; //tdGetModel(intDeviceId); + + } else if (function == L"tdSetModel") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + std::wstring model = TelldusCore::Message::takeString(&msg); + intReturn = 0; // tdSetModel(intDeviceId, model.c_str()); + + } else if (function == L"tdSetDeviceParameter") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring value = TelldusCore::Message::takeString(&msg); + intReturn = 0; //tdSetDeviceParameter(intDeviceId, name.c_str(), value.c_str()); + + } else if (function == L"tdGetDeviceParameter") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring defaultValue = TelldusCore::Message::takeString(&msg); + char *value = "Device parameter default"; //tdGetDeviceParameter(intDeviceId, name.c_str(), defaultValue.c_str()); + wstringReturn = TelldusCore::Message::charToWstring(value); + + } else if (function == L"tdAddDevice") { + intReturn = 0; // tdAddDevice(); + + } else if (function == L"tdRemoveDevice") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + intReturn = 0; // tdRemoveDevice(intDeviceId); + + } else if (function == L"tdMethods") { + int intDeviceId = TelldusCore::Message::takeInt(&msg); + int intMethodsSupported = TelldusCore::Message::takeInt(&msg); + intReturn = 0; // tdMethods(intDeviceId, intMethodsSupported); + + } else if (function == L"tdGetErrorString") { + int intErrorNo = TelldusCore::Message::takeInt(&msg); + char *response = "Default error string"; //tdGetErrorString(intErrorNo); + wstringReturn = TelldusCore::Message::charToWstring(response); + + } else if (function == L"tdSendRawCommand") { + std::wstring command = TelldusCore::Message::takeString(&msg); + int reserved = TelldusCore::Message::takeInt(&msg); + intReturn = 0; //tdSendRawCommand(command.c_str(), reserved); + + } else if (function == L"tdConnectTellStickController") { + int vid = TelldusCore::Message::takeInt(&msg); + int pid = TelldusCore::Message::takeInt(&msg); + std::wstring serial = TelldusCore::Message::takeString(&msg); + //tdConnectTellStickController(vid, pid, serial.c_str()); + wstringReturn = L""; + + } else if (function == L"tdDisconnectTellStickController") { + int vid = TelldusCore::Message::takeInt(&msg); + int pid = TelldusCore::Message::takeInt(&msg); + std::wstring serial = TelldusCore::Message::takeString(&msg); + //tdDisconnectTellStickController(vid, pid, serial.c_str()); + wstringReturn = L""; + + } else{ - intReturn = 5; + intReturn = 6; } - //return L"5"; } + From be68e2cec4a5836f2bf4d5ce2ac47a79d846ecd6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 11 Oct 2010 13:43:29 +0000 Subject: [PATCH 0251/2215] Wstring-wrapper added --- telldus-core/client/common.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/client/common.h b/telldus-core/client/common.h index 37cd9965..dd997835 100644 --- a/telldus-core/client/common.h +++ b/telldus-core/client/common.h @@ -34,3 +34,7 @@ inline char *wrapStdString( const std::string &string) { return returnVal; #endif } + +inline char *wrapStdWstring( const std::wstring &wstring) { + return wrapStdString(std::string(wstring.begin(), wstring.end())); +} \ No newline at end of file From bb9dc7cddc9e4962cbeb3d91e1e10dec12f978f1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 14:11:03 +0000 Subject: [PATCH 0252/2215] Send the event data as pointers instead. --- telldus-core/service/Event.cpp | 12 ++++++------ telldus-core/service/Event.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index f82e06d5..50e97183 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -15,7 +15,7 @@ class EventBase::PrivateData { public: MUTEX_T mutex; EventHandler *handler; - std::list eventDataList; + std::list eventDataList; }; EventBase::EventBase(EventHandler *handler) { @@ -43,10 +43,10 @@ bool EventBase::isSignaled() { } void EventBase::signal() { - signal(EventData()); + signal(new EventData()); } -void EventBase::signal(const EventData &eventData) { +void EventBase::signal(EventData *eventData) { { TelldusCore::MutexLocker locker(&d->mutex); d->eventDataList.push_back(eventData); @@ -54,12 +54,12 @@ void EventBase::signal(const EventData &eventData) { sendSignal(); } -EventData EventBase::takeSignal() { +EventData *EventBase::takeSignal() { TelldusCore::MutexLocker locker(&d->mutex); if (d->eventDataList.size() == 0) { - return EventData(); + return new EventData(); } - EventData data = d->eventDataList.front(); + EventData *data = d->eventDataList.front(); d->eventDataList.pop_front(); if (d->eventDataList.size() == 0) { this->clearSignal(); diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index cbd5ba94..ed7b74b0 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -27,8 +27,8 @@ public: bool isSignaled(); void signal(); - virtual void signal(const EventData &); - EventData takeSignal(); + virtual void signal(EventData *); + EventData *takeSignal(); protected: EventBase(EventHandler *handler); From 22dae8e3d6520e95455e25fb4004800a1dfc6ed0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 14:11:43 +0000 Subject: [PATCH 0253/2215] Use the new event data system to send the new socket. --- telldus-core/service/ConnectionListener.h | 7 ++++++- telldus-core/service/ConnectionListener_win.cpp | 11 +++-------- telldus-core/service/TelldusMain.cpp | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index 18db5f0a..410ef36c 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -3,17 +3,22 @@ #include #include "Thread.h" +#include "Event.h" class Event; namespace TelldusCore { class Socket; }; +class ConnectionListenerEventData : public EventDataBase { +public: + TelldusCore::Socket *socket; +}; + class ConnectionListener : public TelldusCore::Thread { public: ConnectionListener(const std::wstring &name, Event *waitEvent); virtual ~ConnectionListener(void); - TelldusCore::Socket *retrieveClientSocket(); protected: void run(); diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 8f3e0ac9..6889ab3a 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -12,7 +12,6 @@ class ConnectionListener::PrivateData { public: std::wstring pipename; SECURITY_ATTRIBUTES sa; - TelldusCore::Socket *socket; HANDLE hEvent; bool running; Event *waitEvent; @@ -124,15 +123,11 @@ void ConnectionListener::run() { CloseHandle(hPipe); return; } - d->socket = new TelldusCore::Socket(hPipe); - d->waitEvent->signal(); + ConnectionListenerEventData *data = new ConnectionListenerEventData(); + data->socket = new TelldusCore::Socket(hPipe); + d->waitEvent->signal(data); } CloseHandle(d->hEvent); CloseHandle(hPipe); } - -TelldusCore::Socket *ConnectionListener::retrieveClientSocket(){ - return d->socket; - -} diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 25847642..132ca77f 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -37,16 +37,16 @@ void TelldusMain::start(void) { continue; } if (clientEvent->isSignaled()) { - EventData data = clientEvent->takeSignal(); //New client connection - - TelldusCore::Socket *s = clientListener.retrieveClientSocket(); - if (s){ + EventData *eventData = clientEvent->takeSignal(); + ConnectionListenerEventData *data = reinterpret_cast(eventData); + if (data) { Event *handlerEvent = d->eventHandler.addEvent(); - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(s, handlerEvent); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } + delete eventData; } From acb02a6c8b26e37f3fc5d8ee70bbd9629cfb30ce Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 14:25:10 +0000 Subject: [PATCH 0254/2215] EventData::isValid() must of course be virtual. --- telldus-core/service/Event.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index ed7b74b0..8e246574 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -13,12 +13,12 @@ class EventHandler; class EventData { public: - bool isValid() const; + virtual bool isValid() const; }; class EventDataBase : public EventData { public: - bool isValid() const; + virtual bool isValid() const; }; class EventBase { From e01edf90fea0b94559b96d0da49078a51a88975f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 14:40:08 +0000 Subject: [PATCH 0255/2215] Delete the object ourself if we don't return it. --- telldus-core/service/Event.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index 50e97183..b6218887 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -57,12 +57,16 @@ void EventBase::signal(EventData *eventData) { EventData *EventBase::takeSignal() { TelldusCore::MutexLocker locker(&d->mutex); if (d->eventDataList.size() == 0) { - return new EventData(); + return 0; } EventData *data = d->eventDataList.front(); d->eventDataList.pop_front(); if (d->eventDataList.size() == 0) { this->clearSignal(); } + if (!data->isValid()) { + delete data; + return 0; + } return data; } \ No newline at end of file From 29a7ad15bfcf44d01357946f7d6e68577e230e1d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 15:04:08 +0000 Subject: [PATCH 0256/2215] Fix performance warning --- telldus-core/common/Socket_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index b4051cb2..5e146e42 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -35,7 +35,7 @@ Socket::~Socket(void){ } void Socket::connect(const std::wstring &server){ - bool fSuccess = false; + BOOL fSuccess = false; std::wstring name(L"\\\\.\\pipe\\" + server); d->hPipe = CreateFile( From 00112755ffef256e6ba02cad1a48692d5e39573a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 15:06:14 +0000 Subject: [PATCH 0257/2215] Initialize the variable --- telldus-core/common/Socket_win.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 5e146e42..784c7b48 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -16,6 +16,7 @@ public: Socket::Socket() { d = new PrivateData; + d->hPipe = INVALID_HANDLE_VALUE; d->connected = false; } From 45eadc068b40bbaf5c5589aea589906a899f2e45 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 15:07:39 +0000 Subject: [PATCH 0258/2215] Fix performance warning --- telldus-core/common/Socket_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 784c7b48..2c342468 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -73,7 +73,7 @@ std::wstring Socket::read() { OVERLAPPED oOverlap; HANDLE readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); oOverlap.hEvent = readEvent; - bool fSuccess = false; + BOOL fSuccess = false; memset(&buf, 0, BUFSIZE); @@ -101,7 +101,7 @@ void Socket::write(const std::wstring &msg){ OVERLAPPED oOverlap; DWORD bytesWritten = 0; int result; - bool fSuccess; + BOOL fSuccess; HANDLE writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); oOverlap.hEvent = writeEvent; From 57a4eedcacb54b898e022639bc20e95589349280 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 16:01:03 +0000 Subject: [PATCH 0259/2215] Make sure all the messages is cleared in the end. --- telldus-core/service/Event.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index b6218887..15c865db 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -28,6 +28,11 @@ EventBase::~EventBase(void) { if (d->handler) { d->handler->removeEvent(this); } + //If we have signals left, make sure we delete the data + std::list::const_iterator it = d->eventDataList.begin(); + for(; it != d->eventDataList.end(); ++it) { + delete(*it); + } TelldusCore::Thread::destroyMutex(&d->mutex); delete d; } From 10e8d34e41c10dd2b43466520dead172cab5cdca Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 11 Oct 2010 16:01:44 +0000 Subject: [PATCH 0260/2215] Made Settings::~Settings() virtual --- telldus-core/service/Settings.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 837aaa8b..7858fb1a 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -6,6 +6,8 @@ class Settings { public: Settings(void); + virtual ~Settings(void); + std::wstring getSetting(const std::wstring &strName) const; int getNumberOfDevices(void) const; std::wstring getName(int intDeviceId) const; @@ -23,8 +25,6 @@ public: int addDevice(); int getDeviceId(int intDeviceIndex) const; bool removeDevice(int intDeviceId); - - ~Settings(void); protected: std::wstring getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const; From 44beddc80f24d781a1087750d5864df93cd859b1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 07:19:14 +0000 Subject: [PATCH 0261/2215] Added stub Socket::connect() --- telldus-core/common/Socket_unix.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 83c45d2e..12cc8f85 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -6,8 +6,8 @@ class Socket::PrivateData { public: }; -Socket::Socket(const std::wstring &server) { - +Socket::Socket() { + d = new PrivateData; } Socket::Socket(SOCKET_T hPipe) @@ -15,10 +15,13 @@ Socket::Socket(SOCKET_T hPipe) d = new PrivateData; } -Socket::~Socket(void){ +Socket::~Socket(void) { delete d; } +void Socket::connect(const std::wstring &server) { +} + std::wstring Socket::read() { return L""; } From cf72154123868c79900dff3c78dc83f6c41fa12f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 07:20:17 +0000 Subject: [PATCH 0262/2215] Added SettingsConfuse, untested --- telldus-core/service/CMakeLists.txt | 8 +- telldus-core/service/SettingsConfuse.cpp | 373 +++++++++++++++++++++++ 2 files changed, 379 insertions(+), 2 deletions(-) create mode 100644 telldus-core/service/SettingsConfuse.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 585e895b..d496f7a3 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -70,16 +70,20 @@ ELSEIF (WIN32) #### Windows #### ) ELSE (APPLE) #### Linux #### + FIND_LIBRARY(CONFUSE_LIBRARY confuse) + ADD_DEFINITIONS( -D_CONFUSE ) SET( telldus-service_TARGET telldusd ) LIST(APPEND telldus-service_SRCS - main_unix.cpp + ConnectionListener_unix.cpp Event_unix.cpp EventHandler_unix.cpp - ConnectionListener_unix.cpp + main_unix.cpp + SettingsConfuse.cpp ) LIST(APPEND telldus-service_LIBRARIES ${telldus-service_LIBRARIES} + ${CONFUSE_LIBRARY} telldus-common ) ENDIF (APPLE) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp new file mode 100644 index 00000000..7899f666 --- /dev/null +++ b/telldus-core/service/SettingsConfuse.cpp @@ -0,0 +1,373 @@ +// +// C++ Implementation: telldussettingsconfuse +// +// Description: +// +// +// Author: Micke Prag , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "Settings.h" +#include "../client/telldus-core.h" +#include +#include +#include +#include + +using namespace std; + +class Settings::PrivateData { +public: + cfg_t *cfg; + cfg_t *var_cfg; +}; + +bool readConfig(cfg_t **cfg); +bool readVarConfig(cfg_t **cfg); + +const char* CONFIG_FILE = "/etc/tellstick.conf"; +#ifdef __FreeBSD__ +const char* VAR_CONFIG_FILE = "/var/spool/telldus-core.conf"; +#else +const char* VAR_CONFIG_FILE = "/var/state/telldus-core.conf"; +#endif + +/* +* Constructor +*/ +Settings::Settings(void) +{ + d = new PrivateData; + readConfig(&d->cfg); + readVarConfig(&d->var_cfg); +} + +/* +* Destructor +*/ +Settings::~Settings(void) +{ + if (d->cfg > 0) { + cfg_free(d->cfg); + } + if (d->var_cfg > 0) { + cfg_free(d->var_cfg); + } + delete d; +} + +/* +* Return a setting +*/ +std::wstring Settings::getSetting(const std::wstring &strName) const { + if (d->cfg > 0) { + std::string setting(cfg_getstr(d->cfg, std::string(strName.begin(), strName.end()).c_str())); + return std::wstring(setting.begin(), setting.end()); + } + return L""; +} + +/* +* Return the number of stored devices +*/ +int Settings::getNumberOfDevices(void) const { + if (d->cfg > 0) { + return cfg_size(d->cfg, "device"); + } + return 0; +} + +int Settings::getDeviceId(int intDeviceIndex) const { + if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds + return -1; + } + cfg_t *cfg_device = cfg_getnsec(d->cfg, "device", intDeviceIndex); + int id = cfg_getint(cfg_device, "id"); + return id; +} + +/* +* Add a new device +*/ +int Settings::addDevice(){ + int intDeviceId = getNextDeviceId(); + + FILE *fp = fopen(CONFIG_FILE, "w"); + cfg_print(d->cfg, fp); //Print the config-file + fprintf(fp, "device {\n id=%d\n}\n", intDeviceId); //Print the new device + fclose(fp); + + //Re-read config-file + cfg_free(d->cfg); + readConfig(&d->cfg); + return intDeviceId; +} + +/* +* Get next available device id +*/ +int Settings::getNextDeviceId() const { + int intDeviceId = 0; + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") >= intDeviceId) { + intDeviceId = cfg_getint(cfg_device, "id"); + } + } + intDeviceId++; + return intDeviceId; +} + +/* +* Remove a device +*/ +bool Settings::removeDevice(int intDeviceId){ + bool blnSuccess = true; + FILE *fp = fopen(CONFIG_FILE, "w"); + + // Print all opts + for(int i = 0; d->cfg->opts[i].name; i++) { + + // Check if it isn't a device section + if (strcmp(d->cfg->opts[i].name, "device") != 0) { + cfg_opt_print(&d->cfg->opts[i], fp); + } else { + // Print all sections except the one to remove + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") != intDeviceId) { //This isn't the one to skip + fprintf(fp, "device {\n"); + cfg_print_indent(cfg_device, fp, 1); + fprintf(fp, "}\n"); + } + } + } + } + fclose(fp); + + //Re-read config-file + cfg_free(d->cfg); + readConfig(&d->cfg); + + return blnSuccess; +} + +bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { + if (d->var_cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->var_cfg, "device", i); + int deviceId = atoi(cfg_title(cfg_device)); + if (deviceId == intDeviceId) { + cfg_setint(cfg_device, "state", intDeviceState); + cfg_setstr(cfg_device, "stateValue", std::string(strDeviceStateValue.begin(), strDeviceStateValue.end()).c_str()); + + FILE *fp = fopen(VAR_CONFIG_FILE, "w"); + cfg_print(d->var_cfg, fp); + fclose(fp); + return true; + } + } + // The device is not found in the file, we must create it manualy... + FILE *fp = fopen(VAR_CONFIG_FILE, "w"); + if(!fp) { + fprintf(stderr, "Failed to write state to %s: %s\n", + VAR_CONFIG_FILE, strerror(errno)); + return false; + } + + cfg_print(d->var_cfg, fp); //Print the config-file + fprintf(fp, "device %d {\n}\n", intDeviceId); //Print the new device + fclose(fp); + + //Re-read config-file + cfg_free(d->var_cfg); + readVarConfig(&d->var_cfg); + + return false; +} + +int Settings::getDeviceState( int intDeviceId ) const { + if (d->var_cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->var_cfg, "device", i); + int deviceId = atoi(cfg_title(cfg_device)); + if (deviceId == intDeviceId) { + return cfg_getint(cfg_device, "state"); + } + } + return TELLSTICK_TURNOFF; +} + +std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { + if (d->var_cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->var_cfg, "device", i); + int deviceId = atoi(cfg_title(cfg_device)); + if (deviceId == intDeviceId) { + std::string value(cfg_getstr(cfg_device, "stateValue")); + return std::wstring(value.begin(), value.end()); + } + } + return L""; +} + +std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const { + if (d->cfg == 0) { + return L""; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + if (parameter) { + cfg_device = cfg_getsec(cfg_device, "parameters"); + } + std::string setting(cfg_getstr(cfg_device, std::string(name.begin(), name.end()).c_str())); + return std::wstring(setting.begin(), setting.end()); + } + } + return L""; +} + +bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { + if (d->cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + if (parameter) { + cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); + cfg_setstr(cfg_parameters, std::string(name.begin(), name.end()).c_str(), std::string(value.begin(), value.end()).c_str()); + } else { + cfg_setstr(cfg_device, std::string(name.begin(), name.end()).c_str(), std::string(value.begin(), value.end()).c_str()); + } + FILE *fp = fopen(CONFIG_FILE, "w"); + cfg_print(d->cfg, fp); + fclose(fp); + return true; + } + } + return false; +} + +int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const { + if (d->cfg == 0) { + return 0; + } + cfg_t *cfg_device; + for(int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + if (parameter) { + cfg_device = cfg_getsec(cfg_device, "parameters"); + } + return cfg_getint(cfg_device, std::string(name.begin(), name.end()).c_str()); + } + } + return 0; +} + +bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { + if (d->cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->cfg, "device", i); + if (cfg_getint(cfg_device, "id") == intDeviceId) { + if (parameter) { + cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); + cfg_setint(cfg_parameters, std::string(name.begin(), name.end()).c_str(), value); + } else { + cfg_setint(cfg_device, std::string(name.begin(), name.end()).c_str(), value); + } + FILE *fp = fopen(CONFIG_FILE, "w"); + cfg_print(d->cfg, fp); + fclose(fp); + return true; + } + } + return false; +} + + +bool readConfig(cfg_t **cfg) { + cfg_opt_t controller_opts[] = { + CFG_INT("id", -1, CFGF_NONE), + }; + + cfg_opt_t device_parameter_opts[] = { + //Groups + CFG_STR("devices", 0, CFGF_NONE), + + CFG_STR("house", 0, CFGF_NONE), + CFG_STR("unit", 0, CFGF_NONE), + CFG_STR("code", 0, CFGF_NONE), + CFG_STR("system", 0, CFGF_NONE), + CFG_STR("units", 0, CFGF_NONE), + CFG_STR("fade", 0, CFGF_NONE), + + CFG_END() + }; + + cfg_opt_t device_opts[] = { + CFG_INT("id", -1, CFGF_NONE), + CFG_STR("name", "Unnamed", CFGF_NONE), + CFG_INT("controller", 0, CFGF_NONE), + CFG_STR("protocol", "arctech", CFGF_NONE), + CFG_STR("model", "", CFGF_NONE), + CFG_SEC("parameters", device_parameter_opts, CFGF_NONE), + CFG_END() + }; + + cfg_opt_t opts[] = { + CFG_STR("deviceNode", "/dev/tellstick", CFGF_NONE), + CFG_SEC("device", device_opts, CFGF_MULTI), + CFG_END() + }; + + (*cfg) = cfg_init(opts, CFGF_NOCASE); + if (cfg_parse((*cfg), CONFIG_FILE) == CFG_PARSE_ERROR) { + (*cfg) = 0; + return false; + } + + return true; +} + +bool readVarConfig(cfg_t **cfg) { + + cfg_opt_t device_opts[] = { + CFG_INT("state", 0, CFGF_NONE), + CFG_STR("stateValue", "", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t opts[] = { + CFG_SEC("device", device_opts, CFGF_MULTI | CFGF_TITLE), + CFG_END() + }; + + (*cfg) = cfg_init(opts, CFGF_NOCASE); + if (cfg_parse((*cfg), VAR_CONFIG_FILE) == CFG_PARSE_ERROR) { + (*cfg) = 0; + return false; + } + + return true; +} From 09c6932c1f7ca088fd280cb0d22e9588d3845480 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 07:21:40 +0000 Subject: [PATCH 0263/2215] Fixed building of ConnectionListener on Unix --- telldus-core/service/ConnectionListener_unix.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 08d9e9c5..41c90e57 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -5,7 +5,7 @@ class ConnectionListener::PrivateData { public: }; -ConnectionListener::ConnectionListener(const std::wstring &name) +ConnectionListener::ConnectionListener(const std::wstring &name, Event *waitEvent) { d = new PrivateData; } @@ -14,10 +14,7 @@ ConnectionListener::~ConnectionListener(void) { delete d; } -void ConnectionListener::listen(Event *waitEvent){ +void ConnectionListener::run(){ } -TelldusCore::Socket *ConnectionListener::retrieveClientSocket(){ - -} From 6c0e6c23c66ab60a2852e8da21b3645b73d8f2ca Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 07:23:24 +0000 Subject: [PATCH 0264/2215] Added function EventBase::handler() --- telldus-core/service/Event.cpp | 22 +++++++++++++--------- telldus-core/service/Event.h | 11 ++++++----- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index 15c865db..18178c37 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -3,17 +3,17 @@ #include -bool EventData::isValid() const { - return false; -}; - -bool EventDataBase::isValid() const { - return true; -}; - +bool EventData::isValid() const { + return false; +}; + +bool EventDataBase::isValid() const { + return true; +}; + class EventBase::PrivateData { public: - MUTEX_T mutex; + MUTEX_T mutex; EventHandler *handler; std::list eventDataList; }; @@ -42,6 +42,10 @@ void EventBase::clearHandler() { d->handler = 0; } +EventHandler *EventBase::handler() const { + return d->handler; +} + bool EventBase::isSignaled() { TelldusCore::MutexLocker locker(&d->mutex); return (d->eventDataList.size() > 0); diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 8e246574..8a28029c 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -4,11 +4,11 @@ class EventHandler; #include "Thread.h" -#ifdef _WINDOWS - #include - typedef HANDLE EVENT_T; -#else - typedef void* EVENT_T; +#ifdef _WINDOWS + #include + typedef HANDLE EVENT_T; +#else + typedef void* EVENT_T; #endif class EventData { @@ -34,6 +34,7 @@ protected: EventBase(EventHandler *handler); void clearHandler(); virtual void clearSignal() = 0; + EventHandler *handler() const; virtual void sendSignal() = 0; private: From 05c26314bee6ab35537e21104ae58564d1295f60 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 07:23:55 +0000 Subject: [PATCH 0265/2215] Made class Event a frient to EventHandler --- telldus-core/service/EventHandler.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index 5a396b40..aa53e44d 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -20,6 +20,8 @@ protected: private: class PrivateData; PrivateData *d; + + friend class Event; }; #endif //EVENTHANDLER_H From 1a1eb084440fa90da7e78734231e71a8b22dfb01 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 07:24:32 +0000 Subject: [PATCH 0266/2215] Implemented function EventHandler::removeEvent() on Unix --- telldus-core/service/EventHandler_unix.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index fbf577f3..a4dcfb7b 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -28,6 +28,9 @@ Event *EventHandler::addEvent() { return event; } +bool EventHandler::removeEvent(EventBase *event) { +} + void EventHandler::signal(Event *event) { pthread_mutex_lock(&d->mutex); //event->setSignaled(); From 74c26d747ee246f63c89c95b40c8bceef04f96d5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 07:24:58 +0000 Subject: [PATCH 0267/2215] Implemented function Event::clearEvent() on Unix --- telldus-core/service/Event_unix.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Event_unix.cpp b/telldus-core/service/Event_unix.cpp index a5f4c074..4ade1e2f 100644 --- a/telldus-core/service/Event_unix.cpp +++ b/telldus-core/service/Event_unix.cpp @@ -6,7 +6,8 @@ class Event::PrivateData { public: }; -Event::Event(EventHandler *handler) { +Event::Event(EventHandler *handler) + :EventBase(handler){ d = new PrivateData; } @@ -14,6 +15,9 @@ Event::~Event(void) { delete d; } +void Event::clearSignal() { +} + void Event::sendSignal() { EventHandler *handler = this->handler(); if (handler) { From e56997da55179cb553888853df3e414311971615 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 12 Oct 2010 08:45:25 +0000 Subject: [PATCH 0268/2215] DeviceManager added --- .../service/ClientCommunicationHandler.cpp | 81 +++++++++++-------- .../service/ClientCommunicationHandler.h | 5 +- telldus-core/service/DeviceManager.cpp | 13 +++ telldus-core/service/TelldusMain.cpp | 4 +- 4 files changed, 65 insertions(+), 38 deletions(-) create mode 100644 telldus-core/service/DeviceManager.cpp diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index f8ca326f..fc2d9fc1 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -6,19 +6,21 @@ public: TelldusCore::Socket *clientSocket; Event *event; bool done; + DeviceManager *deviceManager; }; ClientCommunicationHandler::ClientCommunicationHandler(){ } -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager) :Thread() { d = new PrivateData; d->clientSocket = clientSocket; d->event = event; d->done = false; + d->deviceManager = deviceManager; } @@ -38,7 +40,7 @@ void ClientCommunicationHandler::run(){ int intReturn; std::wstring strReturn; strReturn = L""; - parseMessage(clientMessage, intReturn, strReturn); + parseMessage(clientMessage, &intReturn, &strReturn); TelldusCore::Message msg; @@ -61,135 +63,144 @@ bool ClientCommunicationHandler::isDone(){ } -void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int &intReturn, std::wstring &wstringReturn){ +void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn){ - intReturn = 0; - wstringReturn = L""; + (*intReturn) = 0; + (*wstringReturn) = L""; std::wstring msg(clientMessage); //Copy std::wstring function(TelldusCore::Message::takeString(&msg)); if (function == L"tdTurnOn") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - intReturn = 0; //tdTurnOn(intDeviceId); + (*intReturn) = 0; //tdTurnOn(intDeviceId); } else if (function == L"tdTurnOff") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - intReturn = 0; //tdTurnOff(intDeviceId); + (*intReturn) = 0; //tdTurnOff(intDeviceId); } else if (function == L"tdBell") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - intReturn = 0; // tdBell(intDeviceId); + (*intReturn) = 0; // tdBell(intDeviceId); } else if (function == L"tdDim") { int intDeviceId = TelldusCore::Message::takeInt(&msg); int level = TelldusCore::Message::takeInt(&msg); - intReturn = 0; // tdDim(intDeviceId, level); + (*intReturn) = 0; // tdDim(intDeviceId, level); } else if (function == L"tdLearn") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - intReturn = 0; //tdLearn(intDeviceId); + (*intReturn) = 0; //tdLearn(intDeviceId); } else if (function == L"tdLastSentCommand") { int intDeviceId = TelldusCore::Message::takeInt(&msg); int methodsSupported = TelldusCore::Message::takeInt(&msg); - intReturn = 0; // tdLastSentCommand(intDeviceId, methodsSupported); + (*intReturn) = 0; // tdLastSentCommand(intDeviceId, methodsSupported); } else if (function == L"tdLastSentValue") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - char *value = ""; //tdLastSentValue(intDeviceId); - wstringReturn = TelldusCore::Message::charToWstring(value); + const char *value = ""; //tdLastSentValue(intDeviceId); + (*wstringReturn) = TelldusCore::Message::charToWstring(value); } else if(function == L"tdGetNumberOfDevices"){ - intReturn = 12; //tdGetNumberOfDevices(); + + (*intReturn) = 12; //d->settings.getNumberOfDevices(); } else if (function == L"tdGetDeviceId") { int intDeviceIndex = TelldusCore::Message::takeInt(&msg); - intReturn = 1; //tdGetDeviceId(intDeviceIndex); + (*intReturn) = 1; //tdGetDeviceId(intDeviceIndex); } else if (function == L"tdGetDeviceType") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - intReturn = 11; // tdGetDeviceType(intDeviceId); + (*intReturn) = 11; // tdGetDeviceType(intDeviceId); } else if (function == L"tdGetName") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - char *name = "Default name"; //tdGetName(intDeviceId); - wstringReturn = TelldusCore::Message::charToWstring(name); + const char *name = "Default name"; //tdGetName(intDeviceId); + (*wstringReturn) = TelldusCore::Message::charToWstring(name); } else if (function == L"tdSetName") { int intDeviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); - intReturn = 0; //tdSetName(intDeviceId, name.c_str()); + (*intReturn) = 0; //tdSetName(intDeviceId, name.c_str()); } else if (function == L"tdGetProtocol") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - char *protocol = "Default protocol"; //tdGetProtocol(intDeviceId); + const char *protocol = "Default protocol"; //tdGetProtocol(intDeviceId); + (*wstringReturn) = TelldusCore::Message::charToWstring(protocol); } else if (function == L"tdSetProtocol") { int intDeviceId = TelldusCore::Message::takeInt(&msg); std::wstring protocol = TelldusCore::Message::takeString(&msg); - intReturn = 0; // tdSetProtocol(intDeviceId, protocol.c_str()); + (*intReturn) = 0; // tdSetProtocol(intDeviceId, protocol.c_str()); } else if (function == L"tdGetModel") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - char *model = "Default model"; //tdGetModel(intDeviceId); + const char *model = "Default model"; //tdGetModel(intDeviceId); + (*wstringReturn) = TelldusCore::Message::charToWstring(model); } else if (function == L"tdSetModel") { int intDeviceId = TelldusCore::Message::takeInt(&msg); std::wstring model = TelldusCore::Message::takeString(&msg); - intReturn = 0; // tdSetModel(intDeviceId, model.c_str()); + (*intReturn) = 0; // tdSetModel(intDeviceId, model.c_str()); } else if (function == L"tdSetDeviceParameter") { int intDeviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring value = TelldusCore::Message::takeString(&msg); - intReturn = 0; //tdSetDeviceParameter(intDeviceId, name.c_str(), value.c_str()); + (*intReturn) = 0; //tdSetDeviceParameter(intDeviceId, name.c_str(), value.c_str()); } else if (function == L"tdGetDeviceParameter") { int intDeviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring defaultValue = TelldusCore::Message::takeString(&msg); - char *value = "Device parameter default"; //tdGetDeviceParameter(intDeviceId, name.c_str(), defaultValue.c_str()); - wstringReturn = TelldusCore::Message::charToWstring(value); + const char *value = "Device parameter default"; //tdGetDeviceParameter(intDeviceId, name.c_str(), defaultValue.c_str()); + (*wstringReturn) = TelldusCore::Message::charToWstring(value); } else if (function == L"tdAddDevice") { - intReturn = 0; // tdAddDevice(); + //TODO + //int deviceId = d->settings.addDevice(); + int deviceId = 0; + if(deviceId > 0){ + //success + //TODO signal event... + } } else if (function == L"tdRemoveDevice") { int intDeviceId = TelldusCore::Message::takeInt(&msg); - intReturn = 0; // tdRemoveDevice(intDeviceId); + (*intReturn) = 0; // tdRemoveDevice(intDeviceId); } else if (function == L"tdMethods") { int intDeviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - intReturn = 0; // tdMethods(intDeviceId, intMethodsSupported); + (*intReturn) = 0; // tdMethods(intDeviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { int intErrorNo = TelldusCore::Message::takeInt(&msg); - char *response = "Default error string"; //tdGetErrorString(intErrorNo); - wstringReturn = TelldusCore::Message::charToWstring(response); + const char *response = "Default error string"; //tdGetErrorString(intErrorNo); + (*wstringReturn) = TelldusCore::Message::charToWstring(response); } else if (function == L"tdSendRawCommand") { std::wstring command = TelldusCore::Message::takeString(&msg); int reserved = TelldusCore::Message::takeInt(&msg); - intReturn = 0; //tdSendRawCommand(command.c_str(), reserved); + (*intReturn) = 0; //tdSendRawCommand(command.c_str(), reserved); } else if (function == L"tdConnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); std::wstring serial = TelldusCore::Message::takeString(&msg); //tdConnectTellStickController(vid, pid, serial.c_str()); - wstringReturn = L""; + (*wstringReturn) = L""; } else if (function == L"tdDisconnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); std::wstring serial = TelldusCore::Message::takeString(&msg); //tdDisconnectTellStickController(vid, pid, serial.c_str()); - wstringReturn = L""; + (*wstringReturn) = L""; } else{ - intReturn = 6; + (*intReturn) = 6; } } diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 31f92858..fbb0e1b2 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -5,12 +5,13 @@ #include "Thread.h" #include "Socket.h" #include "Event.h" +#include "DeviceManager.h" class ClientCommunicationHandler : public TelldusCore::Thread { public: ClientCommunicationHandler(); - ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event); + ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager); ~ClientCommunicationHandler(void); bool isDone(); @@ -22,7 +23,7 @@ private: class PrivateData; PrivateData *d; //std::wstring parseMessage(const std::wstring &clientMessage); - void parseMessage(const std::wstring &clientMessage, int &intReturn, std::wstring &wstringReturn); + void parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn); }; #endif //CLIENTCOMMUNICATIONHANDLER_H \ No newline at end of file diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp new file mode 100644 index 00000000..15f501f0 --- /dev/null +++ b/telldus-core/service/DeviceManager.cpp @@ -0,0 +1,13 @@ +#include "DeviceManager.h" + +class DeviceManager::PrivateData { +public: + //Lista med devices +}; + +DeviceManager::DeviceManager() +{ +} + +DeviceManager::~DeviceManager(void) { +} diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 132ca77f..2afe9588 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -2,6 +2,7 @@ #include "ConnectionListener.h" #include "EventHandler.h" #include "ClientCommunicationHandler.h" +#include "DeviceManager.h" #include #include @@ -27,6 +28,7 @@ TelldusMain::~TelldusMain(void) void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); + DeviceManager *deviceManager; ConnectionListener clientListener(L"TelldusClient", clientEvent); //TODO: eventlistener @@ -42,7 +44,7 @@ void TelldusMain::start(void) { ConnectionListenerEventData *data = reinterpret_cast(eventData); if (data) { Event *handlerEvent = d->eventHandler.addEvent(); - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, deviceManager); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } From 3496a7eaa58fb9d8dc5cd9ddbc0727611eed5ba0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 12 Oct 2010 09:01:21 +0000 Subject: [PATCH 0269/2215] Class added --- telldus-core/service/DeviceManager.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 telldus-core/service/DeviceManager.h diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h new file mode 100644 index 00000000..ff0e3c4a --- /dev/null +++ b/telldus-core/service/DeviceManager.h @@ -0,0 +1,15 @@ +#ifndef DEVICEMANAGER_H +#define DEVICEMANAGER_H + +class DeviceManager +{ +public: + DeviceManager(); + ~DeviceManager(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //DEVICEMANAGER_H \ No newline at end of file From d570119c4c40134069bf30728d0c1acd7dbbccd2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 12 Oct 2010 09:05:47 +0000 Subject: [PATCH 0270/2215] Class "Device" added --- telldus-core/service/CMakeLists.txt | 4 ++++ telldus-core/service/Device.cpp | 15 +++++++++++++++ telldus-core/service/Device.h | 15 +++++++++++++++ telldus-core/service/DeviceManager.cpp | 11 ++++++++--- 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 telldus-core/service/Device.cpp create mode 100644 telldus-core/service/Device.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index d496f7a3..63ecac8c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -8,6 +8,8 @@ SET( telldus-service_SRCS Event.cpp Settings.cpp TelldusMain.cpp + DeviceManager.cpp + Device.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h @@ -16,6 +18,8 @@ SET( telldus-service_HDRS EventHandler.h Settings.h TelldusMain.h + DeviceManager.h + Device.h ) FIND_PACKAGE(Threads) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp new file mode 100644 index 00000000..0f6e12e6 --- /dev/null +++ b/telldus-core/service/Device.cpp @@ -0,0 +1,15 @@ +#include "Device.h" + +class Device::PrivateData { +public: + +}; + +Device::Device(){ + +} + +Device::~Device(void) { + //delete d->devices; + delete d; +} diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h new file mode 100644 index 00000000..8acd7677 --- /dev/null +++ b/telldus-core/service/Device.h @@ -0,0 +1,15 @@ +#ifndef DEVICE_H +#define DEVICE_H + +class Device +{ +public: + Device(); + ~Device(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //DEVICE_H \ No newline at end of file diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 15f501f0..abbf9ec1 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,13 +1,18 @@ #include "DeviceManager.h" +#include "Device.h" + +#include class DeviceManager::PrivateData { public: - //Lista med devices + std::map devices; }; -DeviceManager::DeviceManager() -{ +DeviceManager::DeviceManager(){ + } DeviceManager::~DeviceManager(void) { + //delete d->devices; + delete d; } From cef049ac338ce90534553c483d804e16542b431b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 12 Oct 2010 10:38:12 +0000 Subject: [PATCH 0271/2215] Controller and Protocol classes added (stubs) --- telldus-core/service/CMakeLists.txt | 4 ++++ telldus-core/service/Controller.cpp | 9 ++++++++ telldus-core/service/Controller.h | 17 ++++++++++++++ telldus-core/service/Device.cpp | 31 ++++++++++++++++++++++++-- telldus-core/service/Device.h | 11 +++++++++ telldus-core/service/DeviceManager.cpp | 9 +++++++- telldus-core/service/DeviceManager.h | 5 ++++- telldus-core/service/Protocol.cpp | 16 +++++++++++++ telldus-core/service/Protocol.h | 15 +++++++++++++ 9 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 telldus-core/service/Controller.cpp create mode 100644 telldus-core/service/Controller.h create mode 100644 telldus-core/service/Protocol.cpp create mode 100644 telldus-core/service/Protocol.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 63ecac8c..8d5cec66 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -10,6 +10,8 @@ SET( telldus-service_SRCS TelldusMain.cpp DeviceManager.cpp Device.cpp + Protocol.cpp + Controller.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h @@ -20,6 +22,8 @@ SET( telldus-service_HDRS TelldusMain.h DeviceManager.h Device.h + Protocol.h + Controller.h ) FIND_PACKAGE(Threads) diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp new file mode 100644 index 00000000..ee7e632d --- /dev/null +++ b/telldus-core/service/Controller.cpp @@ -0,0 +1,9 @@ +#include "Controller.h" + +Controller::Controller(){ + +} + +Controller::~Controller(){ + +} \ No newline at end of file diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h new file mode 100644 index 00000000..599732d3 --- /dev/null +++ b/telldus-core/service/Controller.h @@ -0,0 +1,17 @@ +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include + +class Controller { + public: + virtual ~Controller(); + + virtual int firmwareVersion() = 0; + virtual int send( const std::string &message ) = 0; + + protected: + Controller(); +}; + +#endif //CONTROLLER_H \ No newline at end of file diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 0f6e12e6..5b47adf2 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -2,14 +2,41 @@ class Device::PrivateData { public: - + std::wstring name; + Protocol* protocol; }; Device::Device(){ + d = new PrivateData; + //vid skapande, hämta settings från registret, vissa sätts i protokollet, vid dess skapande + //när något uppdateras, spara också till registret + //Denna klass har alla metoder (turnOn, turnOff etc)... + //Men t.ex. att om modellen är bell, då ska turnon returnera bell... eller isDimmer, ska returnera annat... hur göra? - låt vara i samma klass till att börja med + //Men skulle egentligen vilja ha tagit ställning till modell redan i initieringen... åtminstone spara undan det i en egen variabel } Device::~Device(void) { - //delete d->devices; + delete d->protocol; delete d; } + +std::wstring Device::getName(){ + return d->name; +} + +int Device::turnOn(Controller *controller) { + Protocol *p = this->retrieveProtocol(); + + //p->turnOn(controller); + return 0; +} + +Protocol *Device::retrieveProtocol() { + if (d->protocol) { + return d->protocol; + } + + d->protocol = new Protocol(); + return d->protocol; +} \ No newline at end of file diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 8acd7677..bba9b950 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -1,13 +1,24 @@ #ifndef DEVICE_H #define DEVICE_H +#include "Controller.h" +#include "Protocol.h" +#include + class Device { public: Device(); ~Device(void); + std::wstring getName(); + + int turnOn(Controller *controller); + private: + + Protocol *retrieveProtocol(); + class PrivateData; PrivateData *d; }; diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index abbf9ec1..e099c9cd 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -9,10 +9,17 @@ public: }; DeviceManager::DeviceManager(){ - + d = new PrivateData; + fillDevices(); } DeviceManager::~DeviceManager(void) { //delete d->devices; delete d; } + +void DeviceManager::fillDevices(){ + //foreach device i registret + //hämta id, låt devicen själv sätta sina värden i constructorn + //lägg till i devices-listan +} diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index ff0e3c4a..e1bf8742 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -4,10 +4,13 @@ class DeviceManager { public: - DeviceManager(); + DeviceManager(void); ~DeviceManager(void); private: + + void fillDevices(void); + class PrivateData; PrivateData *d; }; diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp new file mode 100644 index 00000000..922dd786 --- /dev/null +++ b/telldus-core/service/Protocol.cpp @@ -0,0 +1,16 @@ +#include "Protocol.h" + +class Protocol::PrivateData { +public: + +}; + +Protocol::Protocol(){ + + d = new PrivateData; + +} + +Protocol::~Protocol(void) { + delete d; +} diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h new file mode 100644 index 00000000..2313ddc1 --- /dev/null +++ b/telldus-core/service/Protocol.h @@ -0,0 +1,15 @@ +#ifndef PROTOCOL_H +#define PROTOCOL_H + +class Protocol +{ +public: + Protocol(); + ~Protocol(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //PROTOCOL_H \ No newline at end of file From b9203914fffebc54e6eced39c14f3f7d1e5ed06b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 12:03:49 +0000 Subject: [PATCH 0272/2215] Added tdtool --- telldus-core/CMakeLists.txt | 2 +- telldus-core/tdtool/CMakeLists.txt | 52 +++++ telldus-core/tdtool/main.cpp | 300 +++++++++++++++++++++++++++++ 3 files changed, 353 insertions(+), 1 deletion(-) create mode 100644 telldus-core/tdtool/CMakeLists.txt create mode 100644 telldus-core/tdtool/main.cpp diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index de510bfc..eea7863b 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -40,7 +40,7 @@ ADD_SUBDIRECTORY(service) ADD_SUBDIRECTORY(client) IF(BUILD_TDTOOL) -# ADD_SUBDIRECTORY(tdtool) + ADD_SUBDIRECTORY(tdtool) ENDIF(BUILD_TDTOOL) IF(BUILD_RFCMD) diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt new file mode 100644 index 00000000..2071ccab --- /dev/null +++ b/telldus-core/tdtool/CMakeLists.txt @@ -0,0 +1,52 @@ +PROJECT(tdtool) + +cmake_policy(SET CMP0005 NEW) + +SET (tdtool_DESCRIPTION + "a command line utility to control a Telldus TellStick" +) + +SET(tdtool_SRCS + main.cpp +) + +ADD_EXECUTABLE(tdtool + ${tdtool_SRCS} +) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/driver +) + +ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) + +IF (WIN32) + FIND_LIBRARY(TELLDUSCORE_LIBRARY TelldusCore) + TARGET_LINK_LIBRARIES(tdtool + ${TELLDUSCORE_LIBRARY} + ) +ELSEIF (APPLE) + TARGET_LINK_LIBRARIES(tdtool + TelldusCore + ) +ELSE (WIN32) + TARGET_LINK_LIBRARIES(tdtool + ${CMAKE_BINARY_DIR}/client/libtelldus-core.so + ) +ENDIF (WIN32) + +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET tdtool + POST_BUILD + COMMAND help2man -n ${tdtool_DESCRIPTION} ./tdtool > tdtool.1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file tdtool.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tdtool.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + +INSTALL(TARGETS tdtool RUNTIME DESTINATION bin) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp new file mode 100644 index 00000000..b6fbd87b --- /dev/null +++ b/telldus-core/tdtool/main.cpp @@ -0,0 +1,300 @@ +#include +#include +#include +#include +#include "../client/telldus-core.h" + +const int SUPPORTED_METHODS = + TELLSTICK_TURNON | + TELLSTICK_TURNOFF | + TELLSTICK_BELL | + TELLSTICK_DIM; + +void print_usage( char *name ) { + printf("Usage: %s [ options ]\n", name); + printf("\n"); + printf("Options:\n"); + printf(" -[bdefhlnrv] [ --list ] [ --help ]\n"); + printf(" [ --on device ] [ --off device ] [ --bell device ]\n"); + printf(" [ --learn device ]\n"); + printf(" [ --dimlevel level --dim device ]\n"); + printf(" [ --raw input ]\n"); + printf("\n"); + printf(" --list (-l short option)\n"); + printf(" List currently configured devices.\n"); + printf("\n"); + printf(" --help (-h short option)\n"); + printf(" Shows this screen.\n"); + printf("\n"); + printf(" --on device (-n short option)\n"); + printf(" Turns on device. 'device' could either be an integer of the\n"); + printf(" device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --off device (-f short option)\n"); + printf(" Turns off device. 'device' could either be an integer of the\n"); + printf(" device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --dim device (-d short option)\n"); + printf(" Dims device. 'device' could either be an integer of the device-id,\n"); + printf(" or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf(" Note: The dimlevel parameter must be set before using this option.\n"); + printf("\n"); + printf(" --dimlevel level (-v short option)\n"); + printf(" Set dim level. 'level' should an integer, 0-255.\n"); + printf(" Note: This parameter must be set before using dim.\n"); + printf("\n"); + printf(" --bell device (-b short option)\n"); + printf(" Sends bell command to devices supporting this. 'device' could\n"); + printf(" either be an integer of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --learn device (-e short option)\n"); + printf(" Sends a special learn command to devices supporting this. This is normaly\n"); + printf(" devices of 'selflearning' type. 'device' could either be an integer\n"); + printf(" of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --raw input (-r short option)\n"); + printf(" This command sends a raw command to TellStick.\n"); + printf(" input can be either - or a filename. If input is - the data is\n"); + printf(" taken from stdin, otherwise the data is taken from the supplied filename.\n"); + printf("\n"); + printf(" Example to turn on an ArcTech codeswitch A1:\n"); + printf(" echo 'S$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$kk$$kk$$kk$$}+' | tdtool --raw -\n"); + printf("\n"); + printf("Report bugs to \n"); +} + +void print_version() { + printf("tdtool " VERSION "\n"); + printf("\n"); + printf("Copyright (C) 2009 Telldus Technologies AB\n"); + printf("\n"); + printf("Written by Micke Prag \n"); +} + +void print_device( int index ) { + int intId = tdGetDeviceId(index); + char *name = tdGetName(intId); + printf("%i\t%s\t", intId, name); + tdReleaseString(name); + int lastSentCommand = tdLastSentCommand(intId, SUPPORTED_METHODS); + char *level = 0; + switch(lastSentCommand) { + case TELLSTICK_TURNON: + printf("ON"); + break; + case TELLSTICK_TURNOFF: + printf("OFF"); + break; + case TELLSTICK_DIM: + level = tdLastSentValue(intId); + printf("DIMMED:%s", level); + tdReleaseString(level); + break; + default: + printf("Unknown state"); + } + printf("\n"); +} + +void list_devices() { + int intNum = tdGetNumberOfDevices(); + if (intNum < 0) { + char *errorString = tdGetErrorString(intNum); + fprintf(stderr, "Error fetching devices: %s\n", errorString); + tdReleaseString(errorString); + return; + } + printf("Number of devices: %i\n", intNum); + int i = 0; + while (i < intNum) { + print_device( i ); + i++; + } +} + +int find_device( char *device ) { + int deviceId = atoi(device); + if (deviceId == 0) { //Try to find the id from the name + int intNum = tdGetNumberOfDevices(); + int index = 0; + while (index < intNum) { + int id = tdGetDeviceId(index); + char *name = tdGetName( id ); + if (strcasecmp(name, device) == 0) { + deviceId = id; + tdReleaseString(name); + break; + } + tdReleaseString(name); + index++; + } + } + return deviceId; +} + +void switch_device( bool turnOn, char *device ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + + char *name = tdGetName( deviceId ); + int deviceType = tdGetDeviceType( deviceId ); + printf("Turning %s %s %i, %s", + (turnOn ? "on" : "off"), + (deviceType == TELLSTICK_TYPE_DEVICE ? "device" : "group"), + deviceId, + name); + tdReleaseString(name); + + int retval = (turnOn ? tdTurnOn( deviceId ) : tdTurnOff( deviceId )); + char *errorString = tdGetErrorString(retval); + + printf(" - %s\n", errorString); + tdReleaseString(errorString); +} + +void dim_device( char *device, int level ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + if (level < 0 || level > 255) { + printf("Level %i out of range!\n", level); + return; + } + + char *name = tdGetName( deviceId ); + int retval = tdDim( deviceId, (unsigned char)level ); + char *errorString = tdGetErrorString(retval); + printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); + tdReleaseString(name); + tdReleaseString(errorString); +} + +void bell_device( char *device ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + + char *name = tdGetName( deviceId ); + int retval = tdBell( deviceId ); + char *errorString = tdGetErrorString(retval); + printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); + tdReleaseString(name); + tdReleaseString(errorString); +} + +void learn_device( char *device ) { + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return; + } + + char *name = tdGetName( deviceId ); + int retval = tdLearn( deviceId ); + char *errorString = tdGetErrorString(retval); + printf("Learning device: %i %s - %s\n", deviceId, name, errorString); + tdReleaseString(name); + tdReleaseString(errorString); +} + +void send_raw_command( char *command ) { + const int MAX_LENGTH = 100; + char msg[MAX_LENGTH]; + + if (strcmp(command, "-") == 0) { + fgets(msg, MAX_LENGTH, stdin); + } else { + FILE *fd; + + fd = fopen(command, "r"); + if (fd == NULL) { + printf("Error opening file %s\n", command); + return; + } + fgets(msg, MAX_LENGTH, fd); + } + + int retval = tdSendRawCommand( msg, 0 ); + char *errorString = tdGetErrorString(retval); + printf("Sending raw command: %s\n", errorString); + tdReleaseString(errorString); +} + +int main(int argc, char **argv) +{ + int optch, longindex; + static char optstring[] = "ln:f:d:b:v:e:r:hi"; + static struct option long_opts[] = { + { "list", 0, 0, 'l' }, + { "on", 1, 0, 'n' }, + { "off", 1, 0, 'f' }, + { "dim", 1, 0, 'd' }, + { "bell", 1, 0, 'b' }, + { "dimlevel", 1, 0, 'v' }, + { "learn", 1, 0, 'e' }, + { "raw", 1, 0, 'r' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'i'}, + { 0, 0, 0, 0} + }; + int level = -1; + + if (argc < 2) { + print_usage( argv[0] ); + return -1; + } + + while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) + switch (optch) { + case 'b' : + bell_device( &optarg[0] ); + break; + case 'd' : + if (level >= 0) { + dim_device( &optarg[0], level ); + } + break; + case 'f' : + switch_device(false, &optarg[0]); + break; + case 'h' : + print_usage( argv[0] ); + break; + case 'i' : + print_version( ); + break; + case 'l' : + list_devices(); + break; + case 'n' : + switch_device(true, &optarg[0]); + break; + case 'e' : + learn_device(&optarg[0]); + break; + case 'r' : + send_raw_command(&optarg[0]); + break; + case 'v' : + level = atoi( &optarg[0] ); + break; + default : + print_usage( argv[0] ); + return -1; + } + + tdClose(); //Cleaning up + return 0; +} From 7225c712217c6a6aa928a10ad7d6b1746ca6dd98 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 12:07:54 +0000 Subject: [PATCH 0273/2215] Fix indentation issues --- telldus-core/common/Message.cpp | 38 +++++++++++++++-------------- telldus-core/common/Message.h | 42 ++++++++++++++++----------------- 2 files changed, 41 insertions(+), 39 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index a3dd0790..62dc9b74 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -1,10 +1,12 @@ #include "Message.h" #include "Socket.h" -using namespace TelldusCore; #include #include #include +using namespace TelldusCore; + + Message::Message() : std::wstring() { @@ -88,28 +90,28 @@ int Message::wideToInteger(const std::wstring &input){ inputstream >> retval; return retval; } - -bool Message::getClientBoolFromSocket(){ + +bool Message::getClientBoolFromSocket(){ //TODO: move - return getClientIntegerFromSocket() == 1; + return getClientIntegerFromSocket() == 1; } -int Message::getClientIntegerFromSocket(){ +int Message::getClientIntegerFromSocket(){ //TODO: move Socket s; s.connect(L"TelldusClient"); - s.write(this->data()); - + s.write(this->data()); + std::wstring response = s.read(); - return takeInt(&response); -} - -std::wstring Message::getClientWStringFromSocket(){ - //TODO: move - Socket s; - s.connect(L"TelldusClient"); - s.write(this->data()); - - std::wstring response = s.read(); - return takeString(&response); + return takeInt(&response); +} + +std::wstring Message::getClientWStringFromSocket(){ + //TODO: move + Socket s; + s.connect(L"TelldusClient"); + s.write(this->data()); + + std::wstring response = s.read(); + return takeString(&response); } diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 9b3cecba..d28b43b1 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -4,30 +4,30 @@ #include namespace TelldusCore { - class Message : public std::wstring { - public: - Message(); - Message(const std::wstring &); - ~Message(void); - - void addArgument(const std::wstring &); - void addArgument(int); - void addArgument(const char *); + class Message : public std::wstring { + public: + Message(); + Message(const std::wstring &); + ~Message(void); - bool getClientBoolFromSocket(); - int getClientIntegerFromSocket(); - std::wstring getClientWStringFromSocket(); + void addArgument(const std::wstring &); + void addArgument(int); + void addArgument(const char *); + + bool getClientBoolFromSocket(); + int getClientIntegerFromSocket(); + std::wstring getClientWStringFromSocket(); - static std::wstring charToWstring(const char *value); - static bool nextIsInt(const std::wstring &); - static bool nextIsString(const std::wstring &); + static std::wstring charToWstring(const char *value); + static bool nextIsInt(const std::wstring &); + static bool nextIsString(const std::wstring &); - static std::wstring takeString(std::wstring *); - static int takeInt(std::wstring *); + static std::wstring takeString(std::wstring *); + static int takeInt(std::wstring *); - private: - static int wideToInteger(const std::wstring &input); - }; + private: + static int wideToInteger(const std::wstring &input); + }; } -#endif //MESSAGE_H \ No newline at end of file +#endif //MESSAGE_H From 74b6c14721a5278a068836cf9a134ba34348444a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 12:08:42 +0000 Subject: [PATCH 0274/2215] Added flag -fPIC for amd64 systems --- telldus-core/common/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 559343cd..719308bd 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -53,4 +53,6 @@ ADD_LIBRARY(${telldus-common_TARGET} STATIC ${telldus-common_HDRS} ) +SET_TARGET_PROPERTIES( ${telldus-common_TARGET} PROPERTIES COMPILE_FLAGS -fPIC) + TARGET_LINK_LIBRARIES( ${telldus-common_TARGET} ${telldus-common_LIBRARIES} ) From d41d71b7c97d7ce85091a749eebccecb4deb5737 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 12:09:18 +0000 Subject: [PATCH 0275/2215] Link agains telldus-common in Linux --- telldus-core/client/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 543afd26..0b994c76 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -70,6 +70,10 @@ ELSEIF (WIN32) ELSE (APPLE) #### Linux #### SET( telldus-core_TARGET telldus-core ) + LIST(APPEND telldus-core_LIBRARIES + telldus-common + ) + ADD_DEFINITIONS( -D_LINUX ) From 3fe6e21bd5b78d5bd8f830fc1baae02d85ce14f5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 12:09:53 +0000 Subject: [PATCH 0276/2215] Removed redundant line --- telldus-core/service/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 8d5cec66..9b45b3a8 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -90,7 +90,6 @@ ELSE (APPLE) #### Linux #### SettingsConfuse.cpp ) LIST(APPEND telldus-service_LIBRARIES - ${telldus-service_LIBRARIES} ${CONFUSE_LIBRARY} telldus-common ) From dedb8febae3ad0f8d2ce4b6d5d7c582317f6f204 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 12:10:35 +0000 Subject: [PATCH 0277/2215] Fix indentation issues --- .../service/ConnectionListener_win.cpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 6889ab3a..4ffa16a4 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -35,35 +35,35 @@ ConnectionListener::ConnectionListener(const std::wstring &name, Event *waitEven pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSD == NULL) { return; - } + } - if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { - LocalFree(pSD); + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { + LocalFree(pSD); return; - } + } if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) { - LocalFree(pSD); - } + LocalFree(pSD); + } ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = STANDARD_RIGHTS_ALL; ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance= NO_INHERITANCE; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; + ea.grfInheritance= NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; - // Add the ACL to the security descriptor. - if (!SetSecurityDescriptorDacl(pSD, - TRUE, // bDaclPresent flag - pACL, - FALSE)) // not a default DACL - { - LocalFree(pSD); + // Add the ACL to the security descriptor. + if (!SetSecurityDescriptorDacl(pSD, + TRUE, // bDaclPresent flag + pACL, + FALSE)) // not a default DACL + { + LocalFree(pSD); FreeSid(pEveryoneSID); - } + } d->sa.nLength = sizeof(SECURITY_ATTRIBUTES); From 4865a63f0c70ca8ec44c8c15b38006446de0eae2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 12:12:55 +0000 Subject: [PATCH 0278/2215] Fix indentation issues --- telldus-core/common/Message.cpp | 62 ++++++++++++++++----------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 62dc9b74..93e47c6c 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -8,69 +8,69 @@ using namespace TelldusCore; Message::Message() - : std::wstring() + : std::wstring() { } Message::Message(const std::wstring &functionName) - :std::wstring() + :std::wstring() { - this->addArgument(functionName); + this->addArgument(functionName); } Message::~Message(void) { } void Message::addArgument(const std::wstring &value) { - std::wstringstream st; - st << (int)value.size(); - this->append(st.str()); - this->append(L":"); - this->append(value); + std::wstringstream st; + st << (int)value.size(); + this->append(st.str()); + this->append(L":"); + this->append(value); } void Message::addArgument(int value) { - std::wstringstream st; - st << (int)value; - this->append(L"i"); - this->append(st.str()); - this->append(L"s"); + std::wstringstream st; + st << (int)value; + this->append(L"i"); + this->append(st.str()); + this->append(L"s"); } void Message::addArgument(const char *value) { - this->addArgument(charToWstring(value)); + this->addArgument(charToWstring(value)); } std::wstring Message::charToWstring(const char *value) { - std::wstringstream st; - st << value; + std::wstringstream st; + st << value; return st.str(); } bool Message::nextIsInt(const std::wstring &message) { - if (message.length() == 0) { - return false; - } - return (message.at(0) == 'i'); + if (message.length() == 0) { + return false; + } + return (message.at(0) == 'i'); } bool Message::nextIsString(const std::wstring &message) { - if (message.length() == 0) { - return false; - } - return (iswdigit(message.at(0)) != 0); + if (message.length() == 0) { + return false; + } + return (iswdigit(message.at(0)) != 0); } std::wstring Message::takeString(std::wstring *message) { if (!Message::nextIsString(*message)) { - return L""; - } - int index = message->find(':'); - int length = wideToInteger(message->substr(0, index)); - std::wstring retval(message->substr(index+1, length)); - message->erase(0, index+length+1); - return retval; + return L""; + } + int index = message->find(':'); + int length = wideToInteger(message->substr(0, index)); + std::wstring retval(message->substr(index+1, length)); + message->erase(0, index+length+1); + return retval; } int Message::takeInt(std::wstring *message) { From 549a146ce993b98df46cf3bc8a1f8e8d428db09b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 13:17:06 +0000 Subject: [PATCH 0279/2215] Implemented the socket in unix --- telldus-core/common/Socket_unix.cpp | 40 ++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 12cc8f85..cc7250f5 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -1,18 +1,31 @@ #include "Socket.h" +#include +#include +#include + +#define BUFSIZE 512 + using namespace TelldusCore; +int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + connect(sockfd, addr, addrlen); +} + class Socket::PrivateData { public: + SOCKET_T socket; }; Socket::Socket() { d = new PrivateData; + d->socket = 0; } -Socket::Socket(SOCKET_T hPipe) +Socket::Socket(SOCKET_T socket) { d = new PrivateData; + d->socket = socket; } Socket::~Socket(void) { @@ -20,12 +33,33 @@ Socket::~Socket(void) { } void Socket::connect(const std::wstring &server) { + struct sockaddr_un remote; + socklen_t len; + + if ((d->socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return; + } + std::string name = "/tmp/" + std::string(server.begin(), server.end()); + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, name.c_str()); + + len = SUN_LEN(&remote); + if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { + return; + } } std::wstring Socket::read() { - return L""; + char inbuf[BUFSIZE]; + memset(inbuf, '\0', sizeof(inbuf)); + + size_t inlen = recv(d->socket, inbuf, BUFSIZE - 1, 0); + + std::string msg(inbuf); + return std::wstring(msg.begin(), msg.end()); } void Socket::write(const std::wstring &msg) { - + std::string newMsg(msg.begin(), msg.end()); + send(d->socket, newMsg.c_str(), newMsg.length(), 0); } From 8c1e97559bd2bb480a908936ca7d2355e937ef23 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 13:17:48 +0000 Subject: [PATCH 0280/2215] Implemented the class ConnectionListener in unix --- .../service/ConnectionListener_unix.cpp | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 41c90e57..00444a46 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -1,20 +1,86 @@ #include "ConnectionListener.h" +#include "Socket.h" +#include +#include +#include + +#include +#include class ConnectionListener::PrivateData { public: + Event *waitEvent; + std::string name; + bool running; }; ConnectionListener::ConnectionListener(const std::wstring &name, Event *waitEvent) { d = new PrivateData; + d->waitEvent = waitEvent; + + d->name = "/tmp/" + std::string(name.begin(), name.end()); + d->running = true; + + this->start(); } ConnectionListener::~ConnectionListener(void) { + d->running = false; + this->wait(); + delete d->waitEvent; delete d; } void ConnectionListener::run(){ + struct timeval tv = { 0, 0 }; + + //Timeout for select + + SOCKET_T serverSocket; + struct sockaddr_un remote, name; + socklen_t len; + serverSocket = socket(PF_LOCAL, SOCK_STREAM, 0); + if (serverSocket < 0) { + return; + } + name.sun_family = AF_LOCAL; + memset(name.sun_path, '\0', sizeof(name.sun_path)); + strncpy(name.sun_path, d->name.c_str(), sizeof(name.sun_path)); + unlink(name.sun_path); + int size = SUN_LEN(&name); + bind(serverSocket, (struct sockaddr *)&name, size); + listen(serverSocket, 5); + len = sizeof(struct sockaddr_un); + + fd_set infds; + FD_ZERO(&infds); + FD_SET(serverSocket, &infds); + while(d->running) { + tv.tv_sec = 5; + + int response = select(serverSocket+1, &infds, NULL, NULL, &tv); + if (response == 0) { + FD_SET(serverSocket, &infds); + continue; + } else if (response < 0 ) { + printf("Select error occured: %i\n", response); + continue; + } + //Make sure it is a new connection + if (!FD_ISSET(serverSocket, &infds)) { + printf("Not ours, error?\n"); + continue; + } + SOCKET_T clientSocket = accept(serverSocket, NULL, NULL); + + ConnectionListenerEventData *data = new ConnectionListenerEventData(); + data->socket = new TelldusCore::Socket(clientSocket); + d->waitEvent->signal(data); + + } + close(serverSocket); } From 1924ad7e416339dc85b6f146c617fc95222e6c39 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 14:39:24 +0000 Subject: [PATCH 0281/2215] Initialize the hasEvent variable --- telldus-core/service/EventHandler_unix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index a4dcfb7b..974d16ac 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -13,6 +13,7 @@ public: EventHandler::EventHandler() { d = new PrivateData; + d->hasEvent = false; pthread_cond_init(&d->event, NULL); pthread_mutex_init(&d->mutex, NULL); } From 7c9eb6c0f2731eb95d0151c7b9dbcf09e9573419 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 12 Oct 2010 14:48:35 +0000 Subject: [PATCH 0282/2215] Removed static declarations. We don't compile telldus-core as static anymore. --- telldus-core/client/telldus-core.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 1fa84fe7..18e2948c 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -10,9 +10,7 @@ // sees symbols defined with this macro as being exported. #ifdef _WINDOWS - #if defined(TELLDUSCORE_STATIC) - #define TELLSTICK_API - #elif defined(TELLDUSCORE_EXPORTS) + #if defined(TELLDUSCORE_EXPORTS) #define TELLSTICK_API __declspec(dllexport) #else #define TELLSTICK_API __declspec(dllimport) From 02584391e7581eaab7f7fd817c0bc538b47a9ecb Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 08:02:20 +0000 Subject: [PATCH 0283/2215] Test protocol-stub added --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/ProtocolNexa.cpp | 306 ++++++++++++++++++++++++++ telldus-core/service/ProtocolNexa.h | 36 +++ 3 files changed, 344 insertions(+) create mode 100644 telldus-core/service/ProtocolNexa.cpp create mode 100644 telldus-core/service/ProtocolNexa.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 9b45b3a8..d5369f39 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -12,6 +12,7 @@ SET( telldus-service_SRCS Device.cpp Protocol.cpp Controller.cpp + ProtocolNexa.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h @@ -24,6 +25,7 @@ SET( telldus-service_HDRS Device.h Protocol.h Controller.h + ProtocolNexa.h ) FIND_PACKAGE(Threads) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp new file mode 100644 index 00000000..d6f23fb6 --- /dev/null +++ b/telldus-core/service/ProtocolNexa.cpp @@ -0,0 +1,306 @@ +// #include "StdAfx.h" +#include "ProtocolNexa.h" +#include +#include +#include +#include +#include +// #include "common.h" + +const char START[] = {'T',127,255,24,1,0}; +//const char START[] = {'T',130,255,26,24,0}; + +/* +* Constructor +*/ +ProtocolNexa::ProtocolNexa() + :Protocol(), + intHouse(0), + intCode(0) +{ + +} + +/* +* Destructor +*/ +ProtocolNexa::~ProtocolNexa(void) +{} + + +//bool DeviceNexa::setHouse(const std::string &newHouse) { +// int house = atoi(newHouse.c_str()); +// if (newHouse.length() == 1 && house == 0) { //Codeswitch +// intHouse = newHouse[0] - 'A'; +// } else { //Selflearning +// intHouse = house; +// } +// return true; +//} +// +//bool DeviceNexa::setUnit(const std::string &newUnit) { +// if (newUnit.length() > 0) { +// intCode = atoi(newUnit.c_str()) - 1; +// } else { +// intCode = 0; +// } +// return true; +//} +// +//bool DeviceNexa::setDeviceParameter(const std::string &strName, const std::string &strValue) { +// if (strName.compare("house") == 0) { +// return setHouse(strValue); +// } else if (strName.compare("unit") == 0) { +// return setUnit(strValue); +// } +// return false; +//} +// +///* +//* Turn on this device +//*/ +// +//int DeviceNexa::turnOn(Controller *controller){ +// if (strcasecmp(this->getModel().c_str(), "bell") == 0) { +// return bell(controller); +// } +// try{ +// std::string strCode = ""; +// if (isDimmer()) { +// return dim(255, controller); +// } else if (isSelflearning()) { +// strCode.append( 1, 'R' ); +// strCode.append( 1, 5 ); +// strCode.append(getStringSelflearning(false, 255)); +// } else { +// strCode.append("S"); +// strCode.append(getStringCodeSwitch(intHouse)); +// strCode.append(getStringCodeSwitch(intCode)); +// strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time +// } +// +// return controller->send(strCode); +// } +// catch(...){ +// throw; +// } +// return TELLSTICK_ERROR_UNKNOWN; +//} +// +///* +//* Turn off this device +//*/ +// +//int DeviceNexa::turnOff(Controller *controller){ +// +// try{ +// std::string strCode = ""; +// if (isSelflearning()) { +// strCode.append( 1, 'R' ); +// strCode.append( 1, 5 ); +// strCode.append(getStringSelflearning(false, 0)); +// } else { +// strCode.append("S"); +// strCode.append(getStringCodeSwitch(intHouse)); +// strCode.append(getStringCodeSwitch(intCode)); +// strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time +// } +// +// return controller->send(strCode); +// } +// catch(...){ +// throw; +// } +// return TELLSTICK_ERROR_UNKNOWN; +//} +// +///* +//* Dim this device +//*/ +// +//int DeviceNexa::dim(unsigned char level, Controller *controller) { +// try{ +// std::string strMessage = ""; +// strMessage.append( 1, 'R' ); +// strMessage.append( 1, 5 ); +// strMessage.append(getStringSelflearning(true, level)); +// return controller->send(strMessage); +// } +// catch(...){ +// throw; +// } +// return TELLSTICK_ERROR_UNKNOWN; +//} +// +// +///* +//* Send a bell +//*/ +// +//int DeviceNexa::bell(Controller *controller){ +// +// try{ +// std::string strCode = getStringCodeSwitch(intHouse); +// +// strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time +// strCode.insert(0, "S"); +// strCode.append("$kk$$kk$$kk$$kk$$k+"); //the "bell"-code, keeps it like this, doesn't have to be regenerated each time +// +// return controller->send(strCode); +// } +// catch(...){ +// throw; +// } +// return TELLSTICK_ERROR_UNKNOWN; +//} +// +//int DeviceNexa::learn(Controller *controller){ +// std::string strCode = ""; +// strCode.append( 1, 'R' ); +// strCode.append( 1, 2 ); +// strCode.append(getStringSelflearning(false, 255)); +// +// int retVal = 0; +// for (int i = 0; i < 5; ++i) { +// retVal = controller->send(strCode); +// if (retVal != TELLSTICK_SUCCESS) { +// return retVal; +// } +// msleep(200); +// } +// return retVal; +//} +// +///* +//* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed +//*/ +// +//std::string DeviceNexa::getStringCodeSwitch(int intToConvert){ +// +// std::string strReturn = ""; +// +// try{ +// for( int i = 0; i < 4; ++i ) { +// if (intToConvert & 1) { //Convert 1 +// strReturn.append("$kk$"); +// } else { //Convert 0 +// strReturn.append("$k$k"); +// } +// intToConvert >>= 1; +// +// } +// } +// catch(...){ +// throw; +// } +// return strReturn; +// +//} +// +//std::string DeviceNexa::getStringSelflearning(bool dim, unsigned char level) { +// std::string strMessage = START; +// strMessage.append(1,(dim ? 147 : 132)); //Number of pulses +// +// std::string m; +// for (int i = 25; i >= 0; --i) { +// m.append( intHouse & 1 << i ? "10" : "01" ); +// } +// m.append("01"); //Group +// +// //On/off +// if (dim) { +// m.append("00"); +// } else if (level == 0) { +// m.append("01"); +// } else { +// m.append("10"); +// } +// +// for (int i = 3; i >= 0; --i) { +// m.append( intCode & 1 << i ? "10" : "01" ); +// } +// +// if (dim) { +// unsigned char newLevel = level/16; +// for (int i = 3; i >= 0; --i) { +// m.append(newLevel & 1 << i ? "10" : "01"); +// } +// } +// +// //The number of data is odd. +// //Add this to make it even, otherwise the following loop will not work +// m.append("0"); +// +// unsigned char code = 9; //b1001, startcode +// for (unsigned int i = 0; i < m.length(); ++i) { +// code <<= 4; +// if (m[i] == '1') { +// code |= 8; //b1000 +// } else { +// code |= 10; //b1010 +//// code |= 11; //b1011 +// } +// if (i % 2 == 0) { +// strMessage.append(1,code); +// code = 0; +// } +// } +// strMessage.append("+"); +// +//// for( int i = 0; i < strMessage.length(); ++i ) { +//// printf("%i,", (unsigned char)strMessage[i]); +//// } +//// printf("\n"); +// return strMessage; +//} +// +//bool DeviceNexa::parameterMatches( const std::string &name, const std::string &value ) const { +// if (name.compare("house") == 0) { +// if (isSelflearning()) { +// return intHouse == atoi(value.c_str()); +// } +// return intHouse == value[0] - 'A'; +// } else if (name.compare("unit") == 0) { +// return intCode == atoi(value.c_str()) - 1; +// } else if (name.compare("type") == 0) { +// if (isSelflearning()) { +// return (value.compare("selflearning") == 0); +// } +// } +// return true; +//} +// +///* +//* Has the device got the method? +//*/ +// +//int DeviceNexa::methods(){ +// std::string strModel = this->getModel(); +// +// if ( strcasecmp(strModel.c_str(), "codeswitch") == 0 ) { +// return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); +// +// } else if (strcasecmp(strModel.c_str(), "selflearning-switch") == 0) { +// return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); +// +// } else if (strcasecmp(strModel.c_str(), "selflearning-dimmer") == 0) { +// return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); +// +// } else if (strcasecmp(strModel.c_str(), "bell") == 0) { +// return TELLSTICK_BELL; +// } +// return 0; +//} +// +//bool DeviceNexa::isSelflearning() const { +// return strncasecmp(getModel().c_str(), "selflearning", 12) == 0; +//} +// +//bool DeviceNexa::isDimmer() const { +// return strcasecmp(getModel().c_str(), "selflearning-dimmer") == 0; +//} +// +//std::string DeviceNexa::getProtocol() const { +// return "arctech"; +//} +// diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h new file mode 100644 index 00000000..7da171c0 --- /dev/null +++ b/telldus-core/service/ProtocolNexa.h @@ -0,0 +1,36 @@ +#pragma once +#include "Device.h" +#include + +class ProtocolNexa : public Protocol +{ + public: + ProtocolNexa(); + //virtual int methods(); + //virtual std::string getProtocol() const; + //virtual bool parameterMatches( const std::string &name, const std::string &value ) const; + + bool setHouse(const std::string &newHouse); + bool setUnit(const std::string &newUnit); + + ~ProtocolNexa(void); + + protected: + /* + virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); + virtual int turnOn(Controller *controller); + virtual int turnOff(Controller *controller); + virtual int dim(unsigned char level, Controller *controller); + virtual int bell(Controller *controller); + virtual int learn(Controller *controller); + + bool isSelflearning() const; + bool isDimmer() const; + + */ + int intHouse; + int intCode; + //std::string getStringCodeSwitch(int); + //std::string getStringSelflearning(bool dim, unsigned char level); + +}; From 7a4eb71393aa542099744c83f94cf23d868891d2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 08:02:48 +0000 Subject: [PATCH 0284/2215] Example protocol stub put in use --- telldus-core/service/Device.cpp | 59 ++++++++++++++--- telldus-core/service/Device.h | 11 +++- telldus-core/service/DeviceManager.cpp | 23 +++++-- telldus-core/service/Protocol.cpp | 88 ++++++++++++++++++++++++-- telldus-core/service/Protocol.h | 10 +++ telldus-core/service/TelldusMain.cpp | 4 +- 6 files changed, 176 insertions(+), 19 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 5b47adf2..734c9871 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -1,19 +1,24 @@ #include "Device.h" +#include "Settings.h" class Device::PrivateData { public: std::wstring name; - Protocol* protocol; + std::wstring model; + std::wstring protocolName; + ParameterMap parameterList; + + Protocol *protocol; }; Device::Device(){ +} +Device::Device(int id){ d = new PrivateData; - //vid skapande, hämta settings från registret, vissa sätts i protokollet, vid dess skapande + //när något uppdateras, spara också till registret - //Denna klass har alla metoder (turnOn, turnOff etc)... - //Men t.ex. att om modellen är bell, då ska turnon returnera bell... eller isDimmer, ska returnera annat... hur göra? - låt vara i samma klass till att börja med - //Men skulle egentligen vilja ha tagit ställning till modell redan i initieringen... åtminstone spara undan det i en egen variabel + //obs, alla hantera om alla värden inte är satta } Device::~Device(void) { @@ -21,22 +26,60 @@ Device::~Device(void) { delete d; } +/** +* Get-/Set-methods +*/ +std::wstring Device::getModel(){ + return d->model; +} + +void Device::setModel(const std::wstring &model){ + d->model = model; +} + std::wstring Device::getName(){ return d->name; } +void Device::setName(const std::wstring &name){ + d->name = name; +} + +std::wstring Device::getParameter(const std::wstring &key){ + return d->parameterList[key]; +} + +void Device::setParameter(const std::wstring &key, const std::wstring &value){ + d->parameterList[key] = value; +} + +std::wstring Device::getProtocolName(){ + return d->protocolName; +} + +void Device::setProtocolName(const std::wstring &protocolName){ + d->protocolName = protocolName; +} + +/** +* End Get-/Set +*/ + int Device::turnOn(Controller *controller) { Protocol *p = this->retrieveProtocol(); //p->turnOn(controller); + //TODO: Handle p return 0; } -Protocol *Device::retrieveProtocol() { +Protocol* Device::retrieveProtocol() { if (d->protocol) { return d->protocol; } - - d->protocol = new Protocol(); + + d->protocol = Protocol::getProtocolInstance(d->protocolName); + d->protocol->setModel(d->model); + d->protocol->setParameters(d->parameterList); return d->protocol; } \ No newline at end of file diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index bba9b950..21b87efa 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -9,10 +9,19 @@ class Device { public: Device(); + Device(int id); ~Device(void); + std::wstring getModel(); + void setModel(const std::wstring &model); std::wstring getName(); - + void setName(const std::wstring &name); + std::wstring getParameter(const std::wstring &key); + void setParameter(const std::wstring &key, const std::wstring &value); + std::wstring getProtocolName(); + void setProtocolName(const std::wstring &name); + + int turnOn(Controller *controller); private: diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index e099c9cd..3d2a8e28 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,11 +1,12 @@ #include "DeviceManager.h" #include "Device.h" +#include "Settings.h" #include class DeviceManager::PrivateData { public: - std::map devices; + std::map devices; }; DeviceManager::DeviceManager(){ @@ -15,11 +16,25 @@ DeviceManager::DeviceManager(){ DeviceManager::~DeviceManager(void) { //delete d->devices; + //todo: delete devices delete d; } void DeviceManager::fillDevices(){ - //foreach device i registret - //hämta id, låt devicen själv sätta sina värden i constructorn - //lägg till i devices-listan + Settings set; + int numberOfDevices = set.getNumberOfDevices(); + + for (int i = 0; i < numberOfDevices; ++i) { + int id = set.getDeviceId(i); + d->devices[id] = new Device(id); + d->devices[id]->setName(set.getName(id)); + d->devices[id]->setModel(set.getModel(id)); + d->devices[id]->setProtocolName(set.getProtocol(id)); + d->devices[id]->setParameter(L"house", set.getDeviceParameter(id, L"house")); + d->devices[id]->setParameter(L"unit", set.getDeviceParameter(id, L"unit")); + d->devices[id]->setParameter(L"code", set.getDeviceParameter(id, L"code")); + d->devices[id]->setParameter(L"units", set.getDeviceParameter(id, L"units")); + d->devices[id]->setParameter(L"fade", set.getDeviceParameter(id, L"fade")); + d->devices[id]->setParameter(L"system", set.getDeviceParameter(id, L"system")); + } } diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 922dd786..a8a0e863 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,16 +1,96 @@ -#include "Protocol.h" +#include "protocol.h" +#include "Settings.h" + +#include "ProtocolNexa.h" +#include class Protocol::PrivateData { public: - + ParameterMap parameterList; + std::wstring model; }; Protocol::Protocol(){ - d = new PrivateData; - + d = new PrivateData; } Protocol::~Protocol(void) { delete d; } + +Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ + + //TODO: tr1:shared_ptr... + Protocol *prot; + if (protocolname.compare(L"arctech") == 0){ //TODO TO LOWER! + prot = new ProtocolNexa(); + //((ProtocolNexa*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); //todo: try to do this in ProtocolNexa instead + //((ProtocolNexa*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); + + } + /*else if (wcscasecmp(protocolname.c_str(), L"brateck") == 0) { + prot = new ProtocolBrateck(deviceId, modelname); + ((ProtocolBrateck*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + + } else if (wcscasecmp(protocolname.c_str(), L"everflourish") == 0){ + prot = new ProtocolEverflourish(deviceId, modelname); + ((ProtocolEverflourish*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + ((ProtocolEverflourish*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); + + } else if (wcscasecmp(protocolname.c_str(), L"fuhaote") == 0) { + prot = new ProtocolFuhaote(deviceId, modelname); + ((ProtocolFuhaote*)prot)->setCode(settings.getDeviceParameter(deviceId, "code")); + + } else if (wcscasecmp(protocolname.c_str(), L"silvanchip") == 0) { + prot = new ProtocolSilvanChip(deviceId, modelname); + ((ProtocolSilvanChip*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + + } else if (wcscasecmp(protocolname.c_str(), L"group") == 0) { + prot = new ProtocolGroup(deviceId, modelname); + //TODO: take a closer look + ((ProtocolGroup*)prot)->setDevices(settings.getDeviceParameter(deviceId, "devices")); + + } else if (wcscasecmp(protocolname.c_str(), L"risingsun") == 0) { + prot = new ProtocolRisingSun(deviceId, modelname); + ((ProtocolRisingSun*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + ((ProtocolRisingSun*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); + + } else if (wcscasecmp(protocolname.c_str(), L"Waveman") == 0) { + prot = new ProtocolWaveman(deviceId, modelname); + ((ProtocolWaveman*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + ((ProtocolWaveman*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); + + } else if (wcscasecmp(protocolname.c_str(), L"Sartano") == 0) { + prot = new ProtocolSartano(deviceId, modelname); + ((ProtocolSartano*)prot)->setCode(settings.getDeviceParameter(deviceId, "code")); + + } else if (wcscasecmp(protocolname.c_str(), L"Ikea") == 0) { + prot = new ProtocolIkea(deviceId, modelname); + ((ProtocolIkea*)prot)->setSystem(settings.getDeviceParameter(deviceId, "system")); + ((ProtocolIkea*)prot)->setUnits(settings.getDeviceParameter(deviceId, "units")); + ((ProtocolIkea*)prot)->setFade(settings.getDeviceParameter(deviceId, "fade")); + + } else if (wcscasecmp(protocolname.c_str(), L"upm") == 0) { + prot = new ProtocolUpm(deviceId, modelname); + ((ProtocolUpm*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + ((ProtocolUpm*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); + + } else if (wcscasecmp(protocolname.c_str(), L"x10") == 0) { + prot = new ProtocolX10(deviceId, modelname); + ((ProtocolX10*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + ((ProtocolX10*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); + + } + */ + + return prot; //TODO can be null +} + +void Protocol::setModel(const std::wstring &model){ + d->model = model; +} + +void Protocol::setParameters(ParameterMap ¶meterList){ + d->parameterList = parameterList; +} diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 2313ddc1..4ba84d9d 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -1,12 +1,22 @@ #ifndef PROTOCOL_H #define PROTOCOL_H +#include +#include + +typedef std::map ParameterMap; + class Protocol { public: Protocol(); ~Protocol(void); + static Protocol *getProtocolInstance(std::wstring &protocolname); + + void setModel(const std::wstring &model); + void setParameters(ParameterMap ¶meterList); + private: class PrivateData; PrivateData *d; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 2afe9588..afab00be 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -28,7 +28,7 @@ TelldusMain::~TelldusMain(void) void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); - DeviceManager *deviceManager; + DeviceManager deviceManager; ConnectionListener clientListener(L"TelldusClient", clientEvent); //TODO: eventlistener @@ -44,7 +44,7 @@ void TelldusMain::start(void) { ConnectionListenerEventData *data = reinterpret_cast(eventData); if (data) { Event *handlerEvent = d->eventHandler.addEvent(); - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, deviceManager); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } From eae2a35d48322a864d123fe15295fa09c0ef5d45 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 08:27:58 +0000 Subject: [PATCH 0285/2215] New string compare for wstring, should be case insensitive. --- telldus-core/service/Protocol.cpp | 33 +++++++++++++++++++++++-------- telldus-core/service/Protocol.h | 1 + 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index a8a0e863..2bb82ba9 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -2,6 +2,7 @@ #include "Settings.h" #include "ProtocolNexa.h" +#include #include class Protocol::PrivateData { @@ -19,11 +20,34 @@ Protocol::~Protocol(void) { delete d; } +void Protocol::setModel(const std::wstring &model){ + d->model = model; +} + +void Protocol::setParameters(ParameterMap ¶meterList){ + d->parameterList = parameterList; +} + +/** +* This method don't support all locales +*/ +bool Protocol::comparei(std::wstring stringA , std::wstring stringB) +{ + //move? + transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); + transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); + + if(stringA == stringB) + return true; + else + return false; +} + Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ //TODO: tr1:shared_ptr... Protocol *prot; - if (protocolname.compare(L"arctech") == 0){ //TODO TO LOWER! + if(comparei(protocolname, L"arctech")){ //TODO: Test this prot = new ProtocolNexa(); //((ProtocolNexa*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); //todo: try to do this in ProtocolNexa instead //((ProtocolNexa*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); @@ -87,10 +111,3 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ return prot; //TODO can be null } -void Protocol::setModel(const std::wstring &model){ - d->model = model; -} - -void Protocol::setParameters(ParameterMap ¶meterList){ - d->parameterList = parameterList; -} diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 4ba84d9d..e23e4daf 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -20,6 +20,7 @@ public: private: class PrivateData; PrivateData *d; + static bool comparei(std::wstring stringA , std::wstring stringB); }; #endif //PROTOCOL_H \ No newline at end of file From 53766282b0a6f11bdc43a453cc55c9ea74e21f85 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 08:32:07 +0000 Subject: [PATCH 0286/2215] Code cleanup --- telldus-core/service/Protocol.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 2bb82ba9..150d66b1 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -34,13 +34,10 @@ void Protocol::setParameters(ParameterMap ¶meterList){ bool Protocol::comparei(std::wstring stringA , std::wstring stringB) { //move? - transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); - transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); + transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); + transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); - if(stringA == stringB) - return true; - else - return false; + return stringA == stringB; } Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ @@ -104,7 +101,7 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ prot = new ProtocolX10(deviceId, modelname); ((ProtocolX10*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); ((ProtocolX10*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); - + } */ From 1149b8caf8dd1adb1f87d1913c0199d3f2ecc912 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 08:35:43 +0000 Subject: [PATCH 0287/2215] Added source group "Protocol Files" --- telldus-core/service/CMakeLists.txt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index d5369f39..5961095c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -10,8 +10,12 @@ SET( telldus-service_SRCS TelldusMain.cpp DeviceManager.cpp Device.cpp - Protocol.cpp Controller.cpp +) +SET( telldus-service_protocol_SRCS + Protocol.h + Protocol.cpp + ProtocolNexa.h ProtocolNexa.cpp ) SET( telldus-service_HDRS @@ -23,11 +27,8 @@ SET( telldus-service_HDRS TelldusMain.h DeviceManager.h Device.h - Protocol.h Controller.h - ProtocolNexa.h ) - FIND_PACKAGE(Threads) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) @@ -99,9 +100,11 @@ ENDIF (APPLE) ######## Configuring ######## +SOURCE_GROUP("Protocol Files" FILES ${telldus-service_protocol_SRCS}) ADD_EXECUTABLE(${telldus-service_TARGET} ${telldus-service_SRCS} + ${telldus-service_protocol_SRCS} ${telldus-service_HDRS} ) SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) From 72910644e53233e410ec03864973092fbf0eb3f8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 09:19:07 +0000 Subject: [PATCH 0288/2215] Service crash fix and the correct number of devices (as set in the register) is now used. --- .../service/ClientCommunicationHandler.cpp | 77 ++++++++++--------- telldus-core/service/DeviceManager.cpp | 9 ++- telldus-core/service/DeviceManager.h | 6 +- telldus-core/service/Protocol.cpp | 2 +- 4 files changed, 54 insertions(+), 40 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index fc2d9fc1..dc6476ee 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -71,89 +71,92 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, std::wstring function(TelldusCore::Message::takeString(&msg)); if (function == L"tdTurnOn") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; //tdTurnOn(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + //TODO: Lock device + //TODO: (*intReturn) = d->deviceManager->getDevice(deviceId)->turnOn(); //Controller... + //TODO: Unlock + //(*intReturn) = 0; //tdTurnOn(deviceId); } else if (function == L"tdTurnOff") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; //tdTurnOff(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = 0; //tdTurnOff(deviceId); } else if (function == L"tdBell") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdBell(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = 0; // tdBell(deviceId); } else if (function == L"tdDim") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); int level = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdDim(intDeviceId, level); + (*intReturn) = 0; // tdDim(deviceId, level); } else if (function == L"tdLearn") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; //tdLearn(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = 0; //tdLearn(deviceId); } else if (function == L"tdLastSentCommand") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); int methodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdLastSentCommand(intDeviceId, methodsSupported); + (*intReturn) = 0; // tdLastSentCommand(deviceId, methodsSupported); } else if (function == L"tdLastSentValue") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - const char *value = ""; //tdLastSentValue(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + const char *value = ""; //tdLastSentValue(deviceId); (*wstringReturn) = TelldusCore::Message::charToWstring(value); } else if(function == L"tdGetNumberOfDevices"){ - (*intReturn) = 12; //d->settings.getNumberOfDevices(); + (*intReturn) = d->deviceManager->getNumberOfDevices(); } else if (function == L"tdGetDeviceId") { int intDeviceIndex = TelldusCore::Message::takeInt(&msg); (*intReturn) = 1; //tdGetDeviceId(intDeviceIndex); } else if (function == L"tdGetDeviceType") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 11; // tdGetDeviceType(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = 11; // tdGetDeviceType(deviceId); } else if (function == L"tdGetName") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - const char *name = "Default name"; //tdGetName(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + const char *name = "Default name"; //tdGetName(deviceId); (*wstringReturn) = TelldusCore::Message::charToWstring(name); } else if (function == L"tdSetName") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; //tdSetName(intDeviceId, name.c_str()); + (*intReturn) = 0; //tdSetName(deviceId, name.c_str()); } else if (function == L"tdGetProtocol") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - const char *protocol = "Default protocol"; //tdGetProtocol(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + const char *protocol = "Default protocol"; //tdGetProtocol(deviceId); (*wstringReturn) = TelldusCore::Message::charToWstring(protocol); } else if (function == L"tdSetProtocol") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring protocol = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; // tdSetProtocol(intDeviceId, protocol.c_str()); + (*intReturn) = 0; // tdSetProtocol(deviceId, protocol.c_str()); } else if (function == L"tdGetModel") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - const char *model = "Default model"; //tdGetModel(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + const char *model = "Default model"; //tdGetModel(deviceId); (*wstringReturn) = TelldusCore::Message::charToWstring(model); } else if (function == L"tdSetModel") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring model = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; // tdSetModel(intDeviceId, model.c_str()); + (*intReturn) = 0; // tdSetModel(deviceId, model.c_str()); } else if (function == L"tdSetDeviceParameter") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring value = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; //tdSetDeviceParameter(intDeviceId, name.c_str(), value.c_str()); + (*intReturn) = 0; //tdSetDeviceParameter(deviceId, name.c_str(), value.c_str()); } else if (function == L"tdGetDeviceParameter") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring defaultValue = TelldusCore::Message::takeString(&msg); - const char *value = "Device parameter default"; //tdGetDeviceParameter(intDeviceId, name.c_str(), defaultValue.c_str()); + const char *value = "Device parameter default"; //tdGetDeviceParameter(deviceId, name.c_str(), defaultValue.c_str()); (*wstringReturn) = TelldusCore::Message::charToWstring(value); } else if (function == L"tdAddDevice") { @@ -166,13 +169,13 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } } else if (function == L"tdRemoveDevice") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdRemoveDevice(intDeviceId); + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = 0; // tdRemoveDevice(deviceId); } else if (function == L"tdMethods") { - int intDeviceId = TelldusCore::Message::takeInt(&msg); + int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdMethods(intDeviceId, intMethodsSupported); + (*intReturn) = 0; // tdMethods(deviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { int intErrorNo = TelldusCore::Message::takeInt(&msg); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 3d2a8e28..ae2947b9 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,5 +1,4 @@ #include "DeviceManager.h" -#include "Device.h" #include "Settings.h" #include @@ -38,3 +37,11 @@ void DeviceManager::fillDevices(){ d->devices[id]->setParameter(L"system", set.getDeviceParameter(id, L"system")); } } + +int DeviceManager::getNumberOfDevices(){ + return d->devices.size(); +} + +Device *DeviceManager::getDevice(int deviceId){ + return d->devices[deviceId]; +} diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index e1bf8742..799e68cf 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -1,16 +1,20 @@ #ifndef DEVICEMANAGER_H #define DEVICEMANAGER_H +#include "Device.h" + class DeviceManager { public: DeviceManager(void); ~DeviceManager(void); + int getNumberOfDevices(void); + Device *getDevice(int deviceId); private: void fillDevices(void); - + class PrivateData; PrivateData *d; }; diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 150d66b1..e97077f8 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -29,7 +29,7 @@ void Protocol::setParameters(ParameterMap ¶meterList){ } /** -* This method don't support all locales +* This method doesn't support all locales */ bool Protocol::comparei(std::wstring stringA , std::wstring stringB) { From f6b13ea489fa26d59e5ab2a4e466becb64ad94bc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 09:22:05 +0000 Subject: [PATCH 0289/2215] Added class ControllerManager --- telldus-core/service/CMakeLists.txt | 14 ++++++----- telldus-core/service/ControllerManager.cpp | 28 ++++++++++++++++++++++ telldus-core/service/ControllerManager.h | 17 +++++++++++++ telldus-core/service/TelldusMain.cpp | 6 +++-- 4 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 telldus-core/service/ControllerManager.cpp create mode 100644 telldus-core/service/ControllerManager.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 5961095c..2690a8af 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -5,12 +5,13 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-service_SRCS ClientCommunicationHandler.cpp + Controller.cpp + ControllerManager.cpp + Device.cpp + DeviceManager.cpp Event.cpp Settings.cpp TelldusMain.cpp - DeviceManager.cpp - Device.cpp - Controller.cpp ) SET( telldus-service_protocol_SRCS Protocol.h @@ -21,13 +22,14 @@ SET( telldus-service_protocol_SRCS SET( telldus-service_HDRS ClientCommunicationHandler.h ConnectionListener.h + Controller.h + ControllerManager.h + Device.h + DeviceManager.h Event.h EventHandler.h Settings.h TelldusMain.h - DeviceManager.h - Device.h - Controller.h ) FIND_PACKAGE(Threads) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp new file mode 100644 index 00000000..0a5db84a --- /dev/null +++ b/telldus-core/service/ControllerManager.cpp @@ -0,0 +1,28 @@ +#include "ControllerManager.h" +#include "Controller.h" + +#include + +typedef std::map ControllerMap; + +class ControllerManager::PrivateData { +public: + int lastControllerId; + ControllerMap controllers; +}; + +ControllerManager::ControllerManager(){ + d = new PrivateData; + d->lastControllerId = 0; +} + +ControllerManager::~ControllerManager(void) { + for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + delete( it->second ); + } + delete d; +} + +void ControllerManager::loadControllers() { + //TODO: Do something +} diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h new file mode 100644 index 00000000..e7fe5e63 --- /dev/null +++ b/telldus-core/service/ControllerManager.h @@ -0,0 +1,17 @@ +#ifndef CONTROLLERMANAGER_H +#define CONTROLLERMANAGER_H + +class ControllerManager { +public: + ControllerManager(void); + ~ControllerManager(void); + +protected: + void loadControllers(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CONTROLLERMANAGER_H \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index afab00be..72c8f007 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -3,6 +3,7 @@ #include "EventHandler.h" #include "ClientCommunicationHandler.h" #include "DeviceManager.h" +#include "ControllerManager.h" #include #include @@ -19,8 +20,7 @@ TelldusMain::TelldusMain(void) d->stopEvent = d->eventHandler.addEvent(); } -TelldusMain::~TelldusMain(void) -{ +TelldusMain::~TelldusMain(void) { delete d->stopEvent; delete d; } @@ -29,6 +29,8 @@ void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); DeviceManager deviceManager; + ControllerManager controllerManager; + ConnectionListener clientListener(L"TelldusClient", clientEvent); //TODO: eventlistener From 027b29af9339be58f9e83528d507d6730ce3eace Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 09:22:49 +0000 Subject: [PATCH 0290/2215] Added controller TellStick --- telldus-core/service/CMakeLists.txt | 6 +- telldus-core/service/TellStick.cpp | 384 +++++++++++ telldus-core/service/TellStick.h | 54 ++ telldus-core/service/ftd2xx.h | 15 + telldus-core/service/win/ftd2xx.h | 963 ++++++++++++++++++++++++++++ 5 files changed, 1421 insertions(+), 1 deletion(-) create mode 100644 telldus-core/service/TellStick.cpp create mode 100644 telldus-core/service/TellStick.h create mode 100644 telldus-core/service/ftd2xx.h create mode 100644 telldus-core/service/win/ftd2xx.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 2690a8af..8874ed15 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -12,6 +12,7 @@ SET( telldus-service_SRCS Event.cpp Settings.cpp TelldusMain.cpp + TellStick.cpp ) SET( telldus-service_protocol_SRCS Protocol.h @@ -30,6 +31,7 @@ SET( telldus-service_HDRS EventHandler.h Settings.h TelldusMain.h + TellStick.h ) FIND_PACKAGE(Threads) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) @@ -62,13 +64,15 @@ IF (APPLE) #### Mac OS X #### ELSEIF (WIN32) #### Windows #### SET( telldus-service_TARGET TelldusService ) - ADD_DEFINITIONS( -DUNICODE ) + FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) + ADD_DEFINITIONS( -DUNICODE -DLIBFTD2XX ) ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" ) LIST(APPEND telldus-service_LIBRARIES ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib + ${FTD2XX_LIBRARY} ) LIST(APPEND telldus-service_SRCS ConnectionListener_win.cpp diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp new file mode 100644 index 00000000..132b5bfb --- /dev/null +++ b/telldus-core/service/TellStick.cpp @@ -0,0 +1,384 @@ +// +// C++ Implementation: TellStick +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "TellStick.h" +#include "../client/telldus-core.h" +#include +#include + +class TellStick::TellStickDescriptor { +public: + bool found; + std::string serial; + int vid, pid; +}; + +class TellStick::PrivateData { +public: + bool open; + TellStickHandle ftHandle; + TellStickDescriptor descriptor; +}; + +TellStick::TellStick( const TellStickDescriptor &td ) { + d = new PrivateData; + d->open = false; + d->descriptor = td; + +#ifdef LIBFTDI + ftdi_init(&d->ftHandle); + + int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str()); + if (ret < 0) { + ftdi_deinit(&d->ftHandle); + return; + } + d->open = true; + ftdi_usb_reset( &d->ftHandle ); + ftdi_disable_bitbang( &d->ftHandle ); +#else + + char *tempSerial = new char[td.serial.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempSerial, td.serial.size()+1, td.serial.c_str()); +#else + strcpy(tempSerial, td.serial.c_str()); + FT_SetVIDPID(td.vid, td.pid); +#endif + FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); + delete tempSerial; + if (ftStatus == FT_OK) { + d->open = true; + FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); + FT_SetTimeouts(d->ftHandle,5000,0); + } +#endif + + if (d->open) { + setBaud(4800); + } +} + +TellStick::~TellStick() { + if (d->open) { +#ifdef LIBFTDI + ftdi_usb_close(&d->ftHandle); + ftdi_deinit(&d->ftHandle); +#else + FT_Close(d->ftHandle); +#endif + } + delete d; +} + +int TellStick::vid() const { + return d->descriptor.vid; +} + +int TellStick::pid() const { + return d->descriptor.pid; +} + +std::string TellStick::serial() const { + return d->descriptor.serial; +} + +bool TellStick::open() const { + return d->open; +} + +TellStick *TellStick::findFirstDevice(int vid, int pid) { + TellStick *tellstick = 0; + + if (vid == 0 && pid == 0) { + tellstick = findFirstDevice(0x1781, 0x0C30); + if (tellstick) { + return tellstick; + } +#ifdef TELLSTICK_DUO + tellstick = findFirstDevice(0x1781, 0x0C31); +#endif + return tellstick; + + } + + TellStickDescriptor d = findByVIDPID(vid, pid); + if (d.found) { +#ifdef TELLSTICK_DUO + if (pid == 0x0C31) { + return new TellStickDuo(d); + } +#endif + return new TellStick(d); + } + return 0; +} + +TellStick *TellStick::loadBy(int vid, int pid, const std::string &serial) { + if (vid != 0x1781) { + return 0; + } + + TellStick *tellstick = 0; + + if (serial.length() == 0) { + tellstick = TellStick::findFirstDevice(); + } else { + TellStickDescriptor d; + d.vid = vid; + d.pid = pid; + d.serial = serial; + + if (pid == 0x0C30) { + tellstick = new TellStick(d); +#ifdef TELLSTICK_DUO + } else if (pid == 0x0C31) { + tellstick = new TellStickDuo(d); +#endif + } + } + if (!tellstick) { + return 0; + } + if (tellstick->open()) { + return tellstick; + } + delete tellstick; + return 0; +} + +TellStick::TellStickDescriptor TellStick::findByVIDPID( int vid, int pid ) { + TellStickDescriptor retval; + retval.found = false; + retval.vid = vid; + retval.pid = pid; + +#ifdef LIBFTDI + ftdi_context ftdic; + struct ftdi_device_list *devlist, *curdev; + char serialBuffer[10]; + ftdi_init(&ftdic); + + int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid); + if (ret > 0) { + for (curdev = devlist; curdev != NULL; curdev = curdev->next) { + ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); + if (ret != 0) { + continue; + } + retval.serial = serialBuffer; + break; + } + retval.found = true; + } + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); +#else + FT_HANDLE fthHandle = 0; + FT_STATUS ftStatus = FT_OK; + + try{ + DWORD dwNumberOfDevices = 0; + +#ifndef _WINDOWS + FT_SetVIDPID(vid, pid); +#endif + ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); + if (ftStatus == FT_OK) { + for (int i = 0; i < (int)dwNumberOfDevices; i++) { + + FT_PROGRAM_DATA pData; + char ManufacturerBuf[32]; + char ManufacturerIdBuf[16]; + char DescriptionBuf[64]; + char SerialNumberBuf[16]; + + pData.Signature1 = 0x00000000; + pData.Signature2 = 0xffffffff; + pData.Version = 0x00000002; // EEPROM structure with FT232R extensions + pData.Manufacturer = ManufacturerBuf; + pData.ManufacturerId = ManufacturerIdBuf; + pData.Description = DescriptionBuf; + pData.SerialNumber = SerialNumberBuf; + + ftStatus = FT_Open(i, &fthHandle); + ftStatus = FT_EE_Read(fthHandle, &pData); + if(ftStatus == FT_OK){ + if(pData.VendorId == vid && pData.ProductId == pid){ + ftStatus = FT_Close(fthHandle); + retval.found = true; + retval.serial = pData.SerialNumber; + break; + } + } + ftStatus = FT_Close(fthHandle); + } + } + } + catch(...){ + throw; + } +#endif + return retval; +} + +int TellStick::firmwareVersion() { + return 1; +} + +int TellStick::send(const std::string & strMessage) { + if (!d->open) { + return TELLSTICK_ERROR_NOT_FOUND; + } + + + bool c = true; +#ifdef LIBFTDI + unsigned char *tempMessage = new unsigned char[strMessage.size()]; + memcpy(tempMessage, strMessage.c_str(), strMessage.size()); + + int ret; + ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ; + if(ret < 0) { + c = false; + } else if(ret != strMessage.length()) { + fprintf(stderr, "wierd send length? retval %i instead of %d\n", + ret, (int)strMessage.length()); + } + + delete[] tempMessage; + + int retrycnt = 500; + unsigned char in; + while(c && --retrycnt) { + ret = ftdi_read_data( &d->ftHandle, &in, 1); + if (ret > 0) { + if (in == '\n') { + break; + } + } else if(ret == 0) { // No data available + usleep(100); + } else { //Error + c = false; + } + } + if (!retrycnt) { + c = false; + } +#else + char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); +#ifdef _WINDOWS + strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str()); +#else + strcpy(tempMessage, strMessage.c_str()); +#endif + ULONG bytesWritten, bytesRead; + char in; + FT_STATUS ftStatus; + ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten); + free(tempMessage); + + while(c) { + ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead); + if (ftStatus == FT_OK) { + if (bytesRead == 1) { + if (in == '\n') { + break; + } + } else { //Timeout + c = false; + } + } else { //Error + c = false; + } + } +#endif + + if (!c) { + return TELLSTICK_ERROR_COMMUNICATION; + } + return TELLSTICK_SUCCESS; +} + +void TellStick::setBaud(int baud) { +#ifdef LIBFTDI + int ret = ftdi_set_baudrate(&d->ftHandle, baud); + if(ret != 0) { + fprintf(stderr, "set Baud failed, retval %i\n", ret); + } +#else + FT_SetBaudRate(d->ftHandle, baud); +#endif +} + +TellStickHandle TellStick::handle() const { + return d->ftHandle; +} + +bool TellStick::stillConnected() const { + std::string serial = this->serial(); + +#ifdef LIBFTDI + ftdi_context ftdic; + struct ftdi_device_list *devlist, *curdev; + char serialBuffer[10]; + ftdi_init(&ftdic); + bool found = false; + + int ret = ftdi_usb_find_all(&ftdic, &devlist, this->vid(), this->pid()); + if (ret > 0) { + for (curdev = devlist; curdev != NULL; curdev = curdev->next) { + ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); + if (ret != 0) { + continue; + } + if (serial.compare(serialBuffer) == 0) { + found = true; + break; + } + } + } + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + return found; +#else + FT_STATUS ftStatus; + DWORD numDevs; + // create the device information list + ftStatus = FT_CreateDeviceInfoList(&numDevs); + if (ftStatus != FT_OK) { + return false; + } + if (numDevs <= 0) { + return false; + } + for (int i = 0; i < (int)numDevs; i++) { + FT_HANDLE ftHandleTemp; + DWORD flags; + DWORD id; + DWORD type; + DWORD locId; + char serialNumber[16]; + char description[64]; + // get information for device 0 + ftStatus = FT_GetDeviceInfoDetail(i, &flags, &type, &id, &locId, serialNumber, description, &ftHandleTemp); + if (ftStatus != FT_OK) { + continue; + } + if (serial.compare(serialNumber) == 0) { + return true; + } + } + return false; +#endif +} diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h new file mode 100644 index 00000000..5b51503c --- /dev/null +++ b/telldus-core/service/TellStick.h @@ -0,0 +1,54 @@ +// +// C++ Interface: TellStick +// +// Description: +// +// +// Author: Micke Prag , (C) 2010 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef TELLSTICK_H +#define TELLSTICK_H + +#include "Controller.h" + +#include "ftd2xx.h" +#ifdef LIBFTDI + typedef ftdi_context TellStickHandle; +#else + typedef FT_HANDLE TellStickHandle; +#endif + +class TellStick : public Controller { +public: + virtual ~TellStick(); + + virtual int firmwareVersion(); + virtual int send( const std::string &message ); + + int vid() const; + int pid() const; + std::string serial() const; + bool open() const; + bool stillConnected() const; + + static TellStick *findFirstDevice(int vid = 0, int pid = 0); + static TellStick *loadBy(int vid, int pid, const std::string &serial); + +protected: + class TellStickDescriptor; + + TellStick(const TellStickDescriptor &d); + void setBaud( int baud ); + TellStickHandle handle() const; + +private: + static TellStickDescriptor findByVIDPID( int vid, int pid ); + + class PrivateData; + PrivateData *d; +}; + +#endif diff --git a/telldus-core/service/ftd2xx.h b/telldus-core/service/ftd2xx.h new file mode 100644 index 00000000..f9d7b817 --- /dev/null +++ b/telldus-core/service/ftd2xx.h @@ -0,0 +1,15 @@ + + +#ifdef LIBFTD2XX + #ifdef _WINDOWS + #include + #include "win\ftd2xx.h" + #else + #include "osx/WinTypes.h" + #include "osx/ftd2xx.h" + #endif +#endif + +#ifdef LIBFTDI + #include +#endif diff --git a/telldus-core/service/win/ftd2xx.h b/telldus-core/service/win/ftd2xx.h new file mode 100644 index 00000000..96a4d318 --- /dev/null +++ b/telldus-core/service/win/ftd2xx.h @@ -0,0 +1,963 @@ +/*++ + +Copyright (c) 2001-2007 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB device driver for FTDI FT8U232/245 + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + 23/01/04 awm Added support for open-by-location. + 16/03/04 awm Added support for FT2232C. + 23/09/04 awm Added support for FT232R. + 20/10/04 awm Added FT_CyclePort. + 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. + 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. + 25/08/05 awm Added FT_SetDeadmanTimeout. + 02/12/05 awm Removed obsolete references. + 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. + 08/09/06 awm Added FT_W32_GetCommMask. + 11/09/06 awm Added FT_Rescan. + 11/07/07 awm Added support for FT2232H and FT4232H. + 10/08/07 awm Added flags definitions. + 21/11/07 mja Added FT_GetComPortNumber. + 05/06/08 mja Added EEPROM extensions for FT2232H. + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR, + FT_DEVICE_LIST_NOT_READY, +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_LINE_STATUS 4 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R, + FT_DEVICE_2232H, + FT_DEVICE_4232H +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToRead, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToWrite, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + // 3 = FT2232H extensions + // 4 = FT4232H extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 (FT232B) extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // Rev 5 (FT2232) extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // Rev 6 (FT232R) extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR RIsD2XX; // non-zero if using D2XX driver + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // + // Rev 8 (FT4232H) Extensions + // + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if AL pins have slow slew + UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if AH pins have slow slew + UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if BL pins have slow slew + UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if BH pins have slow slew + UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCTSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommMask( + FT_HANDLE ftHandle, + LPDWORD lpdwEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +// Device information flags +enum { + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 +}; + + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + +FTD2XX_API +FT_STATUS WINAPI FT_Rescan( + void + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Reload( + WORD wVid, + WORD wPid + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetComPortNumber( + FT_HANDLE ftHandle, + LPLONG lpdwComPortNumber + ); + + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + From 93d59e8175165b9815af7b0c92c49fc6a94e3684 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 09:51:31 +0000 Subject: [PATCH 0291/2215] Load the Controllers on startup --- telldus-core/service/ControllerManager.cpp | 26 +++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 0a5db84a..8ab8efb5 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -1,5 +1,6 @@ #include "ControllerManager.h" #include "Controller.h" +#include "TellStick.h" #include @@ -14,6 +15,7 @@ public: ControllerManager::ControllerManager(){ d = new PrivateData; d->lastControllerId = 0; + this->loadControllers(); } ControllerManager::~ControllerManager(void) { @@ -24,5 +26,27 @@ ControllerManager::~ControllerManager(void) { } void ControllerManager::loadControllers() { - //TODO: Do something + while(1) { + TellStick *controller = TellStick::findFirstDevice(); + if (!controller) { + break; //All TellStick loaded + } + //Make sure this isn't already loaded + bool found = false; + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + TellStick *tellstick = reinterpret_cast(it->second); + if (!tellstick) { //No TellStick controller + continue; + } + if (tellstick->serial().compare(controller->serial()) == 0) { //Found a duplicate + found = true; + break; + } + } + if (found) { + break; + } + d->lastControllerId--; + d->controllers[d->lastControllerId] = controller; + } } From 640c6b12f7ccad5d91a0fedf46cd40c9b3056928 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 09:56:26 +0000 Subject: [PATCH 0292/2215] Added function ControllerManager::getBestControllerById() --- telldus-core/service/ControllerManager.cpp | 4 ++++ telldus-core/service/ControllerManager.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 8ab8efb5..0a27b648 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -25,6 +25,10 @@ ControllerManager::~ControllerManager(void) { delete d; } +Controller *ControllerManager::getBestControllerById(int id) { + return 0; +} + void ControllerManager::loadControllers() { while(1) { TellStick *controller = TellStick::findFirstDevice(); diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index e7fe5e63..4b49d198 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -1,11 +1,15 @@ #ifndef CONTROLLERMANAGER_H #define CONTROLLERMANAGER_H +class Controller; + class ControllerManager { public: ControllerManager(void); ~ControllerManager(void); + Controller *getBestControllerById(int id); + protected: void loadControllers(); From 9a668db847a11bed213714557c57b8eba4f14e20 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 09:58:15 +0000 Subject: [PATCH 0293/2215] Implemented ControllerManager::getBestControllerById() --- telldus-core/service/ControllerManager.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 0a27b648..461aa741 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -26,7 +26,15 @@ ControllerManager::~ControllerManager(void) { } Controller *ControllerManager::getBestControllerById(int id) { - return 0; + if (!d->controllers.size()) { + return 0; + } + ControllerMap::iterator it = d->controllers.find(id); + if (it != d->controllers.end()) { + return it->second; + } + return d->controllers.begin()->second; + } void ControllerManager::loadControllers() { From 0f8f381b94b5dbda2e59c6edd00b4255898f425f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 10:28:18 +0000 Subject: [PATCH 0294/2215] Test the returned value from libconfuse. Else we risk a crash --- telldus-core/service/SettingsConfuse.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 7899f666..694f800b 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -235,7 +235,11 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam if (parameter) { cfg_device = cfg_getsec(cfg_device, "parameters"); } - std::string setting(cfg_getstr(cfg_device, std::string(name.begin(), name.end()).c_str())); + std::string setting; + char *cSetting = cfg_getstr(cfg_device, std::string(name.begin(), name.end()).c_str()); + if (cSetting) { + setting = cSetting; + } return std::wstring(setting.begin(), setting.end()); } } From 9dc2aff5205772bca23add17f21e21adaba7e17a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 10:28:53 +0000 Subject: [PATCH 0295/2215] Include stdio.h --- telldus-core/service/TellStick.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index 132b5bfb..0d4b2897 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -13,6 +13,7 @@ #include "../client/telldus-core.h" #include #include +#include class TellStick::TellStickDescriptor { public: From b2a6c46ceaa9e8245f8b115168e31f95f2bdc339 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 10:29:26 +0000 Subject: [PATCH 0296/2215] Link against libftdi in Linux --- telldus-core/service/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 8874ed15..423a03d1 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -88,7 +88,8 @@ ELSEIF (WIN32) #### Windows #### ELSE (APPLE) #### Linux #### FIND_LIBRARY(CONFUSE_LIBRARY confuse) - ADD_DEFINITIONS( -D_CONFUSE ) + FIND_LIBRARY(FTDI_LIBRARY ftdi) + ADD_DEFINITIONS( -D_CONFUSE -DLIBFTDI ) SET( telldus-service_TARGET telldusd ) LIST(APPEND telldus-service_SRCS @@ -100,6 +101,7 @@ ELSE (APPLE) #### Linux #### ) LIST(APPEND telldus-service_LIBRARIES ${CONFUSE_LIBRARY} + ${FTDI_LIBRARY} telldus-common ) ENDIF (APPLE) From eeaeefe61d39eefbc96d2cdb5613bba6e06ae542 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 10:30:39 +0000 Subject: [PATCH 0297/2215] "TurnOn"-flow implemented until protocol. --- .../service/ClientCommunicationHandler.cpp | 15 ++++++++++++--- .../service/ClientCommunicationHandler.h | 3 ++- telldus-core/service/Device.cpp | 17 +++++++++++------ telldus-core/service/DeviceManager.cpp | 11 +++++++---- telldus-core/service/Protocol.cpp | 9 +++++---- telldus-core/service/TelldusMain.cpp | 2 +- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index dc6476ee..bf0cfb52 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -7,13 +7,14 @@ public: Event *event; bool done; DeviceManager *deviceManager; + ControllerManager *controllerManager; }; ClientCommunicationHandler::ClientCommunicationHandler(){ } -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, ControllerManager *controllerManager) :Thread() { d = new PrivateData; @@ -21,6 +22,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie d->event = event; d->done = false; d->deviceManager = deviceManager; + d->controllerManager = controllerManager; } @@ -72,8 +74,15 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); + //TODO Lock controller? + Controller *controller = d->controllerManager->getBestControllerById(0); //TODO: Lock device - //TODO: (*intReturn) = d->deviceManager->getDevice(deviceId)->turnOn(); //Controller... + if(controller){ + (*intReturn) = d->deviceManager->getDevice(deviceId)->turnOn(controller); //TODO: Choose correct controller and check for none + } + else{ + (*intReturn) = 0; + } //TODO: Unlock //(*intReturn) = 0; //tdTurnOn(deviceId); @@ -175,7 +184,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdMethods(deviceId, intMethodsSupported); + (*intReturn) = 1; // tdMethods(deviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { int intErrorNo = TelldusCore::Message::takeInt(&msg); diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index fbb0e1b2..eed52e86 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -6,12 +6,13 @@ #include "Socket.h" #include "Event.h" #include "DeviceManager.h" +#include "ControllerManager.h" class ClientCommunicationHandler : public TelldusCore::Thread { public: ClientCommunicationHandler(); - ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager); + ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, ControllerManager *controllerManager); ~ClientCommunicationHandler(void); bool isDone(); diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 734c9871..a745a90d 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -67,9 +67,10 @@ void Device::setProtocolName(const std::wstring &protocolName){ int Device::turnOn(Controller *controller) { Protocol *p = this->retrieveProtocol(); - - //p->turnOn(controller); - //TODO: Handle p + if(p){ + //p->turnOn(controller); + } + //TODO: Handle p (shared_ptr?) return 0; } @@ -79,7 +80,11 @@ Protocol* Device::retrieveProtocol() { } d->protocol = Protocol::getProtocolInstance(d->protocolName); - d->protocol->setModel(d->model); - d->protocol->setParameters(d->parameterList); - return d->protocol; + if(d->protocol){ + d->protocol->setModel(d->model); + d->protocol->setParameters(d->parameterList); + return d->protocol; + } + + return 0; } \ No newline at end of file diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index ae2947b9..93e4d233 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -3,9 +3,11 @@ #include +typedef std::map DeviceMap; + class DeviceManager::PrivateData { public: - std::map devices; + DeviceMap devices; }; DeviceManager::DeviceManager(){ @@ -14,8 +16,9 @@ DeviceManager::DeviceManager(){ } DeviceManager::~DeviceManager(void) { - //delete d->devices; - //todo: delete devices + for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { + delete( it->second ); + } delete d; } @@ -43,5 +46,5 @@ int DeviceManager::getNumberOfDevices(){ } Device *DeviceManager::getDevice(int deviceId){ - return d->devices[deviceId]; + return d->devices[deviceId]; //TODO } diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index e97077f8..dc8d30fa 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -43,9 +43,9 @@ bool Protocol::comparei(std::wstring stringA , std::wstring stringB) Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ //TODO: tr1:shared_ptr... - Protocol *prot; + //Protocol *prot; if(comparei(protocolname, L"arctech")){ //TODO: Test this - prot = new ProtocolNexa(); + return new ProtocolNexa(); //((ProtocolNexa*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); //todo: try to do this in ProtocolNexa instead //((ProtocolNexa*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); @@ -104,7 +104,8 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } */ - - return prot; //TODO can be null + else{ + return 0; //TODO can be null + } } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 72c8f007..970d5193 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -46,7 +46,7 @@ void TelldusMain::start(void) { ConnectionListenerEventData *data = reinterpret_cast(eventData); if (data) { Event *handlerEvent = d->eventHandler.addEvent(); - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, &controllerManager); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } From 5a868716a95a44057c4e6d8d7fce95fe7b883dc0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 10:44:01 +0000 Subject: [PATCH 0298/2215] Fixed case in filename --- telldus-core/service/Protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index dc8d30fa..0bc07405 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,4 +1,4 @@ -#include "protocol.h" +#include "Protocol.h" #include "Settings.h" #include "ProtocolNexa.h" From ec0d0596825e402a6d1a6d691c0c8d30e216a509 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 10:45:03 +0000 Subject: [PATCH 0299/2215] Bug fix and possible future error prevention --- telldus-core/service/Device.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index a745a90d..2b773bf5 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -16,7 +16,7 @@ Device::Device(){ Device::Device(int id){ d = new PrivateData; - + d->protocol = 0; //när något uppdateras, spara också till registret //obs, alla hantera om alla värden inte är satta } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 93e4d233..410e117f 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -46,5 +46,13 @@ int DeviceManager::getNumberOfDevices(){ } Device *DeviceManager::getDevice(int deviceId){ - return d->devices[deviceId]; //TODO + + if (!d->devices.size()) { + return 0; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + return it->second; + } + return 0; //not found } From 78dddd7ab3a0a93ecede88d564de17eb684695fc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 10:51:02 +0000 Subject: [PATCH 0300/2215] Removed empty constructor --- telldus-core/service/Device.cpp | 3 --- telldus-core/service/Device.h | 3 +-- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 2b773bf5..25275284 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -11,9 +11,6 @@ public: Protocol *protocol; }; -Device::Device(){ -} - Device::Device(int id){ d = new PrivateData; d->protocol = 0; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 21b87efa..7193900d 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -8,7 +8,6 @@ class Device { public: - Device(); Device(int id); ~Device(void); @@ -32,4 +31,4 @@ private: PrivateData *d; }; -#endif //DEVICE_H \ No newline at end of file +#endif //DEVICE_H From 7cfc12d8fa5dcfa4fa72743c80b0923ac324abe6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 11:39:57 +0000 Subject: [PATCH 0301/2215] Code cleanup, warning removed. --- telldus-core/service/Device.cpp | 3 +-- telldus-core/service/DeviceManager.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 25275284..0a7e63f3 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -15,7 +15,7 @@ Device::Device(int id){ d = new PrivateData; d->protocol = 0; //när något uppdateras, spara också till registret - //obs, alla hantera om alla värden inte är satta + //obs, kunna hantera om alla värden inte är satta } Device::~Device(void) { @@ -67,7 +67,6 @@ int Device::turnOn(Controller *controller) { if(p){ //p->turnOn(controller); } - //TODO: Handle p (shared_ptr?) return 0; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 410e117f..4fcc1000 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -42,7 +42,7 @@ void DeviceManager::fillDevices(){ } int DeviceManager::getNumberOfDevices(){ - return d->devices.size(); + return (int)d->devices.size(); } Device *DeviceManager::getDevice(int deviceId){ From 008feec1c3d3b5288b351f6bf3b0f02a46f47c60 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 12:23:01 +0000 Subject: [PATCH 0302/2215] Rewrote the TellStick controller --- telldus-core/service/CMakeLists.txt | 2 +- telldus-core/service/ControllerManager.cpp | 29 +- telldus-core/service/TellStick.cpp | 385 --------------------- telldus-core/service/TellStick.h | 34 +- telldus-core/service/TellStick_libftdi.cpp | 104 ++++++ 5 files changed, 128 insertions(+), 426 deletions(-) delete mode 100644 telldus-core/service/TellStick.cpp create mode 100644 telldus-core/service/TellStick_libftdi.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 423a03d1..97e1e639 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -12,7 +12,6 @@ SET( telldus-service_SRCS Event.cpp Settings.cpp TelldusMain.cpp - TellStick.cpp ) SET( telldus-service_protocol_SRCS Protocol.h @@ -98,6 +97,7 @@ ELSE (APPLE) #### Linux #### EventHandler_unix.cpp main_unix.cpp SettingsConfuse.cpp + TellStick_libftdi.cpp ) LIST(APPEND telldus-service_LIBRARIES ${CONFUSE_LIBRARY} diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 461aa741..996b2e56 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -3,6 +3,7 @@ #include "TellStick.h" #include +#include typedef std::map ControllerMap; @@ -38,27 +39,17 @@ Controller *ControllerManager::getBestControllerById(int id) { } void ControllerManager::loadControllers() { - while(1) { - TellStick *controller = TellStick::findFirstDevice(); - if (!controller) { - break; //All TellStick loaded - } - //Make sure this isn't already loaded - bool found = false; - for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - TellStick *tellstick = reinterpret_cast(it->second); - if (!tellstick) { //No TellStick controller - continue; - } - if (tellstick->serial().compare(controller->serial()) == 0) { //Found a duplicate - found = true; - break; - } - } - if (found) { - break; + std::list list = TellStick::findAll(); + std::list::iterator it = list.begin(); + for(; it != list.end(); ++it) { + printf("Found (%i/%i): %s\n", (*it).vid, (*it).pid, (*it).serial.c_str()); + TellStick *controller = new TellStick(*it); + if (!controller->isOpen()) { + delete controller; + continue; } d->lastControllerId--; d->controllers[d->lastControllerId] = controller; } + printf("List containing %i controllers\n", (int)d->controllers.size()); } diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp deleted file mode 100644 index 0d4b2897..00000000 --- a/telldus-core/service/TellStick.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// -// C++ Implementation: TellStick -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "TellStick.h" -#include "../client/telldus-core.h" -#include -#include -#include - -class TellStick::TellStickDescriptor { -public: - bool found; - std::string serial; - int vid, pid; -}; - -class TellStick::PrivateData { -public: - bool open; - TellStickHandle ftHandle; - TellStickDescriptor descriptor; -}; - -TellStick::TellStick( const TellStickDescriptor &td ) { - d = new PrivateData; - d->open = false; - d->descriptor = td; - -#ifdef LIBFTDI - ftdi_init(&d->ftHandle); - - int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str()); - if (ret < 0) { - ftdi_deinit(&d->ftHandle); - return; - } - d->open = true; - ftdi_usb_reset( &d->ftHandle ); - ftdi_disable_bitbang( &d->ftHandle ); -#else - - char *tempSerial = new char[td.serial.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempSerial, td.serial.size()+1, td.serial.c_str()); -#else - strcpy(tempSerial, td.serial.c_str()); - FT_SetVIDPID(td.vid, td.pid); -#endif - FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); - delete tempSerial; - if (ftStatus == FT_OK) { - d->open = true; - FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); - FT_SetTimeouts(d->ftHandle,5000,0); - } -#endif - - if (d->open) { - setBaud(4800); - } -} - -TellStick::~TellStick() { - if (d->open) { -#ifdef LIBFTDI - ftdi_usb_close(&d->ftHandle); - ftdi_deinit(&d->ftHandle); -#else - FT_Close(d->ftHandle); -#endif - } - delete d; -} - -int TellStick::vid() const { - return d->descriptor.vid; -} - -int TellStick::pid() const { - return d->descriptor.pid; -} - -std::string TellStick::serial() const { - return d->descriptor.serial; -} - -bool TellStick::open() const { - return d->open; -} - -TellStick *TellStick::findFirstDevice(int vid, int pid) { - TellStick *tellstick = 0; - - if (vid == 0 && pid == 0) { - tellstick = findFirstDevice(0x1781, 0x0C30); - if (tellstick) { - return tellstick; - } -#ifdef TELLSTICK_DUO - tellstick = findFirstDevice(0x1781, 0x0C31); -#endif - return tellstick; - - } - - TellStickDescriptor d = findByVIDPID(vid, pid); - if (d.found) { -#ifdef TELLSTICK_DUO - if (pid == 0x0C31) { - return new TellStickDuo(d); - } -#endif - return new TellStick(d); - } - return 0; -} - -TellStick *TellStick::loadBy(int vid, int pid, const std::string &serial) { - if (vid != 0x1781) { - return 0; - } - - TellStick *tellstick = 0; - - if (serial.length() == 0) { - tellstick = TellStick::findFirstDevice(); - } else { - TellStickDescriptor d; - d.vid = vid; - d.pid = pid; - d.serial = serial; - - if (pid == 0x0C30) { - tellstick = new TellStick(d); -#ifdef TELLSTICK_DUO - } else if (pid == 0x0C31) { - tellstick = new TellStickDuo(d); -#endif - } - } - if (!tellstick) { - return 0; - } - if (tellstick->open()) { - return tellstick; - } - delete tellstick; - return 0; -} - -TellStick::TellStickDescriptor TellStick::findByVIDPID( int vid, int pid ) { - TellStickDescriptor retval; - retval.found = false; - retval.vid = vid; - retval.pid = pid; - -#ifdef LIBFTDI - ftdi_context ftdic; - struct ftdi_device_list *devlist, *curdev; - char serialBuffer[10]; - ftdi_init(&ftdic); - - int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid); - if (ret > 0) { - for (curdev = devlist; curdev != NULL; curdev = curdev->next) { - ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); - if (ret != 0) { - continue; - } - retval.serial = serialBuffer; - break; - } - retval.found = true; - } - - ftdi_list_free(&devlist); - ftdi_deinit(&ftdic); -#else - FT_HANDLE fthHandle = 0; - FT_STATUS ftStatus = FT_OK; - - try{ - DWORD dwNumberOfDevices = 0; - -#ifndef _WINDOWS - FT_SetVIDPID(vid, pid); -#endif - ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); - if (ftStatus == FT_OK) { - for (int i = 0; i < (int)dwNumberOfDevices; i++) { - - FT_PROGRAM_DATA pData; - char ManufacturerBuf[32]; - char ManufacturerIdBuf[16]; - char DescriptionBuf[64]; - char SerialNumberBuf[16]; - - pData.Signature1 = 0x00000000; - pData.Signature2 = 0xffffffff; - pData.Version = 0x00000002; // EEPROM structure with FT232R extensions - pData.Manufacturer = ManufacturerBuf; - pData.ManufacturerId = ManufacturerIdBuf; - pData.Description = DescriptionBuf; - pData.SerialNumber = SerialNumberBuf; - - ftStatus = FT_Open(i, &fthHandle); - ftStatus = FT_EE_Read(fthHandle, &pData); - if(ftStatus == FT_OK){ - if(pData.VendorId == vid && pData.ProductId == pid){ - ftStatus = FT_Close(fthHandle); - retval.found = true; - retval.serial = pData.SerialNumber; - break; - } - } - ftStatus = FT_Close(fthHandle); - } - } - } - catch(...){ - throw; - } -#endif - return retval; -} - -int TellStick::firmwareVersion() { - return 1; -} - -int TellStick::send(const std::string & strMessage) { - if (!d->open) { - return TELLSTICK_ERROR_NOT_FOUND; - } - - - bool c = true; -#ifdef LIBFTDI - unsigned char *tempMessage = new unsigned char[strMessage.size()]; - memcpy(tempMessage, strMessage.c_str(), strMessage.size()); - - int ret; - ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ; - if(ret < 0) { - c = false; - } else if(ret != strMessage.length()) { - fprintf(stderr, "wierd send length? retval %i instead of %d\n", - ret, (int)strMessage.length()); - } - - delete[] tempMessage; - - int retrycnt = 500; - unsigned char in; - while(c && --retrycnt) { - ret = ftdi_read_data( &d->ftHandle, &in, 1); - if (ret > 0) { - if (in == '\n') { - break; - } - } else if(ret == 0) { // No data available - usleep(100); - } else { //Error - c = false; - } - } - if (!retrycnt) { - c = false; - } -#else - char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); -#ifdef _WINDOWS - strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str()); -#else - strcpy(tempMessage, strMessage.c_str()); -#endif - ULONG bytesWritten, bytesRead; - char in; - FT_STATUS ftStatus; - ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten); - free(tempMessage); - - while(c) { - ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead); - if (ftStatus == FT_OK) { - if (bytesRead == 1) { - if (in == '\n') { - break; - } - } else { //Timeout - c = false; - } - } else { //Error - c = false; - } - } -#endif - - if (!c) { - return TELLSTICK_ERROR_COMMUNICATION; - } - return TELLSTICK_SUCCESS; -} - -void TellStick::setBaud(int baud) { -#ifdef LIBFTDI - int ret = ftdi_set_baudrate(&d->ftHandle, baud); - if(ret != 0) { - fprintf(stderr, "set Baud failed, retval %i\n", ret); - } -#else - FT_SetBaudRate(d->ftHandle, baud); -#endif -} - -TellStickHandle TellStick::handle() const { - return d->ftHandle; -} - -bool TellStick::stillConnected() const { - std::string serial = this->serial(); - -#ifdef LIBFTDI - ftdi_context ftdic; - struct ftdi_device_list *devlist, *curdev; - char serialBuffer[10]; - ftdi_init(&ftdic); - bool found = false; - - int ret = ftdi_usb_find_all(&ftdic, &devlist, this->vid(), this->pid()); - if (ret > 0) { - for (curdev = devlist; curdev != NULL; curdev = curdev->next) { - ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); - if (ret != 0) { - continue; - } - if (serial.compare(serialBuffer) == 0) { - found = true; - break; - } - } - } - - ftdi_list_free(&devlist); - ftdi_deinit(&ftdic); - return found; -#else - FT_STATUS ftStatus; - DWORD numDevs; - // create the device information list - ftStatus = FT_CreateDeviceInfoList(&numDevs); - if (ftStatus != FT_OK) { - return false; - } - if (numDevs <= 0) { - return false; - } - for (int i = 0; i < (int)numDevs; i++) { - FT_HANDLE ftHandleTemp; - DWORD flags; - DWORD id; - DWORD type; - DWORD locId; - char serialNumber[16]; - char description[64]; - // get information for device 0 - ftStatus = FT_GetDeviceInfoDetail(i, &flags, &type, &id, &locId, serialNumber, description, &ftHandleTemp); - if (ftStatus != FT_OK) { - continue; - } - if (serial.compare(serialNumber) == 0) { - return true; - } - } - return false; -#endif -} diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 5b51503c..c8b1f228 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -13,39 +13,31 @@ #define TELLSTICK_H #include "Controller.h" +#include -#include "ftd2xx.h" -#ifdef LIBFTDI - typedef ftdi_context TellStickHandle; -#else - typedef FT_HANDLE TellStickHandle; -#endif +class TellStickDescriptor { +public: + std::string serial; + int vid, pid; +}; class TellStick : public Controller { public: + TellStick(const TellStickDescriptor &d); virtual ~TellStick(); virtual int firmwareVersion(); + bool isOpen() const; virtual int send( const std::string &message ); - - int vid() const; - int pid() const; - std::string serial() const; - bool open() const; - bool stillConnected() const; - - static TellStick *findFirstDevice(int vid = 0, int pid = 0); - static TellStick *loadBy(int vid, int pid, const std::string &serial); + + static std::list findAll(); protected: - class TellStickDescriptor; - - TellStick(const TellStickDescriptor &d); void setBaud( int baud ); - TellStickHandle handle() const; - + + private: - static TellStickDescriptor findByVIDPID( int vid, int pid ); + static std::list findAllByVIDPID( int vid, int pid ); class PrivateData; PrivateData *d; diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp new file mode 100644 index 00000000..a42247de --- /dev/null +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -0,0 +1,104 @@ +// +// C++ Implementation: TellStick +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "TellStick.h" +#include "../client/telldus-core.h" +#include +#include +#include + +#include + +class TellStick::PrivateData { +public: + bool open; + ftdi_context ftHandle; +}; + +TellStick::TellStick( const TellStickDescriptor &td ) { + d = new PrivateData; + d->open = false; + + ftdi_init(&d->ftHandle); + + int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str()); + if (ret < 0) { + ftdi_deinit(&d->ftHandle); + return; + } + d->open = true; + ftdi_usb_reset( &d->ftHandle ); + ftdi_disable_bitbang( &d->ftHandle ); + + if (d->open) { +// setBaud(4800); + } +} + +TellStick::~TellStick() { + if (d->open) { + ftdi_usb_close(&d->ftHandle); + ftdi_deinit(&d->ftHandle); + } + delete d; +} + +int TellStick::firmwareVersion() { + return 1; +} + +bool TellStick::isOpen() const { + return d->open; +} + +int TellStick::send( const std::string &message ) { + return TELLSTICK_SUCCESS; +} + +std::list TellStick::findAll() { + std::list tellstick = findAllByVIDPID(0x1781, 0x0C30); + + std::list duo = findAllByVIDPID(0x1781, 0x0C31); + for(std::list::const_iterator it = duo.begin(); it != duo.end(); ++it) { + tellstick.push_back(*it); + } + + return tellstick; + +} + +std::list TellStick::findAllByVIDPID( int vid, int pid ) { + std::list retval; + + ftdi_context ftdic; + struct ftdi_device_list *devlist, *curdev; + char serialBuffer[10]; + ftdi_init(&ftdic); + + int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid); + if (ret > 0) { + for (curdev = devlist; curdev != NULL; curdev = curdev->next) { + ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); + if (ret != 0) { + continue; + } + TellStickDescriptor td; + td.vid = vid; + td.pid = pid; + td.serial = serialBuffer; + retval.push_back(td); + } + } + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + + return retval; +} From 6580e98135650aa6a76b9bb6e9b4a694e278fe09 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 12:33:19 +0000 Subject: [PATCH 0303/2215] Device setting PreferredControllerId introduced --- .../service/ClientCommunicationHandler.cpp | 8 ++++---- telldus-core/service/Device.cpp | 14 +++++++++++--- telldus-core/service/Device.h | 3 ++- telldus-core/service/DeviceManager.cpp | 1 + telldus-core/service/Protocol.cpp | 6 ++---- telldus-core/service/Settings.cpp | 14 ++++++++++++++ telldus-core/service/Settings.h | 4 +++- 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index bf0cfb52..01b1cc26 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -74,11 +74,11 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); - //TODO Lock controller? - Controller *controller = d->controllerManager->getBestControllerById(0); - //TODO: Lock device + //TODO Lock controller and device? + Controller *controller = d->controllerManager->getBestControllerById(d->deviceManager->getDevice(deviceId)->getPreferredControllerId()); //TODO: Get controller id... + //TODO: Lock device? if(controller){ - (*intReturn) = d->deviceManager->getDevice(deviceId)->turnOn(controller); //TODO: Choose correct controller and check for none + (*intReturn) = d->deviceManager->getDevice(deviceId)->turnOn(controller); } else{ (*intReturn) = 0; diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 0a7e63f3..2fb4e97c 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -3,12 +3,12 @@ class Device::PrivateData { public: - std::wstring name; std::wstring model; - std::wstring protocolName; + std::wstring name; ParameterMap parameterList; - Protocol *protocol; + std::wstring protocolName; + int preferredControllerId; }; Device::Device(int id){ @@ -50,6 +50,14 @@ void Device::setParameter(const std::wstring &key, const std::wstring &value){ d->parameterList[key] = value; } +int Device::getPreferredControllerId(){ + return d->preferredControllerId; +} + +void Device::setPreferredControllerId(int controllerId){ + d->preferredControllerId = controllerId; +} + std::wstring Device::getProtocolName(){ return d->protocolName; } diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 7193900d..74d6d35b 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -17,10 +17,11 @@ public: void setName(const std::wstring &name); std::wstring getParameter(const std::wstring &key); void setParameter(const std::wstring &key, const std::wstring &value); + int getPreferredControllerId(); + void setPreferredControllerId(int controllerId); std::wstring getProtocolName(); void setProtocolName(const std::wstring &name); - int turnOn(Controller *controller); private: diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 4fcc1000..57b3d6c4 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -32,6 +32,7 @@ void DeviceManager::fillDevices(){ d->devices[id]->setName(set.getName(id)); d->devices[id]->setModel(set.getModel(id)); d->devices[id]->setProtocolName(set.getProtocol(id)); + d->devices[id]->setPreferredControllerId(set.getPreferredControllerId(id)); d->devices[id]->setParameter(L"house", set.getDeviceParameter(id, L"house")); d->devices[id]->setParameter(L"unit", set.getDeviceParameter(id, L"unit")); d->devices[id]->setParameter(L"code", set.getDeviceParameter(id, L"code")); diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 0bc07405..820177d3 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -42,11 +42,9 @@ bool Protocol::comparei(std::wstring stringA , std::wstring stringB) Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ - //TODO: tr1:shared_ptr... - //Protocol *prot; if(comparei(protocolname, L"arctech")){ //TODO: Test this return new ProtocolNexa(); - //((ProtocolNexa*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); //todo: try to do this in ProtocolNexa instead + //((ProtocolNexa*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); //((ProtocolNexa*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); } @@ -105,7 +103,7 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } */ else{ - return 0; //TODO can be null + return 0; } } diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index d6c32039..219324eb 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -56,6 +56,20 @@ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &s return getStringSetting(intDeviceId, strName, true); } +/* +* Set preferred controller id +*/ +bool Settings::setPreferredControllerId(int intDeviceId, int value){ + return setIntSetting(intDeviceId, L"controllerId", value, false); +} + +/* +* Get preferred controller id +*/ +int Settings::getPreferredControllerId(int intDeviceId) { + return getIntSetting(intDeviceId, L"controllerId", false); +} + #ifndef _CONFUSE bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 7858fb1a..f8be01f2 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -21,7 +21,9 @@ public: bool setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); int getDeviceState( int intDeviceId ) const; std::wstring getDeviceStateValue( int intDeviceId ) const; - + int getPreferredControllerId(int intDeviceId); + bool setPreferredControllerId(int intDeviceId, int value); + int addDevice(); int getDeviceId(int intDeviceIndex) const; bool removeDevice(int intDeviceId); From 845bb9318509a29eab912ad0419b7fd980993ad5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 12:41:24 +0000 Subject: [PATCH 0304/2215] Added stubs for TellStick controller in Windows --- telldus-core/service/CMakeLists.txt | 1 + telldus-core/service/TellStick_ftd2xx.cpp | 68 +++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 telldus-core/service/TellStick_ftd2xx.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 97e1e639..4955600b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -80,6 +80,7 @@ ELSEIF (WIN32) #### Windows #### main_win.cpp SettingsWinRegistry.cpp TelldusWinService_win.cpp + TellStick_ftd2xx.cpp ) LIST(APPEND telldus-service_HDRS TelldusWinService_win.h diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp new file mode 100644 index 00000000..c7c96296 --- /dev/null +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -0,0 +1,68 @@ +// +// C++ Implementation: TellStick +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "TellStick.h" +#include "../client/telldus-core.h" +#include + +#include "ftd2xx.h" + +class TellStick::PrivateData { +public: + bool open; + FT_HANDLE ftHandle; +}; + +TellStick::TellStick( const TellStickDescriptor &td ) { + d = new PrivateData; + d->open = false; + + if (d->open) { +// setBaud(4800); + } +} + +TellStick::~TellStick() { + if (d->open) { + } + delete d; +} + +int TellStick::firmwareVersion() { + return 1; +} + +bool TellStick::isOpen() const { + return d->open; +} + +int TellStick::send( const std::string &message ) { + return TELLSTICK_SUCCESS; +} + +std::list TellStick::findAll() { + std::list tellstick = findAllByVIDPID(0x1781, 0x0C30); + + std::list duo = findAllByVIDPID(0x1781, 0x0C31); + for(std::list::const_iterator it = duo.begin(); it != duo.end(); ++it) { + tellstick.push_back(*it); + } + + return tellstick; + +} + +std::list TellStick::findAllByVIDPID( int vid, int pid ) { + std::list retval; + + + return retval; +} From 9f0e3adbdca1d04a8cc2234315bdcf3e2ab582f8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 12:55:19 +0000 Subject: [PATCH 0305/2215] Implemented TellStick::findAllByVIDPID() on Windows --- telldus-core/service/TellStick_ftd2xx.cpp | 40 +++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index c7c96296..e0291cd6 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -63,6 +63,46 @@ std::list TellStick::findAll() { std::list TellStick::findAllByVIDPID( int vid, int pid ) { std::list retval; + FT_HANDLE fthHandle = 0; + FT_STATUS ftStatus = FT_OK; + DWORD dwNumberOfDevices = 0; +#ifndef _WINDOWS + FT_SetVIDPID(vid, pid); +#endif + + ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices); + if (ftStatus != FT_OK) { + return retval; + } + for (int i = 0; i < (int)dwNumberOfDevices; i++) { + FT_PROGRAM_DATA pData; + char ManufacturerBuf[32]; + char ManufacturerIdBuf[16]; + char DescriptionBuf[64]; + char SerialNumberBuf[16]; + + pData.Signature1 = 0x00000000; + pData.Signature2 = 0xffffffff; + pData.Version = 0x00000002; // EEPROM structure with FT232R extensions + pData.Manufacturer = ManufacturerBuf; + pData.ManufacturerId = ManufacturerIdBuf; + pData.Description = DescriptionBuf; + pData.SerialNumber = SerialNumberBuf; + + ftStatus = FT_Open(i, &fthHandle); + ftStatus = FT_EE_Read(fthHandle, &pData); + ftStatus = FT_Close(fthHandle); + if (ftStatus != FT_OK) { + continue; + } + if (pData.VendorId == vid && pData.ProductId == pid) { + TellStickDescriptor td; + td.vid = vid; + td.pid = pid; + td.serial = pData.SerialNumber; + retval.push_back(td); + } + } return retval; } From c528550b1ed3ce989c3cb757729fe9fb118e43e3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 13:10:26 +0000 Subject: [PATCH 0306/2215] Implemented TellStick::send() on Windows. --- telldus-core/service/TellStick_ftd2xx.cpp | 59 ++++++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index e0291cd6..c9ae97a4 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -24,9 +24,24 @@ public: TellStick::TellStick( const TellStickDescriptor &td ) { d = new PrivateData; d->open = false; + + char *tempSerial = new char[td.serial.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempSerial, td.serial.size()+1, td.serial.c_str()); +#else + strcpy(tempSerial, td.serial.c_str()); + FT_SetVIDPID(td.vid, td.pid); +#endif + FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); + delete tempSerial; + if (ftStatus == FT_OK) { + d->open = true; + FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); + FT_SetTimeouts(d->ftHandle,5000,0); + } if (d->open) { -// setBaud(4800); + setBaud(4800); } } @@ -36,6 +51,10 @@ TellStick::~TellStick() { delete d; } +void TellStick::setBaud( int baud ) { + FT_SetBaudRate(d->ftHandle, baud); +} + int TellStick::firmwareVersion() { return 1; } @@ -44,7 +63,43 @@ bool TellStick::isOpen() const { return d->open; } -int TellStick::send( const std::string &message ) { +int TellStick::send( const std::string &strMessage ) { + if (!d->open) { + return TELLSTICK_ERROR_NOT_FOUND; + } + bool c = true; + + char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); +#ifdef _WINDOWS + strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str()); +#else + strcpy(tempMessage, strMessage.c_str()); +#endif + + ULONG bytesWritten, bytesRead; + char in; + FT_STATUS ftStatus; + ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten); + free(tempMessage); + + while(c) { + ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead); + if (ftStatus == FT_OK) { + if (bytesRead == 1) { + if (in == '\n') { + break; + } + } else { //Timeout + c = false; + } + } else { //Error + c = false; + } + } + + if (!c) { + return TELLSTICK_ERROR_COMMUNICATION; + } return TELLSTICK_SUCCESS; } From 26874c05b2362be6c10a2ba6040ae7fd081148eb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 13:12:18 +0000 Subject: [PATCH 0307/2215] Different baud for TellStick Classic/Duo --- telldus-core/service/TellStick_ftd2xx.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index c9ae97a4..1f285130 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -41,7 +41,11 @@ TellStick::TellStick( const TellStickDescriptor &td ) { } if (d->open) { - setBaud(4800); + if (td.pid == 0x0C31) { + setBaud(9600); + } else { + setBaud(4800); + } } } From b4187a895d5946c5b33e46a959ff40d68e1fb847 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 13:19:51 +0000 Subject: [PATCH 0308/2215] Implemented protocol methods --- telldus-core/service/Protocol.cpp | 21 +++++++++++++++++++++ telldus-core/service/Protocol.h | 10 +++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 820177d3..d73e85c9 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,5 +1,6 @@ #include "Protocol.h" #include "Settings.h" +#include "../client/telldus-core.h" #include "ProtocolNexa.h" #include @@ -28,6 +29,26 @@ void Protocol::setParameters(ParameterMap ¶meterList){ d->parameterList = parameterList; } +int Protocol::turnOn(Controller * ){ + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +int Protocol::turnOff(Controller *) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +int Protocol::bell(Controller *) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +int Protocol::dim(unsigned char level, Controller *) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +int Protocol::learn(Controller *){ + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + /** * This method doesn't support all locales */ diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index e23e4daf..f09f3ef1 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -6,17 +6,25 @@ typedef std::map ParameterMap; +class Controller; + class Protocol { public: Protocol(); - ~Protocol(void); + virtual ~Protocol(void); static Protocol *getProtocolInstance(std::wstring &protocolname); void setModel(const std::wstring &model); void setParameters(ParameterMap ¶meterList); + virtual int turnOn(Controller *controller); + virtual int turnOff(Controller *controller); + virtual int bell(Controller *controller); + virtual int dim(unsigned char level, Controller *controller); + virtual int learn(Controller *controller); + private: class PrivateData; PrivateData *d; From 0b7c181397258dc82f5bb55b756482a2bf41fd53 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 13 Oct 2010 13:44:49 +0000 Subject: [PATCH 0309/2215] "AddDevice" implemented (without locks and stuff yet) --- .../service/ClientCommunicationHandler.cpp | 11 ++++------- telldus-core/service/Device.cpp | 1 + telldus-core/service/DeviceManager.cpp | 18 ++++++++++++++++++ telldus-core/service/DeviceManager.h | 1 + 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 01b1cc26..2d3b3779 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -75,7 +75,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); //TODO Lock controller and device? - Controller *controller = d->controllerManager->getBestControllerById(d->deviceManager->getDevice(deviceId)->getPreferredControllerId()); //TODO: Get controller id... + Controller *controller = d->controllerManager->getBestControllerById(d->deviceManager->getDevice(deviceId)->getPreferredControllerId()); //TODO: Lock device? if(controller){ (*intReturn) = d->deviceManager->getDevice(deviceId)->turnOn(controller); @@ -84,7 +84,6 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*intReturn) = 0; } //TODO: Unlock - //(*intReturn) = 0; //tdTurnOn(deviceId); } else if (function == L"tdTurnOff") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -170,11 +169,9 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdAddDevice") { //TODO - //int deviceId = d->settings.addDevice(); - int deviceId = 0; - if(deviceId > 0){ - //success - //TODO signal event... + if(d->deviceManager->addDevice()){ + (*intReturn) = 1; + //TODO: signalEvent, or do that from where this is called? Or even inside addDevice? } } else if (function == L"tdRemoveDevice") { diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 2fb4e97c..9a80fb86 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -14,6 +14,7 @@ public: Device::Device(int id){ d = new PrivateData; d->protocol = 0; + d->preferredControllerId = 0; //när något uppdateras, spara också till registret //obs, kunna hantera om alla värden inte är satta } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 57b3d6c4..fc163cac 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -57,3 +57,21 @@ Device *DeviceManager::getDevice(int deviceId){ } return 0; //not found } + +bool DeviceManager::addDevice(){ + Settings set; + + //TODO: Lock? + int id = set.addDevice(); + if(id == -1){ + return false; + } + + //TODO: Lock + d->devices[id] = new Device(id); + if(!d->devices[id]){ + return false; + } + return true; + //release locks +} diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 799e68cf..767572d4 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -10,6 +10,7 @@ public: ~DeviceManager(void); int getNumberOfDevices(void); Device *getDevice(int deviceId); + bool addDevice(); private: From 8105da7101e2af3a7b61e1d097f7714f81984bbc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 13:53:39 +0000 Subject: [PATCH 0310/2215] Made the Mutex be an own class. --- telldus-core/common/CMakeLists.txt | 8 ++- telldus-core/common/Mutex.cpp | 74 +++++++++++++++++++++++ telldus-core/common/Mutex.h | 38 ++++++++++++ telldus-core/common/Thread.cpp | 45 +------------- telldus-core/common/Thread.h | 21 ------- telldus-core/service/Event.cpp | 5 +- telldus-core/service/EventHandler_win.cpp | 6 +- 7 files changed, 124 insertions(+), 73 deletions(-) create mode 100644 telldus-core/common/Mutex.cpp create mode 100644 telldus-core/common/Mutex.h diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 719308bd..0f316c94 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -4,14 +4,16 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-common_SRCS - Thread.cpp Message.cpp + Mutex.cpp + Thread.cpp ) SET( telldus-common_HDRS - Thread.h - Socket.h Message.h + Mutex.h + Socket.h + Thread.h ) ######## Configurable options for the platform ######## diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp new file mode 100644 index 00000000..0b3dcf4e --- /dev/null +++ b/telldus-core/common/Mutex.cpp @@ -0,0 +1,74 @@ +// +// C++ Implementation: Thread +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// + +#include "Mutex.h" + +using namespace TelldusCore; + + +#ifdef _WINDOWS + #include + typedef CRITICAL_SECTION MUTEX_T; +#else + #include + typedef pthread_mutex_t MUTEX_T; +#endif + +class Mutex::PrivateData { +public: + MUTEX_T mutex; +}; + +Mutex::Mutex() { + d = new PrivateData; +#ifdef _WINDOWS + InitializeCriticalSection(&d->mutex); +#else + pthread_mutex_init(&d->mutex, NULL); +#endif +} + +Mutex::~Mutex() { +#ifdef _WINDOWS + DeleteCriticalSection(&d->mutex); +#else + pthread_mutex_destroy(&d->mutex); +#endif + delete d; +} + +void Mutex::lock() { +#ifdef _WINDOWS + EnterCriticalSection(&d->mutex); +#else + pthread_mutex_lock(&d->mutex); +#endif +} + +void Mutex::unlock() { +#ifdef _WINDOWS + LeaveCriticalSection(&d->mutex); +#else + pthread_mutex_unlock(&d->mutex); +#endif +} + + +MutexLocker::MutexLocker(Mutex *m) + :mutex(m) +{ + mutex->lock(); +} + +MutexLocker::~MutexLocker() { + mutex->unlock(); +} diff --git a/telldus-core/common/Mutex.h b/telldus-core/common/Mutex.h new file mode 100644 index 00000000..e01d45c1 --- /dev/null +++ b/telldus-core/common/Mutex.h @@ -0,0 +1,38 @@ +// +// C++ Interface: Thread +// +// Description: +// +// +// Author: Micke Prag , (C) 2010 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef MUTEX_H +#define MUTEX_H + +namespace TelldusCore { + class Mutex { + public: + Mutex(); + virtual ~Mutex(); + + void lock(); + void unlock(); + + private: + class PrivateData; + PrivateData *d; + }; + + class MutexLocker { + public: + MutexLocker(Mutex *m); + ~MutexLocker(); + private: + Mutex *mutex; + }; +} + +#endif //MUTEX_H diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index ef70dc27..2f7e73d2 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -11,6 +11,9 @@ // #include "Thread.h" +#ifdef _WINDOWS +#include +#endif using namespace TelldusCore; @@ -61,45 +64,3 @@ void *Thread::exec( void *ptr ) { } return 0; } - -void Thread::initMutex(MUTEX_T * m) { -#ifdef _WINDOWS - InitializeCriticalSection(m); -#else - pthread_mutex_init(m, NULL); -#endif -} - -void Thread::destroyMutex(MUTEX_T * m) { -#ifdef _WINDOWS - DeleteCriticalSection(m); -#else - pthread_mutex_destroy(m); -#endif -} - -void Thread::unlockMutex(MUTEX_T * m) { -#ifdef _WINDOWS - LeaveCriticalSection(m); -#else - pthread_mutex_unlock(m); -#endif -} - -void Thread::lockMutex(MUTEX_T * m) { -#ifdef _WINDOWS - EnterCriticalSection(m); -#else - pthread_mutex_lock(m); -#endif -} - - -MutexLocker::MutexLocker(MUTEX_T *m) - :mutex(m) { - Thread::lockMutex(mutex); -} - -MutexLocker::~MutexLocker() { - Thread::unlockMutex(mutex); -} diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index 35fbe1f3..683efb99 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -14,14 +14,6 @@ #include -#ifdef _WINDOWS - #include - typedef CRITICAL_SECTION MUTEX_T; -#else - #include - typedef pthread_mutex_t MUTEX_T; -#endif - namespace TelldusCore { class ThreadPrivate; class Thread { @@ -30,11 +22,6 @@ namespace TelldusCore { virtual ~Thread(); void start(); bool wait(); - - static void initMutex(MUTEX_T *m); - static void destroyMutex(MUTEX_T *m); - static void lockMutex(MUTEX_T *m); - static void unlockMutex(MUTEX_T *m); protected: virtual void run() = 0; @@ -43,14 +30,6 @@ namespace TelldusCore { static void* exec( void *ptr ); ThreadPrivate *d; }; - - class MutexLocker { - public: - MutexLocker(MUTEX_T *m); - ~MutexLocker(); - private: - MUTEX_T *mutex; - }; } #endif diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index 18178c37..6c3c27b4 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -1,5 +1,6 @@ #include "Event.h" #include "EventHandler.h" +#include "Mutex.h" #include @@ -13,7 +14,7 @@ bool EventDataBase::isValid() const { class EventBase::PrivateData { public: - MUTEX_T mutex; + TelldusCore::Mutex mutex; EventHandler *handler; std::list eventDataList; }; @@ -21,7 +22,6 @@ public: EventBase::EventBase(EventHandler *handler) { d = new PrivateData; d->handler = handler; - TelldusCore::Thread::initMutex(&d->mutex); } EventBase::~EventBase(void) { @@ -33,7 +33,6 @@ EventBase::~EventBase(void) { for(; it != d->eventDataList.end(); ++it) { delete(*it); } - TelldusCore::Thread::destroyMutex(&d->mutex); delete d; } diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 3a9b653f..7c012fe9 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -1,6 +1,6 @@ #include "EventHandler.h" #include "Event.h" -#include "Thread.h" +#include "Mutex.h" #include #include @@ -9,7 +9,7 @@ class EventHandler::PrivateData { public: HANDLE *eventArray; Event **eventObjectArray; - MUTEX_T mutex; + TelldusCore::Mutex mutex; int eventCount; }; @@ -18,11 +18,9 @@ EventHandler::EventHandler() { d->eventCount = 0; d->eventArray = new HANDLE[0]; d->eventObjectArray = new Event*[0]; - TelldusCore::Thread::initMutex(&d->mutex); } EventHandler::~EventHandler(void) { - TelldusCore::Thread::destroyMutex(&d->mutex); delete[] d->eventObjectArray; delete[] d->eventArray; delete d; From edd709de07a12ba8460070c1e267e61b322e13fd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 15:08:38 +0000 Subject: [PATCH 0311/2215] Added functions Protocol::getStringParameter() and Protocol::getIntParameter() Removed methods-stubs. --- telldus-core/service/Protocol.cpp | 39 ++++++++++++++++++------------- telldus-core/service/Protocol.h | 11 +++++---- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index d73e85c9..4c4c9c8d 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -5,6 +5,7 @@ #include "ProtocolNexa.h" #include #include +#include class Protocol::PrivateData { public: @@ -29,24 +30,30 @@ void Protocol::setParameters(ParameterMap ¶meterList){ d->parameterList = parameterList; } -int Protocol::turnOn(Controller * ){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +std::wstring Protocol::getStringParameter(const std::wstring &name, const std::wstring &defaultValue) const { + ParameterMap::const_iterator it = d->parameterList.find(name); + if (it == d->parameterList.end()) { + return defaultValue; + } + return it->second; } -int Protocol::turnOff(Controller *) { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -int Protocol::bell(Controller *) { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -int Protocol::dim(unsigned char level, Controller *) { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -int Protocol::learn(Controller *){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +int Protocol::getIntParameter(const std::wstring &name, int min, int max) const { + std::wstring value = getStringParameter(name, L""); + if (value == L"") { + return min; + } + std::wstringstream st; + st << value; + int intValue = 0; + st >> intValue; + if (intValue < min) { + return min; + } + if (intValue > max) { + return max; + } + return intValue; } /** diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index f09f3ef1..045379f2 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -3,6 +3,7 @@ #include #include +#include "../client/telldus-core.h" typedef std::map ParameterMap; @@ -19,11 +20,11 @@ public: void setModel(const std::wstring &model); void setParameters(ParameterMap ¶meterList); - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int bell(Controller *controller); - virtual int dim(unsigned char level, Controller *controller); - virtual int learn(Controller *controller); + virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller) = 0; + +protected: + std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; + int getIntParameter(const std::wstring &name, int min, int max) const; private: class PrivateData; From 7b59faae25d115636056b347ec0d3624c752c45e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 15:09:22 +0000 Subject: [PATCH 0312/2215] Implemented ProtocolNexa::getStringForMethod() --- telldus-core/service/ProtocolNexa.cpp | 353 +++++--------------------- telldus-core/service/ProtocolNexa.h | 34 +-- 2 files changed, 66 insertions(+), 321 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index d6f23fb6..345d3a15 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,22 +1,7 @@ -// #include "StdAfx.h" #include "ProtocolNexa.h" -#include -#include -#include -#include -#include -// #include "common.h" -const char START[] = {'T',127,255,24,1,0}; -//const char START[] = {'T',130,255,26,24,0}; - -/* -* Constructor -*/ ProtocolNexa::ProtocolNexa() - :Protocol(), - intHouse(0), - intCode(0) + :Protocol() { } @@ -27,280 +12,64 @@ ProtocolNexa::ProtocolNexa() ProtocolNexa::~ProtocolNexa(void) {} +std::string ProtocolNexa::getStringForMethod(int method, const std::string &data, Controller *) { +// const char START[] = {'T',127,255,24,1,0}; + const char START[] = {'T',130,255,26,24,0}; -//bool DeviceNexa::setHouse(const std::string &newHouse) { -// int house = atoi(newHouse.c_str()); -// if (newHouse.length() == 1 && house == 0) { //Codeswitch -// intHouse = newHouse[0] - 'A'; -// } else { //Selflearning -// intHouse = house; -// } -// return true; -//} -// -//bool DeviceNexa::setUnit(const std::string &newUnit) { -// if (newUnit.length() > 0) { -// intCode = atoi(newUnit.c_str()) - 1; -// } else { -// intCode = 0; -// } -// return true; -//} -// -//bool DeviceNexa::setDeviceParameter(const std::string &strName, const std::string &strValue) { -// if (strName.compare("house") == 0) { -// return setHouse(strValue); -// } else if (strName.compare("unit") == 0) { -// return setUnit(strValue); -// } -// return false; -//} -// -///* -//* Turn on this device -//*/ -// -//int DeviceNexa::turnOn(Controller *controller){ -// if (strcasecmp(this->getModel().c_str(), "bell") == 0) { -// return bell(controller); -// } -// try{ -// std::string strCode = ""; -// if (isDimmer()) { -// return dim(255, controller); -// } else if (isSelflearning()) { -// strCode.append( 1, 'R' ); -// strCode.append( 1, 5 ); -// strCode.append(getStringSelflearning(false, 255)); -// } else { -// strCode.append("S"); -// strCode.append(getStringCodeSwitch(intHouse)); -// strCode.append(getStringCodeSwitch(intCode)); -// strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time -// } -// -// return controller->send(strCode); -// } -// catch(...){ -// throw; -// } -// return TELLSTICK_ERROR_UNKNOWN; -//} -// -///* -//* Turn off this device -//*/ -// -//int DeviceNexa::turnOff(Controller *controller){ -// -// try{ -// std::string strCode = ""; -// if (isSelflearning()) { -// strCode.append( 1, 'R' ); -// strCode.append( 1, 5 ); -// strCode.append(getStringSelflearning(false, 0)); -// } else { -// strCode.append("S"); -// strCode.append(getStringCodeSwitch(intHouse)); -// strCode.append(getStringCodeSwitch(intCode)); -// strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time -// } -// -// return controller->send(strCode); -// } -// catch(...){ -// throw; -// } -// return TELLSTICK_ERROR_UNKNOWN; -//} -// -///* -//* Dim this device -//*/ -// -//int DeviceNexa::dim(unsigned char level, Controller *controller) { -// try{ -// std::string strMessage = ""; -// strMessage.append( 1, 'R' ); -// strMessage.append( 1, 5 ); -// strMessage.append(getStringSelflearning(true, level)); -// return controller->send(strMessage); -// } -// catch(...){ -// throw; -// } -// return TELLSTICK_ERROR_UNKNOWN; -//} -// -// -///* -//* Send a bell -//*/ -// -//int DeviceNexa::bell(Controller *controller){ -// -// try{ -// std::string strCode = getStringCodeSwitch(intHouse); -// -// strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time -// strCode.insert(0, "S"); -// strCode.append("$kk$$kk$$kk$$kk$$k+"); //the "bell"-code, keeps it like this, doesn't have to be regenerated each time -// -// return controller->send(strCode); -// } -// catch(...){ -// throw; -// } -// return TELLSTICK_ERROR_UNKNOWN; -//} -// -//int DeviceNexa::learn(Controller *controller){ -// std::string strCode = ""; -// strCode.append( 1, 'R' ); -// strCode.append( 1, 2 ); -// strCode.append(getStringSelflearning(false, 255)); -// -// int retVal = 0; -// for (int i = 0; i < 5; ++i) { -// retVal = controller->send(strCode); -// if (retVal != TELLSTICK_SUCCESS) { -// return retVal; -// } -// msleep(200); -// } -// return retVal; -//} -// -///* -//* Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed -//*/ -// -//std::string DeviceNexa::getStringCodeSwitch(int intToConvert){ -// -// std::string strReturn = ""; -// -// try{ -// for( int i = 0; i < 4; ++i ) { -// if (intToConvert & 1) { //Convert 1 -// strReturn.append("$kk$"); -// } else { //Convert 0 -// strReturn.append("$k$k"); -// } -// intToConvert >>= 1; -// -// } -// } -// catch(...){ -// throw; -// } -// return strReturn; -// -//} -// -//std::string DeviceNexa::getStringSelflearning(bool dim, unsigned char level) { -// std::string strMessage = START; -// strMessage.append(1,(dim ? 147 : 132)); //Number of pulses -// -// std::string m; -// for (int i = 25; i >= 0; --i) { -// m.append( intHouse & 1 << i ? "10" : "01" ); -// } -// m.append("01"); //Group -// -// //On/off -// if (dim) { -// m.append("00"); -// } else if (level == 0) { -// m.append("01"); -// } else { -// m.append("10"); -// } -// -// for (int i = 3; i >= 0; --i) { -// m.append( intCode & 1 << i ? "10" : "01" ); -// } -// -// if (dim) { -// unsigned char newLevel = level/16; -// for (int i = 3; i >= 0; --i) { -// m.append(newLevel & 1 << i ? "10" : "01"); -// } -// } -// -// //The number of data is odd. -// //Add this to make it even, otherwise the following loop will not work -// m.append("0"); -// -// unsigned char code = 9; //b1001, startcode -// for (unsigned int i = 0; i < m.length(); ++i) { -// code <<= 4; -// if (m[i] == '1') { -// code |= 8; //b1000 -// } else { -// code |= 10; //b1010 -//// code |= 11; //b1011 -// } -// if (i % 2 == 0) { -// strMessage.append(1,code); -// code = 0; -// } -// } -// strMessage.append("+"); -// -//// for( int i = 0; i < strMessage.length(); ++i ) { -//// printf("%i,", (unsigned char)strMessage[i]); -//// } -//// printf("\n"); -// return strMessage; -//} -// -//bool DeviceNexa::parameterMatches( const std::string &name, const std::string &value ) const { -// if (name.compare("house") == 0) { -// if (isSelflearning()) { -// return intHouse == atoi(value.c_str()); -// } -// return intHouse == value[0] - 'A'; -// } else if (name.compare("unit") == 0) { -// return intCode == atoi(value.c_str()) - 1; -// } else if (name.compare("type") == 0) { -// if (isSelflearning()) { -// return (value.compare("selflearning") == 0); -// } -// } -// return true; -//} -// -///* -//* Has the device got the method? -//*/ -// -//int DeviceNexa::methods(){ -// std::string strModel = this->getModel(); -// -// if ( strcasecmp(strModel.c_str(), "codeswitch") == 0 ) { -// return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -// -// } else if (strcasecmp(strModel.c_str(), "selflearning-switch") == 0) { -// return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); -// -// } else if (strcasecmp(strModel.c_str(), "selflearning-dimmer") == 0) { -// return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); -// -// } else if (strcasecmp(strModel.c_str(), "bell") == 0) { -// return TELLSTICK_BELL; -// } -// return 0; -//} -// -//bool DeviceNexa::isSelflearning() const { -// return strncasecmp(getModel().c_str(), "selflearning", 12) == 0; -//} -// -//bool DeviceNexa::isDimmer() const { -// return strcasecmp(getModel().c_str(), "selflearning-dimmer") == 0; -//} -// -//std::string DeviceNexa::getProtocol() const { -// return "arctech"; -//} -// + std::string strMessage(START); + strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses + int intHouse = getIntParameter(L"house", 1, 67108863); + int intCode = getIntParameter(L"code", 1, 16)-1; + + std::string m; + for (int i = 25; i >= 0; --i) { + m.append( intHouse & 1 << i ? "10" : "01" ); + } + m.append("01"); //Group + + //On/off + if (method == TELLSTICK_DIM) { + m.append("00"); + } else if (method == TELLSTICK_TURNOFF) { + m.append("01"); + } else { + m.append("10"); + } + + for (int i = 3; i >= 0; --i) { + m.append( intCode & 1 << i ? "10" : "01" ); + } + + if (method == TELLSTICK_DIM) { + /*unsigned char newLevel = level/16; + for (int i = 3; i >= 0; --i) { + m.append(newLevel & 1 << i ? "10" : "01"); + }*/ + } + + //The number of data is odd. + //Add this to make it even, otherwise the following loop will not work + m.append("0"); + + unsigned char code = 9; //b1001, startcode + for (unsigned int i = 0; i < m.length(); ++i) { + code <<= 4; + if (m[i] == '1') { + code |= 8; //b1000 + } else { + code |= 10; //b1010 +// code |= 11; //b1011 + } + if (i % 2 == 0) { + strMessage.append(1,code); + code = 0; + } + } + strMessage.append("+"); + +// for( int i = 0; i < strMessage.length(); ++i ) { +// printf("%i,", (unsigned char)strMessage[i]); +// } +// printf("\n"); + return strMessage; +} diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 7da171c0..df36fb14 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -2,35 +2,11 @@ #include "Device.h" #include -class ProtocolNexa : public Protocol -{ - public: - ProtocolNexa(); - //virtual int methods(); - //virtual std::string getProtocol() const; - //virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - bool setHouse(const std::string &newHouse); - bool setUnit(const std::string &newUnit); - - ~ProtocolNexa(void); - - protected: - /* - virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); - virtual int turnOn(Controller *controller); - virtual int turnOff(Controller *controller); - virtual int dim(unsigned char level, Controller *controller); - virtual int bell(Controller *controller); - virtual int learn(Controller *controller); - - bool isSelflearning() const; - bool isDimmer() const; +class ProtocolNexa : public Protocol { +public: + ProtocolNexa(); + virtual ~ProtocolNexa(void); - */ - int intHouse; - int intCode; - //std::string getStringCodeSwitch(int); - //std::string getStringSelflearning(bool dim, unsigned char level); + virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); }; From caaeb991e107018283dad819f3978b38762f5f2c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 15:09:59 +0000 Subject: [PATCH 0313/2215] Calculate turn on code and send it to the controller. --- telldus-core/service/Device.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 9a80fb86..607055f5 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -74,7 +74,8 @@ void Device::setProtocolName(const std::wstring &protocolName){ int Device::turnOn(Controller *controller) { Protocol *p = this->retrieveProtocol(); if(p){ - //p->turnOn(controller); + std::string code = p->getStringForMethod(TELLSTICK_TURNON, "", controller); + controller->send(code); } return 0; } From 59afb302b73d81b018b6e80127582b9cac4b8c67 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Oct 2010 15:31:37 +0000 Subject: [PATCH 0314/2215] Renamed settings parameter --- telldus-core/service/Settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 219324eb..056a26b6 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -60,14 +60,14 @@ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &s * Set preferred controller id */ bool Settings::setPreferredControllerId(int intDeviceId, int value){ - return setIntSetting(intDeviceId, L"controllerId", value, false); + return setIntSetting(intDeviceId, L"controller", value, false); } /* * Get preferred controller id */ int Settings::getPreferredControllerId(int intDeviceId) { - return getIntSetting(intDeviceId, L"controllerId", false); + return getIntSetting(intDeviceId, L"controller", false); } #ifndef _CONFUSE From 4d0a669207f49dd61313a2c1e57e96f89ab413b3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 08:42:18 +0000 Subject: [PATCH 0315/2215] "Turn on" working all the way with the arctech protcol, but without locks etc --- .../service/ClientCommunicationHandler.cpp | 18 ++-- telldus-core/service/DeviceManager.cpp | 97 +++++++++++++------ telldus-core/service/DeviceManager.h | 5 +- telldus-core/service/Protocol.cpp | 1 - 4 files changed, 85 insertions(+), 36 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 2d3b3779..b2d7a0f7 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -75,10 +75,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); //TODO Lock controller and device? - Controller *controller = d->controllerManager->getBestControllerById(d->deviceManager->getDevice(deviceId)->getPreferredControllerId()); + Controller *controller = d->controllerManager->getBestControllerById(d->deviceManager->getPreferredControllerId(deviceId)); //TODO: Lock device? if(controller){ - (*intReturn) = d->deviceManager->getDevice(deviceId)->turnOn(controller); + (*intReturn) = d->deviceManager->turnOn(deviceId, controller); } else{ (*intReturn) = 0; @@ -117,9 +117,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*intReturn) = d->deviceManager->getNumberOfDevices(); } else if (function == L"tdGetDeviceId") { - int intDeviceIndex = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 1; //tdGetDeviceId(intDeviceIndex); - + int deviceIndex = TelldusCore::Message::takeInt(&msg); + + (*intReturn) = d->deviceManager->getDeviceId(deviceIndex); + } else if (function == L"tdGetDeviceType") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = 11; // tdGetDeviceType(deviceId); @@ -168,7 +169,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*wstringReturn) = TelldusCore::Message::charToWstring(value); } else if (function == L"tdAddDevice") { - //TODO + //TODO: Lock if(d->deviceManager->addDevice()){ (*intReturn) = 1; //TODO: signalEvent, or do that from where this is called? Or even inside addDevice? @@ -176,7 +177,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdRemoveDevice") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdRemoveDevice(deviceId); + if(d->deviceManager->removeDevice(deviceId)){ + (*intReturn) = 1; + //TODO: signalEvent, or do that from where this is called? Or even inside removeDevice? + } } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index fc163cac..983c03d8 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,4 +1,5 @@ #include "DeviceManager.h" +#include "Mutex.h" #include "Settings.h" #include @@ -8,6 +9,7 @@ typedef std::map DeviceMap; class DeviceManager::PrivateData { public: DeviceMap devices; + Settings set; //TODO: have to be here, right? Only one instance? }; DeviceManager::DeviceManager(){ @@ -16,6 +18,8 @@ DeviceManager::DeviceManager(){ } DeviceManager::~DeviceManager(void) { + //TODO: Locks + //always lock list first, device after (or only one of them) for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { delete( it->second ); } @@ -23,22 +27,21 @@ DeviceManager::~DeviceManager(void) { } void DeviceManager::fillDevices(){ - Settings set; - int numberOfDevices = set.getNumberOfDevices(); + int numberOfDevices = d->set.getNumberOfDevices(); for (int i = 0; i < numberOfDevices; ++i) { - int id = set.getDeviceId(i); + int id = d->set.getDeviceId(i); d->devices[id] = new Device(id); - d->devices[id]->setName(set.getName(id)); - d->devices[id]->setModel(set.getModel(id)); - d->devices[id]->setProtocolName(set.getProtocol(id)); - d->devices[id]->setPreferredControllerId(set.getPreferredControllerId(id)); - d->devices[id]->setParameter(L"house", set.getDeviceParameter(id, L"house")); - d->devices[id]->setParameter(L"unit", set.getDeviceParameter(id, L"unit")); - d->devices[id]->setParameter(L"code", set.getDeviceParameter(id, L"code")); - d->devices[id]->setParameter(L"units", set.getDeviceParameter(id, L"units")); - d->devices[id]->setParameter(L"fade", set.getDeviceParameter(id, L"fade")); - d->devices[id]->setParameter(L"system", set.getDeviceParameter(id, L"system")); + d->devices[id]->setName(d->set.getName(id)); + d->devices[id]->setModel(d->set.getModel(id)); + d->devices[id]->setProtocolName(d->set.getProtocol(id)); + d->devices[id]->setPreferredControllerId(d->set.getPreferredControllerId(id)); + d->devices[id]->setParameter(L"house", d->set.getDeviceParameter(id, L"house")); + d->devices[id]->setParameter(L"unit", d->set.getDeviceParameter(id, L"unit")); + d->devices[id]->setParameter(L"code", d->set.getDeviceParameter(id, L"code")); + d->devices[id]->setParameter(L"units", d->set.getDeviceParameter(id, L"units")); + d->devices[id]->setParameter(L"fade", d->set.getDeviceParameter(id, L"fade")); + d->devices[id]->setParameter(L"system", d->set.getDeviceParameter(id, L"system")); } } @@ -46,23 +49,11 @@ int DeviceManager::getNumberOfDevices(){ return (int)d->devices.size(); } -Device *DeviceManager::getDevice(int deviceId){ - - if (!d->devices.size()) { - return 0; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - return it->second; - } - return 0; //not found -} - bool DeviceManager::addDevice(){ Settings set; - //TODO: Lock? - int id = set.addDevice(); + //TODO: Lock? (set too) + int id = d->set.addDevice(); if(id == -1){ return false; } @@ -75,3 +66,55 @@ bool DeviceManager::addDevice(){ return true; //release locks } + +int DeviceManager::getDeviceId(int intDeviceIndex) { + //TODO This must be done differently, device index (why is it even needed?) may be stored in device too + return d->set.getDeviceId(intDeviceIndex); +} + +int DeviceManager::getPreferredControllerId(int deviceId){ + + //TODO: repeating code... + //TODO: Lock + if (!d->devices.size()) { + return 0; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + return it->second->getPreferredControllerId(); + } + return 0; //not found + +} + +bool DeviceManager::removeDevice(int deviceId){ + + //TODO: Lock device/list and set? + if(d->set.removeDevice(deviceId)){ + //TODO ta bort från listan d->devices[id] + } + + + return false; +} + +bool DeviceManager::turnOn(int deviceId, Controller *controller){ + + + { + //TODO: Get device + //TelldusCore::MutexLocker locker(&device); + //device is locked in current scope + + if (!d->devices.size()) { + return false; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + return it->second->turnOn(controller); + } + return false; //not found + + } + +} diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 767572d4..06f53786 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -9,8 +9,11 @@ public: DeviceManager(void); ~DeviceManager(void); int getNumberOfDevices(void); - Device *getDevice(int deviceId); bool addDevice(); + int getDeviceId(int deviceIndex); + int getPreferredControllerId(int deviceId); + bool removeDevice(int deviceId); + bool turnOn(int deviceId, Controller *controller); private: diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 4c4c9c8d..43d11dbb 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,5 +1,4 @@ #include "Protocol.h" -#include "Settings.h" #include "../client/telldus-core.h" #include "ProtocolNexa.h" From bd6de03ec57566149b9e933146c8a492dfbd8d54 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 10:13:28 +0000 Subject: [PATCH 0316/2215] Added function Protocol::model() --- telldus-core/service/Protocol.cpp | 4 ++++ telldus-core/service/Protocol.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 43d11dbb..8f6893c1 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -21,6 +21,10 @@ Protocol::~Protocol(void) { delete d; } +std::wstring Protocol::model() const { + return d->model; +} + void Protocol::setModel(const std::wstring &model){ d->model = model; } diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 045379f2..a054c807 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -17,6 +17,7 @@ public: static Protocol *getProtocolInstance(std::wstring &protocolname); + std::wstring model() const; void setModel(const std::wstring &model); void setParameters(ParameterMap ¶meterList); @@ -25,11 +26,11 @@ public: protected: std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; int getIntParameter(const std::wstring &name, int min, int max) const; + static bool comparei(std::wstring stringA , std::wstring stringB); private: class PrivateData; PrivateData *d; - static bool comparei(std::wstring stringA , std::wstring stringB); }; #endif //PROTOCOL_H \ No newline at end of file From 4604472f5763f8ca992a64656070d1c059cece27 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 10:14:00 +0000 Subject: [PATCH 0317/2215] Selflearning is working. Codeswitch still on TODO --- telldus-core/service/ProtocolNexa.cpp | 47 ++++++++++++++++++++++++--- telldus-core/service/ProtocolNexa.h | 6 +++- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 345d3a15..0fbfbafe 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -13,13 +13,37 @@ ProtocolNexa::~ProtocolNexa(void) {} std::string ProtocolNexa::getStringForMethod(int method, const std::string &data, Controller *) { -// const char START[] = {'T',127,255,24,1,0}; - const char START[] = {'T',130,255,26,24,0}; + if (!comparei(model(), L"codeswitch")) { + return getStringSelflearning(method, data); + } + return getStringCodeSwitch(method); +} + +std::string ProtocolNexa::getStringCodeSwitch(int method) { + std::string strReturn = "S"; + + int intHouse = 0; //TODO: getIntParameter(L"house", 1, 67108863) + strReturn.append(getCodeSwitchTuple(intHouse)); + strReturn.append(getCodeSwitchTuple(getIntParameter(L"code", 1, 16)-1)); + + if (method == TELLSTICK_TURNON) { + strReturn.append("$k$k$kk$$kk$$kk$$k+"); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append("$k$k$kk$$kk$$k$k$k+"); + } else { + return ""; + } + return strReturn; +} + +std::string ProtocolNexa::getStringSelflearning(int method, const std::string &data) { + const char START[] = {'T',127,255,24,1,0}; +// const char START[] = {'T',130,255,26,24,0}; std::string strMessage(START); strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses int intHouse = getIntParameter(L"house", 1, 67108863); - int intCode = getIntParameter(L"code", 1, 16)-1; + int intCode = getIntParameter(L"unit", 1, 16)-1; std::string m; for (int i = 25; i >= 0; --i) { @@ -32,8 +56,10 @@ std::string ProtocolNexa::getStringForMethod(int method, const std::string &data m.append("00"); } else if (method == TELLSTICK_TURNOFF) { m.append("01"); - } else { + } else if (method == TELLSTICK_TURNON) { m.append("10"); + } else { + return ""; } for (int i = 3; i >= 0; --i) { @@ -73,3 +99,16 @@ std::string ProtocolNexa::getStringForMethod(int method, const std::string &data // printf("\n"); return strMessage; } + +std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { + std::string strReturn = ""; + for( int i = 0; i < 4; ++i ) { + if (intCode & 1) { //Convert 1 + strReturn.append("$kk$"); + } else { //Convert 0 + strReturn.append("$k$k"); + } + intCode >>= 1; + } + return strReturn; +} \ No newline at end of file diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index df36fb14..2f74cc0b 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -8,5 +8,9 @@ public: virtual ~ProtocolNexa(void); virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); - + +protected: + std::string getStringSelflearning(int method, const std::string &data); + std::string getStringCodeSwitch(int method); + static std::string getCodeSwitchTuple(int code); }; From 55a37f73231aeb3f29499c0d111089802daf8481 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 10:35:19 +0000 Subject: [PATCH 0318/2215] Strip everything after ':' in the model. --- telldus-core/service/Protocol.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 8f6893c1..371101a5 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -22,7 +22,14 @@ Protocol::~Protocol(void) { } std::wstring Protocol::model() const { - return d->model; + std::wstring strModel = d->model; + //Strip anything after : if it is found + size_t pos = strModel.find(L":"); + if (pos != std::wstring::npos) { + strModel = strModel.substr(0, pos); + } + + return strModel; } void Protocol::setModel(const std::wstring &model){ From a7eae54b3713eb7a69b8cab8ba60c72695deb6f5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 10:40:13 +0000 Subject: [PATCH 0319/2215] Codeswitch working --- telldus-core/service/ProtocolNexa.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 0fbfbafe..bdb84694 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -22,9 +22,10 @@ std::string ProtocolNexa::getStringForMethod(int method, const std::string &data std::string ProtocolNexa::getStringCodeSwitch(int method) { std::string strReturn = "S"; - int intHouse = 0; //TODO: getIntParameter(L"house", 1, 67108863) + std::wstring house = getStringParameter(L"house", L"A"); + int intHouse = house[0] - L'A'; strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append(getCodeSwitchTuple(getIntParameter(L"code", 1, 16)-1)); + strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1)); if (method == TELLSTICK_TURNON) { strReturn.append("$k$k$kk$$kk$$kk$$k+"); From 95e0572a36a90777b99cdf4334b95ed5cce1909d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 10:41:39 +0000 Subject: [PATCH 0320/2215] Constructor/Desctructor not needed. --- telldus-core/service/ProtocolNexa.cpp | 12 ------------ telldus-core/service/ProtocolNexa.h | 3 --- 2 files changed, 15 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index bdb84694..9236f667 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,17 +1,5 @@ #include "ProtocolNexa.h" -ProtocolNexa::ProtocolNexa() - :Protocol() -{ - -} - -/* -* Destructor -*/ -ProtocolNexa::~ProtocolNexa(void) -{} - std::string ProtocolNexa::getStringForMethod(int method, const std::string &data, Controller *) { if (!comparei(model(), L"codeswitch")) { return getStringSelflearning(method, data); diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 2f74cc0b..d4dd546b 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -4,9 +4,6 @@ class ProtocolNexa : public Protocol { public: - ProtocolNexa(); - virtual ~ProtocolNexa(void); - virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); protected: From de12e9fc48628453ef211f7bfe1596b52ab18d28 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 11:22:05 +0000 Subject: [PATCH 0321/2215] Some locks implemented. Returning int:s instead of bools. --- .../service/ClientCommunicationHandler.cpp | 14 +-- .../service/ClientCommunicationHandler.h | 2 +- telldus-core/service/Device.cpp | 9 +- telldus-core/service/Device.h | 6 +- telldus-core/service/DeviceManager.cpp | 108 +++++++++++++----- telldus-core/service/DeviceManager.h | 9 +- telldus-core/service/Protocol.cpp | 2 +- telldus-core/service/TelldusMain.cpp | 6 +- 8 files changed, 99 insertions(+), 57 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index b2d7a0f7..3bf588f4 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -7,14 +7,13 @@ public: Event *event; bool done; DeviceManager *deviceManager; - ControllerManager *controllerManager; }; ClientCommunicationHandler::ClientCommunicationHandler(){ } -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, ControllerManager *controllerManager) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager) :Thread() { d = new PrivateData; @@ -22,7 +21,6 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie d->event = event; d->done = false; d->deviceManager = deviceManager; - d->controllerManager = controllerManager; } @@ -75,14 +73,8 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); //TODO Lock controller and device? - Controller *controller = d->controllerManager->getBestControllerById(d->deviceManager->getPreferredControllerId(deviceId)); - //TODO: Lock device? - if(controller){ - (*intReturn) = d->deviceManager->turnOn(deviceId, controller); - } - else{ - (*intReturn) = 0; - } + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, L""); + //TODO: Unlock } else if (function == L"tdTurnOff") { diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index eed52e86..2d1a442f 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -12,7 +12,7 @@ class ClientCommunicationHandler : public TelldusCore::Thread { public: ClientCommunicationHandler(); - ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, ControllerManager *controllerManager); + ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager); ~ClientCommunicationHandler(void); bool isDone(); diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 607055f5..e26021be 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -11,7 +11,9 @@ public: int preferredControllerId; }; -Device::Device(int id){ +Device::Device(int id) + :Mutex() +{ d = new PrivateData; d->protocol = 0; d->preferredControllerId = 0; @@ -71,10 +73,11 @@ void Device::setProtocolName(const std::wstring &protocolName){ * End Get-/Set */ -int Device::turnOn(Controller *controller) { +int Device::doAction(int action, const std::wstring &data, Controller *controller) { Protocol *p = this->retrieveProtocol(); if(p){ - std::string code = p->getStringForMethod(TELLSTICK_TURNON, "", controller); + std::string stringData(data.begin(), data.end()); //conversion needed + std::string code = p->getStringForMethod(action, stringData, controller); controller->send(code); } return 0; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 74d6d35b..5bd1310b 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -2,10 +2,11 @@ #define DEVICE_H #include "Controller.h" +#include "Mutex.h" #include "Protocol.h" #include -class Device +class Device : public TelldusCore::Mutex { public: Device(int id); @@ -21,9 +22,8 @@ public: void setPreferredControllerId(int controllerId); std::wstring getProtocolName(); void setProtocolName(const std::wstring &name); + int doAction(int action, const std::wstring &data, Controller *controller); - int turnOn(Controller *controller); - private: Protocol *retrieveProtocol(); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 983c03d8..178c0930 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -9,24 +9,29 @@ typedef std::map DeviceMap; class DeviceManager::PrivateData { public: DeviceMap devices; - Settings set; //TODO: have to be here, right? Only one instance? + Settings set; + TelldusCore::Mutex lock; + ControllerManager *controllerManager; }; -DeviceManager::DeviceManager(){ +DeviceManager::DeviceManager(ControllerManager *controllerManager){ d = new PrivateData; + d->controllerManager = controllerManager; fillDevices(); } DeviceManager::~DeviceManager(void) { - //TODO: Locks - //always lock list first, device after (or only one of them) + + TelldusCore::MutexLocker locker(&d->lock); for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { + {TelldusCore::MutexLocker lock(it->second);} //aquire lock, and release it, just to see thats it's not in use anywhere delete( it->second ); } delete d; } void DeviceManager::fillDevices(){ + TelldusCore::MutexLocker locker(&d->lock); int numberOfDevices = d->set.getNumberOfDevices(); for (int i = 0; i < numberOfDevices; ++i) { @@ -46,75 +51,116 @@ void DeviceManager::fillDevices(){ } int DeviceManager::getNumberOfDevices(){ + TelldusCore::MutexLocker locker(&d->lock); return (int)d->devices.size(); } -bool DeviceManager::addDevice(){ +int DeviceManager::addDevice(){ + TelldusCore::MutexLocker locker(&d->lock); Settings set; //TODO: Lock? (set too) int id = d->set.addDevice(); if(id == -1){ - return false; + return TELLSTICK_ERROR_UNKNOWN; } //TODO: Lock d->devices[id] = new Device(id); if(!d->devices[id]){ - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } - return true; + return TELLSTICK_DEVICE_ADDED; //release locks } int DeviceManager::getDeviceId(int intDeviceIndex) { - //TODO This must be done differently, device index (why is it even needed?) may be stored in device too + TelldusCore::MutexLocker locker(&d->lock); return d->set.getDeviceId(intDeviceIndex); } int DeviceManager::getPreferredControllerId(int deviceId){ + TelldusCore::MutexLocker locker(&d->lock); //TODO: repeating code... //TODO: Lock if (!d->devices.size()) { - return 0; + return TELLSTICK_ERROR_NOT_FOUND; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { return it->second->getPreferredControllerId(); } - return 0; //not found + return TELLSTICK_ERROR_NOT_FOUND; //not found } -bool DeviceManager::removeDevice(int deviceId){ - - //TODO: Lock device/list and set? - if(d->set.removeDevice(deviceId)){ - //TODO ta bort från listan d->devices[id] - } - - - return false; -} - -bool DeviceManager::turnOn(int deviceId, Controller *controller){ - +int DeviceManager::removeDevice(int deviceId){ + Device *device = 0; { - //TODO: Get device - //TelldusCore::MutexLocker locker(&device); - //device is locked in current scope - + TelldusCore::MutexLocker locker(&d->lock); + if(!d->set.removeDevice(deviceId)){ //remove from register/settings + return TELLSTICK_ERROR_UNKNOWN; + } + if (!d->devices.size()) { - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - return it->second->turnOn(controller); + //it->second.lock(); + device = it->second; + d->devices.erase(it); //remove from list, keep reference } - return false; //not found + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else + delete device; + + //1 lås lista + //2 ta bort från registret + //4 plocka ut device ur lista + //* Lås upp lista + //3 vänta på device lås + //{TelldusCore::MutexLocker(&device);} + //6 delete device + + return TELLSTICK_DEVICE_REMOVED; +} + +int DeviceManager::doAction(int deviceId, int action, const std::wstring &data){ + Device *device = 0; + { + //devices locked + TelldusCore::MutexLocker deviceLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + it->second->lock(); //device locked + device = it->second; + } + //devices unlocked + } + + if (!device) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found } + //TODO: Get controller here (controllermanager -> locks its own list, controller -> lock for send etc) + Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); + if(controller){ + int retval = device->doAction(action, data, controller); + device->unlock(); + return retval; + } + else{ + device->unlock(); + return TELLSTICK_ERROR_NOT_FOUND; + } } diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 06f53786..ee3b3c9d 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -2,18 +2,19 @@ #define DEVICEMANAGER_H #include "Device.h" +#include "ControllerManager.h" class DeviceManager { public: - DeviceManager(void); + DeviceManager(ControllerManager *controllerManager); ~DeviceManager(void); int getNumberOfDevices(void); - bool addDevice(); + int addDevice(); int getDeviceId(int deviceIndex); int getPreferredControllerId(int deviceId); - bool removeDevice(int deviceId); - bool turnOn(int deviceId, Controller *controller); + int removeDevice(int deviceId); + int doAction(int deviceId, int action, const std::wstring &data); private: diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 371101a5..896035bb 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -80,7 +80,7 @@ bool Protocol::comparei(std::wstring stringA , std::wstring stringB) Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ - if(comparei(protocolname, L"arctech")){ //TODO: Test this + if(comparei(protocolname, L"arctech")){ return new ProtocolNexa(); //((ProtocolNexa*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); //((ProtocolNexa*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 970d5193..e63bfbea 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -28,9 +28,9 @@ TelldusMain::~TelldusMain(void) { void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); - DeviceManager deviceManager; ControllerManager controllerManager; - + DeviceManager deviceManager(&controllerManager); + ConnectionListener clientListener(L"TelldusClient", clientEvent); //TODO: eventlistener @@ -46,7 +46,7 @@ void TelldusMain::start(void) { ConnectionListenerEventData *data = reinterpret_cast(eventData); if (data) { Event *handlerEvent = d->eventHandler.addEvent(); - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, &controllerManager); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } From 579f42568e8e81ef1ac7763c8da62d71a330756b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 11:54:05 +0000 Subject: [PATCH 0322/2215] Code cleanup, some changed in lock and turnoff implemented. --- .../service/ClientCommunicationHandler.cpp | 8 ++--- telldus-core/service/ControllerManager.cpp | 2 +- telldus-core/service/Device.cpp | 1 + telldus-core/service/DeviceManager.cpp | 36 +++++++++---------- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 3bf588f4..050a308f 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -72,14 +72,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); - //TODO Lock controller and device? (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, L""); - - //TODO: Unlock - } else if (function == L"tdTurnOff") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; //tdTurnOff(deviceId); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, L""); } else if (function == L"tdBell") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -177,7 +173,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 1; // tdMethods(deviceId, intMethodsSupported); + (*intReturn) = 3; // tdMethods(deviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { int intErrorNo = TelldusCore::Message::takeInt(&msg); diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 996b2e56..e46d9d01 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -10,7 +10,7 @@ typedef std::map ControllerMap; class ControllerManager::PrivateData { public: int lastControllerId; - ControllerMap controllers; + ControllerMap controllers; //TODO: Lock for this AND lock in controls, for send etc }; ControllerManager::ControllerManager(){ diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index e26021be..ebd64d3c 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -74,6 +74,7 @@ void Device::setProtocolName(const std::wstring &protocolName){ */ int Device::doAction(int action, const std::wstring &data, Controller *controller) { + //TODO, where to check for supported methods? Protocol *p = this->retrieveProtocol(); if(p){ std::string stringData(data.begin(), data.end()); //conversion needed diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 178c0930..0227db28 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -24,8 +24,8 @@ DeviceManager::~DeviceManager(void) { TelldusCore::MutexLocker locker(&d->lock); for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { - {TelldusCore::MutexLocker lock(it->second);} //aquire lock, and release it, just to see thats it's not in use anywhere - delete( it->second ); + {TelldusCore::MutexLocker lock(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere + delete(it->second); } delete d; } @@ -57,21 +57,17 @@ int DeviceManager::getNumberOfDevices(){ int DeviceManager::addDevice(){ TelldusCore::MutexLocker locker(&d->lock); - Settings set; - - //TODO: Lock? (set too) + int id = d->set.addDevice(); if(id == -1){ return TELLSTICK_ERROR_UNKNOWN; } - //TODO: Lock d->devices[id] = new Device(id); if(!d->devices[id]){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_DEVICE_ADDED; - //release locks } int DeviceManager::getDeviceId(int intDeviceIndex) { @@ -80,19 +76,22 @@ int DeviceManager::getDeviceId(int intDeviceIndex) { } int DeviceManager::getPreferredControllerId(int deviceId){ - TelldusCore::MutexLocker locker(&d->lock); - //TODO: repeating code... - //TODO: Lock - if (!d->devices.size()) { - return TELLSTICK_ERROR_NOT_FOUND; + Device *device = 0; + + { + TelldusCore::MutexLocker locker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + return it->second->getPreferredControllerId(); + } + return TELLSTICK_ERROR_NOT_FOUND; //not found } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - return it->second->getPreferredControllerId(); - } - return TELLSTICK_ERROR_NOT_FOUND; //not found - } int DeviceManager::removeDevice(int deviceId){ @@ -109,7 +108,6 @@ int DeviceManager::removeDevice(int deviceId){ } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - //it->second.lock(); device = it->second; d->devices.erase(it); //remove from list, keep reference } From bd97d8616438db2d7776f2f92bdc73b4d5fd97a0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 12:12:46 +0000 Subject: [PATCH 0323/2215] Added protocol Brateck --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/Protocol.cpp | 12 +++---- telldus-core/service/ProtocolBrateck.cpp | 40 ++++++++++++++++++++++++ telldus-core/service/ProtocolBrateck.h | 12 +++++++ 4 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 telldus-core/service/ProtocolBrateck.cpp create mode 100644 telldus-core/service/ProtocolBrateck.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 4955600b..e52da87b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -16,6 +16,8 @@ SET( telldus-service_SRCS SET( telldus-service_protocol_SRCS Protocol.h Protocol.cpp + ProtocolBrateck.h + ProtocolBrateck.cpp ProtocolNexa.h ProtocolNexa.cpp ) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 896035bb..b2a51498 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,7 +1,9 @@ #include "Protocol.h" #include "../client/telldus-core.h" +#include "ProtocolBrateck.h" #include "ProtocolNexa.h" + #include #include #include @@ -82,15 +84,11 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ if(comparei(protocolname, L"arctech")){ return new ProtocolNexa(); - //((ProtocolNexa*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - //((ProtocolNexa*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); - } - /*else if (wcscasecmp(protocolname.c_str(), L"brateck") == 0) { - prot = new ProtocolBrateck(deviceId, modelname); - ((ProtocolBrateck*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + } else if (comparei(protocolname, L"brateck")) { + return new ProtocolBrateck(); - } else if (wcscasecmp(protocolname.c_str(), L"everflourish") == 0){ + } /*else if (wcscasecmp(protocolname.c_str(), L"everflourish") == 0){ prot = new ProtocolEverflourish(deviceId, modelname); ((ProtocolEverflourish*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); ((ProtocolEverflourish*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp new file mode 100644 index 00000000..4d8662d7 --- /dev/null +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -0,0 +1,40 @@ +#include "ProtocolBrateck.h" + +std::string ProtocolBrateck::getStringForMethod(int method, const std::string &, Controller *) { + const char S = '!'; + const char L = 'V'; + const char B1[] = {L,S,L,S,0}; + const char BX[] = {S,L,L,S,0}; + const char B0[] = {S,L,S,L,0}; + const char BUP[] = {L,S,L,S,S,L,S,L,S,L,S,L,S,L,S,L,S,0}; + const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; + const char BDOWN[] = {S,L,S,L,S,L,S,L,S,L,S,L,L,S,L,S,S,0}; + + std::string strReturn; + std::wstring strHouse = this->getStringParameter(L"house", L""); + if (strHouse == L"") { + return ""; + } + + for( size_t i = 0; i < strHouse.length(); ++i ) { + if (strHouse[i] == '1') { + strReturn.insert(0, B1); + } else if (strHouse[i] == '-') { + strReturn.insert(0, BX); + } else if (strHouse[i] == '0') { + strReturn.insert(0, B0); + } + } + + strReturn.insert(0, "S"); + if (method == TELLSTICK_TURNON) { + strReturn.append(BUP); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(BDOWN); + } else { + return ""; + } + strReturn.append("+"); + + return strReturn; +} diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h new file mode 100644 index 00000000..02985e93 --- /dev/null +++ b/telldus-core/service/ProtocolBrateck.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLBRATECK_H +#define PROTOCOLBRATECK_H + +#include "Protocol.h" + +class ProtocolBrateck : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); +}; + +#endif //PROTOCOLBRATECK_H \ No newline at end of file From 73685a9d5fb3d402e667fb7564c22994d7b8e6dc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 12:23:27 +0000 Subject: [PATCH 0324/2215] Added protocol Everflourish --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 9 +-- telldus-core/service/ProtocolEverflourish.cpp | 81 +++++++++++++++++++ telldus-core/service/ProtocolEverflourish.h | 15 ++++ 4 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 telldus-core/service/ProtocolEverflourish.cpp create mode 100644 telldus-core/service/ProtocolEverflourish.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index e52da87b..3825d51f 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -18,6 +18,8 @@ SET( telldus-service_protocol_SRCS Protocol.cpp ProtocolBrateck.h ProtocolBrateck.cpp + ProtocolEverflourish.h + ProtocolEverflourish.cpp ProtocolNexa.h ProtocolNexa.cpp ) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index b2a51498..53ac8252 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -2,6 +2,7 @@ #include "../client/telldus-core.h" #include "ProtocolBrateck.h" +#include "ProtocolEverflourish.h" #include "ProtocolNexa.h" #include @@ -88,12 +89,10 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"brateck")) { return new ProtocolBrateck(); - } /*else if (wcscasecmp(protocolname.c_str(), L"everflourish") == 0){ - prot = new ProtocolEverflourish(deviceId, modelname); - ((ProtocolEverflourish*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - ((ProtocolEverflourish*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); + } else if (comparei(protocolname, L"everflourish")) { + return new ProtocolEverflourish(); - } else if (wcscasecmp(protocolname.c_str(), L"fuhaote") == 0) { + }/* else if (wcscasecmp(protocolname.c_str(), L"fuhaote") == 0) { prot = new ProtocolFuhaote(deviceId, modelname); ((ProtocolFuhaote*)prot)->setCode(settings.getDeviceParameter(deviceId, "code")); diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp new file mode 100644 index 00000000..076dcd5d --- /dev/null +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -0,0 +1,81 @@ +#include "ProtocolEverflourish.h" + +std::string ProtocolEverflourish::getStringForMethod(int method, const std::string &, Controller *) { + unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383); + unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1; + unsigned char action; + + if (method == TELLSTICK_TURNON) { + action = 15; + } else if (method == TELLSTICK_TURNOFF) { + action = 0; + } else if (method == TELLSTICK_LEARN) { + action = 10; + } else { + return ""; + } + + const char ssss = 85; + const char sssl = 84; // 0 + const char slss = 69; // 1 + + const char bits[2] = {sssl,slss}; + int i, check; + + std::string strCode; + + deviceCode = (deviceCode << 2) | intCode; + + check = calculateChecksum(deviceCode); + + char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss,0}; + strCode.append(preamble); + + for(i=15;i>=0;i--) { + strCode.append(1, bits[(deviceCode>>i)&0x01]); + } + for(i=3;i>=0;i--) { + strCode.append(1, bits[(check>>i)&0x01]); + } + for(i=3;i>=0;i--) { + strCode.append(1, bits[(action>>i)&0x01]); + } + + strCode.append(1, ssss); + strCode.append(1, '+'); + + return strCode; +} + +// The calculation used in this function is provided by Frank Stevenson +unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { + unsigned int bits[16] = { + 0xf ,0xa ,0x7 ,0xe, + 0xf ,0xd ,0x9 ,0x1, + 0x1 ,0x2 ,0x4 ,0x8, + 0x3 ,0x6 ,0xc ,0xb + }; + unsigned int bit = 1; + unsigned int res = 0x5; + int i; + unsigned int lo,hi; + + if ((x&0x3)==3) { + lo = x & 0x00ff; + hi = x & 0xff00; + lo += 4; + if (lo>0x100) { + lo = 0x12; + } + x = lo | hi; + } + + for(i=0;i<16;i++) { + if (x&bit) { + res = res ^ bits[i]; + } + bit = bit << 1; + } + + return res; +} diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h new file mode 100644 index 00000000..97462b90 --- /dev/null +++ b/telldus-core/service/ProtocolEverflourish.h @@ -0,0 +1,15 @@ +#ifndef PROTOCOLEVERFLOURISH_H +#define PROTOCOLEVERFLOURISH_H + +#include "Protocol.h" + +class ProtocolEverflourish : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); + +private: + static unsigned int calculateChecksum(unsigned int x); +}; + +#endif //PROTOCOLEVERFLOURISH_H From 2a7b8c499a1df639567e5c3a97739754ffe7379f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 12:35:03 +0000 Subject: [PATCH 0325/2215] Added protocol Fuhaote --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 8 ++-- telldus-core/service/ProtocolBrateck.h | 2 +- telldus-core/service/ProtocolFuhaote.cpp | 50 ++++++++++++++++++++++++ telldus-core/service/ProtocolFuhaote.h | 12 ++++++ 5 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 telldus-core/service/ProtocolFuhaote.cpp create mode 100644 telldus-core/service/ProtocolFuhaote.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 3825d51f..f87ef77b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -20,6 +20,8 @@ SET( telldus-service_protocol_SRCS ProtocolBrateck.cpp ProtocolEverflourish.h ProtocolEverflourish.cpp + ProtocolFuhaote.h + ProtocolFuhaote.cpp ProtocolNexa.h ProtocolNexa.cpp ) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 53ac8252..e8233b5c 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -3,6 +3,7 @@ #include "ProtocolBrateck.h" #include "ProtocolEverflourish.h" +#include "ProtocolFuhaote.h" #include "ProtocolNexa.h" #include @@ -92,11 +93,10 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"everflourish")) { return new ProtocolEverflourish(); - }/* else if (wcscasecmp(protocolname.c_str(), L"fuhaote") == 0) { - prot = new ProtocolFuhaote(deviceId, modelname); - ((ProtocolFuhaote*)prot)->setCode(settings.getDeviceParameter(deviceId, "code")); + } else if (comparei(protocolname, L"fuhaote")) { + return new ProtocolFuhaote(); - } else if (wcscasecmp(protocolname.c_str(), L"silvanchip") == 0) { + }/* else if (wcscasecmp(protocolname.c_str(), L"silvanchip") == 0) { prot = new ProtocolSilvanChip(deviceId, modelname); ((ProtocolSilvanChip*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index 02985e93..1ed5bf0b 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -3,7 +3,7 @@ #include "Protocol.h" -class ProtocolBrateck : public Protocol +class ProtocolBrateck : public Protocol { public: virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp new file mode 100644 index 00000000..9ef5457b --- /dev/null +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -0,0 +1,50 @@ +#include "ProtocolFuhaote.h" + +std::string ProtocolFuhaote::getStringForMethod(int method, const std::string &, Controller *) { + const char S = 19; + const char L = 58; + const char B0[] = {S,L,L,S,0}; + const char B1[] = {L,S,L,S,0}; + const char OFF[] = {S,L,S,L,S,L,L,S,0}; + const char ON[] = {S,L,L,S,S,L,S,L,0}; + + std::string strReturn; + std::wstring strCode = this->getStringParameter(L"code", L""); + if (strCode == L"") { + return ""; + } + + //House code + for(size_t i = 0; i < 5; ++i) { + if (strCode[i] == '0') { + strReturn.append(B0); + } else if (strCode[i] == '1') { + strReturn.append(B1); + } + } + //Unit code + for(size_t i = 5; i < 10; ++i) { + if (strCode[i] == '0') { + strReturn.append(B0); + } else if (strCode[i] == '1') { + strReturn.append(1, S); + strReturn.append(1, L); + strReturn.append(1, S); + strReturn.append(1, L); + } + } + + if (method == TELLSTICK_TURNON) { + strReturn.append(ON); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(OFF); + } else { + return ""; + } + + strReturn.append(1, S); + strReturn.append("+"); + return strReturn; + +} + diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h new file mode 100644 index 00000000..0233a066 --- /dev/null +++ b/telldus-core/service/ProtocolFuhaote.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLFUHAOTE_H +#define PROTOCOLFUHAOTE_H + +#include "Protocol.h" + +class ProtocolFuhaote : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); +}; + +#endif //PROTOCOLFUHAOTE_H \ No newline at end of file From a26781c8d0eac0c7a1ddbc39b8b09cf2819d70b4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 12:37:09 +0000 Subject: [PATCH 0326/2215] Bell and Dim added --- telldus-core/common/Message.cpp | 8 ++++++++ telldus-core/common/Message.h | 1 + telldus-core/service/ClientCommunicationHandler.cpp | 6 +++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 93e47c6c..7fa009cc 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -42,6 +42,14 @@ void Message::addArgument(const char *value) { } std::wstring Message::charToWstring(const char *value) { + //todo move? + std::wstringstream st; + st << value; + return st.str(); +} + +std::wstring Message::intToWstring(int value) { + //todo move? std::wstringstream st; st << value; return st.str(); diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index d28b43b1..9c8f13e5 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -19,6 +19,7 @@ namespace TelldusCore { std::wstring getClientWStringFromSocket(); static std::wstring charToWstring(const char *value); + static std::wstring intToWstring(int value); static bool nextIsInt(const std::wstring &); static bool nextIsString(const std::wstring &); diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 050a308f..5ee8acc8 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -79,12 +79,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdBell") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdBell(deviceId); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, L""); } else if (function == L"tdDim") { int deviceId = TelldusCore::Message::takeInt(&msg); int level = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdDim(deviceId, level); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, TelldusCore::Message::intToWstring(level)); } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -173,7 +173,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 3; // tdMethods(deviceId, intMethodsSupported); + (*intReturn) = 63; // tdMethods(deviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { int intErrorNo = TelldusCore::Message::takeInt(&msg); From 74543441800f59e4e4bbbe0fbc4df4131cd726e8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 13:04:01 +0000 Subject: [PATCH 0327/2215] Added protocol Ikea, dimming not working yet though. --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 13 +- telldus-core/service/ProtocolIkea.cpp | 220 ++++++++++++++++++++++++++ telldus-core/service/ProtocolIkea.h | 12 ++ 4 files changed, 238 insertions(+), 9 deletions(-) create mode 100644 telldus-core/service/ProtocolIkea.cpp create mode 100644 telldus-core/service/ProtocolIkea.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index f87ef77b..0e5dfe0c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -22,6 +22,8 @@ SET( telldus-service_protocol_SRCS ProtocolEverflourish.cpp ProtocolFuhaote.h ProtocolFuhaote.cpp + ProtocolIkea.h + ProtocolIkea.cpp ProtocolNexa.h ProtocolNexa.cpp ) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index e8233b5c..46dad787 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -4,6 +4,7 @@ #include "ProtocolBrateck.h" #include "ProtocolEverflourish.h" #include "ProtocolFuhaote.h" +#include "ProtocolIkea.h" #include "ProtocolNexa.h" #include @@ -96,14 +97,13 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"fuhaote")) { return new ProtocolFuhaote(); + } else if (comparei(protocolname, L"ikea")) { + return new ProtocolIkea(); + }/* else if (wcscasecmp(protocolname.c_str(), L"silvanchip") == 0) { prot = new ProtocolSilvanChip(deviceId, modelname); ((ProtocolSilvanChip*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - } else if (wcscasecmp(protocolname.c_str(), L"group") == 0) { - prot = new ProtocolGroup(deviceId, modelname); - //TODO: take a closer look - ((ProtocolGroup*)prot)->setDevices(settings.getDeviceParameter(deviceId, "devices")); } else if (wcscasecmp(protocolname.c_str(), L"risingsun") == 0) { prot = new ProtocolRisingSun(deviceId, modelname); @@ -119,11 +119,6 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ prot = new ProtocolSartano(deviceId, modelname); ((ProtocolSartano*)prot)->setCode(settings.getDeviceParameter(deviceId, "code")); - } else if (wcscasecmp(protocolname.c_str(), L"Ikea") == 0) { - prot = new ProtocolIkea(deviceId, modelname); - ((ProtocolIkea*)prot)->setSystem(settings.getDeviceParameter(deviceId, "system")); - ((ProtocolIkea*)prot)->setUnits(settings.getDeviceParameter(deviceId, "units")); - ((ProtocolIkea*)prot)->setFade(settings.getDeviceParameter(deviceId, "fade")); } else if (wcscasecmp(protocolname.c_str(), L"upm") == 0) { prot = new ProtocolUpm(deviceId, modelname); diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp new file mode 100644 index 00000000..c06a3171 --- /dev/null +++ b/telldus-core/service/ProtocolIkea.cpp @@ -0,0 +1,220 @@ +#include "ProtocolIkea.h" + +#ifdef _WINDOWS +#define strcasecmp(x, y) _strcmpi(x, y) +#endif + +/* +bool DeviceIkea::setSystem(const std::string &strSystem) { + if (strSystem.length() > 0) { + intSystem = atoi(strSystem.c_str()) - 1; + } else { + intSystem = 0; + } + return true; +} + +bool DeviceIkea::setUnits(const std::string &strUnits) { + if (strUnits.length() > 0) { + intUnits = 0; //Start without any units + + char *tempUnits = new char[strUnits.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); +#else + strcpy(tempUnits, strUnits.c_str()); +#endif + + char *strToken = strtok(tempUnits, ","); + do { + int intUnit = atoi(strToken); + if (intUnit == 10) { + intUnit = 0; + } + intUnits = intUnits | ( 1<<(9-intUnit) ); + } while ( (strToken = strtok(NULL, ",")) != NULL ); + + free(tempUnits); + } + return true; +} + +bool DeviceIkea::setFade(const std::string &strFadeStyle) { + if (strFadeStyle.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { + intFadeStyle = 1; + } else { + intFadeStyle = 0; + } + return true; +} + + +bool DeviceIkea::setDeviceParameter(const std::string &strName, const std::string &strValue) { + if (strName.compare("system") == 0) { + return setSystem(strValue); + } else if (strName.compare("units") == 0) { + return setUnits(strValue); + } else if (strName.compare("fade") == 0) { + return setFade(strValue); + } + return false; +} + + +int DeviceIkea::turnOn(Controller *controller){ + try{ + std::string strMessage = getStringCode(255); + + return controller->send(strMessage); + } + catch(...){ + throw; + } + return TELLSTICK_ERROR_UNKNOWN; +} + + +int DeviceIkea::turnOff(Controller *controller){ + try{ + std::string strMessage = getStringCode(0); + + return controller->send(strMessage); + } + catch(...){ + throw; + } + return TELLSTICK_ERROR_UNKNOWN; +} + + +int DeviceIkea::dim(unsigned char level, Controller *controller){ + try{ + std::string strMessage = getStringCode(level); + + return controller->send(strMessage); + } + catch(...){ + throw; + } + return TELLSTICK_ERROR_UNKNOWN; +}*/ + +std::string ProtocolIkea::getStringForMethod(int method, const std::string &strLevel, Controller *) { + int intSystem = this->getIntParameter(L"system", 1, 16)-1; + int intFadeStyle = comparei(this->getStringParameter(L"fade", L"true"), L"true"); + std::wstring wstrUnits = this->getStringParameter(L"units", L""); + + unsigned char level; + if (method == TELLSTICK_TURNON) { + level = 255; + } else if (method == TELLSTICK_TURNOFF) { + level = 0; + } else if (method == TELLSTICK_DIM) { + level = 50; //TODO + } else { + return ""; + } + + if (wstrUnits == L"") { + return ""; + } + + std::string strUnits(wstrUnits.begin(), wstrUnits.end()); + int intUnits = 0; //Start without any units + + char *tempUnits = new char[strUnits.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); +#else + strcpy(tempUnits, strUnits.c_str()); +#endif + + char *strToken = strtok(tempUnits, ","); + do { + int intUnit = atoi(strToken); + if (intUnit == 10) { + intUnit = 0; + } + intUnits = intUnits | ( 1<<(9-intUnit) ); + } while ( (strToken = strtok(NULL, ",")) != NULL ); + + free(tempUnits); + + std::string strReturn = "STTTTTTª"; //Startcode, always like this; + + std::string strChannels = ""; + int intCode = (intSystem << 10) | intUnits; + int checksum1 = 0; + int checksum2 = 0; + for (int i = 13; i >= 0; --i) { + if ((intCode>>i) & 1) { + strChannels.append("TT"); + if (i % 2 == 0) + checksum2++; + else + checksum1++; + } else { + strChannels.append("ª"); + } + } + strReturn.append(strChannels); //System + Units + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + int intLevel = 0; + if (level <= 12) { + intLevel = 10; // Level 10 is actually off + } else if (level <= 37) { + intLevel = 1; + } else if (level <= 62) { + intLevel = 2; + } else if (level <= 87) { + intLevel = 3; + } else if (level <= 112) { + intLevel = 4; + } else if (level <= 137) { + intLevel = 5; + } else if (level <= 162) { + intLevel = 6; + } else if (level <= 187) { + intLevel = 7; + } else if (level <= 212) { + intLevel = 8; + } else if (level <= 237) { + intLevel = 9; + } else { + intLevel = 0; // Level 0 is actually full on + } + + int intFade = 0; + if (intFadeStyle == 1) { + intFade = 11 << 4; //Smooth + } else { + intFade = 1 << 4; //Instant + } + + intCode = intLevel | intFade; //Concat level and fade + + checksum1 = 0; + checksum2 = 0; + for (int i = 0; i < 6; ++i) { + if ((intCode>>i) & 1) { + strReturn.append("TT"); + if (i % 2 == 0) + checksum1++; + else + checksum2++; + } else { + strReturn.append("ª"); + } + } + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + strReturn.append("+"); + + return strReturn; + +} diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h new file mode 100644 index 00000000..ff19dfc2 --- /dev/null +++ b/telldus-core/service/ProtocolIkea.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLIKEA_H +#define PROTOCOLIKEA_H + +#include "Protocol.h" + +class ProtocolIkea : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); +}; + +#endif //PROTOCOLIKEA_H \ No newline at end of file From d7fd0d03fc911dc433f7878fff19b9bf9928915a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 13:11:28 +0000 Subject: [PATCH 0328/2215] GetDeviceType and some code cleanup --- .../service/ClientCommunicationHandler.cpp | 19 +++++++----- telldus-core/service/DeviceManager.cpp | 31 ++++++++++--------- telldus-core/service/DeviceManager.h | 1 + 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 5ee8acc8..38f8b9fd 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -88,16 +88,16 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; //tdLearn(deviceId); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, L""); } else if (function == L"tdLastSentCommand") { int deviceId = TelldusCore::Message::takeInt(&msg); int methodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdLastSentCommand(deviceId, methodsSupported); + (*intReturn) = 0; // tdLastSentCommand(deviceId, methodsSupported); TODO } else if (function == L"tdLastSentValue") { int deviceId = TelldusCore::Message::takeInt(&msg); - const char *value = ""; //tdLastSentValue(deviceId); + const char *value = ""; //tdLastSentValue(deviceId); TODO (*wstringReturn) = TelldusCore::Message::charToWstring(value); } else if(function == L"tdGetNumberOfDevices"){ @@ -105,13 +105,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*intReturn) = d->deviceManager->getNumberOfDevices(); } else if (function == L"tdGetDeviceId") { - int deviceIndex = TelldusCore::Message::takeInt(&msg); - + int deviceIndex = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->getDeviceId(deviceIndex); } else if (function == L"tdGetDeviceType") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 11; // tdGetDeviceType(deviceId); + (*intReturn) = d->deviceManager->getDeviceType(deviceId); } else if (function == L"tdGetName") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -122,6 +121,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); (*intReturn) = 0; //tdSetName(deviceId, name.c_str()); + //TODO, signal event } else if (function == L"tdGetProtocol") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -132,6 +132,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring protocol = TelldusCore::Message::takeString(&msg); (*intReturn) = 0; // tdSetProtocol(deviceId, protocol.c_str()); + //TODO, signal event } else if (function == L"tdGetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -142,12 +143,14 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring model = TelldusCore::Message::takeString(&msg); (*intReturn) = 0; // tdSetModel(deviceId, model.c_str()); + //TODO, signal event } else if (function == L"tdSetDeviceParameter") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring value = TelldusCore::Message::takeString(&msg); (*intReturn) = 0; //tdSetDeviceParameter(deviceId, name.c_str(), value.c_str()); + //TODO, signal event } else if (function == L"tdGetDeviceParameter") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -191,6 +194,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, std::wstring serial = TelldusCore::Message::takeString(&msg); //tdConnectTellStickController(vid, pid, serial.c_str()); (*wstringReturn) = L""; + //TODO, signal event? Or done in other place? } else if (function == L"tdDisconnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); @@ -198,10 +202,11 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, std::wstring serial = TelldusCore::Message::takeString(&msg); //tdDisconnectTellStickController(vid, pid, serial.c_str()); (*wstringReturn) = L""; + //TODO, signal event? Or done in other place? } else{ - (*intReturn) = 6; + (*intReturn) = TELLSTICK_ERROR_UNKNOWN; } } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 0227db28..54df2ec6 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -70,28 +70,29 @@ int DeviceManager::addDevice(){ return TELLSTICK_DEVICE_ADDED; } -int DeviceManager::getDeviceId(int intDeviceIndex) { +int DeviceManager::getDeviceId(int deviceIndex) { TelldusCore::MutexLocker locker(&d->lock); - return d->set.getDeviceId(intDeviceIndex); + return d->set.getDeviceId(deviceIndex); +} + +int DeviceManager::getDeviceType(int deviceId){ + + return TELLSTICK_TYPE_DEVICE; } int DeviceManager::getPreferredControllerId(int deviceId){ - Device *device = 0; + TelldusCore::MutexLocker locker(&d->lock); - { - TelldusCore::MutexLocker locker(&d->lock); - - if (!d->devices.size()) { - return TELLSTICK_ERROR_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? - return it->second->getPreferredControllerId(); - } - return TELLSTICK_ERROR_NOT_FOUND; //not found + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + return it->second->getPreferredControllerId(); + } + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found } int DeviceManager::removeDevice(int deviceId){ diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index ee3b3c9d..cb3f8dee 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -12,6 +12,7 @@ public: int getNumberOfDevices(void); int addDevice(); int getDeviceId(int deviceIndex); + int getDeviceType(int deviceId); int getPreferredControllerId(int deviceId); int removeDevice(int deviceId); int doAction(int deviceId, int action, const std::wstring &data); From 39ae8ba0e7353c0913c9576698ac2ec47613caad Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 13:35:23 +0000 Subject: [PATCH 0329/2215] Dim support added. Some refactoring was needed. --- .../service/ClientCommunicationHandler.cpp | 8 +- telldus-core/service/Device.cpp | 5 +- telldus-core/service/Device.h | 2 +- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/DeviceManager.h | 2 +- telldus-core/service/Protocol.h | 2 +- telldus-core/service/ProtocolBrateck.cpp | 2 +- telldus-core/service/ProtocolBrateck.h | 2 +- telldus-core/service/ProtocolEverflourish.cpp | 2 +- telldus-core/service/ProtocolEverflourish.h | 2 +- telldus-core/service/ProtocolFuhaote.cpp | 2 +- telldus-core/service/ProtocolFuhaote.h | 2 +- telldus-core/service/ProtocolIkea.cpp | 103 +----------------- telldus-core/service/ProtocolIkea.h | 2 +- telldus-core/service/ProtocolNexa.cpp | 8 +- telldus-core/service/ProtocolNexa.h | 10 +- 16 files changed, 29 insertions(+), 127 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 38f8b9fd..4626aaca 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -72,19 +72,19 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, L""); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); } else if (function == L"tdTurnOff") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, L""); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0); } else if (function == L"tdBell") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, L""); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0); } else if (function == L"tdDim") { int deviceId = TelldusCore::Message::takeInt(&msg); int level = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, TelldusCore::Message::intToWstring(level)); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, level); } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index ebd64d3c..a8639ffe 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -73,12 +73,11 @@ void Device::setProtocolName(const std::wstring &protocolName){ * End Get-/Set */ -int Device::doAction(int action, const std::wstring &data, Controller *controller) { +int Device::doAction(int action, unsigned char data, Controller *controller) { //TODO, where to check for supported methods? Protocol *p = this->retrieveProtocol(); if(p){ - std::string stringData(data.begin(), data.end()); //conversion needed - std::string code = p->getStringForMethod(action, stringData, controller); + std::string code = p->getStringForMethod(action, data, controller); controller->send(code); } return 0; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 5bd1310b..1f108b40 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -22,7 +22,7 @@ public: void setPreferredControllerId(int controllerId); std::wstring getProtocolName(); void setProtocolName(const std::wstring &name); - int doAction(int action, const std::wstring &data, Controller *controller); + int doAction(int action, unsigned char data, Controller *controller); private: diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 54df2ec6..81137618 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -130,7 +130,7 @@ int DeviceManager::removeDevice(int deviceId){ return TELLSTICK_DEVICE_REMOVED; } -int DeviceManager::doAction(int deviceId, int action, const std::wstring &data){ +int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Device *device = 0; { //devices locked diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index cb3f8dee..6e4116a3 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -15,7 +15,7 @@ public: int getDeviceType(int deviceId); int getPreferredControllerId(int deviceId); int removeDevice(int deviceId); - int doAction(int deviceId, int action, const std::wstring &data); + int doAction(int deviceId, int action, unsigned char data); private: diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index a054c807..8f79c917 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -21,7 +21,7 @@ public: void setModel(const std::wstring &model); void setParameters(ParameterMap ¶meterList); - virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller) = 0; + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0; protected: std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 4d8662d7..49577761 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -1,6 +1,6 @@ #include "ProtocolBrateck.h" -std::string ProtocolBrateck::getStringForMethod(int method, const std::string &, Controller *) { +std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) { const char S = '!'; const char L = 'V'; const char B1[] = {L,S,L,S,0}; diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index 1ed5bf0b..205a2aa3 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -6,7 +6,7 @@ class ProtocolBrateck : public Protocol { public: - virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; #endif //PROTOCOLBRATECK_H \ No newline at end of file diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 076dcd5d..dd526691 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -1,6 +1,6 @@ #include "ProtocolEverflourish.h" -std::string ProtocolEverflourish::getStringForMethod(int method, const std::string &, Controller *) { +std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, Controller *) { unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383); unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1; unsigned char action; diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 97462b90..be234f98 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -6,7 +6,7 @@ class ProtocolEverflourish : public Protocol { public: - virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); private: static unsigned int calculateChecksum(unsigned int x); diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index 9ef5457b..a79f190e 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -1,6 +1,6 @@ #include "ProtocolFuhaote.h" -std::string ProtocolFuhaote::getStringForMethod(int method, const std::string &, Controller *) { +std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) { const char S = 19; const char L = 58; const char B0[] = {S,L,L,S,0}; diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index 0233a066..e63ca979 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -6,7 +6,7 @@ class ProtocolFuhaote : public Protocol { public: - virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; #endif //PROTOCOLFUHAOTE_H \ No newline at end of file diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index c06a3171..e1bdc8ea 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -1,116 +1,15 @@ #include "ProtocolIkea.h" -#ifdef _WINDOWS -#define strcasecmp(x, y) _strcmpi(x, y) -#endif - -/* -bool DeviceIkea::setSystem(const std::string &strSystem) { - if (strSystem.length() > 0) { - intSystem = atoi(strSystem.c_str()) - 1; - } else { - intSystem = 0; - } - return true; -} - -bool DeviceIkea::setUnits(const std::string &strUnits) { - if (strUnits.length() > 0) { - intUnits = 0; //Start without any units - - char *tempUnits = new char[strUnits.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); -#else - strcpy(tempUnits, strUnits.c_str()); -#endif - - char *strToken = strtok(tempUnits, ","); - do { - int intUnit = atoi(strToken); - if (intUnit == 10) { - intUnit = 0; - } - intUnits = intUnits | ( 1<<(9-intUnit) ); - } while ( (strToken = strtok(NULL, ",")) != NULL ); - - free(tempUnits); - } - return true; -} - -bool DeviceIkea::setFade(const std::string &strFadeStyle) { - if (strFadeStyle.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { - intFadeStyle = 1; - } else { - intFadeStyle = 0; - } - return true; -} - - -bool DeviceIkea::setDeviceParameter(const std::string &strName, const std::string &strValue) { - if (strName.compare("system") == 0) { - return setSystem(strValue); - } else if (strName.compare("units") == 0) { - return setUnits(strValue); - } else if (strName.compare("fade") == 0) { - return setFade(strValue); - } - return false; -} - - -int DeviceIkea::turnOn(Controller *controller){ - try{ - std::string strMessage = getStringCode(255); - - return controller->send(strMessage); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - - -int DeviceIkea::turnOff(Controller *controller){ - try{ - std::string strMessage = getStringCode(0); - - return controller->send(strMessage); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -} - - -int DeviceIkea::dim(unsigned char level, Controller *controller){ - try{ - std::string strMessage = getStringCode(level); - - return controller->send(strMessage); - } - catch(...){ - throw; - } - return TELLSTICK_ERROR_UNKNOWN; -}*/ - -std::string ProtocolIkea::getStringForMethod(int method, const std::string &strLevel, Controller *) { +std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { int intSystem = this->getIntParameter(L"system", 1, 16)-1; int intFadeStyle = comparei(this->getStringParameter(L"fade", L"true"), L"true"); std::wstring wstrUnits = this->getStringParameter(L"units", L""); - unsigned char level; if (method == TELLSTICK_TURNON) { level = 255; } else if (method == TELLSTICK_TURNOFF) { level = 0; } else if (method == TELLSTICK_DIM) { - level = 50; //TODO } else { return ""; } diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index ff19dfc2..31713941 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -6,7 +6,7 @@ class ProtocolIkea : public Protocol { public: - virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; #endif //PROTOCOLIKEA_H \ No newline at end of file diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 9236f667..f1063762 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,6 +1,6 @@ #include "ProtocolNexa.h" -std::string ProtocolNexa::getStringForMethod(int method, const std::string &data, Controller *) { +std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *) { if (!comparei(model(), L"codeswitch")) { return getStringSelflearning(method, data); } @@ -25,7 +25,7 @@ std::string ProtocolNexa::getStringCodeSwitch(int method) { return strReturn; } -std::string ProtocolNexa::getStringSelflearning(int method, const std::string &data) { +std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { const char START[] = {'T',127,255,24,1,0}; // const char START[] = {'T',130,255,26,24,0}; @@ -56,10 +56,10 @@ std::string ProtocolNexa::getStringSelflearning(int method, const std::string &d } if (method == TELLSTICK_DIM) { - /*unsigned char newLevel = level/16; + unsigned char newLevel = level/16; for (int i = 3; i >= 0; --i) { m.append(newLevel & 1 << i ? "10" : "01"); - }*/ + } } //The number of data is odd. diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index d4dd546b..4b75394b 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -1,13 +1,17 @@ -#pragma once +#ifndef PROTOCOLNEXA_H +#define PROTOCOLNEXA_H + #include "Device.h" #include class ProtocolNexa : public Protocol { public: - virtual std::string getStringForMethod(int method, const std::string &data, Controller *controller); + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); protected: - std::string getStringSelflearning(int method, const std::string &data); + std::string getStringSelflearning(int method, unsigned char data); std::string getStringCodeSwitch(int method); static std::string getCodeSwitchTuple(int code); }; + +#endif //PROTOCOLNEXA_H From 062398511dd11e0157ae7c172a9177c6313be0af Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 13:37:32 +0000 Subject: [PATCH 0330/2215] Small fix after refactoring. --- telldus-core/service/ClientCommunicationHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 4626aaca..17318f7b 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -88,7 +88,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, L""); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); } else if (function == L"tdLastSentCommand") { int deviceId = TelldusCore::Message::takeInt(&msg); From 03c5d8beb5d605c0c87893253b4dd0aaed6761e8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 13:42:40 +0000 Subject: [PATCH 0331/2215] Set/get name --- .../service/ClientCommunicationHandler.cpp | 5 +-- telldus-core/service/DeviceManager.cpp | 42 ++++++++++++++++++- telldus-core/service/DeviceManager.h | 2 + 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 17318f7b..6d4f4df7 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -114,13 +114,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdGetName") { int deviceId = TelldusCore::Message::takeInt(&msg); - const char *name = "Default name"; //tdGetName(deviceId); - (*wstringReturn) = TelldusCore::Message::charToWstring(name); + (*wstringReturn) = d->deviceManager->getDeviceName(deviceId); } else if (function == L"tdSetName") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; //tdSetName(deviceId, name.c_str()); + (*intReturn) = d->deviceManager->setDeviceName(deviceId, name); //TODO, signal event } else if (function == L"tdGetProtocol") { diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 81137618..727c9271 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -50,6 +50,46 @@ void DeviceManager::fillDevices(){ } } +std::wstring DeviceManager::getDeviceName(int deviceId){ + + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; //TODO, what? + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + return it->second->getName(); + } + return L"UNKNOWN"; //TODO, what? +} + +int DeviceManager::setDeviceName(int deviceId, std::wstring name){ + + //TODO: check this locking, ok? + Device *device = 0; + { + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + device = it->second; + d->set.setName(deviceId, name); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + if(device){ + TelldusCore::MutexLocker lock(device); + device->setName(name); + } + + return TELLSTICK_SUCCESS; +} + int DeviceManager::getNumberOfDevices(){ TelldusCore::MutexLocker locker(&d->lock); return (int)d->devices.size(); @@ -92,7 +132,7 @@ int DeviceManager::getPreferredControllerId(int deviceId){ //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? return it->second->getPreferredControllerId(); } - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } int DeviceManager::removeDevice(int deviceId){ diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 6e4116a3..7f9d7569 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -12,6 +12,8 @@ public: int getNumberOfDevices(void); int addDevice(); int getDeviceId(int deviceIndex); + std::wstring getDeviceName(int deviceId); + int setDeviceName(int deviceId, std::wstring name); int getDeviceType(int deviceId); int getPreferredControllerId(int deviceId); int removeDevice(int deviceId); From c297c67db63e8fe7b27845d613c9c02ab5dfe1b3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 15:14:09 +0000 Subject: [PATCH 0332/2215] Send the right type of message. This creates a huge bottleneck otherwise ;) --- telldus-core/client/telldus-core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index f65d4206..1e370df9 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -180,7 +180,7 @@ int WINAPI tdLearn(int intDeviceId) { * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF */ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { - TelldusCore::Message msg(L"tdLearn"); + TelldusCore::Message msg(L"tdLastSentCommand"); msg.addArgument(intDeviceId); msg.addArgument(methodsSupported); return msg.getClientIntegerFromSocket(); From f46c713fa4bcaaf9607b8dc84138bb1ed36e78e0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 15:14:27 +0000 Subject: [PATCH 0333/2215] Fixed compiler warning --- telldus-core/common/Message.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 7fa009cc..818110d9 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -74,7 +74,7 @@ std::wstring Message::takeString(std::wstring *message) { if (!Message::nextIsString(*message)) { return L""; } - int index = message->find(':'); + size_t index = message->find(':'); int length = wideToInteger(message->substr(0, index)); std::wstring retval(message->substr(index+1, length)); message->erase(0, index+length+1); @@ -85,7 +85,7 @@ int Message::takeInt(std::wstring *message) { if (!Message::nextIsInt(*message)) { return 0; } - int index = message->find('s'); + size_t index = message->find('s'); int value = wideToInteger(message->substr(1, index - 1)); message->erase(0, index+1); return value; From ae2161df79561ce34b23dbc42887af6791fa849a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 15:19:03 +0000 Subject: [PATCH 0334/2215] Fixed bug, correct string stored in register --- telldus-core/service/SettingsWinRegistry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index e7360fc9..7c1a4370 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -200,7 +200,7 @@ bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS){ - int length = (int)value.length(); + int length = (int)value.length() * sizeof(wchar_t); RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); } RegCloseKey(hk); From bbb186924f92449e3b220c41a784e666dd385999 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 15:19:24 +0000 Subject: [PATCH 0335/2215] Get/set protocol implemented --- .../service/ClientCommunicationHandler.cpp | 5 +-- telldus-core/service/DeviceManager.cpp | 40 +++++++++++++++++++ telldus-core/service/DeviceManager.h | 2 + 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 6d4f4df7..1782456a 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -124,13 +124,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdGetProtocol") { int deviceId = TelldusCore::Message::takeInt(&msg); - const char *protocol = "Default protocol"; //tdGetProtocol(deviceId); - (*wstringReturn) = TelldusCore::Message::charToWstring(protocol); + (*wstringReturn) = d->deviceManager->getDeviceProtocol(deviceId); } else if (function == L"tdSetProtocol") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring protocol = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; // tdSetProtocol(deviceId, protocol.c_str()); + (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); //TODO, signal event } else if (function == L"tdGetModel") { diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 727c9271..56d8ccf0 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -90,6 +90,46 @@ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ return TELLSTICK_SUCCESS; } +std::wstring DeviceManager::getDeviceProtocol(int deviceId){ + + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; //TODO, what? + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + return it->second->getProtocolName(); + } + return L"UNKNOWN"; //TODO, what? +} + +int DeviceManager::setDeviceProtocol(int deviceId, std::wstring protocol) +{ + //TODO: check this locking, ok? + Device *device = 0; + { + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + device = it->second; + d->set.setProtocol(deviceId, protocol); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + if(device){ + TelldusCore::MutexLocker lock(device); + device->setProtocolName(protocol); + } + + return TELLSTICK_SUCCESS; +} + int DeviceManager::getNumberOfDevices(){ TelldusCore::MutexLocker locker(&d->lock); return (int)d->devices.size(); diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 7f9d7569..b1118cec 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -14,6 +14,8 @@ public: int getDeviceId(int deviceIndex); std::wstring getDeviceName(int deviceId); int setDeviceName(int deviceId, std::wstring name); + std::wstring getDeviceProtocol(int deviceId); + int setDeviceProtocol(int deviceId, std::wstring name); int getDeviceType(int deviceId); int getPreferredControllerId(int deviceId); int removeDevice(int deviceId); From ba56775c59e85104f164192804f8b5e64554c2b9 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 15:35:18 +0000 Subject: [PATCH 0336/2215] Get/set model --- .../service/ClientCommunicationHandler.cpp | 5 +-- telldus-core/service/DeviceManager.cpp | 40 +++++++++++++++++++ telldus-core/service/DeviceManager.h | 2 + 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 1782456a..b60368a8 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -134,13 +134,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdGetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); - const char *model = "Default model"; //tdGetModel(deviceId); - (*wstringReturn) = TelldusCore::Message::charToWstring(model); + (*wstringReturn) = d->deviceManager->getDeviceModel(deviceId); } else if (function == L"tdSetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring model = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; // tdSetModel(deviceId, model.c_str()); + (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); //TODO, signal event } else if (function == L"tdSetDeviceParameter") { diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 56d8ccf0..e1ab348a 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -50,6 +50,46 @@ void DeviceManager::fillDevices(){ } } +std::wstring DeviceManager::getDeviceModel(int deviceId){ + + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; //TODO, what? + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + return it->second->getModel(); + } + return L"UNKNOWN"; //TODO, what? +} + +int DeviceManager::setDeviceModel(int deviceId, std::wstring model) +{ + //TODO: check this locking, ok? + Device *device = 0; + { + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + device = it->second; + d->set.setModel(deviceId, model); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + if(device){ + TelldusCore::MutexLocker lock(device); + device->setModel(model); + } + + return TELLSTICK_SUCCESS; +} + std::wstring DeviceManager::getDeviceName(int deviceId){ TelldusCore::MutexLocker locker(&d->lock); diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index b1118cec..7a9892e0 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -12,6 +12,8 @@ public: int getNumberOfDevices(void); int addDevice(); int getDeviceId(int deviceIndex); + std::wstring getDeviceModel(int deviceId); + int setDeviceModel(int deviceId, std::wstring model); std::wstring getDeviceName(int deviceId); int setDeviceName(int deviceId, std::wstring name); std::wstring getDeviceProtocol(int deviceId); From 798a5b008c4051ad6a3c2c2666278a3c956ab1be Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 14 Oct 2010 16:02:25 +0000 Subject: [PATCH 0337/2215] Set/get parameter --- .../service/ClientCommunicationHandler.cpp | 17 ++++--- telldus-core/service/DeviceManager.cpp | 45 +++++++++++++++++++ telldus-core/service/DeviceManager.h | 2 + 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index b60368a8..f2c01efc 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -142,19 +142,18 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); //TODO, signal event - } else if (function == L"tdSetDeviceParameter") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - std::wstring value = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; //tdSetDeviceParameter(deviceId, name.c_str(), value.c_str()); - //TODO, signal event - } else if (function == L"tdGetDeviceParameter") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring defaultValue = TelldusCore::Message::takeString(&msg); - const char *value = "Device parameter default"; //tdGetDeviceParameter(deviceId, name.c_str(), defaultValue.c_str()); - (*wstringReturn) = TelldusCore::Message::charToWstring(value); + (*wstringReturn) = d->deviceManager->getDeviceParameter(deviceId, name, defaultValue); + + } else if (function == L"tdSetDeviceParameter") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring value = TelldusCore::Message::takeString(&msg); + (*intReturn) = 0; d->deviceManager->setDeviceParameter(deviceId, name, value); + //TODO, signal event } else if (function == L"tdAddDevice") { //TODO: Lock diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index e1ab348a..144b0bf9 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -85,6 +85,7 @@ int DeviceManager::setDeviceModel(int deviceId, std::wstring model) if(device){ TelldusCore::MutexLocker lock(device); device->setModel(model); + //TODO Reset protocol here? } return TELLSTICK_SUCCESS; @@ -130,6 +131,50 @@ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ return TELLSTICK_SUCCESS; } +std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, std::wstring defaultValue){ + + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return defaultValue; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()){ + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + std::wstring returnString = it->second->getParameter(name); + if(returnString != L""){ + return returnString; + } + } + return defaultValue; +} + +int DeviceManager::setDeviceParameter(int deviceId, std::wstring name, std::wstring value) +{ + //TODO: check this locking, ok? + Device *device = 0; + { + TelldusCore::MutexLocker locker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + device = it->second; + d->set.setDeviceParameter(deviceId, name, value); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + if(device){ + TelldusCore::MutexLocker lock(device); + device->setParameter(name, value); + //TODO Reset protocol here? + } + + return TELLSTICK_SUCCESS; +} + std::wstring DeviceManager::getDeviceProtocol(int deviceId){ TelldusCore::MutexLocker locker(&d->lock); diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 7a9892e0..d47ce1f1 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -16,6 +16,8 @@ public: int setDeviceModel(int deviceId, std::wstring model); std::wstring getDeviceName(int deviceId); int setDeviceName(int deviceId, std::wstring name); + std::wstring getDeviceParameter(int deviceId, std::wstring name, std::wstring defauleValue); + int setDeviceParameter(int deviceId, std::wstring name, std::wstring value); std::wstring getDeviceProtocol(int deviceId); int setDeviceProtocol(int deviceId, std::wstring name); int getDeviceType(int deviceId); From 5b290de4df3ae696dd374b9010e741ea8d0e995e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 16:06:28 +0000 Subject: [PATCH 0338/2215] Added protocol RisingSun. --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 8 +- telldus-core/service/ProtocolRisingSun.cpp | 103 +++++++++++++++++++++ telldus-core/service/ProtocolRisingSun.h | 17 ++++ 4 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 telldus-core/service/ProtocolRisingSun.cpp create mode 100644 telldus-core/service/ProtocolRisingSun.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 0e5dfe0c..00f324ef 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -26,6 +26,8 @@ SET( telldus-service_protocol_SRCS ProtocolIkea.cpp ProtocolNexa.h ProtocolNexa.cpp + ProtocolRisingSun.h + ProtocolRisingSun.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 46dad787..8b94c327 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -6,6 +6,7 @@ #include "ProtocolFuhaote.h" #include "ProtocolIkea.h" #include "ProtocolNexa.h" +#include "ProtocolRisingSun.h" #include #include @@ -100,15 +101,14 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"ikea")) { return new ProtocolIkea(); + } else if (comparei(protocolname, L"risingsun")) { + return new ProtocolRisingSun(); + }/* else if (wcscasecmp(protocolname.c_str(), L"silvanchip") == 0) { prot = new ProtocolSilvanChip(deviceId, modelname); ((ProtocolSilvanChip*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - } else if (wcscasecmp(protocolname.c_str(), L"risingsun") == 0) { - prot = new ProtocolRisingSun(deviceId, modelname); - ((ProtocolRisingSun*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - ((ProtocolRisingSun*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); } else if (wcscasecmp(protocolname.c_str(), L"Waveman") == 0) { prot = new ProtocolWaveman(deviceId, modelname); diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp new file mode 100644 index 00000000..41ee406e --- /dev/null +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -0,0 +1,103 @@ +#include "ProtocolRisingSun.h" + +std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) { + if (comparei(model(), L"selflearning")) { + return getStringSelflearning(method); + } + return getStringCodeSwitch(method); +} + +std::string ProtocolRisingSun::getStringSelflearning(int method) { + int intHouse = this->getIntParameter(L"house", 1, 33554432)-1; + int intCode = this->getIntParameter(L"code", 1, 16)-1; + + const char code_on[][7] = { + "110110", "001110", "100110", "010110", + "111001", "000101", "101001", "011001", + "110000", "001000", "100000", "010000", + "111100", "000010", "101100", "011100" + }; + const char code_off[][7] = { + "111110", "000001", "101110", "011110", + "110101", "001101", "100101", "010101", + "111000", "000100", "101000", "011000", + "110010", "001010", "100010", "010010" + }; + const char l = 120; + const char s = 51; + + std::string strCode = "10"; + int code = intCode; + code = (code < 0 ? 0 : code); + code = (code > 15 ? 15 : code); + if (method == TELLSTICK_TURNON) { + strCode.append(code_on[code]); + } else if (method == TELLSTICK_TURNOFF) { + strCode.append(code_off[code]); + } else if (method == TELLSTICK_LEARN) { + strCode.append(code_on[code]); + } else { + return ""; + } + + int house = intHouse; + for(int i = 0; i < 25; ++i) { + if (house & 1) { + strCode.append(1, '1'); + } else { + strCode.append(1, '0'); + } + house >>= 1; + } + + std::string strReturn; + for(unsigned int i = 0; i < strCode.length(); ++i) { + if (strCode[i] == '1') { + strReturn.append(1, l); + strReturn.append(1, s); + } else { + strReturn.append(1, s); + strReturn.append(1, l); + } + } + + std::string prefix = "P"; + prefix.append(1, 5); + if (method == TELLSTICK_LEARN) { + prefix.append("R"); + prefix.append( 1, 50 ); + } + prefix.append("S"); + strReturn.insert(0, prefix); + strReturn.append(1, '+'); + return strReturn; +} + +std::string ProtocolRisingSun::getStringCodeSwitch(int method) { + std::string strReturn = "S.e"; + strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4))); + strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4))); + if (method == TELLSTICK_TURNON) { + strReturn.append("e..ee..ee..ee..e+"); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append("e..ee..ee..e.e.e+"); + } else { + return ""; + } + return strReturn; + +} + +std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) { + + std::string strReturn = ""; + for(int i = 0; i < 4; ++i) { + if (i == intToConvert) { + strReturn.append( ".e.e" ); + } else { + strReturn.append( "e..e" ); + } + } + return strReturn; + +} diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h new file mode 100644 index 00000000..4ecc4b2c --- /dev/null +++ b/telldus-core/service/ProtocolRisingSun.h @@ -0,0 +1,17 @@ +#ifndef PROTOCOLRISINGSUN_H +#define PROTOCOLRISINGSUN_H + +#include "Protocol.h" + +class ProtocolRisingSun : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +protected: + std::string getStringSelflearning(int method); + std::string getStringCodeSwitch(int method); + static std::string getCodeSwitchTuple(int code); +}; + +#endif //PROTOCOLRISINGSUN_H \ No newline at end of file From f4350244d52f8fdc550cbf45c82a481f7f7d9985 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Oct 2010 22:36:48 +0000 Subject: [PATCH 0339/2215] Fixed some compile warnings --- telldus-core/common/Socket_unix.cpp | 4 ++-- telldus-core/service/ConnectionListener_unix.cpp | 2 +- telldus-core/service/EventHandler_unix.cpp | 1 + telldus-core/service/ProtocolBrateck.cpp | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index cc7250f5..6fe6f28f 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -9,7 +9,7 @@ using namespace TelldusCore; int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - connect(sockfd, addr, addrlen); + return connect(sockfd, addr, addrlen); } class Socket::PrivateData { @@ -53,7 +53,7 @@ std::wstring Socket::read() { char inbuf[BUFSIZE]; memset(inbuf, '\0', sizeof(inbuf)); - size_t inlen = recv(d->socket, inbuf, BUFSIZE - 1, 0); + recv(d->socket, inbuf, BUFSIZE - 1, 0); std::string msg(inbuf); return std::wstring(msg.begin(), msg.end()); diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 00444a46..75ea9483 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -39,7 +39,7 @@ void ConnectionListener::run(){ //Timeout for select SOCKET_T serverSocket; - struct sockaddr_un remote, name; + struct sockaddr_un name; socklen_t len; serverSocket = socket(PF_LOCAL, SOCK_STREAM, 0); if (serverSocket < 0) { diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index 974d16ac..d74861fb 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -30,6 +30,7 @@ Event *EventHandler::addEvent() { } bool EventHandler::removeEvent(EventBase *event) { + return true; } void EventHandler::signal(Event *event) { diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 49577761..960c0499 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -7,7 +7,7 @@ std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Contr const char BX[] = {S,L,L,S,0}; const char B0[] = {S,L,S,L,0}; const char BUP[] = {L,S,L,S,S,L,S,L,S,L,S,L,S,L,S,L,S,0}; - const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; + //const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; const char BDOWN[] = {S,L,S,L,S,L,S,L,S,L,S,L,L,S,L,S,S,0}; std::string strReturn; From da58fa63e405b8312da3031af7885900c5e50964 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 07:54:26 +0000 Subject: [PATCH 0340/2215] Added protocol Sartano --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/Protocol.cpp | 9 ++++---- telldus-core/service/ProtocolSartano.cpp | 26 ++++++++++++++++++++++++ telldus-core/service/ProtocolSartano.h | 12 +++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 telldus-core/service/ProtocolSartano.cpp create mode 100644 telldus-core/service/ProtocolSartano.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 00f324ef..213b12fd 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -28,6 +28,8 @@ SET( telldus-service_protocol_SRCS ProtocolNexa.cpp ProtocolRisingSun.h ProtocolRisingSun.cpp + ProtocolSartano.h + ProtocolSartano.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 8b94c327..a2133d32 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -7,6 +7,7 @@ #include "ProtocolIkea.h" #include "ProtocolNexa.h" #include "ProtocolRisingSun.h" +#include "ProtocolSartano.h" #include #include @@ -104,6 +105,10 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"risingsun")) { return new ProtocolRisingSun(); + } else if (comparei(protocolname, L"sartano")) { + return new ProtocolSartano(); + + }/* else if (wcscasecmp(protocolname.c_str(), L"silvanchip") == 0) { prot = new ProtocolSilvanChip(deviceId, modelname); ((ProtocolSilvanChip*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); @@ -115,10 +120,6 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ ((ProtocolWaveman*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); ((ProtocolWaveman*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); - } else if (wcscasecmp(protocolname.c_str(), L"Sartano") == 0) { - prot = new ProtocolSartano(deviceId, modelname); - ((ProtocolSartano*)prot)->setCode(settings.getDeviceParameter(deviceId, "code")); - } else if (wcscasecmp(protocolname.c_str(), L"upm") == 0) { prot = new ProtocolUpm(deviceId, modelname); diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp new file mode 100644 index 00000000..088e4b56 --- /dev/null +++ b/telldus-core/service/ProtocolSartano.cpp @@ -0,0 +1,26 @@ +#include "ProtocolSartano.h" + +std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) { + + std::string strReturn("S"); + std::wstring strCode = this->getStringParameter(L"code", L""); + + for (size_t i = 0; i < strCode.length(); ++i) { + if (strCode[i] == L'1') { + strReturn.append("$k$k"); + } else { + strReturn.append("$kk$"); + } + } + + if (method == TELLSTICK_TURNON) { + strReturn.append("$k$k$kk$$k+"); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append("$kk$$k$k$k+"); + } else { + return ""; + } + + return strReturn; + +} diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h new file mode 100644 index 00000000..f32548d9 --- /dev/null +++ b/telldus-core/service/ProtocolSartano.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLSARTANO_H +#define PROTOCOLSARTANO_H + +#include "Protocol.h" + +class ProtocolSartano : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); +}; + +#endif //PROTOCOLSARTANO_H \ No newline at end of file From c4fcfdfb7f33429f90eb83a389f6cd047093801e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 08:24:04 +0000 Subject: [PATCH 0341/2215] Added protocol SilvanChip --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 9 ++- telldus-core/service/ProtocolSilvanChip.cpp | 72 +++++++++++++++++++++ telldus-core/service/ProtocolSilvanChip.h | 12 ++++ 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 telldus-core/service/ProtocolSilvanChip.cpp create mode 100644 telldus-core/service/ProtocolSilvanChip.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 213b12fd..f02af7f8 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -30,6 +30,8 @@ SET( telldus-service_protocol_SRCS ProtocolRisingSun.cpp ProtocolSartano.h ProtocolSartano.cpp + ProtocolSilvanChip.h + ProtocolSilvanChip.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index a2133d32..112f72cf 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -8,6 +8,7 @@ #include "ProtocolNexa.h" #include "ProtocolRisingSun.h" #include "ProtocolSartano.h" +#include "ProtocolSilvanChip.h" #include #include @@ -108,14 +109,12 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"sartano")) { return new ProtocolSartano(); - - }/* else if (wcscasecmp(protocolname.c_str(), L"silvanchip") == 0) { - prot = new ProtocolSilvanChip(deviceId, modelname); - ((ProtocolSilvanChip*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); + } else if (comparei(protocolname, L"silvanchip")) { + return new ProtocolSilvanChip(); - } else if (wcscasecmp(protocolname.c_str(), L"Waveman") == 0) { + }/* else if (wcscasecmp(protocolname.c_str(), L"Waveman") == 0) { prot = new ProtocolWaveman(deviceId, modelname); ((ProtocolWaveman*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); ((ProtocolWaveman*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp new file mode 100644 index 00000000..0522a0d5 --- /dev/null +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -0,0 +1,72 @@ +#include "ProtocolSilvanChip.h" + +std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { + const unsigned char S = 100; + const unsigned char L = 255; + const std::string LONG = "\255\1\200"; + + const std::string ONE = LONG + "\100"; + const std::string ZERO = "\100" + LONG; + std::string strReturn = "R\1S"; + + strReturn.append(1, S); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, L); + strReturn.append(1, 1); + strReturn.append(1, S); + + int intHouse = this->getIntParameter(L"house", 1, 1048575); + + for( int i = 19; i >= 0; --i ) { + if (intHouse & (1 << i)) { + strReturn.append(ONE); + } else { + strReturn.append(ZERO); + } + } + + if (method == TELLSTICK_TURNON) { + strReturn.append(ZERO); + strReturn.append(ZERO); + strReturn.append(ONE); + strReturn.append(ZERO); + } else if (method == TELLSTICK_LEARN) { + strReturn.append(ZERO); + strReturn.append(ZERO); + strReturn.append(ZERO); + strReturn.append(ONE); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(ONE); + strReturn.append(ZERO); + strReturn.append(ZERO); + strReturn.append(ZERO); + } else { + return ""; + } + + strReturn.append(ZERO); + strReturn.append("+"); + return strReturn; + +} diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h new file mode 100644 index 00000000..468805b9 --- /dev/null +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLSILVANCHIP_H +#define PROTOCOLSILVANCHIP_H + +#include "Protocol.h" + +class ProtocolSilvanChip : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); +}; + +#endif //PROTOCOLSILVANCHIP_H \ No newline at end of file From 60c9f52f73f16bb0c364dcec294ed9d187225408 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 08:53:12 +0000 Subject: [PATCH 0342/2215] Added protocol UPM --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 7 ++- telldus-core/service/ProtocolUpm.cpp | 64 ++++++++++++++++++++++++++++ telldus-core/service/ProtocolUpm.h | 12 ++++++ 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 telldus-core/service/ProtocolUpm.cpp create mode 100644 telldus-core/service/ProtocolUpm.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index f02af7f8..581355c3 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -32,6 +32,8 @@ SET( telldus-service_protocol_SRCS ProtocolSartano.cpp ProtocolSilvanChip.h ProtocolSilvanChip.cpp + ProtocolUpm.h + ProtocolUpm.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 112f72cf..0ec8a612 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -9,6 +9,7 @@ #include "ProtocolRisingSun.h" #include "ProtocolSartano.h" #include "ProtocolSilvanChip.h" +#include "ProtocolUpm.h" #include #include @@ -112,6 +113,8 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"silvanchip")) { return new ProtocolSilvanChip(); + } else if (comparei(protocolname, L"upm")) { + return new ProtocolUpm(); }/* else if (wcscasecmp(protocolname.c_str(), L"Waveman") == 0) { @@ -120,10 +123,6 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ ((ProtocolWaveman*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); - } else if (wcscasecmp(protocolname.c_str(), L"upm") == 0) { - prot = new ProtocolUpm(deviceId, modelname); - ((ProtocolUpm*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - ((ProtocolUpm*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); } else if (wcscasecmp(protocolname.c_str(), L"x10") == 0) { prot = new ProtocolX10(deviceId, modelname); diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp new file mode 100644 index 00000000..2bd40f9b --- /dev/null +++ b/telldus-core/service/ProtocolUpm.cpp @@ -0,0 +1,64 @@ +#include "ProtocolUpm.h" + +std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) { + const char S = ';'; + const char L = '~'; + const char START[] = {S,0}; + const char B1[] = {L,S,0}; + const char B0[] = {S,L,0}; + const char BON[] = {S,L,L,S,0}; + const char BOFF[] = {S,L,S,L,0}; + + int intUnit = this->getIntParameter(L"unit", 1, 4)-1; + std::string strReturn; + + int code = this->getIntParameter(L"house", 0, 4095); + for( size_t i = 0; i < 12; ++i ) { + if (code & 1) { + strReturn.insert(0, B1); + } else { + strReturn.insert(0, B0); + } + code >>= 1; + } + strReturn.insert(0, START); //Startcode, first + + code = 0; + if (method == TELLSTICK_TURNON) { + code += 2; + } else if (method != TELLSTICK_TURNOFF) { + return ""; + } + code <<= 2; + code += intUnit; + + int check1 = 0, check2 = 0; + for( size_t i = 0; i < 6; ++i ) { + if (code & 1) { + if (i % 2 == 0) { + check1++; + } else { + check2++; + } + } + if (code & 1) { + strReturn.append(B1); + } else { + strReturn.append(B0); + } + code >>= 1; + } + + if (check1 % 2 == 0) { + strReturn.append(B0); + } else { + strReturn.append(B1); + } + if (check2 % 2 == 0) { + strReturn.append(B0); + } else { + strReturn.append(B1); + } + return strReturn; +} + diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h new file mode 100644 index 00000000..8306a256 --- /dev/null +++ b/telldus-core/service/ProtocolUpm.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLUPM_H +#define PROTOCOLUPM_H + +#include "Protocol.h" + +class ProtocolUpm : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); +}; + +#endif //PROTOCOLUPM_H \ No newline at end of file From 9d4fe80f91b9f27235eeff5728311343c7fee92c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 09:07:37 +0000 Subject: [PATCH 0343/2215] Added protocol Waveman --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/Protocol.cpp | 11 ++++------- telldus-core/service/ProtocolNexa.cpp | 8 ++++++-- telldus-core/service/ProtocolNexa.h | 1 + telldus-core/service/ProtocolWaveman.cpp | 9 +++++++++ telldus-core/service/ProtocolWaveman.h | 14 ++++++++++++++ 6 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 telldus-core/service/ProtocolWaveman.cpp create mode 100644 telldus-core/service/ProtocolWaveman.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 581355c3..dadd613b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -34,6 +34,8 @@ SET( telldus-service_protocol_SRCS ProtocolSilvanChip.cpp ProtocolUpm.h ProtocolUpm.cpp + ProtocolWaveman.h + ProtocolWaveman.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 0ec8a612..3f834177 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -10,6 +10,7 @@ #include "ProtocolSartano.h" #include "ProtocolSilvanChip.h" #include "ProtocolUpm.h" +#include "ProtocolWaveman.h" #include #include @@ -116,15 +117,11 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"upm")) { return new ProtocolUpm(); - - }/* else if (wcscasecmp(protocolname.c_str(), L"Waveman") == 0) { - prot = new ProtocolWaveman(deviceId, modelname); - ((ProtocolWaveman*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - ((ProtocolWaveman*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); - + } else if (comparei(protocolname, L"waveman")) { + return new ProtocolWaveman(); - } else if (wcscasecmp(protocolname.c_str(), L"x10") == 0) { + }/* else if (wcscasecmp(protocolname.c_str(), L"x10") == 0) { prot = new ProtocolX10(deviceId, modelname); ((ProtocolX10*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); ((ProtocolX10*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index f1063762..8e2ba5e1 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -18,7 +18,7 @@ std::string ProtocolNexa::getStringCodeSwitch(int method) { if (method == TELLSTICK_TURNON) { strReturn.append("$k$k$kk$$kk$$kk$$k+"); } else if (method == TELLSTICK_TURNOFF) { - strReturn.append("$k$k$kk$$kk$$k$k$k+"); + strReturn.append(this->getOffCode()); } else { return ""; } @@ -100,4 +100,8 @@ std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { intCode >>= 1; } return strReturn; -} \ No newline at end of file +} + +std::string ProtocolNexa::getOffCode() const { + return "$k$k$kk$$kk$$k$k$k+"; +} diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 4b75394b..e4ff5cfc 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -11,6 +11,7 @@ public: protected: std::string getStringSelflearning(int method, unsigned char data); std::string getStringCodeSwitch(int method); + virtual std::string getOffCode() const; static std::string getCodeSwitchTuple(int code); }; diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp new file mode 100644 index 00000000..3913e1a0 --- /dev/null +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -0,0 +1,9 @@ +#include "ProtocolWaveman.h" + +std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) { + return getStringCodeSwitch(method); +} + +std::string ProtocolWaveman::getOffCode() const { + return "$k$k$k$k$k$k$k$k$k+"; +} diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h new file mode 100644 index 00000000..19d30e35 --- /dev/null +++ b/telldus-core/service/ProtocolWaveman.h @@ -0,0 +1,14 @@ +#ifndef PROTOCOLWAVEMAN_H +#define PROTOCOLWAVEMAN_H + +#include "ProtocolNexa.h" + +class ProtocolWaveman : public ProtocolNexa { +public: + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +protected: + virtual std::string getOffCode() const; +}; + +#endif //PROTOCOLWAVEMAN_H From f25a97007708da6502840ce6e5eb84a82e6e5797 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 09:25:33 +0000 Subject: [PATCH 0344/2215] Added protocol X10 --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 15 ++--- telldus-core/service/ProtocolX10.cpp | 95 ++++++++++++++++++++++++++++ telldus-core/service/ProtocolX10.h | 12 ++++ 4 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 telldus-core/service/ProtocolX10.cpp create mode 100644 telldus-core/service/ProtocolX10.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index dadd613b..2abd901c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -36,6 +36,8 @@ SET( telldus-service_protocol_SRCS ProtocolUpm.cpp ProtocolWaveman.h ProtocolWaveman.cpp + ProtocolX10.h + ProtocolX10.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 3f834177..15a4e7c8 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -11,6 +11,7 @@ #include "ProtocolSilvanChip.h" #include "ProtocolUpm.h" #include "ProtocolWaveman.h" +#include "ProtocolX10.h" #include #include @@ -119,17 +120,11 @@ Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ } else if (comparei(protocolname, L"waveman")) { return new ProtocolWaveman(); - - }/* else if (wcscasecmp(protocolname.c_str(), L"x10") == 0) { - prot = new ProtocolX10(deviceId, modelname); - ((ProtocolX10*)prot)->setHouse(settings.getDeviceParameter(deviceId, "house")); - ((ProtocolX10*)prot)->setUnit(settings.getDeviceParameter(deviceId, "unit")); - - } - */ - else{ - return 0; + } else if (comparei(protocolname, L"x10")) { + return new ProtocolX10(); } + + return 0; } diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp new file mode 100644 index 00000000..fbf16aa2 --- /dev/null +++ b/telldus-core/service/ProtocolX10.cpp @@ -0,0 +1,95 @@ +#include "ProtocolX10.h" + + +std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) { + const unsigned char S = 59, L = 169; + const char B0[] = {S,S,0}; + const char B1[] = {S,L,0}; + const int HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; + const unsigned char START_CODE[] = {'S',255,1,255,1,255,1,100,255,1,180,0}; + const unsigned char STOP_CODE[] = {S,0}; + + std::string strReturn = reinterpret_cast(START_CODE); + std::string strComplement = ""; + + std::wstring strHouse = getStringParameter(L"house", L"A"); + int intHouse = strHouse[0] - L'A'; + int intCode = getIntParameter(L"unit", 1, 16)-1; + + for( int i = 0; i < 4; ++i ) { + if (intHouse & 1) { + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + intHouse >>= 1; + } + strReturn.append( B0 ); + strComplement.append( B1 ); + + if (intCode >= 8) { + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + strReturn.append( B0 ); + strComplement.append( B1 ); + strReturn.append( B0 ); + strComplement.append( B1 ); + + strReturn.append( strComplement ); + strComplement = ""; + + strReturn.append( B0 ); + strComplement.append( B1 ); + + if (intCode >> 2 & 1) { //Bit 2 of intCode + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + if (method == TELLSTICK_TURNON) { + strReturn.append(B0); + strComplement.append(B1); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(B1); + strComplement.append(B0); + } else { + return ""; + } + + if (intCode & 1) { //Bit 0 of intCode + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + if (intCode >> 1 & 1) { //Bit 1 of intCode + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + for( int i = 0; i < 3; ++i ) { + strReturn.append( B0 ); + strComplement.append( B1 ); + } + + strReturn.append( strComplement ); + strReturn.append( reinterpret_cast(STOP_CODE) ); + strReturn.append("+"); + return strReturn; + +} diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h new file mode 100644 index 00000000..5a48fb02 --- /dev/null +++ b/telldus-core/service/ProtocolX10.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLX10_H +#define PROTOCOLX10_H + +#include "Protocol.h" + +class ProtocolX10 : public Protocol +{ +public: + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); +}; + +#endif //PROTOCOLX10_H \ No newline at end of file From 38dd77a8460ebe7734fba2700ebd3e385d0a9d23 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 09:34:05 +0000 Subject: [PATCH 0345/2215] Code cleanup in TelldusWinService --- .../service/TelldusWinService_win.cpp | 47 +------------------ telldus-core/service/TelldusWinService_win.h | 11 ++--- 2 files changed, 6 insertions(+), 52 deletions(-) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index e5213ce9..fdf35a67 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -1,8 +1,5 @@ #include "TelldusWinService_win.h" #include "TelldusMain.h" -//#include "TelldusCore.h" -//#include -//#include #include @@ -17,35 +14,15 @@ TelldusWinService::TelldusWinService() :tm(0) { tm = new TelldusMain(); - - //setServiceDescription("A Telldus service for managing TellStick Duo."); } TelldusWinService::~TelldusWinService() { -} - -void TelldusWinService::start() { -// tc = new TelldusCore(); - -// connect(this, SIGNAL(deviceInserted(int,int,const QString &)), tc, SLOT(deviceInserted(int,int,const QString &))); -// connect(this, SIGNAL(deviceRemoved(int,int,const QString &)), tc, SLOT(deviceRemoved(int,int,const QString &))); - - //app->quit(); - + delete tm; } void TelldusWinService::stop() { - //running = false; tm->stop(); - //if(tm){ - // delete tm; - //} - //tm = 0; -// if (tc) { -// delete tc; -// } -// tc = 0; } DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { @@ -60,7 +37,6 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); -// QCoreApplication::quit(); return NO_ERROR; case SERVICE_CONTROL_DEVICEEVENT: @@ -107,8 +83,6 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { TelldusWinService instance; -// QCoreApplication app(g_argc, g_argv); - // initialise service status instance.serviceStatus.dwServiceType = SERVICE_WIN32; @@ -127,7 +101,6 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); // running - instance.start(); instance.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); instance.serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); @@ -140,25 +113,9 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE); - if (!deviceNotificationHandle) { -// TelldusCore::logMessage(QString("Fail RegisterDeviceNotification")); - } - - //TelldusCore::logMessage(QString("Main thread waiting for service to stop")); - - //TelldusMain tm; - //tm = new TelldusMain(); - //tm.start(); + //Start our main-loop instance.tm->start(); - //while(instance.running) { - // Sleep(1000); - //} - - -// app.exec(); - //TelldusCore::logMessage(QString("Main thread waited, shutting down")); - // service was stopped instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index 482f66f1..cb9774b8 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -6,27 +6,24 @@ extern int g_argc; extern char **g_argv; -class TelldusCore; class TelldusMain; #define serviceName TEXT("TelldusCore") class TelldusWinService { public: - TelldusWinService(); - ~TelldusWinService(); + TelldusWinService(); + ~TelldusWinService(); static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); protected: - void start(); - void stop(); + void stop(); DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); private: - TelldusCore *tc; TelldusMain *tm; SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE serviceStatusHandle; @@ -34,4 +31,4 @@ private: static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); }; -#endif TELLDUSSERVICE_WIN_H \ No newline at end of file +#endif TELLDUSSERVICE_WIN_H From 3f1afb4b39e362567f2ae08ad9cecb3f1c09151b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 11:02:46 +0000 Subject: [PATCH 0346/2215] Receive device notifications on windows. We don't handle them yet though. --- .../service/TelldusWinService_win.cpp | 89 ++++++++++++------- telldus-core/service/TelldusWinService_win.h | 1 + 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index fdf35a67..ca5da041 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -2,6 +2,7 @@ #include "TelldusMain.h" #include +#include int g_argc; char **g_argv; @@ -37,47 +38,71 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); - return NO_ERROR; - - case SERVICE_CONTROL_DEVICEEVENT: - if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - - PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast(lpEventData); - if (!pDevInf) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - -// TelldusCore::logMessage(QString::fromWCharArray(pDevInf->dbcc_name)); - -/* QRegExp rx("USB#VID_([0-9A-Fa-f]+)&PID_([0-9A-Fa-f]+)", Qt::CaseInsensitive); - if (rx.indexIn(QString::fromWCharArray(pDevInf->dbcc_name)) < 0) { - TelldusCore::logMessage("No match"); - return 0; - } - - int vid = strtol(rx.cap(1).toLocal8Bit(), 0, 16); - int pid = strtol(rx.cap(2).toLocal8Bit(), 0, 16); - - if (dwEventType == DBT_DEVICEARRIVAL) { - TelldusCore::logMessage(QString("Insert %1 %2").arg(vid).arg(pid)); - emit deviceInserted(vid, pid, ""); - } else { - TelldusCore::logMessage(QString("Remove %1").arg(rx.cap(3))); - emit deviceRemoved(vid, pid, ""); - }*/ - return NO_ERROR; } return ERROR_CALL_NOT_IMPLEMENTED; } +DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { + if (controlCode != SERVICE_CONTROL_DEVICEEVENT) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + + if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast(lpEventData); + if (!pDevInf) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + + std::wstring name(pDevInf->dbcc_name); + + //Parse VID + size_t posStart = name.find(L"VID_"); + if (posStart == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + posStart += 4; + size_t posEnd = name.find(L'&', posStart); + if (posEnd == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + std::wstring strVID = name.substr(posStart, posEnd-posStart); + + //Parse PID + posStart = name.find(L"PID_"); + if (posStart == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + posStart += 4; + posEnd = name.find(L'#', posStart); + if (posEnd == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + std::wstring strPID = name.substr(posStart, posEnd-posStart); + + long int vid = strtol(std::string(strVID.begin(), strVID.end()).c_str(), NULL, 16); + long int pid = strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16); + + if (dwEventType == DBT_DEVICEARRIVAL) { + //TODO + } else { + //TODO + } + + return NO_ERROR; +} + DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { TelldusWinService *instance = reinterpret_cast(lpContext); if (!instance) { return ERROR_CALL_NOT_IMPLEMENTED; } + if (controlCode == SERVICE_CONTROL_DEVICEEVENT) { + return instance->deviceNotificationHandler(controlCode, dwEventType, lpEventData); + } return instance->serviceControlHandler(controlCode, dwEventType, lpEventData); } @@ -105,12 +130,12 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { instance.serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + // Register for device notification DEV_BROADCAST_DEVICEINTERFACE devInterface; ZeroMemory( &devInterface, sizeof(devInterface) ); devInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); devInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW; - HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE); //Start our main-loop diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index cb9774b8..04a5df0c 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -22,6 +22,7 @@ protected: void stop(); DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); + DWORD WINAPI deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); private: TelldusMain *tm; From ac1ea0878ef2b8508c9fdeeff34f7bf6c90361d9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 12:01:56 +0000 Subject: [PATCH 0347/2215] Added convenience function EventBase::popSignal() --- telldus-core/service/Event.cpp | 7 +++++++ telldus-core/service/Event.h | 1 + 2 files changed, 8 insertions(+) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index 6c3c27b4..e6209f86 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -41,6 +41,13 @@ void EventBase::clearHandler() { d->handler = 0; } +void EventBase::popSignal() { + EventData *data = this->takeSignal(); + if (data) { + delete data; + } +} + EventHandler *EventBase::handler() const { return d->handler; } diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 8a28029c..698116bb 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -25,6 +25,7 @@ class EventBase { public: virtual ~EventBase(); + void popSignal(); bool isSignaled(); void signal(); virtual void signal(EventData *); From 41ff18ca45d352f70da9033dfc9767bc20b4d2e7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 12:37:16 +0000 Subject: [PATCH 0348/2215] Added listlock for ControllerManager --- telldus-core/service/ControllerManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index e46d9d01..9f32e587 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -1,5 +1,6 @@ #include "ControllerManager.h" #include "Controller.h" +#include "Mutex.h" #include "TellStick.h" #include @@ -10,7 +11,8 @@ typedef std::map ControllerMap; class ControllerManager::PrivateData { public: int lastControllerId; - ControllerMap controllers; //TODO: Lock for this AND lock in controls, for send etc + ControllerMap controllers; //TODO: lock in controls, for send etc + TelldusCore::Mutex mutex; }; ControllerManager::ControllerManager(){ @@ -27,6 +29,7 @@ ControllerManager::~ControllerManager(void) { } Controller *ControllerManager::getBestControllerById(int id) { + TelldusCore::MutexLocker locker(&d->mutex); if (!d->controllers.size()) { return 0; } @@ -39,6 +42,7 @@ Controller *ControllerManager::getBestControllerById(int id) { } void ControllerManager::loadControllers() { + TelldusCore::MutexLocker locker(&d->mutex); std::list list = TellStick::findAll(); std::list::iterator it = list.begin(); for(; it != list.end(); ++it) { From dfa1a2e8979f1729efcd8dd0acb6f21b4a8cc395 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 12:38:04 +0000 Subject: [PATCH 0349/2215] Added function stub ControllerManager::deviceInsertedOrRemoved() --- telldus-core/service/ControllerManager.cpp | 5 +++++ telldus-core/service/ControllerManager.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 9f32e587..59509c7b 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -28,6 +28,11 @@ ControllerManager::~ControllerManager(void) { delete d; } +void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { + TelldusCore::MutexLocker locker(&d->mutex); + //TODO: +} + Controller *ControllerManager::getBestControllerById(int id) { TelldusCore::MutexLocker locker(&d->mutex); if (!d->controllers.size()) { diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 4b49d198..964f9bae 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -8,6 +8,8 @@ public: ControllerManager(void); ~ControllerManager(void); + void deviceInsertedOrRemoved(int vid, int pid, bool inserted); + Controller *getBestControllerById(int id); protected: From ae5655abbe5b609f72a3e9ad3d0d3552476cb61b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 15 Oct 2010 12:38:12 +0000 Subject: [PATCH 0350/2215] Device state and device state value implemented --- telldus-core/common/Message.cpp | 7 ++ telldus-core/common/Message.h | 5 +- .../service/ClientCommunicationHandler.cpp | 5 +- telldus-core/service/Device.cpp | 41 ++++++- telldus-core/service/Device.h | 9 +- telldus-core/service/DeviceManager.cpp | 100 +++++++++++++++--- telldus-core/service/DeviceManager.h | 3 + 7 files changed, 146 insertions(+), 24 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 818110d9..e38f887d 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -48,6 +48,13 @@ std::wstring Message::charToWstring(const char *value) { return st.str(); } +std::wstring Message::charUnsignedToWstring(const unsigned char value) { + //todo move? + std::wstringstream st; + st << value; + return st.str(); +} + std::wstring Message::intToWstring(int value) { //todo move? std::wstringstream st; diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 9c8f13e5..e75a23e5 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -19,6 +19,7 @@ namespace TelldusCore { std::wstring getClientWStringFromSocket(); static std::wstring charToWstring(const char *value); + static std::wstring charUnsignedToWstring(const unsigned char value); static std::wstring intToWstring(int value); static bool nextIsInt(const std::wstring &); static bool nextIsString(const std::wstring &); @@ -26,8 +27,10 @@ namespace TelldusCore { static std::wstring takeString(std::wstring *); static int takeInt(std::wstring *); - private: static int wideToInteger(const std::wstring &input); + + private: + }; } diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index f2c01efc..84e7166a 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -93,12 +93,11 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdLastSentCommand") { int deviceId = TelldusCore::Message::takeInt(&msg); int methodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; // tdLastSentCommand(deviceId, methodsSupported); TODO + (*intReturn) = d->deviceManager->getDeviceLastSentCommand(deviceId, methodsSupported); } else if (function == L"tdLastSentValue") { int deviceId = TelldusCore::Message::takeInt(&msg); - const char *value = ""; //tdLastSentValue(deviceId); TODO - (*wstringReturn) = TelldusCore::Message::charToWstring(value); + (*wstringReturn) = d->deviceManager->getDeviceStateValue(deviceId); } else if(function == L"tdGetNumberOfDevices"){ diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index a8639ffe..006bf1ee 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -9,6 +9,8 @@ public: Protocol *protocol; std::wstring protocolName; int preferredControllerId; + int state; + std::wstring stateValue; }; Device::Device(int id) @@ -17,6 +19,7 @@ Device::Device(int id) d = new PrivateData; d->protocol = 0; d->preferredControllerId = 0; + d->state = 0; //när något uppdateras, spara också till registret //obs, kunna hantera om alla värden inte är satta } @@ -29,6 +32,27 @@ Device::~Device(void) { /** * Get-/Set-methods */ + +int Device::getLastSentCommand(int methodsSupported){ + + int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported); + + if (lastSentCommand == TELLSTICK_BELL) { + //Bell is not a state + lastSentCommand = TELLSTICK_TURNOFF; + } + if (lastSentCommand == 0) { + lastSentCommand = TELLSTICK_TURNOFF; + } + return lastSentCommand; + +} + +void Device::setLastSentCommand(int command, std::wstring value){ + d->state = command; + d->stateValue = value; +} + std::wstring Device::getModel(){ return d->model; } @@ -69,6 +93,10 @@ void Device::setProtocolName(const std::wstring &protocolName){ d->protocolName = protocolName; } +std::wstring Device::getStateValue(){ + return d->stateValue; +} + /** * End Get-/Set */ @@ -78,9 +106,9 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { Protocol *p = this->retrieveProtocol(); if(p){ std::string code = p->getStringForMethod(action, data, controller); - controller->send(code); + return controller->send(code); } - return 0; + return TELLSTICK_ERROR_UNKNOWN; } Protocol* Device::retrieveProtocol() { @@ -96,4 +124,13 @@ Protocol* Device::retrieveProtocol() { } return 0; +} + +int Device::maskUnsupportedMethods(int methods, int supportedMethods) { + // Bell -> On + if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) { + methods |= TELLSTICK_TURNON; + } + //Cut of the rest of the unsupported methods we don't have a fallback for + return methods & supportedMethods; } \ No newline at end of file diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 1f108b40..cbeaa306 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -12,6 +12,9 @@ public: Device(int id); ~Device(void); + int doAction(int action, unsigned char data, Controller *controller); + std::wstring getStateValue(); + int getLastSentCommand(int methodsSupported); std::wstring getModel(); void setModel(const std::wstring &model); std::wstring getName(); @@ -22,10 +25,12 @@ public: void setPreferredControllerId(int controllerId); std::wstring getProtocolName(); void setProtocolName(const std::wstring &name); - int doAction(int action, unsigned char data, Controller *controller); + void setStateValue(int stateValue); + void setLastSentCommand(int command, std::wstring value); + + static int maskUnsupportedMethods(int methods, int supportedMethods); private: - Protocol *retrieveProtocol(); class PrivateData; diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 144b0bf9..de96605a 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,6 +1,7 @@ #include "DeviceManager.h" #include "Mutex.h" #include "Settings.h" +#include "Message.h" #include @@ -22,7 +23,7 @@ DeviceManager::DeviceManager(ControllerManager *controllerManager){ DeviceManager::~DeviceManager(void) { - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { {TelldusCore::MutexLocker lock(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere delete(it->second); @@ -31,7 +32,7 @@ DeviceManager::~DeviceManager(void) { } void DeviceManager::fillDevices(){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); int numberOfDevices = d->set.getNumberOfDevices(); for (int i = 0; i < numberOfDevices; ++i) { @@ -41,6 +42,7 @@ void DeviceManager::fillDevices(){ d->devices[id]->setModel(d->set.getModel(id)); d->devices[id]->setProtocolName(d->set.getProtocol(id)); d->devices[id]->setPreferredControllerId(d->set.getPreferredControllerId(id)); + d->devices[id]->setLastSentCommand(d->set.getDeviceState(id), d->set.getDeviceStateValue(id)); d->devices[id]->setParameter(L"house", d->set.getDeviceParameter(id, L"house")); d->devices[id]->setParameter(L"unit", d->set.getDeviceParameter(id, L"unit")); d->devices[id]->setParameter(L"code", d->set.getDeviceParameter(id, L"code")); @@ -50,9 +52,63 @@ void DeviceManager::fillDevices(){ } } +int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ + TelldusCore::MutexLocker deviceLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + return it->second->getLastSentCommand(methodsSupported); + } + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; +} + +int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, std::wstring value) +{ + //TODO: check this locking, ok? + Device *device = 0; + { + TelldusCore::MutexLocker deviceLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + device = it->second; + d->set.setDeviceState(deviceId, command,value); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + if(device){ + TelldusCore::MutexLocker lock(device); + device->setLastSentCommand(command, value); + } + + return TELLSTICK_SUCCESS; +} + + + +std::wstring DeviceManager::getDeviceStateValue(int deviceId){ + TelldusCore::MutexLocker deviceLocker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; //TODO, what? + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + return it->second->getStateValue(); + } + return L"UNKNOWN"; //TODO, what? +} + std::wstring DeviceManager::getDeviceModel(int deviceId){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; //TODO, what? } @@ -69,7 +125,7 @@ int DeviceManager::setDeviceModel(int deviceId, std::wstring model) //TODO: check this locking, ok? Device *device = 0; { - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -93,7 +149,7 @@ int DeviceManager::setDeviceModel(int deviceId, std::wstring model) std::wstring DeviceManager::getDeviceName(int deviceId){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; //TODO, what? } @@ -110,7 +166,7 @@ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ //TODO: check this locking, ok? Device *device = 0; { - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -133,7 +189,7 @@ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, std::wstring defaultValue){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return defaultValue; } @@ -153,7 +209,7 @@ int DeviceManager::setDeviceParameter(int deviceId, std::wstring name, std::wstr //TODO: check this locking, ok? Device *device = 0; { - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -177,7 +233,7 @@ int DeviceManager::setDeviceParameter(int deviceId, std::wstring name, std::wstr std::wstring DeviceManager::getDeviceProtocol(int deviceId){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; //TODO, what? } @@ -194,7 +250,7 @@ int DeviceManager::setDeviceProtocol(int deviceId, std::wstring protocol) //TODO: check this locking, ok? Device *device = 0; { - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -216,12 +272,12 @@ int DeviceManager::setDeviceProtocol(int deviceId, std::wstring protocol) } int DeviceManager::getNumberOfDevices(){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); return (int)d->devices.size(); } int DeviceManager::addDevice(){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); int id = d->set.addDevice(); if(id == -1){ @@ -236,7 +292,7 @@ int DeviceManager::addDevice(){ } int DeviceManager::getDeviceId(int deviceIndex) { - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); return d->set.getDeviceId(deviceIndex); } @@ -247,7 +303,7 @@ int DeviceManager::getDeviceType(int deviceId){ int DeviceManager::getPreferredControllerId(int deviceId){ - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -264,7 +320,7 @@ int DeviceManager::removeDevice(int deviceId){ Device *device = 0; { - TelldusCore::MutexLocker locker(&d->lock); + TelldusCore::MutexLocker deviceLocker(&d->lock); if(!d->set.removeDevice(deviceId)){ //remove from register/settings return TELLSTICK_ERROR_UNKNOWN; } @@ -306,7 +362,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - it->second->lock(); //device locked + it->second->lock(); //device locked TODO, nog här... device = it->second; } //devices unlocked @@ -320,6 +376,18 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); if(controller){ int retval = device->doAction(action, data, controller); + if(retval == TELLSTICK_SUCCESS){ + std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); + device->setLastSentCommand(action, datastring); + device->unlock(); + { + //new lock, for setting (all other locks are unlocked) + //TODO, it MAY be inconsistency between stored values and device values here... change something? + TelldusCore::MutexLocker deviceLocker(&d->lock); + d->set.setDeviceState(deviceId, action, datastring); + } + //TODO: Signal event, status change? + } device->unlock(); return retval; } diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index d47ce1f1..8354b031 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -12,6 +12,8 @@ public: int getNumberOfDevices(void); int addDevice(); int getDeviceId(int deviceIndex); + int getDeviceLastSentCommand(int deviceId, int methodsSupported); + int setDeviceLastSentCommand(int deviceId, int command, std::wstring value); std::wstring getDeviceModel(int deviceId); int setDeviceModel(int deviceId, std::wstring model); std::wstring getDeviceName(int deviceId); @@ -20,6 +22,7 @@ public: int setDeviceParameter(int deviceId, std::wstring name, std::wstring value); std::wstring getDeviceProtocol(int deviceId); int setDeviceProtocol(int deviceId, std::wstring name); + std::wstring getDeviceStateValue(int deviceId); int getDeviceType(int deviceId); int getPreferredControllerId(int deviceId); int removeDevice(int deviceId); From 9d9fab6323b3cfd6f576a38d35cb4cb8fa6179e0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 12:39:04 +0000 Subject: [PATCH 0351/2215] Added function TelldusMain::deviceInsertedOrRemoved() --- telldus-core/service/TelldusMain.cpp | 28 +++++++++++++++++++++++++++- telldus-core/service/TelldusMain.h | 3 +++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index e63bfbea..4c81f9d5 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -8,23 +8,40 @@ #include #include +class DeviceEventData : public EventDataBase { +public: + int vid, pid; + bool inserted; +}; + class TelldusMain::PrivateData { public: EventHandler eventHandler; - Event *stopEvent; + Event *stopEvent, *deviceChangeEvent; }; TelldusMain::TelldusMain(void) { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); + d->deviceChangeEvent = d->eventHandler.addEvent(); } TelldusMain::~TelldusMain(void) { + delete d->deviceChangeEvent; delete d->stopEvent; delete d; } +void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { + DeviceEventData *data = new DeviceEventData; + data->vid = vid; + data->pid = pid; + data->inserted = inserted; + d->deviceChangeEvent->signal(data); +} + + void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); @@ -53,6 +70,15 @@ void TelldusMain::start(void) { delete eventData; } + if (d->deviceChangeEvent->isSignaled()) { + EventData *eventData = d->deviceChangeEvent->takeSignal(); + DeviceEventData *data = reinterpret_cast(eventData); + if (data) { + controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, data->inserted); + } + delete eventData; + } + for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ if ((*it)->isDone()){ diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index 3dcddd75..46d6dbbe 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -10,6 +10,9 @@ public: void start(); void stop(); + //Thread safe! + void deviceInsertedOrRemoved(int vid, int pid, bool inserted); + private: class PrivateData; PrivateData *d; From 15685d045391bd8254e36985f43de3b71f27c897 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 12:39:28 +0000 Subject: [PATCH 0352/2215] Used the function TelldusMain::deviceInsertedOrRemoved() in TelldusWinService --- telldus-core/service/TelldusWinService_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index ca5da041..9267b46b 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -87,9 +87,9 @@ DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DW long int pid = strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16); if (dwEventType == DBT_DEVICEARRIVAL) { - //TODO + tm->deviceInsertedOrRemoved(vid, pid, true); } else { - //TODO + tm->deviceInsertedOrRemoved(vid, pid, false); } return NO_ERROR; From 3a1215b32903cfb7838c6b52cfdf44d8539c2105 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 12:48:11 +0000 Subject: [PATCH 0353/2215] Added missing includes --- telldus-core/service/ProtocolIkea.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index e1bdc8ea..ab2e426e 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -1,5 +1,8 @@ #include "ProtocolIkea.h" +#include +#include + std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { int intSystem = this->getIntParameter(L"system", 1, 16)-1; int intFadeStyle = comparei(this->getStringParameter(L"fade", L"true"), L"true"); From 2155b6831f2b13d4f85d4a50a5e47a7da8ad5fc6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 15 Oct 2010 13:05:49 +0000 Subject: [PATCH 0354/2215] Stub for device methods --- telldus-core/service/ClientCommunicationHandler.cpp | 3 +-- telldus-core/service/DeviceManager.cpp | 8 ++++++++ telldus-core/service/DeviceManager.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 84e7166a..e2c6e72b 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -155,7 +155,6 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, //TODO, signal event } else if (function == L"tdAddDevice") { - //TODO: Lock if(d->deviceManager->addDevice()){ (*intReturn) = 1; //TODO: signalEvent, or do that from where this is called? Or even inside addDevice? @@ -171,7 +170,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 63; // tdMethods(deviceId, intMethodsSupported); + (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { int intErrorNo = TelldusCore::Message::takeInt(&msg); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index de96605a..c35df3c6 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -106,6 +106,14 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ return L"UNKNOWN"; //TODO, what? } +int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ + + //TODO: + //when implemented in protocols, get a device and look in its protocol for methods + return 63; //TODO + +} + std::wstring DeviceManager::getDeviceModel(int deviceId){ TelldusCore::MutexLocker deviceLocker(&d->lock); diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 8354b031..2fd3e58e 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -14,6 +14,7 @@ public: int getDeviceId(int deviceIndex); int getDeviceLastSentCommand(int deviceId, int methodsSupported); int setDeviceLastSentCommand(int deviceId, int command, std::wstring value); + int getDeviceMethods(int deviceId, int methodsSupported); std::wstring getDeviceModel(int deviceId); int setDeviceModel(int deviceId, std::wstring model); std::wstring getDeviceName(int deviceId); From bae64ccdd025bd92d5ade1c5fca51bdf76cdf158 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 15 Oct 2010 13:25:40 +0000 Subject: [PATCH 0355/2215] Raw command implemented (but untested) --- .../service/ClientCommunicationHandler.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 83 +++++++++++-------- telldus-core/service/DeviceManager.h | 5 +- 3 files changed, 52 insertions(+), 38 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index e2c6e72b..e5858d17 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -180,7 +180,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdSendRawCommand") { std::wstring command = TelldusCore::Message::takeString(&msg); int reserved = TelldusCore::Message::takeInt(&msg); - (*intReturn) = 0; //tdSendRawCommand(command.c_str(), reserved); + (*intReturn) = d->deviceManager->sendRawCommand(command, reserved); } else if (function == L"tdConnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index c35df3c6..940ae5cc 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -324,41 +324,6 @@ int DeviceManager::getPreferredControllerId(int deviceId){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -int DeviceManager::removeDevice(int deviceId){ - - Device *device = 0; - { - TelldusCore::MutexLocker deviceLocker(&d->lock); - if(!d->set.removeDevice(deviceId)){ //remove from register/settings - return TELLSTICK_ERROR_UNKNOWN; - } - - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - device = it->second; - d->devices.erase(it); //remove from list, keep reference - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - } - {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else - delete device; - - //1 lås lista - //2 ta bort från registret - //4 plocka ut device ur lista - //* Lås upp lista - //3 vänta på device lås - //{TelldusCore::MutexLocker(&device);} - //6 delete device - - return TELLSTICK_DEVICE_REMOVED; -} - int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Device *device = 0; { @@ -404,3 +369,51 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return TELLSTICK_ERROR_NOT_FOUND; } } + +int DeviceManager::removeDevice(int deviceId){ + + Device *device = 0; + { + TelldusCore::MutexLocker deviceLocker(&d->lock); + if(!d->set.removeDevice(deviceId)){ //remove from register/settings + return TELLSTICK_ERROR_UNKNOWN; + } + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + device = it->second; + d->devices.erase(it); //remove from list, keep reference + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else + delete device; + + //1 lås lista + //2 ta bort från registret + //4 plocka ut device ur lista + //* Lås upp lista + //3 vänta på device lås + //{TelldusCore::MutexLocker(&device);} + //6 delete device + + return TELLSTICK_DEVICE_REMOVED; +} + +int DeviceManager::sendRawCommand(std::wstring command, int reserved){ + + //TODO test this! + Controller *controller = d->controllerManager->getBestControllerById(-1); + if(controller){ + return controller->send(std::string(command.begin(), command.end())); + } + else{ + return TELLSTICK_ERROR_NOT_FOUND; + } +} + diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 2fd3e58e..02a32f22 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -26,9 +26,10 @@ public: std::wstring getDeviceStateValue(int deviceId); int getDeviceType(int deviceId); int getPreferredControllerId(int deviceId); - int removeDevice(int deviceId); int doAction(int deviceId, int action, unsigned char data); - + int removeDevice(int deviceId); + int sendRawCommand(std::wstring command, int reserved); + private: void fillDevices(void); From 12565a585f2dff87f89ee4b635dea8be4df59217 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 13:29:18 +0000 Subject: [PATCH 0356/2215] Added function TellStick::isSameAsDescriptor() --- telldus-core/service/TellStick.h | 1 + telldus-core/service/TellStick_ftd2xx.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index c8b1f228..9d6c7a13 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -28,6 +28,7 @@ public: virtual int firmwareVersion(); bool isOpen() const; + bool isSameAsDescriptor(const TellStickDescriptor &d) const; virtual int send( const std::string &message ); static std::list findAll(); diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 1f285130..1fda74af 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -18,12 +18,17 @@ class TellStick::PrivateData { public: bool open; + int vid, pid; + std::string serial; FT_HANDLE ftHandle; }; TellStick::TellStick( const TellStickDescriptor &td ) { d = new PrivateData; d->open = false; + d->vid = td.vid; + d->pid = td.pid; + d->serial = td.serial; char *tempSerial = new char[td.serial.size()+1]; #ifdef _WINDOWS @@ -67,6 +72,19 @@ bool TellStick::isOpen() const { return d->open; } +bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const { + if (td.vid != d->vid) { + return false; + } + if (td.pid != d->pid) { + return false; + } + if (td.serial != d->serial) { + return false; + } + return true; +} + int TellStick::send( const std::string &strMessage ) { if (!d->open) { return TELLSTICK_ERROR_NOT_FOUND; From 1c8667f4f848272dabfc6ac04d62ab51fb53197b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 13:30:34 +0000 Subject: [PATCH 0357/2215] Iterate over a const iterator. --- telldus-core/service/ControllerManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 59509c7b..8c1f7179 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -38,7 +38,7 @@ Controller *ControllerManager::getBestControllerById(int id) { if (!d->controllers.size()) { return 0; } - ControllerMap::iterator it = d->controllers.find(id); + ControllerMap::const_iterator it = d->controllers.find(id); if (it != d->controllers.end()) { return it->second; } From 800e0f7a9a987cb4408b81512ae1adae88623b47 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 13:31:23 +0000 Subject: [PATCH 0358/2215] Added a check so we don't open a controller twice. --- telldus-core/service/ControllerManager.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 8c1f7179..18bc939f 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -48,10 +48,31 @@ Controller *ControllerManager::getBestControllerById(int id) { void ControllerManager::loadControllers() { TelldusCore::MutexLocker locker(&d->mutex); + std::list list = TellStick::findAll(); + std::list::iterator it = list.begin(); for(; it != list.end(); ++it) { printf("Found (%i/%i): %s\n", (*it).vid, (*it).pid, (*it).serial.c_str()); + + //Most backend only report non-opened devices. + //If they don't make sure we don't open them twice + bool found = false; + ControllerMap::const_iterator cit = d->controllers.begin(); + for(; cit != d->controllers.end(); ++cit) { + TellStick *tellstick = reinterpret_cast(cit->second); + if (!tellstick) { + continue; + } + if (tellstick->isSameAsDescriptor(*it)) { + found = true; + break; + } + } + if (found) { + continue; + } + TellStick *controller = new TellStick(*it); if (!controller->isOpen()) { delete controller; From 6d7fc0cdee5979913ba5f4287cf5acd6f3675bc5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 13:32:02 +0000 Subject: [PATCH 0359/2215] Add the controller when it's found. --- telldus-core/service/ControllerManager.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 18bc939f..1aaa8b4d 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -29,8 +29,16 @@ ControllerManager::~ControllerManager(void) { } void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { - TelldusCore::MutexLocker locker(&d->mutex); - //TODO: + if (vid != 0x1781) { + return; + } + if (pid != 0x0C30 && pid != 0x0C31) { + return; + } + if (inserted) { + loadControllers(); + return; + } } Controller *ControllerManager::getBestControllerById(int id) { From d91f4d212937ec061bdda7ee4ba7f138b734d2ad Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 13:51:29 +0000 Subject: [PATCH 0360/2215] Added function TellStick::stillConnected() --- telldus-core/service/TellStick.h | 1 + telldus-core/service/TellStick_ftd2xx.cpp | 31 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 9d6c7a13..6cf6ba2b 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -30,6 +30,7 @@ public: bool isOpen() const; bool isSameAsDescriptor(const TellStickDescriptor &d) const; virtual int send( const std::string &message ); + bool stillConnected() const; static std::list findAll(); diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 1fda74af..1c98816c 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -125,6 +125,37 @@ int TellStick::send( const std::string &strMessage ) { return TELLSTICK_SUCCESS; } +bool TellStick::stillConnected() const { + FT_STATUS ftStatus; + DWORD numDevs; + // create the device information list + ftStatus = FT_CreateDeviceInfoList(&numDevs); + if (ftStatus != FT_OK) { + return false; + } + if (numDevs <= 0) { + return false; + } + for (int i = 0; i < (int)numDevs; i++) { + FT_HANDLE ftHandleTemp; + DWORD flags; + DWORD id; + DWORD type; + DWORD locId; + char serialNumber[16]; + char description[64]; + // get information for device i + ftStatus = FT_GetDeviceInfoDetail(i, &flags, &type, &id, &locId, serialNumber, description, &ftHandleTemp); + if (ftStatus != FT_OK) { + continue; + } + if (d->serial.compare(serialNumber) == 0) { + return true; + } + } + return false; +} + std::list TellStick::findAll() { std::list tellstick = findAllByVIDPID(0x1781, 0x0C30); From 2e02e3724c638e180d0c5a9931c8ea4a26f20aea Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 13:51:52 +0000 Subject: [PATCH 0361/2215] Remove controllers when they are disconnected. --- telldus-core/service/ControllerManager.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 1aaa8b4d..a5ba8c19 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -37,7 +37,19 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) } if (inserted) { loadControllers(); - return; + } else { + TelldusCore::MutexLocker locker(&d->mutex); + for(ControllerMap::const_iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + TellStick *tellstick = reinterpret_cast(it->second); + if (!tellstick) { + continue; + } + if (!tellstick->stillConnected()) { + d->controllers.erase(it); + delete tellstick; + break; + } + } } } From d0dee5c270a8123a758b75fca6c739b30a1009b0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 15 Oct 2010 14:00:45 +0000 Subject: [PATCH 0362/2215] Error codes somewhat implemented --- .../service/ClientCommunicationHandler.cpp | 26 ++++++++++++++++--- .../service/ClientCommunicationHandler.h | 2 +- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index e5858d17..04bcfe9a 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -173,9 +173,8 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { - int intErrorNo = TelldusCore::Message::takeInt(&msg); - const char *response = "Default error string"; //tdGetErrorString(intErrorNo); - (*wstringReturn) = TelldusCore::Message::charToWstring(response); + int errorNo = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = getErrorString(errorNo); } else if (function == L"tdSendRawCommand") { std::wstring command = TelldusCore::Message::takeString(&msg); @@ -204,3 +203,24 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } } +std::wstring ClientCommunicationHandler::getErrorString(int errorNo){ + //TODO should this be here? + const int numResponses = 8; + const char *responses[numResponses] = { + "Success", + "TellStick not found", + "Permission denied", + "Device not found", + "The method you tried to use is not supported by the device", + "An error occurred while communicating with TellStick", + "Could not connect to the Telldus Service", + "Received an unknown response" + }; + std::string strReturn; + errorNo = abs(errorNo); //We don't use negative values here. + if (errorNo >= numResponses) { + return L"Unknown error"; + } else { + return TelldusCore::Message::charToWstring(responses[errorNo]); + } +} diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 2d1a442f..37cb3bab 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -23,7 +23,7 @@ protected: private: class PrivateData; PrivateData *d; - //std::wstring parseMessage(const std::wstring &clientMessage); + std::wstring getErrorString(int errorNo); void parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn); }; From d1f26a1685f0de853e174629d6bbd66daf9698b7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 14:24:06 +0000 Subject: [PATCH 0363/2215] Device::retrieveProtocol() should be declared const. --- telldus-core/service/Device.cpp | 2 +- telldus-core/service/Device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 006bf1ee..1056fe24 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -111,7 +111,7 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { return TELLSTICK_ERROR_UNKNOWN; } -Protocol* Device::retrieveProtocol() { +Protocol* Device::retrieveProtocol() const { if (d->protocol) { return d->protocol; } diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index cbeaa306..7e532415 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -31,7 +31,7 @@ public: static int maskUnsupportedMethods(int methods, int supportedMethods); private: - Protocol *retrieveProtocol(); + Protocol *retrieveProtocol() const; class PrivateData; PrivateData *d; From 719995baacbc15e725c19b1e2894056a857d1ff4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 14:24:58 +0000 Subject: [PATCH 0364/2215] Added function Device::getMethods() --- telldus-core/service/Device.cpp | 8 ++++++++ telldus-core/service/Device.h | 1 + 2 files changed, 9 insertions(+) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 1056fe24..347174cf 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -48,6 +48,14 @@ int Device::getLastSentCommand(int methodsSupported){ } +int Device::getMethods() const { + Protocol *p = this->retrieveProtocol(); + if (p) { + return p->methods(); + } + return 0; +} + void Device::setLastSentCommand(int command, std::wstring value){ d->state = command; d->stateValue = value; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 7e532415..65cb3d84 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -15,6 +15,7 @@ public: int doAction(int action, unsigned char data, Controller *controller); std::wstring getStateValue(); int getLastSentCommand(int methodsSupported); + int getMethods() const; std::wstring getModel(); void setModel(const std::wstring &model); std::wstring getName(); From f444a0c0d957e0f86afa5dda5236d8466d161d89 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 14:25:42 +0000 Subject: [PATCH 0365/2215] Implemented DeviceManager::getDeviceMethods() --- telldus-core/service/DeviceManager.cpp | 26 ++++++++++++++++++++++---- telldus-core/service/Protocol.cpp | 4 ++++ telldus-core/service/Protocol.h | 1 + 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 940ae5cc..a56cbc52 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -107,10 +107,28 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ } int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ + Device *device = 0; + { + //devices locked + TelldusCore::MutexLocker devicesLocker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + it->second->lock(); //device locked TODO + device = it->second; + } + //devices unlocked + } - //TODO: - //when implemented in protocols, get a device and look in its protocol for methods - return 63; //TODO + if (!device) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found + } + int methods = device->getMethods(); + device->unlock(); + return Device::maskUnsupportedMethods(methods, methodsSupported); } @@ -335,7 +353,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - it->second->lock(); //device locked TODO, nog här... + it->second->lock(); //device locked device = it->second; } //devices unlocked diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 15a4e7c8..5ed14bb8 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -32,6 +32,10 @@ Protocol::~Protocol(void) { delete d; } +int Protocol::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::wstring Protocol::model() const { std::wstring strModel = d->model; //Strip anything after : if it is found diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 8f79c917..2ef3e361 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -17,6 +17,7 @@ public: static Protocol *getProtocolInstance(std::wstring &protocolname); + int methods() const; //TODO: should be abstract std::wstring model() const; void setModel(const std::wstring &model); void setParameters(ParameterMap ¶meterList); From 52a59434f9d2611e49d72d6c72b6b788e924c5f4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 15 Oct 2010 14:51:36 +0000 Subject: [PATCH 0366/2215] Disconnect/connect-required event from client implemented (untested) --- telldus-core/service/ClientCommunicationHandler.cpp | 8 ++++---- telldus-core/service/DeviceManager.cpp | 8 ++++++++ telldus-core/service/DeviceManager.h | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 04bcfe9a..dec8e7fe 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -185,16 +185,16 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); std::wstring serial = TelldusCore::Message::takeString(&msg); - //tdConnectTellStickController(vid, pid, serial.c_str()); - (*wstringReturn) = L""; + d->deviceManager->connectTellStickController(vid, pid, serial); + //TODO, return what? //TODO, signal event? Or done in other place? } else if (function == L"tdDisconnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); std::wstring serial = TelldusCore::Message::takeString(&msg); - //tdDisconnectTellStickController(vid, pid, serial.c_str()); - (*wstringReturn) = L""; + d->deviceManager->disconnectTellStickController(vid, pid, serial); + //TODO, return what? //TODO, signal event? Or done in other place? } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index a56cbc52..494841b9 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -342,6 +342,14 @@ int DeviceManager::getPreferredControllerId(int deviceId){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } +void DeviceManager::connectTellStickController(int vid, int pid, std::wstring serial){ + d->controllerManager->deviceInsertedOrRemoved(vid, pid, true); +} + +void DeviceManager::disconnectTellStickController(int vid, int pid, std::wstring serial){ + d->controllerManager->deviceInsertedOrRemoved(vid, pid, false); +} + int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Device *device = 0; { diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 02a32f22..12616fef 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -11,6 +11,8 @@ public: ~DeviceManager(void); int getNumberOfDevices(void); int addDevice(); + void connectTellStickController(int vid, int pid, std::wstring serial); + void disconnectTellStickController(int vid, int pid, std::wstring serial); int getDeviceId(int deviceIndex); int getDeviceLastSentCommand(int deviceId, int methodsSupported); int setDeviceLastSentCommand(int deviceId, int command, std::wstring value); From ce52f0909268e5172c207296c8cbd29fab7b328f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 14:53:47 +0000 Subject: [PATCH 0367/2215] Made Protocol::methods() abstract. --- telldus-core/service/Protocol.cpp | 4 ---- telldus-core/service/Protocol.h | 2 +- telldus-core/service/ProtocolBrateck.cpp | 4 ++++ telldus-core/service/ProtocolBrateck.h | 1 + telldus-core/service/ProtocolEverflourish.cpp | 4 ++++ telldus-core/service/ProtocolEverflourish.h | 1 + telldus-core/service/ProtocolFuhaote.cpp | 4 ++++ telldus-core/service/ProtocolFuhaote.h | 1 + telldus-core/service/ProtocolIkea.cpp | 4 ++++ telldus-core/service/ProtocolIkea.h | 1 + telldus-core/service/ProtocolNexa.cpp | 5 +++++ telldus-core/service/ProtocolNexa.h | 1 + telldus-core/service/ProtocolRisingSun.cpp | 5 +++++ telldus-core/service/ProtocolRisingSun.h | 1 + telldus-core/service/ProtocolSartano.cpp | 4 ++++ telldus-core/service/ProtocolSartano.h | 1 + telldus-core/service/ProtocolSilvanChip.cpp | 4 ++++ telldus-core/service/ProtocolSilvanChip.h | 1 + telldus-core/service/ProtocolUpm.cpp | 4 ++++ telldus-core/service/ProtocolUpm.h | 1 + telldus-core/service/ProtocolWaveman.cpp | 4 ++++ telldus-core/service/ProtocolWaveman.h | 1 + telldus-core/service/ProtocolX10.cpp | 3 +++ telldus-core/service/ProtocolX10.h | 1 + 24 files changed, 57 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 5ed14bb8..15a4e7c8 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -32,10 +32,6 @@ Protocol::~Protocol(void) { delete d; } -int Protocol::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - std::wstring Protocol::model() const { std::wstring strModel = d->model; //Strip anything after : if it is found diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 2ef3e361..0b53ea96 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -17,7 +17,7 @@ public: static Protocol *getProtocolInstance(std::wstring &protocolname); - int methods() const; //TODO: should be abstract + virtual int methods() const = 0; std::wstring model() const; void setModel(const std::wstring &model); void setParameters(ParameterMap ¶meterList); diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 960c0499..f795edac 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -1,5 +1,9 @@ #include "ProtocolBrateck.h" +int ProtocolBrateck::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) { const char S = '!'; const char L = 'V'; diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index 205a2aa3..1c729f20 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -6,6 +6,7 @@ class ProtocolBrateck : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index dd526691..eb2022c1 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -1,5 +1,9 @@ #include "ProtocolEverflourish.h" +int ProtocolEverflourish::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; +} + std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, Controller *) { unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383); unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1; diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index be234f98..6007b7ce 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -6,6 +6,7 @@ class ProtocolEverflourish : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); private: diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index a79f190e..277563d2 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -1,5 +1,9 @@ #include "ProtocolFuhaote.h" +int ProtocolFuhaote::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) { const char S = 19; const char L = 58; diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index e63ca979..166c1613 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -6,6 +6,7 @@ class ProtocolFuhaote : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index ab2e426e..0a41cfea 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -3,6 +3,10 @@ #include #include +int ProtocolIkea::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; +} + std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { int intSystem = this->getIntParameter(L"system", 1, 16)-1; int intFadeStyle = comparei(this->getStringParameter(L"fade", L"true"), L"true"); diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index 31713941..01badae9 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -6,6 +6,7 @@ class ProtocolIkea : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 8e2ba5e1..3b2a85df 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,5 +1,10 @@ #include "ProtocolNexa.h" +int ProtocolNexa::methods() const { + //TODO + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *) { if (!comparei(model(), L"codeswitch")) { return getStringSelflearning(method, data); diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index e4ff5cfc..ad72e168 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -6,6 +6,7 @@ class ProtocolNexa : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); protected: diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index 41ee406e..447ec09b 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -1,5 +1,10 @@ #include "ProtocolRisingSun.h" +int ProtocolRisingSun::methods() const { + //TODO + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) { if (comparei(model(), L"selflearning")) { return getStringSelflearning(method); diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h index 4ecc4b2c..748196d0 100644 --- a/telldus-core/service/ProtocolRisingSun.h +++ b/telldus-core/service/ProtocolRisingSun.h @@ -6,6 +6,7 @@ class ProtocolRisingSun : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); protected: diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 088e4b56..a10a225f 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -1,5 +1,9 @@ #include "ProtocolSartano.h" +int ProtocolSartano::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) { std::string strReturn("S"); diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index f32548d9..b2a14fdb 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -6,6 +6,7 @@ class ProtocolSartano : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 0522a0d5..99325b30 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -1,5 +1,9 @@ #include "ProtocolSilvanChip.h" +int ProtocolSilvanChip::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; +} + std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { const unsigned char S = 100; const unsigned char L = 255; diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h index 468805b9..ed6bd7ef 100644 --- a/telldus-core/service/ProtocolSilvanChip.h +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -6,6 +6,7 @@ class ProtocolSilvanChip : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 2bd40f9b..2b46f187 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -1,5 +1,9 @@ #include "ProtocolUpm.h" +int ProtocolUpm::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) { const char S = ';'; const char L = '~'; diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h index 8306a256..c378d296 100644 --- a/telldus-core/service/ProtocolUpm.h +++ b/telldus-core/service/ProtocolUpm.h @@ -6,6 +6,7 @@ class ProtocolUpm : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 3913e1a0..d71bb50a 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -1,5 +1,9 @@ #include "ProtocolWaveman.h" +int ProtocolWaveman::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) { return getStringCodeSwitch(method); } diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h index 19d30e35..da433113 100644 --- a/telldus-core/service/ProtocolWaveman.h +++ b/telldus-core/service/ProtocolWaveman.h @@ -5,6 +5,7 @@ class ProtocolWaveman : public ProtocolNexa { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); protected: diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index fbf16aa2..45f23d74 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -1,5 +1,8 @@ #include "ProtocolX10.h" +int ProtocolX10::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) { const unsigned char S = 59, L = 169; diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 5a48fb02..a71c57b7 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -6,6 +6,7 @@ class ProtocolX10 : public Protocol { public: + int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; From 713f92ccd30d2a147fb9dc70edee09751ac3984f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 15:08:46 +0000 Subject: [PATCH 0368/2215] Implemented correct methods for RisingSun --- telldus-core/service/ProtocolRisingSun.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index 447ec09b..32870e5b 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -1,7 +1,9 @@ #include "ProtocolRisingSun.h" int ProtocolRisingSun::methods() const { - //TODO + if (comparei(model(), L"selflearning")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); + } return TELLSTICK_TURNON | TELLSTICK_TURNOFF; } From 06e5ca8a9e41a2813064a3383dc5c5ac81027c3c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Oct 2010 15:15:32 +0000 Subject: [PATCH 0369/2215] Implemented correct methods for Nexa/ArcTech --- telldus-core/service/ProtocolNexa.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 3b2a85df..335504e4 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,8 +1,19 @@ #include "ProtocolNexa.h" int ProtocolNexa::methods() const { - //TODO - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; + if (comparei(model(), L"codeswitch")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); + + } else if (comparei(model(), L"selflearning-switch")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); + + } else if (comparei(model(), L"selflearning-dimmer")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); + + } else if (comparei(model(), L"bell")) { + return TELLSTICK_BELL; + } + return 0; } std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *) { From 13253a0aa592316e6735bd0f3470b3b167ccb072 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 18 Oct 2010 08:42:49 +0000 Subject: [PATCH 0370/2215] New wstring to string conversion method. Untested and only used in SendRawCommand so far (with todo's on other places where it should be used). --- telldus-core/client/common.h | 2 +- telldus-core/common/Message.cpp | 19 +++++++++++++++++++ telldus-core/common/Message.h | 1 + telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/ProtocolIkea.cpp | 2 +- telldus-core/service/SettingsConfuse.cpp | 2 +- 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/common.h b/telldus-core/client/common.h index dd997835..728a2b50 100644 --- a/telldus-core/client/common.h +++ b/telldus-core/client/common.h @@ -36,5 +36,5 @@ inline char *wrapStdString( const std::string &string) { } inline char *wrapStdWstring( const std::wstring &wstring) { - return wrapStdString(std::string(wstring.begin(), wstring.end())); + return wrapStdString(std::string(wstring.begin(), wstring.end())); //TODO } \ No newline at end of file diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index e38f887d..69e9aeb8 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -106,6 +106,25 @@ int Message::wideToInteger(const std::wstring &input){ return retval; } +std::string Message::wideToString(const std::wstring &input){ + + //return std::string(input.begin(), input.end()); //TODO, change this conversion method + + std::string strReturn; + + size_t len = input.length(); + char* convPointer = new char[len + 1]; + + wcstombs(convPointer, input.c_str(), len + 1); + + strReturn = convPointer; + + delete [] convPointer; + + return strReturn; + +} + bool Message::getClientBoolFromSocket(){ //TODO: move return getClientIntegerFromSocket() == 1; diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index e75a23e5..084965e4 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -28,6 +28,7 @@ namespace TelldusCore { static int takeInt(std::wstring *); static int wideToInteger(const std::wstring &input); + static std::string wideToString(const std::wstring &input); private: diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 494841b9..1f78d6f5 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -436,7 +436,7 @@ int DeviceManager::sendRawCommand(std::wstring command, int reserved){ //TODO test this! Controller *controller = d->controllerManager->getBestControllerById(-1); if(controller){ - return controller->send(std::string(command.begin(), command.end())); + return controller->send(TelldusCore::Message::wideToString(command)); // std::string(command.begin(), command.end())); } else{ return TELLSTICK_ERROR_NOT_FOUND; diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 0a41cfea..b73a31cb 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -25,7 +25,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co return ""; } - std::string strUnits(wstrUnits.begin(), wstrUnits.end()); + std::string strUnits(wstrUnits.begin(), wstrUnits.end()); //TODO int intUnits = 0; //Start without any units char *tempUnits = new char[strUnits.size()+1]; diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 694f800b..3eef2706 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -63,7 +63,7 @@ Settings::~Settings(void) */ std::wstring Settings::getSetting(const std::wstring &strName) const { if (d->cfg > 0) { - std::string setting(cfg_getstr(d->cfg, std::string(strName.begin(), strName.end()).c_str())); + std::string setting(cfg_getstr(d->cfg, std::string(strName.begin(), strName.end()).c_str())); //TODO, safer conversion (other places in this file as well) return std::wstring(setting.begin(), setting.end()); } return L""; From 4e09d37c061a856bf1b03a60c484931fb705c802 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 09:45:51 +0000 Subject: [PATCH 0371/2215] Introduced class Client --- telldus-core/client/CMakeLists.txt | 20 +++----------------- telldus-core/client/Client.cpp | 11 +++++++++++ telldus-core/client/Client.h | 17 +++++++++++++++++ 3 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 telldus-core/client/Client.cpp create mode 100644 telldus-core/client/Client.h diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 0b994c76..ac8484dd 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -4,32 +4,18 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-core_SRCS + Client.cpp telldus-core.cpp - ) +) SET( telldus-core_HDRS + Client.h ) SET( telldus-core_PUB_HDRS telldus-core.h ) -OPTION(USE_FTD2XX_RATHER_THEN_LIBFTDI "Link against ftd2xx even if libftdi is the preferred one" OFF) -IF (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) - FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) - SET( telldus-core_LIBRARIES - ${telldus-core_LIBRARIES} - ${FTD2XX_LIBRARY} - ) - ADD_DEFINITIONS( -DLIBFTD2XX ) -ELSE (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) - FIND_LIBRARY(FTDI_LIBRARY ftdi) - SET( telldus-core_LIBRARIES - ${telldus-core_LIBRARIES} - ${FTDI_LIBRARY} - ) - ADD_DEFINITIONS( -DLIBFTDI ) -ENDIF (APPLE OR WIN32 OR USE_FTD2XX_RATHER_THEN_LIBFTDI) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../common diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp new file mode 100644 index 00000000..4d050e22 --- /dev/null +++ b/telldus-core/client/Client.cpp @@ -0,0 +1,11 @@ +#include "Client.h" + +using namespace TelldusCore; + + +Client::Client() +{ +} + +Client::~Client(void) { +} diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h new file mode 100644 index 00000000..49534182 --- /dev/null +++ b/telldus-core/client/Client.h @@ -0,0 +1,17 @@ +#ifndef CLIENT_H +#define CLIENT_H + +namespace TelldusCore { + class Client{ + public: + Client(); + ~Client(void); + + private: + class PrivateData; + PrivateData *d; + + }; +} + +#endif //CLIENT_H From 9d515851d2703cf2d6b135177d3707d46dcb22ae Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 09:50:19 +0000 Subject: [PATCH 0372/2215] Client now tries to connect an event socket --- telldus-core/client/Client.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 4d050e22..9ebecb32 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,11 +1,18 @@ #include "Client.h" +#include "Socket.h" using namespace TelldusCore; +class Client::PrivateData { +public: + Socket eventSocket; +}; -Client::Client() -{ +Client::Client() { + d = new PrivateData; + d->eventSocket.connect(L"TelldusEvents"); } Client::~Client(void) { + delete d; } From 95505787179c1f100041669e73461d9335f98853 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 09:56:00 +0000 Subject: [PATCH 0373/2215] Client is now a singleton --- telldus-core/client/Client.cpp | 15 +++++++++++++++ telldus-core/client/Client.h | 8 ++++++-- telldus-core/client/telldus-core.cpp | 5 +++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 9ebecb32..7004a240 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -8,6 +8,8 @@ public: Socket eventSocket; }; +Client *Client::instance = 0; + Client::Client() { d = new PrivateData; d->eventSocket.connect(L"TelldusEvents"); @@ -16,3 +18,16 @@ Client::Client() { Client::~Client(void) { delete d; } + +void Client::close() { + if (Client::instance != 0) { + delete Client::instance; + } +} + +Client *Client::getInstance() { + if (Client::instance == 0) { + Client::instance = new Client(); + } + return Client::instance; +} \ No newline at end of file diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 49534182..e019b52e 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -4,13 +4,17 @@ namespace TelldusCore { class Client{ public: - Client(); ~Client(void); + static Client *getInstance(); + static void close(); + private: + Client(); + class PrivateData; PrivateData *d; - + static Client *instance; }; } diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 1e370df9..0531849c 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -6,6 +6,7 @@ #include "telldus-core.h" #include "common.h" +#include "Client.h" #include "Message.h" #include "Socket.h" #include @@ -68,9 +69,8 @@ * Error code. An unkown error has occurred. */ -#define MAX_LOADSTRING 100 - void WINAPI tdInit(void) { + TelldusCore::Client::getInstance(); //Create the manager-object } int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { @@ -95,6 +95,7 @@ int WINAPI tdUnregisterCallback( int callbackId ) { * This should be called when the library is not supposed to be used anymore **/ void WINAPI tdClose(void) { + Client::close(); } /** From 839532f6fb4f2e21e9ecf48a2775c933a14ef697 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 10:06:10 +0000 Subject: [PATCH 0374/2215] Added function Client::getIntegerFromService() --- telldus-core/client/Client.cpp | 12 +++++++++++- telldus-core/client/Client.h | 4 ++++ telldus-core/client/telldus-core.cpp | 8 +++----- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 7004a240..356b49e7 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -30,4 +30,14 @@ Client *Client::getInstance() { Client::instance = new Client(); } return Client::instance; -} \ No newline at end of file +} + +int Client::getIntegerFromService(const Message &msg) { + Socket s; + s.connect(L"TelldusClient"); + s.write(msg.data()); + + std::wstring response = s.read(); + return Message::takeInt(&response); +} + diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index e019b52e..db21e7c1 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -1,6 +1,8 @@ #ifndef CLIENT_H #define CLIENT_H +#include "Message.h" + namespace TelldusCore { class Client{ public: @@ -9,6 +11,8 @@ namespace TelldusCore { static Client *getInstance(); static void close(); + static int getIntegerFromService(const Message &msg); + private: Client(); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 0531849c..6903b055 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -95,7 +95,7 @@ int WINAPI tdUnregisterCallback( int callbackId ) { * This should be called when the library is not supposed to be used anymore **/ void WINAPI tdClose(void) { - Client::close(); + TelldusCore::Client::close(); } /** @@ -203,10 +203,8 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * This function returns the number of devices configured * @returns an integer of the total number of devices configured */ -int WINAPI tdGetNumberOfDevices(void){ - - TelldusCore::Message msg(L"tdGetNumberOfDevices"); - return msg.getClientIntegerFromSocket(); +int WINAPI tdGetNumberOfDevices(void){ + return TelldusCore::Client::getIntegerFromService(TelldusCore::Message(L"tdGetNumberOfDevices")); } /** From 01a983d04f69b4b3499d92b6e54e051bbd7c4b26 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 10:19:33 +0000 Subject: [PATCH 0375/2215] Converted all functions to use Client::getIntegerFromService() --- telldus-core/client/telldus-core.cpp | 76 ++++++++++++++-------------- telldus-core/common/Message.cpp | 14 +---- telldus-core/common/Message.h | 1 - 3 files changed, 41 insertions(+), 50 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 6903b055..88740372 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -11,6 +11,8 @@ #include "Socket.h" #include +using namespace TelldusCore; + /** * @def TELLSTICK_TURNON @@ -70,7 +72,7 @@ */ void WINAPI tdInit(void) { - TelldusCore::Client::getInstance(); //Create the manager-object + Client::getInstance(); //Create the manager-object } int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { @@ -95,7 +97,7 @@ int WINAPI tdUnregisterCallback( int callbackId ) { * This should be called when the library is not supposed to be used anymore **/ void WINAPI tdClose(void) { - TelldusCore::Client::close(); + Client::close(); } /** @@ -118,9 +120,9 @@ void WINAPI tdReleaseString(char *string) { * @param intDeviceId The device id to turn on. **/ int WINAPI tdTurnOn(int intDeviceId){ - TelldusCore::Message msg(L"tdTurnOn"); + Message msg(L"tdTurnOn"); msg.addArgument(intDeviceId); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -130,9 +132,9 @@ int WINAPI tdTurnOn(int intDeviceId){ * @param intDeviceId The device id to turn off. */ int WINAPI tdTurnOff(int intDeviceId){ - TelldusCore::Message msg(L"tdTurnOff"); + Message msg(L"tdTurnOff"); msg.addArgument(intDeviceId); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -142,9 +144,9 @@ int WINAPI tdTurnOff(int intDeviceId){ * @param intDeviceId The device id to send bell to */ int WINAPI tdBell(int intDeviceId){ - TelldusCore::Message msg(L"tdBell"); + Message msg(L"tdBell"); msg.addArgument(intDeviceId); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -155,10 +157,10 @@ int WINAPI tdBell(int intDeviceId){ * @param level The level the device should dim to. This value should be 0-255 */ int WINAPI tdDim(int intDeviceId, unsigned char level){ - TelldusCore::Message msg(L"tdDim"); + Message msg(L"tdDim"); msg.addArgument(intDeviceId); msg.addArgument(level); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -169,9 +171,9 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ * @param intDeviceId The device id to learn. */ int WINAPI tdLearn(int intDeviceId) { - TelldusCore::Message msg(L"tdLearn"); + Message msg(L"tdLearn"); msg.addArgument(intDeviceId); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -181,10 +183,10 @@ int WINAPI tdLearn(int intDeviceId) { * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF */ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { - TelldusCore::Message msg(L"tdLastSentCommand"); + Message msg(L"tdLastSentCommand"); msg.addArgument(intDeviceId); msg.addArgument(methodsSupported); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -193,7 +195,7 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { * @returns the the value as a human readable string, example "128" for 50% */ char * WINAPI tdLastSentValue( int intDeviceId ) { - TelldusCore::Message msg(L"tdLastSentValue"); + Message msg(L"tdLastSentValue"); msg.addArgument(intDeviceId); std::wstring strReturn = msg.getClientWStringFromSocket(); return wrapStdWstring(strReturn); @@ -204,7 +206,7 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * @returns an integer of the total number of devices configured */ int WINAPI tdGetNumberOfDevices(void){ - return TelldusCore::Client::getIntegerFromService(TelldusCore::Message(L"tdGetNumberOfDevices")); + return Client::getIntegerFromService(Message(L"tdGetNumberOfDevices")); } /** @@ -221,9 +223,9 @@ int WINAPI tdGetNumberOfDevices(void){ * @returns the unique id for the device or -1 if the device is not found. */ int WINAPI tdGetDeviceId(int intDeviceIndex){ - TelldusCore::Message msg(L"tdGetDeviceId"); + Message msg(L"tdGetDeviceId"); msg.addArgument(intDeviceIndex); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -231,9 +233,9 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP */ int WINAPI tdGetDeviceType(int intDeviceId) { - TelldusCore::Message msg(L"tdGetDeviceType"); + Message msg(L"tdGetDeviceType"); msg.addArgument(intDeviceId); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -242,7 +244,7 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * @returns The name of the device or an empty string if the device is not found. */ char * WINAPI tdGetName(int intDeviceId){ - TelldusCore::Message msg(L"tdGetName"); + Message msg(L"tdGetName"); msg.addArgument(intDeviceId); std::wstring strReturn = msg.getClientWStringFromSocket(); return wrapStdWstring(strReturn); @@ -256,7 +258,7 @@ char * WINAPI tdGetName(int intDeviceId){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ - TelldusCore::Message msg(L"tdSetName"); + Message msg(L"tdSetName"); msg.addArgument(intDeviceId); msg.addArgument(strNewName); return msg.getClientBoolFromSocket(); @@ -267,7 +269,7 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ * @param intDeviceId The device id to query. */ char* WINAPI tdGetProtocol(int intDeviceId){ - TelldusCore::Message msg(L"tdGetProtocol"); + Message msg(L"tdGetProtocol"); msg.addArgument(intDeviceId); std::wstring strReturn = msg.getClientWStringFromSocket(); return wrapStdWstring(strReturn); @@ -283,7 +285,7 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * @sa tdSetDeviceParameter() */ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ - TelldusCore::Message msg(L"tdSetProtocol"); + Message msg(L"tdSetProtocol"); msg.addArgument(intDeviceId); msg.addArgument(strProtocol); return msg.getClientBoolFromSocket(); @@ -294,7 +296,7 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ * @param intDeviceId The device to query. */ char* WINAPI tdGetModel(int intDeviceId){ - TelldusCore::Message msg(L"tdGetModel"); + Message msg(L"tdGetModel"); msg.addArgument(intDeviceId); std::wstring strReturn = msg.getClientWStringFromSocket(); return wrapStdWstring(strReturn); @@ -308,7 +310,7 @@ char* WINAPI tdGetModel(int intDeviceId){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ - TelldusCore::Message msg(L"tdSetModel"); + Message msg(L"tdSetModel"); msg.addArgument(intDeviceId); msg.addArgument(strModel); return msg.getClientBoolFromSocket(); @@ -323,7 +325,7 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ - TelldusCore::Message msg(L"tdSetDeviceParameter"); + Message msg(L"tdSetDeviceParameter"); msg.addArgument(intDeviceId); msg.addArgument(strName); msg.addArgument(strValue); @@ -337,7 +339,7 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. */ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ - TelldusCore::Message msg(L"tdGetDeviceParameter"); + Message msg(L"tdGetDeviceParameter"); msg.addArgument(intDeviceId); msg.addArgument(strName); msg.addArgument(defaultValue); @@ -352,8 +354,8 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c * negative value. */ int WINAPI tdAddDevice(){ - TelldusCore::Message msg(L"tdAddDevice"); - return msg.getClientIntegerFromSocket(); + Message msg(L"tdAddDevice"); + return Client::getIntegerFromService(msg); } /** @@ -361,7 +363,7 @@ int WINAPI tdAddDevice(){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdRemoveDevice(int intDeviceId){ - TelldusCore::Message msg(L"tdRemoveDevice"); + Message msg(L"tdRemoveDevice"); msg.addArgument(intDeviceId); return msg.getClientBoolFromSocket(); } @@ -386,10 +388,10 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_DIM */ int WINAPI tdMethods(int id, int methodsSupported){ - TelldusCore::Message msg(L"tdMethods"); + Message msg(L"tdMethods"); msg.addArgument(id); msg.addArgument(methodsSupported); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } /** @@ -434,15 +436,15 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure */ int WINAPI tdSendRawCommand(const char *command, int reserved) { - TelldusCore::Message msg(L"tdSendRawCommand"); + Message msg(L"tdSendRawCommand"); msg.addArgument(command); msg.addArgument(reserved); - return msg.getClientIntegerFromSocket(); + return Client::getIntegerFromService(msg); } void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { - TelldusCore::Message msg(L"tdConnectTellStickController"); + Message msg(L"tdConnectTellStickController"); msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); @@ -450,7 +452,7 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { } void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { - TelldusCore::Message msg(L"tdDisconnectTellStickController"); + Message msg(L"tdDisconnectTellStickController"); msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 69e9aeb8..db561469 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -126,18 +126,8 @@ std::string Message::wideToString(const std::wstring &input){ } bool Message::getClientBoolFromSocket(){ - //TODO: move - return getClientIntegerFromSocket() == 1; -} - -int Message::getClientIntegerFromSocket(){ - //TODO: move - Socket s; - s.connect(L"TelldusClient"); - s.write(this->data()); - - std::wstring response = s.read(); - return takeInt(&response); + //TODO: implement + return false; //getClientIntegerFromSocket() == 1; } std::wstring Message::getClientWStringFromSocket(){ diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 084965e4..36785769 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -15,7 +15,6 @@ namespace TelldusCore { void addArgument(const char *); bool getClientBoolFromSocket(); - int getClientIntegerFromSocket(); std::wstring getClientWStringFromSocket(); static std::wstring charToWstring(const char *value); From 3094384f8a0a067e646f8cccc913c9efb71e0ae9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 10:23:18 +0000 Subject: [PATCH 0376/2215] Converted Message::getClientBoolFromSocket() to Client::getBoolFromService() --- telldus-core/client/Client.cpp | 3 +++ telldus-core/client/Client.h | 1 + telldus-core/client/telldus-core.cpp | 10 +++++----- telldus-core/common/Message.cpp | 5 ----- telldus-core/common/Message.h | 1 - 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 356b49e7..9838fb08 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -41,3 +41,6 @@ int Client::getIntegerFromService(const Message &msg) { return Message::takeInt(&response); } +bool Client::getBoolFromService(const Message &msg) { + return getIntegerFromService(msg) == 1; +} diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index db21e7c1..c6ff203a 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -11,6 +11,7 @@ namespace TelldusCore { static Client *getInstance(); static void close(); + static bool getBoolFromService(const Message &msg); static int getIntegerFromService(const Message &msg); private: diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 88740372..1ee4f868 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -261,7 +261,7 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ Message msg(L"tdSetName"); msg.addArgument(intDeviceId); msg.addArgument(strNewName); - return msg.getClientBoolFromSocket(); + return Client::getBoolFromService(msg); } /** @@ -288,7 +288,7 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ Message msg(L"tdSetProtocol"); msg.addArgument(intDeviceId); msg.addArgument(strProtocol); - return msg.getClientBoolFromSocket(); + return Client::getBoolFromService(msg); } /** @@ -313,7 +313,7 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ Message msg(L"tdSetModel"); msg.addArgument(intDeviceId); msg.addArgument(strModel); - return msg.getClientBoolFromSocket(); + return Client::getBoolFromService(msg); } /** @@ -329,7 +329,7 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha msg.addArgument(intDeviceId); msg.addArgument(strName); msg.addArgument(strValue); - return msg.getClientBoolFromSocket(); + return Client::getBoolFromService(msg); } /** @@ -365,7 +365,7 @@ int WINAPI tdAddDevice(){ bool WINAPI tdRemoveDevice(int intDeviceId){ Message msg(L"tdRemoveDevice"); msg.addArgument(intDeviceId); - return msg.getClientBoolFromSocket(); + return Client::getBoolFromService(msg); } /** diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index db561469..10f82c8e 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -125,11 +125,6 @@ std::string Message::wideToString(const std::wstring &input){ } -bool Message::getClientBoolFromSocket(){ - //TODO: implement - return false; //getClientIntegerFromSocket() == 1; -} - std::wstring Message::getClientWStringFromSocket(){ //TODO: move Socket s; diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 36785769..b3ea2765 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -14,7 +14,6 @@ namespace TelldusCore { void addArgument(int); void addArgument(const char *); - bool getClientBoolFromSocket(); std::wstring getClientWStringFromSocket(); static std::wstring charToWstring(const char *value); From ac9a35af21e3f5dcef8821c3e613ec502c12a7fe Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 10:28:20 +0000 Subject: [PATCH 0377/2215] Converted Message::getClientWStringFromSocket() to Client::getWStringFromService() --- telldus-core/client/Client.cpp | 13 +++++++++++-- telldus-core/client/Client.h | 1 + telldus-core/client/telldus-core.cpp | 14 +++++++------- telldus-core/common/Message.cpp | 10 ---------- telldus-core/common/Message.h | 2 -- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 9838fb08..30646548 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -32,6 +32,10 @@ Client *Client::getInstance() { return Client::instance; } +bool Client::getBoolFromService(const Message &msg) { + return getIntegerFromService(msg) == 1; +} + int Client::getIntegerFromService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); @@ -41,6 +45,11 @@ int Client::getIntegerFromService(const Message &msg) { return Message::takeInt(&response); } -bool Client::getBoolFromService(const Message &msg) { - return getIntegerFromService(msg) == 1; +std::wstring Client::getWStringFromService(const Message &msg) { + Socket s; + s.connect(L"TelldusClient"); + s.write(msg.data()); + + std::wstring response = s.read(); + return Message::takeString(&response); } diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index c6ff203a..8d1a6d6e 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -13,6 +13,7 @@ namespace TelldusCore { static bool getBoolFromService(const Message &msg); static int getIntegerFromService(const Message &msg); + static std::wstring getWStringFromService(const Message &msg); private: Client(); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 1ee4f868..ca308636 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -197,7 +197,7 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { char * WINAPI tdLastSentValue( int intDeviceId ) { Message msg(L"tdLastSentValue"); msg.addArgument(intDeviceId); - std::wstring strReturn = msg.getClientWStringFromSocket(); + std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -246,7 +246,7 @@ int WINAPI tdGetDeviceType(int intDeviceId) { char * WINAPI tdGetName(int intDeviceId){ Message msg(L"tdGetName"); msg.addArgument(intDeviceId); - std::wstring strReturn = msg.getClientWStringFromSocket(); + std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -271,7 +271,7 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ char* WINAPI tdGetProtocol(int intDeviceId){ Message msg(L"tdGetProtocol"); msg.addArgument(intDeviceId); - std::wstring strReturn = msg.getClientWStringFromSocket(); + std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -298,7 +298,7 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ char* WINAPI tdGetModel(int intDeviceId){ Message msg(L"tdGetModel"); msg.addArgument(intDeviceId); - std::wstring strReturn = msg.getClientWStringFromSocket(); + std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -343,7 +343,7 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c msg.addArgument(intDeviceId); msg.addArgument(strName); msg.addArgument(defaultValue); - std::wstring strReturn = msg.getClientWStringFromSocket(); + std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -448,7 +448,7 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); - msg.getClientWStringFromSocket(); + Client::getWStringFromService(msg); } void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { @@ -456,7 +456,7 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); - msg.getClientWStringFromSocket(); + Client::getWStringFromService(msg); } diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 10f82c8e..04bb161f 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -124,13 +124,3 @@ std::string Message::wideToString(const std::wstring &input){ return strReturn; } - -std::wstring Message::getClientWStringFromSocket(){ - //TODO: move - Socket s; - s.connect(L"TelldusClient"); - s.write(this->data()); - - std::wstring response = s.read(); - return takeString(&response); -} diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index b3ea2765..8188af2e 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -13,8 +13,6 @@ namespace TelldusCore { void addArgument(const std::wstring &); void addArgument(int); void addArgument(const char *); - - std::wstring getClientWStringFromSocket(); static std::wstring charToWstring(const char *value); static std::wstring charUnsignedToWstring(const unsigned char value); From bd2e9b9826542d02716c1a9b6fc047d0d8ee47ed Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 10:33:31 +0000 Subject: [PATCH 0378/2215] Added helper function Client::sendToService() --- telldus-core/client/Client.cpp | 14 +++++++------- telldus-core/client/Client.h | 1 + telldus-core/client/telldus-core.cpp | 10 +++++----- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 30646548..6f52fec1 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -37,19 +37,19 @@ bool Client::getBoolFromService(const Message &msg) { } int Client::getIntegerFromService(const Message &msg) { - Socket s; - s.connect(L"TelldusClient"); - s.write(msg.data()); - - std::wstring response = s.read(); + std::wstring response = sendToService(msg); return Message::takeInt(&response); } std::wstring Client::getWStringFromService(const Message &msg) { + std::wstring response = sendToService(msg); + return Message::takeString(&response); +} + +std::wstring Client::sendToService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); s.write(msg.data()); - std::wstring response = s.read(); - return Message::takeString(&response); + return s.read(); } diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 8d1a6d6e..2c192cc7 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -17,6 +17,7 @@ namespace TelldusCore { private: Client(); + static std::wstring sendToService(const Message &msg); class PrivateData; PrivateData *d; diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index ca308636..cd9b16e7 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -363,7 +363,7 @@ int WINAPI tdAddDevice(){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdRemoveDevice(int intDeviceId){ - Message msg(L"tdRemoveDevice"); + Message msg(L"tdRemoveDevice"); msg.addArgument(intDeviceId); return Client::getBoolFromService(msg); } @@ -388,7 +388,7 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_DIM */ int WINAPI tdMethods(int id, int methodsSupported){ - Message msg(L"tdMethods"); + Message msg(L"tdMethods"); msg.addArgument(id); msg.addArgument(methodsSupported); return Client::getIntegerFromService(msg); @@ -436,7 +436,7 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure */ int WINAPI tdSendRawCommand(const char *command, int reserved) { - Message msg(L"tdSendRawCommand"); + Message msg(L"tdSendRawCommand"); msg.addArgument(command); msg.addArgument(reserved); return Client::getIntegerFromService(msg); @@ -444,7 +444,7 @@ int WINAPI tdSendRawCommand(const char *command, int reserved) { void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { - Message msg(L"tdConnectTellStickController"); + Message msg(L"tdConnectTellStickController"); msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); @@ -452,7 +452,7 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { } void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { - Message msg(L"tdDisconnectTellStickController"); + Message msg(L"tdDisconnectTellStickController"); msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); From 08e93318a25fe99ac0661944a34bd74521893328 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 18 Oct 2010 10:42:10 +0000 Subject: [PATCH 0379/2215] EventUpdateManager added --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/EventUpdateManager.cpp | 40 +++++++++++++++++++++ telldus-core/service/EventUpdateManager.h | 16 +++++++++ telldus-core/service/TelldusMain.cpp | 28 +++++++++++++-- 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 telldus-core/service/EventUpdateManager.cpp create mode 100644 telldus-core/service/EventUpdateManager.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 2abd901c..52761cbf 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -12,6 +12,7 @@ SET( telldus-service_SRCS Event.cpp Settings.cpp TelldusMain.cpp + EventUpdateManager.cpp ) SET( telldus-service_protocol_SRCS Protocol.h @@ -51,6 +52,7 @@ SET( telldus-service_HDRS Settings.h TelldusMain.h TellStick.h + EventUpdateManager.h ) FIND_PACKAGE(Threads) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp new file mode 100644 index 00000000..9e8afc05 --- /dev/null +++ b/telldus-core/service/EventUpdateManager.cpp @@ -0,0 +1,40 @@ +#include "EventUpdateManager.h" + +class EventUpdateManager::PrivateData { +public: + +}; + +EventUpdateManager::EventUpdateManager(){ + d = new PrivateData; +} + +EventUpdateManager::~EventUpdateManager(void) { + /* + for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + delete( it->second ); + } + */ + delete d; +} + +void EventUpdateManager::sendUpdateMessage(int eventDeviceChanges, int eventChangeType, int eventMethod, int deviceType, int deviceId){ + /* + for(){ + if(isalive){ + + it++; + } + else{ + //ta bort + delete *it; + it = ngt.erase(it); + } + } + */ + + //meddela alla klienter i listan + //eventdata - vad som har hänt + //måste kolla så att de inte har kopplats ifrån, ta bort från listan då också + //tömma listan vid delete, deletea respektive +} \ No newline at end of file diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h new file mode 100644 index 00000000..e351559a --- /dev/null +++ b/telldus-core/service/EventUpdateManager.h @@ -0,0 +1,16 @@ +#ifndef EVENTUPDATEMANAGER_H +#define EVENTUPDATEMANAGER_H + +class EventUpdateManager { +public: + EventUpdateManager(void); + ~EventUpdateManager(void); + + void sendUpdateMessage(int eventDeviceChanges, int eventChangeType, int eventMethod, int deviceType, int deviceId); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //EVENTUPDATEMANAGER_H \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 4c81f9d5..45b44744 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -4,6 +4,7 @@ #include "ClientCommunicationHandler.h" #include "DeviceManager.h" #include "ControllerManager.h" +#include "EventUpdateManager.h" #include #include @@ -14,6 +15,15 @@ public: bool inserted; }; +class EventUpdateData : public EventDataBase { +public: + int eventDeviceChanges; + int eventMethod; + int eventChangeType; + int deviceType; + int deviceId; +}; + class TelldusMain::PrivateData { public: EventHandler eventHandler; @@ -44,13 +54,14 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); + Event *updateEvent = d->eventHandler.addEvent(); ControllerManager controllerManager; DeviceManager deviceManager(&controllerManager); + EventUpdateManager eventUpdateManager; ConnectionListener clientListener(L"TelldusClient", clientEvent); - //TODO: eventlistener - + std::list clientCommunicationHandlerList; while(!d->stopEvent->isSignaled()) { @@ -79,6 +90,19 @@ void TelldusMain::start(void) { delete eventData; } + if(updateEvent->isSignaled()){ + + //till egen tråd, ett ngt-handler-objekt... + //en lyssnare som lyssnar efter nya connections + //lagra sockets... + //tråd... gör trådsäkert... + EventData *eventData = updateEvent->takeSignal(); + EventUpdateData *data = reinterpret_cast(eventData); + if(data){ + eventUpdateManager.sendUpdateMessage(data->eventDeviceChanges, data->eventChangeType, data->eventMethod, data->deviceType, data->deviceId); + } + delete eventData; + } for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ if ((*it)->isDone()){ From 7ea2f3bbb83116dd8e502daac801d69481c258c6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Oct 2010 11:05:43 +0000 Subject: [PATCH 0380/2215] Implemented register and unregister of callbacks. --- telldus-core/client/Client.cpp | 68 ++++++++++++++++++++++++++++ telldus-core/client/Client.h | 6 +++ telldus-core/client/telldus-core.cpp | 13 ++++-- 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 6f52fec1..3e8a2765 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,17 +1,36 @@ #include "Client.h" #include "Socket.h" +#include + using namespace TelldusCore; +template struct CallbackStruct { + T event; + int id; + void *context; +}; +typedef CallbackStruct DeviceEvent; +typedef CallbackStruct DeviceChangeEvent; +typedef CallbackStruct RawDeviceEvent; +typedef std::list DeviceEventList; +typedef std::list DeviceChangeList; +typedef std::list RawDeviceEventList; + class Client::PrivateData { public: Socket eventSocket; + int lastCallbackId; + DeviceEventList deviceEventList; + DeviceChangeList deviceChangeEventList; + RawDeviceEventList rawDeviceEventList; }; Client *Client::instance = 0; Client::Client() { d = new PrivateData; + d->lastCallbackId = 0; d->eventSocket.connect(L"TelldusEvents"); } @@ -46,6 +65,27 @@ std::wstring Client::getWStringFromService(const Message &msg) { return Message::takeString(&response); } +int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { + int id = ++d->lastCallbackId; + DeviceEvent callback = {eventFunction, id, context}; + d->deviceEventList.push_back(callback); + return id; +} + +int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { + int id = ++d->lastCallbackId; + DeviceChangeEvent callback = {eventFunction, id, context}; + d->deviceChangeEventList.push_back(callback); + return id; +} + +int Client::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { + int id = ++d->lastCallbackId; + RawDeviceEvent callback = {eventFunction, id, context}; + d->rawDeviceEventList.push_back(callback); + return id; +} + std::wstring Client::sendToService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); @@ -53,3 +93,31 @@ std::wstring Client::sendToService(const Message &msg) { return s.read(); } + +bool Client::unregisterCallback( int callbackId ) { + for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + if ( (*callback_it).id != callbackId ) { + continue; + } + d->deviceEventList.erase(callback_it); + return true; + } + + for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + if ( (*callback_it).id != callbackId ) { + continue; + } + d->deviceChangeEventList.erase(callback_it); + return true; + } + + for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + if ( (*callback_it).id != callbackId ) { + continue; + } + d->rawDeviceEventList.erase(callback_it); + return true; + } + + return false; +} \ No newline at end of file diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 2c192cc7..b1e57d1d 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -2,6 +2,7 @@ #define CLIENT_H #include "Message.h" +#include "telldus-core.h" namespace TelldusCore { class Client{ @@ -11,6 +12,11 @@ namespace TelldusCore { static Client *getInstance(); static void close(); + int registerDeviceEvent( TDDeviceEvent eventFunction, void *context ); + int registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ); + int registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + bool unregisterCallback( int callbackId ); + static bool getBoolFromService(const Message &msg); static int getIntegerFromService(const Message &msg); static std::wstring getWStringFromService(const Message &msg); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index cd9b16e7..0e661065 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -76,22 +76,25 @@ void WINAPI tdInit(void) { } int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - return 0; + Client *client = Client::getInstance(); + return client->registerDeviceEvent( eventFunction, context ); } int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { - return 0; + Client *client = Client::getInstance(); + return client->registerRawDeviceEvent( eventFunction, context ); } int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { - return 0; + Client *client = Client::getInstance(); + return client->registerDeviceChangeEvent( eventFunction, context ); } int WINAPI tdUnregisterCallback( int callbackId ) { - return TELLSTICK_SUCCESS; + Client *client = Client::getInstance(); + return client->unregisterCallback( callbackId ); } - /** * Close the library and clean up the cache it uses. * This should be called when the library is not supposed to be used anymore From eabfd97db565a2b983de30194e4f2fa217389db7 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 18 Oct 2010 12:49:42 +0000 Subject: [PATCH 0381/2215] Update events, stubs --- .../service/ClientCommunicationHandler.cpp | 5 +- .../service/ClientCommunicationHandler.h | 2 +- telldus-core/service/EventUpdateManager.cpp | 69 +++++++++++++++---- telldus-core/service/EventUpdateManager.h | 22 +++++- telldus-core/service/TelldusMain.cpp | 28 ++------ 5 files changed, 85 insertions(+), 41 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index dec8e7fe..f8c8cace 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -4,7 +4,7 @@ class ClientCommunicationHandler::PrivateData { public: TelldusCore::Socket *clientSocket; - Event *event; + Event *event, *deviceUpdateEvent; bool done; DeviceManager *deviceManager; }; @@ -13,7 +13,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(){ } -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, Event *deviceUpdateEvent) :Thread() { d = new PrivateData; @@ -21,6 +21,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie d->event = event; d->done = false; d->deviceManager = deviceManager; + d->deviceUpdateEvent = deviceUpdateEvent; } diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 37cb3bab..adfd3a06 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -12,7 +12,7 @@ class ClientCommunicationHandler : public TelldusCore::Thread { public: ClientCommunicationHandler(); - ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager); + ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, Event *deviceUpdateEvent); ~ClientCommunicationHandler(void); bool isDone(); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 9e8afc05..610e1e60 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -1,24 +1,74 @@ #include "EventUpdateManager.h" +#include "Socket.h" +#include "EventHandler.h" + +#include + +typedef std::list SocketList; + class EventUpdateManager::PrivateData { public: - + EventHandler eventHandler; + Event *stopEvent, *updateEvent, *clientConnectEvent; + SocketList clients; }; -EventUpdateManager::EventUpdateManager(){ +EventUpdateManager::EventUpdateManager() + :Thread() +{ d = new PrivateData; + d->stopEvent = d->eventHandler.addEvent(); + d->updateEvent = d->eventHandler.addEvent(); + d->clientConnectEvent = d->eventHandler.addEvent(); } EventUpdateManager::~EventUpdateManager(void) { - /* - for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - delete( it->second ); + d->stopEvent->signal(); + wait(); + delete d->stopEvent; + delete d->updateEvent; + delete d->clientConnectEvent; + + for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) { + delete(*it); } - */ + delete d; } -void EventUpdateManager::sendUpdateMessage(int eventDeviceChanges, int eventChangeType, int eventMethod, int deviceType, int deviceId){ +Event *EventUpdateManager::retrieveUpdateEvent(){ + + return d->updateEvent; +} + +Event *EventUpdateManager::retrieveClientConnectEvent(){ + return d->clientConnectEvent; +} + +void EventUpdateManager::run(){ + + while(!d->stopEvent->isSignaled()){ + if (!d->eventHandler.waitForAny()) { + continue; + } + + if(d->clientConnectEvent->isSignaled()){ + //lägg till ny klient + } + else if(d->updateEvent->isSignaled()){ + //event har inträffat + //datan innehåller informationen om eventet som har skickats + //Finns i eventDatan: int eventDeviceChanges, int eventChangeType, int eventMethod, int deviceType, int deviceId + EventData *eventData = d->updateEvent->takeSignal(); + EventUpdateData *data = reinterpret_cast(eventData); + + sendMessageToClients(data); + } + } +} + +void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ /* for(){ if(isalive){ @@ -32,9 +82,4 @@ void EventUpdateManager::sendUpdateMessage(int eventDeviceChanges, int eventChan } } */ - - //meddela alla klienter i listan - //eventdata - vad som har hänt - //måste kolla så att de inte har kopplats ifrån, ta bort från listan då också - //tömma listan vid delete, deletea respektive } \ No newline at end of file diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index e351559a..ef982807 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -1,16 +1,34 @@ #ifndef EVENTUPDATEMANAGER_H #define EVENTUPDATEMANAGER_H -class EventUpdateManager { +#include "Thread.h" +#include "Event.h" + +class EventUpdateData : public EventDataBase { +public: + int eventDeviceChanges; + int eventMethod; + int eventChangeType; + int deviceType; + int deviceId; +}; + +class EventUpdateManager : public TelldusCore::Thread +{ public: EventUpdateManager(void); ~EventUpdateManager(void); - void sendUpdateMessage(int eventDeviceChanges, int eventChangeType, int eventMethod, int deviceType, int deviceId); + Event *retrieveUpdateEvent(); + Event *retrieveClientConnectEvent(); + +protected: + void run(); private: class PrivateData; PrivateData *d; + void sendMessageToClients(EventUpdateData *data); }; #endif //EVENTUPDATEMANAGER_H \ No newline at end of file diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 45b44744..06de58e9 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -15,15 +15,6 @@ public: bool inserted; }; -class EventUpdateData : public EventDataBase { -public: - int eventDeviceChanges; - int eventMethod; - int eventChangeType; - int deviceType; - int deviceId; -}; - class TelldusMain::PrivateData { public: EventHandler eventHandler; @@ -59,8 +50,11 @@ void TelldusMain::start(void) { ControllerManager controllerManager; DeviceManager deviceManager(&controllerManager); EventUpdateManager eventUpdateManager; + Event *deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); + Event *clientConnectUpdateEvent = eventUpdateManager.retrieveClientConnectEvent(); ConnectionListener clientListener(L"TelldusClient", clientEvent); + ConnectionListener eventUpdateClientListener(L"TelldusEvent", clientConnectUpdateEvent); std::list clientCommunicationHandlerList; @@ -74,7 +68,7 @@ void TelldusMain::start(void) { ConnectionListenerEventData *data = reinterpret_cast(eventData); if (data) { Event *handlerEvent = d->eventHandler.addEvent(); - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } @@ -90,20 +84,6 @@ void TelldusMain::start(void) { delete eventData; } - if(updateEvent->isSignaled()){ - - //till egen tråd, ett ngt-handler-objekt... - //en lyssnare som lyssnar efter nya connections - //lagra sockets... - //tråd... gör trådsäkert... - EventData *eventData = updateEvent->takeSignal(); - EventUpdateData *data = reinterpret_cast(eventData); - if(data){ - eventUpdateManager.sendUpdateMessage(data->eventDeviceChanges, data->eventChangeType, data->eventMethod, data->deviceType, data->deviceId); - } - delete eventData; - } - for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ if ((*it)->isDone()){ delete *it; From 80843dc99cbb0c84088f40440678eba49b2b2175 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 18 Oct 2010 15:33:05 +0000 Subject: [PATCH 0382/2215] Device callback events implemented server side (untested) --- telldus-core/common/Socket.h | 1 + telldus-core/common/Socket_win.cpp | 8 ++- telldus-core/service/DeviceManager.cpp | 13 ++++- telldus-core/service/DeviceManager.h | 3 +- telldus-core/service/EventUpdateManager.cpp | 62 +++++++++++++++------ telldus-core/service/EventUpdateManager.h | 8 ++- telldus-core/service/TelldusMain.cpp | 8 +-- 7 files changed, 72 insertions(+), 31 deletions(-) diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 5c95a64a..3985bf26 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -19,6 +19,7 @@ namespace TelldusCore { virtual ~Socket(void); void connect(const std::wstring &server); + bool isConnected(); std::wstring read(); void write(const std::wstring &msg); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 2c342468..203ee449 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -111,13 +111,17 @@ void Socket::write(const std::wstring &msg){ result = WaitForSingleObject(writeEvent, 10000); if (result == WAIT_TIMEOUT) { CloseHandle(writeEvent); - //d->connected = false; + d->connected = false; return; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, false); CloseHandle(writeEvent); if (!fSuccess) { - //d->connected = false; + d->connected = false; return; } +} + +bool Socket::isConnected(){ + return d->connected; } \ No newline at end of file diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 1f78d6f5..fd4ca387 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -13,11 +13,13 @@ public: Settings set; TelldusCore::Mutex lock; ControllerManager *controllerManager; + Event *deviceUpdateEvent; }; -DeviceManager::DeviceManager(ControllerManager *controllerManager){ +DeviceManager::DeviceManager(ControllerManager *controllerManager, Event *deviceUpdateEvent){ d = new PrivateData; d->controllerManager = controllerManager; + d->deviceUpdateEvent = deviceUpdateEvent; fillDevices(); } @@ -371,7 +373,6 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found } - //TODO: Get controller here (controllermanager -> locks its own list, controller -> lock for send etc) Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); if(controller){ int retval = device->doAction(action, data, controller); @@ -385,7 +386,13 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ TelldusCore::MutexLocker deviceLocker(&d->lock); d->set.setDeviceState(deviceId, action, datastring); } - //TODO: Signal event, status change? + + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDDeviceEvent"; + eventData->eventMethod = action; + eventData->deviceId = deviceId; + eventData->eventValue = datastring; + d->deviceUpdateEvent->signal(eventData); } device->unlock(); return retval; diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 12616fef..22e01970 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -3,11 +3,12 @@ #include "Device.h" #include "ControllerManager.h" +#include "EventUpdateManager.h" class DeviceManager { public: - DeviceManager(ControllerManager *controllerManager); + DeviceManager(ControllerManager *controllerManager, Event *deviceUpdateEvent); ~DeviceManager(void); int getNumberOfDevices(void); int addDevice(); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 610e1e60..41556ef9 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -1,7 +1,9 @@ #include "EventUpdateManager.h" -#include "Socket.h" +#include "ConnectionListener.h" #include "EventHandler.h" +#include "Message.h" +#include "Socket.h" #include @@ -12,6 +14,7 @@ public: EventHandler eventHandler; Event *stopEvent, *updateEvent, *clientConnectEvent; SocketList clients; + ConnectionListener *eventUpdateClientListener; }; EventUpdateManager::EventUpdateManager() @@ -21,6 +24,7 @@ EventUpdateManager::EventUpdateManager() d->stopEvent = d->eventHandler.addEvent(); d->updateEvent = d->eventHandler.addEvent(); d->clientConnectEvent = d->eventHandler.addEvent(); + d->eventUpdateClientListener = new ConnectionListener(L"TelldusEvents", d->clientConnectEvent); } EventUpdateManager::~EventUpdateManager(void) { @@ -28,7 +32,7 @@ EventUpdateManager::~EventUpdateManager(void) { wait(); delete d->stopEvent; delete d->updateEvent; - delete d->clientConnectEvent; + delete d->eventUpdateClientListener; for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) { delete(*it); @@ -42,10 +46,6 @@ Event *EventUpdateManager::retrieveUpdateEvent(){ return d->updateEvent; } -Event *EventUpdateManager::retrieveClientConnectEvent(){ - return d->clientConnectEvent; -} - void EventUpdateManager::run(){ while(!d->stopEvent->isSignaled()){ @@ -54,32 +54,58 @@ void EventUpdateManager::run(){ } if(d->clientConnectEvent->isSignaled()){ - //lägg till ny klient + //new client added + EventData *eventData = d->clientConnectEvent->takeSignal(); + ConnectionListenerEventData *data = reinterpret_cast(eventData); + if(data){ + d->clients.push_back(data->socket); + } } else if(d->updateEvent->isSignaled()){ - //event har inträffat - //datan innehåller informationen om eventet som har skickats - //Finns i eventDatan: int eventDeviceChanges, int eventChangeType, int eventMethod, int deviceType, int deviceId + //device event, signal all clients EventData *eventData = d->updateEvent->takeSignal(); EventUpdateData *data = reinterpret_cast(eventData); - - sendMessageToClients(data); + if(data){ + sendMessageToClients(data); + } } } } void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ - /* - for(){ - if(isalive){ + + for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();){ + + if((*it)->isConnected()){ + + TelldusCore::Message msg; + + if(data->messageType == L"TDDeviceEvent"){ + msg.addArgument("TDDeviceEvent"); + msg.addArgument(data->deviceId); + msg.addArgument(data->eventMethod); + msg.addArgument(data->eventValue); //string + } + else if(data->messageType == L"TDDeviceChangeEvent"){ + msg.addArgument("TDDeviceChangeEvent"); + msg.addArgument(data->deviceId); + msg.addArgument(data->eventDeviceChanges); + msg.addArgument(data->eventChangeType); + } + else if(data->messageType == L"TDRawDeviceEvent"){ + msg.addArgument("TDRawDeviceEvent"); + msg.addArgument(data->eventValue); //string + msg.addArgument(data->controllerId); + } + + (*it)->write(msg); it++; } else{ - //ta bort + //connection is dead, remove it delete *it; - it = ngt.erase(it); + it = d->clients.erase(it); } } - */ } \ No newline at end of file diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index ef982807..85904544 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -6,11 +6,13 @@ class EventUpdateData : public EventDataBase { public: + std::wstring messageType; + int controllerId; + int deviceId; + int eventChangeType; int eventDeviceChanges; int eventMethod; - int eventChangeType; - int deviceType; - int deviceId; + std::wstring eventValue; }; class EventUpdateManager : public TelldusCore::Thread diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 06de58e9..b89f25d3 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -8,6 +8,7 @@ #include #include +#include //TODO DEBUG class DeviceEventData : public EventDataBase { public: @@ -42,19 +43,18 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { d->deviceChangeEvent->signal(data); } - void TelldusMain::start(void) { + Sleep(6000); Event *clientEvent = d->eventHandler.addEvent(); Event *updateEvent = d->eventHandler.addEvent(); ControllerManager controllerManager; - DeviceManager deviceManager(&controllerManager); EventUpdateManager eventUpdateManager; Event *deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); - Event *clientConnectUpdateEvent = eventUpdateManager.retrieveClientConnectEvent(); + eventUpdateManager.start(); + DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); ConnectionListener clientListener(L"TelldusClient", clientEvent); - ConnectionListener eventUpdateClientListener(L"TelldusEvent", clientConnectUpdateEvent); std::list clientCommunicationHandlerList; From 96f66a26f7134ca2bf4b74bb71d07ddb3d1e19ba Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 19 Oct 2010 09:35:16 +0000 Subject: [PATCH 0383/2215] IsConnected fixed, now reflects status of connection --- telldus-core/common/Socket_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 203ee449..5e8bfb4a 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -24,7 +24,7 @@ Socket::Socket(SOCKET_T hPipe) { d = new PrivateData; d->hPipe = hPipe; - + d->connected = true; } From 2c2a030c9bcafa165faee55870a69f50bb8a09e7 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 19 Oct 2010 12:31:32 +0000 Subject: [PATCH 0384/2215] Callback events implemented on client side (not tested for device and raw events) --- telldus-core/client/Client.cpp | 79 ++++++++++++++++++++- telldus-core/client/Client.h | 13 +++- telldus-core/common/Socket.h | 1 + telldus-core/common/Socket_win.cpp | 30 ++++++-- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/EventUpdateManager.cpp | 2 +- telldus-core/service/EventUpdateManager.h | 2 +- telldus-core/service/TelldusMain.cpp | 2 - 8 files changed, 115 insertions(+), 16 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 3e8a2765..c187b072 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,5 +1,6 @@ #include "Client.h" #include "Socket.h" +#include "Mutex.h" #include @@ -19,22 +20,33 @@ typedef std::list RawDeviceEventList; class Client::PrivateData { public: - Socket eventSocket; int lastCallbackId; DeviceEventList deviceEventList; DeviceChangeList deviceChangeEventList; + Socket eventSocket; RawDeviceEventList rawDeviceEventList; + bool running; + TelldusCore::Mutex mutex; }; Client *Client::instance = 0; -Client::Client() { +Client::Client() + : Thread() +{ d = new PrivateData; d->lastCallbackId = 0; - d->eventSocket.connect(L"TelldusEvents"); + d->running = true; + start(); } Client::~Client(void) { + stopThread(); + wait(); + { + TelldusCore::MutexLocker locker(&d->mutex); + } + //TODO empty event lists? delete d; } @@ -51,6 +63,27 @@ Client *Client::getInstance() { return Client::instance; } +void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue){ + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceEventList::const_iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + (*callback_it).event(deviceId, deviceState, Message::wideToString(deviceStateValue).c_str(), (*callback_it).id, (*callback_it).context); + } +} + +void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType){ + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceChangeList::const_iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + (*callback_it).event(deviceId, eventDeviceChanges, eventChangeType, (*callback_it).id, (*callback_it).context); + } +} + +void Client::callbackRawEvent(std::wstring command, int controllerId){ + TelldusCore::MutexLocker locker(&d->mutex); + for(RawDeviceEventList::const_iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + (*callback_it).event(Message::wideToString(command).c_str(), controllerId, (*callback_it).id, (*callback_it).context); + } +} + bool Client::getBoolFromService(const Message &msg) { return getIntegerFromService(msg) == 1; } @@ -66,6 +99,7 @@ std::wstring Client::getWStringFromService(const Message &msg) { } int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { + TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; DeviceEvent callback = {eventFunction, id, context}; d->deviceEventList.push_back(callback); @@ -73,6 +107,7 @@ int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { } int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { + TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; DeviceChangeEvent callback = {eventFunction, id, context}; d->deviceChangeEventList.push_back(callback); @@ -80,12 +115,44 @@ int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void * } int Client::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { + TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; RawDeviceEvent callback = {eventFunction, id, context}; d->rawDeviceEventList.push_back(callback); return id; } +void Client::run(){ + //listen here + d->eventSocket.connect(L"TelldusEvents"); + + while(d->running && d->eventSocket.isConnected()){ + //TODO hm, isConnected, never gets the chance of reconnect here... Should maybe retry every something seconds + std::wstring clientMessage = d->eventSocket.read(); + if(clientMessage != L""){ + //a message arrived + std::wstring type = Message::takeString(&clientMessage); + if(type == L"TDDeviceChangeEvent"){ + int deviceId = Message::takeInt(&clientMessage); + int eventDeviceChanges = Message::takeInt(&clientMessage); + int eventChangeType = Message::takeInt(&clientMessage); + callbackDeviceChangeEvent(deviceId, eventDeviceChanges, eventChangeType); + } + else if(type == L"TDDeviceEvent"){ + int deviceId = Message::takeInt(&clientMessage); + int eventState = Message::takeInt(&clientMessage); + std::wstring eventValue = Message::takeString(&clientMessage); + callbackDeviceEvent(deviceId, eventState, eventValue); + } + else if(type == L"TDRawDeviceEvent"){ + std::wstring command = Message::takeString(&clientMessage); + int controllerId = Message::takeInt(&clientMessage); + callbackRawEvent(command, controllerId); + } + } + } +} + std::wstring Client::sendToService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); @@ -94,7 +161,13 @@ std::wstring Client::sendToService(const Message &msg) { return s.read(); } +void Client::stopThread(){ + d->running = false; + d->eventSocket.stopReadWait(); +} + bool Client::unregisterCallback( int callbackId ) { + TelldusCore::MutexLocker locker(&d->mutex); for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { if ( (*callback_it).id != callbackId ) { continue; diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index b1e57d1d..ad017212 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -3,24 +3,33 @@ #include "Message.h" #include "telldus-core.h" +#include "Thread.h" namespace TelldusCore { - class Client{ + class Client : public Thread + { public: ~Client(void); static Client *getInstance(); static void close(); - + + void callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue); + void callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType); + void callbackRawEvent(std::wstring command, int controllerId); int registerDeviceEvent( TDDeviceEvent eventFunction, void *context ); int registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ); int registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + void stopThread(void); bool unregisterCallback( int callbackId ); static bool getBoolFromService(const Message &msg); static int getIntegerFromService(const Message &msg); static std::wstring getWStringFromService(const Message &msg); + protected: + void run(void); + private: Client(); static std::wstring sendToService(const Message &msg); diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 3985bf26..a77270a4 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -21,6 +21,7 @@ namespace TelldusCore { void connect(const std::wstring &server); bool isConnected(); std::wstring read(); + void stopReadWait(); void write(const std::wstring &msg); private: diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 5e8bfb4a..99a08234 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -11,13 +11,16 @@ using namespace TelldusCore; class Socket::PrivateData { public: HANDLE hPipe; + HANDLE readEvent; bool connected; + bool running; }; Socket::Socket() { d = new PrivateData; d->hPipe = INVALID_HANDLE_VALUE; d->connected = false; + d->running = true; } Socket::Socket(SOCKET_T hPipe) @@ -25,10 +28,13 @@ Socket::Socket(SOCKET_T hPipe) d = new PrivateData; d->hPipe = hPipe; d->connected = true; + d->running = true; } Socket::~Socket(void){ + d->running = false; + SetEvent(d->readEvent); //signal for break if (d->hPipe != INVALID_HANDLE_VALUE) { CloseHandle(d->hPipe); } @@ -66,33 +72,45 @@ void Socket::connect(const std::wstring &server){ d->connected = true; } +void Socket::stopReadWait(){ + d->running = false; + SetEvent(d->readEvent); +} + std::wstring Socket::read() { wchar_t buf[BUFSIZE]; int result; DWORD cbBytesRead = 0; OVERLAPPED oOverlap; - HANDLE readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - oOverlap.hEvent = readEvent; + + d->readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + oOverlap.hEvent = d->readEvent; BOOL fSuccess = false; memset(&buf, 0, BUFSIZE); ReadFile( d->hPipe, &buf, sizeof(wchar_t)*BUFSIZE, &cbBytesRead, &oOverlap); - result = WaitForSingleObject(oOverlap.hEvent, 10000); + result = WaitForSingleObject(oOverlap.hEvent, 20000); + + if(!d->running){ + CloseHandle(d->readEvent); + return L""; + } + if (result == WAIT_TIMEOUT) { - CloseHandle(readEvent); + CloseHandle(d->readEvent); return L""; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); if (!fSuccess) { DWORD err = GetLastError(); if (err == ERROR_BROKEN_PIPE) { - //TODO: Connection closed + d->connected = false; } buf[0] = 0; } - CloseHandle(readEvent); + CloseHandle(d->readEvent); return buf; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index fd4ca387..56995c13 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -389,7 +389,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ EventUpdateData *eventData = new EventUpdateData(); eventData->messageType = L"TDDeviceEvent"; - eventData->eventMethod = action; + eventData->eventState = action; eventData->deviceId = deviceId; eventData->eventValue = datastring; d->deviceUpdateEvent->signal(eventData); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 41556ef9..09d66b1a 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -83,7 +83,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ if(data->messageType == L"TDDeviceEvent"){ msg.addArgument("TDDeviceEvent"); msg.addArgument(data->deviceId); - msg.addArgument(data->eventMethod); + msg.addArgument(data->eventState); msg.addArgument(data->eventValue); //string } else if(data->messageType == L"TDDeviceChangeEvent"){ diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 85904544..c8d565f8 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -11,7 +11,7 @@ public: int deviceId; int eventChangeType; int eventDeviceChanges; - int eventMethod; + int eventState; std::wstring eventValue; }; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index b89f25d3..156b60a6 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -8,7 +8,6 @@ #include #include -#include //TODO DEBUG class DeviceEventData : public EventDataBase { public: @@ -44,7 +43,6 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { } void TelldusMain::start(void) { - Sleep(6000); Event *clientEvent = d->eventHandler.addEvent(); Event *updateEvent = d->eventHandler.addEvent(); From 91b037bcce6c23da7522ffc283ca11dd1881633f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Oct 2010 15:33:27 +0000 Subject: [PATCH 0385/2215] Implemented bell --- telldus-core/service/DeviceManager.cpp | 18 +++++++++++------- telldus-core/service/ProtocolNexa.cpp | 19 ++++++++++++++++--- telldus-core/service/ProtocolNexa.h | 1 + 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 56995c13..d13ecf5d 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -378,7 +378,16 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ int retval = device->doAction(action, data, controller); if(retval == TELLSTICK_SUCCESS){ std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); - device->setLastSentCommand(action, datastring); + if (action != TELLSTICK_BELL) { + device->setLastSentCommand(action, datastring); + //TODO: This should maybe be done someware else since the event could be triggered by a TellStick Duo aswell + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDDeviceEvent"; + eventData->eventState = action; + eventData->deviceId = deviceId; + eventData->eventValue = datastring; + d->deviceUpdateEvent->signal(eventData); + } device->unlock(); { //new lock, for setting (all other locks are unlocked) @@ -387,12 +396,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ d->set.setDeviceState(deviceId, action, datastring); } - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDDeviceEvent"; - eventData->eventState = action; - eventData->deviceId = deviceId; - eventData->eventValue = datastring; - d->deviceUpdateEvent->signal(eventData); + } device->unlock(); return retval; diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 335504e4..5b716b42 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -17,10 +17,12 @@ int ProtocolNexa::methods() const { } std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *) { - if (!comparei(model(), L"codeswitch")) { - return getStringSelflearning(method, data); + if (comparei(model(), L"codeswitch")) { + return getStringCodeSwitch(method); + } else if (comparei(model(), L"bell")) { + return getStringBell(); } - return getStringCodeSwitch(method); + return getStringSelflearning(method, data); } std::string ProtocolNexa::getStringCodeSwitch(int method) { @@ -41,6 +43,17 @@ std::string ProtocolNexa::getStringCodeSwitch(int method) { return strReturn; } +std::string ProtocolNexa::getStringBell() { + std::string strReturn = "S"; + + std::wstring house = getStringParameter(L"house", L"A"); + int intHouse = house[0] - L'A'; + strReturn.append(getCodeSwitchTuple(intHouse)); + strReturn.append("$kk$$kk$$kk$$k$k"); //Unit 7 + strReturn.append("$kk$$kk$$kk$$kk$$k+"); //Bell + return strReturn; +} + std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { const char START[] = {'T',127,255,24,1,0}; // const char START[] = {'T',130,255,26,24,0}; diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index ad72e168..33840558 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -12,6 +12,7 @@ public: protected: std::string getStringSelflearning(int method, unsigned char data); std::string getStringCodeSwitch(int method); + std::string getStringBell(); virtual std::string getOffCode() const; static std::string getCodeSwitchTuple(int code); }; From 46bfb123cf292da8dee4abdafd690fa13b3e0971 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 20 Oct 2010 07:45:26 +0000 Subject: [PATCH 0386/2215] Changed socket read/write timeouts. Read to INIFINITE (otherwise one extra click was needed for each timeout-time passed since the last click for callbacks to be registered) and Write to only 500 ms instead of 10 seconds. When a button is clicked after clients disconnect, callbacks and even new client connects will wait for this timeout for each disconnected client. If this is a problem, it will have to be solved in another way, perhaps a "client disconnect"-event that can be called at least when clients are shut down correctly? --- telldus-core/client/Client.cpp | 1 - telldus-core/common/Socket_win.cpp | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index c187b072..3559a81c 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -46,7 +46,6 @@ Client::~Client(void) { { TelldusCore::MutexLocker locker(&d->mutex); } - //TODO empty event lists? delete d; } diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 99a08234..bbee39c2 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -91,8 +91,8 @@ std::wstring Socket::read() { ReadFile( d->hPipe, &buf, sizeof(wchar_t)*BUFSIZE, &cbBytesRead, &oOverlap); - result = WaitForSingleObject(oOverlap.hEvent, 20000); - + result = WaitForSingleObject(oOverlap.hEvent, INFINITE); + if(!d->running){ CloseHandle(d->readEvent); return L""; @@ -126,7 +126,7 @@ void Socket::write(const std::wstring &msg){ WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); - result = WaitForSingleObject(writeEvent, 10000); + result = WaitForSingleObject(writeEvent, 500); if (result == WAIT_TIMEOUT) { CloseHandle(writeEvent); d->connected = false; From 464000515c0191622a9b0425996612e3fed6a9a1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 20 Oct 2010 11:00:59 +0000 Subject: [PATCH 0387/2215] Signaling on name (tested) /model/protocol change, and add/remove device (tested). Error when clients connect/disconnect many times. --- .../service/ClientCommunicationHandler.cpp | 46 +++++++++++-------- .../service/ClientCommunicationHandler.h | 1 + telldus-core/service/DeviceManager.cpp | 6 +-- telldus-core/service/Settings.h | 1 + telldus-core/service/SettingsWinRegistry.cpp | 14 +++--- 5 files changed, 39 insertions(+), 29 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index f8c8cace..692833c9 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -120,8 +120,8 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); (*intReturn) = d->deviceManager->setDeviceName(deviceId, name); - //TODO, signal event - + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME); + } else if (function == L"tdGetProtocol") { int deviceId = TelldusCore::Message::takeInt(&msg); (*wstringReturn) = d->deviceManager->getDeviceProtocol(deviceId); @@ -130,7 +130,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring protocol = TelldusCore::Message::takeString(&msg); (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); - //TODO, signal event + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); } else if (function == L"tdGetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -140,7 +140,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring model = TelldusCore::Message::takeString(&msg); (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); - //TODO, signal event + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); } else if (function == L"tdGetDeviceParameter") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -152,26 +152,25 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring value = TelldusCore::Message::takeString(&msg); - (*intReturn) = 0; d->deviceManager->setDeviceParameter(deviceId, name, value); - //TODO, signal event + (*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value); } else if (function == L"tdAddDevice") { - if(d->deviceManager->addDevice()){ - (*intReturn) = 1; - //TODO: signalEvent, or do that from where this is called? Or even inside addDevice? + (*intReturn) = d->deviceManager->addDevice(); + if((*intReturn) >= 0){ + sendDeviceSignal((*intReturn), TELLSTICK_DEVICE_ADDED, 0); } } else if (function == L"tdRemoveDevice") { int deviceId = TelldusCore::Message::takeInt(&msg); - if(d->deviceManager->removeDevice(deviceId)){ - (*intReturn) = 1; - //TODO: signalEvent, or do that from where this is called? Or even inside removeDevice? + (*intReturn) = d->deviceManager->removeDevice(deviceId); + if((*intReturn) == TELLSTICK_DEVICE_REMOVED){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0); } } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); + (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); } else if (function == L"tdGetErrorString") { int errorNo = TelldusCore::Message::takeInt(&msg); @@ -181,23 +180,22 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, std::wstring command = TelldusCore::Message::takeString(&msg); int reserved = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->sendRawCommand(command, reserved); + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDRawDeviceEvent"; + eventData->controllerId = -1; + eventData->eventValue = command; + d->deviceUpdateEvent->signal(eventData); } else if (function == L"tdConnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); std::wstring serial = TelldusCore::Message::takeString(&msg); d->deviceManager->connectTellStickController(vid, pid, serial); - //TODO, return what? - //TODO, signal event? Or done in other place? - } else if (function == L"tdDisconnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); std::wstring serial = TelldusCore::Message::takeString(&msg); d->deviceManager->disconnectTellStickController(vid, pid, serial); - //TODO, return what? - //TODO, signal event? Or done in other place? - } else{ (*intReturn) = TELLSTICK_ERROR_UNKNOWN; @@ -225,3 +223,13 @@ std::wstring ClientCommunicationHandler::getErrorString(int errorNo){ return TelldusCore::Message::charToWstring(responses[errorNo]); } } + +void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType){ + + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDDeviceChangeEvent"; + eventData->deviceId = deviceId; + eventData->eventDeviceChanges = eventDeviceChanges; + eventData->eventChangeType = eventChangeType; + d->deviceUpdateEvent->signal(eventData); +} diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index adfd3a06..42387e32 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -25,6 +25,7 @@ private: PrivateData *d; std::wstring getErrorString(int errorNo); void parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn); + void sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType); }; #endif //CLIENTCOMMUNICATIONHANDLER_H \ No newline at end of file diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index d13ecf5d..5dd76a40 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -316,7 +316,7 @@ int DeviceManager::addDevice(){ if(!d->devices[id]){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } - return TELLSTICK_DEVICE_ADDED; + return id; } int DeviceManager::getDeviceId(int deviceIndex) { @@ -394,9 +394,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ //TODO, it MAY be inconsistency between stored values and device values here... change something? TelldusCore::MutexLocker deviceLocker(&d->lock); d->set.setDeviceState(deviceId, action, datastring); - } - - + } } device->unlock(); return retval; diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index f8be01f2..0687859d 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -39,6 +39,7 @@ private: class PrivateData; PrivateData *d; + }; #endif diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 7c1a4370..1951043a 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -146,18 +146,20 @@ int Settings::getNextDeviceId() const { * Remove a device */ bool Settings::removeDevice(int intDeviceId){ - bool blnSuccess = true; - + std::wostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; std::wstring strCompleteRegPath = ssRegPath.str(); - long lngSuccess = RegDeleteKeyEx(d->rootKey, strCompleteRegPath.c_str(), KEY_WOW64_32KEY|KEY_WOW64_64KEY, 0); - if(lngSuccess != ERROR_SUCCESS){ - blnSuccess = false; + long lngSuccess32 = RegDeleteKeyEx(d->rootKey, strCompleteRegPath.c_str(), KEY_WOW64_32KEY, 0); + long lngSuccess64 = RegDeleteKeyEx(d->rootKey, strCompleteRegPath.c_str(), KEY_WOW64_64KEY, 0); + + if(lngSuccess32 == ERROR_SUCCESS || lngSuccess64 == ERROR_SUCCESS){ + //one of the deletions succeded + return true; } - return blnSuccess; + return false; } std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const { From 2c7f7b52cc2776cc02fc6702d6b2d9a66f91fe08 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Oct 2010 12:48:07 +0000 Subject: [PATCH 0388/2215] Listen for messages from TellStick (Duo). We don't handle the data yet though. --- telldus-core/service/TellStick.h | 6 +- telldus-core/service/TellStick_ftd2xx.cpp | 71 +++++++++++++++++++++-- 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 6cf6ba2b..4c957909 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -13,6 +13,7 @@ #define TELLSTICK_H #include "Controller.h" +#include "Thread.h" #include class TellStickDescriptor { @@ -21,7 +22,7 @@ public: int vid, pid; }; -class TellStick : public Controller { +class TellStick : public Controller, public TelldusCore::Thread { public: TellStick(const TellStickDescriptor &d); virtual ~TellStick(); @@ -35,9 +36,10 @@ public: static std::list findAll(); protected: + void processData( const std::string &data ); + void run(); void setBaud( int baud ); - private: static std::list findAllByVIDPID( int vid, int pid ); diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 1c98816c..2c124226 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -10,6 +10,7 @@ // // #include "TellStick.h" +#include "Mutex.h" #include "../client/telldus-core.h" #include @@ -17,17 +18,24 @@ class TellStick::PrivateData { public: - bool open; - int vid, pid; - std::string serial; + bool open, running; + int vid, pid, fwVersion; + std::string serial, message; FT_HANDLE ftHandle; + TelldusCore::Mutex mutex; + + HANDLE eh; + }; TellStick::TellStick( const TellStickDescriptor &td ) { d = new PrivateData; + d->eh = CreateEvent( NULL, false, false, NULL ); d->open = false; + d->running = false; d->vid = td.vid; d->pid = td.pid; + d->fwVersion = 0; d->serial = td.serial; char *tempSerial = new char[td.serial.size()+1]; @@ -51,10 +59,17 @@ TellStick::TellStick( const TellStickDescriptor &td ) { } else { setBaud(4800); } + this->start(); } } TellStick::~TellStick() { + if (d->running) { + TelldusCore::MutexLocker locker(&d->mutex); + d->running = false; + SetEvent(d->eh); + } + this->wait(); if (d->open) { } delete d; @@ -65,7 +80,7 @@ void TellStick::setBaud( int baud ) { } int TellStick::firmwareVersion() { - return 1; + return d->fwVersion; } bool TellStick::isOpen() const { @@ -85,12 +100,60 @@ bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const { return true; } +void TellStick::processData( const std::string &data ) { + for (unsigned int i = 0; i < data.length(); ++i) { + if (data[i] == 13) { // Skip \r + continue; + } else if (data[i] == 10) { // \n found + if (d->message.substr(0,2).compare("+V") == 0) { + //TODO save the firmware version + } else if (d->message.substr(0,2).compare("+R") == 0) { + //TODO + } + d->message.clear(); + } else { // Append the character + d->message.append( 1, data[i] ); + } + } +} + +void TellStick::run() { + d->running = true; + DWORD dwBytesInQueue = 0; + DWORD dwBytesRead = 0; + char *buf = 0; + + while(1) { + FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, d->eh); + WaitForSingleObject(d->eh,INFINITE); + + TelldusCore::MutexLocker locker(&d->mutex); + if (!d->running) { + break; + } + FT_GetQueueStatus(d->ftHandle, &dwBytesInQueue); + if (dwBytesInQueue < 1) { + continue; + } + buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); + memset(buf, 0, dwBytesInQueue+1); + FT_Read(d->ftHandle, buf, dwBytesInQueue, &dwBytesRead); + processData( buf ); + free(buf); + } +} + int TellStick::send( const std::string &strMessage ) { if (!d->open) { return TELLSTICK_ERROR_NOT_FOUND; } bool c = true; + //This lock does two things + // 1 Prevents two calls from different threads to this function + // 2 Prevents our running thread from receiving the data we are interested in here + TelldusCore::MutexLocker(&d->mutex); + char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); #ifdef _WINDOWS strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str()); From 4dd2e249728415c32df78a58162c2f719c4af03c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Oct 2010 13:27:53 +0000 Subject: [PATCH 0389/2215] Added an event for controllers to signal. --- telldus-core/service/Controller.cpp | 16 +++++++++++++-- telldus-core/service/Controller.h | 23 ++++++++++++++++------ telldus-core/service/ControllerManager.cpp | 8 +++++--- telldus-core/service/ControllerManager.h | 3 ++- telldus-core/service/TellStick.h | 2 +- telldus-core/service/TellStick_ftd2xx.cpp | 6 ++++-- telldus-core/service/TelldusMain.cpp | 12 ++++++++++- 7 files changed, 54 insertions(+), 16 deletions(-) diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index ee7e632d..1fe93e8b 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -1,9 +1,21 @@ #include "Controller.h" -Controller::Controller(){ +class Controller::PrivateData { +public: + Event *event; +}; +Controller::Controller(Event *event){ + d = new PrivateData; + d->event = event; } Controller::~Controller(){ + delete d; +} -} \ No newline at end of file +void Controller::publishData(const std::string &msg) const { + ControllerEventData *data = new ControllerEventData; + data->msg = msg; + d->event->signal(data); +} diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 599732d3..147761af 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -1,17 +1,28 @@ #ifndef CONTROLLER_H #define CONTROLLER_H +#include "Event.h" #include +class ControllerEventData : public EventDataBase { +public: + std::string msg; +}; + class Controller { - public: - virtual ~Controller(); +public: + virtual ~Controller(); - virtual int firmwareVersion() = 0; - virtual int send( const std::string &message ) = 0; + virtual int firmwareVersion() = 0; + virtual int send( const std::string &message ) = 0; - protected: - Controller(); +protected: + Controller(Event *event); + void publishData(const std::string &data) const; + +private: + class PrivateData; + PrivateData *d; }; #endif //CONTROLLER_H \ No newline at end of file diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index a5ba8c19..7b15af03 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -12,16 +12,18 @@ class ControllerManager::PrivateData { public: int lastControllerId; ControllerMap controllers; //TODO: lock in controls, for send etc + Event *event; TelldusCore::Mutex mutex; }; -ControllerManager::ControllerManager(){ +ControllerManager::ControllerManager(Event *event){ d = new PrivateData; d->lastControllerId = 0; + d->event = event; this->loadControllers(); } -ControllerManager::~ControllerManager(void) { +ControllerManager::~ControllerManager() { for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { delete( it->second ); } @@ -93,7 +95,7 @@ void ControllerManager::loadControllers() { continue; } - TellStick *controller = new TellStick(*it); + TellStick *controller = new TellStick(d->event, *it); if (!controller->isOpen()) { delete controller; continue; diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 964f9bae..78104240 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -2,10 +2,11 @@ #define CONTROLLERMANAGER_H class Controller; +class Event; class ControllerManager { public: - ControllerManager(void); + ControllerManager(Event *event); ~ControllerManager(void); void deviceInsertedOrRemoved(int vid, int pid, bool inserted); diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 4c957909..d6bae8eb 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -24,7 +24,7 @@ public: class TellStick : public Controller, public TelldusCore::Thread { public: - TellStick(const TellStickDescriptor &d); + TellStick(Event *event, const TellStickDescriptor &d); virtual ~TellStick(); virtual int firmwareVersion(); diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 2c124226..3943214f 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -28,7 +28,9 @@ public: }; -TellStick::TellStick( const TellStickDescriptor &td ) { +TellStick::TellStick(Event *event, const TellStickDescriptor &td ) + :Controller(event) +{ d = new PrivateData; d->eh = CreateEvent( NULL, false, false, NULL ); d->open = false; @@ -108,7 +110,7 @@ void TellStick::processData( const std::string &data ) { if (d->message.substr(0,2).compare("+V") == 0) { //TODO save the firmware version } else if (d->message.substr(0,2).compare("+R") == 0) { - //TODO + this->publishData(d->message); } d->message.clear(); } else { // Append the character diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 156b60a6..5c1eb9d0 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -8,6 +8,7 @@ #include #include +#include class DeviceEventData : public EventDataBase { public: @@ -45,8 +46,9 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); Event *updateEvent = d->eventHandler.addEvent(); + std::auto_ptr dataEvent(d->eventHandler.addEvent()); - ControllerManager controllerManager; + ControllerManager controllerManager(dataEvent.get()); EventUpdateManager eventUpdateManager; Event *deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); eventUpdateManager.start(); @@ -82,6 +84,14 @@ void TelldusMain::start(void) { delete eventData; } + if (dataEvent->isSignaled()) { + std::auto_ptr eventData(dataEvent->takeSignal()); + ControllerEventData *data = reinterpret_cast(eventData.get()); + if (data) { + //TODO: Handle the message + } + } + for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ if ((*it)->isDone()){ delete *it; From e68c3b8bca2c568f2ca1bc25e5dc337da8114c4d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Oct 2010 13:49:08 +0000 Subject: [PATCH 0390/2215] Iterator cannot be const if we want to erase something from it --- telldus-core/service/ControllerManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 7b15af03..8ea666ae 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -41,7 +41,7 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) loadControllers(); } else { TelldusCore::MutexLocker locker(&d->mutex); - for(ControllerMap::const_iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { TellStick *tellstick = reinterpret_cast(it->second); if (!tellstick) { continue; From 78de101080c602e6859b0e14a3b71257234025bd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Oct 2010 13:52:51 +0000 Subject: [PATCH 0391/2215] Added missing include --- telldus-core/service/ClientCommunicationHandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 692833c9..e42329df 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -1,6 +1,8 @@ #include "ClientCommunicationHandler.h" #include "Message.h" +#include + class ClientCommunicationHandler::PrivateData { public: TelldusCore::Socket *clientSocket; From 0291473b01de10456d355a1a91972fc92a652322 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Oct 2010 14:50:30 +0000 Subject: [PATCH 0392/2215] Link client library againgt a threading library --- telldus-core/client/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index ac8484dd..cf9cfce8 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -15,7 +15,8 @@ SET( telldus-core_PUB_HDRS telldus-core.h ) - +FIND_PACKAGE(Threads) +LIST(APPEND telldus-core_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../common @@ -78,7 +79,7 @@ ADD_LIBRARY(${telldus-core_TARGET} SHARED TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY FRAMEWORK TRUE + PROPERTY FRAMEWORK TRUE ) SET_PROPERTY(TARGET ${telldus-core_TARGET} PROPERTY PUBLIC_HEADER ${telldus-core_PUB_HDRS} @@ -108,7 +109,7 @@ IF (UNIX AND NOT APPLE) SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) - + INSTALL(FILES tellstick.conf DESTINATION ${SYSCONF_INSTALL_DIR} ) From c94afb760e1eb9a00b158e7d6d075a7410922b00 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Oct 2010 14:51:43 +0000 Subject: [PATCH 0393/2215] Made socket compile under Linux. Some functions still need to be implemented --- telldus-core/common/Socket_unix.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 6fe6f28f..2dfa4110 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -15,17 +15,20 @@ int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { class Socket::PrivateData { public: SOCKET_T socket; + bool connected; }; Socket::Socket() { d = new PrivateData; d->socket = 0; + d->connected = false; } Socket::Socket(SOCKET_T socket) { d = new PrivateData; d->socket = socket; + d->connected = true; } Socket::~Socket(void) { @@ -35,31 +38,42 @@ Socket::~Socket(void) { void Socket::connect(const std::wstring &server) { struct sockaddr_un remote; socklen_t len; - + if ((d->socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { return; } std::string name = "/tmp/" + std::string(server.begin(), server.end()); remote.sun_family = AF_UNIX; strcpy(remote.sun_path, name.c_str()); - + len = SUN_LEN(&remote); if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { return; } + d->connected = true; +} + +bool Socket::isConnected(){ + return d->connected; } std::wstring Socket::read() { + //TODO set d->conneted to false if something goes wrong char inbuf[BUFSIZE]; memset(inbuf, '\0', sizeof(inbuf)); - + recv(d->socket, inbuf, BUFSIZE - 1, 0); std::string msg(inbuf); return std::wstring(msg.begin(), msg.end()); } +void Socket::stopReadWait(){ + //TODO: +} + void Socket::write(const std::wstring &msg) { + //TODO set d->conneted to false if something goes wrong std::string newMsg(msg.begin(), msg.end()); send(d->socket, newMsg.c_str(), newMsg.length(), 0); } From 4029342094122ad47c588f18c2c296ad1de0b4e2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Oct 2010 15:17:33 +0000 Subject: [PATCH 0394/2215] Implemented TellStick_libftdi on Linux, stille some work is needed --- telldus-core/service/TellStick_libftdi.cpp | 69 +++++++++++++++++++--- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index a42247de..d4a85d78 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: TellStick // -// Description: +// Description: // // // Author: Micke Prag , (C) 2009 @@ -20,15 +20,23 @@ class TellStick::PrivateData { public: bool open; + int vid, pid, fwVersion; + std::string serial, message; ftdi_context ftHandle; }; -TellStick::TellStick( const TellStickDescriptor &td ) { +TellStick::TellStick(Event *event, const TellStickDescriptor &td ) + :Controller(event) +{ d = new PrivateData; d->open = false; + d->vid = td.vid; + d->pid = td.pid; + d->fwVersion = 0; + d->serial = td.serial; ftdi_init(&d->ftHandle); - + int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str()); if (ret < 0) { ftdi_deinit(&d->ftHandle); @@ -37,7 +45,7 @@ TellStick::TellStick( const TellStickDescriptor &td ) { d->open = true; ftdi_usb_reset( &d->ftHandle ); ftdi_disable_bitbang( &d->ftHandle ); - + if (d->open) { // setBaud(4800); } @@ -59,6 +67,23 @@ bool TellStick::isOpen() const { return d->open; } +bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const { + if (td.vid != d->vid) { + return false; + } + if (td.pid != d->pid) { + return false; + } + if (td.serial != d->serial) { + return false; + } + return true; +} + +void TellStick::run() { + //TODO +} + int TellStick::send( const std::string &message ) { return TELLSTICK_SUCCESS; } @@ -72,17 +97,43 @@ std::list TellStick::findAll() { } return tellstick; - + } -std::list TellStick::findAllByVIDPID( int vid, int pid ) { - std::list retval; - +bool TellStick::stillConnected() const { ftdi_context ftdic; struct ftdi_device_list *devlist, *curdev; char serialBuffer[10]; ftdi_init(&ftdic); - + bool found = false; + + int ret = ftdi_usb_find_all(&ftdic, &devlist, d->vid, d->pid); + if (ret > 0) { + for (curdev = devlist; curdev != NULL; curdev = curdev->next) { + ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10); + if (ret != 0) { + continue; + } + if (d->serial.compare(serialBuffer) == 0) { + found = true; + break; + } + } + } + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + return found; +} + +std::list TellStick::findAllByVIDPID( int vid, int pid ) { + std::list retval; + + ftdi_context ftdic; + struct ftdi_device_list *devlist, *curdev; + char serialBuffer[10]; + ftdi_init(&ftdic); + int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid); if (ret > 0) { for (curdev = devlist; curdev != NULL; curdev = curdev->next) { From e47891fb0680d7045f76227633b3452432600b40 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 20 Oct 2010 15:19:08 +0000 Subject: [PATCH 0395/2215] Client callback listener will now reconnect if the service disappears and then comes back. --- telldus-core/client/Client.cpp | 14 ++++++++++++-- telldus-core/service/SettingsWinRegistry.cpp | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 3559a81c..f03ab309 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,6 +1,7 @@ #include "Client.h" #include "Socket.h" #include "Mutex.h" +#include "Common.h" #include @@ -125,8 +126,17 @@ void Client::run(){ //listen here d->eventSocket.connect(L"TelldusEvents"); - while(d->running && d->eventSocket.isConnected()){ - //TODO hm, isConnected, never gets the chance of reconnect here... Should maybe retry every something seconds + while(d->running){ + + if(!d->eventSocket.isConnected()){ + d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service + if(!d->eventSocket.isConnected()){ + //reconnect didn't succeed, wait a while and try again + msleep(2000); + continue; + } + } + std::wstring clientMessage = d->eventSocket.read(); if(clientMessage != L""){ //a message arrived diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 1951043a..b946ecba 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -155,7 +155,7 @@ bool Settings::removeDevice(int intDeviceId){ long lngSuccess64 = RegDeleteKeyEx(d->rootKey, strCompleteRegPath.c_str(), KEY_WOW64_64KEY, 0); if(lngSuccess32 == ERROR_SUCCESS || lngSuccess64 == ERROR_SUCCESS){ - //one of the deletions succeded + //one of the deletions succeeded return true; } From 8eed8e6db5b687a2f68805ea77f4a9daea68738d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 20 Oct 2010 15:19:33 +0000 Subject: [PATCH 0396/2215] Possible deadlock fix --- telldus-core/service/TellStick_ftd2xx.cpp | 34 ++++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 3943214f..07866f6b 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -129,19 +129,25 @@ void TellStick::run() { FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, d->eh); WaitForSingleObject(d->eh,INFINITE); - TelldusCore::MutexLocker locker(&d->mutex); - if (!d->running) { - break; + { + d->mutex.lock(); + //TelldusCore::MutexLocker locker(&d->mutex); + if (!d->running) { + d->mutex.unlock(); + break; + } + FT_GetQueueStatus(d->ftHandle, &dwBytesInQueue); + if (dwBytesInQueue < 1) { + d->mutex.unlock(); + continue; + } + buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); + memset(buf, 0, dwBytesInQueue+1); + FT_Read(d->ftHandle, buf, dwBytesInQueue, &dwBytesRead); + processData( buf ); + free(buf); + d->mutex.unlock(); } - FT_GetQueueStatus(d->ftHandle, &dwBytesInQueue); - if (dwBytesInQueue < 1) { - continue; - } - buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); - memset(buf, 0, dwBytesInQueue+1); - FT_Read(d->ftHandle, buf, dwBytesInQueue, &dwBytesRead); - processData( buf ); - free(buf); } } @@ -154,7 +160,8 @@ int TellStick::send( const std::string &strMessage ) { //This lock does two things // 1 Prevents two calls from different threads to this function // 2 Prevents our running thread from receiving the data we are interested in here - TelldusCore::MutexLocker(&d->mutex); + d->mutex.lock(); + //TelldusCore::MutexLocker(&d->mutex); char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); #ifdef _WINDOWS @@ -184,6 +191,7 @@ int TellStick::send( const std::string &strMessage ) { } } + d->mutex.unlock(); if (!c) { return TELLSTICK_ERROR_COMMUNICATION; } From ef2e54a05c5b4c3ce6f72b65f06e343adb7c8300 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 07:39:13 +0000 Subject: [PATCH 0397/2215] Don't do a double unlock. --- telldus-core/service/DeviceManager.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 5dd76a40..1e40a001 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -93,8 +93,6 @@ int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, std::wstr return TELLSTICK_SUCCESS; } - - std::wstring DeviceManager::getDeviceStateValue(int deviceId){ TelldusCore::MutexLocker deviceLocker(&d->lock); if (!d->devices.size()) { @@ -395,8 +393,9 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ TelldusCore::MutexLocker deviceLocker(&d->lock); d->set.setDeviceState(deviceId, action, datastring); } + } else { + device->unlock(); } - device->unlock(); return retval; } else{ From efe4d7bd59ebbd20b5d9d3c169c8c9c94c72494b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Oct 2010 10:10:57 +0000 Subject: [PATCH 0398/2215] Moved common.h to project Common --- telldus-core/common/CMakeLists.txt | 1 + telldus-core/{client => common}/common.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) rename telldus-core/{client => common}/common.h (63%) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 0f316c94..0618c39c 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -10,6 +10,7 @@ SET( telldus-common_SRCS ) SET( telldus-common_HDRS + common.h Message.h Mutex.h Socket.h diff --git a/telldus-core/client/common.h b/telldus-core/common/common.h similarity index 63% rename from telldus-core/client/common.h rename to telldus-core/common/common.h index 728a2b50..5ffd417b 100644 --- a/telldus-core/client/common.h +++ b/telldus-core/common/common.h @@ -13,6 +13,7 @@ #else #include #endif +#include #include #include #include @@ -25,6 +26,24 @@ inline void msleep( const int msec) { #endif } +inline void debuglog(const int intMessage, const std::string strMessage){ + + static bool firstRun = true; + std::ofstream file; + std::string filename("C:/log_locks.txt"); + if (firstRun) { + file.open(filename.c_str(), std::ios::out); + firstRun = false; + } else { + file.open(filename.c_str(), std::ios::out | std::ios::app); + } + + file << intMessage << " - " << strMessage << "\n"; + file.flush(); + file.close(); + +} + inline char *wrapStdString( const std::string &string) { #ifdef _WINDOWS return (char *)SysAllocStringByteLen(string.c_str(), (unsigned int)string.size()); From b1bbecbe999d2056aeb735fe98a1fabfc00ba368 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Oct 2010 10:11:56 +0000 Subject: [PATCH 0399/2215] Fix for non-unlocking mutexes on Windows. --- telldus-core/common/Mutex.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index 0b3dcf4e..453f234b 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -11,6 +11,7 @@ // #include "Mutex.h" +#include "common.h" using namespace TelldusCore; @@ -48,7 +49,13 @@ Mutex::~Mutex() { void Mutex::lock() { #ifdef _WINDOWS - EnterCriticalSection(&d->mutex); + //What we would want is to use EnterCriticalSection instead of our loop. + //For some reason Windows doesn't always let our thread enter the critical section + //even when another thread leaves the critical section + //This loop seems to fix the problem. + while(!TryEnterCriticalSection(&d->mutex)) { + msleep(5); + } #else pthread_mutex_lock(&d->mutex); #endif From a9f8acc0639a8bc9a63fc3172269a66331ffc65f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Oct 2010 11:36:51 +0000 Subject: [PATCH 0400/2215] More consistent locks --- telldus-core/service/ControllerManager.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 201 ++++++++------------- 2 files changed, 78 insertions(+), 125 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 8ea666ae..33915663 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -11,7 +11,7 @@ typedef std::map ControllerMap; class ControllerManager::PrivateData { public: int lastControllerId; - ControllerMap controllers; //TODO: lock in controls, for send etc + ControllerMap controllers; Event *event; TelldusCore::Mutex mutex; }; diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 1e40a001..5eb06522 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -25,18 +25,18 @@ DeviceManager::DeviceManager(ControllerManager *controllerManager, Event *device DeviceManager::~DeviceManager(void) { - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { - {TelldusCore::MutexLocker lock(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere + {TelldusCore::MutexLocker deviceLocker(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere delete(it->second); } delete d; } void DeviceManager::fillDevices(){ - TelldusCore::MutexLocker deviceLocker(&d->lock); int numberOfDevices = d->set.getNumberOfDevices(); - + TelldusCore::MutexLocker deviceListLocker(&d->lock); + for (int i = 0; i < numberOfDevices; ++i) { int id = d->set.getDeviceId(i); d->devices[id] = new Device(id); @@ -55,13 +55,13 @@ void DeviceManager::fillDevices(){ } int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getLastSentCommand(methodsSupported); } return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -69,38 +69,30 @@ int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, std::wstring value) { - //TODO: check this locking, ok? - Device *device = 0; - { - TelldusCore::MutexLocker deviceLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - device = it->second; - d->set.setDeviceState(deviceId, command,value); - } - else{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } } - if(device){ - TelldusCore::MutexLocker lock(device); - device->setLastSentCommand(command, value); + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + d->set.setDeviceState(deviceId, command,value); + it->second->setLastSentCommand(command, value); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } - return TELLSTICK_SUCCESS; } std::wstring DeviceManager::getDeviceStateValue(int deviceId){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; //TODO, what? } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getStateValue(); } return L"UNKNOWN"; //TODO, what? @@ -110,14 +102,14 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ Device *device = 0; { //devices locked - TelldusCore::MutexLocker devicesLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - it->second->lock(); //device locked TODO + TelldusCore::MutexLocker deviceLocker(it->second); device = it->second; } //devices unlocked @@ -134,13 +126,13 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ std::wstring DeviceManager::getDeviceModel(int deviceId){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; //TODO, what? } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getModel(); } return L"UNKNOWN"; //TODO, what? @@ -148,40 +140,32 @@ std::wstring DeviceManager::getDeviceModel(int deviceId){ int DeviceManager::setDeviceModel(int deviceId, std::wstring model) { - //TODO: check this locking, ok? - Device *device = 0; - { - TelldusCore::MutexLocker deviceLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - device = it->second; - d->set.setModel(deviceId, model); - } - else{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } } - if(device){ - TelldusCore::MutexLocker lock(device); - device->setModel(model); - //TODO Reset protocol here? + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + d->set.setModel(deviceId, model); + it->second->setModel(model); } - + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + return TELLSTICK_SUCCESS; } std::wstring DeviceManager::getDeviceName(int deviceId){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; //TODO, what? } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getName(); } return L"UNKNOWN"; //TODO, what? @@ -189,25 +173,18 @@ std::wstring DeviceManager::getDeviceName(int deviceId){ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ - //TODO: check this locking, ok? - Device *device = 0; - { - TelldusCore::MutexLocker deviceLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - device = it->second; - d->set.setName(deviceId, name); - } - else{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } } - if(device){ - TelldusCore::MutexLocker lock(device); - device->setName(name); + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + d->set.setName(deviceId, name); + it->second->setName(name); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_SUCCESS; @@ -215,13 +192,13 @@ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, std::wstring defaultValue){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return defaultValue; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()){ - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + TelldusCore::MutexLocker deviceLocker(it->second); std::wstring returnString = it->second->getParameter(name); if(returnString != L""){ return returnString; @@ -232,40 +209,32 @@ std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, int DeviceManager::setDeviceParameter(int deviceId, std::wstring name, std::wstring value) { - //TODO: check this locking, ok? - Device *device = 0; - { - TelldusCore::MutexLocker deviceLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - device = it->second; - d->set.setDeviceParameter(deviceId, name, value); - } - else{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } } - if(device){ - TelldusCore::MutexLocker lock(device); - device->setParameter(name, value); - //TODO Reset protocol here? + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + d->set.setDeviceParameter(deviceId, name, value); + it->second->setParameter(name, value); } - + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + return TELLSTICK_SUCCESS; } std::wstring DeviceManager::getDeviceProtocol(int deviceId){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; //TODO, what? } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getProtocolName(); } return L"UNKNOWN"; //TODO, what? @@ -273,43 +242,36 @@ std::wstring DeviceManager::getDeviceProtocol(int deviceId){ int DeviceManager::setDeviceProtocol(int deviceId, std::wstring protocol) { - //TODO: check this locking, ok? - Device *device = 0; - { - TelldusCore::MutexLocker deviceLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - device = it->second; - d->set.setProtocol(deviceId, protocol); - } - else{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } } - if(device){ - TelldusCore::MutexLocker lock(device); - device->setProtocolName(protocol); + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + d->set.setProtocol(deviceId, protocol); + it->second->setProtocolName(protocol); } - + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + return TELLSTICK_SUCCESS; } int DeviceManager::getNumberOfDevices(){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); return (int)d->devices.size(); } int DeviceManager::addDevice(){ - TelldusCore::MutexLocker deviceLocker(&d->lock); int id = d->set.addDevice(); if(id == -1){ return TELLSTICK_ERROR_UNKNOWN; } + TelldusCore::MutexLocker deviceListLocker(&d->lock); d->devices[id] = new Device(id); if(!d->devices[id]){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -318,7 +280,6 @@ int DeviceManager::addDevice(){ } int DeviceManager::getDeviceId(int deviceIndex) { - TelldusCore::MutexLocker deviceLocker(&d->lock); return d->set.getDeviceId(deviceIndex); } @@ -329,14 +290,14 @@ int DeviceManager::getDeviceType(int deviceId){ int DeviceManager::getPreferredControllerId(int deviceId){ - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - //TODO: Is it ok NOT to get a lock here? Should be, since the list is locked, and it's an fast operation? + TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getPreferredControllerId(); } return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -354,7 +315,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Device *device = 0; { //devices locked - TelldusCore::MutexLocker deviceLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -408,11 +369,11 @@ int DeviceManager::removeDevice(int deviceId){ Device *device = 0; { - TelldusCore::MutexLocker deviceLocker(&d->lock); if(!d->set.removeDevice(deviceId)){ //remove from register/settings return TELLSTICK_ERROR_UNKNOWN; } + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -428,14 +389,6 @@ int DeviceManager::removeDevice(int deviceId){ {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else delete device; - //1 lås lista - //2 ta bort från registret - //4 plocka ut device ur lista - //* Lås upp lista - //3 vänta på device lås - //{TelldusCore::MutexLocker(&device);} - //6 delete device - return TELLSTICK_DEVICE_REMOVED; } From 88820fc85d0d161dd5f19732ee83c5a6fcaf409c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 11:46:57 +0000 Subject: [PATCH 0401/2215] Added locks to all public functions in Settings --- telldus-core/service/Settings.cpp | 13 +++++++++++++ telldus-core/service/Settings.h | 3 ++- telldus-core/service/SettingsWinRegistry.cpp | 12 +++++++++--- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 056a26b6..118075f5 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -4,6 +4,7 @@ * Get the name of the device */ std::wstring Settings::getName(int intDeviceId) const { + TelldusCore::MutexLocker locker(&mutex); return getStringSetting(intDeviceId, L"name", false); } @@ -11,6 +12,7 @@ std::wstring Settings::getName(int intDeviceId) const { * Set the name of the device */ bool Settings::setName(int intDeviceId, const std::wstring &strNewName){ + TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, L"name", strNewName, false); } @@ -18,6 +20,7 @@ bool Settings::setName(int intDeviceId, const std::wstring &strNewName){ * Get the device vendor */ std::wstring Settings::getProtocol(int intDeviceId) const { + TelldusCore::MutexLocker locker(&mutex); return getStringSetting(intDeviceId, L"protocol", false); } @@ -25,6 +28,7 @@ std::wstring Settings::getProtocol(int intDeviceId) const { * Set the device vendor */ bool Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ + TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, L"protocol", strVendor, false); } @@ -32,6 +36,7 @@ bool Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ * Get the device model */ std::wstring Settings::getModel(int intDeviceId) const { + TelldusCore::MutexLocker locker(&mutex); return getStringSetting(intDeviceId, L"model", false); } @@ -39,6 +44,7 @@ std::wstring Settings::getModel(int intDeviceId) const { * Set the device model */ bool Settings::setModel(int intDeviceId, const std::wstring &strModel){ + TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, L"model", strModel, false); } @@ -46,6 +52,7 @@ bool Settings::setModel(int intDeviceId, const std::wstring &strModel){ * Set device argument */ bool Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue){ + TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, strName, strValue, true); } @@ -53,6 +60,7 @@ bool Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, * Get device argument */ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &strName) const { + TelldusCore::MutexLocker locker(&mutex); return getStringSetting(intDeviceId, strName, true); } @@ -60,6 +68,7 @@ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &s * Set preferred controller id */ bool Settings::setPreferredControllerId(int intDeviceId, int value){ + TelldusCore::MutexLocker locker(&mutex); return setIntSetting(intDeviceId, L"controller", value, false); } @@ -67,22 +76,26 @@ bool Settings::setPreferredControllerId(int intDeviceId, int value){ * Get preferred controller id */ int Settings::getPreferredControllerId(int intDeviceId) { + TelldusCore::MutexLocker locker(&mutex); return getIntSetting(intDeviceId, L"controller", false); } #ifndef _CONFUSE bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { + TelldusCore::MutexLocker locker(&mutex); bool retval = setIntSetting( intDeviceId, L"state", intDeviceState, true ); setStringSetting( intDeviceId, L"stateValue", strDeviceStateValue, true ); return retval; } int Settings::getDeviceState( int intDeviceId ) const { + TelldusCore::MutexLocker locker(&mutex); return getIntSetting( intDeviceId, L"state", true ); } std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { + TelldusCore::MutexLocker locker(&mutex); return getStringSetting( intDeviceId, L"stateValue", true ); } diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 0687859d..e353a311 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -2,6 +2,7 @@ #define SETTINGS_H #include +#include "Mutex.h" class Settings { public: @@ -39,7 +40,7 @@ private: class PrivateData; PrivateData *d; - + mutable TelldusCore::Mutex mutex; }; #endif diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index b946ecba..3333a66a 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -36,7 +36,8 @@ Settings::~Settings(void) { * Return the number of stored devices */ int Settings::getNumberOfDevices(void) const { - + TelldusCore::MutexLocker locker(&mutex); + int intNumberOfDevices = 0; HKEY hk; @@ -57,6 +58,8 @@ int Settings::getNumberOfDevices(void) const { int Settings::getDeviceId(int intDeviceIndex) const { + TelldusCore::MutexLocker locker(&mutex); + int intReturn = -1; HKEY hk; @@ -79,7 +82,8 @@ int Settings::getDeviceId(int intDeviceIndex) const { /* * Add a new device */ -int Settings::addDevice(){ +int Settings::addDevice() { + TelldusCore::MutexLocker locker(&mutex); int intDeviceId = -1; HKEY hk; @@ -104,6 +108,7 @@ int Settings::addDevice(){ * Get next available device id */ int Settings::getNextDeviceId() const { + //Private, no locks needed int intReturn = -1; HKEY hk; DWORD dwDisp; @@ -145,7 +150,8 @@ int Settings::getNextDeviceId() const { /* * Remove a device */ -bool Settings::removeDevice(int intDeviceId){ +bool Settings::removeDevice(int intDeviceId) { + TelldusCore::MutexLocker locker(&mutex); std::wostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; From b9d7c2838d6f4f62046dc3b97e435331740371be Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 11:49:35 +0000 Subject: [PATCH 0402/2215] Converted manual mutex locks to use MutexLocker by an auto_ptr. --- telldus-core/service/DeviceManager.cpp | 33 +++++++++----------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 5eb06522..fe3ab595 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -313,24 +313,23 @@ void DeviceManager::disconnectTellStickController(int vid, int pid, std::wstring int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Device *device = 0; + //On the stack and will be released if we have a device lock. + std::auto_ptr deviceLocker(0); { - //devices locked + //devicelist locked TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - it->second->lock(); //device locked - device = it->second; + if (it == d->devices.end()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found } - //devices unlocked - } - - if (!device) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found - } + //device locked + deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); + device = it->second; + } //devicelist unlocked Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); if(controller){ @@ -347,20 +346,10 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ eventData->eventValue = datastring; d->deviceUpdateEvent->signal(eventData); } - device->unlock(); - { - //new lock, for setting (all other locks are unlocked) - //TODO, it MAY be inconsistency between stored values and device values here... change something? - TelldusCore::MutexLocker deviceLocker(&d->lock); - d->set.setDeviceState(deviceId, action, datastring); - } - } else { - device->unlock(); + d->set.setDeviceState(deviceId, action, datastring); } return retval; - } - else{ - device->unlock(); + } else { return TELLSTICK_ERROR_NOT_FOUND; } } From bd877ec52727415b8a1a2b7361541f9b5b13dca1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 12:01:30 +0000 Subject: [PATCH 0403/2215] Use the old TelldusCore::MutexLocker in TellStick again. --- telldus-core/service/TellStick_ftd2xx.cpp | 35 +++++++++-------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 07866f6b..81e467f0 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -129,25 +129,20 @@ void TellStick::run() { FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, d->eh); WaitForSingleObject(d->eh,INFINITE); - { - d->mutex.lock(); - //TelldusCore::MutexLocker locker(&d->mutex); - if (!d->running) { - d->mutex.unlock(); - break; - } - FT_GetQueueStatus(d->ftHandle, &dwBytesInQueue); - if (dwBytesInQueue < 1) { - d->mutex.unlock(); - continue; - } - buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); - memset(buf, 0, dwBytesInQueue+1); - FT_Read(d->ftHandle, buf, dwBytesInQueue, &dwBytesRead); - processData( buf ); - free(buf); - d->mutex.unlock(); + TelldusCore::MutexLocker locker(&d->mutex); + if (!d->running) { + break; } + FT_GetQueueStatus(d->ftHandle, &dwBytesInQueue); + if (dwBytesInQueue < 1) { + d->mutex.unlock(); + continue; + } + buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); + memset(buf, 0, dwBytesInQueue+1); + FT_Read(d->ftHandle, buf, dwBytesInQueue, &dwBytesRead); + processData( buf ); + free(buf); } } @@ -160,8 +155,7 @@ int TellStick::send( const std::string &strMessage ) { //This lock does two things // 1 Prevents two calls from different threads to this function // 2 Prevents our running thread from receiving the data we are interested in here - d->mutex.lock(); - //TelldusCore::MutexLocker(&d->mutex); + TelldusCore::MutexLocker(&d->mutex); char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); #ifdef _WINDOWS @@ -191,7 +185,6 @@ int TellStick::send( const std::string &strMessage ) { } } - d->mutex.unlock(); if (!c) { return TELLSTICK_ERROR_COMMUNICATION; } From 750a28aa8fb19dd22ca9ac01d25d43b366c10a00 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Oct 2010 12:08:15 +0000 Subject: [PATCH 0404/2215] --- telldus-core/common/Mutex.cpp | 12 ++++++++++++ telldus-core/common/Mutex.h | 9 +++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index 453f234b..d803ec0b 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -69,6 +69,18 @@ void Mutex::unlock() { #endif } + +void LoggedMutex::lock() { + debuglog(GetCurrentThreadId(), "Locking"); + Mutex::lock(); + debuglog(GetCurrentThreadId(), "Locked"); +} + +void LoggedMutex::unlock() { + debuglog(GetCurrentThreadId(), "Unlocking"); + Mutex::unlock(); + debuglog(GetCurrentThreadId(), "Unlocked"); +} MutexLocker::MutexLocker(Mutex *m) :mutex(m) diff --git a/telldus-core/common/Mutex.h b/telldus-core/common/Mutex.h index e01d45c1..06e5087b 100644 --- a/telldus-core/common/Mutex.h +++ b/telldus-core/common/Mutex.h @@ -18,13 +18,18 @@ namespace TelldusCore { Mutex(); virtual ~Mutex(); - void lock(); - void unlock(); + virtual void lock(); + virtual void unlock(); private: class PrivateData; PrivateData *d; }; + class LoggedMutex : public Mutex { + public: + void lock(); + void unlock(); + }; class MutexLocker { public: From 1fe4b8734c779427d5f6ccc08282bd4b1ba06816 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 13:57:02 +0000 Subject: [PATCH 0405/2215] Added stings library --- telldus-core/common/CMakeLists.txt | 2 ++ telldus-core/common/Strings.cpp | 15 +++++++++++++++ telldus-core/common/Strings.h | 10 ++++++++++ 3 files changed, 27 insertions(+) create mode 100644 telldus-core/common/Strings.cpp create mode 100644 telldus-core/common/Strings.h diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 0618c39c..617a7027 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -6,6 +6,7 @@ ENDIF(COMMAND cmake_policy) SET( telldus-common_SRCS Message.cpp Mutex.cpp + Strings.cpp Thread.cpp ) @@ -14,6 +15,7 @@ SET( telldus-common_HDRS Message.h Mutex.h Socket.h + Strings.h Thread.h ) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp new file mode 100644 index 00000000..ed881d27 --- /dev/null +++ b/telldus-core/common/Strings.cpp @@ -0,0 +1,15 @@ +#include "Strings.h" + +#include +#include + +/** +* This method doesn't support all locales +*/ +bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { + //move? + transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); + transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); + + return stringA == stringB; +} diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h new file mode 100644 index 00000000..269fb7a4 --- /dev/null +++ b/telldus-core/common/Strings.h @@ -0,0 +1,10 @@ +#ifndef STRING_H +#define STRING_H + +#include + +namespace TelldusCore { + bool comparei(std::wstring stringA, std::wstring stringB); +} + +#endif //STRING_H From f4360df8d6244d14e8f754d9f9953ac8fa36e1dd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 13:59:48 +0000 Subject: [PATCH 0406/2215] Converted uses of Protocol::comparei to use the strings library instead. --- telldus-core/service/Protocol.cpp | 25 +++++++++++----------- telldus-core/service/ProtocolIkea.cpp | 3 ++- telldus-core/service/ProtocolNexa.cpp | 13 +++++------ telldus-core/service/ProtocolRisingSun.cpp | 5 +++-- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 15a4e7c8..b11de0c7 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -13,8 +13,7 @@ #include "ProtocolWaveman.h" #include "ProtocolX10.h" -#include -#include +#include "Strings.h" #include class Protocol::PrivateData { @@ -91,37 +90,37 @@ bool Protocol::comparei(std::wstring stringA , std::wstring stringB) Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ - if(comparei(protocolname, L"arctech")){ + if(TelldusCore::comparei(protocolname, L"arctech")){ return new ProtocolNexa(); - } else if (comparei(protocolname, L"brateck")) { + } else if (TelldusCore::comparei(protocolname, L"brateck")) { return new ProtocolBrateck(); - } else if (comparei(protocolname, L"everflourish")) { + } else if (TelldusCore::comparei(protocolname, L"everflourish")) { return new ProtocolEverflourish(); - } else if (comparei(protocolname, L"fuhaote")) { + } else if (TelldusCore::comparei(protocolname, L"fuhaote")) { return new ProtocolFuhaote(); - } else if (comparei(protocolname, L"ikea")) { + } else if (TelldusCore::comparei(protocolname, L"ikea")) { return new ProtocolIkea(); - } else if (comparei(protocolname, L"risingsun")) { + } else if (TelldusCore::comparei(protocolname, L"risingsun")) { return new ProtocolRisingSun(); - } else if (comparei(protocolname, L"sartano")) { + } else if (TelldusCore::comparei(protocolname, L"sartano")) { return new ProtocolSartano(); - } else if (comparei(protocolname, L"silvanchip")) { + } else if (TelldusCore::comparei(protocolname, L"silvanchip")) { return new ProtocolSilvanChip(); - } else if (comparei(protocolname, L"upm")) { + } else if (TelldusCore::comparei(protocolname, L"upm")) { return new ProtocolUpm(); - } else if (comparei(protocolname, L"waveman")) { + } else if (TelldusCore::comparei(protocolname, L"waveman")) { return new ProtocolWaveman(); - } else if (comparei(protocolname, L"x10")) { + } else if (TelldusCore::comparei(protocolname, L"x10")) { return new ProtocolX10(); } diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index b73a31cb..4ed1f8e3 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -1,4 +1,5 @@ #include "ProtocolIkea.h" +#include "Strings.h" #include #include @@ -9,7 +10,7 @@ int ProtocolIkea::methods() const { std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { int intSystem = this->getIntParameter(L"system", 1, 16)-1; - int intFadeStyle = comparei(this->getStringParameter(L"fade", L"true"), L"true"); + int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true"); std::wstring wstrUnits = this->getStringParameter(L"units", L""); if (method == TELLSTICK_TURNON) { diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 5b716b42..c4a4fb2f 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,25 +1,26 @@ #include "ProtocolNexa.h" +#include "Strings.h" int ProtocolNexa::methods() const { - if (comparei(model(), L"codeswitch")) { + if (TelldusCore::comparei(model(), L"codeswitch")) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); - } else if (comparei(model(), L"selflearning-switch")) { + } else if (TelldusCore::comparei(model(), L"selflearning-switch")) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); - } else if (comparei(model(), L"selflearning-dimmer")) { + } else if (TelldusCore::comparei(model(), L"selflearning-dimmer")) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); - } else if (comparei(model(), L"bell")) { + } else if (TelldusCore::comparei(model(), L"bell")) { return TELLSTICK_BELL; } return 0; } std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *) { - if (comparei(model(), L"codeswitch")) { + if (TelldusCore::comparei(model(), L"codeswitch")) { return getStringCodeSwitch(method); - } else if (comparei(model(), L"bell")) { + } else if (TelldusCore::comparei(model(), L"bell")) { return getStringBell(); } return getStringSelflearning(method, data); diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index 32870e5b..decb034d 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -1,14 +1,15 @@ #include "ProtocolRisingSun.h" +#include "Strings.h" int ProtocolRisingSun::methods() const { - if (comparei(model(), L"selflearning")) { + if (TelldusCore::comparei(model(), L"selflearning")) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); } return TELLSTICK_TURNON | TELLSTICK_TURNOFF; } std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) { - if (comparei(model(), L"selflearning")) { + if (TelldusCore::comparei(model(), L"selflearning")) { return getStringSelflearning(method); } return getStringCodeSwitch(method); From 1d75c580e05f6173447a0a7e4c6cfef29fd91173 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 14:00:34 +0000 Subject: [PATCH 0407/2215] Removed obsolete function Protocol::comparei() --- telldus-core/service/Protocol.cpp | 12 ------------ telldus-core/service/Protocol.h | 1 - 2 files changed, 13 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index b11de0c7..11d03c24 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -76,18 +76,6 @@ int Protocol::getIntParameter(const std::wstring &name, int min, int max) const return intValue; } -/** -* This method doesn't support all locales -*/ -bool Protocol::comparei(std::wstring stringA , std::wstring stringB) -{ - //move? - transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); - transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); - - return stringA == stringB; -} - Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ if(TelldusCore::comparei(protocolname, L"arctech")){ diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 0b53ea96..d98c5c82 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -27,7 +27,6 @@ public: protected: std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; int getIntParameter(const std::wstring &name, int min, int max) const; - static bool comparei(std::wstring stringA , std::wstring stringB); private: class PrivateData; From c36a702dbae15c6a2130e78f5a0ff8677b52cb31 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 14:01:13 +0000 Subject: [PATCH 0408/2215] Added static function Device::methodId() --- telldus-core/service/Device.cpp | 18 +++++++++++++++++- telldus-core/service/Device.h | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 347174cf..577f6179 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -141,4 +141,20 @@ int Device::maskUnsupportedMethods(int methods, int supportedMethods) { } //Cut of the rest of the unsupported methods we don't have a fallback for return methods & supportedMethods; -} \ No newline at end of file +} + +int Device::methodId( const std::string &methodName ) { + if (methodName.compare("turnon") == 0) { + return TELLSTICK_TURNON; + } + if (methodName.compare("turnoff") == 0) { + return TELLSTICK_TURNOFF; + } + if (methodName.compare("bell") == 0) { + return TELLSTICK_BELL; + } + if (methodName.compare("dim") == 0) { + return TELLSTICK_DIM; + } + return 0; +} diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 65cb3d84..05d36866 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -30,6 +30,7 @@ public: void setLastSentCommand(int command, std::wstring value); static int maskUnsupportedMethods(int methods, int supportedMethods); + static int methodId( const std::string &methodName ); private: Protocol *retrieveProtocol() const; From 3fdc331c112950f2e74a243c68170e902dcfec42 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 14:01:55 +0000 Subject: [PATCH 0409/2215] Don't send '+R' in received events from a TellStick Duo --- telldus-core/service/TellStick_ftd2xx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 81e467f0..f93c643c 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -110,7 +110,7 @@ void TellStick::processData( const std::string &data ) { if (d->message.substr(0,2).compare("+V") == 0) { //TODO save the firmware version } else if (d->message.substr(0,2).compare("+R") == 0) { - this->publishData(d->message); + this->publishData(d->message.substr(2)); } d->message.clear(); } else { // Append the character From c3731ae9f19e2c9b91b92ad5720d8173e5f6b415 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 14:25:06 +0000 Subject: [PATCH 0410/2215] Added function TelldusCore::charToWstring() --- telldus-core/common/Strings.cpp | 8 +++++++- telldus-core/common/Strings.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index ed881d27..166399aa 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -1,13 +1,19 @@ #include "Strings.h" #include +#include #include +std::wstring TelldusCore::charToWstring(const char *value) { + std::wstringstream st; + st << value; + return st.str(); +} + /** * This method doesn't support all locales */ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { - //move? transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index 269fb7a4..6db7cd54 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -4,6 +4,7 @@ #include namespace TelldusCore { + std::wstring charToWstring(const char *value); bool comparei(std::wstring stringA, std::wstring stringB); } From 2a0c9ae686cc6acfe463530206a18b0939ad7039 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 14:27:03 +0000 Subject: [PATCH 0411/2215] Converted uses of Message::charToWstring to use the strings library instead. --- telldus-core/common/Message.cpp | 3 ++- telldus-core/service/ClientCommunicationHandler.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 04bb161f..366c23b2 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -1,5 +1,6 @@ #include "Message.h" #include "Socket.h" +#include "Strings.h" #include #include #include @@ -38,7 +39,7 @@ void Message::addArgument(int value) { } void Message::addArgument(const char *value) { - this->addArgument(charToWstring(value)); + this->addArgument(TelldusCore::charToWstring(value)); } std::wstring Message::charToWstring(const char *value) { diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index e42329df..b0905c34 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -1,5 +1,6 @@ #include "ClientCommunicationHandler.h" #include "Message.h" +#include "Strings.h" #include @@ -222,7 +223,7 @@ std::wstring ClientCommunicationHandler::getErrorString(int errorNo){ if (errorNo >= numResponses) { return L"Unknown error"; } else { - return TelldusCore::Message::charToWstring(responses[errorNo]); + return TelldusCore::charToWstring(responses[errorNo]); } } From 48a055a061cc2c4704a724ed6128ea5347e8ffdb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 14:27:46 +0000 Subject: [PATCH 0412/2215] Removed obsolete function Message::charToWstring() --- telldus-core/common/Message.cpp | 7 ------- telldus-core/common/Message.h | 1 - 2 files changed, 8 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 366c23b2..0ef1a354 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -42,13 +42,6 @@ void Message::addArgument(const char *value) { this->addArgument(TelldusCore::charToWstring(value)); } -std::wstring Message::charToWstring(const char *value) { - //todo move? - std::wstringstream st; - st << value; - return st.str(); -} - std::wstring Message::charUnsignedToWstring(const unsigned char value) { //todo move? std::wstringstream st; diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 8188af2e..7a12e75f 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -14,7 +14,6 @@ namespace TelldusCore { void addArgument(int); void addArgument(const char *); - static std::wstring charToWstring(const char *value); static std::wstring charUnsignedToWstring(const unsigned char value); static std::wstring intToWstring(int value); static bool nextIsInt(const std::wstring &); From 8da5bf1ae5152c0ff2305ebc696c5c55a6c5f42b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Oct 2010 14:52:24 +0000 Subject: [PATCH 0413/2215] Timeout not infinite for client reads after sending --- telldus-core/client/Client.cpp | 2 +- telldus-core/common/Socket.h | 1 + telldus-core/common/Socket_win.cpp | 6 +++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index f03ab309..6a37af00 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -167,7 +167,7 @@ std::wstring Client::sendToService(const Message &msg) { s.connect(L"TelldusClient"); s.write(msg.data()); - return s.read(); + return s.read(500); } void Client::stopThread(){ diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index a77270a4..194a2d6c 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -21,6 +21,7 @@ namespace TelldusCore { void connect(const std::wstring &server); bool isConnected(); std::wstring read(); + std::wstring read(int timeout); void stopReadWait(); void write(const std::wstring &msg); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index bbee39c2..a25df5e0 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -78,6 +78,10 @@ void Socket::stopReadWait(){ } std::wstring Socket::read() { + return read(INFINITE); +} + +std::wstring Socket::read(int timeout){ wchar_t buf[BUFSIZE]; int result; DWORD cbBytesRead = 0; @@ -91,7 +95,7 @@ std::wstring Socket::read() { ReadFile( d->hPipe, &buf, sizeof(wchar_t)*BUFSIZE, &cbBytesRead, &oOverlap); - result = WaitForSingleObject(oOverlap.hEvent, INFINITE); + result = WaitForSingleObject(oOverlap.hEvent, timeout); if(!d->running){ CloseHandle(d->readEvent); From e4e6b005e73c3b52ea22ada1afce6ba3eda6af20 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 14:58:33 +0000 Subject: [PATCH 0414/2215] Added function DeviceManager::triggerDeviceStateChange() --- telldus-core/service/DeviceManager.cpp | 26 ++++++++++++++++---------- telldus-core/service/DeviceManager.h | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index fe3ab595..00b151d5 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -334,19 +334,12 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); if(controller){ int retval = device->doAction(action, data, controller); - if(retval == TELLSTICK_SUCCESS){ + if(retval == TELLSTICK_SUCCESS) { std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); - if (action != TELLSTICK_BELL) { + if (this->triggerDeviceStateChange(deviceId, action, datastring)) { device->setLastSentCommand(action, datastring); - //TODO: This should maybe be done someware else since the event could be triggered by a TellStick Duo aswell - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDDeviceEvent"; - eventData->eventState = action; - eventData->deviceId = deviceId; - eventData->eventValue = datastring; - d->deviceUpdateEvent->signal(eventData); + d->set.setDeviceState(deviceId, action, datastring); } - d->set.setDeviceState(deviceId, action, datastring); } return retval; } else { @@ -393,3 +386,16 @@ int DeviceManager::sendRawCommand(std::wstring command, int reserved){ } } +bool DeviceManager::triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { + if ( intDeviceState == TELLSTICK_BELL || intDeviceState == TELLSTICK_LEARN) { + return false; + } + + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDDeviceEvent"; + eventData->eventState = intDeviceState; + eventData->deviceId = deviceId; + eventData->eventValue = strDeviceStateValue; + d->deviceUpdateEvent->signal(eventData); + return true; +} diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 22e01970..889c6054 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -34,7 +34,7 @@ public: int sendRawCommand(std::wstring command, int reserved); private: - + bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); void fillDevices(void); class PrivateData; From 979ff9d0971170090d29f7b2cd81d7110646291f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Oct 2010 15:16:41 +0000 Subject: [PATCH 0415/2215] ClientCommunicationHandler-event reused --- .../service/ClientCommunicationHandler.cpp | 3 +-- telldus-core/service/TelldusMain.cpp | 21 ++++++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index b0905c34..f322d342 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -31,7 +31,6 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie ClientCommunicationHandler::~ClientCommunicationHandler(void) { wait(); - delete(d->event); delete(d->clientSocket); delete d; } @@ -223,7 +222,7 @@ std::wstring ClientCommunicationHandler::getErrorString(int errorNo){ if (errorNo >= numResponses) { return L"Unknown error"; } else { - return TelldusCore::charToWstring(responses[errorNo]); + return TelldusCore::charToWstring(responses[errorNo]); } } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 5c1eb9d0..6403bbfc 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -58,6 +58,8 @@ void TelldusMain::start(void) { std::list clientCommunicationHandlerList; + std::auto_ptr handlerEvent(d->eventHandler.addEvent()); + while(!d->stopEvent->isSignaled()) { if (!d->eventHandler.waitForAny()) { continue; @@ -67,8 +69,7 @@ void TelldusMain::start(void) { EventData *eventData = clientEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventData); if (data) { - Event *handlerEvent = d->eventHandler.addEvent(); - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent.get(), &deviceManager, deviceUpdateEvent); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } @@ -92,12 +93,16 @@ void TelldusMain::start(void) { } } - for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ - if ((*it)->isDone()){ - delete *it; - it = clientCommunicationHandlerList.erase(it); - } else { - ++it; + if(handlerEvent->isSignaled()){ + handlerEvent->popSignal(); + for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ + if ((*it)->isDone()){ + delete *it; + it = clientCommunicationHandlerList.erase(it); + + } else { + ++it; + } } } } From a815b3426bef7d77aaeef4b802f749bad9e82849 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 15:31:11 +0000 Subject: [PATCH 0416/2215] Use smart pointers in the EventUpdateManager. --- telldus-core/service/EventUpdateManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 09d66b1a..0717228b 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -55,16 +55,16 @@ void EventUpdateManager::run(){ if(d->clientConnectEvent->isSignaled()){ //new client added - EventData *eventData = d->clientConnectEvent->takeSignal(); - ConnectionListenerEventData *data = reinterpret_cast(eventData); + std::auto_ptr eventData(d->clientConnectEvent->takeSignal()); + ConnectionListenerEventData *data = reinterpret_cast(eventData.get()); if(data){ d->clients.push_back(data->socket); } } else if(d->updateEvent->isSignaled()){ //device event, signal all clients - EventData *eventData = d->updateEvent->takeSignal(); - EventUpdateData *data = reinterpret_cast(eventData); + std::auto_ptr eventData(d->updateEvent->takeSignal()); + EventUpdateData *data = reinterpret_cast(eventData.get()); if(data){ sendMessageToClients(data); } From 47f3c59301825594561daed07e7aeb74969b71ae Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 15:38:41 +0000 Subject: [PATCH 0417/2215] Added class ControllerMessage --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/ControllerMessage.cpp | 48 ++++++++++++++++++++++ telldus-core/service/ControllerMessage.h | 19 +++++++++ 3 files changed, 69 insertions(+) create mode 100644 telldus-core/service/ControllerMessage.cpp create mode 100644 telldus-core/service/ControllerMessage.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 52761cbf..37c7347b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -7,6 +7,7 @@ SET( telldus-service_SRCS ClientCommunicationHandler.cpp Controller.cpp ControllerManager.cpp + ControllerMessage.cpp Device.cpp DeviceManager.cpp Event.cpp @@ -45,6 +46,7 @@ SET( telldus-service_HDRS ConnectionListener.h Controller.h ControllerManager.h + ControllerMessage.h Device.h DeviceManager.h Event.h diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp new file mode 100644 index 00000000..a9f305a3 --- /dev/null +++ b/telldus-core/service/ControllerMessage.cpp @@ -0,0 +1,48 @@ +#include "ControllerMessage.h" +#include "Device.h" +#include "Strings.h" + +#include + +class ControllerMessage::PrivateData { +public: + std::map parameters; + std::string protocol; + int method; +}; + +ControllerMessage::ControllerMessage(const std::string &message) { + d = new PrivateData; + + //Process our message into bits + size_t prevPos = 0; + size_t pos = message.find(";"); + while(pos != std::string::npos) { + std::string param = message.substr(prevPos, pos-prevPos); + prevPos = pos+1; + size_t delim = param.find(":"); + if (delim == std::string::npos) { + break; + } + if (param.substr(0, delim).compare("protocol") == 0) { + d->protocol = param.substr(delim+1, param.length()-delim); + } else if (param.substr(0, delim).compare("method") == 0) { + d->method = Device::methodId(param.substr(delim+1, param.length()-delim)); + } else { + d->parameters[param.substr(0, delim)] = param.substr(delim+1, param.length()-delim); + } + pos = message.find(";", pos+1); + } +} + +ControllerMessage::~ControllerMessage(){ + delete d; +} + +int ControllerMessage::method() const { + return d->method; +} + +std::wstring ControllerMessage::protocol() const { + return TelldusCore::charToWstring(d->protocol.c_str()); +} \ No newline at end of file diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h new file mode 100644 index 00000000..f692315f --- /dev/null +++ b/telldus-core/service/ControllerMessage.h @@ -0,0 +1,19 @@ +#ifndef CONTROLLERMESSAGE_H +#define CONTROLLERMESSAGE_H + +#include + +class ControllerMessage { +public: + ControllerMessage(const std::string &rawMessage); + virtual ~ControllerMessage(); + + int method() const; + std::wstring protocol() const; + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CONTROLLERMESSAGE_H \ No newline at end of file From 167db782b807f7b101c33456ec0482d684f33ab0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Oct 2010 15:42:47 +0000 Subject: [PATCH 0418/2215] Timeout in client communication read, to avoid infinite wait when client disappears --- telldus-core/service/ClientCommunicationHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index f322d342..c691b4b9 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -38,7 +38,7 @@ ClientCommunicationHandler::~ClientCommunicationHandler(void) void ClientCommunicationHandler::run(){ //run thread - std::wstring clientMessage = d->clientSocket->read(); + std::wstring clientMessage = d->clientSocket->read(2000); //TODO changed this to a timeout, see if that works better int intReturn; std::wstring strReturn; From 7c60437e6b97f0f7d3f7ded68540d53e3eb4836e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 15:53:49 +0000 Subject: [PATCH 0419/2215] Added function DeviceManager::handleControllerMessage(). Doesn't really do that much yet. --- telldus-core/service/DeviceManager.cpp | 29 ++++++++++++++++++++++++++ telldus-core/service/DeviceManager.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 00b151d5..8b2dfc8b 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,7 +1,10 @@ #include "DeviceManager.h" +#include "ControllerMessage.h" #include "Mutex.h" #include "Settings.h" +#include "Strings.h" #include "Message.h" +#include "common.h" #include @@ -374,6 +377,32 @@ int DeviceManager::removeDevice(int deviceId){ return TELLSTICK_DEVICE_REMOVED; } +void DeviceManager::handleControllerMessage(const ControllerEventData &eventData) { + //Trigger raw-event + EventUpdateData *eventUpdateData = new EventUpdateData(); + eventUpdateData->messageType = L"TDRawDeviceEvent"; + eventUpdateData->controllerId = 0; //TODO add the real controller-id + eventUpdateData->eventValue = TelldusCore::charToWstring(eventData.msg.c_str()); + d->deviceUpdateEvent->signal(eventUpdateData); + + ControllerMessage msg(eventData.msg); + TelldusCore::MutexLocker deviceListLocker(&d->lock); + for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { + TelldusCore::MutexLocker deviceLocker(it->second); + if (!TelldusCore::comparei(it->second->getProtocolName(), msg.protocol())) { + continue; + } + if (! (it->second->getMethods() & msg.method())) { + continue; + } + //TODO: Check the parameters to see if it matches + + //First save the last sent command, this also triggers the callback to the client + //TODO + } + +} + int DeviceManager::sendRawCommand(std::wstring command, int reserved){ //TODO test this! diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 889c6054..88ee4d67 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -32,6 +32,8 @@ public: int doAction(int deviceId, int action, unsigned char data); int removeDevice(int deviceId); int sendRawCommand(std::wstring command, int reserved); + + void handleControllerMessage(const ControllerEventData &event); private: bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); From e2dd4a86fd22c83f4b7b6f80436695d6cf4b2f3a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Oct 2010 15:54:25 +0000 Subject: [PATCH 0420/2215] Added TODO message. --- telldus-core/service/DeviceManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 8b2dfc8b..302187dd 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -102,6 +102,7 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ } int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ + //TODO maybe handle the device lock as in doAction()? Device *device = 0; { //devices locked From 88c65b2657e0a34edebe3363711486666f858d93 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 22 Oct 2010 13:21:05 +0000 Subject: [PATCH 0421/2215] Changed one device lock which was ignored the last time. --- telldus-core/client/Client.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 34 +++++++++----------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 6a37af00..dc227ada 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -167,7 +167,7 @@ std::wstring Client::sendToService(const Message &msg) { s.connect(L"TelldusClient"); s.write(msg.data()); - return s.read(500); + return s.read(1000); } void Client::stopThread(){ diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 302187dd..2c80a7a9 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -102,30 +102,20 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ } int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ - //TODO maybe handle the device lock as in doAction()? - Device *device = 0; - { - //devices locked - TelldusCore::MutexLocker deviceListLocker(&d->lock); - - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - device = it->second; - } - //devices unlocked + //devices locked + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + int methods = it->second->getMethods(); + return Device::maskUnsupportedMethods(methods, methodsSupported); } - if (!device) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found - } - int methods = device->getMethods(); - device->unlock(); - return Device::maskUnsupportedMethods(methods, methodsSupported); - + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } std::wstring DeviceManager::getDeviceModel(int deviceId){ From 9e2a7593688864d5ec691cc388d572303eaf5fc1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 22 Oct 2010 14:44:31 +0000 Subject: [PATCH 0422/2215] Changes in thread wait to make it more idiot (i.e. windows) proof --- telldus-core/common/Thread.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index 2f7e73d2..3f4f5650 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -22,6 +22,7 @@ public: #ifdef _WINDOWS HANDLE thread; DWORD threadId; + bool running; #else pthread_t thread; #endif @@ -38,6 +39,7 @@ Thread::~Thread() { void Thread::start() { #ifdef _WINDOWS + d->running = true; d->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Thread::exec, this, 0, &d->threadId); #else pthread_create(&d->thread, NULL, &Thread::exec, this ); @@ -49,7 +51,9 @@ bool Thread::wait() { return true; } #ifdef _WINDOWS - WaitForSingleObject(d->thread, INFINITE); + while(d->running) { + WaitForSingleObject(d->thread, 200); + } CloseHandle(d->thread); #else pthread_join(d->thread, 0); @@ -61,6 +65,8 @@ void *Thread::exec( void *ptr ) { Thread *t = reinterpret_cast(ptr); if (t) { t->run(); + t->d->running = false; } + ExitThread(0); return 0; } From 0027d98529b35863828494046f56de499b3900c5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 15:38:06 +0000 Subject: [PATCH 0423/2215] Added function TelldusCore::wideToString() --- telldus-core/common/Strings.cpp | 19 +++++++++++++++++++ telldus-core/common/Strings.h | 1 + 2 files changed, 20 insertions(+) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 166399aa..5c56c67f 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -19,3 +19,22 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { return stringA == stringB; } + +std::string TelldusCore::wideToString(const std::wstring &input) { + + //return std::string(input.begin(), input.end()); //TODO, change this conversion method + + std::string strReturn; + + size_t len = input.length(); + char* convPointer = new char[len + 1]; + + wcstombs(convPointer, input.c_str(), len + 1); + + strReturn = convPointer; + + delete [] convPointer; + + return strReturn; + +} diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index 6db7cd54..f6150bb7 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -6,6 +6,7 @@ namespace TelldusCore { std::wstring charToWstring(const char *value); bool comparei(std::wstring stringA, std::wstring stringB); + std::string wideToString(const std::wstring &input); } #endif //STRING_H From 30c0242684dc4e52b8b816c6701565e4cd4386ba Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 15:39:36 +0000 Subject: [PATCH 0424/2215] Added (totaly) untested SettingsCoreFoundationPreferences --- telldus-core/service/CMakeLists.txt | 3 +- .../SettingsCoreFoundationPreferences.cpp | 257 ++++++++++++++++++ 2 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 telldus-core/service/SettingsCoreFoundationPreferences.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 37c7347b..aa57d25e 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -80,9 +80,10 @@ IF (APPLE) #### Mac OS X #### ) LIST(APPEND telldus-service_SRCS main_unix.cpp + ConnectionListener_unix.cpp Event_unix.cpp EventHandler_unix.cpp - ConnectionListener_unix.cpp + SettingsCoreFoundationPreferences.cpp ) ELSEIF (WIN32) #### Windows #### diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp new file mode 100644 index 00000000..1e6dcd7b --- /dev/null +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -0,0 +1,257 @@ +// +// C++ Implementation: telldussettingsconfuse +// +// Description: +// +// +// Author: Micke Prag , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "Settings.h" +#include "Strings.h" +#include +#include +#include + +class privateVars { +public: + CFStringRef app_ID; + CFStringRef userName; + CFStringRef hostName; +}; + +class Settings::PrivateData { +public: + CFStringRef app_ID; + CFStringRef userName; + CFStringRef hostName; +}; + +/* +* Constructor +*/ +Settings::Settings(void) +{ + d = new PrivateData(); + d->app_ID = CFSTR( "com.telldus.core" ); + d->userName = kCFPreferencesAnyUser; + d->hostName = kCFPreferencesCurrentHost; +} + +/* +* Destructor +*/ +Settings::~Settings(void) +{ + delete d; +} + +/* +* Return a setting +*/ +std::wstring Settings::getSetting(const std::wstring &strName) const { + return L""; +} + +/* +* Return the number of stored devices +*/ +int Settings::getNumberOfDevices(void) const { + CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); + if (!cfarray) return 0; + CFIndex size = CFArrayGetCount( cfarray ); + int devices = 0; + for (CFIndex k = 0; k < size; ++k) { + CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); + if (CFStringHasPrefix( key, CFSTR("devices.") ) && + CFStringHasSuffix( key, CFSTR(".name") ) ) { + devices++; + } + } + return devices; +} + +int Settings::getDeviceId(int intDeviceIndex) const { + CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); + if (!cfarray) return 0; + CFIndex size = CFArrayGetCount( cfarray ); + int index = 0; + int id = 0; + for (CFIndex k = 0; k < size; ++k) { + CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); + if (CFStringHasPrefix( key, CFSTR("devices.") ) && + CFStringHasSuffix( key, CFSTR(".name") ) ) { + + if (index == intDeviceIndex) { + CFArrayRef split = CFStringCreateArrayBySeparatingStrings( 0, key, CFSTR(".") ); + if ( !split || CFArrayGetCount( split ) != 3 ) continue; + + // This code crashes! + //CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); + //if (cfid) + // CFNumberGetValue( cfid, kCFNumberIntType, &id); + + CFStringRef cfid = (CFStringRef) CFArrayGetValueAtIndex( split, 1 ); + char *cp = NULL; + CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1; + cp = (char *)malloc(size); + CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); + cp = (char *)realloc( cp, strlen(cp) + 1); + id = atoi(cp); + + + CFRelease(key); + CFRelease(split); + CFRelease(cfid); + break; + } + index++; + } + CFRelease( key ); + } + return id; +} + +/* +* Add a new device +*/ +int Settings::addDevice() { + int id = getNextDeviceId(); + setStringSetting( id, L"name", L"", false ); //Create a empty name so the device has an entry + setStringSetting( id, L"model", L"", false ); + return id; +} + +/* +* Get next available device id +*/ +int Settings::getNextDeviceId() const { + int id = 0, max = 0; + int numberOfDevices = getNumberOfDevices(); + for( int i = 0; i < numberOfDevices; i++) { + id = getDeviceId( i ); + if (id > max) { + max = id; + } + } + max++; + return max; +} + +/* +* Remove a device +*/ +bool Settings::removeDevice(int intDeviceId){ + CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d."), intDeviceId); // The key to search for + + CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); + if (!cfarray) return 0; + CFIndex size = CFArrayGetCount( cfarray ); + for (CFIndex k = 0; k < size; ++k) { + CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); + if (CFStringHasPrefix( key, filterKey ) ) { + CFPreferencesSetValue( key, NULL, d->app_ID, d->userName, d->hostName ); //Remove the key + } + } + + CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); + return true; +} + +std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &wname, bool parameter) const { + std::string name(TelldusCore::wideToString(wname)); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); + + CFStringRef key; + if (parameter) { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + } else { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + } + + CFStringRef value; + + value = (CFStringRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName); + if (!value) { + return L""; + } + + char *cp = NULL; + CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( value ), kCFStringEncodingUTF8) + 1; + cp = (char *)malloc(size); + CFStringGetCString( value, cp, size, kCFStringEncodingUTF8 ); + cp = (char *)realloc( cp, strlen(cp) + 1); + + CFRelease(value); + std::wstring retval = TelldusCore::charToWstring(cp); + free(cp); + return retval; +} + +bool Settings::setStringSetting(int intDeviceId, const std::wstring &wname, const std::wstring &wvalue, bool parameter) { + std::string name(TelldusCore::wideToString(wname)); + std::string value(TelldusCore::wideToString(wvalue)); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); + CFStringRef cfvalue = CFStringCreateWithCString( 0, value.c_str(), kCFStringEncodingUTF8 ); + + CFStringRef key; + if (parameter) { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + } else { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + } + + CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); + CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); + return true; +} + +int Settings::getIntSetting(int intDeviceId, const std::wstring &wname, bool parameter) const { + int retval = 0; + std::string name(TelldusCore::wideToString(wname)); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); + CFNumberRef cfvalue; + + CFStringRef key; + if (parameter) { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + } else { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + } + + cfvalue = (CFNumberRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName); + + // If the preference exists, use it. + if (cfvalue) { + try { + // Numbers come out of preferences as CFNumber objects. + if (!CFNumberGetValue(cfvalue, kCFNumberIntType, &retval)) { + retval = 0; + } + CFRelease(cfvalue); + } catch (std::exception e) { + retval = 0; + } + } + + return retval; +} + +bool Settings::setIntSetting(int intDeviceId, const std::wstring &wname, int value, bool parameter) { + std::string name(TelldusCore::wideToString(wname)); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); + CFNumberRef cfvalue = CFNumberCreate(NULL, kCFNumberIntType, &value); + + CFStringRef key; + if (parameter) { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + } else { + key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + } + + CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); + CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); + return true; +} From af1aad41434988fb0596729fee11fa474f9a7a78 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:05:05 +0000 Subject: [PATCH 0425/2215] GetCurrentThreadId() only exists on windows so turn of logging on other platforms --- telldus-core/common/Mutex.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index d803ec0b..7099e8e0 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -71,15 +71,23 @@ void Mutex::unlock() { void LoggedMutex::lock() { +#ifdef _WINDOWS debuglog(GetCurrentThreadId(), "Locking"); +#endif Mutex::lock(); +#ifdef _WINDOWS debuglog(GetCurrentThreadId(), "Locked"); +#endif } void LoggedMutex::unlock() { +#ifdef _WINDOWS debuglog(GetCurrentThreadId(), "Unlocking"); +#endif Mutex::unlock(); +#ifdef _WINDOWS debuglog(GetCurrentThreadId(), "Unlocked"); +#endif } MutexLocker::MutexLocker(Mutex *m) From 23be1d29fa091e9d5883f85ba4c3a70e63195e35 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:05:38 +0000 Subject: [PATCH 0426/2215] Fixes for other platforms than Windows --- telldus-core/common/Thread.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index 3f4f5650..d823d949 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -19,10 +19,10 @@ using namespace TelldusCore; class TelldusCore::ThreadPrivate { public: + bool running; #ifdef _WINDOWS HANDLE thread; DWORD threadId; - bool running; #else pthread_t thread; #endif @@ -67,6 +67,8 @@ void *Thread::exec( void *ptr ) { t->run(); t->d->running = false; } +#ifdef _WINDOWS ExitThread(0); +#endif return 0; } From c992e7e9673b6734459fae01d6629a78646d20a3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:07:02 +0000 Subject: [PATCH 0427/2215] Added missing function Socket::read(int), timeout not supported on Unix yet though --- telldus-core/common/Socket_unix.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 2dfa4110..924aef89 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -57,6 +57,10 @@ bool Socket::isConnected(){ return d->connected; } +std::wstring Socket::read(int) { + return this->read(); +} + std::wstring Socket::read() { //TODO set d->conneted to false if something goes wrong char inbuf[BUFSIZE]; From 4fe00e4b4e7361d5eac901dc549f267c74f893d8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:08:36 +0000 Subject: [PATCH 0428/2215] Converted usage of Message::wideToString() to TelldusCore::wideToString() --- telldus-core/client/Client.cpp | 64 ++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index dc227ada..2c24ed74 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,5 +1,6 @@ #include "Client.h" #include "Socket.h" +#include "Strings.h" #include "Mutex.h" #include "Common.h" @@ -66,7 +67,7 @@ Client *Client::getInstance() { void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue){ TelldusCore::MutexLocker locker(&d->mutex); for(DeviceEventList::const_iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - (*callback_it).event(deviceId, deviceState, Message::wideToString(deviceStateValue).c_str(), (*callback_it).id, (*callback_it).context); + (*callback_it).event(deviceId, deviceState, TelldusCore::wideToString(deviceStateValue).c_str(), (*callback_it).id, (*callback_it).context); } } @@ -80,7 +81,7 @@ void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int void Client::callbackRawEvent(std::wstring command, int controllerId){ TelldusCore::MutexLocker locker(&d->mutex); for(RawDeviceEventList::const_iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - (*callback_it).event(Message::wideToString(command).c_str(), controllerId, (*callback_it).id, (*callback_it).context); + (*callback_it).event(TelldusCore::wideToString(command).c_str(), controllerId, (*callback_it).id, (*callback_it).context); } } @@ -142,8 +143,8 @@ void Client::run(){ //a message arrived std::wstring type = Message::takeString(&clientMessage); if(type == L"TDDeviceChangeEvent"){ - int deviceId = Message::takeInt(&clientMessage); - int eventDeviceChanges = Message::takeInt(&clientMessage); + int deviceId = Message::takeInt(&clientMessage); + int eventDeviceChanges = Message::takeInt(&clientMessage); int eventChangeType = Message::takeInt(&clientMessage); callbackDeviceChangeEvent(deviceId, eventDeviceChanges, eventChangeType); } @@ -176,30 +177,31 @@ void Client::stopThread(){ } bool Client::unregisterCallback( int callbackId ) { - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - d->deviceEventList.erase(callback_it); - return true; - } - - for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - d->deviceChangeEventList.erase(callback_it); - return true; - } - - for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; - } - d->rawDeviceEventList.erase(callback_it); - return true; - } - - return false; -} \ No newline at end of file + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + if ( (*callback_it).id != callbackId ) { + continue; + } + d->deviceEventList.erase(callback_it); + return true; + } + + for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + if ( (*callback_it).id != callbackId ) { + continue; + } + d->deviceChangeEventList.erase(callback_it); + return true; + } + + for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + if ( (*callback_it).id != callbackId ) { + continue; + } + d->rawDeviceEventList.erase(callback_it); + return true; + } + + return false; +} + From af8ea81eb7eb53c93448b46d766a5c3994fdd0e1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:09:58 +0000 Subject: [PATCH 0429/2215] BON and BOFF doesn't seem to be used? --- telldus-core/service/ProtocolUpm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 2b46f187..3ee1931a 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -10,8 +10,8 @@ std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controlle const char START[] = {S,0}; const char B1[] = {L,S,0}; const char B0[] = {S,L,0}; - const char BON[] = {S,L,L,S,0}; - const char BOFF[] = {S,L,S,L,0}; + //const char BON[] = {S,L,L,S,0}; + //const char BOFF[] = {S,L,S,L,0}; int intUnit = this->getIntParameter(L"unit", 1, 4)-1; std::string strReturn; From d58cc91484b91e9a2606c5f58ec8eeee673eba9c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:11:42 +0000 Subject: [PATCH 0430/2215] Made the ftd2xx engine work on unix platforms --- telldus-core/service/TellStick_ftd2xx.cpp | 27 +++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index f93c643c..38b6dad7 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -24,15 +24,27 @@ public: FT_HANDLE ftHandle; TelldusCore::Mutex mutex; +#ifdef _WINDOWS HANDLE eh; - +#else +//#include + struct { + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + } eh; +#endif }; TellStick::TellStick(Event *event, const TellStickDescriptor &td ) :Controller(event) { d = new PrivateData; +#ifdef _WINDOWS d->eh = CreateEvent( NULL, false, false, NULL ); +#else + pthread_mutex_init(&d->eh.eMutex, NULL); + pthread_cond_init(&d->eh.eCondVar, NULL); +#endif d->open = false; d->running = false; d->vid = td.vid; @@ -69,7 +81,11 @@ TellStick::~TellStick() { if (d->running) { TelldusCore::MutexLocker locker(&d->mutex); d->running = false; +#ifdef _WINDOWS SetEvent(d->eh); +#else + pthread_cond_broadcast(&d->eh.eCondVar); +#endif } this->wait(); if (d->open) { @@ -126,9 +142,16 @@ void TellStick::run() { char *buf = 0; while(1) { +#ifdef _WINDOWS FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, d->eh); WaitForSingleObject(d->eh,INFINITE); - +#else + FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, (PVOID)&d->eh); + pthread_mutex_lock(&d->eh.eMutex); + pthread_cond_wait(&d->eh.eCondVar, &d->eh.eMutex); + pthread_mutex_unlock(&d->eh.eMutex); +#endif + TelldusCore::MutexLocker locker(&d->mutex); if (!d->running) { break; From 74c1fa92ff8769cce973cb2c820bdad90a0947da Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:13:42 +0000 Subject: [PATCH 0431/2215] Use FTD2XX engine in OS X --- telldus-core/service/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index aa57d25e..7fa2ea9b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -71,11 +71,13 @@ IF (APPLE) #### Mac OS X #### SET( telldus-service_TARGET TelldusService ) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) FIND_LIBRARY(IOKIT_LIBRARY IOKit) + ADD_DEFINITIONS( -DLIBFTD2XX ) SET( telldus-service_LIBRARIES ${telldus-service_LIBRARIES} ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} + ${FTD2XX_LIBRARY} TelldusCommon ) LIST(APPEND telldus-service_SRCS @@ -84,6 +86,7 @@ IF (APPLE) #### Mac OS X #### Event_unix.cpp EventHandler_unix.cpp SettingsCoreFoundationPreferences.cpp + TellStick_ftd2xx.cpp ) ELSEIF (WIN32) #### Windows #### From d2b5e6171f8509a284461d98626791e1ebee68ed Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:14:24 +0000 Subject: [PATCH 0432/2215] Converted usage of Message::wideToString() to TelldusCore::wideToString() --- telldus-core/service/DeviceManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 2c80a7a9..3994981d 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -325,7 +325,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ device = it->second; } //devicelist unlocked - Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); + Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); if(controller){ int retval = device->doAction(action, data, controller); if(retval == TELLSTICK_SUCCESS) { @@ -397,9 +397,9 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData int DeviceManager::sendRawCommand(std::wstring command, int reserved){ //TODO test this! - Controller *controller = d->controllerManager->getBestControllerById(-1); + Controller *controller = d->controllerManager->getBestControllerById(-1); if(controller){ - return controller->send(TelldusCore::Message::wideToString(command)); // std::string(command.begin(), command.end())); + return controller->send(TelldusCore::wideToString(command)); // std::string(command.begin(), command.end())); } else{ return TELLSTICK_ERROR_NOT_FOUND; From 01b30bf8e1d25521c333957c87622c20342aa57a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:15:32 +0000 Subject: [PATCH 0433/2215] Added files needed for ftd2xx on OS X --- telldus-core/service/osx/WinTypes.h | 87 +++ telldus-core/service/osx/ftd2xx.h | 924 ++++++++++++++++++++++++++++ 2 files changed, 1011 insertions(+) create mode 100755 telldus-core/service/osx/WinTypes.h create mode 100755 telldus-core/service/osx/ftd2xx.h diff --git a/telldus-core/service/osx/WinTypes.h b/telldus-core/service/osx/WinTypes.h new file mode 100755 index 00000000..c37d66ff --- /dev/null +++ b/telldus-core/service/osx/WinTypes.h @@ -0,0 +1,87 @@ +#ifndef __WINDOWS_TYPES__ +#define __WINDOWS_TYPES__ + +#define MAX_NUM_DEVICES 50 +#include + +typedef unsigned long DWORD; +typedef unsigned long ULONG; +typedef unsigned short USHORT; +typedef short SHORT; +typedef unsigned char UCHAR; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef unsigned char *LPBYTE; +typedef int BOOL; +typedef char BOOLEAN; +typedef char CHAR; +typedef int *LPBOOL; +typedef unsigned char *PUCHAR; +typedef const char *LPCSTR; +typedef char *PCHAR; +typedef void *PVOID; +typedef void *HANDLE; +typedef long LONG; +typedef int INT; +typedef unsigned int UINT; +typedef char *LPSTR; +typedef char *LPTSTR; +typedef DWORD *LPDWORD; +typedef WORD *LPWORD; +typedef ULONG *PULONG; +typedef PVOID LPVOID; +typedef void VOID; +typedef unsigned long long int ULONGLONG; + +typedef struct _OVERLAPPED { + DWORD Internal; + DWORD InternalHigh; + DWORD Offset; + DWORD OffsetHigh; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +typedef struct _SECURITY_ATTRIBUTES { + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; + +typedef struct timeval SYSTEMTIME; +typedef struct timeval FILETIME; +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +// +// Modem Status Flags +// +#define MS_CTS_ON ((DWORD)0x0010) +#define MS_DSR_ON ((DWORD)0x0020) +#define MS_RING_ON ((DWORD)0x0040) +#define MS_RLSD_ON ((DWORD)0x0080) + +// +// Error Flags +// + +#define CE_RXOVER 0x0001 // Receive Queue overflow +#define CE_OVERRUN 0x0002 // Receive Overrun Error +#define CE_RXPARITY 0x0004 // Receive Parity Error +#define CE_FRAME 0x0008 // Receive Framing error +#define CE_BREAK 0x0010 // Break Detected +#define CE_TXFULL 0x0100 // TX Queue is full +#define CE_PTO 0x0200 // LPTx Timeout +#define CE_IOE 0x0400 // LPTx I/O Error +#define CE_DNS 0x0800 // LPTx Device not selected +#define CE_OOP 0x1000 // LPTx Out-Of-Paper +#define CE_MODE 0x8000 // Requested mode unsupported + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE 0xFFFFFFFF +#endif + +#endif diff --git a/telldus-core/service/osx/ftd2xx.h b/telldus-core/service/osx/ftd2xx.h new file mode 100755 index 00000000..67969cfe --- /dev/null +++ b/telldus-core/service/osx/ftd2xx.h @@ -0,0 +1,924 @@ +/*++ + +Copyright (c) 2001-2003 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB interface for FTDI FT8U232/245/2232C + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + /03/04 st modified for linux users + 12/10/04 st added FT_SetVIDPID + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +#ifndef _WINDOWS +#include +#define WINAPI +#endif + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + +#ifndef _WINDOWS +#include "WinTypes.h" + +#ifdef FTD2XX_API +#undef FTD2XX_API +#define FTD2XX_API +#endif +#endif +typedef struct _EVENT_HANDLE{ + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; +} EVENT_HANDLE; + +typedef DWORD *FT_HANDLE; +//typedef unsigned int FT_HANDLE; +//typedef struct ftdi_device * FT_HANDLE; + +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, //7 + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R + }; + + +#ifdef __cplusplus +extern "C" { +#endif + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS FT_SetVIDPID( + DWORD dwVID, + DWORD dwPID + ); + +FTD2XX_API +FT_STATUS FT_GetVIDPID( + DWORD * pdwVID, + DWORD * pdwPID + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // FT2232C extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // FT232R extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + + UCHAR RIsVCP; // zero if using VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + +// +// Events +// + +#define EV_RXCHAR 0x0001 // Any Character received +#define EV_RXFLAG 0x0002 // Received certain character +#define EV_TXEMPTY 0x0004 // Transmitt Queue Empty +#define EV_CTS 0x0008 // CTS changed state +#define EV_DSR 0x0010 // DSR changed state +#define EV_RLSD 0x0020 // RLSD changed state +#define EV_BREAK 0x0040 // BREAK received +#define EV_ERR 0x0080 // Line status error occurred +#define EV_RING 0x0100 // Ring signal detected +#define EV_PERR 0x0200 // Printer error occured +#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full +#define EV_EVENT1 0x0800 // Provider specific event 1 +#define EV_EVENT2 0x1000 // Provider specific event 2 + +// +// Escape Functions +// + +#define SETXOFF 1 // Simulate XOFF received +#define SETXON 2 // Simulate XON received +#define SETRTS 3 // Set RTS high +#define CLRRTS 4 // Set RTS low +#define SETDTR 5 // Set DTR high +#define CLRDTR 6 // Set DTR low +#define RESETDEV 7 // Reset device if possible +#define SETBREAK 8 // Set the device break line. +#define CLRBREAK 9 // Clear the device break line. + +// +// PURGE function flags. +// +#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. +#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. +#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. +#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + + + + + + From e676655a82ce9c036b4a7c8241e81bab2c7af573 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:16:50 +0000 Subject: [PATCH 0434/2215] Removed function Message::wideToString(), we should use TelldusCore::wideToString() from now on --- telldus-core/common/Message.cpp | 19 ------------------- telldus-core/common/Message.h | 2 -- 2 files changed, 21 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 0ef1a354..7cb30bd9 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -99,22 +99,3 @@ int Message::wideToInteger(const std::wstring &input){ inputstream >> retval; return retval; } - -std::string Message::wideToString(const std::wstring &input){ - - //return std::string(input.begin(), input.end()); //TODO, change this conversion method - - std::string strReturn; - - size_t len = input.length(); - char* convPointer = new char[len + 1]; - - wcstombs(convPointer, input.c_str(), len + 1); - - strReturn = convPointer; - - delete [] convPointer; - - return strReturn; - -} diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 7a12e75f..3217c84f 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -23,8 +23,6 @@ namespace TelldusCore { static int takeInt(std::wstring *); static int wideToInteger(const std::wstring &input); - static std::string wideToString(const std::wstring &input); - private: }; From 3451af51709625be3490e55238149db20fc19274 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 24 Oct 2010 16:50:35 +0000 Subject: [PATCH 0435/2215] Return the error TELLSTICK_ERROR_CONNECTING_SERVICE if the client cannot connect to the server --- telldus-core/client/Client.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 2c24ed74..ce195246 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -166,6 +166,11 @@ void Client::run(){ std::wstring Client::sendToService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); + if (!s.isConnected()) { //Connection failed + TelldusCore::Message msg; + msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); + return msg; + } s.write(msg.data()); return s.read(1000); From a6849dcbbe63cbc79f4388c39e56739e50eda471 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 25 Oct 2010 08:13:20 +0000 Subject: [PATCH 0436/2215] Code cleanup --- telldus-core/service/DeviceManager.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 3994981d..3fafc541 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -91,14 +91,14 @@ int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, std::wstr std::wstring DeviceManager::getDeviceStateValue(int deviceId){ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getStateValue(); } - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ @@ -122,14 +122,14 @@ std::wstring DeviceManager::getDeviceModel(int deviceId){ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getModel(); } - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } int DeviceManager::setDeviceModel(int deviceId, std::wstring model) @@ -155,14 +155,14 @@ std::wstring DeviceManager::getDeviceName(int deviceId){ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getName(); } - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } int DeviceManager::setDeviceName(int deviceId, std::wstring name){ @@ -224,14 +224,14 @@ std::wstring DeviceManager::getDeviceProtocol(int deviceId){ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); return it->second->getProtocolName(); } - return L"UNKNOWN"; //TODO, what? + return L"UNKNOWN"; } int DeviceManager::setDeviceProtocol(int deviceId, std::wstring protocol) From 20804d441cecd77baa87af362e0e5e2b15169d63 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 25 Oct 2010 08:14:28 +0000 Subject: [PATCH 0437/2215] New wait-for-object-fix when timeout is used in Socket_win --- telldus-core/client/Client.cpp | 2 +- telldus-core/common/Socket_win.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index ce195246..20b233e1 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -138,7 +138,7 @@ void Client::run(){ } } - std::wstring clientMessage = d->eventSocket.read(); + std::wstring clientMessage = d->eventSocket.read(5000); //testing 5 second timeout if(clientMessage != L""){ //a message arrived std::wstring type = Message::takeString(&clientMessage); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index a25df5e0..3aa32907 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -98,11 +98,13 @@ std::wstring Socket::read(int timeout){ result = WaitForSingleObject(oOverlap.hEvent, timeout); if(!d->running){ + CancelIo(d->hPipe); CloseHandle(d->readEvent); return L""; } if (result == WAIT_TIMEOUT) { + CancelIo(d->hPipe); CloseHandle(d->readEvent); return L""; } @@ -114,6 +116,8 @@ std::wstring Socket::read(int timeout){ } buf[0] = 0; } + + CancelIo(d->hPipe); //TODO maybe remove this row CloseHandle(d->readEvent); return buf; } @@ -132,6 +136,7 @@ void Socket::write(const std::wstring &msg){ result = WaitForSingleObject(writeEvent, 500); if (result == WAIT_TIMEOUT) { + CancelIo(d->hPipe); CloseHandle(writeEvent); d->connected = false; return; @@ -139,6 +144,7 @@ void Socket::write(const std::wstring &msg){ fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, false); CloseHandle(writeEvent); if (!fSuccess) { + CancelIo(d->hPipe); d->connected = false; return; } From 37dea73fa8379c2dfa7f10804a8f00ec9fa54ddf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 09:15:14 +0000 Subject: [PATCH 0438/2215] Fixed compiler warning. --- telldus-core/service/ProtocolNexa.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index c4a4fb2f..b6420fd2 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -56,10 +56,10 @@ std::string ProtocolNexa::getStringBell() { } std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { - const char START[] = {'T',127,255,24,1,0}; + const unsigned char START[] = {'T',127,255,24,1,0}; // const char START[] = {'T',130,255,26,24,0}; - std::string strMessage(START); + std::string strMessage(reinterpret_cast(START)); strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses int intHouse = getIntParameter(L"house", 1, 67108863); int intCode = getIntParameter(L"unit", 1, 16)-1; From 12bcaa1725b7d334acc9d81efb27b4075e95b2df Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 25 Oct 2010 09:37:51 +0000 Subject: [PATCH 0439/2215] Code cleanup --- telldus-core/service/Device.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 577f6179..955c285f 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -20,8 +20,6 @@ Device::Device(int id) d->protocol = 0; d->preferredControllerId = 0; d->state = 0; - //när något uppdateras, spara också till registret - //obs, kunna hantera om alla värden inte är satta } Device::~Device(void) { From 090ed8b7d86a97ee9cc87f119d1c03ea82a1fc50 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 09:43:37 +0000 Subject: [PATCH 0440/2215] Added const modifier to parameter. --- telldus-core/service/Protocol.cpp | 2 +- telldus-core/service/Protocol.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 11d03c24..6551e8b4 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -76,7 +76,7 @@ int Protocol::getIntParameter(const std::wstring &name, int min, int max) const return intValue; } -Protocol *Protocol::getProtocolInstance(std::wstring &protocolname){ +Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ if(TelldusCore::comparei(protocolname, L"arctech")){ return new ProtocolNexa(); diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index d98c5c82..6ea3531f 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -15,7 +15,7 @@ public: Protocol(); virtual ~Protocol(void); - static Protocol *getProtocolInstance(std::wstring &protocolname); + static Protocol *getProtocolInstance(const std::wstring &protocolname); virtual int methods() const = 0; std::wstring model() const; From e9f07594f0e6fdf0baf3982eb6703194d0bd3662 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 09:47:09 +0000 Subject: [PATCH 0441/2215] Added function stub Protocol::getParametersForProtocol() --- telldus-core/service/Protocol.cpp | 5 +++++ telldus-core/service/Protocol.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 6551e8b4..2d577422 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -115,3 +115,8 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ return 0; } +std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { + std::list parameters; + + return parameters; +} diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 6ea3531f..374ce2c3 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -2,6 +2,7 @@ #define PROTOCOL_H #include +#include #include #include "../client/telldus-core.h" @@ -16,6 +17,7 @@ public: virtual ~Protocol(void); static Protocol *getProtocolInstance(const std::wstring &protocolname); + static std::list getParametersForProtocol(const std::wstring &protocolName); virtual int methods() const = 0; std::wstring model() const; From be9c1e1a7953bf64527fbba607d25d312eddf0eb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 09:49:16 +0000 Subject: [PATCH 0442/2215] Made added modifier const to Device::getProtocolName(). --- telldus-core/service/Device.cpp | 2 +- telldus-core/service/Device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 955c285f..5bbaa189 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -91,7 +91,7 @@ void Device::setPreferredControllerId(int controllerId){ d->preferredControllerId = controllerId; } -std::wstring Device::getProtocolName(){ +std::wstring Device::getProtocolName() const { return d->protocolName; } diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 05d36866..69ba1f93 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -24,7 +24,7 @@ public: void setParameter(const std::wstring &key, const std::wstring &value); int getPreferredControllerId(); void setPreferredControllerId(int controllerId); - std::wstring getProtocolName(); + std::wstring getProtocolName() const; void setProtocolName(const std::wstring &name); void setStateValue(int stateValue); void setLastSentCommand(int command, std::wstring value); From 821589392bc155edf34a9018fb6e6c949766423a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 09:50:34 +0000 Subject: [PATCH 0443/2215] Added function Device::getParametersForProtocol() --- telldus-core/service/Device.cpp | 4 ++++ telldus-core/service/Device.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 5bbaa189..8aa45c5a 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -79,6 +79,10 @@ std::wstring Device::getParameter(const std::wstring &key){ return d->parameterList[key]; } +std::list Device::getParametersForProtocol() const { + return Protocol::getParametersForProtocol(getProtocolName()); +} + void Device::setParameter(const std::wstring &key, const std::wstring &value){ d->parameterList[key] = value; } diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 69ba1f93..27519982 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -5,6 +5,7 @@ #include "Mutex.h" #include "Protocol.h" #include +#include class Device : public TelldusCore::Mutex { @@ -21,6 +22,7 @@ public: std::wstring getName(); void setName(const std::wstring &name); std::wstring getParameter(const std::wstring &key); + std::list getParametersForProtocol() const; void setParameter(const std::wstring &key, const std::wstring &value); int getPreferredControllerId(); void setPreferredControllerId(int controllerId); From c3adca9081ee970848693bfc2f7e38442ff9543f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 09:52:49 +0000 Subject: [PATCH 0444/2215] Retrieve the parameters-list. We don't do anything with it yet though --- telldus-core/service/DeviceManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 3fafc541..9fce167e 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -386,7 +386,7 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData if (! (it->second->getMethods() & msg.method())) { continue; } - //TODO: Check the parameters to see if it matches + std::list parameters = it->second->getParametersForProtocol(); //First save the last sent command, this also triggers the callback to the client //TODO From a925c757611a0beea5ae4fb50ffd8d7d6776cbd6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 09:53:36 +0000 Subject: [PATCH 0445/2215] Parse the rawEvent in TelldusMain. --- telldus-core/service/TelldusMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 6403bbfc..0c89fe54 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -89,7 +89,7 @@ void TelldusMain::start(void) { std::auto_ptr eventData(dataEvent->takeSignal()); ControllerEventData *data = reinterpret_cast(eventData.get()); if (data) { - //TODO: Handle the message + deviceManager.handleControllerMessage(*data); } } From 8529b0f3b12f9a557d4717ec2d2c72925531297a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 10:08:42 +0000 Subject: [PATCH 0446/2215] Implemented function Protocol::getParametersForProtocol() --- telldus-core/service/Protocol.cpp | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 2d577422..d3fa24b5 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -118,5 +118,47 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { std::list parameters; + if(TelldusCore::comparei(protocolName, L"arctech")){ + parameters.push_back(L"house"); + parameters.push_back(L"unit"); + + } else if (TelldusCore::comparei(protocolName, L"brateck")) { + parameters.push_back(L"house"); + + } else if (TelldusCore::comparei(protocolName, L"everflourish")) { + parameters.push_back(L"house"); + parameters.push_back(L"unit"); + + } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { + parameters.push_back(L"code"); + + } else if (TelldusCore::comparei(protocolName, L"ikea")) { + parameters.push_back(L"system"); + parameters.push_back(L"units"); + parameters.push_back(L"fade"); + + } else if (TelldusCore::comparei(protocolName, L"risingsun")) { + parameters.push_back(L"house"); + parameters.push_back(L"unit"); + + } else if (TelldusCore::comparei(protocolName, L"sartano")) { + parameters.push_back(L"code"); + + } else if (TelldusCore::comparei(protocolName, L"silvanchip")) { + parameters.push_back(L"house"); + + } else if (TelldusCore::comparei(protocolName, L"upm")) { + parameters.push_back(L"house"); + parameters.push_back(L"unit"); + + } else if (TelldusCore::comparei(protocolName, L"waveman")) { + parameters.push_back(L"house"); + parameters.push_back(L"unit"); + + } else if (TelldusCore::comparei(protocolName, L"x10")) { + parameters.push_back(L"house"); + parameters.push_back(L"unit"); + } + return parameters; } From 24e2611adca1b49e2526b84e5cf40d434b3495c4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 25 Oct 2010 13:42:14 +0000 Subject: [PATCH 0447/2215] Receiving duo-messages, and changing device status and notifying clients --- telldus-core/service/ControllerMessage.cpp | 8 +++++ telldus-core/service/ControllerMessage.h | 1 + telldus-core/service/Device.cpp | 6 +++- telldus-core/service/Device.h | 2 +- telldus-core/service/DeviceManager.cpp | 23 +++++++++--- telldus-core/service/Protocol.cpp | 42 +++++++++++----------- telldus-core/service/Protocol.h | 2 +- telldus-core/service/TelldusMain.cpp | 2 +- 8 files changed, 57 insertions(+), 29 deletions(-) diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index a9f305a3..c4296f62 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -45,4 +45,12 @@ int ControllerMessage::method() const { std::wstring ControllerMessage::protocol() const { return TelldusCore::charToWstring(d->protocol.c_str()); +} + +std::string ControllerMessage::getParameter(const std::string &key){ + std::map::iterator it = d->parameters.find(key); + if (it == d->parameters.end()) { + return ""; + } + return d->parameters[key]; } \ No newline at end of file diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index f692315f..dc0a7595 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -8,6 +8,7 @@ public: ControllerMessage(const std::string &rawMessage); virtual ~ControllerMessage(); + std::string getParameter(const std::string &key); int method() const; std::wstring protocol() const; diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 8aa45c5a..e0e3592c 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -76,10 +76,14 @@ void Device::setName(const std::wstring &name){ } std::wstring Device::getParameter(const std::wstring &key){ + ParameterMap::iterator it = d->parameterList.find(key); + if (it == d->parameterList.end()) { + return L""; + } return d->parameterList[key]; } -std::list Device::getParametersForProtocol() const { +std::list Device::getParametersForProtocol() const { return Protocol::getParametersForProtocol(getProtocolName()); } diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 27519982..1a287c5e 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -22,7 +22,7 @@ public: std::wstring getName(); void setName(const std::wstring &name); std::wstring getParameter(const std::wstring &key); - std::list getParametersForProtocol() const; + std::list getParametersForProtocol() const; void setParameter(const std::wstring &key, const std::wstring &value); int getPreferredControllerId(); void setPreferredControllerId(int controllerId); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 9fce167e..eb9a9fec 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -386,12 +386,27 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData if (! (it->second->getMethods() & msg.method())) { continue; } - std::list parameters = it->second->getParametersForProtocol(); - //First save the last sent command, this also triggers the callback to the client - //TODO + std::list parameters = it->second->getParametersForProtocol(); + bool thisDevice = true; + for (std::list::iterator paramIt = parameters.begin(); paramIt != parameters.end(); ++paramIt){ + //TODO more efficient conversion/compare? wstring or not? + if(!TelldusCore::comparei(it->second->getParameter(TelldusCore::charToWstring((*paramIt).c_str())), TelldusCore::charToWstring(msg.getParameter(*paramIt).c_str()))){ + thisDevice = false; + break; + } + } + + if(!thisDevice){ + continue; + } + + if (this->triggerDeviceStateChange(it->first, msg.method(), L"")) { + d->set.setDeviceState(it->first, msg.method(), L""); + setDeviceLastSentCommand(it->first, msg.method(), L""); //TODO value, when implemented + } + break; } - } int DeviceManager::sendRawCommand(std::wstring command, int reserved){ diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index d3fa24b5..db330659 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -115,49 +115,49 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ return 0; } -std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { - std::list parameters; +std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { + std::list parameters; if(TelldusCore::comparei(protocolName, L"arctech")){ - parameters.push_back(L"house"); - parameters.push_back(L"unit"); + parameters.push_back("house"); + parameters.push_back("unit"); } else if (TelldusCore::comparei(protocolName, L"brateck")) { - parameters.push_back(L"house"); + parameters.push_back("house"); } else if (TelldusCore::comparei(protocolName, L"everflourish")) { - parameters.push_back(L"house"); - parameters.push_back(L"unit"); + parameters.push_back("house"); + parameters.push_back("unit"); } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { - parameters.push_back(L"code"); + parameters.push_back("code"); } else if (TelldusCore::comparei(protocolName, L"ikea")) { - parameters.push_back(L"system"); - parameters.push_back(L"units"); - parameters.push_back(L"fade"); + parameters.push_back("system"); + parameters.push_back("units"); + //parameters.push_back("fade"); } else if (TelldusCore::comparei(protocolName, L"risingsun")) { - parameters.push_back(L"house"); - parameters.push_back(L"unit"); + parameters.push_back("house"); + parameters.push_back("unit"); } else if (TelldusCore::comparei(protocolName, L"sartano")) { - parameters.push_back(L"code"); + parameters.push_back("code"); } else if (TelldusCore::comparei(protocolName, L"silvanchip")) { - parameters.push_back(L"house"); + parameters.push_back("house"); } else if (TelldusCore::comparei(protocolName, L"upm")) { - parameters.push_back(L"house"); - parameters.push_back(L"unit"); + parameters.push_back("house"); + parameters.push_back("unit"); } else if (TelldusCore::comparei(protocolName, L"waveman")) { - parameters.push_back(L"house"); - parameters.push_back(L"unit"); + parameters.push_back("house"); + parameters.push_back("unit"); } else if (TelldusCore::comparei(protocolName, L"x10")) { - parameters.push_back(L"house"); - parameters.push_back(L"unit"); + parameters.push_back("house"); + parameters.push_back("unit"); } return parameters; diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 374ce2c3..16340824 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -17,7 +17,7 @@ public: virtual ~Protocol(void); static Protocol *getProtocolInstance(const std::wstring &protocolname); - static std::list getParametersForProtocol(const std::wstring &protocolName); + static std::list getParametersForProtocol(const std::wstring &protocolName); virtual int methods() const = 0; std::wstring model() const; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 0c89fe54..dce2d8ee 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -89,7 +89,7 @@ void TelldusMain::start(void) { std::auto_ptr eventData(dataEvent->takeSignal()); ControllerEventData *data = reinterpret_cast(eventData.get()); if (data) { - deviceManager.handleControllerMessage(*data); + deviceManager.handleControllerMessage(*data); //TODO thread this (blocking)? } } From f704ba782cfbb4448ba9f6c1dd4883a337c032f7 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 25 Oct 2010 13:54:46 +0000 Subject: [PATCH 0448/2215] Protocol/model changes are now reflected immediately in clients. --- telldus-core/service/Device.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index e0e3592c..090a7b6b 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -64,6 +64,10 @@ std::wstring Device::getModel(){ } void Device::setModel(const std::wstring &model){ + if(d->protocol){ + delete(d->protocol); + d->protocol = 0; + } d->model = model; } @@ -104,6 +108,10 @@ std::wstring Device::getProtocolName() const { } void Device::setProtocolName(const std::wstring &protocolName){ + if(d->protocol){ + delete(d->protocol); + d->protocol = 0; + } d->protocolName = protocolName; } @@ -116,7 +124,7 @@ std::wstring Device::getStateValue(){ */ int Device::doAction(int action, unsigned char data, Controller *controller) { - //TODO, where to check for supported methods? + //TODO where to check for supported methods? Protocol *p = this->retrieveProtocol(); if(p){ std::string code = p->getStringForMethod(action, data, controller); From 592280ad99bcb598736c95de1599911793808b23 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 25 Oct 2010 14:09:51 +0000 Subject: [PATCH 0449/2215] Code cleanup --- telldus-core/common/Strings.cpp | 2 -- telldus-core/service/ClientCommunicationHandler.cpp | 2 +- telldus-core/service/Device.cpp | 1 - telldus-core/service/DeviceManager.cpp | 4 ++-- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 5c56c67f..d052564f 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -22,8 +22,6 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { std::string TelldusCore::wideToString(const std::wstring &input) { - //return std::string(input.begin(), input.end()); //TODO, change this conversion method - std::string strReturn; size_t len = input.length(); diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index c691b4b9..a7cf6b6b 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -38,7 +38,7 @@ ClientCommunicationHandler::~ClientCommunicationHandler(void) void ClientCommunicationHandler::run(){ //run thread - std::wstring clientMessage = d->clientSocket->read(2000); //TODO changed this to a timeout, see if that works better + std::wstring clientMessage = d->clientSocket->read(2000); int intReturn; std::wstring strReturn; diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 090a7b6b..2f02ec38 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -124,7 +124,6 @@ std::wstring Device::getStateValue(){ */ int Device::doAction(int action, unsigned char data, Controller *controller) { - //TODO where to check for supported methods? Protocol *p = this->retrieveProtocol(); if(p){ std::string code = p->getStringForMethod(action, data, controller); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index eb9a9fec..254d0ca8 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -372,7 +372,7 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData //Trigger raw-event EventUpdateData *eventUpdateData = new EventUpdateData(); eventUpdateData->messageType = L"TDRawDeviceEvent"; - eventUpdateData->controllerId = 0; //TODO add the real controller-id + eventUpdateData->controllerId = 0; //TODO add the real controller-id, when implemented eventUpdateData->eventValue = TelldusCore::charToWstring(eventData.msg.c_str()); d->deviceUpdateEvent->signal(eventUpdateData); @@ -414,7 +414,7 @@ int DeviceManager::sendRawCommand(std::wstring command, int reserved){ //TODO test this! Controller *controller = d->controllerManager->getBestControllerById(-1); if(controller){ - return controller->send(TelldusCore::wideToString(command)); // std::string(command.begin(), command.end())); + return controller->send(TelldusCore::wideToString(command)); } else{ return TELLSTICK_ERROR_NOT_FOUND; From a408850d98cf1a4c552f69150c5a39a3b3723c6b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:10:49 +0000 Subject: [PATCH 0450/2215] Convert the strings in wrapStdWstring() --- telldus-core/common/common.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 5ffd417b..261e2a50 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -6,6 +6,7 @@ // #ifdef _WINDOWS +#include "Strings.h" #include #include #define strcasecmp _stricmp @@ -55,5 +56,5 @@ inline char *wrapStdString( const std::string &string) { } inline char *wrapStdWstring( const std::wstring &wstring) { - return wrapStdString(std::string(wstring.begin(), wstring.end())); //TODO + return wrapStdString(TelldusCore::wideToString(wstring)); } \ No newline at end of file From c5d5c2079b6cacd576287f8f2dd666f9d6d9c70f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:39:01 +0000 Subject: [PATCH 0451/2215] Added function TelldusCore::charToInteger() --- telldus-core/common/Strings.cpp | 8 ++++++++ telldus-core/common/Strings.h | 1 + 2 files changed, 9 insertions(+) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index d052564f..89d3bea4 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -10,6 +10,14 @@ std::wstring TelldusCore::charToWstring(const char *value) { return st.str(); } +int TelldusCore::charToInteger(const char *input){ + std::stringstream inputstream; + inputstream << input; + int retval; + inputstream >> retval; + return retval; +} + /** * This method doesn't support all locales */ diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index f6150bb7..ca698b44 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -5,6 +5,7 @@ namespace TelldusCore { std::wstring charToWstring(const char *value); + int charToInteger(const char *value); bool comparei(std::wstring stringA, std::wstring stringB); std::string wideToString(const std::wstring &input); } From d5ef0226881dccff9f12cbd9c0a8357ecf7e30ab Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:39:51 +0000 Subject: [PATCH 0452/2215] Removed TODO, we decided to keep the row --- telldus-core/common/Socket_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 3aa32907..3bc80bc7 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -117,7 +117,7 @@ std::wstring Socket::read(int timeout){ buf[0] = 0; } - CancelIo(d->hPipe); //TODO maybe remove this row + CancelIo(d->hPipe); CloseHandle(d->readEvent); return buf; } From fbe3e7b41c420fceb4a7622142da741bef67663f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:40:25 +0000 Subject: [PATCH 0453/2215] Save the firmware version --- telldus-core/service/TellStick_ftd2xx.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 38b6dad7..cf8e42b2 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -11,6 +11,7 @@ // #include "TellStick.h" #include "Mutex.h" +#include "Strings.h" #include "../client/telldus-core.h" #include @@ -124,7 +125,7 @@ void TellStick::processData( const std::string &data ) { continue; } else if (data[i] == 10) { // \n found if (d->message.substr(0,2).compare("+V") == 0) { - //TODO save the firmware version + d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); } From 4e9b4a55e51386cdeec2d38242130bca9aeab475 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:42:08 +0000 Subject: [PATCH 0454/2215] Added controllerId --- telldus-core/service/Controller.cpp | 5 ++++- telldus-core/service/Controller.h | 3 ++- telldus-core/service/ControllerManager.cpp | 5 +++-- telldus-core/service/DeviceManager.cpp | 5 ++--- telldus-core/service/TellStick.h | 2 +- telldus-core/service/TellStick_ftd2xx.cpp | 4 ++-- 6 files changed, 14 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 1fe93e8b..4737a63d 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -3,11 +3,13 @@ class Controller::PrivateData { public: Event *event; + int id; }; -Controller::Controller(Event *event){ +Controller::Controller(int id, Event *event){ d = new PrivateData; d->event = event; + d->id = id; } Controller::~Controller(){ @@ -17,5 +19,6 @@ Controller::~Controller(){ void Controller::publishData(const std::string &msg) const { ControllerEventData *data = new ControllerEventData; data->msg = msg; + data->controllerId = d->id; d->event->signal(data); } diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 147761af..b9ea8f6f 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -7,6 +7,7 @@ class ControllerEventData : public EventDataBase { public: std::string msg; + int controllerId; }; class Controller { @@ -17,7 +18,7 @@ public: virtual int send( const std::string &message ) = 0; protected: - Controller(Event *event); + Controller(int id, Event *event); void publishData(const std::string &data) const; private: diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 33915663..beff78f6 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -95,12 +95,13 @@ void ControllerManager::loadControllers() { continue; } - TellStick *controller = new TellStick(d->event, *it); + int controllerId = d->lastControllerId-1; + TellStick *controller = new TellStick(controllerId, d->event, *it); if (!controller->isOpen()) { delete controller; continue; } - d->lastControllerId--; + d->lastControllerId = controllerId; d->controllers[d->lastControllerId] = controller; } printf("List containing %i controllers\n", (int)d->controllers.size()); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 254d0ca8..2a0a1487 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -372,7 +372,7 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData //Trigger raw-event EventUpdateData *eventUpdateData = new EventUpdateData(); eventUpdateData->messageType = L"TDRawDeviceEvent"; - eventUpdateData->controllerId = 0; //TODO add the real controller-id, when implemented + eventUpdateData->controllerId = eventData.controllerId; eventUpdateData->eventValue = TelldusCore::charToWstring(eventData.msg.c_str()); d->deviceUpdateEvent->signal(eventUpdateData); @@ -403,7 +403,7 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData if (this->triggerDeviceStateChange(it->first, msg.method(), L"")) { d->set.setDeviceState(it->first, msg.method(), L""); - setDeviceLastSentCommand(it->first, msg.method(), L""); //TODO value, when implemented + setDeviceLastSentCommand(it->first, msg.method(), L""); } break; } @@ -411,7 +411,6 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData int DeviceManager::sendRawCommand(std::wstring command, int reserved){ - //TODO test this! Controller *controller = d->controllerManager->getBestControllerById(-1); if(controller){ return controller->send(TelldusCore::wideToString(command)); diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index d6bae8eb..78f2a923 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -24,7 +24,7 @@ public: class TellStick : public Controller, public TelldusCore::Thread { public: - TellStick(Event *event, const TellStickDescriptor &d); + TellStick(int controllerId, Event *event, const TellStickDescriptor &d); virtual ~TellStick(); virtual int firmwareVersion(); diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index cf8e42b2..1ffd65c4 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -36,8 +36,8 @@ public: #endif }; -TellStick::TellStick(Event *event, const TellStickDescriptor &td ) - :Controller(event) +TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &td ) + :Controller(controllerId, event) { d = new PrivateData; #ifdef _WINDOWS From 5e6b13e1d00a026074af0ceb66907fd7407f2ae8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:42:42 +0000 Subject: [PATCH 0455/2215] Removed TODO, lets have it in the main thread for now --- telldus-core/service/TelldusMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index dce2d8ee..0c89fe54 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -89,7 +89,7 @@ void TelldusMain::start(void) { std::auto_ptr eventData(dataEvent->takeSignal()); ControllerEventData *data = reinterpret_cast(eventData.get()); if (data) { - deviceManager.handleControllerMessage(*data); //TODO thread this (blocking)? + deviceManager.handleControllerMessage(*data); } } From 216c35685f33c0ca4f4e8905eb1e4c34e6007d7d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:51:33 +0000 Subject: [PATCH 0456/2215] Use our real conversion from wstring to string --- telldus-core/service/ProtocolIkea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 4ed1f8e3..134e6d30 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -26,7 +26,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co return ""; } - std::string strUnits(wstrUnits.begin(), wstrUnits.end()); //TODO + std::string strUnits(TelldusCore::wideToString(wstrUnits)); int intUnits = 0; //Start without any units char *tempUnits = new char[strUnits.size()+1]; From 34e85864402e376e15268c2b7ae11606aa29aed7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 14:53:35 +0000 Subject: [PATCH 0457/2215] Removed error strings from the service. Let us have it in the client instead. --- .../service/ClientCommunicationHandler.cpp | 26 ------------------- .../service/ClientCommunicationHandler.h | 1 - 2 files changed, 27 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index a7cf6b6b..6745d1bd 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -174,10 +174,6 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int intMethodsSupported = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); - } else if (function == L"tdGetErrorString") { - int errorNo = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = getErrorString(errorNo); - } else if (function == L"tdSendRawCommand") { std::wstring command = TelldusCore::Message::takeString(&msg); int reserved = TelldusCore::Message::takeInt(&msg); @@ -204,28 +200,6 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } } -std::wstring ClientCommunicationHandler::getErrorString(int errorNo){ - //TODO should this be here? - const int numResponses = 8; - const char *responses[numResponses] = { - "Success", - "TellStick not found", - "Permission denied", - "Device not found", - "The method you tried to use is not supported by the device", - "An error occurred while communicating with TellStick", - "Could not connect to the Telldus Service", - "Received an unknown response" - }; - std::string strReturn; - errorNo = abs(errorNo); //We don't use negative values here. - if (errorNo >= numResponses) { - return L"Unknown error"; - } else { - return TelldusCore::charToWstring(responses[errorNo]); - } -} - void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType){ EventUpdateData *eventData = new EventUpdateData(); diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 42387e32..65fa31f1 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -23,7 +23,6 @@ protected: private: class PrivateData; PrivateData *d; - std::wstring getErrorString(int errorNo); void parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn); void sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType); }; From 6c881923f401fc1538ffa82ff7af832ad8810dc8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 25 Oct 2010 15:00:40 +0000 Subject: [PATCH 0458/2215] Compile fixes for linux --- telldus-core/client/Client.cpp | 2 +- telldus-core/common/common.h | 34 ++++++++++----------- telldus-core/service/DeviceManager.cpp | 1 + telldus-core/service/EventUpdateManager.cpp | 23 +++++++------- telldus-core/service/TellStick_libftdi.cpp | 4 +-- 5 files changed, 33 insertions(+), 31 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 20b233e1..c1928ea4 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -2,7 +2,7 @@ #include "Socket.h" #include "Strings.h" #include "Mutex.h" -#include "Common.h" +#include "common.h" #include diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 261e2a50..08dc6413 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -6,7 +6,6 @@ // #ifdef _WINDOWS -#include "Strings.h" #include #include #define strcasecmp _stricmp @@ -14,6 +13,7 @@ #else #include #endif +#include "Strings.h" #include #include #include @@ -27,22 +27,22 @@ inline void msleep( const int msec) { #endif } -inline void debuglog(const int intMessage, const std::string strMessage){ - - static bool firstRun = true; - std::ofstream file; - std::string filename("C:/log_locks.txt"); - if (firstRun) { - file.open(filename.c_str(), std::ios::out); - firstRun = false; - } else { - file.open(filename.c_str(), std::ios::out | std::ios::app); - } - - file << intMessage << " - " << strMessage << "\n"; - file.flush(); - file.close(); - +inline void debuglog(const int intMessage, const std::string strMessage){ + + static bool firstRun = true; + std::ofstream file; + std::string filename("C:/log_locks.txt"); + if (firstRun) { + file.open(filename.c_str(), std::ios::out); + firstRun = false; + } else { + file.open(filename.c_str(), std::ios::out | std::ios::app); + } + + file << intMessage << " - " << strMessage << "\n"; + file.flush(); + file.close(); + } inline char *wrapStdString( const std::string &string) { diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 2a0a1487..33511391 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -7,6 +7,7 @@ #include "common.h" #include +#include typedef std::map DeviceMap; diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 0717228b..20e7de8a 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -6,6 +6,7 @@ #include "Socket.h" #include +#include typedef std::list SocketList; @@ -81,21 +82,21 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ TelldusCore::Message msg; if(data->messageType == L"TDDeviceEvent"){ - msg.addArgument("TDDeviceEvent"); - msg.addArgument(data->deviceId); - msg.addArgument(data->eventState); - msg.addArgument(data->eventValue); //string + msg.addArgument("TDDeviceEvent"); + msg.addArgument(data->deviceId); + msg.addArgument(data->eventState); + msg.addArgument(data->eventValue); //string } else if(data->messageType == L"TDDeviceChangeEvent"){ - msg.addArgument("TDDeviceChangeEvent"); - msg.addArgument(data->deviceId); - msg.addArgument(data->eventDeviceChanges); - msg.addArgument(data->eventChangeType); + msg.addArgument("TDDeviceChangeEvent"); + msg.addArgument(data->deviceId); + msg.addArgument(data->eventDeviceChanges); + msg.addArgument(data->eventChangeType); } else if(data->messageType == L"TDRawDeviceEvent"){ - msg.addArgument("TDRawDeviceEvent"); - msg.addArgument(data->eventValue); //string - msg.addArgument(data->controllerId); + msg.addArgument("TDRawDeviceEvent"); + msg.addArgument(data->eventValue); //string + msg.addArgument(data->controllerId); } (*it)->write(msg); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index d4a85d78..2fb24d56 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -25,8 +25,8 @@ public: ftdi_context ftHandle; }; -TellStick::TellStick(Event *event, const TellStickDescriptor &td ) - :Controller(event) +TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &td ) + :Controller(controllerId, event) { d = new PrivateData; d->open = false; From 29a759d6e056df98b66e5e9469cb4c514c1988ee Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 25 Oct 2010 15:29:19 +0000 Subject: [PATCH 0459/2215] Fixed compiler warnings --- telldus-core/service/SettingsConfuse.cpp | 41 ++++++++++++------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 3eef2706..ba8b115c 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -167,7 +167,7 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w if (deviceId == intDeviceId) { cfg_setint(cfg_device, "state", intDeviceState); cfg_setstr(cfg_device, "stateValue", std::string(strDeviceStateValue.begin(), strDeviceStateValue.end()).c_str()); - + FILE *fp = fopen(VAR_CONFIG_FILE, "w"); cfg_print(d->var_cfg, fp); fclose(fp); @@ -311,37 +311,38 @@ bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int valu bool readConfig(cfg_t **cfg) { + //All the const_cast keywords is to remove the compiler warnings generated by the C++-compiler. cfg_opt_t controller_opts[] = { - CFG_INT("id", -1, CFGF_NONE), + CFG_INT(const_cast("id"), -1, CFGF_NONE), }; cfg_opt_t device_parameter_opts[] = { //Groups - CFG_STR("devices", 0, CFGF_NONE), + CFG_STR(const_cast("devices"), 0, CFGF_NONE), - CFG_STR("house", 0, CFGF_NONE), - CFG_STR("unit", 0, CFGF_NONE), - CFG_STR("code", 0, CFGF_NONE), - CFG_STR("system", 0, CFGF_NONE), - CFG_STR("units", 0, CFGF_NONE), - CFG_STR("fade", 0, CFGF_NONE), + CFG_STR(const_cast("house"), 0, CFGF_NONE), + CFG_STR(const_cast("unit"), 0, CFGF_NONE), + CFG_STR(const_cast("code"), 0, CFGF_NONE), + CFG_STR(const_cast("system"), 0, CFGF_NONE), + CFG_STR(const_cast("units"), 0, CFGF_NONE), + CFG_STR(const_cast("fade"), 0, CFGF_NONE), CFG_END() }; cfg_opt_t device_opts[] = { - CFG_INT("id", -1, CFGF_NONE), - CFG_STR("name", "Unnamed", CFGF_NONE), - CFG_INT("controller", 0, CFGF_NONE), - CFG_STR("protocol", "arctech", CFGF_NONE), - CFG_STR("model", "", CFGF_NONE), - CFG_SEC("parameters", device_parameter_opts, CFGF_NONE), + CFG_INT(const_cast("id"), -1, CFGF_NONE), + CFG_STR(const_cast("name"), const_cast("Unnamed"), CFGF_NONE), + CFG_INT(const_cast("controller"), 0, CFGF_NONE), + CFG_STR(const_cast("protocol"), const_cast("arctech"), CFGF_NONE), + CFG_STR(const_cast("model"), const_cast(""), CFGF_NONE), + CFG_SEC(const_cast("parameters"), device_parameter_opts, CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { - CFG_STR("deviceNode", "/dev/tellstick", CFGF_NONE), - CFG_SEC("device", device_opts, CFGF_MULTI), + CFG_STR(const_cast("deviceNode"), const_cast("/dev/tellstick"), CFGF_NONE), + CFG_SEC(const_cast("device"), device_opts, CFGF_MULTI), CFG_END() }; @@ -357,13 +358,13 @@ bool readConfig(cfg_t **cfg) { bool readVarConfig(cfg_t **cfg) { cfg_opt_t device_opts[] = { - CFG_INT("state", 0, CFGF_NONE), - CFG_STR("stateValue", "", CFGF_NONE), + CFG_INT(const_cast("state"), 0, CFGF_NONE), + CFG_STR(const_cast("stateValue"), const_cast(""), CFGF_NONE), CFG_END() }; cfg_opt_t opts[] = { - CFG_SEC("device", device_opts, CFGF_MULTI | CFGF_TITLE), + CFG_SEC(const_cast("device"), device_opts, CFGF_MULTI | CFGF_TITLE), CFG_END() }; From 8a08ba2b28230d0039dd39080e11f1ff967c3194 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 26 Oct 2010 07:22:31 +0000 Subject: [PATCH 0460/2215] Added rc file for the client --- telldus-core/client/CMakeLists.txt | 3 ++- telldus-core/client/telldus-core.rc.in | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 telldus-core/client/telldus-core.rc.in diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index cf9cfce8..9e11a489 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -48,7 +48,8 @@ ELSEIF (WIN32) #IF (NOT CMAKE_CL_64) LIST(APPEND telldus-core_SRCS libtelldus-core.def - ) + ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc #ENDIF(NOT CMAKE_CL_64) ADD_DEFINITIONS( -D_WINDOWS diff --git a/telldus-core/client/telldus-core.rc.in b/telldus-core/client/telldus-core.rc.in new file mode 100644 index 00000000..23b37639 --- /dev/null +++ b/telldus-core/client/telldus-core.rc.in @@ -0,0 +1,18 @@ +#include + +VS_VERSION_INFO VERSIONINFO + FILEVERSION ${PACKAGE_MAJOR_VERSION},${PACKAGE_MINOR_VERSION},${PACKAGE_PATCH_VERSION},0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "04090000" + BEGIN + VALUE "FileDescription", "Utilities and driver to control wireless receivers through a TellStick" + VALUE "FileVersion", "${PACKAGE_VERSION}" + VALUE "LegalCopyright", "Copyright (C) 2010 Telldus Technologies AB" + VALUE "OriginalFilename", "TelldusCore.dll" + VALUE "ProductName", "TelldusCore" + VALUE "ProductVersion", "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}" + END + END +END \ No newline at end of file From 635b3c910501d7a090e2e80f7decb9045bf10bd3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 26 Oct 2010 07:23:24 +0000 Subject: [PATCH 0461/2215] Fixed compiler warning on 64 bit compiler --- telldus-core/client/CMakeLists.txt | 12 +++++++++--- telldus-core/client/telldus-core.h | 6 +++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 9e11a489..11aacb33 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -45,16 +45,22 @@ ELSEIF (WIN32) LIST(APPEND telldus-core_LIBRARIES ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib ) - #IF (NOT CMAKE_CL_64) - LIST(APPEND telldus-core_SRCS + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc + ) + LIST(APPEND telldus-core_SRCS libtelldus-core.def ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc - #ENDIF(NOT CMAKE_CL_64) + ) ADD_DEFINITIONS( -D_WINDOWS -DTELLDUSCORE_EXPORTS ) + IF (CMAKE_CL_64) + ADD_DEFINITIONS(-D_CL64) + ENDIF(CMAKE_CL_64) ELSE (APPLE) #### Linux #### SET( telldus-core_TARGET telldus-core ) diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 18e2948c..6ca0caa7 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -11,7 +11,11 @@ #ifdef _WINDOWS #if defined(TELLDUSCORE_EXPORTS) - #define TELLSTICK_API __declspec(dllexport) + #if defined(_CL64) + #define TELLSTICK_API + #else + #define TELLSTICK_API __declspec(dllexport) + #endif #else #define TELLSTICK_API __declspec(dllimport) #endif From db6ac7b93920cfecdc905484489e171a8d76ce75 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 26 Oct 2010 10:40:10 +0000 Subject: [PATCH 0462/2215] Linux actions implemented --- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/TellStick_libftdi.cpp | 43 +++++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 33511391..9d4c39f3 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -326,7 +326,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ device = it->second; } //devicelist unlocked - Controller *controller = d->controllerManager->getBestControllerById(this->getPreferredControllerId(deviceId)); + Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); if(controller){ int retval = device->doAction(action, data, controller); if(retval == TELLSTICK_SUCCESS) { diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 2fb24d56..b6c19826 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -81,10 +81,49 @@ bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const { } void TellStick::run() { - //TODO + //todo } -int TellStick::send( const std::string &message ) { +int TellStick::send( const std::string &strMessage ) { + if (!d->open) { + return TELLSTICK_ERROR_NOT_FOUND; + } + + bool c = true; + unsigned char *tempMessage = new unsigned char[strMessage.size()]; + memcpy(tempMessage, strMessage.c_str(), strMessage.size()); + + int ret; + ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ; + if(ret < 0) { + c = false; + } else if(ret != strMessage.length()) { + fprintf(stderr, "wierd send length? retval %i instead of %d\n", + ret, (int)strMessage.length()); + } + + delete[] tempMessage; + + int retrycnt = 500; + unsigned char in; + while(c && --retrycnt) { + ret = ftdi_read_data( &d->ftHandle, &in, 1); + if (ret > 0) { + if (in == '\n') { + break; + } + } else if(ret == 0) { // No data available + usleep(100); + } else { //Error + c = false; + } + } + if (!retrycnt) { + c = false; + } + if (!c) { + return TELLSTICK_ERROR_COMMUNICATION; + } return TELLSTICK_SUCCESS; } From fbc72cff52cc29be14cbc2ea300d0afa31edc264 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 26 Oct 2010 15:06:02 +0000 Subject: [PATCH 0463/2215] Receive messages in linux. Deadlocks fixed --- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/TellStick.h | 1 + telldus-core/service/TellStick_libftdi.cpp | 86 +++++++++++++++++++++- 3 files changed, 86 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 9d4c39f3..08dc007e 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -404,7 +404,7 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData if (this->triggerDeviceStateChange(it->first, msg.method(), L"")) { d->set.setDeviceState(it->first, msg.method(), L""); - setDeviceLastSentCommand(it->first, msg.method(), L""); + it->second->setLastSentCommand(msg.method(), L""); } break; } diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 78f2a923..4955a2e0 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -39,6 +39,7 @@ protected: void processData( const std::string &data ); void run(); void setBaud( int baud ); + void stop(); private: static std::list findAllByVIDPID( int vid, int pid ); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index b6c19826..fc04c0f6 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -16,6 +16,17 @@ #include #include +#include "Thread.h" +#include "Mutex.h" +#include "Strings.h" + +#include + +typedef struct _EVENT_HANDLE { + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; +} EVENT_HANDLE; +typedef int DWORD; class TellStick::PrivateData { public: @@ -23,6 +34,9 @@ public: int vid, pid, fwVersion; std::string serial, message; ftdi_context ftHandle; + EVENT_HANDLE eh; + bool running; + TelldusCore::Mutex mutex; }; TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &td ) @@ -34,6 +48,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & d->pid = td.pid; d->fwVersion = 0; d->serial = td.serial; + d->running = false; ftdi_init(&d->ftHandle); @@ -47,11 +62,21 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & ftdi_disable_bitbang( &d->ftHandle ); if (d->open) { -// setBaud(4800); + + if (td.pid == 0x0C31) { + this->setBaud(9600); + } else { + this->setBaud(4800); + } + this->start(); } } TellStick::~TellStick() { + if (d->running) { + stop(); + } + if (d->open) { ftdi_usb_close(&d->ftHandle); ftdi_deinit(&d->ftHandle); @@ -80,8 +105,45 @@ bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const { return true; } +void TellStick::processData( const std::string &data ) { + for (unsigned int i = 0; i < data.length(); ++i) { + if (data[i] == 13) { // Skip \r + continue; + } else if (data[i] == 10) { // \n found + if (d->message.substr(0,2).compare("+V") == 0) { + //parent->fwVersion = atoi(message.substr(2).c_str()); + //printf("Firmware version: %s\n", message.substr(2).c_str()); + d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); //TODO used? + } else if (d->message.substr(0,2).compare("+R") == 0) { + this->publishData(d->message.substr(2)); + } + d->message.clear(); + } else { // Append the character + d->message.append( 1, data[i] ); + } + } +} + void TellStick::run() { - //todo + int dwBytesRead = 0; + unsigned char buf[100]; // = 0; + + pthread_mutex_init(&d->eh.eMutex, NULL); + pthread_cond_init(&d->eh.eCondVar, NULL); + + { + TelldusCore::MutexLocker locker(&d->mutex); + d->running = true; + } + + while(1) { + usleep(1000); + dwBytesRead = ftdi_read_data(&d->ftHandle, buf, 100); + if (dwBytesRead < 1) { + continue; + } + processData( reinterpret_cast(&buf) ); + } } int TellStick::send( const std::string &strMessage ) { @@ -127,6 +189,13 @@ int TellStick::send( const std::string &strMessage ) { return TELLSTICK_SUCCESS; } +void TellStick::setBaud(int baud) { + int ret = ftdi_set_baudrate(&d->ftHandle, baud); + if(ret != 0) { + fprintf(stderr, "set Baud failed, retval %i\n", ret); + } +} + std::list TellStick::findAll() { std::list tellstick = findAllByVIDPID(0x1781, 0x0C30); @@ -192,3 +261,16 @@ std::list TellStick::findAllByVIDPID( int vid, int pid ) { return retval; } + +void TellStick::stop() { + if (d->running) { + { + TelldusCore::MutexLocker locker(&d->mutex); + d->running = false; + } + //Unlock the wait-condition + + pthread_cond_broadcast(&d->eh.eCondVar); + } + this->wait(); +} From b9663ab8acd854573accaad90d3dde6d952b70b1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 09:09:14 +0000 Subject: [PATCH 0464/2215] Changed (buggy?) CriticalSection code and replaced with (marginally?) slower Mutex code. --- telldus-core/common/Mutex.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index 7099e8e0..48c277a7 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -15,10 +15,9 @@ using namespace TelldusCore; - #ifdef _WINDOWS #include - typedef CRITICAL_SECTION MUTEX_T; + typedef HANDLE MUTEX_T; #else #include typedef pthread_mutex_t MUTEX_T; @@ -32,7 +31,7 @@ public: Mutex::Mutex() { d = new PrivateData; #ifdef _WINDOWS - InitializeCriticalSection(&d->mutex); + d->mutex = CreateMutex(NULL, FALSE, NULL); #else pthread_mutex_init(&d->mutex, NULL); #endif @@ -40,7 +39,7 @@ Mutex::Mutex() { Mutex::~Mutex() { #ifdef _WINDOWS - DeleteCriticalSection(&d->mutex); + CloseHandle(d->mutex); #else pthread_mutex_destroy(&d->mutex); #endif @@ -49,13 +48,7 @@ Mutex::~Mutex() { void Mutex::lock() { #ifdef _WINDOWS - //What we would want is to use EnterCriticalSection instead of our loop. - //For some reason Windows doesn't always let our thread enter the critical section - //even when another thread leaves the critical section - //This loop seems to fix the problem. - while(!TryEnterCriticalSection(&d->mutex)) { - msleep(5); - } + WaitForSingleObject(d->mutex, INFINITE); #else pthread_mutex_lock(&d->mutex); #endif @@ -63,7 +56,7 @@ void Mutex::lock() { void Mutex::unlock() { #ifdef _WINDOWS - LeaveCriticalSection(&d->mutex); + ReleaseMutex(d->mutex); #else pthread_mutex_unlock(&d->mutex); #endif From 509985293dab259b0089b9a6fed8ed186fdafaf9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 09:10:44 +0000 Subject: [PATCH 0465/2215] RegDeleteKeyEx() was introduced in Vista, that means we cannot use it. Changed to RegDeleteKey() instead. --- telldus-core/service/SettingsWinRegistry.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 3333a66a..4fb39e5c 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -157,10 +157,9 @@ bool Settings::removeDevice(int intDeviceId) { ssRegPath << d->strRegPathDevice << intDeviceId; std::wstring strCompleteRegPath = ssRegPath.str(); - long lngSuccess32 = RegDeleteKeyEx(d->rootKey, strCompleteRegPath.c_str(), KEY_WOW64_32KEY, 0); - long lngSuccess64 = RegDeleteKeyEx(d->rootKey, strCompleteRegPath.c_str(), KEY_WOW64_64KEY, 0); + long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); - if(lngSuccess32 == ERROR_SUCCESS || lngSuccess64 == ERROR_SUCCESS){ + if(lngSuccess == ERROR_SUCCESS){ //one of the deletions succeeded return true; } From 2697fd928f74e168205efaf373f8a3625c62b4ea Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 09:12:08 +0000 Subject: [PATCH 0466/2215] Compare our device strings as uppercase strings. The casing seems to differ on different platforms. --- telldus-core/service/TelldusWinService_win.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 9267b46b..a7c48322 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -3,6 +3,7 @@ #include #include +#include int g_argc; char **g_argv; @@ -58,6 +59,7 @@ DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DW } std::wstring name(pDevInf->dbcc_name); + transform(name.begin(), name.end(), name.begin(), toupper); //Parse VID size_t posStart = name.find(L"VID_"); From 35c8539b73a96693b90fa337747d608e1ed462d5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 10:10:18 +0000 Subject: [PATCH 0467/2215] Workaround for sending 99% to ArcTech dimmers --- telldus-core/service/ProtocolNexa.cpp | 110 +++++++++++++------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index b6420fd2..1dc7f3da 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -23,38 +23,42 @@ std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Con } else if (TelldusCore::comparei(model(), L"bell")) { return getStringBell(); } + if ((method == TELLSTICK_TURNON) && TelldusCore::comparei(model(), L"selflearning-dimmer")) { + //Workaround for not letting a dimmer do into "dimming mode" + return getStringSelflearning(TELLSTICK_DIM, 255); + } return getStringSelflearning(method, data); -} - -std::string ProtocolNexa::getStringCodeSwitch(int method) { - std::string strReturn = "S"; - - std::wstring house = getStringParameter(L"house", L"A"); - int intHouse = house[0] - L'A'; - strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1)); - - if (method == TELLSTICK_TURNON) { - strReturn.append("$k$k$kk$$kk$$kk$$k+"); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(this->getOffCode()); - } else { - return ""; - } - return strReturn; -} - -std::string ProtocolNexa::getStringBell() { - std::string strReturn = "S"; - - std::wstring house = getStringParameter(L"house", L"A"); - int intHouse = house[0] - L'A'; - strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append("$kk$$kk$$kk$$k$k"); //Unit 7 - strReturn.append("$kk$$kk$$kk$$kk$$k+"); //Bell - return strReturn; -} - +} + +std::string ProtocolNexa::getStringCodeSwitch(int method) { + std::string strReturn = "S"; + + std::wstring house = getStringParameter(L"house", L"A"); + int intHouse = house[0] - L'A'; + strReturn.append(getCodeSwitchTuple(intHouse)); + strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1)); + + if (method == TELLSTICK_TURNON) { + strReturn.append("$k$k$kk$$kk$$kk$$k+"); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(this->getOffCode()); + } else { + return ""; + } + return strReturn; +} + +std::string ProtocolNexa::getStringBell() { + std::string strReturn = "S"; + + std::wstring house = getStringParameter(L"house", L"A"); + int intHouse = house[0] - L'A'; + strReturn.append(getCodeSwitchTuple(intHouse)); + strReturn.append("$kk$$kk$$kk$$k$k"); //Unit 7 + strReturn.append("$kk$$kk$$kk$$kk$$k+"); //Bell + return strReturn; +} + std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { const unsigned char START[] = {'T',127,255,24,1,0}; // const char START[] = {'T',130,255,26,24,0}; @@ -63,13 +67,13 @@ std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses int intHouse = getIntParameter(L"house", 1, 67108863); int intCode = getIntParameter(L"unit", 1, 16)-1; - + std::string m; for (int i = 25; i >= 0; --i) { m.append( intHouse & 1 << i ? "10" : "01" ); } m.append("01"); //Group - + //On/off if (method == TELLSTICK_DIM) { m.append("00"); @@ -80,22 +84,22 @@ std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) } else { return ""; } - + for (int i = 3; i >= 0; --i) { m.append( intCode & 1 << i ? "10" : "01" ); } - + if (method == TELLSTICK_DIM) { unsigned char newLevel = level/16; for (int i = 3; i >= 0; --i) { m.append(newLevel & 1 << i ? "10" : "01"); } } - + //The number of data is odd. //Add this to make it even, otherwise the following loop will not work - m.append("0"); - + m.append("0"); + unsigned char code = 9; //b1001, startcode for (unsigned int i = 0; i < m.length(); ++i) { code <<= 4; @@ -111,7 +115,7 @@ std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) } } strMessage.append("+"); - + // for( int i = 0; i < strMessage.length(); ++i ) { // printf("%i,", (unsigned char)strMessage[i]); // } @@ -121,17 +125,17 @@ std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { std::string strReturn = ""; - for( int i = 0; i < 4; ++i ) { - if (intCode & 1) { //Convert 1 - strReturn.append("$kk$"); - } else { //Convert 0 - strReturn.append("$k$k"); - } - intCode >>= 1; - } - return strReturn; -} - -std::string ProtocolNexa::getOffCode() const { - return "$k$k$kk$$kk$$k$k$k+"; -} + for( int i = 0; i < 4; ++i ) { + if (intCode & 1) { //Convert 1 + strReturn.append("$kk$"); + } else { //Convert 0 + strReturn.append("$k$k"); + } + intCode >>= 1; + } + return strReturn; +} + +std::string ProtocolNexa::getOffCode() const { + return "$k$k$kk$$kk$$k$k$k+"; +} From c854a3aba4447bf07693da6b2bb05b8596a4831a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 10:12:22 +0000 Subject: [PATCH 0468/2215] Added check in eternal loop to stop if neccesary --- telldus-core/service/TellStick_libftdi.cpp | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index fc04c0f6..3e620f70 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -21,7 +21,7 @@ #include "Strings.h" #include - + typedef struct _EVENT_HANDLE { pthread_cond_t eCondVar; pthread_mutex_t eMutex; @@ -62,11 +62,11 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & ftdi_disable_bitbang( &d->ftHandle ); if (d->open) { - + if (td.pid == 0x0C31) { this->setBaud(9600); } else { - this->setBaud(4800); + this->setBaud(4800); } this->start(); } @@ -76,7 +76,7 @@ TellStick::~TellStick() { if (d->running) { stop(); } - + if (d->open) { ftdi_usb_close(&d->ftHandle); ftdi_deinit(&d->ftHandle); @@ -127,16 +127,16 @@ void TellStick::processData( const std::string &data ) { void TellStick::run() { int dwBytesRead = 0; unsigned char buf[100]; // = 0; - + pthread_mutex_init(&d->eh.eMutex, NULL); pthread_cond_init(&d->eh.eCondVar, NULL); - + { TelldusCore::MutexLocker locker(&d->mutex); d->running = true; } - - while(1) { + + while(d->running) { //TODO check libftdi doc how to do this best usleep(1000); dwBytesRead = ftdi_read_data(&d->ftHandle, buf, 100); if (dwBytesRead < 1) { @@ -150,7 +150,7 @@ int TellStick::send( const std::string &strMessage ) { if (!d->open) { return TELLSTICK_ERROR_NOT_FOUND; } - + bool c = true; unsigned char *tempMessage = new unsigned char[strMessage.size()]; memcpy(tempMessage, strMessage.c_str(), strMessage.size()); @@ -163,9 +163,9 @@ int TellStick::send( const std::string &strMessage ) { fprintf(stderr, "wierd send length? retval %i instead of %d\n", ret, (int)strMessage.length()); } - + delete[] tempMessage; - + int retrycnt = 500; unsigned char in; while(c && --retrycnt) { @@ -269,7 +269,7 @@ void TellStick::stop() { d->running = false; } //Unlock the wait-condition - + pthread_cond_broadcast(&d->eh.eCondVar); } this->wait(); From e46027915779f3c918c7fb27c72b7eac4aa64128 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 10:33:46 +0000 Subject: [PATCH 0469/2215] Added lock for receiving/sending in TellStick --- telldus-core/service/TellStick_libftdi.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 3e620f70..8ba3e4a6 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -136,8 +136,12 @@ void TellStick::run() { d->running = true; } - while(d->running) { //TODO check libftdi doc how to do this best + while(1) { //TODO check libftdi doc how to do this best usleep(1000); + TelldusCore::MutexLocker locker(&d->mutex); + if (!d->running) { + break; + } dwBytesRead = ftdi_read_data(&d->ftHandle, buf, 100); if (dwBytesRead < 1) { continue; @@ -155,6 +159,11 @@ int TellStick::send( const std::string &strMessage ) { unsigned char *tempMessage = new unsigned char[strMessage.size()]; memcpy(tempMessage, strMessage.c_str(), strMessage.size()); + //This lock does two things + // 1 Prevents two calls from different threads to this function + // 2 Prevents our running thread from receiving the data we are interested in here + TelldusCore::MutexLocker(&d->mutex); + int ret; ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ; if(ret < 0) { From 0d0933494c975ab23a5bee628141eedde043f5b8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 10:56:40 +0000 Subject: [PATCH 0470/2215] Made the ftdi engine easily configurable --- telldus-core/service/CMakeLists.txt | 33 +++++++++++++++++------------ 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 7fa2ea9b..622e88cd 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -68,16 +68,15 @@ INCLUDE_DIRECTORIES( ######## Platforms-specific, non configurable ######## IF (APPLE) #### Mac OS X #### + SET(DEFAULT_FTDI_ENGINE "ftd2xx") SET( telldus-service_TARGET TelldusService ) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) FIND_LIBRARY(IOKIT_LIBRARY IOKit) - ADD_DEFINITIONS( -DLIBFTD2XX ) - + SET( telldus-service_LIBRARIES ${telldus-service_LIBRARIES} ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} - ${FTD2XX_LIBRARY} TelldusCommon ) LIST(APPEND telldus-service_SRCS @@ -86,20 +85,18 @@ IF (APPLE) #### Mac OS X #### Event_unix.cpp EventHandler_unix.cpp SettingsCoreFoundationPreferences.cpp - TellStick_ftd2xx.cpp ) - + ELSEIF (WIN32) #### Windows #### + SET(DEFAULT_FTDI_ENGINE "ftd2xx") SET( telldus-service_TARGET TelldusService ) - FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) - ADD_DEFINITIONS( -DUNICODE -DLIBFTD2XX ) + ADD_DEFINITIONS( -DUNICODE ) ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" ) LIST(APPEND telldus-service_LIBRARIES ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib - ${FTD2XX_LIBRARY} ) LIST(APPEND telldus-service_SRCS ConnectionListener_win.cpp @@ -108,16 +105,15 @@ ELSEIF (WIN32) #### Windows #### main_win.cpp SettingsWinRegistry.cpp TelldusWinService_win.cpp - TellStick_ftd2xx.cpp ) LIST(APPEND telldus-service_HDRS TelldusWinService_win.h ) ELSE (APPLE) #### Linux #### + SET(DEFAULT_FTDI_ENGINE "libftdi") FIND_LIBRARY(CONFUSE_LIBRARY confuse) - FIND_LIBRARY(FTDI_LIBRARY ftdi) - ADD_DEFINITIONS( -D_CONFUSE -DLIBFTDI ) + ADD_DEFINITIONS( -D_CONFUSE ) SET( telldus-service_TARGET telldusd ) LIST(APPEND telldus-service_SRCS @@ -126,15 +122,26 @@ ELSE (APPLE) #### Linux #### EventHandler_unix.cpp main_unix.cpp SettingsConfuse.cpp - TellStick_libftdi.cpp ) LIST(APPEND telldus-service_LIBRARIES ${CONFUSE_LIBRARY} - ${FTDI_LIBRARY} telldus-common ) ENDIF (APPLE) +SET(FTDI_ENGINE ${DEFAULT_FTDI_ENGINE} CACHE STRING "Which FTDI engine to use. This could be either 'libftdi' or 'ftd2xx'") +IF (FTDI_ENGINE STREQUAL "ftd2xx") + FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) + ADD_DEFINITIONS( -DLIBFTD2XX ) + LIST(APPEND telldus-service_SRCS TellStick_ftd2xx.cpp ) + LIST(APPEND telldus-service_LIBRARIES ${FTD2XX_LIBRARY}) +ELSE (FTDI_ENGINE STREQUAL "ftd2xx") + FIND_LIBRARY(FTDI_LIBRARY ftdi) + ADD_DEFINITIONS( -DLIBFTDI ) + LIST(APPEND telldus-service_SRCS TellStick_libftdi.cpp ) + LIST(APPEND telldus-service_LIBRARIES ${FTDI_LIBRARY}) +ENDIF (FTDI_ENGINE STREQUAL "ftd2xx") + ######## Configuring ######## SOURCE_GROUP("Protocol Files" FILES ${telldus-service_protocol_SRCS}) From f4a9cc6e83c25ee0f7e40d88bebeee108cb774f9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 12:09:30 +0000 Subject: [PATCH 0471/2215] Missed sending 'S' in protocol Fuhaote --- telldus-core/service/ProtocolFuhaote.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index 277563d2..33fd9177 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -12,7 +12,7 @@ std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Contr const char OFF[] = {S,L,S,L,S,L,L,S,0}; const char ON[] = {S,L,L,S,S,L,S,L,0}; - std::string strReturn; + std::string strReturn = "S"; std::wstring strCode = this->getStringParameter(L"code", L""); if (strCode == L"") { return ""; From d71a9fa2f9fa8f886bb8b077724e0daa91b7cbdf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 12:12:09 +0000 Subject: [PATCH 0472/2215] If the protocol returns an empty string this means the method is not supported --- telldus-core/service/Device.cpp | 73 +++++++++++++++++---------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 2f02ec38..d98bb621 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -32,16 +32,16 @@ Device::~Device(void) { */ int Device::getLastSentCommand(int methodsSupported){ - - int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported); - - if (lastSentCommand == TELLSTICK_BELL) { - //Bell is not a state - lastSentCommand = TELLSTICK_TURNOFF; - } - if (lastSentCommand == 0) { - lastSentCommand = TELLSTICK_TURNOFF; - } + + int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported); + + if (lastSentCommand == TELLSTICK_BELL) { + //Bell is not a state + lastSentCommand = TELLSTICK_TURNOFF; + } + if (lastSentCommand == 0) { + lastSentCommand = TELLSTICK_TURNOFF; + } return lastSentCommand; } @@ -127,6 +127,9 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { Protocol *p = this->retrieveProtocol(); if(p){ std::string code = p->getStringForMethod(action, data, controller); + if (code == "") { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } return controller->send(code); } return TELLSTICK_ERROR_UNKNOWN; @@ -136,7 +139,7 @@ Protocol* Device::retrieveProtocol() const { if (d->protocol) { return d->protocol; } - + d->protocol = Protocol::getProtocolInstance(d->protocolName); if(d->protocol){ d->protocol->setModel(d->model); @@ -147,27 +150,27 @@ Protocol* Device::retrieveProtocol() const { return 0; } -int Device::maskUnsupportedMethods(int methods, int supportedMethods) { - // Bell -> On - if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) { - methods |= TELLSTICK_TURNON; - } - //Cut of the rest of the unsupported methods we don't have a fallback for - return methods & supportedMethods; -} - -int Device::methodId( const std::string &methodName ) { - if (methodName.compare("turnon") == 0) { - return TELLSTICK_TURNON; - } - if (methodName.compare("turnoff") == 0) { - return TELLSTICK_TURNOFF; - } - if (methodName.compare("bell") == 0) { - return TELLSTICK_BELL; - } - if (methodName.compare("dim") == 0) { - return TELLSTICK_DIM; - } - return 0; -} +int Device::maskUnsupportedMethods(int methods, int supportedMethods) { + // Bell -> On + if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) { + methods |= TELLSTICK_TURNON; + } + //Cut of the rest of the unsupported methods we don't have a fallback for + return methods & supportedMethods; +} + +int Device::methodId( const std::string &methodName ) { + if (methodName.compare("turnon") == 0) { + return TELLSTICK_TURNON; + } + if (methodName.compare("turnoff") == 0) { + return TELLSTICK_TURNOFF; + } + if (methodName.compare("bell") == 0) { + return TELLSTICK_BELL; + } + if (methodName.compare("dim") == 0) { + return TELLSTICK_DIM; + } + return 0; +} From 10f86876b1738ba5c98e4a5019247ee0a15e9713 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 27 Oct 2010 12:19:36 +0000 Subject: [PATCH 0473/2215] Implemented some locks in settings for linux --- telldus-core/service/SettingsConfuse.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index ba8b115c..28645978 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -39,6 +39,7 @@ const char* VAR_CONFIG_FILE = "/var/state/telldus-core.conf"; */ Settings::Settings(void) { + TelldusCore::MutexLocker locker(&mutex); d = new PrivateData; readConfig(&d->cfg); readVarConfig(&d->var_cfg); @@ -49,6 +50,7 @@ Settings::Settings(void) */ Settings::~Settings(void) { + TelldusCore::MutexLocker locker(&mutex); if (d->cfg > 0) { cfg_free(d->cfg); } @@ -62,6 +64,7 @@ Settings::~Settings(void) * Return a setting */ std::wstring Settings::getSetting(const std::wstring &strName) const { + TelldusCore::MutexLocker locker(&mutex); if (d->cfg > 0) { std::string setting(cfg_getstr(d->cfg, std::string(strName.begin(), strName.end()).c_str())); //TODO, safer conversion (other places in this file as well) return std::wstring(setting.begin(), setting.end()); @@ -73,6 +76,7 @@ std::wstring Settings::getSetting(const std::wstring &strName) const { * Return the number of stored devices */ int Settings::getNumberOfDevices(void) const { + TelldusCore::MutexLocker locker(&mutex); if (d->cfg > 0) { return cfg_size(d->cfg, "device"); } @@ -83,6 +87,7 @@ int Settings::getDeviceId(int intDeviceIndex) const { if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds return -1; } + TelldusCore::MutexLocker locker(&mutex); cfg_t *cfg_device = cfg_getnsec(d->cfg, "device", intDeviceIndex); int id = cfg_getint(cfg_device, "id"); return id; @@ -92,6 +97,7 @@ int Settings::getDeviceId(int intDeviceIndex) const { * Add a new device */ int Settings::addDevice(){ + TelldusCore::MutexLocker locker(&mutex); int intDeviceId = getNextDeviceId(); FILE *fp = fopen(CONFIG_FILE, "w"); @@ -109,6 +115,7 @@ int Settings::addDevice(){ * Get next available device id */ int Settings::getNextDeviceId() const { + //Private, no locks needed int intDeviceId = 0; cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { @@ -125,6 +132,7 @@ int Settings::getNextDeviceId() const { * Remove a device */ bool Settings::removeDevice(int intDeviceId){ + TelldusCore::MutexLocker locker(&mutex); bool blnSuccess = true; FILE *fp = fopen(CONFIG_FILE, "w"); @@ -157,6 +165,7 @@ bool Settings::removeDevice(int intDeviceId){ } bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { + TelldusCore::MutexLocker locker(&mutex); if (d->var_cfg == 0) { return false; } @@ -169,6 +178,10 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w cfg_setstr(cfg_device, "stateValue", std::string(strDeviceStateValue.begin(), strDeviceStateValue.end()).c_str()); FILE *fp = fopen(VAR_CONFIG_FILE, "w"); + //TODO debugtest + if(fp == 0){ + return false; + } cfg_print(d->var_cfg, fp); fclose(fp); return true; @@ -194,6 +207,7 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w } int Settings::getDeviceState( int intDeviceId ) const { + TelldusCore::MutexLocker locker(&mutex); if (d->var_cfg == 0) { return false; } @@ -209,6 +223,7 @@ int Settings::getDeviceState( int intDeviceId ) const { } std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { + TelldusCore::MutexLocker locker(&mutex); if (d->var_cfg == 0) { return false; } @@ -225,6 +240,7 @@ std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { } std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const { + //already locked if (d->cfg == 0) { return L""; } @@ -247,6 +263,7 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam } bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { + //already locked if (d->cfg == 0) { return false; } @@ -270,6 +287,7 @@ bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const } int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const { + //already locked if (d->cfg == 0) { return 0; } @@ -287,6 +305,7 @@ int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool para } bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { + //already locked if (d->cfg == 0) { return false; } From 0a2748f84b279151535bd8444dead0f5b118e018 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 27 Oct 2010 12:22:08 +0000 Subject: [PATCH 0474/2215] Reporting error when error in socket creation --- telldus-core/service/ConnectionListener_unix.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 75ea9483..89cb6ce3 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -7,6 +7,7 @@ #include #include +#include class ConnectionListener::PrivateData { public: @@ -75,6 +76,9 @@ void ConnectionListener::run(){ continue; } SOCKET_T clientSocket = accept(serverSocket, NULL, NULL); + if(clientSocket == -1){ + printf("error %i\n", errno); + } ConnectionListenerEventData *data = new ConnectionListenerEventData(); data->socket = new TelldusCore::Socket(clientSocket); From 7fe03d2dad982a0857b7150e190a0ae5086cc02f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 27 Oct 2010 12:24:25 +0000 Subject: [PATCH 0475/2215] Now closing client socket after use --- telldus-core/common/Socket_unix.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 924aef89..5e5025dc 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -32,6 +32,9 @@ Socket::Socket(SOCKET_T socket) } Socket::~Socket(void) { + if(d->socket){ + close(d->socket); + } delete d; } From 1c61acbecc2fcde52517d245e4104cdfdd06539f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 12:30:58 +0000 Subject: [PATCH 0476/2215] House and unit should be substracted with on in protocol risingsun codeswitch --- telldus-core/service/ProtocolRisingSun.cpp | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index decb034d..4068ba40 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -15,10 +15,10 @@ std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data return getStringCodeSwitch(method); } -std::string ProtocolRisingSun::getStringSelflearning(int method) { - int intHouse = this->getIntParameter(L"house", 1, 33554432)-1; - int intCode = this->getIntParameter(L"code", 1, 16)-1; - +std::string ProtocolRisingSun::getStringSelflearning(int method) { + int intHouse = this->getIntParameter(L"house", 1, 33554432)-1; + int intCode = this->getIntParameter(L"code", 1, 16)-1; + const char code_on[][7] = { "110110", "001110", "100110", "010110", "111001", "000101", "101001", "011001", @@ -78,23 +78,23 @@ std::string ProtocolRisingSun::getStringSelflearning(int method) { prefix.append("S"); strReturn.insert(0, prefix); strReturn.append(1, '+'); - return strReturn; -} - -std::string ProtocolRisingSun::getStringCodeSwitch(int method) { - std::string strReturn = "S.e"; - strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4))); - strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4))); + return strReturn; +} + +std::string ProtocolRisingSun::getStringCodeSwitch(int method) { + std::string strReturn = "S.e"; + strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4)-1)); + strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4)-1)); if (method == TELLSTICK_TURNON) { - strReturn.append("e..ee..ee..ee..e+"); - } else if (method == TELLSTICK_TURNOFF) { + strReturn.append("e..ee..ee..ee..e+"); + } else if (method == TELLSTICK_TURNOFF) { strReturn.append("e..ee..ee..e.e.e+"); } else { return ""; } return strReturn; - -} + +} std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) { From 99dfb8ec4a78b4d120c5f613e65bbcd17182663e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 12:55:12 +0000 Subject: [PATCH 0477/2215] Missed both prepending 'S' and appending '+' --- telldus-core/service/ProtocolUpm.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 3ee1931a..de090347 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -26,7 +26,7 @@ std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controlle code >>= 1; } strReturn.insert(0, START); //Startcode, first - + code = 0; if (method == TELLSTICK_TURNON) { code += 2; @@ -35,7 +35,7 @@ std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controlle } code <<= 2; code += intUnit; - + int check1 = 0, check2 = 0; for( size_t i = 0; i < 6; ++i ) { if (code & 1) { @@ -52,7 +52,7 @@ std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controlle } code >>= 1; } - + if (check1 % 2 == 0) { strReturn.append(B0); } else { @@ -63,6 +63,9 @@ std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controlle } else { strReturn.append(B1); } + + strReturn.insert(0, "S"); + strReturn.append("+"); return strReturn; } From 99d2be5270334b41fe9d12bfb48944d4000643ec Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 13:00:55 +0000 Subject: [PATCH 0478/2215] Translate correct housecode for X10 --- telldus-core/service/ProtocolX10.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index 45f23d74..d8922809 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -15,8 +15,15 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont std::string strReturn = reinterpret_cast(START_CODE); std::string strComplement = ""; - std::wstring strHouse = getStringParameter(L"house", L"A"); + std::wstring strHouse = getStringParameter(L"house", L"A"); int intHouse = strHouse[0] - L'A'; + if (intHouse < 0) { + intHouse = 0; + } else if (intHouse > 15) { + intHouse = 15; + } + //Translate it + intHouse = HOUSES[intHouse]; int intCode = getIntParameter(L"unit", 1, 16)-1; for( int i = 0; i < 4; ++i ) { @@ -31,7 +38,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont } strReturn.append( B0 ); strComplement.append( B1 ); - + if (intCode >= 8) { strReturn.append(B1); strComplement.append(B0); @@ -39,15 +46,15 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont strReturn.append(B0); strComplement.append(B1); } - + strReturn.append( B0 ); strComplement.append( B1 ); strReturn.append( B0 ); strComplement.append( B1 ); - + strReturn.append( strComplement ); strComplement = ""; - + strReturn.append( B0 ); strComplement.append( B1 ); @@ -58,7 +65,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont strReturn.append(B0); strComplement.append(B1); } - + if (method == TELLSTICK_TURNON) { strReturn.append(B0); strComplement.append(B1); @@ -68,7 +75,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont } else { return ""; } - + if (intCode & 1) { //Bit 0 of intCode strReturn.append(B1); strComplement.append(B0); @@ -76,7 +83,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont strReturn.append(B0); strComplement.append(B1); } - + if (intCode >> 1 & 1) { //Bit 1 of intCode strReturn.append(B1); strComplement.append(B0); From 1e856c989a4b12741994a3c5bdce806863616b74 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 13:37:39 +0000 Subject: [PATCH 0479/2215] Clear the buffer before each read --- telldus-core/service/TellStick_libftdi.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 8ba3e4a6..81703b44 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -51,6 +51,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & d->running = false; ftdi_init(&d->ftHandle); + ftdi_set_interface(&d->ftHandle, INTERFACE_ANY); int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str()); if (ret < 0) { @@ -126,7 +127,7 @@ void TellStick::processData( const std::string &data ) { void TellStick::run() { int dwBytesRead = 0; - unsigned char buf[100]; // = 0; + unsigned char buf[1024]; // = 0; pthread_mutex_init(&d->eh.eMutex, NULL); pthread_cond_init(&d->eh.eCondVar, NULL); @@ -142,8 +143,10 @@ void TellStick::run() { if (!d->running) { break; } - dwBytesRead = ftdi_read_data(&d->ftHandle, buf, 100); + memset(buf, 0, sizeof(buf)); + dwBytesRead = ftdi_read_data(&d->ftHandle, buf, sizeof(buf)); if (dwBytesRead < 1) { + //printf("No data, continue\n"); continue; } processData( reinterpret_cast(&buf) ); From 9e5308bbb45bcf7b8f367554fee2cc7cf400fc8a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 14:25:33 +0000 Subject: [PATCH 0480/2215] Added Linux version of debugLog --- telldus-core/common/common.h | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 08dc6413..d909a71c 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -28,21 +28,25 @@ inline void msleep( const int msec) { } inline void debuglog(const int intMessage, const std::string strMessage){ - - static bool firstRun = true; - std::ofstream file; - std::string filename("C:/log_locks.txt"); - if (firstRun) { - file.open(filename.c_str(), std::ios::out); - firstRun = false; - } else { - file.open(filename.c_str(), std::ios::out | std::ios::app); - } - - file << intMessage << " - " << strMessage << "\n"; - file.flush(); - file.close(); +#ifdef _WINDOWS + static bool firstRun = true; + std::ofstream file; + std::string filename("C:/log_locks.txt"); + if (firstRun) { + file.open(filename.c_str(), std::ios::out); + firstRun = false; + } else { + file.open(filename.c_str(), std::ios::out | std::ios::app); + } + file << "[" << GetCurrentThreadId() << "] " << intMessage << " - " << strMessage << "\n"; + file.flush(); + file.close(); + +#else + pthread_t thread = pthread_self(); + printf("[%i] %i - %s\n", (int)thread, intMessage, strMessage.c_str()); +#endif } inline char *wrapStdString( const std::string &string) { @@ -57,4 +61,4 @@ inline char *wrapStdString( const std::string &string) { inline char *wrapStdWstring( const std::wstring &wstring) { return wrapStdString(TelldusCore::wideToString(wstring)); -} \ No newline at end of file +} From d0e006c4811002e5ca45f422ded93c17df92972e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 14:26:06 +0000 Subject: [PATCH 0481/2215] LoggedMutex now works on Linux --- telldus-core/common/Mutex.cpp | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index 48c277a7..ca90ecfc 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: Thread // -// Description: +// Description: // // // Author: Micke Prag , (C) 2009 @@ -45,7 +45,7 @@ Mutex::~Mutex() { #endif delete d; } - + void Mutex::lock() { #ifdef _WINDOWS WaitForSingleObject(d->mutex, INFINITE); @@ -62,29 +62,21 @@ void Mutex::unlock() { #endif } - + void LoggedMutex::lock() { -#ifdef _WINDOWS - debuglog(GetCurrentThreadId(), "Locking"); -#endif + debuglog(0, "Locking"); Mutex::lock(); -#ifdef _WINDOWS - debuglog(GetCurrentThreadId(), "Locked"); -#endif + debuglog(0, "Locked"); } void LoggedMutex::unlock() { -#ifdef _WINDOWS - debuglog(GetCurrentThreadId(), "Unlocking"); -#endif + debuglog(0, "Unlocking"); Mutex::unlock(); -#ifdef _WINDOWS - debuglog(GetCurrentThreadId(), "Unlocked"); -#endif + debuglog(0, "Unlocked"); } MutexLocker::MutexLocker(Mutex *m) - :mutex(m) + :mutex(m) { mutex->lock(); } From 287802d527ced4f7831d0afb9d66ec97e36c832b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 14:26:43 +0000 Subject: [PATCH 0482/2215] The lock in send was not properly locked --- telldus-core/service/TellStick_libftdi.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 81703b44..d2e8f4d1 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -146,7 +146,6 @@ void TellStick::run() { memset(buf, 0, sizeof(buf)); dwBytesRead = ftdi_read_data(&d->ftHandle, buf, sizeof(buf)); if (dwBytesRead < 1) { - //printf("No data, continue\n"); continue; } processData( reinterpret_cast(&buf) ); @@ -165,7 +164,7 @@ int TellStick::send( const std::string &strMessage ) { //This lock does two things // 1 Prevents two calls from different threads to this function // 2 Prevents our running thread from receiving the data we are interested in here - TelldusCore::MutexLocker(&d->mutex); + TelldusCore::MutexLocker locker(&d->mutex); int ret; ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ; From aad55f53078f682f65db845f6608cebb628901ba Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 14:31:47 +0000 Subject: [PATCH 0483/2215] The lock in send was not properly locked --- telldus-core/service/TellStick_ftd2xx.cpp | 33 ++++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 1ffd65c4..d357c9ff 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: TellStick // -// Description: +// Description: // // // Author: Micke Prag , (C) 2009 @@ -14,6 +14,7 @@ #include "Strings.h" #include "../client/telldus-core.h" #include +#include #include "ftd2xx.h" @@ -36,7 +37,7 @@ public: #endif }; -TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &td ) +TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &td ) :Controller(controllerId, event) { d = new PrivateData; @@ -67,12 +68,12 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); FT_SetTimeouts(d->ftHandle,5000,0); } - + if (d->open) { if (td.pid == 0x0C31) { setBaud(9600); } else { - setBaud(4800); + setBaud(4800); } this->start(); } @@ -152,7 +153,7 @@ void TellStick::run() { pthread_cond_wait(&d->eh.eCondVar, &d->eh.eMutex); pthread_mutex_unlock(&d->eh.eMutex); #endif - + TelldusCore::MutexLocker locker(&d->mutex); if (!d->running) { break; @@ -179,7 +180,7 @@ int TellStick::send( const std::string &strMessage ) { //This lock does two things // 1 Prevents two calls from different threads to this function // 2 Prevents our running thread from receiving the data we are interested in here - TelldusCore::MutexLocker(&d->mutex); + TelldusCore::MutexLocker locker(&d->mutex); char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); #ifdef _WINDOWS @@ -255,12 +256,12 @@ std::list TellStick::findAll() { } return tellstick; - + } std::list TellStick::findAllByVIDPID( int vid, int pid ) { std::list retval; - + FT_HANDLE fthHandle = 0; FT_STATUS ftStatus = FT_OK; DWORD dwNumberOfDevices = 0; @@ -273,20 +274,20 @@ std::list TellStick::findAllByVIDPID( int vid, int pid ) { if (ftStatus != FT_OK) { return retval; } - for (int i = 0; i < (int)dwNumberOfDevices; i++) { + for (int i = 0; i < (int)dwNumberOfDevices; i++) { FT_PROGRAM_DATA pData; - char ManufacturerBuf[32]; - char ManufacturerIdBuf[16]; - char DescriptionBuf[64]; - char SerialNumberBuf[16]; + char ManufacturerBuf[32]; + char ManufacturerIdBuf[16]; + char DescriptionBuf[64]; + char SerialNumberBuf[16]; pData.Signature1 = 0x00000000; pData.Signature2 = 0xffffffff; pData.Version = 0x00000002; // EEPROM structure with FT232R extensions - pData.Manufacturer = ManufacturerBuf; + pData.Manufacturer = ManufacturerBuf; pData.ManufacturerId = ManufacturerIdBuf; - pData.Description = DescriptionBuf; - pData.SerialNumber = SerialNumberBuf; + pData.Description = DescriptionBuf; + pData.SerialNumber = SerialNumberBuf; ftStatus = FT_Open(i, &fthHandle); ftStatus = FT_EE_Read(fthHandle, &pData); From c59ec99c6d9f85fe11dd9c4d5d70298f44922399 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 15:11:58 +0000 Subject: [PATCH 0484/2215] Added an extra scope so we don't delete the d variable while we have a MutexLocker locking anything inside the d variable --- telldus-core/service/DeviceManager.cpp | 53 +++++++++++++------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 08dc007e..aec2b454 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -28,11 +28,12 @@ DeviceManager::DeviceManager(ControllerManager *controllerManager, Event *device } DeviceManager::~DeviceManager(void) { - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { - {TelldusCore::MutexLocker deviceLocker(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere - delete(it->second); + { + TelldusCore::MutexLocker deviceListLocker(&d->lock); + for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { + {TelldusCore::MutexLocker deviceLocker(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere + delete(it->second); + } } delete d; } @@ -40,7 +41,7 @@ DeviceManager::~DeviceManager(void) { void DeviceManager::fillDevices(){ int numberOfDevices = d->set.getNumberOfDevices(); TelldusCore::MutexLocker deviceListLocker(&d->lock); - + for (int i = 0; i < numberOfDevices; ++i) { int id = d->set.getDeviceId(i); d->devices[id] = new Device(id); @@ -72,7 +73,7 @@ int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ } int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, std::wstring value) -{ +{ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -105,7 +106,7 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ //devices locked TelldusCore::MutexLocker deviceListLocker(&d->lock); - + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -120,7 +121,7 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ } std::wstring DeviceManager::getDeviceModel(int deviceId){ - + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; @@ -134,7 +135,7 @@ std::wstring DeviceManager::getDeviceModel(int deviceId){ } int DeviceManager::setDeviceModel(int deviceId, std::wstring model) -{ +{ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -153,7 +154,7 @@ int DeviceManager::setDeviceModel(int deviceId, std::wstring model) } std::wstring DeviceManager::getDeviceName(int deviceId){ - + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; @@ -167,7 +168,7 @@ std::wstring DeviceManager::getDeviceName(int deviceId){ } int DeviceManager::setDeviceName(int deviceId, std::wstring name){ - + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -181,12 +182,12 @@ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ else{ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } - + return TELLSTICK_SUCCESS; } std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, std::wstring defaultValue){ - + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return defaultValue; @@ -203,7 +204,7 @@ std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, } int DeviceManager::setDeviceParameter(int deviceId, std::wstring name, std::wstring value) -{ +{ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -222,7 +223,7 @@ int DeviceManager::setDeviceParameter(int deviceId, std::wstring name, std::wstr } std::wstring DeviceManager::getDeviceProtocol(int deviceId){ - + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; @@ -236,7 +237,7 @@ std::wstring DeviceManager::getDeviceProtocol(int deviceId){ } int DeviceManager::setDeviceProtocol(int deviceId, std::wstring protocol) -{ +{ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -260,7 +261,7 @@ int DeviceManager::getNumberOfDevices(){ } int DeviceManager::addDevice(){ - + int id = d->set.addDevice(); if(id == -1){ return TELLSTICK_ERROR_UNKNOWN; @@ -284,9 +285,9 @@ int DeviceManager::getDeviceType(int deviceId){ } int DeviceManager::getPreferredControllerId(int deviceId){ - + TelldusCore::MutexLocker deviceListLocker(&d->lock); - + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -310,10 +311,10 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ Device *device = 0; //On the stack and will be released if we have a device lock. std::auto_ptr deviceLocker(0); - { + { //devicelist locked TelldusCore::MutexLocker deviceListLocker(&d->lock); - + if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -325,7 +326,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); device = it->second; } //devicelist unlocked - + Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); if(controller){ int retval = device->doAction(action, data, controller); @@ -343,7 +344,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } int DeviceManager::removeDevice(int deviceId){ - + Device *device = 0; { if(!d->set.removeDevice(deviceId)){ //remove from register/settings @@ -404,14 +405,14 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData if (this->triggerDeviceStateChange(it->first, msg.method(), L"")) { d->set.setDeviceState(it->first, msg.method(), L""); - it->second->setLastSentCommand(msg.method(), L""); + it->second->setLastSentCommand(msg.method(), L""); } break; } } int DeviceManager::sendRawCommand(std::wstring command, int reserved){ - + Controller *controller = d->controllerManager->getBestControllerById(-1); if(controller){ return controller->send(TelldusCore::wideToString(command)); From d7dd125037c3d5185f1e60143e95c7c8378876dd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 15:13:05 +0000 Subject: [PATCH 0485/2215] Added message at the end of our execution --- telldus-core/service/main_unix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 2bd30833..24b34681 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -15,5 +15,6 @@ int main(int argc, char **argv) { signal(SIGINT, shutdownHandler); tm.start(); + printf("telldusd stopped gracefully\n"); return 0; } From af19b80d2e44a5b024e97c59a332b717bbde84cd Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 27 Oct 2010 15:20:46 +0000 Subject: [PATCH 0486/2215] List with multiple events in linux eventhandler --- telldus-core/service/EventHandler.h | 1 + telldus-core/service/EventHandler_unix.cpp | 32 ++++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index aa53e44d..40226c9b 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -20,6 +20,7 @@ protected: private: class PrivateData; PrivateData *d; + bool listIsSignalled(); friend class Event; }; diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index d74861fb..2bde8f1c 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -1,6 +1,8 @@ #include "EventHandler.h" #include "Event.h" +#include "Mutex.h" #include "Thread.h" +#include #include #include @@ -8,12 +10,12 @@ class EventHandler::PrivateData { public: pthread_cond_t event; pthread_mutex_t mutex; - bool hasEvent; + std::list eventList; + TelldusCore::Mutex listMutex; }; EventHandler::EventHandler() { d = new PrivateData; - d->hasEvent = false; pthread_cond_init(&d->event, NULL); pthread_mutex_init(&d->mutex, NULL); } @@ -21,32 +23,52 @@ EventHandler::EventHandler() { EventHandler::~EventHandler(void) { pthread_mutex_destroy(&d->mutex); pthread_cond_destroy(&d->event); + + std::list::const_iterator it = d->eventList.begin(); + for(; it != d->eventList.end(); ++it) { + delete(*it); + } + delete d; } Event *EventHandler::addEvent() { Event *event = new Event(this); + TelldusCore::MutexLocker locker(&d->listMutex); + d->eventList.push_back(event); return event; } +bool EventHandler::listIsSignalled(){ + TelldusCore::MutexLocker locker(&d->listMutex); + + std::list::const_iterator it = d->eventList.begin(); + for(; it != d->eventList.end(); ++it) { + if((*it)->isSignaled()){ + return true; + } + } + return false; +} + bool EventHandler::removeEvent(EventBase *event) { + TelldusCore::MutexLocker locker(&d->listMutex); + d->eventList.remove((Event*)event); return true; } void EventHandler::signal(Event *event) { pthread_mutex_lock(&d->mutex); //event->setSignaled(); - d->hasEvent = true; pthread_cond_signal(&d->event); pthread_mutex_unlock(&d->mutex); } bool EventHandler::waitForAny() { pthread_mutex_lock(&d->mutex); - while(!d->hasEvent) { + while(!listIsSignalled()) { pthread_cond_wait(&d->event, &d->mutex); } - d->hasEvent = false; pthread_mutex_unlock(&d->mutex); return true; From 144083dd6280d612046d3ed786d8c365331a4782 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Oct 2010 15:58:15 +0000 Subject: [PATCH 0487/2215] Removed unused event --- telldus-core/service/TelldusMain.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 0c89fe54..f41f0891 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -45,17 +45,16 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { void TelldusMain::start(void) { Event *clientEvent = d->eventHandler.addEvent(); - Event *updateEvent = d->eventHandler.addEvent(); std::auto_ptr dataEvent(d->eventHandler.addEvent()); - + ControllerManager controllerManager(dataEvent.get()); EventUpdateManager eventUpdateManager; Event *deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); eventUpdateManager.start(); DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); - + ConnectionListener clientListener(L"TelldusClient", clientEvent); - + std::list clientCommunicationHandlerList; std::auto_ptr handlerEvent(d->eventHandler.addEvent()); @@ -99,7 +98,7 @@ void TelldusMain::start(void) { if ((*it)->isDone()){ delete *it; it = clientCommunicationHandlerList.erase(it); - + } else { ++it; } From bb32eb01159b73c250ebeee60dc9729d2e1e9c4a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 06:49:29 +0000 Subject: [PATCH 0488/2215] Class EventData lacked virtual destructor --- telldus-core/service/Event.cpp | 5 ++++- telldus-core/service/Event.h | 9 +++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index e6209f86..cd117e0e 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -4,6 +4,9 @@ #include +EventData::~EventData() { +} + bool EventData::isValid() const { return false; }; @@ -84,4 +87,4 @@ EventData *EventBase::takeSignal() { return 0; } return data; -} \ No newline at end of file +} diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 698116bb..cbd9fe11 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -13,6 +13,7 @@ class EventHandler; class EventData { public: + virtual ~EventData(); virtual bool isValid() const; }; @@ -24,7 +25,7 @@ public: class EventBase { public: virtual ~EventBase(); - + void popSignal(); bool isSignaled(); void signal(); @@ -52,12 +53,12 @@ protected: EVENT_T retrieveNative(); virtual void clearSignal(); virtual void sendSignal(); - + private: class PrivateData; PrivateData *d; - -friend class EventHandler; + +friend class EventHandler; }; #endif //EVENT_H From cd7cdd15f21322218653a63c884efc006718eb01 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 07:53:45 +0000 Subject: [PATCH 0489/2215] The threads library is required --- telldus-core/service/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 622e88cd..08ea9608 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -56,7 +56,7 @@ SET( telldus-service_HDRS TellStick.h EventUpdateManager.h ) -FIND_PACKAGE(Threads) +FIND_PACKAGE(Threads REQUIRED) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) INCLUDE_DIRECTORIES( From a1d0f1401adbf32c96572967f4a84452eceaf305 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 08:08:12 +0000 Subject: [PATCH 0490/2215] Implemented EventData as shared pointers. We are now dependent on tr1 --- telldus-core/service/Event.cpp | 24 ++++++--------------- telldus-core/service/Event.h | 5 ++++- telldus-core/service/EventUpdateManager.cpp | 20 ++++++++--------- telldus-core/service/TelldusMain.cpp | 12 +++++------ 4 files changed, 25 insertions(+), 36 deletions(-) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index cd117e0e..d83d8445 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -19,7 +19,7 @@ class EventBase::PrivateData { public: TelldusCore::Mutex mutex; EventHandler *handler; - std::list eventDataList; + std::list eventDataList; }; EventBase::EventBase(EventHandler *handler) { @@ -31,11 +31,6 @@ EventBase::~EventBase(void) { if (d->handler) { d->handler->removeEvent(this); } - //If we have signals left, make sure we delete the data - std::list::const_iterator it = d->eventDataList.begin(); - for(; it != d->eventDataList.end(); ++it) { - delete(*it); - } delete d; } @@ -45,10 +40,7 @@ void EventBase::clearHandler() { } void EventBase::popSignal() { - EventData *data = this->takeSignal(); - if (data) { - delete data; - } + this->takeSignal(); } EventHandler *EventBase::handler() const { @@ -67,24 +59,20 @@ void EventBase::signal() { void EventBase::signal(EventData *eventData) { { TelldusCore::MutexLocker locker(&d->mutex); - d->eventDataList.push_back(eventData); + d->eventDataList.push_back(EventDataRef(eventData)); } sendSignal(); } -EventData *EventBase::takeSignal() { +EventDataRef EventBase::takeSignal() { TelldusCore::MutexLocker locker(&d->mutex); if (d->eventDataList.size() == 0) { - return 0; + return EventDataRef(new EventData()); } - EventData *data = d->eventDataList.front(); + EventDataRef data = d->eventDataList.front(); d->eventDataList.pop_front(); if (d->eventDataList.size() == 0) { this->clearSignal(); } - if (!data->isValid()) { - delete data; - return 0; - } return data; } diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index cbd9fe11..db285b8f 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -3,6 +3,7 @@ class EventHandler; #include "Thread.h" +#include #ifdef _WINDOWS #include @@ -22,6 +23,8 @@ public: virtual bool isValid() const; }; +typedef std::tr1::shared_ptr EventDataRef; + class EventBase { public: virtual ~EventBase(); @@ -30,7 +33,7 @@ public: bool isSignaled(); void signal(); virtual void signal(EventData *); - EventData *takeSignal(); + EventDataRef takeSignal(); protected: EventBase(EventHandler *handler); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 20e7de8a..4c84fc46 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -34,11 +34,11 @@ EventUpdateManager::~EventUpdateManager(void) { delete d->stopEvent; delete d->updateEvent; delete d->eventUpdateClientListener; - + for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) { delete(*it); } - + delete d; } @@ -56,7 +56,7 @@ void EventUpdateManager::run(){ if(d->clientConnectEvent->isSignaled()){ //new client added - std::auto_ptr eventData(d->clientConnectEvent->takeSignal()); + EventDataRef eventData = d->clientConnectEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventData.get()); if(data){ d->clients.push_back(data->socket); @@ -64,7 +64,7 @@ void EventUpdateManager::run(){ } else if(d->updateEvent->isSignaled()){ //device event, signal all clients - std::auto_ptr eventData(d->updateEvent->takeSignal()); + EventDataRef eventData = d->updateEvent->takeSignal(); EventUpdateData *data = reinterpret_cast(eventData.get()); if(data){ sendMessageToClients(data); @@ -74,13 +74,13 @@ void EventUpdateManager::run(){ } void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ - + for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();){ - + if((*it)->isConnected()){ - + TelldusCore::Message msg; - + if(data->messageType == L"TDDeviceEvent"){ msg.addArgument("TDDeviceEvent"); msg.addArgument(data->deviceId); @@ -100,7 +100,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ } (*it)->write(msg); - + it++; } else{ @@ -109,4 +109,4 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ it = d->clients.erase(it); } } -} \ No newline at end of file +} diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index f41f0891..c47d4659 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -65,27 +65,25 @@ void TelldusMain::start(void) { } if (clientEvent->isSignaled()) { //New client connection - EventData *eventData = clientEvent->takeSignal(); - ConnectionListenerEventData *data = reinterpret_cast(eventData); + EventDataRef eventDataRef = clientEvent->takeSignal(); + ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent.get(), &deviceManager, deviceUpdateEvent); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } - delete eventData; } if (d->deviceChangeEvent->isSignaled()) { - EventData *eventData = d->deviceChangeEvent->takeSignal(); - DeviceEventData *data = reinterpret_cast(eventData); + EventDataRef eventDataRef = d->deviceChangeEvent->takeSignal(); + DeviceEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, data->inserted); } - delete eventData; } if (dataEvent->isSignaled()) { - std::auto_ptr eventData(dataEvent->takeSignal()); + EventDataRef eventData = dataEvent->takeSignal(); ControllerEventData *data = reinterpret_cast(eventData.get()); if (data) { deviceManager.handleControllerMessage(*data); From 41c763cbd49d8f8bab86c88328569939befc4411 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 08:45:17 +0000 Subject: [PATCH 0491/2215] Converted Event pointers to smart pointers instead --- .../service/ClientCommunicationHandler.cpp | 250 +++++++++--------- .../service/ClientCommunicationHandler.h | 58 ++-- telldus-core/service/ConnectionListener.h | 2 +- .../service/ConnectionListener_unix.cpp | 11 +- telldus-core/service/DeviceManager.cpp | 4 +- telldus-core/service/DeviceManager.h | 90 +++---- telldus-core/service/Event.h | 2 + telldus-core/service/EventHandler.h | 9 +- telldus-core/service/EventHandler_unix.cpp | 27 +- telldus-core/service/EventUpdateManager.cpp | 6 +- telldus-core/service/EventUpdateManager.h | 70 ++--- telldus-core/service/TelldusMain.cpp | 14 +- 12 files changed, 272 insertions(+), 271 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 6745d1bd..330086f4 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -2,12 +2,12 @@ #include "Message.h" #include "Strings.h" -#include - +#include + class ClientCommunicationHandler::PrivateData { public: TelldusCore::Socket *clientSocket; - Event *event, *deviceUpdateEvent; + EventRef event, deviceUpdateEvent; bool done; DeviceManager *deviceManager; }; @@ -16,7 +16,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(){ } -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, Event *deviceUpdateEvent) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, EventRef event, DeviceManager *deviceManager, EventRef deviceUpdateEvent) :Thread() { d = new PrivateData; @@ -25,7 +25,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie d->done = false; d->deviceManager = deviceManager; d->deviceUpdateEvent = deviceUpdateEvent; - + } ClientCommunicationHandler::~ClientCommunicationHandler(void) @@ -37,16 +37,16 @@ ClientCommunicationHandler::~ClientCommunicationHandler(void) void ClientCommunicationHandler::run(){ //run thread - + std::wstring clientMessage = d->clientSocket->read(2000); int intReturn; std::wstring strReturn; strReturn = L""; parseMessage(clientMessage, &intReturn, &strReturn); - + TelldusCore::Message msg; - + if(strReturn == L""){ msg.addArgument(intReturn); } @@ -72,136 +72,136 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*wstringReturn) = L""; std::wstring msg(clientMessage); //Copy std::wstring function(TelldusCore::Message::takeString(&msg)); - - if (function == L"tdTurnOn") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); - } else if (function == L"tdTurnOff") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0); - - } else if (function == L"tdBell") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0); - - } else if (function == L"tdDim") { - int deviceId = TelldusCore::Message::takeInt(&msg); - int level = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, level); - - } else if (function == L"tdLearn") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); - - } else if (function == L"tdLastSentCommand") { - int deviceId = TelldusCore::Message::takeInt(&msg); - int methodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceLastSentCommand(deviceId, methodsSupported); - - } else if (function == L"tdLastSentValue") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceStateValue(deviceId); - + + if (function == L"tdTurnOn") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); + } else if (function == L"tdTurnOff") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0); + + } else if (function == L"tdBell") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0); + + } else if (function == L"tdDim") { + int deviceId = TelldusCore::Message::takeInt(&msg); + int level = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, level); + + } else if (function == L"tdLearn") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); + + } else if (function == L"tdLastSentCommand") { + int deviceId = TelldusCore::Message::takeInt(&msg); + int methodsSupported = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceLastSentCommand(deviceId, methodsSupported); + + } else if (function == L"tdLastSentValue") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceStateValue(deviceId); + } else if(function == L"tdGetNumberOfDevices"){ - (*intReturn) = d->deviceManager->getNumberOfDevices(); - + (*intReturn) = d->deviceManager->getNumberOfDevices(); + } else if (function == L"tdGetDeviceId") { - int deviceIndex = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceId(deviceIndex); - - } else if (function == L"tdGetDeviceType") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceType(deviceId); - - } else if (function == L"tdGetName") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceName(deviceId); - - } else if (function == L"tdSetName") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - (*intReturn) = d->deviceManager->setDeviceName(deviceId, name); - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME); - - } else if (function == L"tdGetProtocol") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceProtocol(deviceId); - - } else if (function == L"tdSetProtocol") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring protocol = TelldusCore::Message::takeString(&msg); - (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); - - } else if (function == L"tdGetModel") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceModel(deviceId); - - } else if (function == L"tdSetModel") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring model = TelldusCore::Message::takeString(&msg); - (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); - - } else if (function == L"tdGetDeviceParameter") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - std::wstring defaultValue = TelldusCore::Message::takeString(&msg); - (*wstringReturn) = d->deviceManager->getDeviceParameter(deviceId, name, defaultValue); - - } else if (function == L"tdSetDeviceParameter") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - std::wstring value = TelldusCore::Message::takeString(&msg); - (*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value); - - } else if (function == L"tdAddDevice") { - (*intReturn) = d->deviceManager->addDevice(); - if((*intReturn) >= 0){ - sendDeviceSignal((*intReturn), TELLSTICK_DEVICE_ADDED, 0); - } - - } else if (function == L"tdRemoveDevice") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->removeDevice(deviceId); - if((*intReturn) == TELLSTICK_DEVICE_REMOVED){ - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0); - } - - } else if (function == L"tdMethods") { - int deviceId = TelldusCore::Message::takeInt(&msg); - int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); - - } else if (function == L"tdSendRawCommand") { - std::wstring command = TelldusCore::Message::takeString(&msg); - int reserved = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->sendRawCommand(command, reserved); + int deviceIndex = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceId(deviceIndex); + + } else if (function == L"tdGetDeviceType") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceType(deviceId); + + } else if (function == L"tdGetName") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceName(deviceId); + + } else if (function == L"tdSetName") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + (*intReturn) = d->deviceManager->setDeviceName(deviceId, name); + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME); + + } else if (function == L"tdGetProtocol") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceProtocol(deviceId); + + } else if (function == L"tdSetProtocol") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring protocol = TelldusCore::Message::takeString(&msg); + (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); + + } else if (function == L"tdGetModel") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceModel(deviceId); + + } else if (function == L"tdSetModel") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring model = TelldusCore::Message::takeString(&msg); + (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); + + } else if (function == L"tdGetDeviceParameter") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring defaultValue = TelldusCore::Message::takeString(&msg); + (*wstringReturn) = d->deviceManager->getDeviceParameter(deviceId, name, defaultValue); + + } else if (function == L"tdSetDeviceParameter") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring value = TelldusCore::Message::takeString(&msg); + (*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value); + + } else if (function == L"tdAddDevice") { + (*intReturn) = d->deviceManager->addDevice(); + if((*intReturn) >= 0){ + sendDeviceSignal((*intReturn), TELLSTICK_DEVICE_ADDED, 0); + } + + } else if (function == L"tdRemoveDevice") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->removeDevice(deviceId); + if((*intReturn) == TELLSTICK_DEVICE_REMOVED){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0); + } + + } else if (function == L"tdMethods") { + int deviceId = TelldusCore::Message::takeInt(&msg); + int intMethodsSupported = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); + + } else if (function == L"tdSendRawCommand") { + std::wstring command = TelldusCore::Message::takeString(&msg); + int reserved = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->sendRawCommand(command, reserved); EventUpdateData *eventData = new EventUpdateData(); eventData->messageType = L"TDRawDeviceEvent"; eventData->controllerId = -1; eventData->eventValue = command; - d->deviceUpdateEvent->signal(eventData); - - } else if (function == L"tdConnectTellStickController") { - int vid = TelldusCore::Message::takeInt(&msg); - int pid = TelldusCore::Message::takeInt(&msg); - std::wstring serial = TelldusCore::Message::takeString(&msg); - d->deviceManager->connectTellStickController(vid, pid, serial); - } else if (function == L"tdDisconnectTellStickController") { - int vid = TelldusCore::Message::takeInt(&msg); - int pid = TelldusCore::Message::takeInt(&msg); - std::wstring serial = TelldusCore::Message::takeString(&msg); - d->deviceManager->disconnectTellStickController(vid, pid, serial); - } + d->deviceUpdateEvent->signal(eventData); + + } else if (function == L"tdConnectTellStickController") { + int vid = TelldusCore::Message::takeInt(&msg); + int pid = TelldusCore::Message::takeInt(&msg); + std::wstring serial = TelldusCore::Message::takeString(&msg); + d->deviceManager->connectTellStickController(vid, pid, serial); + } else if (function == L"tdDisconnectTellStickController") { + int vid = TelldusCore::Message::takeInt(&msg); + int pid = TelldusCore::Message::takeInt(&msg); + std::wstring serial = TelldusCore::Message::takeString(&msg); + d->deviceManager->disconnectTellStickController(vid, pid, serial); + } else{ (*intReturn) = TELLSTICK_ERROR_UNKNOWN; } } void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType){ - + EventUpdateData *eventData = new EventUpdateData(); eventData->messageType = L"TDDeviceChangeEvent"; eventData->deviceId = deviceId; diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 65fa31f1..e05c2000 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -1,30 +1,30 @@ #ifndef CLIENTCOMMUNICATIONHANDLER_H -#define CLIENTCOMMUNICATIONHANDLER_H - -#include -#include "Thread.h" -#include "Socket.h" -#include "Event.h" -#include "DeviceManager.h" -#include "ControllerManager.h" - -class ClientCommunicationHandler : public TelldusCore::Thread -{ -public: - ClientCommunicationHandler(); - ClientCommunicationHandler(TelldusCore::Socket *clientSocket, Event *event, DeviceManager *deviceManager, Event *deviceUpdateEvent); - ~ClientCommunicationHandler(void); - - bool isDone(); - -protected: - void run(); - -private: - class PrivateData; - PrivateData *d; - void parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn); - void sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType); -}; - -#endif //CLIENTCOMMUNICATIONHANDLER_H \ No newline at end of file +#define CLIENTCOMMUNICATIONHANDLER_H + +#include +#include "Thread.h" +#include "Socket.h" +#include "Event.h" +#include "DeviceManager.h" +#include "ControllerManager.h" + +class ClientCommunicationHandler : public TelldusCore::Thread +{ +public: + ClientCommunicationHandler(); + ClientCommunicationHandler(TelldusCore::Socket *clientSocket, EventRef event, DeviceManager *deviceManager, EventRef deviceUpdateEvent); + ~ClientCommunicationHandler(void); + + bool isDone(); + +protected: + void run(); + +private: + class PrivateData; + PrivateData *d; + void parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn); + void sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType); +}; + +#endif //CLIENTCOMMUNICATIONHANDLER_H diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index 410ef36c..e92252aa 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -17,7 +17,7 @@ public: class ConnectionListener : public TelldusCore::Thread { public: - ConnectionListener(const std::wstring &name, Event *waitEvent); + ConnectionListener(const std::wstring &name, EventRef waitEvent); virtual ~ConnectionListener(void); protected: diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 89cb6ce3..83f2c2a2 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -11,16 +11,16 @@ class ConnectionListener::PrivateData { public: - Event *waitEvent; + EventRef waitEvent; std::string name; bool running; }; -ConnectionListener::ConnectionListener(const std::wstring &name, Event *waitEvent) +ConnectionListener::ConnectionListener(const std::wstring &name, EventRef waitEvent) { d = new PrivateData; d->waitEvent = waitEvent; - + d->name = "/tmp/" + std::string(name.begin(), name.end()); d->running = true; @@ -30,7 +30,6 @@ ConnectionListener::ConnectionListener(const std::wstring &name, Event *waitEven ConnectionListener::~ConnectionListener(void) { d->running = false; this->wait(); - delete d->waitEvent; delete d; } @@ -58,7 +57,7 @@ void ConnectionListener::run(){ fd_set infds; FD_ZERO(&infds); FD_SET(serverSocket, &infds); - + while(d->running) { tv.tv_sec = 5; @@ -77,7 +76,7 @@ void ConnectionListener::run(){ } SOCKET_T clientSocket = accept(serverSocket, NULL, NULL); if(clientSocket == -1){ - printf("error %i\n", errno); + printf("error %i\n", errno); } ConnectionListenerEventData *data = new ConnectionListenerEventData(); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index aec2b454..124036c5 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -17,10 +17,10 @@ public: Settings set; TelldusCore::Mutex lock; ControllerManager *controllerManager; - Event *deviceUpdateEvent; + EventRef deviceUpdateEvent; }; -DeviceManager::DeviceManager(ControllerManager *controllerManager, Event *deviceUpdateEvent){ +DeviceManager::DeviceManager(ControllerManager *controllerManager, EventRef deviceUpdateEvent){ d = new PrivateData; d->controllerManager = controllerManager; d->deviceUpdateEvent = deviceUpdateEvent; diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 88ee4d67..b68f73a1 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -1,46 +1,46 @@ #ifndef DEVICEMANAGER_H -#define DEVICEMANAGER_H - -#include "Device.h" -#include "ControllerManager.h" -#include "EventUpdateManager.h" - -class DeviceManager -{ -public: - DeviceManager(ControllerManager *controllerManager, Event *deviceUpdateEvent); - ~DeviceManager(void); - int getNumberOfDevices(void); - int addDevice(); - void connectTellStickController(int vid, int pid, std::wstring serial); - void disconnectTellStickController(int vid, int pid, std::wstring serial); - int getDeviceId(int deviceIndex); - int getDeviceLastSentCommand(int deviceId, int methodsSupported); - int setDeviceLastSentCommand(int deviceId, int command, std::wstring value); - int getDeviceMethods(int deviceId, int methodsSupported); - std::wstring getDeviceModel(int deviceId); - int setDeviceModel(int deviceId, std::wstring model); - std::wstring getDeviceName(int deviceId); - int setDeviceName(int deviceId, std::wstring name); - std::wstring getDeviceParameter(int deviceId, std::wstring name, std::wstring defauleValue); - int setDeviceParameter(int deviceId, std::wstring name, std::wstring value); - std::wstring getDeviceProtocol(int deviceId); - int setDeviceProtocol(int deviceId, std::wstring name); - std::wstring getDeviceStateValue(int deviceId); - int getDeviceType(int deviceId); - int getPreferredControllerId(int deviceId); - int doAction(int deviceId, int action, unsigned char data); - int removeDevice(int deviceId); - int sendRawCommand(std::wstring command, int reserved); - - void handleControllerMessage(const ControllerEventData &event); - -private: - bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); - void fillDevices(void); - - class PrivateData; - PrivateData *d; -}; - -#endif //DEVICEMANAGER_H \ No newline at end of file +#define DEVICEMANAGER_H + +#include "Device.h" +#include "ControllerManager.h" +#include "EventUpdateManager.h" + +class DeviceManager +{ +public: + DeviceManager(ControllerManager *controllerManager, EventRef deviceUpdateEvent); + ~DeviceManager(void); + int getNumberOfDevices(void); + int addDevice(); + void connectTellStickController(int vid, int pid, std::wstring serial); + void disconnectTellStickController(int vid, int pid, std::wstring serial); + int getDeviceId(int deviceIndex); + int getDeviceLastSentCommand(int deviceId, int methodsSupported); + int setDeviceLastSentCommand(int deviceId, int command, std::wstring value); + int getDeviceMethods(int deviceId, int methodsSupported); + std::wstring getDeviceModel(int deviceId); + int setDeviceModel(int deviceId, std::wstring model); + std::wstring getDeviceName(int deviceId); + int setDeviceName(int deviceId, std::wstring name); + std::wstring getDeviceParameter(int deviceId, std::wstring name, std::wstring defauleValue); + int setDeviceParameter(int deviceId, std::wstring name, std::wstring value); + std::wstring getDeviceProtocol(int deviceId); + int setDeviceProtocol(int deviceId, std::wstring name); + std::wstring getDeviceStateValue(int deviceId); + int getDeviceType(int deviceId); + int getPreferredControllerId(int deviceId); + int doAction(int deviceId, int action, unsigned char data); + int removeDevice(int deviceId); + int sendRawCommand(std::wstring command, int reserved); + + void handleControllerMessage(const ControllerEventData &event); + +private: + bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); + void fillDevices(void); + + class PrivateData; + PrivateData *d; +}; + +#endif //DEVICEMANAGER_H diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index db285b8f..3408aed4 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -64,4 +64,6 @@ private: friend class EventHandler; }; +typedef std::tr1::shared_ptr EventRef; + #endif //EVENT_H diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index 40226c9b..61c3d80a 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -1,17 +1,16 @@ #ifndef EVENTHANDLER_H #define EVENTHANDLER_H -class Event; -class EventBase; +#include "Event.h" class EventHandler { public: EventHandler(); virtual ~EventHandler(void); - Event *addEvent(); + EventRef addEvent(); bool removeEvent(EventBase *event); - + bool waitForAny(); protected: @@ -21,7 +20,7 @@ private: class PrivateData; PrivateData *d; bool listIsSignalled(); - + friend class Event; }; diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index 2bde8f1c..93e97beb 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -10,7 +10,7 @@ class EventHandler::PrivateData { public: pthread_cond_t event; pthread_mutex_t mutex; - std::list eventList; + std::list eventList; TelldusCore::Mutex listMutex; }; @@ -23,17 +23,17 @@ EventHandler::EventHandler() { EventHandler::~EventHandler(void) { pthread_mutex_destroy(&d->mutex); pthread_cond_destroy(&d->event); - - std::list::const_iterator it = d->eventList.begin(); + + std::list::const_iterator it = d->eventList.begin(); for(; it != d->eventList.end(); ++it) { - delete(*it); + (*it)->clearHandler(); } - + delete d; } -Event *EventHandler::addEvent() { - Event *event = new Event(this); +EventRef EventHandler::addEvent() { + EventRef event(new Event(this)); TelldusCore::MutexLocker locker(&d->listMutex); d->eventList.push_back(event); return event; @@ -41,8 +41,8 @@ Event *EventHandler::addEvent() { bool EventHandler::listIsSignalled(){ TelldusCore::MutexLocker locker(&d->listMutex); - - std::list::const_iterator it = d->eventList.begin(); + + std::list::const_iterator it = d->eventList.begin(); for(; it != d->eventList.end(); ++it) { if((*it)->isSignaled()){ return true; @@ -51,9 +51,14 @@ bool EventHandler::listIsSignalled(){ return false; } -bool EventHandler::removeEvent(EventBase *event) { +bool EventHandler::removeEvent(EventBase *eventBase) { + Event *event = reinterpret_cast(eventBase); + if (!event) { + return false; + } TelldusCore::MutexLocker locker(&d->listMutex); - d->eventList.remove((Event*)event); + //TODO! + //d->eventList.remove(event); return true; } diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 4c84fc46..1b8b7749 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -13,7 +13,7 @@ typedef std::list SocketList; class EventUpdateManager::PrivateData { public: EventHandler eventHandler; - Event *stopEvent, *updateEvent, *clientConnectEvent; + EventRef stopEvent, updateEvent, clientConnectEvent; SocketList clients; ConnectionListener *eventUpdateClientListener; }; @@ -31,8 +31,6 @@ EventUpdateManager::EventUpdateManager() EventUpdateManager::~EventUpdateManager(void) { d->stopEvent->signal(); wait(); - delete d->stopEvent; - delete d->updateEvent; delete d->eventUpdateClientListener; for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) { @@ -42,7 +40,7 @@ EventUpdateManager::~EventUpdateManager(void) { delete d; } -Event *EventUpdateManager::retrieveUpdateEvent(){ +EventRef EventUpdateManager::retrieveUpdateEvent(){ return d->updateEvent; } diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index c8d565f8..b9ca1270 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -1,36 +1,36 @@ #ifndef EVENTUPDATEMANAGER_H -#define EVENTUPDATEMANAGER_H - -#include "Thread.h" -#include "Event.h" - -class EventUpdateData : public EventDataBase { -public: - std::wstring messageType; - int controllerId; - int deviceId; - int eventChangeType; - int eventDeviceChanges; - int eventState; - std::wstring eventValue; -}; - -class EventUpdateManager : public TelldusCore::Thread -{ -public: - EventUpdateManager(void); - ~EventUpdateManager(void); - - Event *retrieveUpdateEvent(); - Event *retrieveClientConnectEvent(); - -protected: - void run(); - -private: - class PrivateData; - PrivateData *d; - void sendMessageToClients(EventUpdateData *data); -}; - -#endif //EVENTUPDATEMANAGER_H \ No newline at end of file +#define EVENTUPDATEMANAGER_H + +#include "Thread.h" +#include "Event.h" + +class EventUpdateData : public EventDataBase { +public: + std::wstring messageType; + int controllerId; + int deviceId; + int eventChangeType; + int eventDeviceChanges; + int eventState; + std::wstring eventValue; +}; + +class EventUpdateManager : public TelldusCore::Thread +{ +public: + EventUpdateManager(void); + ~EventUpdateManager(void); + + EventRef retrieveUpdateEvent(); + EventRef retrieveClientConnectEvent(); + +protected: + void run(); + +private: + class PrivateData; + PrivateData *d; + void sendMessageToClients(EventUpdateData *data); +}; + +#endif //EVENTUPDATEMANAGER_H diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index c47d4659..ddc5dba2 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -19,7 +19,7 @@ public: class TelldusMain::PrivateData { public: EventHandler eventHandler; - Event *stopEvent, *deviceChangeEvent; + EventRef stopEvent, deviceChangeEvent; }; TelldusMain::TelldusMain(void) @@ -30,8 +30,6 @@ TelldusMain::TelldusMain(void) } TelldusMain::~TelldusMain(void) { - delete d->deviceChangeEvent; - delete d->stopEvent; delete d; } @@ -44,12 +42,12 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { } void TelldusMain::start(void) { - Event *clientEvent = d->eventHandler.addEvent(); - std::auto_ptr dataEvent(d->eventHandler.addEvent()); + EventRef clientEvent = d->eventHandler.addEvent(); + EventRef dataEvent = d->eventHandler.addEvent(); ControllerManager controllerManager(dataEvent.get()); EventUpdateManager eventUpdateManager; - Event *deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); + EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); eventUpdateManager.start(); DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); @@ -57,7 +55,7 @@ void TelldusMain::start(void) { std::list clientCommunicationHandlerList; - std::auto_ptr handlerEvent(d->eventHandler.addEvent()); + EventRef handlerEvent = d->eventHandler.addEvent(); while(!d->stopEvent->isSignaled()) { if (!d->eventHandler.waitForAny()) { @@ -68,7 +66,7 @@ void TelldusMain::start(void) { EventDataRef eventDataRef = clientEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent.get(), &deviceManager, deviceUpdateEvent); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } From 93fa34545d972892bcb65eb1b670e7251444fadf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 09:17:42 +0000 Subject: [PATCH 0492/2215] By having smartpointers, the function EventHandler::removeEvent() is obsolete --- telldus-core/service/Event.cpp | 3 --- telldus-core/service/EventHandler.h | 1 - telldus-core/service/EventHandler_unix.cpp | 12 +----------- telldus-core/service/TelldusMain.cpp | 2 +- 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/telldus-core/service/Event.cpp b/telldus-core/service/Event.cpp index d83d8445..b982d99a 100644 --- a/telldus-core/service/Event.cpp +++ b/telldus-core/service/Event.cpp @@ -28,9 +28,6 @@ EventBase::EventBase(EventHandler *handler) { } EventBase::~EventBase(void) { - if (d->handler) { - d->handler->removeEvent(this); - } delete d; } diff --git a/telldus-core/service/EventHandler.h b/telldus-core/service/EventHandler.h index 61c3d80a..44a220a2 100644 --- a/telldus-core/service/EventHandler.h +++ b/telldus-core/service/EventHandler.h @@ -9,7 +9,6 @@ public: virtual ~EventHandler(void); EventRef addEvent(); - bool removeEvent(EventBase *event); bool waitForAny(); diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/service/EventHandler_unix.cpp index 93e97beb..2e10f7e0 100644 --- a/telldus-core/service/EventHandler_unix.cpp +++ b/telldus-core/service/EventHandler_unix.cpp @@ -26,6 +26,7 @@ EventHandler::~EventHandler(void) { std::list::const_iterator it = d->eventList.begin(); for(; it != d->eventList.end(); ++it) { + //We clear the handler if someone else still has a reference to the event (*it)->clearHandler(); } @@ -51,17 +52,6 @@ bool EventHandler::listIsSignalled(){ return false; } -bool EventHandler::removeEvent(EventBase *eventBase) { - Event *event = reinterpret_cast(eventBase); - if (!event) { - return false; - } - TelldusCore::MutexLocker locker(&d->listMutex); - //TODO! - //d->eventList.remove(event); - return true; -} - void EventHandler::signal(Event *event) { pthread_mutex_lock(&d->mutex); //event->setSignaled(); diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index ddc5dba2..a586cccf 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -88,7 +88,7 @@ void TelldusMain::start(void) { } } - if(handlerEvent->isSignaled()){ + if (handlerEvent->isSignaled()) { handlerEvent->popSignal(); for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ if ((*it)->isDone()){ From 00b77137611b90dcb533539b251ffa089e2d4098 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 09:19:18 +0000 Subject: [PATCH 0493/2215] Removed debug message --- telldus-core/service/ControllerManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index beff78f6..960a9f42 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -104,5 +104,4 @@ void ControllerManager::loadControllers() { d->lastControllerId = controllerId; d->controllers[d->lastControllerId] = controller; } - printf("List containing %i controllers\n", (int)d->controllers.size()); } From b5fc49747f9e5cdf987c6ea4a0780d7860f7fec0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 09:32:06 +0000 Subject: [PATCH 0494/2215] Fixed small error in the returned value from Settings::getDeviceStateValue() using libConfuse engine --- telldus-core/service/SettingsConfuse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 28645978..7ce85059 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -225,7 +225,7 @@ int Settings::getDeviceState( int intDeviceId ) const { std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { TelldusCore::MutexLocker locker(&mutex); if (d->var_cfg == 0) { - return false; + return L""; } cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { From b0a75060c762591749d73d4496da94181ec2ffe9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 09:35:01 +0000 Subject: [PATCH 0495/2215] Added Valgrind suppression file --- telldus-core/valgrind.supp | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 telldus-core/valgrind.supp diff --git a/telldus-core/valgrind.supp b/telldus-core/valgrind.supp new file mode 100644 index 00000000..c8118927 --- /dev/null +++ b/telldus-core/valgrind.supp @@ -0,0 +1,57 @@ +{ + Glibc + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start + obj:/lib64/ld-2.11.2.so +} +{ + LibUSB problems + Memcheck:Leak + fun:malloc + fun:usb_parse_configuration + fun:usb_os_find_devices + fun:usb_find_devices +} +{ + libUSB + Memcheck:Leak + fun:malloc + fun:usb_os_determine_children + fun:usb_find_devices +} +{ + libUSB + Memcheck:Leak + fun:malloc + fun:usb_os_find_devices + fun:usb_find_devices +} +{ + libUSB + Memcheck:Leak + fun:malloc + fun:realloc + fun:usb_parse_configuration + fun:usb_os_find_devices + fun:usb_find_devices +} +{ + libUSB + Memcheck:Leak + fun:malloc + fun:usb_os_find_busses + fun:usb_find_busses +} +{ + libConfuse + Memcheck:Leak + fun:realloc + fun:cfg_yyensure_buffer_stack + fun:cfg_yy_switch_to_buffer + fun:cfg_parse_fp + fun:cfg_parse +} + From 79e956093ff83471ecf253a05c38961dd138e19f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 10:09:02 +0000 Subject: [PATCH 0496/2215] tr1 is, of course, placed differently on Windows/Unix... --- telldus-core/service/Event.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Event.h b/telldus-core/service/Event.h index 3408aed4..ad52aa02 100644 --- a/telldus-core/service/Event.h +++ b/telldus-core/service/Event.h @@ -3,12 +3,13 @@ class EventHandler; #include "Thread.h" -#include #ifdef _WINDOWS #include + #include typedef HANDLE EVENT_T; #else + #include typedef void* EVENT_T; #endif From 485b1e3601f0b1ebe10e33d65420750cfa105bdb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 10:20:14 +0000 Subject: [PATCH 0497/2215] Smart pointers fixes for Windows. --- .../service/ConnectionListener_win.cpp | 5 ++- telldus-core/service/EventHandler_win.cpp | 32 +++---------------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 4ffa16a4..5d328bd9 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -14,10 +14,10 @@ public: SECURITY_ATTRIBUTES sa; HANDLE hEvent; bool running; - Event *waitEvent; + EventRef waitEvent; }; -ConnectionListener::ConnectionListener(const std::wstring &name, Event *waitEvent) +ConnectionListener::ConnectionListener(const std::wstring &name, EventRef waitEvent) { d = new PrivateData; d->hEvent = 0; @@ -79,7 +79,6 @@ ConnectionListener::~ConnectionListener(void) { SetEvent(d->hEvent); } wait(); - delete d->waitEvent; delete d; } diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 7c012fe9..730b5b40 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -8,7 +8,7 @@ class EventHandler::PrivateData { public: HANDLE *eventArray; - Event **eventObjectArray; + EventRef *eventObjectArray; TelldusCore::Mutex mutex; int eventCount; }; @@ -17,7 +17,7 @@ EventHandler::EventHandler() { d = new PrivateData; d->eventCount = 0; d->eventArray = new HANDLE[0]; - d->eventObjectArray = new Event*[0]; + d->eventObjectArray = new EventRef[0]; } EventHandler::~EventHandler(void) { @@ -26,13 +26,13 @@ EventHandler::~EventHandler(void) { delete d; } -Event *EventHandler::addEvent() { - Event *event = new Event(this); +EventRef EventHandler::addEvent() { + EventRef event(new Event(this)); TelldusCore::MutexLocker locker(&d->mutex); HANDLE *newArray = new HANDLE[d->eventCount+1]; - Event **newObjectArray = new Event*[d->eventCount+1]; + EventRef *newObjectArray = new EventRef[d->eventCount+1]; for (int i = 0; i < d->eventCount; ++i) { newArray[i] = d->eventArray[i]; newObjectArray[i] = d->eventObjectArray[i]; @@ -47,28 +47,6 @@ Event *EventHandler::addEvent() { return event; } -bool EventHandler::removeEvent(EventBase *event) { - TelldusCore::MutexLocker locker(&d->mutex); - HANDLE *newArray = new HANDLE[d->eventCount-1]; - Event **newObjectArray = new Event*[d->eventCount-1]; - int index = 0; - int i = 0; - for (; i < d->eventCount; ++i) { - if ( d->eventObjectArray[i] == event ) { - continue; - } - newArray[index] = d->eventArray[i]; - newObjectArray[index] = d->eventObjectArray[i]; - ++index; - } - delete[] d->eventArray; - delete[] d->eventObjectArray; - d->eventArray = newArray; - d->eventObjectArray = newObjectArray; - --d->eventCount; - return (i != index); -} - void EventHandler::signal(Event *) { } From 3a6bacb52933f34fab5554a4dced515b15f9f474 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 11:03:23 +0000 Subject: [PATCH 0498/2215] Added handler for SIGPIPE, just ignore the signal for now --- telldus-core/service/main_unix.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 24b34681..4527225e 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -9,10 +9,15 @@ void shutdownHandler(int onSignal) { tm.stop(); } +void sigpipeHandler(int onSignal) { + printf("SIGPIPE received\n"); +} + int main(int argc, char **argv) { /* Install signal traps for proper shutdown */ signal(SIGTERM, shutdownHandler); signal(SIGINT, shutdownHandler); + signal(SIGPIPE, sigpipeHandler); tm.start(); printf("telldusd stopped gracefully\n"); From aa8d4a0f9d450b10b3a1714521a368c36092ec47 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 14:29:46 +0000 Subject: [PATCH 0499/2215] Set connected to false if error occur --- telldus-core/common/Socket_unix.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 5e5025dc..a86a1aa4 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -80,7 +80,9 @@ void Socket::stopReadWait(){ } void Socket::write(const std::wstring &msg) { - //TODO set d->conneted to false if something goes wrong std::string newMsg(msg.begin(), msg.end()); - send(d->socket, newMsg.c_str(), newMsg.length(), 0); + int sent = send(d->socket, newMsg.c_str(), newMsg.length(), 0); + if (sent < 0) { + d->connected = false; + } } From 9d10ea4c9f09f2718b18498abdba9e82731479a0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 15:15:36 +0000 Subject: [PATCH 0500/2215] Added reading using select --- telldus-core/common/Socket_unix.cpp | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index a86a1aa4..7de9e123 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -16,18 +16,21 @@ class Socket::PrivateData { public: SOCKET_T socket; bool connected; + fd_set infds; }; Socket::Socket() { d = new PrivateData; d->socket = 0; d->connected = false; + FD_ZERO(&d->infds); } Socket::Socket(SOCKET_T socket) { d = new PrivateData; d->socket = socket; + FD_ZERO(&d->infds); d->connected = true; } @@ -53,6 +56,7 @@ void Socket::connect(const std::wstring &server) { if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { return; } + d->connected = true; } @@ -65,18 +69,34 @@ std::wstring Socket::read(int) { } std::wstring Socket::read() { - //TODO set d->conneted to false if something goes wrong + struct timeval tv = { 1, 0 }; char inbuf[BUFSIZE]; memset(inbuf, '\0', sizeof(inbuf)); - recv(d->socket, inbuf, BUFSIZE - 1, 0); + FD_SET(d->socket, &d->infds); + while(d->connected) { + tv.tv_sec = 1; + + int response = select(d->socket+1, &d->infds, NULL, NULL, &tv); + if (response <= 0) { + FD_SET(d->socket, &d->infds); + continue; + } + + int received = recv(d->socket, inbuf, BUFSIZE - 1, 0); + if (received <= 0) { + d->connected = false; + } + break; + } std::string msg(inbuf); return std::wstring(msg.begin(), msg.end()); } void Socket::stopReadWait(){ - //TODO: + //TODO, lock? + d->connected = false; } void Socket::write(const std::wstring &msg) { From f94392025fd9cc82c00e4e97279277551df4a5bb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 28 Oct 2010 15:16:10 +0000 Subject: [PATCH 0501/2215] Changed the description of tdtool a bit --- telldus-core/tdtool/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt index 2071ccab..c94f703f 100644 --- a/telldus-core/tdtool/CMakeLists.txt +++ b/telldus-core/tdtool/CMakeLists.txt @@ -3,7 +3,7 @@ PROJECT(tdtool) cmake_policy(SET CMP0005 NEW) SET (tdtool_DESCRIPTION - "a command line utility to control a Telldus TellStick" + "a command line utility to send commands to a Telldus TellStick" ) SET(tdtool_SRCS @@ -26,11 +26,11 @@ IF (WIN32) TARGET_LINK_LIBRARIES(tdtool ${TELLDUSCORE_LIBRARY} ) -ELSEIF (APPLE) +ELSEIF (APPLE) TARGET_LINK_LIBRARIES(tdtool TelldusCore ) -ELSE (WIN32) +ELSE (WIN32) TARGET_LINK_LIBRARIES(tdtool ${CMAKE_BINARY_DIR}/client/libtelldus-core.so ) From a163a78982291265ed14d64de947b3e8642ad8fe Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 28 Oct 2010 15:44:15 +0000 Subject: [PATCH 0502/2215] Lock for 'connect'-variable in Socket_unix --- telldus-core/common/Socket_unix.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 7de9e123..22cecf50 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -1,5 +1,7 @@ #include "Socket.h" +#include "Mutex.h" + #include #include #include @@ -17,6 +19,7 @@ public: SOCKET_T socket; bool connected; fd_set infds; + Mutex mutex; }; Socket::Socket() { @@ -56,11 +59,13 @@ void Socket::connect(const std::wstring &server) { if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { return; } - + + TelldusCore::MutexLocker locker(&d->mutex); d->connected = true; } bool Socket::isConnected(){ + TelldusCore::MutexLocker locker(&d->mutex); return d->connected; } @@ -74,7 +79,7 @@ std::wstring Socket::read() { memset(inbuf, '\0', sizeof(inbuf)); FD_SET(d->socket, &d->infds); - while(d->connected) { + while(isConnected()) { tv.tv_sec = 1; int response = select(d->socket+1, &d->infds, NULL, NULL, &tv); @@ -85,6 +90,7 @@ std::wstring Socket::read() { int received = recv(d->socket, inbuf, BUFSIZE - 1, 0); if (received <= 0) { + TelldusCore::MutexLocker locker(&d->mutex); d->connected = false; } break; @@ -95,7 +101,7 @@ std::wstring Socket::read() { } void Socket::stopReadWait(){ - //TODO, lock? + TelldusCore::MutexLocker locker(&d->mutex); d->connected = false; } @@ -103,6 +109,7 @@ void Socket::write(const std::wstring &msg) { std::string newMsg(msg.begin(), msg.end()); int sent = send(d->socket, newMsg.c_str(), newMsg.length(), 0); if (sent < 0) { + TelldusCore::MutexLocker locker(&d->mutex); d->connected = false; } } From d3fe7dc954d7d9c2b378b75d228203bbfb3834f8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 29 Oct 2010 07:37:17 +0000 Subject: [PATCH 0503/2215] Minimal code cleanup --- telldus-core/service/SettingsConfuse.cpp | 1 - telldus-core/service/TellStick_libftdi.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 7ce85059..c12c0900 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -178,7 +178,6 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w cfg_setstr(cfg_device, "stateValue", std::string(strDeviceStateValue.begin(), strDeviceStateValue.end()).c_str()); FILE *fp = fopen(VAR_CONFIG_FILE, "w"); - //TODO debugtest if(fp == 0){ return false; } diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index d2e8f4d1..0be37ccb 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -114,7 +114,7 @@ void TellStick::processData( const std::string &data ) { if (d->message.substr(0,2).compare("+V") == 0) { //parent->fwVersion = atoi(message.substr(2).c_str()); //printf("Firmware version: %s\n", message.substr(2).c_str()); - d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); //TODO used? + d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); } From 027c04e819d2826ffe7c61c564983bcb9a3150c2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 29 Oct 2010 08:18:13 +0000 Subject: [PATCH 0504/2215] Fix for client messages that are received together --- telldus-core/client/Client.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index c1928ea4..692d917c 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -139,7 +139,7 @@ void Client::run(){ } std::wstring clientMessage = d->eventSocket.read(5000); //testing 5 second timeout - if(clientMessage != L""){ + while(clientMessage != L""){ //a message arrived std::wstring type = Message::takeString(&clientMessage); if(type == L"TDDeviceChangeEvent"){ @@ -159,6 +159,9 @@ void Client::run(){ int controllerId = Message::takeInt(&clientMessage); callbackRawEvent(command, controllerId); } + else{ + clientMessage = L""; //cleanup, if message contained garbage/unhandled data + } } } } From 72ad39381e2e74b9505ebb082b256bd6561245e2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 29 Oct 2010 10:13:51 +0000 Subject: [PATCH 0505/2215] Loop to remove all controllers --- telldus-core/service/ControllerManager.cpp | 29 ++++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 960a9f42..2ce3ce6c 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -41,18 +41,26 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) loadControllers(); } else { TelldusCore::MutexLocker locker(&d->mutex); - for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - TellStick *tellstick = reinterpret_cast(it->second); - if (!tellstick) { - continue; - } - if (!tellstick->stillConnected()) { - d->controllers.erase(it); - delete tellstick; - break; + bool again = true; + while(again) { + again = false; + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + TellStick *tellstick = reinterpret_cast(it->second); + if (!tellstick) { + continue; + } + if (!tellstick->stillConnected()) { + printf("Controller lost\n"); + d->controllers.erase(it); + delete tellstick; + again=true; + break; + } } } } + printf("List contains %i controllers\n", (int)d->controllers.size()); + } Controller *ControllerManager::getBestControllerById(int id) { @@ -75,8 +83,6 @@ void ControllerManager::loadControllers() { std::list::iterator it = list.begin(); for(; it != list.end(); ++it) { - printf("Found (%i/%i): %s\n", (*it).vid, (*it).pid, (*it).serial.c_str()); - //Most backend only report non-opened devices. //If they don't make sure we don't open them twice bool found = false; @@ -101,6 +107,7 @@ void ControllerManager::loadControllers() { delete controller; continue; } + printf("Found (%i/%i): %s\n", (*it).vid, (*it).pid, (*it).serial.c_str()); d->lastControllerId = controllerId; d->controllers[d->lastControllerId] = controller; } From 46bc83e1b1eb83c39aafa183a43c50f620752709 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 29 Oct 2010 10:15:33 +0000 Subject: [PATCH 0506/2215] Added class ControllerListener --- telldus-core/service/CMakeLists.txt | 3 + telldus-core/service/ControllerListener.h | 26 +++ .../service/ControllerListener_mac.cpp | 174 ++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 telldus-core/service/ControllerListener.h create mode 100644 telldus-core/service/ControllerListener_mac.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 08ea9608..486749fd 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -45,6 +45,7 @@ SET( telldus-service_HDRS ClientCommunicationHandler.h ConnectionListener.h Controller.h + ControllerListener.h ControllerManager.h ControllerMessage.h Device.h @@ -70,6 +71,7 @@ INCLUDE_DIRECTORIES( IF (APPLE) #### Mac OS X #### SET(DEFAULT_FTDI_ENGINE "ftd2xx") SET( telldus-service_TARGET TelldusService ) + ADD_DEFINITIONS( -D_MACOSX ) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) FIND_LIBRARY(IOKIT_LIBRARY IOKit) @@ -82,6 +84,7 @@ IF (APPLE) #### Mac OS X #### LIST(APPEND telldus-service_SRCS main_unix.cpp ConnectionListener_unix.cpp + ControllerListener_mac.cpp Event_unix.cpp EventHandler_unix.cpp SettingsCoreFoundationPreferences.cpp diff --git a/telldus-core/service/ControllerListener.h b/telldus-core/service/ControllerListener.h new file mode 100644 index 00000000..7fd7fbce --- /dev/null +++ b/telldus-core/service/ControllerListener.h @@ -0,0 +1,26 @@ +#ifndef CONTROLLERLISTENER_H +#define CONTROLLERLISTENER_H + +#include "Thread.h" +#include "Event.h" + +class ControllerChangeEventData : public EventDataBase { +public: + int vid, pid; + bool inserted; +}; + +class ControllerListener : public TelldusCore::Thread { +public: + ControllerListener(EventRef event); + virtual ~ControllerListener(); + +protected: + void run(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CONTROLLERLISTENER_H diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp new file mode 100644 index 00000000..c3749cb2 --- /dev/null +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -0,0 +1,174 @@ +#include "ControllerListener.h" + +#include +#include +#include +#include +#include + +class TellStickData { +public: + io_object_t notification; + CFStringRef serialNumber; + UInt32 vid; + UInt32 pid; + EventRef event; +}; + +class ControllerListener::PrivateData { +public: + IONotificationPortRef gNotifyPort; + CFRunLoopRef gRunLoop; + io_iterator_t gAddedIter; + EventRef event; + + static void DeviceAdded(void *refCon, io_iterator_t iterator); + static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); +}; + +ControllerListener::ControllerListener(EventRef event) +:Thread() +{ + d = new PrivateData; + d->event = event; + this->start(); +} + +ControllerListener::~ControllerListener() { + CFRunLoopStop(d->gRunLoop); + this->wait(); + delete d; +} + +void ControllerListener::run() { + CFMutableDictionaryRef matchingDict; + CFRunLoopSourceRef runLoopSource; + CFNumberRef numberRef; + kern_return_t kr; + long usbVendor = 0x1781; + long usbProduct = 0x0c30; + + matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class + // IOUSBDevice and its subclasses + + if (matchingDict == NULL) { + return; + } + + // Create a CFNumber for the idVendor and set the value in the dictionary + numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor); + CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); + CFRelease(numberRef); + + // Create a CFNumber for the idProduct and set the value in the dictionary + numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct); + CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); + CFRelease(numberRef); + numberRef = NULL; + + d->gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); + runLoopSource = IONotificationPortGetRunLoopSource(d->gNotifyPort); + + d->gRunLoop = CFRunLoopGetCurrent(); + CFRunLoopAddSource(d->gRunLoop, runLoopSource, kCFRunLoopDefaultMode); + + // Now set up a notification to be called when a device is first matched by I/O Kit. + kr = IOServiceAddMatchingNotification(d->gNotifyPort, // notifyPort + kIOFirstMatchNotification, // notificationType + matchingDict, // matching + PrivateData::DeviceAdded, // callback + this, // refCon + &d->gAddedIter // notification + ); + + + // Iterate once to get already-present devices and arm the notification + PrivateData::DeviceAdded(this, d->gAddedIter); + CFRunLoopRun(); +} + +void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { + kern_return_t kr; + + if (messageType != kIOMessageServiceIsTerminated) { + return; + } + + TellStickData *tsd = reinterpret_cast (refCon); + if (!tsd) { + return; + } + + CFIndex size = CFStringGetLength(tsd->serialNumber); + char *s = new char[size+1]; + CFStringGetCString(tsd->serialNumber, s, size+1, kCFStringEncodingASCII); + std::string serial(s); //Copy the string to the stack + delete[] s; + + ControllerChangeEventData *data = new ControllerChangeEventData; + data->vid = tsd->vid; + data->pid = tsd->pid; + data->inserted = false; + tsd->event->signal(data); + + // Free the data we're no longer using now that the device is going away + CFRelease(tsd->serialNumber); + + kr = IOObjectRelease(tsd->notification); + + delete tsd; +} + +void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t iterator) { + io_service_t usbDevice; + kern_return_t kr; + + ControllerListener *parent = reinterpret_cast (refCon); + + while ((usbDevice = IOIteratorNext(iterator))) { + TellStickData *tsd = new TellStickData; + tsd->event = parent->d->event; + + // Get the serial number + CFStringRef serialRef = reinterpret_cast(IORegistryEntryCreateCFProperty( usbDevice, CFSTR("USB Serial Number" ), kCFAllocatorDefault, 0 )); + if (serialRef == NULL) { + //No serial number, we cannot continue. Sorry + continue; + } + + + CFNumberRef vidRef = reinterpret_cast (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idVendor"), kCFAllocatorDefault, 0)); + if (vidRef) { + CFNumberGetValue(vidRef, kCFNumberIntType, &(tsd->vid)); + CFRelease(vidRef); + } + + CFNumberRef pidRef = reinterpret_cast (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idProduct"), kCFAllocatorDefault, 0)); + if (pidRef) { + CFNumberGetValue(pidRef, kCFNumberIntType, &(tsd->pid)); + CFRelease(pidRef); + } + + CFStringRef serialNumberAsCFString = CFStringCreateCopy(kCFAllocatorDefault, serialRef); + tsd->serialNumber = serialNumberAsCFString; + CFRelease(serialRef); + + // Register for an interest notification of this device being removed. Use a reference to our + // private data as the refCon which will be passed to the notification callback. + kr = IOServiceAddInterestNotification(parent->d->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); + + CFIndex size = CFStringGetLength(serialNumberAsCFString); + char *s = new char[size+1]; + CFStringGetCString(serialNumberAsCFString, s, size+1, kCFStringEncodingASCII); + std::string serial(s); //Copy the string to the stack + delete[] s; + + kr = IOObjectRelease(usbDevice); + + ControllerChangeEventData *data = new ControllerChangeEventData; + data->vid = tsd->vid; + data->pid = tsd->pid; + data->inserted = true; + tsd->event->signal(data); + } +} From e86b1db6a884fa9f27c8ba6c9cbfbc705def62ec Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 29 Oct 2010 10:16:20 +0000 Subject: [PATCH 0507/2215] Use our new ControllerListener class on OSX --- telldus-core/service/TelldusMain.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index a586cccf..f2397975 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -4,29 +4,24 @@ #include "ClientCommunicationHandler.h" #include "DeviceManager.h" #include "ControllerManager.h" +#include "ControllerListener.h" #include "EventUpdateManager.h" #include #include #include -class DeviceEventData : public EventDataBase { -public: - int vid, pid; - bool inserted; -}; - class TelldusMain::PrivateData { public: EventHandler eventHandler; - EventRef stopEvent, deviceChangeEvent; + EventRef stopEvent, controllerChangeEvent; }; TelldusMain::TelldusMain(void) { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); - d->deviceChangeEvent = d->eventHandler.addEvent(); + d->controllerChangeEvent = d->eventHandler.addEvent(); } TelldusMain::~TelldusMain(void) { @@ -34,11 +29,11 @@ TelldusMain::~TelldusMain(void) { } void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { - DeviceEventData *data = new DeviceEventData; + ControllerChangeEventData *data = new ControllerChangeEventData; data->vid = vid; data->pid = pid; data->inserted = inserted; - d->deviceChangeEvent->signal(data); + d->controllerChangeEvent->signal(data); } void TelldusMain::start(void) { @@ -56,6 +51,12 @@ void TelldusMain::start(void) { std::list clientCommunicationHandlerList; EventRef handlerEvent = d->eventHandler.addEvent(); + +#ifdef _MACOSX + //This is only needed on OS X + ControllerListener controllerListener(d->controllerChangeEvent); +#endif + while(!d->stopEvent->isSignaled()) { if (!d->eventHandler.waitForAny()) { @@ -72,9 +73,9 @@ void TelldusMain::start(void) { } } - if (d->deviceChangeEvent->isSignaled()) { - EventDataRef eventDataRef = d->deviceChangeEvent->takeSignal(); - DeviceEventData *data = reinterpret_cast(eventDataRef.get()); + if (d->controllerChangeEvent->isSignaled()) { + EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal(); + ControllerChangeEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, data->inserted); } From 59d2d6521bbb495da981b03c5d3f6d88d9e4160c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 29 Oct 2010 10:17:56 +0000 Subject: [PATCH 0508/2215] Implemented debuglog() on OSX --- telldus-core/common/common.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index d909a71c..cc8e58d4 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -43,9 +43,11 @@ inline void debuglog(const int intMessage, const std::string strMessage){ file.flush(); file.close(); -#else +#elif !defined(_MACOSX) pthread_t thread = pthread_self(); printf("[%i] %i - %s\n", (int)thread, intMessage, strMessage.c_str()); +#else + printf("%i - %s\n", intMessage, strMessage.c_str()); #endif } From 80ecb561948a7c56aa86357405a6fa343d02fbed Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 29 Oct 2010 11:18:02 +0000 Subject: [PATCH 0509/2215] Handle multiple usb devices and added listening for Duo --- .../service/ControllerListener_mac.cpp | 73 ++++++++++--------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp index c3749cb2..7ae64ffc 100644 --- a/telldus-core/service/ControllerListener_mac.cpp +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -22,6 +22,7 @@ public: io_iterator_t gAddedIter; EventRef event; + void addUsbFilter(int vid, int pid); static void DeviceAdded(void *refCon, io_iterator_t iterator); static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); }; @@ -41,50 +42,52 @@ ControllerListener::~ControllerListener() { } void ControllerListener::run() { - CFMutableDictionaryRef matchingDict; CFRunLoopSourceRef runLoopSource; - CFNumberRef numberRef; - kern_return_t kr; - long usbVendor = 0x1781; - long usbProduct = 0x0c30; - - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class - // IOUSBDevice and its subclasses - - if (matchingDict == NULL) { - return; - } - - // Create a CFNumber for the idVendor and set the value in the dictionary - numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbVendor); - CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); - CFRelease(numberRef); - - // Create a CFNumber for the idProduct and set the value in the dictionary - numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &usbProduct); - CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); - CFRelease(numberRef); - numberRef = NULL; - + d->gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); runLoopSource = IONotificationPortGetRunLoopSource(d->gNotifyPort); d->gRunLoop = CFRunLoopGetCurrent(); CFRunLoopAddSource(d->gRunLoop, runLoopSource, kCFRunLoopDefaultMode); - // Now set up a notification to be called when a device is first matched by I/O Kit. - kr = IOServiceAddMatchingNotification(d->gNotifyPort, // notifyPort + d->addUsbFilter(0x1781, 0x0c30); + d->addUsbFilter(0x1781, 0x0c31); + + CFRunLoopRun(); +} + +void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) { + CFNumberRef numberRef; + kern_return_t kr; + CFMutableDictionaryRef matchingDict; + + matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class + // IOUSBDevice and its subclasses + if (matchingDict == NULL) { + return; + } + + // Create a CFNumber for the idVendor and set the value in the dictionary + numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vid); + CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); + CFRelease(numberRef); + + // Create a CFNumber for the idProduct and set the value in the dictionary + numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid); + CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); + CFRelease(numberRef); + + // Now set up a notification to be called when a device is first matched by I/O Kit. + kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort kIOFirstMatchNotification, // notificationType matchingDict, // matching PrivateData::DeviceAdded, // callback this, // refCon - &d->gAddedIter // notification - ); - - + &gAddedIter // notification + ); // Iterate once to get already-present devices and arm the notification - PrivateData::DeviceAdded(this, d->gAddedIter); - CFRunLoopRun(); + PrivateData::DeviceAdded(this, gAddedIter); + } void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { @@ -123,11 +126,11 @@ void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t it io_service_t usbDevice; kern_return_t kr; - ControllerListener *parent = reinterpret_cast (refCon); + PrivateData *pd = reinterpret_cast (refCon); while ((usbDevice = IOIteratorNext(iterator))) { TellStickData *tsd = new TellStickData; - tsd->event = parent->d->event; + tsd->event = pd->event; // Get the serial number CFStringRef serialRef = reinterpret_cast(IORegistryEntryCreateCFProperty( usbDevice, CFSTR("USB Serial Number" ), kCFAllocatorDefault, 0 )); @@ -155,7 +158,7 @@ void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t it // Register for an interest notification of this device being removed. Use a reference to our // private data as the refCon which will be passed to the notification callback. - kr = IOServiceAddInterestNotification(parent->d->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); + kr = IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); CFIndex size = CFStringGetLength(serialNumberAsCFString); char *s = new char[size+1]; From 948062074776a04cf5fa51a41f163ba6d7f522dc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 29 Oct 2010 12:15:42 +0000 Subject: [PATCH 0510/2215] Fixed version number --- telldus-core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index eea7863b..82d31c3c 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -6,7 +6,7 @@ CMAKE_POLICY(SET CMP0003 NEW) SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 0) -SET(PACKAGE_PATCH_VERSION 200) +SET(PACKAGE_PATCH_VERSION 103) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") SET(PACKAGE_SUBVERSION) SET(PACKAGE_SOVERSION 2) From 88a8c8df2910b33b69be2814c13392d18b610738 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 31 Oct 2010 13:38:29 +0000 Subject: [PATCH 0511/2215] Allow everyone to access our pipe --- telldus-core/service/ConnectionListener_unix.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 83f2c2a2..88fa0282 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include + #include #include @@ -30,6 +33,7 @@ ConnectionListener::ConnectionListener(const std::wstring &name, EventRef waitEv ConnectionListener::~ConnectionListener(void) { d->running = false; this->wait(); + unlink(d->name.c_str()); delete d; } @@ -52,6 +56,9 @@ void ConnectionListener::run(){ int size = SUN_LEN(&name); bind(serverSocket, (struct sockaddr *)&name, size); listen(serverSocket, 5); + + //Change permissions to allow everyone + chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); len = sizeof(struct sockaddr_un); fd_set infds; From d989d9dad5811fbb71493b1f09b94f7870d4680a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 1 Nov 2010 10:29:45 +0000 Subject: [PATCH 0512/2215] Added new project tdadmin --- telldus-core/tdadmin/CMakeLists.txt | 52 ++++++++++++++++++ telldus-core/tdadmin/main.cpp | 85 +++++++++++++++++++++++++++++ telldus-core/tdadmin/udev.sh | 9 +++ 3 files changed, 146 insertions(+) create mode 100644 telldus-core/tdadmin/CMakeLists.txt create mode 100644 telldus-core/tdadmin/main.cpp create mode 100755 telldus-core/tdadmin/udev.sh diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt new file mode 100644 index 00000000..c79c507c --- /dev/null +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -0,0 +1,52 @@ +PROJECT(tdadmin) + +cmake_policy(SET CMP0005 NEW) + +SET (tdadmin_DESCRIPTION + "a command line utility to edit devices and controllers for Telldus TellStick" +) + +SET(tdadmin_SRCS + main.cpp +) + +ADD_EXECUTABLE(tdadmin + ${tdadmin_SRCS} +) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/driver +) + +ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) + +IF (WIN32) + FIND_LIBRARY(TELLDUSCORE_LIBRARY TelldusCore) + TARGET_LINK_LIBRARIES(tdadmin + ${TELLDUSCORE_LIBRARY} + ) +ELSEIF (APPLE) + TARGET_LINK_LIBRARIES(tdadmin + TelldusCore + ) +ELSE (WIN32) + TARGET_LINK_LIBRARIES(tdadmin + ${CMAKE_BINARY_DIR}/client/libtelldus-core.so + ) +ENDIF (WIN32) + +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET tdadmin + POST_BUILD + COMMAND help2man -n ${tdadmin_DESCRIPTION} ./tdadmin > tdadmin.1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file tdadmin.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tdadmin.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + +INSTALL(TARGETS tdadmin RUNTIME DESTINATION sbin) diff --git a/telldus-core/tdadmin/main.cpp b/telldus-core/tdadmin/main.cpp new file mode 100644 index 00000000..db040050 --- /dev/null +++ b/telldus-core/tdadmin/main.cpp @@ -0,0 +1,85 @@ +#include "../client/telldus-core.h" +#include +#include +#include +#include + +const char *argp_program_version = "tdadmin " VERSION ; +const char *argp_program_bug_address = ""; + +static char args_doc[] = "COMMAND ACTION"; + +static char doc[] = "TellStick admin tool -- a command line utility to edit devices and controllers for Telldus TellStick"; + +const int VID = 1; +const int PID = 2; +const int SERIAL = 3; + +static struct argp_option options[] = { + {0,0,0,0, + "COMMAND: controller, ACTION: connect/disconnect\n" + "Tells the deamon to add or remove a TellStick (duo)" + }, + {"vid",VID,"VID",0, "The vendor id (1781)" }, + {"pid",PID,"PID",0,"The product id (0c30 or 0c31)" }, + {"serial",SERIAL,"SERIAL",0,"The usb serial number" }, + { 0 } +}; + +static std::string command, action; + +int vid, pid; +static std::string serial; + +static error_t parse_opt (int key, char *arg, struct argp_state *state) { + switch (key) { + case PID: + pid = strtol(arg, NULL, 16); + break; + case SERIAL: + serial = arg; + break; + case VID: + vid = strtol(arg, NULL, 16); + break; + + case ARGP_KEY_NO_ARGS: + argp_usage (state); + + case ARGP_KEY_ARG: + command = arg; + action = state->argv[state->next]; + state->next = state->argc; + + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; + +void handle_controller(void) { + if (vid == 0 || pid == 0) { + fprintf(stderr, "Missing parameter vid or pid\n"); + } + if (action.compare("connect") == 0) { + tdConnectTellStickController(vid,pid,serial.c_str()); + + } else if (action.compare("disconnect") == 0) { + tdDisconnectTellStickController(vid,pid,serial.c_str()); + } +} + +int main(int argc, char **argv) { + + argp_parse (&argp, argc, argv, 0, 0, 0); + + if (command.compare("controller") == 0) { + handle_controller(); + } + + return 0; +} diff --git a/telldus-core/tdadmin/udev.sh b/telldus-core/tdadmin/udev.sh new file mode 100755 index 00000000..5ff565f3 --- /dev/null +++ b/telldus-core/tdadmin/udev.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if [ "${ID_VENDOR_ID}" == "1781" ]; then + if [ "${ACTION}" == "add" ]; then + tdadmin controller connect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} + elif [ "${ACTION}" == "remove" ]; then + tdadmin controller disconnect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} + fi +fi From cb260c2d7f0b2bc4d210abb920a34374309b279d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 1 Nov 2010 10:40:31 +0000 Subject: [PATCH 0513/2215] Added udev rule --- telldus-core/service/05-tellstick.rules | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 telldus-core/service/05-tellstick.rules diff --git a/telldus-core/service/05-tellstick.rules b/telldus-core/service/05-tellstick.rules new file mode 100644 index 00000000..e806dc1a --- /dev/null +++ b/telldus-core/service/05-tellstick.rules @@ -0,0 +1,2 @@ +BUS=="usb", ID_VENDOR_ID=="1781" RUN+="/usr/share/telldus-core/helpers/udev.sh" + From 0e321f9a995a7cb3d263ea8288afc86e4df9c2a2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 2 Nov 2010 11:20:00 +0000 Subject: [PATCH 0514/2215] Implemented timeouts on Unix --- telldus-core/common/Socket_unix.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 22cecf50..9c945faf 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #define BUFSIZE 512 @@ -69,21 +70,24 @@ bool Socket::isConnected(){ return d->connected; } -std::wstring Socket::read(int) { - return this->read(); +std::wstring Socket::read() { + return this->read(0); } -std::wstring Socket::read() { - struct timeval tv = { 1, 0 }; +std::wstring Socket::read(int timeout) { + struct timeval tv; char inbuf[BUFSIZE]; memset(inbuf, '\0', sizeof(inbuf)); FD_SET(d->socket, &d->infds); while(isConnected()) { - tv.tv_sec = 1; + tv.tv_sec = floor(timeout / 1000.0); + tv.tv_usec = timeout % 1000; int response = select(d->socket+1, &d->infds, NULL, NULL, &tv); - if (response <= 0) { + if (response == 0 && timeout > 0) { + return L""; + } else if (response <= 0) { FD_SET(d->socket, &d->infds); continue; } From 348de3092845015ced47c6bd1b05b3d1d21ba4df Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 2 Nov 2010 14:30:30 +0000 Subject: [PATCH 0515/2215] Welcome new class CallbackDispatcher --- telldus-core/client/CMakeLists.txt | 2 + telldus-core/client/CallbackDispatcher.cpp | 29 +++++++++++++++ telldus-core/client/CallbackDispatcher.h | 43 ++++++++++++++++++++++ telldus-core/client/Client.cpp | 26 +++++++++---- 4 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 telldus-core/client/CallbackDispatcher.cpp create mode 100644 telldus-core/client/CallbackDispatcher.h diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 11aacb33..2abdb6c7 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -4,11 +4,13 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-core_SRCS + CallbackDispatcher.cpp Client.cpp telldus-core.cpp ) SET( telldus-core_HDRS + CallbackDispatcher.h Client.h ) SET( telldus-core_PUB_HDRS diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp new file mode 100644 index 00000000..9881c3af --- /dev/null +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -0,0 +1,29 @@ +/* + * CallbackDispatcher.cpp + * telldus-core + * + * Created by Micke Prag on 2010-11-02. + * Copyright 2010 Telldus Technologies AB. All rights reserved. + * + */ + +#include "CallbackDispatcher.h" + +using namespace TelldusCore; + +template CallbackDispatcher::CallbackDispatcher(const CallbackStruct &data) +:Thread(), d(data) +{ + this->start(); +} + +template CallbackDispatcher::~CallbackDispatcher() { + this->wait(); +} + +TDDeviceEventDispatcher::TDDeviceEventDispatcher(const CallbackStruct &data, int id, int m, const std::string &strD) +:CallbackDispatcher(data), deviceId(id), method(m), strData(strD) {} + +void TDDeviceEventDispatcher::run() { + d.event(deviceId, method, strData.c_str(), d.id, d.context); +} diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h new file mode 100644 index 00000000..61e2803a --- /dev/null +++ b/telldus-core/client/CallbackDispatcher.h @@ -0,0 +1,43 @@ +/* + * CallbackDispatcher.h + * telldus-core + * + * Created by Micke Prag on 2010-11-02. + * Copyright 2010 Telldus Technologies AB. All rights reserved. + * + */ + + +#ifndef CALLBACKDISPATCHER_H +#define CALLBACKDISPATCHER_H + +#include "Thread.h" +#include "telldus-core.h" + +namespace TelldusCore { + template struct CallbackStruct { + T event; + int id; + void *context; + }; + + template class CallbackDispatcher: public Thread { + public: + CallbackDispatcher(const CallbackStruct &data); + virtual ~CallbackDispatcher(); + protected: + CallbackStruct d; + }; + + class TDDeviceEventDispatcher : public CallbackDispatcher { + public: + TDDeviceEventDispatcher(const CallbackStruct &data, int deviceId, int method, const std::string &strData); + protected: + virtual void run(); + private: + int deviceId, method; + std::string strData; + }; +} + +#endif //CALLBACKDISPATCHER_H diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 692d917c..3398d830 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,18 +1,20 @@ #include "Client.h" +#include "CallbackDispatcher.h" #include "Socket.h" #include "Strings.h" #include "Mutex.h" #include "common.h" #include +#ifdef _WINDOWS +#include +#else +#include +#endif + using namespace TelldusCore; -template struct CallbackStruct { - T event; - int id; - void *context; -}; typedef CallbackStruct DeviceEvent; typedef CallbackStruct DeviceChangeEvent; typedef CallbackStruct RawDeviceEvent; @@ -65,9 +67,17 @@ Client *Client::getInstance() { } void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue){ - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceEventList::const_iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - (*callback_it).event(deviceId, deviceState, TelldusCore::wideToString(deviceStateValue).c_str(), (*callback_it).id, (*callback_it).context); + std::list > list; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceEventList::const_iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDDeviceEventDispatcher(*callback_it, deviceId, deviceState, TelldusCore::wideToString(deviceStateValue))); + list.push_back(ptr); + } + } + std::list >::const_iterator it = list.begin(); + for (; it != list.end(); ++it) { + (*it)->wait(); } } From 7f7d9445a73bd88a1bc6c7f6e10565f2a45d13db Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 2 Nov 2010 14:48:13 +0000 Subject: [PATCH 0516/2215] Use CallbackDispatcher for DeviceChange- and RawDevice events also --- telldus-core/client/CallbackDispatcher.cpp | 14 +++++++++++ telldus-core/client/CallbackDispatcher.h | 17 +++++++++++++ telldus-core/client/Client.cpp | 28 +++++++++++++++++----- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 9881c3af..92c9bc7f 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -27,3 +27,17 @@ TDDeviceEventDispatcher::TDDeviceEventDispatcher(const CallbackStruct &data, int id, int event, int type) +:CallbackDispatcher(data), deviceId(id), changeEvent(event), changeType(type) {} + +void TDDeviceChangeEventDispatcher::run() { + d.event(deviceId, changeEvent, changeType, d.id, d.context); +} + +TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher(const CallbackStruct &data, const std::string &strD, int id) +:CallbackDispatcher(data), controllerId(id), strData(strD) {} + +void TDRawDeviceEventDispatcher::run() { + d.event(strData.c_str(), controllerId, d.id, d.context); +} diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 61e2803a..2516d1e9 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -38,6 +38,23 @@ namespace TelldusCore { int deviceId, method; std::string strData; }; + class TDDeviceChangeEventDispatcher : public CallbackDispatcher { + public: + TDDeviceChangeEventDispatcher(const CallbackStruct &data, int deviceId, int changeEvent, int changeType); + protected: + virtual void run(); + private: + int deviceId, changeEvent, changeType; + }; + class TDRawDeviceEventDispatcher : public CallbackDispatcher { + public: + TDRawDeviceEventDispatcher(const CallbackStruct &data, const std::string &strData, int controllerId); + protected: + virtual void run(); + private: + int controllerId; + std::string strData; + }; } #endif //CALLBACKDISPATCHER_H diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 3398d830..52313c1c 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -82,16 +82,32 @@ void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstri } void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType){ - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceChangeList::const_iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { - (*callback_it).event(deviceId, eventDeviceChanges, eventChangeType, (*callback_it).id, (*callback_it).context); + std::list > list; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceChangeList::const_iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDDeviceChangeEventDispatcher(*callback_it, deviceId, eventDeviceChanges, eventChangeType)); + list.push_back(ptr); + } + } + std::list >::const_iterator it = list.begin(); + for (; it != list.end(); ++it) { + (*it)->wait(); } } void Client::callbackRawEvent(std::wstring command, int controllerId){ - TelldusCore::MutexLocker locker(&d->mutex); - for(RawDeviceEventList::const_iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - (*callback_it).event(TelldusCore::wideToString(command).c_str(), controllerId, (*callback_it).id, (*callback_it).context); + std::list > list; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(RawDeviceEventList::const_iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDRawDeviceEventDispatcher(*callback_it, TelldusCore::wideToString(command), controllerId)); + list.push_back(ptr); + } + } + std::list >::const_iterator it = list.begin(); + for (; it != list.end(); ++it) { + (*it)->wait(); } } From 0163ba4d445673edfb1ac3b90b4848dcb61b99c3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 2 Nov 2010 17:08:55 +0000 Subject: [PATCH 0517/2215] Removed our templated CallbackDispatcher, is only caused problems. --- telldus-core/client/CallbackDispatcher.cpp | 28 +++++++++++++++------- telldus-core/client/CallbackDispatcher.h | 20 +++++++--------- telldus-core/client/Client.cpp | 12 ---------- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 92c9bc7f..ffc4ebae 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -11,32 +11,44 @@ using namespace TelldusCore; -template CallbackDispatcher::CallbackDispatcher(const CallbackStruct &data) -:Thread(), d(data) +TDDeviceEventDispatcher::TDDeviceEventDispatcher(const CallbackStruct &data, int id, int m, const std::string &strD) +:Thread(), d(data), deviceId(id), method(m), strData(strD) { this->start(); } -template CallbackDispatcher::~CallbackDispatcher() { +TDDeviceEventDispatcher::~TDDeviceEventDispatcher() { this->wait(); } -TDDeviceEventDispatcher::TDDeviceEventDispatcher(const CallbackStruct &data, int id, int m, const std::string &strD) -:CallbackDispatcher(data), deviceId(id), method(m), strData(strD) {} - void TDDeviceEventDispatcher::run() { d.event(deviceId, method, strData.c_str(), d.id, d.context); } + TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(const CallbackStruct &data, int id, int event, int type) -:CallbackDispatcher(data), deviceId(id), changeEvent(event), changeType(type) {} +:Thread(), d(data), deviceId(id), changeEvent(event), changeType(type) +{ + this->start(); +} + +TDDeviceChangeEventDispatcher::~TDDeviceChangeEventDispatcher() { + this->wait(); +} void TDDeviceChangeEventDispatcher::run() { d.event(deviceId, changeEvent, changeType, d.id, d.context); } TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher(const CallbackStruct &data, const std::string &strD, int id) -:CallbackDispatcher(data), controllerId(id), strData(strD) {} +:Thread(), d(data), controllerId(id), strData(strD) +{ + this->start(); +} + +TDRawDeviceEventDispatcher::~TDRawDeviceEventDispatcher() { + this->wait(); +} void TDRawDeviceEventDispatcher::run() { d.event(strData.c_str(), controllerId, d.id, d.context); diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 2516d1e9..a18059e2 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -21,37 +21,35 @@ namespace TelldusCore { void *context; }; - template class CallbackDispatcher: public Thread { - public: - CallbackDispatcher(const CallbackStruct &data); - virtual ~CallbackDispatcher(); - protected: - CallbackStruct d; - }; - - class TDDeviceEventDispatcher : public CallbackDispatcher { + class TDDeviceEventDispatcher : public Thread { public: TDDeviceEventDispatcher(const CallbackStruct &data, int deviceId, int method, const std::string &strData); + virtual ~TDDeviceEventDispatcher(); protected: virtual void run(); private: + CallbackStruct d; int deviceId, method; std::string strData; }; - class TDDeviceChangeEventDispatcher : public CallbackDispatcher { + class TDDeviceChangeEventDispatcher : public Thread { public: TDDeviceChangeEventDispatcher(const CallbackStruct &data, int deviceId, int changeEvent, int changeType); + virtual ~TDDeviceChangeEventDispatcher(); protected: virtual void run(); private: + CallbackStruct d; int deviceId, changeEvent, changeType; }; - class TDRawDeviceEventDispatcher : public CallbackDispatcher { + class TDRawDeviceEventDispatcher : public Thread { public: TDRawDeviceEventDispatcher(const CallbackStruct &data, const std::string &strData, int controllerId); + virtual ~TDRawDeviceEventDispatcher(); protected: virtual void run(); private: + CallbackStruct d; int controllerId; std::string strData; }; diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 52313c1c..b77717c8 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -75,10 +75,6 @@ void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstri list.push_back(ptr); } } - std::list >::const_iterator it = list.begin(); - for (; it != list.end(); ++it) { - (*it)->wait(); - } } void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType){ @@ -90,10 +86,6 @@ void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int list.push_back(ptr); } } - std::list >::const_iterator it = list.begin(); - for (; it != list.end(); ++it) { - (*it)->wait(); - } } void Client::callbackRawEvent(std::wstring command, int controllerId){ @@ -105,10 +97,6 @@ void Client::callbackRawEvent(std::wstring command, int controllerId){ list.push_back(ptr); } } - std::list >::const_iterator it = list.begin(); - for (; it != list.end(); ++it) { - (*it)->wait(); - } } bool Client::getBoolFromService(const Message &msg) { From ba56976c9fa7d64239280604001dfc277bac36e9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Nov 2010 10:47:04 +0000 Subject: [PATCH 0518/2215] Added virtual function ProtocolSartano::getStringForCode() --- telldus-core/service/ProtocolSartano.cpp | 8 ++++++-- telldus-core/service/ProtocolSartano.h | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index a10a225f..12f679e3 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -5,9 +5,13 @@ int ProtocolSartano::methods() const { } std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) { - - std::string strReturn("S"); std::wstring strCode = this->getStringParameter(L"code", L""); + return getStringForCode(strCode, method); +} + +std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int method) { + + std::string strReturn("S"); for (size_t i = 0; i < strCode.length(); ++i) { if (strCode[i] == L'1') { diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index b2a14fdb..ae91acde 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -8,6 +8,9 @@ class ProtocolSartano : public Protocol public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +protected: + std::string getStringForCode(const std::wstring &code, int method); }; -#endif //PROTOCOLSARTANO_H \ No newline at end of file +#endif //PROTOCOLSARTANO_H From fce9214a71a84387b7194d6ad164ea9ba83bbf6c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Nov 2010 10:54:32 +0000 Subject: [PATCH 0519/2215] Added protocol Yidong --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 153 +++++++++++++----------- telldus-core/service/ProtocolYidong.cpp | 26 ++++ telldus-core/service/ProtocolYidong.h | 12 ++ 4 files changed, 120 insertions(+), 73 deletions(-) create mode 100644 telldus-core/service/ProtocolYidong.cpp create mode 100644 telldus-core/service/ProtocolYidong.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 486749fd..c410dc99 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -40,6 +40,8 @@ SET( telldus-service_protocol_SRCS ProtocolWaveman.cpp ProtocolX10.h ProtocolX10.cpp + ProtocolYidong.h + ProtocolYidong.cpp ) SET( telldus-service_HDRS ClientCommunicationHandler.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index db330659..3d2ebd33 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -12,6 +12,7 @@ #include "ProtocolUpm.h" #include "ProtocolWaveman.h" #include "ProtocolX10.h" +#include "ProtocolYidong.h" #include "Strings.h" #include @@ -24,7 +25,7 @@ public: Protocol::Protocol(){ - d = new PrivateData; + d = new PrivateData; } Protocol::~Protocol(void) { @@ -35,7 +36,7 @@ std::wstring Protocol::model() const { std::wstring strModel = d->model; //Strip anything after : if it is found size_t pos = strModel.find(L":"); - if (pos != std::wstring::npos) { + if (pos != std::wstring::npos) { strModel = strModel.substr(0, pos); } @@ -77,39 +78,42 @@ int Protocol::getIntParameter(const std::wstring &name, int min, int max) const } Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ - + if(TelldusCore::comparei(protocolname, L"arctech")){ - return new ProtocolNexa(); - - } else if (TelldusCore::comparei(protocolname, L"brateck")) { - return new ProtocolBrateck(); - - } else if (TelldusCore::comparei(protocolname, L"everflourish")) { - return new ProtocolEverflourish(); - - } else if (TelldusCore::comparei(protocolname, L"fuhaote")) { - return new ProtocolFuhaote(); - - } else if (TelldusCore::comparei(protocolname, L"ikea")) { - return new ProtocolIkea(); - - } else if (TelldusCore::comparei(protocolname, L"risingsun")) { - return new ProtocolRisingSun(); - - } else if (TelldusCore::comparei(protocolname, L"sartano")) { - return new ProtocolSartano(); - - } else if (TelldusCore::comparei(protocolname, L"silvanchip")) { - return new ProtocolSilvanChip(); - - } else if (TelldusCore::comparei(protocolname, L"upm")) { - return new ProtocolUpm(); - - } else if (TelldusCore::comparei(protocolname, L"waveman")) { - return new ProtocolWaveman(); - - } else if (TelldusCore::comparei(protocolname, L"x10")) { - return new ProtocolX10(); + return new ProtocolNexa(); + + } else if (TelldusCore::comparei(protocolname, L"brateck")) { + return new ProtocolBrateck(); + + } else if (TelldusCore::comparei(protocolname, L"everflourish")) { + return new ProtocolEverflourish(); + + } else if (TelldusCore::comparei(protocolname, L"fuhaote")) { + return new ProtocolFuhaote(); + + } else if (TelldusCore::comparei(protocolname, L"ikea")) { + return new ProtocolIkea(); + + } else if (TelldusCore::comparei(protocolname, L"risingsun")) { + return new ProtocolRisingSun(); + + } else if (TelldusCore::comparei(protocolname, L"sartano")) { + return new ProtocolSartano(); + + } else if (TelldusCore::comparei(protocolname, L"silvanchip")) { + return new ProtocolSilvanChip(); + + } else if (TelldusCore::comparei(protocolname, L"upm")) { + return new ProtocolUpm(); + + } else if (TelldusCore::comparei(protocolname, L"waveman")) { + return new ProtocolWaveman(); + + } else if (TelldusCore::comparei(protocolname, L"x10")) { + return new ProtocolX10(); + + } else if (TelldusCore::comparei(protocolname, L"yidong")) { + return new ProtocolYidong(); } return 0; @@ -119,45 +123,48 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr std::list parameters; if(TelldusCore::comparei(protocolName, L"arctech")){ - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"brateck")) { - parameters.push_back("house"); - - } else if (TelldusCore::comparei(protocolName, L"everflourish")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { - parameters.push_back("code"); - - } else if (TelldusCore::comparei(protocolName, L"ikea")) { - parameters.push_back("system"); - parameters.push_back("units"); - //parameters.push_back("fade"); - - } else if (TelldusCore::comparei(protocolName, L"risingsun")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"sartano")) { - parameters.push_back("code"); - - } else if (TelldusCore::comparei(protocolName, L"silvanchip")) { - parameters.push_back("house"); - - } else if (TelldusCore::comparei(protocolName, L"upm")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"waveman")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"x10")) { - parameters.push_back("house"); - parameters.push_back("unit"); + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"brateck")) { + parameters.push_back("house"); + + } else if (TelldusCore::comparei(protocolName, L"everflourish")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { + parameters.push_back("code"); + + } else if (TelldusCore::comparei(protocolName, L"ikea")) { + parameters.push_back("system"); + parameters.push_back("units"); + //parameters.push_back("fade"); + + } else if (TelldusCore::comparei(protocolName, L"risingsun")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"sartano")) { + parameters.push_back("code"); + + } else if (TelldusCore::comparei(protocolName, L"silvanchip")) { + parameters.push_back("house"); + + } else if (TelldusCore::comparei(protocolName, L"upm")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"waveman")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"x10")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"yidong")) { + parameters.push_back("unit"); } return parameters; diff --git a/telldus-core/service/ProtocolYidong.cpp b/telldus-core/service/ProtocolYidong.cpp new file mode 100644 index 00000000..94ff57d5 --- /dev/null +++ b/telldus-core/service/ProtocolYidong.cpp @@ -0,0 +1,26 @@ +#include "ProtocolYidong.h" +#include + +std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { + int intCode = this->getIntParameter(L"unit", 1, 4); + std::wstring strCode = L"111"; + + switch(intCode) { + case 1: + strCode.append(L"0010"); + break; + case 2: + strCode.append(L"0001"); + break; + case 3: + strCode.append(L"0100"); + break; + case 4: + strCode.append(L"1000"); + break; + } + + strCode.append(L"110"); + printf("Code: %s\n", std::string(strCode.begin(), strCode.end()).c_str()); + return getStringForCode(strCode, method); +} diff --git a/telldus-core/service/ProtocolYidong.h b/telldus-core/service/ProtocolYidong.h new file mode 100644 index 00000000..580d250f --- /dev/null +++ b/telldus-core/service/ProtocolYidong.h @@ -0,0 +1,12 @@ +#ifndef PROTOCOLYIDONG_H +#define PROTOCOLYIDONG_H + +#include "ProtocolSartano.h" + +class ProtocolYidong : public ProtocolSartano +{ +public: + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); +}; + +#endif //PROTOCOLYIDONG_H From 3f67606e5ad49057f4b56bcc4751401648f83096 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Nov 2010 11:15:37 +0000 Subject: [PATCH 0520/2215] Removed debug print --- telldus-core/service/ProtocolYidong.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/telldus-core/service/ProtocolYidong.cpp b/telldus-core/service/ProtocolYidong.cpp index 94ff57d5..3961a29c 100644 --- a/telldus-core/service/ProtocolYidong.cpp +++ b/telldus-core/service/ProtocolYidong.cpp @@ -1,5 +1,4 @@ #include "ProtocolYidong.h" -#include std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { int intCode = this->getIntParameter(L"unit", 1, 4); @@ -21,6 +20,5 @@ std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Contro } strCode.append(L"110"); - printf("Code: %s\n", std::string(strCode.begin(), strCode.end()).c_str()); return getStringForCode(strCode, method); } From a11b36bf9caa9dffc7c40966a7910f91b3127d63 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Nov 2010 14:30:34 +0000 Subject: [PATCH 0521/2215] Added static function ProtocolNexa::getStringSelflearningForCode() --- telldus-core/service/ProtocolNexa.cpp | 8 ++++++-- telldus-core/service/ProtocolNexa.h | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 1dc7f3da..fe4265d4 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -60,13 +60,17 @@ std::string ProtocolNexa::getStringBell() { } std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { + int intHouse = getIntParameter(L"house", 1, 67108863); + int intCode = getIntParameter(L"unit", 1, 16)-1; + return getStringSelflearningForCode(intHouse, intCode, method, level); +} + +std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode, int method, unsigned char level) { const unsigned char START[] = {'T',127,255,24,1,0}; // const char START[] = {'T',130,255,26,24,0}; std::string strMessage(reinterpret_cast(START)); strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses - int intHouse = getIntParameter(L"house", 1, 67108863); - int intCode = getIntParameter(L"unit", 1, 16)-1; std::string m; for (int i = 25; i >= 0; --i) { diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 33840558..2e540976 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -6,7 +6,7 @@ class ProtocolNexa : public Protocol { public: - int methods() const; + virtual int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); protected: @@ -15,6 +15,7 @@ protected: std::string getStringBell(); virtual std::string getOffCode() const; static std::string getCodeSwitchTuple(int code); + static std::string getStringSelflearningForCode(int house, int unit, int method, unsigned char data); }; #endif //PROTOCOLNEXA_H From 27841797e410b9b00ce693a1216b6dfbe4f9f622 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Nov 2010 14:33:40 +0000 Subject: [PATCH 0522/2215] Added protocol Comen --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/Protocol.cpp | 8 ++++++++ telldus-core/service/ProtocolComen.cpp | 12 ++++++++++++ telldus-core/service/ProtocolComen.h | 13 +++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 telldus-core/service/ProtocolComen.cpp create mode 100644 telldus-core/service/ProtocolComen.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index c410dc99..8c35b10f 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -20,6 +20,8 @@ SET( telldus-service_protocol_SRCS Protocol.cpp ProtocolBrateck.h ProtocolBrateck.cpp + ProtocolComen.h + ProtocolComen.cpp ProtocolEverflourish.h ProtocolEverflourish.cpp ProtocolFuhaote.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 3d2ebd33..84949e3b 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -2,6 +2,7 @@ #include "../client/telldus-core.h" #include "ProtocolBrateck.h" +#include "ProtocolComen.h" #include "ProtocolEverflourish.h" #include "ProtocolFuhaote.h" #include "ProtocolIkea.h" @@ -85,6 +86,9 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ } else if (TelldusCore::comparei(protocolname, L"brateck")) { return new ProtocolBrateck(); + } else if (TelldusCore::comparei(protocolname, L"comen")) { + return new ProtocolComen(); + } else if (TelldusCore::comparei(protocolname, L"everflourish")) { return new ProtocolEverflourish(); @@ -129,6 +133,10 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"brateck")) { parameters.push_back("house"); + } else if (TelldusCore::comparei(protocolName, L"comen")) { + parameters.push_back("house"); + parameters.push_back("unit"); + } else if (TelldusCore::comparei(protocolName, L"everflourish")) { parameters.push_back("house"); parameters.push_back("unit"); diff --git a/telldus-core/service/ProtocolComen.cpp b/telldus-core/service/ProtocolComen.cpp new file mode 100644 index 00000000..cfaf99df --- /dev/null +++ b/telldus-core/service/ProtocolComen.cpp @@ -0,0 +1,12 @@ +#include "ProtocolComen.h" + +int ProtocolComen::methods() const { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); +} + +std::string ProtocolComen::getStringForMethod(int method, unsigned char level, Controller *) { + int intHouse = getIntParameter(L"house", 1, 33554431); + intHouse <<= 1; //They seem to only accept even codes? + int intCode = getIntParameter(L"unit", 1, 16)-1; + return getStringSelflearningForCode(intHouse, intCode, method, level); +} diff --git a/telldus-core/service/ProtocolComen.h b/telldus-core/service/ProtocolComen.h new file mode 100644 index 00000000..35bdab8a --- /dev/null +++ b/telldus-core/service/ProtocolComen.h @@ -0,0 +1,13 @@ +#ifndef PROTOCOLCOMEN_H +#define PROTOCOLCOMEN_H + +#include "ProtocolNexa.h" +#include + +class ProtocolComen : public ProtocolNexa { +public: + virtual int methods() const; + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); +}; + +#endif //PROTOCOLCOMEN_H From fa7879d76955e783f7491ef4aaf1ec7e62748f8f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 10:42:57 +0000 Subject: [PATCH 0523/2215] Added file tellstick.conf --- telldus-core/client/tellstick.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 telldus-core/client/tellstick.conf diff --git a/telldus-core/client/tellstick.conf b/telldus-core/client/tellstick.conf new file mode 100644 index 00000000..28301848 --- /dev/null +++ b/telldus-core/client/tellstick.conf @@ -0,0 +1,10 @@ +device { + id = 1 + name = "Example device" + protocol = "arctech" + model = "codeswitch" + parameters { + house = "A" + unit = "1" + } +} From e7f1e377e528b109ab21310b270b7027abe7b1bb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 10:45:43 +0000 Subject: [PATCH 0524/2215] Added empty file telldus-core.conf --- telldus-core/client/telldus-core.conf | 1 + 1 file changed, 1 insertion(+) create mode 100644 telldus-core/client/telldus-core.conf diff --git a/telldus-core/client/telldus-core.conf b/telldus-core/client/telldus-core.conf new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/telldus-core/client/telldus-core.conf @@ -0,0 +1 @@ + From 1bfec7d9b5177c77cb3f76ab62590e80902cba52 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 11:10:08 +0000 Subject: [PATCH 0525/2215] Added tool tdadmin to the build --- telldus-core/CMakeLists.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 82d31c3c..6ec766a4 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -24,9 +24,8 @@ IF (WIN32) SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") ENDIF (WIN32) -SET(BUILD_RFCMD FALSE CACHE BOOL "Build rfcmd") - SET(BUILD_TDTOOL TRUE CACHE BOOL "Build tdtool") +SET(BUILD_TDADMIN TRUE CACHE BOOL "Build tdadmin") SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") @@ -42,7 +41,6 @@ ADD_SUBDIRECTORY(client) IF(BUILD_TDTOOL) ADD_SUBDIRECTORY(tdtool) ENDIF(BUILD_TDTOOL) - -IF(BUILD_RFCMD) -# ADD_SUBDIRECTORY(rfcmd) -ENDIF(BUILD_RFCMD) +IF(BUILD_TDADMIN) + ADD_SUBDIRECTORY(tdadmin) +ENDIF(BUILD_TDADMIN) From 2951bf6bfd08574143575ebf0e3bdc53c3d5d89d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 11:13:33 +0000 Subject: [PATCH 0526/2215] Don't build the tools by default on Windows --- telldus-core/CMakeLists.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 6ec766a4..4da35b7b 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -24,8 +24,13 @@ IF (WIN32) SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") ENDIF (WIN32) -SET(BUILD_TDTOOL TRUE CACHE BOOL "Build tdtool") -SET(BUILD_TDADMIN TRUE CACHE BOOL "Build tdadmin") +IF (WIN32) + SET(TOOLS_DEFAULT FALSE) +ELSE (WIN32) + SET(TOOLS_DEFAULT TRUE) +ENDIF (WIN32) +SET(BUILD_TDTOOL ${TOOLS_DEFAULT} CACHE BOOL "Build tdtool") +SET(BUILD_TDADMIN ${TOOLS_DEFAULT} CACHE BOOL "Build tdadmin") SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") From 6f56394ede2075ef9ece318b62a99279fc797cc7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 11:14:18 +0000 Subject: [PATCH 0527/2215] The configuration files should be handled by the service, not the client --- telldus-core/client/CMakeLists.txt | 16 ---------------- telldus-core/service/CMakeLists.txt | 12 ++++++++++++ .../{client => service}/telldus-core.conf | 0 telldus-core/{client => service}/tellstick.conf | 0 4 files changed, 12 insertions(+), 16 deletions(-) rename telldus-core/{client => service}/telldus-core.conf (100%) rename telldus-core/{client => service}/tellstick.conf (100%) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 2abdb6c7..589c0cf7 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -114,19 +114,3 @@ IF (UNIX) ) ENDIF (UNIX) -IF (UNIX AND NOT APPLE) - SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) - SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) - SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) - - INSTALL(FILES tellstick.conf - DESTINATION ${SYSCONF_INSTALL_DIR} - ) - INSTALL(FILES telldus-core.conf - DESTINATION ${STATE_INSTALL_DIR} - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE - ) - INSTALL(FILES 99-tellstick.rules - DESTINATION ${UDEV_RULES_DIR} - ) -ENDIF (UNIX AND NOT APPLE) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 8c35b10f..97ec9ebe 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -171,3 +171,15 @@ IF (APPLE) ) ENDIF (APPLE) +IF (UNIX AND NOT APPLE) + SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) + SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) + + INSTALL(FILES tellstick.conf + DESTINATION ${SYSCONF_INSTALL_DIR} + ) + INSTALL(FILES telldus-core.conf + DESTINATION ${STATE_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE + ) +ENDIF (UNIX AND NOT APPLE) diff --git a/telldus-core/client/telldus-core.conf b/telldus-core/service/telldus-core.conf similarity index 100% rename from telldus-core/client/telldus-core.conf rename to telldus-core/service/telldus-core.conf diff --git a/telldus-core/client/tellstick.conf b/telldus-core/service/tellstick.conf similarity index 100% rename from telldus-core/client/tellstick.conf rename to telldus-core/service/tellstick.conf From 4fc60e3d353eef2f23ae1da7e17c3e2b38e2e556 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 11:28:40 +0000 Subject: [PATCH 0528/2215] Install the udev and udev helper script in the project tdadmin --- telldus-core/service/05-tellstick.rules | 2 -- telldus-core/tdadmin/05-tellstick.rules | 2 ++ telldus-core/tdadmin/CMakeLists.txt | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) delete mode 100644 telldus-core/service/05-tellstick.rules create mode 100644 telldus-core/tdadmin/05-tellstick.rules diff --git a/telldus-core/service/05-tellstick.rules b/telldus-core/service/05-tellstick.rules deleted file mode 100644 index e806dc1a..00000000 --- a/telldus-core/service/05-tellstick.rules +++ /dev/null @@ -1,2 +0,0 @@ -BUS=="usb", ID_VENDOR_ID=="1781" RUN+="/usr/share/telldus-core/helpers/udev.sh" - diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules new file mode 100644 index 00000000..6f8db78a --- /dev/null +++ b/telldus-core/tdadmin/05-tellstick.rules @@ -0,0 +1,2 @@ +BUS=="usb", ID_VENDOR_ID=="1781" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" + diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt index c79c507c..e2ecc623 100644 --- a/telldus-core/tdadmin/CMakeLists.txt +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -50,3 +50,17 @@ IF (UNIX) ENDIF (UNIX) INSTALL(TARGETS tdadmin RUNTIME DESTINATION sbin) + +IF (UNIX AND NOT APPLE) + SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/05-tellstick.rules + ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules + ) + INSTALL(FILES ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules + DESTINATION ${UDEV_RULES_DIR} + ) + INSTALL(PROGRAMS udev.sh + DESTINATION share/telldus-core/helpers/ + ) +ENDIF (UNIX AND NOT APPLE) From b6a861c26a9a7944d551999e5838d37089f9a66e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 12:44:16 +0000 Subject: [PATCH 0529/2215] Added meta information files --- telldus-core/AUTHORS | 7 ++ telldus-core/INSTALL | 51 +++++++++++++ telldus-core/LICENSE | 165 +++++++++++++++++++++++++++++++++++++++++++ telldus-core/README | 30 ++++++++ 4 files changed, 253 insertions(+) create mode 100644 telldus-core/AUTHORS create mode 100644 telldus-core/INSTALL create mode 100644 telldus-core/LICENSE create mode 100644 telldus-core/README diff --git a/telldus-core/AUTHORS b/telldus-core/AUTHORS new file mode 100644 index 00000000..58bd0e4e --- /dev/null +++ b/telldus-core/AUTHORS @@ -0,0 +1,7 @@ +telldus-core has been developed by : + + Micke Prag + Fredrik Jacobsson + Stefan Persson + +The package is maintained by Micke Prag diff --git a/telldus-core/INSTALL b/telldus-core/INSTALL new file mode 100644 index 00000000..9d2b0b4a --- /dev/null +++ b/telldus-core/INSTALL @@ -0,0 +1,51 @@ +Unpacking +--------- + +Unpack the archive if you have not done so already: + + cd /usr/src + gunzip telldus-core-{version}.tar.gz #Change {version} to the downloaded version + tar xvf telldus-core-{version}.tar + +This creates the directory /usr/src/telldus-core-{version} containing the files +from the archive. We only support the GNU version of tar archiving utility. Note +on some systems it is called gtar. + +Configuring +----------- + +Telldus Core is built using CMake (http://www.cmake.org), version 2.4.0 is the +minimum required version. This means there is no configure-script, but you +need to run cmake. + +To configure telldus-core for your machine type: + + cmake . + +in the package directory. + +By default, Telldus Core is configured for installation in the /usr/local +directory, but this can be changed by using the -DCMAKE_INSTALL_PREFIX=/usr +option. Alternatively, the DESTDIR="/opt" option can be used to specify a "local" +installation within the source directory when running "make install". + +Building +-------- + +To create the library and compile all the tools type: + + make + +If you did not configure Telldus Core using the -DCMAKE_INSTALL_PREFIX=/usr +option, you need to install the library and tools in the appropriate place. To +do this, type: + + su -c "make install" + +and enter the root password. + +If you want to install in another directory, type: + + su -c "make DESTDIR=/opt install" + +Note that on some systems the make utility is named differently, e.g. gmake. diff --git a/telldus-core/LICENSE b/telldus-core/LICENSE new file mode 100644 index 00000000..f0156c53 --- /dev/null +++ b/telldus-core/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/telldus-core/README b/telldus-core/README new file mode 100644 index 00000000..5778ee2b --- /dev/null +++ b/telldus-core/README @@ -0,0 +1,30 @@ +This is Telldus Core version {version} + +Telldus Core is the driver and tools for controlling a Telldus Technologies +TellStick. It does not containing any GUI tools which makes it suitable for +server use. + + +INSTALLING Telldus Core + +On Windows, if you want to install the precompiles binary packages, simply +launch the package and follow the instructions in the installation wizard. + +If you have a source package (a .tag.gz file), follow the instruction in the +INSTALL file. + + +CONFIGURATION AND TOOLS + +Once Telldus Core is installed, we suggest that you start by adding the devices +you want to control. + +On Windows, this is done with the tool TelldusSetup. On Linux this is done in +the file /etc/tellstick.conf. + +Telldus Core installs the tool tdtool for controlling devices with TellStick. +Have a look in the man page for a description how to use it: + + man tdtool + +TellStick is a trademark of Telldus Technologies AB From bb9307b8ae5cdfaa94b764bbc78959593840194f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 14:10:04 +0000 Subject: [PATCH 0530/2215] Do install the telldusd binary --- telldus-core/service/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 97ec9ebe..df937ae4 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -172,6 +172,7 @@ IF (APPLE) ENDIF (APPLE) IF (UNIX AND NOT APPLE) + INSTALL(TARGETS ${telldus-service_TARGET} RUNTIME DESTINATION sbin) SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) From 83aa0dcc47204b7dd101ca9d72390f0700ff857b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 17:44:16 +0000 Subject: [PATCH 0531/2215] Added osx specific main.cpp --- telldus-core/service/CMakeLists.txt | 2 +- telldus-core/service/main_mac.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 telldus-core/service/main_mac.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index df937ae4..c9eac37a 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -86,7 +86,7 @@ IF (APPLE) #### Mac OS X #### TelldusCommon ) LIST(APPEND telldus-service_SRCS - main_unix.cpp + main_mac.cpp ConnectionListener_unix.cpp ControllerListener_mac.cpp Event_unix.cpp diff --git a/telldus-core/service/main_mac.cpp b/telldus-core/service/main_mac.cpp new file mode 100644 index 00000000..4527225e --- /dev/null +++ b/telldus-core/service/main_mac.cpp @@ -0,0 +1,25 @@ +#include "TelldusMain.h" +#include +#include + +TelldusMain tm; + +void shutdownHandler(int onSignal) { + printf("Shutting down\n"); + tm.stop(); +} + +void sigpipeHandler(int onSignal) { + printf("SIGPIPE received\n"); +} + +int main(int argc, char **argv) { + /* Install signal traps for proper shutdown */ + signal(SIGTERM, shutdownHandler); + signal(SIGINT, shutdownHandler); + signal(SIGPIPE, sigpipeHandler); + + tm.start(); + printf("telldusd stopped gracefully\n"); + return 0; +} From 2e5caf4960b7ff892f322887a3a176b57a522158 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 18:56:24 +0000 Subject: [PATCH 0532/2215] Fork to a daemon --- telldus-core/service/main_unix.cpp | 78 +++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 4527225e..813b5a7d 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -1,25 +1,79 @@ #include "TelldusMain.h" #include +#include #include +#include +#include +#include +#include + +#define DAEMON_NAME "telldusd" +#define PID_FILE "/var/run/" DAEMON_NAME ".pid" TelldusMain tm; -void shutdownHandler(int onSignal) { - printf("Shutting down\n"); - tm.stop(); -} - -void sigpipeHandler(int onSignal) { - printf("SIGPIPE received\n"); +void signalHandler(int sig) { + switch(sig) { + case SIGHUP: + syslog(LOG_WARNING, "Received SIGHUP signal."); + break; + case SIGTERM: + syslog(LOG_WARNING, "Received SIGTERM signal."); + syslog(LOG_WARNING, "Shutting down"); + tm.stop(); + break; + case SIGPIPE: + syslog(LOG_WARNING, "Received SIGPIPE signal."); + break; + default: + syslog(LOG_WARNING, "Unhandled signal (%d) %s", strsignal(sig)); + break; + } } int main(int argc, char **argv) { + pid_t pid, sid; + + pid = fork(); + if (pid < 0) { + exit(EXIT_FAILURE); + } + if (pid > 0) { + //We are the parent + exit(EXIT_SUCCESS); + } + + setlogmask(LOG_UPTO(LOG_INFO)); + openlog(DAEMON_NAME, LOG_CONS, LOG_USER); + + syslog(LOG_INFO, "%s daemon starting up", DAEMON_NAME); + + /* Change the file mode mask */ + umask(0); + + sid = setsid(); + + if (sid < 0) { + //Something went wrong + exit(EXIT_FAILURE); + } + + /* Change the current working directory */ + if ((chdir("/")) < 0) { + exit(EXIT_FAILURE); + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + /* Install signal traps for proper shutdown */ - signal(SIGTERM, shutdownHandler); - signal(SIGINT, shutdownHandler); - signal(SIGPIPE, sigpipeHandler); + signal(SIGTERM, signalHandler); + signal(SIGINT, signalHandler); + signal(SIGPIPE, signalHandler); tm.start(); - printf("telldusd stopped gracefully\n"); - return 0; + + syslog(LOG_INFO, "%s daemon exited", DAEMON_NAME); + exit(EXIT_SUCCESS); } From a6769ad91b0cd0b7f06e529105f936ff7dc5c25c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 11 Nov 2010 21:00:38 +0000 Subject: [PATCH 0533/2215] Write the pid file on startup --- telldus-core/service/main_unix.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 813b5a7d..e4e65d54 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -33,6 +33,7 @@ void signalHandler(int sig) { int main(int argc, char **argv) { pid_t pid, sid; + FILE *fd; pid = fork(); if (pid < 0) { @@ -51,6 +52,15 @@ int main(int argc, char **argv) { /* Change the file mode mask */ umask(0); + /* Record the pid */ + fd = fopen(PID_FILE,"w"); + if (!fd) { + syslog(LOG_ERR, "Could not write pid file"); + exit(EXIT_FAILURE); + } + fprintf(fd,"%d\n",getpid()); + fclose(fd); + sid = setsid(); if (sid < 0) { From b1f0e4ba5a7d12d01b0514eba109172b2356a974 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 12 Nov 2010 08:16:59 +0000 Subject: [PATCH 0534/2215] Fixed missing parameter for output to syslog on unhandled signal --- telldus-core/service/main_unix.cpp | 42 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index e4e65d54..b7086806 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -14,27 +14,27 @@ TelldusMain tm; void signalHandler(int sig) { switch(sig) { - case SIGHUP: - syslog(LOG_WARNING, "Received SIGHUP signal."); - break; - case SIGTERM: - syslog(LOG_WARNING, "Received SIGTERM signal."); + case SIGHUP: + syslog(LOG_WARNING, "Received SIGHUP signal."); + break; + case SIGTERM: + syslog(LOG_WARNING, "Received SIGTERM signal."); syslog(LOG_WARNING, "Shutting down"); tm.stop(); - break; + break; case SIGPIPE: syslog(LOG_WARNING, "Received SIGPIPE signal."); break; - default: - syslog(LOG_WARNING, "Unhandled signal (%d) %s", strsignal(sig)); - break; - } + default: + syslog(LOG_WARNING, "Unhandled signal (%d) %s", sig, strsignal(sig)); + break; + } } int main(int argc, char **argv) { pid_t pid, sid; FILE *fd; - + pid = fork(); if (pid < 0) { exit(EXIT_FAILURE); @@ -43,15 +43,15 @@ int main(int argc, char **argv) { //We are the parent exit(EXIT_SUCCESS); } - + setlogmask(LOG_UPTO(LOG_INFO)); - openlog(DAEMON_NAME, LOG_CONS, LOG_USER); + openlog(DAEMON_NAME, LOG_CONS, LOG_USER); syslog(LOG_INFO, "%s daemon starting up", DAEMON_NAME); - + /* Change the file mode mask */ umask(0); - + /* Record the pid */ fd = fopen(PID_FILE,"w"); if (!fd) { @@ -60,30 +60,30 @@ int main(int argc, char **argv) { } fprintf(fd,"%d\n",getpid()); fclose(fd); - + sid = setsid(); - + if (sid < 0) { //Something went wrong exit(EXIT_FAILURE); } - + /* Change the current working directory */ if ((chdir("/")) < 0) { exit(EXIT_FAILURE); } - + close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); - + /* Install signal traps for proper shutdown */ signal(SIGTERM, signalHandler); signal(SIGINT, signalHandler); signal(SIGPIPE, signalHandler); tm.start(); - + syslog(LOG_INFO, "%s daemon exited", DAEMON_NAME); exit(EXIT_SUCCESS); } From 81cbc229888f8dbabcc55aadc5f8a4bda5d95486 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 12 Nov 2010 08:30:19 +0000 Subject: [PATCH 0535/2215] Don't exit on failure to write our pid file --- telldus-core/service/main_unix.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index b7086806..9ed5fb7e 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -56,7 +56,6 @@ int main(int argc, char **argv) { fd = fopen(PID_FILE,"w"); if (!fd) { syslog(LOG_ERR, "Could not write pid file"); - exit(EXIT_FAILURE); } fprintf(fd,"%d\n",getpid()); fclose(fd); @@ -73,6 +72,8 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } + //TODO: Reduce our permissions (change user) + close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); From 79132102afac3f74fc75afb2978aa8542967130b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 12 Nov 2010 12:54:09 +0000 Subject: [PATCH 0536/2215] Let the parent write the pid file --- telldus-core/service/main_unix.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 9ed5fb7e..4124d90e 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -41,6 +41,16 @@ int main(int argc, char **argv) { } if (pid > 0) { //We are the parent + //Let the parent store the clients pid, + //This way anyone starting the daemon can read the pidfile immediately + + /* Record the pid */ + fd = fopen(PID_FILE,"w"); + if (!fd) { + syslog(LOG_ERR, "Could not write pid file"); + } + fprintf(fd,"%d\n",pid); + fclose(fd); exit(EXIT_SUCCESS); } @@ -52,14 +62,6 @@ int main(int argc, char **argv) { /* Change the file mode mask */ umask(0); - /* Record the pid */ - fd = fopen(PID_FILE,"w"); - if (!fd) { - syslog(LOG_ERR, "Could not write pid file"); - } - fprintf(fd,"%d\n",getpid()); - fclose(fd); - sid = setsid(); if (sid < 0) { From aa8fa0c4517e4a414b9796498a6b271ced8ba4d2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 16 Nov 2010 09:40:09 +0000 Subject: [PATCH 0537/2215] Relocated the function wideToInteger to Strings. --- telldus-core/common/Message.cpp | 8 -------- telldus-core/common/Message.h | 1 - telldus-core/common/Strings.cpp | 8 ++++++++ telldus-core/common/Strings.h | 2 ++ 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 7cb30bd9..290be250 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -91,11 +91,3 @@ int Message::takeInt(std::wstring *message) { message->erase(0, index+1); return value; } - -int Message::wideToInteger(const std::wstring &input){ - std::wstringstream inputstream; - inputstream << input; - int retval; - inputstream >> retval; - return retval; -} diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 3217c84f..8ae7991a 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -22,7 +22,6 @@ namespace TelldusCore { static std::wstring takeString(std::wstring *); static int takeInt(std::wstring *); - static int wideToInteger(const std::wstring &input); private: }; diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 89d3bea4..8be1af6d 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -28,6 +28,14 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { return stringA == stringB; } +int TelldusCore::wideToInteger(const std::wstring &input){ + std::wstringstream inputstream; + inputstream << input; + int retval; + inputstream >> retval; + return retval; +} + std::string TelldusCore::wideToString(const std::wstring &input) { std::string strReturn; diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index ca698b44..8b97792b 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -8,6 +8,8 @@ namespace TelldusCore { int charToInteger(const char *value); bool comparei(std::wstring stringA, std::wstring stringB); std::string wideToString(const std::wstring &input); + + int wideToInteger(const std::wstring &input); } #endif //STRING_H From 6910512aaefa79f7338768ef7aae6693a5a2fb4e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 16 Nov 2010 09:42:24 +0000 Subject: [PATCH 0538/2215] Basic support for groups in core. Still some locking/unlocking issues to discuss. --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Device.cpp | 7 ++ telldus-core/service/Device.h | 1 + telldus-core/service/DeviceManager.cpp | 101 +++++++++++++++++++++---- telldus-core/service/DeviceManager.h | 1 + telldus-core/service/Protocol.cpp | 15 +++- 6 files changed, 110 insertions(+), 17 deletions(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index c9eac37a..d0542206 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -26,6 +26,8 @@ SET( telldus-service_protocol_SRCS ProtocolEverflourish.cpp ProtocolFuhaote.h ProtocolFuhaote.cpp + ProtocolGroup.h + ProtocolGroup.cpp ProtocolIkea.h ProtocolIkea.cpp ProtocolNexa.h diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index d98bb621..93906a6a 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -119,6 +119,13 @@ std::wstring Device::getStateValue(){ return d->stateValue; } +int Device::getType(){ + if(d->model == L"group"){ + return TELLSTICK_TYPE_GROUP; + } + return TELLSTICK_TYPE_DEVICE; +} + /** * End Get-/Set */ diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 1a287c5e..75037d1a 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -30,6 +30,7 @@ public: void setProtocolName(const std::wstring &name); void setStateValue(int stateValue); void setLastSentCommand(int command, std::wstring value); + int getType(); static int maskUnsupportedMethods(int methods, int supportedMethods); static int methodId( const std::string &methodName ); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 124036c5..d879b37c 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -8,6 +8,7 @@ #include #include +#include typedef std::map DeviceMap; @@ -56,6 +57,7 @@ void DeviceManager::fillDevices(){ d->devices[id]->setParameter(L"units", d->set.getDeviceParameter(id, L"units")); d->devices[id]->setParameter(L"fade", d->set.getDeviceParameter(id, L"fade")); d->devices[id]->setParameter(L"system", d->set.getDeviceParameter(id, L"system")); + d->devices[id]->setParameter(L"devices", d->set.getDeviceParameter(id, L"devices")); } } @@ -112,9 +114,33 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - int methods = it->second->getMethods(); - return Device::maskUnsupportedMethods(methods, methodsSupported); + + int type; + int methods; + std::wstring deviceIds; + + { + //TODO: better way to lock (release) + TelldusCore::MutexLocker deviceLocker(it->second); + type = it->second->getType(); + methods = it->second->getMethods(); + deviceIds = it->second->getParameter(L"devices"); + } + if(type == TELLSTICK_TYPE_GROUP){ + + //get all methods that some device in the groups supports + std::wstring buffer; + std::wstringstream ss(deviceIds); + + while(ss >> buffer){ + int deviceId = TelldusCore::wideToInteger(buffer); + methods |= getDeviceMethods(deviceId, methodsSupported); + } + return methods; + } + else{ + return Device::maskUnsupportedMethods(methods, methodsSupported); + } } return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -281,7 +307,16 @@ int DeviceManager::getDeviceId(int deviceIndex) { int DeviceManager::getDeviceType(int deviceId){ - return TELLSTICK_TYPE_DEVICE; +TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getType(); + } + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } int DeviceManager::getPreferredControllerId(int deviceId){ @@ -327,20 +362,54 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ device = it->second; } //devicelist unlocked - Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - if(controller){ - int retval = device->doAction(action, data, controller); - if(retval == TELLSTICK_SUCCESS) { - std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); - if (this->triggerDeviceStateChange(deviceId, action, datastring)) { - device->setLastSentCommand(action, datastring); - d->set.setDeviceState(deviceId, action, datastring); - } + int retval = TELLSTICK_ERROR_UNKNOWN; + + if(device->getType() == TELLSTICK_TYPE_GROUP){ + deviceLocker = std::auto_ptr(0); //TODO better way? Must unlock here somehow though... + retval = doGroupAction(device->getParameter(L"devices"), action, data); + if(device != NULL){ //TODO, some kind of test here... that device still exists... + deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(device)); //TODO this isn't good either, device may have been deleted etc + } + else{ + retval = TELLSTICK_ERROR_UNKNOWN; } - return retval; - } else { - return TELLSTICK_ERROR_NOT_FOUND; } + else{ + Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); + if(controller){ + retval = device->doAction(action, data, controller); + } else { + return TELLSTICK_ERROR_NOT_FOUND; + } + } + if(retval == TELLSTICK_SUCCESS) { + std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); + if (this->triggerDeviceStateChange(deviceId, action, datastring)) { + device->setLastSentCommand(action, datastring); + d->set.setDeviceState(deviceId, action, datastring); + } + } + return retval; +} + +int DeviceManager::doGroupAction(const std::wstring deviceIds, int action, unsigned char data){ + int retval = TELLSTICK_SUCCESS; //TODO or no devices found? + + std::wstring buffer; + std::wstringstream ss(deviceIds); + + while(ss >> buffer){ + int deviceId = TelldusCore::wideToInteger(buffer); + int deviceReturnValue = doAction(deviceId, action, data); + + if(retval == TELLSTICK_SUCCESS){ + //if error(s), return the first error, but still try to continue the action with the other devices + //quite possible that some device don't support the current method + retval = deviceReturnValue; + } + + } + return retval; } int DeviceManager::removeDevice(int deviceId){ diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index b68f73a1..8ffa73dc 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -36,6 +36,7 @@ public: void handleControllerMessage(const ControllerEventData &event); private: + int doGroupAction(const std::wstring deviceIds, int action, unsigned char data); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); void fillDevices(void); diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 84949e3b..ab86acea 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -5,6 +5,7 @@ #include "ProtocolComen.h" #include "ProtocolEverflourish.h" #include "ProtocolFuhaote.h" +#include "ProtocolGroup.h" #include "ProtocolIkea.h" #include "ProtocolNexa.h" #include "ProtocolRisingSun.h" @@ -118,6 +119,13 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ } else if (TelldusCore::comparei(protocolname, L"yidong")) { return new ProtocolYidong(); + + } else if (TelldusCore::comparei(protocolname, L"group")) { + return new ProtocolGroup(); + } + + else if (TelldusCore::comparei(protocolname, L"scene")) { + return new ProtocolGroup(); //TODO } return 0; @@ -125,7 +133,6 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { std::list parameters; - if(TelldusCore::comparei(protocolName, L"arctech")){ parameters.push_back("house"); parameters.push_back("unit"); @@ -173,6 +180,12 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"yidong")) { parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"group")) { + parameters.push_back("devices"); + + } else if (TelldusCore::comparei(protocolName, L"scene")) { + //parameters.push_back("unit"); //TODO } return parameters; From d308ddaeb80494293a4c2023593d77655e5d9a0b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 16 Nov 2010 09:43:33 +0000 Subject: [PATCH 0539/2215] ...and the new group protocol too. --- telldus-core/service/ProtocolGroup.cpp | 9 +++++++++ telldus-core/service/ProtocolGroup.h | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 telldus-core/service/ProtocolGroup.cpp create mode 100644 telldus-core/service/ProtocolGroup.h diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp new file mode 100644 index 00000000..a832be1b --- /dev/null +++ b/telldus-core/service/ProtocolGroup.cpp @@ -0,0 +1,9 @@ +#include "ProtocolGroup.h" + +int ProtocolGroup::methods() const { + return 0; +} + +std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { + return ""; +} \ No newline at end of file diff --git a/telldus-core/service/ProtocolGroup.h b/telldus-core/service/ProtocolGroup.h new file mode 100644 index 00000000..b75e36e3 --- /dev/null +++ b/telldus-core/service/ProtocolGroup.h @@ -0,0 +1,16 @@ +#ifndef PROTOCOLGROUP_H +#define PROTOCOLGROUP_H + +#include "Protocol.h" + +class ProtocolGroup : public Protocol { +public: + virtual int methods() const; + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +}; + +#endif //PROTOCOLGROUP_H + + + From c54088b27c8cd655feb7b01e7530990d842be1bd Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 17 Nov 2010 08:53:46 +0000 Subject: [PATCH 0540/2215] Basic scene support added to core. --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Device.cpp | 9 ++++ telldus-core/service/DeviceManager.cpp | 73 ++++++++++++++++++++++---- telldus-core/service/DeviceManager.h | 3 +- telldus-core/service/Protocol.cpp | 5 +- telldus-core/service/ProtocolScene.cpp | 9 ++++ telldus-core/service/ProtocolScene.h | 16 ++++++ 7 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 telldus-core/service/ProtocolScene.cpp create mode 100644 telldus-core/service/ProtocolScene.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index d0542206..616d5b9c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -36,6 +36,8 @@ SET( telldus-service_protocol_SRCS ProtocolRisingSun.cpp ProtocolSartano.h ProtocolSartano.cpp + ProtocolScene.h + ProtocolScene.cpp ProtocolSilvanChip.h ProtocolSilvanChip.cpp ProtocolUpm.h diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 93906a6a..0020a916 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -162,6 +162,12 @@ int Device::maskUnsupportedMethods(int methods, int supportedMethods) { if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) { methods |= TELLSTICK_TURNON; } + + // Execute -> On + if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) { //TODO ok everywhere? + methods |= TELLSTICK_TURNON; + } + //Cut of the rest of the unsupported methods we don't have a fallback for return methods & supportedMethods; } @@ -179,5 +185,8 @@ int Device::methodId( const std::string &methodName ) { if (methodName.compare("dim") == 0) { return TELLSTICK_DIM; } + if (methodName.compare("execute") == 0) { + return TELLSTICK_EXECUTE; + } return 0; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index d879b37c..5a892b2a 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -118,6 +118,7 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ int type; int methods; std::wstring deviceIds; + std::wstring protocol; { //TODO: better way to lock (release) @@ -125,8 +126,9 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ type = it->second->getType(); methods = it->second->getMethods(); deviceIds = it->second->getParameter(L"devices"); + protocol = it->second->getProtocolName(); } - if(type == TELLSTICK_TYPE_GROUP){ + if(type == TELLSTICK_TYPE_GROUP && protocol != L"scene"){ //TODO would really like to be able to do this on protocol level instead of comparing protocol name here //get all methods that some device in the groups supports std::wstring buffer; @@ -363,10 +365,13 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } //devicelist unlocked int retval = TELLSTICK_ERROR_UNKNOWN; + std::wstring protocol = L""; if(device->getType() == TELLSTICK_TYPE_GROUP){ + std::wstring devices = device->getParameter(L"devices"); + protocol = device->getProtocolName(); deviceLocker = std::auto_ptr(0); //TODO better way? Must unlock here somehow though... - retval = doGroupAction(device->getParameter(L"devices"), action, data); + retval = doGroupAction(devices, action, data, protocol); if(device != NULL){ //TODO, some kind of test here... that device still exists... deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(device)); //TODO this isn't good either, device may have been deleted etc } @@ -382,7 +387,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return TELLSTICK_ERROR_NOT_FOUND; } } - if(retval == TELLSTICK_SUCCESS) { + if(retval == TELLSTICK_SUCCESS && protocol != L"scene") { //TODO move this check, or make a "scene constant" or something else, to make this more general std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); if (this->triggerDeviceStateChange(deviceId, action, datastring)) { device->setLastSentCommand(action, datastring); @@ -392,15 +397,25 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return retval; } -int DeviceManager::doGroupAction(const std::wstring deviceIds, int action, unsigned char data){ +int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigned char data, const std::wstring protocol){ int retval = TELLSTICK_SUCCESS; //TODO or no devices found? - std::wstring buffer; - std::wstringstream ss(deviceIds); + std::wstring singledevice; + std::wstringstream devicesstream(devices); - while(ss >> buffer){ - int deviceId = TelldusCore::wideToInteger(buffer); - int deviceReturnValue = doAction(deviceId, action, data); + while(std::getline(devicesstream, singledevice, L',')){ + + int deviceReturnValue = TELLSTICK_SUCCESS; + + if(protocol == L"scene" && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ //TODO action check neccessary? + deviceReturnValue = executeScene(singledevice); + } + else if(protocol == L"group"){ + int deviceId = TelldusCore::wideToInteger(singledevice); + if(deviceId > 0){ //todo, check, never 0 for devices, right? + deviceReturnValue = doAction(deviceId, action, data); + } + } if(retval == TELLSTICK_SUCCESS){ //if error(s), return the first error, but still try to continue the action with the other devices @@ -412,6 +427,44 @@ int DeviceManager::doGroupAction(const std::wstring deviceIds, int action, unsig return retval; } +int DeviceManager::executeScene(std::wstring singledevice){ + + /*std::wstring deviceIdPart = L""; + std::wstring methodPart = L""; + std::wstring dataPart = L""; + */ + std::wstringstream devicestream(singledevice); + + const int deviceParameterLength = 3; + std::wstring deviceParts[deviceParameterLength] = {L"", L"", L""}; + std::wstring devicePart = L""; + int i = 0; + while(std::getline(devicestream, devicePart, L':') && i < deviceParameterLength){ + deviceParts[i] = devicePart; + i++; + } + + if(deviceParts[0] == L"" || deviceParts[1] == L""){ + return TELLSTICK_ERROR_UNKNOWN; //malformed or missing parameter + } + + int deviceId = TelldusCore::wideToInteger(deviceParts[0]); + int method = Device::methodId(TelldusCore::wideToString(deviceParts[1])); //support methodparts both in the form of integers (e.g. TELLSTICK_TURNON) or text (e.g. "turnon") + if(method == 0){ + method = TelldusCore::wideToInteger(deviceParts[1]); + } + unsigned char devicedata = 0; + if(deviceParts[2] != L""){ + devicedata = TelldusCore::wideToInteger(deviceParts[2]); + } + + if(deviceId > 0 && method > 0){ //check for format error in parameter "devices" + return doAction(deviceId, method, devicedata); + } + + return TELLSTICK_ERROR_UNKNOWN; +} + int DeviceManager::removeDevice(int deviceId){ Device *device = 0; @@ -492,7 +545,7 @@ int DeviceManager::sendRawCommand(std::wstring command, int reserved){ } bool DeviceManager::triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { - if ( intDeviceState == TELLSTICK_BELL || intDeviceState == TELLSTICK_LEARN) { + if ( intDeviceState == TELLSTICK_BELL || intDeviceState == TELLSTICK_LEARN || intDeviceState == TELLSTICK_EXECUTE) { return false; } diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 8ffa73dc..09a67c65 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -36,7 +36,8 @@ public: void handleControllerMessage(const ControllerEventData &event); private: - int doGroupAction(const std::wstring deviceIds, int action, unsigned char data); + int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const std::wstring protocol); + int executeScene(std::wstring singledevice); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); void fillDevices(void); diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index ab86acea..e2552032 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -10,6 +10,7 @@ #include "ProtocolNexa.h" #include "ProtocolRisingSun.h" #include "ProtocolSartano.h" +#include "ProtocolScene.h" #include "ProtocolSilvanChip.h" #include "ProtocolUpm.h" #include "ProtocolWaveman.h" @@ -125,7 +126,7 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ } else if (TelldusCore::comparei(protocolname, L"scene")) { - return new ProtocolGroup(); //TODO + return new ProtocolScene(); } return 0; @@ -185,7 +186,7 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr parameters.push_back("devices"); } else if (TelldusCore::comparei(protocolName, L"scene")) { - //parameters.push_back("unit"); //TODO + parameters.push_back("devices"); } return parameters; diff --git a/telldus-core/service/ProtocolScene.cpp b/telldus-core/service/ProtocolScene.cpp new file mode 100644 index 00000000..c874023a --- /dev/null +++ b/telldus-core/service/ProtocolScene.cpp @@ -0,0 +1,9 @@ +#include "ProtocolScene.h" + +int ProtocolScene::methods() const { + return TELLSTICK_EXECUTE; +} + +std::string ProtocolScene::getStringForMethod(int method, unsigned char data, Controller *) { + return ""; +} \ No newline at end of file diff --git a/telldus-core/service/ProtocolScene.h b/telldus-core/service/ProtocolScene.h new file mode 100644 index 00000000..4b1b6903 --- /dev/null +++ b/telldus-core/service/ProtocolScene.h @@ -0,0 +1,16 @@ +#ifndef PROTOCOLSCENE_H +#define PROTOCOLSCENE_H + +#include "Protocol.h" + +class ProtocolScene : public Protocol { +public: + virtual int methods() const; + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +}; + +#endif //PROTOCOLSCENE_H + + + From 3483e2e91562ddd5311088c43a8d95358ed849ce Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 17 Nov 2010 08:54:37 +0000 Subject: [PATCH 0541/2215] tdExecute, new api method for scenes added --- telldus-core/client/libtelldus-core.def | 1 + telldus-core/client/telldus-core.cpp | 16 ++++++++++++++++ telldus-core/client/telldus-core.h | 2 ++ .../service/ClientCommunicationHandler.cpp | 6 +++++- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def index 8932354c..2ca59e6a 100644 --- a/telldus-core/client/libtelldus-core.def +++ b/telldus-core/client/libtelldus-core.def @@ -44,4 +44,5 @@ EXPORTS tdDisconnectTellStickController @31 tdRegisterDeviceChangeEvent @32 + tdExecute @33 \ No newline at end of file diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 0e661065..4605e63e 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -30,6 +30,9 @@ using namespace TelldusCore; * @def TELLSTICK_DIM * Device-flag for devices supporting the tdDim() call. * + * @def TELLSTICK_EXECUTE + * Device-flag for devices (scenes) supporting the tdExecute() call. + * * @def TELLSTICK_LEARN * Device-flag for devices supporting the tdLearn() call. * @@ -166,6 +169,18 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ return Client::getIntegerFromService(msg); } +/** + * Execute a scene action. + * Make sure the device group supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The id to execute + */ +int WINAPI tdExecute(int intDeviceId){ + Message msg(L"tdExecute"); + msg.addArgument(intDeviceId); + return Client::getIntegerFromService(msg); +} + /** * Sends a special learn command to some devices that need a special learn-command * to be used from TellStick @@ -389,6 +404,7 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_BELL * @sa TELLSTICK_TOGGLE * @sa TELLSTICK_DIM + * @sa TELLSTICK_EXECUTE */ int WINAPI tdMethods(int id, int methodsSupported){ Message msg(L"tdMethods"); diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 6ca0caa7..eec33167 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -48,6 +48,7 @@ extern "C" { TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); TELLSTICK_API int WINAPI tdBell(int intDeviceId); TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI tdExecute(int intDeviceId); TELLSTICK_API int WINAPI tdLearn(int intDeviceId); TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); @@ -88,6 +89,7 @@ extern "C" { #define TELLSTICK_TOGGLE 8 #define TELLSTICK_DIM 16 #define TELLSTICK_LEARN 32 +#define TELLSTICK_EXECUTE 64 //Error codes #define TELLSTICK_SUCCESS 0 diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 330086f4..2a71f979 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -89,7 +89,11 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int level = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, level); - } else if (function == L"tdLearn") { + } else if (function == L"tdExecute") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_EXECUTE, 0); + + } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); From c63a8d6a99836134cbb9366447edc0cd63d56277 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 17 Nov 2010 09:24:28 +0000 Subject: [PATCH 0542/2215] Check so that group/scene doesn't call itself again. Secondary calls are not monitored though. --- telldus-core/service/DeviceManager.cpp | 23 ++++++++++++++--------- telldus-core/service/DeviceManager.h | 4 ++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 5a892b2a..7b2330b3 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -371,7 +371,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ std::wstring devices = device->getParameter(L"devices"); protocol = device->getProtocolName(); deviceLocker = std::auto_ptr(0); //TODO better way? Must unlock here somehow though... - retval = doGroupAction(devices, action, data, protocol); + retval = doGroupAction(devices, action, data, protocol, deviceId); if(device != NULL){ //TODO, some kind of test here... that device still exists... deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(device)); //TODO this isn't good either, device may have been deleted etc } @@ -397,7 +397,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return retval; } -int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigned char data, const std::wstring protocol){ +int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigned char data, const std::wstring protocol, int groupDeviceId){ int retval = TELLSTICK_SUCCESS; //TODO or no devices found? std::wstring singledevice; @@ -408,13 +408,19 @@ int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigne int deviceReturnValue = TELLSTICK_SUCCESS; if(protocol == L"scene" && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ //TODO action check neccessary? - deviceReturnValue = executeScene(singledevice); + deviceReturnValue = executeScene(singledevice, groupDeviceId); } else if(protocol == L"group"){ int deviceId = TelldusCore::wideToInteger(singledevice); - if(deviceId > 0){ //todo, check, never 0 for devices, right? + if(deviceId == groupDeviceId){ + deviceReturnValue = TELLSTICK_ERROR_UNKNOWN; //avoid infinite loops if this group itself has been added to its devices + } + else if(deviceId > 0){ //todo, check, never 0 for devices, right? deviceReturnValue = doAction(deviceId, action, data); } + else{ + deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; //Probably incorrectly formatted parameter + } } if(retval == TELLSTICK_SUCCESS){ @@ -427,12 +433,8 @@ int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigne return retval; } -int DeviceManager::executeScene(std::wstring singledevice){ +int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId){ - /*std::wstring deviceIdPart = L""; - std::wstring methodPart = L""; - std::wstring dataPart = L""; - */ std::wstringstream devicestream(singledevice); const int deviceParameterLength = 3; @@ -449,6 +451,9 @@ int DeviceManager::executeScene(std::wstring singledevice){ } int deviceId = TelldusCore::wideToInteger(deviceParts[0]); + if(deviceId == groupDeviceId){ + return TELLSTICK_ERROR_UNKNOWN; //the scene itself has been added to its devices, avoid infinite loop + } int method = Device::methodId(TelldusCore::wideToString(deviceParts[1])); //support methodparts both in the form of integers (e.g. TELLSTICK_TURNON) or text (e.g. "turnon") if(method == 0){ method = TelldusCore::wideToInteger(deviceParts[1]); diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 09a67c65..32cb379d 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -36,8 +36,8 @@ public: void handleControllerMessage(const ControllerEventData &event); private: - int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const std::wstring protocol); - int executeScene(std::wstring singledevice); + int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const std::wstring protocol, int groupDeviceId); + int executeScene(std::wstring singledevice, int groupDeviceId); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); void fillDevices(void); From 88067a97b7c89b71da7d45949f0475c07e8e5f41 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 17 Nov 2010 11:49:58 +0000 Subject: [PATCH 0543/2215] Supported methods-fix, bell not changing state even when turnon was called (as a fallback) --- telldus-core/service/DeviceManager.cpp | 11 ++++++----- telldus-core/service/ProtocolGroup.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 7b2330b3..a9315841 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -131,11 +131,11 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ if(type == TELLSTICK_TYPE_GROUP && protocol != L"scene"){ //TODO would really like to be able to do this on protocol level instead of comparing protocol name here //get all methods that some device in the groups supports - std::wstring buffer; - std::wstringstream ss(deviceIds); + std::wstring deviceIdBuffer; + std::wstringstream devicesstream(deviceIds); - while(ss >> buffer){ - int deviceId = TelldusCore::wideToInteger(buffer); + while(std::getline(devicesstream, deviceIdBuffer, L',')){ + int deviceId = TelldusCore::wideToInteger(deviceIdBuffer); methods |= getDeviceMethods(deviceId, methodsSupported); } return methods; @@ -387,7 +387,8 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return TELLSTICK_ERROR_NOT_FOUND; } } - if(retval == TELLSTICK_SUCCESS && protocol != L"scene") { //TODO move this check, or make a "scene constant" or something else, to make this more general + if(retval == TELLSTICK_SUCCESS && protocol != L"scene" && device->getMethods() & action) { //TODO move this check, or make a "scene constant" or something else, to make this more general + //if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); if (this->triggerDeviceStateChange(deviceId, action, datastring)) { device->setLastSentCommand(action, datastring); diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index a832be1b..131fd83e 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -1,7 +1,7 @@ #include "ProtocolGroup.h" int ProtocolGroup::methods() const { - return 0; + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE; } std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { From 66e54a2095ccadd57949ca30fac7cb803e0ec25a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 17 Nov 2010 12:53:28 +0000 Subject: [PATCH 0544/2215] Supported method-fix for state callback for groups --- telldus-core/service/DeviceManager.cpp | 9 ++++++++- telldus-core/service/ProtocolGroup.cpp | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index a9315841..9eed9dd6 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -133,10 +133,17 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ //get all methods that some device in the groups supports std::wstring deviceIdBuffer; std::wstringstream devicesstream(deviceIds); + methods = 0; while(std::getline(devicesstream, deviceIdBuffer, L',')){ int deviceId = TelldusCore::wideToInteger(deviceIdBuffer); - methods |= getDeviceMethods(deviceId, methodsSupported); + int deviceMethods = getDeviceMethods(deviceId, methodsSupported); + if(deviceMethods > 0){ + debuglog(deviceId, "DEVICE ID"); + debuglog(deviceMethods, "DEVICE METHODS"); + methods |= deviceMethods; + debuglog(methods, "METHODS"); + } } return methods; } diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index 131fd83e..452227e1 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -1,7 +1,7 @@ #include "ProtocolGroup.h" int ProtocolGroup::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE; + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE; } std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { From 72f0346a842e1eff523e18ac7797ad4c6ecd7441 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 17 Nov 2010 13:34:50 +0000 Subject: [PATCH 0545/2215] Core support for up and down command, completely untested --- telldus-core/client/libtelldus-core.def | 2 ++ telldus-core/client/telldus-core.cpp | 32 +++++++++++++++++++ telldus-core/client/telldus-core.h | 4 +++ .../service/ClientCommunicationHandler.cpp | 8 +++++ telldus-core/service/Device.cpp | 16 ++++++++++ telldus-core/service/ProtocolGroup.cpp | 2 +- 6 files changed, 63 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def index 2ca59e6a..d7aa5bb1 100644 --- a/telldus-core/client/libtelldus-core.def +++ b/telldus-core/client/libtelldus-core.def @@ -45,4 +45,6 @@ EXPORTS tdRegisterDeviceChangeEvent @32 tdExecute @33 + tdUp @34 + tdDown @35 \ No newline at end of file diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 4605e63e..ab97237c 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -33,6 +33,12 @@ using namespace TelldusCore; * @def TELLSTICK_EXECUTE * Device-flag for devices (scenes) supporting the tdExecute() call. * + * @def TELLSTICK_UP + * Device-flag for devices supporting the tdUp() call. + * + * @def TELLSTICK_DOWN + * Device-flag for devices supporting the tdDown() call. + * * @def TELLSTICK_LEARN * Device-flag for devices supporting the tdLearn() call. * @@ -181,6 +187,30 @@ int WINAPI tdExecute(int intDeviceId){ return Client::getIntegerFromService(msg); } +/** + * Send "up" command to device. + * Make sure the device group supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to send the command to + */ +int WINAPI tdUp(int intDeviceId){ + Message msg(L"tdUp"); + msg.addArgument(intDeviceId); + return Client::getIntegerFromService(msg); +} + +/** + * Send "down" command to device. + * Make sure the device group supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to send the command to + */ +int WINAPI tdDown(int intDeviceId){ + Message msg(L"tdDown"); + msg.addArgument(intDeviceId); + return Client::getIntegerFromService(msg); +} + /** * Sends a special learn command to some devices that need a special learn-command * to be used from TellStick @@ -405,6 +435,8 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_TOGGLE * @sa TELLSTICK_DIM * @sa TELLSTICK_EXECUTE + * @sa TELLSTICK_UP + * @sa TELLSTICK_DOWN */ int WINAPI tdMethods(int id, int methodsSupported){ Message msg(L"tdMethods"); diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index eec33167..efeaba43 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -49,6 +49,8 @@ extern "C" { TELLSTICK_API int WINAPI tdBell(int intDeviceId); TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); TELLSTICK_API int WINAPI tdExecute(int intDeviceId); + TELLSTICK_API int WINAPI tdUp(int intDeviceId); + TELLSTICK_API int WINAPI tdDown(int intDeviceId); TELLSTICK_API int WINAPI tdLearn(int intDeviceId); TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); @@ -90,6 +92,8 @@ extern "C" { #define TELLSTICK_DIM 16 #define TELLSTICK_LEARN 32 #define TELLSTICK_EXECUTE 64 +#define TELLSTICK_UP 128 +#define TELLSTICK_DOWN 256 //Error codes #define TELLSTICK_SUCCESS 0 diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 2a71f979..fdb9204d 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -93,6 +93,14 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_EXECUTE, 0); + } else if (function == L"tdUp") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_UP, 0); + + } else if (function == L"tdDown") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DOWN, 0); + } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 0020a916..82ca43f9 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -168,6 +168,16 @@ int Device::maskUnsupportedMethods(int methods, int supportedMethods) { methods |= TELLSTICK_TURNON; } + // Up -> Off + if ((methods & TELLSTICK_UP) && !(supportedMethods & TELLSTICK_UP)) { + methods |= TELLSTICK_TURNOFF; + } + + // Down -> On + if ((methods & TELLSTICK_DOWN) && !(supportedMethods & TELLSTICK_DOWN)) { + methods |= TELLSTICK_TURNON; + } + //Cut of the rest of the unsupported methods we don't have a fallback for return methods & supportedMethods; } @@ -188,5 +198,11 @@ int Device::methodId( const std::string &methodName ) { if (methodName.compare("execute") == 0) { return TELLSTICK_EXECUTE; } + if (methodName.compare("up") == 0) { + return TELLSTICK_UP; + } + if (methodName.compare("down") == 0) { + return TELLSTICK_DOWN; + } return 0; } diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index 452227e1..3baf3218 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -1,7 +1,7 @@ #include "ProtocolGroup.h" int ProtocolGroup::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE; + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN; } std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { From a6a554b4d765cb44cc7101fb40891c34467731fd Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 18 Nov 2010 11:31:54 +0000 Subject: [PATCH 0546/2215] Another fix to avoid infinite loops in group belonging to itself. Different approach when relocking devices in doGroupAction. --- telldus-core/service/Device.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 40 +++++++++++++++++++------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 82ca43f9..9c4f50f8 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -164,7 +164,7 @@ int Device::maskUnsupportedMethods(int methods, int supportedMethods) { } // Execute -> On - if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) { //TODO ok everywhere? + if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) { //TODO ok everywhere? (check down/up too) methods |= TELLSTICK_TURNON; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 9eed9dd6..19f3f5a4 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -136,13 +136,14 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ methods = 0; while(std::getline(devicesstream, deviceIdBuffer, L',')){ - int deviceId = TelldusCore::wideToInteger(deviceIdBuffer); - int deviceMethods = getDeviceMethods(deviceId, methodsSupported); + int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); + if(deviceId == deviceIdInGroup){ + //group exists in group, avoid infinite loop + continue; + } + int deviceMethods = getDeviceMethods(deviceIdInGroup, methodsSupported); if(deviceMethods > 0){ - debuglog(deviceId, "DEVICE ID"); - debuglog(deviceMethods, "DEVICE METHODS"); methods |= deviceMethods; - debuglog(methods, "METHODS"); } } return methods; @@ -379,12 +380,29 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ protocol = device->getProtocolName(); deviceLocker = std::auto_ptr(0); //TODO better way? Must unlock here somehow though... retval = doGroupAction(devices, action, data, protocol, deviceId); - if(device != NULL){ //TODO, some kind of test here... that device still exists... - deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(device)); //TODO this isn't good either, device may have been deleted etc - } - else{ - retval = TELLSTICK_ERROR_UNKNOWN; - } + + { + //reaquire device lock, make sure it still exists + //devicelist locked + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it == d->devices.end()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found + } + //device locked + deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); + device = it->second; + } //devicelist unlocked + //if(device != NULL){ //TODO, some kind of test here... that device still exists... + // deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(device)); //TODO this isn't good either, device may have been deleted etc + //} + //else{ + //retval = TELLSTICK_ERROR_UNKNOWN; + //} } else{ Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); From 77fe336120fff6a10cc88465453436b5edfb8968 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 18 Nov 2010 16:22:32 +0000 Subject: [PATCH 0547/2215] Execute, up and down methods added to Telldus Center --- telldus-core/service/ProtocolBrateck.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index f795edac..3c301801 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -1,7 +1,7 @@ #include "ProtocolBrateck.h" int ProtocolBrateck::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; } std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) { @@ -11,7 +11,7 @@ std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Contr const char BX[] = {S,L,L,S,0}; const char B0[] = {S,L,S,L,0}; const char BUP[] = {L,S,L,S,S,L,S,L,S,L,S,L,S,L,S,L,S,0}; - //const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; + const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; const char BDOWN[] = {S,L,S,L,S,L,S,L,S,L,S,L,L,S,L,S,S,0}; std::string strReturn; @@ -35,6 +35,8 @@ std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Contr strReturn.append(BUP); } else if (method == TELLSTICK_TURNOFF) { strReturn.append(BDOWN); + } else if (method == TELLSTICK_STOP) { + strReturn.append(BSTOP); } else { return ""; } From 75d13d228e9bc0452a7c873a0b6c8499fced1b27 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 18 Nov 2010 16:24:23 +0000 Subject: [PATCH 0548/2215] Device group functionallity added to Telldus Center. --- telldus-core/service/DeviceManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 19f3f5a4..a607640c 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -441,7 +441,7 @@ int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigne if(deviceId == groupDeviceId){ deviceReturnValue = TELLSTICK_ERROR_UNKNOWN; //avoid infinite loops if this group itself has been added to its devices } - else if(deviceId > 0){ //todo, check, never 0 for devices, right? + else if(deviceId != 0){ deviceReturnValue = doAction(deviceId, action, data); } else{ From b16a54ad6d362ffca54d89a7b9839ffed875cf61 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 22 Nov 2010 09:41:53 +0000 Subject: [PATCH 0549/2215] TELLSTICK_STOP-method added (although untested) --- telldus-core/client/libtelldus-core.def | 1 + telldus-core/client/telldus-core.cpp | 27 ++++++++++++++++--- telldus-core/client/telldus-core.h | 3 +++ .../service/ClientCommunicationHandler.cpp | 4 +++ telldus-core/service/ProtocolGroup.cpp | 2 +- 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def index d7aa5bb1..c65ea387 100644 --- a/telldus-core/client/libtelldus-core.def +++ b/telldus-core/client/libtelldus-core.def @@ -47,4 +47,5 @@ EXPORTS tdExecute @33 tdUp @34 tdDown @35 + tdStop @36 \ No newline at end of file diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index ab97237c..5374b5fa 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -39,6 +39,9 @@ using namespace TelldusCore; * @def TELLSTICK_DOWN * Device-flag for devices supporting the tdDown() call. * + * @def TELLSTICK_STOP + * Device-flag for devices supporting the tdStop() call. + * * @def TELLSTICK_LEARN * Device-flag for devices supporting the tdLearn() call. * @@ -48,6 +51,9 @@ using namespace TelldusCore; * @def TELLSTICK_TYPE_GROUP * Device type of a device which contains other devices. * + * @def TELLSTICK_TYPE_SCENE + * Device type of a device which contains other devices that are sent different commands when executed (i.e. one device turns on, another turns off). + * * @def TELLSTICK_SUCCESS * Error code. Returned when the command succeeded. * @@ -177,7 +183,7 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ /** * Execute a scene action. - * Make sure the device group supports this by calling tdMethods() before any + * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The id to execute */ @@ -189,7 +195,7 @@ int WINAPI tdExecute(int intDeviceId){ /** * Send "up" command to device. - * Make sure the device group supports this by calling tdMethods() before any + * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to send the command to */ @@ -201,7 +207,7 @@ int WINAPI tdUp(int intDeviceId){ /** * Send "down" command to device. - * Make sure the device group supports this by calling tdMethods() before any + * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to send the command to */ @@ -211,6 +217,18 @@ int WINAPI tdDown(int intDeviceId){ return Client::getIntegerFromService(msg); } +/** + * Send "stop" command to device. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to stop + */ +int WINAPI tdStop(int intDeviceId){ + Message msg(L"tdStop"); + msg.addArgument(intDeviceId); + return Client::getIntegerFromService(msg); +} + /** * Sends a special learn command to some devices that need a special learn-command * to be used from TellStick @@ -278,7 +296,7 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ /** * Returns which type the device is. The device could be either - * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP + * TELLSTICK_TYPE_DEVICE, TELLSTICK_TYPE_GROUP or TELLSTICK_TYPE_SCENE */ int WINAPI tdGetDeviceType(int intDeviceId) { Message msg(L"tdGetDeviceType"); @@ -437,6 +455,7 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_EXECUTE * @sa TELLSTICK_UP * @sa TELLSTICK_DOWN + * @sa TELLSTICK_STOP */ int WINAPI tdMethods(int id, int methodsSupported){ Message msg(L"tdMethods"); diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index efeaba43..5138eebd 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -51,6 +51,7 @@ extern "C" { TELLSTICK_API int WINAPI tdExecute(int intDeviceId); TELLSTICK_API int WINAPI tdUp(int intDeviceId); TELLSTICK_API int WINAPI tdDown(int intDeviceId); + TELLSTICK_API int WINAPI tdStop(int intDeviceId); TELLSTICK_API int WINAPI tdLearn(int intDeviceId); TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); @@ -94,6 +95,7 @@ extern "C" { #define TELLSTICK_EXECUTE 64 #define TELLSTICK_UP 128 #define TELLSTICK_DOWN 256 +#define TELLSTICK_STOP 512 //Error codes #define TELLSTICK_SUCCESS 0 @@ -109,6 +111,7 @@ extern "C" { //Device typedef #define TELLSTICK_TYPE_DEVICE 1 #define TELLSTICK_TYPE_GROUP 2 +#define TELLSTICK_TYPE_SCENE 3 //Device changes #define TELLSTICK_DEVICE_ADDED 1 diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index fdb9204d..2074e0c3 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -101,6 +101,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DOWN, 0); + } else if (function == L"tdStop") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_STOP, 0); + } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index 3baf3218..d6452df5 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -1,7 +1,7 @@ #include "ProtocolGroup.h" int ProtocolGroup::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN; + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; } std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { From baf414e8713b92e20106a51c24916fdb57b22994 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 22 Nov 2010 09:42:33 +0000 Subject: [PATCH 0550/2215] "Group"-type divided into group and scene. --- telldus-core/service/Device.cpp | 8 +++++++- telldus-core/service/DeviceManager.cpp | 26 +++++++++----------------- telldus-core/service/DeviceManager.h | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 9c4f50f8..05da296c 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -120,9 +120,12 @@ std::wstring Device::getStateValue(){ } int Device::getType(){ - if(d->model == L"group"){ + if(d->protocolName == L"group"){ return TELLSTICK_TYPE_GROUP; } + else if(d->protocolName == L"scene"){ + return TELLSTICK_TYPE_SCENE; + } return TELLSTICK_TYPE_DEVICE; } @@ -204,5 +207,8 @@ int Device::methodId( const std::string &methodName ) { if (methodName.compare("down") == 0) { return TELLSTICK_DOWN; } + if (methodName.compare("stop") == 0) { + return TELLSTICK_STOP; + } return 0; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index a607640c..6975c1ad 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -128,7 +128,7 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ deviceIds = it->second->getParameter(L"devices"); protocol = it->second->getProtocolName(); } - if(type == TELLSTICK_TYPE_GROUP && protocol != L"scene"){ //TODO would really like to be able to do this on protocol level instead of comparing protocol name here + if(type == TELLSTICK_TYPE_GROUP){ //get all methods that some device in the groups supports std::wstring deviceIdBuffer; @@ -373,13 +373,11 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } //devicelist unlocked int retval = TELLSTICK_ERROR_UNKNOWN; - std::wstring protocol = L""; - - if(device->getType() == TELLSTICK_TYPE_GROUP){ + + if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE){ std::wstring devices = device->getParameter(L"devices"); - protocol = device->getProtocolName(); - deviceLocker = std::auto_ptr(0); //TODO better way? Must unlock here somehow though... - retval = doGroupAction(devices, action, data, protocol, deviceId); + deviceLocker = std::auto_ptr(0); + retval = doGroupAction(devices, action, data, device->getType(), deviceId); { //reaquire device lock, make sure it still exists @@ -397,12 +395,6 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); device = it->second; } //devicelist unlocked - //if(device != NULL){ //TODO, some kind of test here... that device still exists... - // deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(device)); //TODO this isn't good either, device may have been deleted etc - //} - //else{ - //retval = TELLSTICK_ERROR_UNKNOWN; - //} } else{ Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); @@ -412,7 +404,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return TELLSTICK_ERROR_NOT_FOUND; } } - if(retval == TELLSTICK_SUCCESS && protocol != L"scene" && device->getMethods() & action) { //TODO move this check, or make a "scene constant" or something else, to make this more general + if(retval == TELLSTICK_SUCCESS && device->getType() != TELLSTICK_TYPE_SCENE && device->getMethods() & action) { //if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); if (this->triggerDeviceStateChange(deviceId, action, datastring)) { @@ -423,7 +415,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return retval; } -int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigned char data, const std::wstring protocol, int groupDeviceId){ +int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId){ int retval = TELLSTICK_SUCCESS; //TODO or no devices found? std::wstring singledevice; @@ -433,10 +425,10 @@ int DeviceManager::doGroupAction(const std::wstring devices, int action, unsigne int deviceReturnValue = TELLSTICK_SUCCESS; - if(protocol == L"scene" && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ //TODO action check neccessary? + if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ deviceReturnValue = executeScene(singledevice, groupDeviceId); } - else if(protocol == L"group"){ + else if(type == TELLSTICK_TYPE_GROUP){ int deviceId = TelldusCore::wideToInteger(singledevice); if(deviceId == groupDeviceId){ deviceReturnValue = TELLSTICK_ERROR_UNKNOWN; //avoid infinite loops if this group itself has been added to its devices diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 32cb379d..4441abaa 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -36,7 +36,7 @@ public: void handleControllerMessage(const ControllerEventData &event); private: - int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const std::wstring protocol, int groupDeviceId); + int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId); int executeScene(std::wstring singledevice, int groupDeviceId); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); void fillDevices(void); From 070534ad37bd20819cb9e1946f207f9cdd5e4a06 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 3 Dec 2010 10:46:28 +0000 Subject: [PATCH 0551/2215] Changed methods for IKEA protocol from learn to dim --- telldus-core/service/ProtocolIkea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 134e6d30..aae28b38 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -5,7 +5,7 @@ #include int ProtocolIkea::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM; } std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { From 9b9fae9522cf01b97add39b219838e86d75cffaf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Jan 2011 11:37:14 +0000 Subject: [PATCH 0552/2215] Skipped unnecessary copies. --- telldus-core/service/DeviceManager.cpp | 18 +++++++++--------- telldus-core/service/DeviceManager.h | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 6975c1ad..021140de 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -74,7 +74,7 @@ int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, std::wstring value) +int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -170,7 +170,7 @@ std::wstring DeviceManager::getDeviceModel(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::setDeviceModel(int deviceId, std::wstring model) +int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -203,7 +203,7 @@ std::wstring DeviceManager::getDeviceName(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::setDeviceName(int deviceId, std::wstring name){ +int DeviceManager::setDeviceName(int deviceId, const std::wstring &name){ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -222,7 +222,7 @@ int DeviceManager::setDeviceName(int deviceId, std::wstring name){ return TELLSTICK_SUCCESS; } -std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, std::wstring defaultValue){ +std::wstring DeviceManager::getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defaultValue){ TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -239,7 +239,7 @@ std::wstring DeviceManager::getDeviceParameter(int deviceId, std::wstring name, return defaultValue; } -int DeviceManager::setDeviceParameter(int deviceId, std::wstring name, std::wstring value) +int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -272,7 +272,7 @@ std::wstring DeviceManager::getDeviceProtocol(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::setDeviceProtocol(int deviceId, std::wstring protocol) +int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -344,11 +344,11 @@ int DeviceManager::getPreferredControllerId(int deviceId){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -void DeviceManager::connectTellStickController(int vid, int pid, std::wstring serial){ +void DeviceManager::connectTellStickController(int vid, int pid, const std::wstring &serial){ d->controllerManager->deviceInsertedOrRemoved(vid, pid, true); } -void DeviceManager::disconnectTellStickController(int vid, int pid, std::wstring serial){ +void DeviceManager::disconnectTellStickController(int vid, int pid, const std::wstring &serial){ d->controllerManager->deviceInsertedOrRemoved(vid, pid, false); } @@ -556,7 +556,7 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData } } -int DeviceManager::sendRawCommand(std::wstring command, int reserved){ +int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){ Controller *controller = d->controllerManager->getBestControllerById(-1); if(controller){ diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 4441abaa..3e827b31 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -12,26 +12,26 @@ public: ~DeviceManager(void); int getNumberOfDevices(void); int addDevice(); - void connectTellStickController(int vid, int pid, std::wstring serial); - void disconnectTellStickController(int vid, int pid, std::wstring serial); + void connectTellStickController(int vid, int pid, const std::wstring &serial); + void disconnectTellStickController(int vid, int pid, const std::wstring &serial); int getDeviceId(int deviceIndex); int getDeviceLastSentCommand(int deviceId, int methodsSupported); - int setDeviceLastSentCommand(int deviceId, int command, std::wstring value); + int setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value); int getDeviceMethods(int deviceId, int methodsSupported); std::wstring getDeviceModel(int deviceId); - int setDeviceModel(int deviceId, std::wstring model); + int setDeviceModel(int deviceId, const std::wstring &model); std::wstring getDeviceName(int deviceId); - int setDeviceName(int deviceId, std::wstring name); - std::wstring getDeviceParameter(int deviceId, std::wstring name, std::wstring defauleValue); - int setDeviceParameter(int deviceId, std::wstring name, std::wstring value); + int setDeviceName(int deviceId, const std::wstring &name); + std::wstring getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defauleValue); + int setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value); std::wstring getDeviceProtocol(int deviceId); - int setDeviceProtocol(int deviceId, std::wstring name); + int setDeviceProtocol(int deviceId, const std::wstring &name); std::wstring getDeviceStateValue(int deviceId); int getDeviceType(int deviceId); int getPreferredControllerId(int deviceId); int doAction(int deviceId, int action, unsigned char data); int removeDevice(int deviceId); - int sendRawCommand(std::wstring command, int reserved); + int sendRawCommand(const std::wstring &command, int reserved); void handleControllerMessage(const ControllerEventData &event); From 8d4b6d2b12b8f792643c7401e3d55a8bd45da386 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 18 Feb 2011 15:48:10 +0000 Subject: [PATCH 0553/2215] Added flag to default fail building code from trunk. You should only do that if you know what you are doing --- telldus-core/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 4da35b7b..e8505c77 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -4,6 +4,11 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) CMAKE_POLICY(SET CMP0003 NEW) +OPTION(FORCE_COMPILE_FROM_TRUNK FALSE "Accept compiling souce from trunk. This is unsupported and highly unrecommended") +IF(NOT FORCE_COMPILE_FROM_TRUNK) + MESSAGE(FATAL_ERROR "You are compiling sources from trunk. Don't do that!") +ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) + SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 0) SET(PACKAGE_PATCH_VERSION 103) @@ -28,7 +33,7 @@ IF (WIN32) SET(TOOLS_DEFAULT FALSE) ELSE (WIN32) SET(TOOLS_DEFAULT TRUE) -ENDIF (WIN32) +ENDIF (WIN32) SET(BUILD_TDTOOL ${TOOLS_DEFAULT} CACHE BOOL "Build tdtool") SET(BUILD_TDADMIN ${TOOLS_DEFAULT} CACHE BOOL "Build tdadmin") From e41a20ac9e1b2cfffda57e7973450a4f2c68b40d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 18 Feb 2011 15:48:32 +0000 Subject: [PATCH 0554/2215] Typo --- telldus-core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index e8505c77..8e18dc56 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -4,7 +4,7 @@ CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) CMAKE_POLICY(SET CMP0003 NEW) -OPTION(FORCE_COMPILE_FROM_TRUNK FALSE "Accept compiling souce from trunk. This is unsupported and highly unrecommended") +OPTION(FORCE_COMPILE_FROM_TRUNK FALSE "Accept compiling source from trunk. This is unsupported and highly unrecommended") IF(NOT FORCE_COMPILE_FROM_TRUNK) MESSAGE(FATAL_ERROR "You are compiling sources from trunk. Don't do that!") ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) From 6632ac6207eb8fd14a5c6e50474189e57514277e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Feb 2011 09:48:10 +0000 Subject: [PATCH 0555/2215] Added method 'learn' to UPM devices to avoid confusion. It is only an alias for 'on' --- telldus-core/service/ProtocolUpm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index de090347..5150009d 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -1,7 +1,7 @@ #include "ProtocolUpm.h" int ProtocolUpm::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; } std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) { @@ -28,7 +28,7 @@ std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controlle strReturn.insert(0, START); //Startcode, first code = 0; - if (method == TELLSTICK_TURNON) { + if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { code += 2; } else if (method != TELLSTICK_TURNOFF) { return ""; From e81ebe5fb94514955fd73d9d8269aca28e916f7b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Feb 2011 13:35:43 +0000 Subject: [PATCH 0556/2215] Added function TellStick::pid() --- telldus-core/service/TellStick.h | 11 ++++++----- telldus-core/service/TellStick_libftdi.cpp | 6 ++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 4955a2e0..4715a2fe 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -1,7 +1,7 @@ // // C++ Interface: TellStick // -// Description: +// Description: // // // Author: Micke Prag , (C) 2010 @@ -23,18 +23,19 @@ public: }; class TellStick : public Controller, public TelldusCore::Thread { -public: +public: TellStick(int controllerId, Event *event, const TellStickDescriptor &d); virtual ~TellStick(); - + virtual int firmwareVersion(); + virtual int pid() const; bool isOpen() const; bool isSameAsDescriptor(const TellStickDescriptor &d) const; virtual int send( const std::string &message ); bool stillConnected() const; - + static std::list findAll(); - + protected: void processData( const std::string &data ); void run(); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 0be37ccb..7c0bb65f 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -89,6 +89,10 @@ int TellStick::firmwareVersion() { return 1; } +int TellStick::pid() const { + return d->pid; +} + bool TellStick::isOpen() const { return d->open; } @@ -112,8 +116,6 @@ void TellStick::processData( const std::string &data ) { continue; } else if (data[i] == 10) { // \n found if (d->message.substr(0,2).compare("+V") == 0) { - //parent->fwVersion = atoi(message.substr(2).c_str()); - //printf("Firmware version: %s\n", message.substr(2).c_str()); d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); From ed125d584e71f85730908fa6c668dc2bbcaa85b2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Feb 2011 13:37:55 +0000 Subject: [PATCH 0557/2215] Try detecting firmware version when a new TellStick is connected --- telldus-core/service/TellStick_libftdi.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 7c0bb65f..1be1e9db 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -86,7 +86,7 @@ TellStick::~TellStick() { } int TellStick::firmwareVersion() { - return 1; + return d->fwVersion; } int TellStick::pid() const { @@ -139,6 +139,10 @@ void TellStick::run() { d->running = true; } + //Send a firmware version request + unsigned char msg[] = "V+"; + ftdi_write_data( &d->ftHandle, msg, 2 ) ; + while(1) { //TODO check libftdi doc how to do this best usleep(1000); TelldusCore::MutexLocker locker(&d->mutex); From 72a90c6465bb6879d2d0bcb31d0539582cb5077a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Feb 2011 13:51:02 +0000 Subject: [PATCH 0558/2215] Implemented TELLSTICK_LEARN for Arctech Selflearning again, with the workaround for older TellStick --- telldus-core/service/ProtocolNexa.cpp | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index fe4265d4..9343f935 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,4 +1,5 @@ #include "ProtocolNexa.h" +#include "TellStick.h" #include "Strings.h" int ProtocolNexa::methods() const { @@ -17,7 +18,7 @@ int ProtocolNexa::methods() const { return 0; } -std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *) { +std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *controller) { if (TelldusCore::comparei(model(), L"codeswitch")) { return getStringCodeSwitch(method); } else if (TelldusCore::comparei(model(), L"bell")) { @@ -27,6 +28,31 @@ std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Con //Workaround for not letting a dimmer do into "dimming mode" return getStringSelflearning(TELLSTICK_DIM, 255); } + if (method == TELLSTICK_LEARN) { + std::string str = getStringSelflearning(TELLSTICK_TURNON, data); + + //Check to see if we are an old TellStick (fw <= 2, batch <= 8) + TellStick *ts = reinterpret_cast(controller); + if (!ts) { + return str; + } + if (ts->pid() == 0x0c30 && ts->firmwareVersion() <= 2) { + //Workaround for the bug in early firmwares + //The TellStick have a fixed pause (max) between two packets. + //It is only correct between the first and second packet. + //It seems faster to send two packes at a time and some + //receivers seems picky about this when learning. + //We also return the last packet so Device::doAction() doesn't + //report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + + str.insert(0, 1, 2); //Repeat two times + str.insert(0, 1, 'R'); + for (int i = 0; i < 5; ++i) { + controller->send(str); + } + } + return str; + } return getStringSelflearning(method, data); } From c7d720f4e3e8c58b80322ff3e34f6fb2ec02bbde Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Feb 2011 13:52:23 +0000 Subject: [PATCH 0559/2215] Catch SIGINT --- telldus-core/service/main_unix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 4124d90e..c0fd3d9d 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -18,6 +18,7 @@ void signalHandler(int sig) { syslog(LOG_WARNING, "Received SIGHUP signal."); break; case SIGTERM: + case SIGINT: syslog(LOG_WARNING, "Received SIGTERM signal."); syslog(LOG_WARNING, "Shutting down"); tm.stop(); From ab17be77c654d6e381ad1e115cbf3d56292dd849 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Feb 2011 14:59:45 +0000 Subject: [PATCH 0560/2215] Dont compile tdadmin on OS X --- telldus-core/CMakeLists.txt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 8e18dc56..4b6311d8 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -30,12 +30,18 @@ IF (WIN32) ENDIF (WIN32) IF (WIN32) - SET(TOOLS_DEFAULT FALSE) + SET(TDTOOL_DEFAULT FALSE) + SET(TDADMIN_DEFAULT FALSE) +ELSEIF(APPLE) + SET(TDTOOL_DEFAULT TRUE) + SET(TDADMIN_DEFAULT FALSE) ELSE (WIN32) - SET(TOOLS_DEFAULT TRUE) + SET(TDTOOL_DEFAULT TRUE) + SET(TDADMIN_DEFAULT TRUE) ENDIF (WIN32) -SET(BUILD_TDTOOL ${TOOLS_DEFAULT} CACHE BOOL "Build tdtool") -SET(BUILD_TDADMIN ${TOOLS_DEFAULT} CACHE BOOL "Build tdadmin") + +SET(BUILD_TDTOOL ${TDTOOL_DEFAULT} CACHE BOOL "Build tdtool") +SET(BUILD_TDADMIN ${TDADMIN_DEFAULT} CACHE BOOL "Build tdadmin") SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") From 2c7d8a199ea5c2a446dca8c8fe33f28145261d99 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Feb 2011 15:01:04 +0000 Subject: [PATCH 0561/2215] Updated ftd2xx library and updated the header files --- telldus-core/service/osx/WinTypes.h | 56 ++++----- telldus-core/service/osx/ftd2xx.h | 184 ++++++++++++++++++++-------- 2 files changed, 162 insertions(+), 78 deletions(-) diff --git a/telldus-core/service/osx/WinTypes.h b/telldus-core/service/osx/WinTypes.h index c37d66ff..e8b5b090 100755 --- a/telldus-core/service/osx/WinTypes.h +++ b/telldus-core/service/osx/WinTypes.h @@ -4,34 +4,34 @@ #define MAX_NUM_DEVICES 50 #include -typedef unsigned long DWORD; -typedef unsigned long ULONG; -typedef unsigned short USHORT; -typedef short SHORT; -typedef unsigned char UCHAR; -typedef unsigned short WORD; -typedef unsigned char BYTE; -typedef unsigned char *LPBYTE; -typedef int BOOL; -typedef char BOOLEAN; -typedef char CHAR; -typedef int *LPBOOL; -typedef unsigned char *PUCHAR; -typedef const char *LPCSTR; -typedef char *PCHAR; -typedef void *PVOID; -typedef void *HANDLE; -typedef long LONG; -typedef int INT; -typedef unsigned int UINT; -typedef char *LPSTR; -typedef char *LPTSTR; -typedef DWORD *LPDWORD; -typedef WORD *LPWORD; -typedef ULONG *PULONG; -typedef PVOID LPVOID; -typedef void VOID; -typedef unsigned long long int ULONGLONG; +typedef unsigned int DWORD; +typedef unsigned int ULONG; +typedef unsigned short USHORT; +typedef unsigned short SHORT; +typedef unsigned char UCHAR; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef BYTE *LPBYTE; +typedef unsigned int BOOL; +typedef unsigned char BOOLEAN; +typedef unsigned char CHAR; +typedef BOOL *LPBOOL; +typedef UCHAR *PUCHAR; +typedef const char *LPCSTR; +typedef char *PCHAR; +typedef void *PVOID; +typedef void *HANDLE; +typedef unsigned int LONG; +typedef int INT; +typedef unsigned int UINT; +typedef char *LPSTR; +typedef char *LPTSTR; +typedef DWORD *LPDWORD; +typedef WORD *LPWORD; +typedef ULONG *PULONG; +typedef PVOID LPVOID; +typedef void VOID; +typedef unsigned long long int ULONGLONG; typedef struct _OVERLAPPED { DWORD Internal; diff --git a/telldus-core/service/osx/ftd2xx.h b/telldus-core/service/osx/ftd2xx.h index 67969cfe..04b65274 100755 --- a/telldus-core/service/osx/ftd2xx.h +++ b/telldus-core/service/osx/ftd2xx.h @@ -1,33 +1,41 @@ /*++ -Copyright (c) 2001-2003 Future Technology Devices International Ltd. - -Module Name: - - ftd2xx.h - -Abstract: - - Native USB interface for FTDI FT8U232/245/2232C - FTD2XX library definitions - -Environment: - - kernel & user mode - -Revision History: - - 13/03/01 awm Created. - 13/01/03 awm Added device information support. - 19/03/03 awm Added FT_W32_CancelIo. - 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. - 18/09/03 awm Added FT_SetResetPipeRetryCount. - 10/10/03 awm Added FT_ResetPort. - /03/04 st modified for linux users - 12/10/04 st added FT_SetVIDPID - - ---*/ + Copyright (c) 2001-2011 Future Technology Devices International Limited + + THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. + + FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. + + IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE + RESPONSIBILITY OF THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL + RE-CERTIFICATION AS A RESULT OF MAKING THESE CHANGES. + + + Module Name: + + ftd2xx.h + + Abstract: + + Native USB device driver for FTDI FT232x, FT245x, FT2232x and FT4232x devices + FTD2XX library definitions + + Environment: + + user mode + + + --*/ #ifndef FTD2XX_H @@ -66,11 +74,8 @@ typedef struct _EVENT_HANDLE{ int iVar; } EVENT_HANDLE; -typedef DWORD *FT_HANDLE; -//typedef unsigned int FT_HANDLE; -//typedef struct ftdi_device * FT_HANDLE; - -typedef ULONG FT_STATUS; +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; // // Device status @@ -107,6 +112,7 @@ enum { #define FT_OPEN_BY_SERIAL_NUMBER 1 #define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 // // FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags @@ -114,7 +120,7 @@ enum { #define FT_LIST_NUMBER_ONLY 0x80000000 #define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 +#define FT_LIST_ALL 0x20000000 #define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) @@ -143,15 +149,12 @@ enum { #define FT_BITS_8 (UCHAR) 8 #define FT_BITS_7 (UCHAR) 7 -#define FT_BITS_6 (UCHAR) 6 -#define FT_BITS_5 (UCHAR) 5 // // Stop Bits // #define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_1_5 (UCHAR) 1 #define FT_STOP_BITS_2 (UCHAR) 2 // @@ -185,8 +188,9 @@ enum { typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_LINE_STATUS 4 // // Timeouts @@ -207,9 +211,24 @@ enum { FT_DEVICE_100AX, FT_DEVICE_UNKNOWN, FT_DEVICE_2232C, - FT_DEVICE_232R + FT_DEVICE_232R, + FT_DEVICE_2232H, + FT_DEVICE_4232H }; +// +// Bit Modes +// + +#define FT_BITMODE_RESET 0x00 +#define FT_BITMODE_ASYNC_BITBANG 0x01 +#define FT_BITMODE_MPSSE 0x02 +#define FT_BITMODE_SYNC_BITBANG 0x04 +#define FT_BITMODE_MCU_HOST 0x08 +#define FT_BITMODE_FAST_SERIAL 0x10 +#define FT_BITMODE_CBUS_BITBANG 0x20 +#define FT_BITMODE_SYNC_FIFO 0x40 + #ifdef __cplusplus extern "C" { @@ -440,7 +459,8 @@ typedef struct ft_program_data { // 0 = original // 1 = FT2232C extensions // 2 = FT232R extensions - + // 3 = FT2232H extensions + // 4 = FT4232H extensions WORD VendorId; // 0x0403 WORD ProductId; // 0x6001 char *Manufacturer; // "FTDI" @@ -452,7 +472,7 @@ typedef struct ft_program_data { WORD SelfPowered; // 0 = bus powered, 1 = self powered WORD RemoteWakeup; // 0 = not capable, 1 = capable // - // Rev4 extensions + // Rev4 (FT232B) extensions // UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise UCHAR IsoIn; // non-zero if in endpoint is isochronous @@ -462,7 +482,7 @@ typedef struct ft_program_data { UCHAR USBVersionEnable; // non-zero if chip uses USBVersion WORD USBVersion; // BCD (0x0200 => USB2) // - // FT2232C extensions + // Rev 5 (FT2232) extensions // UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise UCHAR IsoInA; // non-zero if in endpoint is isochronous @@ -484,15 +504,13 @@ typedef struct ft_program_data { UCHAR IFBIsFastSer; // non-zero if interface is Fast serial UCHAR BIsVCP; // non-zero if interface is to use VCP drivers // - // FT232R extensions + // Rev 6 (FT232R) extensions // UCHAR UseExtOsc; // Use External Oscillator UCHAR HighDriveIOs; // High Drive I/Os UCHAR EndpointSize; // Endpoint size - UCHAR PullDownEnableR; // non-zero if pull down enabled UCHAR SerNumEnableR; // non-zero if serial number to be used - UCHAR InvertTXD; // non-zero if invert TXD UCHAR InvertRXD; // non-zero if invert RXD UCHAR InvertRTS; // non-zero if invert RTS @@ -501,18 +519,67 @@ typedef struct ft_program_data { UCHAR InvertDSR; // non-zero if invert DSR UCHAR InvertDCD; // non-zero if invert DCD UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control UCHAR Cbus1; // Cbus Mux control UCHAR Cbus2; // Cbus Mux control UCHAR Cbus3; // Cbus Mux control UCHAR Cbus4; // Cbus Mux control - - UCHAR RIsVCP; // zero if using VCP drivers + UCHAR RIsD2XX; // non-zero if using D2XX drivers + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // + // Rev 8 (FT4232H) Extensions + // + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if AL pins have slow slew + UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if AH pins have slow slew + UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if BL pins have slow slew + UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if BH pins have slow slew + UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers } FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - + FTD2XX_API FT_STATUS WINAPI FT_EE_Program( FT_HANDLE ftHandle, @@ -607,6 +674,12 @@ FT_STATUS WINAPI FT_GetDeviceInfo( PCHAR Description, LPVOID Dummy ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceLocId( + FT_HANDLE ftHandle, + LPDWORD lpdwLocId + ); FTD2XX_API FT_STATUS WINAPI FT_StopInTask( @@ -836,6 +909,12 @@ typedef struct _ft_device_list_info_node { FT_HANDLE ftHandle; } FT_DEVICE_LIST_INFO_NODE; +// Device information flags +enum { + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 +}; + FTD2XX_API FT_STATUS WINAPI FT_CreateDeviceInfoList( LPDWORD lpdwNumDevs @@ -859,6 +938,11 @@ FT_STATUS WINAPI FT_GetDeviceInfoDetail( FT_HANDLE *pftHandle ); + +// +// Version information +// + FTD2XX_API FT_STATUS WINAPI FT_GetDriverVersion( FT_HANDLE ftHandle, From a2387dcd5fb3bbf2338d80958306c1aa87e1af4d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Feb 2011 15:06:29 +0000 Subject: [PATCH 0562/2215] Implemented TellStick::pid() when using ftd2xx engine --- telldus-core/service/TellStick_ftd2xx.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index d357c9ff..2f745ae1 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -103,6 +103,10 @@ int TellStick::firmwareVersion() { return d->fwVersion; } +int TellStick::pid() const { + return d->pid; +} + bool TellStick::isOpen() const { return d->open; } From 118b2da71a1aa44cf12bc3f8b515a9c6e727e595 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Feb 2011 15:08:54 +0000 Subject: [PATCH 0563/2215] Implemented TellStick::findAllByVIDPID() using FT_GetDeviceInfoList() instead of reading the EEPROM. This gives us a much cleaner code --- telldus-core/service/TellStick_ftd2xx.cpp | 46 +++++++++-------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 2f745ae1..bd5ff58f 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -266,7 +266,6 @@ std::list TellStick::findAll() { std::list TellStick::findAllByVIDPID( int vid, int pid ) { std::list retval; - FT_HANDLE fthHandle = 0; FT_STATUS ftStatus = FT_OK; DWORD dwNumberOfDevices = 0; @@ -278,34 +277,25 @@ std::list TellStick::findAllByVIDPID( int vid, int pid ) { if (ftStatus != FT_OK) { return retval; } - for (int i = 0; i < (int)dwNumberOfDevices; i++) { - FT_PROGRAM_DATA pData; - char ManufacturerBuf[32]; - char ManufacturerIdBuf[16]; - char DescriptionBuf[64]; - char SerialNumberBuf[16]; - - pData.Signature1 = 0x00000000; - pData.Signature2 = 0xffffffff; - pData.Version = 0x00000002; // EEPROM structure with FT232R extensions - pData.Manufacturer = ManufacturerBuf; - pData.ManufacturerId = ManufacturerIdBuf; - pData.Description = DescriptionBuf; - pData.SerialNumber = SerialNumberBuf; - - ftStatus = FT_Open(i, &fthHandle); - ftStatus = FT_EE_Read(fthHandle, &pData); - ftStatus = FT_Close(fthHandle); - if (ftStatus != FT_OK) { - continue; - } - if (pData.VendorId == vid && pData.ProductId == pid) { - TellStickDescriptor td; - td.vid = vid; - td.pid = pid; - td.serial = pData.SerialNumber; - retval.push_back(td); + if (dwNumberOfDevices > 0) { + FT_DEVICE_LIST_INFO_NODE *devInfo; + // allocate storage for list based on dwNumberOfDevices + devInfo = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*dwNumberOfDevices); // get the device information list + ftStatus = FT_GetDeviceInfoList(devInfo,&dwNumberOfDevices); + if (ftStatus == FT_OK) { + unsigned int id = (vid << 16) | pid; + for (unsigned int i = 0; i < dwNumberOfDevices; i++) { + if (devInfo[i].ID != id) { + continue; + } + TellStickDescriptor td; + td.vid = vid; + td.pid = pid; + td.serial = devInfo[i].SerialNumber; + retval.push_back(td); + } } + free(devInfo); } return retval; } From 2c7836133c22a4a6abcf70ad2591d9324509d7f7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Feb 2011 15:09:57 +0000 Subject: [PATCH 0564/2215] Close the handle in the destructor. If we miss this the ftd2xx library crashed upon reconnecting a TellStick --- telldus-core/service/TellStick_ftd2xx.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index bd5ff58f..33f5448b 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -91,6 +91,7 @@ TellStick::~TellStick() { } this->wait(); if (d->open) { + FT_Close(d->ftHandle); } delete d; } From 6b5c95b81e016a577ebce54650f618287eb8952c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 22 Feb 2011 16:29:29 +0000 Subject: [PATCH 0565/2215] Send a firmware request when a new TellStick is attached --- telldus-core/service/TellStick_ftd2xx.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 33f5448b..bb045bf2 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -148,6 +148,10 @@ void TellStick::run() { DWORD dwBytesRead = 0; char *buf = 0; + //Send a firmware version request + char msg[] = "V+"; + FT_Write(d->ftHandle, msg, (DWORD)strlen(msg), &dwBytesRead); + while(1) { #ifdef _WINDOWS FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, d->eh); From 16a4c96035043728f5130f94ad2d5ce91a219fea Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 08:40:51 +0000 Subject: [PATCH 0566/2215] Added --nodaemon switch to telldusd on unix platforms --- telldus-core/service/main_unix.cpp | 69 +++++++++++++++++------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index c0fd3d9d..67ab2b3c 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -19,7 +19,7 @@ void signalHandler(int sig) { break; case SIGTERM: case SIGINT: - syslog(LOG_WARNING, "Received SIGTERM signal."); + syslog(LOG_WARNING, "Received SIGTERM or SIGINT signal."); syslog(LOG_WARNING, "Shutting down"); tm.stop(); break; @@ -35,24 +35,33 @@ void signalHandler(int sig) { int main(int argc, char **argv) { pid_t pid, sid; FILE *fd; + bool deamonize = true; - pid = fork(); - if (pid < 0) { - exit(EXIT_FAILURE); - } - if (pid > 0) { - //We are the parent - //Let the parent store the clients pid, - //This way anyone starting the daemon can read the pidfile immediately - - /* Record the pid */ - fd = fopen(PID_FILE,"w"); - if (!fd) { - syslog(LOG_ERR, "Could not write pid file"); + for (int i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--nodaemon") == 0) { + deamonize = false; + } + } + + if (deamonize) { + pid = fork(); + if (pid < 0) { + exit(EXIT_FAILURE); + } + if (pid > 0) { + //We are the parent + //Let the parent store the clients pid, + //This way anyone starting the daemon can read the pidfile immediately + + // Record the pid + fd = fopen(PID_FILE,"w"); + if (!fd) { + syslog(LOG_ERR, "Could not write pid file"); + } + fprintf(fd,"%d\n",pid); + fclose(fd); + exit(EXIT_SUCCESS); } - fprintf(fd,"%d\n",pid); - fclose(fd); - exit(EXIT_SUCCESS); } setlogmask(LOG_UPTO(LOG_INFO)); @@ -60,14 +69,22 @@ int main(int argc, char **argv) { syslog(LOG_INFO, "%s daemon starting up", DAEMON_NAME); - /* Change the file mode mask */ - umask(0); + if (deamonize) { + /* Change the file mode mask */ + umask(0); - sid = setsid(); + sid = setsid(); - if (sid < 0) { - //Something went wrong - exit(EXIT_FAILURE); + if (sid < 0) { + //Something went wrong + printf("Could not set sid\n"); + exit(EXIT_FAILURE); + } + //TODO: Reduce our permissions (change user) + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); } /* Change the current working directory */ @@ -75,12 +92,6 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } - //TODO: Reduce our permissions (change user) - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - /* Install signal traps for proper shutdown */ signal(SIGTERM, signalHandler); signal(SIGINT, signalHandler); From d128376e5753a6f9d6d8ce8d7d58821620c0883c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 09:51:49 +0000 Subject: [PATCH 0567/2215] Implemented methods as UP/DOWN/STOP/LEARN for KingPin --- telldus-core/service/ProtocolSilvanChip.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 99325b30..610e0f4b 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -1,6 +1,10 @@ #include "ProtocolSilvanChip.h" +#include "Strings.h" int ProtocolSilvanChip::methods() const { + if (TelldusCore::comparei(model(), L"kp100")) { + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; + } return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; } @@ -50,21 +54,26 @@ std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char dat } } - if (method == TELLSTICK_TURNON) { + if (method == TELLSTICK_TURNOFF || method == TELLSTICK_UP) { strReturn.append(ZERO); strReturn.append(ZERO); strReturn.append(ONE); strReturn.append(ZERO); + } else if (method == TELLSTICK_TURNON || method == TELLSTICK_DOWN) { + strReturn.append(ONE); + strReturn.append(ZERO); + strReturn.append(ZERO); + strReturn.append(ZERO); + } else if (method == TELLSTICK_STOP) { + strReturn.append(ZERO); + strReturn.append(ONE); + strReturn.append(ZERO); + strReturn.append(ZERO); } else if (method == TELLSTICK_LEARN) { strReturn.append(ZERO); strReturn.append(ZERO); strReturn.append(ZERO); strReturn.append(ONE); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(ONE); - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ZERO); } else { return ""; } From 70fbe15883ffec3b24e0643d55b12f1eef83b45d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 09:53:32 +0000 Subject: [PATCH 0568/2215] Fixed declaration and build issue with TellStick::convertSToT() --- telldus-core/service/CMakeLists.txt | 1 + telldus-core/service/TellStick.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 616d5b9c..0d4a1413 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -13,6 +13,7 @@ SET( telldus-service_SRCS Event.cpp Settings.cpp TelldusMain.cpp + TellStick.cpp EventUpdateManager.cpp ) SET( telldus-service_protocol_SRCS diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 4715a2fe..ffa1300f 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -44,7 +44,8 @@ protected: private: static std::list findAllByVIDPID( int vid, int pid ); - + static std::string convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ); + class PrivateData; PrivateData *d; }; From 9e31881f1cfeec8f3ab466e13681bdfe7bf82c0c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 13:48:43 +0000 Subject: [PATCH 0569/2215] Added missing file TellStick.cpp --- telldus-core/service/TellStick.cpp | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 telldus-core/service/TellStick.cpp diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp new file mode 100644 index 00000000..35ca5caf --- /dev/null +++ b/telldus-core/service/TellStick.cpp @@ -0,0 +1,50 @@ +// +// C++ Implementation: TellStick +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "TellStick.h" + +#include + +std::string TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ) { + unsigned char dataByte = 0; + std::string retString = "R\1T"; + retString.append(1, t0); + retString.append(1, t1); + retString.append(1, t2); + retString.append(1, t3); + + if (data.length() > 255) { + return ""; + } + unsigned char length = (unsigned char)data.length(); + retString.append(1, length); + + for (size_t i = 0; i < data.length(); ++i) { + dataByte <<= 2; + if (data.at(i) == 1) { + dataByte |= 1; + } else if (data.at(i) == 2) { + dataByte |= 2; + } else if (data.at(i) == 3) { + dataByte |= 3; + } + if ( (i+1) % 4 == 0) { + retString.append(1, dataByte); + dataByte = 0; + } + } + if (data.length() % 4 != 0) { + retString.append(1, dataByte); + } + + retString.append("+"); + return retString; +} From 5a4da75b54375abb4d505a8d3b8ebf6da1e258bc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 14:42:04 +0000 Subject: [PATCH 0570/2215] Fixed bug where the last byte was wrong. And also repeat more then one time --- telldus-core/service/TellStick.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index 35ca5caf..7e7d2a3c 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -15,7 +15,7 @@ std::string TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ) { unsigned char dataByte = 0; - std::string retString = "R\1T"; + std::string retString = "T"; retString.append(1, t0); retString.append(1, t1); retString.append(1, t2); @@ -42,6 +42,7 @@ std::string TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned } } if (data.length() % 4 != 0) { + dataByte <<= (data.length() % 4)*2; retString.append(1, dataByte); } From 05a8162762754e91bb7791d7f425c01d1cc19837 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 14:43:01 +0000 Subject: [PATCH 0571/2215] Added static function TellStick::createTPacket() --- telldus-core/service/TellStick.cpp | 33 ++++++++++++++++++++++++++++++ telldus-core/service/TellStick.h | 4 +++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index 7e7d2a3c..3a108e7d 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -12,6 +12,39 @@ #include "TellStick.h" #include +#include +#include + +std::string TellStick::createTPacket( const std::string &msg ) { + std::map times; + std::string data; + int index = 0; + for(size_t i = 0; i < msg.length(); ++i) { + //Search to se if it already exists and get the index + if (times.find(msg.at(i)) == times.end()) { + times[msg.at(i)] = index++; + if (times.size() > 4) { + return ""; + } + } + data.append(1, times[msg.at(i)]); + } + //Reorder the times + unsigned char t0 = 1, t1 = 1, t2 = 1, t3 = 1; + for(std::map::const_iterator it = times.begin(); it != times.end(); ++it) { + if ((*it).second == 0) { + t0 = (*it).first; + } else if ((*it).second == 1) { + t1 = (*it).first; + } else if ((*it).second == 2) { + t2 = (*it).first; + } else if ((*it).second == 3) { + t3 = (*it).first; + } + } + + return TellStick::convertSToT(t0,t1,t2,t3,data); +} std::string TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ) { unsigned char dataByte = 0; diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index ffa1300f..3824b1d8 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -36,6 +36,9 @@ public: static std::list findAll(); + static std::string createTPacket( const std::string & ); + static std::string convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ); + protected: void processData( const std::string &data ); void run(); @@ -44,7 +47,6 @@ protected: private: static std::list findAllByVIDPID( int vid, int pid ); - static std::string convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ); class PrivateData; PrivateData *d; From 87db8e46fa90a49093fd59f39140d3b86127a726 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 14:45:55 +0000 Subject: [PATCH 0572/2215] If the protocols returns an unspecified transmit-method, detect the best one depending on the controller on convert to appropriate --- telldus-core/service/Device.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 05da296c..b7b1d16c 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -1,5 +1,6 @@ #include "Device.h" #include "Settings.h" +#include "TellStick.h" class Device::PrivateData { public: @@ -140,6 +141,24 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { if (code == "") { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } + if (code[0] != 'S' && code[0] != 'T' && code[0] != 'P' && code[0] != 'R') { + //Try autodetect sendtype + TellStick *tellstick = reinterpret_cast(controller); + if (!tellstick) { + return TELLSTICK_ERROR_UNKNOWN; + } + int maxlength = 80; + if (tellstick->pid() == 0x0c31) { + maxlength = 512; + } + if (code.length() <= maxlength) { + //S is enough + code.insert(0, 1, 'S'); + code.append(1, '+'); + } else { + code = TellStick::createTPacket(code); + } + } return controller->send(code); } return TELLSTICK_ERROR_UNKNOWN; @@ -175,7 +194,7 @@ int Device::maskUnsupportedMethods(int methods, int supportedMethods) { if ((methods & TELLSTICK_UP) && !(supportedMethods & TELLSTICK_UP)) { methods |= TELLSTICK_TURNOFF; } - + // Down -> On if ((methods & TELLSTICK_DOWN) && !(supportedMethods & TELLSTICK_DOWN)) { methods |= TELLSTICK_TURNON; From 188140cf2e4dc7fadbed04afd7c2b7b8beb49817 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 14:47:38 +0000 Subject: [PATCH 0573/2215] Fixed some timing issues and don't force the transmit method. Let it be determined depending on the connected controller --- telldus-core/service/ProtocolSilvanChip.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 610e0f4b..6d9e0a15 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -11,11 +11,11 @@ int ProtocolSilvanChip::methods() const { std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { const unsigned char S = 100; const unsigned char L = 255; - const std::string LONG = "\255\1\200"; + const std::string LONG = "\xFF\x1\x2E"; - const std::string ONE = LONG + "\100"; - const std::string ZERO = "\100" + LONG; - std::string strReturn = "R\1S"; + const std::string ONE = LONG + "\x2E"; + const std::string ZERO = "\x2E" + LONG; + std::string strReturn; strReturn.append(1, S); strReturn.append(1, L); @@ -79,7 +79,6 @@ std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char dat } strReturn.append(ZERO); - strReturn.append("+"); return strReturn; } From 27e1a2829553cad88956a0c8b4184b3a385e27fe Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 15:25:42 +0000 Subject: [PATCH 0574/2215] ProtocolBrateck should listen to TELLSTICK_UP and TELLSTICK_DOWN. Not on/off --- telldus-core/service/ProtocolBrateck.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 3c301801..2f01531e 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -29,11 +29,11 @@ std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Contr strReturn.insert(0, B0); } } - + strReturn.insert(0, "S"); - if (method == TELLSTICK_TURNON) { + if (method == TELLSTICK_UP) { strReturn.append(BUP); - } else if (method == TELLSTICK_TURNOFF) { + } else if (method == TELLSTICK_DOWN) { strReturn.append(BDOWN); } else if (method == TELLSTICK_STOP) { strReturn.append(BSTOP); @@ -41,6 +41,6 @@ std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Contr return ""; } strReturn.append("+"); - + return strReturn; } From eaf49ce33d58a8b84fe5a8d234d97a088a874c19 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 16:28:29 +0000 Subject: [PATCH 0575/2215] Refactored ProtocolSilvanChip to easier allow different models (timings) --- telldus-core/service/ProtocolSilvanChip.cpp | 127 +++++++++++--------- telldus-core/service/ProtocolSilvanChip.h | 5 +- 2 files changed, 75 insertions(+), 57 deletions(-) diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 6d9e0a15..8f020ec1 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -9,76 +9,91 @@ int ProtocolSilvanChip::methods() const { } std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { - const unsigned char S = 100; - const unsigned char L = 255; - const std::string LONG = "\xFF\x1\x2E"; + if (TelldusCore::comparei(model(), L"kp100")) { + std::string preamble; + preamble.append(1, 100); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 100); - const std::string ONE = LONG + "\x2E"; - const std::string ZERO = "\x2E" + LONG; - std::string strReturn; + const std::string one = "\xFF\x1\x2E\x2E"; + const std::string zero = "\x2E\xFF\x1\x2E"; + int button = 0; + if (method == TELLSTICK_UP) { + button = 2; + } else if (method == TELLSTICK_DOWN) { + button = 4; + } else if (method == TELLSTICK_STOP) { + button = 3; + } else if (method == TELLSTICK_LEARN) { + button = 1; + } else { + return ""; + } + return this->getString(preamble, one, zero, button); + } + return ""; +} - strReturn.append(1, S); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, L); - strReturn.append(1, 1); - strReturn.append(1, S); +std::string ProtocolSilvanChip::getString(const std::string &preamble, const std::string &one, const std::string &zero, int button) { int intHouse = this->getIntParameter(L"house", 1, 1048575); + std::string strReturn = preamble; for( int i = 19; i >= 0; --i ) { if (intHouse & (1 << i)) { - strReturn.append(ONE); + strReturn.append(one); } else { - strReturn.append(ZERO); + strReturn.append(zero); } } - if (method == TELLSTICK_TURNOFF || method == TELLSTICK_UP) { - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ONE); - strReturn.append(ZERO); - } else if (method == TELLSTICK_TURNON || method == TELLSTICK_DOWN) { - strReturn.append(ONE); - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ZERO); - } else if (method == TELLSTICK_STOP) { - strReturn.append(ZERO); - strReturn.append(ONE); - strReturn.append(ZERO); - strReturn.append(ZERO); - } else if (method == TELLSTICK_LEARN) { - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ZERO); - strReturn.append(ONE); + if (button == 1) { + strReturn.append(zero); + strReturn.append(zero); + strReturn.append(zero); + strReturn.append(one); + } else if (button == 2) { + strReturn.append(zero); + strReturn.append(zero); + strReturn.append(one); + strReturn.append(zero); + } else if (button == 3) { + strReturn.append(zero); + strReturn.append(one); + strReturn.append(zero); + strReturn.append(zero); + } else if (button == 4) { + strReturn.append(one); + strReturn.append(zero); + strReturn.append(zero); + strReturn.append(zero); } else { return ""; } - strReturn.append(ZERO); + strReturn.append(zero); return strReturn; - } diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h index ed6bd7ef..c27dcc52 100644 --- a/telldus-core/service/ProtocolSilvanChip.h +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -8,6 +8,9 @@ class ProtocolSilvanChip : public Protocol public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +protected: + virtual std::string getString(const std::string &preamble, const std::string &one, const std::string &zero, int button); }; -#endif //PROTOCOLSILVANCHIP_H \ No newline at end of file +#endif //PROTOCOLSILVANCHIP_H From 21cdf85fbb7cec1e53fe61c592943b3ec8b47f4b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 17:18:24 +0000 Subject: [PATCH 0576/2215] Added support for displaymatic projectorscreens --- telldus-core/service/ProtocolSilvanChip.cpp | 27 ++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 8f020ec1..13d2452d 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -4,8 +4,10 @@ int ProtocolSilvanChip::methods() const { if (TelldusCore::comparei(model(), L"kp100")) { return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; + } else if (TelldusCore::comparei(model(), L"displaymatic")) { + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; } - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; + return 0; } std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { @@ -53,6 +55,29 @@ std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char dat return ""; } return this->getString(preamble, one, zero, button); + } else if (TelldusCore::comparei(model(), L"displaymatic")) { + std::string preamble; + preamble.append(1, 0x25); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 0x25); + const std::string one = "\x69\25"; + const std::string zero = "\x25\x69"; + int button = 0; + if (method == TELLSTICK_UP) { + button = 1; + } else if (method == TELLSTICK_DOWN) { + button = 3; + } else if (method == TELLSTICK_STOP) { + button = 2; + } + return this->getString(preamble, one, zero, button); } return ""; } From 801b7f302929edcdc1ca67adb8126cea4d20b117 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 25 Feb 2011 13:17:36 +0000 Subject: [PATCH 0577/2215] Fixed bug that deadlocked service in Linux when groups were used. --- telldus-core/service/DeviceManager.cpp | 83 ++++++++++++++------------ 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 021140de..bc15e016 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -106,51 +106,56 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ } int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ - //devices locked - TelldusCore::MutexLocker deviceListLocker(&d->lock); + int type = 0; + int methods = 0; + std::wstring deviceIds; + std::wstring protocol; + + { + //devices locked + TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - - int type; - int methods; - std::wstring deviceIds; - std::wstring protocol; - - { - //TODO: better way to lock (release) - TelldusCore::MutexLocker deviceLocker(it->second); - type = it->second->getType(); - methods = it->second->getMethods(); - deviceIds = it->second->getParameter(L"devices"); - protocol = it->second->getProtocolName(); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } - if(type == TELLSTICK_TYPE_GROUP){ + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { - //get all methods that some device in the groups supports - std::wstring deviceIdBuffer; - std::wstringstream devicesstream(deviceIds); - methods = 0; - - while(std::getline(devicesstream, deviceIdBuffer, L',')){ - int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); - if(deviceId == deviceIdInGroup){ - //group exists in group, avoid infinite loop - continue; - } - int deviceMethods = getDeviceMethods(deviceIdInGroup, methodsSupported); - if(deviceMethods > 0){ - methods |= deviceMethods; - } + { + TelldusCore::MutexLocker deviceLocker(it->second); + type = it->second->getType(); + methods = it->second->getMethods(); + deviceIds = it->second->getParameter(L"devices"); + protocol = it->second->getProtocolName(); } - return methods; } - else{ - return Device::maskUnsupportedMethods(methods, methodsSupported); + } + if(type == 0){ + return 0; + } + if(type == TELLSTICK_TYPE_GROUP){ + + //get all methods that some device in the groups supports + std::wstring deviceIdBuffer; + std::wstringstream devicesstream(deviceIds); + methods = 0; + + while(std::getline(devicesstream, deviceIdBuffer, L',')){ + int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); + if(deviceId == deviceIdInGroup){ + //group exists in group, avoid infinite loop + continue; + } + + int deviceMethods = getDeviceMethods(deviceIdInGroup, methodsSupported); + if(deviceMethods > 0){ + methods |= deviceMethods; + } } + return methods; + } + else{ + return Device::maskUnsupportedMethods(methods, methodsSupported); } return TELLSTICK_ERROR_DEVICE_NOT_FOUND; From 98add27446644147a697a2c5a600fdc3ee6778a6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 25 Feb 2011 13:37:25 +0000 Subject: [PATCH 0578/2215] Added support for ecosavers --- telldus-core/service/ProtocolSilvanChip.cpp | 66 +++++++++++++-------- 1 file changed, 41 insertions(+), 25 deletions(-) diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 13d2452d..dbde18bf 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -4,6 +4,8 @@ int ProtocolSilvanChip::methods() const { if (TelldusCore::comparei(model(), L"kp100")) { return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; + } else if (TelldusCore::comparei(model(), L"ecosavers")) { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; } else if (TelldusCore::comparei(model(), L"displaymatic")) { return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; } @@ -46,9 +48,9 @@ std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char dat if (method == TELLSTICK_UP) { button = 2; } else if (method == TELLSTICK_DOWN) { - button = 4; + button = 8; } else if (method == TELLSTICK_STOP) { - button = 3; + button = 4; } else if (method == TELLSTICK_LEARN) { button = 1; } else { @@ -73,11 +75,41 @@ std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char dat if (method == TELLSTICK_UP) { button = 1; } else if (method == TELLSTICK_DOWN) { - button = 3; + button = 4; } else if (method == TELLSTICK_STOP) { button = 2; } return this->getString(preamble, one, zero, button); + } else if (TelldusCore::comparei(model(), L"ecosavers")) { + std::string preamble; + preamble.append(1, 0x25); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 0x25); + const std::string one = "\x69\25"; + const std::string zero = "\x25\x69"; + int intUnit = this->getIntParameter(L"unit", 1, 4); + int button = 0; + if (intUnit == 1) { + button = 7; + } else if (intUnit == 2) { + button = 3; + } else if (intUnit == 3) { + button = 5; + } else if (intUnit == 4) { + button = 6; + } + + if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { + button |= 8; + } + return this->getString(preamble, one, zero, button); } return ""; } @@ -95,28 +127,12 @@ std::string ProtocolSilvanChip::getString(const std::string &preamble, const std } } - if (button == 1) { - strReturn.append(zero); - strReturn.append(zero); - strReturn.append(zero); - strReturn.append(one); - } else if (button == 2) { - strReturn.append(zero); - strReturn.append(zero); - strReturn.append(one); - strReturn.append(zero); - } else if (button == 3) { - strReturn.append(zero); - strReturn.append(one); - strReturn.append(zero); - strReturn.append(zero); - } else if (button == 4) { - strReturn.append(one); - strReturn.append(zero); - strReturn.append(zero); - strReturn.append(zero); - } else { - return ""; + for( int i = 3; i >= 0; --i) { + if (button & (1 << i)) { + strReturn.append(one); + } else { + strReturn.append(zero); + } } strReturn.append(zero); From bde48287d99c16f568de9314166b152e0795be0c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 25 Feb 2011 16:14:21 +0000 Subject: [PATCH 0579/2215] Support 'upmasking' when using masked methods --- telldus-core/service/Device.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index b7b1d16c..03cabd5f 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -137,6 +137,20 @@ int Device::getType(){ int Device::doAction(int action, unsigned char data, Controller *controller) { Protocol *p = this->retrieveProtocol(); if(p){ + //Try to determine if we need to call another method due to masking + int methods = p->methods(); + if ((action & methods) == 0) { + //Loop all methods an see if any method masks to this one + for(int i = 1; i <= methods; i<<=1) { + if ((i & methods) == 0) { + continue; + } + if (this->maskUnsupportedMethods(i, action)) { + action = i; + break; + } + } + } std::string code = p->getStringForMethod(action, data, controller); if (code == "") { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; From 97cc7ae376d528ea908ddedf085c1cd1a3c03cb4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Feb 2011 10:48:20 +0000 Subject: [PATCH 0580/2215] Client::getBoolFromService() should compare to TELLSTICK_SUCCESS instead of 1 --- telldus-core/client/Client.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index b77717c8..fa6dbd4f 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -100,7 +100,7 @@ void Client::callbackRawEvent(std::wstring command, int controllerId){ } bool Client::getBoolFromService(const Message &msg) { - return getIntegerFromService(msg) == 1; + return getIntegerFromService(msg) == TELLSTICK_SUCCESS; } int Client::getIntegerFromService(const Message &msg) { @@ -142,7 +142,7 @@ void Client::run(){ d->eventSocket.connect(L"TelldusEvents"); while(d->running){ - + if(!d->eventSocket.isConnected()){ d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service if(!d->eventSocket.isConnected()){ @@ -207,7 +207,7 @@ bool Client::unregisterCallback( int callbackId ) { d->deviceEventList.erase(callback_it); return true; } - + for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { if ( (*callback_it).id != callbackId ) { continue; @@ -215,7 +215,7 @@ bool Client::unregisterCallback( int callbackId ) { d->deviceChangeEventList.erase(callback_it); return true; } - + for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { if ( (*callback_it).id != callbackId ) { continue; @@ -223,7 +223,7 @@ bool Client::unregisterCallback( int callbackId ) { d->rawDeviceEventList.erase(callback_it); return true; } - + return false; } From 6a23dba5533072745cf887d091f33ca6c221ec72 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Feb 2011 10:57:42 +0000 Subject: [PATCH 0581/2215] Don't write the pid if opening the file failed --- telldus-core/service/main_unix.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 67ab2b3c..22b109ff 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -55,11 +55,12 @@ int main(int argc, char **argv) { // Record the pid fd = fopen(PID_FILE,"w"); - if (!fd) { + if (fd) { + fprintf(fd,"%d\n",pid); + fclose(fd); + } else { syslog(LOG_ERR, "Could not write pid file"); } - fprintf(fd,"%d\n",pid); - fclose(fd); exit(EXIT_SUCCESS); } } @@ -80,13 +81,14 @@ int main(int argc, char **argv) { printf("Could not set sid\n"); exit(EXIT_FAILURE); } - //TODO: Reduce our permissions (change user) close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } + //TODO: Reduce our permissions (change user) + /* Change the current working directory */ if ((chdir("/")) < 0) { exit(EXIT_FAILURE); From a8155bdfe6840cb6068bf1e21c31330042d7f00d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Feb 2011 13:38:47 +0000 Subject: [PATCH 0582/2215] Removed TODO since I couldn't find any better way of doing this --- telldus-core/service/TellStick_libftdi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 1be1e9db..3a1d4cf3 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -143,7 +143,8 @@ void TellStick::run() { unsigned char msg[] = "V+"; ftdi_write_data( &d->ftHandle, msg, 2 ) ; - while(1) { //TODO check libftdi doc how to do this best + while(1) { + //Is there any better way then sleeping between reads? usleep(1000); TelldusCore::MutexLocker locker(&d->mutex); if (!d->running) { From b4a96af45f9f645c18e56544e87680b3279943af Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 28 Feb 2011 13:56:21 +0000 Subject: [PATCH 0583/2215] Groups in group doesn't crash service now. Status of groups in group are updated. --- .../service/ClientCommunicationHandler.cpp | 6 +- telldus-core/service/DeviceManager.cpp | 58 ++++++++++++++----- telldus-core/service/DeviceManager.h | 5 +- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 2074e0c3..45a1fdcc 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -72,7 +72,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*wstringReturn) = L""; std::wstring msg(clientMessage); //Copy std::wstring function(TelldusCore::Message::takeString(&msg)); - + if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); @@ -188,7 +188,9 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); + std::set *duplicateDeviceIds = new std::set; + (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported, duplicateDeviceIds); + delete duplicateDeviceIds; } else if (function == L"tdSendRawCommand") { std::wstring command = TelldusCore::Message::takeString(&msg); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index bc15e016..d163f21d 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -105,7 +105,7 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ +int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported, std::set *duplicateDeviceIds){ int type = 0; int methods = 0; std::wstring deviceIds; @@ -140,14 +140,18 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported){ std::wstringstream devicesstream(deviceIds); methods = 0; + duplicateDeviceIds->insert(deviceId); + while(std::getline(devicesstream, deviceIdBuffer, L',')){ int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); - if(deviceId == deviceIdInGroup){ - //group exists in group, avoid infinite loop + if(duplicateDeviceIds->count(deviceIdInGroup) == 1){ + //action for device already executed, or will execute, do nothing to avoid infinite loop continue; } - int deviceMethods = getDeviceMethods(deviceIdInGroup, methodsSupported); + duplicateDeviceIds->insert(deviceIdInGroup); + + int deviceMethods = getDeviceMethods(deviceIdInGroup, methodsSupported, duplicateDeviceIds); if(deviceMethods > 0){ methods |= deviceMethods; } @@ -382,7 +386,9 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE){ std::wstring devices = device->getParameter(L"devices"); deviceLocker = std::auto_ptr(0); - retval = doGroupAction(devices, action, data, device->getType(), deviceId); + std::set *duplicateDeviceIds = new std::set; + retval = doGroupAction(devices, action, data, device->getType(), deviceId, duplicateDeviceIds); + delete duplicateDeviceIds; { //reaquire device lock, make sure it still exists @@ -420,26 +426,50 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return retval; } -int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId){ +int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId, std::set *duplicateDeviceIds){ int retval = TELLSTICK_SUCCESS; //TODO or no devices found? - std::wstring singledevice; std::wstringstream devicesstream(devices); - + + duplicateDeviceIds->insert(groupDeviceId); + while(std::getline(devicesstream, singledevice, L',')){ + int deviceId = TelldusCore::wideToInteger(singledevice); + + if(duplicateDeviceIds->count(deviceId) == 1){ + //action for device already executed, or will execute, do nothing to avoid infinite loop + continue; + } + + duplicateDeviceIds->insert(deviceId); + int deviceReturnValue = TELLSTICK_SUCCESS; if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ deviceReturnValue = executeScene(singledevice, groupDeviceId); } else if(type == TELLSTICK_TYPE_GROUP){ - int deviceId = TelldusCore::wideToInteger(singledevice); - if(deviceId == groupDeviceId){ - deviceReturnValue = TELLSTICK_ERROR_UNKNOWN; //avoid infinite loops if this group itself has been added to its devices - } - else if(deviceId != 0){ - deviceReturnValue = doAction(deviceId, action, data); + if(deviceId != 0){ + int childType = DeviceManager::getDeviceType(deviceId); + if(childType == TELLSTICK_TYPE_DEVICE){ + deviceReturnValue = doAction(deviceId, action, data); + } + else if(childType == TELLSTICK_TYPE_SCENE){ + deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes (and test) infinite loops-safe + } + else{ + //group (in group) + deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); + + if(deviceReturnValue == TELLSTICK_SUCCESS) { + std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); + if (this->triggerDeviceStateChange(deviceId, action, datastring)) { + DeviceManager::setDeviceLastSentCommand(deviceId, action, datastring); + d->set.setDeviceState(deviceId, action, datastring); + } + } + } } else{ deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; //Probably incorrectly formatted parameter diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 3e827b31..6fbb4f9b 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -4,6 +4,7 @@ #include "Device.h" #include "ControllerManager.h" #include "EventUpdateManager.h" +#include class DeviceManager { @@ -17,7 +18,7 @@ public: int getDeviceId(int deviceIndex); int getDeviceLastSentCommand(int deviceId, int methodsSupported); int setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value); - int getDeviceMethods(int deviceId, int methodsSupported); + int getDeviceMethods(int deviceId, int methodsSupported, std::set *duplicateDeviceIds); std::wstring getDeviceModel(int deviceId); int setDeviceModel(int deviceId, const std::wstring &model); std::wstring getDeviceName(int deviceId); @@ -36,7 +37,7 @@ public: void handleControllerMessage(const ControllerEventData &event); private: - int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId); + int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId, std::set *duplicateDeviceIds); int executeScene(std::wstring singledevice, int groupDeviceId); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); void fillDevices(void); From e9a7504c9f2eaeae37ae66fff85620568ef7bc4d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Feb 2011 16:28:28 +0000 Subject: [PATCH 0584/2215] Ignore TELLSTICK_ERROR_METHOD_NOT_SUPPORTED on groups since there might be other devices supporting the method. Except if no device supports the method --- telldus-core/service/DeviceManager.cpp | 47 +++++++++++++------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index d163f21d..751f81b0 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -110,7 +110,7 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported, std::set int methods = 0; std::wstring deviceIds; std::wstring protocol; - + { //devices locked TelldusCore::MutexLocker deviceListLocker(&d->lock); @@ -139,18 +139,18 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported, std::set std::wstring deviceIdBuffer; std::wstringstream devicesstream(deviceIds); methods = 0; - + duplicateDeviceIds->insert(deviceId); - + while(std::getline(devicesstream, deviceIdBuffer, L',')){ int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); if(duplicateDeviceIds->count(deviceIdInGroup) == 1){ //action for device already executed, or will execute, do nothing to avoid infinite loop continue; } - + duplicateDeviceIds->insert(deviceIdInGroup); - + int deviceMethods = getDeviceMethods(deviceIdInGroup, methodsSupported, duplicateDeviceIds); if(deviceMethods > 0){ methods |= deviceMethods; @@ -382,14 +382,14 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } //devicelist unlocked int retval = TELLSTICK_ERROR_UNKNOWN; - + if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE){ std::wstring devices = device->getParameter(L"devices"); deviceLocker = std::auto_ptr(0); std::set *duplicateDeviceIds = new std::set; retval = doGroupAction(devices, action, data, device->getType(), deviceId, duplicateDeviceIds); delete duplicateDeviceIds; - + { //reaquire device lock, make sure it still exists //devicelist locked @@ -427,25 +427,25 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId, std::set *duplicateDeviceIds){ - int retval = TELLSTICK_SUCCESS; //TODO or no devices found? + int retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; std::wstring singledevice; std::wstringstream devicesstream(devices); - + duplicateDeviceIds->insert(groupDeviceId); - + while(std::getline(devicesstream, singledevice, L',')){ int deviceId = TelldusCore::wideToInteger(singledevice); - + if(duplicateDeviceIds->count(deviceId) == 1){ //action for device already executed, or will execute, do nothing to avoid infinite loop continue; } - + duplicateDeviceIds->insert(deviceId); - + int deviceReturnValue = TELLSTICK_SUCCESS; - + if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ deviceReturnValue = executeScene(singledevice, groupDeviceId); } @@ -461,7 +461,7 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c else{ //group (in group) deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); - + if(deviceReturnValue == TELLSTICK_SUCCESS) { std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); if (this->triggerDeviceStateChange(deviceId, action, datastring)) { @@ -476,20 +476,21 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c } } - if(retval == TELLSTICK_SUCCESS){ - //if error(s), return the first error, but still try to continue the action with the other devices - //quite possible that some device don't support the current method + if(deviceReturnValue != TELLSTICK_ERROR_METHOD_NOT_SUPPORTED){ + //if error(s), return the last error, but still try to continue the action with the other devices + //if the error is a method not supported we igore is since there might be others supporting it + //If no devices support the method the default value will be returned (method not supported) retval = deviceReturnValue; } - + } return retval; } int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId){ - + std::wstringstream devicestream(singledevice); - + const int deviceParameterLength = 3; std::wstring deviceParts[deviceParameterLength] = {L"", L"", L""}; std::wstring devicePart = L""; @@ -502,7 +503,7 @@ int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId){ if(deviceParts[0] == L"" || deviceParts[1] == L""){ return TELLSTICK_ERROR_UNKNOWN; //malformed or missing parameter } - + int deviceId = TelldusCore::wideToInteger(deviceParts[0]); if(deviceId == groupDeviceId){ return TELLSTICK_ERROR_UNKNOWN; //the scene itself has been added to its devices, avoid infinite loop @@ -515,7 +516,7 @@ int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId){ if(deviceParts[2] != L""){ devicedata = TelldusCore::wideToInteger(deviceParts[2]); } - + if(deviceId > 0 && method > 0){ //check for format error in parameter "devices" return doAction(deviceId, method, devicedata); } From a83391e615586e8ee083170a135a4301be8734a4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Feb 2011 16:29:22 +0000 Subject: [PATCH 0585/2215] Do a new check after method 'unmasking' if we still supports the method --- telldus-core/service/Device.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 03cabd5f..ac84194a 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -151,6 +151,9 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { } } } + if ((action & methods) == 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } std::string code = p->getStringForMethod(action, data, controller); if (code == "") { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; From 11c7870c78a6019fcb8d48a0d453eb6839fe1226 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Feb 2011 21:19:55 +0000 Subject: [PATCH 0586/2215] Fixed compiler warning --- telldus-core/service/Device.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index ac84194a..4152c580 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -164,7 +164,7 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { if (!tellstick) { return TELLSTICK_ERROR_UNKNOWN; } - int maxlength = 80; + unsigned int maxlength = 80; if (tellstick->pid() == 0x0c31) { maxlength = 512; } From 8328d2b609c034c88847749da8b1dff0bf6e30bf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 1 Mar 2011 18:05:22 +0000 Subject: [PATCH 0587/2215] Flush stdout after printf just to make sure --- telldus-core/common/common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index cc8e58d4..465379ab 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -46,6 +46,7 @@ inline void debuglog(const int intMessage, const std::string strMessage){ #elif !defined(_MACOSX) pthread_t thread = pthread_self(); printf("[%i] %i - %s\n", (int)thread, intMessage, strMessage.c_str()); + fflush(stdout); #else printf("%i - %s\n", intMessage, strMessage.c_str()); #endif From b717a62e81a50fae34655b0e1d4d1b4c1549090f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 1 Mar 2011 18:06:47 +0000 Subject: [PATCH 0588/2215] Disable copy on Mutex, it is not possible to copy a mutex --- telldus-core/common/Mutex.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telldus-core/common/Mutex.h b/telldus-core/common/Mutex.h index 06e5087b..75a91b87 100644 --- a/telldus-core/common/Mutex.h +++ b/telldus-core/common/Mutex.h @@ -1,7 +1,7 @@ // // C++ Interface: Thread // -// Description: +// Description: // // // Author: Micke Prag , (C) 2010 @@ -17,11 +17,13 @@ namespace TelldusCore { public: Mutex(); virtual ~Mutex(); - + virtual void lock(); virtual void unlock(); - + private: + Mutex(const Mutex&); //Disable copy + Mutex& operator = (const Mutex&); class PrivateData; PrivateData *d; }; @@ -30,7 +32,7 @@ namespace TelldusCore { void lock(); void unlock(); }; - + class MutexLocker { public: MutexLocker(Mutex *m); From 228b02b680efd3d5034729da05df23e9565aa306 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 1 Mar 2011 18:14:06 +0000 Subject: [PATCH 0589/2215] Store a pointer to the callback-information instead of copy it --- telldus-core/client/Client.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index fa6dbd4f..ac26e365 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -18,9 +18,9 @@ using namespace TelldusCore; typedef CallbackStruct DeviceEvent; typedef CallbackStruct DeviceChangeEvent; typedef CallbackStruct RawDeviceEvent; -typedef std::list DeviceEventList; -typedef std::list DeviceChangeList; -typedef std::list RawDeviceEventList; +typedef std::list DeviceEventList; +typedef std::list DeviceChangeList; +typedef std::list RawDeviceEventList; class Client::PrivateData { public: @@ -70,7 +70,7 @@ void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstri std::list > list; { TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceEventList::const_iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { std::tr1::shared_ptr ptr(new TDDeviceEventDispatcher(*callback_it, deviceId, deviceState, TelldusCore::wideToString(deviceStateValue))); list.push_back(ptr); } @@ -81,7 +81,7 @@ void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int std::list > list; { TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceChangeList::const_iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { std::tr1::shared_ptr ptr(new TDDeviceChangeEventDispatcher(*callback_it, deviceId, eventDeviceChanges, eventChangeType)); list.push_back(ptr); } @@ -92,7 +92,7 @@ void Client::callbackRawEvent(std::wstring command, int controllerId){ std::list > list; { TelldusCore::MutexLocker locker(&d->mutex); - for(RawDeviceEventList::const_iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { std::tr1::shared_ptr ptr(new TDRawDeviceEventDispatcher(*callback_it, TelldusCore::wideToString(command), controllerId)); list.push_back(ptr); } @@ -116,7 +116,10 @@ std::wstring Client::getWStringFromService(const Message &msg) { int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; - DeviceEvent callback = {eventFunction, id, context}; + DeviceEvent *callback = new DeviceEvent; + callback->event = eventFunction; + callback->id = id; + callback->context = context; d->deviceEventList.push_back(callback); return id; } @@ -124,7 +127,10 @@ int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; - DeviceChangeEvent callback = {eventFunction, id, context}; + DeviceChangeEvent *callback = new DeviceChangeEvent; + callback->event = eventFunction; + callback->id = id; + callback->context = context; d->deviceChangeEventList.push_back(callback); return id; } @@ -132,7 +138,10 @@ int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void * int Client::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; - RawDeviceEvent callback = {eventFunction, id, context}; + RawDeviceEvent *callback = new RawDeviceEvent; + callback->event = eventFunction; + callback->id = id; + callback->context = context; d->rawDeviceEventList.push_back(callback); return id; } From b81b656e83d239f0067a6035f89844cff379b4bf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 1 Mar 2011 18:17:30 +0000 Subject: [PATCH 0590/2215] Retrieve callbackstruct as pointer instead of copy --- telldus-core/client/CallbackDispatcher.cpp | 12 ++++++------ telldus-core/client/CallbackDispatcher.h | 16 ++++++++-------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index ffc4ebae..bcea6b58 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -11,7 +11,7 @@ using namespace TelldusCore; -TDDeviceEventDispatcher::TDDeviceEventDispatcher(const CallbackStruct &data, int id, int m, const std::string &strD) +TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct *data, int id, int m, const std::string &strD) :Thread(), d(data), deviceId(id), method(m), strData(strD) { this->start(); @@ -22,11 +22,11 @@ TDDeviceEventDispatcher::~TDDeviceEventDispatcher() { } void TDDeviceEventDispatcher::run() { - d.event(deviceId, method, strData.c_str(), d.id, d.context); + d->event(deviceId, method, strData.c_str(), d->id, d->context); } -TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(const CallbackStruct &data, int id, int event, int type) +TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStruct *data, int id, int event, int type) :Thread(), d(data), deviceId(id), changeEvent(event), changeType(type) { this->start(); @@ -37,10 +37,10 @@ TDDeviceChangeEventDispatcher::~TDDeviceChangeEventDispatcher() { } void TDDeviceChangeEventDispatcher::run() { - d.event(deviceId, changeEvent, changeType, d.id, d.context); + d->event(deviceId, changeEvent, changeType, d->id, d->context); } -TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher(const CallbackStruct &data, const std::string &strD, int id) +TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id) :Thread(), d(data), controllerId(id), strData(strD) { this->start(); @@ -51,5 +51,5 @@ TDRawDeviceEventDispatcher::~TDRawDeviceEventDispatcher() { } void TDRawDeviceEventDispatcher::run() { - d.event(strData.c_str(), controllerId, d.id, d.context); + d->event(strData.c_str(), controllerId, d->id, d->context); } diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index a18059e2..4b42174b 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -20,36 +20,36 @@ namespace TelldusCore { int id; void *context; }; - + class TDDeviceEventDispatcher : public Thread { public: - TDDeviceEventDispatcher(const CallbackStruct &data, int deviceId, int method, const std::string &strData); + TDDeviceEventDispatcher(CallbackStruct *data, int deviceId, int method, const std::string &strData); virtual ~TDDeviceEventDispatcher(); protected: virtual void run(); private: - CallbackStruct d; + CallbackStruct *d; int deviceId, method; std::string strData; }; class TDDeviceChangeEventDispatcher : public Thread { public: - TDDeviceChangeEventDispatcher(const CallbackStruct &data, int deviceId, int changeEvent, int changeType); + TDDeviceChangeEventDispatcher(CallbackStruct *data, int deviceId, int changeEvent, int changeType); virtual ~TDDeviceChangeEventDispatcher(); protected: virtual void run(); - private: - CallbackStruct d; + public: + CallbackStruct *d; int deviceId, changeEvent, changeType; }; class TDRawDeviceEventDispatcher : public Thread { public: - TDRawDeviceEventDispatcher(const CallbackStruct &data, const std::string &strData, int controllerId); + TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strData, int controllerId); virtual ~TDRawDeviceEventDispatcher(); protected: virtual void run(); private: - CallbackStruct d; + CallbackStruct *d; int controllerId; std::string strData; }; From 0345f70616af7ce3dbebb676393f1e1ab2dec87f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 09:09:32 +0000 Subject: [PATCH 0591/2215] Added mutexes to the callbacks to allow unregistering and callbacks at the same time --- telldus-core/client/CallbackDispatcher.cpp | 6 +++ telldus-core/client/CallbackDispatcher.h | 2 + telldus-core/client/Client.cpp | 57 +++++++++++++++++----- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index bcea6b58..b62beb02 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -14,11 +14,13 @@ using namespace TelldusCore; TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct *data, int id, int m, const std::string &strD) :Thread(), d(data), deviceId(id), method(m), strData(strD) { + d->mutex.lock(); this->start(); } TDDeviceEventDispatcher::~TDDeviceEventDispatcher() { this->wait(); + d->mutex.unlock(); } void TDDeviceEventDispatcher::run() { @@ -29,11 +31,13 @@ void TDDeviceEventDispatcher::run() { TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStruct *data, int id, int event, int type) :Thread(), d(data), deviceId(id), changeEvent(event), changeType(type) { + d->mutex.lock(); this->start(); } TDDeviceChangeEventDispatcher::~TDDeviceChangeEventDispatcher() { this->wait(); + d->mutex.unlock(); } void TDDeviceChangeEventDispatcher::run() { @@ -43,11 +47,13 @@ void TDDeviceChangeEventDispatcher::run() { TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id) :Thread(), d(data), controllerId(id), strData(strD) { + d->mutex.lock(); this->start(); } TDRawDeviceEventDispatcher::~TDRawDeviceEventDispatcher() { this->wait(); + d->mutex.unlock(); } void TDRawDeviceEventDispatcher::run() { diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 4b42174b..6af43c98 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -12,6 +12,7 @@ #define CALLBACKDISPATCHER_H #include "Thread.h" +#include "Mutex.h" #include "telldus-core.h" namespace TelldusCore { @@ -19,6 +20,7 @@ namespace TelldusCore { T event; int id; void *context; + TelldusCore::Mutex mutex; }; class TDDeviceEventDispatcher : public Thread { diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index ac26e365..089c98d0 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -208,28 +208,59 @@ void Client::stopThread(){ } bool Client::unregisterCallback( int callbackId ) { - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; + DeviceEventList newDEList; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + if ( (*callback_it)->id != callbackId ) { + continue; + } + newDEList.splice(newDEList.begin(), d->deviceEventList, callback_it); + break; } - d->deviceEventList.erase(callback_it); + } + if (newDEList.size()) { + DeviceEventList::iterator it = newDEList.begin(); + { //Lock and unlock to make sure no one else uses the object + TelldusCore::MutexLocker locker( &(*it)->mutex ); + } + newDEList.erase(it); return true; } - for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; + DeviceChangeList newDCList; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + if ( (*callback_it)->id != callbackId ) { + continue; + } + newDCList.splice(newDCList.begin(), d->deviceChangeEventList, callback_it); + break; } - d->deviceChangeEventList.erase(callback_it); + } + if (newDCList.size()) { + DeviceChangeList::iterator it = newDCList.begin(); + {TelldusCore::MutexLocker locker( &(*it)->mutex );} + newDCList.erase(it); return true; } - for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - if ( (*callback_it).id != callbackId ) { - continue; + RawDeviceEventList newRDEList; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + if ( (*callback_it)->id != callbackId ) { + continue; + } + newRDEList.splice(newRDEList.begin(), d->rawDeviceEventList, callback_it ); + break; } - d->rawDeviceEventList.erase(callback_it); + } + if (newRDEList.size()) { + RawDeviceEventList::iterator it = newRDEList.begin(); + {TelldusCore::MutexLocker locker( &(*it)->mutex );} + newRDEList.erase(it); return true; } From 923c8fc3bb08a93e197e6a38e38ce930a1c8b2f6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 2 Mar 2011 09:28:52 +0000 Subject: [PATCH 0592/2215] TELLSTICK_CHANGE_METHOD added --- telldus-core/client/telldus-core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 5138eebd..892544ac 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -123,5 +123,6 @@ extern "C" { #define TELLSTICK_CHANGE_NAME 1 #define TELLSTICK_CHANGE_PROTOCOL 2 #define TELLSTICK_CHANGE_MODEL 3 +#define TELLSTICK_CHANGE_METHOD 4 #endif From adce4c941c89be434833cea60bb15b4b35dafdbf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 09:58:54 +0000 Subject: [PATCH 0593/2215] Refactored DeviceManager::getDeviceMethods() to clean up the interface and added 2 overloaded helper functions --- .../service/ClientCommunicationHandler.cpp | 6 ++--- telldus-core/service/DeviceManager.cpp | 26 +++++++++++-------- telldus-core/service/DeviceManager.h | 4 ++- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 45a1fdcc..2074e0c3 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -72,7 +72,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*wstringReturn) = L""; std::wstring msg(clientMessage); //Copy std::wstring function(TelldusCore::Message::takeString(&msg)); - + if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); @@ -188,9 +188,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdMethods") { int deviceId = TelldusCore::Message::takeInt(&msg); int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - std::set *duplicateDeviceIds = new std::set; - (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported, duplicateDeviceIds); - delete duplicateDeviceIds; + (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); } else if (function == L"tdSendRawCommand") { std::wstring command = TelldusCore::Message::takeString(&msg); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 751f81b0..f951266c 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -105,7 +105,16 @@ std::wstring DeviceManager::getDeviceStateValue(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported, std::set *duplicateDeviceIds){ +int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported) { + return Device::maskUnsupportedMethods(DeviceManager::getDeviceMethods(deviceId), methodsSupported); +} + +int DeviceManager::getDeviceMethods(int deviceId) { + std::set duplicateDeviceIds; + return DeviceManager::getDeviceMethods(deviceId, duplicateDeviceIds); +} + +int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDeviceIds){ int type = 0; int methods = 0; std::wstring deviceIds; @@ -140,29 +149,24 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported, std::set std::wstringstream devicesstream(deviceIds); methods = 0; - duplicateDeviceIds->insert(deviceId); + duplicateDeviceIds.insert(deviceId); while(std::getline(devicesstream, deviceIdBuffer, L',')){ int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); - if(duplicateDeviceIds->count(deviceIdInGroup) == 1){ + if(duplicateDeviceIds.count(deviceIdInGroup) == 1){ //action for device already executed, or will execute, do nothing to avoid infinite loop continue; } - duplicateDeviceIds->insert(deviceIdInGroup); + duplicateDeviceIds.insert(deviceIdInGroup); - int deviceMethods = getDeviceMethods(deviceIdInGroup, methodsSupported, duplicateDeviceIds); + int deviceMethods = getDeviceMethods(deviceIdInGroup, duplicateDeviceIds); if(deviceMethods > 0){ methods |= deviceMethods; } } - return methods; } - else{ - return Device::maskUnsupportedMethods(methods, methodsSupported); - } - - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + return methods; } std::wstring DeviceManager::getDeviceModel(int deviceId){ diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 6fbb4f9b..4dc992ed 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -18,7 +18,8 @@ public: int getDeviceId(int deviceIndex); int getDeviceLastSentCommand(int deviceId, int methodsSupported); int setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value); - int getDeviceMethods(int deviceId, int methodsSupported, std::set *duplicateDeviceIds); + int getDeviceMethods(int deviceId); + int getDeviceMethods(int deviceId, int methodsSupported); std::wstring getDeviceModel(int deviceId); int setDeviceModel(int deviceId, const std::wstring &model); std::wstring getDeviceName(int deviceId); @@ -37,6 +38,7 @@ public: void handleControllerMessage(const ControllerEventData &event); private: + int getDeviceMethods(int deviceId, std::set &duplicateDeviceIds); int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId, std::set *duplicateDeviceIds); int executeScene(std::wstring singledevice, int groupDeviceId); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); From 643b33b199b0eaf34389b12dbed0d5f6e005f975 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 2 Mar 2011 10:08:35 +0000 Subject: [PATCH 0594/2215] Sending TELLSTICK_CHANGE_METHOD on method changes --- .../service/ClientCommunicationHandler.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 2074e0c3..5ba45d47 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -147,18 +147,26 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdSetProtocol") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring protocol = TelldusCore::Message::takeString(&msg); + int oldMethods = d->deviceManager->getDeviceMethods(deviceId); (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); + } } else if (function == L"tdGetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); (*wstringReturn) = d->deviceManager->getDeviceModel(deviceId); - + } else if (function == L"tdSetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring model = TelldusCore::Message::takeString(&msg); + int oldMethods = d->deviceManager->getDeviceMethods(deviceId); (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); + } } else if (function == L"tdGetDeviceParameter") { int deviceId = TelldusCore::Message::takeInt(&msg); @@ -170,7 +178,11 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); std::wstring value = TelldusCore::Message::takeString(&msg); + int oldMethods = d->deviceManager->getDeviceMethods(deviceId); (*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value); + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); + } } else if (function == L"tdAddDevice") { (*intReturn) = d->deviceManager->addDevice(); From b25802cd264355af4c96209cdd536e5ea1ccf8c2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 13:10:16 +0000 Subject: [PATCH 0595/2215] Use our conversion functions instead of the old ugly hack to convert between utf-8<->wchar_t --- telldus-core/common/Socket_unix.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 9c945faf..35045c20 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -1,6 +1,7 @@ #include "Socket.h" #include "Mutex.h" +#include "Strings.h" #include #include @@ -60,7 +61,7 @@ void Socket::connect(const std::wstring &server) { if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { return; } - + TelldusCore::MutexLocker locker(&d->mutex); d->connected = true; } @@ -101,7 +102,7 @@ std::wstring Socket::read(int timeout) { } std::string msg(inbuf); - return std::wstring(msg.begin(), msg.end()); + return TelldusCore::charToWstring(msg.c_str()); } void Socket::stopReadWait(){ @@ -110,7 +111,7 @@ void Socket::stopReadWait(){ } void Socket::write(const std::wstring &msg) { - std::string newMsg(msg.begin(), msg.end()); + std::string newMsg(TelldusCore::wideToString(msg)); int sent = send(d->socket, newMsg.c_str(), newMsg.length(), 0); if (sent < 0) { TelldusCore::MutexLocker locker(&d->mutex); From 0be5a12de0da78bee6ec655b097c89049708928c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 15:05:46 +0000 Subject: [PATCH 0596/2215] Use real conversions in SettingsConfuse --- telldus-core/service/SettingsConfuse.cpp | 28 +++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index c12c0900..db423b28 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -11,6 +11,7 @@ // #include "Settings.h" #include "../client/telldus-core.h" +#include "Strings.h" #include #include #include @@ -66,8 +67,8 @@ Settings::~Settings(void) std::wstring Settings::getSetting(const std::wstring &strName) const { TelldusCore::MutexLocker locker(&mutex); if (d->cfg > 0) { - std::string setting(cfg_getstr(d->cfg, std::string(strName.begin(), strName.end()).c_str())); //TODO, safer conversion (other places in this file as well) - return std::wstring(setting.begin(), setting.end()); + std::string setting(cfg_getstr(d->cfg, TelldusCore::wideToString(strName).c_str())); + return TelldusCore::charToWstring(setting.c_str()); } return L""; } @@ -175,7 +176,7 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w int deviceId = atoi(cfg_title(cfg_device)); if (deviceId == intDeviceId) { cfg_setint(cfg_device, "state", intDeviceState); - cfg_setstr(cfg_device, "stateValue", std::string(strDeviceStateValue.begin(), strDeviceStateValue.end()).c_str()); + cfg_setstr(cfg_device, "stateValue", TelldusCore::wideToString(strDeviceStateValue).c_str()); FILE *fp = fopen(VAR_CONFIG_FILE, "w"); if(fp == 0){ @@ -232,7 +233,7 @@ std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { int deviceId = atoi(cfg_title(cfg_device)); if (deviceId == intDeviceId) { std::string value(cfg_getstr(cfg_device, "stateValue")); - return std::wstring(value.begin(), value.end()); + return TelldusCore::charToWstring(value.c_str()); } } return L""; @@ -250,12 +251,12 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam if (parameter) { cfg_device = cfg_getsec(cfg_device, "parameters"); } - std::string setting; - char *cSetting = cfg_getstr(cfg_device, std::string(name.begin(), name.end()).c_str()); + std::wstring setting; + char *cSetting = cfg_getstr(cfg_device, TelldusCore::wideToString(name).c_str()); if (cSetting) { - setting = cSetting; + setting = TelldusCore::charToWstring(cSetting); } - return std::wstring(setting.begin(), setting.end()); + return setting; } } return L""; @@ -270,11 +271,12 @@ bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { cfg_device = cfg_getnsec(d->cfg, "device", i); if (cfg_getint(cfg_device, "id") == intDeviceId) { + std::string newValue = TelldusCore::wideToString(value); if (parameter) { cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); - cfg_setstr(cfg_parameters, std::string(name.begin(), name.end()).c_str(), std::string(value.begin(), value.end()).c_str()); + cfg_setstr(cfg_parameters, TelldusCore::wideToString(name).c_str(), newValue.c_str()); } else { - cfg_setstr(cfg_device, std::string(name.begin(), name.end()).c_str(), std::string(value.begin(), value.end()).c_str()); + cfg_setstr(cfg_device, TelldusCore::wideToString(name).c_str(), newValue.c_str()); } FILE *fp = fopen(CONFIG_FILE, "w"); cfg_print(d->cfg, fp); @@ -297,7 +299,7 @@ int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool para if (parameter) { cfg_device = cfg_getsec(cfg_device, "parameters"); } - return cfg_getint(cfg_device, std::string(name.begin(), name.end()).c_str()); + return cfg_getint(cfg_device, TelldusCore::wideToString(name).c_str()); } } return 0; @@ -314,9 +316,9 @@ bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int valu if (cfg_getint(cfg_device, "id") == intDeviceId) { if (parameter) { cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); - cfg_setint(cfg_parameters, std::string(name.begin(), name.end()).c_str(), value); + cfg_setint(cfg_parameters, TelldusCore::wideToString(name).c_str(), value); } else { - cfg_setint(cfg_device, std::string(name.begin(), name.end()).c_str(), value); + cfg_setint(cfg_device, TelldusCore::wideToString(name).c_str(), value); } FILE *fp = fopen(CONFIG_FILE, "w"); cfg_print(d->cfg, fp); From 0427de76d8a0963e45fb6a0f1e4471a605526b6e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 15:34:05 +0000 Subject: [PATCH 0597/2215] Rewrote function charToWstring() to use real coversion using iconv --- telldus-core/common/Strings.cpp | 38 ++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 8be1af6d..4bbc360e 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -3,11 +3,36 @@ #include #include #include +#include +#include std::wstring TelldusCore::charToWstring(const char *value) { - std::wstringstream st; - st << value; - return st.str(); + size_t utf8Length = strlen(value); + size_t outbytesLeft = utf8Length*sizeof(wchar_t); + + iconv_t convDesc = iconv_open("WCHAR_T", "UTF-8"); + + //Copy the instring + char *inString = new char[strlen(value)+1]; + strcpy(inString, value); + + //Create buffer for output + char *outString = (char*)new wchar_t[utf8Length+1]; + memset(outString, 0, sizeof(wchar_t)*(utf8Length+1)); + + char *inPointer = inString; + char *outPointer = outString; + + iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft); + + std::wstring retval( (wchar_t *)outString ); + + //Cleanup + iconv_close(convDesc); + delete[] inString; + delete[] outString; + + return retval; } int TelldusCore::charToInteger(const char *input){ @@ -37,18 +62,11 @@ int TelldusCore::wideToInteger(const std::wstring &input){ } std::string TelldusCore::wideToString(const std::wstring &input) { - std::string strReturn; - size_t len = input.length(); char* convPointer = new char[len + 1]; - wcstombs(convPointer, input.c_str(), len + 1); - strReturn = convPointer; - delete [] convPointer; - return strReturn; - } From d1bc127a2987b67c3ac22a08ec8aad177fc9b378 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 16:08:13 +0000 Subject: [PATCH 0598/2215] Rewrote function wideToString() to use real coversion using iconv --- telldus-core/common/Strings.cpp | 37 ++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 4bbc360e..e7b519fb 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -10,8 +10,6 @@ std::wstring TelldusCore::charToWstring(const char *value) { size_t utf8Length = strlen(value); size_t outbytesLeft = utf8Length*sizeof(wchar_t); - iconv_t convDesc = iconv_open("WCHAR_T", "UTF-8"); - //Copy the instring char *inString = new char[strlen(value)+1]; strcpy(inString, value); @@ -23,12 +21,13 @@ std::wstring TelldusCore::charToWstring(const char *value) { char *inPointer = inString; char *outPointer = outString; + iconv_t convDesc = iconv_open("WCHAR_T", "UTF-8"); iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft); + iconv_close(convDesc); std::wstring retval( (wchar_t *)outString ); //Cleanup - iconv_close(convDesc); delete[] inString; delete[] outString; @@ -62,11 +61,29 @@ int TelldusCore::wideToInteger(const std::wstring &input){ } std::string TelldusCore::wideToString(const std::wstring &input) { - std::string strReturn; - size_t len = input.length(); - char* convPointer = new char[len + 1]; - wcstombs(convPointer, input.c_str(), len + 1); - strReturn = convPointer; - delete [] convPointer; - return strReturn; + size_t wideSize = sizeof(wchar_t)*input.length(); + size_t outbytesLeft = wideSize+sizeof(char); //We cannot know how many wide character there is yet + + //Copy the instring + char *inString = (char*)new wchar_t[input.length()+1]; + memcpy(inString, input.c_str(), wideSize+sizeof(wchar_t)); + + //Create buffer for output + char *outString = new char[outbytesLeft]; + memset(outString, 0, sizeof(char)*(outbytesLeft)); + + char *inPointer = inString; + char *outPointer = outString; + + iconv_t convDesc = iconv_open("UTF-8", "WCHAR_T"); + size_t converted = iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft); + iconv_close(convDesc); + + std::string retval(outString); + + //Cleanup + delete[] inString; + delete[] outString; + + return retval; } From 86b5cdc5bda7100163bb91b440003e383b52db92 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 20:02:25 +0000 Subject: [PATCH 0599/2215] Fix for broken(?) conversion from and to wchar_t on OS X using iconv --- telldus-core/common/Strings.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index e7b519fb..406b05f3 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -6,6 +6,12 @@ #include #include +#ifdef _MACOSX +#define WCHAR_T_ENCODING "UCS-4-INTERNAL" +#else +#define WCHAR_T_ENCODING "WCHAR_T" +#endif + std::wstring TelldusCore::charToWstring(const char *value) { size_t utf8Length = strlen(value); size_t outbytesLeft = utf8Length*sizeof(wchar_t); @@ -21,7 +27,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { char *inPointer = inString; char *outPointer = outString; - iconv_t convDesc = iconv_open("WCHAR_T", "UTF-8"); + iconv_t convDesc = iconv_open(WCHAR_T_ENCODING, "UTF-8"); iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft); iconv_close(convDesc); @@ -75,7 +81,7 @@ std::string TelldusCore::wideToString(const std::wstring &input) { char *inPointer = inString; char *outPointer = outString; - iconv_t convDesc = iconv_open("UTF-8", "WCHAR_T"); + iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING); size_t converted = iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft); iconv_close(convDesc); From 89ddc3484a39c577aedd022f4de00bc4119fc281 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 20:11:53 +0000 Subject: [PATCH 0600/2215] The iconv library must be found and set explicitly on OS X --- telldus-core/common/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 617a7027..f07e1504 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -27,10 +27,14 @@ SET( telldus-common_HDRS IF (APPLE) #### Mac OS X #### SET( telldus-common_TARGET TelldusCommon ) + FIND_LIBRARY(ICONV_LIBRARY iconv) ADD_DEFINITIONS( -D_MACOSX ) LIST(APPEND telldus-common_SRCS Socket_unix.cpp ) + LIST(APPEND telldus-common_LIBRARIES + ${ICONV_LIBRARY} + ) ELSEIF (WIN32) #### Windows #### ADD_DEFINITIONS( -DUNICODE ) From 082a7c9b95601bbab867f0a148fde2097d707326 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 09:07:16 +0000 Subject: [PATCH 0601/2215] Include file not used --- telldus-core/service/TellStick.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index 3a108e7d..b77f512f 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -11,7 +11,6 @@ // #include "TellStick.h" -#include #include #include From 740be082554e1dd519dbd059fcd390d94f8dcfe4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 09:07:58 +0000 Subject: [PATCH 0602/2215] Implemented character conversion between utf-8 and wchar_t on Windows. --- telldus-core/common/Strings.cpp | 39 +++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 406b05f3..6b2d7484 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -4,7 +4,12 @@ #include #include #include + +#ifdef _WINDOWS +#include +#else #include +#endif #ifdef _MACOSX #define WCHAR_T_ENCODING "UCS-4-INTERNAL" @@ -13,6 +18,22 @@ #endif std::wstring TelldusCore::charToWstring(const char *value) { +#ifdef _WINDOWS + //Determine size + int size = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0); + if (size == 0) { + return L""; + } + wchar_t *buffer; + buffer = new wchar_t[size]; + memset(buffer, 0, sizeof(wchar_t)*(size)); + + int bytes = MultiByteToWideChar(CP_UTF8, 0, value, -1, buffer, size); + std::wstring retval(buffer); + delete[] buffer; + return retval; + +#else size_t utf8Length = strlen(value); size_t outbytesLeft = utf8Length*sizeof(wchar_t); @@ -38,6 +59,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { delete[] outString; return retval; +#endif } int TelldusCore::charToInteger(const char *input){ @@ -67,6 +89,22 @@ int TelldusCore::wideToInteger(const std::wstring &input){ } std::string TelldusCore::wideToString(const std::wstring &input) { +#ifdef _WINDOWS + //Determine size + int size = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, NULL, 0, NULL, NULL); + if (size == 0) { + return ""; + } + char *buffer; + buffer = new char[size]; + memset(buffer, 0, sizeof(char)*size); + + int bytes = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, buffer, size, NULL, NULL); + std::string retval(buffer); + delete[] buffer; + return retval; + +#else size_t wideSize = sizeof(wchar_t)*input.length(); size_t outbytesLeft = wideSize+sizeof(char); //We cannot know how many wide character there is yet @@ -92,4 +130,5 @@ std::string TelldusCore::wideToString(const std::wstring &input) { delete[] outString; return retval; +#endif } From cccaf86cb8733ac33ce9e5ac9671c23385fc4d46 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 11:21:41 +0000 Subject: [PATCH 0603/2215] Made it possible to specify a serial to a controller to disconnect. This controller will be disconnected even if it is still available --- .../service/ClientCommunicationHandler.cpp | 6 +-- telldus-core/service/ControllerManager.cpp | 26 +++++++--- telldus-core/service/ControllerManager.h | 48 ++++++++++--------- telldus-core/service/DeviceManager.cpp | 8 ++-- telldus-core/service/DeviceManager.h | 4 +- telldus-core/service/TelldusMain.cpp | 6 +-- 6 files changed, 56 insertions(+), 42 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 5ba45d47..aac7045a 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -157,7 +157,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdGetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); (*wstringReturn) = d->deviceManager->getDeviceModel(deviceId); - + } else if (function == L"tdSetModel") { int deviceId = TelldusCore::Message::takeInt(&msg); std::wstring model = TelldusCore::Message::takeString(&msg); @@ -215,12 +215,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdConnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); - std::wstring serial = TelldusCore::Message::takeString(&msg); + std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); d->deviceManager->connectTellStickController(vid, pid, serial); } else if (function == L"tdDisconnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); - std::wstring serial = TelldusCore::Message::takeString(&msg); + std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); d->deviceManager->disconnectTellStickController(vid, pid, serial); } else{ diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 2ce3ce6c..511eb29e 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -30,7 +30,7 @@ ControllerManager::~ControllerManager() { delete d; } -void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { +void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) { if (vid != 0x1781) { return; } @@ -38,8 +38,11 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) return; } if (inserted) { + printf("Trying to insert(%i) %x, %x, %s\n", inserted, vid, pid, serial.c_str()); loadControllers(); } else { + //Autodetect which has been disconnected + printf("Trying to disconnect(%i) %x, %x, %s\n", inserted, vid, pid, serial.c_str()); TelldusCore::MutexLocker locker(&d->mutex); bool again = true; while(again) { @@ -49,13 +52,22 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, bool inserted) if (!tellstick) { continue; } - if (!tellstick->stillConnected()) { - printf("Controller lost\n"); - d->controllers.erase(it); - delete tellstick; - again=true; - break; + if (serial.compare("") != 0) { + TellStickDescriptor tsd; + tsd.vid = vid; + tsd.pid = pid; + tsd.serial = serial; + if (!tellstick->isSameAsDescriptor(tsd)) { + continue; + } + } else if (tellstick->stillConnected()) { + continue; } + + d->controllers.erase(it); + delete tellstick; + again=true; + break; } } } diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 78104240..199f7610 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -1,24 +1,26 @@ #ifndef CONTROLLERMANAGER_H -#define CONTROLLERMANAGER_H - -class Controller; -class Event; - -class ControllerManager { -public: - ControllerManager(Event *event); - ~ControllerManager(void); - - void deviceInsertedOrRemoved(int vid, int pid, bool inserted); - - Controller *getBestControllerById(int id); - -protected: - void loadControllers(); - -private: - class PrivateData; - PrivateData *d; -}; - -#endif //CONTROLLERMANAGER_H \ No newline at end of file +#define CONTROLLERMANAGER_H + +class Controller; +class Event; + +#include + +class ControllerManager { +public: + ControllerManager(Event *event); + ~ControllerManager(void); + + void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted); + + Controller *getBestControllerById(int id); + +protected: + void loadControllers(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CONTROLLERMANAGER_H diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index f951266c..2a2efe23 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -357,12 +357,12 @@ int DeviceManager::getPreferredControllerId(int deviceId){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -void DeviceManager::connectTellStickController(int vid, int pid, const std::wstring &serial){ - d->controllerManager->deviceInsertedOrRemoved(vid, pid, true); +void DeviceManager::connectTellStickController(int vid, int pid, const std::string &serial){ + d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, true); } -void DeviceManager::disconnectTellStickController(int vid, int pid, const std::wstring &serial){ - d->controllerManager->deviceInsertedOrRemoved(vid, pid, false); +void DeviceManager::disconnectTellStickController(int vid, int pid, const std::string &serial){ + d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, false); } int DeviceManager::doAction(int deviceId, int action, unsigned char data){ diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 4dc992ed..4efa7662 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -13,8 +13,8 @@ public: ~DeviceManager(void); int getNumberOfDevices(void); int addDevice(); - void connectTellStickController(int vid, int pid, const std::wstring &serial); - void disconnectTellStickController(int vid, int pid, const std::wstring &serial); + void connectTellStickController(int vid, int pid, const std::string &serial); + void disconnectTellStickController(int vid, int pid, const std::string &serial); int getDeviceId(int deviceIndex); int getDeviceLastSentCommand(int deviceId, int methodsSupported); int setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value); diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index f2397975..7a24561d 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -51,12 +51,12 @@ void TelldusMain::start(void) { std::list clientCommunicationHandlerList; EventRef handlerEvent = d->eventHandler.addEvent(); - + #ifdef _MACOSX //This is only needed on OS X ControllerListener controllerListener(d->controllerChangeEvent); #endif - + while(!d->stopEvent->isSignaled()) { if (!d->eventHandler.waitForAny()) { @@ -77,7 +77,7 @@ void TelldusMain::start(void) { EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal(); ControllerChangeEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { - controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, data->inserted); + controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, "", data->inserted); } } From 983764cc7173bba2527ca1703060f6669d75656d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 3 Mar 2011 13:22:33 +0000 Subject: [PATCH 0604/2215] Updated udev-rules for better device filtering --- telldus-core/tdadmin/05-tellstick.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules index 6f8db78a..ea9d551e 100644 --- a/telldus-core/tdadmin/05-tellstick.rules +++ b/telldus-core/tdadmin/05-tellstick.rules @@ -1,2 +1,2 @@ -BUS=="usb", ID_VENDOR_ID=="1781" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ID_VENDOR_ID=="1781", SUBSYSTEM=="usb" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" From fe7f8f6eb8d163b6159abce55d29aefe2fc0b1bd Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 3 Mar 2011 14:21:57 +0000 Subject: [PATCH 0605/2215] Code cleanup, removed todos --- telldus-core/common/Message.cpp | 14 -------------- telldus-core/common/Message.h | 2 -- telldus-core/common/Strings.cpp | 12 ++++++++++++ telldus-core/common/Strings.h | 3 +++ telldus-core/service/Device.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 5 ++--- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 290be250..56504d9e 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -42,20 +42,6 @@ void Message::addArgument(const char *value) { this->addArgument(TelldusCore::charToWstring(value)); } -std::wstring Message::charUnsignedToWstring(const unsigned char value) { - //todo move? - std::wstringstream st; - st << value; - return st.str(); -} - -std::wstring Message::intToWstring(int value) { - //todo move? - std::wstringstream st; - st << value; - return st.str(); -} - bool Message::nextIsInt(const std::wstring &message) { if (message.length() == 0) { return false; diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 8ae7991a..cf63251d 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -14,8 +14,6 @@ namespace TelldusCore { void addArgument(int); void addArgument(const char *); - static std::wstring charUnsignedToWstring(const unsigned char value); - static std::wstring intToWstring(int value); static bool nextIsInt(const std::wstring &); static bool nextIsString(const std::wstring &); diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 6b2d7484..d301ff1a 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -70,6 +70,12 @@ int TelldusCore::charToInteger(const char *input){ return retval; } +std::wstring TelldusCore::charUnsignedToWstring(const unsigned char value) { + std::wstringstream st; + st << value; + return st.str(); +} + /** * This method doesn't support all locales */ @@ -80,6 +86,12 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { return stringA == stringB; } +std::wstring TelldusCore::intToWstring(int value) { + std::wstringstream st; + st << value; + return st.str(); +} + int TelldusCore::wideToInteger(const std::wstring &input){ std::wstringstream inputstream; inputstream << input; diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index 8b97792b..211c74a2 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -6,7 +6,10 @@ namespace TelldusCore { std::wstring charToWstring(const char *value); int charToInteger(const char *value); + std::wstring charUnsignedToWstring(const unsigned char value); + bool comparei(std::wstring stringA, std::wstring stringB); + std::wstring intToWstring(int value); std::string wideToString(const std::wstring &input); int wideToInteger(const std::wstring &input); diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 4152c580..3e565472 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -203,7 +203,7 @@ int Device::maskUnsupportedMethods(int methods, int supportedMethods) { } // Execute -> On - if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) { //TODO ok everywhere? (check down/up too) + if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) { methods |= TELLSTICK_TURNON; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 2a2efe23..358545b3 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -421,7 +421,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ } if(retval == TELLSTICK_SUCCESS && device->getType() != TELLSTICK_TYPE_SCENE && device->getMethods() & action) { //if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state - std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); + std::wstring datastring = TelldusCore::charUnsignedToWstring(data); if (this->triggerDeviceStateChange(deviceId, action, datastring)) { device->setLastSentCommand(action, datastring); d->set.setDeviceState(deviceId, action, datastring); @@ -467,7 +467,7 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); if(deviceReturnValue == TELLSTICK_SUCCESS) { - std::wstring datastring = TelldusCore::Message::charUnsignedToWstring(data); + std::wstring datastring = TelldusCore::charUnsignedToWstring(data); if (this->triggerDeviceStateChange(deviceId, action, datastring)) { DeviceManager::setDeviceLastSentCommand(deviceId, action, datastring); d->set.setDeviceState(deviceId, action, datastring); @@ -577,7 +577,6 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData std::list parameters = it->second->getParametersForProtocol(); bool thisDevice = true; for (std::list::iterator paramIt = parameters.begin(); paramIt != parameters.end(); ++paramIt){ - //TODO more efficient conversion/compare? wstring or not? if(!TelldusCore::comparei(it->second->getParameter(TelldusCore::charToWstring((*paramIt).c_str())), TelldusCore::charToWstring(msg.getParameter(*paramIt).c_str()))){ thisDevice = false; break; From bea7b7bfd12b6b848202b0c415130f5127ddca51 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 15:01:42 +0000 Subject: [PATCH 0606/2215] Added settings user and group to the config file under Linux --- telldus-core/service/SettingsConfuse.cpp | 2 ++ telldus-core/service/tellstick.conf | 2 ++ 2 files changed, 4 insertions(+) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index db423b28..b59177f0 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -361,6 +361,8 @@ bool readConfig(cfg_t **cfg) { }; cfg_opt_t opts[] = { + CFG_STR(const_cast("user"), const_cast("nobody"), CFGF_NONE), + CFG_STR(const_cast("group"), const_cast("plugdev"), CFGF_NONE), CFG_STR(const_cast("deviceNode"), const_cast("/dev/tellstick"), CFGF_NONE), CFG_SEC(const_cast("device"), device_opts, CFGF_MULTI), CFG_END() diff --git a/telldus-core/service/tellstick.conf b/telldus-core/service/tellstick.conf index 28301848..1a1bfe81 100644 --- a/telldus-core/service/tellstick.conf +++ b/telldus-core/service/tellstick.conf @@ -1,3 +1,5 @@ +user = "nobody" +group = "plugdev" device { id = 1 name = "Example device" From f8384f7a801c4cc662838d9e91cd112da979830f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 15:02:27 +0000 Subject: [PATCH 0607/2215] Reduce our permissions if we are run as root under Linux --- telldus-core/service/main_unix.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 22b109ff..af4ed71b 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -6,6 +6,11 @@ #include #include #include +#include +#include + +#include "Settings.h" +#include "Strings.h" #define DAEMON_NAME "telldusd" #define PID_FILE "/var/run/" DAEMON_NAME ".pid" @@ -87,7 +92,27 @@ int main(int argc, char **argv) { close(STDERR_FILENO); } - //TODO: Reduce our permissions (change user) + /* Reduce our permissions (change user and group) */ + if (getuid() == 0 || geteuid() == 0) { + Settings settings; + std::string user = TelldusCore::wideToString(settings.getSetting(L"user")); + std::string group = TelldusCore::wideToString(settings.getSetting(L"group")); + + struct passwd *pw = getpwnam(user.c_str()); + if (pw) { + setuid( pw->pw_uid ); + } else { + syslog(LOG_WARNING, "User %s could not be found", user.c_str()); + exit(EXIT_FAILURE); + } + struct group *grp = getgrnam(group.c_str()); + if (grp) { + setgid(grp->gr_gid); + } else { + syslog(LOG_WARNING, "Group %s could not be found", group.c_str()); + exit(EXIT_FAILURE); + } + } /* Change the current working directory */ if ((chdir("/")) < 0) { From 42b078206f4127144ad99ee04db83958cf93495e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 15:12:50 +0000 Subject: [PATCH 0608/2215] Make sure we can write the file before we try --- telldus-core/service/SettingsConfuse.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index b59177f0..41a0f19d 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -102,6 +102,9 @@ int Settings::addDevice(){ int intDeviceId = getNextDeviceId(); FILE *fp = fopen(CONFIG_FILE, "w"); + if (!fp) { + return -TELLSTICK_ERROR_PERMISSION_DENIED; + } cfg_print(d->cfg, fp); //Print the config-file fprintf(fp, "device {\n id=%d\n}\n", intDeviceId); //Print the new device fclose(fp); @@ -136,6 +139,9 @@ bool Settings::removeDevice(int intDeviceId){ TelldusCore::MutexLocker locker(&mutex); bool blnSuccess = true; FILE *fp = fopen(CONFIG_FILE, "w"); + if (!fp) { + return false; + } // Print all opts for(int i = 0; d->cfg->opts[i].name; i++) { @@ -279,6 +285,9 @@ bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const cfg_setstr(cfg_device, TelldusCore::wideToString(name).c_str(), newValue.c_str()); } FILE *fp = fopen(CONFIG_FILE, "w"); + if (!fp) { + return false; + } cfg_print(d->cfg, fp); fclose(fp); return true; @@ -321,6 +330,9 @@ bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int valu cfg_setint(cfg_device, TelldusCore::wideToString(name).c_str(), value); } FILE *fp = fopen(CONFIG_FILE, "w"); + if (!fp) { + return false; + } cfg_print(d->cfg, fp); fclose(fp); return true; From 8d15204aefd1613a9294f943e8c6e6ad53940069 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 15:27:45 +0000 Subject: [PATCH 0609/2215] Return real error messages in Settings that actually reports what went wrong --- telldus-core/service/Settings.cpp | 10 ++++----- telldus-core/service/Settings.h | 22 +++++++++---------- telldus-core/service/SettingsConfuse.cpp | 27 ++++++++++++------------ 3 files changed, 29 insertions(+), 30 deletions(-) diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 118075f5..a32fffef 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -11,7 +11,7 @@ std::wstring Settings::getName(int intDeviceId) const { /* * Set the name of the device */ -bool Settings::setName(int intDeviceId, const std::wstring &strNewName){ +int Settings::setName(int intDeviceId, const std::wstring &strNewName){ TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, L"name", strNewName, false); } @@ -27,7 +27,7 @@ std::wstring Settings::getProtocol(int intDeviceId) const { /* * Set the device vendor */ -bool Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ +int Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, L"protocol", strVendor, false); } @@ -43,7 +43,7 @@ std::wstring Settings::getModel(int intDeviceId) const { /* * Set the device model */ -bool Settings::setModel(int intDeviceId, const std::wstring &strModel){ +int Settings::setModel(int intDeviceId, const std::wstring &strModel){ TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, L"model", strModel, false); } @@ -51,7 +51,7 @@ bool Settings::setModel(int intDeviceId, const std::wstring &strModel){ /* * Set device argument */ -bool Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue){ +int Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue){ TelldusCore::MutexLocker locker(&mutex); return setStringSetting(intDeviceId, strName, strValue, true); } @@ -67,7 +67,7 @@ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &s /* * Set preferred controller id */ -bool Settings::setPreferredControllerId(int intDeviceId, int value){ +int Settings::setPreferredControllerId(int intDeviceId, int value){ TelldusCore::MutexLocker locker(&mutex); return setIntSetting(intDeviceId, L"controller", value, false); } diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index e353a311..730e3fdb 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -12,32 +12,32 @@ public: std::wstring getSetting(const std::wstring &strName) const; int getNumberOfDevices(void) const; std::wstring getName(int intDeviceId) const; - bool setName(int intDeviceId, const std::wstring &strNewName); + int setName(int intDeviceId, const std::wstring &strNewName); std::wstring getProtocol(int intDeviceId) const; - bool setProtocol(int intDeviceId, const std::wstring &strVendor); + int setProtocol(int intDeviceId, const std::wstring &strVendor); std::wstring getModel(int intDeviceId) const; - bool setModel(int intDeviceId, const std::wstring &strModel); + int setModel(int intDeviceId, const std::wstring &strModel); std::wstring getDeviceParameter(int intDeviceId, const std::wstring &strName) const; - bool setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue); + int setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue); bool setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); int getDeviceState( int intDeviceId ) const; std::wstring getDeviceStateValue( int intDeviceId ) const; int getPreferredControllerId(int intDeviceId); - bool setPreferredControllerId(int intDeviceId, int value); - + int setPreferredControllerId(int intDeviceId, int value); + int addDevice(); int getDeviceId(int intDeviceIndex) const; - bool removeDevice(int intDeviceId); - + int removeDevice(int intDeviceId); + protected: std::wstring getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const; - bool setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter); + int setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter); int getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const; - bool setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter); + int setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter); private: int getNextDeviceId() const; - + class PrivateData; PrivateData *d; mutable TelldusCore::Mutex mutex; diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 41a0f19d..8bd627d8 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -135,12 +135,11 @@ int Settings::getNextDeviceId() const { /* * Remove a device */ -bool Settings::removeDevice(int intDeviceId){ +int Settings::removeDevice(int intDeviceId){ TelldusCore::MutexLocker locker(&mutex); - bool blnSuccess = true; FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { - return false; + return TELLSTICK_ERROR_PERMISSION_DENIED; } // Print all opts @@ -168,7 +167,7 @@ bool Settings::removeDevice(int intDeviceId){ cfg_free(d->cfg); readConfig(&d->cfg); - return blnSuccess; + return TELLSTICK_SUCCESS; } bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { @@ -268,10 +267,10 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam return L""; } -bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { +int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { //already locked if (d->cfg == 0) { - return false; + return TELLSTICK_ERROR_PERMISSION_DENIED; } cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { @@ -286,14 +285,14 @@ bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const } FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { - return false; + return TELLSTICK_ERROR_PERMISSION_DENIED; } cfg_print(d->cfg, fp); fclose(fp); - return true; + return TELLSTICK_SUCCESS; } } - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const { @@ -314,10 +313,10 @@ int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool para return 0; } -bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { +int Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { //already locked if (d->cfg == 0) { - return false; + return TELLSTICK_ERROR_PERMISSION_DENIED; } cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { @@ -331,14 +330,14 @@ bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int valu } FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { - return false; + return TELLSTICK_ERROR_PERMISSION_DENIED; } cfg_print(d->cfg, fp); fclose(fp); - return true; + return TELLSTICK_SUCCESS; } } - return false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } From c4ef48123289419fdb4e126e0e5326241f454ba9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 15:36:46 +0000 Subject: [PATCH 0610/2215] Error codes are already negative --- telldus-core/service/SettingsConfuse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 8bd627d8..af7e005f 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -103,7 +103,7 @@ int Settings::addDevice(){ FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { - return -TELLSTICK_ERROR_PERMISSION_DENIED; + return TELLSTICK_ERROR_PERMISSION_DENIED; } cfg_print(d->cfg, fp); //Print the config-file fprintf(fp, "device {\n id=%d\n}\n", intDeviceId); //Print the new device From 17e93f0a4d2a54931d3d40ad4642fcc053437e4f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 15:37:36 +0000 Subject: [PATCH 0611/2215] Return the error messages from Settings if something goes wrong --- .../service/ClientCommunicationHandler.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 33 +++++++++++++------ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index aac7045a..180d1788 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -193,7 +193,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdRemoveDevice") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->removeDevice(deviceId); - if((*intReturn) == TELLSTICK_DEVICE_REMOVED){ + if((*intReturn) == TELLSTICK_SUCCESS){ sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0); } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 358545b3..2f83bdfd 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -192,7 +192,10 @@ int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); - d->set.setModel(deviceId, model); + int ret = d->set.setModel(deviceId, model); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } it->second->setModel(model); } else{ @@ -225,7 +228,10 @@ int DeviceManager::setDeviceName(int deviceId, const std::wstring &name){ DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); - d->set.setName(deviceId, name); + int ret = d->set.setName(deviceId, name); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } it->second->setName(name); } else{ @@ -261,7 +267,10 @@ int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, co DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); - d->set.setDeviceParameter(deviceId, name, value); + int ret = d->set.setDeviceParameter(deviceId, name, value); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } it->second->setParameter(name, value); } else{ @@ -294,7 +303,10 @@ int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); - d->set.setProtocol(deviceId, protocol); + int ret = d->set.setProtocol(deviceId, protocol); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } it->second->setProtocolName(protocol); } else{ @@ -312,8 +324,8 @@ int DeviceManager::getNumberOfDevices(){ int DeviceManager::addDevice(){ int id = d->set.addDevice(); - if(id == -1){ - return TELLSTICK_ERROR_UNKNOWN; + if(id < 0){ + return id; } TelldusCore::MutexLocker deviceListLocker(&d->lock); @@ -330,7 +342,7 @@ int DeviceManager::getDeviceId(int deviceIndex) { int DeviceManager::getDeviceType(int deviceId){ -TelldusCore::MutexLocker deviceListLocker(&d->lock); + TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -532,8 +544,9 @@ int DeviceManager::removeDevice(int deviceId){ Device *device = 0; { - if(!d->set.removeDevice(deviceId)){ //remove from register/settings - return TELLSTICK_ERROR_UNKNOWN; + int ret = d->set.removeDevice(deviceId); //remove from register/settings + if (ret != TELLSTICK_SUCCESS) { + return ret; } TelldusCore::MutexLocker deviceListLocker(&d->lock); @@ -552,7 +565,7 @@ int DeviceManager::removeDevice(int deviceId){ {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else delete device; - return TELLSTICK_DEVICE_REMOVED; + return TELLSTICK_SUCCESS; } void DeviceManager::handleControllerMessage(const ControllerEventData &eventData) { From de292eeaf520ce260b8b5e2b72fe3e99d7939bb8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 15:52:44 +0000 Subject: [PATCH 0612/2215] Return real error messages on Windows. --- telldus-core/service/SettingsWinRegistry.cpp | 24 ++++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 4fb39e5c..d5bb1473 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -6,6 +6,8 @@ #include #include +#include "../client/telldus-core.h" + const int intMaxRegValueLength = 1000; class Settings::PrivateData { @@ -150,7 +152,7 @@ int Settings::getNextDeviceId() const { /* * Remove a device */ -bool Settings::removeDevice(int intDeviceId) { +int Settings::removeDevice(int intDeviceId) { TelldusCore::MutexLocker locker(&mutex); std::wostringstream ssRegPath; @@ -161,10 +163,10 @@ bool Settings::removeDevice(int intDeviceId) { if(lngSuccess == ERROR_SUCCESS){ //one of the deletions succeeded - return true; + return TELLSTICK_SUCCESS; } - return false; + return TELLSTICK_ERROR_UNKNOWN; } std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const { @@ -196,10 +198,10 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam return strReturn; } -bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { +int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { - bool blnSuccess = false; HKEY hk; + int ret = TELLSTICK_SUCCESS; std::wostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; @@ -209,10 +211,12 @@ bool Settings::setStringSetting(int intDeviceId, const std::wstring &name, const if (lnExists == ERROR_SUCCESS){ int length = (int)value.length() * sizeof(wchar_t); RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); + } else { + ret = TELLSTICK_ERROR_UNKNOWN; } RegCloseKey(hk); - return blnSuccess; + return ret; } @@ -227,8 +231,8 @@ int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool para return intReturn; } -bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { - bool blnReturn = false; +int Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { + int intReturn = TELLSTICK_ERROR_UNKNOWN; HKEY hk; std::wostringstream ssRegPath; @@ -239,9 +243,9 @@ bool Settings::setIntSetting(int intDeviceId, const std::wstring &name, int valu DWORD dwVal = value; lnExists = RegSetValueEx (hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); if (lnExists == ERROR_SUCCESS) { - blnReturn = true; + intReturn = TELLSTICK_SUCCESS; } } RegCloseKey(hk); - return blnReturn; + return intReturn; } From bf4589fb0f10d9f18387e8c419b5690564d9f0c5 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 3 Mar 2011 16:00:49 +0000 Subject: [PATCH 0613/2215] Code cleanup, printouts removed --- telldus-core/service/ConnectionListener_unix.cpp | 7 +------ telldus-core/service/ControllerManager.cpp | 5 ----- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 88fa0282..4648a273 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -73,19 +73,14 @@ void ConnectionListener::run(){ FD_SET(serverSocket, &infds); continue; } else if (response < 0 ) { - printf("Select error occured: %i\n", response); continue; } //Make sure it is a new connection if (!FD_ISSET(serverSocket, &infds)) { - printf("Not ours, error?\n"); continue; } SOCKET_T clientSocket = accept(serverSocket, NULL, NULL); - if(clientSocket == -1){ - printf("error %i\n", errno); - } - + ConnectionListenerEventData *data = new ConnectionListenerEventData(); data->socket = new TelldusCore::Socket(clientSocket); d->waitEvent->signal(data); diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 511eb29e..6081a421 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -38,11 +38,9 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str return; } if (inserted) { - printf("Trying to insert(%i) %x, %x, %s\n", inserted, vid, pid, serial.c_str()); loadControllers(); } else { //Autodetect which has been disconnected - printf("Trying to disconnect(%i) %x, %x, %s\n", inserted, vid, pid, serial.c_str()); TelldusCore::MutexLocker locker(&d->mutex); bool again = true; while(again) { @@ -71,8 +69,6 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str } } } - printf("List contains %i controllers\n", (int)d->controllers.size()); - } Controller *ControllerManager::getBestControllerById(int id) { @@ -119,7 +115,6 @@ void ControllerManager::loadControllers() { delete controller; continue; } - printf("Found (%i/%i): %s\n", (*it).vid, (*it).pid, (*it).serial.c_str()); d->lastControllerId = controllerId; d->controllers[d->lastControllerId] = controller; } From 0a86d1d6fe122fb40150cae219c0711b81e241e6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 16:01:58 +0000 Subject: [PATCH 0614/2215] Return real error messages in SettingsCoreFoundationPreferences --- .../SettingsCoreFoundationPreferences.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index 1e6dcd7b..bbac1d02 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -15,6 +15,8 @@ #include #include +#include "../client/telldus-core.h" + class privateVars { public: CFStringRef app_ID; @@ -143,21 +145,25 @@ int Settings::getNextDeviceId() const { /* * Remove a device */ -bool Settings::removeDevice(int intDeviceId){ +int Settings::removeDevice(int intDeviceId){ + int ret = TELLSTICK_ERROR_DEVICE_NOT_FOUND; CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d."), intDeviceId); // The key to search for CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); - if (!cfarray) return 0; + if (!cfarray) { + return TELLSTICK_ERROR_UNKNOWN; + } CFIndex size = CFArrayGetCount( cfarray ); for (CFIndex k = 0; k < size; ++k) { CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); if (CFStringHasPrefix( key, filterKey ) ) { CFPreferencesSetValue( key, NULL, d->app_ID, d->userName, d->hostName ); //Remove the key + ret = TELLSTICK_SUCCESS; } } CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); - return true; + return ret; } std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &wname, bool parameter) const { @@ -190,7 +196,7 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &wna return retval; } -bool Settings::setStringSetting(int intDeviceId, const std::wstring &wname, const std::wstring &wvalue, bool parameter) { +int Settings::setStringSetting(int intDeviceId, const std::wstring &wname, const std::wstring &wvalue, bool parameter) { std::string name(TelldusCore::wideToString(wname)); std::string value(TelldusCore::wideToString(wvalue)); CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); @@ -205,7 +211,7 @@ bool Settings::setStringSetting(int intDeviceId, const std::wstring &wname, cons CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); - return true; + return TELLSTICK_SUCCESS; } int Settings::getIntSetting(int intDeviceId, const std::wstring &wname, bool parameter) const { @@ -239,7 +245,7 @@ int Settings::getIntSetting(int intDeviceId, const std::wstring &wname, bool par return retval; } -bool Settings::setIntSetting(int intDeviceId, const std::wstring &wname, int value, bool parameter) { +int Settings::setIntSetting(int intDeviceId, const std::wstring &wname, int value, bool parameter) { std::string name(TelldusCore::wideToString(wname)); CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); CFNumberRef cfvalue = CFNumberCreate(NULL, kCFNumberIntType, &value); @@ -253,5 +259,5 @@ bool Settings::setIntSetting(int intDeviceId, const std::wstring &wname, int val CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); - return true; + return TELLSTICK_SUCCESS; } From 8d4f2407444e239ae58379e486e7841f3bc75a29 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 16:03:02 +0000 Subject: [PATCH 0615/2215] Removed unused variable --- telldus-core/common/Strings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index d301ff1a..7fee0582 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -132,7 +132,7 @@ std::string TelldusCore::wideToString(const std::wstring &input) { char *outPointer = outString; iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING); - size_t converted = iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft); + iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft); iconv_close(convDesc); std::string retval(outString); From c25a848578925854e5853b7dcd8b426b858c5dd5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 16:36:13 +0000 Subject: [PATCH 0616/2215] We must change our group first to have permissions to do so --- telldus-core/service/main_unix.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index af4ed71b..f6fcef66 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -98,13 +98,6 @@ int main(int argc, char **argv) { std::string user = TelldusCore::wideToString(settings.getSetting(L"user")); std::string group = TelldusCore::wideToString(settings.getSetting(L"group")); - struct passwd *pw = getpwnam(user.c_str()); - if (pw) { - setuid( pw->pw_uid ); - } else { - syslog(LOG_WARNING, "User %s could not be found", user.c_str()); - exit(EXIT_FAILURE); - } struct group *grp = getgrnam(group.c_str()); if (grp) { setgid(grp->gr_gid); @@ -112,6 +105,13 @@ int main(int argc, char **argv) { syslog(LOG_WARNING, "Group %s could not be found", group.c_str()); exit(EXIT_FAILURE); } + struct passwd *pw = getpwnam(user.c_str()); + if (pw) { + setuid( pw->pw_uid ); + } else { + syslog(LOG_WARNING, "User %s could not be found", user.c_str()); + exit(EXIT_FAILURE); + } } /* Change the current working directory */ From aabc18c55b52684c2b0d5b58e2ebf35dc29958f5 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 3 Mar 2011 16:39:03 +0000 Subject: [PATCH 0617/2215] Changed device permissions and group --- telldus-core/tdadmin/05-tellstick.rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules index ea9d551e..c22d4888 100644 --- a/telldus-core/tdadmin/05-tellstick.rules +++ b/telldus-core/tdadmin/05-tellstick.rules @@ -1,2 +1,2 @@ -ID_VENDOR_ID=="1781", SUBSYSTEM=="usb" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" From 4c8110b9af9d2e14fea93cba2ebaab94aec208b8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 11:09:03 +0000 Subject: [PATCH 0618/2215] Dont flood if an error occur --- telldus-core/service/TellStick_libftdi.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 3a1d4cf3..3a2003ca 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -19,6 +19,7 @@ #include "Thread.h" #include "Mutex.h" #include "Strings.h" +#include "common.h" #include @@ -152,6 +153,11 @@ void TellStick::run() { } memset(buf, 0, sizeof(buf)); dwBytesRead = ftdi_read_data(&d->ftHandle, buf, sizeof(buf)); + if (dwBytesRead < 0) { + //An error occured, avoid flooding by sleeping longer + //Hopefully if will start working again + msleep(1000); //1s + } if (dwBytesRead < 1) { continue; } From 8e9536a3696a9e98b8ced6271501c5227c5df3b2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 11:09:42 +0000 Subject: [PATCH 0619/2215] Reset the parameters in the protocol if they change --- telldus-core/service/Device.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 3e565472..b660c671 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -94,6 +94,9 @@ std::list Device::getParametersForProtocol() const { void Device::setParameter(const std::wstring &key, const std::wstring &value){ d->parameterList[key] = value; + if(d->protocol){ + d->protocol->setParameters(d->parameterList); + } } int Device::getPreferredControllerId(){ From 7bb5b2b51d3eba6f5ee09efe374474ffa4016bfb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 12:51:15 +0000 Subject: [PATCH 0620/2215] Bumped version --- telldus-core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 4b6311d8..353054e2 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -11,7 +11,7 @@ ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 0) -SET(PACKAGE_PATCH_VERSION 103) +SET(PACKAGE_PATCH_VERSION 104) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") SET(PACKAGE_SUBVERSION) SET(PACKAGE_SOVERSION 2) From 80dfac02212ebddaf3a763349c0fbe5b1bcd5315 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 4 Mar 2011 13:35:47 +0000 Subject: [PATCH 0621/2215] Fixed udev-rule to work on device removal too --- telldus-core/tdadmin/05-tellstick.rules | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules index c22d4888..078ff757 100644 --- a/telldus-core/tdadmin/05-tellstick.rules +++ b/telldus-core/tdadmin/05-tellstick.rules @@ -1,2 +1,3 @@ -ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", ACTION=="remove" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" From 38f4ab6f530810d03efd6d979fca2bcfb22e6871 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 7 Mar 2011 09:57:44 +0000 Subject: [PATCH 0622/2215] Increased timeout from 1s to 5s between client library and service --- telldus-core/client/Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 089c98d0..594ac725 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -199,7 +199,7 @@ std::wstring Client::sendToService(const Message &msg) { } s.write(msg.data()); - return s.read(1000); + return s.read(5000); } void Client::stopThread(){ From 5466a79aadfa732c16da4743f0e66ed376f42c30 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 7 Mar 2011 09:59:56 +0000 Subject: [PATCH 0623/2215] Decreased the retry counter since it was longer than the timout between client and service --- telldus-core/service/TellStick_libftdi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 3a2003ca..cc98019b 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -190,7 +190,7 @@ int TellStick::send( const std::string &strMessage ) { delete[] tempMessage; - int retrycnt = 500; + int retrycnt = 200; unsigned char in; while(c && --retrycnt) { ret = ftdi_read_data( &d->ftHandle, &in, 1); From 11fda0dfc6b6e24651800a523ebedad66addd0db Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Mar 2011 11:36:10 +0000 Subject: [PATCH 0624/2215] Added paths for FreeBSD --- telldus-core/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 353054e2..3cb31edb 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -40,6 +40,11 @@ ELSE (WIN32) SET(TDADMIN_DEFAULT TRUE) ENDIF (WIN32) +IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + INCLUDE_DIRECTORIES(/usr/local/include) + LINK_DIRECTORIES(/usr/local/lib) +ENDIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + SET(BUILD_TDTOOL ${TDTOOL_DEFAULT} CACHE BOOL "Build tdtool") SET(BUILD_TDADMIN ${TDADMIN_DEFAULT} CACHE BOOL "Build tdadmin") From 6c4163f8317af4dae7235c8e53da234945950700 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Mar 2011 08:41:43 +0000 Subject: [PATCH 0625/2215] Integrated patches for FreeBSD from jstrom --- telldus-core/common/common.h | 2 +- telldus-core/service/main_unix.cpp | 8 +++++--- telldus-core/tdadmin/CMakeLists.txt | 6 ++++++ telldus-core/tdadmin/main.cpp | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 465379ab..1d009f54 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -43,7 +43,7 @@ inline void debuglog(const int intMessage, const std::string strMessage){ file.flush(); file.close(); -#elif !defined(_MACOSX) +#elif !defined(_MACOSX) && !defined(__FreeBSD__) pthread_t thread = pthread_self(); printf("[%i] %i - %s\n", (int)thread, intMessage, strMessage.c_str()); fflush(stdout); diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index f6fcef66..4ea53637 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -64,7 +65,8 @@ int main(int argc, char **argv) { fprintf(fd,"%d\n",pid); fclose(fd); } else { - syslog(LOG_ERR, "Could not write pid file"); + syslog(LOG_ERR, "Could not open pid file %s: %s", PID_FILE, strerror(errno)); + exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } @@ -73,7 +75,7 @@ int main(int argc, char **argv) { setlogmask(LOG_UPTO(LOG_INFO)); openlog(DAEMON_NAME, LOG_CONS, LOG_USER); - syslog(LOG_INFO, "%s daemon starting up", DAEMON_NAME); + syslog(LOG_NOTICE, "%s daemon starting up", DAEMON_NAME); if (deamonize) { /* Change the file mode mask */ @@ -126,6 +128,6 @@ int main(int argc, char **argv) { tm.start(); - syslog(LOG_INFO, "%s daemon exited", DAEMON_NAME); + syslog(LOG_NOTICE, "%s daemon exited", DAEMON_NAME); exit(EXIT_SUCCESS); } diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt index e2ecc623..3c4ffbd6 100644 --- a/telldus-core/tdadmin/CMakeLists.txt +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -30,6 +30,12 @@ ELSEIF (APPLE) TARGET_LINK_LIBRARIES(tdadmin TelldusCore ) +ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + # FreeBSD does not have argp in base libc; port devel/argp-standalone is required. + TARGET_LINK_LIBRARIES(tdadmin + ${CMAKE_BINARY_DIR}/client/libtelldus-core.so + argp + ) ELSE (WIN32) TARGET_LINK_LIBRARIES(tdadmin ${CMAKE_BINARY_DIR}/client/libtelldus-core.so diff --git a/telldus-core/tdadmin/main.cpp b/telldus-core/tdadmin/main.cpp index db040050..6afd4733 100644 --- a/telldus-core/tdadmin/main.cpp +++ b/telldus-core/tdadmin/main.cpp @@ -1,6 +1,6 @@ #include "../client/telldus-core.h" #include -#include +#include #include #include From 35c7fc13a1a3ff61059a447dcdb5cbdbfc6dadf8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Mar 2011 10:41:46 +0000 Subject: [PATCH 0626/2215] Build fixes for FreeBSD. Find libraries and make sure correct constness on different platforms --- telldus-core/common/CMakeLists.txt | 11 +++++++++++ telldus-core/common/Strings.cpp | 12 ++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index f07e1504..aaa310ea 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -44,6 +44,17 @@ ELSEIF (WIN32) LIST(APPEND telldus-common_SRCS Socket_win.cpp ) +ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + #### FreeBSD #### + SET( telldus-common_TARGET telldus-common ) + FIND_LIBRARY(ICONV_LIBRARY iconv) + ADD_DEFINITIONS( -D_FREEBSD ) + LIST(APPEND telldus-common_SRCS + Socket_unix.cpp + ) + LIST(APPEND telldus-common_LIBRARIES + ${ICONV_LIBRARY} + ) ELSE (APPLE) #### Linux #### SET( telldus-common_TARGET telldus-common ) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 7fee0582..ff786ae8 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -45,7 +45,11 @@ std::wstring TelldusCore::charToWstring(const char *value) { char *outString = (char*)new wchar_t[utf8Length+1]; memset(outString, 0, sizeof(wchar_t)*(utf8Length+1)); - char *inPointer = inString; +#ifdef _FREEBSD + const char *inPointer = inString; +#else + char *inPointer = inString; +#endif char *outPointer = outString; iconv_t convDesc = iconv_open(WCHAR_T_ENCODING, "UTF-8"); @@ -128,7 +132,11 @@ std::string TelldusCore::wideToString(const std::wstring &input) { char *outString = new char[outbytesLeft]; memset(outString, 0, sizeof(char)*(outbytesLeft)); - char *inPointer = inString; +#ifdef _FREEBSD + const char *inPointer = inString; +#else + char *inPointer = inString; +#endif char *outPointer = outString; iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING); From 16caccfbb4b1f4b21be64fe7551ffafaad45347d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Mar 2011 10:42:35 +0000 Subject: [PATCH 0627/2215] Find argp prettier on FreeBSD --- telldus-core/tdadmin/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt index 3c4ffbd6..7118bca2 100644 --- a/telldus-core/tdadmin/CMakeLists.txt +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -32,9 +32,10 @@ ELSEIF (APPLE) ) ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") # FreeBSD does not have argp in base libc; port devel/argp-standalone is required. + FIND_LIBRARY(ARGP_LIBRARY argp) TARGET_LINK_LIBRARIES(tdadmin ${CMAKE_BINARY_DIR}/client/libtelldus-core.so - argp + ${ARGP_LIBRARY} ) ELSE (WIN32) TARGET_LINK_LIBRARIES(tdadmin From 8bbdea67971a570bd8f6d1ad32abffe6dbc88d49 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Mar 2011 10:46:35 +0000 Subject: [PATCH 0628/2215] Fixed some 'No newline at end of file' warnings --- telldus-core/service/Controller.h | 2 +- telldus-core/service/ControllerMessage.cpp | 2 +- telldus-core/service/ControllerMessage.h | 2 +- telldus-core/service/Protocol.h | 2 +- telldus-core/service/ProtocolBrateck.h | 2 +- telldus-core/service/ProtocolFuhaote.h | 2 +- telldus-core/service/ProtocolGroup.cpp | 2 +- telldus-core/service/ProtocolIkea.h | 2 +- telldus-core/service/ProtocolRisingSun.h | 2 +- telldus-core/service/ProtocolScene.cpp | 2 +- telldus-core/service/ProtocolUpm.h | 2 +- telldus-core/service/ProtocolX10.h | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index b9ea8f6f..5d0cbd0b 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -26,4 +26,4 @@ private: PrivateData *d; }; -#endif //CONTROLLER_H \ No newline at end of file +#endif //CONTROLLER_H diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index c4296f62..afbc73b8 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -53,4 +53,4 @@ std::string ControllerMessage::getParameter(const std::string &key){ return ""; } return d->parameters[key]; -} \ No newline at end of file +} diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index dc0a7595..cea095f7 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -17,4 +17,4 @@ private: PrivateData *d; }; -#endif //CONTROLLERMESSAGE_H \ No newline at end of file +#endif //CONTROLLERMESSAGE_H diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 16340824..69b645b5 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -35,4 +35,4 @@ private: PrivateData *d; }; -#endif //PROTOCOL_H \ No newline at end of file +#endif //PROTOCOL_H diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index 1c729f20..97eba44d 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -10,4 +10,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLBRATECK_H \ No newline at end of file +#endif //PROTOCOLBRATECK_H diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index 166c1613..3b89d06c 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -10,4 +10,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLFUHAOTE_H \ No newline at end of file +#endif //PROTOCOLFUHAOTE_H diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index d6452df5..6fdb0222 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -6,4 +6,4 @@ int ProtocolGroup::methods() const { std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { return ""; -} \ No newline at end of file +} diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index 01badae9..81327d8e 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -10,4 +10,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLIKEA_H \ No newline at end of file +#endif //PROTOCOLIKEA_H diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h index 748196d0..1d338fc3 100644 --- a/telldus-core/service/ProtocolRisingSun.h +++ b/telldus-core/service/ProtocolRisingSun.h @@ -15,4 +15,4 @@ protected: static std::string getCodeSwitchTuple(int code); }; -#endif //PROTOCOLRISINGSUN_H \ No newline at end of file +#endif //PROTOCOLRISINGSUN_H diff --git a/telldus-core/service/ProtocolScene.cpp b/telldus-core/service/ProtocolScene.cpp index c874023a..811aa7f0 100644 --- a/telldus-core/service/ProtocolScene.cpp +++ b/telldus-core/service/ProtocolScene.cpp @@ -6,4 +6,4 @@ int ProtocolScene::methods() const { std::string ProtocolScene::getStringForMethod(int method, unsigned char data, Controller *) { return ""; -} \ No newline at end of file +} diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h index c378d296..1f91dafe 100644 --- a/telldus-core/service/ProtocolUpm.h +++ b/telldus-core/service/ProtocolUpm.h @@ -10,4 +10,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLUPM_H \ No newline at end of file +#endif //PROTOCOLUPM_H diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index a71c57b7..53327bbd 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -10,4 +10,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLX10_H \ No newline at end of file +#endif //PROTOCOLX10_H From 60dd56194028a270e1af0d6e3fba978691b05169 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 14 Mar 2011 15:32:08 +0000 Subject: [PATCH 0629/2215] Fixed two typos --- telldus-core/service/TellStick_libftdi.cpp | 2 +- telldus-core/tdadmin/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index cc98019b..b2496421 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -184,7 +184,7 @@ int TellStick::send( const std::string &strMessage ) { if(ret < 0) { c = false; } else if(ret != strMessage.length()) { - fprintf(stderr, "wierd send length? retval %i instead of %d\n", + fprintf(stderr, "weird send length? retval %i instead of %d\n", ret, (int)strMessage.length()); } diff --git a/telldus-core/tdadmin/main.cpp b/telldus-core/tdadmin/main.cpp index 6afd4733..698f13b0 100644 --- a/telldus-core/tdadmin/main.cpp +++ b/telldus-core/tdadmin/main.cpp @@ -18,7 +18,7 @@ const int SERIAL = 3; static struct argp_option options[] = { {0,0,0,0, "COMMAND: controller, ACTION: connect/disconnect\n" - "Tells the deamon to add or remove a TellStick (duo)" + "Tells the daemon to add or remove a TellStick (duo)" }, {"vid",VID,"VID",0, "The vendor id (1781)" }, {"pid",PID,"PID",0,"The product id (0c30 or 0c31)" }, From 55f49a2c5a47ba74f74c2818135b00feba4ceb49 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 14 Mar 2011 15:34:10 +0000 Subject: [PATCH 0630/2215] Added man page to telldusd --- telldus-core/service/CMakeLists.txt | 19 +++++++++++++++++++ telldus-core/service/main_unix.cpp | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 0d4a1413..5ad4f31d 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -2,6 +2,12 @@ IF(COMMAND cmake_policy) CMAKE_POLICY(SET CMP0003 NEW) ENDIF(COMMAND cmake_policy) +SET (telldusd_DESCRIPTION + "background service for Telldus TellStick, must be running to control TellStick" +) + +ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) + ######## Non configurable options ######## SET( telldus-service_SRCS ClientCommunicationHandler.cpp @@ -176,6 +182,19 @@ IF (APPLE) ) ENDIF (APPLE) +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET ${telldus-service_TARGET} + POST_BUILD + COMMAND help2man -n ${telldusd_DESCRIPTION} ./telldusd > telldusd.1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file telldusd.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/telldusd.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + IF (UNIX AND NOT APPLE) INSTALL(TARGETS ${telldus-service_TARGET} RUNTIME DESTINATION sbin) SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 4ea53637..7bfc36c5 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -47,6 +47,17 @@ int main(int argc, char **argv) { if (strcmp(argv[i], "--nodaemon") == 0) { deamonize = false; } + if (strcmp(argv[i], "--help") == 0) { + printf("Telldus TellStick background service\n\nStart with --nodaemon to not run as daemon\n\n"); + printf("Report bugs to \n"); + exit(EXIT_SUCCESS); + } + if (strcmp(argv[i], "--version") == 0) { + printf("telldusd " VERSION "\n\n"); + printf("Copyright (C) 2011 Telldus Technologies AB\n\n"); + printf("Written by Micke Prag \n"); + exit(EXIT_SUCCESS); + } } if (deamonize) { From 2c9df662d6b7f89ede4da0d13c76181ce3e40d6e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 14 Mar 2011 15:37:21 +0000 Subject: [PATCH 0631/2215] Make sure we only export the public symbols --- telldus-core/client/CMakeLists.txt | 4 ++++ telldus-core/client/telldus-core.h | 2 +- telldus-core/common/CMakeLists.txt | 4 +++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 589c0cf7..a060dcf3 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -85,6 +85,10 @@ ADD_LIBRARY(${telldus-core_TARGET} SHARED ${telldus-core_PUB_HDRS} ) +IF (UNIX) + SET_TARGET_PROPERTIES( ${telldus-core_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") +ENDIF (UNIX) + TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) SET_PROPERTY(TARGET ${telldus-core_TARGET} diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 892544ac..5fc031da 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -22,7 +22,7 @@ #define WINAPI __stdcall #else #define WINAPI - #define TELLSTICK_API + #define TELLSTICK_API __attribute__ ((visibility("default"))) #endif typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index aaa310ea..9a4eb15a 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -73,6 +73,8 @@ ADD_LIBRARY(${telldus-common_TARGET} STATIC ${telldus-common_HDRS} ) -SET_TARGET_PROPERTIES( ${telldus-common_TARGET} PROPERTIES COMPILE_FLAGS -fPIC) +IF (UNIX) + SET_TARGET_PROPERTIES( ${telldus-common_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") +ENDIF (UNIX) TARGET_LINK_LIBRARIES( ${telldus-common_TARGET} ${telldus-common_LIBRARIES} ) From 8565682ad825dae8a9ee3cb1d57b791dd8401f6f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 31 Mar 2011 12:54:28 +0000 Subject: [PATCH 0632/2215] Initializing OVERLAPPED to a value, possibly fixing service communication error in Windows Server 2003. --- telldus-core/common/Socket_win.cpp | 6 +++++- telldus-core/service/ConnectionListener_win.cpp | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 3bc80bc7..023b5e94 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -86,6 +86,8 @@ std::wstring Socket::read(int timeout){ int result; DWORD cbBytesRead = 0; OVERLAPPED oOverlap; + + memset(&oOverlap, 0, sizeof(OVERLAPPED)); d->readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); oOverlap.hEvent = d->readEvent; @@ -124,11 +126,13 @@ std::wstring Socket::read(int timeout){ void Socket::write(const std::wstring &msg){ - OVERLAPPED oOverlap; + OVERLAPPED oOverlap; DWORD bytesWritten = 0; int result; BOOL fSuccess; + memset(&oOverlap, 0, sizeof(OVERLAPPED)); + HANDLE writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); oOverlap.hEvent = writeEvent; diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 5d328bd9..03919f6e 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -87,6 +87,8 @@ void ConnectionListener::run() { OVERLAPPED oOverlap; DWORD cbBytesRead; + memset(&oOverlap, 0, sizeof(OVERLAPPED)); + d->hEvent = CreateEvent(NULL, true, false, NULL); oOverlap.hEvent = d->hEvent; From 99f0b133a8bef4f7da7432888634fe0f54bee32c Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 9 May 2011 15:29:41 +0000 Subject: [PATCH 0633/2215] Added decoding of receiving protocol everflourish --- telldus-core/service/Controller.cpp | 15 ++++++++ telldus-core/service/Controller.h | 5 ++- telldus-core/service/Protocol.cpp | 14 +++++++ telldus-core/service/Protocol.h | 5 ++- telldus-core/service/ProtocolEverflourish.cpp | 38 +++++++++++++++++++ telldus-core/service/ProtocolEverflourish.h | 1 + telldus-core/service/TellStick_libftdi.cpp | 2 + 7 files changed, 76 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 4737a63d..ca4bc4e7 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -1,4 +1,7 @@ #include "Controller.h" +#include "Protocol.h" +#include "ControllerMessage.h" +#include //TODO DEBUG class Controller::PrivateData { public: @@ -22,3 +25,15 @@ void Controller::publishData(const std::string &msg) const { data->controllerId = d->id; d->event->signal(data); } + +void Controller::decodePublishData(const std::string &data) const { + + ControllerMessage dataMsg(data); + std::wstring protocolName = dataMsg.protocol(); + std::string dataParam = dataMsg.getParameter("data"); + std::list msgList = Protocol::decodeData(protocolName, dataParam); + + for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt){ + this->publishData(*msgIt); + } +} \ No newline at end of file diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 5d0cbd0b..a1b92e74 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -1,4 +1,4 @@ -#ifndef CONTROLLER_H +#ifndef CONTROLLER_H #define CONTROLLER_H #include "Event.h" @@ -20,10 +20,11 @@ public: protected: Controller(int id, Event *event); void publishData(const std::string &data) const; + void decodePublishData(const std::string &data) const; private: class PrivateData; PrivateData *d; }; -#endif //CONTROLLER_H +#endif //CONTROLLER_H diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index e2552032..e2699eff 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -191,3 +191,17 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr return parameters; } + +std::list Protocol::decodeData(const std::wstring &protocolName, const std::string &data) { + std::list retval; + std::string decoded = ""; + + if( protocolName == L"everflourish" ) { + decoded = ProtocolEverflourish::decodeData(data); + if (decoded != "") { + retval.push_back(decoded); + } + } + + return retval; +} diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 69b645b5..12bf37f9 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -1,4 +1,4 @@ -#ifndef PROTOCOL_H +#ifndef PROTOCOL_H #define PROTOCOL_H #include @@ -18,6 +18,7 @@ public: static Protocol *getProtocolInstance(const std::wstring &protocolname); static std::list getParametersForProtocol(const std::wstring &protocolName); + static std::list decodeData(const std::wstring &protocolname, const std::string &data); virtual int methods() const = 0; std::wstring model() const; @@ -35,4 +36,4 @@ private: PrivateData *d; }; -#endif //PROTOCOL_H +#endif //PROTOCOL_H diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index eb2022c1..d7081beb 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -1,4 +1,6 @@ #include "ProtocolEverflourish.h" +#include +#include int ProtocolEverflourish::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; @@ -83,3 +85,39 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { return res; } + +std::string ProtocolEverflourish::decodeData(const std::string& data) +{ + unsigned int allData; + unsigned int house = 0; + unsigned int unit = 0; + unsigned int method = 0; + + sscanf(data.c_str(), "%X", &allData); + + house = allData & 0xFFFC00; + house >>= 10; + + unit = allData & 0x300; + unit >>= 8; + + method = allData & 0xF; + + std::stringstream retString; + retString << "class:command;protocol:everflourish;model:selflearning;house:0x" << std::hex << house << std::dec << ";unit:0x" << std::hex << unit << std::dec << ";method:"; + if(method == 0){ + retString << "turnoff;"; + } + else if(method == 15){ + retString << "turnon;"; + } + else if(method == 10){ + retString << "learn;"; + } + else { + //not everflourish + return ""; + } + + return retString.str(); +} \ No newline at end of file diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 6007b7ce..23f1f72b 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -8,6 +8,7 @@ class ProtocolEverflourish : public Protocol public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + static std::string decodeData(const std::string &data); private: static unsigned int calculateChecksum(unsigned int x); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index b2496421..1642e273 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -120,6 +120,8 @@ void TellStick::processData( const std::string &data ) { d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); + } else if(d->message.substr(0,2).compare("+W") == 0) { + this->decodePublishData(d->message.substr(2)); } d->message.clear(); } else { // Append the character From c7d51b249f66ae0cf09f6d97d0d4058d4e41cd25 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 10 May 2011 09:53:38 +0000 Subject: [PATCH 0634/2215] Added function Protocol::checkBit() --- telldus-core/service/Protocol.cpp | 12 ++++++++---- telldus-core/service/Protocol.h | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index e2699eff..574f177a 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -80,6 +80,10 @@ int Protocol::getIntParameter(const std::wstring &name, int min, int max) const return intValue; } +bool Protocol::checkBit(int data, int bitno) { + return ((data>>bitno)&0x01); +} + Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ if(TelldusCore::comparei(protocolname, L"arctech")){ @@ -181,10 +185,10 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"yidong")) { parameters.push_back("unit"); - + } else if (TelldusCore::comparei(protocolName, L"group")) { parameters.push_back("devices"); - + } else if (TelldusCore::comparei(protocolName, L"scene")) { parameters.push_back("devices"); } @@ -195,13 +199,13 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr std::list Protocol::decodeData(const std::wstring &protocolName, const std::string &data) { std::list retval; std::string decoded = ""; - + if( protocolName == L"everflourish" ) { decoded = ProtocolEverflourish::decodeData(data); if (decoded != "") { retval.push_back(decoded); } } - + return retval; } diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 12bf37f9..fca85d8e 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -31,6 +31,8 @@ protected: std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; int getIntParameter(const std::wstring &name, int min, int max) const; + static bool checkBit(int data, int bit); + private: class PrivateData; PrivateData *d; From f5b832c3c6afb954bf5b7f1363b29e6fe9aaff6d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 10 May 2011 09:54:13 +0000 Subject: [PATCH 0635/2215] Changed to a better compare function for protocol --- telldus-core/service/Protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 574f177a..c228ded0 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -200,7 +200,7 @@ std::list Protocol::decodeData(const std::wstring &protocolName, co std::list retval; std::string decoded = ""; - if( protocolName == L"everflourish" ) { + if( protocolName.compare(L"everflourish") == 0 ) { decoded = ProtocolEverflourish::decodeData(data); if (decoded != "") { retval.push_back(decoded); From 6d5ec4214c857cc5fb7689fb7b857d63b2c459c7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 10 May 2011 09:55:46 +0000 Subject: [PATCH 0636/2215] Added decoding of X10-data --- telldus-core/service/Protocol.cpp | 5 ++ telldus-core/service/ProtocolX10.cpp | 71 +++++++++++++++++++++++++++- telldus-core/service/ProtocolX10.h | 2 + 3 files changed, 77 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index c228ded0..b2a3818b 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -205,6 +205,11 @@ std::list Protocol::decodeData(const std::wstring &protocolName, co if (decoded != "") { retval.push_back(decoded); } + } else if( protocolName.compare(L"x10") == 0 ) { + decoded = ProtocolX10::decodeData(data); + if (decoded != "") { + retval.push_back(decoded); + } } return retval; diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index d8922809..d37abf61 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -1,4 +1,8 @@ #include "ProtocolX10.h" +#include +#include + +const unsigned char HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; int ProtocolX10::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; @@ -8,7 +12,6 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont const unsigned char S = 59, L = 169; const char B0[] = {S,S,0}; const char B1[] = {S,L,0}; - const int HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; const unsigned char START_CODE[] = {'S',255,1,255,1,255,1,100,255,1,180,0}; const unsigned char STOP_CODE[] = {S,0}; @@ -103,3 +106,69 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont return strReturn; } + +std::string ProtocolX10::decodeData(const std::string& data) { + int intData = 0, currentBit = 31; + bool method=0; + sscanf(data.c_str(), "%X", &intData); + + int unit = 0; + int rawHouse = 0; + for(int i = 0; i < 4; ++i) { + rawHouse >>= 1; + if (checkBit(intData, currentBit--)) { + rawHouse |= 0x8; + } + } + + if (checkBit(intData, currentBit--) != 0) { + return ""; + } + + if (checkBit(intData, currentBit--)) { + unit |= (1<<3); + } + + if (checkBit(intData, currentBit--)) { + return ""; + } + if (checkBit(intData, currentBit--)) { + return ""; + } + + currentBit = 14; + + if (checkBit(intData, currentBit--)) { + unit |= (1<<2); + } + if (checkBit(intData, currentBit--)) { + method = 1; + } + if (checkBit(intData, currentBit--)) { + unit |= (1<<0); + } + if (checkBit(intData, currentBit--)) { + unit |= (1<<1); + } + + int intHouse = 0; + for(int i = 0; i < 16; ++i) { + if (HOUSES[i] == rawHouse) { + intHouse = i; + break; + } + } + + std::stringstream retString; + retString << "class:command;protocol:x10;model:codeswitch;"; + retString << "house:" << (char)('A' + intHouse); + retString << ";unit:" << unit+1; + retString << ";method:"; + if(method == 0){ + retString << "turnon;"; + } else { + retString << "turnoff;"; + } + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 53327bbd..e998a4b6 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -8,6 +8,8 @@ class ProtocolX10 : public Protocol public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + + static std::string decodeData(const std::string& data); }; #endif //PROTOCOLX10_H From 4d2b80ae118527a3530e3d7ac6070022e7e2fb15 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 10:32:45 +0000 Subject: [PATCH 0637/2215] Added debug function dlog which works lite printf but it always flushes the result. --- telldus-core/common/common.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 1d009f54..e078688a 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -18,6 +18,7 @@ #include #include #include +#include inline void msleep( const int msec) { #ifdef _WINDOWS @@ -27,6 +28,15 @@ inline void msleep( const int msec) { #endif } +inline void dlog(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + fflush(stdout); +} + inline void debuglog(const int intMessage, const std::string strMessage){ #ifdef _WINDOWS static bool firstRun = true; From 281621a4ef0fa17d25b5cb6dfbcf0639a8ea4a85 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 12 May 2011 14:09:37 +0000 Subject: [PATCH 0638/2215] Receiving protocols decode according to new standard --- telldus-core/service/Protocol.cpp | 25 ++-- telldus-core/service/Protocol.h | 2 +- telldus-core/service/ProtocolEverflourish.cpp | 14 ++- telldus-core/service/ProtocolEverflourish.h | 3 +- telldus-core/service/ProtocolNexa.cpp | 111 ++++++++++++++++++ telldus-core/service/ProtocolNexa.h | 7 ++ telldus-core/service/ProtocolSartano.cpp | 70 +++++++++++ telldus-core/service/ProtocolSartano.h | 2 + telldus-core/service/ProtocolWaveman.cpp | 64 +++++++++- telldus-core/service/ProtocolWaveman.h | 4 + 10 files changed, 286 insertions(+), 16 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index b2a3818b..3974b015 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,6 +1,7 @@ #include "Protocol.h" #include "../client/telldus-core.h" +#include "ControllerMessage.h" #include "ProtocolBrateck.h" #include "ProtocolComen.h" #include "ProtocolEverflourish.h" @@ -196,21 +197,31 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr return parameters; } -std::list Protocol::decodeData(const std::wstring &protocolName, const std::string &data) { +std::list Protocol::decodeData(const std::string &fullData) { std::list retval; std::string decoded = ""; - - if( protocolName.compare(L"everflourish") == 0 ) { - decoded = ProtocolEverflourish::decodeData(data); + + ControllerMessage dataMsg(fullData); + if( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) { + decoded = ProtocolNexa::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); } - } else if( protocolName.compare(L"x10") == 0 ) { - decoded = ProtocolX10::decodeData(data); + decoded = ProtocolWaveman::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + decoded = ProtocolSartano::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); } } - + else if(TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) { + decoded = ProtocolEverflourish::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } + return retval; } diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index fca85d8e..6168f8d6 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -18,7 +18,7 @@ public: static Protocol *getProtocolInstance(const std::wstring &protocolname); static std::list getParametersForProtocol(const std::wstring &protocolName); - static std::list decodeData(const std::wstring &protocolname, const std::string &data); + static std::list decodeData(const std::string &fullData); virtual int methods() const = 0; std::wstring model() const; diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index d7081beb..c74326fa 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -1,6 +1,7 @@ #include "ProtocolEverflourish.h" -#include #include +#include +#include "ControllerMessage.h" int ProtocolEverflourish::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; @@ -86,8 +87,9 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { return res; } -std::string ProtocolEverflourish::decodeData(const std::string& data) +std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) { + std::string data = dataMsg.getParameter("data"); unsigned int allData; unsigned int house = 0; unsigned int unit = 0; @@ -100,11 +102,17 @@ std::string ProtocolEverflourish::decodeData(const std::string& data) unit = allData & 0x300; unit >>= 8; + unit++; //unit from 1 to 4 method = allData & 0xF; + if(house < 0 || house > 16383 || unit < 1 || unit > 4){ + //not everflourish + return ""; + } + std::stringstream retString; - retString << "class:command;protocol:everflourish;model:selflearning;house:0x" << std::hex << house << std::dec << ";unit:0x" << std::hex << unit << std::dec << ";method:"; + retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:"; if(method == 0){ retString << "turnoff;"; } diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 23f1f72b..28d783eb 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -1,6 +1,7 @@ #ifndef PROTOCOLEVERFLOURISH_H #define PROTOCOLEVERFLOURISH_H +#include "ControllerMessage.h" #include "Protocol.h" class ProtocolEverflourish : public Protocol @@ -8,7 +9,7 @@ class ProtocolEverflourish : public Protocol public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(const std::string &data); + static std::string decodeData(ControllerMessage &dataMsg); private: static unsigned int calculateChecksum(unsigned int x); diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 9343f935..4ec2ecc9 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,7 +1,11 @@ #include "ProtocolNexa.h" +#include +#include #include "TellStick.h" #include "Strings.h" +int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; //TODO, always removing first turnon now, make more flexible (waveman too) + int ProtocolNexa::methods() const { if (TelldusCore::comparei(model(), L"codeswitch")) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); @@ -153,6 +157,113 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode return strMessage; } +std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) +{ + unsigned long allData = 0; + + sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); + + if(dataMsg.getParameter("model") == "selflearning"){ + //selflearning + return decodeDataSelfLearning(allData); + } + else{ + //codeswitch + return decodeDataCodeSwitch(allData); + } +} + +std::string ProtocolNexa::decodeDataSelfLearning(long allData){ + unsigned int house = 0; + unsigned int unit = 0; + unsigned int group = 0; + unsigned int method = 0; + + house = allData & 0xFFFFFFC0; + house >>= 6; + + group = allData & 0x20; + group >>= 5; + + method = allData & 0x10; + method >>= 4; + + unit = allData & 0xF; + unit++; + + if(house < 1 || house > 67108863 || unit < 1 || unit > 16){ + //not arctech selflearning + return ""; + } + + std::stringstream retString; + retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:"; + if(method == 1){ + retString << "turnon;"; + } + else if(method == 0){ + retString << "turnoff;"; + } + else { + //not arctech selflearning + return ""; + } + + return retString.str(); +} + +std::string ProtocolNexa::decodeDataCodeSwitch(long allData){ + + unsigned int house = 0; + unsigned int unit = 0; + unsigned int method = 0; + + method = allData & 0xF00; + method >>= 8; + + unit = allData & 0xF0; + unit >>= 4; + unit++; + + house = allData & 0xF; + + if(house < 0 || house > 16 || unit < 1 || unit > 16){ + //not arctech codeswitch + return ""; + } + + house = house + 'A'; //house from A to P + + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ + lastArctecCodeSwitchWasTurnOff = 0; + return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose + //one turnon/bell, but it's better than the alternative... + } + + if(method == 6){ + lastArctecCodeSwitchWasTurnOff = 1; + } + + std::stringstream retString; + retString << "class:command;protocol:arctech;model:codeswitch;house:" << char(house); + + if(method == 6){ + retString << ";unit:" << unit << ";method:turnoff;"; + } + else if(method == 14){ + retString << ";unit:" << unit << ";method:turnon;"; + } + else if(method == 15){ + retString << ";method:bell;"; + } + else { + //not arctech codeswitch + return ""; + } + + return retString.str(); +} + std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { std::string strReturn = ""; for( int i = 0; i < 4; ++i ) { diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 2e540976..90cf06db 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -1,6 +1,7 @@ #ifndef PROTOCOLNEXA_H #define PROTOCOLNEXA_H +#include "ControllerMessage.h" #include "Device.h" #include @@ -8,6 +9,7 @@ class ProtocolNexa : public Protocol { public: virtual int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + static std::string decodeData(ControllerMessage& dataMsg); protected: std::string getStringSelflearning(int method, unsigned char data); @@ -16,6 +18,11 @@ protected: virtual std::string getOffCode() const; static std::string getCodeSwitchTuple(int code); static std::string getStringSelflearningForCode(int house, int unit, int method, unsigned char data); + +private: + static int lastArctecCodeSwitchWasTurnOff; + static std::string decodeDataCodeSwitch(long allData); + static std::string decodeDataSelfLearning(long allData); }; #endif //PROTOCOLNEXA_H diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 12f679e3..a5f59d81 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -1,4 +1,6 @@ #include "ProtocolSartano.h" +#include +#include int ProtocolSartano::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; @@ -32,3 +34,71 @@ std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int m return strReturn; } + +std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + signed int allDataIn; + signed int allData = 0; + unsigned int code = 0; + unsigned int method1 = 0; + unsigned int method2 = 0; + unsigned int method = 0; + + sscanf(data.c_str(), "%X", &allDataIn); + + unsigned long mask = 0b100000000000; + for(int i=0;i<12;++i){ + allData >>= 1; + if((allDataIn & mask) == 0){ + allData |= (1<<11); + } + mask >>= 1; + } + + code = allData & 0xFFC; + code >>= 2; + + method1 = allData & 0x2; + method1 >>= 1; + + method2 = allData & 0x1; + + if(method1 == 0 && method2 == 1){ + method = 0; //off + } + else if(method1 == 1 && method2 == 0){ + method = 1; //on + } + else{ + return ""; + } + + if(code < 0 || code > 1023){ + //not sartano + return ""; + } + + std::stringstream retString; + retString << "class:command;protocol:sartano;model:codeswitch;code:"; + mask = 0b1000000000; + for(int i=0;i<10;i++){ + if((code & mask) != 0){ + retString << 1; + } + else{ + retString << 0; + } + mask >>= 1; + } + retString << ";method:"; + + if(method == 0){ + retString << "turnoff;"; + } + else{ + retString << "turnon;"; + } + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index ae91acde..6c38a263 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -1,6 +1,7 @@ #ifndef PROTOCOLSARTANO_H #define PROTOCOLSARTANO_H +#include "ControllerMessage.h" #include "Protocol.h" class ProtocolSartano : public Protocol @@ -8,6 +9,7 @@ class ProtocolSartano : public Protocol public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + static std::string decodeData(ControllerMessage &dataMsg); protected: std::string getStringForCode(const std::wstring &code, int method); diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index d71bb50a..c5f68d2e 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -1,4 +1,8 @@ #include "ProtocolWaveman.h" +#include +#include + +int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff=0; int ProtocolWaveman::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; @@ -6,8 +10,60 @@ int ProtocolWaveman::methods() const { std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) { return getStringCodeSwitch(method); -} - -std::string ProtocolWaveman::getOffCode() const { - return "$k$k$k$k$k$k$k$k$k+"; +} + +std::string ProtocolWaveman::getOffCode() const { + return "$k$k$k$k$k$k$k$k$k+"; +} + +std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) +{ + unsigned long allData = 0; + unsigned int house = 0; + unsigned int unit = 0; + unsigned int method = 0; + + sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); + + method = allData & 0xF00; + method >>= 8; + + unit = allData & 0xF0; + unit >>= 4; + unit++; + + house = allData & 0xF; + + if(house < 0 || house > 16 || unit < 1 || unit > 16){ + //not waveman + return ""; + } + + house = house + 'A'; //house from A to P + + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ + lastArctecCodeSwitchWasTurnOff = 0; + return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose + //one turnon/bell, but it's better than the alternative... + } + + if(method == 6){ + lastArctecCodeSwitchWasTurnOff = 1; + } + + std::stringstream retString; + retString << "class:command;protocol:waveman;model:codeswitch;house:" << char(house); + + if(method == 0){ + retString << ";unit:" << unit << ";method:turnoff;"; + } + else if(method == 14){ + retString << ";unit:" << unit << ";method:turnon;"; + } + else { + //not waveman + return ""; + } + + return retString.str(); } diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h index da433113..69b26333 100644 --- a/telldus-core/service/ProtocolWaveman.h +++ b/telldus-core/service/ProtocolWaveman.h @@ -7,9 +7,13 @@ class ProtocolWaveman : public ProtocolNexa { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + static std::string decodeData(ControllerMessage& dataMsg); protected: virtual std::string getOffCode() const; + +private: + static int lastArctecCodeSwitchWasTurnOff; }; #endif //PROTOCOLWAVEMAN_H From 6c48005af2cb0e98d83f1de6441c99da538f74e5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 14:45:23 +0000 Subject: [PATCH 0639/2215] Added class Sensor --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/Sensor.cpp | 39 +++++++++++++++++++++++++++++ telldus-core/service/Sensor.h | 24 ++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 telldus-core/service/Sensor.cpp create mode 100644 telldus-core/service/Sensor.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 5ad4f31d..61037f88 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -17,6 +17,7 @@ SET( telldus-service_SRCS Device.cpp DeviceManager.cpp Event.cpp + Sensor.cpp Settings.cpp TelldusMain.cpp TellStick.cpp @@ -67,6 +68,7 @@ SET( telldus-service_HDRS DeviceManager.h Event.h EventHandler.h + Sensor.h Settings.h TelldusMain.h TellStick.h diff --git a/telldus-core/service/Sensor.cpp b/telldus-core/service/Sensor.cpp new file mode 100644 index 00000000..d9781868 --- /dev/null +++ b/telldus-core/service/Sensor.cpp @@ -0,0 +1,39 @@ +#include "Sensor.h" +#include "common.h" + +class Sensor::PrivateData { +public: + std::wstring protocol, model; + int id; + time_t timestamp; +}; + +Sensor::Sensor(const std::wstring &protocol, const std::wstring &model, int id) + :Mutex() +{ + d = new PrivateData; + d->protocol = protocol; + d->model = model; + d->id = id; +} + +Sensor::~Sensor() { + delete d; +} + +std::wstring Sensor::protocol() const { + return d->protocol; +} + +std::wstring Sensor::model() const { + return d->model; +} + +int Sensor::id() const { + return d->id; +} + +void Sensor::setValue(const std::string &name, const std::string &value, time_t timestamp) { + //TODO: Do acctual storing of values + d->timestamp = timestamp; +} diff --git a/telldus-core/service/Sensor.h b/telldus-core/service/Sensor.h new file mode 100644 index 00000000..3b06e052 --- /dev/null +++ b/telldus-core/service/Sensor.h @@ -0,0 +1,24 @@ +#ifndef SENSOR_H +#define SENSOR_H + +#include "Mutex.h" +#include + +class Sensor : public TelldusCore::Mutex +{ +public: + Sensor(const std::wstring &protocol, const std::wstring &model, int id); + ~Sensor(); + + std::wstring protocol() const; + std::wstring model() const; + int id() const; + + void setValue(const std::string &name, const std::string &value, time_t timestamp); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif // SENSOR_H From 0b12c5379429da9ead26e773e05b14d231787a79 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 12 May 2011 14:46:54 +0000 Subject: [PATCH 0640/2215] Missing changes --- telldus-core/service/Controller.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index ca4bc4e7..fe663f65 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -1,6 +1,5 @@ #include "Controller.h" #include "Protocol.h" -#include "ControllerMessage.h" #include //TODO DEBUG class Controller::PrivateData { @@ -28,11 +27,8 @@ void Controller::publishData(const std::string &msg) const { void Controller::decodePublishData(const std::string &data) const { - ControllerMessage dataMsg(data); - std::wstring protocolName = dataMsg.protocol(); - std::string dataParam = dataMsg.getParameter("data"); - std::list msgList = Protocol::decodeData(protocolName, dataParam); - + std::list msgList = Protocol::decodeData(data); + for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt){ this->publishData(*msgIt); } From 183cc7ca0d377482c190decd046938d081fc54ce Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 14:49:31 +0000 Subject: [PATCH 0641/2215] Added functions ControllerMessage::msgClass(), ControllerMessage::model(), ControllerMessage::getIntMessage() and ControllerMessage::hasParameter() --- telldus-core/service/ControllerMessage.cpp | 41 +++++++++++++++++++--- telldus-core/service/ControllerMessage.h | 41 ++++++++++++---------- 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index afbc73b8..72c83f24 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -2,12 +2,14 @@ #include "Device.h" #include "Strings.h" +#include "common.h" + #include class ControllerMessage::PrivateData { public: std::map parameters; - std::string protocol; + std::string protocol, model, msgClass; int method; }; @@ -24,8 +26,12 @@ ControllerMessage::ControllerMessage(const std::string &message) { if (delim == std::string::npos) { break; } - if (param.substr(0, delim).compare("protocol") == 0) { + if (param.substr(0, delim).compare("class") == 0) { + d->msgClass = param.substr(delim+1, param.length()-delim); + } else if (param.substr(0, delim).compare("protocol") == 0) { d->protocol = param.substr(delim+1, param.length()-delim); + } else if (param.substr(0, delim).compare("model") == 0) { + d->model = param.substr(delim+1, param.length()-delim); } else if (param.substr(0, delim).compare("method") == 0) { d->method = Device::methodId(param.substr(delim+1, param.length()-delim)); } else { @@ -39,6 +45,10 @@ ControllerMessage::~ControllerMessage(){ delete d; } +std::string ControllerMessage::msgClass() const { + return d->msgClass; +} + int ControllerMessage::method() const { return d->method; } @@ -47,10 +57,33 @@ std::wstring ControllerMessage::protocol() const { return TelldusCore::charToWstring(d->protocol.c_str()); } -std::string ControllerMessage::getParameter(const std::string &key){ +std::wstring ControllerMessage::model() const { + return TelldusCore::charToWstring(d->model.c_str()); +} + +int ControllerMessage::getIntParameter(const std::string &key) const { + std::string strValue = getParameter(key); + if (strValue.compare("") == 0) { + return -1; + } + if (strValue.substr(0,2).compare("0x") == 0) { + return strtol(strValue.c_str(), NULL, 16); + } + return strtol(strValue.c_str(), NULL, 10); +} + +std::string ControllerMessage::getParameter(const std::string &key) const { std::map::iterator it = d->parameters.find(key); if (it == d->parameters.end()) { return ""; } return d->parameters[key]; -} +} + +bool ControllerMessage::hasParameter(const std::string &key) const { + std::map::iterator it = d->parameters.find(key); + if (it == d->parameters.end()) { + return false; + } + return true; +} diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index cea095f7..d08691ec 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -1,20 +1,25 @@ #ifndef CONTROLLERMESSAGE_H -#define CONTROLLERMESSAGE_H - -#include - -class ControllerMessage { -public: - ControllerMessage(const std::string &rawMessage); - virtual ~ControllerMessage(); - - std::string getParameter(const std::string &key); - int method() const; - std::wstring protocol() const; - -private: - class PrivateData; - PrivateData *d; -}; - +#define CONTROLLERMESSAGE_H + +#include + +class ControllerMessage { +public: + ControllerMessage(const std::string &rawMessage); + virtual ~ControllerMessage(); + + std::string msgClass() const; + int getIntParameter(const std::string &key) const; + std::string getParameter(const std::string &key) const; + int method() const; + std::wstring protocol() const; + std::wstring model() const; + + bool hasParameter(const std::string &key) const; + +private: + class PrivateData; + PrivateData *d; +}; + #endif //CONTROLLERMESSAGE_H From f25ca42ed74199db00cfcba7f2c847c7515710e8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 14:54:28 +0000 Subject: [PATCH 0642/2215] Added TDSensorEvent to EventUpdateManager --- telldus-core/service/EventUpdateManager.cpp | 9 +++++++++ telldus-core/service/EventUpdateManager.h | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 1b8b7749..b1175ff6 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -96,6 +96,15 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ msg.addArgument(data->eventValue); //string msg.addArgument(data->controllerId); } + else if(data->messageType == L"TDSensorEvent"){ + msg.addArgument("TDSensorEvent"); + msg.addArgument(data->protocol); + msg.addArgument(data->model); + msg.addArgument(data->sensorId); + msg.addArgument(data->dataType); + msg.addArgument(data->value); + msg.addArgument(data->timestamp); + } (*it)->write(msg); diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index b9ca1270..821bb43c 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -13,6 +13,14 @@ public: int eventDeviceChanges; int eventState; std::wstring eventValue; + + //Sensor event + std::wstring protocol; + std::wstring model; + int sensorId; + std::wstring dataType; + std::wstring value; + int timestamp; }; class EventUpdateManager : public TelldusCore::Thread From 38cfda5fcc3ce906293586e0eed520b56a09c690 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 14:56:07 +0000 Subject: [PATCH 0643/2215] Handle sensor messages and post them to the client --- telldus-core/service/DeviceManager.cpp | 58 ++++++++++++++++++++++++++ telldus-core/service/DeviceManager.h | 5 +++ 2 files changed, 63 insertions(+) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 2f83bdfd..8efd44dd 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,6 +1,7 @@ #include "DeviceManager.h" #include "ControllerMessage.h" #include "Mutex.h" +#include "Sensor.h" #include "Settings.h" #include "Strings.h" #include "Message.h" @@ -15,6 +16,7 @@ typedef std::map DeviceMap; class DeviceManager::PrivateData { public: DeviceMap devices; + std::list sensorList; Settings set; TelldusCore::Mutex lock; ControllerManager *controllerManager; @@ -35,6 +37,10 @@ DeviceManager::~DeviceManager(void) { {TelldusCore::MutexLocker deviceLocker(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere delete(it->second); } + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + {TelldusCore::MutexLocker sensorLocker(*it);} //aquire lock, and release it, just to see that the device it's not in use anywhere + delete(*it); + } } delete d; } @@ -577,6 +583,11 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData d->deviceUpdateEvent->signal(eventUpdateData); ControllerMessage msg(eventData.msg); + if (msg.msgClass().compare("sensor") == 0) { + handleSensorMessage(msg); + return; + } + TelldusCore::MutexLocker deviceListLocker(&d->lock); for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { TelldusCore::MutexLocker deviceLocker(it->second); @@ -608,6 +619,53 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData } } +void DeviceManager::handleSensorMessage(const ControllerMessage &msg) { + TelldusCore::MutexLocker sensorListLocker(&d->lock); + Sensor *sensor = 0; + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + TelldusCore::MutexLocker sensorLocker(*it); + if (!TelldusCore::comparei((*it)->protocol(), msg.protocol())) { + continue; + } + if (!TelldusCore::comparei((*it)->model(), msg.model())) { + continue; + } + if ((*it)->id() != msg.getIntParameter("id")) { + continue; + } + sensor = *it; + break; + } + + if (!sensor) { + sensor = new Sensor(msg.protocol(), msg.model(), msg.getIntParameter("id")); + d->sensorList.push_back(sensor); + } + TelldusCore::MutexLocker sensorLocker(sensor); + + time_t t = time(NULL); + + setSensorValueAndSignal("temp", sensor, msg, t); + setSensorValueAndSignal("humidity", sensor, msg, t); +} + +void DeviceManager::setSensorValueAndSignal( const std::string &dataType, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const { + if (!msg.hasParameter(dataType)) { + return; + } + sensor->setValue(dataType, msg.getParameter(dataType), timestamp); + + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDSensorEvent"; + eventData->protocol = sensor->protocol(); + eventData->model = sensor->model(); + eventData->sensorId = sensor->id(); + eventData->dataType = TelldusCore::charToWstring(dataType.c_str()); + eventData->value = TelldusCore::charToWstring(msg.getParameter(dataType).c_str()); + eventData->timestamp = timestamp; + d->deviceUpdateEvent->signal(eventData); +} + int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){ Controller *controller = d->controllerManager->getBestControllerById(-1); diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 4efa7662..b101e1f4 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -3,9 +3,12 @@ #include "Device.h" #include "ControllerManager.h" +#include "ControllerMessage.h" #include "EventUpdateManager.h" #include +class Sensor; + class DeviceManager { public: @@ -38,6 +41,8 @@ public: void handleControllerMessage(const ControllerEventData &event); private: + void handleSensorMessage(const ControllerMessage &msg); + void setSensorValueAndSignal( const std::string &dataType, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const; int getDeviceMethods(int deviceId, std::set &duplicateDeviceIds); int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId, std::set *duplicateDeviceIds); int executeScene(std::wstring singledevice, int groupDeviceId); From 61b193ad2d696687aca9fabdbb2f4327bba777f2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 14:57:54 +0000 Subject: [PATCH 0644/2215] Added class TDSensorEventDispatcher --- telldus-core/client/CallbackDispatcher.cpp | 16 ++++++++++++++++ telldus-core/client/CallbackDispatcher.h | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index b62beb02..72166b43 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -59,3 +59,19 @@ TDRawDeviceEventDispatcher::~TDRawDeviceEventDispatcher() { void TDRawDeviceEventDispatcher::run() { d->event(strData.c_str(), controllerId, d->id, d->context); } + +TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, const std::string &type, const std::string &v, int t) + :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t) +{ + d->mutex.lock(); + this->start(); +} + +TDSensorEventDispatcher::~TDSensorEventDispatcher() { + this->wait(); + d->mutex.unlock(); +} + +void TDSensorEventDispatcher::run() { + d->event(protocol.c_str(), model.c_str(), sensorId, dataType.c_str(), value.c_str(), timestamp, d->id, d->context); +} diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 6af43c98..b0a6a52f 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -55,6 +55,21 @@ namespace TelldusCore { int controllerId; std::string strData; }; + class TDSensorEventDispatcher : public Thread { + public: + TDSensorEventDispatcher( CallbackStruct *data, const std::string &protocol, const std::string &model, int id, const std::string &dataType, const std::string &value, int timestamp); + virtual ~TDSensorEventDispatcher(); + protected: + virtual void run(); + private: + CallbackStruct *d; + std::string protocol; + std::string model; + int sensorId; + std::string dataType; + std::string value; + int timestamp; + }; } #endif //CALLBACKDISPATCHER_H From b179835fc37e4d0f10f6adaf8e8ff74ca0fcf38c Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 12 May 2011 15:11:30 +0000 Subject: [PATCH 0645/2215] Readded x10 as receiving protocol --- telldus-core/service/Protocol.cpp | 11 +++++++++-- telldus-core/service/ProtocolX10.cpp | 4 ++-- telldus-core/service/ProtocolX10.h | 3 ++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 3974b015..8bf97ab8 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -85,6 +85,7 @@ bool Protocol::checkBit(int data, int bitno) { return ((data>>bitno)&0x01); } + Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ if(TelldusCore::comparei(protocolname, L"arctech")){ @@ -186,10 +187,10 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"yidong")) { parameters.push_back("unit"); - + } else if (TelldusCore::comparei(protocolName, L"group")) { parameters.push_back("devices"); - + } else if (TelldusCore::comparei(protocolName, L"scene")) { parameters.push_back("devices"); } @@ -222,6 +223,12 @@ std::list Protocol::decodeData(const std::string &fullData) { retval.push_back(decoded); } } + else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { + decoded = ProtocolX10::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } return retval; } diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index d37abf61..e6d3fef8 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -107,10 +107,10 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont } -std::string ProtocolX10::decodeData(const std::string& data) { +std::string ProtocolX10::decodeData(ControllerMessage& dataMsg) { int intData = 0, currentBit = 31; bool method=0; - sscanf(data.c_str(), "%X", &intData); + sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); int unit = 0; int rawHouse = 0; diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index e998a4b6..8e53095e 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -2,6 +2,7 @@ #define PROTOCOLX10_H #include "Protocol.h" +#include "ControllerMessage.h" class ProtocolX10 : public Protocol { @@ -9,7 +10,7 @@ public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(const std::string& data); + static std::string decodeData(ControllerMessage& dataMsg); }; #endif //PROTOCOLX10_H From 8f2413e630654884a79702fd57fdffd4ab378cb8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 15:17:24 +0000 Subject: [PATCH 0646/2215] Changed parameter dataType in SensorEvent to be an int instead of string --- telldus-core/service/DeviceManager.cpp | 8 ++++---- telldus-core/service/DeviceManager.h | 2 +- telldus-core/service/EventUpdateManager.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 8efd44dd..b9d65aee 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -645,11 +645,11 @@ void DeviceManager::handleSensorMessage(const ControllerMessage &msg) { time_t t = time(NULL); - setSensorValueAndSignal("temp", sensor, msg, t); - setSensorValueAndSignal("humidity", sensor, msg, t); + setSensorValueAndSignal("temp", TELLSTICK_TEMPERATURE, sensor, msg, t); + setSensorValueAndSignal("humidity", TELLSTICK_HUMIDITY, sensor, msg, t); } -void DeviceManager::setSensorValueAndSignal( const std::string &dataType, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const { +void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const { if (!msg.hasParameter(dataType)) { return; } @@ -660,7 +660,7 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, Sensor eventData->protocol = sensor->protocol(); eventData->model = sensor->model(); eventData->sensorId = sensor->id(); - eventData->dataType = TelldusCore::charToWstring(dataType.c_str()); + eventData->dataType = dataTypeId; eventData->value = TelldusCore::charToWstring(msg.getParameter(dataType).c_str()); eventData->timestamp = timestamp; d->deviceUpdateEvent->signal(eventData); diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index b101e1f4..57313f0c 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -42,7 +42,7 @@ public: private: void handleSensorMessage(const ControllerMessage &msg); - void setSensorValueAndSignal( const std::string &dataType, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const; + void setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const; int getDeviceMethods(int deviceId, std::set &duplicateDeviceIds); int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId, std::set *duplicateDeviceIds); int executeScene(std::wstring singledevice, int groupDeviceId); diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 821bb43c..56811c4c 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -18,7 +18,7 @@ public: std::wstring protocol; std::wstring model; int sensorId; - std::wstring dataType; + int dataType; std::wstring value; int timestamp; }; From 054f8076e12dadf4d8fdebfedc004e0a27249234 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 15:31:17 +0000 Subject: [PATCH 0647/2215] Changed parameter dataType in SensorEvent to be an int instead of string --- telldus-core/client/CallbackDispatcher.cpp | 4 ++-- telldus-core/client/CallbackDispatcher.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 72166b43..f23cfbf4 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -60,7 +60,7 @@ void TDRawDeviceEventDispatcher::run() { d->event(strData.c_str(), controllerId, d->id, d->context); } -TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, const std::string &type, const std::string &v, int t) +TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, int type, const std::string &v, int t) :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t) { d->mutex.lock(); @@ -73,5 +73,5 @@ TDSensorEventDispatcher::~TDSensorEventDispatcher() { } void TDSensorEventDispatcher::run() { - d->event(protocol.c_str(), model.c_str(), sensorId, dataType.c_str(), value.c_str(), timestamp, d->id, d->context); + d->event(protocol.c_str(), model.c_str(), sensorId, dataType, value.c_str(), timestamp, d->id, d->context); } diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index b0a6a52f..a355b44f 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -57,7 +57,7 @@ namespace TelldusCore { }; class TDSensorEventDispatcher : public Thread { public: - TDSensorEventDispatcher( CallbackStruct *data, const std::string &protocol, const std::string &model, int id, const std::string &dataType, const std::string &value, int timestamp); + TDSensorEventDispatcher( CallbackStruct *data, const std::string &protocol, const std::string &model, int id, int dataType, const std::string &value, int timestamp); virtual ~TDSensorEventDispatcher(); protected: virtual void run(); @@ -66,7 +66,7 @@ namespace TelldusCore { std::string protocol; std::string model; int sensorId; - std::string dataType; + int dataType; std::string value; int timestamp; }; From 7532d315d83c8b01eda84e28a9a962b3a531f999 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 15:32:11 +0000 Subject: [PATCH 0648/2215] Added new callback TDSensorEvent --- telldus-core/client/Client.cpp | 54 ++++++++- telldus-core/client/Client.h | 4 +- telldus-core/client/telldus-core.cpp | 175 ++++++++++++++------------- telldus-core/client/telldus-core.h | 26 ++-- 4 files changed, 162 insertions(+), 97 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 594ac725..ecb125fc 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -18,9 +18,11 @@ using namespace TelldusCore; typedef CallbackStruct DeviceEvent; typedef CallbackStruct DeviceChangeEvent; typedef CallbackStruct RawDeviceEvent; +typedef CallbackStruct SensorEvent; typedef std::list DeviceEventList; typedef std::list DeviceChangeList; typedef std::list RawDeviceEventList; +typedef std::list SensorEventList; class Client::PrivateData { public: @@ -29,6 +31,7 @@ public: DeviceChangeList deviceChangeEventList; Socket eventSocket; RawDeviceEventList rawDeviceEventList; + SensorEventList sensorEventList; bool running; TelldusCore::Mutex mutex; }; @@ -88,7 +91,7 @@ void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int } } -void Client::callbackRawEvent(std::wstring command, int controllerId){ +void Client::callbackRawEvent(std::wstring command, int controllerId) { std::list > list; { TelldusCore::MutexLocker locker(&d->mutex); @@ -99,6 +102,17 @@ void Client::callbackRawEvent(std::wstring command, int controllerId){ } } +void Client::callbackSensorEvent(const std::wstring &protocol, const std::wstring &model, int id, int dataType, const std::wstring &value, int timestamp) { + std::list > list; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(SensorEventList::iterator callback_it = d->sensorEventList.begin(); callback_it != d->sensorEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDSensorEventDispatcher(*callback_it, TelldusCore::wideToString(protocol), TelldusCore::wideToString(model), id, dataType, TelldusCore::wideToString(value), timestamp)); + list.push_back(ptr); + } + } +} + bool Client::getBoolFromService(const Message &msg) { return getIntegerFromService(msg) == TELLSTICK_SUCCESS; } @@ -146,6 +160,17 @@ int Client::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *contex return id; } +int Client::registerSensorEvent( TDSensorEvent eventFunction, void *context ) { + TelldusCore::MutexLocker locker(&d->mutex); + int id = ++d->lastCallbackId; + SensorEvent *callback = new SensorEvent; + callback->event = eventFunction; + callback->id = id; + callback->context = context; + d->sensorEventList.push_back(callback); + return id; +} + void Client::run(){ //listen here d->eventSocket.connect(L"TelldusEvents"); @@ -182,6 +207,15 @@ void Client::run(){ int controllerId = Message::takeInt(&clientMessage); callbackRawEvent(command, controllerId); } + else if(type == L"TDSensorEvent"){ + std::wstring protocol = Message::takeString(&clientMessage); + std::wstring model = Message::takeString(&clientMessage); + int sensorId = Message::takeInt(&clientMessage); + int dataType = Message::takeInt(&clientMessage); + std::wstring value = Message::takeString(&clientMessage); + int timestamp = Message::takeInt(&clientMessage); + callbackSensorEvent(protocol, model, sensorId, dataType, value, timestamp); + } else{ clientMessage = L""; //cleanup, if message contained garbage/unhandled data } @@ -264,6 +298,24 @@ bool Client::unregisterCallback( int callbackId ) { return true; } + SensorEventList newSEList; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(SensorEventList::iterator callback_it = d->sensorEventList.begin(); callback_it != d->sensorEventList.end(); ++callback_it) { + if ( (*callback_it)->id != callbackId ) { + continue; + } + newSEList.splice(newSEList.begin(), d->sensorEventList, callback_it ); + break; + } + } + if (newSEList.size()) { + SensorEventList::iterator it = newSEList.begin(); + {TelldusCore::MutexLocker locker( &(*it)->mutex );} + newSEList.erase(it); + return true; + } + return false; } diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index ad017212..fc9a6e22 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -13,13 +13,15 @@ namespace TelldusCore { static Client *getInstance(); static void close(); - + void callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue); void callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType); void callbackRawEvent(std::wstring command, int controllerId); + void callbackSensorEvent(const std::wstring &protocol, const std::wstring &model, int id, int dataType, const std::wstring &value, int timestamp); int registerDeviceEvent( TDDeviceEvent eventFunction, void *context ); int registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ); int registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + int registerSensorEvent( TDSensorEvent eventFunction, void *context ); void stopThread(void); bool unregisterCallback( int callbackId ); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 5374b5fa..1898ffbf 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -17,19 +17,19 @@ using namespace TelldusCore; /** * @def TELLSTICK_TURNON * Device-flag for devices supporting the tdTurnOn() call. - * + * * @def TELLSTICK_TURNOFF * Device-flag for devices supporting the tdTurnOff() call. - * + * * @def TELLSTICK_BELL * Device-flag for devices supporting the tdBell() call. - * + * * @def TELLSTICK_TOGGLE * This method is currently unimplemented. - * + * * @def TELLSTICK_DIM * Device-flag for devices supporting the tdDim() call. - * + * * @def TELLSTICK_EXECUTE * Device-flag for devices (scenes) supporting the tdExecute() call. * @@ -44,33 +44,33 @@ using namespace TelldusCore; * * @def TELLSTICK_LEARN * Device-flag for devices supporting the tdLearn() call. - * + * * @def TELLSTICK_TYPE_DEVICE * Device type of a single device. - * + * * @def TELLSTICK_TYPE_GROUP * Device type of a device which contains other devices. - * + * * @def TELLSTICK_TYPE_SCENE * Device type of a device which contains other devices that are sent different commands when executed (i.e. one device turns on, another turns off). - * + * * @def TELLSTICK_SUCCESS * Error code. Returned when the command succeeded. - * + * * @def TELLSTICK_ERROR_NOT_FOUND * Error code. Returned if a TellStick was not found on the system. - * + * * @def TELLSTICK_ERROR_PERMISSION_DENIED * Error code. Returned if the user doesn't have privileges to open * the TellStick device. - * + * * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND * Error code. The supplied device id was not found. - * + * * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED * Error code. The requested method is not supported by the device. * This should be avoided by a call to tdMethods(). - * + * * @def TELLSTICK_ERROR_COMMUNICATION * Error code. An error occurred when communicating with TellStick. * @@ -81,7 +81,7 @@ using namespace TelldusCore; * @def TELLSTICK_ERROR_UNKNOWN_RESPONSE * Error code. The client library received a response from the service * it did not understand. - * + * * @def TELLSTICK_ERROR_UNKNOWN * Error code. An unkown error has occurred. */ @@ -105,6 +105,11 @@ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void return client->registerDeviceChangeEvent( eventFunction, context ); } +int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { + Client *client = Client::getInstance(); + return client->registerSensorEvent( eventFunction, context ); +} + int WINAPI tdUnregisterCallback( int callbackId ) { Client *client = Client::getInstance(); return client->unregisterCallback( callbackId ); @@ -138,8 +143,8 @@ void WINAPI tdReleaseString(char *string) { * @param intDeviceId The device id to turn on. **/ int WINAPI tdTurnOn(int intDeviceId){ - Message msg(L"tdTurnOn"); - msg.addArgument(intDeviceId); + Message msg(L"tdTurnOn"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -150,8 +155,8 @@ int WINAPI tdTurnOn(int intDeviceId){ * @param intDeviceId The device id to turn off. */ int WINAPI tdTurnOff(int intDeviceId){ - Message msg(L"tdTurnOff"); - msg.addArgument(intDeviceId); + Message msg(L"tdTurnOff"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -162,8 +167,8 @@ int WINAPI tdTurnOff(int intDeviceId){ * @param intDeviceId The device id to send bell to */ int WINAPI tdBell(int intDeviceId){ - Message msg(L"tdBell"); - msg.addArgument(intDeviceId); + Message msg(L"tdBell"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -175,9 +180,9 @@ int WINAPI tdBell(int intDeviceId){ * @param level The level the device should dim to. This value should be 0-255 */ int WINAPI tdDim(int intDeviceId, unsigned char level){ - Message msg(L"tdDim"); - msg.addArgument(intDeviceId); - msg.addArgument(level); + Message msg(L"tdDim"); + msg.addArgument(intDeviceId); + msg.addArgument(level); return Client::getIntegerFromService(msg); } @@ -188,8 +193,8 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ * @param intDeviceId The id to execute */ int WINAPI tdExecute(int intDeviceId){ - Message msg(L"tdExecute"); - msg.addArgument(intDeviceId); + Message msg(L"tdExecute"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -200,8 +205,8 @@ int WINAPI tdExecute(int intDeviceId){ * @param intDeviceId The device id to send the command to */ int WINAPI tdUp(int intDeviceId){ - Message msg(L"tdUp"); - msg.addArgument(intDeviceId); + Message msg(L"tdUp"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -212,8 +217,8 @@ int WINAPI tdUp(int intDeviceId){ * @param intDeviceId The device id to send the command to */ int WINAPI tdDown(int intDeviceId){ - Message msg(L"tdDown"); - msg.addArgument(intDeviceId); + Message msg(L"tdDown"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -224,8 +229,8 @@ int WINAPI tdDown(int intDeviceId){ * @param intDeviceId The device id to stop */ int WINAPI tdStop(int intDeviceId){ - Message msg(L"tdStop"); - msg.addArgument(intDeviceId); + Message msg(L"tdStop"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -237,8 +242,8 @@ int WINAPI tdStop(int intDeviceId){ * @param intDeviceId The device id to learn. */ int WINAPI tdLearn(int intDeviceId) { - Message msg(L"tdLearn"); - msg.addArgument(intDeviceId); + Message msg(L"tdLearn"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -249,9 +254,9 @@ int WINAPI tdLearn(int intDeviceId) { * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF */ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { - Message msg(L"tdLastSentCommand"); - msg.addArgument(intDeviceId); - msg.addArgument(methodsSupported); + Message msg(L"tdLastSentCommand"); + msg.addArgument(intDeviceId); + msg.addArgument(methodsSupported); return Client::getIntegerFromService(msg); } @@ -261,8 +266,8 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { * @returns the the value as a human readable string, example "128" for 50% */ char * WINAPI tdLastSentValue( int intDeviceId ) { - Message msg(L"tdLastSentValue"); - msg.addArgument(intDeviceId); + Message msg(L"tdLastSentValue"); + msg.addArgument(intDeviceId); std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -271,7 +276,7 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * This function returns the number of devices configured * @returns an integer of the total number of devices configured */ -int WINAPI tdGetNumberOfDevices(void){ +int WINAPI tdGetNumberOfDevices(void){ return Client::getIntegerFromService(Message(L"tdGetNumberOfDevices")); } @@ -289,8 +294,8 @@ int WINAPI tdGetNumberOfDevices(void){ * @returns the unique id for the device or -1 if the device is not found. */ int WINAPI tdGetDeviceId(int intDeviceIndex){ - Message msg(L"tdGetDeviceId"); - msg.addArgument(intDeviceIndex); + Message msg(L"tdGetDeviceId"); + msg.addArgument(intDeviceIndex); return Client::getIntegerFromService(msg); } @@ -299,8 +304,8 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ * TELLSTICK_TYPE_DEVICE, TELLSTICK_TYPE_GROUP or TELLSTICK_TYPE_SCENE */ int WINAPI tdGetDeviceType(int intDeviceId) { - Message msg(L"tdGetDeviceType"); - msg.addArgument(intDeviceId); + Message msg(L"tdGetDeviceType"); + msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); } @@ -310,23 +315,23 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * @returns The name of the device or an empty string if the device is not found. */ char * WINAPI tdGetName(int intDeviceId){ - Message msg(L"tdGetName"); - msg.addArgument(intDeviceId); + Message msg(L"tdGetName"); + msg.addArgument(intDeviceId); std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } /** - * Sets a new name for a device. The devices are global for all application, changing + * Sets a new name for a device. The devices are global for all application, changing * this will change the name for other applications aswell. * @param intDeviceId The device id to change the name for * @param strNewName The new name for the devices * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ - Message msg(L"tdSetName"); - msg.addArgument(intDeviceId); - msg.addArgument(strNewName); + Message msg(L"tdSetName"); + msg.addArgument(intDeviceId); + msg.addArgument(strNewName); return Client::getBoolFromService(msg); } @@ -335,8 +340,8 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ * @param intDeviceId The device id to query. */ char* WINAPI tdGetProtocol(int intDeviceId){ - Message msg(L"tdGetProtocol"); - msg.addArgument(intDeviceId); + Message msg(L"tdGetProtocol"); + msg.addArgument(intDeviceId); std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -351,9 +356,9 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * @sa tdSetDeviceParameter() */ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ - Message msg(L"tdSetProtocol"); - msg.addArgument(intDeviceId); - msg.addArgument(strProtocol); + Message msg(L"tdSetProtocol"); + msg.addArgument(intDeviceId); + msg.addArgument(strProtocol); return Client::getBoolFromService(msg); } @@ -362,8 +367,8 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ * @param intDeviceId The device to query. */ char* WINAPI tdGetModel(int intDeviceId){ - Message msg(L"tdGetModel"); - msg.addArgument(intDeviceId); + Message msg(L"tdGetModel"); + msg.addArgument(intDeviceId); std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -376,9 +381,9 @@ char* WINAPI tdGetModel(int intDeviceId){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ - Message msg(L"tdSetModel"); - msg.addArgument(intDeviceId); - msg.addArgument(strModel); + Message msg(L"tdSetModel"); + msg.addArgument(intDeviceId); + msg.addArgument(strModel); return Client::getBoolFromService(msg); } @@ -391,10 +396,10 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ - Message msg(L"tdSetDeviceParameter"); - msg.addArgument(intDeviceId); - msg.addArgument(strName); - msg.addArgument(strValue); + Message msg(L"tdSetDeviceParameter"); + msg.addArgument(intDeviceId); + msg.addArgument(strName); + msg.addArgument(strValue); return Client::getBoolFromService(msg); } @@ -405,10 +410,10 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. */ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ - Message msg(L"tdGetDeviceParameter"); - msg.addArgument(intDeviceId); - msg.addArgument(strName); - msg.addArgument(defaultValue); + Message msg(L"tdGetDeviceParameter"); + msg.addArgument(intDeviceId); + msg.addArgument(strName); + msg.addArgument(defaultValue); std::wstring strReturn = Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -416,11 +421,11 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c /** * Add a new device to the global database of devices. This function must be called first before * any call to tdSetName(), tdSetProtocol() and similar functions. - * @returns the new device id for the newly created device. If the creation fails it returnes a + * @returns the new device id for the newly created device. If the creation fails it returnes a * negative value. */ int WINAPI tdAddDevice(){ - Message msg(L"tdAddDevice"); + Message msg(L"tdAddDevice"); return Client::getIntegerFromService(msg); } @@ -429,8 +434,8 @@ int WINAPI tdAddDevice(){ * @returns \c true on success, \c false otherwise. */ bool WINAPI tdRemoveDevice(int intDeviceId){ - Message msg(L"tdRemoveDevice"); - msg.addArgument(intDeviceId); + Message msg(L"tdRemoveDevice"); + msg.addArgument(intDeviceId); return Client::getBoolFromService(msg); } @@ -458,9 +463,9 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_STOP */ int WINAPI tdMethods(int id, int methodsSupported){ - Message msg(L"tdMethods"); - msg.addArgument(id); - msg.addArgument(methodsSupported); + Message msg(L"tdMethods"); + msg.addArgument(id); + msg.addArgument(methodsSupported); return Client::getIntegerFromService(msg); } @@ -506,26 +511,26 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure */ int WINAPI tdSendRawCommand(const char *command, int reserved) { - Message msg(L"tdSendRawCommand"); - msg.addArgument(command); - msg.addArgument(reserved); + Message msg(L"tdSendRawCommand"); + msg.addArgument(command); + msg.addArgument(reserved); return Client::getIntegerFromService(msg); } void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { - Message msg(L"tdConnectTellStickController"); - msg.addArgument(vid); - msg.addArgument(pid); + Message msg(L"tdConnectTellStickController"); + msg.addArgument(vid); + msg.addArgument(pid); msg.addArgument(serial); Client::getWStringFromService(msg); } void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { - Message msg(L"tdDisconnectTellStickController"); - msg.addArgument(vid); - msg.addArgument(pid); - msg.addArgument(serial); + Message msg(L"tdDisconnectTellStickController"); + msg.addArgument(vid); + msg.addArgument(pid); + msg.addArgument(serial); Client::getWStringFromService(msg); } diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 5fc031da..099a7654 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -26,11 +26,12 @@ #endif typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); -typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); +typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); +typedef void (WINAPI *TDSensorEvent)(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context); -#ifndef __cplusplus - #define bool char +#ifndef __cplusplus + #define bool char #endif #ifdef __cplusplus @@ -40,10 +41,11 @@ extern "C" { TELLSTICK_API int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ); TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context ); TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); TELLSTICK_API void WINAPI tdClose(void); TELLSTICK_API void WINAPI tdReleaseString(char *string); - + TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); TELLSTICK_API int WINAPI tdBell(int intDeviceId); @@ -56,26 +58,26 @@ extern "C" { TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); TELLSTICK_API char *WINAPI tdLastSentValue( int intDeviceId ); - + TELLSTICK_API int WINAPI tdGetNumberOfDevices(); TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); - + TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); - + TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); TELLSTICK_API char * WINAPI tdGetModel(int intDeviceId); TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, const char *intModel); - + TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); - + TELLSTICK_API int WINAPI tdAddDevice(); TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); - + TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); @@ -97,6 +99,10 @@ extern "C" { #define TELLSTICK_DOWN 256 #define TELLSTICK_STOP 512 +//Sensor value types +#define TELLSTICK_TEMPERATURE 1 +#define TELLSTICK_HUMIDITY 2 + //Error codes #define TELLSTICK_SUCCESS 0 #define TELLSTICK_ERROR_NOT_FOUND -1 From cc351a8c60080d3e1773bb2575706aca28e0ce7f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 May 2011 10:38:58 +0000 Subject: [PATCH 0649/2215] Corrected selflearning string comparison error --- telldus-core/service/ProtocolNexa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 4ec2ecc9..ab6c4d71 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -163,7 +163,7 @@ std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); - if(dataMsg.getParameter("model") == "selflearning"){ + if(dataMsg.getParameter("model").compare("selflearning")){ //selflearning return decodeDataSelfLearning(allData); } From 11dd17d2cfddaa94e74c9821dcdf5daef7e3bd01 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 May 2011 12:46:05 +0000 Subject: [PATCH 0650/2215] Added function TelldusCore::intToString() --- telldus-core/common/Strings.cpp | 22 ++++++++++++++-------- telldus-core/common/Strings.h | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index ff786ae8..83c1384f 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -45,11 +45,11 @@ std::wstring TelldusCore::charToWstring(const char *value) { char *outString = (char*)new wchar_t[utf8Length+1]; memset(outString, 0, sizeof(wchar_t)*(utf8Length+1)); -#ifdef _FREEBSD +#ifdef _FREEBSD const char *inPointer = inString; -#else - char *inPointer = inString; -#endif +#else + char *inPointer = inString; +#endif char *outPointer = outString; iconv_t convDesc = iconv_open(WCHAR_T_ENCODING, "UTF-8"); @@ -96,6 +96,12 @@ std::wstring TelldusCore::intToWstring(int value) { return st.str(); } +std::string TelldusCore::intToString(int value) { + std::stringstream st; + st << value; + return st.str(); +} + int TelldusCore::wideToInteger(const std::wstring &input){ std::wstringstream inputstream; inputstream << input; @@ -132,11 +138,11 @@ std::string TelldusCore::wideToString(const std::wstring &input) { char *outString = new char[outbytesLeft]; memset(outString, 0, sizeof(char)*(outbytesLeft)); -#ifdef _FREEBSD +#ifdef _FREEBSD const char *inPointer = inString; -#else - char *inPointer = inString; -#endif +#else + char *inPointer = inString; +#endif char *outPointer = outString; iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING); diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index 211c74a2..aca16060 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -7,9 +7,10 @@ namespace TelldusCore { std::wstring charToWstring(const char *value); int charToInteger(const char *value); std::wstring charUnsignedToWstring(const unsigned char value); - + bool comparei(std::wstring stringA, std::wstring stringB); std::wstring intToWstring(int value); + std::string intToString(int value); std::string wideToString(const std::wstring &input); int wideToInteger(const std::wstring &input); From 4da456b5156e9f9fb72895c7ef1be6402777f44d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 May 2011 12:47:15 +0000 Subject: [PATCH 0651/2215] Implemented acctual storing of sensor-values --- telldus-core/service/Sensor.cpp | 32 ++++++++++++++++++++++++++++++-- telldus-core/service/Sensor.h | 6 +++++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/Sensor.cpp b/telldus-core/service/Sensor.cpp index d9781868..649a576a 100644 --- a/telldus-core/service/Sensor.cpp +++ b/telldus-core/service/Sensor.cpp @@ -1,10 +1,13 @@ #include "Sensor.h" #include "common.h" +#include "../client/telldus-core.h" +#include class Sensor::PrivateData { public: std::wstring protocol, model; int id; + std::map values; time_t timestamp; }; @@ -33,7 +36,32 @@ int Sensor::id() const { return d->id; } -void Sensor::setValue(const std::string &name, const std::string &value, time_t timestamp) { - //TODO: Do acctual storing of values +time_t Sensor::timestamp() const { + return d->timestamp; +} + +int Sensor::dataTypes() const { + int retval = 0; + for (std::map::iterator it = d->values.begin(); it != d->values.end(); ++it) { + retval |= (*it).first; + } + return retval; +} + +void Sensor::setValue(int type, const std::string &value, time_t timestamp) { + if (value.substr(0,2).compare("0x") == 0) { + int intval = strtol(value.c_str(), NULL, 16); + d->values[type] = TelldusCore::intToString(intval); + } else { + d->values[type] = value; + } d->timestamp = timestamp; } + +std::string Sensor::value(int type) const { + std::map::const_iterator it = d->values.find(type); + if (it == d->values.end()) { + return ""; + } + return (*it).second; +} diff --git a/telldus-core/service/Sensor.h b/telldus-core/service/Sensor.h index 3b06e052..83fcf57d 100644 --- a/telldus-core/service/Sensor.h +++ b/telldus-core/service/Sensor.h @@ -13,8 +13,12 @@ public: std::wstring protocol() const; std::wstring model() const; int id() const; + time_t timestamp() const; - void setValue(const std::string &name, const std::string &value, time_t timestamp); + int dataTypes() const; + + void setValue(int type, const std::string &value, time_t timestamp); + std::string value(int type) const; private: class PrivateData; From 856e23d7da59406dadd4234a80e6e419eb4f0be8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 May 2011 12:48:45 +0000 Subject: [PATCH 0652/2215] Added functions DeviceManager::getSensors() and DeviceManager::getSensorValue() --- telldus-core/service/DeviceManager.cpp | 52 +++++++++++++++++++++++++- telldus-core/service/DeviceManager.h | 3 ++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index b9d65aee..156bc4ee 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -574,6 +574,56 @@ int DeviceManager::removeDevice(int deviceId){ return TELLSTICK_SUCCESS; } +std::wstring DeviceManager::getSensors() const { + TelldusCore::MutexLocker sensorListLocker(&d->lock); + + TelldusCore::Message msg; + + msg.addArgument(d->sensorList.size()); + + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + TelldusCore::MutexLocker sensorLocker(*it); + msg.addArgument((*it)->protocol()); + msg.addArgument((*it)->model()); + msg.addArgument((*it)->id()); + msg.addArgument((*it)->dataTypes()); + } + + return msg; +} + +std::wstring DeviceManager::getSensorValue(const std::wstring &protocol, const std::wstring &model, int id, int dataType) const { + TelldusCore::MutexLocker sensorListLocker(&d->lock); + Sensor *sensor = 0; + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + TelldusCore::MutexLocker sensorLocker(*it); + if (!TelldusCore::comparei((*it)->protocol(), protocol)) { + continue; + } + if (!TelldusCore::comparei((*it)->model(), model)) { + continue; + } + if ((*it)->id() != id) { + continue; + } + sensor = *it; + break; + } + + if (!sensor) { + return L""; + } + TelldusCore::MutexLocker sensorLocker(sensor); + TelldusCore::Message msg; + std::string value = sensor->value(dataType); + if (value.length() > 0) { + msg.addArgument(TelldusCore::charToWstring(value.c_str())); + msg.addArgument(sensor->timestamp()); + } + return msg; +} + + void DeviceManager::handleControllerMessage(const ControllerEventData &eventData) { //Trigger raw-event EventUpdateData *eventUpdateData = new EventUpdateData(); @@ -653,7 +703,7 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int da if (!msg.hasParameter(dataType)) { return; } - sensor->setValue(dataType, msg.getParameter(dataType), timestamp); + sensor->setValue(dataTypeId, msg.getParameter(dataType), timestamp); EventUpdateData *eventData = new EventUpdateData(); eventData->messageType = L"TDSensorEvent"; diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 57313f0c..814efd18 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -38,6 +38,9 @@ public: int removeDevice(int deviceId); int sendRawCommand(const std::wstring &command, int reserved); + std::wstring getSensors() const; + std::wstring getSensorValue(const std::wstring &protocol, const std::wstring &model, int id, int dataType) const; + void handleControllerMessage(const ControllerEventData &event); private: From ad1b182a7189b813476fb283519221e80d9cff5c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 May 2011 12:49:22 +0000 Subject: [PATCH 0653/2215] Implemeted function tdSensor and tdSensorValue in the service --- telldus-core/service/ClientCommunicationHandler.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 180d1788..7f84da27 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -217,11 +217,23 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int pid = TelldusCore::Message::takeInt(&msg); std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); d->deviceManager->connectTellStickController(vid, pid, serial); + } else if (function == L"tdDisconnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); int pid = TelldusCore::Message::takeInt(&msg); std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); d->deviceManager->disconnectTellStickController(vid, pid, serial); + + } else if (function == L"tdSensor") { + (*wstringReturn) = d->deviceManager->getSensors(); + + } else if (function == L"tdSensorValue") { + std::wstring protocol = TelldusCore::Message::takeString(&msg); + std::wstring model = TelldusCore::Message::takeString(&msg); + int id = TelldusCore::Message::takeInt(&msg); + int dataType = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getSensorValue(protocol, model, id, dataType); + } else{ (*intReturn) = TELLSTICK_ERROR_UNKNOWN; From 8eaaf6f4a6d4320686f4a87ba91649e583fa55c2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 May 2011 12:51:13 +0000 Subject: [PATCH 0654/2215] Added functions tdSensor() and tdSensorValue() to the client library. The function tdSensor() caches the result and only returns one sensor per call --- telldus-core/client/Client.cpp | 41 +++++++++++++++++++++++++++- telldus-core/client/Client.h | 2 ++ telldus-core/client/telldus-core.cpp | 27 ++++++++++++++++++ telldus-core/client/telldus-core.h | 3 ++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index ecb125fc..f7f38391 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -32,7 +32,8 @@ public: Socket eventSocket; RawDeviceEventList rawDeviceEventList; SensorEventList sensorEventList; - bool running; + bool running, sensorCached; + std::wstring sensorCache; TelldusCore::Mutex mutex; }; @@ -44,6 +45,7 @@ Client::Client() d = new PrivateData; d->lastCallbackId = 0; d->running = true; + d->sensorCached = false; start(); } @@ -319,3 +321,40 @@ bool Client::unregisterCallback( int callbackId ) { return false; } +int Client::getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *sensorId, int *dataTypes) { + if (!d->sensorCached) { + Message msg(L"tdSensor"); + std::wstring response = Client::getWStringFromService(msg); + int count = Message::takeInt(&response); + d->sensorCached = true; + d->sensorCache = L""; + if (count > 0) { + d->sensorCache = response; + } + } + + if (d->sensorCache == L"") { + d->sensorCached = false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + std::wstring p = Message::takeString(&d->sensorCache); + std::wstring m = Message::takeString(&d->sensorCache); + int id = Message::takeInt(&d->sensorCache); + int dt = Message::takeInt(&d->sensorCache); + + if (protocol && protocolLen) { + strncpy(protocol, TelldusCore::wideToString(p).c_str(), protocolLen); + } + if (model && modelLen) { + strncpy(model, TelldusCore::wideToString(m).c_str(), modelLen); + } + if (sensorId) { + (*sensorId) = id; + } + if (dataTypes) { + (*dataTypes) = dt; + } + + return TELLSTICK_SUCCESS; +} diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index fc9a6e22..b7261318 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -25,6 +25,8 @@ namespace TelldusCore { void stopThread(void); bool unregisterCallback( int callbackId ); + int getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); + static bool getBoolFromService(const Message &msg); static int getIntegerFromService(const Message &msg); static std::wstring getWStringFromService(const Message &msg); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 1898ffbf..d859701a 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -534,5 +534,32 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial Client::getWStringFromService(msg); } +int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes) { + Client *client = Client::getInstance(); + return client->getSensor(protocol, protocolLen, model, modelLen, id, dataTypes); +} + +int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp) { + Message msg(L"tdSensorValue"); + msg.addArgument(protocol); + msg.addArgument(model); + msg.addArgument(id); + msg.addArgument(dataType); + std::wstring retval = Client::getWStringFromService(msg); + if (retval.length() == 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } + + std::wstring v = Message::takeString(&retval); + int t = Message::takeInt(&retval); + if (value && len) { + strncpy(value, TelldusCore::wideToString(v).c_str(), len); + } + if (timestamp) { + (*timestamp) = t; + } + return TELLSTICK_SUCCESS; +} + /*\@}*/ diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 099a7654..1f25e0f3 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -83,6 +83,9 @@ extern "C" { TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); + TELLSTICK_API int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); + TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); + #ifdef __cplusplus } #endif From 777256a05f0af6471e44a012945665ca9d93baf7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 16 May 2011 08:35:03 +0000 Subject: [PATCH 0655/2215] Handle +W-messages in our ftd2xx engine. --- telldus-core/service/TellStick_ftd2xx.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index bb045bf2..8769cd30 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -134,6 +134,8 @@ void TellStick::processData( const std::string &data ) { d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); + } else if(d->message.substr(0,2).compare("+W") == 0) { + this->decodePublishData(d->message.substr(2)); } d->message.clear(); } else { // Append the character From 5ddcfa46443e35ee3e208f20c2183d358661b8b0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 16 May 2011 08:36:57 +0000 Subject: [PATCH 0656/2215] The binary notation doesn't work in Visual Studio. --- telldus-core/service/ProtocolSartano.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index a5f59d81..6c214cb6 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -47,7 +47,7 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) sscanf(data.c_str(), "%X", &allDataIn); - unsigned long mask = 0b100000000000; + unsigned long mask = (1<<11); for(int i=0;i<12;++i){ allData >>= 1; if((allDataIn & mask) == 0){ @@ -81,7 +81,7 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) std::stringstream retString; retString << "class:command;protocol:sartano;model:codeswitch;code:"; - mask = 0b1000000000; + mask = (1<<9); for(int i=0;i<10;i++){ if((code & mask) != 0){ retString << 1; From c247ec4269afc22f5e1c38c49c96135d45729c89 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 16 May 2011 08:37:30 +0000 Subject: [PATCH 0657/2215] Compiler fixes for Windows. --- telldus-core/service/DeviceManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 156bc4ee..73836c1a 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -10,6 +10,7 @@ #include #include #include +#include typedef std::map DeviceMap; @@ -579,7 +580,7 @@ std::wstring DeviceManager::getSensors() const { TelldusCore::Message msg; - msg.addArgument(d->sensorList.size()); + msg.addArgument((int)d->sensorList.size()); for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { TelldusCore::MutexLocker sensorLocker(*it); @@ -618,7 +619,7 @@ std::wstring DeviceManager::getSensorValue(const std::wstring &protocol, const s std::string value = sensor->value(dataType); if (value.length() > 0) { msg.addArgument(TelldusCore::charToWstring(value.c_str())); - msg.addArgument(sensor->timestamp()); + msg.addArgument((int)sensor->timestamp()); } return msg; } @@ -712,7 +713,7 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int da eventData->sensorId = sensor->id(); eventData->dataType = dataTypeId; eventData->value = TelldusCore::charToWstring(msg.getParameter(dataType).c_str()); - eventData->timestamp = timestamp; + eventData->timestamp = (int)timestamp; d->deviceUpdateEvent->signal(eventData); } From 59325ddc1274ad1eca9ca6536e670675b528c947 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 16 May 2011 08:56:52 +0000 Subject: [PATCH 0658/2215] Export our sensor function in Windows. --- telldus-core/client/libtelldus-core.def | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def index c65ea387..36cbfecb 100644 --- a/telldus-core/client/libtelldus-core.def +++ b/telldus-core/client/libtelldus-core.def @@ -48,4 +48,8 @@ EXPORTS tdUp @34 tdDown @35 tdStop @36 + + tdRegisterSensorEvent @37 + tdSensor @38 + tdSensorValue @39 \ No newline at end of file From c4864af31be9c7a1755866e297bf4cdb5ca21ad2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 16 May 2011 14:18:02 +0000 Subject: [PATCH 0659/2215] Take the value from the sensor object instead of the message. This way we allow it to be converted into a more suitable format. --- telldus-core/service/DeviceManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 73836c1a..d921ed7f 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -712,7 +712,7 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int da eventData->model = sensor->model(); eventData->sensorId = sensor->id(); eventData->dataType = dataTypeId; - eventData->value = TelldusCore::charToWstring(msg.getParameter(dataType).c_str()); + eventData->value = TelldusCore::charToWstring(sensor->value(dataTypeId).c_str()); eventData->timestamp = (int)timestamp; d->deviceUpdateEvent->signal(eventData); } From 65bbbc0351c23977bd516ca182686b946fbfe588 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 May 2011 10:22:01 +0000 Subject: [PATCH 0660/2215] Moved the c++-events into its own subdirectory --- examples/{events => cpp/callbacks}/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) rename examples/{events => cpp/callbacks}/main.cpp (81%) diff --git a/examples/events/main.cpp b/examples/cpp/callbacks/main.cpp similarity index 81% rename from examples/events/main.cpp rename to examples/cpp/callbacks/main.cpp index b3bdd6a8..f3e2d3b1 100644 --- a/examples/events/main.cpp +++ b/examples/cpp/callbacks/main.cpp @@ -23,7 +23,13 @@ Events::~Events() { } void Events::deviceEvent(int deviceId, int method, const char *data) { - printf("Event from device %i\n", deviceId); + if (method == TELLSTICK_TURNON) { + printf("ON event from device %i\n", deviceId); + } else if (method == TELLSTICK_TURNOFF) { + printf("OFF event from device %i\n", deviceId); + } else { + printf("Unknown event from device %i\n", deviceId); + } } void Events::deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *context) { From 692fa852904e17be0fc929aafb765bafb6a2d15c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 May 2011 10:23:52 +0000 Subject: [PATCH 0661/2215] Added Makefile --- examples/cpp/callbacks/Makefile | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 examples/cpp/callbacks/Makefile diff --git a/examples/cpp/callbacks/Makefile b/examples/cpp/callbacks/Makefile new file mode 100644 index 00000000..84b4955a --- /dev/null +++ b/examples/cpp/callbacks/Makefile @@ -0,0 +1,13 @@ +CC=gcc +CFLAGS=-Wall -ltelldus-core + +OBJS = main.o + +all: ${OBJS} + ${CC} -o callbacks ${CFLAGS} ${OBJS} + +main.cpp: + ${CC} ${CFLAGS} -c main.cpp + +clean: + rm -f callbacks main.o From 1b98044f3d1130268103feaa861c8c9819a5f423 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 May 2011 11:12:10 +0000 Subject: [PATCH 0662/2215] Added a sensor example in C using polling --- examples/c/sensors/polling/Makefile | 13 ++++++++++ examples/c/sensors/polling/main.c | 38 +++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 examples/c/sensors/polling/Makefile create mode 100644 examples/c/sensors/polling/main.c diff --git a/examples/c/sensors/polling/Makefile b/examples/c/sensors/polling/Makefile new file mode 100644 index 00000000..20509a12 --- /dev/null +++ b/examples/c/sensors/polling/Makefile @@ -0,0 +1,13 @@ +CC=gcc +CFLAGS=-Wall -ltelldus-core + +OBJS = main.o + +all: ${OBJS} + ${CC} -o sensor ${CFLAGS} ${OBJS} + +main.c: + ${CC} ${CFLAGS} -c main.c + +clean: + rm -f sensor main.o diff --git a/examples/c/sensors/polling/main.c b/examples/c/sensors/polling/main.c new file mode 100644 index 00000000..953ef188 --- /dev/null +++ b/examples/c/sensors/polling/main.c @@ -0,0 +1,38 @@ +#include +#include +#include + +const int DATA_LENGTH = 20; + +int main(void) { + char protocol[DATA_LENGTH], model[DATA_LENGTH]; + int sensorId = 0, dataTypes = 0; + char value[DATA_LENGTH]; + char timeBuf[80]; + time_t timestamp = 0; + + + tdInit(); + + while(tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes) == TELLSTICK_SUCCESS) { + //Print the sensor + printf("%s,\t%s,\t%i\n", protocol, model, sensorId); + + //Retrieve the values the sensor supports + if (dataTypes & TELLSTICK_TEMPERATURE) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, value, DATA_LENGTH, (int *)×tamp); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + printf("Temperature:\t%sº\t(%s)\n", value, timeBuf); + } + if (dataTypes & TELLSTICK_HUMIDITY) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, value, DATA_LENGTH, (int *)×tamp); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + printf("Humidity:\t%s%%\t(%s)\n", value, timeBuf); + } + printf("\n"); + } + + tdClose(); + + return 0; +} From 97e88a175fd64eb5deef6ec8830c81fb11eab045 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 May 2011 11:48:12 +0000 Subject: [PATCH 0663/2215] Added C example of our sensor-api using callbacks --- examples/c/sensors/callback/Makefile | 13 +++++++++ examples/c/sensors/callback/main.c | 43 ++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 examples/c/sensors/callback/Makefile create mode 100644 examples/c/sensors/callback/main.c diff --git a/examples/c/sensors/callback/Makefile b/examples/c/sensors/callback/Makefile new file mode 100644 index 00000000..20509a12 --- /dev/null +++ b/examples/c/sensors/callback/Makefile @@ -0,0 +1,13 @@ +CC=gcc +CFLAGS=-Wall -ltelldus-core + +OBJS = main.o + +all: ${OBJS} + ${CC} -o sensor ${CFLAGS} ${OBJS} + +main.c: + ${CC} ${CFLAGS} -c main.c + +clean: + rm -f sensor main.o diff --git a/examples/c/sensors/callback/main.c b/examples/c/sensors/callback/main.c new file mode 100644 index 00000000..907c8d08 --- /dev/null +++ b/examples/c/sensors/callback/main.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include + +void WINAPI sensorEvent(const char *protocol, const char *model, int sensorId, int dataType, const char *value, int ts, int callbackId, void *context) { + char timeBuf[80]; + time_t timestamp = ts; + + //Print the sensor + printf("%s,\t%s,\t%i\n", protocol, model, sensorId); + + //Retrieve the values the sensor supports + if (dataType == TELLSTICK_TEMPERATURE) { + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + printf("Temperature:\t%sº\t(%s)\n", value, timeBuf); + + } else if (dataType == TELLSTICK_HUMIDITY) { + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + printf("Humidity:\t%s%%\t(%s)\n", value, timeBuf); + } + printf("\n"); +} + +int main(void) { + int callbackId = 0; + + tdInit(); + + //Register for callback + callbackId = tdRegisterSensorEvent( (TDSensorEvent)&sensorEvent, 0 ); + + //Our own simple eventloop + while(1) { + sleep(100); + } + + //Cleanup + tdUnregisterCallback( callbackId ); + tdClose(); + + return 0; +} From a788753e8a8df8805d7357f873a7b0a566176c65 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 19 May 2011 09:52:00 +0000 Subject: [PATCH 0664/2215] Java sensor poll and callback examples --- examples/java/sensors/SensorsJNACallback.java | 94 +++++++++++++++++++ examples/java/sensors/SensorsJNAPoll.java | 60 ++++++++++++ 2 files changed, 154 insertions(+) create mode 100644 examples/java/sensors/SensorsJNACallback.java create mode 100644 examples/java/sensors/SensorsJNAPoll.java diff --git a/examples/java/sensors/SensorsJNACallback.java b/examples/java/sensors/SensorsJNACallback.java new file mode 100644 index 00000000..f0740292 --- /dev/null +++ b/examples/java/sensors/SensorsJNACallback.java @@ -0,0 +1,94 @@ +import java.io.*; +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.ptr.*; +import com.sun.jna.Callback; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.Memory; + +import java.util.Date; + +public class SensorsJNACallback +{ + public interface CLibrary extends Library { + + static int TELLSTICK_TEMPERATURE = 1; + static int TELLSTICK_HUMIDITY = 2; + + void tdInit(); + void tdClose(); + int tdRegisterSensorEvent(SensorCallback function, Pointer context); + int tdUnregisterCallback(int callbackID); + + public interface SensorCallback extends Callback{ + public void callbackfunction(Pointer protocol, Pointer model, int id, int dataType, Pointer value, int timestamp, int callbackId, Pointer context); + } + } + + int callbackID; + CLibrary lib; + CLibrary.SensorCallback callback; + + public SensorsJNACallback(){ + lib = (CLibrary)Native.loadLibrary("libtelldus-core.so.2", CLibrary.class); + } + + public void startListening(){ + + lib.tdInit(); + + //save reference to callback to avoid garbage collection + CLibrary.SensorCallback callback = new CLibrary.SensorCallback(){ + + public void callbackfunction(Pointer protocol, Pointer model, int id, int dataType, Pointer value, int timestamp, int callbackId, Pointer context){ + System.out.println("Sensor: " + protocol.getString(0) + " " + model.getString(0)); + long timestampvalue = (long)timestamp * 1000; + Date date = new Date(timestampvalue); + + if(dataType == CLibrary.TELLSTICK_TEMPERATURE){ + System.out.println("Temperature: " + value.getString(0) + "C, " + date.toString()); + } + else if(dataType == CLibrary.TELLSTICK_HUMIDITY){ + System.out.println("Humidity: " + value.getString(0) + "%, " + date.toString()); + } + System.out.println(""); + } + }; + + //register callback function for sensor events + callbackID = lib.tdRegisterSensorEvent(callback, (Pointer)null); + + while(true){ + try{ + //just wait for sensor callbacks + Thread.currentThread().sleep(1000); + } + catch(InterruptedException e){ + System.exit(0); + } + } + } + + public void stopListening(){ + System.out.println("Exiting"); + lib.tdUnregisterCallback(callbackID); + callback = null; + lib.tdClose(); + } + + public static void main(String[] args) + { + final SensorsJNACallback sensorsjnacallback = new SensorsJNACallback(); + + //add shutdown hook to allow callback unregistration + Runtime.getRuntime().addShutdownHook(new Thread(){ + public void run(){ + sensorsjnacallback.stopListening(); + Runtime.getRuntime().halt(0); + } + }); + + sensorsjnacallback.startListening(); + } +} \ No newline at end of file diff --git a/examples/java/sensors/SensorsJNAPoll.java b/examples/java/sensors/SensorsJNAPoll.java new file mode 100644 index 00000000..51512936 --- /dev/null +++ b/examples/java/sensors/SensorsJNAPoll.java @@ -0,0 +1,60 @@ +import java.io.*; +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.ptr.*; + +import java.util.Date; + +public class SensorsJNAPoll +{ + public interface CLibrary extends Library { + + static int TELLSTICK_TEMPERATURE = 1; + static int TELLSTICK_HUMIDITY = 2; + + void tdInit(); + void tdClose(); + int tdTurnOn(int deviceId); + int tdTurnOff(int deviceId); + int tdSensor(byte[] protocol, int protocolLength, byte[] model, int modelLength, IntByReference id,IntByReference dataTypes); + int tdSensorValue(byte[] protocol, byte[] model, int id, int dataType, byte[] value, int valueLength, IntByReference timestamp); + } + + public static void main(String[] args) + { + CLibrary lib = (CLibrary)Native.loadLibrary("libtelldus-core.so.2", CLibrary.class); + lib.tdInit(); + + IntByReference id = new IntByReference(); + IntByReference dataTypes = new IntByReference(); + + System.out.println("getting sensors"); + System.out.println(""); + + byte protocol[] = new byte[20]; + byte model[] = new byte[20]; + + //check every sensor + while(lib.tdSensor(protocol, 20, model, 20, id, dataTypes) == 0){ + System.out.println("Sensor: " + Native.toString(protocol) + " " + Native.toString(model)); + + byte value[] = new byte[20]; + IntByReference timestamp = new IntByReference(); + if((dataTypes.getValue() & CLibrary.TELLSTICK_TEMPERATURE) != 0){ + lib.tdSensorValue(protocol, model, id.getValue(), 1, value, 20, timestamp); + long timestampvalue = (long)timestamp.getValue() * 1000; + Date date = new Date(timestampvalue); + System.out.println("Temperature: " + Native.toString(value) + "C, " + date.toString()); + } + if((dataTypes.getValue() & CLibrary.TELLSTICK_HUMIDITY) != 0){ + lib.tdSensorValue(protocol, model, id.getValue(), 2, value, 20, timestamp); + long timestampvalue = (long)timestamp.getValue() * 1000; + Date date = new Date(timestampvalue); + System.out.println("Humidity: " + Native.toString(value) + "%, " + date.toString()); + } + System.out.println(""); + } + lib.tdClose(); + } + +} \ No newline at end of file From 37ef7920245feacf17cf150145ea3709171e9fce Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 19 May 2011 12:40:22 +0000 Subject: [PATCH 0665/2215] Fixed memory leak --- telldus-core/client/Client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index f7f38391..acfe68e8 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -260,6 +260,7 @@ bool Client::unregisterCallback( int callbackId ) { { //Lock and unlock to make sure no one else uses the object TelldusCore::MutexLocker locker( &(*it)->mutex ); } + delete (*it); newDEList.erase(it); return true; } @@ -278,6 +279,7 @@ bool Client::unregisterCallback( int callbackId ) { if (newDCList.size()) { DeviceChangeList::iterator it = newDCList.begin(); {TelldusCore::MutexLocker locker( &(*it)->mutex );} + delete (*it); newDCList.erase(it); return true; } @@ -296,6 +298,7 @@ bool Client::unregisterCallback( int callbackId ) { if (newRDEList.size()) { RawDeviceEventList::iterator it = newRDEList.begin(); {TelldusCore::MutexLocker locker( &(*it)->mutex );} + delete (*it); newRDEList.erase(it); return true; } @@ -314,6 +317,7 @@ bool Client::unregisterCallback( int callbackId ) { if (newSEList.size()) { SensorEventList::iterator it = newSEList.begin(); {TelldusCore::MutexLocker locker( &(*it)->mutex );} + delete (*it); newSEList.erase(it); return true; } From 894997d8f0b4bf08eee8060030f8181a7e09f457 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 19 May 2011 12:42:52 +0000 Subject: [PATCH 0666/2215] Changed controller listener interval for Linux to reduce cpu usage --- telldus-core/service/TellStick_libftdi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 1642e273..c5e6c3ae 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -148,7 +148,7 @@ void TellStick::run() { while(1) { //Is there any better way then sleeping between reads? - usleep(1000); + msleep(100); TelldusCore::MutexLocker locker(&d->mutex); if (!d->running) { break; From c1f3579a7243f2af4db40c2dd7e2de0568f3942e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 19 May 2011 13:07:10 +0000 Subject: [PATCH 0667/2215] Python sensor poll and callback examples --- examples/python/sensors/sensorscallback.py | 48 +++++++++++++++++++++ examples/python/sensors/sensorspoll.py | 49 ++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 examples/python/sensors/sensorscallback.py create mode 100644 examples/python/sensors/sensorspoll.py diff --git a/examples/python/sensors/sensorscallback.py b/examples/python/sensors/sensorscallback.py new file mode 100644 index 00000000..7a592b89 --- /dev/null +++ b/examples/python/sensors/sensorscallback.py @@ -0,0 +1,48 @@ + +from ctypes import c_int, c_ubyte, c_void_p, POINTER, string_at, create_string_buffer, c_char_p, c_int, byref #imports allowing the use of our library +import time +import platform +from datetime import datetime + +#platform specific imports: +if (platform.system() == 'Windows'): + #Windows + from ctypes import windll, WINFUNCTYPE + lib = windll.LoadLibrary('TelldusCore.dll') #import our library +else: + #Linux + from ctypes import cdll, CFUNCTYPE + lib = cdll.LoadLibrary('libtelldus-core.so.2') #import our library + +TELLSTICK_TEMPERATURE = 1; +TELLSTICK_HUMIDITY = 2; + +#function to be called when a sensor event occurs +def callbackfunction(protocol, model, id, dataType, value, timestamp, callbackId, context): + + print "Sensor:", string_at(protocol), string_at(model), "id:", id + if(dataType == TELLSTICK_TEMPERATURE): + print "Temperature:", string_at(value), "C,", datetime.fromtimestamp(timestamp) + elif(dataType == TELLSTICK_HUMIDITY): + print "Humidity:", string_at(value), "%,", datetime.fromtimestamp(timestamp) + print "" + + +if (platform.system() == 'Windows'): + CMPFUNC = WINFUNCTYPE(c_void_p, POINTER(c_ubyte), POINTER(c_ubyte), c_int, c_int, POINTER(c_ubyte), c_int, c_int, c_void_p) #first is return type +else: + CMPFUNC = CFUNCTYPE(c_void_p, POINTER(c_ubyte), POINTER(c_ubyte), c_int, c_int, POINTER(c_ubyte), c_int, c_int, c_void_p) + +cmp_func = CMPFUNC(callbackfunction) + +lib.tdInit() +callbackid = lib.tdRegisterSensorEvent(cmp_func, 0) + +print "Waiting for events..." +try: + while(1): + time.sleep(0.5) #don't exit +except KeyboardInterrupt: + print "Exiting" + lib.tdUnregisterCallback(callbackid) + lib.tdClose() diff --git a/examples/python/sensors/sensorspoll.py b/examples/python/sensors/sensorspoll.py new file mode 100644 index 00000000..042bebec --- /dev/null +++ b/examples/python/sensors/sensorspoll.py @@ -0,0 +1,49 @@ + +from ctypes import c_int, c_ubyte, c_void_p, POINTER, string_at, create_string_buffer, c_char_p, c_int, byref #imports allowing the use of our library +from threading import Timer +import time +import platform +from datetime import datetime + +#platform specific imports: +if (platform.system() == 'Windows'): + #Windows + from ctypes import windll, WINFUNCTYPE + lib = windll.LoadLibrary('TelldusCore.dll') #import our library +else: + #Linux + from ctypes import cdll, CFUNCTYPE + lib = cdll.LoadLibrary('libtelldus-core.so.2') #import our library + +TELLSTICK_TEMPERATURE = 1; +TELLSTICK_HUMIDITY = 2; + +def poll(): + print "getting sensors" + + protocollength = 20 + modellength = 20 + valuelength = 20 + + protocol = create_string_buffer(protocollength) + model = create_string_buffer(modellength) + idvalue = c_int() + dataTypes = c_int() + while(lib.tdSensor(protocol, protocollength, model, modellength, byref(idvalue), byref(dataTypes)) == 0): + print "Sensor: ", protocol.value, model.value, "id:", idvalue.value + value = create_string_buffer(valuelength) + timestampvalue = c_int() + + if((dataTypes.value & TELLSTICK_TEMPERATURE) != 0): + success = lib.tdSensorValue(protocol.value, model.value, idvalue.value, TELLSTICK_TEMPERATURE, value, valuelength, byref(timestampvalue)) + print "Temperature: ", value.value, "C,", datetime.fromtimestamp(timestampvalue.value) + + if((dataTypes.value & TELLSTICK_HUMIDITY) != 0): + success = lib.tdSensorValue(protocol.value, model.value, idvalue.value, TELLSTICK_HUMIDITY, value, valuelength, byref(timestampvalue)) + print "Humidity: ", value.value, "%,", datetime.fromtimestamp(timestampvalue.value) + + print " " + +lib.tdInit() +poll() +lib.tdClose() \ No newline at end of file From f096faf367f5467f00e59e5c143b1b97bb952869 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 19 May 2011 14:43:00 +0000 Subject: [PATCH 0668/2215] .NET (C#) sensor poll and callback examples --- examples/dotnet/sensors/SensorPollWin.sln | 26 +++++++ .../dotnet/sensors/SensorPollWin/Program.cs | 64 +++++++++++++++ .../SensorPollWin/Properties/AssemblyInfo.cs | 36 +++++++++ .../SensorPollWin/SensorPollWin.csproj | 77 +++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 examples/dotnet/sensors/SensorPollWin.sln create mode 100644 examples/dotnet/sensors/SensorPollWin/Program.cs create mode 100644 examples/dotnet/sensors/SensorPollWin/Properties/AssemblyInfo.cs create mode 100644 examples/dotnet/sensors/SensorPollWin/SensorPollWin.csproj diff --git a/examples/dotnet/sensors/SensorPollWin.sln b/examples/dotnet/sensors/SensorPollWin.sln new file mode 100644 index 00000000..c10d19d6 --- /dev/null +++ b/examples/dotnet/sensors/SensorPollWin.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SensorPollWin", "SensorPollWin\SensorPollWin.csproj", "{47D37594-BFDD-4A4E-9736-32EDAE2E22F0}" +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 + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Debug|x86.ActiveCfg = Debug|x86 + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Debug|x86.Build.0 = Debug|x86 + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Release|Any CPU.Build.0 = Release|Any CPU + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Release|x86.ActiveCfg = Release|x86 + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/examples/dotnet/sensors/SensorPollWin/Program.cs b/examples/dotnet/sensors/SensorPollWin/Program.cs new file mode 100644 index 00000000..e352b297 --- /dev/null +++ b/examples/dotnet/sensors/SensorPollWin/Program.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Runtime.InteropServices; + +namespace SensorPollWin +{ + unsafe class Program + { + [DllImport("TelldusCore.dll")] + public static extern int tdTurnOn(int deviceId); + + [DllImport("TelldusCore.dll")] + public static extern int tdSensor(char* protocol, int protocolLength, char* model, int modelLength, int* id, int* dataTypes); + + [DllImport("TelldusCore.dll")] + public static extern int tdSensorValue(char* protocol, char* model, int id, int dataType, char* value, int valueLength, int* timestamp); + + static unsafe void Main(string[] args) + { + int protocolstringsize = 20; + int modelstringsize = 20; + int valuestringsize = 20; + char* protocol = (char*)Marshal.AllocHGlobal(Marshal.SystemDefaultCharSize * protocolstringsize); + char* model = (char*)Marshal.AllocHGlobal(Marshal.SystemDefaultCharSize * modelstringsize); + IntPtr id = Marshal.AllocHGlobal(sizeof(int)); + IntPtr dataType = Marshal.AllocHGlobal(sizeof(int)); + Console.WriteLine("getting sensors"); + + while (tdSensor(protocol, protocolstringsize, model, modelstringsize, (int*)id, (int*)dataType) == 0) + { + Console.WriteLine("Sensor: " + System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(protocol))) + " " + System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(model)))); + + char* value = (char*)Marshal.AllocHGlobal(Marshal.SystemDefaultCharSize * valuestringsize); + IntPtr timestamp = Marshal.AllocHGlobal(sizeof(int)); + if ((Marshal.ReadIntPtr(dataType).ToInt32() & 1) != 0) + { + tdSensorValue(protocol, model, Marshal.ReadIntPtr(id).ToInt32(), 1, value, valuestringsize, (int*)timestamp); + Console.WriteLine("Temperature: " + System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(value))) + "C, " + datify(Marshal.ReadIntPtr(timestamp).ToInt32())); + } + if ((Marshal.ReadIntPtr(dataType).ToInt32() & 2) != 0) + { + tdSensorValue(protocol, model, Marshal.ReadIntPtr(id).ToInt32(), 2, value, valuestringsize, (int*)timestamp); + Console.WriteLine("Humidity: " + System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(value))) + "%, " + datify(Marshal.ReadIntPtr(timestamp).ToInt32())); + } + Console.WriteLine(""); + Marshal.FreeHGlobal((IntPtr)value); + Marshal.FreeHGlobal(timestamp); + } + Marshal.FreeHGlobal((IntPtr)protocol); + Marshal.FreeHGlobal((IntPtr)model); + Marshal.FreeHGlobal(id); + Marshal.FreeHGlobal(dataType); + } + + private static string datify(int timestamp){ + System.DateTime dateTime = new System.DateTime(1970, 1, 1, 0, 0, 0, 0); + dateTime = dateTime.AddSeconds(timestamp); + dateTime = dateTime.ToLocalTime(); + return dateTime.ToString(); + } + } +} diff --git a/examples/dotnet/sensors/SensorPollWin/Properties/AssemblyInfo.cs b/examples/dotnet/sensors/SensorPollWin/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..8b921453 --- /dev/null +++ b/examples/dotnet/sensors/SensorPollWin/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +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("SensorPollWin")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("SensorPollWin")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[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("31424c50-2c39-4b7c-a4e8-5a11bd6b8c1d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/examples/dotnet/sensors/SensorPollWin/SensorPollWin.csproj b/examples/dotnet/sensors/SensorPollWin/SensorPollWin.csproj new file mode 100644 index 00000000..7d50d1a7 --- /dev/null +++ b/examples/dotnet/sensors/SensorPollWin/SensorPollWin.csproj @@ -0,0 +1,77 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {47D37594-BFDD-4A4E-9736-32EDAE2E22F0} + Exe + Properties + SensorPollWin + SensorPollWin + v3.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + true + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + + + + + 3.5 + + + 3.5 + + + 3.5 + + + + + + + + + + + \ No newline at end of file From fbee2fd1fec7a56eff77f8b044e87b651d834564 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 19 May 2011 15:21:27 +0000 Subject: [PATCH 0669/2215] Better cleanup in .NET sensor example. --- examples/dotnet/sensors/SensorPollWin/Program.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/examples/dotnet/sensors/SensorPollWin/Program.cs b/examples/dotnet/sensors/SensorPollWin/Program.cs index e352b297..11a692b5 100644 --- a/examples/dotnet/sensors/SensorPollWin/Program.cs +++ b/examples/dotnet/sensors/SensorPollWin/Program.cs @@ -9,14 +9,17 @@ namespace SensorPollWin unsafe class Program { [DllImport("TelldusCore.dll")] - public static extern int tdTurnOn(int deviceId); + public static extern void tdInit(); + + [DllImport("TelldusCore.dll")] + public static extern void tdClose(); [DllImport("TelldusCore.dll")] public static extern int tdSensor(char* protocol, int protocolLength, char* model, int modelLength, int* id, int* dataTypes); [DllImport("TelldusCore.dll")] public static extern int tdSensorValue(char* protocol, char* model, int id, int dataType, char* value, int valueLength, int* timestamp); - + static unsafe void Main(string[] args) { int protocolstringsize = 20; @@ -27,7 +30,8 @@ namespace SensorPollWin IntPtr id = Marshal.AllocHGlobal(sizeof(int)); IntPtr dataType = Marshal.AllocHGlobal(sizeof(int)); Console.WriteLine("getting sensors"); - + + tdInit(); while (tdSensor(protocol, protocolstringsize, model, modelstringsize, (int*)id, (int*)dataType) == 0) { Console.WriteLine("Sensor: " + System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(protocol))) + " " + System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(model)))); @@ -52,6 +56,7 @@ namespace SensorPollWin Marshal.FreeHGlobal((IntPtr)model); Marshal.FreeHGlobal(id); Marshal.FreeHGlobal(dataType); + tdClose(); } private static string datify(int timestamp){ From eae70c9833d3b26823fa21115ba1ddea9f51971a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 19 May 2011 15:31:07 +0000 Subject: [PATCH 0670/2215] Increased model string value in .NET example. --- examples/dotnet/sensors/SensorPollWin/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dotnet/sensors/SensorPollWin/Program.cs b/examples/dotnet/sensors/SensorPollWin/Program.cs index 11a692b5..ad4a5c26 100644 --- a/examples/dotnet/sensors/SensorPollWin/Program.cs +++ b/examples/dotnet/sensors/SensorPollWin/Program.cs @@ -23,7 +23,7 @@ namespace SensorPollWin static unsafe void Main(string[] args) { int protocolstringsize = 20; - int modelstringsize = 20; + int modelstringsize = 30; int valuestringsize = 20; char* protocol = (char*)Marshal.AllocHGlobal(Marshal.SystemDefaultCharSize * protocolstringsize); char* model = (char*)Marshal.AllocHGlobal(Marshal.SystemDefaultCharSize * modelstringsize); From b92e1972178b695b8f081636719ba0612822f26a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 18 Aug 2011 08:22:50 +0000 Subject: [PATCH 0671/2215] Add protocol Hasta --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 8 ++++ telldus-core/service/ProtocolHasta.cpp | 66 ++++++++++++++++++++++++++ telldus-core/service/ProtocolHasta.h | 16 +++++++ 4 files changed, 92 insertions(+) create mode 100644 telldus-core/service/ProtocolHasta.cpp create mode 100644 telldus-core/service/ProtocolHasta.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 61037f88..50d60835 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -36,6 +36,8 @@ SET( telldus-service_protocol_SRCS ProtocolFuhaote.cpp ProtocolGroup.h ProtocolGroup.cpp + ProtocolHasta.h + ProtocolHasta.cpp ProtocolIkea.h ProtocolIkea.cpp ProtocolNexa.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 8bf97ab8..ebcfebb3 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -7,6 +7,7 @@ #include "ProtocolEverflourish.h" #include "ProtocolFuhaote.h" #include "ProtocolGroup.h" +#include "ProtocolHasta.h" #include "ProtocolIkea.h" #include "ProtocolNexa.h" #include "ProtocolRisingSun.h" @@ -103,6 +104,9 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ } else if (TelldusCore::comparei(protocolname, L"fuhaote")) { return new ProtocolFuhaote(); + } else if (TelldusCore::comparei(protocolname, L"hasta")) { + return new ProtocolHasta(); + } else if (TelldusCore::comparei(protocolname, L"ikea")) { return new ProtocolIkea(); @@ -158,6 +162,10 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { parameters.push_back("code"); + } else if (TelldusCore::comparei(protocolName, L"hasta")) { + parameters.push_back("house"); + parameters.push_back("unit"); + } else if (TelldusCore::comparei(protocolName, L"ikea")) { parameters.push_back("system"); parameters.push_back("units"); diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp new file mode 100644 index 00000000..d9b41db1 --- /dev/null +++ b/telldus-core/service/ProtocolHasta.cpp @@ -0,0 +1,66 @@ +#include "ProtocolHasta.h" +#include +#include + +int ProtocolHasta::methods() const { + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; +} + +std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Controller *) { + int house = this->getIntParameter(L"house", 1, 65536); + int unit = this->getIntParameter(L"unit", 1, 15); + std::string strReturn; + + std::string preamble; + strReturn.append(1, 190); + strReturn.append(1, 1); + strReturn.append(1, 190); + strReturn.append(1, 1); + strReturn.append(1, 190); + strReturn.append(1, 190); + + strReturn.append(convertByte( (house&0xFF) )); + strReturn.append(convertByte( (house>>8)&0xFF )); + + int byte = unit&0x0F; + + if (method == TELLSTICK_UP) { + byte |= 0x00; + + } else if (method == TELLSTICK_DOWN) { + byte |= 0x10; + + } else if (method == TELLSTICK_STOP) { + byte |= 0x50; + + } else if (method == TELLSTICK_LEARN) { + byte |= 0x40; + + } else { + return ""; + } + strReturn.append(convertByte(byte)); + + strReturn.append(convertByte(0x0)); + strReturn.append(convertByte(0x0)); + + //Remove the last pulse + strReturn.erase(strReturn.end()-1,strReturn.end()); + + return strReturn; +} + +std::string ProtocolHasta::convertByte(unsigned char byte) { + std::string retval; + for(int i = 0; i < 8; ++i) { + if (byte & 1) { + retval.append(1, 33); + retval.append(1, 17); + } else { + retval.append(1, 17); + retval.append(1, 33); + } + byte >>= 1; + } + return retval; +} \ No newline at end of file diff --git a/telldus-core/service/ProtocolHasta.h b/telldus-core/service/ProtocolHasta.h new file mode 100644 index 00000000..971f0762 --- /dev/null +++ b/telldus-core/service/ProtocolHasta.h @@ -0,0 +1,16 @@ +#ifndef PROTOCOLHASTA_H +#define PROTOCOLHASTA_H + +#include "Protocol.h" + +class ProtocolHasta : public Protocol +{ +public: + int methods() const; + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +protected: + static std::string convertByte(unsigned char byte); +}; + +#endif //PROTOCOLHASTA_H From 981545858d6b1f90c5f601d4e9afa3ce897bdd94 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 31 Aug 2011 13:02:24 +0000 Subject: [PATCH 0672/2215] Bump version --- telldus-core/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 3cb31edb..f6add68f 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -10,8 +10,8 @@ IF(NOT FORCE_COMPILE_FROM_TRUNK) ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) SET(PACKAGE_MAJOR_VERSION 2) -SET(PACKAGE_MINOR_VERSION 0) -SET(PACKAGE_PATCH_VERSION 104) +SET(PACKAGE_MINOR_VERSION 1) +SET(PACKAGE_PATCH_VERSION 0) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") SET(PACKAGE_SUBVERSION) SET(PACKAGE_SOVERSION 2) From 708d09a85f019a956b4aecc0413df5c7c469d861 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 1 Sep 2011 07:22:56 +0000 Subject: [PATCH 0673/2215] Adding some examples for the TelldusNetWrapper. --- .../example/BasicListDevicesNetExample.zip | Bin 0 -> 19647 bytes .../example/BasicTurnOnDeviceNetExample.zip | Bin 0 -> 19013 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 bindings/dotnet/example/BasicListDevicesNetExample.zip create mode 100644 bindings/dotnet/example/BasicTurnOnDeviceNetExample.zip diff --git a/bindings/dotnet/example/BasicListDevicesNetExample.zip b/bindings/dotnet/example/BasicListDevicesNetExample.zip new file mode 100644 index 0000000000000000000000000000000000000000..d2e7b2bf3b58e7468c3c52da4a14a7530b3e3ad5 GIT binary patch literal 19647 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 Date: Thu, 1 Sep 2011 07:28:01 +0000 Subject: [PATCH 0674/2215] Added support for more methods. Added explicit check for /0 in imported strings, and truncate strings there. --- .../TelldusNETWrapper/TelldusNETWrapper.cs | 114 +++++++++++++++--- 1 file changed, 95 insertions(+), 19 deletions(-) diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs index 9f46353a..82164cb8 100644 --- a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs @@ -9,6 +9,8 @@ namespace TelldusWrapper int lastEventID = 0; Dictionary callbackFunctionReferenceList = new Dictionary(); //this prevents errors in "unknown module" due to callback functions being garbage collected since there are no reference to them + //TODO + List lista = new List(); //Device methods public const int TELLSTICK_TURNON = 1; @@ -17,6 +19,10 @@ namespace TelldusWrapper public const int TELLSTICK_TOGGLE = 8; public const int TELLSTICK_DIM = 16; public const int TELLSTICK_LEARN = 32; + public const int TELLSTICK_EXECUTE = 64; + public const int TELLSTICK_UP = 128; + public const int TELLSTICK_DOWN = 256; + public const int TELLSTICK_STOP = 512; //Error codes public const int TELLSTICK_SUCCESS = 0; @@ -32,6 +38,7 @@ namespace TelldusWrapper //Device typedef public const int TELLSTICK_TYPE_DEVICE = 1; public const int TELLSTICK_TYPE_GROUP = 2; + public const int TELLSTICK_TYPE_SCENE = 3; //Device changes public const int TELLSTICK_DEVICE_ADDED = 1; @@ -63,7 +70,6 @@ namespace TelldusWrapper GCHandle rawListenerContextHandle; int registeredRawListenerFunctionId = -1; - public TelldusNETWrapper() { } @@ -157,6 +163,18 @@ namespace TelldusWrapper [DllImport("TelldusCore.dll")] public static extern int tdDim(int deviceId, char level); + [DllImport("TelldusCore.dll")] + public static extern int tdExecute(int deviceId); + + [DllImport("TelldusCore.dll")] + public static extern int tdUp(int deviceId); + + [DllImport("TelldusCore.dll")] + public static extern int tdDown(int deviceId); + + [DllImport("TelldusCore.dll")] + public static extern int tdStop(int deviceId); + [DllImport("TelldusCore.dll")] public static unsafe extern char* tdGetErrorString(int errorNo); @@ -197,13 +215,13 @@ namespace TelldusWrapper public static unsafe extern int tdRegisterDeviceChangeEvent(Delegate deviceEventFunction, void* context); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public unsafe delegate int EventFunctionDelegate(int deviceId, int method, char* data, int callbackId, void* context); + public unsafe delegate void EventFunctionDelegate(); //int deviceId, int method, int callbackId, void* context [MarshalAs(UnmanagedType.LPStr)]string data, [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public unsafe delegate int DeviceChangeEventFunctionDelegate(int deviceId, int changeEvent, int changeType, int callbackId, void* context); + public unsafe delegate void DeviceChangeEventFunctionDelegate(int deviceId, int changeEvent, int changeType, int callbackId, void* context); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public unsafe delegate int RawListeningDelegate(char* data, int controllerId, int callbackId, void* context); + public unsafe delegate void RawListeningDelegate(char* data, int controllerId, int callbackId, void* context); #endregion } @@ -254,6 +272,28 @@ namespace TelldusWrapper return UnmanagedImport.tdDim(deviceId, level); } + /// + /// Send "down" command to device. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// The device id to send the command to + /// Success or error code + public static int tdDown(int deviceId) + { + return UnmanagedImport.tdDown(deviceId); + } + + /// + /// Execute a scene action. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// Id of device to perform the execute action on + /// Success or error code + public static int tdExecute(int deviceId) + { + return UnmanagedImport.tdExecute(deviceId); + } + /// /// This function returns the unique id of a device with a specific index. /// To get all the id numbers you should loop over all the devices, use tdGetNumberOfDevices() to get the number of devices @@ -329,6 +369,10 @@ namespace TelldusWrapper /// TELLSTICK_BELL /// TELLSTICK_TOGGLE /// TELLSTICK_DIM + /// TELLSTICK_EXECUTE + /// TELLSTICK_UP + /// TELLSTICK_DOWN + /// TELLSTICK_EXECUTE /// TELLSTICK_LEARN /// public static int tdMethods(int deviceId, int methodsSupported) @@ -421,6 +465,7 @@ namespace TelldusWrapper { registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(eventFunctionDelegate, (void*)null); //context here or above? } + GC.Collect(); callbackFunctionReferenceList.Add(registeredEventFunctionId, eventFunctionDelegate); } @@ -434,7 +479,7 @@ namespace TelldusWrapper /// /// Register a callback device change event function to be called when a device change event (e.g. change of name, device added) occurs /// - /// Callback function to be called + /// Callback function to be called /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. /// Callback event id public unsafe int tdRegisterDeviceChangeEvent(DeviceChangeEventCallbackFunction deviceEventFunc, Object obj) @@ -455,6 +500,7 @@ namespace TelldusWrapper { registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)null); } + GC.Collect(); callbackFunctionReferenceList.Add(registeredDeviceChangeEventFunctionId, deviceChangeEventFunctionDelegate); } @@ -468,7 +514,7 @@ namespace TelldusWrapper /// /// Register a callback listening function to be called when a listening event (e.g. data is received with Tellstick Duo) occurs /// - /// Callback function to be called + /// Callback function to be called /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. /// Callback event id public unsafe int tdRegisterRawDeviceEvent(RawListeningCallbackFunction listeningFunc, Object obj) @@ -490,6 +536,7 @@ namespace TelldusWrapper { registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)null); } + GC.Collect(); callbackFunctionReferenceList.Add(registeredRawListenerFunctionId, listeningFunctionDelegate); } ++lastEventID; @@ -581,13 +628,24 @@ namespace TelldusWrapper return returnValue; } + /// + /// Send "stop" command to device. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// The device id to stop + /// Success or error code + public static int tdStop(int deviceId) + { + return UnmanagedImport.tdStop(deviceId); + } + /// /// Turns a device on. /// Make sure the device supports this by calling tdMethods() before any calls to this function. /// /// Id of device to turn on /// Success or error code - public static unsafe int tdTurnOn(int deviceId) + public static int tdTurnOn(int deviceId) { return UnmanagedImport.tdTurnOn(deviceId); } @@ -598,7 +656,7 @@ namespace TelldusWrapper /// /// Id of device to turn off /// Success or error code - public static unsafe int tdTurnOff(int deviceId) + public static int tdTurnOff(int deviceId) { return UnmanagedImport.tdTurnOff(deviceId); } @@ -646,6 +704,17 @@ namespace TelldusWrapper } } + /// + /// Send "up" command to device. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// The device id to send the command to + /// Success or error code + public static int tdUp(int deviceId) + { + return UnmanagedImport.tdUp(deviceId); + } + #endregion @@ -670,10 +739,17 @@ namespace TelldusWrapper private static unsafe string getString(char* input, bool release) { string returnString = System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(input))); + + if (returnString.Contains("\0")) + { + returnString = returnString.Substring(0, returnString.IndexOf('\0')); + } + if (release) { UnmanagedImport.tdReleaseString(input); } + GC.Collect(); return returnString; } @@ -704,22 +780,24 @@ namespace TelldusWrapper /// Callback event id /// Context (optional) /// 0 - private unsafe int eventFunction(int deviceId, int method, char* data, int callbackId, void* context) + private unsafe void eventFunction() //int deviceId, int method, int callbackId, void* context[MarshalAs(UnmanagedType.LPStr)]string data { foreach (EventCallbackFunction eventFunc in eventList.Values) { + /* if (context != null) { GCHandle eventContextHandle = GCHandle.FromIntPtr((IntPtr)context); - eventFunc(deviceId, method, getString(data, false), callbackId, (Object)eventContextHandle.Target); + eventFunc(deviceId, method, "", callbackId, (Object)eventContextHandle.Target); //data } else { - eventFunc(deviceId, method, getString(data, false), callbackId, null); + eventFunc(deviceId, method, "", callbackId, null); } + */ + eventFunc(1, 1, "", 1, null); + GC.Collect(); } - - return 0; } /// @@ -733,7 +811,7 @@ namespace TelldusWrapper /// Callback event id /// Context (optional) /// 0 - private unsafe int deviceEventFunction(int deviceId, int changeEvent, int changeType, int callbackId, void* context) + private unsafe void deviceEventFunction(int deviceId, int changeEvent, int changeType, int callbackId, void* context) { foreach (DeviceChangeEventCallbackFunction deviceEventFunc in deviceChangeEventList.Values) { @@ -746,9 +824,8 @@ namespace TelldusWrapper { deviceEventFunc(deviceId, changeEvent, changeType, callbackId, null); } + GC.Collect(); } - - return 0; } /// @@ -761,7 +838,7 @@ namespace TelldusWrapper /// Callback event id /// Context (optional) /// 0 - private unsafe int rawListeningFunction(char* data, int controllerId, int callbackId, void* context) + private unsafe void rawListeningFunction(char* data, int controllerId, int callbackId, void* context) { foreach (RawListeningCallbackFunction rawListeningFunc in rawListenerList.Values) { @@ -774,9 +851,8 @@ namespace TelldusWrapper { rawListeningFunc(getString(data, false), controllerId, callbackId, null); } + GC.Collect(); } - - return 0; } #endregion From 09db7743838bb869785e6ed70eff6aac0e43ddc1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 1 Sep 2011 07:31:06 +0000 Subject: [PATCH 0675/2215] Corrected information in Assembly File --- .../TelldusNETWrapper/Properties/AssemblyInfo.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs index f7acaacc..19d83da2 100644 --- a/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs +++ b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs @@ -5,19 +5,19 @@ 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("ClassLibrary1")] +[assembly: AssemblyTitle("TelldusNETWrapper")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("ClassLibrary1")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[assembly: AssemblyCompany("Telldus Technologies AB")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("Copyright © Telldus Technologies AB 2010")] [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)] +[assembly: ComVisible(true)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("a66028f7-b342-4dc0-9504-9e07c462ec15")] From be46145b16d81f169f66c94081d85dba58b7c18e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 1 Sep 2011 07:45:48 +0000 Subject: [PATCH 0676/2215] Root name changed to TelldusNETWrapper --- bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj index 255d47bb..6ed93111 100644 --- a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj @@ -1,4 +1,4 @@ - + Debug @@ -8,7 +8,7 @@ {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43} Library Properties - ClassLibrary1 + TelldusNETWrapper TelldusNETWrapper v2.0 512 From 1646ebd71b158cc887ac30556d1f435963313783 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 5 Sep 2011 09:01:30 +0000 Subject: [PATCH 0677/2215] Always iterate all devices when we get at controller message. Even if it matches it can match more then one device. --- telldus-core/service/DeviceManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index d921ed7f..7a17eb12 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -666,7 +666,6 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData d->set.setDeviceState(it->first, msg.method(), L""); it->second->setLastSentCommand(msg.method(), L""); } - break; } } From 5758ae088c8ed1a6dada951bf1f3cc355e6c3141 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 5 Sep 2011 09:48:52 +0000 Subject: [PATCH 0678/2215] Updated copyright info --- bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs index 19d83da2..2238f2f5 100644 --- a/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs +++ b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Telldus Technologies AB")] [assembly: AssemblyProduct("")] -[assembly: AssemblyCopyright("Copyright © Telldus Technologies AB 2010")] +[assembly: AssemblyCopyright("Copyright © Telldus Technologies AB 2011")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] From ee627eb6dad340ee190cdef5a26de818d255cbba Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 5 Sep 2011 15:37:46 +0000 Subject: [PATCH 0679/2215] Fixed problem with distinguishing between selflearning/codeswitch in arctech receiving. --- telldus-core/service/ProtocolNexa.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index ab6c4d71..2b29ced5 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -3,6 +3,7 @@ #include #include "TellStick.h" #include "Strings.h" +#include "common.h" int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; //TODO, always removing first turnon now, make more flexible (waveman too) @@ -163,7 +164,7 @@ std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); - if(dataMsg.getParameter("model").compare("selflearning")){ + if(TelldusCore::comparei(dataMsg.model(), L"selflearning")){ //selflearning return decodeDataSelfLearning(allData); } From fc033f1463e3a8c4351910312514507eb8038e8a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 5 Sep 2011 16:02:07 +0000 Subject: [PATCH 0680/2215] Add dependency to TelldusCommon for correct build order on all platforms. --- telldus-core/client/CMakeLists.txt | 2 ++ telldus-core/common/CMakeLists.txt | 11 +++-------- telldus-core/service/CMakeLists.txt | 1 + 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index a060dcf3..303d48fd 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -85,6 +85,8 @@ ADD_LIBRARY(${telldus-core_TARGET} SHARED ${telldus-core_PUB_HDRS} ) +ADD_DEPENDENCIES(${telldus-core_TARGET} TelldusCommon) + IF (UNIX) SET_TARGET_PROPERTIES( ${telldus-core_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") ENDIF (UNIX) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 9a4eb15a..93f5a8ee 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -26,7 +26,6 @@ SET( telldus-common_HDRS IF (APPLE) #### Mac OS X #### - SET( telldus-common_TARGET TelldusCommon ) FIND_LIBRARY(ICONV_LIBRARY iconv) ADD_DEFINITIONS( -D_MACOSX ) LIST(APPEND telldus-common_SRCS @@ -39,14 +38,12 @@ ELSEIF (WIN32) #### Windows #### ADD_DEFINITIONS( -DUNICODE ) ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No - SET( telldus-common_TARGET TelldusCommon ) ADD_DEFINITIONS( -D_WINDOWS ) LIST(APPEND telldus-common_SRCS Socket_win.cpp ) ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") #### FreeBSD #### - SET( telldus-common_TARGET telldus-common ) FIND_LIBRARY(ICONV_LIBRARY iconv) ADD_DEFINITIONS( -D_FREEBSD ) LIST(APPEND telldus-common_SRCS @@ -57,7 +54,6 @@ ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") ) ELSE (APPLE) #### Linux #### - SET( telldus-common_TARGET telldus-common ) ADD_DEFINITIONS( -D_LINUX ) LIST(APPEND telldus-common_SRCS Socket_unix.cpp @@ -67,14 +63,13 @@ ENDIF (APPLE) ######## Configuring ######## - -ADD_LIBRARY(${telldus-common_TARGET} STATIC +ADD_LIBRARY(TelldusCommon STATIC ${telldus-common_SRCS} ${telldus-common_HDRS} ) IF (UNIX) - SET_TARGET_PROPERTIES( ${telldus-common_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") + SET_TARGET_PROPERTIES( TelldusCommon PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") ENDIF (UNIX) -TARGET_LINK_LIBRARIES( ${telldus-common_TARGET} ${telldus-common_LIBRARIES} ) +TARGET_LINK_LIBRARIES( TelldusCommon ${telldus-common_LIBRARIES} ) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 50d60835..c430a65d 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -173,6 +173,7 @@ ADD_EXECUTABLE(${telldus-service_TARGET} ${telldus-service_protocol_SRCS} ${telldus-service_HDRS} ) +ADD_DEPENDENCIES(${telldus-service_TARGET} TelldusCommon) SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) TARGET_LINK_LIBRARIES( ${telldus-service_TARGET} ${telldus-service_LIBRARIES} ) From e77687f7b1ce99cfcc82003de5554fd716cd7c69 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 5 Sep 2011 16:17:02 +0000 Subject: [PATCH 0681/2215] Link agains correct telldus-common. Windows build still broken though --- telldus-core/client/CMakeLists.txt | 2 +- telldus-core/service/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 303d48fd..45909ddd 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -67,7 +67,7 @@ ELSE (APPLE) #### Linux #### SET( telldus-core_TARGET telldus-core ) LIST(APPEND telldus-core_LIBRARIES - telldus-common + TelldusCommon ) ADD_DEFINITIONS( diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index c430a65d..6f7feee4 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -147,7 +147,7 @@ ELSE (APPLE) #### Linux #### ) LIST(APPEND telldus-service_LIBRARIES ${CONFUSE_LIBRARY} - telldus-common + TelldusCommon ) ENDIF (APPLE) From 98753b6a678d76083d84bcc8fefcad0d76002514 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 5 Sep 2011 16:38:21 +0000 Subject: [PATCH 0682/2215] Don't hard code path to TelldusCommon. Let CMake resolve it instead. --- telldus-core/client/CMakeLists.txt | 2 +- telldus-core/service/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 45909ddd..a4ad7778 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -45,7 +45,7 @@ ELSEIF (WIN32) ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No SET( telldus-core_TARGET TelldusCore ) LIST(APPEND telldus-core_LIBRARIES - ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib + TelldusCommon ) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 6f7feee4..dc0bcf4d 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -118,7 +118,7 @@ ELSEIF (WIN32) #### Windows #### "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" ) LIST(APPEND telldus-service_LIBRARIES - ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCommon.lib + TelldusCommon ) LIST(APPEND telldus-service_SRCS ConnectionListener_win.cpp From 4735b596ff88cba9b447fb235949369c2611696f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 15 Dec 2008 19:33:52 +0000 Subject: [PATCH 0683/2215] Initial import of telldus-gui --- telldus-gui/TelldusGui/TelldusGui.pro | 24 ++++++ telldus-gui/TelldusGui/TelldusGui_global.h | 18 ++++ telldus-gui/TelldusGui/device.cpp | 33 ++++++++ telldus-gui/TelldusGui/device.h | 32 +++++++ telldus-gui/TelldusGui/devicemodel.cpp | 78 ++++++++++++++++++ telldus-gui/TelldusGui/devicemodel.h | 34 ++++++++ telldus-gui/TelldusGui/devicewidget.cpp | 67 +++++++++++++++ telldus-gui/TelldusGui/devicewidget.h | 30 +++++++ telldus-gui/TelldusGui/images/list-add.png | Bin 0 -> 601 bytes telldus-gui/TelldusGui/images/list-remove.png | Bin 0 -> 317 bytes telldus-gui/TelldusGui/telldusgui.cpp | 7 ++ 11 files changed, 323 insertions(+) create mode 100644 telldus-gui/TelldusGui/TelldusGui.pro create mode 100644 telldus-gui/TelldusGui/TelldusGui_global.h create mode 100644 telldus-gui/TelldusGui/device.cpp create mode 100644 telldus-gui/TelldusGui/device.h create mode 100644 telldus-gui/TelldusGui/devicemodel.cpp create mode 100644 telldus-gui/TelldusGui/devicemodel.h create mode 100644 telldus-gui/TelldusGui/devicewidget.cpp create mode 100644 telldus-gui/TelldusGui/devicewidget.h create mode 100644 telldus-gui/TelldusGui/images/list-add.png create mode 100644 telldus-gui/TelldusGui/images/list-remove.png create mode 100644 telldus-gui/TelldusGui/telldusgui.cpp diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro new file mode 100644 index 00000000..29a67846 --- /dev/null +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -0,0 +1,24 @@ +# ------------------------------------------------- +# Project created by QtCreator 2008-12-11T15:48:29 +# ------------------------------------------------- +TARGET = TelldusGui +TEMPLATE = lib +DEFINES += TELLDUSGUI_LIBRARY +SOURCES += telldusgui.cpp \ + devicewidget.cpp \ + devicemodel.cpp \ + devicesetting/devicesetting.cpp \ + device.cpp +HEADERS += telldusgui.h \ + TelldusGui_global.h \ + devicewidget.h \ + devicemodel.h \ + devicesetting/devicesetting.h \ + device.h +FORMS += +macx { + LIBS += -framework \ + telldus-core + ICON = images/telldussetup.icns +} +RESOURCES += resource.qrc diff --git a/telldus-gui/TelldusGui/TelldusGui_global.h b/telldus-gui/TelldusGui/TelldusGui_global.h new file mode 100644 index 00000000..f4b9d63c --- /dev/null +++ b/telldus-gui/TelldusGui/TelldusGui_global.h @@ -0,0 +1,18 @@ +#ifndef TELLDUSGUI_GLOBAL_H +#define TELLDUSGUI_GLOBAL_H + +#include + +#if defined(TELLDUSGUI_LIBRARY) +# define TELLDUSGUISHARED_EXPORT Q_DECL_EXPORT +#else +# define TELLDUSGUISHARED_EXPORT Q_DECL_IMPORT +#endif + +class QWidget; + +extern "C" { + QWidget *tdDeviceWidget( QWidget *parent = 0 ); +} + +#endif // TELLDUSGUI_GLOBAL_H diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp new file mode 100644 index 00000000..23f42bf9 --- /dev/null +++ b/telldus-gui/TelldusGui/device.cpp @@ -0,0 +1,33 @@ +#include "device.h" +#include "telldus-core.h" + +QHash Device::devices; + +Device::Device(int id) + :p_id(id) +{ +} + +Device::~Device() { +} + +Device *Device::getDevice( int id ) { + + if (devices.contains(id)) { + return devices[id]; + } + Device *device = new Device(id); + devices[id] = device; + return device; +} + +Device *Device::newDevice( ) { + return new Device(0); +} + +void Device::save() { + if (p_id == 0) { //This is a new device + p_id = tdAddDevice(); + emit deviceAdded(p_id); + } +} diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h new file mode 100644 index 00000000..f0b06c75 --- /dev/null +++ b/telldus-gui/TelldusGui/device.h @@ -0,0 +1,32 @@ +#ifndef DEVICE_H +#define DEVICE_H + +#include +#include + +class Device : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(Device) + +public: + virtual ~Device(); + + static Device *getDevice( int id ); + static Device *newDevice( ); + +public slots: + void save(); + +signals: + void deviceAdded( int id ); + +private: + Device(int id); + + static QHash devices; + QHash p_settings; + int p_id; +}; + +#endif // DEVICE_H diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp new file mode 100644 index 00000000..8dc9ff7f --- /dev/null +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -0,0 +1,78 @@ +#include "devicemodel.h" +#include +#include +#include + +DeviceModel::DeviceModel(QObject *parent) + :QAbstractTableModel(parent) +{ +} + + +DeviceModel::~DeviceModel() +{ +} + +int DeviceModel::rowCount(const QModelIndex &) const { + return tdGetNumberOfDevices(); +} + +int DeviceModel::columnCount(const QModelIndex &) const { + return 1; +} + +QVariant DeviceModel::data(const QModelIndex &index, int role) const { + if (index.column() != 0) { + return QVariant(); + } + + if (role == Qt::DisplayRole) { + int id = deviceId( index ); + char *name = tdGetName( id ); + QString deviceName = QString( name ); + delete name; + return deviceName; + } + + return QVariant(); +} + +bool DeviceModel::removeRows ( int row, int count, const QModelIndex & parent ) { + beginRemoveRows( parent, row, row + count - 1 ); + + QQueue idList; + for ( int i = row; i < row + count; ++i ) { + idList.enqueue( deviceId(i) ); + } + + while(!idList.isEmpty()) { + tdRemoveDevice( idList.dequeue() ); + } + indexToId.clear(); //Clear the index-to-id cache + + endRemoveRows(); + return true; +} + +const Device &DeviceModel::newDevice() const { + Device *device = Device::newDevice(); + connect(device, SIGNAL(deviceAdded(int)), this, SLOT(deviceAdded(int))); + return *device; +} + +void DeviceModel::deviceAdded( int id ) { + qDebug("Yes"); +} + +int DeviceModel::deviceId( const QModelIndex &index ) const { + return deviceId( index.row() ); +} + +int DeviceModel::deviceId( int index ) const { + if (indexToId.contains(index)) { + return indexToId[index]; + } + int id = tdGetDeviceId( index ); + indexToId[index] = id; + return id; +} diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h new file mode 100644 index 00000000..3bed6512 --- /dev/null +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -0,0 +1,34 @@ +#ifndef DEVICEMODEL_H +#define DEVICEMODEL_H + +#include +#include +#include "device.h" + +class DeviceModel : public QAbstractTableModel +{ + Q_OBJECT +public: + DeviceModel(QObject *parent = 0); + virtual ~DeviceModel(); + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + virtual bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() ); + + const Device &newDevice() const; + +private slots: + void deviceAdded( int id ); + +private: + int deviceId( const QModelIndex &index ) const; + int deviceId( int index ) const; + + mutable QHash indexToId; +}; + +#endif // DEVICEMODEL_H diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp new file mode 100644 index 00000000..52fb4cd6 --- /dev/null +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -0,0 +1,67 @@ +#include "devicewidget.h" + +#include +#include +#include +#include +#include + +DeviceWidget::DeviceWidget(QWidget *parent) : + QWidget(parent), + deviceView(this), + addToolButton(this), + removeToolButton(this) +{ + deviceView.setModel( &model ); + connect( &deviceView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(listActivated(const QModelIndex &)) ); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(&deviceView); + + QHBoxLayout *buttonLayout = new QHBoxLayout( this ); + buttonLayout->setSpacing(0); + + addToolButton.setIcon( QIcon( ":/images/list-add.png" ) ); + buttonLayout->addWidget( &addToolButton ); + + removeToolButton.setIcon( QIcon( ":/images/list-remove.png" ) ); + removeToolButton.setEnabled( false ); + connect(&removeToolButton, SIGNAL(clicked()), this, SLOT(deleteDevice())); + buttonLayout->addWidget( &removeToolButton ); + + buttonLayout->addStretch(); + + layout->addLayout( buttonLayout ); +} + +DeviceWidget::~DeviceWidget() +{ +} + +void DeviceWidget::changeEvent(QEvent *e) +{ + switch(e->type()) { + case QEvent::LanguageChange: + //m_ui->retranslateUi(this); + break; + default: + break; + } +} + +void DeviceWidget::deleteDevice() { + QMessageBox msgBox; + msgBox.setText( tr("Are you sure you want to remove the selected device?") ); + msgBox.setInformativeText( tr("The device will be removed premanently from this application as well as all other applications.") ); + msgBox.setIcon( QMessageBox::Warning ); + msgBox.setStandardButtons( QMessageBox::Yes | QMessageBox::No ); + msgBox.setDefaultButton( QMessageBox::No ); + if ( msgBox.exec() == QMessageBox::Yes) { + QModelIndex index = deviceView.currentIndex(); + model.removeRow(index.row()); + } +} + +void DeviceWidget::listActivated(const QModelIndex &) { + removeToolButton.setEnabled( true ); +} diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h new file mode 100644 index 00000000..fe103a7d --- /dev/null +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -0,0 +1,30 @@ +#ifndef DEVICEWIDGET_H +#define DEVICEWIDGET_H + +#include +#include +#include +#include "devicemodel.h" + + +class DeviceWidget : public QWidget { + Q_OBJECT + Q_DISABLE_COPY(DeviceWidget) +public: + explicit DeviceWidget(QWidget *parent = 0); + virtual ~DeviceWidget(); + +protected: + virtual void changeEvent(QEvent *e); + +private slots: + void listActivated(const QModelIndex &); + void deleteDevice(); + +private: + DeviceModel model; + QListView deviceView; + QToolButton addToolButton, removeToolButton; +}; + +#endif // DEVICEWIDGET_H diff --git a/telldus-gui/TelldusGui/images/list-add.png b/telldus-gui/TelldusGui/images/list-add.png new file mode 100644 index 0000000000000000000000000000000000000000..2acdd8f514c199a37b7b14f53081467f88ef7bff GIT binary patch literal 601 zcmV-f0;c_mP)i&hw@usRe0Hlp%^VXF!>2}-I+fVC+BCh2Xu(H}= zWwkR-i17&Q1@?r1slIQmGmt?bz+``iz=_N4nTEMJnWp6PdlDi4$xDysihSSRJ^#HD zfm0WkcL*Ezw|WjD;wX`Y@`OQ$i> zk~|wHA%P^W-+NY=qm+O%@!?CCIP&DpgbAGaz)s%w=F2r6?z` z-r3~+=g{XtaVheZEby-7%X^w2a;hK35HfD6NN^I8P7V;(0mQ@Z@*Wtm@8FfUzLwkFPvfh|u~3@f)V nN>6CzLo>o}j6Z`3{#X10^GpxssPJ~100000NkvXXu0mjfzW5Zm literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/list-remove.png b/telldus-gui/TelldusGui/images/list-remove.png new file mode 100644 index 0000000000000000000000000000000000000000..c5524f7284e4ecb40cbee1e3d3a449bd58a0e4a8 GIT binary patch literal 317 zcmV-D0mA-?P)oXoi$Ept^qyG_6h*pUY)JY1xUgL61ap*$YU>o#o9`0ukRmwYg7fy z#q{lyri8qE6g3Y4Q)K4C3`{ULEziwO932j7CF%n2voBs=XUn#u^MV%pm5i9iZx-vp zUj3U@1pr3JL$sKN`)b!NVJ6&T Date: Mon, 15 Dec 2008 19:36:21 +0000 Subject: [PATCH 0684/2215] Initial import of TelldusCenter --- telldus-gui/TelldusCenter/TelldusCenter.pro | 11 ++++ telldus-gui/TelldusCenter/images/devices.png | Bin 0 -> 1483 bytes telldus-gui/TelldusCenter/main.cpp | 12 ++++ telldus-gui/TelldusCenter/mainwindow.cpp | 58 +++++++++++++++++++ telldus-gui/TelldusCenter/mainwindow.h | 24 ++++++++ telldus-gui/TelldusCenter/resource.qrc | 5 ++ 6 files changed, 110 insertions(+) create mode 100644 telldus-gui/TelldusCenter/TelldusCenter.pro create mode 100644 telldus-gui/TelldusCenter/images/devices.png create mode 100644 telldus-gui/TelldusCenter/main.cpp create mode 100644 telldus-gui/TelldusCenter/mainwindow.cpp create mode 100644 telldus-gui/TelldusCenter/mainwindow.h create mode 100644 telldus-gui/TelldusCenter/resource.qrc diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro new file mode 100644 index 00000000..c0eccfef --- /dev/null +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -0,0 +1,11 @@ +# ------------------------------------------------- +# Project created by QtCreator 2008-12-11T11:01:36 +# ------------------------------------------------- +TARGET = TelldusCenter +TEMPLATE = app +SOURCES += main.cpp \ + mainwindow.cpp +HEADERS += mainwindow.h +FORMS += +RESOURCES += resource.qrc +LIBS += -lTelldusGui -L../TelldusGui diff --git a/telldus-gui/TelldusCenter/images/devices.png b/telldus-gui/TelldusCenter/images/devices.png new file mode 100644 index 0000000000000000000000000000000000000000..438efaf1dca97a3787f032daa09b797eea1c09f3 GIT binary patch literal 1483 zcmV;+1vL7JP)We7q zgU|;lC7z9#1PZePHfAVnIx0p%=OHi z%bYoL_I2&G*XP6DV<*!YgBw2fX2but{@?elZ!IMv?0l3`0N(gGwQru_qjw(S6Rxno z(`5SE4DWt*oMpi5rbR?<3Ba44<{^`Oc}239wAFvjB%89L-?272t!?*5XT_}qq=84fv*r#<@d*3n)N9a*zzffYl&nO?o@+KAdkQVU^Y?1_v{<4@i5?ffbZG6Mj-_Olmn`Si2}0HVGg!*XyXEyhlSf@ z4$pG;=kH^mbNYG4l-w;yTC9#L+^HHUw^#&QrmP_^Q{HkI*CAd-gzSe8bKE&n-LdG=RK(OYnk4DvphRj`|7L?B7ogt8HN z1SW)d9-6O0&;bofFYSf^@A2ts&8%ffyS_`~yfG z!2D}QUXc3v1hWCA16dnPtNdPvtOuqKSpX)2G=?OBB!!}^!5g#u7%*NrDOdWx{pY#C zk>d}l58UBErPzY#U?ZTzrfOHe$K12b8VX<{%;&anHQ}nqQ2}+mOy7x{0ZurR9BOD&~u?lQn%&dt( z_aW{JkpNNRv&hXgr zyndY^3B$?S(%(PJkw=PVG%v%_Sx8;b4w!vpy=eAN*9dp&ot-~`yxF#Ykokp#%{pWj z`s)x{h%yLM*y!dPz4W!>D7p<$MC8v?ycWl!CSC34X;ib#<$Y#$am36lkC>~?5i=Xy znZ3ET&r@eFJZVTK7_NvwD lUA0>6V7J?y0rdaU{0Bermul{N&(r__002ovPDHLkV1oL5&JzFt literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusCenter/main.cpp b/telldus-gui/TelldusCenter/main.cpp new file mode 100644 index 00000000..c5515038 --- /dev/null +++ b/telldus-gui/TelldusCenter/main.cpp @@ -0,0 +1,12 @@ +#include +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE( resource ); + + QApplication a(argc, argv); + MainWindow *w = new MainWindow(); + w->show(); + return a.exec(); +} diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp new file mode 100644 index 00000000..b9e6a995 --- /dev/null +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -0,0 +1,58 @@ +#include "mainwindow.h" + +#include +#include +#include +#include +#include + + +#include "../TelldusGui/TelldusGui_global.h" + +MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) + : QMainWindow(parent, flags) + , m_pagesBar(0) +{ + setAttribute(Qt::WA_DeleteOnClose, true); + statusBar()->setSizeGripEnabled(true); + setupMenu(); + setupToolBar(); + + //QStackedWidget *centralWidget = new QStackedWidget(this); + QWidget *centralWidget = tdDeviceWidget(this); + setCentralWidget(centralWidget); + + setWindowTitle( tr("Telldus Center") ); +} + +MainWindow::~MainWindow() +{ + +} + +void MainWindow::setupMenu() +{ + menuBar()->clear(); + + // File + QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + // Help + QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); + helpMenu->addSeparator(); + helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt())); + helpMenu->addAction(tr("About &TelldusCenter"), this, SLOT(slotAboutApplication())); +} + +void MainWindow::setupToolBar() +{ + setUnifiedTitleAndToolBarOnMac(true); + m_pagesBar = addToolBar(tr("Pages")); + + QActionGroup *ag = new QActionGroup(this); + + QAction *actionDevices = new QAction( QIcon(":/images/devices.png"), tr("Devices"), this ); + actionDevices->setCheckable( true ); + actionDevices->setChecked( true ); + ag->addAction(actionDevices); + m_pagesBar->addActions( ag->actions() ); +} diff --git a/telldus-gui/TelldusCenter/mainwindow.h b/telldus-gui/TelldusCenter/mainwindow.h new file mode 100644 index 00000000..544422c9 --- /dev/null +++ b/telldus-gui/TelldusCenter/mainwindow.h @@ -0,0 +1,24 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +class QToolBar; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0); + ~MainWindow(); + +private: + void setupMenu(); + void setupToolBar(); + +private: + QToolBar *m_pagesBar; +}; + +#endif // MAINWINDOW_H diff --git a/telldus-gui/TelldusCenter/resource.qrc b/telldus-gui/TelldusCenter/resource.qrc new file mode 100644 index 00000000..e4c7cec9 --- /dev/null +++ b/telldus-gui/TelldusCenter/resource.qrc @@ -0,0 +1,5 @@ + + + images/devices.png + + From c3d04c6b6933de7d6a381f55dd0ecd09327de564 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 15 Dec 2008 19:42:44 +0000 Subject: [PATCH 0685/2215] Forgot resource.qrc --- telldus-gui/TelldusGui/resource.qrc | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 telldus-gui/TelldusGui/resource.qrc diff --git a/telldus-gui/TelldusGui/resource.qrc b/telldus-gui/TelldusGui/resource.qrc new file mode 100644 index 00000000..38ed5ab4 --- /dev/null +++ b/telldus-gui/TelldusGui/resource.qrc @@ -0,0 +1,6 @@ + + + images/list-add.png + images/list-remove.png + + From ab2d72683f436be562848c72e26d10952b1d7dc3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 15 Dec 2008 23:00:07 +0000 Subject: [PATCH 0686/2215] * First build on Linux * Added EditDeviceDialog * Added SystrayIcon --- telldus-gui/TelldusCenter/TelldusCenter.pro | 10 ++- .../TelldusCenter/images/devices-bw.png | Bin 0 -> 1453 bytes telldus-gui/TelldusCenter/main.cpp | 8 ++- telldus-gui/TelldusCenter/mainwindow.cpp | 17 ++++- telldus-gui/TelldusCenter/mainwindow.h | 3 + telldus-gui/TelldusCenter/resource.qrc | 1 + .../tellduscenterapplication.cpp | 22 +++++++ .../TelldusCenter/tellduscenterapplication.h | 20 ++++++ telldus-gui/TelldusGui/TelldusGui.pro | 22 ++++--- telldus-gui/TelldusGui/devicemodel.cpp | 9 ++- telldus-gui/TelldusGui/devicemodel.h | 2 +- telldus-gui/TelldusGui/devicewidget.cpp | 16 +++++ telldus-gui/TelldusGui/devicewidget.h | 1 + telldus-gui/TelldusGui/editdevicedialog.cpp | 58 ++++++++++++++++++ telldus-gui/TelldusGui/editdevicedialog.h | 16 +++++ telldus-gui/TelldusGui/telldusgui.cpp | 2 +- .../{TelldusGui_global.h => telldusgui.h} | 0 .../{resource.qrc => telldusgui.qrc} | 0 18 files changed, 185 insertions(+), 22 deletions(-) create mode 100644 telldus-gui/TelldusCenter/images/devices-bw.png create mode 100644 telldus-gui/TelldusCenter/tellduscenterapplication.cpp create mode 100644 telldus-gui/TelldusCenter/tellduscenterapplication.h create mode 100644 telldus-gui/TelldusGui/editdevicedialog.cpp create mode 100644 telldus-gui/TelldusGui/editdevicedialog.h rename telldus-gui/TelldusGui/{TelldusGui_global.h => telldusgui.h} (100%) rename telldus-gui/TelldusGui/{resource.qrc => telldusgui.qrc} (100%) diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index c0eccfef..510b8376 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -4,8 +4,12 @@ TARGET = TelldusCenter TEMPLATE = app SOURCES += main.cpp \ - mainwindow.cpp -HEADERS += mainwindow.h + mainwindow.cpp \ + tellduscenterapplication.cpp +HEADERS += mainwindow.h \ + tellduscenterapplication.h FORMS += RESOURCES += resource.qrc -LIBS += -lTelldusGui -L../TelldusGui +macx:LIBS += -lTelldusGui \ + -L../TelldusGui +!macx:LIBS += -ltelldus-gui diff --git a/telldus-gui/TelldusCenter/images/devices-bw.png b/telldus-gui/TelldusCenter/images/devices-bw.png new file mode 100644 index 0000000000000000000000000000000000000000..007a177832a03e7c3cc84a343591e8bf67f79cd1 GIT binary patch literal 1453 zcmV;e1ycHnP)( z`eLz)g$4=+(L!7LAhGmDAEc$wry}&thf;;~2BJi$Vv$+`F*P<;EgFlL+>?{bo;`c^ z%*@}1J$rJZC$$|Ic9-4noA00R`)7%n@$eub08lGdJeORxYW=gR)Pl82sVc4g>#m!= zdj9;$2LNjuDwG< z-!XH34nA6ih^V=F&(mABZ24yI-j=lu4Rw-800`elVwf4sjQ;-n!G#N#`>tN?ef{|H zFK$LWDk^c~#vRLAT3-IGt?kw7L?Q-&05F(ClG1x-VEOW;vE93C)+r?~3=Y1wfrti} zxma>+-MSY~wzlr9ipL!g0pT{Hpm3JVS}rP0CgZey`{ueJ$anPgTzm;YP7o38+jscw zZQGjHRa7JiAP@-uPBnz(=)`rj3)eA&px3?LjGpL?VV%Dis%9T|f7Eo-Y7EYlCbyhak|zQfDi&oi9)&gY=02@7B&?XNCl*n(Awnk zdB5Y}!TqA_BBOG-08$D#jzTQv0DwO*F!Xs-)0$5?Z0y;zm(CYn*tD>>_b>O( zod@i?9=oo`>GTW_4^Qye*d$L*&amrxJTWmf)6%l7=3#uXxEro zisgs<%eT&+?aVxke}oW#aoy=3l@h)&ws@R5jx1(R2w^-ga|S^Ev4qUb7cc&D#&MKp zw#HgxUDwq^Lqq!R-Fv#f|Bk+Q?|#0g=kgC+=C@Z)A&wk5JUTj>&S`C>wGjC{t4zkI z(b0?=8_TLom;RhNdi2b%02HK@2m-6;!_BAAW-?hLB|&SA$;l}U3=G5bvWUlH@O|IW+L-@C==Jyi{mID4 z#Cw&MPNU~#oWa2%WV6P&uDv@lGWK;}-^Jl_Kq?cZ@C6aAT)DF9z=0$0YHi-i +#include "tellduscenterapplication.h" #include "mainwindow.h" int main(int argc, char *argv[]) { Q_INIT_RESOURCE( resource ); - QApplication a(argc, argv); + TelldusCenterApplication application(argc, argv); + MainWindow *w = new MainWindow(); w->show(); - return a.exec(); + + return application.exec(); } diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index b9e6a995..fbff6cf3 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -5,9 +5,10 @@ #include #include #include +#include -#include "../TelldusGui/TelldusGui_global.h" +#include "../TelldusGui/telldusgui.h" MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) @@ -40,13 +41,18 @@ void MainWindow::setupMenu() QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addSeparator(); helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt())); - helpMenu->addAction(tr("About &TelldusCenter"), this, SLOT(slotAboutApplication())); + helpMenu->addAction(tr("About &Telldus Center"), this, SLOT(slotAboutApplication())); } void MainWindow::setupToolBar() { setUnifiedTitleAndToolBarOnMac(true); m_pagesBar = addToolBar(tr("Pages")); +#if defined(Q_WS_MAC) + m_pagesBar->setIconSize(QSize(18, 18)); +#else + m_pagesBar->setIconSize(QSize(32, 32)); +#endif QActionGroup *ag = new QActionGroup(this); @@ -56,3 +62,10 @@ void MainWindow::setupToolBar() ag->addAction(actionDevices); m_pagesBar->addActions( ag->actions() ); } + +void MainWindow::slotAboutApplication() { + QMessageBox::about(this, tr("About Telldus Center"), + tr("

Telldus Center 0.1

" + "

Copyright © 2008 Telldus Technologies AB

" + "

Telldus Center is a configuration utility for Telldus TellStick®

")); +} diff --git a/telldus-gui/TelldusCenter/mainwindow.h b/telldus-gui/TelldusCenter/mainwindow.h index 544422c9..f48a66a6 100644 --- a/telldus-gui/TelldusCenter/mainwindow.h +++ b/telldus-gui/TelldusCenter/mainwindow.h @@ -13,6 +13,9 @@ public: MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0); ~MainWindow(); +private slots: + void slotAboutApplication(); + private: void setupMenu(); void setupToolBar(); diff --git a/telldus-gui/TelldusCenter/resource.qrc b/telldus-gui/TelldusCenter/resource.qrc index e4c7cec9..873496eb 100644 --- a/telldus-gui/TelldusCenter/resource.qrc +++ b/telldus-gui/TelldusCenter/resource.qrc @@ -1,5 +1,6 @@ + images/devices-bw.png images/devices.png diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp new file mode 100644 index 00000000..c042fdb4 --- /dev/null +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -0,0 +1,22 @@ +#include "tellduscenterapplication.h" + +TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) + :QApplication(argc, argv), + systrayIcon(this) +{ +#if defined(Q_WS_MAC) + systrayIcon.setIcon(QIcon(":/images/devices-bw.png")); +#else + systrayIcon.setIcon(QIcon(":/images/devices.png")); +#endif + systrayIcon.show(); + + //setQuitOnLastWindowClosed( false ); +} + +TelldusCenterApplication::~TelldusCenterApplication() { +} + +TelldusCenterApplication *TelldusCenterApplication::instance() { + return (static_cast(QCoreApplication::instance())); +} diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h new file mode 100644 index 00000000..35eac6cb --- /dev/null +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -0,0 +1,20 @@ +#ifndef TELLDUSCENTERAPPLICATION_H +#define TELLDUSCENTERAPPLICATION_H + +#include +#include + +class TelldusCenterApplication : public QApplication +{ + Q_OBJECT +public: + TelldusCenterApplication(int &argc, char **argv); + virtual ~TelldusCenterApplication(); + + static TelldusCenterApplication *instance(); + +private: + QSystemTrayIcon systrayIcon; +}; + +#endif // TELLDUSCENTERAPPLICATION_H diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 29a67846..6f777c8d 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -1,24 +1,28 @@ # ------------------------------------------------- # Project created by QtCreator 2008-12-11T15:48:29 # ------------------------------------------------- -TARGET = TelldusGui TEMPLATE = lib DEFINES += TELLDUSGUI_LIBRARY SOURCES += telldusgui.cpp \ devicewidget.cpp \ - devicemodel.cpp \ - devicesetting/devicesetting.cpp \ - device.cpp + devicemodel.cpp \ # devicesetting/devicesetting.cpp \ + device.cpp \ + editdevicedialog.cpp HEADERS += telldusgui.h \ - TelldusGui_global.h \ devicewidget.h \ - devicemodel.h \ - devicesetting/devicesetting.h \ - device.h + devicemodel.h \ # devicesetting/devicesetting.h \ + device.h \ + editdevicedialog.h FORMS += macx { LIBS += -framework \ telldus-core ICON = images/telldussetup.icns + TARGET = TelldusGui } -RESOURCES += resource.qrc +!macx { + LIBS += -l \ + telldus-core + TARGET = telldus-gui +} +RESOURCES += telldusgui.qrc diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index 8dc9ff7f..cb557f52 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -54,14 +54,17 @@ bool DeviceModel::removeRows ( int row, int count, const QModelIndex & parent ) return true; } -const Device &DeviceModel::newDevice() const { +Device *DeviceModel::newDevice() const { Device *device = Device::newDevice(); connect(device, SIGNAL(deviceAdded(int)), this, SLOT(deviceAdded(int))); - return *device; + return device; } void DeviceModel::deviceAdded( int id ) { - qDebug("Yes"); + int deviceCount = tdGetNumberOfDevices(); + beginInsertRows( QModelIndex(), deviceCount - 1, deviceCount ); + qDebug() << "Ny enhet: " << id; + endInsertRows(); } int DeviceModel::deviceId( const QModelIndex &index ) const { diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index 3bed6512..957c5de2 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -19,7 +19,7 @@ public: virtual bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() ); - const Device &newDevice() const; + Device *newDevice() const; private slots: void deviceAdded( int id ); diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 52fb4cd6..9a775272 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -6,6 +6,8 @@ #include #include +#include "editdevicedialog.h" + DeviceWidget::DeviceWidget(QWidget *parent) : QWidget(parent), deviceView(this), @@ -22,6 +24,7 @@ DeviceWidget::DeviceWidget(QWidget *parent) : buttonLayout->setSpacing(0); addToolButton.setIcon( QIcon( ":/images/list-add.png" ) ); + connect(&addToolButton, SIGNAL(clicked()), this, SLOT(addDevice())); buttonLayout->addWidget( &addToolButton ); removeToolButton.setIcon( QIcon( ":/images/list-remove.png" ) ); @@ -49,6 +52,19 @@ void DeviceWidget::changeEvent(QEvent *e) } } +void DeviceWidget::addDevice() { + Device *device = model.newDevice(); + + EditDeviceDialog *dialog = new EditDeviceDialog( ); + if (dialog->exec() == QDialog::Accepted) { + //device->save(); + } else { + delete device; + } + + delete dialog; +} + void DeviceWidget::deleteDevice() { QMessageBox msgBox; msgBox.setText( tr("Are you sure you want to remove the selected device?") ); diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index fe103a7d..703ee76a 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -19,6 +19,7 @@ protected: private slots: void listActivated(const QModelIndex &); + void addDevice(); void deleteDevice(); private: diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp new file mode 100644 index 00000000..21670555 --- /dev/null +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -0,0 +1,58 @@ +#include "editdevicedialog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) + :QDialog(parent, flags) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + QHBoxLayout *deviceLayout = new QHBoxLayout(this); + + QTreeView *deviceView = new QTreeView(this); + deviceLayout->addWidget(deviceView); + + QGroupBox *deviceGroupBox = new QGroupBox(this); + deviceGroupBox->setTitle( tr("Device") ); + deviceGroupBox->setLayout(deviceLayout); + layout->addWidget(deviceGroupBox); + + QVBoxLayout *addressLayout = new QVBoxLayout(this); + + QFormLayout *nameLayout = new QFormLayout(this); + + QLabel *nameLabel = new QLabel(this); + nameLabel->setText( tr("&Name:") ); + QLineEdit *nameLineEdit = new QLineEdit( this ); + nameLabel->setBuddy(nameLineEdit); + + nameLayout->addRow(nameLabel, nameLineEdit); + addressLayout->addLayout( nameLayout ); + + QStackedLayout *settingsLayout = new QStackedLayout(this); + QLabel *noDeviceLabel = new QLabel( tr("Choose a device above"), this ); + noDeviceLabel->setAlignment( Qt::AlignCenter ); + settingsLayout->addWidget( noDeviceLabel ); + addressLayout->addLayout(settingsLayout); + + QGroupBox *settingsGroupBox = new QGroupBox(this); + settingsGroupBox->setTitle( tr("Addresscode") ); + settingsGroupBox->setLayout( addressLayout ); + layout->addWidget( settingsGroupBox ); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons( QDialogButtonBox::Save | QDialogButtonBox::Cancel ); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + layout->addWidget(buttonBox); +} + +EditDeviceDialog::~EditDeviceDialog() { +} diff --git a/telldus-gui/TelldusGui/editdevicedialog.h b/telldus-gui/TelldusGui/editdevicedialog.h new file mode 100644 index 00000000..40a2a6ae --- /dev/null +++ b/telldus-gui/TelldusGui/editdevicedialog.h @@ -0,0 +1,16 @@ +#ifndef EDITDEVICEDIALOG_H +#define EDITDEVICEDIALOG_H + +#include + +class EditDeviceDialog : public QDialog +{ +public: + EditDeviceDialog(QWidget *parent = 0, Qt::WFlags flags = 0); + virtual ~EditDeviceDialog(); + +private: + +}; + +#endif // EDITDEVICEDIALOG_H diff --git a/telldus-gui/TelldusGui/telldusgui.cpp b/telldus-gui/TelldusGui/telldusgui.cpp index d90b1923..b1fc3c4d 100644 --- a/telldus-gui/TelldusGui/telldusgui.cpp +++ b/telldus-gui/TelldusGui/telldusgui.cpp @@ -1,4 +1,4 @@ -#include "TelldusGui_global.h" +#include "telldusgui.h" #include "devicewidget.h" diff --git a/telldus-gui/TelldusGui/TelldusGui_global.h b/telldus-gui/TelldusGui/telldusgui.h similarity index 100% rename from telldus-gui/TelldusGui/TelldusGui_global.h rename to telldus-gui/TelldusGui/telldusgui.h diff --git a/telldus-gui/TelldusGui/resource.qrc b/telldus-gui/TelldusGui/telldusgui.qrc similarity index 100% rename from telldus-gui/TelldusGui/resource.qrc rename to telldus-gui/TelldusGui/telldusgui.qrc From b1bd974fa54cbbf48a819496e5172d1e29fcbc0e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 16 Dec 2008 09:50:33 +0000 Subject: [PATCH 0687/2215] Fixed some warnings when adding the layouts to a widget --- telldus-gui/TelldusCenter/mainwindow.cpp | 4 ---- telldus-gui/TelldusGui/devicewidget.cpp | 2 +- telldus-gui/TelldusGui/editdevicedialog.cpp | 8 ++++---- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index fbff6cf3..75dfd638 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -48,11 +48,7 @@ void MainWindow::setupToolBar() { setUnifiedTitleAndToolBarOnMac(true); m_pagesBar = addToolBar(tr("Pages")); -#if defined(Q_WS_MAC) - m_pagesBar->setIconSize(QSize(18, 18)); -#else m_pagesBar->setIconSize(QSize(32, 32)); -#endif QActionGroup *ag = new QActionGroup(this); diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 9a775272..a101ff55 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -20,7 +20,7 @@ DeviceWidget::DeviceWidget(QWidget *parent) : QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(&deviceView); - QHBoxLayout *buttonLayout = new QHBoxLayout( this ); + QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->setSpacing(0); addToolButton.setIcon( QIcon( ":/images/list-add.png" ) ); diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 21670555..9a4646a7 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -14,7 +14,7 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) { QVBoxLayout *layout = new QVBoxLayout(this); - QHBoxLayout *deviceLayout = new QHBoxLayout(this); + QHBoxLayout *deviceLayout = new QHBoxLayout; QTreeView *deviceView = new QTreeView(this); deviceLayout->addWidget(deviceView); @@ -24,9 +24,9 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) deviceGroupBox->setLayout(deviceLayout); layout->addWidget(deviceGroupBox); - QVBoxLayout *addressLayout = new QVBoxLayout(this); + QVBoxLayout *addressLayout = new QVBoxLayout; - QFormLayout *nameLayout = new QFormLayout(this); + QFormLayout *nameLayout = new QFormLayout; QLabel *nameLabel = new QLabel(this); nameLabel->setText( tr("&Name:") ); @@ -36,7 +36,7 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) nameLayout->addRow(nameLabel, nameLineEdit); addressLayout->addLayout( nameLayout ); - QStackedLayout *settingsLayout = new QStackedLayout(this); + QStackedLayout *settingsLayout = new QStackedLayout; QLabel *noDeviceLabel = new QLabel( tr("Choose a device above"), this ); noDeviceLabel->setAlignment( Qt::AlignCenter ); settingsLayout->addWidget( noDeviceLabel ); From 345de77e773cadbb5ea96b35df6b3b65fda81748 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 18 Dec 2008 17:40:16 +0000 Subject: [PATCH 0688/2215] Added class VendorDeviceModel --- telldus-gui/TelldusGui/TelldusGui.pro | 20 +++++++++++++++---- telldus-gui/TelldusGui/editdevicedialog.cpp | 5 ++++- telldus-gui/TelldusGui/editdevicedialog.h | 4 +++- telldus-gui/TelldusGui/vendordevicemodel.cpp | 9 +++++++++ telldus-gui/TelldusGui/vendordevicemodel.h | 14 +++++++++++++ .../TelldusGui/vendordevicetreeitem.cpp | 5 +++++ telldus-gui/TelldusGui/vendordevicetreeitem.h | 10 ++++++++++ 7 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 telldus-gui/TelldusGui/vendordevicemodel.cpp create mode 100644 telldus-gui/TelldusGui/vendordevicemodel.h create mode 100644 telldus-gui/TelldusGui/vendordevicetreeitem.cpp create mode 100644 telldus-gui/TelldusGui/vendordevicetreeitem.h diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 6f777c8d..97a3d3d5 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -5,14 +5,26 @@ TEMPLATE = lib DEFINES += TELLDUSGUI_LIBRARY SOURCES += telldusgui.cpp \ devicewidget.cpp \ - devicemodel.cpp \ # devicesetting/devicesetting.cpp \ + devicemodel.cpp \ + \ \ + \ \ + \ \ + \ \ # devicesetting/devicesetting.cpp \ device.cpp \ - editdevicedialog.cpp + editdevicedialog.cpp \ + vendordevicemodel.cpp \ + vendordevicetreeitem.cpp HEADERS += telldusgui.h \ devicewidget.h \ - devicemodel.h \ # devicesetting/devicesetting.h \ + devicemodel.h \ + \ \ + \ \ + \ \ + \ \ # devicesetting/devicesetting.h \ device.h \ - editdevicedialog.h + editdevicedialog.h \ + vendordevicemodel.h \ + vendordevicetreeitem.h FORMS += macx { LIBS += -framework \ diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 9a4646a7..84f45058 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -1,4 +1,6 @@ #include "editdevicedialog.h" +#include "vendordevicemodel.h" + #include #include #include @@ -10,7 +12,8 @@ #include EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) - :QDialog(parent, flags) + :QDialog(parent, flags), + model(new VendorDeviceModel(this)) { QVBoxLayout *layout = new QVBoxLayout(this); diff --git a/telldus-gui/TelldusGui/editdevicedialog.h b/telldus-gui/TelldusGui/editdevicedialog.h index 40a2a6ae..de5772e0 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.h +++ b/telldus-gui/TelldusGui/editdevicedialog.h @@ -3,6 +3,8 @@ #include +class VendorDeviceModel; + class EditDeviceDialog : public QDialog { public: @@ -10,7 +12,7 @@ public: virtual ~EditDeviceDialog(); private: - + VendorDeviceModel *model; }; #endif // EDITDEVICEDIALOG_H diff --git a/telldus-gui/TelldusGui/vendordevicemodel.cpp b/telldus-gui/TelldusGui/vendordevicemodel.cpp new file mode 100644 index 00000000..4d0c6573 --- /dev/null +++ b/telldus-gui/TelldusGui/vendordevicemodel.cpp @@ -0,0 +1,9 @@ +#include "vendordevicemodel.h" + +VendorDeviceModel::VendorDeviceModel(QObject *parent) + :QAbstractItemModel(parent) +{ +} + +VendorDeviceModel::~VendorDeviceModel() { +} diff --git a/telldus-gui/TelldusGui/vendordevicemodel.h b/telldus-gui/TelldusGui/vendordevicemodel.h new file mode 100644 index 00000000..374f3ea2 --- /dev/null +++ b/telldus-gui/TelldusGui/vendordevicemodel.h @@ -0,0 +1,14 @@ +#ifndef VENDORDEVICEMODEL_H +#define VENDORDEVICEMODEL_H + +#include + +class VendorDeviceModel : public QAbstractItemModel +{ + Q_OBJECT +public: + VendorDeviceModel(QObject *parent = 0); + ~VendorDeviceModel(); +}; + +#endif // VENDORDEVICEMODEL_H diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp new file mode 100644 index 00000000..d7f17dc3 --- /dev/null +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -0,0 +1,5 @@ +#include "vendordevicetreeitem.h" + +VendorDeviceTreeItem::VendorDeviceTreeItem() +{ +} diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.h b/telldus-gui/TelldusGui/vendordevicetreeitem.h new file mode 100644 index 00000000..1a404144 --- /dev/null +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.h @@ -0,0 +1,10 @@ +#ifndef VENDORDEVICETREEITEM_H +#define VENDORDEVICETREEITEM_H + +class VendorDeviceTreeItem +{ +public: + VendorDeviceTreeItem(); +}; + +#endif // VENDORDEVICETREEITEM_H From 13fc866f76c68408bd6ad9a98b64fcfd4f2a6b42 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 18 Dec 2008 17:44:25 +0000 Subject: [PATCH 0689/2215] Added project file for building both telldus-gui and telldus-center --- telldus-gui/telldus-gui.pro | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 telldus-gui/telldus-gui.pro diff --git a/telldus-gui/telldus-gui.pro b/telldus-gui/telldus-gui.pro new file mode 100644 index 00000000..4e6a9f6e --- /dev/null +++ b/telldus-gui/telldus-gui.pro @@ -0,0 +1,3 @@ +TEMPLATE=subdirs +SUBDIRS = TelldusGui \ + TelldusCenter From bf7dd1a55bd56f38fc673e20187da347751b2cdd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 18 Dec 2008 19:46:38 +0000 Subject: [PATCH 0690/2215] First working VendorDeviceModel --- telldus-gui/TelldusGui/TelldusGui.pro | 8 -- telldus-gui/TelldusGui/editdevicedialog.cpp | 1 + telldus-gui/TelldusGui/vendordevicemodel.cpp | 97 ++++++++++++++++++- telldus-gui/TelldusGui/vendordevicemodel.h | 14 +++ .../TelldusGui/vendordevicetreeitem.cpp | 44 ++++++++- telldus-gui/TelldusGui/vendordevicetreeitem.h | 21 +++- 6 files changed, 174 insertions(+), 11 deletions(-) diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 97a3d3d5..4db3acbb 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -6,10 +6,6 @@ DEFINES += TELLDUSGUI_LIBRARY SOURCES += telldusgui.cpp \ devicewidget.cpp \ devicemodel.cpp \ - \ \ - \ \ - \ \ - \ \ # devicesetting/devicesetting.cpp \ device.cpp \ editdevicedialog.cpp \ vendordevicemodel.cpp \ @@ -17,10 +13,6 @@ SOURCES += telldusgui.cpp \ HEADERS += telldusgui.h \ devicewidget.h \ devicemodel.h \ - \ \ - \ \ - \ \ - \ \ # devicesetting/devicesetting.h \ device.h \ editdevicedialog.h \ vendordevicemodel.h \ diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 84f45058..4b7baae5 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -20,6 +20,7 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) QHBoxLayout *deviceLayout = new QHBoxLayout; QTreeView *deviceView = new QTreeView(this); + deviceView->setModel( model ); deviceLayout->addWidget(deviceView); QGroupBox *deviceGroupBox = new QGroupBox(this); diff --git a/telldus-gui/TelldusGui/vendordevicemodel.cpp b/telldus-gui/TelldusGui/vendordevicemodel.cpp index 4d0c6573..9ebcc7ca 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.cpp +++ b/telldus-gui/TelldusGui/vendordevicemodel.cpp @@ -1,9 +1,104 @@ #include "vendordevicemodel.h" +#include "vendordevicetreeitem.h" VendorDeviceModel::VendorDeviceModel(QObject *parent) - :QAbstractItemModel(parent) + :QAbstractItemModel(parent), + rootItem(new VendorDeviceTreeItem(0, "")) { + rootItem->appendChild( new VendorDeviceTreeItem(0, "Ikea", rootItem) ); + rootItem->appendChild( new VendorDeviceTreeItem(0, "Nexa", rootItem) ); + rootItem->appendChild( new VendorDeviceTreeItem(0, "Proove", rootItem) ); + rootItem->appendChild( new VendorDeviceTreeItem(0, "Sartano", rootItem) ); + rootItem->appendChild( new VendorDeviceTreeItem(0, "Waveman", rootItem) ); } VendorDeviceModel::~VendorDeviceModel() { + delete rootItem; +} + +int VendorDeviceModel::columnCount(const QModelIndex &parent) const { + if (parent.isValid()) { + return static_cast(parent.internalPointer())->columnCount(); + } + return rootItem->columnCount(); +} + +QVariant VendorDeviceModel::data(const QModelIndex &index, int role) const { + if (!index.isValid()) { + return QVariant(); + } + + if (role != Qt::DisplayRole) { + return QVariant(); + } + + VendorDeviceTreeItem *item = static_cast(index.internalPointer()); + + return item->data(index.column()); +} + +Qt::ItemFlags VendorDeviceModel::flags(const QModelIndex &index) const { + if (!index.isValid()) { + return 0; + } + + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant VendorDeviceModel::headerData(int section, Qt::Orientation orientation, int role) const { + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { + return tr("Name"); + } + + return QVariant(); +} + +QModelIndex VendorDeviceModel::index(int row, int column, const QModelIndex &parent) const { + if (!hasIndex(row, column, parent)) { + return QModelIndex(); + } + + VendorDeviceTreeItem *parentItem; + + if (!parent.isValid()) { + parentItem = rootItem; + } else { + parentItem = static_cast(parent.internalPointer()); + } + + VendorDeviceTreeItem *childItem = parentItem->child(row); + if (childItem) { + return createIndex(row, column, childItem); + } + return QModelIndex(); +} + +QModelIndex VendorDeviceModel::parent(const QModelIndex &index) const { + if (!index.isValid()) { + return QModelIndex(); + } + + VendorDeviceTreeItem *childItem = static_cast(index.internalPointer()); + VendorDeviceTreeItem *parentItem = childItem->parent(); + + if (parentItem == rootItem) { + return QModelIndex(); + } + + return createIndex(parentItem->row(), 0, parentItem); +} + +int VendorDeviceModel::rowCount(const QModelIndex &parent) const { + VendorDeviceTreeItem *parentItem; + if (parent.column() > 0) { + return 0; + } + + if (!parent.isValid()) { + parentItem = rootItem; + } else { + parentItem = static_cast(parent.internalPointer()); + } + + return parentItem->childCount(); } diff --git a/telldus-gui/TelldusGui/vendordevicemodel.h b/telldus-gui/TelldusGui/vendordevicemodel.h index 374f3ea2..50932325 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.h +++ b/telldus-gui/TelldusGui/vendordevicemodel.h @@ -2,6 +2,9 @@ #define VENDORDEVICEMODEL_H #include +#include + +class VendorDeviceTreeItem; class VendorDeviceModel : public QAbstractItemModel { @@ -9,6 +12,17 @@ class VendorDeviceModel : public QAbstractItemModel public: VendorDeviceModel(QObject *parent = 0); ~VendorDeviceModel(); + + int columnCount(const QModelIndex &parent) const; + QVariant data(const QModelIndex &index, int role) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; + int rowCount(const QModelIndex &parent) const; + QModelIndex parent(const QModelIndex &index) const; + +private: + VendorDeviceTreeItem *rootItem; }; #endif // VENDORDEVICEMODEL_H diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index d7f17dc3..d875b0da 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -1,5 +1,47 @@ #include "vendordevicetreeitem.h" -VendorDeviceTreeItem::VendorDeviceTreeItem() +VendorDeviceTreeItem::VendorDeviceTreeItem(int id, const QString &displayString, VendorDeviceTreeItem *parent) + :deviceId(id), + deviceName(displayString), + parentItem(parent) { } + +VendorDeviceTreeItem::~VendorDeviceTreeItem() { + qDeleteAll(childItems); +} + +void VendorDeviceTreeItem::appendChild(VendorDeviceTreeItem *item) { + childItems.append(item); +} + +VendorDeviceTreeItem *VendorDeviceTreeItem::child(int row) { + return childItems.value(row); +} + +int VendorDeviceTreeItem::childCount() const { + return childItems.count(); +} +int VendorDeviceTreeItem::columnCount() const { + return 1; +} + +QVariant VendorDeviceTreeItem::data(int column) const { + if (column == 0) { + return deviceName; + } + + return "Da"; +} + +VendorDeviceTreeItem *VendorDeviceTreeItem::parent() { + return parentItem; +} + +int VendorDeviceTreeItem::row() const { + if (parentItem) { + return parentItem->childItems.indexOf(const_cast(this)); + } + + return 0; +} diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.h b/telldus-gui/TelldusGui/vendordevicetreeitem.h index 1a404144..8ce0495a 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.h +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.h @@ -1,10 +1,29 @@ #ifndef VENDORDEVICETREEITEM_H #define VENDORDEVICETREEITEM_H +#include + class VendorDeviceTreeItem { public: - VendorDeviceTreeItem(); + VendorDeviceTreeItem(int id, const QString &displayString, VendorDeviceTreeItem *parent = 0); + ~VendorDeviceTreeItem(); + + void appendChild(VendorDeviceTreeItem *child); + + VendorDeviceTreeItem *child(int row); + int childCount() const; + int columnCount() const; + QVariant data(int column) const; + int row() const; + VendorDeviceTreeItem *parent(); + +private: + QList childItems; + + int deviceId; + QString deviceName; + VendorDeviceTreeItem *parentItem; }; #endif // VENDORDEVICETREEITEM_H From 5e3c96d433e22a13538076d83ea69f5f123c4d35 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 18 Dec 2008 20:14:55 +0000 Subject: [PATCH 0691/2215] Added xml with devices --- telldus-gui/TelldusGui/data/devices.xml | 18 ++++++++++++++++++ telldus-gui/TelldusGui/telldusgui.qrc | 1 + 2 files changed, 19 insertions(+) create mode 100644 telldus-gui/TelldusGui/data/devices.xml diff --git a/telldus-gui/TelldusGui/data/devices.xml b/telldus-gui/TelldusGui/data/devices.xml new file mode 100644 index 00000000..6d309c3a --- /dev/null +++ b/telldus-gui/TelldusGui/data/devices.xml @@ -0,0 +1,18 @@ + + + + Koppla + + + YCR-3500 + + + EL2000 + + + 51343 + + + 17-356 + + diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index 38ed5ab4..cb0550cd 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -1,5 +1,6 @@ + data/devices.xml images/list-add.png images/list-remove.png From 081d863d0cb30b0f71107158c0f6bf4ce82b8e87 Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Thu, 18 Dec 2008 21:51:22 +0000 Subject: [PATCH 0692/2215] Added devices from types.db to devices.xml --- telldus-gui/TelldusGui/data/devices.xml | 35 ++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/telldus-gui/TelldusGui/data/devices.xml b/telldus-gui/TelldusGui/data/devices.xml index 6d309c3a..09aa4dbc 100644 --- a/telldus-gui/TelldusGui/data/devices.xml +++ b/telldus-gui/TelldusGui/data/devices.xml @@ -1,18 +1,41 @@ - - Koppla - YCR-3500 - - - EL2000 + YCR-300D + WSR-10000 + CMR-1000 + CMR-300 + PA3-3300 + SYCR-3500 + SYCR-300 + HDR-105 + ML-7100 + LYCR-1000 + LYCR-300 + LCMR-1000 + LCMR-300 51343 + + EL2000 + EL2005 + EL2006 + EL2004 + EL2016 + EL2010 + EL2023 + EL2024 + EL2021 + EL2017 + EL2019 + 17-356 + + Koppla + From a42788e13de140be5b77cd01924c6f1cffcf454f Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Thu, 18 Dec 2008 22:09:40 +0000 Subject: [PATCH 0693/2215] Changed to alphabetical order and changed widget for device 15 --- telldus-gui/TelldusGui/data/devices.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/telldus-gui/TelldusGui/data/devices.xml b/telldus-gui/TelldusGui/data/devices.xml index 09aa4dbc..87d64354 100644 --- a/telldus-gui/TelldusGui/data/devices.xml +++ b/telldus-gui/TelldusGui/data/devices.xml @@ -1,5 +1,8 @@ + + Koppla + YCR-3500 YCR-300D @@ -10,15 +13,12 @@ SYCR-3500 SYCR-300 HDR-105 - ML-7100 + ML-7100 LYCR-1000 LYCR-300 LCMR-1000 LCMR-300 - - 51343 - EL2000 EL2005 @@ -32,10 +32,10 @@ EL2017 EL2019 + + 51343 + 17-356 - - Koppla - From 4e490e1ccd7ef81540d56b538c31908b31f18925 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 18 Dec 2008 22:37:54 +0000 Subject: [PATCH 0694/2215] VendorDeviceModel now parses the xml with device information --- telldus-gui/TelldusGui/data/devices.xml | 2 +- telldus-gui/TelldusGui/vendordevicemodel.cpp | 8 +- .../TelldusGui/vendordevicetreeitem.cpp | 106 +++++++++++++++++- telldus-gui/TelldusGui/vendordevicetreeitem.h | 8 ++ 4 files changed, 116 insertions(+), 8 deletions(-) diff --git a/telldus-gui/TelldusGui/data/devices.xml b/telldus-gui/TelldusGui/data/devices.xml index 87d64354..4143d3a3 100644 --- a/telldus-gui/TelldusGui/data/devices.xml +++ b/telldus-gui/TelldusGui/data/devices.xml @@ -38,4 +38,4 @@ 17-356 - + diff --git a/telldus-gui/TelldusGui/vendordevicemodel.cpp b/telldus-gui/TelldusGui/vendordevicemodel.cpp index 9ebcc7ca..39e5c482 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.cpp +++ b/telldus-gui/TelldusGui/vendordevicemodel.cpp @@ -5,11 +5,7 @@ VendorDeviceModel::VendorDeviceModel(QObject *parent) :QAbstractItemModel(parent), rootItem(new VendorDeviceTreeItem(0, "")) { - rootItem->appendChild( new VendorDeviceTreeItem(0, "Ikea", rootItem) ); - rootItem->appendChild( new VendorDeviceTreeItem(0, "Nexa", rootItem) ); - rootItem->appendChild( new VendorDeviceTreeItem(0, "Proove", rootItem) ); - rootItem->appendChild( new VendorDeviceTreeItem(0, "Sartano", rootItem) ); - rootItem->appendChild( new VendorDeviceTreeItem(0, "Waveman", rootItem) ); + rootItem->parseXml( ":/data/devices.xml" ); } VendorDeviceModel::~VendorDeviceModel() { @@ -45,7 +41,7 @@ Qt::ItemFlags VendorDeviceModel::flags(const QModelIndex &index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } -QVariant VendorDeviceModel::headerData(int section, Qt::Orientation orientation, int role) const { +QVariant VendorDeviceModel::headerData(int , Qt::Orientation orientation, int role) const { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { return tr("Name"); } diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index d875b0da..87f96ffc 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -1,5 +1,9 @@ #include "vendordevicetreeitem.h" +#include +#include +#include + VendorDeviceTreeItem::VendorDeviceTreeItem(int id, const QString &displayString, VendorDeviceTreeItem *parent) :deviceId(id), deviceName(displayString), @@ -31,7 +35,7 @@ QVariant VendorDeviceTreeItem::data(int column) const { return deviceName; } - return "Da"; + return QVariant(); } VendorDeviceTreeItem *VendorDeviceTreeItem::parent() { @@ -45,3 +49,103 @@ int VendorDeviceTreeItem::row() const { return 0; } + +bool VendorDeviceTreeItem::parseXml( const QString &filename ) { + QFile file(filename); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + std::cerr << "Error: Cannot read file " << qPrintable(filename) + << ": " << qPrintable(file.errorString()) + << std::endl; + return false; + } + + QXmlStreamReader reader; + reader.setDevice(&file); + + reader.readNext(); + while (!reader.atEnd()) { + if (reader.isStartElement()) { + if (reader.name() == "devices") { //First element + reader.readNext(); + } else if (reader.name() == "vendor") { + parseVendor( &reader ); + } else { + reader.raiseError( QObject::tr("Not a Telldus device-file")); + } + } else { + reader.readNext(); + } + } + + file.close(); + if (reader.hasError()) { + std::cerr << "Error: Failed to parse file " + << qPrintable(filename) << ": " + << qPrintable(reader.errorString()) << std::endl; + return false; + } else if (file.error() != QFile::NoError) { + std::cerr << "Error: Cannot read file " << qPrintable(filename) + << ": " << qPrintable(file.errorString()) + << std::endl; + return false; + } + + return true; +} + +void VendorDeviceTreeItem::parseVendor( QXmlStreamReader *reader ) { + VendorDeviceTreeItem *item = new VendorDeviceTreeItem(0, reader->attributes().value("name").toString(), this); + appendChild(item); + + reader->readNext(); + while(!reader->atEnd()) { + if (reader->isEndElement()) { + reader->readNext(); + break; + } + + if (reader->isStartElement()) { + if (reader->name() == "device") { + parseDevice( reader, item ); + } else { + skipUnknownElement( reader ); + } + } else { + reader->readNext(); + } + } +} + +void VendorDeviceTreeItem::parseDevice( QXmlStreamReader *reader, VendorDeviceTreeItem *parent ) { + VendorDeviceTreeItem *item = new VendorDeviceTreeItem(reader->attributes().value("id").toString().toInt(), reader->readElementText(), parent); + parent->appendChild(item); + + while(!reader->atEnd()) { + if (reader->isEndElement()) { + reader->readNext(); + break; + } + + if (reader->isStartElement()) { + skipUnknownElement( reader ); + } else { + reader->readNext(); + } + } +} + +void VendorDeviceTreeItem::skipUnknownElement( QXmlStreamReader *reader ) { + reader->readNext(); + while (!reader->atEnd()) { + if (reader->isEndElement()) { + reader->readNext(); + break; + } + + if (reader->isStartElement()) { + skipUnknownElement( reader ); + } else { + reader->readNext(); + } + } +} diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.h b/telldus-gui/TelldusGui/vendordevicetreeitem.h index 8ce0495a..5f3d205b 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.h +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.h @@ -3,6 +3,8 @@ #include +class QXmlStreamReader; + class VendorDeviceTreeItem { public: @@ -18,7 +20,13 @@ public: int row() const; VendorDeviceTreeItem *parent(); + bool parseXml( const QString &filename ); + private: + void parseVendor( QXmlStreamReader *reader ); + void parseDevice( QXmlStreamReader *reader, VendorDeviceTreeItem *parent ); + void skipUnknownElement( QXmlStreamReader *reader ); + QList childItems; int deviceId; From 75d9aa8086467f5adbce5d69cb0cac72656de6e8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 18 Dec 2008 22:48:15 +0000 Subject: [PATCH 0695/2215] Fixed stange bug with QXmlStreamReader when compiling on Mac --- telldus-gui/TelldusGui/vendordevicetreeitem.cpp | 1 - telldus-gui/TelldusGui/vendordevicetreeitem.h | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index 87f96ffc..aafc7cff 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -1,7 +1,6 @@ #include "vendordevicetreeitem.h" #include -#include #include VendorDeviceTreeItem::VendorDeviceTreeItem(int id, const QString &displayString, VendorDeviceTreeItem *parent) diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.h b/telldus-gui/TelldusGui/vendordevicetreeitem.h index 5f3d205b..17d28f5f 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.h +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.h @@ -2,8 +2,7 @@ #define VENDORDEVICETREEITEM_H #include - -class QXmlStreamReader; +#include class VendorDeviceTreeItem { From 84c6090209e674e3baa09c77a5d5f376eee1280b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 22 Dec 2008 12:36:10 +0000 Subject: [PATCH 0696/2215] Added device images to EditDeviceDialog --- telldus-gui/TelldusGui/TelldusGui.pro | 8 +- telldus-gui/TelldusGui/data/devices.xml | 2 +- telldus-gui/TelldusGui/devicesetting.cpp | 31 +++++ telldus-gui/TelldusGui/devicesetting.h | 37 ++++++ telldus-gui/TelldusGui/devicesettingnexa.cpp | 109 ++++++++++++++++++ telldus-gui/TelldusGui/devicesettingnexa.h | 49 ++++++++ telldus-gui/TelldusGui/editdevicedialog.cpp | 30 +++++ telldus-gui/TelldusGui/editdevicedialog.h | 10 ++ .../TelldusGui/images/devices/143011.jpg | Bin 0 -> 2244 bytes .../TelldusGui/images/devices/14323.jpg | Bin 0 -> 13874 bytes .../TelldusGui/images/devices/14327.jpg | Bin 0 -> 13380 bytes .../TelldusGui/images/devices/145041.jpg | Bin 0 -> 1471 bytes .../TelldusGui/images/devices/145071.jpg | Bin 0 -> 1857 bytes .../TelldusGui/images/devices/145091.jpg | Bin 0 -> 1700 bytes .../TelldusGui/images/devices/17-356.jpg | Bin 0 -> 21369 bytes .../TelldusGui/images/devices/51340.jpg | Bin 0 -> 1593 bytes .../TelldusGui/images/devices/el2005.jpg | Bin 0 -> 1570 bytes .../TelldusGui/images/devices/el2019.jpg | Bin 0 -> 13133 bytes telldus-gui/TelldusGui/images/devices/hdr.jpg | Bin 0 -> 15414 bytes .../TelldusGui/images/devices/koppla.jpg | Bin 0 -> 2060 bytes telldus-gui/TelldusGui/images/devices/ml.jpg | Bin 0 -> 15133 bytes .../TelldusGui/images/devices/sycr.jpg | Bin 0 -> 18027 bytes .../TelldusGui/images/vendors/ikea.jpg | Bin 0 -> 15658 bytes .../TelldusGui/images/vendors/intertechno.jpg | Bin 0 -> 20888 bytes .../TelldusGui/images/vendors/nexa.jpg | Bin 0 -> 22438 bytes .../TelldusGui/images/vendors/proove.jpg | Bin 0 -> 20998 bytes .../TelldusGui/images/vendors/sartano.jpg | Bin 0 -> 18550 bytes .../TelldusGui/images/vendors/telldus.jpg | Bin 0 -> 1955 bytes .../TelldusGui/images/vendors/waveman.jpg | Bin 0 -> 18172 bytes telldus-gui/TelldusGui/telldusgui.qrc | 21 ++++ telldus-gui/TelldusGui/vendordevicemodel.cpp | 15 ++- telldus-gui/TelldusGui/vendordevicemodel.h | 2 + .../TelldusGui/vendordevicetreeitem.cpp | 28 ++++- telldus-gui/TelldusGui/vendordevicetreeitem.h | 6 +- 34 files changed, 339 insertions(+), 9 deletions(-) create mode 100644 telldus-gui/TelldusGui/devicesetting.cpp create mode 100644 telldus-gui/TelldusGui/devicesetting.h create mode 100644 telldus-gui/TelldusGui/devicesettingnexa.cpp create mode 100644 telldus-gui/TelldusGui/devicesettingnexa.h create mode 100644 telldus-gui/TelldusGui/images/devices/143011.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/14323.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/14327.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/145041.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/145071.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/145091.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/17-356.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/51340.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/el2005.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/el2019.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/hdr.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/koppla.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/ml.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/sycr.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/ikea.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/intertechno.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/nexa.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/proove.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/sartano.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/telldus.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/waveman.jpg diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 4db3acbb..36193328 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -9,14 +9,18 @@ SOURCES += telldusgui.cpp \ device.cpp \ editdevicedialog.cpp \ vendordevicemodel.cpp \ - vendordevicetreeitem.cpp + vendordevicetreeitem.cpp \ + devicesettingnexa.cpp \ + devicesetting.cpp HEADERS += telldusgui.h \ devicewidget.h \ devicemodel.h \ device.h \ editdevicedialog.h \ vendordevicemodel.h \ - vendordevicetreeitem.h + vendordevicetreeitem.h \ + devicesettingnexa.h \ + devicesetting.h FORMS += macx { LIBS += -framework \ diff --git a/telldus-gui/TelldusGui/data/devices.xml b/telldus-gui/TelldusGui/data/devices.xml index 4143d3a3..36da271d 100644 --- a/telldus-gui/TelldusGui/data/devices.xml +++ b/telldus-gui/TelldusGui/data/devices.xml @@ -20,7 +20,7 @@ LCMR-300 - EL2000 + EL2000 EL2005 EL2006 EL2004 diff --git a/telldus-gui/TelldusGui/devicesetting.cpp b/telldus-gui/TelldusGui/devicesetting.cpp new file mode 100644 index 00000000..0abeff3a --- /dev/null +++ b/telldus-gui/TelldusGui/devicesetting.cpp @@ -0,0 +1,31 @@ +// +// C++ Implementation: devicesetting +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "devicesetting.h" + +DeviceSetting::DeviceSetting(QWidget *parent) + : QWidget(parent) +{ +} + + +DeviceSetting::~DeviceSetting() +{ +} + + +/** + * @fn DeviceSetting::setDevice( DeviceInfo * ) + */ +//void DeviceSetting::setDevice( DeviceInfo *device ) +//{ +// p_dev = device; +//} diff --git a/telldus-gui/TelldusGui/devicesetting.h b/telldus-gui/TelldusGui/devicesetting.h new file mode 100644 index 00000000..592bcc3c --- /dev/null +++ b/telldus-gui/TelldusGui/devicesetting.h @@ -0,0 +1,37 @@ +// +// C++ Interface: devicesetting +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DEVICESETTING_H +#define DEVICESETTING_H + +#include +//#include "deviceinfo.h" + +/** + @author Micke Prag +*/ +class DeviceSetting : public QWidget +{ +Q_OBJECT +public: + DeviceSetting(QWidget *parent = 0); + + ~DeviceSetting(); + +//public slots: +// virtual void setDevice( DeviceInfo * ); +// virtual void saveSetting() = 0; + +//protected: +// DeviceInfo *p_dev; +}; + +#endif diff --git a/telldus-gui/TelldusGui/devicesettingnexa.cpp b/telldus-gui/TelldusGui/devicesettingnexa.cpp new file mode 100644 index 00000000..22997854 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingnexa.cpp @@ -0,0 +1,109 @@ +// +// C++ Implementation: devicesettingnexa +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "devicesettingnexa.h" +#include +#include +#include + +DeviceSettingNexa::DeviceSettingNexa(QWidget *parent) + : DeviceSetting(parent) +{ + gridLayout1 = new QGridLayout(this); + gridLayout1->setSpacing(6); + gridLayout1->setMargin(9); + gridLayout1->setObjectName(QString::fromUtf8("gridLayout1")); + + dialCode = new QDial(this); + dialCode->setObjectName(QString::fromUtf8("dialCode")); + dialCode->setMinimum(1); + dialCode->setMaximum(16); + dialCode->setPageStep(1); + dialCode->setOrientation(Qt::Horizontal); + dialCode->setNotchesVisible(true); + + gridLayout1->addWidget(dialCode, 1, 1, 1, 1); + + dialHouse = new QDial(this); + dialHouse->setObjectName(QString::fromUtf8("dialHouse")); + dialHouse->setMinimum(0); + dialHouse->setMaximum(15); + dialHouse->setPageStep(1); + dialHouse->setOrientation(Qt::Horizontal); + dialHouse->setNotchesVisible(true); + + gridLayout1->addWidget(dialHouse, 1, 0, 1, 1); + + label = new QLabel(this); + label->setObjectName(QString::fromUtf8("label")); + label->setAlignment(Qt::AlignCenter); + label->setText( tr("Housecode") ); + + gridLayout1->addWidget(label, 0, 0, 1, 1); + + label_2 = new QLabel(this); + label_2->setObjectName(QString::fromUtf8("label_2")); + label_2->setAlignment(Qt::AlignCenter); + label_2->setText( tr("Unitcode") ); + + gridLayout1->addWidget(label_2, 0, 1, 1, 1); + + labelHouse = new QLabel(this); + labelHouse->setObjectName(QString::fromUtf8("labelHouse")); + labelHouse->setAlignment(Qt::AlignCenter); + labelHouse->setText( "A" ); + connect( dialHouse, SIGNAL( valueChanged( int ) ), this, SLOT( houseChanged(int) ) ); + + gridLayout1->addWidget(labelHouse, 2, 0, 1, 1); + + label_4 = new QLabel(this); + label_4->setObjectName(QString::fromUtf8("label_4")); + label_4->setAlignment(Qt::AlignCenter); + label_4->setText( "1" ); + connect( dialCode, SIGNAL(valueChanged(int)), label_4, SLOT(setNum(int)) ); + + gridLayout1->addWidget(label_4, 2, 1, 1, 1); +} + + +DeviceSettingNexa::~DeviceSettingNexa() +{ +} + + +/** + * @fn DeviceSettingNexa::setDevice( DeviceInfo * ) + */ +//void DeviceSettingNexa::setDevice( DeviceInfo *device ) +//{ +// DeviceSetting::setDevice( device ); +// QString strHouse = device->setting("nexa_house", "A"); +// uint intHouse = strHouse[0].toAscii() - 'A'; +// dialHouse->setValue( intHouse ); +// dialCode->setValue( device->setting("nexa_unit", "1").toInt() ); +//} +// +///** +// * @fn DeviceSettingNexa::saveSetting() +// */ +//void DeviceSettingNexa::saveSetting() { +// p_dev->setSetting( "nexa_house", QString('A' + dialHouse->value()) ); +// p_dev->setSetting( "nexa_unit", QString::number(dialCode->value()) ); +//} + +/** + * @fn DeviceSettingNexa::houseChanged( int house ) + */ +void DeviceSettingNexa::houseChanged( int house ) +{ + labelHouse->setText( QString('A' + house) ); +} + diff --git a/telldus-gui/TelldusGui/devicesettingnexa.h b/telldus-gui/TelldusGui/devicesettingnexa.h new file mode 100644 index 00000000..7d855646 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingnexa.h @@ -0,0 +1,49 @@ +// +// C++ Interface: devicesettingnexa +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DEVICESETTINGNEXA_H +#define DEVICESETTINGNEXA_H + +#include + +class QGridLayout; +class QDial; +class QLabel; + +/** + @author Micke Prag +*/ +class DeviceSettingNexa : public DeviceSetting +{ +Q_OBJECT +public: + DeviceSettingNexa(QWidget *parent = 0); + + ~DeviceSettingNexa(); + +//public slots: +// virtual void setDevice( DeviceInfo * ); +// virtual void saveSetting(); + +protected slots: + void houseChanged( int house ); + +protected: + QGridLayout *gridLayout1; + QDial *dialCode; + QDial *dialHouse; + QLabel *label; + QLabel *label_2; + QLabel *labelHouse; + QLabel *label_4; +}; + +#endif diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 4b7baae5..abba4dee 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -1,5 +1,8 @@ #include "editdevicedialog.h" #include "vendordevicemodel.h" +#include "vendordevicetreeitem.h" + +#include "devicesettingnexa.h" #include #include @@ -11,6 +14,8 @@ #include #include +#include + EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) :QDialog(parent, flags), model(new VendorDeviceModel(this)) @@ -21,8 +26,17 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) QTreeView *deviceView = new QTreeView(this); deviceView->setModel( model ); + QItemSelectionModel *selection = deviceView->selectionModel(); + connect( selection, SIGNAL( currentChanged(const QModelIndex, const QModelIndex &) ), this, SLOT(selectionChanged( const QModelIndex & ) )); deviceLayout->addWidget(deviceView); + QVBoxLayout *deviceInfoLayout = new QVBoxLayout; + deviceImage = new QLabel( this ); + deviceInfoLayout->addWidget( deviceImage ); + deviceInfoLayout->addStretch(); + + deviceLayout->addLayout( deviceInfoLayout ); + QGroupBox *deviceGroupBox = new QGroupBox(this); deviceGroupBox->setTitle( tr("Device") ); deviceGroupBox->setLayout(deviceLayout); @@ -56,7 +70,23 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); layout->addWidget(buttonBox); + + deviceSettings[1] = new DeviceSettingNexa(); + foreach( DeviceSetting *s, deviceSettings ) { + settingsLayout->addWidget( s ); + } } EditDeviceDialog::~EditDeviceDialog() { + qDeleteAll( deviceSettings ); +} + +void EditDeviceDialog::selectionChanged( const QModelIndex & index ) { + const VendorDeviceTreeItem* const item = model->item(index); + if (!item) { + return; + } + + deviceImage->setPixmap( item->image() ); +// qDebug() << "Selection changed" << item->image(); } diff --git a/telldus-gui/TelldusGui/editdevicedialog.h b/telldus-gui/TelldusGui/editdevicedialog.h index de5772e0..858a22d2 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.h +++ b/telldus-gui/TelldusGui/editdevicedialog.h @@ -2,17 +2,27 @@ #define EDITDEVICEDIALOG_H #include +#include +#include class VendorDeviceModel; +class DeviceSetting; +class QLabel; class EditDeviceDialog : public QDialog { + Q_OBJECT public: EditDeviceDialog(QWidget *parent = 0, Qt::WFlags flags = 0); virtual ~EditDeviceDialog(); +private slots: + void selectionChanged( const QModelIndex & ); + private: VendorDeviceModel *model; + QLabel *deviceImage; + QHash deviceSettings; }; #endif // EDITDEVICEDIALOG_H diff --git a/telldus-gui/TelldusGui/images/devices/143011.jpg b/telldus-gui/TelldusGui/images/devices/143011.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f30c30a19daba431f1d48de4e9cfbb805ca41180 GIT binary patch literal 2244 zcmb7FcTm$?7XGEtNlZu(kX{x;6%-y#5Ky`j6A6&`L=i+vkQR!{Ly)FCgY>6>Ak73K zC58YZilBmm^kyh4(iRXzsz8JX?#}GY{^3WdP-5)208;};R&-vdHeSWpCs zK%tNbBvMRV`k)wE3WG#SC`d@j$jHgbi5*l_R+LqimX(v;7Xj_H^7HY-1q9%-Xe3(p z|Hf`3fE3st76MWPz(^1T3EF)F$N(S!4B1-)^zV81GM@kx#t#7t?$ag*01yNM2J^$9 zLXclqKwtv)6raU-!Sl z`wn0bWRH+V{$lp6|6>aRkYJPoL`Tv5>@F7&+4BM;AxOXss0%5^s$lJG?eMAi^rG}% zg*|~@L2)hApMRQ#o?BNiZ0tDNK9HLmC}XK*;kM%si@HgyxywS2%q!U_RnG)OY*+w1 zC$uHSpa6e8E)O|s`u%sqNjuq;=jS8Il(5t^g+kuxnWZ$>N^Q>jo|kP>B;rm_IkVW7 z$fp~TERviXbi-j>YB7JsN9gVscwlUW$vZ?7XI(f6SB;o;P8(2VP#f;4tE%JS5fjh6 z<)k9S?5WcJ#kE_6z*YKcq^n=pi;>J%UvEVT>Se>Xy&q`mNMvT1=G#zg@wP43uF~I) zYL-mQo^I)>EdNb{xcZnND+Pl!FO@mm%zo%d)&)&0*hPs!U_{^wWWv zk{7ACuJ;i3O3Nm_jWk+(croU_SsX7fv-<=Yjm`X}S?J)i9h@L^4=Y=woLo?*(_njr zyinN_RkUP3|`v_UbWOo`nadc^ak8z(}>8d8>{qkm|}W8TgZl@HDq>>`OXLt8wG7j>db` z{j`yL$mU@D>sw~-i({4z8GH#=KiyP1M=e@bYR!HyPfl@nwA-5RWhHXR_F~0rx%P(m zb$R-Ve5g>I>!OZ-6*?XjpG(Rf>mu1DxDeu`R?- zVU=f~%N-`7<{?KoHUnppyXSot?^L;@Z_-EzC8n*!G(G~*)yWA3eR!6a)1v?NCN8|X z&;y!tQ0~&J?AFd+z0T#~HwOvT7Xfja_5H2B-lTF$Z{_gMh1W&An5<17u;)96{Pmc@)$vgzRDo8!rz9^-%dKy$8N$0-r_sD@-eWr zU7Q@KWxU~`tRG`si=k|pFEwq`*QB>|IlW53{{FOOzSS2o=^2okhXE|67jL@k?eG<^CbC~5XRcR+Lv)3AM7WKE~*MFdH_&Sy{S2Vg8h;6sj2)K>|+&Xa0`Li<< z$##jSXfDEV!}t#;?9hfqwB9_DnhWH2E%dyx)sw{j0mZ&sx>+P=J^ccN($0LrRYB36 z>X8YG$`vI${zjmBG7483*?qx}Q_U+2!0F`rhIY?(s!kAxD)MO>YgGae@hFX*Q&)K2%SVC7(HrE1U3eKxb6K*?ynas2{eUuaIa$L4k!D`YCL z|3b)$bp&lBOq^Xb5p=hbzfF($##2wncdUe~Le9o@*nTx!-RW=ds(@{i;fO%gAd}=c zl1Pw{Z;+P$)9Zm_F*RG`-7B|+W+7)TIi+$_=CP|8VEvB13-DdBk9(``uE?a~G5t(< zkKpSc?&Xh*k_x(fr4G(?coWXwGbpMSB&NJ6b9I_}o zmJ>ac{sbU4NX8``o>^mw;4rCCL?VMMbO0X3@COa9T)GSC)*&F@H?c+rUioGySdS-CFTn59TwW@8tE62K>iq%5p8%KG7(%Qo>OV6*`dp(Up z58<#x0aK{6nbYQWwcKX}TnkB+zEM5OiR}ZijLspP+qh?!zfTeKEE*}KRL{33zqzYP z*etE5pNkUugQ_V`#(PK#)>zuVxmcTtLjPg#(W6Q-6NPWSN>QGSEfVQJ{wSbwYP5l2 O=WI0fzyIg%r@sLnhvK&Y literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/14323.jpg b/telldus-gui/TelldusGui/images/devices/14323.jpg new file mode 100644 index 0000000000000000000000000000000000000000..133f69518a9f58ae10889b40fb15500ff7810354 GIT binary patch literal 13874 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/14327.jpg b/telldus-gui/TelldusGui/images/devices/14327.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a51b9fe0c1d7747419beac26f02aaf3314db40dd GIT binary patch literal 13380 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 Xk+{dLxs_J!`<|{ozQR0Pb>sg4^OF45 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/145041.jpg b/telldus-gui/TelldusGui/images/devices/145041.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef54cc8335c1da525408593bf4c124744f84c7bf GIT binary patch literal 1471 zcmb7CdpOit7(TxlW5#v-+;7bo%n}izs1So80Ad!F>001N1Qb?wN8$cmtWMq&iX+WV+vS>vNS_-U!f}A3ZRaJ$t zFs!DjucfB0s{zB>1Z~|78}N9%nwFulAVDeI&HAS4n($)IHs3V+>z00Jq4f~{p$ z2{s4OYH4>h3|&sfr_DS=#r1SZYHb6iCDJ5{Q^cX4C z`dS!5z}BiZNSA|Zl1ZQ_B@i$Y2F^fifpHz7yl>(+b(NH9pW7=kM@KLgP3)d2XC|OR z!UB)eou}~(KFt%Cv-Xo;;6oj67gp;^0h<{;%+H85xPWCm_n${aZRO8ovG3WrSDer2 z2(Cy&N`POsgRB1puWP!#flAh}!V!DxikEA=^*Ra(@+z(>ZG=@~SN7eDg_j2N_R%<- zj@t*_`mih)${9{=G1C>k!W^fkQcd%Pxh9T-P$j*#kzI9rk+&l+Ieg)Rp9S}nVBLe1 z)KWCbvbuWC$6{U%+m`ZR!Dp59(I;mqCTppNJ9Fy`3l$=GusE0(#u2c+Z(y`g~0O2qnq7ifI{R zvJ339qyJ*?i3SPebA{gCNB8ru3`Lwd8Mm#bC{1Yp+6IfVTrY@?9nS6)Z z_S%*BH#y@20fM}EF=JP>>0b5?J7!aJWPt9AfnM+=W+Sh=N|D8*sAdw}Fs_>6jQ7PY z$W^aktU*a|br6d>ZOr@Is%`B>D_36Q=~LFWVUH7fA@i9y@#zRcv3qiBTbE2l+ryh_ z%{K17XmY8yU+kn#)NkE`E~H8mr5N4r@-oNa@bKUFjOl6~>bXVBbzidPbU4&rLQfWy ztfosqSXaCJb~@3>aAP2ADSxalq{)EV{)T8Kq-SMm-xOyPibfTwJ-epgiNWI^UurPf zBFzJopi&W&(UDZ~`n(>^Ndg4r-J0X$ae`;7&+mV}`$y-_ErrIpBZIR+POt>nTn;yN zvt<42J*tng>E`tVT{ZZkEzY~|C9Jszt>8REIge@O!YL)*jqK+PawM@KYPZsCQZ#`> ziHRUPS~+=F3%(gWaJGEZcRY$#vceTVY%ZA^C5~D;2|YPyxdBr??OP5%=ofkQP8`AN zD`EIfO~lo?_f0#;*^O*!?6WqdrWIa&8Ig3K?$?dEKCp`9?= z7)@?`H2Ev4uB2~;+j_mReCF8PP~TXCztR9{mUU6U4e_S*JHOpeotHCj3l)t)Yt|KF z6aVGR3k%J-e?Dln|D?`bI?ID(bi~ST`v=ly&Ivju%z>^wlXAVX$&&u4lR32DLeN%q zc;paS$}e71ZY+Nn6LrbHuJM$g3Iz?Berk0T8Z{hC;`nYL8+^8^5vY3vn58_$xAwTq zr376|?7pXxmB0_yu-9H}NTr6>2j|O^8!ZIixsf^*WOD|z0=G`ZyhtyUfd1JDk7{Ph ze0xge>_o8f`sEeo#1Eun3Ht1pNy#@lceE95Qs;74MmE)_n+ELPo0C>qfhy~+(u?C! Nxla#dnzl$L{sabvW48bR literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/145071.jpg b/telldus-gui/TelldusGui/images/devices/145071.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3384ad91229dc0816760424772c3476cd968fe02 GIT binary patch literal 1857 zcmb7=X*k>Y7RUcdNJvz~-Uty~C5o|+SW0WJsUT9dbE%?=+G8E3wmZ`#ks6{hsG{-h9vboO6D>S>6&L=3rxQ1Assv zz>gmQZyAubP6)XP06+Wy-~j*-;y=E4^S~8A5F#KT01@OTK|w(%OhgFA7ZQOG7C|A! z#ZgEUN0_^mJ~OjJlnR6!CYsqlY` z_ZmP6eOnd+QUbsz5CjF{^#T|G0D~d?EB+%vC?Eg=Lxf;_*Fp>cK_DO~7z%|V{$0U$ zP=J7-I8*|sW9bb0QPRafs-RFxT1nUSx!&cw8I8-z2Bhdm6;0iov2i{@hW|tVP3J@S zh;Ih!e+(2zhxa=m0s-;Y<4?H+?0Y+mGogF<=3$Pk4U=I8b0xVYf6~>@4WE{(?%hisj9_iv`%pR>(sT{ z6uqRexzmA0EhJ$8j)Z(hJ9lY>o?g>$#@!+@Ej~%wa+9WzqC#{Ikc!dhxIf>!S?ON{;_510&L(MYw{pki+4qN%a*o3$Qf0zpyXH4zTViQF*VL_l zopO>28x{g*@N`~8;UMMLIrv&$!6^Dhj*c^jb=YQ$|&&8?WdLLF6n%LdjRPFf9 zRN@nKUhVT0Q7wZP5N>-!ynHtvYPN(9*cej~3$LF^DRKKegv&k-HZroaT~Jj~H|G#y z6tjX!rx%gl-8_KE%!e7`JdrOE?DjQld)uSCA6CiQtZ_` zOt{5{*?SZwXEcX_-g_Fn<=1Q4C^}BC9 zGWABuU?S1S3mmusMT(;Ry7NpA;d*QPAL*}r6>H^^A~rWqGK$h?I~dMyC4g;xwN)b6DmA~^ScKt z*3Q*iYEbK6#B<~EDN`yB)boNLd)pu=pyj_qyWq{RK_D0zy3|fA9!NVg2 z9@Y2wvdj0?qsF)Gav8Udej}s}xuJJoxXT&LuDG{EX0S8dFqMT)A3_g2`djFD@}8Pn zkj`eH>|%#vetYAvDs86eD^O9sGH1VLPdq7`pgT0Qaj~tx< literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/145091.jpg b/telldus-gui/TelldusGui/images/devices/145091.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94fc4048d43b8b68454e1c48b3044e2c5b850760 GIT binary patch literal 1700 zcmb7^dr*_d8pij_mm3z4FN6p}0)!}vqJ_#e7~l}mh_s-f7Elz3TuKdSD*?H*asbPL zAR-nKf`vBJfLvk@LJ-iSP{2Y!LIH4IpJqAd7xRIv-@b(5)006uuG*S-%4}gKuXf%w`Oc)FXi_^yA zG+O`BM_Ss*dIAAik0AOalMVXBjRpu}Xl}TXOg1$&)!#s+Q7JSNiYa9c0%=llSez~% zuS+2!M9Tjy^*w;#*P4YPDnKC+j6mv#fD8Z%1+N|BZ$Vf9qcM0CPD^9E=m7|ZQ7{Ip zS%2680hGo@ur>s9cbq=eHy3YvGWLi2#DfMT+CMzLt+n{%P)Mn$ckGoW+Xw>xgVq3G zG=#!vEK@|oS!4ZIVHAv*qiqOOcVG1&&|Y&97y+(eR!kOcp@%^edz^p%hMGwLv?B05 z$C=MBD2Q;odHuBcyui7;W`fqp`ry>8XkgTD!*HplY@x@SI4Y2tRc zn)gOV353ueK&Msk{utRK#n`5h8Z#?KF)Xz1 z^K>K5?la4};9Si&ffPmJVL>3%X{3Sk!^Gm}3cu1k_X9)RuCjA`u(O$$Zd{~?`6Rc) z_Z^Ms=zqn|*>|iwA{Es-EOxaHdmf*38#t+B^0q{3`2w0!G&l?f4%(~1v0K#}4}G?O z>+Ip>k$vOFH8bTkFPpk8RNQYtv>SR}eEipd6-jj+-5bM<<~i4SBWDxel{+Q{Z1DA3 zY&*xE8ULz!lZYoT(sZAZyUedZZ3*aYw=Sc}T?pL5#HX}uq~U=}hX2?5oi1MOf&)-h zf>KAU)+1h*alVIe#5cWn?1dWW$L3@dN(ysp8?&c)9t~RucdiRW_lGf3&`E~6YT&wS zysYG6cq)T*DZu5nrWEt;odDL`TlxIhsh*r=R#UWLC!eLGBO@A%wn?{9gXS2kb2hRG zHSno9<(1SNDW`C>UEt+L$mYl9;W-1w%OpreBCss4d5>gz`$x@%dp%^|pS3n+e=bVEIS$ z@gZ^O9R3xtjjT<}B3HU;zT|KaePGlWcfsw|f9}^iO*gVEis@qI(IesMs_jl=SI>FM zol(_-;{08;ex8Yhn%yl_+uEIXZ(8J06uph_-IDr!Lc+3CwvMBd%u!P6H<>$B9dECo zN_Soeu1OR1eL5zoNj{akD3yJ2m7PDlA>iyEi3!S}fx7JjEh4h9Xp2MGk%9oG>4%5= zs_N-voeqc7=OYWLWIw%J`bA^?nf5}MdCD!GyZU9@l+koEJ9wZf^-AZ;`LF%;OY+|B z4!nnZp=FjpOJWZ)gpWsl{(T)swmDyw$+Pe^viv7K-Q@(&J^M7le`iF3a$SaWWhi(X zUoMxS*=4(7ZVax&&aRjwS7n@tU}+axNgv9mYrZadHn5&p=`mD`?0;d{3ku_g~h$}v|l3>CfIm!^{pBOv9)si zk2d~+X!-NtRj=3*gc4O)qIa!~@=NFQ;ia^NoZi-O>m*pF(1`t^HU?ID9FhzTh_g<&kF^*@-U|m-f+n6aDd!5_j zxr&nAJl#04ba7>-`*z=lU!WkK=*xuGLeQT*{_pQYhqW-L~ zIkvh7?~=T-E~iT;1W}#;km!}&neGkO>RZ-lTj=(Rw6OU(Awd5Q literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/17-356.jpg b/telldus-gui/TelldusGui/images/devices/17-356.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2403692d33fb3a86447f938bca64046809a12fda GIT binary patch literal 21369 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 Ir+54R4?=^kaR2}S literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/51340.jpg b/telldus-gui/TelldusGui/images/devices/51340.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f7199df424a84eb7747adf565628c5553340cef3 GIT binary patch literal 1593 zcmb7AdpOg39RAL(%Ap^IVcWx~NMx)FHW@1>w<+nU(7H`cF*2T`4&~J8xXU$CjjWAL zJ!z42Avr`xZW$?ai5xj{GU;Sz)$^REf6x28pU*$<=Y5~|`&GSAy#_0oTfDXam>M=P z8vsjg{$4iFF$ zrE6yI77(syPL6u0Phw?V!A2+D=p3f+%g(ua^O4$V_~mE53ssxdR<(eGzAE2KFvwoR zOeF_eaCH|54gpv2IiJZ&`o>_#PVqYfg>}hK;F!upt_l)mdwCyA7nilUIhAx_Dqt(*2G^kn)x|FEXbxhq!d zNjE!xNI`rvROj0<)hjP{<4rzA*OB=dq&pJ7b#;G79X4~=&+f6XC6oD4W5w}RCATuP z#5TSG-DA6aF_feDgNd{b#bJr1EUo-knIOmL01Y!TH^VxIR*0Hgrws=%HMP698E!Hy z&~EsF8;hqqp359&n?6g3G@8GE&r=X4!ERPkwo~?aNwgKCjLrmEPH;rgnS8r+Pn!N> zDdoDuu}#}8GgupEXM=05&mQTg!sn9=l@;rUtFJG#%qXPHE8DGq21X#J>SVjSg)z2_ z)yzI#XdR!L&F^ilWClq?x_xf>VQW#`!R+`|9rt4I&axv5NZq+IJ?d=nQtoc<_)2Dwqh^t!NN|NvNG1B(K%9zAYx`l zd-B6?Q4Z|!oz@&tS~o6*cFj%iUhKn)+e_sfx}_vGNr&CaoctY70 z2aYOsyq}?5rJ13n9@IP7Bh+yiUtrTjeN{%XZ~AN}eA(@zZiUcPhTiOR1DC$8z`q6=N7?(~)h z_NVCt-1)@lNyd4#IoZ=+QJ*^m#4`HRw7C%@@iIY;`%KP+OW(GeHOa00YpVoM(`m5m f(;+Uhq%LH@fxQT6`|D<`3x literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/el2005.jpg b/telldus-gui/TelldusGui/images/devices/el2005.jpg new file mode 100644 index 0000000000000000000000000000000000000000..69adb288945594b212fbcfe087dddf4f44f1df51 GIT binary patch literal 1570 zcmb7EYdF(=82!6Ikw^$7CKL)Kf!>Tki-E&pB{#!385tM{ z!?Fs>in4Nec^FnwRl=*N5Q#)tMUoncpr%Y95;j6Wu@xKwE?-8h!_c~R_C5J&!&x#0y7VjT}}=+N&i5Jt$T?hy?F zo5eB$hG4)HSWk(G!NgqoMRCZL^G%i6sbRK!+X;TF`&bAT{Nd<;TsF6XVGzC)(%+hD z+?d1RMfRxhOJ;B1(;9?ZgEJ$_vMRi~2uoD6a)+H&S@lXw_z-G<-|qBqTZU1c|9SoV z16!HmY&8Cxv?FsA}Gjrh5IQRXt#?E!bhhPESL~{7p=0&~2 z=v^VL48{F;%5@P?VwE3UTzCD^-b+6}{4LKkuk8HTzDEAK{}Y@ z{I^dNn(L{G#=~>v-rsB&c*%Oj(S#g$*@^kHdpR(@{>2f_y#Th}&7Q#1J63Z?7nEGj z{xL*wR4%8{Qx!9b0jY=jXfuOp)AQ`M81?Hc!{*Tm*8Kf@!R(6YW45$+vsZmtHv1}H zu2aMLi(eKP9-6oJ?m2$I>KYwg8RIezGXXz@&s>7C{*Wr~eG4`jKx zu*t~yF*=L4`e=>X=3s5MPn*%dTEU44G9z-Ll5vSaeBat9r~@(K^b;e0onub*2H)Lv;wFg!*vDV;Rdok|%G&W)%qEzPlGjHTaod%=yr-*IHd zFuVTsJHMOSelGLm88=E(U0hQ1{;E0q()T`vTWn};kl|O$`7cI-lC%fs?p^a`f`3Ya@FvUUFkSFwl>G)DU41!Pj0JVXbYQ zVJo-R{MfZsTBU8W4FB3c;Z4^S!nPiXPnz@^+JNU9sam`47CTPDW2w}%xUE1YaV^wuCG+K;NTE`cc-Tbq4-_I71c8YIJ(M9^L zg8Fhwk3m*$z7#i~qJmj)cpjPB^0BI*mr_*QOzIMHc@tkIs|_W16^@b4)`!$GE*m(< U{>*H8bt(@*+D0P%BAjU8U($Y@-2eap literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/el2019.jpg b/telldus-gui/TelldusGui/images/devices/el2019.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6d4408abe656c450e971aaa0e4efd702f53bc49f GIT binary patch literal 13133 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/hdr.jpg b/telldus-gui/TelldusGui/images/devices/hdr.jpg new file mode 100644 index 0000000000000000000000000000000000000000..372fa17978b5e2b238fb8886cc5d34c10a6571c7 GIT binary patch literal 15414 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 h<9FU%Y~rvsxY5baQwUf3h>NpDs literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/koppla.jpg b/telldus-gui/TelldusGui/images/devices/koppla.jpg new file mode 100644 index 0000000000000000000000000000000000000000..20e921d22c6c65ad650bbbc58abc1836319e170b GIT binary patch literal 2060 zcmb7FdpOhkAOCJMbD7I`<{Dd#h0~#2!zRWtyW~2pusW$xWNMMzszVpKq**Q{A(l-p z1*7V4MtTLyk)2(s7dVTfd&)^ZWh#dwrhI>-{|M*Zci`-p~8}d7jVO^R<_N zHjPXr0}u!VpePQoCIj@m5+Wl2z{dyp0RR9M#Z_Q!6z~M#FeN1=7+gVcI9wTlR6!`9 zrLL}u1hr5oPzwZg^o;d&&_=o-Xt2S+$ixJT#p>we%y1YpV+$M~e`Bp309Am!z+M;x2S7mx41}yb0@eWl6bgfUZ}vMQlvSWGCAdO#&;}qd7*q*{ zfGWfOEkYCu00)&(IvZ?Ah=A*8To^Ys_rbn;T|HCVzp}uTYkK^0~fnySy;zAw$x`?Im)Xpl>q z9nU*I33>PTZnbcU)1`59TvcPvc>JCFld~MZ=EnS1Sv$pypICfq+%|Bf_`8Nv4>K zb61SCQkHIx+-&3&zafl9#ZwqML!9KoMpl=p_6WA@q+~MQrnMYnonxJyq#EoI;c|{inh_K75IyGDkiw!} z2^SK!XPwUdIb>ayM&GgECp%J$XC{l81#%O-prgT3RA1OZQ}g85>p3rc9qjou91_eS zrSV2L+_--?_W{Ej#(PTLR$N_Q8ga!0FQoA*zM3L>5_9CutPsI#CHs*voio|Too~ht zmU=e@?2jBeYRzvG`aNb+e;jjQ*4`b*36vwK!J9XK_SkAtmblPK`%Ql}G>%m{@N1gH zV?eQ6MgutCeM95^rT|%`oyK*I8-&1XE!fYDqI-|R@4z#quMJ!7IS*N|Ypt{=%FKta zzA#a7Id)6N#fcn0r-q7A$1$u$`ak{=_e8t~`?P_e;@XT%U!9fQK@l-MBy5)aC~L*0 z*J}E}?4TsG=AWpPM&PW@AIPDgjM&nRbE)xSYGmiL!0U}aDV)fnhC*|gj%VhNmJ#DxpX>8B_-J>SAy_p?yZ6!?A+o_ zoS9}CZFv;m$w$ml+%)F4UmzE1mc(nbEq%6y!v&>QcUn-+%UGjRg0S_8Y7>Lz(Ri10 zrcMjbw54kK3owV^yUc6rTMSDQ`7 z`!7D|4Le4U|Ev$M=vo-_``PXBfwH&9vnu-OdY>XQKaH`g$_pOa^`u=tz0_-nw@LA8 zwS3$N7uy*|r?dRR*;5Cmvn86k@*!M6=3x7+%fKc>*Y-ZQI zNtac7MP2%%o;on=bA{D_wJ>H0*Xl?Y4wAR8o@Ki`~}oe}CNn zqVGmsU;ddRGGgr`HgbLO!N4I4f+b?k!|5&%}t{I z5#Qm_XgsV-&F5pucx$4oIe{2I@@1|cUm&>MgymS<*EdrAyKohQ_B*b;Oo03)T-t2< zwq|9YpdrBNOh|(|c$kuJ^(unwj<>QZP9D#AMS8q_;)Ut0Gdv;Gw>`P|Xl)*tn`x(# z)d9X^&c=7srrrfsjQ?QrrgLB=PI}ISZ^m&ORQ26LU@yBx9i{)#l+PE{xf+zTzw^80 z7BW9|Ff!Z4IDEL2;=D}txHu@RWz|3Xurl3>L6Xbt&o+NLnAadx%PZsAx?^qjh|d|t z$fD9$JtjAXqRiegc(j2~GFNPBI0n2;mQ?nu+Uz&0GDvhkY&Nx8-C8-$nmqqLL-WW| z%HT}B+p)^L-1NJazsZTtmzD-5AB6ci?e@sjkqC^xBnP&DY;xSzjf9$NS7Q?OV{OK? zlp%Z=I2w9h)mp$_Ns?clSH?BCxqqqJyN_D9Hz>iUSuA-&bNBWSyj^zkYOK#j5}iVQ yje;M>bLaBW0shzj`|;>zo%hU;Hk{SM*#!rXsuVk6zPiFe^jboj`n?cqBmV+fv2d~g literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/ml.jpg b/telldus-gui/TelldusGui/images/devices/ml.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5162a56371c549d79b3d16586a396ee2f6c5d564 GIT binary patch literal 15133 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/proove.jpg b/telldus-gui/TelldusGui/images/vendors/proove.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2d665afe6a06aab6ffbb041d2a337f57c301173f GIT binary patch literal 20998 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/waveman.jpg b/telldus-gui/TelldusGui/images/vendors/waveman.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8ba987a42110286432ef8358984f59d4cbfec7b3 GIT binary patch literal 18172 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index cb0550cd..0775cf84 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -3,5 +3,26 @@ data/devices.xml images/list-add.png images/list-remove.png + images/devices/17-356.jpg + images/devices/14323.jpg + images/devices/14327.jpg + images/devices/51340.jpg + images/devices/143011.jpg + images/devices/145041.jpg + images/devices/145071.jpg + images/devices/145091.jpg + images/devices/el2005.jpg + images/devices/el2019.jpg + images/devices/hdr.jpg + images/devices/koppla.jpg + images/devices/ml.jpg + images/devices/sycr.jpg + images/vendors/ikea.jpg + images/vendors/intertechno.jpg + images/vendors/nexa.jpg + images/vendors/proove.jpg + images/vendors/sartano.jpg + images/vendors/telldus.jpg + images/vendors/waveman.jpg diff --git a/telldus-gui/TelldusGui/vendordevicemodel.cpp b/telldus-gui/TelldusGui/vendordevicemodel.cpp index 39e5c482..27947f22 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.cpp +++ b/telldus-gui/TelldusGui/vendordevicemodel.cpp @@ -3,7 +3,7 @@ VendorDeviceModel::VendorDeviceModel(QObject *parent) :QAbstractItemModel(parent), - rootItem(new VendorDeviceTreeItem(0, "")) + rootItem(new VendorDeviceTreeItem(0)) { rootItem->parseXml( ":/data/devices.xml" ); } @@ -98,3 +98,16 @@ int VendorDeviceModel::rowCount(const QModelIndex &parent) const { return parentItem->childCount(); } + +const VendorDeviceTreeItem* const VendorDeviceModel::item( const QModelIndex &index ) const { + if (!index.isValid()) { + return 0; + } + + VendorDeviceTreeItem *item = static_cast(index.internalPointer()); + if (item) { + return item; + } + + return 0; +} diff --git a/telldus-gui/TelldusGui/vendordevicemodel.h b/telldus-gui/TelldusGui/vendordevicemodel.h index 50932325..faf54706 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.h +++ b/telldus-gui/TelldusGui/vendordevicemodel.h @@ -21,6 +21,8 @@ public: int rowCount(const QModelIndex &parent) const; QModelIndex parent(const QModelIndex &index) const; + const VendorDeviceTreeItem* const item( const QModelIndex &index ) const; + private: VendorDeviceTreeItem *rootItem; }; diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index aafc7cff..e58fbe80 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -1,11 +1,12 @@ #include "vendordevicetreeitem.h" #include +#include +#include #include -VendorDeviceTreeItem::VendorDeviceTreeItem(int id, const QString &displayString, VendorDeviceTreeItem *parent) +VendorDeviceTreeItem::VendorDeviceTreeItem(int id, VendorDeviceTreeItem *parent) :deviceId(id), - deviceName(displayString), parentItem(parent) { } @@ -49,6 +50,21 @@ int VendorDeviceTreeItem::row() const { return 0; } +QPixmap VendorDeviceTreeItem::image() const { + QString filename; + if (deviceId == 0) { + filename = ":/images/vendors/" + img.toLower() + ".jpg"; + } else { + filename = ":/images/devices/" + img + ".jpg"; + } + QPixmap image = QPixmap(filename); + if (image.isNull()) { + image = QPixmap( 96, 96 ); + image.fill( Qt::transparent ); + } + return image; +} + bool VendorDeviceTreeItem::parseXml( const QString &filename ) { QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { @@ -93,7 +109,9 @@ bool VendorDeviceTreeItem::parseXml( const QString &filename ) { } void VendorDeviceTreeItem::parseVendor( QXmlStreamReader *reader ) { - VendorDeviceTreeItem *item = new VendorDeviceTreeItem(0, reader->attributes().value("name").toString(), this); + VendorDeviceTreeItem *item = new VendorDeviceTreeItem(0, this); + item->deviceName = reader->attributes().value("name").toString(); + item->img = reader->attributes().value("name").toString(); appendChild(item); reader->readNext(); @@ -116,7 +134,9 @@ void VendorDeviceTreeItem::parseVendor( QXmlStreamReader *reader ) { } void VendorDeviceTreeItem::parseDevice( QXmlStreamReader *reader, VendorDeviceTreeItem *parent ) { - VendorDeviceTreeItem *item = new VendorDeviceTreeItem(reader->attributes().value("id").toString().toInt(), reader->readElementText(), parent); + VendorDeviceTreeItem *item = new VendorDeviceTreeItem(reader->attributes().value("id").toString().toInt(), parent); + item->img = reader->attributes().value("image").toString(); + item->deviceName = reader->readElementText(); //This call must be the last one because it clears the attribute-list parent->appendChild(item); while(!reader->atEnd()) { diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.h b/telldus-gui/TelldusGui/vendordevicetreeitem.h index 17d28f5f..f774875b 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.h +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.h @@ -6,8 +6,9 @@ class VendorDeviceTreeItem { + Q_DISABLE_COPY(VendorDeviceTreeItem) public: - VendorDeviceTreeItem(int id, const QString &displayString, VendorDeviceTreeItem *parent = 0); + VendorDeviceTreeItem(int id = 0, VendorDeviceTreeItem *parent = 0); ~VendorDeviceTreeItem(); void appendChild(VendorDeviceTreeItem *child); @@ -21,6 +22,8 @@ public: bool parseXml( const QString &filename ); + QPixmap image() const; + private: void parseVendor( QXmlStreamReader *reader ); void parseDevice( QXmlStreamReader *reader, VendorDeviceTreeItem *parent ); @@ -30,6 +33,7 @@ private: int deviceId; QString deviceName; + QString img; VendorDeviceTreeItem *parentItem; }; From 82ef5890abdd1403d6f287dfe7e6514101a65e6e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 22 Dec 2008 15:21:26 +0000 Subject: [PATCH 0697/2215] Styled DeviceWidget and added an edit button --- telldus-gui/TelldusGui/devicemodel.cpp | 46 +++++++++++++++---- telldus-gui/TelldusGui/devicemodel.h | 2 + telldus-gui/TelldusGui/devicewidget.cpp | 20 +++++++- telldus-gui/TelldusGui/devicewidget.h | 6 +-- telldus-gui/TelldusGui/editdevicedialog.cpp | 4 +- telldus-gui/TelldusGui/editdevicedialog.h | 2 + telldus-gui/TelldusGui/telldusgui.qrc | 3 +- .../TelldusGui/vendordevicetreeitem.cpp | 12 ++++- telldus-gui/TelldusGui/vendordevicetreeitem.h | 3 +- 9 files changed, 80 insertions(+), 18 deletions(-) diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index cb557f52..d3df046d 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -1,6 +1,7 @@ #include "devicemodel.h" #include #include +#include #include DeviceModel::DeviceModel(QObject *parent) @@ -18,20 +19,49 @@ int DeviceModel::rowCount(const QModelIndex &) const { } int DeviceModel::columnCount(const QModelIndex &) const { - return 1; + return 2; } QVariant DeviceModel::data(const QModelIndex &index, int role) const { - if (index.column() != 0) { + if (index.column() > 1) { return QVariant(); } - if (role == Qt::DisplayRole) { - int id = deviceId( index ); - char *name = tdGetName( id ); - QString deviceName = QString( name ); - delete name; - return deviceName; + if (index.column() == 0) { + if (role == Qt::DisplayRole) { + return tr("on"); + } else if (role == Qt::DecorationRole) { + return QIcon( ":/images/list-add.png" ); + } else if (role == Qt::TextAlignmentRole) { + return Qt::AlignCenter; + } + } else if (index.column() == 1) { + if (role == Qt::DisplayRole) { + int id = deviceId( index ); + char *name = tdGetName( id ); + QString deviceName = QString( name ); + free( name ); + return deviceName; + } + } + + return QVariant(); +} + +QVariant DeviceModel::headerData ( int section, Qt::Orientation orientation, int role ) const { + if (orientation != Qt::Horizontal) { + return QVariant(); + } + + if (role != Qt::DisplayRole) { + return QVariant(); + } + + switch (section) { + case 0: + return tr("State"); + case 1: + return tr("Device name"); } return QVariant(); diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index 957c5de2..c8fec2e6 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -19,6 +19,8 @@ public: virtual bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() ); + virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; + Device *newDevice() const; private slots: diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index a101ff55..9d584262 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -12,9 +12,14 @@ DeviceWidget::DeviceWidget(QWidget *parent) : QWidget(parent), deviceView(this), addToolButton(this), - removeToolButton(this) + removeToolButton(this), + editToolButton(this) { deviceView.setModel( &model ); + deviceView.resizeColumnsToContents(); + deviceView.resizeRowsToContents(); + deviceView.setAlternatingRowColors( true ); + deviceView.setSelectionBehavior( QAbstractItemView::SelectRows ); connect( &deviceView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(listActivated(const QModelIndex &)) ); QVBoxLayout *layout = new QVBoxLayout(this); @@ -24,11 +29,23 @@ DeviceWidget::DeviceWidget(QWidget *parent) : buttonLayout->setSpacing(0); addToolButton.setIcon( QIcon( ":/images/list-add.png" ) ); + addToolButton.setText( tr("New") ); + addToolButton.setToolButtonStyle( Qt::ToolButtonTextBesideIcon ); connect(&addToolButton, SIGNAL(clicked()), this, SLOT(addDevice())); buttonLayout->addWidget( &addToolButton ); + buttonLayout->addSpacing( 10 ); + + editToolButton.setIcon( QIcon( ":/images/list-edit.png" ) ); + editToolButton.setText( tr("Edit") ); + editToolButton.setToolButtonStyle( Qt::ToolButtonTextBesideIcon ); + editToolButton.setEnabled( false ); + buttonLayout->addWidget( &editToolButton ); + removeToolButton.setIcon( QIcon( ":/images/list-remove.png" ) ); removeToolButton.setEnabled( false ); + removeToolButton.setText( tr("Remove") ); + removeToolButton.setToolButtonStyle( Qt::ToolButtonTextBesideIcon ); connect(&removeToolButton, SIGNAL(clicked()), this, SLOT(deleteDevice())); buttonLayout->addWidget( &removeToolButton ); @@ -80,4 +97,5 @@ void DeviceWidget::deleteDevice() { void DeviceWidget::listActivated(const QModelIndex &) { removeToolButton.setEnabled( true ); + editToolButton.setEnabled( true ); } diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index 703ee76a..b8d8c08d 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -2,7 +2,7 @@ #define DEVICEWIDGET_H #include -#include +#include #include #include "devicemodel.h" @@ -24,8 +24,8 @@ private slots: private: DeviceModel model; - QListView deviceView; - QToolButton addToolButton, removeToolButton; + QTableView deviceView; + QToolButton addToolButton, removeToolButton, editToolButton; }; #endif // DEVICEWIDGET_H diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index abba4dee..028c9618 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -54,7 +54,7 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) nameLayout->addRow(nameLabel, nameLineEdit); addressLayout->addLayout( nameLayout ); - QStackedLayout *settingsLayout = new QStackedLayout; + settingsLayout = new QStackedLayout; QLabel *noDeviceLabel = new QLabel( tr("Choose a device above"), this ); noDeviceLabel->setAlignment( Qt::AlignCenter ); settingsLayout->addWidget( noDeviceLabel ); @@ -88,5 +88,5 @@ void EditDeviceDialog::selectionChanged( const QModelIndex & index ) { } deviceImage->setPixmap( item->image() ); -// qDebug() << "Selection changed" << item->image(); + settingsLayout->setCurrentIndex( item->widget() ); } diff --git a/telldus-gui/TelldusGui/editdevicedialog.h b/telldus-gui/TelldusGui/editdevicedialog.h index 858a22d2..17a6c400 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.h +++ b/telldus-gui/TelldusGui/editdevicedialog.h @@ -8,6 +8,7 @@ class VendorDeviceModel; class DeviceSetting; class QLabel; +class QStackedLayout; class EditDeviceDialog : public QDialog { @@ -21,6 +22,7 @@ private slots: private: VendorDeviceModel *model; + QStackedLayout *settingsLayout; QLabel *deviceImage; QHash deviceSettings; }; diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index 0775cf84..4139bf94 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -2,7 +2,8 @@ data/devices.xml images/list-add.png - images/list-remove.png + images/list-edit.png + images/list-remove.png images/devices/17-356.jpg images/devices/14323.jpg images/devices/14327.jpg diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index e58fbe80..c00d2645 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -7,6 +7,7 @@ VendorDeviceTreeItem::VendorDeviceTreeItem(int id, VendorDeviceTreeItem *parent) :deviceId(id), + settingsWidget(0), parentItem(parent) { } @@ -65,6 +66,11 @@ QPixmap VendorDeviceTreeItem::image() const { return image; } +int VendorDeviceTreeItem::widget() const { + return settingsWidget; +} + + bool VendorDeviceTreeItem::parseXml( const QString &filename ) { QFile file(filename); if (!file.open(QFile::ReadOnly | QFile::Text)) { @@ -134,8 +140,10 @@ void VendorDeviceTreeItem::parseVendor( QXmlStreamReader *reader ) { } void VendorDeviceTreeItem::parseDevice( QXmlStreamReader *reader, VendorDeviceTreeItem *parent ) { - VendorDeviceTreeItem *item = new VendorDeviceTreeItem(reader->attributes().value("id").toString().toInt(), parent); - item->img = reader->attributes().value("image").toString(); + QXmlStreamAttributes attributes = reader->attributes(); + VendorDeviceTreeItem *item = new VendorDeviceTreeItem(attributes.value("id").toString().toInt(), parent); + item->img = attributes.value("image").toString(); + item->settingsWidget = attributes.value("widget").toString().toInt(); item->deviceName = reader->readElementText(); //This call must be the last one because it clears the attribute-list parent->appendChild(item); diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.h b/telldus-gui/TelldusGui/vendordevicetreeitem.h index f774875b..a46ace66 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.h +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.h @@ -23,6 +23,7 @@ public: bool parseXml( const QString &filename ); QPixmap image() const; + int widget() const; private: void parseVendor( QXmlStreamReader *reader ); @@ -31,7 +32,7 @@ private: QList childItems; - int deviceId; + int deviceId, settingsWidget; QString deviceName; QString img; VendorDeviceTreeItem *parentItem; From ff74c0f387b856db4d2c428fe7889595fcddb7ec Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 29 Dec 2008 14:02:59 +0000 Subject: [PATCH 0698/2215] Added image edit --- telldus-gui/TelldusGui/images/list-edit.png | Bin 0 -> 2129 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/list-edit.png diff --git a/telldus-gui/TelldusGui/images/list-edit.png b/telldus-gui/TelldusGui/images/list-edit.png new file mode 100644 index 0000000000000000000000000000000000000000..6e52db7cfd482e228dae640a7717ea1dcaf523e8 GIT binary patch literal 2129 zcmV-X2(I^uP)vW`Lad_VL}O~L?M$bw z+VP81m0&@1Ql}}fVs*6EWJrveWIAoav|0^Dh=!q^#+pvjDB^_$6}c_!!on^rd+w(n z!e&+lv6Bz|(r4zG_kGWKpXdL3p7)(I2l&7JkByjaLrqQ9a+;;z2S^+s>j-1CZ5AAhGv1NDoNlAXT)3gF0*BPNxQ0%@tUk(av={y+e&w_7;xpx4a>g@S_z z4-QNxe&ocv`xRBGp(v_b5TxaYN_Rerd`~_rxU8&flqRW_-93-S{eghuNN`~7n)TYO z%{JUo9>uKw?UYonfedSDtt~>$w2{ptQ97@0=*D`sB)G zQdL!6k|bm;$fgW>!-DFguNO{Q^^tc>4+qAZOlI@eoV-N_R--|J!$H{{j%ZRPZ`Rh< zGE)LnRaM12`K)4p#peM0qA2zP0MGMCO-(bfv}Vhs)H>>``1ttztlS&}MNl2!*#ojURT$mi9^s&fHYXqpbvG!2p@VKf>Enx<1G(zWg9!V6%#|k)HTdOBH zwt4=%G*Oi$#_#hX6dFfgpNAk6Wm8$%&e5m36}dQmqNXx^er8#2&O(YLAHN>5EF%~U zLQxbj3F$%f*=S;k_3vP;Pd&=+S&@6%?4YX4Gj(T952cn z6(;szUgo@ls3;?Q<5v6l@UZ{Qvc20&Clie{Dss`()D$dQx5n*qwXJg`IB2WY3Wj08 zFbrf_hCeU@MOGk+A_(GZ_VkPl+VybYM_K9Lam3l8+15K9A@AVG+vWSVmrN)AR0qO# z^r&+a&C+L#2BR*f;QQU) zGv)hs?0z2cDFJ}5zhn;{+)Gy}B92suF^19Kl;zMIieW!nTeRLF@FH>RUMDOT3lbgi zxYPC!?w&4zSB7REdi7BEw+5KZlGazH$C|MtBZ1nzV&ObC#$v#%BsR8&-WpC{+EpW?8kZm8a_Wto4yvTntmkS3M--T4j}Ez#(>-wh}-(&r{2 zAt8~>&dQC}88u%zoleX1^2JqJbqaocgst1=THCvilV@A9Fmh$NPoZ|C5rso{QQFVo12^Esq#Pb2xhIXUPY1A zmG!Ih^$J13>l=gneha$qeva{A5ThYJ=nabdE;oM6DXIcRQ9zO;0)YTtC|FL%+H5&7 z)*1D6b#+q~Iwe3_an&w{r9RqRyv(H4>4-j$AH#k35DJbU!I6lLPOrf8!j1E%51v*; z>E(vTOS~*g004p@5DW%UxMCG+Hd|H>c>DgOs_LW{{waXDFa6eU+iF0T581o5HWZdnEly}zu7f^DB%xy*AM2b!k8fmrq88VyA=KRx;TV+WoD_@*r>#m*J1hWRLS zewsNeBLy?`6lO+gaqi=0bawS1F4hWxvPf<1y)N)r8Yv!W$4?&JMySMlt5>gOS%yU* z5WwKzARG<{8n0aDL|(QZIB;P2sSc=6SH;<4Oskj9Lq?JrX){eY*LWSBk9uG>nn3ET zxYyA)DiBi9RN??ovSMMcRZsVth}2$W7OLxxN` z8eRPXoVoA?Iv;j`W;BRRNJVQ~cZeVJZtbZ*pGw0VXU7V@q1N{J_he8?f20ssU6;>5@k08C*302 Date: Mon, 29 Dec 2008 19:14:12 +0000 Subject: [PATCH 0699/2215] Renamed the device parameter 'vendor' to 'protocol' --- .../settings/TelldusSettings.cpp | 24 +++++++++---------- .../settings/TelldusSettings.h | 4 ++-- .../settings/TelldusSettingsConfuse.cpp | 2 +- .../driver/libtelldus-core/telldus-core.cpp | 8 +++---- .../driver/libtelldus-core/telldus-core.h | 4 ++-- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp index fdc56722..ffd20a61 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp @@ -15,32 +15,32 @@ Device* TelldusSettings::getDevice(int intDeviceId){ Device* dev = NULL; try{ - char* vendor = getVendor(intDeviceId); - if (vendor == NULL) { + char* protocol = getProtocol(intDeviceId); + if (protocol == NULL) { return NULL; } //each new brand must be added here - if (strcmp(vendor, "Nexa") == 0){ + if (strcmp(protocol, "Nexa") == 0){ char *strHouse = getArgument(intDeviceId, "nexa_house"); char *strCode = getArgument(intDeviceId, "nexa_unit"); dev = new DeviceNexa(strHouse, strCode); free(strHouse); free(strCode); - } else if (strcmp(vendor, "Waveman") == 0) { + } else if (strcmp(protocol, "Waveman") == 0) { char *strHouse = getArgument(intDeviceId, "nexa_house"); char *strCode = getArgument(intDeviceId, "nexa_unit"); dev = new DeviceWaveman(strHouse, strCode); free(strHouse); free(strCode); - } else if (strcmp(vendor, "Sartano") == 0) { + } else if (strcmp(protocol, "Sartano") == 0) { char *strCode = getArgument(intDeviceId, "sartano_code"); dev = new DeviceSartano(strCode); free(strCode); - } else if (strcmp(vendor, "Ikea") == 0) { + } else if (strcmp(protocol, "Ikea") == 0) { char *strSystem = getArgument(intDeviceId, "ikea_system"); char *strUnits = getArgument(intDeviceId, "ikea_units"); char *strFade = getArgument(intDeviceId, "ikea_fade"); @@ -50,10 +50,10 @@ Device* TelldusSettings::getDevice(int intDeviceId){ free(strFade); } else { - free(vendor); + free(protocol); return NULL; } - free(vendor); + free(protocol); #ifdef _LINUX dev->setDevice( getSetting("deviceNode") ); @@ -83,15 +83,15 @@ bool TelldusSettings::setName(int intDeviceId, const char* strNewName){ /* * Get the device vendor */ -char* TelldusSettings::getVendor(int intDeviceId){ - return getStringSetting(intDeviceId, "vendor", false); +char* TelldusSettings::getProtocol(int intDeviceId){ + return getStringSetting(intDeviceId, "protocol", false); } /* * Set the device vendor */ -bool TelldusSettings::setVendor(int intDeviceId, const char* strVendor){ - return setStringSetting(intDeviceId, "vendor", strVendor, false); +bool TelldusSettings::setProtocol(int intDeviceId, const char* strVendor){ + return setStringSetting(intDeviceId, "protocol", strVendor, false); } /* diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h index d9d24b22..9dadc71e 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h @@ -15,8 +15,8 @@ public: Device* getDevice(int intDeviceId); char* getName(int intDeviceId); bool setName(int intDeviceId, const char* strNewName); - char* getVendor(int intDeviceId); - bool setVendor(int intDeviceId, const char* strVendor); + char* getProtocol(int intDeviceId); + bool setProtocol(int intDeviceId, const char* strVendor); int getModel(int intDeviceId); bool setModel(int intDeviceId, int intModel); char* getArgument(int intDeviceId, const char *strName); diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp index 02c1d73e..59d86365 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp @@ -248,7 +248,7 @@ bool readConfig(cfg_t **cfg) { cfg_opt_t device_opts[] = { CFG_INT("id", -1, CFGF_NONE), CFG_STR("name", "Unnamed", CFGF_NONE), - CFG_STR("vendor", "Nexa", CFGF_NONE), + CFG_STR("protocol", "Nexa", CFGF_NONE), CFG_INT("model", 1, CFGF_NONE), CFG_SEC("parameters", parameter_opts, CFGF_NONE), CFG_END() diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index bbd280d1..e0cecfaf 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -287,11 +287,11 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ return blnSuccess; } -char* WINAPI tdGetVendor(int intDeviceId){ +char* WINAPI tdGetProtocol(int intDeviceId){ char* strReturn = ""; try{ TelldusSettings ts; - strReturn = ts.getVendor(intDeviceId); + strReturn = ts.getProtocol(intDeviceId); #ifdef _WINDOWS strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); #endif @@ -303,11 +303,11 @@ char* WINAPI tdGetVendor(int intDeviceId){ return strReturn; } -bool WINAPI tdSetVendor(int intDeviceId, const char* strVendor){ +bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ bool blnSuccess = false; try{ TelldusSettings ts; - blnSuccess = ts.setVendor(intDeviceId, strVendor); + blnSuccess = ts.setProtocol(intDeviceId, strProtocol); } catch(exception e){ blnSuccess = false; diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index eea76199..38cb86ec 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -37,8 +37,8 @@ extern "C" { TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); - TELLSTICK_API char * WINAPI tdGetVendor(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetVendor(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); TELLSTICK_API int WINAPI tdGetModel(int intDeviceId); TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, int intModel); From d7751732ef4a108e576c045e5cb8f20a3bc252d3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 29 Dec 2008 19:18:48 +0000 Subject: [PATCH 0700/2215] Made it possible to edit the device name and model for a device --- telldus-gui/TelldusGui/device.cpp | 74 ++++++++++++++++++- telldus-gui/TelldusGui/device.h | 16 +++- telldus-gui/TelldusGui/devicemodel.cpp | 15 ++-- telldus-gui/TelldusGui/devicemodel.h | 1 + telldus-gui/TelldusGui/devicewidget.cpp | 16 +++- telldus-gui/TelldusGui/devicewidget.h | 1 + telldus-gui/TelldusGui/editdevicedialog.cpp | 57 ++++++++++++-- telldus-gui/TelldusGui/editdevicedialog.h | 9 ++- telldus-gui/TelldusGui/vendordevicemodel.cpp | 12 ++- telldus-gui/TelldusGui/vendordevicemodel.h | 4 +- .../TelldusGui/vendordevicetreeitem.cpp | 25 +++++++ telldus-gui/TelldusGui/vendordevicetreeitem.h | 7 +- 12 files changed, 215 insertions(+), 22 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 23f42bf9..1b3cde46 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -1,16 +1,68 @@ #include "device.h" #include "telldus-core.h" +#include QHash Device::devices; Device::Device(int id) - :p_id(id) + :p_id(id), + p_model(0), + p_name(""), + p_protocol(""), + p_modelChanged(false), + p_nameChanged(false), + p_protocolChanged(false) { + if (id > 0) { + char *name = tdGetName(id); + p_name = QString::fromLocal8Bit( name ); + free( name ); + + p_model = tdGetModel(id); + + char *protocol = tdGetProtocol(id); + p_protocol = QString::fromUtf8( protocol ); + free( protocol ); + } } Device::~Device() { } +void Device::setModel( int model ) { + p_model = model; + p_modelChanged = true; +} + +int Device::model() { + return p_model; +} + +void Device::setName( const QString & name ) { + if (name.compare(p_name, Qt::CaseSensitive) == 0) { + return; + } + p_name = name; + p_nameChanged = true; +} + +const QString &Device::name() { + return p_name; +} + +void Device::setProtocol( const QString & protocol ) { + if (protocol.compare(p_protocol, Qt::CaseSensitive) == 0) { + return; + } + p_protocol = protocol; + p_protocolChanged = true; +} + +const QString &Device::protocol() { + return p_protocol; +} + + Device *Device::getDevice( int id ) { if (devices.contains(id)) { @@ -26,8 +78,28 @@ Device *Device::newDevice( ) { } void Device::save() { + bool deviceIsAdded = false; if (p_id == 0) { //This is a new device p_id = tdAddDevice(); + deviceIsAdded = true; + } + + if (p_nameChanged) { + tdSetName(p_id, p_name.toLocal8Bit()); + p_nameChanged = false; + } + + if (p_modelChanged) { + tdSetModel(p_id, p_model); + p_modelChanged = false; + } + + if (p_protocolChanged) { + tdSetProtocol(p_id, p_protocol.toUtf8()); + p_protocolChanged = false; + } + + if (deviceIsAdded) { emit deviceAdded(p_id); } } diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index f0b06c75..fad98df7 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -3,6 +3,7 @@ #include #include +#include class Device : public QObject { @@ -10,11 +11,20 @@ class Device : public QObject Q_DISABLE_COPY(Device) public: - virtual ~Device(); + ~Device(); static Device *getDevice( int id ); static Device *newDevice( ); + void setModel( int model ); + int model(); + + void setName( const QString & name ); + const QString &name(); + + void setProtocol( const QString & protocol ); + const QString &protocol(); + public slots: void save(); @@ -26,7 +36,9 @@ private: static QHash devices; QHash p_settings; - int p_id; + int p_id, p_model; + QString p_name, p_protocol; + bool p_modelChanged, p_nameChanged, p_protocolChanged; }; #endif // DEVICE_H diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index d3df046d..ecb19f2f 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -37,11 +37,8 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const { } } else if (index.column() == 1) { if (role == Qt::DisplayRole) { - int id = deviceId( index ); - char *name = tdGetName( id ); - QString deviceName = QString( name ); - free( name ); - return deviceName; + Device *device = this->device( index ); + return device->name(); } } @@ -84,6 +81,10 @@ bool DeviceModel::removeRows ( int row, int count, const QModelIndex & parent ) return true; } +Device *DeviceModel::device( const QModelIndex &index ) const { + return Device::getDevice( deviceId( index ) ); +} + Device *DeviceModel::newDevice() const { Device *device = Device::newDevice(); connect(device, SIGNAL(deviceAdded(int)), this, SLOT(deviceAdded(int))); @@ -91,9 +92,9 @@ Device *DeviceModel::newDevice() const { } void DeviceModel::deviceAdded( int id ) { + Q_UNUSED(id); int deviceCount = tdGetNumberOfDevices(); - beginInsertRows( QModelIndex(), deviceCount - 1, deviceCount ); - qDebug() << "Ny enhet: " << id; + beginInsertRows( QModelIndex(), deviceCount, deviceCount ); endInsertRows(); } diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index c8fec2e6..0dd4b462 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -22,6 +22,7 @@ public: virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; Device *newDevice() const; + Device *device( const QModelIndex & ) const; private slots: void deviceAdded( int id ); diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 9d584262..dc5e6ea4 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -40,6 +40,7 @@ DeviceWidget::DeviceWidget(QWidget *parent) : editToolButton.setText( tr("Edit") ); editToolButton.setToolButtonStyle( Qt::ToolButtonTextBesideIcon ); editToolButton.setEnabled( false ); + connect(&editToolButton, SIGNAL(clicked()), this, SLOT(editDevice())); buttonLayout->addWidget( &editToolButton ); removeToolButton.setIcon( QIcon( ":/images/list-remove.png" ) ); @@ -72,9 +73,9 @@ void DeviceWidget::changeEvent(QEvent *e) void DeviceWidget::addDevice() { Device *device = model.newDevice(); - EditDeviceDialog *dialog = new EditDeviceDialog( ); + EditDeviceDialog *dialog = new EditDeviceDialog(device); if (dialog->exec() == QDialog::Accepted) { - //device->save(); + device->save(); } else { delete device; } @@ -95,6 +96,17 @@ void DeviceWidget::deleteDevice() { } } +void DeviceWidget::editDevice() { + Device *device = model.device( deviceView.currentIndex() ); + + EditDeviceDialog *dialog = new EditDeviceDialog( device ); + if (dialog->exec() == QDialog::Accepted) { + device->save(); + } + + delete dialog; +} + void DeviceWidget::listActivated(const QModelIndex &) { removeToolButton.setEnabled( true ); editToolButton.setEnabled( true ); diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index b8d8c08d..55962050 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -21,6 +21,7 @@ private slots: void listActivated(const QModelIndex &); void addDevice(); void deleteDevice(); + void editDevice(); private: DeviceModel model; diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 028c9618..92bba5b9 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -1,6 +1,7 @@ #include "editdevicedialog.h" #include "vendordevicemodel.h" #include "vendordevicetreeitem.h" +#include "device.h" #include "devicesettingnexa.h" @@ -13,12 +14,18 @@ #include #include #include +#include #include -EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) +EditDeviceDialog::EditDeviceDialog(Device *d, QWidget *parent, Qt::WFlags flags) :QDialog(parent, flags), - model(new VendorDeviceModel(this)) + model(new VendorDeviceModel(this)), + device(d), + settingsLayout(0), + deviceImage(0), + nameLineEdit(0), + selection(0) { QVBoxLayout *layout = new QVBoxLayout(this); @@ -26,7 +33,8 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) QTreeView *deviceView = new QTreeView(this); deviceView->setModel( model ); - QItemSelectionModel *selection = deviceView->selectionModel(); + + selection = deviceView->selectionModel(); connect( selection, SIGNAL( currentChanged(const QModelIndex, const QModelIndex &) ), this, SLOT(selectionChanged( const QModelIndex & ) )); deviceLayout->addWidget(deviceView); @@ -48,7 +56,7 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) QLabel *nameLabel = new QLabel(this); nameLabel->setText( tr("&Name:") ); - QLineEdit *nameLineEdit = new QLineEdit( this ); + nameLineEdit = new QLineEdit(device->name(), this ); nameLabel->setBuddy(nameLineEdit); nameLayout->addRow(nameLabel, nameLineEdit); @@ -67,7 +75,7 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) QDialogButtonBox *buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons( QDialogButtonBox::Save | QDialogButtonBox::Cancel ); - connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(okClicked())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); layout->addWidget(buttonBox); @@ -75,6 +83,13 @@ EditDeviceDialog::EditDeviceDialog(QWidget *parent, Qt::WFlags flags) foreach( DeviceSetting *s, deviceSettings ) { settingsLayout->addWidget( s ); } + + QModelIndex index = model->index( device ); + if (index.isValid()) { + deviceView->expand( index.parent() ); + selection->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect ); + } + } EditDeviceDialog::~EditDeviceDialog() { @@ -82,7 +97,7 @@ EditDeviceDialog::~EditDeviceDialog() { } void EditDeviceDialog::selectionChanged( const QModelIndex & index ) { - const VendorDeviceTreeItem* const item = model->item(index); + VendorDeviceTreeItem* const item = model->item(index); if (!item) { return; } @@ -90,3 +105,33 @@ void EditDeviceDialog::selectionChanged( const QModelIndex & index ) { deviceImage->setPixmap( item->image() ); settingsLayout->setCurrentIndex( item->widget() ); } + +void EditDeviceDialog::okClicked() { + VendorDeviceTreeItem* const item = model->item( selection->currentIndex() ); + if (!item || !item->isDevice()) { + QMessageBox msgBox; + msgBox.setText( tr("You must choose a device") ); + msgBox.setInformativeText( tr("Please select the device you have.") ); + msgBox.setIcon( QMessageBox::Critical ); + msgBox.setStandardButtons( QMessageBox::Ok ); + msgBox.exec(); + return; + } + + if (nameLineEdit->text().trimmed() == "") { + QMessageBox msgBox; + msgBox.setText( tr("The device must have a name.") ); + msgBox.setInformativeText( tr("Please fill in a name in the field under 'Name'") ); + msgBox.setIcon( QMessageBox::Critical ); + msgBox.setStandardButtons( QMessageBox::Ok ); + msgBox.exec(); + nameLineEdit->setFocus(); + return; + } + + device->setName( nameLineEdit->text().trimmed() ); + device->setModel( item->deviceModel() ); + device->setProtocol( item->deviceProtocol() ); + + this->accept(); +} diff --git a/telldus-gui/TelldusGui/editdevicedialog.h b/telldus-gui/TelldusGui/editdevicedialog.h index 17a6c400..bc19ad0b 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.h +++ b/telldus-gui/TelldusGui/editdevicedialog.h @@ -7,23 +7,30 @@ class VendorDeviceModel; class DeviceSetting; +class Device; class QLabel; +class QLineEdit; class QStackedLayout; +class QItemSelectionModel; class EditDeviceDialog : public QDialog { Q_OBJECT public: - EditDeviceDialog(QWidget *parent = 0, Qt::WFlags flags = 0); + EditDeviceDialog(Device *device, QWidget *parent = 0, Qt::WFlags flags = 0); virtual ~EditDeviceDialog(); private slots: void selectionChanged( const QModelIndex & ); + void okClicked(); private: VendorDeviceModel *model; + Device *device; QStackedLayout *settingsLayout; QLabel *deviceImage; + QLineEdit *nameLineEdit; + QItemSelectionModel *selection; QHash deviceSettings; }; diff --git a/telldus-gui/TelldusGui/vendordevicemodel.cpp b/telldus-gui/TelldusGui/vendordevicemodel.cpp index 27947f22..fa2d980f 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.cpp +++ b/telldus-gui/TelldusGui/vendordevicemodel.cpp @@ -1,5 +1,6 @@ #include "vendordevicemodel.h" #include "vendordevicetreeitem.h" +#include "device.h" VendorDeviceModel::VendorDeviceModel(QObject *parent) :QAbstractItemModel(parent), @@ -69,6 +70,15 @@ QModelIndex VendorDeviceModel::index(int row, int column, const QModelIndex &par return QModelIndex(); } +QModelIndex VendorDeviceModel::index(Device *device) const { + VendorDeviceTreeItem *item = rootItem->findByDeviceId( device->model() ); + if (!item) { + return QModelIndex(); + } + + return createIndex( item->row(), 0, item ); +} + QModelIndex VendorDeviceModel::parent(const QModelIndex &index) const { if (!index.isValid()) { return QModelIndex(); @@ -99,7 +109,7 @@ int VendorDeviceModel::rowCount(const QModelIndex &parent) const { return parentItem->childCount(); } -const VendorDeviceTreeItem* const VendorDeviceModel::item( const QModelIndex &index ) const { +VendorDeviceTreeItem* VendorDeviceModel::item( const QModelIndex &index ) const { if (!index.isValid()) { return 0; } diff --git a/telldus-gui/TelldusGui/vendordevicemodel.h b/telldus-gui/TelldusGui/vendordevicemodel.h index faf54706..592eaac8 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.h +++ b/telldus-gui/TelldusGui/vendordevicemodel.h @@ -5,6 +5,7 @@ #include class VendorDeviceTreeItem; +class Device; class VendorDeviceModel : public QAbstractItemModel { @@ -18,10 +19,11 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; QVariant headerData(int section, Qt::Orientation orientation, int role) const; QModelIndex index(int row, int column, const QModelIndex &parent) const; + QModelIndex index(Device *device) const; int rowCount(const QModelIndex &parent) const; QModelIndex parent(const QModelIndex &index) const; - const VendorDeviceTreeItem* const item( const QModelIndex &index ) const; + VendorDeviceTreeItem* item( const QModelIndex &index ) const; private: VendorDeviceTreeItem *rootItem; diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index c00d2645..332ea330 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -70,6 +70,30 @@ int VendorDeviceTreeItem::widget() const { return settingsWidget; } +bool VendorDeviceTreeItem::isDevice() const { + return deviceId > 0; +} + +int VendorDeviceTreeItem::deviceModel() const { + return deviceId; +} + +const QString &VendorDeviceTreeItem::deviceProtocol() const { + return protocol; +} + +VendorDeviceTreeItem * VendorDeviceTreeItem::findByDeviceId( int deviceId ) const { + foreach( VendorDeviceTreeItem *item, childItems ) { + if (item->deviceId == deviceId) { + return item; + } + VendorDeviceTreeItem *i = item->findByDeviceId( deviceId ); + if (i) { + return i; + } + } + return 0; +} bool VendorDeviceTreeItem::parseXml( const QString &filename ) { QFile file(filename); @@ -144,6 +168,7 @@ void VendorDeviceTreeItem::parseDevice( QXmlStreamReader *reader, VendorDeviceTr VendorDeviceTreeItem *item = new VendorDeviceTreeItem(attributes.value("id").toString().toInt(), parent); item->img = attributes.value("image").toString(); item->settingsWidget = attributes.value("widget").toString().toInt(); + item->protocol = attributes.value("protocol").toString(); item->deviceName = reader->readElementText(); //This call must be the last one because it clears the attribute-list parent->appendChild(item); diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.h b/telldus-gui/TelldusGui/vendordevicetreeitem.h index a46ace66..f822677a 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.h +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.h @@ -24,6 +24,11 @@ public: QPixmap image() const; int widget() const; + bool isDevice() const; + int deviceModel() const; + const QString &deviceProtocol() const; + + VendorDeviceTreeItem *findByDeviceId( int deviceId ) const; private: void parseVendor( QXmlStreamReader *reader ); @@ -33,7 +38,7 @@ private: QList childItems; int deviceId, settingsWidget; - QString deviceName; + QString deviceName, protocol; QString img; VendorDeviceTreeItem *parentItem; }; From 79356beb32b7869293a818e2967fd59cfcf9383a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 29 Dec 2008 20:22:45 +0000 Subject: [PATCH 0701/2215] Added Sparkle to Telldus Center --- telldus-gui/TelldusCenter/AutoUpdater.cpp | 9 +++++ telldus-gui/TelldusCenter/AutoUpdater.h | 11 ++++++ telldus-gui/TelldusCenter/CocoaInitializer.h | 19 ++++++++++ telldus-gui/TelldusCenter/CocoaInitializer.mm | 27 ++++++++++++++ telldus-gui/TelldusCenter/Info.plist | 24 ++++++++++++ .../TelldusCenter/SparkleAutoUpdater.h | 25 +++++++++++++ .../TelldusCenter/SparkleAutoUpdater.mm | 37 +++++++++++++++++++ telldus-gui/TelldusCenter/TelldusCenter.pro | 17 +++++++-- telldus-gui/TelldusCenter/main.cpp | 14 +++++++ 9 files changed, 179 insertions(+), 4 deletions(-) create mode 100644 telldus-gui/TelldusCenter/AutoUpdater.cpp create mode 100644 telldus-gui/TelldusCenter/AutoUpdater.h create mode 100644 telldus-gui/TelldusCenter/CocoaInitializer.h create mode 100644 telldus-gui/TelldusCenter/CocoaInitializer.mm create mode 100644 telldus-gui/TelldusCenter/Info.plist create mode 100644 telldus-gui/TelldusCenter/SparkleAutoUpdater.h create mode 100644 telldus-gui/TelldusCenter/SparkleAutoUpdater.mm diff --git a/telldus-gui/TelldusCenter/AutoUpdater.cpp b/telldus-gui/TelldusCenter/AutoUpdater.cpp new file mode 100644 index 00000000..9b94ad32 --- /dev/null +++ b/telldus-gui/TelldusCenter/AutoUpdater.cpp @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2008 Remko Troncon + */ + +#include "AutoUpdater.h" + +AutoUpdater::~AutoUpdater() +{ +} diff --git a/telldus-gui/TelldusCenter/AutoUpdater.h b/telldus-gui/TelldusCenter/AutoUpdater.h new file mode 100644 index 00000000..130725d0 --- /dev/null +++ b/telldus-gui/TelldusCenter/AutoUpdater.h @@ -0,0 +1,11 @@ +#ifndef AUTOUPDATER_H +#define AUTOUPDATER_H + +class AutoUpdater +{ +public: + virtual ~AutoUpdater(); + virtual void checkForUpdates() = 0; +}; + +#endif diff --git a/telldus-gui/TelldusCenter/CocoaInitializer.h b/telldus-gui/TelldusCenter/CocoaInitializer.h new file mode 100644 index 00000000..4761a973 --- /dev/null +++ b/telldus-gui/TelldusCenter/CocoaInitializer.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2008 Remko Troncon + */ + +#ifndef COCOAINITIALIZER_H +#define COCOAINITIALIZER_H + +class CocoaInitializer +{ + public: + CocoaInitializer(); + ~CocoaInitializer(); + + private: + class Private; + Private* d; +}; + +#endif diff --git a/telldus-gui/TelldusCenter/CocoaInitializer.mm b/telldus-gui/TelldusCenter/CocoaInitializer.mm new file mode 100644 index 00000000..fc1916d4 --- /dev/null +++ b/telldus-gui/TelldusCenter/CocoaInitializer.mm @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2008 Remko Troncon + */ + +#include "CocoaInitializer.h" + +#include +#include +#include + +class CocoaInitializer::Private { +public: + NSAutoreleasePool* autoReleasePool_; +}; + +CocoaInitializer::CocoaInitializer() +{ + d = new CocoaInitializer::Private(); + NSApplicationLoad(); + d->autoReleasePool_ = [[NSAutoreleasePool alloc] init]; +} + +CocoaInitializer::~CocoaInitializer() +{ + [d->autoReleasePool_ release]; + delete d; +} diff --git a/telldus-gui/TelldusCenter/Info.plist b/telldus-gui/TelldusCenter/Info.plist new file mode 100644 index 00000000..5fd55514 --- /dev/null +++ b/telldus-gui/TelldusCenter/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleIconFile + + CFBundlePackageType + APPL + CFBundleSignature + tellduscenter + CFBundleExecutable + TelldusCenter + CFBundleIdentifier + com.telldus.center + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Telldus Center + CFBundleShortVersionString + Telldus Center 1.3.0 + CFBundleVersion + 1.3.0 + + diff --git a/telldus-gui/TelldusCenter/SparkleAutoUpdater.h b/telldus-gui/TelldusCenter/SparkleAutoUpdater.h new file mode 100644 index 00000000..eba96a9f --- /dev/null +++ b/telldus-gui/TelldusCenter/SparkleAutoUpdater.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2008 Remko Troncon + */ + +#ifndef SPARKLEAUTOUPDATER_H +#define SPARKLEAUTOUPDATER_H + +#include + +#include "AutoUpdater.h" + +class SparkleAutoUpdater : public AutoUpdater +{ +public: + SparkleAutoUpdater(const QString& url); + ~SparkleAutoUpdater(); + + void checkForUpdates(); + +private: + class Private; + Private* d; +}; + +#endif diff --git a/telldus-gui/TelldusCenter/SparkleAutoUpdater.mm b/telldus-gui/TelldusCenter/SparkleAutoUpdater.mm new file mode 100644 index 00000000..82d2afe9 --- /dev/null +++ b/telldus-gui/TelldusCenter/SparkleAutoUpdater.mm @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 Remko Troncon + */ + +#include "SparkleAutoUpdater.h" + +#include +#include + +class SparkleAutoUpdater::Private +{ +public: + SUUpdater* updater; +}; + +SparkleAutoUpdater::SparkleAutoUpdater(const QString& aUrl) +{ + d = new Private; + + d->updater = [SUUpdater sharedUpdater]; + [d->updater retain]; + + NSURL* url = [NSURL URLWithString: + [NSString stringWithUTF8String: aUrl.toUtf8().data()]]; + [d->updater setFeedURL: url]; +} + +SparkleAutoUpdater::~SparkleAutoUpdater() +{ + [d->updater release]; + delete d; +} + +void SparkleAutoUpdater::checkForUpdates() +{ + [d->updater checkForUpdatesInBackground]; +} diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index 510b8376..f006cf01 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -5,11 +5,20 @@ TARGET = TelldusCenter TEMPLATE = app SOURCES += main.cpp \ mainwindow.cpp \ - tellduscenterapplication.cpp + tellduscenterapplication.cpp \ + autoupdater.cpp HEADERS += mainwindow.h \ - tellduscenterapplication.h + tellduscenterapplication.h \ + autoupdater.h \ + CocoaInitializer.h FORMS += RESOURCES += resource.qrc -macx:LIBS += -lTelldusGui \ - -L../TelldusGui +macx { + HEADERS += sparkleautoupdater.h + LIBS += -framework TelldusGui -framework Sparkle + OBJECTIVE_SOURCES += SparkleAutoUpdater.mm \ + CocoaInitializer.mm + QMAKE_INFO_PLIST = Info.plist +} !macx:LIBS += -ltelldus-gui +VERSION = 1.3.0 diff --git a/telldus-gui/TelldusCenter/main.cpp b/telldus-gui/TelldusCenter/main.cpp index cdda2ee0..75aaa40d 100644 --- a/telldus-gui/TelldusCenter/main.cpp +++ b/telldus-gui/TelldusCenter/main.cpp @@ -1,6 +1,11 @@ #include "tellduscenterapplication.h" #include "mainwindow.h" +#ifdef Q_WS_MAC +#include "CocoaInitializer.h" +#include "SparkleAutoUpdater.h" +#endif + int main(int argc, char *argv[]) { Q_INIT_RESOURCE( resource ); @@ -10,5 +15,14 @@ int main(int argc, char *argv[]) MainWindow *w = new MainWindow(); w->show(); + AutoUpdater* updater = 0; +#ifdef Q_WS_MAC + CocoaInitializer initializer; + updater = new SparkleAutoUpdater("file:///Users/micke/Documents/dev/appcast.xml"); +#endif + if (updater) { + //updater->checkForUpdates(); + } + return application.exec(); } From bd71667cadc1c3a34eacaf8bcb464b38b6a08bd6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 29 Dec 2008 20:23:45 +0000 Subject: [PATCH 0702/2215] Changed telldus-gui to build as a framework on Mac OS X --- telldus-gui/TelldusGui/TelldusGui.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 36193328..350841b1 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -27,6 +27,7 @@ macx { telldus-core ICON = images/telldussetup.icns TARGET = TelldusGui + CONFIG += lib_bundle } !macx { LIBS += -l \ From a50114351beab921fcd3f7832c3ad46db723767f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 29 Dec 2008 23:44:12 +0000 Subject: [PATCH 0703/2215] Changed the target name for telldus-core on Mac OS X --- .../driver/libtelldus-core/CMakeLists.txt | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 3be4998f..1a39f9bd 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -1,4 +1,3 @@ - SET( telldus-core_SRCS Device.cpp DeviceIkea.cpp @@ -14,6 +13,7 @@ SET( telldus-core_HDRS ) IF (APPLE) + SET( telldus-core_TARGET TelldusCore ) SET( telldus-core_SRCS ${telldus-core_SRCS} win/Device.cpp @@ -22,7 +22,8 @@ IF (APPLE) ADD_DEFINITIONS( -D_MACOSX ) -ELSE (APPLE) +ELSE (APPLE) + SET( telldus-core_TARGET telldus-core ) SET( telldus-core_SRCS ${telldus-core_SRCS} linux/Device.cpp @@ -34,36 +35,37 @@ ELSE (APPLE) ENDIF (APPLE) -ADD_LIBRARY(telldus-core SHARED +ADD_LIBRARY(${telldus-core_TARGET} SHARED ${telldus-core_SRCS} ${telldus-core_HDRS} ) -SET_PROPERTY(TARGET telldus-core +SET_PROPERTY(TARGET ${telldus-core_TARGET} PROPERTY PUBLIC_HEADER {$telldus-core_HDRS} ) IF (APPLE) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) + FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) - TARGET_LINK_LIBRARIES(telldus-core + TARGET_LINK_LIBRARIES(${telldus-core_TARGET} ${COREFOUNDATION_LIBRARY} - ftd2xx + ${FTD2XX_LIBRARY} ) - SET_PROPERTY(TARGET telldus-core + SET_PROPERTY(TARGET ${telldus-core_TARGET} PROPERTY FRAMEWORK TRUE ) ELSE (APPLE) - TARGET_LINK_LIBRARIES(telldus-core + TARGET_LINK_LIBRARIES(${telldus-core_TARGET} confuse ) ENDIF (APPLE) -INSTALL(TARGETS telldus-core +INSTALL(TARGETS ${telldus-core_TARGET} DESTINATION lib - PUBLIC_HEADER DESTINATION ${HEADER_DIR} +# PUBLIC_HEADER DESTINATION ${HEADER_DIR} ) SET(SYSCONF_INSTALL_DIR @@ -78,3 +80,4 @@ IF (UNIX) DESTINATION ${SYSCONF_INSTALL_DIR} ) ENDIF (UNIX) + From 3890fb1bc48e0a5d84780f8ff4f02c88ba615471 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 30 Dec 2008 11:03:58 +0000 Subject: [PATCH 0704/2215] Small cosmetic changes to the list of devices in DeviceWidget --- telldus-gui/TelldusGui/devicewidget.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index dc5e6ea4..cf6bdd91 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "editdevicedialog.h" @@ -19,7 +20,10 @@ DeviceWidget::DeviceWidget(QWidget *parent) : deviceView.resizeColumnsToContents(); deviceView.resizeRowsToContents(); deviceView.setAlternatingRowColors( true ); + deviceView.setShowGrid( false ); deviceView.setSelectionBehavior( QAbstractItemView::SelectRows ); + deviceView.horizontalHeader()->setStretchLastSection( true ); + deviceView.verticalHeader()->hide(); connect( &deviceView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(listActivated(const QModelIndex &)) ); QVBoxLayout *layout = new QVBoxLayout(this); From fea831f13df04299511cc3116854c418862dff53 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 30 Dec 2008 15:08:11 +0000 Subject: [PATCH 0705/2215] Added settings widgets to all types and made it possible to store these settings --- telldus-gui/TelldusGui/TelldusGui.pro | 6 + telldus-gui/TelldusGui/device.cpp | 11 ++ telldus-gui/TelldusGui/device.h | 3 + telldus-gui/TelldusGui/devicesetting.cpp | 16 +-- telldus-gui/TelldusGui/devicesetting.h | 18 +-- telldus-gui/TelldusGui/devicesettingikea.cpp | 116 ++++++++++++++++++ telldus-gui/TelldusGui/devicesettingikea.h | 41 +++++++ telldus-gui/TelldusGui/devicesettingnexa.cpp | 111 ++++++++--------- telldus-gui/TelldusGui/devicesettingnexa.h | 21 ++-- .../TelldusGui/devicesettingnexabell.cpp | 80 ++++++++++++ .../TelldusGui/devicesettingnexabell.h | 45 +++++++ .../TelldusGui/devicesettingsartano.cpp | 74 +++++++++++ telldus-gui/TelldusGui/devicesettingsartano.h | 38 ++++++ telldus-gui/TelldusGui/editdevicedialog.cpp | 20 ++- 14 files changed, 503 insertions(+), 97 deletions(-) create mode 100644 telldus-gui/TelldusGui/devicesettingikea.cpp create mode 100644 telldus-gui/TelldusGui/devicesettingikea.h create mode 100644 telldus-gui/TelldusGui/devicesettingnexabell.cpp create mode 100644 telldus-gui/TelldusGui/devicesettingnexabell.h create mode 100644 telldus-gui/TelldusGui/devicesettingsartano.cpp create mode 100644 telldus-gui/TelldusGui/devicesettingsartano.h diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 350841b1..88ef7303 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -10,7 +10,10 @@ SOURCES += telldusgui.cpp \ editdevicedialog.cpp \ vendordevicemodel.cpp \ vendordevicetreeitem.cpp \ + devicesettingikea.cpp \ devicesettingnexa.cpp \ + devicesettingnexabell.cpp \ + devicesettingsartano.cpp \ devicesetting.cpp HEADERS += telldusgui.h \ devicewidget.h \ @@ -19,7 +22,10 @@ HEADERS += telldusgui.h \ editdevicedialog.h \ vendordevicemodel.h \ vendordevicetreeitem.h \ + devicesettingikea.h \ devicesettingnexa.h \ + devicesettingnexabell.h \ + devicesettingsartano.h \ devicesetting.h FORMS += macx { diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 1b3cde46..d8c60a41 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -50,6 +50,17 @@ const QString &Device::name() { return p_name; } +void Device::setParameter( const QString &name, const QString &value ) { + tdSetArgument(p_id, name.toLocal8Bit(), value.toLocal8Bit()); +} + +QString Device::parameter( const QString &name, const QString &defaultValue ) const { + char *p = tdGetArgument(p_id, name.toLocal8Bit(), defaultValue.toLocal8Bit()); + QString param( p ); + free(p); + return param; +} + void Device::setProtocol( const QString & protocol ) { if (protocol.compare(p_protocol, Qt::CaseSensitive) == 0) { return; diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index fad98df7..771b9ece 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -22,6 +22,9 @@ public: void setName( const QString & name ); const QString &name(); + void setParameter( const QString &name, const QString &value ); + QString parameter( const QString &name, const QString &defaultValue ) const; + void setProtocol( const QString & protocol ); const QString &protocol(); diff --git a/telldus-gui/TelldusGui/devicesetting.cpp b/telldus-gui/TelldusGui/devicesetting.cpp index 0abeff3a..d83ab775 100644 --- a/telldus-gui/TelldusGui/devicesetting.cpp +++ b/telldus-gui/TelldusGui/devicesetting.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: devicesetting // -// Description: +// Description: // // // Author: Micke Prag , (C) 2007 @@ -11,8 +11,9 @@ // #include "devicesetting.h" -DeviceSetting::DeviceSetting(QWidget *parent) - : QWidget(parent) +DeviceSetting::DeviceSetting(Device *device, QWidget *parent) + : QWidget(parent), + p_device(device) { } @@ -20,12 +21,3 @@ DeviceSetting::DeviceSetting(QWidget *parent) DeviceSetting::~DeviceSetting() { } - - -/** - * @fn DeviceSetting::setDevice( DeviceInfo * ) - */ -//void DeviceSetting::setDevice( DeviceInfo *device ) -//{ -// p_dev = device; -//} diff --git a/telldus-gui/TelldusGui/devicesetting.h b/telldus-gui/TelldusGui/devicesetting.h index 592bcc3c..5cb79e56 100644 --- a/telldus-gui/TelldusGui/devicesetting.h +++ b/telldus-gui/TelldusGui/devicesetting.h @@ -1,7 +1,7 @@ // // C++ Interface: devicesetting // -// Description: +// Description: // // // Author: Micke Prag , (C) 2007 @@ -13,7 +13,8 @@ #define DEVICESETTING_H #include -//#include "deviceinfo.h" + +class Device; /** @author Micke Prag @@ -22,16 +23,15 @@ class DeviceSetting : public QWidget { Q_OBJECT public: - DeviceSetting(QWidget *parent = 0); + DeviceSetting(Device *device, QWidget *parent = 0); - ~DeviceSetting(); + virtual ~DeviceSetting(); -//public slots: -// virtual void setDevice( DeviceInfo * ); -// virtual void saveSetting() = 0; +public slots: + virtual void saveParameters() = 0; -//protected: -// DeviceInfo *p_dev; +protected: + Device *p_device; }; #endif diff --git a/telldus-gui/TelldusGui/devicesettingikea.cpp b/telldus-gui/TelldusGui/devicesettingikea.cpp new file mode 100644 index 00000000..54d378d6 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingikea.cpp @@ -0,0 +1,116 @@ +// +// C++ Implementation: devicesettingikea +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "devicesettingikea.h" +#include "device.h" +#include +#include +#include + +DeviceSettingIkea::DeviceSettingIkea(Device *device, QWidget *parent) + : DeviceSetting(device, parent) +{ + QVBoxLayout *layout = new QVBoxLayout( this ); + QGridLayout *gl = new QGridLayout; + + // System + QLabel *l = new QLabel(tr("System"), this); + l->setAlignment( Qt::AlignHCenter ); + gl->addWidget( l, 0, 0 ); + + spinBox = new QSpinBox( this ); + spinBox->setMinimum( 1 ); + spinBox->setMaximum( 16 ); + gl->addWidget( spinBox, 1, 0 ); + + // Units + l = new QLabel(tr("Units"), this); + l->setAlignment( Qt::AlignHCenter ); + gl->addWidget( l, 0, 1 ); + + QGridLayout *bl = new QGridLayout; + for ( int i = 0; i < 10; ++i ) { + unit[i] = new QCheckBox(this); + if (i > 0) { + bl->addWidget( unit[i], 0, i-1 ); + bl->addWidget( new QLabel(QString::number(i), this), 1, i-1 ); + } else { + bl->addWidget( unit[i], 0, 9 ); + bl->addWidget( new QLabel("10", this), 1, 9 ); + } + } + gl->addLayout( bl, 1, 1 ); + + //Fade + l = new QLabel(tr("Fade"), this); + l->setAlignment( Qt::AlignHCenter ); + gl->addWidget( l, 0, 2 ); + + QVBoxLayout *vl = new QVBoxLayout; + smooth = new QRadioButton( tr("Smooth"), this ); + vl->addWidget( smooth ); + QRadioButton *instant = new QRadioButton( tr("Instant"), this ); + instant->setChecked( true ); + vl->addWidget( instant ); + gl->addLayout( vl, 1, 2 ); + + layout->addLayout( gl ); + layout->addStretch( 1 ); +} + + +DeviceSettingIkea::~DeviceSettingIkea() +{ +} + +/** +void DeviceSettingIkea::setDevice( DeviceInfo *device ) +{ + DeviceSetting::setDevice( device ); + + spinBox->setValue( device->setting("ikea_system", "1").toInt() ); + + QString setting = device->setting("ikea_units", ""); + if (setting != "") { + QStringList units = setting.split(","); + for(int i = 0; i < units.size(); ++i) { + int intUnit = units.at(i).toInt(); + if (intUnit == 10) { + intUnit = 0; + } else if (intUnit > 10) { + continue; + } + unit[intUnit]->setChecked(true); + } + } + + QString fade = device->setting("ikea_fade", "false"); + if (fade.compare("true", Qt::CaseInsensitive) == 0) + smooth->setChecked( true ); +}*/ + +void DeviceSettingIkea::saveParameters() { + p_device->setParameter( "ikea_system", QString::number(spinBox->value()) ); //System + + QStringList units; + for (int i = 0; i < 10; ++i) { + if (unit[i]->isChecked()) { + if (i == 0) { + units << "10"; + } else { + units << QString::number(i); + } + } + } + p_device->setParameter( "ikea_units", units.join(",") ); + + p_device->setParameter( "ikea_fade", (smooth->isChecked() ? "true" : "false") ); +} diff --git a/telldus-gui/TelldusGui/devicesettingikea.h b/telldus-gui/TelldusGui/devicesettingikea.h new file mode 100644 index 00000000..c822970e --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingikea.h @@ -0,0 +1,41 @@ +// +// C++ Interface: devicesettingikea +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DEVICESETTINGIKEA_H +#define DEVICESETTINGIKEA_H + +#include +#include +#include +#include +#include + +/** + * @author Micke Prag + **/ +class DeviceSettingIkea : public DeviceSetting +{ +Q_OBJECT +public: + DeviceSettingIkea(Device *device, QWidget *parent = 0); + + virtual ~DeviceSettingIkea(); + +public slots: + virtual void saveParameters(); + +protected: + QSpinBox *spinBox; + QHash unit; + QRadioButton *smooth; +}; + +#endif diff --git a/telldus-gui/TelldusGui/devicesettingnexa.cpp b/telldus-gui/TelldusGui/devicesettingnexa.cpp index 22997854..02ed1ca4 100644 --- a/telldus-gui/TelldusGui/devicesettingnexa.cpp +++ b/telldus-gui/TelldusGui/devicesettingnexa.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: devicesettingnexa // -// Description: +// Description: // // // Author: Micke Prag , (C) 2007 @@ -10,27 +10,34 @@ // // #include "devicesettingnexa.h" +#include "device.h" #include #include #include -DeviceSettingNexa::DeviceSettingNexa(QWidget *parent) - : DeviceSetting(parent) +DeviceSettingNexa::DeviceSettingNexa(Device *device, QWidget *parent) + : DeviceSetting(device, parent), + dialHouse(0), + dialUnit(0), + labelHouse(0), + labelUnit(0) { - gridLayout1 = new QGridLayout(this); - gridLayout1->setSpacing(6); - gridLayout1->setMargin(9); - gridLayout1->setObjectName(QString::fromUtf8("gridLayout1")); - - dialCode = new QDial(this); - dialCode->setObjectName(QString::fromUtf8("dialCode")); - dialCode->setMinimum(1); - dialCode->setMaximum(16); - dialCode->setPageStep(1); - dialCode->setOrientation(Qt::Horizontal); - dialCode->setNotchesVisible(true); + QGridLayout *gridLayout = new QGridLayout(this); + gridLayout->setSpacing(6); + gridLayout->setMargin(9); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); - gridLayout1->addWidget(dialCode, 1, 1, 1, 1); + QLabel *labelHouseTitle = new QLabel(this); + labelHouseTitle->setObjectName(QString::fromUtf8("labelHouseTitle")); + labelHouseTitle->setAlignment(Qt::AlignCenter); + labelHouseTitle->setText( tr("Housecode") ); + gridLayout->addWidget(labelHouseTitle, 0, 0, 1, 1); + + QLabel *labelUnitTitle = new QLabel(this); + labelUnitTitle->setObjectName(QString::fromUtf8("label_2")); + labelUnitTitle->setAlignment(Qt::AlignCenter); + labelUnitTitle->setText( tr("Unitcode") ); + gridLayout->addWidget(labelUnitTitle, 0, 1, 1, 1); dialHouse = new QDial(this); dialHouse->setObjectName(QString::fromUtf8("dialHouse")); @@ -39,38 +46,37 @@ DeviceSettingNexa::DeviceSettingNexa(QWidget *parent) dialHouse->setPageStep(1); dialHouse->setOrientation(Qt::Horizontal); dialHouse->setNotchesVisible(true); + gridLayout->addWidget(dialHouse, 1, 0, 1, 1); - gridLayout1->addWidget(dialHouse, 1, 0, 1, 1); - - label = new QLabel(this); - label->setObjectName(QString::fromUtf8("label")); - label->setAlignment(Qt::AlignCenter); - label->setText( tr("Housecode") ); - - gridLayout1->addWidget(label, 0, 0, 1, 1); - - label_2 = new QLabel(this); - label_2->setObjectName(QString::fromUtf8("label_2")); - label_2->setAlignment(Qt::AlignCenter); - label_2->setText( tr("Unitcode") ); - - gridLayout1->addWidget(label_2, 0, 1, 1, 1); + dialUnit = new QDial(this); + dialUnit->setObjectName(QString::fromUtf8("dialCode")); + dialUnit->setMinimum(1); + dialUnit->setMaximum(16); + dialUnit->setPageStep(1); + dialUnit->setOrientation(Qt::Horizontal); + dialUnit->setNotchesVisible(true); + gridLayout->addWidget(dialUnit, 1, 1, 1, 1); labelHouse = new QLabel(this); labelHouse->setObjectName(QString::fromUtf8("labelHouse")); labelHouse->setAlignment(Qt::AlignCenter); labelHouse->setText( "A" ); + gridLayout->addWidget(labelHouse, 2, 0, 1, 1); + + labelUnit = new QLabel(this); + labelUnit->setObjectName(QString::fromUtf8("labelUnit")); + labelUnit->setAlignment(Qt::AlignCenter); + labelUnit->setText( "1" ); + gridLayout->addWidget(labelUnit, 2, 1, 1, 1); + connect( dialHouse, SIGNAL( valueChanged( int ) ), this, SLOT( houseChanged(int) ) ); + connect( dialUnit, SIGNAL(valueChanged(int)), labelUnit, SLOT(setNum(int)) ); - gridLayout1->addWidget(labelHouse, 2, 0, 1, 1); + QString strHouse = device->parameter("nexa_house", "A"); + uint intHouse = strHouse[0].toAscii() - 'A'; + dialHouse->setValue( intHouse ); - label_4 = new QLabel(this); - label_4->setObjectName(QString::fromUtf8("label_4")); - label_4->setAlignment(Qt::AlignCenter); - label_4->setText( "1" ); - connect( dialCode, SIGNAL(valueChanged(int)), label_4, SLOT(setNum(int)) ); - - gridLayout1->addWidget(label_4, 2, 1, 1, 1); + dialUnit->setValue( device->parameter("nexa_unit", "1").toInt() ); } @@ -78,30 +84,11 @@ DeviceSettingNexa::~DeviceSettingNexa() { } +void DeviceSettingNexa::saveParameters() { + p_device->setParameter( "nexa_house", QString('A' + dialHouse->value()) ); + p_device->setParameter( "nexa_unit", QString::number(dialUnit->value()) ); +} -/** - * @fn DeviceSettingNexa::setDevice( DeviceInfo * ) - */ -//void DeviceSettingNexa::setDevice( DeviceInfo *device ) -//{ -// DeviceSetting::setDevice( device ); -// QString strHouse = device->setting("nexa_house", "A"); -// uint intHouse = strHouse[0].toAscii() - 'A'; -// dialHouse->setValue( intHouse ); -// dialCode->setValue( device->setting("nexa_unit", "1").toInt() ); -//} -// -///** -// * @fn DeviceSettingNexa::saveSetting() -// */ -//void DeviceSettingNexa::saveSetting() { -// p_dev->setSetting( "nexa_house", QString('A' + dialHouse->value()) ); -// p_dev->setSetting( "nexa_unit", QString::number(dialCode->value()) ); -//} - -/** - * @fn DeviceSettingNexa::houseChanged( int house ) - */ void DeviceSettingNexa::houseChanged( int house ) { labelHouse->setText( QString('A' + house) ); diff --git a/telldus-gui/TelldusGui/devicesettingnexa.h b/telldus-gui/TelldusGui/devicesettingnexa.h index 7d855646..12c7934e 100644 --- a/telldus-gui/TelldusGui/devicesettingnexa.h +++ b/telldus-gui/TelldusGui/devicesettingnexa.h @@ -1,7 +1,7 @@ // // C++ Interface: devicesettingnexa // -// Description: +// Description: // // // Author: Micke Prag , (C) 2007 @@ -12,7 +12,7 @@ #ifndef DEVICESETTINGNEXA_H #define DEVICESETTINGNEXA_H -#include +#include "devicesetting.h" class QGridLayout; class QDial; @@ -25,25 +25,22 @@ class DeviceSettingNexa : public DeviceSetting { Q_OBJECT public: - DeviceSettingNexa(QWidget *parent = 0); + DeviceSettingNexa(Device *device, QWidget *parent = 0); - ~DeviceSettingNexa(); + virtual ~DeviceSettingNexa(); -//public slots: -// virtual void setDevice( DeviceInfo * ); -// virtual void saveSetting(); +public slots: + virtual void saveParameters(); protected slots: void houseChanged( int house ); protected: QGridLayout *gridLayout1; - QDial *dialCode; - QDial *dialHouse; - QLabel *label; - QLabel *label_2; + QDial *dialHouse; + QDial *dialUnit; QLabel *labelHouse; - QLabel *label_4; + QLabel *labelUnit; }; #endif diff --git a/telldus-gui/TelldusGui/devicesettingnexabell.cpp b/telldus-gui/TelldusGui/devicesettingnexabell.cpp new file mode 100644 index 00000000..228d83c9 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingnexabell.cpp @@ -0,0 +1,80 @@ +// +// C++ Implementation: devicesettingnexa +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "devicesettingnexabell.h" +#include "device.h" +#include +#include +#include + +DeviceSettingNexaBell::DeviceSettingNexaBell(Device *device, QWidget *parent) + : DeviceSetting(device, parent) +{ + gridLayout1 = new QGridLayout(this); + gridLayout1->setSpacing(6); + gridLayout1->setMargin(9); + gridLayout1->setObjectName(QString::fromUtf8("gridLayout1")); + + dialHouse = new QDial(this); + dialHouse->setObjectName(QString::fromUtf8("dialHouse")); + dialHouse->setMinimum(0); + dialHouse->setMaximum(15); + dialHouse->setPageStep(1); + dialHouse->setOrientation(Qt::Horizontal); + dialHouse->setNotchesVisible(true); + + gridLayout1->addWidget(dialHouse, 1, 0, 1, 1); + + label = new QLabel(this); + label->setObjectName(QString::fromUtf8("label")); + label->setAlignment(Qt::AlignCenter); + label->setText( tr("Housecode") ); + + gridLayout1->addWidget(label, 0, 0, 1, 1); + + labelHouse = new QLabel(this); + labelHouse->setObjectName(QString::fromUtf8("labelHouse")); + labelHouse->setAlignment(Qt::AlignCenter); + labelHouse->setText( "A" ); + connect( dialHouse, SIGNAL( valueChanged( int ) ), this, SLOT( houseChanged(int) ) ); + + gridLayout1->addWidget(labelHouse, 2, 0, 1, 1); + +} + + +DeviceSettingNexaBell::~DeviceSettingNexaBell() +{ +} + + +/** +void DeviceSettingNexaBell::setDevice( DeviceInfo *device ) +{ + DeviceSetting::setDevice( device ); + QString strHouse = device->setting("nexa_house", "A"); + uint intHouse = strHouse[0].toAscii() - 'A'; + dialHouse->setValue( intHouse ); +} +*/ + +void DeviceSettingNexaBell::saveParameters() { + p_device->setParameter( "nexa_house", QString('A' + dialHouse->value()) ); +} + +/** + * @fn DeviceSettingNexaBell::houseChanged( int house ) + */ +void DeviceSettingNexaBell::houseChanged( int house ) +{ + labelHouse->setText( QString('A' + house) ); +} + diff --git a/telldus-gui/TelldusGui/devicesettingnexabell.h b/telldus-gui/TelldusGui/devicesettingnexabell.h new file mode 100644 index 00000000..f96fd654 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingnexabell.h @@ -0,0 +1,45 @@ +// +// C++ Interface: devicesettingnexa +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DEVICESETTINGNEXABELL_H +#define DEVICESETTINGNEXABELL_H + +#include + +class QGridLayout; +class QDial; +class QLabel; + +/** + @author Micke Prag +*/ +class DeviceSettingNexaBell : public DeviceSetting +{ +Q_OBJECT +public: + DeviceSettingNexaBell(Device *device, QWidget *parent = 0); + + virtual ~DeviceSettingNexaBell(); + +public slots: + virtual void saveParameters(); + +protected slots: + void houseChanged( int house ); + +protected: + QGridLayout *gridLayout1; + QDial *dialHouse; + QLabel *label; + QLabel *labelHouse; +}; + +#endif diff --git a/telldus-gui/TelldusGui/devicesettingsartano.cpp b/telldus-gui/TelldusGui/devicesettingsartano.cpp new file mode 100644 index 00000000..78e87166 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingsartano.cpp @@ -0,0 +1,74 @@ +// +// C++ Implementation: devicesettingsartano +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "devicesettingsartano.h" +#include "device.h" +#include +#include +#include +#include + +DeviceSettingSartano::DeviceSettingSartano(Device *device, QWidget *parent) + : DeviceSetting(device, parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + QGridLayout *gl = new QGridLayout(this); + + for( int i = 0; i < 10; ++i ) { + QButtonGroup *g = new QButtonGroup(this); + button1[i] = new QRadioButton(this); + button0[i] = new QRadioButton(this); + button0[i]->setChecked( true ); + g->addButton(button1[i]); + g->addButton(button0[i]); + + gl->addWidget(button1[i], 1, i); + gl->addWidget(button0[i], 0, i); + if (i < 5) { + gl->addWidget( new QLabel(QString::number(i+1), this), 2, i ); + } else { + gl->addWidget( new QLabel(QString('A'+i-5), this), 2, i ); + } + } + + layout->addLayout( gl ); + layout->addStretch( 1 ); +} + +DeviceSettingSartano::~DeviceSettingSartano() { +} + +/** +void DeviceSettingSartano::setDevice( DeviceInfo *device ) +{ + DeviceSetting::setDevice( device ); + + QString setting = device->setting("sartano_code", "0000000000"); + for (int i = 0; i < 10; ++i) { + qDebug(QString(setting[i]).toAscii()); + if (setting[i] == '0') { + button1[i]->setChecked(true); + } + } +} +*/ + +void DeviceSettingSartano::saveParameters() { + QString setting; + for (int i = 0; i < 10; ++i) { + if (button0[i]->isChecked()) { + setting.append("1"); + } else { + setting.append("0"); + } + } + p_device->setParameter( "sartano_code", setting ); +} diff --git a/telldus-gui/TelldusGui/devicesettingsartano.h b/telldus-gui/TelldusGui/devicesettingsartano.h new file mode 100644 index 00000000..14e3d87b --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingsartano.h @@ -0,0 +1,38 @@ +// +// C++ Interface: devicesettingsartano +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DEVICESETTINGSARTANO_H +#define DEVICESETTINGSARTANO_H + +#include +#include +#include + +/** + * @author Micke Prag + */ +class DeviceSettingSartano : public DeviceSetting +{ +Q_OBJECT +public: + DeviceSettingSartano(Device *device, QWidget *parent = 0); + + virtual ~DeviceSettingSartano(); + +public slots: + virtual void saveParameters(); + +protected: + QHash button1; + QHash button0; +}; + +#endif diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 92bba5b9..9a979ad8 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -3,7 +3,10 @@ #include "vendordevicetreeitem.h" #include "device.h" +#include "devicesettingikea.h" #include "devicesettingnexa.h" +#include "devicesettingnexabell.h" +#include "devicesettingsartano.h" #include #include @@ -79,7 +82,10 @@ EditDeviceDialog::EditDeviceDialog(Device *d, QWidget *parent, Qt::WFlags flags) connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); layout->addWidget(buttonBox); - deviceSettings[1] = new DeviceSettingNexa(); + deviceSettings[1] = new DeviceSettingNexa(device, this); + deviceSettings[2] = new DeviceSettingSartano(device, this); + deviceSettings[3] = new DeviceSettingIkea(device, this); + deviceSettings[4] = new DeviceSettingNexaBell(device, this); foreach( DeviceSetting *s, deviceSettings ) { settingsLayout->addWidget( s ); } @@ -103,7 +109,12 @@ void EditDeviceDialog::selectionChanged( const QModelIndex & index ) { } deviceImage->setPixmap( item->image() ); - settingsLayout->setCurrentIndex( item->widget() ); + + int widget = item->widget(); + if (widget >= settingsLayout->count()) { + widget = 0; + } + settingsLayout->setCurrentIndex( widget ); } void EditDeviceDialog::okClicked() { @@ -133,5 +144,10 @@ void EditDeviceDialog::okClicked() { device->setModel( item->deviceModel() ); device->setProtocol( item->deviceProtocol() ); + DeviceSetting *w = qobject_cast(settingsLayout->currentWidget()); + if (w) { + w->saveParameters(); + } + this->accept(); } From ac59f0d442d89b3827f34c3da66ef56d2354217f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 30 Dec 2008 15:10:01 +0000 Subject: [PATCH 0706/2215] Removed the 'const' attribute from tdGetArgument() --- telldus-core/driver/libtelldus-core/telldus-core.cpp | 4 ++-- telldus-core/driver/libtelldus-core/telldus-core.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index e0cecfaf..78b04803 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -354,13 +354,13 @@ bool WINAPI tdSetArgument(int intDeviceId, const char *strName, const char *strV return false; } -const char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue){ +char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue){ char *strReturn = ""; try{ TelldusSettings ts; strReturn = ts.getArgument(intDeviceId, strName); if (strReturn == NULL) { - return defaultValue; + strReturn = strdup(defaultValue); } #ifdef _WINDOWS strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index 38cb86ec..825b849d 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -42,7 +42,7 @@ extern "C" { TELLSTICK_API int WINAPI tdGetModel(int intDeviceId); TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, int intModel); - TELLSTICK_API const char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue); TELLSTICK_API bool WINAPI tdSetArgument(int intDeviceId, const char *strName, const char* strValue); TELLSTICK_API int WINAPI tdAddDevice(); From 848731adf7a83b7f5457b4f515d07eec7a7281d9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 30 Dec 2008 16:39:07 +0000 Subject: [PATCH 0707/2215] Changed the function name getArgument()/setArgument() to getDeviceParameter()/setDeviceParameter() --- .../settings/TelldusSettings.cpp | 20 +++++++++---------- .../settings/TelldusSettings.h | 4 ++-- .../driver/libtelldus-core/telldus-core.cpp | 8 ++++---- .../driver/libtelldus-core/telldus-core.h | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp index ffd20a61..b266c1a9 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp @@ -22,28 +22,28 @@ Device* TelldusSettings::getDevice(int intDeviceId){ //each new brand must be added here if (strcmp(protocol, "Nexa") == 0){ - char *strHouse = getArgument(intDeviceId, "nexa_house"); - char *strCode = getArgument(intDeviceId, "nexa_unit"); + char *strHouse = getDeviceParameter(intDeviceId, "nexa_house"); + char *strCode = getDeviceParameter(intDeviceId, "nexa_unit"); dev = new DeviceNexa(strHouse, strCode); free(strHouse); free(strCode); } else if (strcmp(protocol, "Waveman") == 0) { - char *strHouse = getArgument(intDeviceId, "nexa_house"); - char *strCode = getArgument(intDeviceId, "nexa_unit"); + char *strHouse = getDeviceParameter(intDeviceId, "nexa_house"); + char *strCode = getDeviceParameter(intDeviceId, "nexa_unit"); dev = new DeviceWaveman(strHouse, strCode); free(strHouse); free(strCode); } else if (strcmp(protocol, "Sartano") == 0) { - char *strCode = getArgument(intDeviceId, "sartano_code"); + char *strCode = getDeviceParameter(intDeviceId, "sartano_code"); dev = new DeviceSartano(strCode); free(strCode); } else if (strcmp(protocol, "Ikea") == 0) { - char *strSystem = getArgument(intDeviceId, "ikea_system"); - char *strUnits = getArgument(intDeviceId, "ikea_units"); - char *strFade = getArgument(intDeviceId, "ikea_fade"); + char *strSystem = getDeviceParameter(intDeviceId, "ikea_system"); + char *strUnits = getDeviceParameter(intDeviceId, "ikea_units"); + char *strFade = getDeviceParameter(intDeviceId, "ikea_fade"); dev = new DeviceIkea(strSystem, strUnits, strFade); free(strSystem); free(strUnits); @@ -111,13 +111,13 @@ bool TelldusSettings::setModel(int intDeviceId, int intModel){ /* * Set device argument */ -bool TelldusSettings::setArgument(int intDeviceId, const char *strName, const char *strValue){ +bool TelldusSettings::setDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ return setStringSetting(intDeviceId, strName, strValue, true); } /* * Get device argument */ -char* TelldusSettings::getArgument(int intDeviceId, const char *strName) { +char* TelldusSettings::getDeviceParameter(int intDeviceId, const char *strName) { return getStringSetting(intDeviceId, strName, true); } diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h index 9dadc71e..0f5a603d 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h +++ b/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h @@ -19,8 +19,8 @@ public: bool setProtocol(int intDeviceId, const char* strVendor); int getModel(int intDeviceId); bool setModel(int intDeviceId, int intModel); - char* getArgument(int intDeviceId, const char *strName); - bool setArgument(int intDeviceId, const char *strName, const char *strValue); + char* getDeviceParameter(int intDeviceId, const char *strName); + bool setDeviceParameter(int intDeviceId, const char *strName, const char *strValue); int addDevice(); int getDeviceId(int intDeviceIndex); bool removeDevice(int intDeviceId); diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 78b04803..1f6ce419 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -342,11 +342,11 @@ bool WINAPI tdSetModel(int intDeviceId, int intModel){ return blnSuccess; } -bool WINAPI tdSetArgument(int intDeviceId, const char *strName, const char *strValue){ +bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ try{ TelldusSettings ts; - return ts.setArgument(intDeviceId, strName, strValue); + return ts.setDeviceParameter(intDeviceId, strName, strValue); } catch(exception e){ handleException(e); @@ -354,11 +354,11 @@ bool WINAPI tdSetArgument(int intDeviceId, const char *strName, const char *strV return false; } -char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue){ +char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ char *strReturn = ""; try{ TelldusSettings ts; - strReturn = ts.getArgument(intDeviceId, strName); + strReturn = ts.getDeviceParameter(intDeviceId, strName); if (strReturn == NULL) { strReturn = strdup(defaultValue); } diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index 825b849d..a2263803 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -42,8 +42,8 @@ extern "C" { TELLSTICK_API int WINAPI tdGetModel(int intDeviceId); TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, int intModel); - TELLSTICK_API char * WINAPI tdGetArgument(int intDeviceId, const char *strName, const char *defaultValue); - TELLSTICK_API bool WINAPI tdSetArgument(int intDeviceId, const char *strName, const char* strValue); + TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); TELLSTICK_API int WINAPI tdAddDevice(); TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); From eecd626a325a9e2de3d4233866e787657fabd99e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 30 Dec 2008 16:39:48 +0000 Subject: [PATCH 0708/2215] Changed the function name getArgument()/setArgument() to getDeviceParameter()/setDeviceParameter() --- telldus-gui/TelldusGui/device.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index d8c60a41..b12352bc 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -51,11 +51,11 @@ const QString &Device::name() { } void Device::setParameter( const QString &name, const QString &value ) { - tdSetArgument(p_id, name.toLocal8Bit(), value.toLocal8Bit()); + tdSetDeviceParameter(p_id, name.toLocal8Bit(), value.toLocal8Bit()); } QString Device::parameter( const QString &name, const QString &defaultValue ) const { - char *p = tdGetArgument(p_id, name.toLocal8Bit(), defaultValue.toLocal8Bit()); + char *p = tdGetDeviceParameter(p_id, name.toLocal8Bit(), defaultValue.toLocal8Bit()); QString param( p ); free(p); return param; From 58e15191cb701a4982440eb6d765a909106dcc96 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 10:21:39 +0000 Subject: [PATCH 0709/2215] Stored the settings in DeviceSettingNexaBell --- .../TelldusGui/devicesettingnexabell.cpp | 45 +++++++------------ .../TelldusGui/devicesettingnexabell.h | 2 - 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/telldus-gui/TelldusGui/devicesettingnexabell.cpp b/telldus-gui/TelldusGui/devicesettingnexabell.cpp index 228d83c9..371de712 100644 --- a/telldus-gui/TelldusGui/devicesettingnexabell.cpp +++ b/telldus-gui/TelldusGui/devicesettingnexabell.cpp @@ -18,10 +18,16 @@ DeviceSettingNexaBell::DeviceSettingNexaBell(Device *device, QWidget *parent) : DeviceSetting(device, parent) { - gridLayout1 = new QGridLayout(this); - gridLayout1->setSpacing(6); - gridLayout1->setMargin(9); - gridLayout1->setObjectName(QString::fromUtf8("gridLayout1")); + QGridLayout *gridLayout = new QGridLayout(this); + gridLayout->setSpacing(6); + gridLayout->setMargin(9); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + + QLabel *labelHouseTitle = new QLabel(this); + labelHouseTitle->setObjectName(QString::fromUtf8("labelHouseTitle")); + labelHouseTitle->setAlignment(Qt::AlignCenter); + labelHouseTitle->setText( tr("Housecode") ); + gridLayout->addWidget(labelHouseTitle, 0, 0, 1, 1); dialHouse = new QDial(this); dialHouse->setObjectName(QString::fromUtf8("dialHouse")); @@ -30,24 +36,19 @@ DeviceSettingNexaBell::DeviceSettingNexaBell(Device *device, QWidget *parent) dialHouse->setPageStep(1); dialHouse->setOrientation(Qt::Horizontal); dialHouse->setNotchesVisible(true); - - gridLayout1->addWidget(dialHouse, 1, 0, 1, 1); - - label = new QLabel(this); - label->setObjectName(QString::fromUtf8("label")); - label->setAlignment(Qt::AlignCenter); - label->setText( tr("Housecode") ); - - gridLayout1->addWidget(label, 0, 0, 1, 1); + gridLayout->addWidget(dialHouse, 1, 0, 1, 1); labelHouse = new QLabel(this); labelHouse->setObjectName(QString::fromUtf8("labelHouse")); labelHouse->setAlignment(Qt::AlignCenter); labelHouse->setText( "A" ); + gridLayout->addWidget(labelHouse, 2, 0, 1, 1); + connect( dialHouse, SIGNAL( valueChanged( int ) ), this, SLOT( houseChanged(int) ) ); - gridLayout1->addWidget(labelHouse, 2, 0, 1, 1); - + QString strHouse = device->parameter("nexa_house", "A"); + uint intHouse = strHouse[0].toAscii() - 'A'; + dialHouse->setValue( intHouse ); } @@ -55,24 +56,10 @@ DeviceSettingNexaBell::~DeviceSettingNexaBell() { } - -/** -void DeviceSettingNexaBell::setDevice( DeviceInfo *device ) -{ - DeviceSetting::setDevice( device ); - QString strHouse = device->setting("nexa_house", "A"); - uint intHouse = strHouse[0].toAscii() - 'A'; - dialHouse->setValue( intHouse ); -} -*/ - void DeviceSettingNexaBell::saveParameters() { p_device->setParameter( "nexa_house", QString('A' + dialHouse->value()) ); } -/** - * @fn DeviceSettingNexaBell::houseChanged( int house ) - */ void DeviceSettingNexaBell::houseChanged( int house ) { labelHouse->setText( QString('A' + house) ); diff --git a/telldus-gui/TelldusGui/devicesettingnexabell.h b/telldus-gui/TelldusGui/devicesettingnexabell.h index f96fd654..9a0b4818 100644 --- a/telldus-gui/TelldusGui/devicesettingnexabell.h +++ b/telldus-gui/TelldusGui/devicesettingnexabell.h @@ -36,9 +36,7 @@ protected slots: void houseChanged( int house ); protected: - QGridLayout *gridLayout1; QDial *dialHouse; - QLabel *label; QLabel *labelHouse; }; From 73eb03f175527e2fb884ffcb0be5d8219063e36b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 10:24:23 +0000 Subject: [PATCH 0710/2215] Minor cleanup fixes in DeviceSettingNexa --- telldus-gui/TelldusGui/devicesettingnexa.cpp | 2 +- telldus-gui/TelldusGui/devicesettingnexa.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-gui/TelldusGui/devicesettingnexa.cpp b/telldus-gui/TelldusGui/devicesettingnexa.cpp index 02ed1ca4..bb8cedb1 100644 --- a/telldus-gui/TelldusGui/devicesettingnexa.cpp +++ b/telldus-gui/TelldusGui/devicesettingnexa.cpp @@ -34,7 +34,7 @@ DeviceSettingNexa::DeviceSettingNexa(Device *device, QWidget *parent) gridLayout->addWidget(labelHouseTitle, 0, 0, 1, 1); QLabel *labelUnitTitle = new QLabel(this); - labelUnitTitle->setObjectName(QString::fromUtf8("label_2")); + labelUnitTitle->setObjectName(QString::fromUtf8("labelUnitTitle")); labelUnitTitle->setAlignment(Qt::AlignCenter); labelUnitTitle->setText( tr("Unitcode") ); gridLayout->addWidget(labelUnitTitle, 0, 1, 1, 1); diff --git a/telldus-gui/TelldusGui/devicesettingnexa.h b/telldus-gui/TelldusGui/devicesettingnexa.h index 12c7934e..e2755202 100644 --- a/telldus-gui/TelldusGui/devicesettingnexa.h +++ b/telldus-gui/TelldusGui/devicesettingnexa.h @@ -36,7 +36,6 @@ protected slots: void houseChanged( int house ); protected: - QGridLayout *gridLayout1; QDial *dialHouse; QDial *dialUnit; QLabel *labelHouse; From 801fbcd2a1e9c1e3a2ef541cc870087101f6ead4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 10:41:56 +0000 Subject: [PATCH 0711/2215] Stored the settings in DeviceSettingIkea --- telldus-gui/TelldusGui/devicesettingikea.cpp | 29 +++++++++----------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/telldus-gui/TelldusGui/devicesettingikea.cpp b/telldus-gui/TelldusGui/devicesettingikea.cpp index 54d378d6..2990fd37 100644 --- a/telldus-gui/TelldusGui/devicesettingikea.cpp +++ b/telldus-gui/TelldusGui/devicesettingikea.cpp @@ -64,21 +64,11 @@ DeviceSettingIkea::DeviceSettingIkea(Device *device, QWidget *parent) layout->addLayout( gl ); layout->addStretch( 1 ); -} + //Restore the settings + spinBox->setValue( device->parameter("ikea_system", "1").toInt() ); -DeviceSettingIkea::~DeviceSettingIkea() -{ -} - -/** -void DeviceSettingIkea::setDevice( DeviceInfo *device ) -{ - DeviceSetting::setDevice( device ); - - spinBox->setValue( device->setting("ikea_system", "1").toInt() ); - - QString setting = device->setting("ikea_units", ""); + QString setting = device->parameter("ikea_units", ""); if (setting != "") { QStringList units = setting.split(","); for(int i = 0; i < units.size(); ++i) { @@ -92,10 +82,17 @@ void DeviceSettingIkea::setDevice( DeviceInfo *device ) } } - QString fade = device->setting("ikea_fade", "false"); - if (fade.compare("true", Qt::CaseInsensitive) == 0) + QString fade = device->parameter("ikea_fade", "false"); + if (fade.compare("true", Qt::CaseInsensitive) == 0) { smooth->setChecked( true ); -}*/ + } + +} + + +DeviceSettingIkea::~DeviceSettingIkea() +{ +} void DeviceSettingIkea::saveParameters() { p_device->setParameter( "ikea_system", QString::number(spinBox->value()) ); //System From 4c4f6c03778f6a37e07b0637dff9ec8731ad0ba9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 10:49:31 +0000 Subject: [PATCH 0712/2215] Stored the settings in DeviceSettingSartano --- .../TelldusGui/devicesettingsartano.cpp | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/telldus-gui/TelldusGui/devicesettingsartano.cpp b/telldus-gui/TelldusGui/devicesettingsartano.cpp index 78e87166..b57ddfcc 100644 --- a/telldus-gui/TelldusGui/devicesettingsartano.cpp +++ b/telldus-gui/TelldusGui/devicesettingsartano.cpp @@ -20,7 +20,7 @@ DeviceSettingSartano::DeviceSettingSartano(Device *device, QWidget *parent) : DeviceSetting(device, parent) { QVBoxLayout *layout = new QVBoxLayout(this); - QGridLayout *gl = new QGridLayout(this); + QGridLayout *gl = new QGridLayout; for( int i = 0; i < 10; ++i ) { QButtonGroup *g = new QButtonGroup(this); @@ -32,34 +32,28 @@ DeviceSettingSartano::DeviceSettingSartano(Device *device, QWidget *parent) gl->addWidget(button1[i], 1, i); gl->addWidget(button0[i], 0, i); + QLabel *label = 0; if (i < 5) { - gl->addWidget( new QLabel(QString::number(i+1), this), 2, i ); + label = new QLabel(QString::number(i+1), this); } else { - gl->addWidget( new QLabel(QString('A'+i-5), this), 2, i ); + label = new QLabel(QString('A'+i-5), this); } + gl->addWidget( label, 2, i ); } layout->addLayout( gl ); layout->addStretch( 1 ); -} -DeviceSettingSartano::~DeviceSettingSartano() { -} - -/** -void DeviceSettingSartano::setDevice( DeviceInfo *device ) -{ - DeviceSetting::setDevice( device ); - - QString setting = device->setting("sartano_code", "0000000000"); + QString setting = device->parameter("sartano_code", "0000000000"); for (int i = 0; i < 10; ++i) { - qDebug(QString(setting[i]).toAscii()); if (setting[i] == '0') { button1[i]->setChecked(true); } } } -*/ + +DeviceSettingSartano::~DeviceSettingSartano() { +} void DeviceSettingSartano::saveParameters() { QString setting; From 60f12c3b96550e9d949f539c6351d362dc8ce768 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 14:29:43 +0000 Subject: [PATCH 0713/2215] Moved files and removed 'Telldus'-prefix from the settings class --- .../driver/libtelldus-core/CMakeLists.txt | 17 ++++++++++++----- .../TelldusSettings.cpp => Settings.cpp} | 8 ++++---- .../{settings/TelldusSettings.h => Settings.h} | 0 ...sSettingsConfuse.cpp => SettingsConfuse.cpp} | 11 ++++++++--- ...pp => SettingsCoreFoundationPreferences.cpp} | 0 ...sWinRegistry.cpp => SettingsWinRegistry.cpp} | 0 6 files changed, 24 insertions(+), 12 deletions(-) rename telldus-core/driver/libtelldus-core/{settings/TelldusSettings.cpp => Settings.cpp} (93%) rename telldus-core/driver/libtelldus-core/{settings/TelldusSettings.h => Settings.h} (100%) rename telldus-core/driver/libtelldus-core/{settings/TelldusSettingsConfuse.cpp => SettingsConfuse.cpp} (95%) rename telldus-core/driver/libtelldus-core/{settings/TelldusSettingsCoreFoundationPreferences.cpp => SettingsCoreFoundationPreferences.cpp} (100%) rename telldus-core/driver/libtelldus-core/{settings/TelldusSettingsWinRegistry.cpp => SettingsWinRegistry.cpp} (100%) diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 1a39f9bd..e6e3b426 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -1,10 +1,15 @@ +FIND_PACKAGE( Qt4 REQUIRED ) +SET( QT_DONT_USE_QTGUI TRUE ) +INCLUDE( ${QT_USE_FILE} ) + SET( telldus-core_SRCS + Controller.cpp Device.cpp DeviceIkea.cpp DeviceNexa.cpp DeviceSartano.cpp DeviceWaveman.cpp - settings/TelldusSettings.cpp + Settings.cpp telldus-core.cpp ) @@ -13,21 +18,21 @@ SET( telldus-core_HDRS ) IF (APPLE) - SET( telldus-core_TARGET TelldusCore ) + SET( telldus-core_TARGET TelldusCore ) SET( telldus-core_SRCS ${telldus-core_SRCS} win/Device.cpp - settings/TelldusSettingsCoreFoundationPreferences.cpp + SettingsCoreFoundationPreferences.cpp ) ADD_DEFINITIONS( -D_MACOSX ) -ELSE (APPLE) +ELSE (APPLE) SET( telldus-core_TARGET telldus-core ) SET( telldus-core_SRCS ${telldus-core_SRCS} linux/Device.cpp - settings/TelldusSettingsConfuse.cpp + SettingsConfuse.cpp ) ADD_DEFINITIONS( -D_LINUX @@ -51,6 +56,7 @@ IF (APPLE) TARGET_LINK_LIBRARIES(${telldus-core_TARGET} ${COREFOUNDATION_LIBRARY} + ${QT_LIBRARIES} ${FTD2XX_LIBRARY} ) SET_PROPERTY(TARGET ${telldus-core_TARGET} @@ -59,6 +65,7 @@ IF (APPLE) ELSE (APPLE) TARGET_LINK_LIBRARIES(${telldus-core_TARGET} + ${QT_LIBRARIES} confuse ) ENDIF (APPLE) diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp b/telldus-core/driver/libtelldus-core/Settings.cpp similarity index 93% rename from telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp rename to telldus-core/driver/libtelldus-core/Settings.cpp index b266c1a9..c45ac6d4 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.cpp +++ b/telldus-core/driver/libtelldus-core/Settings.cpp @@ -21,26 +21,26 @@ Device* TelldusSettings::getDevice(int intDeviceId){ } //each new brand must be added here - if (strcmp(protocol, "Nexa") == 0){ + if (strcasecmp(protocol, "arctech") == 0){ char *strHouse = getDeviceParameter(intDeviceId, "nexa_house"); char *strCode = getDeviceParameter(intDeviceId, "nexa_unit"); dev = new DeviceNexa(strHouse, strCode); free(strHouse); free(strCode); - } else if (strcmp(protocol, "Waveman") == 0) { + } else if (strcasecmp(protocol, "Waveman") == 0) { char *strHouse = getDeviceParameter(intDeviceId, "nexa_house"); char *strCode = getDeviceParameter(intDeviceId, "nexa_unit"); dev = new DeviceWaveman(strHouse, strCode); free(strHouse); free(strCode); - } else if (strcmp(protocol, "Sartano") == 0) { + } else if (strcasecmp(protocol, "Sartano") == 0) { char *strCode = getDeviceParameter(intDeviceId, "sartano_code"); dev = new DeviceSartano(strCode); free(strCode); - } else if (strcmp(protocol, "Ikea") == 0) { + } else if (strcasecmp(protocol, "Ikea") == 0) { char *strSystem = getDeviceParameter(intDeviceId, "ikea_system"); char *strUnits = getDeviceParameter(intDeviceId, "ikea_units"); char *strFade = getDeviceParameter(intDeviceId, "ikea_fade"); diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettings.h b/telldus-core/driver/libtelldus-core/Settings.h similarity index 100% rename from telldus-core/driver/libtelldus-core/settings/TelldusSettings.h rename to telldus-core/driver/libtelldus-core/Settings.h diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp similarity index 95% rename from telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp rename to telldus-core/driver/libtelldus-core/SettingsConfuse.cpp index 59d86365..83d58202 100644 --- a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp @@ -229,7 +229,11 @@ bool TelldusSettings::setIntSetting(int intDeviceId, const char* name, int value bool readConfig(cfg_t **cfg) { - cfg_opt_t parameter_opts[] = { + cfg_opt_t controller_opts[] = { + CFG_INT("id", -1, CFGF_NONE), + }; + + cfg_opt_t device_parameter_opts[] = { //Nexa CFG_STR("nexa_house", 0, CFGF_NONE), CFG_STR("nexa_unit", 0, CFGF_NONE), @@ -248,9 +252,10 @@ bool readConfig(cfg_t **cfg) { cfg_opt_t device_opts[] = { CFG_INT("id", -1, CFGF_NONE), CFG_STR("name", "Unnamed", CFGF_NONE), - CFG_STR("protocol", "Nexa", CFGF_NONE), + CFG_INT("controller", 0, CFGF_NONE), + CFG_STR("protocol", "arctech", CFGF_NONE), CFG_INT("model", 1, CFGF_NONE), - CFG_SEC("parameters", parameter_opts, CFGF_NONE), + CFG_SEC("parameters", device_parameter_opts, CFGF_NONE), CFG_END() }; diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsCoreFoundationPreferences.cpp b/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp similarity index 100% rename from telldus-core/driver/libtelldus-core/settings/TelldusSettingsCoreFoundationPreferences.cpp rename to telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp diff --git a/telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp b/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp similarity index 100% rename from telldus-core/driver/libtelldus-core/settings/TelldusSettingsWinRegistry.cpp rename to telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp From 698597bbfc40dbf5721cffdf31d081bc3741e44b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 14:52:20 +0000 Subject: [PATCH 0714/2215] Renamed class TelldusSettings to Settings --- .../driver/libtelldus-core/Settings.cpp | 28 ++++----- .../driver/libtelldus-core/Settings.h | 15 +++-- .../libtelldus-core/SettingsConfuse.cpp | 26 ++++---- .../driver/libtelldus-core/telldus-core.cpp | 63 +++++++++++-------- .../driver/libtelldus-core/telldus-core.h | 2 +- 5 files changed, 71 insertions(+), 63 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Settings.cpp b/telldus-core/driver/libtelldus-core/Settings.cpp index c45ac6d4..fd654056 100644 --- a/telldus-core/driver/libtelldus-core/Settings.cpp +++ b/telldus-core/driver/libtelldus-core/Settings.cpp @@ -1,8 +1,8 @@ -#include "TelldusSettings.h" -#include "../DeviceNexa.h" -#include "../DeviceWaveman.h" -#include "../DeviceSartano.h" -#include "../DeviceIkea.h" +#include "Settings.h" +#include "DeviceNexa.h" +#include "DeviceWaveman.h" +#include "DeviceSartano.h" +#include "DeviceIkea.h" #include #include @@ -10,7 +10,7 @@ * Get the requested device * Note that the returned Device should be deleted when not in use anymore */ -Device* TelldusSettings::getDevice(int intDeviceId){ +Device* Settings::getDevice(int intDeviceId){ Device* dev = NULL; @@ -69,55 +69,55 @@ Device* TelldusSettings::getDevice(int intDeviceId){ /* * Get the name of the device */ -char* TelldusSettings::getName(int intDeviceId){ +char* Settings::getName(int intDeviceId){ return getStringSetting(intDeviceId, "name", false); } /* * Set the name of the device */ -bool TelldusSettings::setName(int intDeviceId, const char* strNewName){ +bool Settings::setName(int intDeviceId, const char* strNewName){ return setStringSetting(intDeviceId, "name", strNewName, false); } /* * Get the device vendor */ -char* TelldusSettings::getProtocol(int intDeviceId){ +char* Settings::getProtocol(int intDeviceId){ return getStringSetting(intDeviceId, "protocol", false); } /* * Set the device vendor */ -bool TelldusSettings::setProtocol(int intDeviceId, const char* strVendor){ +bool Settings::setProtocol(int intDeviceId, const char* strVendor){ return setStringSetting(intDeviceId, "protocol", strVendor, false); } /* * Get the device model */ -int TelldusSettings::getModel(int intDeviceId){ +int Settings::getModel(int intDeviceId){ return getIntSetting(intDeviceId, "model", false); } /* * Set the device model */ -bool TelldusSettings::setModel(int intDeviceId, int intModel){ +bool Settings::setModel(int intDeviceId, int intModel){ return setIntSetting(intDeviceId, "model", intModel, false); } /* * Set device argument */ -bool TelldusSettings::setDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ +bool Settings::setDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ return setStringSetting(intDeviceId, strName, strValue, true); } /* * Get device argument */ -char* TelldusSettings::getDeviceParameter(int intDeviceId, const char *strName) { +char* Settings::getDeviceParameter(int intDeviceId, const char *strName) { return getStringSetting(intDeviceId, strName, true); } diff --git a/telldus-core/driver/libtelldus-core/Settings.h b/telldus-core/driver/libtelldus-core/Settings.h index 0f5a603d..9bca8f41 100644 --- a/telldus-core/driver/libtelldus-core/Settings.h +++ b/telldus-core/driver/libtelldus-core/Settings.h @@ -1,16 +1,15 @@ -#ifndef TELLDUSSETTINGS_H -#define TELLDUSSETTINGS_H +#ifndef SETTINGS_H +#define SETTINGS_H -#include "../Device.h" -//#include +#include "Device.h" class privateVars; -class TelldusSettings +class Settings { public: - TelldusSettings(void); - char * getSetting(const char *strName); + Settings(void); + const char * getSetting(const char *strName); int getNumberOfDevices(void); Device* getDevice(int intDeviceId); char* getName(int intDeviceId); @@ -25,7 +24,7 @@ public: int getDeviceId(int intDeviceIndex); bool removeDevice(int intDeviceId); - ~TelldusSettings(void); + ~Settings(void); protected: char *getStringSetting(int intDeviceId, const char* name, bool parameter); diff --git a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp index 83d58202..447bb9d8 100644 --- a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp @@ -9,7 +9,7 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "TelldusSettings.h" +#include "Settings.h" #include #include #include @@ -28,7 +28,7 @@ const char* CONFIG_FILE = "/etc/tellstick.conf"; /* * Constructor */ -TelldusSettings::TelldusSettings(void) +Settings::Settings(void) { d = new privateVars(); readConfig(&d->cfg); @@ -37,7 +37,7 @@ TelldusSettings::TelldusSettings(void) /* * Destructor */ -TelldusSettings::~TelldusSettings(void) +Settings::~Settings(void) { if (d->cfg > 0) cfg_free(d->cfg); @@ -47,7 +47,7 @@ TelldusSettings::~TelldusSettings(void) /* * Return a setting */ -char *TelldusSettings::getSetting(const char *strName) { +const char *Settings::getSetting(const char *strName) { if (d->cfg > 0) { return cfg_getstr(d->cfg, strName); } @@ -57,14 +57,14 @@ char *TelldusSettings::getSetting(const char *strName) { /* * Return the number of stored devices */ -int TelldusSettings::getNumberOfDevices(void){ +int Settings::getNumberOfDevices(void){ if (d->cfg > 0) { return cfg_size(d->cfg, "device"); } return 0; } -int TelldusSettings::getDeviceId(int intDeviceIndex){ +int Settings::getDeviceId(int intDeviceIndex){ if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds return -1; } @@ -76,7 +76,7 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ /* * Add a new device */ -int TelldusSettings::addDevice(){ +int Settings::addDevice(){ int intDeviceId = getNextDeviceId(); FILE *fp = fopen(CONFIG_FILE, "w"); @@ -93,7 +93,7 @@ int TelldusSettings::addDevice(){ /* * Get next available device id */ -int TelldusSettings::getNextDeviceId(){ +int Settings::getNextDeviceId(){ int intDeviceId = 0; cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { @@ -109,7 +109,7 @@ int TelldusSettings::getNextDeviceId(){ /* * Remove a device */ -bool TelldusSettings::removeDevice(int intDeviceId){ +bool Settings::removeDevice(int intDeviceId){ bool blnSuccess = true; FILE *fp = fopen(CONFIG_FILE, "w"); @@ -141,7 +141,7 @@ bool TelldusSettings::removeDevice(int intDeviceId){ return blnSuccess; } -char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { +char *Settings::getStringSetting(int intDeviceId, const char* name, bool parameter) { if (d->cfg == 0) { return NULL; } @@ -164,7 +164,7 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool return NULL; } -bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { +bool Settings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { if (d->cfg == 0) { return false; } @@ -187,7 +187,7 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const return false; } -int TelldusSettings::getIntSetting(int intDeviceId, const char* name, bool parameter) { +int Settings::getIntSetting(int intDeviceId, const char* name, bool parameter) { if (d->cfg == 0) { return 0; } @@ -204,7 +204,7 @@ int TelldusSettings::getIntSetting(int intDeviceId, const char* name, bool param return 0; } -bool TelldusSettings::setIntSetting(int intDeviceId, const char* name, int value, bool parameter) { +bool Settings::setIntSetting(int intDeviceId, const char* name, int value, bool parameter) { if (d->cfg == 0) { return false; } diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 1f6ce419..96be1381 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -9,7 +9,7 @@ #include #endif #include "telldus-core.h" -#include "settings/TelldusSettings.h" +#include "Settings.h" #include "Device.h" #include #include @@ -72,11 +72,11 @@ using namespace std; int WINAPI tdTurnOn(int intDeviceId){ try{ - TelldusSettings ts; + Settings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model ); + int methods = dev->methods( model, TELLSTICK_TURNON ); int retval = 0; @@ -88,8 +88,7 @@ int WINAPI tdTurnOn(int intDeviceId){ delete(dev); return retval; - } - else{ + } else{ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } @@ -108,11 +107,11 @@ int WINAPI tdTurnOn(int intDeviceId){ int WINAPI tdTurnOff(int intDeviceId){ try{ - TelldusSettings ts; + Settings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model ); + int methods = dev->methods( model, TELLSTICK_TURNOFF ); int retval = 0; if ( !(methods & TELLSTICK_TURNOFF) ) { @@ -143,11 +142,11 @@ int WINAPI tdTurnOff(int intDeviceId){ int WINAPI tdBell(int intDeviceId){ try{ - TelldusSettings ts; + Settings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model ); + int methods = dev->methods( model, TELLSTICK_BELL ); int retval = 0; if ( !(methods & TELLSTICK_BELL) ) { @@ -178,11 +177,11 @@ int WINAPI tdBell(int intDeviceId){ */ int WINAPI tdDim(int intDeviceId, unsigned char level){ try{ - TelldusSettings ts; + Settings ts; Device* dev = ts.getDevice(intDeviceId); if(dev != NULL){ int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model ); + int methods = dev->methods( model, TELLSTICK_DIM ); int retval = 0; if ( !(methods & TELLSTICK_DIM) ) { @@ -217,7 +216,7 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ int WINAPI tdGetNumberOfDevices(void){ int intReturn = -1; try{ - TelldusSettings ts; + Settings ts; intReturn = ts.getNumberOfDevices(); } catch(exception e){ @@ -243,7 +242,7 @@ int WINAPI tdGetNumberOfDevices(void){ int WINAPI tdGetDeviceId(int intDeviceIndex){ int intReturn = -1; try{ - TelldusSettings ts; + Settings ts; intReturn = ts.getDeviceId(intDeviceIndex); } catch(exception e){ @@ -261,7 +260,7 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ char * WINAPI tdGetName(int intDeviceId){ char* strReturn; try{ - TelldusSettings ts; + Settings ts; strReturn = ts.getName(intDeviceId); #ifdef _WINDOWS strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); @@ -277,7 +276,7 @@ char * WINAPI tdGetName(int intDeviceId){ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ bool blnSuccess = false; try{ - TelldusSettings ts; + Settings ts; blnSuccess = ts.setName(intDeviceId, strNewName); } catch(exception e){ @@ -290,7 +289,7 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ char* WINAPI tdGetProtocol(int intDeviceId){ char* strReturn = ""; try{ - TelldusSettings ts; + Settings ts; strReturn = ts.getProtocol(intDeviceId); #ifdef _WINDOWS strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); @@ -306,7 +305,7 @@ char* WINAPI tdGetProtocol(int intDeviceId){ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ bool blnSuccess = false; try{ - TelldusSettings ts; + Settings ts; blnSuccess = ts.setProtocol(intDeviceId, strProtocol); } catch(exception e){ @@ -319,7 +318,7 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ int WINAPI tdGetModel(int intDeviceId){ int intReturn = 0; try{ - TelldusSettings ts; + Settings ts; intReturn = ts.getModel(intDeviceId); } catch(exception e){ @@ -332,7 +331,7 @@ int WINAPI tdGetModel(int intDeviceId){ bool WINAPI tdSetModel(int intDeviceId, int intModel){ bool blnSuccess = false; try{ - TelldusSettings ts; + Settings ts; blnSuccess = ts.setModel(intDeviceId, intModel); } catch(exception e){ @@ -345,7 +344,7 @@ bool WINAPI tdSetModel(int intDeviceId, int intModel){ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ try{ - TelldusSettings ts; + Settings ts; return ts.setDeviceParameter(intDeviceId, strName, strValue); } catch(exception e){ @@ -357,7 +356,7 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ char *strReturn = ""; try{ - TelldusSettings ts; + Settings ts; strReturn = ts.getDeviceParameter(intDeviceId, strName); if (strReturn == NULL) { strReturn = strdup(defaultValue); @@ -375,7 +374,7 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c int WINAPI tdAddDevice(){ int intNewDeviceId = -1; try{ - TelldusSettings ts; + Settings ts; intNewDeviceId = ts.addDevice(); } catch(exception e){ @@ -388,7 +387,7 @@ int WINAPI tdAddDevice(){ bool WINAPI tdRemoveDevice(int intDeviceId){ bool blnSuccess = false; try{ - TelldusSettings ts; + Settings ts; blnSuccess = ts.removeDevice(intDeviceId); } catch(exception e){ @@ -399,8 +398,17 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ } /** - * Query a device for which methods it supports. + * Query a device for which methods it supports. By supplying the methods you support + * the library could remap the methods a device support for better fit the application. + * Example of querying a device supporting TELLSTICK_BELL: + * \code + * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); + * //methods is now TELLSTICK_BELL + * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); + * //methods is now TELLSTICK_TURNON because the client application doesn't support TELLSTICK_BELL + * \endcode * @param id The device id to query + * @param methodsSupported The methods the client application supports * @returns The method-flags OR'ed into an integer. * @sa TELLSTICK_TURNON * @sa TELLSTICK_TURNOFF @@ -408,21 +416,22 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_TOGGLE * @sa TELLSTICK_DIM */ -int WINAPI tdMethods(int id){ +int WINAPI tdMethods(int id, int methodsSupported){ int intMethods = 0; try{ - TelldusSettings ts; + Settings ts; int intModel = ts.getModel(id); Device* dev = ts.getDevice(id); if (dev != NULL) { - intMethods = dev->methods(intModel); + intMethods = dev->methods(intModel, methodsSupported); } } catch(exception e){ intMethods = 0; handleException(e); } + intMethods = intMethods & methodsSupported; //Strip the methods not supported by client. return intMethods; } diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index a2263803..dba36ce6 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -28,7 +28,7 @@ extern "C" { TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); TELLSTICK_API int WINAPI tdBell(int intDeviceId); TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); - TELLSTICK_API int WINAPI tdMethods(int id); + TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); TELLSTICK_API int WINAPI tdGetNumberOfDevices(); TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); From 65c0851e697eb98b6cdfb05fce7907b1f111f089 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 14:55:39 +0000 Subject: [PATCH 0715/2215] Added extra parameter to Device::methods() and made it pure virtual in the base class --- telldus-core/driver/libtelldus-core/Device.cpp | 7 ------- telldus-core/driver/libtelldus-core/Device.h | 6 +++++- telldus-core/driver/libtelldus-core/DeviceIkea.cpp | 2 +- telldus-core/driver/libtelldus-core/DeviceIkea.h | 2 +- telldus-core/driver/libtelldus-core/DeviceNexa.cpp | 8 ++++++-- telldus-core/driver/libtelldus-core/DeviceNexa.h | 2 +- telldus-core/driver/libtelldus-core/DeviceSartano.cpp | 2 +- telldus-core/driver/libtelldus-core/DeviceSartano.h | 2 +- telldus-core/driver/libtelldus-core/DeviceWaveman.cpp | 2 +- telldus-core/driver/libtelldus-core/DeviceWaveman.h | 2 +- 10 files changed, 18 insertions(+), 17 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 6e7b60c7..b3fbea15 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -50,10 +50,3 @@ int Device::bell(void){ int Device::dim(unsigned char level){ return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } - -/* -* Methods, virtual -*/ -int Device::methods(int intModel){ - return 0; -} diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index ec44749e..8bf86fcc 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -1,6 +1,7 @@ #pragma once #include "telldus-core.h" +//#include class Device { @@ -12,7 +13,7 @@ public: virtual int turnOff(void); virtual int bell(void); virtual int dim(unsigned char level); - virtual int methods(int intModel); + virtual int methods(int intModel, int methodsSupported) = 0; #ifdef _LINUX void setDevice(const char *device); @@ -22,4 +23,7 @@ protected: protected: int send(char* strMessage); + +//private: +// static QMutex deviceMutex; }; diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index 14071dd4..f1b85b9b 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -194,7 +194,7 @@ string DeviceIkea::getStringCode(unsigned char level){ /* * Has the device got the method? */ -int DeviceIkea::methods(int intModel){ +int DeviceIkea::methods(int intModel, int){ if(intModel == TELLSTICK_DEVICE_KOPPLA) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index 669e1840..b730dce3 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -9,7 +9,7 @@ public: virtual int turnOn(void); virtual int turnOff(void); virtual int dim(unsigned char level); - virtual int methods(int intModel); + virtual int methods(int intModel, int methodsSupported); public: ~DeviceIkea(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 9e2e02ec..d1b90754 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -145,7 +145,7 @@ string DeviceNexa::getStringCode(int intToConvert){ /* * Has the device got the method? */ -int DeviceNexa::methods(int intModel){ +int DeviceNexa::methods(int intModel, int methodsSupported){ if( (intModel == TELLSTICK_DEVICE_YCR3500) || (intModel == TELLSTICK_DEVICE_YCR300D) || @@ -175,7 +175,11 @@ int DeviceNexa::methods(int intModel){ { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } else if ( intModel == TELLSTICK_DEVICE_ML7100) { - return TELLSTICK_BELL; + if (methodsSupported & TELLSTICK_BELL) { + return TELLSTICK_BELL; + } else if (methodsSupported & TELLSTICK_TURNON) { + return TELLSTICK_TURNON; + } } return 0; } diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index fa520ac2..60a689c9 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -9,7 +9,7 @@ public: virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); - virtual int methods(int intModel); + virtual int methods(int intModel, int methodsSupported); public: ~DeviceNexa(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index fc8c3da5..be0dd440 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -67,7 +67,7 @@ int DeviceSartano::turnOff(void){ /* * Has the device got the method? */ -int DeviceSartano::methods(int){ +int DeviceSartano::methods(int, int){ return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index 490d08ea..0b6b1798 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -9,7 +9,7 @@ public: DeviceSartano(char *strCode); virtual int turnOn(void); virtual int turnOff(void); - virtual int methods(int strModel); + virtual int methods(int strModel, int methodsSupported); ~DeviceSartano(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index 115c1db2..5d13a7b5 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -41,6 +41,6 @@ int DeviceWaveman::turnOff(void){ /* * Has the device got the method? */ -int DeviceWaveman::methods(int intModel){ +int DeviceWaveman::methods(int intModel, int){ return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index b8e5f63e..3ad4d5ae 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -7,5 +7,5 @@ class DeviceWaveman : public DeviceNexa public: DeviceWaveman(char *strHouse, char *strCode); virtual int turnOff(void); - virtual int methods(int intModel); + virtual int methods(int intModel, int methodsSupported); }; From b7ac3082c139841262e32d83a589483ee9994da8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 20:50:44 +0000 Subject: [PATCH 0716/2215] Created a Manager class and moved Settings::getDevice() to it --- .../driver/libtelldus-core/Manager.cpp | 117 ++++++++++++++++++ telldus-core/driver/libtelldus-core/Manager.h | 42 +++++++ .../driver/libtelldus-core/Settings.cpp | 66 ---------- .../driver/libtelldus-core/Settings.h | 1 - 4 files changed, 159 insertions(+), 67 deletions(-) create mode 100644 telldus-core/driver/libtelldus-core/Manager.cpp create mode 100644 telldus-core/driver/libtelldus-core/Manager.h diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp new file mode 100644 index 00000000..e54adf9f --- /dev/null +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -0,0 +1,117 @@ +// +// C++ Implementation: controller +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "Manager.h" +#include "Device.h" + +#include "DeviceNexa.h" +#include "DeviceWaveman.h" +#include "DeviceSartano.h" +#include "DeviceIkea.h" + + +#include +#include +#include + +Manager *Manager::instance = 0; + +Manager::Manager() { +} + +Manager::~Manager() { + // Clean up the device-map + for (DeviceMap::iterator it = devices.begin(); it != devices.end(); ++it) { + delete( it->second ); + } +} + +/** + * Get the requested device + * Note that the Manager keeps ownership of the returned Device + * and should not be deleted when not in use anymore. + **/ +Device *Manager::getDevice(int intDeviceId){ + Device* dev = NULL; + + DeviceMap::iterator iterator = devices.find(intDeviceId); + if (iterator != devices.end()) { + return iterator->second; + } + + try{ + char* protocol = settings.getProtocol(intDeviceId); + if (protocol == NULL) { + return NULL; + } + + //each new brand must be added here + if (strcasecmp(protocol, "arctech") == 0){ + char *strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); + char *strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); + dev = new DeviceNexa(strHouse, strCode); + free(strHouse); + free(strCode); + + } else if (strcasecmp(protocol, "Waveman") == 0) { + char *strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); + char *strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); + dev = new DeviceWaveman(strHouse, strCode); + free(strHouse); + free(strCode); + + } else if (strcasecmp(protocol, "Sartano") == 0) { + char *strCode = settings.getDeviceParameter(intDeviceId, "sartano_code"); + dev = new DeviceSartano(strCode); + free(strCode); + + } else if (strcasecmp(protocol, "Ikea") == 0) { + char *strSystem = settings.getDeviceParameter(intDeviceId, "ikea_system"); + char *strUnits = settings.getDeviceParameter(intDeviceId, "ikea_units"); + char *strFade = settings.getDeviceParameter(intDeviceId, "ikea_fade"); + dev = new DeviceIkea(strSystem, strUnits, strFade); + free(strSystem); + free(strUnits); + free(strFade); + + } else { + free(protocol); + return NULL; + } + free(protocol); + +#ifdef _LINUX + dev->setDevice( settings.getSetting("deviceNode") ); +#endif + + } + catch(...){ + throw; + } + + devices[intDeviceId] = dev; + return dev; +} + +Manager *Manager::getInstance() { + if (Manager::instance == 0) { + Manager::instance = new Manager(); + } + return Manager::instance; +} + +void Manager::close() { + if (Manager::instance != 0) { + delete Manager::instance; + } +} + + diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h new file mode 100644 index 00000000..9691b3b9 --- /dev/null +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -0,0 +1,42 @@ +// +// C++ Interface: controller +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef MANAGER_H +#define MANAGER_H + +#include "Settings.h" +#include +class Device; + +typedef std::map DeviceMap; + +/** + @author Micke Prag +*/ +class Manager { +public: + ~Manager(); + + Device *getDevice(int deviceId); + + static Manager *getInstance(); + static void close(); + +private: + Manager(); + + Settings settings; + DeviceMap devices; + + static Manager *instance; +}; + +#endif diff --git a/telldus-core/driver/libtelldus-core/Settings.cpp b/telldus-core/driver/libtelldus-core/Settings.cpp index fd654056..448d1a1f 100644 --- a/telldus-core/driver/libtelldus-core/Settings.cpp +++ b/telldus-core/driver/libtelldus-core/Settings.cpp @@ -1,70 +1,4 @@ #include "Settings.h" -#include "DeviceNexa.h" -#include "DeviceWaveman.h" -#include "DeviceSartano.h" -#include "DeviceIkea.h" -#include -#include - -/* -* Get the requested device -* Note that the returned Device should be deleted when not in use anymore -*/ -Device* Settings::getDevice(int intDeviceId){ - - Device* dev = NULL; - - try{ - char* protocol = getProtocol(intDeviceId); - if (protocol == NULL) { - return NULL; - } - - //each new brand must be added here - if (strcasecmp(protocol, "arctech") == 0){ - char *strHouse = getDeviceParameter(intDeviceId, "nexa_house"); - char *strCode = getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceNexa(strHouse, strCode); - free(strHouse); - free(strCode); - - } else if (strcasecmp(protocol, "Waveman") == 0) { - char *strHouse = getDeviceParameter(intDeviceId, "nexa_house"); - char *strCode = getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceWaveman(strHouse, strCode); - free(strHouse); - free(strCode); - - } else if (strcasecmp(protocol, "Sartano") == 0) { - char *strCode = getDeviceParameter(intDeviceId, "sartano_code"); - dev = new DeviceSartano(strCode); - free(strCode); - - } else if (strcasecmp(protocol, "Ikea") == 0) { - char *strSystem = getDeviceParameter(intDeviceId, "ikea_system"); - char *strUnits = getDeviceParameter(intDeviceId, "ikea_units"); - char *strFade = getDeviceParameter(intDeviceId, "ikea_fade"); - dev = new DeviceIkea(strSystem, strUnits, strFade); - free(strSystem); - free(strUnits); - free(strFade); - - } else { - free(protocol); - return NULL; - } - free(protocol); - -#ifdef _LINUX - dev->setDevice( getSetting("deviceNode") ); -#endif - - } - catch(...){ - throw; - } - return dev; -} /* * Get the name of the device diff --git a/telldus-core/driver/libtelldus-core/Settings.h b/telldus-core/driver/libtelldus-core/Settings.h index 9bca8f41..9798d295 100644 --- a/telldus-core/driver/libtelldus-core/Settings.h +++ b/telldus-core/driver/libtelldus-core/Settings.h @@ -11,7 +11,6 @@ public: Settings(void); const char * getSetting(const char *strName); int getNumberOfDevices(void); - Device* getDevice(int intDeviceId); char* getName(int intDeviceId); bool setName(int intDeviceId, const char* strNewName); char* getProtocol(int intDeviceId); From 8d3593cea3e4cb2d2ae6a2bb40a88fc799d1df62 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 20:55:26 +0000 Subject: [PATCH 0717/2215] Added Device::getProtocol() and Device::getModel() --- telldus-core/driver/libtelldus-core/Device.cpp | 4 ++++ telldus-core/driver/libtelldus-core/Device.h | 5 ++++- telldus-core/driver/libtelldus-core/DeviceIkea.cpp | 8 ++++++-- telldus-core/driver/libtelldus-core/DeviceIkea.h | 3 ++- telldus-core/driver/libtelldus-core/DeviceNexa.cpp | 9 +++++++-- telldus-core/driver/libtelldus-core/DeviceNexa.h | 3 ++- telldus-core/driver/libtelldus-core/DeviceSartano.cpp | 6 +++++- telldus-core/driver/libtelldus-core/DeviceSartano.h | 3 ++- telldus-core/driver/libtelldus-core/DeviceWaveman.cpp | 2 +- telldus-core/driver/libtelldus-core/DeviceWaveman.h | 2 +- 10 files changed, 34 insertions(+), 11 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index b3fbea15..341fb82e 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -23,6 +23,10 @@ Device::~Device(void) #endif } +int Device::getModel() { + return 1; +} + /* * Turn on, virtual */ diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 8bf86fcc..401f3947 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -1,6 +1,7 @@ #pragma once #include "telldus-core.h" +#include //#include class Device @@ -13,7 +14,9 @@ public: virtual int turnOff(void); virtual int bell(void); virtual int dim(unsigned char level); - virtual int methods(int intModel, int methodsSupported) = 0; + virtual int methods(int methodsSupported) = 0; + virtual std::string getProtocol() = 0; + int getModel(); #ifdef _LINUX void setDevice(const char *device); diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index f1b85b9b..7e7076fe 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -194,10 +194,14 @@ string DeviceIkea::getStringCode(unsigned char level){ /* * Has the device got the method? */ -int DeviceIkea::methods(int intModel, int){ +int DeviceIkea::methods(int){ - if(intModel == TELLSTICK_DEVICE_KOPPLA) { + if(this->getModel() == TELLSTICK_DEVICE_KOPPLA) { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); } return 0; } + +std::string DeviceIkea::getProtocol() { + return "ikea"; +} diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index b730dce3..fca10f9f 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -9,7 +9,8 @@ public: virtual int turnOn(void); virtual int turnOff(void); virtual int dim(unsigned char level); - virtual int methods(int intModel, int methodsSupported); + virtual int methods(int methodsSupported); + virtual std::string getProtocol(); public: ~DeviceIkea(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index d1b90754..931d12a6 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -145,8 +145,9 @@ string DeviceNexa::getStringCode(int intToConvert){ /* * Has the device got the method? */ -int DeviceNexa::methods(int intModel, int methodsSupported){ - +int DeviceNexa::methods(int methodsSupported){ + int intModel = this->getModel(); + if( (intModel == TELLSTICK_DEVICE_YCR3500) || (intModel == TELLSTICK_DEVICE_YCR300D) || (intModel == TELLSTICK_DEVICE_WSR1000) || @@ -183,3 +184,7 @@ int DeviceNexa::methods(int intModel, int methodsSupported){ } return 0; } + +std::string DeviceNexa::getProtocol() { + return "arctech"; +} diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 60a689c9..ec7ca283 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -9,7 +9,8 @@ public: virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); - virtual int methods(int intModel, int methodsSupported); + virtual int methods(int methodsSupported); + virtual std::string getProtocol(); public: ~DeviceNexa(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index be0dd440..33dfa332 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -67,7 +67,7 @@ int DeviceSartano::turnOff(void){ /* * Has the device got the method? */ -int DeviceSartano::methods(int, int){ +int DeviceSartano::methods(int){ return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } @@ -98,3 +98,7 @@ string DeviceSartano::getStringCode(void){ } +std::string DeviceSartano::getProtocol() { + return "sartano"; +} + diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index 0b6b1798..18fe61a0 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -9,7 +9,8 @@ public: DeviceSartano(char *strCode); virtual int turnOn(void); virtual int turnOff(void); - virtual int methods(int strModel, int methodsSupported); + virtual int methods(int methodsSupported); + virtual std::string getProtocol(); ~DeviceSartano(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index 5d13a7b5..dd80a588 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -41,6 +41,6 @@ int DeviceWaveman::turnOff(void){ /* * Has the device got the method? */ -int DeviceWaveman::methods(int intModel, int){ +int DeviceWaveman::methods(int){ return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); } diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index 3ad4d5ae..ac8e81de 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -7,5 +7,5 @@ class DeviceWaveman : public DeviceNexa public: DeviceWaveman(char *strHouse, char *strCode); virtual int turnOff(void); - virtual int methods(int intModel, int methodsSupported); + virtual int methods(int methodsSupported); }; From 74a84904b311f7879d0778c88862684865786e1d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Jan 2009 20:58:35 +0000 Subject: [PATCH 0718/2215] * Added class Manager to CMakeLists.txt * Used the Manager class in the exported functions in telldus-core * Used std::string instead of char * in some places. This is the prefered way in telldus-core. Added a inline wrapper function for converting std::string to char * for exporting to the C API --- .../driver/libtelldus-core/CMakeLists.txt | 1 + .../driver/libtelldus-core/linux/Device.cpp | 2 + .../driver/libtelldus-core/telldus-core.cpp | 92 ++++++++++--------- .../driver/libtelldus-core/telldus-core.h | 1 + 4 files changed, 54 insertions(+), 42 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index e6e3b426..57151b6c 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -9,6 +9,7 @@ SET( telldus-core_SRCS DeviceNexa.cpp DeviceSartano.cpp DeviceWaveman.cpp + Manager.cpp Settings.cpp telldus-core.cpp ) diff --git a/telldus-core/driver/libtelldus-core/linux/Device.cpp b/telldus-core/driver/libtelldus-core/linux/Device.cpp index 2e1446c6..e7866709 100644 --- a/telldus-core/driver/libtelldus-core/linux/Device.cpp +++ b/telldus-core/driver/libtelldus-core/linux/Device.cpp @@ -33,6 +33,8 @@ int Device::send(char* strMessage) { close(fd); + sleep(1); + return TELLSTICK_SUCCESS; } diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 96be1381..b0e5bde1 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -9,7 +9,7 @@ #include #endif #include "telldus-core.h" -#include "Settings.h" +#include "Manager.h" #include "Device.h" #include #include @@ -20,6 +20,8 @@ void handleException(std::exception e); using namespace std; +char *wrapStdString( const std::string &string); + /** * @def TELLSTICK_TURNON * Device-flag for devices supporting the tdTurnOn() call. @@ -59,9 +61,13 @@ using namespace std; #define MAX_LOADSTRING 100 -//TODO: -//delete on created objects -//comment (just copy from the called methods) +/** + * Close the library and clean up the cache it uses. + * This should be called when the library is not supposed to be used anymore + **/ +void WINAPI tdClose(void) { + Manager::close(); +} /** * Turns a device on. @@ -72,11 +78,11 @@ using namespace std; int WINAPI tdTurnOn(int intDeviceId){ try{ - Settings ts; - Device* dev = ts.getDevice(intDeviceId); + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); if(dev != NULL){ - int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model, TELLSTICK_TURNON ); + int model = dev->getModel(); + int methods = dev->methods( TELLSTICK_TURNON ); int retval = 0; @@ -86,7 +92,6 @@ int WINAPI tdTurnOn(int intDeviceId){ retval = dev->turnOn(); } - delete(dev); return retval; } else{ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -107,11 +112,11 @@ int WINAPI tdTurnOn(int intDeviceId){ int WINAPI tdTurnOff(int intDeviceId){ try{ - Settings ts; - Device* dev = ts.getDevice(intDeviceId); + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); if(dev != NULL){ - int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model, TELLSTICK_TURNOFF ); + int model = dev->getModel( ); + int methods = dev->methods( TELLSTICK_TURNOFF ); int retval = 0; if ( !(methods & TELLSTICK_TURNOFF) ) { @@ -120,7 +125,6 @@ int WINAPI tdTurnOff(int intDeviceId){ retval = dev->turnOff(); } - delete(dev); return retval; } else{ @@ -142,11 +146,10 @@ int WINAPI tdTurnOff(int intDeviceId){ int WINAPI tdBell(int intDeviceId){ try{ - Settings ts; - Device* dev = ts.getDevice(intDeviceId); + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); if(dev != NULL){ - int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model, TELLSTICK_BELL ); + int methods = dev->methods( TELLSTICK_BELL ); int retval = 0; if ( !(methods & TELLSTICK_BELL) ) { @@ -155,7 +158,6 @@ int WINAPI tdBell(int intDeviceId){ retval = dev->bell(); } - delete(dev); return retval; } else{ @@ -177,11 +179,10 @@ int WINAPI tdBell(int intDeviceId){ */ int WINAPI tdDim(int intDeviceId, unsigned char level){ try{ - Settings ts; - Device* dev = ts.getDevice(intDeviceId); + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); if(dev != NULL){ - int model = ts.getModel( intDeviceId ); - int methods = dev->methods( model, TELLSTICK_DIM ); + int methods = dev->methods( TELLSTICK_DIM ); int retval = 0; if ( !(methods & TELLSTICK_DIM) ) { @@ -196,7 +197,6 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ } } - delete(dev); return retval; } else{ @@ -258,19 +258,18 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ * @returns The name of the device or an empty string if the device is not found. */ char * WINAPI tdGetName(int intDeviceId){ - char* strReturn; + std::string strReturn; try{ Settings ts; - strReturn = ts.getName(intDeviceId); -#ifdef _WINDOWS - strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); -#endif + char *name = ts.getName(intDeviceId); + strReturn = name; + free(name); } catch(exception e){ strReturn = ""; handleException(e); } - return strReturn; + return wrapStdString(strReturn); } bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ @@ -287,19 +286,18 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ } char* WINAPI tdGetProtocol(int intDeviceId){ - char* strReturn = ""; + std::string strReturn = ""; try{ - Settings ts; - strReturn = ts.getProtocol(intDeviceId); -#ifdef _WINDOWS - strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); -#endif + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if (dev != NULL) { + strReturn = dev->getProtocol(); + } } catch(exception e){ - strReturn = ""; handleException(e); } - return strReturn; + return wrapStdString(strReturn); } bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ @@ -420,11 +418,10 @@ int WINAPI tdMethods(int id, int methodsSupported){ int intMethods = 0; try{ - Settings ts; - int intModel = ts.getModel(id); - Device* dev = ts.getDevice(id); + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(id); if (dev != NULL) { - intMethods = dev->methods(intModel, methodsSupported); + intMethods = dev->methods(methodsSupported); } } catch(exception e){ @@ -490,4 +487,15 @@ void handleException(exception e){ } } +inline char *wrapStdString( const std::string &string) { + char *returnVal; +#ifdef _WINDOWS + returnVal = (char *)SysAllocStringByteLen(string.c_str(), string.size()); +#else + returnVal = (char *)malloc(sizeof(char) * (string.size()+1)); + strcpy(returnVal, string.c_str()); +#endif + return returnVal; +} + /*\@}*/ diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index dba36ce6..68958c22 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -24,6 +24,7 @@ #ifdef __cplusplus extern "C" { #endif + TELLSTICK_API void WINAPI tdClose(void); TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); TELLSTICK_API int WINAPI tdBell(int intDeviceId); From bb73cb06e4ca21b47fdc93f98c4dfd38c0df11a1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 10:13:06 +0000 Subject: [PATCH 0719/2215] Switched to std::string in Device::send() --- telldus-core/driver/libtelldus-core/Device.h | 2 +- telldus-core/driver/libtelldus-core/linux/Device.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 401f3947..5b76eca1 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -25,7 +25,7 @@ protected: #endif protected: - int send(char* strMessage); + int send(const std::string &strMessage); //private: // static QMutex deviceMutex; diff --git a/telldus-core/driver/libtelldus-core/linux/Device.cpp b/telldus-core/driver/libtelldus-core/linux/Device.cpp index e7866709..ba36e231 100644 --- a/telldus-core/driver/libtelldus-core/linux/Device.cpp +++ b/telldus-core/driver/libtelldus-core/linux/Device.cpp @@ -8,7 +8,7 @@ /* * Send message to the USB dongle */ -int Device::send(char* strMessage) { +int Device::send(const std::string &strMessage) { int fd = -1; struct termios tio; @@ -29,7 +29,7 @@ int Device::send(char* strMessage) { tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&tio); - write(fd, strMessage, strlen(strMessage)); + write(fd, strMessage.c_str(), strMessage.length()); close(fd); From d0f59fe08ee343ae5fc10121d40fd2858df8b63e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 10:18:54 +0000 Subject: [PATCH 0720/2215] Switched to std::string in DeviceIkea --- .../driver/libtelldus-core/DeviceIkea.cpp | 36 +++++++++---------- .../driver/libtelldus-core/DeviceIkea.h | 2 +- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index 7e7076fe..ef147e63 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -6,8 +6,6 @@ #include #include -using namespace std; - #ifdef _WINDOWS #define strcasecmp(x, y) _strcmpi(x, y) #endif @@ -15,18 +13,21 @@ using namespace std; /* * Constructor */ -DeviceIkea::DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle) +DeviceIkea::DeviceIkea(const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle) :Device() { - if (strSystem != NULL && strlen(strSystem) > 0) { - intSystem = atoi(strSystem) - 1; + if (strSystem.length() > 0) { + intSystem = atoi(strSystem.c_str()) - 1; } else { intSystem = 0; } - if (strUnits != NULL && strlen(strUnits) > 0) { + if (strUnits.length() > 0) { intUnits = 0; //Start without any units - char *strTemp = strtok(strUnits, ","); + char tempUnits[strUnits.size()]; + strUnits.copy(tempUnits, strUnits.length(), 0); + + char *strTemp = strtok(tempUnits, ","); do { int intUnit = atoi(strTemp); if (intUnit == 10) { @@ -34,8 +35,9 @@ DeviceIkea::DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle) } intUnits = intUnits | ( 1<<(9-intUnit) ); } while ( (strTemp = strtok(NULL, ",")) != NULL ); + } - if (strUnits != NULL && strlen(strUnits) > 0 && strcasecmp(strFadeStyle, "true") == 0) { + if (strUnits.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { intFadeStyle = 1; } else { intFadeStyle = 0; @@ -57,9 +59,7 @@ DeviceIkea::~DeviceIkea(void) */ int DeviceIkea::turnOn(void){ try{ - string strCode = getStringCode(255); - - char* strMessage = const_cast(strCode.c_str()); + std::string strMessage = getStringCode(255); return Device::send(strMessage); } @@ -74,9 +74,7 @@ int DeviceIkea::turnOn(void){ */ int DeviceIkea::turnOff(void){ try{ - string strCode = getStringCode(0); - - char* strMessage = const_cast(strCode.c_str()); + std::string strMessage = getStringCode(0); return Device::send(strMessage); } @@ -91,9 +89,7 @@ int DeviceIkea::turnOff(void){ */ int DeviceIkea::dim(unsigned char level){ try{ - string strCode = getStringCode(level); - - char* strMessage = const_cast(strCode.c_str()); + std::string strMessage = getStringCode(level); return Device::send(strMessage); } @@ -106,12 +102,12 @@ int DeviceIkea::dim(unsigned char level){ /* * Convert an integer to byte string where 0 is represented by ª and 1 by TT */ -string DeviceIkea::getStringCode(unsigned char level){ +std::string DeviceIkea::getStringCode(unsigned char level){ - string strReturn = "STTTTTTª"; //Startcode, always like this; + std::string strReturn = "STTTTTTª"; //Startcode, always like this; try{ - string strChannels = ""; + std::string strChannels = ""; int intCode = (intSystem << 10) | intUnits; int checksum1 = 0; int checksum2 = 0; diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index fca10f9f..8775b9d5 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -5,7 +5,7 @@ class DeviceIkea : public Device { public: - DeviceIkea(char *strSystem, char *strUnits, char *strFadeStyle); + DeviceIkea(const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); virtual int turnOn(void); virtual int turnOff(void); virtual int dim(unsigned char level); From d4ecd2ad5195660febbfca6de85e5cc472d9458f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 10:26:55 +0000 Subject: [PATCH 0721/2215] Switched to std::string in DeviceNexa --- .../driver/libtelldus-core/DeviceNexa.cpp | 59 ++++++++----------- .../driver/libtelldus-core/DeviceNexa.h | 2 +- 2 files changed, 25 insertions(+), 36 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 931d12a6..67bc1b7d 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -6,22 +6,20 @@ #include #include -using namespace std; - /* * Constructor */ -DeviceNexa::DeviceNexa(char *strNewHouse, char *strNewCode) +DeviceNexa::DeviceNexa(const std::string &strHouse, const std::string &strCode) :Device() { - if (strNewHouse != NULL && strlen(strNewHouse) > 0) { - intHouse = strNewHouse[0] - 'A'; + if (strHouse.length() > 0) { + intHouse = strHouse[0] - 'A'; } else { intHouse = 0; } - if (strNewCode != NULL && strlen(strNewCode) > 0) { - intCode = atoi(strNewCode) - 1; + if (strCode.length() > 0) { + intCode = atoi(strCode.c_str()) - 1; } else { intCode = 0; } @@ -31,10 +29,7 @@ DeviceNexa::DeviceNexa(char *strNewHouse, char *strNewCode) * Destructor */ DeviceNexa::~DeviceNexa(void) -{ -// intHouse = -1; -// intCode = -1; -} +{} /* * Turn on this device @@ -42,16 +37,14 @@ DeviceNexa::~DeviceNexa(void) int DeviceNexa::turnOn(void){ try{ - string strCode = getStringCode(intHouse); - string strUnit = getStringCode(intCode); + std::string strCode = getStringCode(intHouse); + std::string strUnit = getStringCode(intCode); strCode.append(strUnit); strCode.insert(0, "S"); strCode.append("$k$k$kk$$kk$$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strCode.c_str()); - - return Device::send(strMessage); + return Device::send(strCode); } catch(...){ throw; @@ -65,16 +58,14 @@ int DeviceNexa::turnOn(void){ int DeviceNexa::turnOff(void){ try{ - string strCode = getStringCode(intHouse); - string strUnit = getStringCode(intCode); + std::string strCode = getStringCode(intHouse); + std::string strUnit = getStringCode(intCode); strCode.append(strUnit); strCode.insert(0, "S"); strCode.append("$k$k$kk$$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strCode.c_str()); - - return Device::send(strMessage); + return Device::send(strCode); } catch(...){ throw; @@ -88,15 +79,13 @@ int DeviceNexa::turnOff(void){ int DeviceNexa::bell(void){ try{ - string strCode = getStringCode(intHouse); + std::string strCode = getStringCode(intHouse); strCode.append("$kk$$kk$$kk$$k$k"); //the unit-code is always 7, doesn't have to be regenerated each time strCode.insert(0, "S"); strCode.append("$kk$$kk$$kk$$kk$$k+"); //the "bell"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strCode.c_str()); - - return Device::send(strMessage); + return Device::send(strCode); } catch(...){ throw; @@ -107,30 +96,30 @@ int DeviceNexa::bell(void){ /* * Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed */ -string DeviceNexa::getStringCode(int intToConvert){ +std::string DeviceNexa::getStringCode(int intToConvert){ - string strReturn = ""; + std::string strReturn = ""; try{ - bitset<4> bs ((long)intToConvert); + std::bitset<4> bs ((long)intToConvert); strReturn = bs.to_string(); reverse(strReturn.begin(), strReturn.end()); - int intPos = (int)strReturn.find("0"); - while (intPos < string::npos){ + size_t intPos = strReturn.find("0"); + while (intPos < std::string::npos){ strReturn.replace(intPos, 1, "$k"); - intPos = (int)strReturn.find("0", intPos + 1); + intPos = strReturn.find("0", intPos + 1); } - intPos = (int)strReturn.find("1"); - while (intPos < string::npos){ + intPos = strReturn.find("1"); + while (intPos < std::string::npos){ strReturn.replace(intPos, 1, "k$"); - intPos = (int)strReturn.find("1", intPos + 1); + intPos = strReturn.find("1", intPos + 1); } intPos = 0; - while (intPos < (int)strReturn.length()){ + while (intPos < strReturn.length()){ strReturn.insert(intPos, "$k"); intPos = intPos + 4; } diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index ec7ca283..0c81f457 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -5,7 +5,7 @@ class DeviceNexa : public Device { public: - DeviceNexa(char *strHouse, char *strCode); + DeviceNexa(const std::string &strHouse, const std::string &strCode); virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); From ca391ae7a2f3c16c0ecf4b8fa000b7b1a9d1b635 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 10:31:20 +0000 Subject: [PATCH 0722/2215] Switched to std::string in DeviceSartano --- .../driver/libtelldus-core/DeviceSartano.cpp | 28 ++++++++----------- .../driver/libtelldus-core/DeviceSartano.h | 2 +- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index 33dfa332..ab8fd79a 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -10,7 +10,7 @@ using namespace std; /* * Constructor */ -DeviceSartano::DeviceSartano(char *strNewCode) +DeviceSartano::DeviceSartano(const std::string &strNewCode) :Device() { strCode = strNewCode; @@ -28,14 +28,12 @@ DeviceSartano::~DeviceSartano(void) int DeviceSartano::turnOn(void){ try{ - string strCode = getStringCode(); + std::string strCode = getStringCode(); strCode.insert(0, "S"); strCode.append("$k$k$kk$$k+"); //the "turn on"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strCode.c_str()); - - return Device::send(strMessage); + return Device::send(strCode); } catch(...){ throw; @@ -49,14 +47,12 @@ int DeviceSartano::turnOn(void){ int DeviceSartano::turnOff(void){ try{ - string strCode = getStringCode(); + std::string strCode = getStringCode(); strCode.insert(0, "S"); strCode.append("$kk$$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strCode.c_str()); - - return Device::send(strMessage); + return Device::send(strCode); } catch(...){ throw; @@ -76,19 +72,19 @@ int DeviceSartano::methods(int){ */ string DeviceSartano::getStringCode(void){ - string strReturn = strCode; + std::string strReturn = strCode; try{ - int intPos = (int)strReturn.find("0"); - while (intPos < string::npos){ + size_t intPos = strReturn.find("0"); + while (intPos < std::string::npos){ strReturn.replace(intPos, 1, "$kk$"); - intPos = (int)strReturn.find("0", intPos + 1); + intPos = strReturn.find("0", intPos + 1); } - intPos = (int)strReturn.find("1"); - while (intPos < string::npos){ + intPos = strReturn.find("1"); + while (intPos < std::string::npos){ strReturn.replace(intPos, 1, "$k$k"); - intPos = (int)strReturn.find("1", intPos + 1); + intPos = strReturn.find("1", intPos + 1); } } catch(...){ diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index 18fe61a0..ce61d675 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -6,7 +6,7 @@ class DeviceSartano : public Device { public: - DeviceSartano(char *strCode); + DeviceSartano(const std::string &strCode); virtual int turnOn(void); virtual int turnOff(void); virtual int methods(int methodsSupported); From 7dfb6611266076a1b950a32b217c542ab34c797f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 10:36:54 +0000 Subject: [PATCH 0723/2215] Switched to std::string in DeviceWaveman --- telldus-core/driver/libtelldus-core/DeviceWaveman.cpp | 8 +++----- telldus-core/driver/libtelldus-core/DeviceWaveman.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index dd80a588..64452093 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -11,8 +11,8 @@ using namespace std; /* * Constructor */ -DeviceWaveman::DeviceWaveman(char *strNewHouse, char *strNewCode) - :DeviceNexa(strNewHouse, strNewCode){ +DeviceWaveman::DeviceWaveman(const std::string &strHouse, const std::string &strCode) + :DeviceNexa(strHouse, strCode){ } /* @@ -28,9 +28,7 @@ int DeviceWaveman::turnOff(void){ strCode.insert(0, "S"); strCode.append("$k$k$k$k$k$k$k$k$k+"); //the "turn off"-code, keeps it like this, doesn't have to be regenerated each time - char* strMessage = const_cast(strCode.c_str()); - - return Device::send(strMessage); + return Device::send(strCode); } catch(...){ throw; diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index ac8e81de..5659e286 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -5,7 +5,7 @@ class DeviceWaveman : public DeviceNexa { public: - DeviceWaveman(char *strHouse, char *strCode); + DeviceWaveman(const std::string &strHouse, const std::string &strCode); virtual int turnOff(void); virtual int methods(int methodsSupported); }; From 32ee03ed5c54fcfc3c06e5a8e09f9d6c9caf70a3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 11:02:53 +0000 Subject: [PATCH 0724/2215] Switched to std::string in tdGetErrorString() --- telldus-core/driver/libtelldus-core/telldus-core.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index b0e5bde1..b741971c 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -453,20 +453,15 @@ char * WINAPI tdGetErrorString(int intErrorNo) { "Device not found", "The method you tried to use is not supported by the device" }; - char *strReturn; + std::string strReturn; intErrorNo = abs(intErrorNo); //We don't use negative values here. if (intErrorNo >= numResponses) { strReturn = "Unknown error"; } else { // Copy the error string to strReturn - strReturn = (char *)malloc( sizeof(char) * (strlen(responses[intErrorNo])+1) ); - strcpy( strReturn, responses[intErrorNo] ); + strReturn = responses[intErrorNo]; } - -#ifdef _WINDOWS - strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); -#endif - return strReturn; + return wrapStdString(strReturn); } From 7bdaeb9a6e7a03efc23a30e2e7078851bb7fcbe7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 11:25:51 +0000 Subject: [PATCH 0725/2215] Switched to std::string in Settings --- .../driver/libtelldus-core/Settings.cpp | 12 +++---- .../driver/libtelldus-core/Settings.h | 22 ++++++------- .../libtelldus-core/SettingsConfuse.cpp | 31 ++++++++----------- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Settings.cpp b/telldus-core/driver/libtelldus-core/Settings.cpp index 448d1a1f..30345070 100644 --- a/telldus-core/driver/libtelldus-core/Settings.cpp +++ b/telldus-core/driver/libtelldus-core/Settings.cpp @@ -3,28 +3,28 @@ /* * Get the name of the device */ -char* Settings::getName(int intDeviceId){ +std::string Settings::getName(int intDeviceId){ return getStringSetting(intDeviceId, "name", false); } /* * Set the name of the device */ -bool Settings::setName(int intDeviceId, const char* strNewName){ +bool Settings::setName(int intDeviceId, const std::string &strNewName){ return setStringSetting(intDeviceId, "name", strNewName, false); } /* * Get the device vendor */ -char* Settings::getProtocol(int intDeviceId){ +std::string Settings::getProtocol(int intDeviceId){ return getStringSetting(intDeviceId, "protocol", false); } /* * Set the device vendor */ -bool Settings::setProtocol(int intDeviceId, const char* strVendor){ +bool Settings::setProtocol(int intDeviceId, const std::string &strVendor){ return setStringSetting(intDeviceId, "protocol", strVendor, false); } @@ -45,13 +45,13 @@ bool Settings::setModel(int intDeviceId, int intModel){ /* * Set device argument */ -bool Settings::setDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ +bool Settings::setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue){ return setStringSetting(intDeviceId, strName, strValue, true); } /* * Get device argument */ -char* Settings::getDeviceParameter(int intDeviceId, const char *strName) { +std::string Settings::getDeviceParameter(int intDeviceId, const std::string &strName) { return getStringSetting(intDeviceId, strName, true); } diff --git a/telldus-core/driver/libtelldus-core/Settings.h b/telldus-core/driver/libtelldus-core/Settings.h index 9798d295..560e1a50 100644 --- a/telldus-core/driver/libtelldus-core/Settings.h +++ b/telldus-core/driver/libtelldus-core/Settings.h @@ -9,16 +9,16 @@ class Settings { public: Settings(void); - const char * getSetting(const char *strName); + std::string getSetting(const std::string &strName); int getNumberOfDevices(void); - char* getName(int intDeviceId); - bool setName(int intDeviceId, const char* strNewName); - char* getProtocol(int intDeviceId); - bool setProtocol(int intDeviceId, const char* strVendor); + std::string getName(int intDeviceId); + bool setName(int intDeviceId, const std::string &strNewName); + std::string getProtocol(int intDeviceId); + bool setProtocol(int intDeviceId, const std::string &strVendor); int getModel(int intDeviceId); bool setModel(int intDeviceId, int intModel); - char* getDeviceParameter(int intDeviceId, const char *strName); - bool setDeviceParameter(int intDeviceId, const char *strName, const char *strValue); + std::string getDeviceParameter(int intDeviceId, const std::string &strName); + bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); int addDevice(); int getDeviceId(int intDeviceIndex); bool removeDevice(int intDeviceId); @@ -26,10 +26,10 @@ public: ~Settings(void); protected: - char *getStringSetting(int intDeviceId, const char* name, bool parameter); - bool setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter); - int getIntSetting(int intDeviceId, const char* name, bool parameter); - bool setIntSetting(int intDeviceId, const char* name, int value, bool parameter); + std::string getStringSetting(int intDeviceId, const std::string &name, bool parameter); + bool setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter); + int getIntSetting(int intDeviceId, const std::string &name, bool parameter); + bool setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter); private: int getNextDeviceId(); diff --git a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp index 447bb9d8..7bf2c14e 100644 --- a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp @@ -47,9 +47,9 @@ Settings::~Settings(void) /* * Return a setting */ -const char *Settings::getSetting(const char *strName) { +std::string Settings::getSetting(const std::string &strName) { if (d->cfg > 0) { - return cfg_getstr(d->cfg, strName); + return cfg_getstr(d->cfg, strName.c_str()); } return ""; } @@ -141,7 +141,7 @@ bool Settings::removeDevice(int intDeviceId){ return blnSuccess; } -char *Settings::getStringSetting(int intDeviceId, const char* name, bool parameter) { +std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) { if (d->cfg == 0) { return NULL; } @@ -152,19 +152,14 @@ char *Settings::getStringSetting(int intDeviceId, const char* name, bool paramet if (parameter) { cfg_device = cfg_getsec(cfg_device, "parameters"); } - const char *strSetting = cfg_getstr(cfg_device, name); - if (strSetting == NULL) { - return NULL; - } - char *strReturn = (char *)malloc((strlen(strSetting)+1) * sizeof(char)); - strcpy(strReturn, strSetting); - return strReturn; + std::string strSetting = cfg_getstr(cfg_device, name.c_str()); + return strSetting; } } return NULL; } -bool Settings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { +bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { if (d->cfg == 0) { return false; } @@ -174,9 +169,9 @@ bool Settings::setStringSetting(int intDeviceId, const char* name, const char *v if (cfg_getint(cfg_device, "id") == intDeviceId) { if (parameter) { cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); - cfg_setstr(cfg_parameters, name, value); + cfg_setstr(cfg_parameters, name.c_str(), value.c_str()); } else { - cfg_setstr(cfg_device, name, value); + cfg_setstr(cfg_device, name.c_str(), value.c_str()); } FILE *fp = fopen(CONFIG_FILE, "w"); cfg_print(d->cfg, fp); @@ -187,7 +182,7 @@ bool Settings::setStringSetting(int intDeviceId, const char* name, const char *v return false; } -int Settings::getIntSetting(int intDeviceId, const char* name, bool parameter) { +int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) { if (d->cfg == 0) { return 0; } @@ -198,13 +193,13 @@ int Settings::getIntSetting(int intDeviceId, const char* name, bool parameter) { if (parameter) { cfg_device = cfg_getsec(cfg_device, "parameters"); } - return cfg_getint(cfg_device, name); + return cfg_getint(cfg_device, name.c_str()); } } return 0; } -bool Settings::setIntSetting(int intDeviceId, const char* name, int value, bool parameter) { +bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { if (d->cfg == 0) { return false; } @@ -214,9 +209,9 @@ bool Settings::setIntSetting(int intDeviceId, const char* name, int value, bool if (cfg_getint(cfg_device, "id") == intDeviceId) { if (parameter) { cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); - cfg_setint(cfg_parameters, name, value); + cfg_setint(cfg_parameters, name.c_str(), value); } else { - cfg_setint(cfg_device, name, value); + cfg_setint(cfg_device, name.c_str(), value); } FILE *fp = fopen(CONFIG_FILE, "w"); cfg_print(d->cfg, fp); From 59095cff600a0ce290410594d23289b15b46c21d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 11:26:42 +0000 Subject: [PATCH 0726/2215] Switched to std::string in Manager::getDevice() --- .../driver/libtelldus-core/Manager.cpp | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index e54adf9f..754457ff 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -48,45 +48,35 @@ Device *Manager::getDevice(int intDeviceId){ } try{ - char* protocol = settings.getProtocol(intDeviceId); - if (protocol == NULL) { + std::string protocol = settings.getProtocol(intDeviceId); + if (protocol.length() == 0) { return NULL; } //each new brand must be added here - if (strcasecmp(protocol, "arctech") == 0){ - char *strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); - char *strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); + if (strcasecmp(protocol.c_str(), "arctech") == 0){ + std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); + std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); dev = new DeviceNexa(strHouse, strCode); - free(strHouse); - free(strCode); - - } else if (strcasecmp(protocol, "Waveman") == 0) { - char *strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); - char *strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); + + } else if (strcasecmp(protocol.c_str(), "Waveman") == 0) { + std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); + std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); dev = new DeviceWaveman(strHouse, strCode); - free(strHouse); - free(strCode); - } else if (strcasecmp(protocol, "Sartano") == 0) { - char *strCode = settings.getDeviceParameter(intDeviceId, "sartano_code"); + } else if (strcasecmp(protocol.c_str(), "Sartano") == 0) { + std::string strCode = settings.getDeviceParameter(intDeviceId, "sartano_code"); dev = new DeviceSartano(strCode); - free(strCode); - } else if (strcasecmp(protocol, "Ikea") == 0) { - char *strSystem = settings.getDeviceParameter(intDeviceId, "ikea_system"); - char *strUnits = settings.getDeviceParameter(intDeviceId, "ikea_units"); - char *strFade = settings.getDeviceParameter(intDeviceId, "ikea_fade"); + } else if (strcasecmp(protocol.c_str(), "Ikea") == 0) { + std::string strSystem = settings.getDeviceParameter(intDeviceId, "ikea_system"); + std::string strUnits = settings.getDeviceParameter(intDeviceId, "ikea_units"); + std::string strFade = settings.getDeviceParameter(intDeviceId, "ikea_fade"); dev = new DeviceIkea(strSystem, strUnits, strFade); - free(strSystem); - free(strUnits); - free(strFade); } else { - free(protocol); return NULL; } - free(protocol); #ifdef _LINUX dev->setDevice( settings.getSetting("deviceNode") ); From 67da379f5109690d0bc5891dd9dca710589eb8c7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 15:54:36 +0000 Subject: [PATCH 0727/2215] Converted some char * to std::string --- .../driver/libtelldus-core/telldus-core.cpp | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index b741971c..98f6e7a3 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -20,7 +20,7 @@ void handleException(std::exception e); using namespace std; -char *wrapStdString( const std::string &string); +inline char *wrapStdString( const std::string &string); /** * @def TELLSTICK_TURNON @@ -261,9 +261,7 @@ char * WINAPI tdGetName(int intDeviceId){ std::string strReturn; try{ Settings ts; - char *name = ts.getName(intDeviceId); - strReturn = name; - free(name); + strReturn = ts.getName(intDeviceId); } catch(exception e){ strReturn = ""; @@ -352,21 +350,18 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha } char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ - char *strReturn = ""; + std::string strReturn = ""; try{ Settings ts; strReturn = ts.getDeviceParameter(intDeviceId, strName); - if (strReturn == NULL) { - strReturn = strdup(defaultValue); + if (strReturn.empty()) { + strReturn = defaultValue; } -#ifdef _WINDOWS - strReturn = (char *)SysAllocStringByteLen (strReturn, lstrlen(strReturn)); -#endif } catch(exception e){ handleException(e); } - return strReturn; + return wrapStdString(strReturn); } int WINAPI tdAddDevice(){ @@ -470,11 +465,11 @@ char * WINAPI tdGetErrorString(int intErrorNo) { //* void handleException(exception e){ - char* strLogName = "errorlog.txt"; + std::string strLogName = "errorlog.txt"; //char* strLogName = ""; - if(strlen(strLogName) > 0){ - ofstream errorfile(strLogName, ios::app); + if(strLogName.length() > 0){ + ofstream errorfile(strLogName.c_str(), ios::app); if(errorfile){ errorfile << e.what() << endl; errorfile.close(); From f3c74762d7e7c53d8d7cb60e2f022f54e9da0224 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 16:12:39 +0000 Subject: [PATCH 0728/2215] Fixed possible memory leak in DeviceIkea --- telldus-core/driver/libtelldus-core/DeviceIkea.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index ef147e63..c8a1f49c 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -24,17 +24,17 @@ DeviceIkea::DeviceIkea(const std::string &strSystem, const std::string &strUnits if (strUnits.length() > 0) { intUnits = 0; //Start without any units - char tempUnits[strUnits.size()]; - strUnits.copy(tempUnits, strUnits.length(), 0); + char tempUnits[strUnits.size()+1]; + strcpy(tempUnits, strUnits.c_str()); - char *strTemp = strtok(tempUnits, ","); + char *strToken = strtok(tempUnits, ","); do { - int intUnit = atoi(strTemp); + int intUnit = atoi(strToken); if (intUnit == 10) { intUnit = 0; } intUnits = intUnits | ( 1<<(9-intUnit) ); - } while ( (strTemp = strtok(NULL, ",")) != NULL ); + } while ( (strToken = strtok(NULL, ",")) != NULL ); } if (strUnits.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { From 63c60e71b86c0b9829b571956311439f536b32ac Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 16:16:11 +0000 Subject: [PATCH 0729/2215] Added model to the class Device --- telldus-core/driver/libtelldus-core/Device.cpp | 16 ++++------------ telldus-core/driver/libtelldus-core/Device.h | 9 +++++---- .../driver/libtelldus-core/DeviceIkea.cpp | 4 ++-- telldus-core/driver/libtelldus-core/DeviceIkea.h | 2 +- .../driver/libtelldus-core/DeviceNexa.cpp | 4 ++-- telldus-core/driver/libtelldus-core/DeviceNexa.h | 2 +- .../driver/libtelldus-core/DeviceSartano.cpp | 4 ++-- .../driver/libtelldus-core/DeviceSartano.h | 2 +- .../driver/libtelldus-core/DeviceWaveman.cpp | 4 ++-- .../driver/libtelldus-core/DeviceWaveman.h | 2 +- telldus-core/driver/libtelldus-core/Manager.cpp | 9 +++++---- 11 files changed, 26 insertions(+), 32 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 341fb82e..391320ff 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -4,27 +4,19 @@ /* * Constructor */ -Device::Device() +Device::Device(int model) + : model(model) { -#ifdef _LINUX - strDevice = 0; -#endif } /* * Destructor */ -Device::~Device(void) -{ -#ifdef _LINUX - if (strDevice != 0) { - free(strDevice); - } -#endif +Device::~Device(void) { } int Device::getModel() { - return 1; + return model; } /* diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 5b76eca1..a757a95e 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -7,7 +7,7 @@ class Device { public: - Device(); + Device(int model); ~Device(void); virtual int turnOn(void); @@ -19,14 +19,15 @@ public: int getModel(); #ifdef _LINUX - void setDevice(const char *device); + void setDevice(const std::string &device); protected: - char *strDevice; + std::string strDevice; #endif protected: int send(const std::string &strMessage); -//private: +private: + int model; // static QMutex deviceMutex; }; diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index c8a1f49c..523ee68d 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -13,8 +13,8 @@ /* * Constructor */ -DeviceIkea::DeviceIkea(const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle) - :Device() +DeviceIkea::DeviceIkea(int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle) + :Device(model) { if (strSystem.length() > 0) { intSystem = atoi(strSystem.c_str()) - 1; diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index 8775b9d5..84d8bda8 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -5,7 +5,7 @@ class DeviceIkea : public Device { public: - DeviceIkea(const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); + DeviceIkea(int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); virtual int turnOn(void); virtual int turnOff(void); virtual int dim(unsigned char level); diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 67bc1b7d..89855ae3 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -9,8 +9,8 @@ /* * Constructor */ -DeviceNexa::DeviceNexa(const std::string &strHouse, const std::string &strCode) - :Device() +DeviceNexa::DeviceNexa(int model, const std::string &strHouse, const std::string &strCode) + :Device(model) { if (strHouse.length() > 0) { intHouse = strHouse[0] - 'A'; diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 0c81f457..27466477 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -5,7 +5,7 @@ class DeviceNexa : public Device { public: - DeviceNexa(const std::string &strHouse, const std::string &strCode); + DeviceNexa(int model, const std::string &strHouse, const std::string &strCode); virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index ab8fd79a..990ecc48 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -10,8 +10,8 @@ using namespace std; /* * Constructor */ -DeviceSartano::DeviceSartano(const std::string &strNewCode) - :Device() +DeviceSartano::DeviceSartano(int model, const std::string &strNewCode) + :Device(model) { strCode = strNewCode; } diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index ce61d675..2a0f9108 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -6,7 +6,7 @@ class DeviceSartano : public Device { public: - DeviceSartano(const std::string &strCode); + DeviceSartano(int model, const std::string &strCode); virtual int turnOn(void); virtual int turnOff(void); virtual int methods(int methodsSupported); diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index 64452093..02a6df4d 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -11,8 +11,8 @@ using namespace std; /* * Constructor */ -DeviceWaveman::DeviceWaveman(const std::string &strHouse, const std::string &strCode) - :DeviceNexa(strHouse, strCode){ +DeviceWaveman::DeviceWaveman(int model, const std::string &strHouse, const std::string &strCode) + :DeviceNexa(model, strHouse, strCode){ } /* diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index 5659e286..9bb484ab 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -5,7 +5,7 @@ class DeviceWaveman : public DeviceNexa { public: - DeviceWaveman(const std::string &strHouse, const std::string &strCode); + DeviceWaveman(int model, const std::string &strHouse, const std::string &strCode); virtual int turnOff(void); virtual int methods(int methodsSupported); }; diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index 754457ff..155d522d 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -52,27 +52,28 @@ Device *Manager::getDevice(int intDeviceId){ if (protocol.length() == 0) { return NULL; } + int intModel = settings.getModel(intDeviceId); //each new brand must be added here if (strcasecmp(protocol.c_str(), "arctech") == 0){ std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceNexa(strHouse, strCode); + dev = new DeviceNexa(intModel, strHouse, strCode); } else if (strcasecmp(protocol.c_str(), "Waveman") == 0) { std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceWaveman(strHouse, strCode); + dev = new DeviceWaveman(intModel, strHouse, strCode); } else if (strcasecmp(protocol.c_str(), "Sartano") == 0) { std::string strCode = settings.getDeviceParameter(intDeviceId, "sartano_code"); - dev = new DeviceSartano(strCode); + dev = new DeviceSartano(intModel, strCode); } else if (strcasecmp(protocol.c_str(), "Ikea") == 0) { std::string strSystem = settings.getDeviceParameter(intDeviceId, "ikea_system"); std::string strUnits = settings.getDeviceParameter(intDeviceId, "ikea_units"); std::string strFade = settings.getDeviceParameter(intDeviceId, "ikea_fade"); - dev = new DeviceIkea(strSystem, strUnits, strFade); + dev = new DeviceIkea(intModel, strSystem, strUnits, strFade); } else { return NULL; From 126e653473df1be5310d3ce8a8a63de7c44795e8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 16:16:52 +0000 Subject: [PATCH 0730/2215] Switched to std::string in linux/Device.cpp --- telldus-core/driver/libtelldus-core/linux/Device.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/linux/Device.cpp b/telldus-core/driver/libtelldus-core/linux/Device.cpp index ba36e231..29789b97 100644 --- a/telldus-core/driver/libtelldus-core/linux/Device.cpp +++ b/telldus-core/driver/libtelldus-core/linux/Device.cpp @@ -12,7 +12,7 @@ int Device::send(const std::string &strMessage) { int fd = -1; struct termios tio; - if( 0 > ( fd = open( strDevice, O_RDWR ) ) ) { + if( 0 > ( fd = open( strDevice.c_str(), O_RDWR ) ) ) { if (errno == ENOENT) { return TELLSTICK_ERROR_NOT_FOUND; } else if (errno == EACCES) { @@ -38,6 +38,6 @@ int Device::send(const std::string &strMessage) { return TELLSTICK_SUCCESS; } -void Device::setDevice(const char *device) { - strDevice = strdup(device); +void Device::setDevice(const std::string &device) { + strDevice = device; } From fcf91265352342d7a3ecbd587549f7b944659428 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 16:24:48 +0000 Subject: [PATCH 0731/2215] Added const to the getters in Settings --- .../driver/libtelldus-core/Settings.cpp | 8 ++++---- .../driver/libtelldus-core/Settings.h | 20 +++++++++---------- .../libtelldus-core/SettingsConfuse.cpp | 12 +++++------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Settings.cpp b/telldus-core/driver/libtelldus-core/Settings.cpp index 30345070..52f3cd58 100644 --- a/telldus-core/driver/libtelldus-core/Settings.cpp +++ b/telldus-core/driver/libtelldus-core/Settings.cpp @@ -3,7 +3,7 @@ /* * Get the name of the device */ -std::string Settings::getName(int intDeviceId){ +std::string Settings::getName(int intDeviceId) const { return getStringSetting(intDeviceId, "name", false); } @@ -17,7 +17,7 @@ bool Settings::setName(int intDeviceId, const std::string &strNewName){ /* * Get the device vendor */ -std::string Settings::getProtocol(int intDeviceId){ +std::string Settings::getProtocol(int intDeviceId) const { return getStringSetting(intDeviceId, "protocol", false); } @@ -31,7 +31,7 @@ bool Settings::setProtocol(int intDeviceId, const std::string &strVendor){ /* * Get the device model */ -int Settings::getModel(int intDeviceId){ +int Settings::getModel(int intDeviceId) const { return getIntSetting(intDeviceId, "model", false); } @@ -52,6 +52,6 @@ bool Settings::setDeviceParameter(int intDeviceId, const std::string &strName, c /* * Get device argument */ -std::string Settings::getDeviceParameter(int intDeviceId, const std::string &strName) { +std::string Settings::getDeviceParameter(int intDeviceId, const std::string &strName) const { return getStringSetting(intDeviceId, strName, true); } diff --git a/telldus-core/driver/libtelldus-core/Settings.h b/telldus-core/driver/libtelldus-core/Settings.h index 560e1a50..e09d7ed8 100644 --- a/telldus-core/driver/libtelldus-core/Settings.h +++ b/telldus-core/driver/libtelldus-core/Settings.h @@ -9,30 +9,30 @@ class Settings { public: Settings(void); - std::string getSetting(const std::string &strName); - int getNumberOfDevices(void); - std::string getName(int intDeviceId); + std::string getSetting(const std::string &strName) const; + int getNumberOfDevices(void) const; + std::string getName(int intDeviceId) const; bool setName(int intDeviceId, const std::string &strNewName); - std::string getProtocol(int intDeviceId); + std::string getProtocol(int intDeviceId) const; bool setProtocol(int intDeviceId, const std::string &strVendor); - int getModel(int intDeviceId); + int getModel(int intDeviceId) const; bool setModel(int intDeviceId, int intModel); - std::string getDeviceParameter(int intDeviceId, const std::string &strName); + std::string getDeviceParameter(int intDeviceId, const std::string &strName) const; bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); int addDevice(); - int getDeviceId(int intDeviceIndex); + int getDeviceId(int intDeviceIndex) const; bool removeDevice(int intDeviceId); ~Settings(void); protected: - std::string getStringSetting(int intDeviceId, const std::string &name, bool parameter); + std::string getStringSetting(int intDeviceId, const std::string &name, bool parameter) const; bool setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter); - int getIntSetting(int intDeviceId, const std::string &name, bool parameter); + int getIntSetting(int intDeviceId, const std::string &name, bool parameter) const; bool setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter); private: - int getNextDeviceId(); + int getNextDeviceId() const; privateVars *d; }; diff --git a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp index 7bf2c14e..e7c03d48 100644 --- a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp @@ -47,7 +47,7 @@ Settings::~Settings(void) /* * Return a setting */ -std::string Settings::getSetting(const std::string &strName) { +std::string Settings::getSetting(const std::string &strName) const { if (d->cfg > 0) { return cfg_getstr(d->cfg, strName.c_str()); } @@ -57,14 +57,14 @@ std::string Settings::getSetting(const std::string &strName) { /* * Return the number of stored devices */ -int Settings::getNumberOfDevices(void){ +int Settings::getNumberOfDevices(void) const { if (d->cfg > 0) { return cfg_size(d->cfg, "device"); } return 0; } -int Settings::getDeviceId(int intDeviceIndex){ +int Settings::getDeviceId(int intDeviceIndex) const { if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds return -1; } @@ -93,7 +93,7 @@ int Settings::addDevice(){ /* * Get next available device id */ -int Settings::getNextDeviceId(){ +int Settings::getNextDeviceId() const { int intDeviceId = 0; cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { @@ -141,7 +141,7 @@ bool Settings::removeDevice(int intDeviceId){ return blnSuccess; } -std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) { +std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { if (d->cfg == 0) { return NULL; } @@ -182,7 +182,7 @@ bool Settings::setStringSetting(int intDeviceId, const std::string &name, const return false; } -int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) { +int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { if (d->cfg == 0) { return 0; } From c6502c7ad01759f48baacbcdb809fd4ccbe79c0c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 17:23:07 +0000 Subject: [PATCH 0732/2215] Updated TelldusCore with fixes for building on Windows --- .../driver/TellUsbD101/TellUsbD101.cpp | 14 ++-- .../driver/libtelldus-core/DeviceIkea.cpp | 11 ++- .../driver/libtelldus-core/Manager.cpp | 5 +- .../libtelldus-core/SettingsWinRegistry.cpp | 67 +++++++++---------- .../libtelldus-core/libtelldus-core.def | 10 +-- .../libtelldus-core/libtelldus-core.vcproj | 40 ++++++----- .../driver/libtelldus-core/win/Device.cpp | 8 ++- 7 files changed, 89 insertions(+), 66 deletions(-) diff --git a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp index 5591bdde..3441f497 100644 --- a/telldus-core/driver/TellUsbD101/TellUsbD101.cpp +++ b/telldus-core/driver/TellUsbD101/TellUsbD101.cpp @@ -21,7 +21,7 @@ char * __stdcall devGetName(int intDeviceId){ } char* __stdcall devGetVendor(int intDeviceId){ - return tdGetVendor(intDeviceId); + return tdGetProtocol(intDeviceId); } char* __stdcall devGetModel(int intDeviceId){ @@ -31,7 +31,7 @@ char* __stdcall devGetModel(int intDeviceId){ std::string str; ss << intModel; str = ss.str(); - char *strModel = (char *)SysAllocStringByteLen (str.c_str(), str.length()); + char *strModel = (char *)SysAllocStringByteLen (str.c_str(), (UINT)str.length()); return strModel; } @@ -47,8 +47,12 @@ bool __stdcall devSetName(int intDeviceId, char* strNewName){ return tdSetName(intDeviceId, strNewName); } -bool __stdcall devSetVendor(int intDeviceId, char* strVendor){ - return tdSetVendor(intDeviceId, strVendor); +bool __stdcall devSetVendor(int intDeviceId, char* strVendor) { + if (_stricmp(strVendor, "nexa") == 0) { + return tdSetProtocol(intDeviceId, "arctech"); + } else { + return tdSetProtocol(intDeviceId, strVendor); + } } bool __stdcall devSetModel(int intDeviceId, char* strNewModel){ @@ -69,7 +73,7 @@ bool __stdcall devRemoveDevice(int intDeviceId){ } int __stdcall devMethods(int id){ - return tdMethods(id); + return tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL); } bool __stdcall devTurnOn(int intDeviceId){ diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index 523ee68d..945f5cdd 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -24,9 +24,13 @@ DeviceIkea::DeviceIkea(int model, const std::string &strSystem, const std::strin if (strUnits.length() > 0) { intUnits = 0; //Start without any units - char tempUnits[strUnits.size()+1]; + char *tempUnits = new char[strUnits.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); +#else strcpy(tempUnits, strUnits.c_str()); - +#endif + char *strToken = strtok(tempUnits, ","); do { int intUnit = atoi(strToken); @@ -35,7 +39,8 @@ DeviceIkea::DeviceIkea(int model, const std::string &strSystem, const std::strin } intUnits = intUnits | ( 1<<(9-intUnit) ); } while ( (strToken = strtok(NULL, ",")) != NULL ); - + + free(tempUnits); } if (strUnits.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { intFadeStyle = 1; diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index 155d522d..74014c36 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -17,11 +17,14 @@ #include "DeviceSartano.h" #include "DeviceIkea.h" - #include #include #include +#ifdef _WINDOWS +#define strcasecmp _stricmp +#endif + Manager *Manager::instance = 0; Manager::Manager() { diff --git a/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp b/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp index 426bb931..279801a9 100644 --- a/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp @@ -1,12 +1,11 @@ -#include "../StdAfx.h" -#include "TelldusSettings.h" +#include "StdAfx.h" +#include "Settings.h" #include #include #include #include #include -using namespace std; bool storeGlobal(privateVars *d); class privateVars { @@ -21,7 +20,7 @@ public: /* * Constructor */ -TelldusSettings::TelldusSettings(void) +Settings::Settings(void) { d = new privateVars(); d->strRegPathDevice = "SOFTWARE\\Telldus\\Devices\\"; @@ -37,7 +36,7 @@ TelldusSettings::TelldusSettings(void) /* * Destructor */ -TelldusSettings::~TelldusSettings(void) +Settings::~Settings(void) { //RegCloseKey(hk); //close all, if still open //TODO: Need some way to know if open or closed d->strRegPath = ""; @@ -49,7 +48,7 @@ TelldusSettings::~TelldusSettings(void) /* * Return the number of stored devices */ -int TelldusSettings::getNumberOfDevices(void){ +int Settings::getNumberOfDevices(void) const { int intNumberOfDevices = 0; @@ -59,7 +58,7 @@ int TelldusSettings::getNumberOfDevices(void){ if(lnExists == ERROR_SUCCESS){ - string strNumSubKeys; + std::string strNumSubKeys; DWORD dNumSubKeys; RegQueryInfoKey(d->hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); @@ -68,7 +67,7 @@ int TelldusSettings::getNumberOfDevices(void){ RegCloseKey(d->hk); } else{ - throw exception(); //couldn't open reg key + throw std::exception(); //couldn't open reg key } } catch(...){ @@ -78,7 +77,7 @@ int TelldusSettings::getNumberOfDevices(void){ } -int TelldusSettings::getDeviceId(int intDeviceIndex){ +int Settings::getDeviceId(int intDeviceIndex) const { int intReturn = -1; try{ @@ -98,7 +97,7 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ RegCloseKey(d->hk); } else{ - throw exception(); //couldn't open reg key + throw std::exception(); //couldn't open reg key } } catch(...){ @@ -112,7 +111,7 @@ int TelldusSettings::getDeviceId(int intDeviceIndex){ /* * Add a new device */ -int TelldusSettings::addDevice(){ +int Settings::addDevice(){ int intDeviceId = -1; try{ @@ -122,7 +121,7 @@ int TelldusSettings::addDevice(){ std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); + std::string strCompleteRegPath = ssRegPath.str(); if(RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), @@ -134,7 +133,7 @@ int TelldusSettings::addDevice(){ &d->hk, &dwDisp)){ //fail - throw exception("Create Key failed"); + throw std::exception("Create Key failed"); } RegCloseKey(d->hk); @@ -149,7 +148,7 @@ int TelldusSettings::addDevice(){ /* * Get next available device id */ -int TelldusSettings::getNextDeviceId(){ +int Settings::getNextDeviceId() const { int intReturn = -1; try{ @@ -200,13 +199,13 @@ int TelldusSettings::getNextDeviceId(){ /* * Remove a device */ -bool TelldusSettings::removeDevice(int intDeviceId){ +bool Settings::removeDevice(int intDeviceId){ bool blnSuccess = true; try{ std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); + std::string strCompleteRegPath = ssRegPath.str(); long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); if(lngSuccess != ERROR_SUCCESS){ @@ -220,28 +219,28 @@ bool TelldusSettings::removeDevice(int intDeviceId){ return blnSuccess; } -char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { - char* strReturn = ""; +std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { + std::string strReturn = ""; try{ std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); + std::string strCompleteRegPath = ssRegPath.str(); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &d->hk); if(lnExists == ERROR_SUCCESS){ DWORD dwLength; char* Buff = new char[d->intMaxRegValueLength]; - long lngStatus = RegQueryValueEx(d->hk, name, NULL, NULL, (LPBYTE)Buff, &dwLength); + long lngStatus = RegQueryValueEx(d->hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA){ Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(d->hk, name, NULL, NULL, (LPBYTE)Buff, &dwLength); + lngStatus = RegQueryValueEx(d->hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); } strReturn = Buff; } else{ - throw exception(); //couldn't open reg key + throw std::exception(); //couldn't open reg key } RegCloseKey(d->hk); } @@ -251,22 +250,22 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool return strReturn; } -bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { +bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { bool blnSuccess = true; try{ std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); + std::string strCompleteRegPath = ssRegPath.str(); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); if(lnExists == ERROR_SUCCESS){ - d->intMaxRegValueLength = (int)strlen(value); - RegSetValueEx(d->hk, name, 0, REG_SZ, (LPBYTE)value, d->intMaxRegValueLength); + d->intMaxRegValueLength = (int)value.length(); + RegSetValueEx(d->hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), d->intMaxRegValueLength); } else{ - throw exception(); //couldn't open reg key + throw std::exception(); //couldn't open reg key } RegCloseKey(d->hk); @@ -278,27 +277,27 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const } -int TelldusSettings::getIntSetting(int intDeviceId, const char* name, bool parameter) { +int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { int intReturn = 0; - char *strSetting = getStringSetting(intDeviceId, name, parameter); - if (strlen(strSetting)) { - intReturn = (int)strSetting[0]; + std::string strSetting = getStringSetting(intDeviceId, name, parameter); + if (strSetting.length()) { + intReturn = atoi(strSetting.c_str()); } return intReturn; } -bool TelldusSettings::setIntSetting(int intDeviceId, const char* name, int value, bool parameter) { +bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { bool blnReturn = false; std::ostringstream ssRegPath; ssRegPath << d->strRegPathDevice << intDeviceId; - string strCompleteRegPath = ssRegPath.str(); + std::string strCompleteRegPath = ssRegPath.str(); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &d->hk); if (lnExists == ERROR_SUCCESS) { DWORD dwVal = value; - lnExists = RegSetValueEx (d->hk, name, 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + lnExists = RegSetValueEx (d->hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); if (lnExists == ERROR_SUCCESS) { blnReturn = true; } diff --git a/telldus-core/driver/libtelldus-core/libtelldus-core.def b/telldus-core/driver/libtelldus-core/libtelldus-core.def index dd0b34fe..7f9c2475 100644 --- a/telldus-core/driver/libtelldus-core/libtelldus-core.def +++ b/telldus-core/driver/libtelldus-core/libtelldus-core.def @@ -4,14 +4,14 @@ EXPORTS tdGetDeviceId @2 tdGetName @3 - tdGetVendor @4 + tdGetProtocol @4 tdGetModel @5 - tdGetArgument @6 + tdGetDeviceParameter @6 tdSetName @7 - tdSetVendor @8 + tdSetProtocol @8 tdSetModel @9 - tdSetArgument @10 + tdSetDeviceParameter @10 tdAddDevice @11 tdRemoveDevice @12 @@ -23,3 +23,5 @@ EXPORTS tdDim @17 tdGetErrorString @18 + + tdClose @19 diff --git a/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj b/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj index 1f7eb42c..e89a3712 100644 --- a/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj +++ b/telldus-core/driver/libtelldus-core/libtelldus-core.vcproj @@ -180,6 +180,10 @@ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" > + + @@ -202,10 +206,6 @@ /> - - @@ -222,6 +222,18 @@ RelativePath=".\DeviceWaveman.cpp" > + + + + + + @@ -230,14 +242,6 @@ RelativePath=".\telldus-core.cpp" > - - - - + + + + @@ -280,10 +292,6 @@ RelativePath=".\telldus-core.h" > - - Date: Wed, 7 Jan 2009 19:13:03 +0000 Subject: [PATCH 0733/2215] Fixed bug in Settings::getIntSetting() on Windows --- telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp b/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp index 279801a9..64b36c75 100644 --- a/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsWinRegistry.cpp @@ -282,7 +282,7 @@ int Settings::getIntSetting(int intDeviceId, const std::string &name, bool param std::string strSetting = getStringSetting(intDeviceId, name, parameter); if (strSetting.length()) { - intReturn = atoi(strSetting.c_str()); + intReturn = (int)strSetting[0]; } return intReturn; From 6b0bcf6f09943d742cb049479ae612faf96bdda2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 19:21:09 +0000 Subject: [PATCH 0734/2215] Made the AutoUpdater only work for Max OS X --- telldus-gui/TelldusCenter/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusCenter/main.cpp b/telldus-gui/TelldusCenter/main.cpp index 75aaa40d..5bb03556 100644 --- a/telldus-gui/TelldusCenter/main.cpp +++ b/telldus-gui/TelldusCenter/main.cpp @@ -15,14 +15,14 @@ int main(int argc, char *argv[]) MainWindow *w = new MainWindow(); w->show(); - AutoUpdater* updater = 0; #ifdef Q_WS_MAC + AutoUpdater* updater = 0; CocoaInitializer initializer; updater = new SparkleAutoUpdater("file:///Users/micke/Documents/dev/appcast.xml"); -#endif if (updater) { //updater->checkForUpdates(); } +#endif return application.exec(); } From 5395aaf28cd482ab7d3179bfbe514523c81b2616 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 19:22:40 +0000 Subject: [PATCH 0735/2215] Added flag for finding telldus-core and telldus-gui on Windows --- telldus-gui/TelldusCenter/TelldusCenter.pro | 51 ++++++------ telldus-gui/TelldusGui/TelldusGui.pro | 89 +++++++++++---------- 2 files changed, 73 insertions(+), 67 deletions(-) diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index f006cf01..8e7bc696 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -1,24 +1,27 @@ -# ------------------------------------------------- -# Project created by QtCreator 2008-12-11T11:01:36 -# ------------------------------------------------- -TARGET = TelldusCenter -TEMPLATE = app -SOURCES += main.cpp \ - mainwindow.cpp \ - tellduscenterapplication.cpp \ - autoupdater.cpp -HEADERS += mainwindow.h \ - tellduscenterapplication.h \ - autoupdater.h \ - CocoaInitializer.h -FORMS += -RESOURCES += resource.qrc -macx { - HEADERS += sparkleautoupdater.h - LIBS += -framework TelldusGui -framework Sparkle - OBJECTIVE_SOURCES += SparkleAutoUpdater.mm \ - CocoaInitializer.mm - QMAKE_INFO_PLIST = Info.plist -} -!macx:LIBS += -ltelldus-gui -VERSION = 1.3.0 +# ------------------------------------------------- +# Project created by QtCreator 2008-12-11T11:01:36 +# ------------------------------------------------- +TARGET = TelldusCenter +TEMPLATE = app +SOURCES += main.cpp \ + mainwindow.cpp \ + tellduscenterapplication.cpp \ + autoupdater.cpp +HEADERS += mainwindow.h \ + tellduscenterapplication.h \ + autoupdater.h \ + CocoaInitializer.h +FORMS += +RESOURCES += resource.qrc +macx { + HEADERS += sparkleautoupdater.h + LIBS += -framework TelldusGui -framework Sparkle + OBJECTIVE_SOURCES += SparkleAutoUpdater.mm \ + CocoaInitializer.mm + QMAKE_INFO_PLIST = Info.plist +} +!macx:LIBS += -ltelldus-gui +win32 { + LIBS += -L . +} +VERSION = 1.3.0 diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 88ef7303..32a9beab 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -1,43 +1,46 @@ -# ------------------------------------------------- -# Project created by QtCreator 2008-12-11T15:48:29 -# ------------------------------------------------- -TEMPLATE = lib -DEFINES += TELLDUSGUI_LIBRARY -SOURCES += telldusgui.cpp \ - devicewidget.cpp \ - devicemodel.cpp \ - device.cpp \ - editdevicedialog.cpp \ - vendordevicemodel.cpp \ - vendordevicetreeitem.cpp \ - devicesettingikea.cpp \ - devicesettingnexa.cpp \ - devicesettingnexabell.cpp \ - devicesettingsartano.cpp \ - devicesetting.cpp -HEADERS += telldusgui.h \ - devicewidget.h \ - devicemodel.h \ - device.h \ - editdevicedialog.h \ - vendordevicemodel.h \ - vendordevicetreeitem.h \ - devicesettingikea.h \ - devicesettingnexa.h \ - devicesettingnexabell.h \ - devicesettingsartano.h \ - devicesetting.h -FORMS += -macx { - LIBS += -framework \ - telldus-core - ICON = images/telldussetup.icns - TARGET = TelldusGui - CONFIG += lib_bundle -} -!macx { - LIBS += -l \ - telldus-core - TARGET = telldus-gui -} -RESOURCES += telldusgui.qrc +# ------------------------------------------------- +# Project created by QtCreator 2008-12-11T15:48:29 +# ------------------------------------------------- +TEMPLATE = lib +DEFINES += TELLDUSGUI_LIBRARY +SOURCES += telldusgui.cpp \ + devicewidget.cpp \ + devicemodel.cpp \ + device.cpp \ + editdevicedialog.cpp \ + vendordevicemodel.cpp \ + vendordevicetreeitem.cpp \ + devicesettingikea.cpp \ + devicesettingnexa.cpp \ + devicesettingnexabell.cpp \ + devicesettingsartano.cpp \ + devicesetting.cpp +HEADERS += telldusgui.h \ + devicewidget.h \ + devicemodel.h \ + device.h \ + editdevicedialog.h \ + vendordevicemodel.h \ + vendordevicetreeitem.h \ + devicesettingikea.h \ + devicesettingnexa.h \ + devicesettingnexabell.h \ + devicesettingsartano.h \ + devicesetting.h +FORMS += +macx { + LIBS += -framework \ + telldus-core + ICON = images/telldussetup.icns + TARGET = TelldusGui + CONFIG += lib_bundle +} +!macx { + LIBS += -l \ + telldus-core + TARGET = telldus-gui +} +win32 { + LIBS += -L . +} +RESOURCES += telldusgui.qrc From 094e2a39365877e9795ef09f8e7bd3c29564d6b0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 19:38:43 +0000 Subject: [PATCH 0736/2215] Cleaned up telldusgui.h --- telldus-gui/TelldusGui/telldusgui.h | 32 +++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/telldus-gui/TelldusGui/telldusgui.h b/telldus-gui/TelldusGui/telldusgui.h index f4b9d63c..132993ea 100644 --- a/telldus-gui/TelldusGui/telldusgui.h +++ b/telldus-gui/TelldusGui/telldusgui.h @@ -1,18 +1,34 @@ -#ifndef TELLDUSGUI_GLOBAL_H -#define TELLDUSGUI_GLOBAL_H +#ifndef TELLDUSGUI_H +#define TELLDUSGUI_H -#include +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TELLDUSGUI_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLSTICK_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. -#if defined(TELLDUSGUI_LIBRARY) -# define TELLDUSGUISHARED_EXPORT Q_DECL_EXPORT +#ifdef _WINDOWS + #ifdef TELLDUSGUI_EXPORTS + #define TELLSTICK_API __declspec(dllexport) + #else + #define TELLSTICK_API __declspec(dllimport) + #endif + #define WINAPI __stdcall #else -# define TELLDUSGUISHARED_EXPORT Q_DECL_IMPORT + #define WINAPI + #define TELLSTICK_API #endif class QWidget; +#ifdef __cplusplus extern "C" { - QWidget *tdDeviceWidget( QWidget *parent = 0 ); +#endif + TELLSTICK_API QWidget WINAPI *tdDeviceWidget( QWidget *parent = 0 ); +#ifdef __cplusplus } +#endif -#endif // TELLDUSGUI_GLOBAL_H +#endif // TELLDUSGUI_H From f1e9f2f9f2932d9bdd27cb64210b35917098b023 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Jan 2009 21:14:59 +0000 Subject: [PATCH 0737/2215] Added namespace 'TelldusCore' to classes in library telldus-core --- .../driver/libtelldus-core/Device.cpp | 5 +- telldus-core/driver/libtelldus-core/Device.h | 54 ++++++++++--------- .../driver/libtelldus-core/DeviceIkea.cpp | 2 + .../driver/libtelldus-core/DeviceIkea.h | 41 +++++++------- .../driver/libtelldus-core/DeviceNexa.cpp | 2 + .../driver/libtelldus-core/DeviceNexa.h | 39 +++++++------- .../driver/libtelldus-core/DeviceSartano.cpp | 4 +- .../driver/libtelldus-core/DeviceSartano.h | 31 ++++++----- .../driver/libtelldus-core/DeviceWaveman.cpp | 6 +-- .../driver/libtelldus-core/DeviceWaveman.h | 18 ++++--- .../driver/libtelldus-core/Manager.cpp | 2 + telldus-core/driver/libtelldus-core/Manager.h | 47 ++++++++-------- .../driver/libtelldus-core/linux/Device.cpp | 2 + .../driver/libtelldus-core/telldus-core.cpp | 5 +- 14 files changed, 144 insertions(+), 114 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 391320ff..86538a52 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -1,11 +1,12 @@ #include "Device.h" #include +using namespace TelldusCore; /* * Constructor */ -Device::Device(int model) - : model(model) +Device::Device(int m) + : model(m) { } diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index a757a95e..ccff670c 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -4,30 +4,34 @@ #include //#include -class Device -{ -public: - Device(int model); - ~Device(void); - - virtual int turnOn(void); - virtual int turnOff(void); - virtual int bell(void); - virtual int dim(unsigned char level); - virtual int methods(int methodsSupported) = 0; - virtual std::string getProtocol() = 0; - int getModel(); - -#ifdef _LINUX - void setDevice(const std::string &device); -protected: - std::string strDevice; -#endif +namespace TelldusCore { -protected: - int send(const std::string &strMessage); + class Device + { + public: + Device(int model); + ~Device(void); + + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); + virtual int dim(unsigned char level); + virtual int methods(int methodsSupported) = 0; + virtual std::string getProtocol() = 0; + int getModel(); + + #ifdef _LINUX + void setDevice(const std::string &device); + protected: + std::string strDevice; + #endif + + protected: + int send(const std::string &strMessage); + + private: + int model; + // static QMutex deviceMutex; + }; -private: - int model; -// static QMutex deviceMutex; -}; +} diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index 945f5cdd..8a109a02 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -10,6 +10,8 @@ #define strcasecmp(x, y) _strcmpi(x, y) #endif +using namespace TelldusCore; + /* * Constructor */ diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index 84d8bda8..b61d0308 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -2,23 +2,26 @@ #include "Device.h" #include -class DeviceIkea : public Device -{ -public: - DeviceIkea(int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); - virtual int turnOn(void); - virtual int turnOff(void); - virtual int dim(unsigned char level); - virtual int methods(int methodsSupported); - virtual std::string getProtocol(); +namespace TelldusCore { + + class DeviceIkea : public Device + { + public: + DeviceIkea(int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); + virtual int turnOn(void); + virtual int turnOff(void); + virtual int dim(unsigned char level); + virtual int methods(int methodsSupported); + virtual std::string getProtocol(); + + public: + ~DeviceIkea(void); -public: - ~DeviceIkea(void); - -protected: - int intSystem; - int intUnits; - int intFadeStyle; - std::string getStringCode(unsigned char); -}; - + protected: + int intSystem; + int intUnits; + int intFadeStyle; + std::string getStringCode(unsigned char); + }; + +} diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 89855ae3..4ea01141 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -6,6 +6,8 @@ #include #include +using namespace TelldusCore; + /* * Constructor */ diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 27466477..728d325e 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -2,22 +2,25 @@ #include "Device.h" #include -class DeviceNexa : public Device -{ -public: - DeviceNexa(int model, const std::string &strHouse, const std::string &strCode); - virtual int turnOn(void); - virtual int turnOff(void); - virtual int bell(void); - virtual int methods(int methodsSupported); - virtual std::string getProtocol(); +namespace TelldusCore { -public: - ~DeviceNexa(void); - -protected: - int intHouse; - int intCode; - std::string getStringCode(int); -}; - + class DeviceNexa : public Device + { + public: + DeviceNexa(int model, const std::string &strHouse, const std::string &strCode); + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); + virtual int methods(int methodsSupported); + virtual std::string getProtocol(); + + public: + ~DeviceNexa(void); + + protected: + int intHouse; + int intCode; + std::string getStringCode(int); + }; + +} diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index 990ecc48..5cf910ee 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -5,7 +5,7 @@ #include #include -using namespace std; +using namespace TelldusCore; /* * Constructor @@ -70,7 +70,7 @@ int DeviceSartano::methods(int){ /* * Convert an integer to byte string where 0 is represented by $k and 1 by k$, reversed and padded with 0's as needed */ -string DeviceSartano::getStringCode(void){ +std::string DeviceSartano::getStringCode(void){ std::string strReturn = strCode; diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index 2a0f9108..defcde2e 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -2,19 +2,22 @@ #include "Device.h" #include +namespace TelldusCore { -class DeviceSartano : public Device -{ -public: - DeviceSartano(int model, const std::string &strCode); - virtual int turnOn(void); - virtual int turnOff(void); - virtual int methods(int methodsSupported); - virtual std::string getProtocol(); + class DeviceSartano : public Device + { + public: + DeviceSartano(int model, const std::string &strCode); + virtual int turnOn(void); + virtual int turnOff(void); + virtual int methods(int methodsSupported); + virtual std::string getProtocol(); + + ~DeviceSartano(void); + + protected: + std::string getStringCode(void); + std::string strCode; + }; - ~DeviceSartano(void); - -protected: - std::string getStringCode(void); - std::string strCode; -}; +} diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index 02a6df4d..a5f27ef4 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -6,7 +6,7 @@ #include #include -using namespace std; +using namespace TelldusCore; /* * Constructor @@ -21,8 +21,8 @@ DeviceWaveman::DeviceWaveman(int model, const std::string &strHouse, const std:: int DeviceWaveman::turnOff(void){ try{ - string strCode = getStringCode(intHouse); - string strUnit = getStringCode(intCode); + std::string strCode = getStringCode(intHouse); + std::string strUnit = getStringCode(intCode); strCode.append(strUnit); strCode.insert(0, "S"); diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index 9bb484ab..2a9f1c16 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -2,10 +2,14 @@ #include "DeviceNexa.h" #include -class DeviceWaveman : public DeviceNexa -{ -public: - DeviceWaveman(int model, const std::string &strHouse, const std::string &strCode); - virtual int turnOff(void); - virtual int methods(int methodsSupported); -}; +namespace TelldusCore { + + class DeviceWaveman : public DeviceNexa + { + public: + DeviceWaveman(int model, const std::string &strHouse, const std::string &strCode); + virtual int turnOff(void); + virtual int methods(int methodsSupported); + }; + +} diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index 74014c36..ba431b8e 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -25,6 +25,8 @@ #define strcasecmp _stricmp #endif +using namespace TelldusCore; + Manager *Manager::instance = 0; Manager::Manager() { diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index 9691b3b9..27f54b71 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -14,29 +14,32 @@ #include "Settings.h" #include -class Device; -typedef std::map DeviceMap; +namespace TelldusCore { + class Device; -/** - @author Micke Prag -*/ -class Manager { -public: - ~Manager(); - - Device *getDevice(int deviceId); - - static Manager *getInstance(); - static void close(); - -private: - Manager(); - - Settings settings; - DeviceMap devices; - - static Manager *instance; -}; + typedef std::map DeviceMap; + + /** + @author Micke Prag + */ + class Manager { + public: + ~Manager(); + + Device *getDevice(int deviceId); + + static Manager *getInstance(); + static void close(); + + private: + Manager(); + + Settings settings; + DeviceMap devices; + + static Manager *instance; + }; +} #endif diff --git a/telldus-core/driver/libtelldus-core/linux/Device.cpp b/telldus-core/driver/libtelldus-core/linux/Device.cpp index 29789b97..b8bd6e4c 100644 --- a/telldus-core/driver/libtelldus-core/linux/Device.cpp +++ b/telldus-core/driver/libtelldus-core/linux/Device.cpp @@ -5,6 +5,8 @@ #include #include +using namespace TelldusCore; + /* * Send message to the USB dongle */ diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 98f6e7a3..f56f8041 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -19,6 +19,7 @@ void handleException(std::exception e); using namespace std; +using namespace TelldusCore; inline char *wrapStdString( const std::string &string); @@ -465,8 +466,8 @@ char * WINAPI tdGetErrorString(int intErrorNo) { //* void handleException(exception e){ - std::string strLogName = "errorlog.txt"; - //char* strLogName = ""; +// std::string strLogName = "errorlog.txt"; + std::string strLogName = ""; if(strLogName.length() > 0){ ofstream errorfile(strLogName.c_str(), ios::app); From daa4b9327e121a9edca79a72961488804547efb9 Mon Sep 17 00:00:00 2001 From: Magnus Juntti Date: Thu, 8 Jan 2009 09:08:23 +0000 Subject: [PATCH 0738/2215] fixed a bug in the redhat init-script. it referred to /usr/local/bin/tellstickd while the rpm installs itself into /usr/bin/ --- tellstickd/init_script/tellstickd | 2 +- tellstickd/tellstickd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tellstickd/init_script/tellstickd b/tellstickd/init_script/tellstickd index 4188db2c..bbcae277 100755 --- a/tellstickd/init_script/tellstickd +++ b/tellstickd/init_script/tellstickd @@ -13,7 +13,7 @@ source /etc/rc.d/init.d/functions -EXECUTABLE="/usr/local/bin/tellstickd" +EXECUTABLE="/usr/bin/tellstickd" CONFIG_FILE="/etc/tellstickd.conf" OPTIONS="" diff --git a/tellstickd/tellstickd b/tellstickd/tellstickd index b48ff72f..e5f51636 100755 --- a/tellstickd/tellstickd +++ b/tellstickd/tellstickd @@ -45,7 +45,7 @@ my $dayOfWeek; my $dayOfMonth; my $PROGRAM_NAME = "tellstickd"; -my $VERSION = "pre 0.6.3"; +my $VERSION = "0.6.3"; # Structure of the configurations to be read; # $device_cfg[$i][0]; # Protocol, only NEXA, WAVEMAN and SARTANO supported so far by rfcmd From ea2ef568a538f3fbb7ec48ba0bb886a24d3364b9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Jan 2009 11:57:25 +0000 Subject: [PATCH 0739/2215] Added 'const' to Device::getProtocol() --- telldus-core/driver/libtelldus-core/Device.h | 2 +- telldus-core/driver/libtelldus-core/DeviceIkea.cpp | 2 +- telldus-core/driver/libtelldus-core/DeviceIkea.h | 2 +- telldus-core/driver/libtelldus-core/DeviceNexa.cpp | 2 +- telldus-core/driver/libtelldus-core/DeviceNexa.h | 2 +- telldus-core/driver/libtelldus-core/DeviceSartano.cpp | 2 +- telldus-core/driver/libtelldus-core/DeviceSartano.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index ccff670c..4dd8fa6d 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -17,7 +17,7 @@ namespace TelldusCore { virtual int bell(void); virtual int dim(unsigned char level); virtual int methods(int methodsSupported) = 0; - virtual std::string getProtocol() = 0; + virtual std::string getProtocol() const = 0; int getModel(); #ifdef _LINUX diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index 8a109a02..3abce7d0 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -205,6 +205,6 @@ int DeviceIkea::methods(int){ return 0; } -std::string DeviceIkea::getProtocol() { +std::string DeviceIkea::getProtocol() const { return "ikea"; } diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index b61d0308..898f371b 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -12,7 +12,7 @@ namespace TelldusCore { virtual int turnOff(void); virtual int dim(unsigned char level); virtual int methods(int methodsSupported); - virtual std::string getProtocol(); + virtual std::string getProtocol() const; public: ~DeviceIkea(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 4ea01141..16079cc8 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -176,6 +176,6 @@ int DeviceNexa::methods(int methodsSupported){ return 0; } -std::string DeviceNexa::getProtocol() { +std::string DeviceNexa::getProtocol() const { return "arctech"; } diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 728d325e..2fafbfff 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -12,7 +12,7 @@ namespace TelldusCore { virtual int turnOff(void); virtual int bell(void); virtual int methods(int methodsSupported); - virtual std::string getProtocol(); + virtual std::string getProtocol() const; public: ~DeviceNexa(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index 5cf910ee..1df64d56 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -94,7 +94,7 @@ std::string DeviceSartano::getStringCode(void){ } -std::string DeviceSartano::getProtocol() { +std::string DeviceSartano::getProtocol() const { return "sartano"; } diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index defcde2e..c1e19f2e 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -11,7 +11,7 @@ namespace TelldusCore { virtual int turnOn(void); virtual int turnOff(void); virtual int methods(int methodsSupported); - virtual std::string getProtocol(); + virtual std::string getProtocol() const; ~DeviceSartano(void); From f73f61c85dc1987db064656f9b8ecff4bd6b97ad Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Jan 2009 16:05:57 +0000 Subject: [PATCH 0740/2215] Added new device-type: DeviceGroup --- .../driver/libtelldus-core/CMakeLists.txt | 1 + .../driver/libtelldus-core/DeviceGroup.cpp | 135 ++++++++++++++++++ .../driver/libtelldus-core/DeviceGroup.h | 30 ++++ .../driver/libtelldus-core/Manager.cpp | 5 + .../libtelldus-core/SettingsConfuse.cpp | 3 + .../driver/libtelldus-core/telldus-core.cpp | 28 ++++ .../driver/libtelldus-core/telldus-core.h | 5 + 7 files changed, 207 insertions(+) create mode 100644 telldus-core/driver/libtelldus-core/DeviceGroup.cpp create mode 100644 telldus-core/driver/libtelldus-core/DeviceGroup.h diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 57151b6c..5f8d2fff 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -5,6 +5,7 @@ INCLUDE( ${QT_USE_FILE} ) SET( telldus-core_SRCS Controller.cpp Device.cpp + DeviceGroup.cpp DeviceIkea.cpp DeviceNexa.cpp DeviceSartano.cpp diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp new file mode 100644 index 00000000..7d475a62 --- /dev/null +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -0,0 +1,135 @@ +#include + +#include "DeviceGroup.h" +#include "Manager.h" + +using namespace TelldusCore; + +const int ALL_METHODS = + TELLSTICK_TURNON | + TELLSTICK_TURNOFF | + TELLSTICK_BELL | + TELLSTICK_DIM; + +/* +* Constructor +*/ +DeviceGroup::DeviceGroup(int model, const std::string &strDevices) + :Device(model) +{ + if (strDevices.length() > 0) { + char *tempDevices = new char[strDevices.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempDevices, strDevices.size()+1, strDevices.c_str()); +#else + strcpy(tempDevices, strDevices.c_str()); +#endif + + Manager *manager = Manager::getInstance(); + char *strToken = strtok(tempDevices, ","); + do { + int intDevice = atoi(strToken); + Device *device = manager->getDevice(intDevice); + if (device != NULL) { + deviceList.push_back( device ); + } + } while ( (strToken = strtok(NULL, ",")) != NULL ); + + free(tempDevices); + } +} + +/* +* Destructor +*/ +DeviceGroup::~DeviceGroup(void) { +} + +/* +* Turn on this device +*/ +int DeviceGroup::turnOn(void) { + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (ALL_METHODS & TELLSTICK_TURNON) { + int success = (*it)->turnOn(); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +/* +* Turn off this device +*/ +int DeviceGroup::turnOff(void) { + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (ALL_METHODS & TELLSTICK_TURNOFF) { + int success = (*it)->turnOff(); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +/* +* Send a bell +*/ +int DeviceGroup::bell(void){ + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (ALL_METHODS & TELLSTICK_BELL) { + int success = (*it)->bell(); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +/* +* Turn off this device +*/ +int DeviceGroup::dim(unsigned char level){ + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (ALL_METHODS & TELLSTICK_DIM) { + int success = (*it)->dim(level); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +/* +* Has the device got the method? +*/ +int DeviceGroup::methods(int supportedMethods){ + int retVal = 0; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + retVal = retVal | (*it)->methods(supportedMethods); + } + + return retVal; +} + +std::string DeviceGroup::getProtocol() const { + return "group"; +} diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.h b/telldus-core/driver/libtelldus-core/DeviceGroup.h new file mode 100644 index 00000000..b39aef92 --- /dev/null +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.h @@ -0,0 +1,30 @@ +#pragma once +#include "Device.h" +#include +#include + +class Controller; + +namespace TelldusCore { + + typedef std::list DeviceList; + + class DeviceGroup : public Device + { + public: + DeviceGroup(int model, const std::string &strDevices); + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); + virtual int dim(unsigned char level); + virtual int methods(int methodsSupported); + virtual std::string getProtocol() const; + + public: + ~DeviceGroup(void); + + private: + DeviceList deviceList; + }; + +} diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index ba431b8e..3ec645bb 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -12,6 +12,7 @@ #include "Manager.h" #include "Device.h" +#include "DeviceGroup.h" #include "DeviceNexa.h" #include "DeviceWaveman.h" #include "DeviceSartano.h" @@ -65,6 +66,10 @@ Device *Manager::getDevice(int intDeviceId){ std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); dev = new DeviceNexa(intModel, strHouse, strCode); + } else if (strcasecmp(protocol.c_str(), "group") == 0) { + std::string strDevices = settings.getDeviceParameter(intDeviceId, "devices"); + dev = new DeviceGroup(intModel, strDevices); + } else if (strcasecmp(protocol.c_str(), "Waveman") == 0) { std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); diff --git a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp index e7c03d48..85c1a6c8 100644 --- a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp @@ -229,6 +229,9 @@ bool readConfig(cfg_t **cfg) { }; cfg_opt_t device_parameter_opts[] = { + //Groups + CFG_STR("devices", 0, CFGF_NONE), + //Nexa CFG_STR("nexa_house", 0, CFGF_NONE), CFG_STR("nexa_unit", 0, CFGF_NONE), diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index f56f8041..e50836f8 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -11,6 +11,7 @@ #include "telldus-core.h" #include "Manager.h" #include "Device.h" +#include "DeviceGroup.h" #include #include #include @@ -39,6 +40,12 @@ inline char *wrapStdString( const std::string &string); * @def TELLSTICK_DIM * Device-flag for devices supporting the tdDim() call. * + * @def TELLSTICK_TYPE_DEVICE + * Device type of a single device. + * + * @def TELLSTICK_TYPE_GROUP + * Device type of a device which contains other devices. + * * @def TELLSTICK_SUCCESS * Error code. Returned when the command succeeded. * @@ -253,6 +260,27 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ return intReturn; } +/** + * Returns which type the device is. The device could be either + * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP + */ +int WINAPI tdGetDeviceType(int intDeviceId) { + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if (dev != NULL) { + DeviceGroup *deviceGroup = dynamic_cast(dev); + if (deviceGroup) { + return TELLSTICK_TYPE_GROUP; + } + } + } + catch(exception e){ + handleException(e); + } + return TELLSTICK_TYPE_DEVICE; +} + /** * Query a device for it's name. * @param intDeviceId The unique id of the device to query diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index 68958c22..d6e8c8a3 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -33,6 +33,7 @@ extern "C" { TELLSTICK_API int WINAPI tdGetNumberOfDevices(); TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); + TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceIndex); TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); @@ -67,6 +68,10 @@ extern "C" { #define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 #define TELLSTICK_ERROR_UNKNOWN -99 +//Device typedef +#define TELLSTICK_TYPE_DEVICE 1 +#define TELLSTICK_TYPE_GROUP 2 + //Protocol Nexa #define TELLSTICK_DEVICE_YCR3500 1 #define TELLSTICK_DEVICE_YCR300D 2 From c57ef6efb32c80a6305a5ed092ac7c2c4d64172a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Jan 2009 16:09:53 +0000 Subject: [PATCH 0741/2215] Removed the sleep since it is now in telldus-core and altered the output from switch_device() a bit --- telldus-core/tdtool/main.cpp | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 404a2275..abefc470 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -1,12 +1,8 @@ #include #include #include -#include #include #include "../driver/libtelldus-core/telldus-core.h" -#ifdef __MINGW32__ - #define sleep(x) _sleep((x)*1000) -#endif void print_usage( char *name ) { printf("\"tdtool\" is a command line utility to control a Telldus TellStick\n"); @@ -87,10 +83,10 @@ int find_device( char *device ) { char *name = tdGetName( id ); if (strcasecmp(name, device) == 0) { deviceId = id; - free(name); + free(name); break; } - free(name); + free(name); index++; } } @@ -105,15 +101,19 @@ void switch_device( bool turnOn, char *device ) { } char *name = tdGetName( deviceId ); + int deviceType = tdGetDeviceType( deviceId ); + printf("Turning %s %s %i, %s", + (turnOn ? "on" : "off"), + (deviceType == TELLSTICK_TYPE_DEVICE ? "device" : "group"), + deviceId, + name); + free(name); + int retval = (turnOn ? tdTurnOn( deviceId ) : tdTurnOff( deviceId )); char *errorString = tdGetErrorString(retval); - printf("Turning %s device: %i %s - %s\n", (turnOn ? "on" : "off"), deviceId, name, errorString); - free(name); + printf(" - %s\n", errorString); free(errorString); - if (retval == TELLSTICK_SUCCESS) { - sleep(1); - } } void dim_device( char *device, int level ) { @@ -133,9 +133,6 @@ void dim_device( char *device, int level ) { printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); free(name); free(errorString); - if (retval == TELLSTICK_SUCCESS) { - sleep(1); - } } void bell_device( char *device ) { @@ -149,11 +146,8 @@ void bell_device( char *device ) { int retval = tdBell( deviceId ); char *errorString = tdGetErrorString(retval); printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); - free(name); + free(name); free(errorString); - if (retval == TELLSTICK_SUCCESS) { - sleep(1); - } } int main(int argc, char **argv) @@ -211,5 +205,6 @@ int main(int argc, char **argv) return -1; } + tdClose(); //Cleaning up return 0; } From 1d1bc00f9b3f5f321aeb91ba99a61bdc44d567ad Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Jan 2009 16:15:11 +0000 Subject: [PATCH 0742/2215] Small typo in the parameter name --- telldus-core/driver/libtelldus-core/telldus-core.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index d6e8c8a3..06c80579 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -33,7 +33,7 @@ extern "C" { TELLSTICK_API int WINAPI tdGetNumberOfDevices(); TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); - TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceIndex); + TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); From 895e6df9ee1d007f2d2bee24740bc7c6315ee033 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Jan 2009 20:59:29 +0000 Subject: [PATCH 0743/2215] Bugfix, update the device-cache if we change the model of a device --- telldus-core/driver/libtelldus-core/Device.cpp | 6 +++++- telldus-core/driver/libtelldus-core/Device.h | 3 ++- telldus-core/driver/libtelldus-core/Manager.cpp | 10 +++++++++- telldus-core/driver/libtelldus-core/Manager.h | 2 ++ telldus-core/driver/libtelldus-core/telldus-core.cpp | 7 +++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 86538a52..377c9848 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -16,10 +16,14 @@ Device::Device(int m) Device::~Device(void) { } -int Device::getModel() { +int Device::getModel() const { return model; } +void Device::setModel( int intModel ) { + model = intModel; +} + /* * Turn on, virtual */ diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 4dd8fa6d..fea04e0f 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -18,7 +18,8 @@ namespace TelldusCore { virtual int dim(unsigned char level); virtual int methods(int methodsSupported) = 0; virtual std::string getProtocol() const = 0; - int getModel(); + int getModel() const; + void setModel( int intModel ); #ifdef _LINUX void setDevice(const std::string &device); diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index 3ec645bb..a492d6a4 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -102,6 +102,15 @@ Device *Manager::getDevice(int intDeviceId){ return dev; } + +bool Manager::deviceLoaded(int deviceId) const { + DeviceMap::const_iterator iterator = devices.find(deviceId); + if (iterator == devices.end()) { + return false; + } + return true; +} + Manager *Manager::getInstance() { if (Manager::instance == 0) { Manager::instance = new Manager(); @@ -115,4 +124,3 @@ void Manager::close() { } } - diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index 27f54b71..7b86f7cd 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -29,6 +29,8 @@ namespace TelldusCore { Device *getDevice(int deviceId); + bool deviceLoaded(int deviceId) const; + static Manager *getInstance(); static void close(); diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index e50836f8..fde63c6c 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -358,6 +358,13 @@ bool WINAPI tdSetModel(int intDeviceId, int intModel){ try{ Settings ts; blnSuccess = ts.setModel(intDeviceId, intModel); + Manager *manager = Manager::getInstance(); + if (manager->deviceLoaded(intDeviceId)) { + Device *device = manager->getDevice(intDeviceId); + if (device) { + device->setModel( intModel ); + } + } } catch(exception e){ blnSuccess = false; From 582029b63c8b47bf5ed07f48fa1d43e2e02bc5ca Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 10 Jan 2009 11:22:27 +0000 Subject: [PATCH 0744/2215] Saved the MainWindow geometry on window close --- telldus-gui/TelldusCenter/main.cpp | 5 +++++ telldus-gui/TelldusCenter/mainwindow.cpp | 15 ++++++++++++++- telldus-gui/TelldusCenter/mainwindow.h | 3 +++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/main.cpp b/telldus-gui/TelldusCenter/main.cpp index 5bb03556..e3c64934 100644 --- a/telldus-gui/TelldusCenter/main.cpp +++ b/telldus-gui/TelldusCenter/main.cpp @@ -10,6 +10,11 @@ int main(int argc, char *argv[]) { Q_INIT_RESOURCE( resource ); + QCoreApplication::setOrganizationName("Telldus"); + QCoreApplication::setOrganizationDomain("www.telldus.se"); + QCoreApplication::setApplicationName("Telldus Center"); + + TelldusCenterApplication application(argc, argv); MainWindow *w = new MainWindow(); diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 75dfd638..170c6254 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -6,7 +6,7 @@ #include #include #include - +#include #include "../TelldusGui/telldusgui.h" @@ -15,6 +15,12 @@ MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) , m_pagesBar(0) { setAttribute(Qt::WA_DeleteOnClose, true); + + // Restore size and position + QSettings settings; + resize(settings.value("Size", size()).toSize()); + move(settings.value("Pos", pos()).toPoint()); + statusBar()->setSizeGripEnabled(true); setupMenu(); setupToolBar(); @@ -31,6 +37,13 @@ MainWindow::~MainWindow() } +void MainWindow::closeEvent( QCloseEvent *event ) { + QSettings settings; + settings.setValue("Size", size()); + settings.setValue("Pos", pos()); + +} + void MainWindow::setupMenu() { menuBar()->clear(); diff --git a/telldus-gui/TelldusCenter/mainwindow.h b/telldus-gui/TelldusCenter/mainwindow.h index f48a66a6..0221aeb5 100644 --- a/telldus-gui/TelldusCenter/mainwindow.h +++ b/telldus-gui/TelldusCenter/mainwindow.h @@ -13,6 +13,9 @@ public: MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0); ~MainWindow(); +protected: + virtual void closeEvent( QCloseEvent *event ); + private slots: void slotAboutApplication(); From 635e12084786904013b8210a1bf2bdfe84a5f51f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 10 Jan 2009 11:25:51 +0000 Subject: [PATCH 0745/2215] Added column 'Action' to DeviceWidget --- telldus-gui/TelldusGui/TelldusGui.pro | 95 +++++++++++---------- telldus-gui/TelldusGui/device.cpp | 33 ++++++- telldus-gui/TelldusGui/device.h | 9 ++ telldus-gui/TelldusGui/devicemodel.cpp | 21 ++++- telldus-gui/TelldusGui/devicemodel.h | 1 + telldus-gui/TelldusGui/deviceview.cpp | 32 +++++++ telldus-gui/TelldusGui/deviceview.h | 17 ++++ telldus-gui/TelldusGui/devicewidget.cpp | 7 +- telldus-gui/TelldusGui/devicewidget.h | 3 +- telldus-gui/TelldusGui/images/bell.png | Bin 0 -> 1803 bytes telldus-gui/TelldusGui/images/turn-off.png | Bin 0 -> 1453 bytes telldus-gui/TelldusGui/images/turn-on.png | Bin 0 -> 1483 bytes telldus-gui/TelldusGui/methodwidget.cpp | 47 ++++++++++ telldus-gui/TelldusGui/methodwidget.h | 23 +++++ telldus-gui/TelldusGui/telldusgui.qrc | 15 ++-- 15 files changed, 241 insertions(+), 62 deletions(-) create mode 100644 telldus-gui/TelldusGui/deviceview.cpp create mode 100644 telldus-gui/TelldusGui/deviceview.h create mode 100644 telldus-gui/TelldusGui/images/bell.png create mode 100644 telldus-gui/TelldusGui/images/turn-off.png create mode 100644 telldus-gui/TelldusGui/images/turn-on.png create mode 100644 telldus-gui/TelldusGui/methodwidget.cpp create mode 100644 telldus-gui/TelldusGui/methodwidget.h diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 32a9beab..4d7be802 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -1,46 +1,49 @@ -# ------------------------------------------------- -# Project created by QtCreator 2008-12-11T15:48:29 -# ------------------------------------------------- -TEMPLATE = lib -DEFINES += TELLDUSGUI_LIBRARY -SOURCES += telldusgui.cpp \ - devicewidget.cpp \ - devicemodel.cpp \ - device.cpp \ - editdevicedialog.cpp \ - vendordevicemodel.cpp \ - vendordevicetreeitem.cpp \ - devicesettingikea.cpp \ - devicesettingnexa.cpp \ - devicesettingnexabell.cpp \ - devicesettingsartano.cpp \ - devicesetting.cpp -HEADERS += telldusgui.h \ - devicewidget.h \ - devicemodel.h \ - device.h \ - editdevicedialog.h \ - vendordevicemodel.h \ - vendordevicetreeitem.h \ - devicesettingikea.h \ - devicesettingnexa.h \ - devicesettingnexabell.h \ - devicesettingsartano.h \ - devicesetting.h -FORMS += -macx { - LIBS += -framework \ - telldus-core - ICON = images/telldussetup.icns - TARGET = TelldusGui - CONFIG += lib_bundle -} -!macx { - LIBS += -l \ - telldus-core - TARGET = telldus-gui -} -win32 { - LIBS += -L . -} -RESOURCES += telldusgui.qrc +# ------------------------------------------------- +# Project created by QtCreator 2008-12-11T15:48:29 +# ------------------------------------------------- +TEMPLATE = lib +DEFINES += TELLDUSGUI_LIBRARY +SOURCES += telldusgui.cpp \ + devicewidget.cpp \ + devicemodel.cpp \ + device.cpp \ + editdevicedialog.cpp \ + vendordevicemodel.cpp \ + vendordevicetreeitem.cpp \ + devicesettingikea.cpp \ + devicesettingnexa.cpp \ + devicesettingnexabell.cpp \ + devicesettingsartano.cpp \ + devicesetting.cpp \ + methodwidget.cpp \ + deviceview.cpp +HEADERS += telldusgui.h \ + devicewidget.h \ + devicemodel.h \ + device.h \ + editdevicedialog.h \ + vendordevicemodel.h \ + vendordevicetreeitem.h \ + devicesettingikea.h \ + devicesettingnexa.h \ + devicesettingnexabell.h \ + devicesettingsartano.h \ + devicesetting.h \ + methodwidget.h \ + deviceview.h +FORMS += +macx { + LIBS += -framework \ + telldus-core + ICON = images/telldussetup.icns + TARGET = TelldusGui + CONFIG += lib_bundle +} +!macx { + LIBS += -l \ + telldus-core + TARGET = telldus-gui +} +win32:LIBS += -L \ + . +RESOURCES += telldusgui.qrc diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index b12352bc..bdb9732d 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -11,7 +11,8 @@ Device::Device(int id) p_protocol(""), p_modelChanged(false), p_nameChanged(false), - p_protocolChanged(false) + p_protocolChanged(false), + p_methods(0) { if (id > 0) { char *name = tdGetName(id); @@ -73,6 +74,12 @@ const QString &Device::protocol() { return p_protocol; } +int Device::methods() const { + if (p_methods == 0) { + const_cast(this)->updateMethods(); + } + return p_methods; +} Device *Device::getDevice( int id ) { @@ -102,6 +109,7 @@ void Device::save() { if (p_modelChanged) { tdSetModel(p_id, p_model); + updateMethods(); p_modelChanged = false; } @@ -114,3 +122,26 @@ void Device::save() { emit deviceAdded(p_id); } } + +void Device::turnOff() { + tdTurnOff( p_id ); +} + +void Device::turnOn() { + tdTurnOn( p_id ); +} + +void Device::bell() { + tdBell( p_id ); +} + +void Device::updateMethods() { + int methods = tdMethods(p_id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM); + if (p_methods != methods) { + bool doEmit = (p_methods > 0); + p_methods = methods; + if (doEmit) { + emit methodsChanged( p_methods ); + } + } +} diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index 771b9ece..a6b855ab 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -28,20 +28,29 @@ public: void setProtocol( const QString & protocol ); const QString &protocol(); + int methods() const; + public slots: void save(); + void turnOff(); + void turnOn(); + void bell(); + signals: void deviceAdded( int id ); + void methodsChanged( int newMethods ); private: Device(int id); + void updateMethods(); static QHash devices; QHash p_settings; int p_id, p_model; QString p_name, p_protocol; bool p_modelChanged, p_nameChanged, p_protocolChanged; + mutable int p_methods; }; #endif // DEVICE_H diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index ecb19f2f..4289c08f 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -19,11 +19,11 @@ int DeviceModel::rowCount(const QModelIndex &) const { } int DeviceModel::columnCount(const QModelIndex &) const { - return 2; + return 3; } QVariant DeviceModel::data(const QModelIndex &index, int role) const { - if (index.column() > 1) { + if (index.column() > 2) { return QVariant(); } @@ -31,7 +31,7 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { return tr("on"); } else if (role == Qt::DecorationRole) { - return QIcon( ":/images/list-add.png" ); + return QIcon( ":/images/devices.png" ); } else if (role == Qt::TextAlignmentRole) { return Qt::AlignCenter; } @@ -40,11 +40,24 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const { Device *device = this->device( index ); return device->name(); } + } else if (index.column() == 2) { +// if (role == Qt::DisplayRole) { +// Device *device = this->device( index ); +// return device->methods(); +// } } return QVariant(); } +/*Qt::ItemFlags DeviceModel::flags ( const QModelIndex & index ) const { + if (!index.isValid()) { + return Qt::ItemIsEnabled; + } + + return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; +}*/ + QVariant DeviceModel::headerData ( int section, Qt::Orientation orientation, int role ) const { if (orientation != Qt::Horizontal) { return QVariant(); @@ -59,6 +72,8 @@ QVariant DeviceModel::headerData ( int section, Qt::Orientation orientation, int return tr("State"); case 1: return tr("Device name"); + case 2: + return tr("Action"); } return QVariant(); diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index 0dd4b462..07c33f22 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -16,6 +16,7 @@ public: virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; +// virtual Qt::ItemFlags flags ( const QModelIndex & index ) const; virtual bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() ); diff --git a/telldus-gui/TelldusGui/deviceview.cpp b/telldus-gui/TelldusGui/deviceview.cpp new file mode 100644 index 00000000..64e1f4bd --- /dev/null +++ b/telldus-gui/TelldusGui/deviceview.cpp @@ -0,0 +1,32 @@ +#include "deviceview.h" +#include "methodwidget.h" +#include "devicemodel.h" +#include +#include + +DeviceView::DeviceView(QWidget *parent) + : QTableView(parent) +{ + setAlternatingRowColors( true ); + setShowGrid( false ); + setSelectionBehavior( QAbstractItemView::SelectRows ); + horizontalHeader()->setStretchLastSection( true ); + verticalHeader()->hide(); +} + +void DeviceView::setModel ( QAbstractItemModel * model ) { + QTableView::setModel( model ); + rowsInserted(QModelIndex(), 0, model->rowCount()); +} + +void DeviceView::rowsInserted ( const QModelIndex & /*parent*/, int start, int end ) { + DeviceModel *model = qobject_cast( this->model() ); + if (!model) { + return; + } + + for (int i = start; i < end; ++i) { + QModelIndex index = model->index( i, 2, QModelIndex() ); + this->setIndexWidget( index, new MethodWidget( model->device(index), this ) ); + } +} diff --git a/telldus-gui/TelldusGui/deviceview.h b/telldus-gui/TelldusGui/deviceview.h new file mode 100644 index 00000000..27d0ca9a --- /dev/null +++ b/telldus-gui/TelldusGui/deviceview.h @@ -0,0 +1,17 @@ +#ifndef DEVICEVIEW_H +#define DEVICEVIEW_H + +#include + +class DeviceView : public QTableView +{ + Q_OBJECT +public: + DeviceView( QWidget *parent = 0); + virtual void setModel ( QAbstractItemModel * model ); + +private slots: + void rowsInserted ( const QModelIndex & parent, int start, int end ); +}; + +#endif // DEVICEVIEW_H diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index cf6bdd91..6d57e873 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -8,6 +8,7 @@ #include #include "editdevicedialog.h" +#include "methodwidget.h" DeviceWidget::DeviceWidget(QWidget *parent) : QWidget(parent), @@ -19,13 +20,9 @@ DeviceWidget::DeviceWidget(QWidget *parent) : deviceView.setModel( &model ); deviceView.resizeColumnsToContents(); deviceView.resizeRowsToContents(); - deviceView.setAlternatingRowColors( true ); - deviceView.setShowGrid( false ); - deviceView.setSelectionBehavior( QAbstractItemView::SelectRows ); - deviceView.horizontalHeader()->setStretchLastSection( true ); - deviceView.verticalHeader()->hide(); connect( &deviceView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(listActivated(const QModelIndex &)) ); + QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(&deviceView); diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index 55962050..f41beb92 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -5,6 +5,7 @@ #include #include #include "devicemodel.h" +#include "deviceview.h" class DeviceWidget : public QWidget { @@ -25,7 +26,7 @@ private slots: private: DeviceModel model; - QTableView deviceView; + DeviceView deviceView; QToolButton addToolButton, removeToolButton, editToolButton; }; diff --git a/telldus-gui/TelldusGui/images/bell.png b/telldus-gui/TelldusGui/images/bell.png new file mode 100644 index 0000000000000000000000000000000000000000..7876598021f853aa10c9502cc3b260d58d2b08e7 GIT binary patch literal 1803 zcmV+m2lV)fP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iO7w z5F;6!D73u*00xUmL_t(o!_}8tY+S_|$A2?(=A1pd>-DbhiIX^vO-Lb$b0di;D2>{x z&_)RLBGEqeq4fGdQAHI&C8$)WP=&-(U#eDAl`24`O@so1DpF}^5?V+oPSoHyapL&8 zw%3>S?zx}o14gPqN*y~z>PY{G`E=%+pZ?!>Ml*s{j2C{^y}=8tuO`NBG-+}sG5Xkd ze%>G7NDi^m&7Xg2+ktt%`IwQ7f3dU})QY?P#pzI5?iU_>;?E1q%_CO|kXjv23#a3e z?>=$#(6=5t@%b=h z;H%zI-zz^fdS&ux&ux3H>FJ4@l{&Y7@qwRI{wIGy7``c#vZYtk`KgKI@chi+_t$jP z3P~`>+|&rulamBdvnjOhdaJQ{-Q!z!e*X2F+5?uQ9FW`nntXfs!YhZj+-?_&&7HV~ zUh<_|DV91=!8vj9)RX%!pF95QrSoq-c+*Odrl%y(T3g8fYT(=-dUxN|hiyZgb2F2>v-t^JS0hM}vWgG} zX=N};og|zD6nVSG*zj2^^s3LUx&&!@N&t<4Z-2dBAELdzNNQq0AP`6?5Tqp0Bqpt6 zXI(NG@D@f1z1baqKk;hsY8}vND!L=z>`UV@Y+Ha)7$jg2LINoQA3Kx5(iwzQ)aNe~ z1wJN?_O1#*2;nBN`?)Br+afJvDMgwXAYJ;vAS5Uyuyh8?aZ#2g@Mj6UMT|+etQf$U z(*h`jzPzhe9mBC>gfJv=h)L5AHYY_0fu%Ltaj~?EWoL+z7~fkU3jChcIG~I%MZXs8 z4E+flTOkl6QAnCb2n>i6Ar+RBLpxb4+eK;zDJ5~_K^kpX4S-H!*&9b;%gppJQW%Ue z#BoFtCm53;FbJVgRtD|3*qJQaamhLsNfJ@3R@SZtz=Dlq=o(;1V?z|wiKB=# z6&PbMCPu0Z+IF#>EVi3PYa8F2B@P$!Y3zxWIG~I%#raCOt#Y-WJU*cp5cq;9SR{@D z;#iO-F=|1>WjmmM@z%CfkDpx^`BU| zb~-n8(X+LWHJjRT3kxVEkTOE*9BHaqtik+(AyM<3IQbr#d`k;ZT{gh!)4vtQh^)8h zJ{*Qa;?mXkC>9z>$Eu7Ek5evtj9fFU-5Ao=xsgmZk5{WQH9pMv@Brnpi)cII)*anc zDiiG4(su_iv}}M)UE5W4-gzcioW5gt=wC!}o#w7JOroz76O>EeZedNe^W!>Sczn4iQH_ z9UX0-x$oYCr=LIiw@cS`V03JvTG7?P)`oiT)*XE~xe~}M3zbP0E8}(?UwfH?>e| zUq`9ElZK`y9M=T_0*fd}sm;$)ug;tP^COibuMNEX;*o#+qP-<|VeraK`riQLk}SYp zk^>YP3)!B{x2*ZprmmLWb!&>9ZEeM-QgdUjp)qe4iAE)9vYn2e>mmFI#29N)T@o)CC)0DI&AgBNU002ovPDHLkV1nP8WRU;> literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/turn-off.png b/telldus-gui/TelldusGui/images/turn-off.png new file mode 100644 index 0000000000000000000000000000000000000000..007a177832a03e7c3cc84a343591e8bf67f79cd1 GIT binary patch literal 1453 zcmV;e1ycHnP)( z`eLz)g$4=+(L!7LAhGmDAEc$wry}&thf;;~2BJi$Vv$+`F*P<;EgFlL+>?{bo;`c^ z%*@}1J$rJZC$$|Ic9-4noA00R`)7%n@$eub08lGdJeORxYW=gR)Pl82sVc4g>#m!= zdj9;$2LNjuDwG< z-!XH34nA6ih^V=F&(mABZ24yI-j=lu4Rw-800`elVwf4sjQ;-n!G#N#`>tN?ef{|H zFK$LWDk^c~#vRLAT3-IGt?kw7L?Q-&05F(ClG1x-VEOW;vE93C)+r?~3=Y1wfrti} zxma>+-MSY~wzlr9ipL!g0pT{Hpm3JVS}rP0CgZey`{ueJ$anPgTzm;YP7o38+jscw zZQGjHRa7JiAP@-uPBnz(=)`rj3)eA&px3?LjGpL?VV%Dis%9T|f7Eo-Y7EYlCbyhak|zQfDi&oi9)&gY=02@7B&?XNCl*n(Awnk zdB5Y}!TqA_BBOG-08$D#jzTQv0DwO*F!Xs-)0$5?Z0y;zm(CYn*tD>>_b>O( zod@i?9=oo`>GTW_4^Qye*d$L*&amrxJTWmf)6%l7=3#uXxEro zisgs<%eT&+?aVxke}oW#aoy=3l@h)&ws@R5jx1(R2w^-ga|S^Ev4qUb7cc&D#&MKp zw#HgxUDwq^Lqq!R-Fv#f|Bk+Q?|#0g=kgC+=C@Z)A&wk5JUTj>&S`C>wGjC{t4zkI z(b0?=8_TLom;RhNdi2b%02HK@2m-6;!_BAAW-?hLB|&SA$;l}U3=G5bvWUlH@O|IW+L-@C==Jyi{mID4 z#Cw&MPNU~#oWa2%WV6P&uDv@lGWK;}-^Jl_Kq?cZ@C6aAT)DF9z=0$0YHi-iWe7q zgU|;lC7z9#1PZePHfAVnIx0p%=OHi z%bYoL_I2&G*XP6DV<*!YgBw2fX2but{@?elZ!IMv?0l3`0N(gGwQru_qjw(S6Rxno z(`5SE4DWt*oMpi5rbR?<3Ba44<{^`Oc}239wAFvjB%89L-?272t!?*5XT_}qq=84fv*r#<@d*3n)N9a*zzffYl&nO?o@+KAdkQVU^Y?1_v{<4@i5?ffbZG6Mj-_Olmn`Si2}0HVGg!*XyXEyhlSf@ z4$pG;=kH^mbNYG4l-w;yTC9#L+^HHUw^#&QrmP_^Q{HkI*CAd-gzSe8bKE&n-LdG=RK(OYnk4DvphRj`|7L?B7ogt8HN z1SW)d9-6O0&;bofFYSf^@A2ts&8%ffyS_`~yfG z!2D}QUXc3v1hWCA16dnPtNdPvtOuqKSpX)2G=?OBB!!}^!5g#u7%*NrDOdWx{pY#C zk>d}l58UBErPzY#U?ZTzrfOHe$K12b8VX<{%;&anHQ}nqQ2}+mOy7x{0ZurR9BOD&~u?lQn%&dt( z_aW{JkpNNRv&hXgr zyndY^3B$?S(%(PJkw=PVG%v%_Sx8;b4w!vpy=eAN*9dp&ot-~`yxF#Ykokp#%{pWj z`s)x{h%yLM*y!dPz4W!>D7p<$MC8v?ycWl!CSC34X;ib#<$Y#$am36lkC>~?5i=Xy znZ3ET&r@eFJZVTK7_NvwD lUA0>6V7J?y0rdaU{0Bermul{N&(r__002ovPDHLkV1oL5&JzFt literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/methodwidget.cpp b/telldus-gui/TelldusGui/methodwidget.cpp new file mode 100644 index 00000000..706d3a87 --- /dev/null +++ b/telldus-gui/TelldusGui/methodwidget.cpp @@ -0,0 +1,47 @@ +#include "methodwidget.h" +#include "device.h" + +#include + +#include +#include +#include + +MethodWidget::MethodWidget( Device *device, QWidget *parent ) + :QWidget(parent), + turnOff( new QToolButton( this ) ), + turnOn( new QToolButton( this ) ), + bell( new QToolButton( this ) ) +{ +// this->setAutoFillBackground( true ); + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + + turnOff->setIcon( QIcon(":/images/turn-off.png") ); + turnOff->setVisible( false ); + layout->addWidget( turnOff ); + + turnOn->setIcon( QIcon(":/images/turn-on.png") ); + turnOn->setVisible( false ); + layout->addWidget( turnOn ); + + bell->setIcon( QIcon(":/images/bell.png") ); + bell->setVisible( false ); + layout->addWidget( bell ); + + connect(device, SIGNAL(methodsChanged(int)), this, SLOT(updateMethods(int))); + connect(turnOff, SIGNAL(clicked()), device, SLOT(turnOff())); + connect(turnOn, SIGNAL(clicked()), device, SLOT(turnOn())); + connect(bell, SIGNAL(clicked()), device, SLOT(bell())); + + updateMethods(device->methods()); +} + +void MethodWidget::updateMethods(int newMethods) { + turnOff->setVisible( newMethods & TELLSTICK_TURNOFF ); + turnOn->setVisible( newMethods & TELLSTICK_TURNON ); + bell->setVisible( newMethods & TELLSTICK_BELL ); +// qDebug() << "Methods: " << newMethods; +} + diff --git a/telldus-gui/TelldusGui/methodwidget.h b/telldus-gui/TelldusGui/methodwidget.h new file mode 100644 index 00000000..8ed4cd58 --- /dev/null +++ b/telldus-gui/TelldusGui/methodwidget.h @@ -0,0 +1,23 @@ +#ifndef METHODWIDGET_H +#define METHODWIDGET_H + +#include + +class Device; +class QToolButton; + +class MethodWidget : public QWidget +{ + Q_OBJECT +public: + MethodWidget( Device *device, QWidget *parent = 0 ); + +private slots: + void updateMethods(int newMethods); + +private: + Device *device; + QToolButton *turnOff, *turnOn, *bell; +}; + +#endif // METHODWIDGET_H diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index 4139bf94..2a2f4ccc 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -1,23 +1,26 @@ data/devices.xml - images/list-add.png - images/list-edit.png - images/list-remove.png - images/devices/17-356.jpg + images/bell.png + images/devices/143011.jpg images/devices/14323.jpg images/devices/14327.jpg - images/devices/51340.jpg - images/devices/143011.jpg images/devices/145041.jpg images/devices/145071.jpg images/devices/145091.jpg + images/devices/17-356.jpg + images/devices/51340.jpg images/devices/el2005.jpg images/devices/el2019.jpg images/devices/hdr.jpg images/devices/koppla.jpg images/devices/ml.jpg images/devices/sycr.jpg + images/list-add.png + images/list-edit.png + images/list-remove.png + images/turn-off.png + images/turn-on.png images/vendors/ikea.jpg images/vendors/intertechno.jpg images/vendors/nexa.jpg From 7c2ca424c6d646105a0fc071297839fe8e603d0e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 10 Jan 2009 14:31:02 +0000 Subject: [PATCH 0746/2215] DeviceWidget now emits signals on events like turnOn/turnOff --- telldus-gui/TelldusGui/device.cpp | 16 +++++++++++++--- telldus-gui/TelldusGui/device.h | 4 ++++ telldus-gui/TelldusGui/devicemodel.cpp | 11 ++++++++++- telldus-gui/TelldusGui/devicemodel.h | 4 ++++ telldus-gui/TelldusGui/devicewidget.cpp | 3 ++- telldus-gui/TelldusGui/devicewidget.h | 4 ++++ 6 files changed, 37 insertions(+), 5 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index bdb9732d..23d0f339 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -95,6 +95,10 @@ Device *Device::newDevice( ) { return new Device(0); } +bool Device::deviceLoaded( int id ) { + return devices.contains(id); +} + void Device::save() { bool deviceIsAdded = false; if (p_id == 0) { //This is a new device @@ -124,15 +128,15 @@ void Device::save() { } void Device::turnOff() { - tdTurnOff( p_id ); + triggerEvent( tdTurnOff( p_id ) ); } void Device::turnOn() { - tdTurnOn( p_id ); + triggerEvent( tdTurnOn( p_id ) ); } void Device::bell() { - tdBell( p_id ); + triggerEvent( tdBell( p_id ) ); } void Device::updateMethods() { @@ -145,3 +149,9 @@ void Device::updateMethods() { } } } + +void Device::triggerEvent( int messageId ) { + char *message = tdGetErrorString( messageId ); + emit showMessage( "", message, "" ); + free( message ); +} diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index a6b855ab..6f030ceb 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -15,6 +15,7 @@ public: static Device *getDevice( int id ); static Device *newDevice( ); + static bool deviceLoaded( int id ); void setModel( int model ); int model(); @@ -40,10 +41,13 @@ public slots: signals: void deviceAdded( int id ); void methodsChanged( int newMethods ); + void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); + void eventTriggered( const QString &name, const QString &title ); private: Device(int id); void updateMethods(); + void triggerEvent( int message ); static QHash devices; QHash p_settings; diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index 4289c08f..4868fef5 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -97,12 +97,21 @@ bool DeviceModel::removeRows ( int row, int count, const QModelIndex & parent ) } Device *DeviceModel::device( const QModelIndex &index ) const { - return Device::getDevice( deviceId( index ) ); + int id = deviceId( index ); + bool loaded = Device::deviceLoaded( id ); + Device *device = Device::getDevice( id ); + if (!loaded) { + connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); + connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); + } + return device; } Device *DeviceModel::newDevice() const { Device *device = Device::newDevice(); connect(device, SIGNAL(deviceAdded(int)), this, SLOT(deviceAdded(int))); + connect(device, SIGNAL(shfowMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showsMessage(const QString &, const QString &, const QString &))); + connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); return device; } diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index 07c33f22..ff65899a 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -25,6 +25,10 @@ public: Device *newDevice() const; Device *device( const QModelIndex & ) const; +signals: + void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); + void eventTriggered( const QString &name, const QString &title ); + private slots: void deviceAdded( int id ); diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 6d57e873..25910b16 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -21,7 +21,8 @@ DeviceWidget::DeviceWidget(QWidget *parent) : deviceView.resizeColumnsToContents(); deviceView.resizeRowsToContents(); connect( &deviceView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(listActivated(const QModelIndex &)) ); - + connect(&model, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); + connect(&model, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(&deviceView); diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index f41beb92..54af343a 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -15,6 +15,10 @@ public: explicit DeviceWidget(QWidget *parent = 0); virtual ~DeviceWidget(); +signals: + void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); + void eventTriggered( const QString &name, const QString &title ); + protected: virtual void changeEvent(QEvent *e); From 272bcb0daf4ac7d8f775b95d3d351a378112bef2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 10 Jan 2009 14:31:43 +0000 Subject: [PATCH 0747/2215] Outputs messages in the console on events --- telldus-gui/TelldusCenter/mainwindow.cpp | 5 +++++ telldus-gui/TelldusCenter/tellduscenterapplication.cpp | 9 +++++++++ telldus-gui/TelldusCenter/tellduscenterapplication.h | 5 +++++ 3 files changed, 19 insertions(+) diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 170c6254..5743612d 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -8,6 +8,7 @@ #include #include +#include "tellduscenterapplication.h" #include "../TelldusGui/telldusgui.h" MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) @@ -26,8 +27,12 @@ MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) setupToolBar(); //QStackedWidget *centralWidget = new QStackedWidget(this); + TelldusCenterApplication *app = TelldusCenterApplication::instance(); QWidget *centralWidget = tdDeviceWidget(this); setCentralWidget(centralWidget); + connect(centralWidget, SIGNAL(showMessage(const QString &, const QString &, const QString &)), app, SLOT(showMessage(const QString &, const QString &, const QString &))); + connect(centralWidget, SIGNAL(eventTriggered(const QString &, const QString &)), app, SLOT(eventTriggered(const QString &, const QString &))); + setWindowTitle( tr("Telldus Center") ); } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index c042fdb4..6834aa30 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -1,4 +1,5 @@ #include "tellduscenterapplication.h" +#include TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) :QApplication(argc, argv), @@ -17,6 +18,14 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) TelldusCenterApplication::~TelldusCenterApplication() { } +void TelldusCenterApplication::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { + qDebug() << "showMessage:" << title << message << detailedMessage; +} + +void TelldusCenterApplication::eventTriggered( const QString &name, const QString &title ) { + qDebug() << "eventTriggered:" << name << title; +} + TelldusCenterApplication *TelldusCenterApplication::instance() { return (static_cast(QCoreApplication::instance())); } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index 35eac6cb..6e64be47 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -13,6 +13,11 @@ public: static TelldusCenterApplication *instance(); +public slots: + void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); + void eventTriggered( const QString &name, const QString &title ); + + private: QSystemTrayIcon systrayIcon; }; From 16560d02a17670cdd2025b5e4c45dbddd8f6095f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 11 Jan 2009 17:03:03 +0000 Subject: [PATCH 0748/2215] Removed Controller.cpp from CMakeLists.txt since it is not implemented yet --- telldus-core/driver/libtelldus-core/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 5f8d2fff..80f472d0 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -3,7 +3,6 @@ SET( QT_DONT_USE_QTGUI TRUE ) INCLUDE( ${QT_USE_FILE} ) SET( telldus-core_SRCS - Controller.cpp Device.cpp DeviceGroup.cpp DeviceIkea.cpp From 93734b0373f17c52c76a87a85415a834b35d83fc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 11 Jan 2009 17:03:52 +0000 Subject: [PATCH 0749/2215] Added namespace 'TelldusCore' to win/Device.cpp --- telldus-core/driver/libtelldus-core/win/Device.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/driver/libtelldus-core/win/Device.cpp b/telldus-core/driver/libtelldus-core/win/Device.cpp index 88b05ecc..1a268759 100644 --- a/telldus-core/driver/libtelldus-core/win/Device.cpp +++ b/telldus-core/driver/libtelldus-core/win/Device.cpp @@ -14,6 +14,8 @@ int getDongleIndex(); +using namespace TelldusCore; + /* * Send message to the USB dongle */ From 0a2f8105a4b811043002225b1488d393568fd869 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 11 Jan 2009 17:04:55 +0000 Subject: [PATCH 0750/2215] Fixed building of SettingsCoreFoundationPreferences.cpp on Mac OS X --- .../SettingsCoreFoundationPreferences.cpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp b/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp index 875ed5b1..133d1ad8 100644 --- a/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp @@ -9,7 +9,7 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "TelldusSettings.h" +#include "Settings.h" #include #include #include @@ -25,7 +25,7 @@ public: /* * Constructor */ -TelldusSettings::TelldusSettings(void) +Settings::Settings(void) { d = new privateVars(); d->app_ID = CFSTR( "com.telldus.core" ); @@ -34,21 +34,21 @@ TelldusSettings::TelldusSettings(void) /* * Destructor */ -TelldusSettings::~TelldusSettings(void) +Settings::~Settings(void) { } /* * Return a setting */ -char *TelldusSettings::getSetting(const char *strName) { +std::string Settings::getSetting(const std::string &strName) const { return ""; } /* * Return the number of stored devices */ -int TelldusSettings::getNumberOfDevices(void) { +int Settings::getNumberOfDevices(void) const { CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost ); if (!cfarray) return 0; CFIndex size = CFArrayGetCount( cfarray ); @@ -63,7 +63,7 @@ int TelldusSettings::getNumberOfDevices(void) { return devices; } -int TelldusSettings::getDeviceId(int intDeviceIndex) { +int Settings::getDeviceId(int intDeviceIndex) const { CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost ); if (!cfarray) return 0; CFIndex size = CFArrayGetCount( cfarray ); @@ -107,7 +107,7 @@ int TelldusSettings::getDeviceId(int intDeviceIndex) { /* * Add a new device */ -int TelldusSettings::addDevice() { +int Settings::addDevice() { int id = getNextDeviceId(); setStringSetting( id, "name", "", false ); //Create a empty name so the device has an entry setStringSetting( id, "model", "", false ); @@ -117,7 +117,7 @@ int TelldusSettings::addDevice() { /* * Get next available device id */ -int TelldusSettings::getNextDeviceId() { +int Settings::getNextDeviceId() const { int id = 0, max = 0; int numberOfDevices = getNumberOfDevices(); for( int i = 0; i < numberOfDevices; i++) { @@ -133,7 +133,7 @@ int TelldusSettings::getNextDeviceId() { /* * Remove a device */ -bool TelldusSettings::removeDevice(int intDeviceId){ +bool Settings::removeDevice(int intDeviceId){ CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("device.%d."), intDeviceId); // The key to search for CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, kCFPreferencesCurrentUser, kCFPreferencesAnyHost ); @@ -150,8 +150,8 @@ bool TelldusSettings::removeDevice(int intDeviceId){ return true; } -char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool parameter) { - CFStringRef cfname = CFStringCreateWithCString( 0, name, 0 ); +std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); CFStringRef key; if (parameter) { @@ -177,9 +177,9 @@ char *TelldusSettings::getStringSetting(int intDeviceId, const char* name, bool return cp; } -bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const char *value, bool parameter) { - CFStringRef cfname = CFStringCreateWithCString( 0, name, 0 ); - CFStringRef cfvalue = CFStringCreateWithCString( 0, value, 0 ); +bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); + CFStringRef cfvalue = CFStringCreateWithCString( 0, value.c_str(), 0 ); CFStringRef key; if (parameter) { @@ -193,9 +193,9 @@ bool TelldusSettings::setStringSetting(int intDeviceId, const char* name, const return true; } -int TelldusSettings::getIntSetting(int intDeviceId, const char* name, bool parameter) { +int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { int retval = 0; - CFStringRef cfname = CFStringCreateWithCString( 0, name, 0 ); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); CFNumberRef cfvalue; CFStringRef key; @@ -219,8 +219,8 @@ int TelldusSettings::getIntSetting(int intDeviceId, const char* name, bool param return retval; } -bool TelldusSettings::setIntSetting(int intDeviceId, const char* name, int value, bool parameter) { - CFStringRef cfname = CFStringCreateWithCString( 0, name, 0 ); +bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); CFNumberRef cfvalue = CFNumberCreate(NULL, kCFNumberIntType, &value); CFStringRef key; From ef96904fbe034bd9e1d50d7feea04846eddd5ede Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 11 Jan 2009 17:06:45 +0000 Subject: [PATCH 0751/2215] Linked TelldusGui with TelldusCore as a framework instead of as a library --- telldus-gui/TelldusGui/TelldusGui.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 4d7be802..987a5539 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -34,7 +34,7 @@ HEADERS += telldusgui.h \ FORMS += macx { LIBS += -framework \ - telldus-core + TelldusCore ICON = images/telldussetup.icns TARGET = TelldusGui CONFIG += lib_bundle From 6737a3eb47685221ac9e55f7e2c101d963726873 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 11 Jan 2009 17:07:18 +0000 Subject: [PATCH 0752/2215] Removed a warning when compiling MainWindow --- telldus-gui/TelldusCenter/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 5743612d..df1d53f8 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -42,7 +42,7 @@ MainWindow::~MainWindow() } -void MainWindow::closeEvent( QCloseEvent *event ) { +void MainWindow::closeEvent( QCloseEvent */*event*/ ) { QSettings settings; settings.setValue("Size", size()); settings.setValue("Pos", pos()); From 49b25f689190437ede95d2fa772fb89a17113bbf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 12 Jan 2009 15:01:34 +0000 Subject: [PATCH 0753/2215] Replaced the device-images to images with transparent background --- .../TelldusGui/images/devices/143011.jpg | Bin 2244 -> 0 bytes .../TelldusGui/images/devices/143011.png | Bin 0 -> 10090 bytes .../TelldusGui/images/devices/14323.jpg | Bin 13874 -> 0 bytes .../TelldusGui/images/devices/14323.png | Bin 0 -> 7558 bytes .../TelldusGui/images/devices/14327.jpg | Bin 13380 -> 0 bytes .../TelldusGui/images/devices/14327.png | Bin 0 -> 9180 bytes .../TelldusGui/images/devices/145041.jpg | Bin 1471 -> 0 bytes .../TelldusGui/images/devices/145041.png | Bin 0 -> 5230 bytes .../TelldusGui/images/devices/145071.jpg | Bin 1857 -> 0 bytes .../TelldusGui/images/devices/145071.png | Bin 0 -> 8095 bytes .../TelldusGui/images/devices/145091.jpg | Bin 1700 -> 0 bytes .../TelldusGui/images/devices/145091.png | Bin 0 -> 8602 bytes .../TelldusGui/images/devices/17-356.jpg | Bin 21369 -> 0 bytes .../TelldusGui/images/devices/17-356.png | Bin 0 -> 11684 bytes .../TelldusGui/images/devices/51340.jpg | Bin 1593 -> 0 bytes .../TelldusGui/images/devices/51340.png | Bin 0 -> 8266 bytes .../TelldusGui/images/devices/el2005.jpg | Bin 1570 -> 0 bytes .../TelldusGui/images/devices/el2005.png | Bin 0 -> 8147 bytes .../TelldusGui/images/devices/el2019.jpg | Bin 13133 -> 0 bytes .../TelldusGui/images/devices/el2019.png | Bin 0 -> 8998 bytes telldus-gui/TelldusGui/images/devices/hdr.jpg | Bin 15414 -> 0 bytes telldus-gui/TelldusGui/images/devices/hdr.png | Bin 0 -> 8238 bytes .../TelldusGui/images/devices/koppla.jpg | Bin 2060 -> 0 bytes .../TelldusGui/images/devices/koppla.png | Bin 0 -> 9440 bytes telldus-gui/TelldusGui/images/devices/ml.jpg | Bin 15133 -> 0 bytes telldus-gui/TelldusGui/images/devices/ml.png | Bin 0 -> 6611 bytes .../TelldusGui/images/devices/sycr.jpg | Bin 18027 -> 0 bytes .../TelldusGui/images/devices/sycr.png | Bin 0 -> 10413 bytes telldus-gui/TelldusGui/telldusgui.qrc | 28 +++++++++--------- .../TelldusGui/vendordevicetreeitem.cpp | 2 +- 30 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 telldus-gui/TelldusGui/images/devices/143011.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/143011.png delete mode 100644 telldus-gui/TelldusGui/images/devices/14323.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/14323.png delete mode 100644 telldus-gui/TelldusGui/images/devices/14327.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/14327.png delete mode 100644 telldus-gui/TelldusGui/images/devices/145041.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/145041.png delete mode 100644 telldus-gui/TelldusGui/images/devices/145071.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/145071.png delete mode 100644 telldus-gui/TelldusGui/images/devices/145091.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/145091.png delete mode 100644 telldus-gui/TelldusGui/images/devices/17-356.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/17-356.png delete mode 100644 telldus-gui/TelldusGui/images/devices/51340.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/51340.png delete mode 100644 telldus-gui/TelldusGui/images/devices/el2005.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/el2005.png delete mode 100644 telldus-gui/TelldusGui/images/devices/el2019.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/el2019.png delete mode 100644 telldus-gui/TelldusGui/images/devices/hdr.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/hdr.png delete mode 100644 telldus-gui/TelldusGui/images/devices/koppla.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/koppla.png delete mode 100644 telldus-gui/TelldusGui/images/devices/ml.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/ml.png delete mode 100644 telldus-gui/TelldusGui/images/devices/sycr.jpg create mode 100644 telldus-gui/TelldusGui/images/devices/sycr.png diff --git a/telldus-gui/TelldusGui/images/devices/143011.jpg b/telldus-gui/TelldusGui/images/devices/143011.jpg deleted file mode 100644 index f30c30a19daba431f1d48de4e9cfbb805ca41180..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2244 zcmb7FcTm$?7XGEtNlZu(kX{x;6%-y#5Ky`j6A6&`L=i+vkQR!{Ly)FCgY>6>Ak73K zC58YZilBmm^kyh4(iRXzsz8JX?#}GY{^3WdP-5)208;};R&-vdHeSWpCs zK%tNbBvMRV`k)wE3WG#SC`d@j$jHgbi5*l_R+LqimX(v;7Xj_H^7HY-1q9%-Xe3(p z|Hf`3fE3st76MWPz(^1T3EF)F$N(S!4B1-)^zV81GM@kx#t#7t?$ag*01yNM2J^$9 zLXclqKwtv)6raU-!Sl z`wn0bWRH+V{$lp6|6>aRkYJPoL`Tv5>@F7&+4BM;AxOXss0%5^s$lJG?eMAi^rG}% zg*|~@L2)hApMRQ#o?BNiZ0tDNK9HLmC}XK*;kM%si@HgyxywS2%q!U_RnG)OY*+w1 zC$uHSpa6e8E)O|s`u%sqNjuq;=jS8Il(5t^g+kuxnWZ$>N^Q>jo|kP>B;rm_IkVW7 z$fp~TERviXbi-j>YB7JsN9gVscwlUW$vZ?7XI(f6SB;o;P8(2VP#f;4tE%JS5fjh6 z<)k9S?5WcJ#kE_6z*YKcq^n=pi;>J%UvEVT>Se>Xy&q`mNMvT1=G#zg@wP43uF~I) zYL-mQo^I)>EdNb{xcZnND+Pl!FO@mm%zo%d)&)&0*hPs!U_{^wWWv zk{7ACuJ;i3O3Nm_jWk+(croU_SsX7fv-<=Yjm`X}S?J)i9h@L^4=Y=woLo?*(_njr zyinN_RkUP3|`v_UbWOo`nadc^ak8z(}>8d8>{qkm|}W8TgZl@HDq>>`OXLt8wG7j>db` z{j`yL$mU@D>sw~-i({4z8GH#=KiyP1M=e@bYR!HyPfl@nwA-5RWhHXR_F~0rx%P(m zb$R-Ve5g>I>!OZ-6*?XjpG(Rf>mu1DxDeu`R?- zVU=f~%N-`7<{?KoHUnppyXSot?^L;@Z_-EzC8n*!G(G~*)yWA3eR!6a)1v?NCN8|X z&;y!tQ0~&J?AFd+z0T#~HwOvT7Xfja_5H2B-lTF$Z{_gMh1W&An5<17u;)96{Pmc@)$vgzRDo8!rz9^-%dKy$8N$0-r_sD@-eWr zU7Q@KWxU~`tRG`si=k|pFEwq`*QB>|IlW53{{FOOzSS2o=^2okhXE|67jL@k?eG<^CbC~5XRcR+Lv)3AM7WKE~*MFdH_&Sy{S2Vg8h;6sj2)K>|+&Xa0`Li<< z$##jSXfDEV!}t#;?9hfqwB9_DnhWH2E%dyx)sw{j0mZ&sx>+P=J^ccN($0LrRYB36 z>X8YG$`vI${zjmBG7483*?qx}Q_U+2!0F`rhIY?(s!kAxD)MO>YgGae@hFX*Q&)K2%SVC7(HrE1U3eKxb6K*?ynas2{eUuaIa$L4k!D`YCL z|3b)$bp&lBOq^Xb5p=hbzfF($##2wncdUe~Le9o@*nTx!-RW=ds(@{i;fO%gAd}=c zl1Pw{Z;+P$)9Zm_F*RG`-7B|+W+7)TIi+$_=CP|8VEvB13-DdBk9(``uE?a~G5t(< zkKpSc?&Xh*k_x(fr4G(?coWXwGbpMSB&NJ6b9I_}o zmJ>ac{sbU4NX8``o>^mw;4rCCL?VMMbO0X3@COa9T)GSC)*&F@H?c+rUioGySdS-CFTn59TwW@8tE62K>iq%5p8%KG7(%Qo>OV6*`dp(Up z58<#x0aK{6nbYQWwcKX}TnkB+zEM5OiR}ZijLspP+qh?!zfTeKEE*}KRL{33zqzYP z*etE5pNkUugQ_V`#(PK#)>zuVxmcTtLjPg#(W6Q-6NPWSN>QGSEfVQJ{wSbwYP5l2 O=WI0fzyIg%r@sLnhvK&Y diff --git a/telldus-gui/TelldusGui/images/devices/143011.png b/telldus-gui/TelldusGui/images/devices/143011.png new file mode 100644 index 0000000000000000000000000000000000000000..c5c9c640b55c898691e2ec4ac3a7a840103b64f8 GIT binary patch literal 10090 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/14323.jpg b/telldus-gui/TelldusGui/images/devices/14323.jpg deleted file mode 100644 index 133f69518a9f58ae10889b40fb15500ff7810354..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13874 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 diff --git a/telldus-gui/TelldusGui/images/devices/14323.png b/telldus-gui/TelldusGui/images/devices/14323.png new file mode 100644 index 0000000000000000000000000000000000000000..0b095b6d54d1da44912f80cb01b6bbfcead01ae0 GIT binary patch literal 7558 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 Xk+{dLxs_J!`<|{ozQR0Pb>sg4^OF45 diff --git a/telldus-gui/TelldusGui/images/devices/14327.png b/telldus-gui/TelldusGui/images/devices/14327.png new file mode 100644 index 0000000000000000000000000000000000000000..37761b61790436a2c9bdccf88c4684a7c2c3ae3a GIT binary patch literal 9180 zcmWk!1z1yE7~bfVAqZ265t0*zfK0k$k|PA927-=~MjA#*BNEamj+7RV?htT@6KO$0 zT0lS={`>E_cjvjg&pkW${p$U`@5JcqYS7c%q5*+G^jey#XkfJY|D>V-z8By4B7uS0 zP1DR11iIGy{|QbLzIGe<5oV`})&YV1?|?v|;ULh-6)>)YK;8%tXu}2sl70gMu|7|+ z?o$VWcx<&)m5g3YZv_R!+k5A(uKMO3<(ySM9ycBzA3yMXmYT7sX#RK-(>+KQ3DNP9bb%p1wZz8Ja-$fyAKEFYC=|48x^K!8 z_K&6&{#@i<&KWi~yLvZrYvmJkeCGo;WrOFBR?ki@V>Jcc|GZebwlsS^hpF=cI7fy+ zy^sSUusCUa~wIY&V{k$^dJUzsxF65MF@JCG6&C>gb_y0rm|8pZ8Wfz@9 zY&PpL(?s$+&&Y4c+=mb2uvs7w;Xwoh7SV|y6H(DzRip-QQYV?@V~oyZbCSrSEdpb9pTl|ZR*73n2S+yWmXlZ;?Oi)WZFdF zc?BWA%lQe%`t%)E5C}U2iwJd@LFka2IJhef&5n1BkKVl4QsJh3Uyy3`P_Ql2Gg$n+ z!FXgbp$AH82lu4xfrCNs-8ar25}Avz4$9+yz&W1CBJUDY_)n9n2~N?BVMKhM@pa{& zY$VWsO_v-i+HwbZm+ycVeWSnHc-L2LcR43qEFHVy7-ofPQUT7vK%f!TF?I^J^3kxOdd|<=0x4MH%%`D$>jPt`v(YdlH2bxle6%NF~Hx~v!T9PYY zH21K0Eu4}SpXb?|nW^L9h6+-4BnHf3Vo|m=$CJRvW!&+w#QtXT_3B-|>d-Dq+s8zS z3!AJW&L{EPkmM;`c}8#o5=D70El|Gdac6b7O5Q#74~Kz8*rU5#N-4b6E&*6)=dGQA z{{G-CX}&?u8S;wEmCn%18(dG)rOKU(1XZ$%SPf7|{qBLnc;*I|LVbZJOqfY=jK*c!O~PX4WdLFilHnD(^(5g zCXx~*9+Ameo~4b36eb0RHo$2sHvwzvbq{=0Hx5+n`za+9`GBH)D%8$T6p;V}k! ziO?Yqd%fOT8FBdc%?X&Gt_+QBKb@+JQO~2E&Wc7j&zPW$vhwq0= zvKTi0H81Ia*St-ZQijIASGj%${;62~huZfZexb7GKWvU+q)DuHxoyBaH|^T!D;z2! z`bnV~1ZAS?*^NRbc9duvX<0LT*ubQ28ju)dRaHaV%r8AL&H|D8Lxq3l8eBeA#_1OC z>*eb5$KBX;S9uB#MbL@r5f9GVoQ^y^(gX$Eh7oj;6?DtnLM>k_co~Y?#-eLcb9aQm zrs?GKM~nk|d9IBC!|RHNJk&5E3c5g&90k^;``FVdm{y*FiTLq~OYQ}H%Ls1XXC*X-^3NmPu#fU#Mg>%y1f8m$xyD!}Y-dNNk1!5D?{@f3Po4R?Ya8kr^4 zreYpkl}wlMWTc{14I&V9k9s-Vlr76`ej)d&;h6jrO}j)3;o-fPtpt8FnqBPMhQ%BP(BV(Gmxa~fkRs= zTYR!)Hgwj^d!T2OgeGhjpLXGqn*npzQP6Qa10X2+@0M|ww|>8i0-HHuOY@AWxfYPR z6bG3_0Gv_HZ@12QWLuh}AS6nVP;_i*sbK4>+)kJE#kh4(Eqr8jl;>IFFC>9oDO@`hu zMnXO>HFDKV)+YX~Rn=0gaAl`d`yRcvjt*v~!DX_^Mc8?!y>;Btav4e3Q7>IiFyPcb zyV60U^lq5=$9>&zg_9aQX!lS%`N4~4#%ATY*Ow14;43!TjqWAuiB4=z(?pWMhe`0v zXw+mw0Cmu9A!yz zBN`=cWQaBApq9{K%CoClyDyldkho-=eOT_@YSK(4E*!5-RE3a%LQ(i{j}c>rbVP|U zdXnSzB!`wXG4>xDB`e{LwfF7Ei?E9^{CSFXQ@#JTXT-$B!1G6smzI{YQFz-4bJCma zQzWNTQT!2~xH=S_`#7_mw`rkKBeiAr zee;zDM^|IVh0Dmuh|MY?*UggEo$b*QvOV&d*);ZXsB3J6&rvh47DtM@-lkDnNw|x2 z#b_;@*;%*_v=RliGh=*BS^Xpb;=uM*u!wyw;0^C-{fHKLB=oFt20}J<^vFr=+Cwrg zVH1-0cT|V|?76y>8i{OxaR{WLO2!?NMhS%W8D%}OgWtqvxZ+(eh0*pq3^y2hTz@#H zR-rHQbk#nPlwbdJEf*T~%D7U<(36c4o8@r$**{MH!YUF1OmY14s6AR{r)B+Dot;zH22b(ZRP<{xpWLn2lHTC8dE&#})~M3a!@wZTWQ7XFOkXW!DmWaz zkl%5r<2?P5n)A4mvhxgVtjG4_dbfFO3NN+KpV^qBww<8eAkK#mADUWOMeUsZ{{H=Y zJ%~g0hP%zOa=e&NeX56c#_v*^Y|O!*aaia$EY2Go8RU>HM2AmB2A?C_&*pX(AJ3lx z)(R{a@XQT!JhT3JzUu2$Lmz*h5PTQMG&uYC6;8BdFAj*4)fiGh-Ego^B0CNfE?~zl zsGU@4iQd@=B_7)hI`~=Q3ik6K5;)i~s8DK@#kpiUAdU(E?0^%juV z0PZ*DSnqbW-Do$E$Zl$3p~^N;?Q%8^qtc#fIJvopqvCp#pC7`9KSvL^Lk!a;OT1w^ z(PTzD-|uUhxS6Gs6Z|OB>BHk6J=D-kixP@gKk-kar{;278xMylFKj;#kx2H38}+`=C#!$Cr~Rv(Cud}e zf2av9f>D&LEp10p_xFK{UN=UJn8*K|r(S~eg0yMb$h7}8Wfy^my+K69p_^pjm-aZC zYf5fItgq>e^dWJf;o&qiSWU!d*vrm_4kYJl$D#6jWn~Ddm_33{IDnA|q9XxQ6B{Tl z=j>c>C#O8A`k8WbYP9^va(6cgU^>y6nKv!`R?+|!M9`69P*o2jWiKRBp?m`N08WAF zG=8t%{bejnLd3qd;KX~Ek%%zUWTpvlS6p*GgySmR?EDLZjZV+Z`-0nVWXY9tiTl6% zwkDw?-u=d|socS*t!xs&8qk<1j12|@_Vn}wh2DMKP+$tbbaiyxSgb*v9E7{IXTD?Q z-VndQvsg4`j_<-E`PYLVd*`d0of{C1Kwtf|Ht;m}1n+#4__AQf{%QEpUQey`N)!X9 ze0Bzl3_xD(T187wCr~v(!k`>j>7#y8M!Twa-Pv?o7*UKvPO&Jk` zse{GEPYXpqL=^awmW9}4@l98_QY_z$A`drR^HaMmrh~cZG46R?8A8VXebZYXC3gRQ zR9nE&B92z16Mzf{)2{|((e9U}ubSS)Hgx0_T|f8tMF=#C^ycg9p%^GY(Gr*7nw#6b zb@j&^fsS2XMc!FO0K5XsG&IVc=jXC4tgLljKG5>VM-=tu^j{pr!oW9o9Lkr#0*v(VVSB2vf^>G!G(uT1sW9wqtX{({<`i}o7anN zf$4x0UJ0^OeUp2{TXTzD<-&UBZCR=T_Kp3`XZN!K!(8!rKsruHCl|2MO?p~pI1bp) z)-g4r9}>mYJSXDt^r-=yg)2fe<-J*18SGH@%1|y}h~yAdWs@YK)AIBgn5+oPLFOhf zN88t+XLiCYOczlpV~hdHFIDXz`v9dF_yoNCIJyW70i}5`@-6qIjOCe( zF{fkc3c~$vz4W)1{A^4bVrxr+fi8woa&!(T)UaOtUAt1PF$#OUtCSgvnO>t{)E<6t zhk2Ii;4- zYez`}-atGk%_!43qPPO*N73Jk^ZaQT#j2JCvXvw?tNJ* zt_4310X!n1-ZL2B#5Mr2ss&~9Qd?!ogsK;YA?U`|z3w$4q@<#AWqfTNeC*V@HHi|1 zKa9$and8({F_c;<0*`PWO*zK1(hc=d!^=-2$V*4?`U2;?Iz&6|m!*fhj?HscWsM&{ zMp&OOvcAd9?b~jgPrUn>&=bab6?(SQ!3lWGp2G?2q|cwV;CJtKHEeS<4&2vp94uKB zq*DRjAEtGkObIl)zqe_9MU!FWFIZG`{|SA-gm*w63mG8qZbXF3Oo@@u&Gijn8q%lO ze(<3zL*A-=Z+UCWm%`@h`8gs>D2nyWq?5kq_}as7Z9S$G<#+W9#}tc+N=+918VaWd zsVMn>J0UFjr{9bBHr}dCw)%;?w(hAr&$qJ!22`%;ZPHhY`ye#UHt>1zb8oMzUioV) zc65aazzb1$w245&jEh%~NZ`Ci;n?7Zf+=T*gyTJRxkB?YwMSw~qAZV`-d3i4PT0cv zD~%|<)&C?~$=YAd_2sygK!JmG*4Pc`myg%x10opScKE^JZOO`X`<59SO`*sO&J*LWk&YE* zAq-1mD}rw#lGoxlK;tPAx+4FAlwZmf_JZtjv9)Vw^8Et?duxSBi)Zs!@(xnZ`&;HO zT({<0Slf4&c7OE%UMKs$OZVa;_j_jH-&IjcBtmoSoSYi<=3k!OtK57Cpg%%2;mt?} zW*g|5on>>LP{yOX0HLw?e(#M#NqR?RUr(p$Etjvw|a7y>x1*O0>70zyJtKbLl;cj3;j=)_d0M}Wc8JCw!pE}l%E4$eq zk?HpK#+9pnYd$T&@p1`*Pnl;;k2yJ6x_K@pE*_5C2@^~I0$#0u+;l5Q$l9#eQ6)mf zLSNz@+uWH}=sVk>cJu9= zOHHeJJ$xzjkfILp!-Xke(TQmg5`Zn> z(OPk&;iQYg*aLpbUY!|m&B)JPB=6A5J+zApUC&T5DZzir_665iK4}48@Ggf@%J;o`|&Pj>u1~T1a(sP@9aXM&IYGu$>wC_X(bOLmj;ra3cg>g z*zoL#!c>$jQx-fOd#KX1l`xMYK}?_JS-L5G(nX2iQ%4rE0fe^lPDo?W*}u5BzQt!O zU)RZAE*?}$=yXie*7DjZ1mtC4Gs{k?#2$50l6DPB)P5X23erabnqV=ZmQ{qjI%j|J zEAqkl-;9plS3DZ}rABUJYOI)vO3St~i3F3-z|#|N|M%SF8p3oZ5xPV~ z{{cuW1ATn4aeBPB1mtB#Wd+NuVChMQN2Kr}?z4!W1A1yfW_#55gL3Uy^nA!q>$^8X zU=hf4-p~8kEM2p7?~2Xl0GV8Z!?=NY#Uv~OrgJ?Ng{Rx}wPcM{23MHSY9w*=egDq< zr|rlJa4Kx_fzYF$0it=qr`T42viAXw0W|n_OQP-DA1`TBQ`1m;vu6^w1X$v3E*JQI zVBV_mtxcsJ#wYM+|506>?3M*mb5>!fFbjr}7QRi-O|!oo#U;I8wd27vTzlE5d|ll` zDcV}0K~!goK5yr$2wmD*w`?wqE@9e_lgdH5+ggi$*{Ap@Jm0Xi%o}cYVx88~Qb{{6 zy0~7P-_MgIi(|EV0nV`SpmuFu=L3?hf|+fcVx|A375K(eGK_J}#y*yYnP?r(eCyuV z`^MAd=5M&PzLt#t^5c-M5Rv|3KUqW!hilVPKm17lz(1Wsjj(5yoo|+WlVLw=;j-6RG^x9;)sQRdWZuOZR{c>j!6}V|`i@CaeNj0BYW|l3|_r zf7V1KzJ76e!n%7{6~bOuS9d&fWHB=%CsG%hcf|F+(J944L8#t{wlax&eb@ccYJb@( zEky|Yy}`LNPP8q;#PjBjj(FRyaA6R?mQ4mbR5_nL-OPAyl)zzCuFuXFdU3)0Tu(D{ zbw*u671Rh+oE`PD`+}7R@qSXTD2JIDG<1y0w0hWOd=`eSFYh_e^xGxLMU4jkt3$dk zl2x|;Mg7my%dgjemplzPezN!3J!fRmXjM4>*V?LKj9LmW>14;ET+m@h5PK@xdG6!Q z=Pk?I0>;7!3=YZi(!QJ7p}(83-91_FazISM4tGuK8dmn*?eHuNH$(ln5um zC~O+qKNGSjq&#SRk?@a$Kcd5$>Yvc+2$=4R+JT7Ukxr601rcG>Eb_I(Y{Fe%Bx5gb zAUN@Vq5yJRN{|AwoJvKYGE+zAc_&(e zH#Uks+T%rfIQ~6p-C{U7%WqcQf*y0KFVK$5i#pT1=f8Na{+T#eZ+v<(FvFM@R?Kk8 zf#;ta^&@f+{<#}f+6)AWjA6rm!?*R zq3z$DERy4AHKwxt&=yg;9+~fnxMt9gjixprg#S-?EPdx96K+e{1_rVLH823|Ud1yv zqf^^Uc^6wyQTUs_f}HM!i;Gn{rf6#!+>^YwTLGHr*nyBU-gGm%VF@k^CX=!5tt~jm z*+o^gdyfPvl6!iX-8t(GC_$IPn<&w>^4ZLmaDr~KxJ0#CS!dUXeb`&{`x%~Yf5AH5 zoA^$kM-k*U;k^Tt#$}x9r-81EflyleVzbC-_KAQ_c1?|#ww|7yj}J@brmed>BVg_6 z<2}#*g1w-V_z5bZxi5csbinGEqnIb|LvFik25fl>VWd?Y>b)`osk9~I8w(?fZ}pYC z$*-~Hs@Q0JTEkgtN`v7dd#A!0m_pWNx%p@;gKJfhMJ6`Ox(p}`)sL?ax9@~} zanI>Ui@zMaKZu?>x(p~Z3A*YvZ8Nxg<0^M`G8#?-rLZyUR~oMUGcoh}H@cX4btHR@BY@gxtUIby z%XzAm-C%IxQJLwQ2zM=$(U4l}er<>9(F-Q~7OH4ua!SG6c4xI-zhvYcM&(2kp|k)1 zsb{(U7>4(^SOFkayN_eCn(AGgY#!EHIZn>pCNykUArtqN2u)2KDdj_oK%{`^-1u%W zA$Qj?w%w2iPkn9+-lcig*jy0LUBo=vw##khB>L7Q<>iYA_vg2sw;a2?*k}q-vulnu zsg5`K-uqr5vVxesTV71JYZ6;Cgp}T<3T`4%rb>Cw`f2>QY}LQ=%>BcU)cv9D;`|MS5LbM>a>o_o|}PZ#2q+^!Kp&cj~?qecVre5<<6QneCMK}N6l9TlPs6AtN| zLO(Q&hpjZZ#mQeHq@wwQ4|%PSyWFvOn)|M^5ws#NgstR*p&`gq8eBo#ei46-y(7)* zL+NMG#go6u*PLc!YbqhW)=KPO?IztK#5Fa zYTteTP-^k+jA-YJAZ{KT$?Q0QdKIL0BjPXW&9|TP@$r2^=NPCL#E-v7MTPIH8t2B( z1n4oAf@T_8B9gC4MC6C)OLSjPQ>aI0YQ%6kePN<{ZSyDX!FdwrB?PD?EaViT;TQ*h zp8LAmZ{;7vWH7YF{{G7yIMA>5`~hc2$nTr)=OB-EnrLYE_aRuEe<{uU9_&FUl#-v# z;5rW#3DBFAN!*vRv$NZ;cPwQ%)rwbkx~Fh;GFpW?`ccYS-bNSR36o16k)WbezD(|4 z_sJ^CFfF2{PPurc{Lkw8%>oB=vK(QGpeTQ`wIea^B8taMNGcytSRr#(B2MKGOidzhMlS3ZMvo z5_2pl-tGO|7%>uZM8>bE*}r#QlKNMuf6^h-PJcBTiDbRm>-JZz)_NL|6E7LaEv}cq z8v)Z&k+|ipDQNI7?u|k)i2-!6HRkSQdk}4~`>xpeuO`;&CRuVrsHRF(#pA{v;dDqb zGxqx7Z+5y)iMza7IM)_>6m|nikZRnX{l5+AeA2FvdiT>G__K@X!TyL-SE{_71_6Ad zn!$l*IK;EQ##rzUZ*N(g5I#aF9{kZ`Qgua;GxhzODGBm$&74L*rfwfv(Y6<$nW6?8 z=XddcuCR*=S7%od?5i$nUt@l?sJVTH+!4G!#6_m^c8B=5g3tVmy=jBr{8oRaD8M4v zgg*TSVIMuewcbJ*KbvCld|Kn>h<@Meu(ZI*9rF`Ezj*Uw>^^3^Gx?wu(b^!jLkzhMX$% zpJdpRg*V;jg#ulBk-wp<=Zu7tm1c-~F1giq@Bw4#`9H9<(j+2a*R85*W`368o>S7d zNGiM|IamjF_sO#PXXNy7#f4qMDL;_p1xr78Kpl6$jN>a6lCP7m4(@1{{7~hHt0frwjM~Cn;X@0|hnZqJY2b76BUH9mrpcDx(*=U34>jlWH zY5jPq;oj9V5*WoqFp+WW{_nLL&TNWooKW_)kv+nh{;ynm1*P+4WiueDNau-Nt66(*b4j4gZMA53N2CdFNx z>}`H*KqSvA1`Yj8!WU@;mDXp*JPF`iUHh$g^9rBQ|Y>En%Dpuh7<%*67U&!c0lpd>=gUVkhY5=7d`t5rMKc;MnGk)qUpwbO^!RH6h* z)n9+F$NayCKrRi1$3I&wqnWTA%r*f@vuZRY2KNNUqfeV6R|xFbENL1hH2t;Q!~5`E zp-07QFHheG%d<`#6*a))GKN>qZYT81t$3U$PI*%JoQ%f}V*;EB**VOngXrctU8K~gxI%r^hk_eudE-j4{W?cq*vE4tM6{ryL)5cgP%?Q|;1JY8{RjpLE G!TkpVn7H}? literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/145041.jpg b/telldus-gui/TelldusGui/images/devices/145041.jpg deleted file mode 100644 index ef54cc8335c1da525408593bf4c124744f84c7bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1471 zcmb7CdpOit7(TxlW5#v-+;7bo%n}izs1So80Ad!F>001N1Qb?wN8$cmtWMq&iX+WV+vS>vNS_-U!f}A3ZRaJ$t zFs!DjucfB0s{zB>1Z~|78}N9%nwFulAVDeI&HAS4n($)IHs3V+>z00Jq4f~{p$ z2{s4OYH4>h3|&sfr_DS=#r1SZYHb6iCDJ5{Q^cX4C z`dS!5z}BiZNSA|Zl1ZQ_B@i$Y2F^fifpHz7yl>(+b(NH9pW7=kM@KLgP3)d2XC|OR z!UB)eou}~(KFt%Cv-Xo;;6oj67gp;^0h<{;%+H85xPWCm_n${aZRO8ovG3WrSDer2 z2(Cy&N`POsgRB1puWP!#flAh}!V!DxikEA=^*Ra(@+z(>ZG=@~SN7eDg_j2N_R%<- zj@t*_`mih)${9{=G1C>k!W^fkQcd%Pxh9T-P$j*#kzI9rk+&l+Ieg)Rp9S}nVBLe1 z)KWCbvbuWC$6{U%+m`ZR!Dp59(I;mqCTppNJ9Fy`3l$=GusE0(#u2c+Z(y`g~0O2qnq7ifI{R zvJ339qyJ*?i3SPebA{gCNB8ru3`Lwd8Mm#bC{1Yp+6IfVTrY@?9nS6)Z z_S%*BH#y@20fM}EF=JP>>0b5?J7!aJWPt9AfnM+=W+Sh=N|D8*sAdw}Fs_>6jQ7PY z$W^aktU*a|br6d>ZOr@Is%`B>D_36Q=~LFWVUH7fA@i9y@#zRcv3qiBTbE2l+ryh_ z%{K17XmY8yU+kn#)NkE`E~H8mr5N4r@-oNa@bKUFjOl6~>bXVBbzidPbU4&rLQfWy ztfosqSXaCJb~@3>aAP2ADSxalq{)EV{)T8Kq-SMm-xOyPibfTwJ-epgiNWI^UurPf zBFzJopi&W&(UDZ~`n(>^Ndg4r-J0X$ae`;7&+mV}`$y-_ErrIpBZIR+POt>nTn;yN zvt<42J*tng>E`tVT{ZZkEzY~|C9Jszt>8REIge@O!YL)*jqK+PawM@KYPZsCQZ#`> ziHRUPS~+=F3%(gWaJGEZcRY$#vceTVY%ZA^C5~D;2|YPyxdBr??OP5%=ofkQP8`AN zD`EIfO~lo?_f0#;*^O*!?6WqdrWIa&8Ig3K?$?dEKCp`9?= z7)@?`H2Ev4uB2~;+j_mReCF8PP~TXCztR9{mUU6U4e_S*JHOpeotHCj3l)t)Yt|KF z6aVGR3k%J-e?Dln|D?`bI?ID(bi~ST`v=ly&Ivju%z>^wlXAVX$&&u4lR32DLeN%q zc;paS$}e71ZY+Nn6LrbHuJM$g3Iz?Berk0T8Z{hC;`nYL8+^8^5vY3vn58_$xAwTq zr376|?7pXxmB0_yu-9H}NTr6>2j|O^8!ZIixsf^*WOD|z0=G`ZyhtyUfd1JDk7{Ph ze0xge>_o8f`sEeo#1Eun3Ht1pNy#@lceE95Qs;74MmE)_n+ELPo0C>qfhy~+(u?C! Nxla#dnzl$L{sabvW48bR diff --git a/telldus-gui/TelldusGui/images/devices/145041.png b/telldus-gui/TelldusGui/images/devices/145041.png new file mode 100644 index 0000000000000000000000000000000000000000..1bac417b4bac3b1a531e37e1934698aeee6388f8 GIT binary patch literal 5230 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 diff --git a/telldus-gui/TelldusGui/images/devices/145071.png b/telldus-gui/TelldusGui/images/devices/145071.png new file mode 100644 index 0000000000000000000000000000000000000000..d67a2d3433046b6239efd5a13d0b306a60ff1626 GIT binary patch literal 8095 zcmZ8mcQ{*b*p67SV^t6uqbjZ1BZ}IamRO}q>{+uYwS}T~QG3>?J*sBK*4lf|S}nC2 zEoyz|_x<%<-ybLEoa8!h&ig*keLwg8yiq!jRjJ5X$Uz_wmAaY|8aQMAJ0K*$=l3)p z6mTMQQ#1Aifv9`_I|x$lQ?mkJBCOQV+8~hM9S|ru3Xcq$lJxl|E zm|T<0dsRT7+jrEJ=I{0i8MzoVM6Bfu%lC34tW<|5P5^4x~cxrS=4;z5jRYM-H% zRy7r*=W8Kz)DwRT+5LXw>k#80#f51;^RWUpSc3P~athRh!xpPlPnWmvvf_caZ`j|h zI`CVzd$dt|TbS#i>&zE}#+HSe2}2E|KW*u>?%%WUQaI1YrUeas^M7_)f6UWmk*#Tg z>}JzJBSdcA+5h+E%0ZyyG7P=jBawg(MU!iI8aq~66gVkBlF?eoKcAB6&>HrY@{n4A z{LQPF*S9;UK+ySdt4I73C6wM3lV+ebU-qZR@f!Da6!uR)G<`|GQ5Qh7uU$d%q{n}E zWjaZ--vEOTY9M)wcy3{#;BY-OM@EhYh~;wY&o7ir+y}cSz9zsw^+48hr zHWL*6oVtjCw+MlibBg5~L}1TaQE@ldycQuzdX=&SQoj%TN1{pBfZ zFPPq^rUn{QI3{Q)Ac_0kK}9!hV8KHU?3}!{afBcxE`j@7PO30ZHl>i5(WjglxFYtTF!Q9y!f`YwdEua-8_^kB0-fz=!Vbh zYH(=lVJ*(CMYVAh2uuu{$4DR9v;3?iY9@uO5p0SUX8tm*S^;v_9?v&8w)ZEskoR9Z zdiPy^r3C)h8Kr8IDD@Z%StVT}ig2VSPS*Z;Hw}7<+OL`}_5P_mY3E&HOlc>SrQY2LV-h zs$H0@0I6+jY&;z`PJQlw5|B9y-?^sxW(r0*>WV_Xqm*HNH^xp^mom@PqR%>z`Y+Ig zG23(|A;pX-kIWDZSU7u1v;V40A5n9!$PetD1WpNgi>x_!k-mzKZb4J6q|MyS5Fhs! zFZMI`j!t>##3=-wIO_NmQ*DB(lmD@XVTYD6H>b;LEZZa7WY=7>>Td-5zyTP5$ zx1o02;Qjp4MGRGY8LJOgTDD(#||L}Yn9BsPR`grI&4H+aOl+gW=c?&k8fZD<_50)z661t&z$ z@B3lB_qt4Lz|C9PQB?dQ5q4J{m;dp~3>nTHy&o{pCAccmH+FbxPV9CrGal?vW*X}B z;tqEqA`dZ!p6_HmvDT%(qeJx9Ch*aLamgRuzK{_=WYp5ipmb@gYC6u9e- zNzqO{?v9ZauQ#7-aJ$h*#c|Bs+7y*XYJeJ2}OYMNbfI9K(!LEjXEUglSBiny9lg_dXt6`oDQH zJLY?(I=!l&D^C&B2MdFOjZ-`EZTiUGa46>C>}4lrtm(D_zTNVNFuAZ=h!6?#&V*=q zGMxn-7o}p8OBF{NEkfN_)Sv?<2q9X?2Q1D#jgKc^@wWoh%Dpa?S~V$Zy8&To4oQ!zcLqU`iG_yhX9EZ4FGgUuN;Z z?-z$UOC{qUKve`Gij;*A-6YO;&xZQIr07`4G|#&GHPU18TrHZ_jY11g$dd?w^O^;^JdJU+R>f&n+&7p~+)a2n)v{ z^3bPE>G9@DeLec$)I4Q5lz>D<5=oCLXILLeGntf4X6AXIp7WG-2|8;w87>d<^j-25 zVK-2vvwJ`O_!;K?@nc(DTs*tIdU>nrd22+g&tbu|qdX+!_*G22|E6No%b#>Pe!Iv| zi!V@d@46Rxu`|s<>PbWm2#^(}1&mXjZcoH?RvAk4>U8GTia%ca@|WEWY1JNQH0Q7V zePF5^8@F#z{AT`SPo$5DU{(My8%%~(T6(`9+E>0W=NU?CHmQubx(b*IGeKa3jUdDB zaJ7%|VnQQih#jSCBM3o}K4R*NR^oU}UG)(KtKaFtb7yB~L^S7#p9~xhUyGGk>6qDn z!NfZiG~mF~zHza6v~*gKC3ehNyfTlizw?#! zXZk0T4D!%5RoQ>E*Mkx_;~!|X8%P%R#r?jp^P9KFJZoI(Ez*2{G@&VAOwOS_>5=!@ zpFzVT%U|)lef6k`f*heuyc8Phi*V*`-Ldb0DKaR-sNW#4M~-MKlNPj7?BkNK>}wSaZu zrA={xZ00xrX0-#7iqyIUdqze80_z?aAU{}Y4s-S2U_I*<2n?~UH*S+f(Iq4|U<6@# z^UejUhZ2FO7qW61R3q7z{+lP@QcE8WqR)+uwG9o#NSoIz-Nu0c)dHlKvt!}zP77R^ zUo6Z5(hbNkZyz68<-`XLWZh7Q3@-W+Nto4HCrx1R{{9Oh`Cz`mwTt#5;vo_t7M<$Z z{DwXW+_^R-2_c2euw`@AThE=5_53&Nb&NC`NdJq))xLuRe$?sRgoRI(&*$OHpYV&T z*W#}>VkLg9dbWHgun%U&>iQt>xU9Cv`m6>pne655CYLE-VvHX|7C@@@zArR50U7#g zud)$XJa-`OZTJzXxrK$U>+45=PIFmli@I-Ah4JxW!d?HVc0d1Z1E@RR=wCflgiik2 z49ca`j!o_xBvoc#qW}Eyq998_8`=Z2#X^;Ii8zQxa%JQ9W~(=LWN(^@f>G4E<z~0$FC?yBn2)a>+oWPk0%+HU1s^O z7hQ2wBh3%?HIs;9gw6un@ddmJ@P4=FOxce~yVs$Bm^=e8U{8-A(Pc)V*yC&K>cAtC zK$2CNvM_QtYGxUF{)Urx#fydgMmD&Ph0`13Tp z2z1r5D4BHd|4yIVVJ~{mK0S*|$^c=gz0WNAskWA26pz5#(|>>LC7$Zy{hacR;*_Hp zZ&3yF&zBGFMOntM3z5be4%sqAf~Hc2Mn;t))w529(klXjeD|Q%x(*j-u>C@>!duni^Tw$4J84HM8it?{>>eI)FDKR8(DV*9O>bg=+} zT^gO3+$}5!vM$t;AUmVE{d!Mi!c___HliJfG28P7<~5%`N8HWzr`vKI^ez2qMU1&s z2~U=c3*+Q-H44{bOADzg9!r6S8kzYL$IJYkQ}S5qq3mOVZ6^vvFqyp~xP7@sD#RYY ze(?yk1B>sUX~Yn(UvCPu3e|%@n_wHM&jz3Vi43{hUbwavy`dV-|RBN|BoRPY|^7#fq|xbJO-w>B{UYyAkO+`^?dYc zZ=l&yNOR7$Umd2iRCM`vGc)fCtw!-{E&P8^Pvs$<8}YJnv*tl;qcS&4XX`XUk*ik+ zKEQOU?5M*Hl0@a^M%uwe1tZ zdk+yr(0TulGhF3`!(FNS73a7>Ts*+pY<6!NdJ)uNY7x2zuVqJ$$4P>5(UXo!_7Jg@+`I-Z=cg`hGE`}$%|!LPpt@M^GqzSu9BV- zb{8=~LQNjrf8PX~q9-~BGglUb2M_Zb2;V;Z{+$ze7x;mRVZ*%hfpDMrFwC#X z)#@1BGlC!TxiwK72%as4r-GL(5GElCT+xd5ygI3N>C(A`N>(WLu61hD(eQ51??Z?? zvtB^17x0E2&PHQ+f;TqB&OpixMQhR^D>xdg07g(lyyQzMwms|>X#2=aM^#hRQPcn< z>n3qOf5#)%2`47tVlYnHP6DY#)&u?*Qnn_(n0g( z#5fblryScE5k(*ihKyuk=MxA4tUwcDVGzS8)iD<^B8l2bK#O+?X1VFu+ObGE6s&e) zFhQ;m0nZ!TdI#Fr`IH6|sxbMHz4x9}(;u#-QznS}1;{uEiWqzjmO`LlKs;$6U**^_ z4Gr~A5ilPK!6^B{UHULjjYNEqHaO>jVVNZE^dC)<6J$HZBx5GVdI^l`c6SJVyjD}Y zPlt*r1o&0`Hyr~Pw_ci!M~_WDb%f$uzrGD2$A%tGMBxa}*y6%MomxMtJ<4xV5*?_X z1OfqNhJu1(=G(#kJ^`q!0R2trM?{?XC@a7n{+}0L+~=#eIQVtIK~EPwrkl12W{y=s z@oJ?p2c`D?y#|^Hli4*;BuN-;GMW{eU{l0U+T8)W2<~pGe9eKCu1q!=sryBNb_8mY z1)xy@sdh^!T>ZME6BFFfAO@1Fp6zbL;n}A4yk0(J18})Ekdhnb8TTaU-(-{bJ`0f3 z|68+mjc{H6VS6X%^@vLKr1!WxSg2RHe@l5*$6QE$jC`lqW<{mXJ?sG!G6uguZg~?#7g2UWt+6@Qx z>GfB`3b+It+Ra6-rZO6e&xC z2WwPxtv%^04Jq8=R&$y|En;zy9((JlY`VKUlMVM?;lG3m3y#+iaSTKp*iLL^s4EKb z@$-j5Ljj6>mht1_5g<#qZAXUNPA1GPot!8RU$63fNWLST!zIiyL1t$v{6^$AOwDs> zO)iq5YVatZM#f^`+wtbRctwqOir6}X1 zLk8z#kx3X)QAlrZZ6;jjMni(%aPj4_)wP$H#Qv@NA$t(nf9AE}Flg3kPAmoG7lT~{KhUNK& zcsVjYZFEgXrxt-=-@gdR9^0>N?wQ{cN_X4H`oj>sr527%=1807qzXvhfpT*5c9v{V zASXt%-~;8>FNIh9jgeN~Wy#tP?&xa})1TDpW3URg;3apC`cMrEYVd0PX2E#ieN46p zXlYQ}g9k16W?r~gbkMg-+Ewm>y8U)r>uV4=7Knprrgj+LxfVf;3YQuZU+M|p=!<1- z3b0#D^@RPAC=T~@5zEU;7AQ<9bUY*D0CM&X^;h22YUhc#0ll={yOsBf!cz{i6^k{Z z0LPwkkzp8T*>b07g5D6Qw;a)&Z5IcvfM=_;?e1eMKEf1(SYl1A(ay_Ty)5c3_%Q zV~~?Dl>;6hZRHGs#~0q(G?rdHU2mmEu!*w7&Od(T?(Xh{g5w%+xSJ4@%2X!Zc{L-G zz@9nj?s!17W!DC|bz`%@_xV}@AnQO3FHR&im!DgP*YwqGhvKoEu5Nwgx z#m@|K+_S&fhy&>W<^~lP1{j-pQi{srMsb5%DF(tW)5}jEJ8IEJ5OtKfos{z6tZ3ZI zoRb_08wp6%lQvU)8(1Q`IZS7-T(Jq}BumRK4JLWX*Au5#pBDF3O!ih$B97Rvo552= zGTc~@1#yunoXXaFYGq~RO|{vVe{YXb0{cLi=9ZQ|@$lYfbJSlMFRLpQER_0<%5uf( zy_k^tNS2v0m@~8E9NkLUOWQAW4Jh$o&p5jr-)$~dR#x0e*5wZ@-#hWzQ5d05y3ISg ziSY=n!95mFuhfFI@TcxdOuP_CXvXZRKa&OQ8D5V%Z743?Rwd5qLr$Z1Lm7uE8OD(N z1*o^e$bf6WZc{Rj@D1pmCas&#W-EhkG8d-`!5blzSWr^ctcT@0scBBWckdc38XpZE ziu83zsse3{@@9MFR+saZTN3DnxIb#tY*ZNxei3}QhE7hXzqf4gOu%lJ>Od5Iy z>{(e=frzsDlrb!-No@LlYy7o?nN38n0ZacAPs`M-S+m@~!ky-cc4{f;rLkF_8>bvs z=TGV_a0#9OrTDovJd)_v@T`?8dm5;~m+riTF?!vUTn`#<0dsbBT_mBbZv|)t==_vV zXMDZgW|UcQuVeR^7;jcWEBCOvP-@@ch))VV0MuKTr6xd(TlutnqbYH44A7TEWtCid zuv})9wBz)z#&Nm6xqrvn^__;FL^nLK-ig__b~e_CQYj1()js~p6|W_jvelik?cR>x zrjLtdC4bObLa>{5x<`617y=5S3FrXH4Js`gr_L{A`+ad?d(m(^-}zSDeHy;Z*bB*% z>Q}D%+gaE8JU7YFZ>G=Ly zP{85LU$5zzetif!TJ?4S!L_t9HB7C%# zr?ib4|1`K+6qEW;DsFOTlig5)!j;!dS7Tu5P;4XlR%V-!g5U!U9!cT7io6Q~f-S>R z4>9jR?@yn_RL-CBAd{>{t8(lJitjv&M#p43M7=fEKf3B8*j}+&bjhlV3XKgCeALar=|G>2`u(gTLq8|3gFQ9eaxm^v?Z1Kz5m*erP z53UdQ&bLgD`LG5q45EjU`<*L15I(zWtpq!|eL&=!FYN!_Ib`x3t|XYuBHw`nqT<;f zzpH{|kHIPV)O)2*JdO*sFp|t@ne5s&{II2gY~_aNf|0G9HX&yG_rG{1pyp5ge5oQy zCgEGWL?~HTkuk+DVK3M>X5W-h_gc{@z+IH(N)1x$tTQNm4|Rwy|BPFzwh`@NFv_+j z*ghuM3QJ4k21IOw$^I%JUxH@$y(^2~6%h3*{lIrD(&sYii&LE+fEM;ic#B+-Mf}tx zVYfAqOxpY>p91rKjcJ{0>bf~;V#*j9X_DUE^ZCbMm4HnMTHN=(+1T#$h1$evyWJgO z$)2Un{YNjV#Z`RX1X!!=`2EAfAamrjc!1&b6JxXnm8i{w2f}MBBlP z;J@j%a)klFRp|YPu!wIxu;=WA z$c4#ud%=`cUUAZK(zo?DWq za>2HUby=>b;Y37k4qz(lot&H&+YcA%b=Vp3um3&K1)ALB|JX%-wp5%M7tHQm*)S;I z20E9Sx(opt8XpGIH4IpJqAd7xRIv-@b(5)006uuG*S-%4}gKuXf%w`Oc)FXi_^yA zG+O`BM_Ss*dIAAik0AOalMVXBjRpu}Xl}TXOg1$&)!#s+Q7JSNiYa9c0%=llSez~% zuS+2!M9Tjy^*w;#*P4YPDnKC+j6mv#fD8Z%1+N|BZ$Vf9qcM0CPD^9E=m7|ZQ7{Ip zS%2680hGo@ur>s9cbq=eHy3YvGWLi2#DfMT+CMzLt+n{%P)Mn$ckGoW+Xw>xgVq3G zG=#!vEK@|oS!4ZIVHAv*qiqOOcVG1&&|Y&97y+(eR!kOcp@%^edz^p%hMGwLv?B05 z$C=MBD2Q;odHuBcyui7;W`fqp`ry>8XkgTD!*HplY@x@SI4Y2tRc zn)gOV353ueK&Msk{utRK#n`5h8Z#?KF)Xz1 z^K>K5?la4};9Si&ffPmJVL>3%X{3Sk!^Gm}3cu1k_X9)RuCjA`u(O$$Zd{~?`6Rc) z_Z^Ms=zqn|*>|iwA{Es-EOxaHdmf*38#t+B^0q{3`2w0!G&l?f4%(~1v0K#}4}G?O z>+Ip>k$vOFH8bTkFPpk8RNQYtv>SR}eEipd6-jj+-5bM<<~i4SBWDxel{+Q{Z1DA3 zY&*xE8ULz!lZYoT(sZAZyUedZZ3*aYw=Sc}T?pL5#HX}uq~U=}hX2?5oi1MOf&)-h zf>KAU)+1h*alVIe#5cWn?1dWW$L3@dN(ysp8?&c)9t~RucdiRW_lGf3&`E~6YT&wS zysYG6cq)T*DZu5nrWEt;odDL`TlxIhsh*r=R#UWLC!eLGBO@A%wn?{9gXS2kb2hRG zHSno9<(1SNDW`C>UEt+L$mYl9;W-1w%OpreBCss4d5>gz`$x@%dp%^|pS3n+e=bVEIS$ z@gZ^O9R3xtjjT<}B3HU;zT|KaePGlWcfsw|f9}^iO*gVEis@qI(IesMs_jl=SI>FM zol(_-;{08;ex8Yhn%yl_+uEIXZ(8J06uph_-IDr!Lc+3CwvMBd%u!P6H<>$B9dECo zN_Soeu1OR1eL5zoNj{akD3yJ2m7PDlA>iyEi3!S}fx7JjEh4h9Xp2MGk%9oG>4%5= zs_N-voeqc7=OYWLWIw%J`bA^?nf5}MdCD!GyZU9@l+koEJ9wZf^-AZ;`LF%;OY+|B z4!nnZp=FjpOJWZ)gpWsl{(T)swmDyw$+Pe^viv7K-Q@(&J^M7le`iF3a$SaWWhi(X zUoMxS*=4(7ZVax&&aRjwS7n@tU}+axNgv9mYrZadHn5&p=`mD`?0;d{3ku_g~h$}v|l3>CfIm!^{pBOv9)si zk2d~+X!-NtRj=3*gc4O)qIa!~@=NFQ;ia^NoZi-O>m*pF(1`t^HU?ID9FhzTh_g<&kF^*@-U|m-f+n6aDd!5_j zxr&nAJl#04ba7>-`*z=lU!WkK=*xuGLeQT*{_pQYhqW-L~ zIkvh7?~=T-E~iT;1W}#;km!}&neGkO>RZ-lTj=(Rw6OU(Awd5Q diff --git a/telldus-gui/TelldusGui/images/devices/145091.png b/telldus-gui/TelldusGui/images/devices/145091.png new file mode 100644 index 0000000000000000000000000000000000000000..287a6656098cf023be2a7cfb6ab9278049e6369e GIT binary patch literal 8602 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/17-356.jpg b/telldus-gui/TelldusGui/images/devices/17-356.jpg deleted file mode 100644 index 2403692d33fb3a86447f938bca64046809a12fda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21369 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 Ir+54R4?=^kaR2}S diff --git a/telldus-gui/TelldusGui/images/devices/17-356.png b/telldus-gui/TelldusGui/images/devices/17-356.png new file mode 100644 index 0000000000000000000000000000000000000000..5691035420aef60fbe0acc74e4ad71105deb31f9 GIT binary patch literal 11684 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

h{%8DmwJ%9e3%H=`yJ?1Yf@ZTvrT3m%wcJ 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 f(;+Uhq%LH@fxQT6`|D<`3x diff --git a/telldus-gui/TelldusGui/images/devices/51340.png b/telldus-gui/TelldusGui/images/devices/51340.png new file mode 100644 index 0000000000000000000000000000000000000000..fae3e22f9da1e6370fc7333c061e87ce4b743a74 GIT binary patch literal 8266 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 UK4^h3@IL?$TtipAM%6s@e^0IV$^ZZW literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/el2005.jpg b/telldus-gui/TelldusGui/images/devices/el2005.jpg deleted file mode 100644 index 69adb288945594b212fbcfe087dddf4f44f1df51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1570 zcmb7EYdF(=82!6Ikw^$7CKL)Kf!>Tki-E&pB{#!385tM{ z!?Fs>in4Nec^FnwRl=*N5Q#)tMUoncpr%Y95;j6Wu@xKwE?-8h!_c~R_C5J&!&x#0y7VjT}}=+N&i5Jt$T?hy?F zo5eB$hG4)HSWk(G!NgqoMRCZL^G%i6sbRK!+X;TF`&bAT{Nd<;TsF6XVGzC)(%+hD z+?d1RMfRxhOJ;B1(;9?ZgEJ$_vMRi~2uoD6a)+H&S@lXw_z-G<-|qBqTZU1c|9SoV z16!HmY&8Cxv?FsA}Gjrh5IQRXt#?E!bhhPESL~{7p=0&~2 z=v^VL48{F;%5@P?VwE3UTzCD^-b+6}{4LKkuk8HTzDEAK{}Y@ z{I^dNn(L{G#=~>v-rsB&c*%Oj(S#g$*@^kHdpR(@{>2f_y#Th}&7Q#1J63Z?7nEGj z{xL*wR4%8{Qx!9b0jY=jXfuOp)AQ`M81?Hc!{*Tm*8Kf@!R(6YW45$+vsZmtHv1}H zu2aMLi(eKP9-6oJ?m2$I>KYwg8RIezGXXz@&s>7C{*Wr~eG4`jKx zu*t~yF*=L4`e=>X=3s5MPn*%dTEU44G9z-Ll5vSaeBat9r~@(K^b;e0onub*2H)Lv;wFg!*vDV;Rdok|%G&W)%qEzPlGjHTaod%=yr-*IHd zFuVTsJHMOSelGLm88=E(U0hQ1{;E0q()T`vTWn};kl|O$`7cI-lC%fs?p^a`f`3Ya@FvUUFkSFwl>G)DU41!Pj0JVXbYQ zVJo-R{MfZsTBU8W4FB3c;Z4^S!nPiXPnz@^+JNU9sam`47CTPDW2w}%xUE1YaV^wuCG+K;NTE`cc-Tbq4-_I71c8YIJ(M9^L zg8Fhwk3m*$z7#i~qJmj)cpjPB^0BI*mr_*QOzIMHc@tkIs|_W16^@b4)`!$GE*m(< U{>*H8bt(@*+D0P%BAjU8U($Y@-2eap diff --git a/telldus-gui/TelldusGui/images/devices/el2005.png b/telldus-gui/TelldusGui/images/devices/el2005.png new file mode 100644 index 0000000000000000000000000000000000000000..f093ce3edc4fd4594fd754d7ee2b1e390aaee6f7 GIT binary patch literal 8147 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

Copyright © 2008 Telldus Technologies AB

" "

Telldus Center is a configuration utility for Telldus TellStick®

")); } + +void MainWindow::slotPagesClick() { + QAction *action = qobject_cast(sender()); + if (action) { + d->stackedLayout->setCurrentIndex(action->data().toInt()); + } +} diff --git a/telldus-gui/TelldusCenter/mainwindow.h b/telldus-gui/TelldusCenter/mainwindow.h index 87c78547..c1377f86 100644 --- a/telldus-gui/TelldusCenter/mainwindow.h +++ b/telldus-gui/TelldusCenter/mainwindow.h @@ -2,10 +2,13 @@ #define MAINWINDOW_H #include +#include class QToolBar; class Message; +class MainWindowPrivate; + class MainWindow : public QMainWindow { Q_OBJECT @@ -22,14 +25,14 @@ protected: private slots: void slotAboutApplication(); + void slotPagesClick(); private: void setupMenu(); void setupToolBar(); private: - QToolBar *m_pagesBar; - Message *p_message; + MainWindowPrivate *d; }; #endif // MAINWINDOW_H diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 95bfa872..dd0ffda8 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -1,7 +1,12 @@ #include "tellduscenterapplication.h" #include +#include +#include +#include + #include #include +#include "tellduscenterplugin.h" TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) :QApplication(argc, argv), @@ -15,12 +20,19 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) connect(this, SIGNAL(sigDeviceEvent(int, int, const QString &)), this, SLOT(deviceEvent(int, int, const QString &)), Qt::QueuedConnection); tdInit(); tdRegisterDeviceEvent( &TelldusCenterApplication::deviceEvent, 0 ); + + loadPlugins(); } TelldusCenterApplication::~TelldusCenterApplication() { + qDeleteAll(p_plugins); tdClose(); } +PluginList TelldusCenterApplication::plugins() const { + return p_plugins; +} + void TelldusCenterApplication::showMainWindow() { if (!isMainWindowShown()) { mainWindow = new MainWindow(); @@ -64,6 +76,38 @@ void TelldusCenterApplication::deviceEvent(int deviceId, int method, const char emit app->sigDeviceEvent(deviceId, method, data); } +void TelldusCenterApplication::loadPlugins() { + QDir pluginsDir = QDir(qApp->applicationDirPath()); + +#if defined(Q_OS_WIN) + if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release") + pluginsDir.cdUp(); +#elif defined(Q_OS_MAC) + if (pluginsDir.dirName() == "MacOS") { + pluginsDir.cdUp(); + pluginsDir.cdUp(); + pluginsDir.cdUp(); + } +#endif + pluginsDir.cd("plugins"); + + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (plugin) { //Load the plugin + loadPlugin(plugin); + } + } +} + +void TelldusCenterApplication::loadPlugin(QObject *plugin) { + TelldusCenterPlugin *iPlugin = qobject_cast(plugin); + if (!iPlugin) { + return; + } + p_plugins.append(iPlugin); +} + void TelldusCenterApplication::deviceEvent(int deviceId, int method, const QString &/*data*/) { char *name = tdGetName(deviceId); QString deviceName(name); diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index 2dd00328..b6ab94ef 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -3,10 +3,15 @@ #include #include +//#incldue #include "systrayicon.h" #include "mainwindow.h" +class TelldusCenterPlugin; + +typedef QList PluginList; + class TelldusCenterApplication : public QApplication { Q_OBJECT @@ -18,6 +23,7 @@ public: bool event(QEvent *event); #endif + PluginList plugins() const; void showMainWindow(); bool isMainWindowShown(); @@ -35,8 +41,11 @@ private slots: private: static void deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); + void loadPlugins(); + void loadPlugin(QObject *plugin); SystrayIcon systrayIcon; + PluginList p_plugins; QPointer mainWindow; }; diff --git a/telldus-gui/TelldusCenter/tellduscenterplugin.h b/telldus-gui/TelldusCenter/tellduscenterplugin.h new file mode 100644 index 00000000..58b86388 --- /dev/null +++ b/telldus-gui/TelldusCenter/tellduscenterplugin.h @@ -0,0 +1,17 @@ +#ifndef TELLDUSCENTERPLUGININTERFACE_H +#define TELLDUSCENTERPLUGININTERFACE_H + +class TelldusCenterPlugin +{ +public: + virtual ~TelldusCenterPlugin() {} + + virtual QIcon iconForPage( const QString &page ) const = 0; + virtual QString pluginName() const = 0; + virtual QWidget *widget( const QString &page, QWidget *parent ) const = 0; + virtual QStringList widgets() const = 0; +}; + +Q_DECLARE_INTERFACE(TelldusCenterPlugin, "com.telldus.TelldusCenter.Plugin/1.0") + +#endif // TELLDUSCENTERPLUGININTERFACE_H From f1539158aa3c15eb2f808f5e08c779ba43ec9c27 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 10 Mar 2009 16:39:03 +0000 Subject: [PATCH 0807/2215] Added the first plugin for TelldusCenter --- telldus-gui/Plugins/Plugins.pro | 3 +++ .../Plugins/TouchInterface/TouchInterface.pro | 12 ++++++++++ .../Plugins/TouchInterface/TouchInterface.qrc | 5 +++++ .../TouchInterface/images/touchinterface.png | Bin 0 -> 1787 bytes .../Plugins/TouchInterface/touchplugin.cpp | 21 ++++++++++++++++++ .../Plugins/TouchInterface/touchplugin.h | 21 ++++++++++++++++++ 6 files changed, 62 insertions(+) create mode 100644 telldus-gui/Plugins/Plugins.pro create mode 100644 telldus-gui/Plugins/TouchInterface/TouchInterface.pro create mode 100644 telldus-gui/Plugins/TouchInterface/TouchInterface.qrc create mode 100644 telldus-gui/Plugins/TouchInterface/images/touchinterface.png create mode 100644 telldus-gui/Plugins/TouchInterface/touchplugin.cpp create mode 100644 telldus-gui/Plugins/TouchInterface/touchplugin.h diff --git a/telldus-gui/Plugins/Plugins.pro b/telldus-gui/Plugins/Plugins.pro new file mode 100644 index 00000000..e7648c12 --- /dev/null +++ b/telldus-gui/Plugins/Plugins.pro @@ -0,0 +1,3 @@ +TEMPLATE=subdirs +SUBDIRS = TouchInterface + diff --git a/telldus-gui/Plugins/TouchInterface/TouchInterface.pro b/telldus-gui/Plugins/TouchInterface/TouchInterface.pro new file mode 100644 index 00000000..9678f9d6 --- /dev/null +++ b/telldus-gui/Plugins/TouchInterface/TouchInterface.pro @@ -0,0 +1,12 @@ +# ------------------------------------------------- +# Project created by QtCreator 2009-03-10T12:16:44 +# ------------------------------------------------- +QT += core \ + gui +TARGET = TouchInterface +TEMPLATE = lib +CONFIG += plugin +DESTDIR = ../../TelldusCenter/plugins +SOURCES += touchplugin.cpp +HEADERS += touchplugin.h +RESOURCES += TouchInterface.qrc diff --git a/telldus-gui/Plugins/TouchInterface/TouchInterface.qrc b/telldus-gui/Plugins/TouchInterface/TouchInterface.qrc new file mode 100644 index 00000000..7a847a13 --- /dev/null +++ b/telldus-gui/Plugins/TouchInterface/TouchInterface.qrc @@ -0,0 +1,5 @@ + + + images/touchinterface.png + + diff --git a/telldus-gui/Plugins/TouchInterface/images/touchinterface.png b/telldus-gui/Plugins/TouchInterface/images/touchinterface.png new file mode 100644 index 0000000000000000000000000000000000000000..45d81edefbea7cf1dc56685fd2db29eab0a59609 GIT binary patch literal 1787 zcmV2xI{}5lINK@%m#o&U(DNo}I6r?)U0(=-&0L zLy#a+xTK`gdo$|Suj*g*ud0U6<^L=S;M}=$FP=Vq`e(DVvo9#6KJnog^SGW&#qj#^2A+*YiA&pOvhvtioCO6Ukz(K(u4(klwYjn`q zR5LlZ593lm2w^)Zquzoaz*@t^WP>PzNI-%hK?pwJi$GBn6a&x3W}g@KM1J)07~`=^ ztCO+W>hkSVHD3AhE_SD$PA?;h5QE^oP)iMsMglS5y(h+4g?GpRV>DVRf)|31cppkF z0!0yMcL%h41AHDBty`wY60C-YYaL!Xknqhj)12BrO0PFS0(c(?l@k&oN3J;nfu`q> zhmP)LdiMzZZjR4A{ix`oSZQ|o>j#gqb<2sPlg#cN;Y%mRh{3b=sLk@dHQMcd)pa0B zBvifOV+d%a%low^tvig>bUGP#|Jmf->r13sXw)6;&5X&hgqiV#U8&~U8!NOQXB?iZ zbM)D9etm73rKNS&njMNfFx=pxM525G0?KHtwYbz$t2yfRgprXHg<|RUV^$w*@|73& zp%8-iBt{6iroD@JU7F$vm@MJZt=%IeaQGkgCD%|McVzqA8tJ2%|GAcqlaA@jao@PUDDWB zMnrj13ANVPVR)2QB&kJoS@T_Du&y* zV+Y3g)}bkWe!a;%w_4m@?m`S`V`(%@SwmE106=OnRud!;q^d8l69G^-XNks=Rv~c7 zRwy*0H1&p~)`06bH)(ZqHv7W#bOY}N?-ljBrYNcySEPy&oU<6MOBRHPG3w)$Fh;>z zL$symHnH0VIH${eFdAbtA8zE_ZD!P*rB*jp)eGC6M?hkAS%_F$&K2dX5QwotV5b2k z6SURnEhC)8RsDYp39S`1tpG)gWl|X%Foi)Gk5ZZ#6)`F#f(RIAQN~nVHeie`lh9gg z073{H*f+t&@1F#v(MF*)+Y^vh3Z=`0Qc#xXSfVCU(n~^VjEHP^L0_%ez;k4_LAT!| zNW_-ySlLdev$18sXg%Q@XOit%Ac!C$C3Peq)o%&%WM65JP>yFJr7;q>&q@?xj12O} zw6g-G%F(Xd?e_J>ix*#OHk%|#g0YrDG=&(7Xz-N|?|n3Qc4`rI`J8BS(d0ps2Spwf zgP<6AMOJ_pMUo`U&CRj6xY)dP>(*NeaA(h+{mH_@!uR&?-#=M-6w925+cW*vepsLW z|397CqFD$*78e)qUAS=J)%ErDUu<#E053V`<|~5!+b@velKMZ23L!{Q6idKcK>lf8 d__=&)`4`=`$CQJ;Ap`&b002ovPDHLkV1k_NS+f8D literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/TouchInterface/touchplugin.cpp b/telldus-gui/Plugins/TouchInterface/touchplugin.cpp new file mode 100644 index 00000000..93da18d2 --- /dev/null +++ b/telldus-gui/Plugins/TouchInterface/touchplugin.cpp @@ -0,0 +1,21 @@ +#include +#include +#include "touchplugin.h" + +QIcon TouchPlugin::iconForPage( const QString &page ) const { + return QIcon(":/images/touchinterface.png"); +} + +QString TouchPlugin::pluginName() const { + return "TouchInterface"; +} + +QWidget *TouchPlugin::widget( const QString &page, QWidget *parent ) const { + return new QLabel("Hello world", parent); +} + +QStringList TouchPlugin::widgets() const { + return QStringList() << "touch.default"; +} + +Q_EXPORT_PLUGIN2(TouchInterface, TouchPlugin) diff --git a/telldus-gui/Plugins/TouchInterface/touchplugin.h b/telldus-gui/Plugins/TouchInterface/touchplugin.h new file mode 100644 index 00000000..5c737add --- /dev/null +++ b/telldus-gui/Plugins/TouchInterface/touchplugin.h @@ -0,0 +1,21 @@ +#ifndef TOUCHPLUGIN_H +#define TOUCHPLUGIN_H + +#include +#include +#include "../../TelldusCenter/tellduscenterplugin.h" + +class TouchPlugin : public QObject, public TelldusCenterPlugin +{ + Q_OBJECT + Q_INTERFACES(TelldusCenterPlugin) +public: + virtual QIcon iconForPage( const QString &page ) const; + virtual QString pluginName() const; + + virtual QWidget *widget( const QString &page, QWidget *parent ) const; + virtual QStringList widgets() const; + +}; + +#endif // TOUCHPLUGIN_H From b0d8dd685f1dc46dac532c0402cd4c5a9bac475a Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Tue, 10 Mar 2009 20:12:54 +0000 Subject: [PATCH 0808/2215] Added Rising Sun image --- .../TelldusGui/images/devices/RSL366R.png | Bin 0 -> 7523 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/RSL366R.png diff --git a/telldus-gui/TelldusGui/images/devices/RSL366R.png b/telldus-gui/TelldusGui/images/devices/RSL366R.png new file mode 100644 index 0000000000000000000000000000000000000000..508769a8f76170e7529a8bd6f8073331903ab1eb GIT binary patch literal 7523 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 f@Y9k&ucOdRT)r|RHphm?CTSAHMt_IwY%U literal 0 HcmV?d00001 From ffcc4dde525d6fc8af4b5afa1ff579ca94469c0f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 11 Mar 2009 09:41:55 +0000 Subject: [PATCH 0809/2215] Started a QT backend for settings --- .../driver/libtelldus-core/CMakeLists.txt | 3 +- .../driver/libtelldus-core/SettingsQt.cpp | 100 ++++++++++++++++++ 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 telldus-core/driver/libtelldus-core/SettingsQt.cpp diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 71c70501..52b475c8 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -31,7 +31,8 @@ IF (APPLE) SET( telldus-core_SRCS ${telldus-core_SRCS} win/Device.cpp - SettingsCoreFoundationPreferences.cpp +# SettingsCoreFoundationPreferences.cpp + SettingsQt.cpp ) ADD_DEFINITIONS( -D_MACOSX diff --git a/telldus-core/driver/libtelldus-core/SettingsQt.cpp b/telldus-core/driver/libtelldus-core/SettingsQt.cpp new file mode 100644 index 00000000..593b2dac --- /dev/null +++ b/telldus-core/driver/libtelldus-core/SettingsQt.cpp @@ -0,0 +1,100 @@ +// +// C++ Implementation: telldussettingsconfuse +// +// Description: +// +// +// Author: Micke Prag , (C) 2008 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "Settings.h" +#include +#include +#include + +using namespace std; + +class privateVars { +public: + QSettings *settings; +}; + + +/* +* Constructor +*/ +Settings::Settings(void) +{ + d = new privateVars(); + d->settings = new QSettings("Telldus", "Core"); +} + +/* +* Destructor +*/ +Settings::~Settings(void) +{ + delete d->settings; + delete d; +} + +/* +* Return a setting +*/ +std::string Settings::getSetting(const std::string &strName) const { + return ""; +} + +/* +* Return the number of stored devices +*/ +int Settings::getNumberOfDevices(void) const { + int devices = 1; + return devices; +} + +int Settings::getDeviceId(int intDeviceIndex) const { + int id = 1; + return id; +} + +/* +* Add a new device +*/ +int Settings::addDevice() { + return -1; +} + +/* +* Get next available device id +*/ +int Settings::getNextDeviceId() const { + int id = 0, max = 0; + return max; +} + +/* +* Remove a device +*/ +bool Settings::removeDevice(int intDeviceId) { + return false; +} + +std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { + return "hej"; +} + +bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { + return true; +} + +int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { + int retval = 0; + return retval; +} + +bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { + return true; +} From 8f13ff385d716a9db453f1f3b66b7460e855560c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 11 Mar 2009 11:25:40 +0000 Subject: [PATCH 0810/2215] Moved the devices to a own plugin --- telldus-gui/Plugins/Devices/Devices.pro | 12 +++++++++ telldus-gui/Plugins/Devices/devicesplugin.cpp | 27 +++++++++++++++++++ telldus-gui/Plugins/Devices/devicesplugin.h | 21 +++++++++++++++ telldus-gui/TelldusCenter/mainwindow.cpp | 16 +---------- telldus-gui/telldus-gui.pro | 3 ++- 5 files changed, 63 insertions(+), 16 deletions(-) create mode 100644 telldus-gui/Plugins/Devices/Devices.pro create mode 100644 telldus-gui/Plugins/Devices/devicesplugin.cpp create mode 100644 telldus-gui/Plugins/Devices/devicesplugin.h diff --git a/telldus-gui/Plugins/Devices/Devices.pro b/telldus-gui/Plugins/Devices/Devices.pro new file mode 100644 index 00000000..475d6741 --- /dev/null +++ b/telldus-gui/Plugins/Devices/Devices.pro @@ -0,0 +1,12 @@ +# ------------------------------------------------- +# Project created by QtCreator 2009-03-10T12:16:44 +# ------------------------------------------------- +QT += core \ + gui +TARGET = Devices +TEMPLATE = lib +CONFIG += plugin +DESTDIR = ../../TelldusCenter/plugins +SOURCES += devicesplugin.cpp +HEADERS += devicesplugin.h +#RESOURCES += Devices.qrc diff --git a/telldus-gui/Plugins/Devices/devicesplugin.cpp b/telldus-gui/Plugins/Devices/devicesplugin.cpp new file mode 100644 index 00000000..f4838ab2 --- /dev/null +++ b/telldus-gui/Plugins/Devices/devicesplugin.cpp @@ -0,0 +1,27 @@ +#include +#include +#include +#include "devicesplugin.h" + +#include "../../TelldusGui/telldusgui.h" + +QIcon DevicesPlugin::iconForPage( const QString &page ) const { + return QIcon(":/images/devices.png"); +} + +QString DevicesPlugin::pluginName() const { + return "Devices"; +} + +QWidget *DevicesPlugin::widget( const QString &page, QWidget *parent ) const { + QWidget *deviceWidget = tdDeviceWidget(parent); + connect(deviceWidget, SIGNAL(showMessage(const QString &, const QString &, const QString &)), qApp, SLOT(showMessage(const QString &, const QString &, const QString &))); + connect(deviceWidget, SIGNAL(eventTriggered(const QString &, const QString &)), qApp, SLOT(eventTriggered(const QString &, const QString &))); + return deviceWidget; +} + +QStringList DevicesPlugin::widgets() const { + return QStringList() << "devicest.default"; +} + +Q_EXPORT_PLUGIN2(DevicesInterface, DevicesPlugin) diff --git a/telldus-gui/Plugins/Devices/devicesplugin.h b/telldus-gui/Plugins/Devices/devicesplugin.h new file mode 100644 index 00000000..bca029de --- /dev/null +++ b/telldus-gui/Plugins/Devices/devicesplugin.h @@ -0,0 +1,21 @@ +#ifndef DEVICESPLUGIN_H +#define DEVICESPLUGIN_H + +#include +#include +#include "../../TelldusCenter/tellduscenterplugin.h" + +class DevicesPlugin : public QObject, public TelldusCenterPlugin +{ + Q_OBJECT + Q_INTERFACES(TelldusCenterPlugin) +public: + virtual QIcon iconForPage( const QString &page ) const; + virtual QString pluginName() const; + + virtual QWidget *widget( const QString &page, QWidget *parent ) const; + virtual QStringList widgets() const; + +}; + +#endif // DEVICESPLUGIN_H diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 97e0c41b..ceee21d4 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -14,7 +14,6 @@ #include "tellduscenterapplication.h" #include "tellduscenterplugin.h" #include "message.h" -#include "../TelldusGui/telldusgui.h" class MainWindowPrivate { public: @@ -48,12 +47,6 @@ MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) d->stackedLayout = new QStackedLayout; layout->addLayout(d->stackedLayout); - TelldusCenterApplication *app = TelldusCenterApplication::instance(); - QWidget *deviceWidget = tdDeviceWidget(this); - connect(deviceWidget, SIGNAL(showMessage(const QString &, const QString &, const QString &)), app, SLOT(showMessage(const QString &, const QString &, const QString &))); - connect(deviceWidget, SIGNAL(eventTriggered(const QString &, const QString &)), app, SLOT(eventTriggered(const QString &, const QString &))); - d->stackedLayout->addWidget(deviceWidget); - setCentralWidget(centralWidget); setupToolBar(); @@ -99,14 +92,6 @@ void MainWindow::setupToolBar() QActionGroup *ag = new QActionGroup(this); QSet toolbarIcons; - QAction *actionDevices = new QAction( QIcon(":/images/devices.png"), tr("Devices"), this ); - actionDevices->setCheckable( true ); - actionDevices->setChecked( true ); - actionDevices->setData(0); - connect(actionDevices, SIGNAL(triggered()), this, SLOT(slotPagesClick())); - ag->addAction(actionDevices); - toolbarIcons.insert("devices"); - TelldusCenterApplication *app = TelldusCenterApplication::instance(); PluginList plugins = app->plugins(); foreach( TelldusCenterPlugin *plugin, plugins ) { @@ -133,6 +118,7 @@ void MainWindow::setupToolBar() } } + ag->actions().first()->setChecked( true ); d->pagesBar->addActions( ag->actions() ); } diff --git a/telldus-gui/telldus-gui.pro b/telldus-gui/telldus-gui.pro index 4e6a9f6e..4a0691f6 100644 --- a/telldus-gui/telldus-gui.pro +++ b/telldus-gui/telldus-gui.pro @@ -1,3 +1,4 @@ TEMPLATE=subdirs SUBDIRS = TelldusGui \ - TelldusCenter + TelldusCenter \ + Plugins From c2a866052356e6e16ee46ae0f3f99cefe793f5db Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 11 Mar 2009 11:26:48 +0000 Subject: [PATCH 0811/2215] Added plugin Devices to makefile --- telldus-gui/Plugins/Plugins.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Plugins.pro b/telldus-gui/Plugins/Plugins.pro index e7648c12..14bc3e92 100644 --- a/telldus-gui/Plugins/Plugins.pro +++ b/telldus-gui/Plugins/Plugins.pro @@ -1,3 +1,4 @@ TEMPLATE=subdirs -SUBDIRS = TouchInterface +SUBDIRS = Devices \ + TouchInterface From 755f212e1f6c1300bbda40746a5c8312a9fa14eb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 11 Mar 2009 12:35:25 +0000 Subject: [PATCH 0812/2215] Switched to pimpl idiom for class TelldusCenterApplication --- .../tellduscenterapplication.cpp | 43 ++++++++++++++----- .../TelldusCenter/tellduscenterapplication.h | 5 +-- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index dd0ffda8..da13b2b3 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -8,11 +8,25 @@ #include #include "tellduscenterplugin.h" +class TelldusCenterPlugin; + +typedef QList PluginList; + + +class TelldusCenterApplicationPrivate { +public: + SystrayIcon *systrayIcon; + PluginList plugins; + QPointer mainWindow; +}; + TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) - :QApplication(argc, argv), - systrayIcon(this) + :QApplication(argc, argv) { - connect(&systrayIcon, SIGNAL(showEventMessage(const QString &, const QString &, const QString &)), this, SLOT(showMessage(QString,QString,QString))); + d = new TelldusCenterApplicationPrivate; + d->systrayIcon = new SystrayIcon( this ); + + connect(d->systrayIcon, SIGNAL(showEventMessage(const QString &, const QString &, const QString &)), this, SLOT(showMessage(QString,QString,QString))); setQuitOnLastWindowClosed( false ); @@ -25,23 +39,24 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) } TelldusCenterApplication::~TelldusCenterApplication() { - qDeleteAll(p_plugins); + qDeleteAll(d->plugins); + delete d; tdClose(); } PluginList TelldusCenterApplication::plugins() const { - return p_plugins; + return d->plugins; } void TelldusCenterApplication::showMainWindow() { if (!isMainWindowShown()) { - mainWindow = new MainWindow(); + d->mainWindow = new MainWindow(); } - mainWindow->show(); + d->mainWindow->show(); } bool TelldusCenterApplication::isMainWindowShown() { - return !mainWindow.isNull(); + return !d->mainWindow.isNull(); } #if defined(Q_WS_MAC) @@ -65,9 +80,9 @@ void TelldusCenterApplication::eventTriggered( const QString &name, const QStrin void TelldusCenterApplication::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { if (isMainWindowShown()) { - mainWindow->showMessage(title, message, detailedMessage); + d->mainWindow->showMessage(title, message, detailedMessage); } else { - systrayIcon.showMessage((title != "" ? title : "Telldus Center"), message, QSystemTrayIcon::Warning); + d->systrayIcon->showMessage((title != "" ? title : "Telldus Center"), message, QSystemTrayIcon::Warning); } } @@ -105,7 +120,13 @@ void TelldusCenterApplication::loadPlugin(QObject *plugin) { if (!iPlugin) { return; } - p_plugins.append(iPlugin); + QObject *qObjectPlugin = qobject_cast(plugin); + if (qObjectPlugin) { + if (qObjectPlugin->metaObject()->indexOfSignal( QMetaObject::normalizedSignature("hej()") ) >= 0) { + connect(qObjectPlugin, SIGNAL(hej()), this, SLOT(aboutQt())); + } + } + d->plugins.append(iPlugin); } void TelldusCenterApplication::deviceEvent(int deviceId, int method, const QString &/*data*/) { diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index b6ab94ef..b0a0cfab 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -9,6 +9,7 @@ #include "mainwindow.h" class TelldusCenterPlugin; +class TelldusCenterApplicationPrivate; typedef QList PluginList; @@ -44,9 +45,7 @@ private: void loadPlugins(); void loadPlugin(QObject *plugin); - SystrayIcon systrayIcon; - PluginList p_plugins; - QPointer mainWindow; + TelldusCenterApplicationPrivate *d; }; #endif // TELLDUSCENTERAPPLICATION_H From bc623ef5291eada460454b7dda8908d2fb20ea4d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 11 Mar 2009 14:13:41 +0000 Subject: [PATCH 0813/2215] Added QScript to TelldusCenter --- telldus-gui/TelldusCenter/TelldusCenter.pro | 2 +- .../TelldusCenter/tellduscenterapplication.cpp | 18 +++++++++++++++++- .../TelldusCenter/tellduscenterapplication.h | 1 + 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index b60f4971..a6b7460d 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -2,7 +2,7 @@ # Project created by QtCreator 2008-12-11T11:01:36 # ------------------------------------------------- TEMPLATE = app - +QT += script SOURCES += main.cpp \ mainwindow.cpp \ tellduscenterapplication.cpp \ diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index da13b2b3..0364a85c 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -18,6 +19,7 @@ public: SystrayIcon *systrayIcon; PluginList plugins; QPointer mainWindow; + QScriptEngine scriptEngine; }; TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) @@ -36,6 +38,7 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) tdRegisterDeviceEvent( &TelldusCenterApplication::deviceEvent, 0 ); loadPlugins(); + loadScripts(); } TelldusCenterApplication::~TelldusCenterApplication() { @@ -104,7 +107,10 @@ void TelldusCenterApplication::loadPlugins() { pluginsDir.cdUp(); } #endif - pluginsDir.cd("plugins"); + if (!pluginsDir.cd("plugins")) { + return; + } + this->addLibraryPath( pluginsDir.absolutePath() ); foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); @@ -129,6 +135,16 @@ void TelldusCenterApplication::loadPlugin(QObject *plugin) { d->plugins.append(iPlugin); } +void TelldusCenterApplication::loadScripts() { + foreach (QString extension, d->scriptEngine.availableExtensions()) { + d->scriptEngine.importExtension( extension ); + if (d->scriptEngine.hasUncaughtException()) { + qDebug() << QString("Error in %1:%2:").arg(extension).arg(d->scriptEngine.uncaughtExceptionLineNumber()) + << d->scriptEngine.uncaughtException().toString(); + } + } +} + void TelldusCenterApplication::deviceEvent(int deviceId, int method, const QString &/*data*/) { char *name = tdGetName(deviceId); QString deviceName(name); diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index b0a0cfab..d9e7d7f7 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -44,6 +44,7 @@ private: static void deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); void loadPlugins(); void loadPlugin(QObject *plugin); + void loadScripts(); TelldusCenterApplicationPrivate *d; }; From 11e57c3bdc981176be245b8c4ac1cdb9f468e96c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 11 Mar 2009 18:27:22 +0000 Subject: [PATCH 0814/2215] Started with some initial animation on the Touchscreen-interface --- .../Plugins/TouchInterface/TouchInterface.pro | 9 +- telldus-gui/Plugins/TouchInterface/button.cpp | 23 +++++ telldus-gui/Plugins/TouchInterface/button.h | 20 ++++ telldus-gui/Plugins/TouchInterface/panel.cpp | 98 +++++++++++++++++++ telldus-gui/Plugins/TouchInterface/panel.h | 28 ++++++ .../Plugins/TouchInterface/touchplugin.cpp | 8 +- .../Plugins/TouchInterface/touchplugin.h | 4 + 7 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 telldus-gui/Plugins/TouchInterface/button.cpp create mode 100644 telldus-gui/Plugins/TouchInterface/button.h create mode 100644 telldus-gui/Plugins/TouchInterface/panel.cpp create mode 100644 telldus-gui/Plugins/TouchInterface/panel.h diff --git a/telldus-gui/Plugins/TouchInterface/TouchInterface.pro b/telldus-gui/Plugins/TouchInterface/TouchInterface.pro index 9678f9d6..0d436948 100644 --- a/telldus-gui/Plugins/TouchInterface/TouchInterface.pro +++ b/telldus-gui/Plugins/TouchInterface/TouchInterface.pro @@ -7,6 +7,11 @@ TARGET = TouchInterface TEMPLATE = lib CONFIG += plugin DESTDIR = ../../TelldusCenter/plugins -SOURCES += touchplugin.cpp -HEADERS += touchplugin.h +SOURCES += touchplugin.cpp \ + panel.cpp \ + button.cpp +HEADERS += touchplugin.h \ + panel.h \ + button.h RESOURCES += TouchInterface.qrc +contains(QT_CONFIG, opengl):QT += opengl diff --git a/telldus-gui/Plugins/TouchInterface/button.cpp b/telldus-gui/Plugins/TouchInterface/button.cpp new file mode 100644 index 00000000..eeadebea --- /dev/null +++ b/telldus-gui/Plugins/TouchInterface/button.cpp @@ -0,0 +1,23 @@ +#include "button.h" +#include +#include + +Button::Button(const QRectF &rect, const QBrush &brush, QObject *parent) + : QObject(parent), + QGraphicsRectItem(rect) +{ +} + +void Button::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(0, 0, 0, 64)); + painter->drawRoundRect(rect().translated(2, 2)); + + painter->setBrush(Qt::black); + painter->setPen(Qt::black); + painter->drawText( rect().adjusted( 10, 10, -10, -10 ), "Hej"); +} + +void Button::mousePressEvent(QGraphicsSceneMouseEvent * ) { + emit clicked(); +} diff --git a/telldus-gui/Plugins/TouchInterface/button.h b/telldus-gui/Plugins/TouchInterface/button.h new file mode 100644 index 00000000..91074c43 --- /dev/null +++ b/telldus-gui/Plugins/TouchInterface/button.h @@ -0,0 +1,20 @@ +#ifndef BUTTON_H +#define BUTTON_H + +#include + +class Button : public QObject, public QGraphicsRectItem +{ + Q_OBJECT +public: + Button(const QRectF &rect, const QBrush &brush, QObject *parent = 0); + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *); + + virtual void mousePressEvent(QGraphicsSceneMouseEvent * ); + +signals: + void clicked(); +}; + +#endif // BUTTON_H diff --git a/telldus-gui/Plugins/TouchInterface/panel.cpp b/telldus-gui/Plugins/TouchInterface/panel.cpp new file mode 100644 index 00000000..796353ab --- /dev/null +++ b/telldus-gui/Plugins/TouchInterface/panel.cpp @@ -0,0 +1,98 @@ +#include "panel.h" +#include "button.h" + +#ifndef QT_NO_OPENGL +#include +#endif +#include +#include +#include + +class PanelPrivate { +public: + QVector buttons; + Button *animatedButton; + QRectF from, to; + QTimeLine *timer; +}; + +Panel::Panel(QWidget *parent) + :QGraphicsView(parent), + d( new PanelPrivate ) +{ + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setFrameStyle(0); + setBackgroundBrush( Qt::blue ); + +#ifndef QT_NO_OPENGL + setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); +#endif + + QRectF bounds(0, 0, 200, 200); + + setScene(new QGraphicsScene(bounds, this)); + + Button *button = new Button(QRectF(-25, -25, 50, 50), Qt::red); + button->setPos(50, 150); + scene()->addItem(button); + connect(button, SIGNAL(clicked()), this, SLOT(click())); + d->buttons.append(button); + + button = new Button(QRectF(-25, -25, 50, 50), Qt::red); + button->setPos(125, 150); + scene()->addItem(button); + connect(button, SIGNAL(clicked()), this, SLOT(click())); + d->buttons.append(button); + + d->timer = new QTimeLine(400, this); + d->timer->setFrameRange(0, 100); + connect(d->timer, SIGNAL(frameChanged(int)), this, SLOT(tick(int))); + +} + +Panel::~Panel() { + delete d; +} + +void Panel::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { + painter->setPen(Qt::NoPen); + painter->setBrush(QColor(0, 0, 0, 64)); + painter->drawRoundRect(rect().translated(2, 2)); +} + +void Panel::resizeEvent(QResizeEvent *event) +{ + QGraphicsView::resizeEvent(event); + fitInView(scene()->sceneRect(), Qt::KeepAspectRatio); +} + +void Panel::tick( int frame) { + if (!d->animatedButton) { + d->timer->stop(); + return; + } + + float percent = (frame/100.0); + QPointF from = d->from.topLeft(), to = d->to.topLeft(); + QPointF rect = from - percent * (from - to); + d->animatedButton->setPos( rect ); + + QTransform trans; + trans = trans.rotate(180 * percent, Qt::YAxis); + + trans = trans.scale(percent * d->to.width() / d->animatedButton->rect().width() + 1, percent * d->to.height() / d->animatedButton->rect().height() + 1); + + d->animatedButton->setTransform( trans ); +} + +void Panel::click() { + d->animatedButton = qobject_cast

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 diff --git a/telldus-gui/TelldusGui/images/devices/el2019.png b/telldus-gui/TelldusGui/images/devices/el2019.png new file mode 100644 index 0000000000000000000000000000000000000000..d1f2b15ae949099292049e2a108a2c9712b5277e GIT binary patch literal 8998 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 VMzXrVe_22vRYffYG~6=c{{R3JA!Yyo literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/hdr.jpg b/telldus-gui/TelldusGui/images/devices/hdr.jpg deleted file mode 100644 index 372fa17978b5e2b238fb8886cc5d34c10a6571c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15414 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 h<9FU%Y~rvsxY5baQwUf3h>NpDs diff --git a/telldus-gui/TelldusGui/images/devices/hdr.png b/telldus-gui/TelldusGui/images/devices/hdr.png new file mode 100644 index 0000000000000000000000000000000000000000..c25efe5d13b7254bd6448e738fe6720cecf40bf1 GIT binary patch literal 8238 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/devices/koppla.jpg b/telldus-gui/TelldusGui/images/devices/koppla.jpg deleted file mode 100644 index 20e921d22c6c65ad650bbbc58abc1836319e170b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2060 zcmb7FdpOhkAOCJMbD7I`<{Dd#h0~#2!zRWtyW~2pusW$xWNMMzszVpKq**Q{A(l-p z1*7V4MtTLyk)2(s7dVTfd&)^ZWh#dwrhI>-{|M*Zci`-p~8}d7jVO^R<_N zHjPXr0}u!VpePQoCIj@m5+Wl2z{dyp0RR9M#Z_Q!6z~M#FeN1=7+gVcI9wTlR6!`9 zrLL}u1hr5oPzwZg^o;d&&_=o-Xt2S+$ixJT#p>we%y1YpV+$M~e`Bp309Am!z+M;x2S7mx41}yb0@eWl6bgfUZ}vMQlvSWGCAdO#&;}qd7*q*{ zfGWfOEkYCu00)&(IvZ?Ah=A*8To^Ys_rbn;T|HCVzp}uTYkK^0~fnySy;zAw$x`?Im)Xpl>q z9nU*I33>PTZnbcU)1`59TvcPvc>JCFld~MZ=EnS1Sv$pypICfq+%|Bf_`8Nv4>K zb61SCQkHIx+-&3&zafl9#ZwqML!9KoMpl=p_6WA@q+~MQrnMYnonxJyq#EoI;c|{inh_K75IyGDkiw!} z2^SK!XPwUdIb>ayM&GgECp%J$XC{l81#%O-prgT3RA1OZQ}g85>p3rc9qjou91_eS zrSV2L+_--?_W{Ej#(PTLR$N_Q8ga!0FQoA*zM3L>5_9CutPsI#CHs*voio|Too~ht zmU=e@?2jBeYRzvG`aNb+e;jjQ*4`b*36vwK!J9XK_SkAtmblPK`%Ql}G>%m{@N1gH zV?eQ6MgutCeM95^rT|%`oyK*I8-&1XE!fYDqI-|R@4z#quMJ!7IS*N|Ypt{=%FKta zzA#a7Id)6N#fcn0r-q7A$1$u$`ak{=_e8t~`?P_e;@XT%U!9fQK@l-MBy5)aC~L*0 z*J}E}?4TsG=AWpPM&PW@AIPDgjM&nRbE)xSYGmiL!0U}aDV)fnhC*|gj%VhNmJ#DxpX>8B_-J>SAy_p?yZ6!?A+o_ zoS9}CZFv;m$w$ml+%)F4UmzE1mc(nbEq%6y!v&>QcUn-+%UGjRg0S_8Y7>Lz(Ri10 zrcMjbw54kK3owV^yUc6rTMSDQ`7 z`!7D|4Le4U|Ev$M=vo-_``PXBfwH&9vnu-OdY>XQKaH`g$_pOa^`u=tz0_-nw@LA8 zwS3$N7uy*|r?dRR*;5Cmvn86k@*!M6=3x7+%fKc>*Y-ZQI zNtac7MP2%%o;on=bA{D_wJ>H0*Xl?Y4wAR8o@Ki`~}oe}CNn zqVGmsU;ddRGGgr`HgbLO!N4I4f+b?k!|5&%}t{I z5#Qm_XgsV-&F5pucx$4oIe{2I@@1|cUm&>MgymS<*EdrAyKohQ_B*b;Oo03)T-t2< zwq|9YpdrBNOh|(|c$kuJ^(unwj<>QZP9D#AMS8q_;)Ut0Gdv;Gw>`P|Xl)*tn`x(# z)d9X^&c=7srrrfsjQ?QrrgLB=PI}ISZ^m&ORQ26LU@yBx9i{)#l+PE{xf+zTzw^80 z7BW9|Ff!Z4IDEL2;=D}txHu@RWz|3Xurl3>L6Xbt&o+NLnAadx%PZsAx?^qjh|d|t z$fD9$JtjAXqRiegc(j2~GFNPBI0n2;mQ?nu+Uz&0GDvhkY&Nx8-C8-$nmqqLL-WW| z%HT}B+p)^L-1NJazsZTtmzD-5AB6ci?e@sjkqC^xBnP&DY;xSzjf9$NS7Q?OV{OK? zlp%Z=I2w9h)mp$_Ns?clSH?BCxqqqJyN_D9Hz>iUSuA-&bNBWSyj^zkYOK#j5}iVQ yje;M>bLaBW0shzj`|;>zo%hU;Hk{SM*#!rXsuVk6zPiFe^jboj`n?cqBmV+fv2d~g diff --git a/telldus-gui/TelldusGui/images/devices/koppla.png b/telldus-gui/TelldusGui/images/devices/koppla.png new file mode 100644 index 0000000000000000000000000000000000000000..20d56cc1d2a2063e5edfd2c224066c38b33b5044 GIT binary patch literal 9440 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 Ofwa~2)#^~T*#85 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 XL5^VhQIoM800000NkvXXu0mjf{IrX? literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index 2a2f4ccc..b919045f 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -2,20 +2,20 @@ data/devices.xml images/bell.png - images/devices/143011.jpg - images/devices/14323.jpg - images/devices/14327.jpg - images/devices/145041.jpg - images/devices/145071.jpg - images/devices/145091.jpg - images/devices/17-356.jpg - images/devices/51340.jpg - images/devices/el2005.jpg - images/devices/el2019.jpg - images/devices/hdr.jpg - images/devices/koppla.jpg - images/devices/ml.jpg - images/devices/sycr.jpg + images/devices/143011.png + images/devices/14323.png + images/devices/14327.png + images/devices/145041.png + images/devices/145071.png + images/devices/145091.png + images/devices/17-356.png + images/devices/51340.png + images/devices/el2005.png + images/devices/el2019.png + images/devices/hdr.png + images/devices/koppla.png + images/devices/ml.png + images/devices/sycr.png images/list-add.png images/list-edit.png images/list-remove.png diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index 332ea330..e7b0f0a8 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -56,7 +56,7 @@ QPixmap VendorDeviceTreeItem::image() const { if (deviceId == 0) { filename = ":/images/vendors/" + img.toLower() + ".jpg"; } else { - filename = ":/images/devices/" + img + ".jpg"; + filename = ":/images/devices/" + img + ".png"; } QPixmap image = QPixmap(filename); if (image.isNull()) { From e93972fc460d3cc5bc05873a04571dee3cca3440 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 15 Jan 2009 17:30:53 +0000 Subject: [PATCH 0754/2215] Typo in signal name --- telldus-gui/TelldusGui/devicemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index 4868fef5..b5f5d766 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -110,7 +110,7 @@ Device *DeviceModel::device( const QModelIndex &index ) const { Device *DeviceModel::newDevice() const { Device *device = Device::newDevice(); connect(device, SIGNAL(deviceAdded(int)), this, SLOT(deviceAdded(int))); - connect(device, SIGNAL(shfowMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showsMessage(const QString &, const QString &, const QString &))); + connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showsMessage(const QString &, const QString &, const QString &))); connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); return device; } From d7dc523b142a9fb6f5dc147901dd531b8ff08a9a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 15 Jan 2009 17:32:28 +0000 Subject: [PATCH 0755/2215] Added the device-icon as the decoration-role to the devices in VendorDeviceModel --- telldus-gui/TelldusGui/vendordevicemodel.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/telldus-gui/TelldusGui/vendordevicemodel.cpp b/telldus-gui/TelldusGui/vendordevicemodel.cpp index fa2d980f..68d4b29c 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.cpp +++ b/telldus-gui/TelldusGui/vendordevicemodel.cpp @@ -1,6 +1,7 @@ #include "vendordevicemodel.h" #include "vendordevicetreeitem.h" #include "device.h" +#include VendorDeviceModel::VendorDeviceModel(QObject *parent) :QAbstractItemModel(parent), @@ -25,13 +26,15 @@ QVariant VendorDeviceModel::data(const QModelIndex &index, int role) const { return QVariant(); } - if (role != Qt::DisplayRole) { - return QVariant(); + if (role == Qt::DisplayRole) { + VendorDeviceTreeItem *item = static_cast(index.internalPointer()); + return item->data(index.column()); + } else if (role == Qt::DecorationRole) { + VendorDeviceTreeItem *item = static_cast(index.internalPointer()); + QPixmap pixmap = item->image(); + return pixmap.scaled(22, 22, Qt::KeepAspectRatio); } - - VendorDeviceTreeItem *item = static_cast(index.internalPointer()); - - return item->data(index.column()); + return QVariant(); } Qt::ItemFlags VendorDeviceModel::flags(const QModelIndex &index) const { From 1e5051704744a4abebf4f64e8bbd1095e30afc9c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 16 Jan 2009 09:32:35 +0000 Subject: [PATCH 0756/2215] Typo in signalname in DeviceModel --- telldus-gui/TelldusGui/devicemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index b5f5d766..b1117cac 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -110,7 +110,7 @@ Device *DeviceModel::device( const QModelIndex &index ) const { Device *DeviceModel::newDevice() const { Device *device = Device::newDevice(); connect(device, SIGNAL(deviceAdded(int)), this, SLOT(deviceAdded(int))); - connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showsMessage(const QString &, const QString &, const QString &))); + connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); return device; } From 3a6014103a1132aae06b1d2cb963d44f14d4172a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 16 Jan 2009 13:13:31 +0000 Subject: [PATCH 0757/2215] Added EditGroupDialog --- telldus-gui/TelldusGui/TelldusGui.pro | 2 + telldus-gui/TelldusGui/devicewidget.cpp | 25 +++++++- telldus-gui/TelldusGui/devicewidget.h | 1 + telldus-gui/TelldusGui/editgroupdialog.cpp | 70 ++++++++++++++++++++++ telldus-gui/TelldusGui/editgroupdialog.h | 24 ++++++++ telldus-gui/TelldusGui/methodwidget.cpp | 4 +- 6 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 telldus-gui/TelldusGui/editgroupdialog.cpp create mode 100644 telldus-gui/TelldusGui/editgroupdialog.h diff --git a/telldus-gui/TelldusGui/TelldusGui.pro b/telldus-gui/TelldusGui/TelldusGui.pro index 987a5539..ef8b8093 100644 --- a/telldus-gui/TelldusGui/TelldusGui.pro +++ b/telldus-gui/TelldusGui/TelldusGui.pro @@ -8,6 +8,7 @@ SOURCES += telldusgui.cpp \ devicemodel.cpp \ device.cpp \ editdevicedialog.cpp \ + editgroupdialog.cpp \ vendordevicemodel.cpp \ vendordevicetreeitem.cpp \ devicesettingikea.cpp \ @@ -22,6 +23,7 @@ HEADERS += telldusgui.h \ devicemodel.h \ device.h \ editdevicedialog.h \ + editgroupdialog.h \ vendordevicemodel.h \ vendordevicetreeitem.h \ devicesettingikea.h \ diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 25910b16..838762a5 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -6,8 +6,10 @@ #include #include #include +#include #include "editdevicedialog.h" +#include "editgroupdialog.h" #include "methodwidget.h" DeviceWidget::DeviceWidget(QWidget *parent) : @@ -30,10 +32,18 @@ DeviceWidget::DeviceWidget(QWidget *parent) : QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->setSpacing(0); + QMenu *newMenu = new QMenu( this ); + QAction *newDeviceMenuAction = newMenu->addAction( tr("New device...") ); + connect(newDeviceMenuAction, SIGNAL(triggered()), this, SLOT(addDevice())); + QAction *newGroupMenuAction = newMenu->addAction( tr("New group...") ); + connect(newGroupMenuAction, SIGNAL(triggered()), this, SLOT(addGroup())); + addToolButton.setIcon( QIcon( ":/images/list-add.png" ) ); addToolButton.setText( tr("New") ); addToolButton.setToolButtonStyle( Qt::ToolButtonTextBesideIcon ); - connect(&addToolButton, SIGNAL(clicked()), this, SLOT(addDevice())); + addToolButton.setPopupMode( QToolButton::MenuButtonPopup ); + addToolButton.setMenu( newMenu ); + connect(&addToolButton, SIGNAL(clicked()), this, SLOT(addGroup())); buttonLayout->addWidget( &addToolButton ); buttonLayout->addSpacing( 10 ); @@ -85,6 +95,19 @@ void DeviceWidget::addDevice() { delete dialog; } +void DeviceWidget::addGroup() { + Device *device = model.newDevice(); + + EditGroupDialog *dialog = new EditGroupDialog(device, &model); + if (dialog->exec() == QDialog::Accepted) { + device->save(); + } else { + delete device; + } + + delete dialog; +} + void DeviceWidget::deleteDevice() { QMessageBox msgBox; msgBox.setText( tr("Are you sure you want to remove the selected device?") ); diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index 54af343a..916923e3 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -25,6 +25,7 @@ protected: private slots: void listActivated(const QModelIndex &); void addDevice(); + void addGroup(); void deleteDevice(); void editDevice(); diff --git a/telldus-gui/TelldusGui/editgroupdialog.cpp b/telldus-gui/TelldusGui/editgroupdialog.cpp new file mode 100644 index 00000000..b56bd925 --- /dev/null +++ b/telldus-gui/TelldusGui/editgroupdialog.cpp @@ -0,0 +1,70 @@ +#include "editgroupdialog.h" +#include "device.h" +#include "devicemodel.h" + +#include +#include +#include +#include +#include +#include + +EditGroupDialog::EditGroupDialog(Device *d, DeviceModel *m, QWidget *parent, Qt::WFlags flags) + :QDialog(parent, flags), + device(d), + model(model) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + QHBoxLayout *mainLayout = new QHBoxLayout; + + QListView *availableListView = new QListView( this ); + availableListView->setModel( model ); + mainLayout->addWidget( availableListView ); + + QVBoxLayout *buttonsLayout = new QVBoxLayout; + buttonsLayout->addStretch(); + + QToolButton *addToolButton = new QToolButton( this ); + addToolButton->setIcon( qApp->style()->standardIcon( QStyle::SP_ArrowRight) ); + addToolButton->setEnabled( false ); + buttonsLayout->addWidget( addToolButton ); + + QToolButton *removeToolButton = new QToolButton( this ); + removeToolButton->setIcon( qApp->style()->standardIcon( QStyle::SP_ArrowLeft) ); + removeToolButton->setEnabled( false ); + buttonsLayout->addWidget( removeToolButton ); + + buttonsLayout->addStretch(); + mainLayout->addLayout( buttonsLayout ); + + QListView *addedListView = new QListView( this ); + mainLayout->addWidget( addedListView ); + + layout->addLayout( mainLayout ); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + buttonBox->setStandardButtons( QDialogButtonBox::Save | QDialogButtonBox::Cancel ); + connect(buttonBox, SIGNAL(accepted()), this, SLOT(okClicked())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + layout->addWidget(buttonBox); + +} + +EditGroupDialog::~EditGroupDialog() { +} + + +void EditGroupDialog::okClicked() { + +// if (!item || !item->isDevice()) { +// QMessageBox msgBox; +// msgBox.setText( tr("You must choose a device") ); +// msgBox.setInformativeText( tr("Please select the device you have.") ); +// msgBox.setIcon( QMessageBox::Critical ); +// msgBox.setStandardButtons( QMessageBox::Ok ); +// msgBox.exec(); +// return; +// } + this->accept(); +} diff --git a/telldus-gui/TelldusGui/editgroupdialog.h b/telldus-gui/TelldusGui/editgroupdialog.h new file mode 100644 index 00000000..7cfed514 --- /dev/null +++ b/telldus-gui/TelldusGui/editgroupdialog.h @@ -0,0 +1,24 @@ +#ifndef EDITGROUPDIALOG_H +#define EDITGROUPDIALOG_H + +#include + +class Device; +class DeviceModel; + +class EditGroupDialog : public QDialog +{ + Q_OBJECT +public: + EditGroupDialog(Device *device, DeviceModel *model, QWidget *parent = 0, Qt::WFlags flags = 0); + virtual ~EditGroupDialog(); + +private slots: + void okClicked(); + +private: + Device *device; + DeviceModel *model; +}; + +#endif // EDITGROUPDIALOG_H diff --git a/telldus-gui/TelldusGui/methodwidget.cpp b/telldus-gui/TelldusGui/methodwidget.cpp index 706d3a87..87a57a86 100644 --- a/telldus-gui/TelldusGui/methodwidget.cpp +++ b/telldus-gui/TelldusGui/methodwidget.cpp @@ -42,6 +42,8 @@ void MethodWidget::updateMethods(int newMethods) { turnOff->setVisible( newMethods & TELLSTICK_TURNOFF ); turnOn->setVisible( newMethods & TELLSTICK_TURNON ); bell->setVisible( newMethods & TELLSTICK_BELL ); -// qDebug() << "Methods: " << newMethods; + if (newMethods == 0) { + qDebug() << "Methods: " << newMethods; + } } From 46ea2bf5afa4cb52d3734fe4eb160a8d182b1deb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 16 Jan 2009 13:42:03 +0000 Subject: [PATCH 0758/2215] Made it blend into Mac OS X better by only having one MainWindow and raise it on activation --- telldus-gui/TelldusCenter/main.cpp | 5 +---- .../tellduscenterapplication.cpp | 22 +++++++++++++++++++ .../TelldusCenter/tellduscenterapplication.h | 10 +++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/telldus-gui/TelldusCenter/main.cpp b/telldus-gui/TelldusCenter/main.cpp index e3c64934..3adc6cd9 100644 --- a/telldus-gui/TelldusCenter/main.cpp +++ b/telldus-gui/TelldusCenter/main.cpp @@ -1,5 +1,4 @@ #include "tellduscenterapplication.h" -#include "mainwindow.h" #ifdef Q_WS_MAC #include "CocoaInitializer.h" @@ -16,9 +15,7 @@ int main(int argc, char *argv[]) TelldusCenterApplication application(argc, argv); - - MainWindow *w = new MainWindow(); - w->show(); + application.showMainWindow(); #ifdef Q_WS_MAC AutoUpdater* updater = 0; diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 6834aa30..eeca3160 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -18,6 +18,28 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) TelldusCenterApplication::~TelldusCenterApplication() { } +void TelldusCenterApplication::showMainWindow() { + if (!mainWindow) { + mainWindow = new MainWindow(); + } + mainWindow->show(); +} + +#if defined(Q_WS_MAC) +bool TelldusCenterApplication::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::ApplicationActivate: { + showMainWindow(); + return true; + } + default: + break; + } + return QApplication::event(event); +} +#endif + void TelldusCenterApplication::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { qDebug() << "showMessage:" << title << message << detailedMessage; } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index 6e64be47..8897363a 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -3,6 +3,9 @@ #include #include +#include + +#include "mainwindow.h" class TelldusCenterApplication : public QApplication { @@ -11,6 +14,12 @@ public: TelldusCenterApplication(int &argc, char **argv); virtual ~TelldusCenterApplication(); +#if defined(Q_WS_MAC) + bool event(QEvent *event); +#endif + + void showMainWindow(); + static TelldusCenterApplication *instance(); public slots: @@ -20,6 +29,7 @@ public slots: private: QSystemTrayIcon systrayIcon; + QPointer mainWindow; }; #endif // TELLDUSCENTERAPPLICATION_H From c1581ebcc767691316e1fb78875fc1aab90c4138 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 16 Jan 2009 16:40:52 +0000 Subject: [PATCH 0759/2215] Added a menu to the systray-icon --- telldus-gui/TelldusCenter/TelldusCenter.pro | 2 +- telldus-gui/TelldusCenter/mainwindow.cpp | 2 +- .../tellduscenterapplication.cpp | 119 +++++++++++++++++- .../TelldusCenter/tellduscenterapplication.h | 7 ++ 4 files changed, 126 insertions(+), 4 deletions(-) diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index 8e7bc696..0360daf7 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -15,7 +15,7 @@ FORMS += RESOURCES += resource.qrc macx { HEADERS += sparkleautoupdater.h - LIBS += -framework TelldusGui -framework Sparkle + LIBS += -framework TelldusGui -framework TelldusCore -framework Sparkle OBJECTIVE_SOURCES += SparkleAutoUpdater.mm \ CocoaInitializer.mm QMAKE_INFO_PLIST = Info.plist diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index df1d53f8..ac18cdc2 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -54,7 +54,7 @@ void MainWindow::setupMenu() menuBar()->clear(); // File - QMenu *fileMenu = menuBar()->addMenu(tr("&File")); +// QMenu *fileMenu = menuBar()->addMenu(tr("&File")); // Help QMenu *helpMenu = menuBar()->addMenu(tr("&Help")); helpMenu->addSeparator(); diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index eeca3160..9203313f 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -1,4 +1,7 @@ #include "tellduscenterapplication.h" +#include "telldus-core.h" +#include +#include #include TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) @@ -10,6 +13,9 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) #else systrayIcon.setIcon(QIcon(":/images/devices.png")); #endif + connect(&systrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason))); + updateSystrayMenu(); + systrayIcon.setContextMenu( &systrayMenu ); systrayIcon.show(); //setQuitOnLastWindowClosed( false ); @@ -19,12 +25,16 @@ TelldusCenterApplication::~TelldusCenterApplication() { } void TelldusCenterApplication::showMainWindow() { - if (!mainWindow) { + if (!isMainWindowShown()) { mainWindow = new MainWindow(); } mainWindow->show(); } +bool TelldusCenterApplication::isMainWindowShown() { + return !mainWindow.isNull(); +} + #if defined(Q_WS_MAC) bool TelldusCenterApplication::event(QEvent *event) { @@ -40,14 +50,119 @@ bool TelldusCenterApplication::event(QEvent *event) } #endif +void TelldusCenterApplication::activated( QSystemTrayIcon::ActivationReason reason ) { + if (reason == QSystemTrayIcon::Trigger) { + } +} + void TelldusCenterApplication::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { - qDebug() << "showMessage:" << title << message << detailedMessage; + if (isMainWindowShown()) { + QMessageBox msgBox( mainWindow ); + msgBox.setText( message ); + msgBox.setInformativeText( detailedMessage ); + msgBox.setIcon( QMessageBox::Warning ); + msgBox.setStandardButtons( QMessageBox::Ok ); + msgBox.exec(); + } else { + systrayIcon.showMessage(title, message, QSystemTrayIcon::Warning); + qDebug() << "showMessage:" << title << message << detailedMessage; + } } void TelldusCenterApplication::eventTriggered( const QString &name, const QString &title ) { qDebug() << "eventTriggered:" << name << title; } + +void TelldusCenterApplication::updateSystrayMenu() { + systrayMenu.clear(); + + int intNum = tdGetNumberOfDevices(); + int index = 0; + while (index < intNum) { + int id = tdGetDeviceId(index); + addDevice(id); + index++; + } + + systrayMenu.addSeparator(); + + QAction *quit = systrayMenu.addAction(tr("&Quit")); + quit->setIcon( QIcon(":/images/system-log-out.png") ); + connect(quit, SIGNAL(triggered()), qApp, SLOT(quit())); + +// i.setContextMenu(&menu); +} + +void TelldusCenterApplication::addDevice( int intId ) { + char *name = tdGetName(intId); + QString deviceName( name ); + free(name); + QMenu *m = systrayMenu.addMenu( deviceName ); + + int methods = tdMethods(intId, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL ); + if (methods & TELLSTICK_TURNON) { + QAction *on = m->addAction(tr("&On")); + on->setToolTip( tr("Turn on %1").arg( deviceName ) ); + on->setIcon(QIcon(":/images/turn-on.png")); + on->setData( intId ); + connect( on, SIGNAL(triggered()), this, SLOT(on())); + } + + if (methods & TELLSTICK_DIM) { + QAction *dim = m->addAction(tr("90%")); + dim->setData( QString("%1:230").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("80%")); + dim->setData( QString("%1:204").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("70%")); + dim->setData( QString("%1:179").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("60%")); + dim->setData( QString("%1:153").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("50%")); + dim->setData( QString("%1:128").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("40%")); + dim->setData( QString("%1:102").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("30%")); + dim->setData( QString("%1:77").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("20%")); + dim->setData( QString("%1:51").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("10%")); + dim->setData( QString("%1:25").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + } + + if (methods & TELLSTICK_TURNON) { + QAction *off = m->addAction(tr("O&ff")); + off->setToolTip( tr("Turn off %1").arg( deviceName ) ); + off->setData( intId ); + off->setIcon(QIcon(":/images/turn-off.png")); + connect( off, SIGNAL(triggered()), this, SLOT(off())); + } + + if (methods & TELLSTICK_BELL) { + QAction *bell = m->addAction(tr("&Bell")); + bell->setData( intId ); + bell->setIcon(QIcon(":/images/bell.png")); + connect( bell, SIGNAL(triggered()), this, SLOT(bell())); + } +} + TelldusCenterApplication *TelldusCenterApplication::instance() { return (static_cast(QCoreApplication::instance())); } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index 8897363a..ffdb3ac7 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "mainwindow.h" @@ -19,6 +20,7 @@ public: #endif void showMainWindow(); + bool isMainWindowShown(); static TelldusCenterApplication *instance(); @@ -26,10 +28,15 @@ public slots: void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); void eventTriggered( const QString &name, const QString &title ); +private slots: + void activated( QSystemTrayIcon::ActivationReason reason ); + void updateSystrayMenu(); + void addDevice( int id ); private: QSystemTrayIcon systrayIcon; QPointer mainWindow; + QMenu systrayMenu; }; #endif // TELLDUSCENTERAPPLICATION_H From 0d215a41b2d47aadfcfcf3a6cac554266f3ecdc8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 16 Jan 2009 17:52:55 +0000 Subject: [PATCH 0760/2215] Moved the systray icon from TelldusCenterApplication into its own class --- telldus-gui/TelldusCenter/TelldusCenter.pro | 60 +++++---- telldus-gui/TelldusCenter/systrayicon.cpp | 115 ++++++++++++++++++ telldus-gui/TelldusCenter/systrayicon.h | 28 +++++ .../tellduscenterapplication.cpp | 112 +---------------- .../TelldusCenter/tellduscenterapplication.h | 11 +- 5 files changed, 181 insertions(+), 145 deletions(-) create mode 100644 telldus-gui/TelldusCenter/systrayicon.cpp create mode 100644 telldus-gui/TelldusCenter/systrayicon.h diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index 0360daf7..9ca82b17 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -1,27 +1,33 @@ -# ------------------------------------------------- -# Project created by QtCreator 2008-12-11T11:01:36 -# ------------------------------------------------- -TARGET = TelldusCenter -TEMPLATE = app -SOURCES += main.cpp \ - mainwindow.cpp \ - tellduscenterapplication.cpp \ - autoupdater.cpp -HEADERS += mainwindow.h \ - tellduscenterapplication.h \ - autoupdater.h \ - CocoaInitializer.h -FORMS += -RESOURCES += resource.qrc -macx { - HEADERS += sparkleautoupdater.h - LIBS += -framework TelldusGui -framework TelldusCore -framework Sparkle - OBJECTIVE_SOURCES += SparkleAutoUpdater.mm \ - CocoaInitializer.mm - QMAKE_INFO_PLIST = Info.plist -} -!macx:LIBS += -ltelldus-gui -win32 { - LIBS += -L . -} -VERSION = 1.3.0 +# ------------------------------------------------- +# Project created by QtCreator 2008-12-11T11:01:36 +# ------------------------------------------------- +TARGET = TelldusCenter +TEMPLATE = app +SOURCES += main.cpp \ + mainwindow.cpp \ + tellduscenterapplication.cpp \ + autoupdater.cpp \ + systrayicon.cpp +HEADERS += mainwindow.h \ + tellduscenterapplication.h \ + autoupdater.h \ + CocoaInitializer.h \ + systrayicon.h +FORMS += +RESOURCES += resource.qrc +macx { + HEADERS += sparkleautoupdater.h + LIBS += -framework \ + TelldusGui \ + -framework \ + TelldusCore \ + -framework \ + Sparkle + OBJECTIVE_SOURCES += SparkleAutoUpdater.mm \ + CocoaInitializer.mm + QMAKE_INFO_PLIST = Info.plist +} +!macx:LIBS += -ltelldus-gui +win32:LIBS += -L \ + . +VERSION = 1.3.0 diff --git a/telldus-gui/TelldusCenter/systrayicon.cpp b/telldus-gui/TelldusCenter/systrayicon.cpp new file mode 100644 index 00000000..c378e74f --- /dev/null +++ b/telldus-gui/TelldusCenter/systrayicon.cpp @@ -0,0 +1,115 @@ +#include "systrayicon.h" +#include "telldus-core.h" + +#include +#include + +SystrayIcon::SystrayIcon( QObject * parent ) + :QSystemTrayIcon( parent ) +{ +#if defined(Q_WS_MAC) + setIcon(QIcon(":/images/devices-bw.png")); +#else + setIcon(QIcon(":/images/devices.png")); +#endif +// connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason))); + updateSystrayMenu(); + setContextMenu( &systrayMenu ); + show(); +} + +//void SystrayIcon::activated( QSystemTrayIcon::ActivationReason reason ) { +// if (reason == QSystemTrayIcon::Trigger) { +// } +//} + +void SystrayIcon::eventTriggered( const QString &name, const QString &title ) { + qDebug() << "Systray - eventTriggered:" << name << title; +} + +void SystrayIcon::updateSystrayMenu() { + systrayMenu.clear(); + + int intNum = tdGetNumberOfDevices(); + int index = 0; + while (index < intNum) { + int id = tdGetDeviceId(index); + addDevice(id); + index++; + } + + systrayMenu.addSeparator(); + + QAction *quit = systrayMenu.addAction(tr("&Quit")); + quit->setIcon( QIcon(":/images/system-log-out.png") ); + connect(quit, SIGNAL(triggered()), qApp, SLOT(quit())); +} + +void SystrayIcon::addDevice( int intId ) { + char *name = tdGetName(intId); + QString deviceName( name ); + free(name); + QMenu *m = systrayMenu.addMenu( deviceName ); + + int methods = tdMethods(intId, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL ); + if (methods & TELLSTICK_TURNON) { + QAction *on = m->addAction(tr("&On")); + on->setToolTip( tr("Turn on %1").arg( deviceName ) ); + on->setIcon(QIcon(":/images/turn-on.png")); + on->setData( intId ); + connect( on, SIGNAL(triggered()), this, SLOT(on())); + } + + if (methods & TELLSTICK_DIM) { + QAction *dim = m->addAction(tr("90%")); + dim->setData( QString("%1:230").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("80%")); + dim->setData( QString("%1:204").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("70%")); + dim->setData( QString("%1:179").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("60%")); + dim->setData( QString("%1:153").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("50%")); + dim->setData( QString("%1:128").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("40%")); + dim->setData( QString("%1:102").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("30%")); + dim->setData( QString("%1:77").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("20%")); + dim->setData( QString("%1:51").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + + dim = m->addAction(tr("10%")); + dim->setData( QString("%1:25").arg(intId) ); + connect( dim, SIGNAL(triggered()), this, SLOT(dim())); + } + + if (methods & TELLSTICK_TURNON) { + QAction *off = m->addAction(tr("O&ff")); + off->setToolTip( tr("Turn off %1").arg( deviceName ) ); + off->setData( intId ); + off->setIcon(QIcon(":/images/turn-off.png")); + connect( off, SIGNAL(triggered()), this, SLOT(off())); + } + + if (methods & TELLSTICK_BELL) { + QAction *bell = m->addAction(tr("&Bell")); + bell->setData( intId ); + bell->setIcon(QIcon(":/images/bell.png")); + connect( bell, SIGNAL(triggered()), this, SLOT(bell())); + } +} diff --git a/telldus-gui/TelldusCenter/systrayicon.h b/telldus-gui/TelldusCenter/systrayicon.h new file mode 100644 index 00000000..512e8bb6 --- /dev/null +++ b/telldus-gui/TelldusCenter/systrayicon.h @@ -0,0 +1,28 @@ +#ifndef SYSTRAYICON_H +#define SYSTRAYICON_H + +#include +#include + +class SystrayIcon : public QSystemTrayIcon +{ + Q_OBJECT +public: + SystrayIcon( QObject * parent = 0 ); + +signals: + void showEventMessage( const QString &title, const QString &message, const QString &detailedMessage ); + +public slots: + void eventTriggered( const QString &name, const QString &title ); + +private slots: +// void activated( QSystemTrayIcon::ActivationReason reason ); + void updateSystrayMenu(); + void addDevice( int id ); + +private: + QMenu systrayMenu; +}; + +#endif // SYSTRAYICON_H diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 9203313f..f6d511ad 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -1,23 +1,12 @@ #include "tellduscenterapplication.h" -#include "telldus-core.h" #include -#include #include TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) :QApplication(argc, argv), systrayIcon(this) { -#if defined(Q_WS_MAC) - systrayIcon.setIcon(QIcon(":/images/devices-bw.png")); -#else - systrayIcon.setIcon(QIcon(":/images/devices.png")); -#endif - connect(&systrayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason))); - updateSystrayMenu(); - systrayIcon.setContextMenu( &systrayMenu ); - systrayIcon.show(); - + connect(&systrayIcon, SIGNAL(showEventMessage(const QString &, const QString &, const QString &)), this, SLOT(showMessage(QString,QString,QString))); //setQuitOnLastWindowClosed( false ); } @@ -50,9 +39,8 @@ bool TelldusCenterApplication::event(QEvent *event) } #endif -void TelldusCenterApplication::activated( QSystemTrayIcon::ActivationReason reason ) { - if (reason == QSystemTrayIcon::Trigger) { - } +void TelldusCenterApplication::eventTriggered( const QString &name, const QString &title ) { + qDebug() << "Systray - eventTriggered:" << name << title; } void TelldusCenterApplication::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { @@ -69,100 +57,6 @@ void TelldusCenterApplication::showMessage( const QString &title, const QString } } -void TelldusCenterApplication::eventTriggered( const QString &name, const QString &title ) { - qDebug() << "eventTriggered:" << name << title; -} - - -void TelldusCenterApplication::updateSystrayMenu() { - systrayMenu.clear(); - - int intNum = tdGetNumberOfDevices(); - int index = 0; - while (index < intNum) { - int id = tdGetDeviceId(index); - addDevice(id); - index++; - } - - systrayMenu.addSeparator(); - - QAction *quit = systrayMenu.addAction(tr("&Quit")); - quit->setIcon( QIcon(":/images/system-log-out.png") ); - connect(quit, SIGNAL(triggered()), qApp, SLOT(quit())); - -// i.setContextMenu(&menu); -} - -void TelldusCenterApplication::addDevice( int intId ) { - char *name = tdGetName(intId); - QString deviceName( name ); - free(name); - QMenu *m = systrayMenu.addMenu( deviceName ); - - int methods = tdMethods(intId, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL ); - if (methods & TELLSTICK_TURNON) { - QAction *on = m->addAction(tr("&On")); - on->setToolTip( tr("Turn on %1").arg( deviceName ) ); - on->setIcon(QIcon(":/images/turn-on.png")); - on->setData( intId ); - connect( on, SIGNAL(triggered()), this, SLOT(on())); - } - - if (methods & TELLSTICK_DIM) { - QAction *dim = m->addAction(tr("90%")); - dim->setData( QString("%1:230").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("80%")); - dim->setData( QString("%1:204").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("70%")); - dim->setData( QString("%1:179").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("60%")); - dim->setData( QString("%1:153").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("50%")); - dim->setData( QString("%1:128").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("40%")); - dim->setData( QString("%1:102").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("30%")); - dim->setData( QString("%1:77").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("20%")); - dim->setData( QString("%1:51").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("10%")); - dim->setData( QString("%1:25").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - } - - if (methods & TELLSTICK_TURNON) { - QAction *off = m->addAction(tr("O&ff")); - off->setToolTip( tr("Turn off %1").arg( deviceName ) ); - off->setData( intId ); - off->setIcon(QIcon(":/images/turn-off.png")); - connect( off, SIGNAL(triggered()), this, SLOT(off())); - } - - if (methods & TELLSTICK_BELL) { - QAction *bell = m->addAction(tr("&Bell")); - bell->setData( intId ); - bell->setIcon(QIcon(":/images/bell.png")); - connect( bell, SIGNAL(triggered()), this, SLOT(bell())); - } -} - TelldusCenterApplication *TelldusCenterApplication::instance() { return (static_cast(QCoreApplication::instance())); } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index ffdb3ac7..d72d313d 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -2,10 +2,9 @@ #define TELLDUSCENTERAPPLICATION_H #include -#include #include -#include +#include "systrayicon.h" #include "mainwindow.h" class TelldusCenterApplication : public QApplication @@ -28,15 +27,9 @@ public slots: void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); void eventTriggered( const QString &name, const QString &title ); -private slots: - void activated( QSystemTrayIcon::ActivationReason reason ); - void updateSystrayMenu(); - void addDevice( int id ); - private: - QSystemTrayIcon systrayIcon; + SystrayIcon systrayIcon; QPointer mainWindow; - QMenu systrayMenu; }; #endif // TELLDUSCENTERAPPLICATION_H From 5a4e8f00302a26f14635fab3300e78771109a1f5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Jan 2009 09:48:41 +0000 Subject: [PATCH 0761/2215] Bugfix in EditGroupDialog --- telldus-gui/TelldusGui/editgroupdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/editgroupdialog.cpp b/telldus-gui/TelldusGui/editgroupdialog.cpp index b56bd925..7aa7c880 100644 --- a/telldus-gui/TelldusGui/editgroupdialog.cpp +++ b/telldus-gui/TelldusGui/editgroupdialog.cpp @@ -12,7 +12,7 @@ EditGroupDialog::EditGroupDialog(Device *d, DeviceModel *m, QWidget *parent, Qt::WFlags flags) :QDialog(parent, flags), device(d), - model(model) + model(m) { QVBoxLayout *layout = new QVBoxLayout(this); From 42adeeb6c1a6c292ce75fab364804c6a0a5efda1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Jan 2009 10:06:43 +0000 Subject: [PATCH 0762/2215] Made EdtiDeviceDialog show when you press edit on a group device --- telldus-gui/TelldusCenter/systrayicon.cpp | 2 +- telldus-gui/TelldusGui/device.cpp | 5 ++++- telldus-gui/TelldusGui/device.h | 4 ++++ telldus-gui/TelldusGui/devicewidget.cpp | 7 ++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/telldus-gui/TelldusCenter/systrayicon.cpp b/telldus-gui/TelldusCenter/systrayicon.cpp index c378e74f..222a6b26 100644 --- a/telldus-gui/TelldusCenter/systrayicon.cpp +++ b/telldus-gui/TelldusCenter/systrayicon.cpp @@ -47,7 +47,7 @@ void SystrayIcon::updateSystrayMenu() { void SystrayIcon::addDevice( int intId ) { char *name = tdGetName(intId); - QString deviceName( name ); + QString deviceName = QString::fromLocal8Bit( name ); free(name); QMenu *m = systrayMenu.addMenu( deviceName ); diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 23d0f339..96399e54 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -1,5 +1,4 @@ #include "device.h" -#include "telldus-core.h" #include QHash Device::devices; @@ -81,6 +80,10 @@ int Device::methods() const { return p_methods; } +int Device::deviceType() const { + return tdGetDeviceType(p_id); +} + Device *Device::getDevice( int id ) { if (devices.contains(id)) { diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index 6f030ceb..f61b6b7b 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -1,6 +1,8 @@ #ifndef DEVICE_H #define DEVICE_H +#include "telldus-core.h" + #include #include #include @@ -29,6 +31,8 @@ public: void setProtocol( const QString & protocol ); const QString &protocol(); + int deviceType() const; + int methods() const; public slots: diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 838762a5..7def74cd 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -124,7 +124,12 @@ void DeviceWidget::deleteDevice() { void DeviceWidget::editDevice() { Device *device = model.device( deviceView.currentIndex() ); - EditDeviceDialog *dialog = new EditDeviceDialog( device ); + QDialog *dialog; + if (device->deviceType() == TELLSTICK_TYPE_GROUP) { + dialog = new EditGroupDialog( device, &model ); + } else { + dialog = new EditDeviceDialog( device ); + } if (dialog->exec() == QDialog::Accepted) { device->save(); } From 95d6cf0704f5d7e523defe7e14c294291ebbe35c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Jan 2009 16:04:13 +0000 Subject: [PATCH 0763/2215] Added vendor-logos to the list of available devices --- telldus-gui/TelldusGui/images/vendors/ikea.jpg | Bin 15658 -> 0 bytes telldus-gui/TelldusGui/images/vendors/ikea.png | Bin 0 -> 7246 bytes telldus-gui/TelldusGui/images/vendors/nexa.jpg | Bin 22438 -> 0 bytes telldus-gui/TelldusGui/images/vendors/nexa.png | Bin 0 -> 8427 bytes .../TelldusGui/images/vendors/proove.jpg | Bin 20998 -> 0 bytes .../TelldusGui/images/vendors/proove.png | Bin 0 -> 7963 bytes .../TelldusGui/images/vendors/sartano.jpg | Bin 18550 -> 0 bytes .../TelldusGui/images/vendors/sartano.png | Bin 0 -> 7658 bytes .../TelldusGui/images/vendors/waveman.jpg | Bin 18172 -> 0 bytes .../TelldusGui/images/vendors/waveman.png | Bin 0 -> 6474 bytes telldus-gui/TelldusGui/telldusgui.qrc | 10 +++++----- telldus-gui/TelldusGui/vendordevicemodel.cpp | 10 ++++++++-- telldus-gui/TelldusGui/vendordevicetreeitem.cpp | 2 +- 13 files changed, 14 insertions(+), 8 deletions(-) delete mode 100644 telldus-gui/TelldusGui/images/vendors/ikea.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/ikea.png delete mode 100644 telldus-gui/TelldusGui/images/vendors/nexa.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/nexa.png delete mode 100644 telldus-gui/TelldusGui/images/vendors/proove.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/proove.png delete mode 100644 telldus-gui/TelldusGui/images/vendors/sartano.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/sartano.png delete mode 100644 telldus-gui/TelldusGui/images/vendors/waveman.jpg create mode 100644 telldus-gui/TelldusGui/images/vendors/waveman.png diff --git a/telldus-gui/TelldusGui/images/vendors/ikea.jpg b/telldus-gui/TelldusGui/images/vendors/ikea.jpg deleted file mode 100644 index 5ab03814be390b2bb73966d74113f0401bad707f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15658 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 diff --git a/telldus-gui/TelldusGui/images/vendors/nexa.png b/telldus-gui/TelldusGui/images/vendors/nexa.png new file mode 100644 index 0000000000000000000000000000000000000000..41c031aae27143703daa5b8abe1236620f0cee08 GIT binary patch literal 8427 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 RM0EfF002ovPDHLkV1lm9bV2|C literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/sartano.jpg b/telldus-gui/TelldusGui/images/vendors/sartano.jpg deleted file mode 100644 index 01a652bf37178eb9935abd13c4159865c2c7031b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18550 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 diff --git a/telldus-gui/TelldusGui/images/vendors/waveman.png b/telldus-gui/TelldusGui/images/vendors/waveman.png new file mode 100644 index 0000000000000000000000000000000000000000..104ea3af79e6486020b16f01d60de5e4a6860dd2 GIT binary patch literal 6474 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index b919045f..d486cd7c 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -21,12 +21,12 @@ images/list-remove.png images/turn-off.png images/turn-on.png - images/vendors/ikea.jpg + images/vendors/ikea.png images/vendors/intertechno.jpg - images/vendors/nexa.jpg - images/vendors/proove.jpg - images/vendors/sartano.jpg + images/vendors/nexa.png + images/vendors/proove.png + images/vendors/sartano.png images/vendors/telldus.jpg - images/vendors/waveman.jpg + images/vendors/waveman.png diff --git a/telldus-gui/TelldusGui/vendordevicemodel.cpp b/telldus-gui/TelldusGui/vendordevicemodel.cpp index 68d4b29c..d1204bc0 100644 --- a/telldus-gui/TelldusGui/vendordevicemodel.cpp +++ b/telldus-gui/TelldusGui/vendordevicemodel.cpp @@ -28,11 +28,17 @@ QVariant VendorDeviceModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { VendorDeviceTreeItem *item = static_cast(index.internalPointer()); - return item->data(index.column()); + if (item->isDevice()) { + return item->data(index.column()); + } + return ""; } else if (role == Qt::DecorationRole) { VendorDeviceTreeItem *item = static_cast(index.internalPointer()); QPixmap pixmap = item->image(); - return pixmap.scaled(22, 22, Qt::KeepAspectRatio); + if (item->isDevice()) { + return pixmap.scaled(22, 22, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + return pixmap.scaled(150, 15, Qt::KeepAspectRatio, Qt::SmoothTransformation); } return QVariant(); } diff --git a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp index e7b0f0a8..71d885ff 100644 --- a/telldus-gui/TelldusGui/vendordevicetreeitem.cpp +++ b/telldus-gui/TelldusGui/vendordevicetreeitem.cpp @@ -54,7 +54,7 @@ int VendorDeviceTreeItem::row() const { QPixmap VendorDeviceTreeItem::image() const { QString filename; if (deviceId == 0) { - filename = ":/images/vendors/" + img.toLower() + ".jpg"; + filename = ":/images/vendors/" + img.toLower() + ".png"; } else { filename = ":/images/devices/" + img + ".png"; } From 536c233b5eb441806e3b8d35e1ca00dcb5545cd6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Jan 2009 16:06:09 +0000 Subject: [PATCH 0764/2215] Made the menu options in the systray work --- telldus-gui/TelldusCenter/systrayicon.cpp | 69 +++++++++++++++++-- telldus-gui/TelldusCenter/systrayicon.h | 9 ++- .../tellduscenterapplication.cpp | 6 +- 3 files changed, 75 insertions(+), 9 deletions(-) diff --git a/telldus-gui/TelldusCenter/systrayicon.cpp b/telldus-gui/TelldusCenter/systrayicon.cpp index 222a6b26..d966edbc 100644 --- a/telldus-gui/TelldusCenter/systrayicon.cpp +++ b/telldus-gui/TelldusCenter/systrayicon.cpp @@ -1,5 +1,6 @@ #include "systrayicon.h" #include "telldus-core.h" +#include "tellduscenterapplication.h" #include #include @@ -11,17 +12,75 @@ SystrayIcon::SystrayIcon( QObject * parent ) setIcon(QIcon(":/images/devices-bw.png")); #else setIcon(QIcon(":/images/devices.png")); + connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason))); #endif -// connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason))); updateSystrayMenu(); setContextMenu( &systrayMenu ); show(); } -//void SystrayIcon::activated( QSystemTrayIcon::ActivationReason reason ) { -// if (reason == QSystemTrayIcon::Trigger) { -// } -//} +#if !defined(Q_WS_MAC) +void SystrayIcon::activated( QSystemTrayIcon::ActivationReason reason ) { + if (reason == QSystemTrayIcon::Trigger) { + TelldusCenterApplication *app = TelldusCenterApplication::instance(); + app->showMainWindow(); + } +} +#endif + +void SystrayIcon::on() { + QAction *action = qobject_cast(sender()); + if (action) { + int retval = tdTurnOn( action->data().toInt() ); + if (retval != TELLSTICK_SUCCESS) { + char *errorString = tdGetErrorString( retval ); + QString message = QString::fromLocal8Bit( errorString ); + free(errorString); + emit showEventMessage("", message, ""); + } + } +} + +void SystrayIcon::off() { + QAction *action = qobject_cast(sender()); + if (action) { + int retval = tdTurnOff( action->data().toInt() ); + if (retval != TELLSTICK_SUCCESS) { + char *errorString = tdGetErrorString( retval ); + QString message = QString::fromLocal8Bit( errorString ); + free(errorString); + emit showEventMessage("", message, ""); + } + } +} + +void SystrayIcon::dim() { + QAction *action = qobject_cast(sender()); + if (action) { + int intId = action->data().toString().section(":", 0, 0).toInt(); + int intLevel = action->data().toString().section(":", 1, 1).toInt(); + int retval = tdDim( intId, intLevel ); + if (retval != TELLSTICK_SUCCESS) { + char *errorString = tdGetErrorString( retval ); + QString message = QString::fromLocal8Bit( errorString ); + free(errorString); + emit showEventMessage("", message, ""); + } + } +} + +void SystrayIcon::bell() { + QAction *action = qobject_cast(sender()); + if (action) { + int retval = tdBell( action->data().toInt() ); + if (retval != TELLSTICK_SUCCESS) { + char *errorString = tdGetErrorString( retval ); + QString message = QString::fromLocal8Bit( errorString ); + free(errorString); + emit showEventMessage("", message, ""); + } + } +} void SystrayIcon::eventTriggered( const QString &name, const QString &title ) { qDebug() << "Systray - eventTriggered:" << name << title; diff --git a/telldus-gui/TelldusCenter/systrayicon.h b/telldus-gui/TelldusCenter/systrayicon.h index 512e8bb6..5a4355a0 100644 --- a/telldus-gui/TelldusCenter/systrayicon.h +++ b/telldus-gui/TelldusCenter/systrayicon.h @@ -17,10 +17,17 @@ public slots: void eventTriggered( const QString &name, const QString &title ); private slots: -// void activated( QSystemTrayIcon::ActivationReason reason ); +#if !defined(Q_WS_MAC) + void activated( QSystemTrayIcon::ActivationReason reason ); +#endif void updateSystrayMenu(); void addDevice( int id ); + void on(); + void off(); + void dim(); + void bell(); + private: QMenu systrayMenu; }; diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index f6d511ad..68735146 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -7,7 +7,8 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) systrayIcon(this) { connect(&systrayIcon, SIGNAL(showEventMessage(const QString &, const QString &, const QString &)), this, SLOT(showMessage(QString,QString,QString))); - //setQuitOnLastWindowClosed( false ); + + setQuitOnLastWindowClosed( false ); } TelldusCenterApplication::~TelldusCenterApplication() { @@ -52,8 +53,7 @@ void TelldusCenterApplication::showMessage( const QString &title, const QString msgBox.setStandardButtons( QMessageBox::Ok ); msgBox.exec(); } else { - systrayIcon.showMessage(title, message, QSystemTrayIcon::Warning); - qDebug() << "showMessage:" << title << message << detailedMessage; + systrayIcon.showMessage((title != "" ? title : "Telldus Center"), message, QSystemTrayIcon::Warning); } } From 7aa697cf3eb5b7badd019b151488267807c14e92 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Jan 2009 14:29:39 +0000 Subject: [PATCH 0765/2215] =?UTF-8?q?Fixed=20bug=20with=20=C3=A5=C3=A4?= =?UTF-8?q?=C3=B6=20on=20Mac=20OS=20X?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SettingsCoreFoundationPreferences.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp b/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp index 133d1ad8..b1aadbc7 100644 --- a/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsCoreFoundationPreferences.cpp @@ -151,7 +151,7 @@ bool Settings::removeDevice(int intDeviceId){ } std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); CFStringRef key; if (parameter) { @@ -178,8 +178,8 @@ std::string Settings::getStringSetting(int intDeviceId, const std::string &name, } bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); - CFStringRef cfvalue = CFStringCreateWithCString( 0, value.c_str(), 0 ); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); + CFStringRef cfvalue = CFStringCreateWithCString( 0, value.c_str(), kCFStringEncodingUTF8 ); CFStringRef key; if (parameter) { @@ -195,7 +195,7 @@ bool Settings::setStringSetting(int intDeviceId, const std::string &name, const int Settings::getIntSetting(int intDeviceId, const std::string &name, bool parameter) const { int retval = 0; - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); CFNumberRef cfvalue; CFStringRef key; @@ -220,7 +220,7 @@ int Settings::getIntSetting(int intDeviceId, const std::string &name, bool param } bool Settings::setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter) { - CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), 0 ); + CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); CFNumberRef cfvalue = CFNumberCreate(NULL, kCFNumberIntType, &value); CFStringRef key; From 8be4a3520092d12ecd2ba098678b4b3a42c7bb1e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Jan 2009 17:00:50 +0000 Subject: [PATCH 0766/2215] Reloaded the device after a protocol-change --- telldus-core/driver/libtelldus-core/Manager.cpp | 11 +++++++++++ telldus-core/driver/libtelldus-core/Manager.h | 2 ++ telldus-core/driver/libtelldus-core/telldus-core.cpp | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index a492d6a4..ddd36926 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -102,6 +102,17 @@ Device *Manager::getDevice(int intDeviceId){ return dev; } +bool Manager::setProtocol(int intDeviceId, const std::string &strProtocol) { + bool retval = settings.setProtocol( intDeviceId, strProtocol ); + + // Delete the device to reload it when the protocol changes + DeviceMap::iterator iterator = devices.find(intDeviceId); + if (iterator != devices.end()) { + Device *device = iterator->second; + devices.erase( iterator ); + delete device; + } +} bool Manager::deviceLoaded(int deviceId) const { DeviceMap::const_iterator iterator = devices.find(deviceId); diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index 7b86f7cd..89394f4b 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -31,6 +31,8 @@ namespace TelldusCore { bool deviceLoaded(int deviceId) const; + bool setProtocol(int intDeviceId, const std::string &strProtocol); + static Manager *getInstance(); static void close(); diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index fde63c6c..d48a4fa8 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -330,8 +330,8 @@ char* WINAPI tdGetProtocol(int intDeviceId){ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ bool blnSuccess = false; try{ - Settings ts; - blnSuccess = ts.setProtocol(intDeviceId, strProtocol); + Manager *manager = Manager::getInstance(); + blnSuccess = manager->setProtocol(intDeviceId, strProtocol); } catch(exception e){ blnSuccess = false; From 1c28bb54cc1c2782602bf3e2549353d1ba64a151 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Jan 2009 17:11:41 +0000 Subject: [PATCH 0767/2215] Fixed bug if the parameter does not exist in the configuration-file --- .../libtelldus-core/SettingsConfuse.cpp | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp index 85c1a6c8..f002dc23 100644 --- a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: telldussettingsconfuse // -// Description: +// Description: // // // Author: Micke Prag , (C) 2008 @@ -83,7 +83,7 @@ int Settings::addDevice(){ cfg_print(d->cfg, fp); //Print the config-file fprintf(fp, "device {\n id=%d\n}\n", intDeviceId); //Print the new device fclose(fp); - + //Re-read config-file cfg_free(d->cfg); readConfig(&d->cfg); @@ -112,10 +112,10 @@ int Settings::getNextDeviceId() const { bool Settings::removeDevice(int intDeviceId){ bool blnSuccess = true; FILE *fp = fopen(CONFIG_FILE, "w"); - + // Print all opts for(int i = 0; d->cfg->opts[i].name; i++) { - + // Check if it isn't a device section if (strcmp(d->cfg->opts[i].name, "device") != 0) { cfg_opt_print(&d->cfg->opts[i], fp); @@ -133,17 +133,17 @@ bool Settings::removeDevice(int intDeviceId){ } } fclose(fp); - + //Re-read config-file cfg_free(d->cfg); readConfig(&d->cfg); - + return blnSuccess; } std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { if (d->cfg == 0) { - return NULL; + return ""; } cfg_t *cfg_device; for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { @@ -152,11 +152,14 @@ std::string Settings::getStringSetting(int intDeviceId, const std::string &name, if (parameter) { cfg_device = cfg_getsec(cfg_device, "parameters"); } - std::string strSetting = cfg_getstr(cfg_device, name.c_str()); - return strSetting; + char *setting = cfg_getstr(cfg_device, name.c_str()); + if (setting == 0) { //The parameter does not exists + return ""; + } + return setting; } } - return NULL; + return ""; } bool Settings::setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter) { @@ -227,26 +230,26 @@ bool readConfig(cfg_t **cfg) { cfg_opt_t controller_opts[] = { CFG_INT("id", -1, CFGF_NONE), }; - + cfg_opt_t device_parameter_opts[] = { //Groups CFG_STR("devices", 0, CFGF_NONE), - + //Nexa CFG_STR("nexa_house", 0, CFGF_NONE), CFG_STR("nexa_unit", 0, CFGF_NONE), - + //Sartano CFG_STR("sartano_code", 0, CFGF_NONE), - + //Ikea CFG_STR("ikea_system", 0, CFGF_NONE), CFG_STR("ikea_units", 0, CFGF_NONE), CFG_STR("ikea_fade", 0, CFGF_NONE), - + CFG_END() }; - + cfg_opt_t device_opts[] = { CFG_INT("id", -1, CFGF_NONE), CFG_STR("name", "Unnamed", CFGF_NONE), @@ -256,13 +259,13 @@ bool readConfig(cfg_t **cfg) { CFG_SEC("parameters", device_parameter_opts, CFGF_NONE), CFG_END() }; - + cfg_opt_t opts[] = { CFG_STR("deviceNode", "/dev/tellstick", CFGF_NONE), CFG_SEC("device", device_opts, CFGF_MULTI), CFG_END() }; - + (*cfg) = cfg_init(opts, CFGF_NOCASE); if (cfg_parse((*cfg), CONFIG_FILE) == CFG_PARSE_ERROR) { (*cfg) = 0; From e0343827c84b95c8f9db315963d7ec20b220c367 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 23 Jan 2009 09:49:56 +0000 Subject: [PATCH 0768/2215] Moved setModel() into Manager --- telldus-core/driver/libtelldus-core/Manager.cpp | 12 ++++++++++++ telldus-core/driver/libtelldus-core/Manager.h | 3 +++ .../driver/libtelldus-core/telldus-core.cpp | 16 ++++++---------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index ddd36926..f1bd1a2c 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -114,6 +114,18 @@ bool Manager::setProtocol(int intDeviceId, const std::string &strProtocol) { } } +bool Manager::setModel(int intDeviceId, int intModel) { + bool retval = settings.setModel(intDeviceId, intModel); + if (deviceLoaded(intDeviceId)) { + Device *device = getDevice(intDeviceId); + if (device) { + device->setModel( intModel ); + } + } + return retval; +} + + bool Manager::deviceLoaded(int deviceId) const { DeviceMap::const_iterator iterator = devices.find(deviceId); if (iterator == devices.end()) { diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index 89394f4b..c65b2c02 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -32,6 +32,9 @@ namespace TelldusCore { bool deviceLoaded(int deviceId) const; bool setProtocol(int intDeviceId, const std::string &strProtocol); +// bool setName(int intDeviceId, const std::string &strNewName); + bool setModel(int intDeviceId, int intModel); +// bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); static Manager *getInstance(); static void close(); diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index d48a4fa8..eba98954 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -343,8 +343,11 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ int WINAPI tdGetModel(int intDeviceId){ int intReturn = 0; try{ - Settings ts; - intReturn = ts.getModel(intDeviceId); + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if (dev != NULL) { + intReturn = dev->getModel(); + } } catch(exception e){ intReturn = 0; @@ -356,15 +359,8 @@ int WINAPI tdGetModel(int intDeviceId){ bool WINAPI tdSetModel(int intDeviceId, int intModel){ bool blnSuccess = false; try{ - Settings ts; - blnSuccess = ts.setModel(intDeviceId, intModel); Manager *manager = Manager::getInstance(); - if (manager->deviceLoaded(intDeviceId)) { - Device *device = manager->getDevice(intDeviceId); - if (device) { - device->setModel( intModel ); - } - } + manager->setModel(intDeviceId, intModel); } catch(exception e){ blnSuccess = false; From d3035eb546315567467ef695a502b13266634945 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 13:03:21 +0000 Subject: [PATCH 0769/2215] Added first version of TellStick Duo controller --- .../driver/libtelldus-core/Controller.cpp | 25 +++ .../driver/libtelldus-core/Controller.h | 34 ++++ .../driver/libtelldus-core/TellStickDuo.cpp | 167 ++++++++++++++++++ .../driver/libtelldus-core/TellStickDuo.h | 50 ++++++ 4 files changed, 276 insertions(+) create mode 100644 telldus-core/driver/libtelldus-core/Controller.cpp create mode 100644 telldus-core/driver/libtelldus-core/Controller.h create mode 100644 telldus-core/driver/libtelldus-core/TellStickDuo.cpp create mode 100644 telldus-core/driver/libtelldus-core/TellStickDuo.h diff --git a/telldus-core/driver/libtelldus-core/Controller.cpp b/telldus-core/driver/libtelldus-core/Controller.cpp new file mode 100644 index 00000000..04d6225e --- /dev/null +++ b/telldus-core/driver/libtelldus-core/Controller.cpp @@ -0,0 +1,25 @@ +// +// C++ Implementation: controller +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "Controller.h" + +using namespace TelldusCore; + +Controller::Controller() +{ +} + + +Controller::~Controller() +{ +} + + diff --git a/telldus-core/driver/libtelldus-core/Controller.h b/telldus-core/driver/libtelldus-core/Controller.h new file mode 100644 index 00000000..8001a770 --- /dev/null +++ b/telldus-core/driver/libtelldus-core/Controller.h @@ -0,0 +1,34 @@ +// +// C++ Interface: controller +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include +#include + +/** + @author Micke Prag +*/ +namespace TelldusCore { + class Controller { + public: + Controller(); + + virtual ~Controller(); + + virtual int firmwareVersion() = 0; + virtual int send( const std::string &message ) = 0; + + }; +} + +#endif diff --git a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp new file mode 100644 index 00000000..74ca235e --- /dev/null +++ b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp @@ -0,0 +1,167 @@ +// +// C++ Implementation: controller +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "TellStickDuo.h" +#include "Manager.h" +#include +#include + +using namespace TelldusCore; + +namespace TelldusCore { + class PrivateTellStickDuoListener: public QThread { + public: + PrivateTellStickDuoListener( TellStickDuo *parent ); + ~PrivateTellStickDuoListener(); + void stop(); + protected: + void run(); + private: + void processData( const std::string &data ); + + TellStickDuo *parent; + EVENT_HANDLE eh; + bool running; + QMutex mutex; + std::string message; + }; +} + +TellStickDuo::TellStickDuo(const std::string &serial) + : Controller(), + ftHandle(0), + open(false), + listener(0), + fwVersion(0) +{ + FT_STATUS ftStatus = FT_OK; + + char *tempSerial = new char[serial.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempSerial, serial.size()+1, serial.c_str()); +#else + strcpy(tempSerial, serial.c_str()); +#endif + + ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &ftHandle); + delete tempSerial; + + + if (ftStatus == FT_OK) { + open = true; + FT_SetBaudRate(ftHandle, 9600); + FT_SetFlowControl(ftHandle, FT_FLOW_NONE, 0, 0); + + listener = new PrivateTellStickDuoListener(this); + listener->start(); + + char message[] = "V+"; + DWORD bytesWritten; + FT_Write(ftHandle, message, sizeof(message), &bytesWritten); + } + + printf("Open: %d - %d\n", (int)ftStatus, connected()); +} + + +TellStickDuo::~TellStickDuo() { + if (listener) { + listener->stop(); + delete listener; + } + if (connected()) { + FT_Close(ftHandle); + } +} + +int TellStickDuo::firmwareVersion() { + return fwVersion; +} + +int TellStickDuo::send( const std::string &message ) { +} + +bool TellStickDuo::connected() const { + return open; +} + +PrivateTellStickDuoListener::PrivateTellStickDuoListener( TellStickDuo *p ) + : QThread(), + parent(p), + running(false) +{ +} + +PrivateTellStickDuoListener::~PrivateTellStickDuoListener() { + if (running) { + stop(); + } +} + +void PrivateTellStickDuoListener::stop() { + if (running) { + QMutexLocker locker(&mutex); + running = false; + //Unlock the wait-condition + pthread_cond_broadcast(&eh.eCondVar); + } + wait(); +} + +void PrivateTellStickDuoListener::run() { + DWORD dwBytesInQueue = 0; + DWORD dwBytesRead = 0; + char *buf = 0; + + pthread_mutex_init(&eh.eMutex, NULL); + pthread_cond_init(&eh.eCondVar, NULL); + + { + QMutexLocker locker(&mutex); + running = true; + } + + while(running) { + FT_SetEventNotification(parent->ftHandle, FT_EVENT_RXCHAR, (PVOID)&eh); + pthread_mutex_lock(&eh.eMutex); + pthread_cond_wait(&eh.eCondVar, &eh.eMutex); + pthread_mutex_unlock(&eh.eMutex); + + FT_GetQueueStatus(parent->ftHandle, &dwBytesInQueue); + if (dwBytesInQueue <= 1) { + continue; + } + + buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); + memset(buf, 0, dwBytesInQueue+1); + FT_Read(parent->ftHandle, buf, dwBytesInQueue, &dwBytesRead); + processData( buf ); + free(buf); + } +} + +void PrivateTellStickDuoListener::processData( const std::string &data ) { + for (int i = 0; i < data.length(); ++i) { + if (data[i] == 13) { // Skip \r + continue; + } else if (data[i] == 10) { // \n found + if (message.substr(0,2).compare("+V") == 0) { + parent->fwVersion = atoi(message.substr(2).c_str()); + } else { + Manager *manager = Manager::getInstance(); + manager->parseMessage(message); + } + message.clear(); + } else { // Append the character + message.append( 1, data[i] ); + } + } +} diff --git a/telldus-core/driver/libtelldus-core/TellStickDuo.h b/telldus-core/driver/libtelldus-core/TellStickDuo.h new file mode 100644 index 00000000..bdf476f7 --- /dev/null +++ b/telldus-core/driver/libtelldus-core/TellStickDuo.h @@ -0,0 +1,50 @@ +// +// C++ Interface: controller +// +// Description: +// +// +// Author: Micke Prag , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef TELLSTICKDUO_H +#define TELLSTICKDUO_H + +#include +#include + +#include "Controller.h" +#include "win/WinTypes.h" +#include "win/ftd2xx.h" + +/** + @author Micke Prag +*/ +namespace TelldusCore { + class PrivateTellStickDuoListener; + + class TellStickDuo : public Controller { + friend class PrivateTellStickDuoListener; + + public: + TellStickDuo(const std::string &serial); + + ~TellStickDuo(); + + virtual int firmwareVersion(); + virtual int send( const std::string &message ); + + bool connected() const; + + private: + + FT_HANDLE ftHandle; + bool open; + PrivateTellStickDuoListener *listener; + int fwVersion; + }; +} + +#endif From 146232e915c2c2a1fccf4b961651f684618a9447 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 13:13:00 +0000 Subject: [PATCH 0770/2215] Added class TellStickDuo to CMakeLists.txt --- telldus-core/driver/libtelldus-core/CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 80f472d0..73c54436 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -12,11 +12,18 @@ SET( telldus-core_SRCS Manager.cpp Settings.cpp telldus-core.cpp + TellStickDuo.cpp ) SET( telldus-core_HDRS telldus-core.h ) + +SET( telldus-core_MOC_HDRS + ) + +QT4_WRAP_CPP( telldus-core_MOC_SRCS ${telldus-core_MOC_HDRS} ) +QT4_AUTOMOC ( ${telldus-core_SRCS} ) IF (APPLE) SET( telldus-core_TARGET TelldusCore ) @@ -44,16 +51,17 @@ ENDIF (APPLE) ADD_LIBRARY(${telldus-core_TARGET} SHARED ${telldus-core_SRCS} ${telldus-core_HDRS} + ${telldus-core_MOC_SRCS} ) SET_PROPERTY(TARGET ${telldus-core_TARGET} PROPERTY PUBLIC_HEADER {$telldus-core_HDRS} ) +FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) IF (APPLE) FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) - FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) TARGET_LINK_LIBRARIES(${telldus-core_TARGET} ${COREFOUNDATION_LIBRARY} @@ -67,6 +75,7 @@ IF (APPLE) ELSE (APPLE) TARGET_LINK_LIBRARIES(${telldus-core_TARGET} ${QT_LIBRARIES} + ${FTD2XX_LIBRARY} confuse ) ENDIF (APPLE) From 8da9064e59e9afbb90ae6c5ca8fae01b35d56a3e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 13:24:10 +0000 Subject: [PATCH 0771/2215] Loaded a TellStick Duo in the Manager --- .../driver/libtelldus-core/Manager.cpp | 19 +++++++++++++++++++ telldus-core/driver/libtelldus-core/Manager.h | 14 ++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index f1bd1a2c..d6a0e1ce 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -18,6 +18,8 @@ #include "DeviceSartano.h" #include "DeviceIkea.h" +#include "TellStickDuo.h" + #include #include #include @@ -31,6 +33,8 @@ using namespace TelldusCore; Manager *Manager::instance = 0; Manager::Manager() { + Controller *controller = new TellStickDuo("TSQVB5HU"); + controllers[1] = controller; } Manager::~Manager() { @@ -38,6 +42,10 @@ Manager::~Manager() { for (DeviceMap::iterator it = devices.begin(); it != devices.end(); ++it) { delete( it->second ); } + // Clean up the controller-map + for (ControllerMap::iterator it = controllers.begin(); it != controllers.end(); ++it) { + delete( it->second ); + } } /** @@ -134,6 +142,17 @@ bool Manager::deviceLoaded(int deviceId) const { return true; } +void Manager::parseMessage( const std::string &message ) { + for(CallbackList::const_iterator it = callbacks.begin(); it != callbacks.end(); ++it) { + (*it).event(1, 1, message.c_str(), (*it).context); + } +} + +void Manager::registerDeviceEvent( deviceEvent eventFunction, void *context ) { + CallbackStruct callback = {eventFunction, context}; + callbacks.push_back(callback); +} + Manager *Manager::getInstance() { if (Manager::instance == 0) { Manager::instance = new Manager(); diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index c65b2c02..c852a27e 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -12,13 +12,22 @@ #ifndef MANAGER_H #define MANAGER_H +#include #include "Settings.h" #include namespace TelldusCore { class Device; + class Controller; + + struct CallbackStruct { + deviceEvent event; + void *context; + }; typedef std::map DeviceMap; + typedef std::map ControllerMap; + typedef std::list CallbackList; /** @author Micke Prag @@ -39,11 +48,16 @@ namespace TelldusCore { static Manager *getInstance(); static void close(); + void registerDeviceEvent( deviceEvent eventFunction, void *context ); + void parseMessage( const std::string &message ); + private: Manager(); Settings settings; DeviceMap devices; + ControllerMap controllers; + CallbackList callbacks; static Manager *instance; }; From 622c5a519afd92c66e7ec2aee1e37f87072b069d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 16:03:09 +0000 Subject: [PATCH 0772/2215] Added function Device::parameterMatches() and implemented it on DeviceNexa --- telldus-core/driver/libtelldus-core/Device.h | 1 + telldus-core/driver/libtelldus-core/DeviceGroup.cpp | 4 ++++ telldus-core/driver/libtelldus-core/DeviceGroup.h | 1 + telldus-core/driver/libtelldus-core/DeviceIkea.cpp | 4 ++++ telldus-core/driver/libtelldus-core/DeviceIkea.h | 1 + telldus-core/driver/libtelldus-core/DeviceNexa.cpp | 13 +++++++++++++ telldus-core/driver/libtelldus-core/DeviceNexa.h | 1 + .../driver/libtelldus-core/DeviceSartano.cpp | 4 ++++ telldus-core/driver/libtelldus-core/DeviceSartano.h | 1 + 9 files changed, 30 insertions(+) diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index fea04e0f..5217775d 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -18,6 +18,7 @@ namespace TelldusCore { virtual int dim(unsigned char level); virtual int methods(int methodsSupported) = 0; virtual std::string getProtocol() const = 0; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const = 0; int getModel() const; void setModel( int intModel ); diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp index 7d475a62..5e3a997b 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -117,6 +117,10 @@ int DeviceGroup::dim(unsigned char level){ return retVal; } +bool DeviceGroup::parameterMatches( const std::string &name, const std::string &value ) const { + return false; +} + /* * Has the device got the method? */ diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.h b/telldus-core/driver/libtelldus-core/DeviceGroup.h index b39aef92..11f08229 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.h +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.h @@ -19,6 +19,7 @@ namespace TelldusCore { virtual int dim(unsigned char level); virtual int methods(int methodsSupported); virtual std::string getProtocol() const; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const; public: ~DeviceGroup(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index 3abce7d0..c9ec6c6a 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -194,6 +194,10 @@ std::string DeviceIkea::getStringCode(unsigned char level){ } +bool DeviceIkea::parameterMatches( const std::string &name, const std::string &value ) const { + return false; +} + /* * Has the device got the method? */ diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index 898f371b..54de3521 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -13,6 +13,7 @@ namespace TelldusCore { virtual int dim(unsigned char level); virtual int methods(int methodsSupported); virtual std::string getProtocol() const; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const; public: ~DeviceIkea(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 16079cc8..46fcccd1 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -133,6 +133,19 @@ std::string DeviceNexa::getStringCode(int intToConvert){ } +bool DeviceNexa::parameterMatches( const std::string &name, const std::string &value ) const { + if (value.length() == 0) { + return false; + } + + if (name.compare("arctech_house") == 0) { + return intHouse == value[0] - 'A'; + } else if (name.compare("arctech_unit") == 0) { + return intCode == atoi(value.c_str()) - 1; + } + return true; +} + /* * Has the device got the method? */ diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 2fafbfff..48b37e53 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -13,6 +13,7 @@ namespace TelldusCore { virtual int bell(void); virtual int methods(int methodsSupported); virtual std::string getProtocol() const; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const; public: ~DeviceNexa(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index 1df64d56..580a49e3 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -60,6 +60,10 @@ int DeviceSartano::turnOff(void){ return TELLSTICK_ERROR_UNKNOWN; } +bool DeviceSartano::parameterMatches( const std::string &name, const std::string &value ) const { + return false; +} + /* * Has the device got the method? */ diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index c1e19f2e..5da531be 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -12,6 +12,7 @@ namespace TelldusCore { virtual int turnOff(void); virtual int methods(int methodsSupported); virtual std::string getProtocol() const; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const; ~DeviceSartano(void); From d692eff42da6699643eb791f744a15b5e39cfc10 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 16:13:03 +0000 Subject: [PATCH 0773/2215] Added static function Device::methodId() --- telldus-core/driver/libtelldus-core/Device.cpp | 16 ++++++++++++++++ telldus-core/driver/libtelldus-core/Device.h | 8 ++++++++ .../driver/libtelldus-core/DeviceGroup.cpp | 6 ------ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 377c9848..0e24795c 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -51,3 +51,19 @@ int Device::bell(void){ int Device::dim(unsigned char level){ return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } + +bool Device::methodId( const std::string &methodName ) { + if (methodName.compare("turnon") == 0) { + return TELLSTICK_TURNON; + } + if (methodName.compare("turnoff") == 0) { + return TELLSTICK_TURNOFF; + } + if (methodName.compare("bell") == 0) { + return TELLSTICK_BELL; + } + if (methodName.compare("dim") == 0) { + return TELLSTICK_DIM; + } + return 0; +} diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 5217775d..421a7395 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -6,6 +6,12 @@ namespace TelldusCore { + const int ALL_METHODS = + TELLSTICK_TURNON | + TELLSTICK_TURNOFF | + TELLSTICK_BELL | + TELLSTICK_DIM; + class Device { public: @@ -22,6 +28,8 @@ namespace TelldusCore { int getModel() const; void setModel( int intModel ); + static bool methodId( const std::string &methodName ); + #ifdef _LINUX void setDevice(const std::string &device); protected: diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp index 5e3a997b..f763fb6d 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -5,12 +5,6 @@ using namespace TelldusCore; -const int ALL_METHODS = - TELLSTICK_TURNON | - TELLSTICK_TURNOFF | - TELLSTICK_BELL | - TELLSTICK_DIM; - /* * Constructor */ From 41ff87e6672fe8fdd046a0b0d44c8bb38e26ae9e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 16:14:38 +0000 Subject: [PATCH 0774/2215] Added Controller.cpp to CMakeLists.txt --- telldus-core/driver/libtelldus-core/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/driver/libtelldus-core/CMakeLists.txt b/telldus-core/driver/libtelldus-core/CMakeLists.txt index 73c54436..71c70501 100644 --- a/telldus-core/driver/libtelldus-core/CMakeLists.txt +++ b/telldus-core/driver/libtelldus-core/CMakeLists.txt @@ -9,6 +9,7 @@ SET( telldus-core_SRCS DeviceNexa.cpp DeviceSartano.cpp DeviceWaveman.cpp + Controller.cpp Manager.cpp Settings.cpp telldus-core.cpp From 2c3d54f93295ce6c4fdbc3c9708d34e09a2b02e5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 16:15:34 +0000 Subject: [PATCH 0775/2215] Only parse messages which starts with '+R' --- telldus-core/driver/libtelldus-core/TellStickDuo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp index 74ca235e..bf76f837 100644 --- a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp +++ b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp @@ -155,9 +155,9 @@ void PrivateTellStickDuoListener::processData( const std::string &data ) { } else if (data[i] == 10) { // \n found if (message.substr(0,2).compare("+V") == 0) { parent->fwVersion = atoi(message.substr(2).c_str()); - } else { + } else if (message.substr(0,2).compare("+R") == 0) { Manager *manager = Manager::getInstance(); - manager->parseMessage(message); + manager->parseMessage(message.substr(2)); } message.clear(); } else { // Append the character From cbd8a68d1c4bb6b7ffd6daabb53d6620bb5580fb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 16:17:50 +0000 Subject: [PATCH 0776/2215] Added function Manager::registerRawDeviceEvent() and parsed the incomming message from TellStick Duo and evaluated it against the preconfigured devices --- .../driver/libtelldus-core/Manager.cpp | 76 +++++++++++++++++-- telldus-core/driver/libtelldus-core/Manager.h | 16 +++- 2 files changed, 86 insertions(+), 6 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index d6a0e1ce..a0796f97 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -32,7 +32,9 @@ using namespace TelldusCore; Manager *Manager::instance = 0; -Manager::Manager() { +Manager::Manager() + : lastCallbackId(0) +{ Controller *controller = new TellStickDuo("TSQVB5HU"); controllers[1] = controller; } @@ -110,6 +112,16 @@ Device *Manager::getDevice(int intDeviceId){ return dev; } +void Manager::loadAllDevices() { + int numberOfDevices = settings.getNumberOfDevices(); + for (int i = 0; i < numberOfDevices; ++i) { + int id = settings.getDeviceId(i); + if (!deviceLoaded(id)) { + getDevice(id); + } + } +} + bool Manager::setProtocol(int intDeviceId, const std::string &strProtocol) { bool retval = settings.setProtocol( intDeviceId, strProtocol ); @@ -143,14 +155,68 @@ bool Manager::deviceLoaded(int deviceId) const { } void Manager::parseMessage( const std::string &message ) { - for(CallbackList::const_iterator it = callbacks.begin(); it != callbacks.end(); ++it) { - (*it).event(1, 1, message.c_str(), (*it).context); + loadAllDevices(); //Make sure all devices is loaded before we iterator the list. + + std::map parameters; + std::string protocol; + int method = 0; + + size_t prevPos = 0; + size_t pos = message.find(";"); + while(pos != std::string::npos) { + std::string param = message.substr(prevPos, pos-prevPos); + prevPos = pos+1; + size_t delim = param.find(":"); + if (delim == std::string::npos) { + break; + } + if (param.substr(0, delim).compare("protocol") == 0) { + protocol = param.substr(delim+1, param.length()-delim); + } else if (param.substr(0, delim).compare("method") == 0) { + method = Device::methodId(param.substr(delim+1, param.length()-delim)); + } else { + parameters[param.substr(0, delim)] = param.substr(delim+1, param.length()-delim); + } + pos = message.find(";", pos+1); + } + for (DeviceMap::const_iterator it = devices.begin(); it != devices.end(); ++it) { + if (it->second->getProtocol().compare(protocol) != 0) { + continue; + } + if (! (it->second->methods(ALL_METHODS) & method)) { + continue; + } + bool found = true; + for (std::map::const_iterator p_it = parameters.begin(); p_it != parameters.end(); ++p_it) { + if (!it->second->parameterMatches(p_it->first, p_it->second)) { + found = false; + break; + } + } + if (found) { + for(CallbackList::const_iterator callback_it = callbacks.begin(); callback_it != callbacks.end(); ++callback_it) { + (*callback_it).event(it->first, 1, message.c_str(), (*callback_it).id, (*callback_it).context); + } + } + } + + for(RawCallbackList::const_iterator it = rawCallbacks.begin(); it != rawCallbacks.end(); ++it) { + (*it).event(message.c_str(), (*it).id, (*it).context); } } -void Manager::registerDeviceEvent( deviceEvent eventFunction, void *context ) { - CallbackStruct callback = {eventFunction, context}; +int Manager::registerDeviceEvent( deviceEvent eventFunction, void *context ) { + int id = ++lastCallbackId; + CallbackStruct callback = {eventFunction, id, context}; callbacks.push_back(callback); + return id; +} + +int Manager::registerRawDeviceEvent( rawDeviceEvent eventFunction, void *context ) { + int id = ++lastCallbackId; + RawCallbackStruct callback = {eventFunction, id, context}; + rawCallbacks.push_back(callback); + return id; } Manager *Manager::getInstance() { diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index c852a27e..898c0563 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -22,12 +22,19 @@ namespace TelldusCore { struct CallbackStruct { deviceEvent event; + int id; + void *context; + }; + struct RawCallbackStruct { + rawDeviceEvent event; + int id; void *context; }; typedef std::map DeviceMap; typedef std::map ControllerMap; typedef std::list CallbackList; + typedef std::list RawCallbackList; /** @author Micke Prag @@ -48,8 +55,12 @@ namespace TelldusCore { static Manager *getInstance(); static void close(); - void registerDeviceEvent( deviceEvent eventFunction, void *context ); + int registerDeviceEvent( deviceEvent eventFunction, void *context ); + int registerRawDeviceEvent( rawDeviceEvent eventFunction, void *context ); void parseMessage( const std::string &message ); + + protected: + void loadAllDevices(); private: Manager(); @@ -58,6 +69,9 @@ namespace TelldusCore { DeviceMap devices; ControllerMap controllers; CallbackList callbacks; + RawCallbackList rawCallbacks; + + int lastCallbackId; static Manager *instance; }; From 8fc5045c4badaeb5e80072c7d78e21e57b3f3803 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 16:20:13 +0000 Subject: [PATCH 0777/2215] Added functions tdInit(), tdRegisterDeviceEvent() and tdRegisterRawDeviceEvent() --- .../driver/libtelldus-core/telldus-core.cpp | 15 +++++++++++++++ .../driver/libtelldus-core/telldus-core.h | 6 ++++++ 2 files changed, 21 insertions(+) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index eba98954..2448631e 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -12,6 +12,7 @@ #include "Manager.h" #include "Device.h" #include "DeviceGroup.h" +#include "TellStickDuo.h" #include #include #include @@ -69,6 +70,20 @@ inline char *wrapStdString( const std::string &string); #define MAX_LOADSTRING 100 +void WINAPI tdInit(void) { + Manager::getInstance(); //Create the manager-object +} + +int WINAPI tdRegisterDeviceEvent( deviceEvent eventFunction, void *context ) { + Manager *manager = Manager::getInstance(); + return manager->registerDeviceEvent( eventFunction, context ); +} + +int WINAPI tdRegisterRawDeviceEvent( rawDeviceEvent eventFunction, void *context ) { + Manager *manager = Manager::getInstance(); + return manager->registerRawDeviceEvent( eventFunction, context ); +} + /** * Close the library and clean up the cache it uses. * This should be called when the library is not supposed to be used anymore diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index 06c80579..3e5afe49 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -21,9 +21,15 @@ #define TELLSTICK_API #endif +typedef void (WINAPI *deviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); +typedef void (WINAPI *rawDeviceEvent)(const char *data, int callbackId, void *context); + #ifdef __cplusplus extern "C" { #endif + TELLSTICK_API void WINAPI tdInit(void); + TELLSTICK_API int WINAPI tdRegisterDeviceEvent( deviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( rawDeviceEvent eventFunction, void *context ); TELLSTICK_API void WINAPI tdClose(void); TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); From b46c1e2d5cc55ad7352de51ceb2ce62bd6e9c83a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Feb 2009 19:38:47 +0000 Subject: [PATCH 0778/2215] Added first icon for TelldusCenter on Mac OS X --- telldus-gui/TelldusCenter/Info.plist | 2 +- telldus-gui/TelldusCenter/TelldusCenter.icns | Bin 0 -> 137201 bytes telldus-gui/TelldusCenter/TelldusCenter.pro | 10 ++++++---- 3 files changed, 7 insertions(+), 5 deletions(-) create mode 100644 telldus-gui/TelldusCenter/TelldusCenter.icns diff --git a/telldus-gui/TelldusCenter/Info.plist b/telldus-gui/TelldusCenter/Info.plist index 5fd55514..52642797 100644 --- a/telldus-gui/TelldusCenter/Info.plist +++ b/telldus-gui/TelldusCenter/Info.plist @@ -3,7 +3,7 @@ CFBundleIconFile - + TelldusCenter.icns CFBundlePackageType APPL CFBundleSignature diff --git a/telldus-gui/TelldusCenter/TelldusCenter.icns b/telldus-gui/TelldusCenter/TelldusCenter.icns new file mode 100644 index 0000000000000000000000000000000000000000..f87f36b07e37b9c43c44a9b0425e35fe32588a9b GIT binary patch literal 137201 zcmeFZ2UJtp_dg0Gp;=L+mn1OGj2#P|1k&gwy@7y=f*>GWK)6Xr0Ht>okY2>z#@?}u zDA@ZHr&(v5neU7<^7cs-QNO?UTmM<>t+(EKs9^57XMfJ#`|NVgzUL-paeT6tj_J#o zD){(19v!E3_bZ-%xwF)_M=HkRSIZfLEZxyh6%Cgv8H`B*E%l|v=={tOmv zft?Lzmpj!sW2kh>7xq(UQiEKqi6r|;X+uSJOCuwB^K9vUB;sdqU2NqtZLUw!3i|~C zM0CH*AS81o+l(fk;m9CPP8%v6&k~2PX`eScheTg6A$_Q1lC{Z1W3O#?Jaux$&>CG!m8q_UUgFRmAD)V%!}D%^FX;i{Vk}Y-p|?oTJ=8Fp;*Pm#QDoFy z+T4PnChzD)OCtH+G;bEm$F*dr+0EbECwO73n8sjwyA%yIvR1EJmB6J%E@Lo!;CiE{ zD1Z}HpkVQ%>F9ooLu|1s)+4+sP!P$0>*fWElhQZrwZOfMQclNHaRzyPj( z-rg*4ZzkQF>FZK5R6mRA?(TuP8+f?8Q|IIl9g9j-#p@(S?F4aO7yLzd{buM`Oo}W? zzH&@*^!A}nA3m4E;qqmIu_FJfp>9dq%H);NQV|xKyO6zZXcIeJ8n!55)pC(U8WvJF z)F~~@Q{^lbC8bFu=(%fhjUo`~IlK zjpC%}pt_;%5D_;hFyZ);lmbzDFkA;maEo82$L!>mEQ*uX3~dSy=jPv&`&7$gbH5CY zLJeV3p;#zhqLOAyc`!i8!q71ID;0%G5QFXBd@h%VaSeD}9^a>Os5do7wOS`9b$_z+ zidZczZT*=;|BU$a=AZw+UB|>Bzc!etGc@$3ZbO!};ftpAxw1bnWTY_B4(B^laJSprw(lS$Urmcd4-tfgi&(R4Y{*K4g>IEiCKGKjn=wTD zX^uXUh`^cFB(ehCM8m>OGjq&htht$~h0W*g;&4x*Em=;oe0$eu*3yKeQsiUh3))M!521UjFhXnUpkp=ZDVb1L!M5F zEZUg0z}$LGFEVA znVMTnOKFak)d!vfySAWTvOq_YJ*xXWBFvIFgo{Q1@ z`*vo$I}ff))pKhv zCs~lqCR>2U?M&jE$>zSwX*Q&(Z_UD9LDI3ax08`{iS{#XiJv)QBz=wE$|l>dB@u`= zBofgI8sD1OWcwnL7R)aCdD~WDtg+z5FkJBja+R$)HE zdVstC_3NRAAw2lPz?rJE`e!b@8v1AGD>u(7s=k+FIZ$kL@vUO%`?#-y&#f*#D%M)2 zzPB6lk``B{(o2WNU==bAz1_0VeJ4Ro47OZ1da)#!gEDsq4^Dv;&e5I+G3mJ5loN4*? zo>TDZJXO9*mKqsIrFi))&W`h;vt&%Gx3?X6b(O_MW$W5DcdUt^dD405EB$CJj5$qn zzsZ&9>E-3=#qgJ|YTQ=JrO*OXRssN%`S!kx4~rsqweX;_mbY}rQfUDxaZJXDyIwKa znoL=2pgWc7SGXhHlNOR5Nn;ID`+9WTJa_5FgR6}qcRDq5dlHo3_uiaW3S@kUPut)#)v%Rf2P%SWxVCKqox z)54qT;_9yay3T_Z(vn4`hb8*5+>u7%u8e8P@`$Mnr@G|b&vf@pY~gzPCWJEH-Nryo z?g_8{{&As~`^Jl0s!uJ@hsOK91Bd%QPE9Xv{95S33^=*L!!u!BfR|r_$QjLXvx_&P z_lUjwa6sbe>za8^;vQTVO=T=zu9;BH@RX=Ep%fOA;k~zt;w4kk=&yXy#rp$BrxbqCc_IFHL7ZH@h)O& z!Nj5;Xj5CEn~&OJvthW6j;t!W9@8ZQtoo#HwZBdPvjrQ{dGq7fRo~#g{_geA22CdT zYw)^x4veuaLA*!(JfXlZNXx^?w!TlQ?LNfZb~OO;rdI20SEW=mm_GhP%Pr|R0bA&Mu8 zP+*~A4DqBHI4qQph2*k1JicVr=AD^*QG{}}SR$2b?t?~z8RaDY14_PV zaelHebohQackA80t9QP+-WAP}a0?E~c*5BHC}HS3`Y>2Ai6l$1I`7^q;Yzth`&RPB z8M)A?9>0?vCY6XK5(^=Z6Se)PF0Mqdp*u_%u80>5caTdh!UQ24cEyiv9Py$pg*;Kb zEL8fATqd;)<)*KX=LeTRF5vQWw=5Ba=ByC$kaU2KAw{kJ{mswuqLA*vC_!io(67i2 zJIj zC44?D4X;|L6E5ynTmCmy-{QUj%a2p93-S6|=fO|@r$2uW9Ui?us-OSKJU}y}_VNF5 z|A|RK`y!ugE%@_po^^+YUjOmy^JkBq;-9^E^~c}EkR@L|JkqwV^idI^Y<>HQZ+gXJ`NUbgzONf2 zq*-MtYp?&HVRvu4Q#&TR(jSpwy>ollaHx; zcf9Y7kqoVgGv>^9a&dE~KmkVE(-Wf_Q9RsSo##8u_?&EGWod0gB#{pf6OMnm4#`0x z+e{4>L-v%5Wg?XrlZ+J!xdC)%*pymY*$@v7_aF1NKgrs6p{Q0oP9hBrmGT3qbEjHc zS`+uF`?Ui@1}`+YwsySruu>TZ%bl=LfxpKLTT3eWz zz{&=SC6W-zG#g9XUFyDVpsTTO`;x4jp?rab65zK~B9Vy=VUZCE_$YB=BBj_+Boa%* z!~qM)mNq*yW8p}i>4+QHY4<>l_Yz+u+R8M5hgsq zceAzrq;ETE3~V~BtjP2H#Oj`iji4C-+x{_Z7s(L1T3S!13Bx36OsUwz#+uyramOB# z0hwrRHI*U&L>Y`N3Jv(ulGr+;UoGOZlB7*0SCjO~Bpb`mynsO&C_y9@xk9m_`Qy$q z(ioyzC<`+)b2D?f8D_3$W^REj6*l)eBqFg8h6SWA7*eT7goz0ti0@}sp8#PbJ0i*4 z((a2{^PJr%G#Zo1Vlfyrs=M>N8J`m^O-)QKZDE#*NV?XRvx37!z!hE;%AaM~^f5~q zNsnmmks;4tQ&dzup{P)mo4S-ook=t`v9KjW8Hiv-q)H?}PY_8YE|$c`4*+0_FcQJi zp{%x|0xMUPX_uGF%dqkZ6_wSsb=AeW%K{v%P0Ve{g(O`v(Q+0WsfPfnq*&WF3q@=XGs#DWM21S=8^EELT}7|Yg{L|i|NFm41w zZE=~bw6Fv#RhEq_Eh#Chs;yito?~We1H~(Xt)&AG@c}HRaFK8 z)L^w*byzJ{XINWXQ(akJR$5Y8swguo1-QW@dj|*8 z#F7`Oa?<0MMMwo)4jVQZ5zAJtlCQ0(sjI1keMPCf%m6TJYH|Z?O>OgmBO5D9s2o8C zlWpE}NO-PR6Gk#163vJ+rrKDVndX~JG&Q#(Pj_UA6R?t++R8Enr&n51RV(whGAkhA ziI&b%2#t7QXdua^ZdhExi<+rmy)u$Mkz@lgz?MWRAWtF^Z7j`AP0Va(`z*mKYO4TE zhM23WUFB*5>QaHc4kED-6A=Vbf2hyZj08lJmmhe6QZLiv!b>Fq3D*D zR98iiOo1h<83HwgFx1D|mRS8UL?e(J0=2bcgsQf>6lnEIOY3AVQ*6k2P#_{%PUFLt z07*o*`hdE6Dwtyn!~(Ldxyfff8C5lE;*zRLskJ$os08M}LI;>b& zMb?x7BEF{NCt&>H)<4&Kw(0}#PzEZ(d zBNL)s0Z43P;#*mPG+0ud`ZmrZW_k0E{cHjW7W%+1dsO zc^F?u%&__Z_cO3}CCP$FGI3MY7OYwk0eLhmVtGbU)2=i9SNqQP_R7!b^`7oOlWA)V zECaCFG$jC+5Q=L8ryxCOTYo9%<9I>`tD+G~s6@ajsP&S}CQX@)8ObJLMq?+NkzM(# zJ5OD`eC8DJtlxWPU^9K94T>{}V}~_m#j+AynUfiW2Arj<2pGl*f=RY(KL&=dN+jEn z$oY2TA+4KDGO}=7)_8W{0z%b0)ptJG!psgpClJXd&ZVWrB_+k>a(gRe0fs~yUlEVb z=ZPtnpTMpqX%j&kT95_DfsNam8JSWt_YRytbs7UDoEd1H2ai1RkWf=9&JcRfTuGV);*JG-&M959 zcI}#qI5QL$tY!+h03rymwFSd}w`kO0v_WXHn_`o3{^BX@4E}WQVC)1HL^w0YV%b{! znhK@~Or3!hO~B!DIYLLPPv|?qFRdpqck~0f?&;nuQ4^63jfaWiRu%#a#d3S_E;&iZ zW-3R<#q)yfY*C*2kcln`;giXg11GW5y1l3SBok5O8AG(SOe!s0v!(dFu38)+9TCz>&@8u9X++taX6MgR>ZDAK@kfkqE5mY)DLK-ibt z<&$vZ5-y*>PU4SWXt%b8`Luy2Mfn8<`6U!Hc$kJGk^*=b2geN}LvZ*=hI*0?*}@1L zuVZWro{2L`zIY5ffjiQtoCG*zQ))57DN3@mMKdyw&*pI0d}pf>Fq#Ck4)JY1emXyH z#S*&dWIO0UG|Ihn1UrsDdQoI#mj|jehiBjU`Kn@14O2vaE@CQ>1kl4wy+a#Eo;Jz{^ zFqlcy!T&t@9(zpq;nmNnlVH%XWD9clsY6GP9y(KF3MM?pG@>|9rBbe?s3!tPB>HnO zHjd+mobw|NYXQ(?{@s_~{viKR_wkQ^VH1!Aj5w3`@t=D?vt2aoKY zVF5D3j4WKMP%85Z9FYnPZAk$f1jw{j=cRYnsb0IFb=YM8XOHuL#6A9Pi;)VVmT__K z{(}ei^%hLdgK4*%Ez83x)+{nb8N-Daf@J;D8g_HTvT7DV0Ax45{I_rOzb8EY;p+t` zu8t*}&)9i*|A7Phk28&7a&e}M)+n$%oP4?^u%%=BSulWw@F-R&TYk(Hamwyz-xPd@ z|MusA$v``nXlEoov3K9Tua4GR+MSMQpxYAy;OQtU+Y!>1-?nAIzO^1uLat z#x!6cC2>m6<2wcS@OQoooD5hvvZ?b|*k1ge18s=f(9EkqCYQ?!JWY}6i8f4ja7Zx6 z+Xe#tr&xC5^B!N%zeTut`^p?M@T_q}vQhf6oqP7|JQit${M^8Xn3gA#%kr0+BPr)1 zDGk}v;PEl+qu=hZ)r)(i{z;q%1NqnRS0A(*6Z1i1B#Y@=_U_ufYhMcyIK!E+3vw|T z4x53rZ)8gjV26YRb3Lp+!Kx+UZOpgc?o(bN^!Hz97{h95jNPPVhqv$Awc~KuB*-AJ z&YXb(R&IVEWc-O%?%d#z5Ox3=HUl5BRSU{DruO%rSM=##Jby1^0-3mmWN2mIzGuhI z9eW#Wt&xt*qm;Q=ZeD^l%qxy;J&lb88wPRaSfX0NNEyMMKtCbp2G7aP5YG19EHJSt z0%M=F_~6#<+qWKIBWJ*w(p0$^hLg`lo-mPU!(s;q2eG}ZM{uUzey=CtCe7b)UN(U5 z|7wY`bqR1awSC9dZCm!1m?AHoyP02D=c8552=CU^ zqYl7+X-eR}Et__=ehE<+sX8YsD>s>BTQb5&)ZhnUTV0Q2{%FDomziz>Z?X z!cv2Ih@@w0{KY&QQzB$TeaO%Bn8lu!BUka7O4K2cgKPzb1r-S+63i?u%!#1z_nxV) zb{#>bnKh6S$wcCaU6cl)9~Nz&G(JWUGg?u36H0cloz*m;8XjtZ)!EwybxmwU1F8rT zG!;g5kC~q|j3{<$dVJC_qIjzAG3(QY_jOlIj}g_`kqz&Q!fz|QBN{#_3acA_ZJnVJ z&W=2P2h^tVzwdJ<+C2ta{EWyt4b^MhUpJ$yzJszi9MiB(fAsg7A>51oJp1pg2{yzp zBTxOhb_oCXlXF!`-z?Kz8lASG|M@>fL%4tbc>2w^_wf(Dd;Z6p(jl!kkN?qnqbaz{ z-qqcQP~rWzm(QL&`WgS^*)P9C;a&gDuMbXb?`W)VxL>c^u(5Od>92n)8q$4rwPFz` z(D#v#u5Una#JZbMc_+MnSn2QWjjILT*nXKbT%C~Upju>;Sr&mA_hbMqKGE}GK zVaDqEw2;pY_Gi&NDHKm2WU&sZ33mXWhR@Z6Os1E2tSVJIB~_84NS&CLnv#?d6Cns> zP$^VIfg$d94^xeKOU0l@txBm)HA+j*NKZ?Q4r8;Z6i+zwz+&xT;#l16Fo3}`wIY~w zM&kNZEM;tJT1G~C(lUv^r-vs4orKs4Jvpf7n72I{UMtd*6)6R&@|1j_7z5y`aZ+C@ zg~oi}d90>0i%At^q^HX=aOrSrL7s|BOG8&WX=y;IOdXq&k_yz(T)KxBleHa2VsC?y zrabEigvo(_)R3rUix!Fn+~A-9f0^GT|A1f)UlJa*JRt>6jHQDfQu0#u5lBL)H^ozf z@Diq1gMcw{3@X)APSK`PF;C1(OY`J|LiMEk1dA8NCL_J1fJT9lw2b5kUtj~2vk8g3 zO%2nD7?Hs#5{CLWiz#E_P!|PrB7^2hrBJ-QgQd%ofR|K&F-T6$NQv~JczuAO7G?v} z2w4){iwehp*x~VM88EOsRWBtqBRSlgLLV_^2ePRRXhvnsaqy8wq0oaO63`IxR9!?M z^7QO}&!f73J97++NvBfioMovQsG|XNjPa+yF(g*oM}51PhAbwHLiLMC1}+d2=_yiA z&rdt{Fb!A?PY+gT57kULMSa$jOp$#)L{#kn<9N7Y0I45;)Y;G=Vku{HNYHsc5?rJVgV!Jzf&B}G+>ABJnw2eMo12?jI=b7+6a1Z>y$YEGnn!SA2EgD` zRxS1Ps(*(;c-DrPz?cReAsrnpZS5UhUGi?NE?GCBtE;2E6?js#7^<C0)J!x9pnwrTuQkM2VCrFpnIE1f1gIyyNyyCLUF zR8%%~b+xx3H2vo0j;^W*S646HS~IEI&pvlE3KU((v$h9GpCn>#zws4fMdwt$r>$ruuG36)+utTPQjEpi71b1aML z1$GmXTG!R7CU0u)uHr86$_H}4#8eG=1chERO#ZAj01|OCP=c$wInpB5c62tuz=Wob z_9Qnq6_dcA`Xr<#$&z)_B_8kTp1!41M;|>;XID`{XGfE)MX$M~yDZ3&jwGh~CL%53 zlF~So>fsSJl-*326BlV|cPk90*VNIn)Cts-$HYMR&C_%}xB>c+c6%4P+k4V69;dnmSn4FGhfG5K`rG%;L<;aqEwKice z=}p~*p6=j63MS5jld=*^(p{Mf>SeOZK0-n!<}}vZSvi>(G!F>!O7?p#>gr*&D;ZwQzJw+1^S<~TA`%n3m06j0Z( zvALJBF(D;_!YKX#90dRi z24exYx~;Y#H#u=dY(i32!TK$SFW|P`02|lb!f{c8)eBP+uteO-SQ>4FKGe_!u$%$LSw`^k4MaPa zd2<{CS8cj-XP^(EUb=o&;phym10YVErY3A7zOl91iwZ7Gr$!}XiTH$M35BtCgdPyT zb+9rrq`5fE=M^5iGk_i{5&HUXZ}XpvA`R0qtgR7%8ai^E=-`qpPwzx|f=;53=Li@z zZyNwcpXNNvbM?vF{qRUi@6ye45wpR=!2}u11#uk>SR!5R>ITi@WRgf10UIxK5&)PR-o zSOR|KGA}ygJN&Fy}m`A%n7T<%;_ttR>te0=lX$Wu!Mbc=?6R>zZ8Xv?P9$rnq38u?) zR`$S!3l}e*??3J9gs2UjRy42Muwi`@<_sz|pm0~ltymGaQb@`Fh`IrisFt^iiKkD` zxqcqIfIl~|&6xrR|Ghkl8`iB~ziy+*MKhD}*a|{?3{n7Gzf*uZsWmY5+~&@lF>8Sr z*fyR%TRw0WJ5M-st#S?>vEm|btOKA%m5avfDeS~JG#yA8A49EUPGB(IX3&>rW+e;e z&SQY>$(eZCtm1()*g5=}!B__%F=ROBHrB0MSJxE|~5G;Q_qbbMD3~r?Ip63n#o?08+;-cs*8!uWeAd!ip5-b}DcQ zDof;mGCqW?MTuc9=ho{NKVv`XKKbKW-YhSWbF91j&WpWg&h%bxnNNf3F;1zCwRLs1 z^+H!B2!Who1r|qG5#^;8>O;&rCc(+?(QiLKkw4Y_>FGbkGZ5$d9E3-slbo zo_|;HJ^t~N@cCecV^|Kc=Z_vge)LSI6C|=RZo#!x)zwuSmOH7JE);2eEEcB|!=R0T zQZH4j!JcUIkN^C2!MFIYpTx`s*BC>a+jtgXosXM~lty>ST~}3IRlAnzr4G4%Fs;BB zm#U5wn*FV2k%_?Q4!eH1U+@rr|1mI@&(wAfmL0_(Il0x10#Ga$$-2s_s>*d@S7g@I zMJr zD(f;`U@~yjkoZ_x94P+-BuGz)C+~TSA6?JCiNF4Jj|1#^4BZ)fjvhLE==f$gl#QIC z*HvJZxC&6bf@wgbFIy1@Oi3v3kzgOBMuJ)PoWJ|tRpmAO;NUIc{IyI&hxFe4hYlU+ zjYq1|@$dm8eEGU1&fsGcDdPC$v9WQ{bQ)O4TjSDfsj6XV#9}Vs4qUsexT@QK`Jr+q zgRzEbNTF;ya^T>Bqg}3GM1~BPRkh_6<<$yz8lZXk#RA&$6+u*3xO{*H&cv7#dGSV{ z{37A%?Ft7fB-ODjhtv~a?ce{^i6!&Z?&vD1EypT!ssi2RXeq_;Tokt)&=ykB2Jvl? zLcL!^XmkhP)=RQ$gsX>==TI0$U|t@c+YWxU@2ey0=hHw*o?dGz%gf7ZV<6v5WKlUQ zketitXx}{y1sYq&9Lr!jIk3}9O0Y=RIi4jjiA;x8$I-K;gB+kWa7wBzD=(`8384_e zqA_AX!nmch5j?4j9`!IUPP1pvngt70Mj6x4jk$B*S6}Tpn(qLXZF6`d-m))wA2w^7aGHGPOL61E3L|Lqr+?y=u|H+Dt&~}sLLq_ zz<=hiKd^Jpj>9nv;58zgs{rweTMNrz$U;a^D7p;~rKUN^)L#&JbkFXCTj&(fktYpK zP!yM|JZbM&x6j^o)T2AC+_IxZuz=?8>I{AYOAwly zG&@7=MjzP?nKz6Izp3u1as^5O6QQ}fxw_Fo-|yK&9gjfy5_ahjZy8YS{P12MEW18# z`(E7#%5eluEe~C*%X4q9)kR))W$@DmO?7odj}Z-ARM#YEDwOIT|E6K*hh^Uns;mf< z$$eWG4))emn};jK?~2RbZ%fC+^=NNR`T6BmHYf`)ynVz6;GqEix1&-f>s#=A2Furb z*?Cm;{_AEgjrko**W1_6yZ9j#>~)_VP4uDD=nrXnba;b3Wc9gUP}TnDi!BA;Vgy-H z_Z3vM$G`dg=dbU7a}WREo2P%gDTAv0cmK6&|K{)CUp)Ew5u}}Gzx?qJs@lK0cciDS zVZ#Qf+HYuV>pAuiPR#4Qx>Oz?wP@kOM`47Bh~-s-sA~WB{ffx&g;?k#sV4d3wX z8_@M1#}XsLLmx}=q0+ST@W288%jTuwp+87*VavZlMf>NSOBRMozK82&J3y~^xDHd_ zUbbDW=8na1e0lgb)K-VD)%XAR>qT$~8|XuqZbNv_+81f?{`c#xYV&JH^fD<<3`KKH zqK$s3;0KfHz`I?&2={}2N^v0^SJzVCi9&ZKXhxL6A#NcLj>2#hY&kro*XFP>jvklK z7mDDJ`w0+V-FxD2Zyql+EIcAIa_yptk&zMM3qwWdt$tLz7fTMm>u&hAy98cvtC3HZ zVc8jp%ff|R4j1}K;3&FSvIqJu*#eA=dDf0pCl&M3^5r#(NqKonl`1bcW5psdm&1cY zz?!~MsILLwg4j}_Fn7HIlaEzEU!^QPHjKySi9ict$qtZQ-PQ0}o4Turzgn3mFHp$k z`HBg0IikqRij{IXh!fO%$z}kC-iy(pcriCxg()$Wwo-}Z$rU*GNF$dgWy(NUKv5{h z0g_6#GL(%##FFlJQV^cDBPlQ`0kj53`!T5&{Ak0;f2oNCj{d`WeF2&+zBn>29Ro!m zFhjXQB~Oy5u|^=N^|3)J6OR+YDPpd8aU#49oF@kr7$AZK2}dZAbiE&0t?doc$;cjI zhQ(kOY(ZpVj#3G7EA$Xe43{f@Pw}i3%}<+jENC4pL$D+*PldYbf`(Qtc09gE3sT2=-_?Nr)o}=Qf;xg33V6oIN~_eT?SmpRT)yY@W1qy z!DuQm(i{9Om+DExe2yqV4rfJxNGXru@FXq6%sf@IE|ZQCOOW-4z~lMAKzRTbXc!b6 z^47+YQ;NYQfdk-JvN8{Jhbai4hg1;=zIsfY(=m$2_S%Xo<^P0W8Wu{dsxOY@xXE9ed-4@z@Ku?ApG) zeA~qBJ9q8gv8iEAQfQ!GumJeV12JJhAtyXrg~ZeaMaOXj@0lV12sk+=#RXuyyDNIM zHp_d)Z`rpGRO}kkbtgqMO=QuTP{>dTo8G~J1)j)0AP>+Y}Y2B#x}`%v^Q;% z_b4}GJ!7`)*uAYjJJc_LFOewG>-u*<6Q8yqP5_7?AW2) zWw0BLyX@MzW5>45vL40eaXp(hZ{O8Z9v9?~OiO|A#9U#j67cX~L3}( zlPNR#!22-l#3#)fHpL=gAY04}4v_oF{4u|YzA$mZi1^iI8+&%`+P=95Pz`!|w(n|+ z4-684f#8MgWqAsjoFG#IqvByey(e$wmWlNR$i%>AByy=tVgxaP6CB{@A1qDG-?()r zV9Gb^_kaf0E%D)jHYbS1>_v(^MIOMaGI#<>?K{~C8q7R+MYa_A8zvbCrWxQD5}Cbz z>#l7*Ju<}Gj_r9NfiPO0lpy9Tl;z1V#9RtTAg=ics8$Ukoq%RX%n$Ypj8L@g+<{<# zpWRK1eL+JCNaA8ns2T<@Q>|nR-=k=zqDiVH!NdlFU|()R?T(#@TyN91ZCDVzw}p7% zN--szCnJD~vc=-6k9cT82^1vJ7xVo6msRcDhR9*`4GaB*F!*?hm>VinB4sF4QJhc6 zJEaC-e1ZPU*YDn{9(enf6ko7EImBc!Ck!%xLMMzXsr+cvdf>SLLWZs|ATYgar+Un- zy9xr>XpV3a2`54hu_G^6$d^>SCvA=dOI`~MOT-Fzc}EZ4F@xMHl@ub6=KBguc5Us! z&=l;h;e?1GO32^^XLghlJXBAvO5-9MDE$adg#_UHL4DVgN|jLzsPG7qn z7rUo(_ugIky|H)i-WoWyr7Sj>#$szyUmo(_;DEfHn>Em_!XTv6abf{46S6wE^lE`% z1j|3Gm8z8DC5&~C2MPwY24sWduiv`+;MUpp)LnZ^)!DZy0(f9o*e7 z3N*ZV^OnuK)(3N-75E3!S%myXSC+S!1AbfdDXy5&{iuJ~ zRz-5qE-VK8LfdxsU|V#1c9;2qK_YHNVs?BU9LOWcb3_8M_)}CBzU(+8PxOVSOcQ}nB0~>%Bk^)36I{=^1vs>XS1o(--wve|}xaiO46iar4HCg4LO;(lb}9Dq41(yng@T-RlDb@@obIgAcD& z`ueD22Q1x#gl#awW*8yaS0t88b;LZWLWWl?;z~wfKWRdmR!OZSqCnW!!DCA}%EDyO zX*6a)cuMvDs}Js8Ljo9He|R{`i}zObh}*!h?(LhmY}veJ>!LtpBj77BNIf`tHeWD8 zIqCuO!5efyD2R_>yW9X4-CL^IdHvz7fkD|dgR6IL7P0)n8~_IH`!CwO70$=?Y-@p) zl-gy4+%yF`aF_=k^Ik6+-t$oaLtZb1@T>!|P!8#pAIM-tR-S%%a{y`?gV!JK6)`a} zEbTN_=eI(wnN7Qj{DdOd6-Yoec^F>G1H&qKuXZ)(8>C~=8eHJ-8I*tS!F9mH58S^T z=Y@&1U?c)eN!HG8tcTFOW2GOmlL-(xI5CLZTzN7_B!(~E7@o(CNY@*{o5U#ah(l<> z<=5^2qW<8mTQV=S#Fn9uDezmnqkGe)?w(E|`z^-;UWOdQbaQ2qpb<&_Fr-EW%~JTv z4oQe-#DRx{1K2hFfou1RXaWc~zz&!#m)*Dp@Vd5_fIq4u5H}pl!E*7k46bm5z#6b7 zh(E}|#J)adH*W)+(cs`Cl_#8yP$wENtjHeuCY^0@0T_Ud6LS*fIk|BBaw!L>R3CBH zF4YrDxSq>S+#ir#*SmIK?uAxgGNdKHjBRkBp{u7ECK+*x6Z6G6vRnd|3EvSS`V>eX zxx2T2_oG1!kgna!plOgmUjda{I^j&gHklu&5UuB724rxUlOSKlflkWzOsT_F2ZRo> zNE*zjeuy52!lTh>rrLrb^o4cFJMrCNA!rvcRxA)?=7Mlo76iQ!9H~(@sFRRBnoBM< z|L!&HI{w2d1F3YJm>0BeQ+r28d(W~!q(Zzz$j``?<={bIV$sKd z>rrA71v5M;o<2M|Qi@pURdV+#Hc05d-{>WTfG|!X35ZrBZmRG{hJmv6Vk~?0>g?R5 zNNOP%ZJVM4 z0To_3`0#}??*&Jgbtv+&f;+$Y{jb0NeA&CmgO6g>SP7Tjef#p&t5*ik z3j!4&t0XwQ18W=K+Ep1KP#dC}S8O#d8(RYUgtV{Oni4cC!CJ@zB1ZV#e|~+AJ=1;u z=ZhjLPYg zCH}&1{&@0S{zCWZi=k?Y2w=uaBtGGNmoN48UA&o1M;3q+hlpFSR^67)(g2|bSImvd z!LkUMIgt=XN8qYgn$nF+=y3b$yw$vN-87C3ba;{&1hh>+0Vf}yx68Xux znp<02+9QJ1+7}D>8LP1@-0GEF(TE9q3rdhky<>iTmj8nA1@sk9m2L+iR z?#YYi&YwTmAMGOn#z3)tiVpPydoi*l6rly8Oe`Cpl@rJPM6ETj68Ad!`;&ra_@}?b zdWR~&6~-{qubw$~?(F4l-aH_HxeIRvz^2Z02(-un#GJU*nIL+G09o&c1^|Ep`q>xX z7yO9-;bjUFzT;?|M8N3iJAL-->Hc(ZceEcB`mb$kYHn(+4dElZ<%MOfg0)umVu-Q8 z?>mE1s}eCtJMdKVvIH=wf_0>SsO+>!@A%}`c~d|i10o?kG}umb>&Un8#nJR_7+3hf$9TYe&N`O6UQ#BVgMvq z4o6&%H4y4sk^)drf;AZ@W;F<%mBxql@(4^=Ygfb4N+R}Nc^yw&S&TwqM|2CQDEF)ReqHq?7~NmXLO7hOu9cy^JjlLII$kXD_YBLeuFjA1rSU|tegyBP%TFIXeE86@2!CXe zhGPF5c$&VUu{cNo-@F74gRL^m$V}ynK0z}CP4fNV{HQ03jlqI^OfYxf;X{WGoGJsK zMiUdXc;k9(1HL{~y(yX?=Eme?X02Yr1w;LSv3i&kRLVmJT!xI0UUCxNOgg-W19}=O z;fGX$gzKA={ZX9Lhw5ika`IxX=)FB_j$#19;@bi$B!F*vO zs5JGh1CZl<;!Ymie{3fdWYKhRt2eBxt1o8@&=Lv68sRAKNd&NB+uIf82l-%(SQNMt z4q!CJ294Z)XqZCqBEC0A;^!}dzJ?N!ASk9l5gjBPu>pFjuKXQPZx6)W5I(BI!55>! z7D5Q$zZoPHzu$&wx*h~YDNvPB0n1f9syjjf?VUC>h0Q*+A{B|>Z(ZLt%g}Z4vMcHj=~jJTbKUmQ^>9gDUBVtwV*fw94qLkQgA#q% zMPK^h*B+>5@n z=k=f*?Do4*LU?3E$^C!ewTI{XQ=!L0w7U-rUm`oHdG+CR|NrN2Vg28u=)dnV8h=OQ?`ZrTjlZMucQpR~`z-SBDM$0q zX#N?^Kco3)H2;j|pMRf4{ypVr{u#|bqxokv|BU9J(fsr8v&g@v9L+zY`DZl$jOL%w z{4<(={(Tnt_mrdgXEgte=AY60Gn#)!^UuG}BLALpH2;j|pV9m?ntw*~&uISn_gUoM zQ;z1J(fl)-e@64qX#N?^KmR_9{CmpL{4<(=M)S{T{u#|bqxt9GXOVwTIhub)^Uwe5 z`6p)a9A_=9=x175T4R@o5Q*aq^9|v%@zRu4iOUn`65+Gf+y8^%|7f^0iHTm4q@|?| zAK?eDr-wdiO<0@|m!$rrH4!e!iVd|b=eq9g2%us8Iva#Q2k!|t!1j}Mo;%$j`nyOcYz zhLH)&IwsF@lIDB-^P^x%i`Un&KctxOJ@K*CSAYMHLvnyWzxw#EohDg+Z*Co{?#;|# zFq0nHPorLawEqyNrKEm$#CDu--?Q5-yMp&+O*#3~tSOfpLddHxJ(#%g%GKNJ4KXiC zpHGnTEW7{N<7>O44aOhm6xlWpc}b--)dT(f%g4%0Z~W;p^XVJ+(9QNl<(D^qH;#Ly z^>T=yb7;cdWXB0_D(GB~d1oFb*vh`8;>v&N#(BYcXXdM7zYKBUPUxn+MeqyD0B2Xt6J{wp1uFhQ+I=Xyn$z}CBK}$ z6vS-Q%>#o2t4$?@_U+f`S%{*ObOq) zbzdNB!rwiGFODcI{-}s|n*I8TphCB{y{7)h47-Pm{O;`e{f#T`f^TVM>D~n)Kde}b z?M|rhPOD#kW^?2uV;IfrHxtjl3b6&t6P852Vb}z=c83WCFRUMJ)~(HU3B2nXwDLRV zxN1CijN=Nw4cQNF741FshjpXV@9C~upBtakIXt~HyxiC8Tax^0H`npx!+pQ}R61^- z@4_$LUXqqCWx7T+nKe+x-LRHFaGicDy>Lxes!qthDi?G14dXc=1?XKgSI zQQ%01XXc%G#Pfb6q`zqOTo|~U5@ma!M z;kVIq>(|XMS@K21s!a!rC!hVI+(z5J?P#p$BgI_3FP0Sb+f4LW`a~WVa?NaT(%x%P zNvDoUsx8B$i^ROW`$hE(ZJmt|-E!Kp*5|i#WSg1tpp2*e9$7PU&ulK0&$%?P>3dR> zXX*1TlTwJQrwR^SocOTe@rioNu?4gIn~v`qW7W6a5qo6N{Nf}v<;ulZ2XLZG#ZN_B z+?%3t^V)Fh2la4A_N^KC>YlfD-02?{q)4hmwar9Cnhr- zR}e2W&mZfXRCV{tk3TYWme*wp`z?HSB$@IbD-C8?CEdpMQrd$)8=86`y6XAB#sD4R zoAe#eFDCtTs(tKz!=(+T1G`!BXWO1F4eJj2PoUSH8{__Vc&In$Jl`eg`^6?9FLAG) zJP`k*dx}7~y|;Gz*{mcL%R-I7aF^vEv+mV8-H0{&(iokNG^S`qKJSu|XH~CiZ;0 zAlmIj+>5*0HqNp7tgw<(u<(TSj_LRKc|mV}_-^a0@JCL6{r#Hh(Y$@jq`rgeTz~q} zBlpbfrs1m;98VllEs>&)FLfPrvcE9=vzdvZ=}FwqVQ#otO|ATd3RKRDX7x+f9|ja%^r1%k;^kxx0&kp9L`w z$R->*H_q2L`HS8qpW$u?FVhQmjL7)qv2p&c*U|d5abEI`|E%PePROr*_GREso5LLY zjkTZo9{o+&g?B8BQYQHh-GO<4PAa0?4-}r&CyXNe}$4z|DMG8qY$HmS4GNw$G z^XNaxFC9GN#`#b2WPmsIac@g(owm|qTUHF}}iXa4g3A7kvwZrwfZ^y~P~q|YBSY>uT! z`A4nm*Tt#6wVp=bX{NWQu{di<*oxbePS=bjdi zQ{4FJ+;k)R0rp*$|CafM53+6k$?ATUd|^gBDd)ForY*r)T`IlBjt23LvuA(jN=W)* zXVDAU!`F|b1`7ku(;XAB*rZ1Vc@Hx=uN3E6&(j;WMBbR@d2rL2hYScg?r%6%s)t^H)s`n&(c8T9{jB(r9l zBx&lJ6HdEMz3h*xj{EzEo}*<)=3ILC&35In#2E%RRUxx-*x&!Mv{|p6{^xztU-E04 zRjU?$ftwXId4KT3rDltMo~lP!Qe112Y}2P-H%XPAdt``y)6{JucHqZn|FGxZ z-jv_^Y+uP@5+z~j#E@B~Ym(2bFF93_`(j3Di194ZjC;{fDoh+^zFL%(m%90{ig}MG z7so0X_4}`X?%>T8-=*IA*5t3P?bnlM%~^bwU4-um|2b#lt9iJm`XXhWmG^h2XZ~k? z<6WY%0{4wc-u#X;ck&JnexrY6{5fO)%*ai9vC^_8JO8*%sxez`ZLR2a-6xrI>tSu_ z+^?oS&9QuR_MXnEH~U>%I(Hmi=K4lx6_HIaR@C|*c*1u6r9ykI-@?4QfabV6Ate<@ zmb;8y?l>m5jNGkSU1sssNs{?e+ABuP)k7sRkMDaQ`}LRHcX+yX)1gQHaZgpo z<+PWSiN8NKojZWP@k@4$h1WM*OoJ+ z%CG#)M5oOsIM(o%+;#DBsW!zKggx(2_$2gQSrKqtb~mG+`U_WBNp+hRe6Wi@E=`4dHvfOweg4KVoy#({$(lH4}9$xp$78I(_ciGq1$0jj9N;G<0ZD z>&xUTN5_}m4m!JhaHb>g%X_-dqovKi%(`Rxdl{D#X>#Bzi+tV}Tm9qOHYIQ0{kr1$ z4OcT7_4YvL)oq94&z(5CWX3c4(gdzWPhF|>;z~b$O`%!b(f-UgF*1WS^XJYmPMv=E zRAtSsAJT27-)UK;^24-nWRKu6bv;%!N#8sE;g-d^YYai_ftF>#wr$(CZQHiZ-L`Gpwr$(CZFj$O?%bIdvm&ZK z>boLxWmZO{6c$Np(iG$+LI5i9Fe0B$t)9W!nK=udd@@dV^iIFB6NfvSW)#y=7kCQ z&$Mkr%j^gzv3I1CoF>2gQypGcm!mKcJPT{@XCxu2mRd)RkKI;Uh0^VN~vB`uAm<~ag zr3I9WQ23IX5a6_j0%0?$A(D1V2v`PUv%VyMl0`p^=z%KOvVKWeyx^tu{+*E%ezg(( z+K++8uys*^N|XV(cTYbRH3HUgqRo0G?%>tuGIdFjUfv@3vV~oHWbfV4#JbyQg^Dd< za-#pGq`_5b%6|1lf^XxH!@ZD4XB)AXkkgyFPB{X7)8Q`8KULFaNM`d^n3be@iWui9bqf=w73SJNbb}F2BT6iY zesP+96-Vo6sJUF-aJVfJBTx9-rmp%FoE>5CVc{1>E)uPfZ%qtd<%toHWBG_Y9hCT0 zxmWslF9q04HDcqpeWfbQudG;{3tGshoLZ zdxt54vBA*66o9cvwXm?k=g|tkx9f|{-PTRsX1tlaB7P-4T;%u(%{#dM}=0Q!Hv=dh?0gRd8x@r{roqA5ElVzi$~FT zNPAuKU%VvErv2FFOJu>vP{!Ti^oTb8cXTfO8^v&PYJ4>*S=lYR1el3MrqO2IGrrir z@5%trB7020C6Bhps~>w$RwlUZ!~XM(H(a!nDhUtLA#~DD z88opVQ9I7gH`S_ZL@rX(^$kbo&&R|Ry$?ZEgl@M#lfZ2ik=87eF`Q9w^lbefpRmAZ z=gHu6?fw5n-(J`r08Qps15o2`5*P@1$qhR-pxUW@CM{?mgSz^@plywN2aZf5;ItM= z0k~z;s)dVR!v(3u`)jLgexj9IyGi}=Eg3y4EXxwfCW`6y?3v+g!WH?dAVY=i24@Qp z$f8mD&sr>TL}-_fhv~R%O881@m;YoG$9j1i;wzyX3T-Fp{e|Al5;I3ce_DSc+=CO1 z^ALgBu(+@avQRpq97gH{a&)af9oLfBagLv&HLoNuS#yPy{)fFZcVpm+vM?ucbQP2J zzvDs#&nx!g*&nCtmyy&Fu&R?ZI*rmtEZRi>5x=eGtm)rFvuF`!ttNL#-L|2kU|Hd` zMe2r}!J2mb7vT=HHYc|;e>nGwjlhViZA)}k_LQx_-&qhpRH=)DKR<<_ z;m87qBOX=)B{^vp%6YAkGqnNpX*A(Z&;}JQUcgG(gzPX>9Q^UoJLA$A=zM|m;vi~r z0?u-DlW$8X=1L#WhZO52gAMAQiX-KcOfEl&lyhpK&=bW-;Z^iP?M^>0nNyUTW^VCR zpW+4Ybpkv7D{6qw)3dA`|IvpAZljnVV1jW(KRvJ%uhs_Frqv<*fhlW7Jg}((rZ#B1 z6bCqhn_Kzf{ELr3vkE0Z;?6*Js^8!+<1p)huV7vWtG`P+(UU)w|5LWcKkb25ohl_s zo5d;?{V&P@(8aj%#$ifhq9D!FwGvy$ZysQxRYx^lJLqffT`x$ixL8^yLWn9Z7mnG{ zehhi%SQ=YCA~f|&e&iTBCii^jPSka(R*oN%_VDu66-pON$=(2ED?8_MeoKItOnj0KTwt}- zcBT_sCDSueN6Tv2;S~q9LHD_^U!vIp8!wIvn5N#SFEmj+m791GgCP!T!+}R$`Cn_N zt>BVk6z1&U=r2i;E@Dgrp@eVutWnD5S>u{~HasKTRV*X|70%5NM6m->`%1mHZyfv+ zNjF-(I{oMf>nYN(VZ(+E9n#5kyBL~Qg^WU|xKy07W_UiME_lr{Q{V@tV>*&Xb^?W$ zUI?4iQ+iBG9y{3O@x^@-KiI5)dg0|_yCmlInN1S5t@QRJ4@Yyc<@wWnB}#%&z^0Ka zZ5T{%Xr}OH2JiV9_iicPi=&6HB9K0iZe|Yax9XD90L@c<$$$dMdDF>WPW4kzmcnZf z4GIGuW)*0)1EArjrU;%kh^n#I$|?lEg!kOUkIa4%T(?EPP@DFH|iJ-E_*el z9mDUSHUhhWv-xvLWKne;0fSmh#VKNiI1Ml*n2tv0^_L(+{NYNd+jY*`w4_j;pm_jF zW>tkHwVO}zuZKj7Uy0}j(w1MIQDuU@d3$q~~I6MZAVq~i;l*enuP-y#`n;8h4)lMVi{cOpH*(@afa`? zI4Pqo<}hcFDsJIXw1kOwOTU2P!L79LW2HFXx@WtKr{lY{xGTO9RBKLlbCz&=6xwnYO-lUo(DqBWnh-PMC-P#vhhIP0Fj)0En~y7D^V=H@*qfW+ zN#dr&K*zL9A~Mq}HhH_Y47^sBEf=ot{gcjHyraoM>XzI>;~uO`eVYMemm9ZLDdTmh zV;3C)(?Y=|R)_Yjjo45Rwh?+*6Ev<;xrS}Ye;Eh~>mG?>(e0}MCXyU6W$s;BH9PN& zl-=En@sK~LODMX%F<%|eJAq&Lv%bM@=j+E2j7d zZBt75yANw6DS~kPG*$TP*LDMpam@kG*Dux z{v^~7sX2OcuNcnk`zTyt#ddsuT?A&n4PqyDA)_)`sYHPr7^vZYd(O7lW@%+g6%mf5 z%>lqbMq*fP%yg5iR2vLu(N_WI2_0$lOON=QgszHa1zi(5LcwGuu_%_DrVT}(vwcWo5`vDQx*);Aouf!|cPq!!mvU~!Rv#fq^ zp6kH&=-p$r-iMPo2*Y9FFvYV}w17DNMcYcc@#9BE(8s>H0HoRJI0Cc$&_ zrfDc@qOC{dRozhSa8VslC54qXvkU@6!sBXMQ6A^8o3z=HjF**$*+I$ST?dL3U~&BX z_%50Z=Gx*o62ilMx1R$HLeEQ!=idallab<}ryUr_&X zat5`zS6gnj2^UL8U+V3ts`(i8GCbB%nLP}_1jSKy<}Lmq%N37t&kM3x+PgAjwpQ(2 zAv&RNIB8G?k{!W&h$j2mBFIgP8#FLlb!0}ucG5EYx{wK1@RBX7k-JX_lPJ%u>)Pn| z&+l3{V@S9%I!NMiBNv`J;>QCIXS8nppRvlJAjNu7+_%YsS&A-D=0L0J=pZJ}dEHnq zSmXI1R>FWV2Alr)qQta?-fH^{UKDkna?Pgv9j zSnx9WsGxdMjwWVj*`J@2F4&Tl+@Sy5mTK*wNAuS~j)L)T&zS3tblMg*arO2y_a_e( z#XN7R-u~q+uWyiunfu~2nLpEqIail2N^{k@^)_b_1tT$sob|!OAQ4Kr| z(R#k@-Y?Ce1RK{GW7i67^yKwJ88rV+EQx$(;V!N>U*T!*!2>AhD zG*sYgA52e41$!reAqf0RU4b;<7J{grcZ=DKwtCQ}>7hyfmjy>9sSse>6Cit-67F5zXe`N-vGJ5654a6TC zAjA16@=$Y)m{O2tTycQCf$JO~6v&`{J|EOe$v+e}kD(p>x(i^k;Q?ovs>(8{20IsU z^(O+M#$gZXG(b0?L%w{09mkCp*S@y{ElTwR5@8LJD`2@{OcB_&{^ihgU4`a%HNA08 zAcw3^XtiZ;PgPDk0jp7LG``jnW4F63jL-}(!v|^$RR%Wr9$Q6Zm|kzA^%i5cif~q? zlY6B9QDaJ~10?<)gQHn~WO|A*`T595`B*@yQR_)W1!`AD@D`GphnM82#yrZa)HIpI2p z__NONS21I7qEy+myZ(bbuksaXKx?TVl;i_N2C)X-=3i}6GVV;(jiPkkPQ%~s4^-a& z!e6aw>a-K~Y3*!lUZI;1Sz1paz+3XQe z4uO-;T88Hh<187GQyU&Zod<4tMD@2q`Bs;XtcdQ5yLGDEeb&{Vg6E5nDufhL*DyE) zwg!SyuLs!Hp$B|#gwn%M10!%`V-9kI4O?UYBABplJF>c&{(vA&JA4ve<9Qrv!+K|sk+3$> zcaK&DV>}>y>L?N_rZ%tQypa5(>0AY_E?Q%PavZQpkVQ06eFZ*Y&8%Kn&IiqjYWO^4 zzu&91PE#+ZiLVV9s$U==S`|c0>9G&ymEN`r&jc-xB=5`d+JXSfy=b(Pc!!Z~Cp5|H zIjuyj=7$q?*f(gdr>ZmhlE}oU`UCK%%G4+IC;@4hxw)@^<0OzEM}BdzruA_z&EU|} z&E47(xUNQp`3b=B5@t>(^$+WL+V)(*M=-2c&3d021nqM1hC9bA^}!kmN{+i%y*YJP zzWv^>l#K!CM zYC+moVnj6SJYd}KDXaWaa-wp~H;f0GOe-YvaSI)Qjr>7n{!ip1X@@)UD=+>Dc^D>A zBA1IeIEU@Q{%@F<-k#}$7%PhrQvW6SrK-pWXE#iJNIUnP=hjdg)aFf8^^^Cy{9PC6@FIuVZz4gC^QcF^)RiI}qC@XT0$r(=2S2gZ)uv}P z_4rdiqvogJzL{UP*%A_InC<-M0MKoL!_$P3hrcP z{<72sf1bO;qN-f4Y!3;2(nQja1ab%N{_19WQJgH?mJM31q!Qn-)4m9t*uNO8oINTy z^w6gFqved6hEHS>o!cK{v9K6pcgpG0ugB=rLuKp$+@HXV?&rh;5{jvZhic4wNZtF zjl~SLX^7pYy!$}?SI7gTF#wl$TOSz4a#W96vUz|V-*0PFHO`20O)_?RhkpNxh=LpE zO)u9MW)K@&C)&4C5eH&V(BXI+Ml^wjx3AC|v`7yQ7c89wE6iMni0sZ{CD`U^%W1$f zm>6Anl-Agn?%gVKLl740cwF;6@{vJVy$6obAASh*zV$=U+!B4t7|~jqU18-ze|RMA ztEZ3kr>KBsdtp%|{WeG$lGejBk;u8xSHljYCb0tfH}CUxj{E^N z`*{51F{cK}8^en5vy$kus2O|KOEIU`7-*x|`!~_3)Os5IF8oKnJ=QKrTIzYY5>p zy$m~lroI1>1b%%t!(U1DAAZU+0}|9ZIj>MWb-<`Y?E!tZEQP@2Guc$yvw9O`OuAM$ zA%t<5b{?Tr#M|k%!Ixy#rR~;c;RE!J2A12>s$wM`3=5~x4S#7Yw>>Sw&RBzz8Isf_ z@4vS0b-d)SJ--KnH#F_ApIElO1#a0b>==^|Y4bm#YH2Q1J(N)tP!%nDUZCue^5ia( zBN}HD*O01zxUfiE2n(+sD&(lSCUyv?dOEm2;lHT>9g;v%- zG+T0W_`mKae(6w4(QsXgC(IhAIo8IFowvo$1>2NIneXu3rtt zlq#6g$xnu#oTdU5umJ%5An@ZB-eKmDw;H8@yIeN6S$wm&CF&$>O%L6`U8p z#ap`S%M?H~f2XX6J zHv4||=z<5wl<45j?c){cH791R$!-s#zH<*R=JQhhNRd@G@xS;9t^s>7{3cYuw8u@P zw?r!m#kZvAeRE`>ugcuzPvZgx9N_)m1xo0J-xC@t=&$M#*e}PcE5z0 z>k)OE{Ej?{=L_whaUOxmz~clmoHP+vDfJ#(DI8_{Ish;74Am~@^zu&G%4$@|ri5Rx z;()rNl1~6d8vDYV5AW%=~3c}#d_xXvP1?8Dv5xPutqtSIR)TpIuB+|AB~`$ci8 zWE+=^wYsIYp~0ek^{}C02r;k>kq)F`hoU-aGzv;{!Sl8rB1o^=fQhE)uP zUPxYRrzT3srn6ATf8(0@~ zcfHN2wcYFr>2A2p@|up6n(47C#*^JmVYlp~)Ua!)r8|>z>h3IC?1R!&_Acj=+h+a_ z)>(+Pu`^?gWK9%V)$eT9SmP#Wo&eSL3kEHZKd`&%gpxR}GdQ8CGDNs^5lN+Cp(j4GZh#plFvrH96c5 zlkOr6B%M!V2}~X8rdNs8eJTY_>RnD!6S{~8&2uEd@NQ+CqQw%&Sj<_s!7fJ^aYu>! z+5^gq!Ee-=&OPP^lt{1799s4Z^A4Y=e_>$4dYBf@F(1$S&S5wBMg>GOj+6) z!W!c)AFe)l^Ztn6$4wZ~Cz-$`Cn50i?gwVW8PSxF;)hY`ReSM;wG#aNLC77bn!z(+ z7^%|jz?21i!F`6C=8WXEww9kKFxqnN=0?KXnyC2t`#uFQYDBxWIcI&+o)+U5H}7gW z|6n$1U+^(QX7Ea?fcZ8ZU2Y_S3u+s36=o*!{Mlh1^mwKYDM%Wy|8(%_pJP|)Q1dDh z3?nIl=^w(qI3BlF3#$9yta=d5AqlC2?pX&d<+;AsL2&!tV(2)d=1jcZmsOZ@^l>*j zaxs~Es_dJNWUQenEQn6!(tv?20q?nk6_4(8G661GgR-4)_L9WI>zM)yW~ll(w;aa` zGNm-jmtDW(b?7-|=`$ihdgf?8kT;Bo9Km&ZT2a2|6y8Bi_Vutt9 z%aB=#HgOyvH=JYz8veN4t}YO|QOAvNbO(d}J>3#V7Z$9C?)@J1t)88upClkT@>sF5 z?qoX0(13x6JKhc{`720S6hto(XwvmQn*W2pgUZj$5T13BJ|uAi^|4oXHNYBzSJO<)B)1!l;Z#y8{qR#cjOIEI-kc5 z%xWxu52QXmNMkoVpGY2%#HY!4Z0wlQy*tACFsJtzym=Fz?;~gs%iGSQ8&<5cA+vx^ zd>CXP9UXh9v$-s1ye|j|r+|c-s>{_TWh9esAT7pWlJPc_RZyH5l-~SV!V}wbbk${Dk1H z+PR&OVAS0Eh&zhdyKx5&t97pU7QmCJSy(*3SRvOnnmP^4K)=9;QF_TkckX`_QmN#| zlYALqZQFM#ukm3w^elJ{vv`YR#wP>=o- zpOZq6*EWwML3PjK&U2gV|_+>)&aaKkZP#O}`us*k>Zwk}nDfWN6bk?CS~_L2pf0WZH@gqV%3nNAX!CM zEWtA76;?*VoNNc2`XrUBfBM-Re9aW%+xg}NwS-&f>`n`|@qMQX4KQ5+JmUGtH2}Ee zIp!Yx>~cF-zO4_3Zma>&*IU~Dw9Kp1it4Jt=Z#b)1o?LY4bsUV|F@-*H~jjngBxI8 z3alHJ0Luhi!~1*x@7;ou8JUqKJA@0G5ICl`7P;o7xwAD*ZSitbS6jNu($$u(rex*+ zj!=$XpRIkg6TaNIK0Dt>Ufd9Uw7b6CVm~_z2R}P$dTR=PIyHTC*#X`yb+Nut*VRU7 z(XGNJypqPr07?BD0L4l}fp-UR^pm3rkR)=6qcZ2oSLBZnY8OEBN>RR3#dHN}nkN$D z+?g&Q^gCY>j5^UpbIuM!lmfcTUh$pX6#bp@#lfXoNH`!f$b6Caht&6aQH5nxc=NE; zmF}qlmk}!hOyFi)OCy&`iqdnrgFpF2H0$rwG1osYs13EaIs)QWP*MAm#8=$@qgh2p zx_Bp)E?JyzID`4KhDHtDNGg5<-0ea0?E5OlB0daMKHMfJkM^~Y8_Ygm<{kd}WULbe zY|C80AiSxV;W^Kj`Trbjz-I*A=hq42ezIHm#gwGnEn}~tTTI*iOf{lkctalEa5BHg zMKt(?&V1V^$I;I$)s>qhF(-I2H%{em)YSi~<(>a#q4k5;SM4h!&Jf~wto8QJSIsZQ z>!2;4M#n8pw2D=N516|+#@oRdT_i7Jxa&+ilE8koFpy9E@fd?h43(3iBey&Meue0w zY?rvfPg8xzTNfqoS5WbBagw1y+H zcz~TkKwLW#54J?ibA5~`N`DFO`~HhFFvhgLIEkRtOKT!z;ydwJ)BJ(in>txGXQR*& zyL=|*1v38BG~?Q!grkaIHFL0Nv0!YSjgSTnmu8O<^G$udrje>CJJ5a+cSJXb5>wek z->L?ancXugb9WD4556aZLYI}C9y-4wbwt#gyJizr#>K+iL{Iv#X?nmiR6IMcJ@(1b zg#hMsRW{9~*-y37Hy4y6_FMS@v}%$mU5RP)88FxWf*sH{8h;=EuQ$QsT(rYY6a2iU*cV0Q-1x7U?_=70s6`aeo~pp&PT z7Dg+DgZO2_u_~5`o5qUJDfPP!Ypv|7EdrM~M0?3HlX?(_ zI}{LcliROLZUkMGv)dtLv90*iJ$$`AyEKgif*4+08FV9{P(Y8(5mh?mZ@P#bn$E=h z2SY!d&&qS4TmR~LXQ6X37(&wV13PETDYXHs_KpDNjJffRK-bfl*#TCK9e^Aaa)au@ zKv6G~_et25OV{3rTTP{i5Yj-r<9q3_fPCpP4rgNQ3e-vj5tR{kdYjRt zodq?O+=K(5zUV&I$>7Ce;vOi$dp#F_tZd>!(baI}QCg-(kz4T*H|9W2m%e8P$HX!1 zXegc$+ZK-@BEhd>@0K1+VL>-EN>_bXJpi@F^^|5ZtLxR=!lo67AFq;pWQ%PdNxbU;QALVKqm&3EZQ<_ zB9<+L6%u;AnE?d?5&tAr9wQwZRZVQS*xS}AP<cSJyb*03g8KjFWiK#3cc!#_65(_`C$Hauym&hj5#%;aK<~0ajOMZ4KFS0 z0_6QUTO$CfEG8~^bD{$bMG_g=%-Nc<{=!Dgpm9B03EpR*Y>8D0c4UC6d854WhmXHU zyA!Rzez-5A%8=fi_P`)qU)e7Q7r~V-#hgk|&$7JuJa9V_vWIutS`JOkz}PyQZ^s!x zYZYH~VV3*k3wy2eCUQLGoZact9(^lv=_jMdJ+--1pOS24E1HONnXs$px2Xeu5}#IP z{PXt&mg!QvF`eicda>c<+I?>9*ptItql~8!uGttAH1gQ(ZbU_73Yt=0i`t7@ZkG3DB2iE}*XN7d$=gk;-;je*I0X(Hirruv;K1G3?Bmm%CLU zh;xwd6%cW-nBT;d*qo24%M65h-+}JBs|ry?SkCL#je6)zXU>$7s^Mm!T3rwFFA{g=4D2%OI;(GUsY`IhP96a%2v>RhaDJ1topOJ0s}D+ z->mIA{5D2L3CJazM~5PM#?Kw0M~?fm! z1k}=Yv3l|5&C#>qXFAB_#5OXq&cR4AaXzD6z)2xeD@lA#Mk5bTNiHyOIQIjd_X_-NY8M0LT-}KNfLPG*nvJqLu-Kpy)%%q zmiZ!n{;LzkVSayn1eX}chUTcV=DODTZ}82Vm_)-vIO=n)6!%XcwGIm&H~VA~tLu-U z)^Ji1&onzhg6XE^9<`s(tT~jc4(9Rep<8;-AcHZfpg|hlt?D8J$(UCjv#s7C-1wk;|s7#SS=pxMaGI=j(4H7hEsBxF4eQ^e@ zDfuIKP7})V$t0Lw^m*%@5?IE_H(RxJeNOZzPv5+)C@hI)&@EN$&8}N1hjjw1WmMl8 zh#}=c@_dAem@Smy9U7G5?hN7U53lR!!OYb7`c-`{_P1Qv$sePpRcFDK?(GmRg!3mJ z4$aby*5?1SlhZ-U;Q2JCW^egWl);ON^4r-3B;z#JV)-$`Bhu-8*v>evtkHt-*YO9E z!;Y9!in4bYYCRR*T&xg|Ed34w6fd$dUD$WSak0aHGyXw8+Ay+wv3+BZpvBJ~TiaOz#z=l%lf2fcE>W>LPxFAmY*cn_p zmppXcgbmo)FFRk9FWJ&ftZ1haztrk)szbE6=z0$s1mS*M67JHOdU`c-Hk$mIwpJvJ zh$%T;e=+2iFkqk(%Af8Wq;-?_7+@NNJjSQTMLHSUhZl=L1p;%h3BW=^K+!CX7iY@0VsKrHt%dJA zOZRIZTn<1Lo5(2*W)dL;$r+a>y@r`TM>81v%?Bu}6ahtlm1CL2G0qQ2REk=S-w*QT zr9(@AZ5@kB$va`^d~ZXDK%BXsQ22kh0ma*xufu*8K}ia1VWq?q$rxz4Z-k^i_m12V3FDwuS+|?gS)P6;XIfm#QQntI5yl{-ss6 zsR(fvz?dEbDJ5Ev@ED4X7KR2X6G>YaXR#0eObd=OYaTmXA?|3KF0v`%jPi%;?kB?x zWW4#2!epI&w_BI`0m=_po=borMGnxq zt83zM~oI zdrv~;QU|U1bO_cVE%&|u78bo9H7jA$NV>A!GR_woB?%66fcEZ6>wk>)sj`d6&Cw}; z66n^86mC7G5%yUjVI}!x(#P9=vTeK|P2d1(&8P11Ulz33Q2`20&sF4)0A|FpF=TkO zH0~e-svonKNHMS)mP0Hd?I45Zk;pqKUHDVFTGHR}iDb9{HFXzS2Tt}0W-Xr_=zV#+T}@!SU@Fp2R`46Z#RA3G0!_g!>x zO%_@q>2ReIS}f3(vKBJ=@t|E$XKsISky|KMj}cbY0suvF-K7BR(RACz?) zg07DlZ);)m@Rm-T;MA1KNzvH+23$3lsQ&k<)PK$KJ9mrn62~J0d+7G)_~lt$7~>->4+9(`5KUF@01QFT&|apw!+h^o}nyG zi7McBMT8d+_D)kz+-6)&&mPSVRR>{oanAHd*PfG&)(?1=b0D9Q8MGTCaF>r`f9WfY zSbl#=L)i5D1zspFeF2Diz1Epi(tJGe^X$380dB>Ak3J^LFtbH-ER?c}4_%Zc(fSlXHT5iYf*xG0h zUqsqJ*Keen6BHqLXBHCe(wjCCQ?a;r$gwYUm%fN3MuAwcJevf1KpqRx@|WpM=YVfu zo{Eok`r2~Ye74Rf*RoL~IhI|TyaHnE^0L5_#|Ee2$)C?YsCbM!v{-!9Lri*(-b z*~ZB)kP@aGTI_E6_X5;fh(6w-UQlt~bcqN?k{OMy?iO|wd!B;fYYdqqKU5C6Y%6}l zM8DZTe<0>JNAK%zbfefsYLV!r0efr}1&?;;3KICa(Ro`)basz^)lcMkKs(A1=kTM6 zbs@^Est|X!aoeU6g?;+W%?Luc#5m}nWJ_)OdE;P!@rrTlj5*ujnJ~#{ zt>65N*~sd%-aTcq$V@NY7##Z=>DL7A+Vn)YOXK_c|DesFx~&RKau~9bB4ApJ7j@J- z)CMVFZmSgmtzv%*nZVV zc2?Z0Ao_pzuadgW2ZWEMOaIj53_D5$kz-nMr4NW>t$}um3JdVv(kgbB>6~qu*yUEy zy1hP{9Zk$$v^H@t*hOzfp}l^8UG9a5^|)t!uO5ZX`W7V?)8po&&y~+|5`-H)UM(3$ zG6Ek6LRfZ~XyB%YknkLDTsuzW>FFyW!i4-K_g`dH>t78C84YK7 z%l5TP{LJ*$2av|C(Fq0N&RCMC`cUCtw47xc-_htUHFgDUdf;^nL z=y$9gj7crz8L(n0_p4_Gt~&FxW}5n3KwcY)ju1nZo$k=@OOGdXZV|$tc>Hqa?Pu2u z!JQY)Hx2+EMhe7UoUKCC&hEH2i#Pp+ig7JqdNFf4;zs*foR_8%`V!T4@@*C~BIS&q zt{r0?2s>my+{ctw?P7mgzX}~U?NGN;bxdT1^sgk_!}qvA*%F<$HDSYy0__lYvSQRVv16 zlf4~yqPeZQg6F5?h)m-=KuR*(4n$wVMvuscgXzVtlRf#WT7ldO8=i_)c`vu3uJ@ut z<^@=3T(hV-mxY==!U&CJpX(2&_4}|eUr#vVwZ@vw#Q0DTey-jLW1X)q2OqRApT%(Q zvfO%SGV-`bktw$x)>nk-k7wmQSj9nef4s_s_JcP+MEM0>5LH;y<2zI<&%#N~RXOrR z`OPW)jH9zWe^WsUMk@EAB)Gp24ytOZ_Z$*afc$yih)#x)EXYUTHQqQlRq=0^^1aMR zMx5O-@7c_I67}1g(y9e(q*lHo)7uWHG60(IQmcV%% z)sq$mkiSmdvAk@h6RcG8t((RFc}q4KzBnQIZ<<8CNyk&dRv#&5mrd3SIavZGi6Mok zFw)!)RDS?-;e&=|(p4*zS+w77iZcn`JlpMC_f4Obw%`dvZpB)nq)7m{(6Xbm z_t`;RFbzH;M>i`wQDSn%3`*V9QKX8-higP;mcP}>Z!(@5v#$bOd0$c919h^H;=Rov z-M3**$a2oH3^fn02Z|!9FT2)r^UGRcnR9Z$fex<0j=rZYvHw@*rwRNqt2_owThvK) z+)Q;ChO;G9W;+MWv11ddGVgR_RI_#0BiAugB~@D~UCa(= z`f})9>^g)PV#RXS@2WsfIIzqO zzUuCwfl16R-S8!SS0QU*+)k<)Y%QPRiRSIRE!+b zPW{K#E5AG05}-#akl>hu54s>-$XfyQEzn2Iz&D|aF_X97Go0Ec=O-YVYa9h@yF@Il z?BmAA;n{3JzStUWK5_78Mp#cFI+}8lRwnYYSSa*z8tBt)upN*3k|EzOQ@(jRZtlym zt5tq%&nnZP4@(fy4~2AW_jbl`5R_p^=v}PPgEy!4{Qd0WvVgJZ`8BEt z7zbFYk5{5xwk|%H>9uaYw9-*NgIY#pbIoyrfb%h@+8|Uv9b6cG&~q8b(V`^i9SqoZ zr>NN-Nis$Rtc*F>Hr@!Cq?s5Yw-T}ePz`5A0ap6fj+aN%n&n*|q@Wt<0cF5fG##LB z^#>~mq>i_CzX{Dbp# zJ2>H4^Du%GGcV0YFGJ2BfioH0KQT|>cnI-bq0=^)c+S)zX{-x#b?*~sBzkV>(G?Lp z&PhuhlJF`NsF|orF+9D%E9xlvs^c9@5v=AVwzn_vtsP@DhHEqMRM~-2Fa2gJE z;$4rMdATOuwFrevu$O&s*zC1E@y&V_+&Sa>!Jp{Q7u2)b>BzClIgB zl_3Akf?0UyutMI3aSr{K+qRt>+qP}n zwr$(C?c6xIaVGD3@69*!&CDNDH8ovzc6FUUc2{?wuHI*@z19!J1ObYX921-t9`FjAQ?}N`tc{uVdhcxX*=TJK!TP3|Yyb+x+_DbY!++^mz|AUS4Us zzh5NvCM_nnj2A8MzdB*S4U{L(vbaKPc#Tu7BO)98OnTyMe`U%5CGh)gVVV9D#5&OV zXeEOQS0hauR?~^3zkq~CbbCuD>v+eqGbw=Paj1(cewVL;pxljDVQvV~jZuG8yZF5s zJ|X2<5Q}SxL50H`0kzzgr+?o{Pi+RzrddwFO=PVZa&RQniGxsiO{pc+`pJvk==4^& z2kBQG!|;4H8gQ&9zTDh8-=2|gp}koe5WM`c#va-n{k>(7Hl&HTzEl_wlLkM++@}iF zhH`uUsPOXeY_#g4$i(7)z>+Yt3yEE&!0*7$rw~R_o>7@?m`i*Lum8MypCeJ3nz2MTsLtTYYLp$$ z^ff`PJ*t5Jlyyvq0|8r3Rzmt`r&aME>%^20qfwE1kB#5ohRRTnAX|`@lUL6feZnx% zLd0KCGTbi0t-Prd6J|cXG8^E9<9=?+r?x@25pYx4!0YA?DS_9u-3Sz|d^J~RWSsLx zovf@E;Pe6e;#2#lIrS~^XTM*)-tZxfhp&n3jrfPIb=|lz#;w8}&<-XP-sf{pY__}x zfN$~rpo&<+3$YjswyFabbs7r{rF!8oEF8F_JHH*uuUOXy&jQ60R-)qHy}cH$w9mEA-JUeV%{_E}DN(CMBG6UYl7j-Nikrx+20(M9?pn3qsQUaZy zWua92bQ`zspk|5>90nm*lZ?6%p@k#1(VJ7d&?7N8dq0CPa7eXkkEpvbGgxn)v@Y}gAq#~aaS1yoLwA_@_@CQ^oEr03w=c zA3nHx=!DK|b3F&oq!ui$y#GFE*s~&>dLUgN)SbUg_IYUo>bVMpbN&Ir~ z^*-U-H`MdWh)C@~UrDdk*oP}7`#_)6jdPA^Y;#!eUtCTa{z@P2Fu|^ zLuLFxVS<6LQRLjrxNk=Hp3;IGj(!$?(ii6pIKn zi(i>8&%5IhN=|fq5GE%_rmgg=6K-}R#EtmMt95_ZOS&t6c{m96D!QQw<#0GjGJOT7 z7pfO=^wdX&6g0YCpd9>tsjTvD>2W_*4}?!U3HD<8ysR=Rj#vWn6{c@WcIrMzf{n5P zWZEsha9Nmut_$ZHPz*q*uDy1C|?uxbQmvk`XrB` zJw(J=Y`xDzoK^9=t zqZ)05ErzBOS-ZPvr%|9@%DRsPPMp?yXUk61ZK(uXD^)QUm(f^Qj!;zrvRHsK%to)e z=hdK#%Q{bvr}@LZJ_N`3PwdJsu=Dti_xmbTqs2tV$8Bt;5p6f;eg;;Hg9cr=C#rhN z)HAlW!j8$KU(CLghY-zC5QMdB*2T!a->!hmfk5kGRr#VNKB>+9MrG>XKHaz5)&4AZ zI1J)y!mS^6A}->zT?kbnerWg4v7>CU5n(Dv>rbXBAVuS6_Rm$z4#`y~m}J@vkdvfT zT3pB8O`R!OLiij!k(nnNWd^{pHUl6$llr*VVx_$`D0xSMaO@xtrWQZ~QL+i9$zaVW z#?*@CU4bn+)zW@>#QfJrVQFA=2LsKj;Uv8w`r*D=PUQ!#XNKU1p^T=^$sxYLScVAL<}Y|Bj2ozQz?0VJ}U4BO1DckOq`O64KJJ7F=8@xvFG$k}bX{r7U9HujI6)%rL9et*=1*cp{4%B$oJKC^ zNV?MEZ=zqvVt&cX_ADm=8pA1e>@#*t%CUiuSv4;qcY;TH=WHoZitD6aMI0zL39vf^ zWTF)-Y?F9a&~tB_CF{pL@Q$ zRtmEI(K?qPP%;>#YX+Pi_g>^6TNpMj2t@UL@%*G9=i@S>xiIhv&v z$hrY6wXOb>ax8EoK=Bc&%i^iArXk^Ez)ipMM4>5tNOhf!M-`dcI`=o_E@(h1lQ`g!^BK@bN`N@}sRT2G_i->(mJ(gKVIwT=NYDY>#xC6(*So34n zKf11XC4^LPXsd`Unq3hR?-Kf~fT^Zvj-$TgbGG|XTg%f}S*EvelqU*^xNTO0aJYc? z@BBCXS4f-0;3N(RQAg5)VIKZ=#Q0X1QDKVBthQPE>;OTw7D0h}V_B|8N!KG?9%^(lSHp@q#dJH@L9 zt|5Vt_pnBUx(Un$o5q}xTFtKcd;Mn_YS@K1<^h^v@VZxRo>ZK1rzKP{)X?L-%xIZ_ zeIY!iPVkCQBT|uIp$8glC*Fre#4E6ct)Lh9eT5AzpCh!X8FrYqQRBW$z!Czg4Jc~% zAUrnOuC1j+7d=OlTN-9a)%$ZdS1sWUnt&j7b#1cVbIN{iOX$h%l+cmE>bGzDgI|>p zA-0T-iv@+M$|DuBz}WN%$IDqkId&Q*Qx(2573uv-j~efD;J5M z51!>W_&ogJ)^6y=+)TDjXdlOzRYS|gD>v+`wF8k58|!)QtLBBQHxZr_)hp~R7vPw9 zX!>)h_oFLWCmK-9PKqkDSNPVV-)AKbZATW7jn8yAW2tb@#mczBq`5-<)w7(iNnuP8Dicm&!68M;@)|p#Yb#4!H$dmT_6W^SQ8tbB6mb<5SvqFUnLlR43 z$kX7onJX_fhy}-^;Uv!KPLxd==o<&OZz)QAt9GSkU2tieuTE^?N$s7c&X>UWgm8V3%|E$)M4!!fkz&aja_gdm;WK7a zNIUR>((DQY!ulcsVgiVFny15~i^6DxBZqI;0c&`xSWBf*y$iIJfK8ASUzrYevz1ay)C*&nkvI-Edm*8L5c$ar_ z8J=g|4dpB7>eUUZZ7b<7tizn(<|ZRKFVzgvis)Ko)e*HV(IKN~iVhgCS5Dwvq zn_E*IJP3TP#@G#!aJ(_ZjMSdHS!&2b3-Uq^^|pJq_Pc)ujLOlerQ}lylEsJPa}C8t zS7{{D&B`FGDzme`NOJe2KR4f`zf+^}vgS0`NmQJOJ|VW#TrC>%-4ExO9mR_KE<_Uq z5P-HHb`}MnAF)uOPEXXM2|o{1YuBCbh|96Sq(FHUWQT>M%JoDK0f-mW23f?|W=m#j z+tzkcFlPd@Upi?oI{f0yo;k!RlkTh1Ht>CklkLE@-$EhM9R&mok2d9eEUg9u`Rq`AR^hY7L1XPV!93nN~O0^3gH zeiLHF$pIOxyWl1t!DRloWOeOZD;opsr7{nRXs`tG09yI)w*1`I!m#0cIbA5PhjxI4 z#0v}y#wlleFEGR3ZSHQPV$Shi>I}nb`mrF6C8#%mvYq+kwUu`E2JoBh&?NBiJmIzBxUGQIWRd#Vw8sKlI2nHNO z>m}6a)Hrj@H>=}kV2LfEtsxRH<`vshv#^+ybK0Z@$cZ0El#GAJokO8A#@kudWHTTJ z-=40FC#@P(HsNxlx0FC<<=nogoP_JQCUJ}0xUhRHAq3nrl^FG7KLymfTjQ?Ushs=u zyYt2#ZFqo~v8ISn@Nc{A1EO#&Ft`vru%0CY3N zI~f&SgekW^cGlpPg`}MjWuJAtVPAHVNZqccH+@lfuRs~R`beXt3qyrp#mFwu zS)hEmJxX`q`ydOC4}sC|FjJv38(J&R-!#q)V+h?n5P)C%F$mlJEyd5il}$pV{7qIp?=SmYsdxr}sw2Cp&J<+@fgOfzch7JshN)60@^+ ze*IORa>qqYTeFUMn8bp#l_^4ZL#^}+LKj!SjLEMg#IY8oj8?NP3R`N;|8<09hh;zeEI_LUCU*dPi2KW}0|=u=fOJ8_vw zy2?Eylo8^Oe>sP84|*!6NVYo6e`2i87L8izOa0h3CNPOVA2fIY41 z_EQ8l+{`4#RTf-`vG(TRNBv--3Bz94CgNctI<8v;<4$N`#$DxACYH2^@k^G?TUZGV z(U6H|!@fSX&U=Hvoks_+aF4qLD`GWrFcKMQ%sH2tEC9K34r3m|{52LUrrg5q4uESK zH2wr{YjXa{Rz0w@8AfZVve;xS_l?q>?%R2nNzi0!ru;sc>tg0M7}ux!T-D^%_|?UVGrbuoH4)kduCEP1JIj3$}(0gzK+ zU2@@W_=ZF&xz*0cdzKz>)1ieIxv?)0dDcqtj+Fy6%VJr-GNjoUh5NE<_-JuBXr!Nz z_pkT?ID<3P`>Cee4NPDiovG3$xf#yqMa@9sxnxWu!k^5g)W8C)iZCcgq3+1vPvPhX zj&5y;*^H+<=&6oG?v)IsYJ^_0?iZ{y=0@x&o%p`P_IMf<d`}Gh}$+=H~uE@ za;U#YZvxGIP(V-^FRrAGg3*GEoK)tR?~onc=9t z1L3+NF7AvO9=!yoTfj9!39?6ttBF`sXg;?b=CGb3Hc=Eg0iSxEK3Sw?s&($l3dPKO zCERECdU_8W&jr`ecJKie`J6u@aRbu8od++5uT^n&-T9)<;v6WI1!h1Inegu8S>={a z;A?#2$hJd!)XAc7bX3&3gHoN@#qAeBm?9E`-F9zsqKe%qDJ(zxd*4JMa%#+_DnJ5n zB7m{JGqOv%Wgz<(UImFy6CqYl zm(`A8?J3lf%9a*VHXj1kL{Aa`kw*8vx05Zj{Pk@dA& zE=CBO#w3E=zdStliG6<(men!qj$e#3(!NghqAUBpz8 zvTJN?>YA&mwXha-nQrfPAU|7qMY^QyXblLsc-*)O8?_C_mWY2NY`xKB0d%|sl2KOkBs0I)sEKIe8Ec?9RZ6!hmbpD*Q)N=He_h5^@K)m zGhs5wrM$))$Mb@!WLD~Z45Qae9PfTk{)UOMd_Y^DdlYL6J~?wf6m1)%T6v1qPjc5u zR^3vXb4dB47(0YICxA+5i>2sSv}&F!ONUkDjKEQ8iDO%q3%2vL>4yNnCyLtT;C_@) z(vGL%JxgRXDo;!VJEU|sh!{>ltMzd{kRrOL>4rrQRf+NtNpKN@$yVM6cEqU0Vyyxs9d_+uD#<^zcjq2&GuBxZdhy#CM0b^ak>T)NiDuRsc)90gOx{dQK-hw2x1z;6lqziw zLaY0OEmgD=kOGEx9q+BRtHG?Odku7|CwLum^iSOvq!JDb3^&}XUi~brI@oc_G$4HB zCdV;ZJS}A>QjN+dwU;=fU}E~PX#r`7NT##cg04vT3Gk5v*4ZPkldnURqVRN2ru`f8 z5V)y$!c;X--IfpI?d#N~doZwq0_C2Elej{-IR|i}32$XvooqW*#5Ct|t-ad*-_BMG8fuitk&ph*4ojx!aHM@F#z-Ko(b`;MN8DAxY>k}L!fN@zFUHI%w~D`c zB~bT0{SX>IO-lej3Yc1Eg!z&-lhNyeX??-6f?oKUoNg9HFYl?d-5l83s%9W85Wf*0 zkqY1NKeCO47#r22FKthU5TV4S*Nfe0uQaJp_2OV$$R069kd1|@hB(TB5aWTVpX{M9 z-xI1O%6SADAN(Nn>4kjYlbY6OipqI+VcPfeE}b}qG2$nU*0DVpEJG|b2lvCW%;pX8e6|L z5qXaf()<8mh>7{6f7S{hb=Pe_flv{c_b}deYNlPAMJ<(01(yl=RN&j zYDfQ2i++y(SK86Pru)}A>_4Xd4;blRC;s1QM}R0X|DhcXJi~>Qy3A86COPxjq6<#0 zd<%&O(yG2%dTUe~lMxU4O$l9bl>k|(Jv?3Uw0_Y^jV%%!IkMihLQnt@B*6+gE`6AK zSkrfXOZ5)l(#|2B<$S!THmqZp5L7BjRSZ*IR58py3h5E|h?7l`O_v}i3MSBc+Ft5d z4A%k4Ut^wt{ghi3A(k!|()&UD6psby&z%quj_(+E(@@Iyxb06lUS6ZZ0)JsPb~gA~ ziZnRVJpS@2!`TIKQv^m|KXheSLUEiBfWqL%NK*bU*2uv>|h_4P^J5C z#h+dUw`jT%1@0Gj)gra3Mu%ECSf-v>@}%gCW-x6?wnj{Hgp6UOE#HLqchFv^(fcZ{ z-vo}e*r9}(zt1txn?@Nc69>l&50&ntI>WL@jYHVK&<=DQ435ScdCH^G6u8AMTll1Aw>XPy&VIm2!q;1`zy=D`a0da}iBREnppb~zlvnsoT1jg5^#5-)=+k|~a1&nV9e z$qCVRI&qNJ7@7l@(UGBLNM4a;UOLU`muEBfnWfTgbv=2()ojZ}IUZ5QK?Zf>jL`sz zz%M`6p_-)kOf~zytd)l>CT*P67U_M3g1*`LdtBh!>!H8&6gdX(E5+kggRHR6!EsV4 zKfth|iJuIU0ZrIQz6=Prx^}NIInlw&#qRf8va`itA?n|)HMar|c!hGvGLyBcT%zac z-K0VXs;)#p}KtG;?Ydd{=7LmLeS4vPjaVnN^m4q@=uZ z1^b=2RSx@=>H1@Klb`f6#?~K~o$s`}$CA#A!aA_sW6nx)Ha)9mb~$0- z^BOQ_25m1&5;Xd0ygox1>|6X3`wuRL8DKk;O zt$WU#M-*}B4JLy4zK5Zack685w|pac8Wmp31nWKCMxpFE%$(eYL@S^M5V)(zwJ@Ku z_dl@+JaPQkNqPUWliHHoCtZQeX7K)$^>AsA-(Jj#nYd*%*TwNAO%rI;=O>=i3D)yBy`7-gW zKqbwYS{$pB{x5P8=9ULr8Trs1qK>5Eml&;Ptb~*GPl{7*Tps;~1lYbdQ_=5f`_|A1 z>p-N%NLYIMGZTP<>mWU*GU>+K1nUqd&>1Ce;>zbwF-f;*cg!8X93a093(dQ84zReE zOjveMo-Xkzl}`Q*u6c^S&vUbPJiq}7o&U!;_OJF@B&;j9y&BG$Q2-(Wnz%R}ZO<1! z2x9!-KBEu|Lr19fgD9q8!IK69)8Kooy%Ow9n`Xy@Ymi@eu^5Oc5FPEKd!qjZOmfIe zPpUwi90=eJ%4?GtL0l)kX?KgY}9-fmE zxJW@D()yAFNe`l$WLPXw|JuH#+fVLjB8kyTCA?h3(-}?5PODo)FWqW8{>2)XA9ZXX zFYOCi2^sX}qjKuA;N)KvpvcL!qh56z2y^>Zh~|hU=UfeRiH%5y4cp@-f4Tz7lqr|t zL}A_P@Ck*xu^T!e0V;lJdgMfI{e6fuEZZQ?VICwq0vRN^Ahdo4pbh1EJm8r{L)rZ- z1C=hXCF3WZ>5MWB$7`IGF# znM$oAAA|Hh)aqd&(H-*#;XyrD0vl<256)99R+Z+#F9{>wOOPu+oGrF?(8_^uto^*a z^4{j>|Ej5atC%r2Gl%a6V9755{1L z+WHk)1!AtfPC1XMfhs`HqP%MNyqmTOBWkW$YK<~K(-T$EYWVsrN8%Z-sf$_DD98B@#6rdY(jBf7; znNZ+>{dfL&TSSIsB`65g){CeDqDGS-x{uVpx9$n7MQQ0>w2cVtH3hmt7Kz`g4U z2F`j6tPL`fhJ{)OXUo2aBl9GE5ZZ^?9?_fpVKvzu?3crT)S9N+<8UNmetP-)|5rDO zW(1e7&=S5J$&HHW60S54Q-xN(jnq>Wy=;x15A@u;j2Z%SOH*;I3~$k(%p)%BAfVUn zK2Rpo<1xC9Q|>B6GYIcOHo{D-qtGo+)9~`GBK2W{Y!+c8EWVS6G*Y+B4->^7kv_84 zgyqq)9Jt5d2hK|0{Djw5TIvRJbb zRXn=HqEc6?=IFs;j8+2ts7^6US23J96Ydj^HmMCVWmDw|1K`j`BMoLOY?egpSX?4# zkxxY^A~BQoK)z1g2m#*Ts{Q9MXK!?{m!-cRX@a$K3L6AaX{80>Dd|2b8E!_#lR31sT6NtmaheRPdI+VU!8s zSW~Hbg{MUfkp-lllS-0ok2KHvvh+SAq?30S0E*M-oV^fxPoXUHSIXgic!vfopGc{4 z>owF9!;zJA9+SRKuK^igqAtp$q{|dqt)O%q|mU3Wa7{ie0vPHyzy^w z2yL|!YsElFo+z_SGo&&jSf+^#sxmvR8eipL3uz|NBAW z6d<>34Kq{97#+Jgs{I=Mi`3mDf`uDl6F;JSUT?2cII)YhIw@Pu&>{!iEzrizQQsd6 z0^Vs^8TgjCx69gn3PTt~-k~O4#m-pI?m{$1(+XU`6&yQ4A%#$$;@bG3857?YQ|$l| z?@b;gcG0NM(r*J=ePd3KCgkdh9P40upGc$>%A`n&THYE1(990jJB zxNL|qub>|@eBM}ZY9CGVw6RAV%q97`bU)y83+C{6_y13>(kbFQsF!DeNmgfG)YPm` zImovPxVPYk76wAMx_?jJfJaM(z?l+sXEE_HR#xgEZ~qOaK^3rI+#z~;@z+|j1F{cI z>{|a@ik({$pISRkYAvDCSa-H^&}37E!Lb`R6FSj?;5~LjBEWo z-b952VD+FOjBxxG!@uh)r@yUOko^7LR_?dS#XqxM_NqCA9rQApB~-^(R!>(41h;Sq z!eM&O0+h17{s}5AKQ~8sLRPlE*@TIuHP-urO8e%Izv;2+8JSMhTd4l&p<|-~T97wx zs8GGspCzTTsqzfARjf;Qh!UX(+(Vfs9EoED;F+bSt-ts!glt*%zzw4!P`e*Pb@L5~ z3`+n9i8HHGM5uRE@0Bb}Td15^$)uwuxiE_H@u06K`ToZWm7^5Q!^00X>N%Zp-u7MS z;5s7|ktxUbfd3!S4vy1YEC`CQzGm*#swm`dLqFs01`ED#myQkBmx(F(p3vAY{BHKv zK}PFw#8r3K=UNm9VI~Td}psiG+iRZ?QLwZr5I};wp(~AGB}-;l0(LDc{$! zROwz%rBP;6D)+|H?L*Ib&9Je;?;>+fmgpk@y~rK(-42^I=^mYUtXVpiN9bK$OIn)_ zeKWnjj_|6s@jgQ_#($}TJ7h$5qyjrleRBdm!4g$M0}>1RMql$>DK_V5O2836?|D;L z)Cxdu`T<2h^;MN!tqguD6-5>~$DE!dDv42_bIwl9{clL65LC-AwT$)%GAjPo+c0)G z5c*m>s8^A2^%cg{q^{y)%+dW_EgxJzyALj#fAdKmadU!DLYZV7l_|bJhCWhUV0tzv zLk_iYZd8oPs+KLEF+NW-v;7z>rQF>*JZo2x5>MihjABO9$&qo8ACM73`*pWffR!qNkh`MsmxD{ zQ8RN;ysDao{UvZGhFVPgeHJQx>=6>qV&Eo{74z#p$g`StCg^VipPGnE9zw1EQ!}HL zy04S~&&i+VFFOg$#bOlgyniv&N z(ueY+Zhd35E%LeWRg!U!1QzSStR)#(6#xYnO(N(*NkG(VepYz@TGixQnUi=2lH8U1 zkd;BZsdL#G(wM2_63NV@J6^a&|hHhfVZ_G7(GIB^FeM5e8mA&hXvJ_6(lUJ z0gHnR(Q$)^%j#U$_gm~})I7`Z+{$X;l65E6r-0_o&F{nOEkP-jbyu#hhB-2Rk-Q`# zpLf`;F^%>GC@NVqawJ7t8{s}S9niqpUsarb2NQ8Qi@ zf2$UcH8^Q@6qK&0qc1a>XA-Syi4L;VQ=#1LH5AxQ{-9bTzf-@%gT3fl$gBuh&|{{> zfI_#<+pkTt#MG_4o`6;{x$E)k+Ll-cqqtLF4Q!Kqv2s|-c#WYlvX3OhK^%9(j>6_W zkm*jF4qt9NoUoEG@*DCPezS2(Sq~JQ=?$E_MbTW>=BiH|DiYbFb{s!{sqQ%e?zK9YQkj$>)zy;tTj-ib zQDq+=E0qG>I)osM4yKarj4J9AD^IPtplC8SrTI)sSfI!rAn7yo-^9{X_ZnXsb;7g& zL)4#N&8C^t?7A9M`$G5fGpP2A1_kiBvj-PcpejWEgF^lrB(}w@mTHRJxb6NNN*W3P zlF58^O)U~9QUK3#)otR;0X9~%H{81y21B+j@_~SK@@Ed^Z-s^DpPNE&NUIdJO zAzwc@-SYs|BED&baLLW6z396eQI|>l1l-Dk@1d8&md9|_$Qn)6hv$z}f9L;Vuf>oX zW!PV`W=qKZ=^yTUJPKI3a0aS|YM{mgCEg)(n2lI(TW`+9l~H@ZM&WLZ>*Ok+Kanb* zo%>2Z9J?5hU1U|xoD1KDOxC4R=4$bwJsQ{8lS)uNSN=%}@zZ)*1S55$*>`3JNni#? zzz1hiSwi630A&Fo?p62N$!yo3qfq%E0-rco<1Ddo|cwoHnQ@k z#bVyK9RvC6n{23m1`z=9ZE>r5cFIspWRf|?otFT4*n#TnqpIQiC)d+?y|T&RkW~YB zwoHi;ot@hlilMPDW6Ctdn;(b3?~$U+-EW^t4Q#2^w|bguaNQD{Y@6y0l7IZc{_{c1 z)4rZey`E#DkVoj$f0jtg-kA2*rE<8KSHByli^}d*7D5Jb9r&Il5XksN?UIuwf5wq& zO0TAI>i6#{00`$G3b&Jk$N-QvZ7K;MYa~2gzm50%LB*aIiyl&*luSAM6xr7qD^rj# z0TRpk8pcU3BvN@8{d{dqZXX~HNho!RPBHl$6D899DbQ(9f6L~$H-Vgdta&_g(wqV- zafW|28MtbuXpO?U9 zY0clR3d?MgHwVJobl|GcVQ&5OBtsu*Mb)fkAZe{c*D+Lmp5_CJj{kj{eqv&_gkh34 zx9Z&L5pCSy<>2j=a-|>d+gJ9)mSP0_EmAQ~9VQ!+)Y<&FP0dh>>0+sjy9@0FmVSYq z-wHvJaa3l(WGN9KFT`(;_I@WplwVsC!)Vq!WfQ&6N;`ED{5hy{h#I=+Ak_v?kQ11Z zvfI8@3l8=R@EC3zQBfJt)HPeF2vQPEP`Pt&HI>#i?!SM301KTZclE!E<%VH~Ofvbv zF?Upgo9kQ#{^2jdsDf;wH6tN?6CL67n+bg>tZ^=+exCZS^qvWvL+trv7-%YD?<=Ta zNU7mXCr+vq{%Q^i&FkqLo91WO7HzWg4hU0fMK$cW(()ReYO0UkD8iJStB~d6930ZXAC-Y}&3+VSfc}SFHLe zpW`vYkg!JQ7f^}g`rwy49*cHj0>#c>e?!B+8h#QND*sUQatY_^W=9Gj2sS&9svP?5Yd4d7|kkns2ya(_A)ZE>WFLZ=|fJY}V9 zRdsf#S!5kMl)MODo)0XzmzKUe&F_ywBCz^97^UpIbh&=n1Ckn^VYM-nk2Ol^aumDTs2HOxy=Iu_RERn! z(K4VH9Z~ofvwNPF}-J3cz0y7(dLUc(@S3hS1H&UIsy|c&TG{R5__7p zAYa}e=7RR;VCVPxitYQS%kV&U5BG} zY;3*SGf;On(1ClMHRlYD2Imf7FvJWoR>F=&F6zWL{!l!LlJm5nj}V0_?qm@6JnxwD zfb-$~7Z<=e^R1NmQA+rF3u$3+PTS;|@Q+15i-}7Ygr8zrj({MJE~jo{SA{N1*9;l{ z)cgh?tfTM)VPhXOxrBSrAN+{JM{J&1OulRIvELOegfGMp(3i~1Wa z*3b<8#8qxVn?LXyN4EJq@3}a7s~@o-i*@$y0R7T~#_0Iqo9iFGxrKsgB+Xu*9vBWc z$pS%CsRL-s>@wK%e<(gid1l&Qi<2i0;kV;#cB7W!@jQz4XCQO6_*ffJGSvA&#oh-C z{)8WGhsKcxq)oRxi*)QMi(cZnQz19ikxYUwIHhS*Qp}Y$(=qLKYFsq!ATd2^|3o!=5n|ZEg2UuezKuWhF`3f*!*FShA!v^YB0859p7c_Mf$xAhgx< z<_*wN79P&5%g-aHv_NVo=edX;e9p2nR;}J}I0h&_`dRHdXdH{?Xr(!O)JBv5zZjNd zQhV(B$!*u&dfl=w>yNvCfEhMv)y^ckKMxHqFtHPRDxAocbLTh1m!#X?7Q8>SEBTJB2oN@{>0AOd?RA)4 zP=GSaHoa*3h;eFJ6qx~Sy59ghznpV2oN6bpQ!0=H8cA(0z^2OhT5uWubtIz*W+!Cv zX?J%Zx}jr+O!1}X4IdQtd%oJH+paKKzXjr4=4jXEeLuu3NvTkTpk`;IahGt;Ruh_O zUXrks!Q3CZf+GPttz=f6V0=}}@vYeuXd3!p6_MiHi{NklDM;TCG;bYkQe-{DlGM+< zH7@aIW#hN1G>SeV0FhpK!%IVw4lv&(_PZShp?Z#)~!0t#{k#l@DT^$m{u= zY+77WUEKW;I2sN^~x2L%c8Q{#~U`#Qf#SS-EAJxt53HN1$+z& z(G1R^Qr&+!i5Dudn=9c-&tUs!JcO88Lty5l|4Ib4`tl8}IVK{H6?2xVNJdeSg2%d} zsIvN&!?X=B<6q64kw65l(XManb4LN>Bj|HR4)U$_@ymS}74kylXmx0Ql~e3B%%Nas z2xDm~Z%j8&N0`J>*`@A(0QO}#Z}I9`zP4Wcfc}j6>1#l=2Hf&^M9-QxV46tyEgqRb zvJa8=MO837)i#<`W}Z;#aZEC5nJoJ$zNa)Uf7r142#H?r$YmM<8KUe=L-6H;g3YD4 z(QGvJpQ{I!7C+4~lPKz9Ujp&``-zfi$OglXCF+jNu(U`1pq(nhe-cjvABwul2P-0= z%d)UVbQ8#K2*iRmEF94almk7$7+8tKo|_DSe1!|p^q5a4>kp>6yZOZHyynD|igFxY zL0?#b6EpFtpCeSiXRn?fwIjXwkv9%cH|hiU3&_%d%SN9*)?GOnmm|qtcCf`VORIYf z)?g(U=2k=_9p!ip09Sl}5kcUK&tvE2JoBPha%U<-W3vwONUgyV{rzY`$VJ7l z+aoBGsSO>^b6NQ&i?EA=cEB2~@7i1o zW~eZFX5LODr7aK4EV2>B5ubXjufC)z>ynG64hF%Cjt$fjt&Gol z+HVOAvkUD>&B8sx*w z-3S!QDV()kbD*3)-W-CG6mb|RdkqnY67jW$7Meqz8zweIyn~ziZ(O}ol;}`{ty{Kj z+qP}nwr$(CYnN@?w(Y82wyW;$K7Ic_<2>XcdB{kzR+5pKIp-%eX63}kPfv-8cU9XZ zZZhqhfFs7<46_Y_eE@F0_TEX2LZER$|Hf4e^+7b6(=^C1zM2aC@1;omZ=vq@`H2l^ zOq?8`c4C%-x{=oYvHB>HC7D;vChi?)9^d=*uEVl|-ry@KGvAUowANx$Wcb4Z<%vf| zR-<@;^})VJE+G&|1|d<-F7ku<_k9;PsB5{mjVyfB#Q=;_ zmh^K8&$I2ElnV4c2$k#S+=n+|_QoS~h;o4}&YeYt*KH_Tm?En-dStxw8dv(Xp|hI| zI4Qs74&_~rjy}%t%V?S>I{Yef>sbSlgslNlM?HCiBii&1XaR`hFc6*iK9p56If`^Q=R?|yhFAUqZDpZM{8 z`_ZEyU%`^6E`TUA((nyNuol>bXWQtqM~)?{s+2rWN&e-Tzhe3}rmFlq*>cyKg~m_4 z&R$DK>7hQ)t=v+U9Fx@6{(N^u!`!j6lrhl62wU%sO0fQvACNaCEfh7e=7_7~G2AW6 zQWPAm-ZC>gn(H%22vEJRmm(EBn&N9a>+~2jEb>G&YD-K37BqiB7FE7Y!J34`J8?4Q zXID@3gJvzzW*i-ER|C&^o;hX|8Uy3ofXb{ha{$YlsJ}lWkEp~(u6<7Rfr#pYo<+Jb ztN^6W#i7AAaHWzbe-Y4srbts$=~Xd^}zX_#Yz_`#lx@1AdCKwKi^neY|b-k-^0FK3b*}ptoqnfbV5b^{9tCk@`o`+Rxnf z8#888onh5;{m3W*BMfs>xi3SdiOD8RWQk?IBZQogP0Nt{iHfo(ppw;*eJW^TZz{78 zlmP_uCymV*>2A++7MEX}K2oKBzGZwuD!|+iV!aQX1xK!k#gQUVOyRk4NC~oN?an#H z0cRc7%+R7D^jK!!)?F{EOyC49JTi$mODFtH1M`t9(aO^_E#tGTc4)y_Uv&DG5r8s zM;TiGpYGu?z_ZTb<~OOU%<(vl(V~j8vg$V(%_<)0!E8O-7eIcA&JF(++p<1fg#>f+ zH%=64^;_i}y28+~GbHIfb5i=(W^XA`jwSL1gc-M*%43qly@={vS zWx+Q>Mj}6?;)XuZ8l|fGH)vaW&rt@G@J(YtMJ^JlBjOc&G3aqsJOuC?zPTIAT7LsVN zIo^qM$OeaX0ddhFCN3@@UnL6>~O7>%WIKu{Gw zd#V!%cs(#pYF%~`?rWu#8dd=Q4;xC{F#?kEG6R67dw$laR&c%%Px__{&*+Z}CRsqE zi4RZ7Ve)(>pN(qb#&>tWR?x-WkJA|#g8Xb?egrGNME zl1geM2njHL6hj=aw6KttRwAElLy**YQ!hHMD#4y3b1Q?GE&&bS z=5bHZulXXtgK*=Eo^1+Bh6-9GA{p3Gk2`1S1X(FqH||AW|KgIL#7V>s5VA;W{+Ps@ zU*j_cNB>ktRL=_JWC{`*wvW#=6b*rwkG*e`QA7o0`UVVf{uijba~g5Th(Q1Q!4gbm z&lV&M_t;}Wms3Vl+$zV%H$-ehx|E8M;&xSIQuGzqwd;B@az3x#0gi{=-}-)|Og~<8 zXcYWmP!lA?NC-cRy)@_sYe-1Ve*NKS&amVH_$lm|VOs9alA(s#oK5ob-EuKI6A7ng z0d=dNabFz5IIkSJqCdicBRo;SIBN8Y4yw2)F4kJwA$Qz?!mWAPyZde1=_@N=A!U|AHbx~+~DFZk;=`}Ar0OjH$b(1uo5bclLmk7Khj-Rb}UHWAMasfRe?#lYh?yp z`CEc01lZX*%yR-KvutpR1JH@_H)nE6az`it-A_Fxc<^kmM4pT*a z{P&|@JpRYAACF)2_^f;Na8C zzqe-TyG!`f>(}tp8@IRS`MXQjSJ%Yw(@XEW%lXsg?B$u`jR2%y$QL6&Kfk3qcgG^}T1Y52-jTWh^Ch@}n&2%SK%Vq$CN^`)b19ej)e zl~VDf!^6+Q12vI}H^^sT)EQ&E0uP!I+7a400H#h=rfj30ELnBduD@H#k(Q+!}3gG*}0^$O3H#xqLAwc4jnq>saskDc&nJFtu zww{E#MRjwIUJc5>cCw&OO|d-x*P`|jAKYSrLaK3pQrOw@ratmuqM>9m}1f}&m*EPe@?>uYYEVYm`k4|9zvtkG>B}`t-=Eho1Ry1or#5+G=&mBQX}y5I4@m= zn{1LuQ{nyAJq{cS5knAlM2`8c{eGm+Qr#m_O9sohs2#%nad3immAFNvm+?%`;?PdMVLY_=TXEfr`H~+HZ%(jrH&ffGp z<@S=|GV{Gqs*Ue(X>U^NNjW}#`(%Vv?CiDqvg0&h)nOiH658?9Rxzpt*F;5DG&qhT zKK=zjx8@OObdt|Fd+ki^O1BX3QVV|PA{Ea-xJUoGOI?2zw&ijc+uMuvg6MeEW#NSW zwR+9T;3A?A%Bhmpg1T>l@XNy;?Q0Cq__g56=0c(Lg$YNzKNRlZ!F)xM{~}S*M>p98 zzL+t?7%C8X`ths6!9cpIOONk)ahf5?2xBOm-d&~nX(sHBkGi2H(itWil6sy4Q`SSH zw*JLG+`tOiQ>mcy=lZT~*-$<7gc1cNz5~?nz|a-T*gF+$NgQ_=EZ?Yb_A;6WanZjp zvK0PUT77(MaY&+H6RY?a8zQ!CHMCRCXGnp`r^&AP6>Jwx+3%yA`N%TN)E;y~QA8<4 z3oCx$74E|65^5Z_G9mBb_=A543GFo3v(Atqw#L#q# zkowWiq*x|tlXf1*F4+^p>z?+W7`46(DBFMvvC~iC0nW`E_s*+$=7TKYeQ6O%V-Auf zKpam(3x(XvZYIWpHVf=}@sf8%Oy zHhoD-wPVDc>#|~y^i#;AG(?(1Z1LoE#=F~&%B^m(q)*#%uAEd5NOhjz)#2W1cyiG6 z1$pp3IU`kep7o^s4gC(UsB8*y8s5lWaRTis zk>_v?4L5&7S}G^+J(?|IZ+UphDva zuqfvu;@;Y!cK%r8$h~-$rZGLL@%g9D-I1VXTa##$5>9`;IHyS9pE2h{JcnooBxI77 zXN${E(z?U?Pjbi9Z_92-yNTq-~nFA>itU_Z9 zpM0Pa_&rW^wfG)Gs)w22teNg5&T&AQd%x+SUW7U*Dq*=4|}NNeJ1 zl9qHeWC2+Yg7N%e5adL6K04n+RXbT{eQ`YW+v9|&tjWtuvD|<4%G(r~6%2ty^6}xh zJPVJ)P>s;1MIOxhSY0dc)kZM%y^HoGJEZTqLQQ==)io$=OZe}$iwrs*f4t-+H3wx|oFSO5iUCl1{ zQ(VfbmYF>{TtSwbbV{D)4$a&l;eT*_J*G)hg+C~E4O`|Ix3&mVL*CTe z3+IaK#Q6y1nLaNl>R^i!Dlx#X=(hRKX8k(|ybipelV4K1RC@N=8YGm1tTxVKmP}wy zlBHSUJJ+tSEVQsp3+7+;L$)LS}$=c0>b371S_$k+a5J`?evUyo5^u zOZnqY2tUvQ+SaY7TQJdIVbMT)VD*5a7!otNm{MVs!HHq<8bk_m+cZ$}wshHdE94Wg z&b~Rwc}1ep+L8ewQdowMc{07#hQ)owBp8T+wLlNg~0YMLD*9I z!?wL|G6o(Qi~1cLe^o}`m8no+UweE~#FvPeM+W^QQ-9YoUh8(Fd+T2ZnWO#7lMttU z(0>l%d&U(xG4e@JEq<}2q%riWDcN_#3zmF#5<8JN4thIYMr*9ro&i8WXFv1(;z4h` zqv-1e6`&|s&CXZ#FiX}jtS^PgxRr){=Ki^i^Ojmd_ ztE>hhZnuklGkvpX$OZId<6;&f0mT3Np@#fQ;X;DIlGAK8^Bl={(-VtHd0vc60?y;Am!Tut#&7Nq=%9-%8Tjze;xXyNR)Lb#q!jJIR9DHkMWAGQYD*|26T=%qI0>>p#7qaG%3Ki{1Pq!fv zT>JXE1d0h|bUS{wrl@%Vw<)JxC@PGuD+RK6MiHD}54KRAPC+*Y>7-X(EjaobbzUNe zpV+`$&xpBef1##!Q?AbTLZm#5r5WdS@F1oz8*Nrfc{B5mCOJtMAKB}z#}i)0vV7nL z^bcC{C40iDB+)jbgZ|Lqi^t;QV%(* z0)J@BNB5xyW(bozTZGyC8(S*k?Q~&Jg;jjSq4VV5>cT zYWMW8FSt-Pb>2HB-xB~S`AiDEV|dl#V3737s0AN}bu3%}>CB zP?YP}H#&7`(}6B^zZr|O^r6%4SDnYAWJ=r9^nI?|&MX3Z(6)ULA9>=xQwIMBaFrN{ zm<(_~&qMwNvrQSrj#H|I`;bN-*F!&|^9@*Fo;AZVVk?sC`%u5&x|m_kG9-R}N5nXU zinCnb&yK7qLX!%nU6^;kS}<%pKZ^hBF0jXQjA!`r1>xZkBVSj#9A1WIOSWdbhv8Y@ z-i7%8pn@b`F1wi-;8tYReg#9rm=zc#8|_UeH%!JPg8kcqb>#~YWvkM~4rQ1o{)=VB z)Ttp01Tgy{_&5U7O(}4hAE8= z2~{M|zd-UNU9VZCK-f6D40{3r{26a*%jc$hn|J^rgWEV^T+U}K>hyZGQP7`0zxjwR z;DnbQR>GZ>Mxm|{cr@uh8f5+RgCgY2Cj)#7()U}^Nw}g-$ zs+CgszoQBOz=Py5p-UTZgelxX?>%=JSMaS4520-_uoH1miu6EmCdm}$RghU2TFRkou#iNcQ-Er&0e3L_^pXS?RnGHgPb`# z^iYVF`Z21*!-)!_0(OAphz*0n?orP8^b{%V7{W)M^nXLrG&Gd`!OZ-C3#)~$ZQj{t z;e6+u?a=Xv68Sl!yO8h2V~C@ZiAa=_u`Od>2%AWM>9Kh@Mx{bHF zT0rqR@4Kx(&zo zo_3X3YZ$Ex-mm3#g;*W6Xid^&c;KmuS@M-ftfk^h0D^iLZ&-G~mHL^;ID{^4GGo$0Ri%lAfJ?{8OUV>vQIUqr3eVQO92;NAr}wsE09oZ%RFz z@+TgtgM_z`^PCsvTW=*C2a*jWbs|`V)aNkZYIFq>Y2Eegxg;jgctMkPfm{Z z(qMP6fGoV18IN|#W)6@3`-(PJEdWO;nX+typy+fKMEUXtQET?VJ)~dxg;s`p>JasQ z#on`7tM_DFNl2>`*GDMZXLZlF%}&gpZRWAJxDYj}?(Ak2uhvI~Bj?ouF3DM8&c;lS z1MNyW2l>eNB51g*ljep@`9hfIj9+O02OTtpn=2xRywQTT+Zyk_ayUrfo0&)6Li_%{ zjN?r0^|!Uue{k`hl3Kb+BXq3wFn^0jDBx>-vaZe(zFQfjF=3}rZA4X_sd#0I7+?x8 zLb_ALYTw?E&x42_K4*CkIaFi;(jhrb@LWh>cv?X#a3v5o%U`@av%*QY-e7v#!Qn!NEdyvqb4oAWsQNC1WXV>$bMei#II}0AWhs#nqeR6bFy$HWyHk?1@cnO=l`Wm%jTf6Q6H4}t+`cNHl zbhyC(s_(U^U7jURI;ma}MPZ+An=?#?Cx_z`sU+cV50X9r0gYBb$o}=r03nEJ+MG2t zcX7swQR(bV(o3PP)dXpG{BynFdZr4CfGQBOz3|K0f-*_^-0H`c_Ul@sY@^+n@vd^T zhNqtcbgPvcAulS6J=GJz|8k0~?t5_B#3eT;^ z18qge48hIF5pANIkozsQ>l~+ASHBX|4FO`L&rcvxI*@4nmrd*N6i{|#D ztdej*2QY^Lt*Mw-)Q2Ku#LV>n;wE2|cZQJrIaGxux2sye0MY@I`CkM{mW{f+IMaG>vs9) zKm|y&&LGE9dd%&yZ!D#WM134tCDW8t4^52|wMSjGk`zVcRR5jZ(ZjVP9K}3x@(T4V zA599Dpocb1`i2`Q^?%EktdP#q9JO8lHoWNjpz)M2%Gmgk9CUB?bS;Da#T7jAK=Vv~ zt#Ozlp}mBucsP*R(#xSC;zeDHF=ftxFXxdFb<%swK2cm#MV8K8h!^bdiQp6c+eL5V z50A)MIIi{%fy~eS#5l&oX-bin5?Op4tc7=T>0H?@RV_ciw|A+>DuF$)UYm}&rFI|F z0mkmbn>AcpqGV7w^z8Ho3*hSd8qUFsBAI6y7LKcIA8Y|q2U>_7vD~;&A~nAZK1*+G zBpLy+XnDm1VqRh`c5AeF^Ft=rL;M%mpW!uMz~pJ=i;I;0=9>~ z8eO5Rr*rKE3kER#yONqqYBo@Mv7#oUTvz4Yq^oK<(6$4cyI2Ene4}s6;cLK?;=W&t z4vKNfI_fE+wQsKjkiE^ZV3n#1=cbd5)HF)ZQy4*aww{;{f^=WAvb2q%&Vm?E@-QjD zfxJFVO@+CU=L0k(9fZG1qH0|R(X_~T+_a@O!uwckg`u|qgKuZx*S-ZqnXk7^zS#EW zTo0jn{OM*nD=QWiI)V4;gE>I}=@GV56I4pUDK-H_li0o1^9Xl0s6kQPjP#!(Kn(3^ zXZ!im5`;$qYk-BZ4vEU;+@IY=e&?z$FGBTY&OUaU(&#^PUp%1KS)K=*4utr@ z;iK8%JHiSSH_01>9pj~lurkF3kpk|QzDvwDrDs6>bSsh-zS<$7{2-!ZyAyp=bp$e- z#(kVNOZ1!x(1~tqa73pg?Q1qEy=D|Xe}l~;riyFSGfdautGtRwdx zUrhwVHii|AVF^vL)=yVWb8wP4H|iZogkgR7$F)E1O4OKwR0~4yI7tO>O_$N}d{jV~ z2}y(MGbp7Q3DkbKI_C1Oyi^al{-pkbDC};F#6Zt#QXw|anmr{ia)r9cdXY1SmLi@| z%-eeLUBs+3|LWY3xzewjAF@zrzyweQ*X=^-Z9&ulY_O=xT4^AZhl zC*d!ysmEe5LV<*6pz*QXiNeTVNHDPHR5?@hKh%Vpo*8}80cC=qNv32FN$}WdV1h;# zO8X*~b)l({d5a}O(^hTIJ<HoI2Tn#8g&?pQeA_)K z)i`^*)7NrqlN8g8hwSpPV^YMrJL<`hzxeW1e4i;MbSFD7mE#k{LlCynHpI=^tih-PIkx}ae`ldIvSG|CTT`y}r zU65&QJj^}I-6zpT3^Uc}Ytj}2lDi2+Px6;0`NlVU1%BLg9JewM{QGvN!Kt}6J!HAR z6CmPaY2f0@2St#;4mJziG9y|En15!*RRV9dor?0AK;q+#3>+Z4`{`F1je*2d0W>|jz~%$-;v znae?C7bTJBq3@zLImnr;3|59V060EYh`S9t+&{x&sTM(T*GN>W0F>dRS64d1cRtNr zh{5q3RyVeR2dFcu#kUYVjxoSOok)3REp^kzh0Z|z&nbA~$epugnM43;q6oGkkL;Te zrM3K+Q=9uhBix1II2ptcX;?&kroZa%WPr-$w{*tpG5B#|<)$3A+4 zryGmo)jVjKl>N>#9BdWpZr4h^otkmC{k%vO?>GWcKj}k%gkwSmI5_?XWjIFpQ<#Fs zYC?}w2JquSI>Fs>HYLH!Pe=G`{?p+N&zx4GCIAYwfW0^GHJaK3dm#ur>pVMbFL6%3 zXLQAjh}NCw)wX~g9#6=52c0vgUsI7xP#%dKmAZJ{K>3886|jr$(mnou0-`7J7c>4JTNdqyfL~`> z{lIY4!XSdY3CdqpYBdR#%*$&o+xw3?1##Sz`pEQr;}~niGje@^GDqw~j~5h%DgP+9 z%Ig`wrcA5-1r-}(`5jLu<$9W&j9@dKK|Jwv)vXq0|E2V7vv7}`nseiRws(h~LwA@X zu>H_YQ?sj$yDEZFL5w?tsx|~{SUTkTj)aI{BU6Bk^-?oG=kAByA4EoCp5?0IoPAzy zaP)Ob;fF*h)IQ|;i7vzXSJsGPgG-vcN zZ!2Z)9XL%pG6D**=$D<_vBT$gV3|t{mO9}Oi)@;aZ6)#i1;h+7^s@QuM9oa0eF7yH zWx8-o<5FP-2hU6Ut$LIU_0*}5>wY%VFyUqCX0a;>qMy*+@h^2d#Wo~KjZu=Sn%ILx z({t2%JXRDg6pFe{s0%za7jq{1teA{zM=h80Vv_dT%D4a(FWZ|RIJ=FIJLNqbsx^s3 z=xkW6z#;ZishOcpKHEllt8se5Jmsg|orsk!iyA-kj-p+wxxS!gBCGG%blbAScAt&= z?c})XWXIv@{2qS8{gy%eO3^>68eq=K*fdL%?T$I-j~6t%>*v58c2k-u^!B?ON?WFGE+Iu8;7ZXJTBz9ODzAR3-kinq0quYg6rkY0#=P zt3GK9dYVA~Qo=9Ptx`Ml2eZ6B*T-$e%XGtWCl+y#ie&(y8R3?NdhQ$2{sd zI6*|*;ugJm75}=l)NE5*y;6na@93ztQ`MQfqARI5oAt7te5ZhE%gLSn-(SClrPZ?) z=W*4sdKJm!@wl~c+r?Az93hd^fLv3NHiAFbrTd_)H>B3wygvL;^p)49F%lD*cIi>v zA&VW)artOr_@lPe8(09e@#U!|02$Eb)5{(%1^F-!Hook`lX`yc6B0{O3RmD`EhKC~ zQn(tuSIs#Hw80Tt9p3>aP=p3~f1)?wAWt8`rYVmx^O?(Jd#bTfHqNoUjw42R=Ek8e z9hAOsrDAh3cBs3tYo`s$pVxf#@nYF>PI*4|^_3k4?5nZeNO{z42ZG3rUK!Ho@JLH( zd-zCZ1&HtIrcVy@&!@J}>=SZYUUWJ@ zja<18C;lAa_3y-$iKhAJt$RPH1DT=9zw!T5@uGR_qUiGeqjEvMCDBqd`GaqMv-7oO zqx9A|P+{G^KrgwTS8JX`Qq2!XG?e}!uFf916p8w3mmS?~g4_SdaMTw-`9@Yt8&Fiw zdo{yYw*_%FY|IV}8Ebu4R>yy#sqny%>&FoK#~t$lPHF*Kb)p1f*=lT@D)k3KLY~>? zU?hvMo_v`f<@bbF;F$bjd0^>x9A?n6h9Yvp&`ILyAiSPs?PHop@w1eFYjKM=tK#V%|ZThlwV3)Pp+LN~{3NZDj< z+q?bjc2RM)mo>?rbnPxI`1N9t!#W@>R#A{fQI;%xva2ii_+mwh9gr}flW}*t+tLx| z0hEjj9i>q;r25ZT06KG^_=`4CN65@}x7Jp@OV06EU$*qM;f0n~Bx-Mn zwuaU5L1x#;PkR2Bk4L$8=|L9iC<9xS$C|1QOYQ7=U-^6L8 z4tFngbN$44c*k3ow=#NE$nTDhMkiag;l94BL$py(x*L`-kYVyUR|pseG?69>@^Hld zn8iodUCKffNC_=6AC$Xp$$WIhMUFjDm5SEZeiNk=uIgd`E6o0v|JR=?n6`~>wwo)V z|36m=exT9eE~|^DR%VE!S$ta>$nt#T;QTY_H77%X+cQE>Z5^J4 zOsIN&IA--$NOlNFXXd7N`xLo~IFMVWn_fTpWcCgs1D$8q=ngT>vuVv1a)r_E}jh=<@4*rs-?^F&gGjW)2P-M*5B%uZinkdJt_h ztm2wIDz|frp@M(_cJD+ltfwvmoQJ0+tyDD@=+bpQXw@D@%;zK=PJu{sLz%tDxJfG-8{6f}RxCaW>l2CAw8ca*f+%cE1+n7ea%DD}4)Y zT9w`|A(8n4y6f8;{xq0h=dVQRFtvlYfQClVYK- zgebE{s1mVV7!C|-KFFO+P286R10VYWb)JI5DJf2qLYq$n2ixC3Z87xCiOP1GnO|B? z$+RBp)X4F^_!KUGFhc{p>so4Th3;rPK0ao!2-2g+yo?7AMv16TT*@dVdnb^bwgOSX zk2Dg13U0SFI?FOzliBH+ya51@mAXMgG%3>#vU3DOPVTK=MLPPM*1 zzAkQWv0xvwfaFAXD3vRjV$7C)ONaREEo>!dZ3a1NnfBDF`bj9sJxlzx09?jc zS}_uH^>b|Oq>r|cT477Q1N^|`vQA_jHT^9@Pr??aZ@S^c$EZ0VWgHhPV>%xULbFmY)XH{k0u@NZ?R)FxT)II+ZfbtE3Pf3_KlaOkv0;^cd6;6E z>6e=2wiX1%QV_%RxzB^av*2=94G{mpJ8^)yQ9H@$p_%p-mprkFA`RR}(3TuNZ~dAv zNLn&?4tZ`93)6&*6|{T-pz}5`6&moM^n!rT^kGEi$gkgmC-r7`Pn_i=(q1;%V|tWh z7;s0!lfSy272sg>y$Nc&u=A<~y(wzx=`K*b&FdVa^No+wH*4G4&)(}a`OKdJ- z@gyLlfipjPwf?hTw>D-ktb_o=`FJuo%%5mIyro(&INzAtAeSMiMqjt;tEy_7Y9?MI zBzPs5(>jSXw7T{2-;lR>)Yu$SBB6Va7>Aov)goZd2bT2>0`VBj*x@!+t${u=(vjsn zf>IzCl4;eI&0KiAG2(~_CcdAPupeFneARAgtYE`x&l(X2-y5CBoa`TxIneyUUpKQ! z@fS`;h^yCwZs5#Q8Ej|qV4@|dpC6u2uy*ndbV)X)Kkd(XnL}_yd89)9uv`#PmBuQ^ zYX~`9E$j?Dl_wOOQ2G;$cVW+5m|HqgOKxq7X1S#Wv>dW{WC;&?DW8vxbkw@LifC0r zHkESI_;=r*IY3dKi_p54hhRs_TXU`Sub`+7BX(4lWWs8TnnMK@GNba`NQZ#)QPMVo z0PE&JJYEPmp@tQGTVz# zA?52V^uFuPy;6m3*x#11$BetxydkP(>y-T~v$?4J9!nK!6?osr`HEQ9Cx`A#w9~9V zN!lBa(iu`m3YnTqACrw#3)t6|n(8f5hs|5I3Y~lG7_vTSZow?ygHn!Vgx9asY}_Q_ zbWKYE6u4W!3={It*U-@MdsY2q^VfL)WX0i_2K;9*k8FAt! zl#=Qbeg0SxnZT(8u<-n#?TI-}ypg}3r_4wSD+`~OfQM$o)y?YzV}pNWb@IjlskWeK zs~5MBP?Z&^F*&z`6~Ei18)ULTK(0wi8t;cyLWD4mbP-M=DVljyUO#9;CuG*$e68us zRzBA+>d6`Fi$&>m24`+b09tQHJ92xHeZ$_kfB_~}nR7LlnbU^KkaWfVb5d6Tr+)m9 zww+v{$^|+6ddtOk_;W8%`oQDPX!CQI1RVIC<}VXy0?kKdt=kcnT8%orlD2A9{3&Z3 z>ttMYR5R$Cn#`1|n~71I6|v7xZtYJl)kiM=i@d-F{NP3SmCOH?3;vZ`-|r`P?I)M* zCl}}^_Xg0$<29FarzuDK2r5C8CuhRqtLO0;*I@kh-4EW2Oc@9a7r4w@?pqNmuunwJ z02iLAq#qaX>tg#FWt7#P^@O^|Imii#p!87;N*Ej8iXK-WDDYbCjc&;;_m~?RMBVhv zh3}|{+c%XdU~^>w0ObfJBAWyW0y5)yp*vqs-UO{y=5*nJogUEG4tJ0$TcKa4Y~pU= zSK`LI^DZ#hxC^ROltpPsJshy+jo?@s{ut^@9KiI8nLj9y`#2U_FlWhfNvE2wAZ?t9 z!KFTFfZNjZ)6;mZ?0#E%{#+ZTS+E^5HXzg*39aypv@9{V72W#RgR670f-vvE6E5ww z>JhVc;Jn`O24o>v%pEuRhtSc;;Mi!=VN(|90gfZdXAdKUfz(Bs)_vpfs#yq*$n7j(xZ$ zSa7lmPEV4t^=vy@Sw;3+`VDv1KXMzuKtdhzE@eWLMW5+fJKS#oxcB&^2Q%+4p%IsB zve?~bzc9G;uZGru|3mxXlMf18q0nk?@z-?HFnE|>BDblT8$nRkF-21~8xt#5m`<1? zwT?a(UzvabCryFsC7FO;C5FICJ3B8c@Qp<{4~oowk>t)QLW~us3g|j9E)R?7>lRZf zJ?yt6{wtAM*HwG50<3EMg#T(4|DX-Lu%T38L9zfsI*w9C9%axJQIO2R6B_Qp&#%h* zn2wXxMVO?QYu?sOQ2%!WCRwf>jc+lHX%u}lHVfUNTREFCPz$(Il#Q9{0v|!kC050L(>78 z%q<2}hXWjBax(m)Ib`no2N4ge7^bkLg^<4TJV=ddRv3Ta3Jd-IQv5tDqHP3$k>P83a1w(94wYfy+R8#_Es?~=tTTfLiM@?v`eTj1-k)>`GL zv|!7p1pRM?TmdWYICx^KjOuZ}r|yl1FJp;Y0m=Jw0SArrGmzCX)AJJNI}eT* zb0R%|(oxBOMrSRABAWx0ixfWV&4y53BPeh%QK2HO7u6Y*2wJ<^f+JA z1%Ek#71_o{V+XzLDnQ&fZz`VZWo0n*AZK>9PGL~5y1d?YhG()GbDsk_wKaA0NZ4Rg zzJH~R6(urpV{%Dnph8J!&HoSyKWmz?97wiX4m7GzM_;;PDyN&K3NOZbiU}F$^PK!^ zj!=x?lW?u+7vxWlxhs9XxP-@Z0Qj>^tru{yFEwXhwNT(;_KdHKwpkYFD@6*&>EF?v3Z)o~cUN<>sLa6W$D>>wTJKSh0s-6ud>gE_p-$;9acf16*Ra>*wbra?O zfHxgbSc3`?di?$2R+5`svix`I)Z=MSSaD6j{R_b!ff3rN45=%{iF&voZO?-u`}ldP zRKbnh%&w(Va;Rxa>En34{}nZ*c+Y}U|7PH>=O7w0iS;!1}a~2-)+=ck8E7cmxR^T!m$?V9bJJx9T?stHVGfkXx!)0zwBSHGUBJAO2|#UQ~&U;6MC{J>Al1Fry~a-WsFLNhVKhKsTDVX-YCM&1J4WnvqlH ztIDsSix!nofKg4A+tMF5Gk|-v!D?(56Sw|?k%A->0pg;99sfm;%S>s^8V52gu9THvT@gLWn=3U9rZ}~#L~8=iL27<40sBKx;GW=Mvq!`t)g15< z06;mni=gmAOPgLW)D!{@pPIab3F(65z*0mfA%$50c8J|>LFzU zue57O%Sk`eM{v8b{c&hSo9o5Fahc_U|3>Qn{e8=IZ&?s*uFP;!F)pdtarrz2=_c)C zLyhNFsdk%uGn2DSeh7sJn)R$ou->Mkb4DFkPyK|b%*`jg56JGflWaX!)!b^23XlT_ z!zNK>NTRER^nUlGd543fv<~I%1&J0|q5D`17Ckllx|(C$kp$RYY+9(L(ntb~OU=-O zHsn;*^?j?oJ*z%|A;9W@rO=T8aS&dvg=&OYd*U2`VJd!%{sG?#S2p#%H_ zE|3trfnAw_0QXe6^XetzrHD?=m6$a5vBSO~;dsw(*5;2yH(VUQq@4a)&uSV$(*5!* zIL)D5i#G+Mm$*7#+?8v;{p-A?8{}cry}3Gp50obW##5;3JVh<(a9V7biWTI=*Hwzb~O{Q8YYk{?#`=UyP0D23uc4AP?bTWP0;h=lVXQK806Xllw zKi1wUSd^gI)}36_wr$(CZQHhOV@=z(ZQHhOmR)e zw}##9{7|dt2h?hP)<#5)Umpt9W|KE4d}13{WWcju&K-6CH$E+#n4hmMln%_cIzPSB zavNGt;Yol~uoriwu0j0*pOLTb2E;PWzC^wFt|8t)j3IAh>`qrvU(%HPOuINO*2&1 zeH%SE-0KM+Lp}-!*>u6Pv>%S z6WxT2U`?a^o<$w-AR@zr;<;|iFq=JONqwaKV1amHd#zjj%U@r150HGz5Jpn}l@yBc zEr^bN1+=!%{M%#xwnmdtiZME?of3Fs9hx)d! zAc;ZeGDwz}u(dN$6BsNHu7v%TMM2IOw(1902j|=!FK4@o4`0YJ!#2*)WzdGX{#Gdn z97T1wR*wX* zKZ>}xO?plXbOGC#+u-=;k}DlG=k6fe&6R4{R1p13|JSJwX7b`|LLyZ>^uCx#SlsvZ z;&9l=r3#wtw!#3{5>zjSJ}SF8HlrB9+{{@!q%q)zd0+z)zB1sY8%jX~Xc=WZ1(}5h zXAKYcJ;r-hGQe*Z=wVkgsJ2ErIq4mwbQO9Qp)j1nwV)GuU-Lc-~85(x}QIA;jhoE zl@@J}%xVL1rIl5<2FG(59XDbCW;Y&F(}~R^dDkNbN%%bmo%6v+YHx<*MF-7H9|Mmq z>S9)ASE1OJctR)o;_jW{m&pXa#NI0*hlW>rM{Ihu$i%k}Iwz8L;1Yh`bw`w2c9vCp z_;eJpw-+h@*4cW?ctH5HhwOeJScw}?oHu_t{N=qAK9gF4^ORv7-ry7{_?9$&O!(o9 zELsh`8k)tCXLA3g#N??M{)PPY(6zx@A2x!)2jV<#UDSo8AxlVM2AXS7^g>eu<&N_* zdzeHpZ7m6~z@_Aj{|oN9wb>Y9#Jy!~MICM2)@A*v|G38AVSX4!iNyhb-A~6!DI$>( zV$WVP9#!~M4RQ(t;i_1^i+CV!i%gC2lt{jA)$eJAIV}YiVHU@E-i85}-`utJa+mzA3c@Y% z;A!veXglSxH^PF_VzW*{b@~^W>>Uusw=SmSnjvz>hwO`i5IPRy*OtQ(g&VFyNo5R} z?bFE5mLo#5$-npyl7|{ZY>IFTQ#aeu`GMz;XR1fPGUC4UPcpvKa%X^&8!V>jrrp{M zGpN75G9$#gZDE#Op9D4pGdJ;p9~;nnWnZDz##K!L3i!b5s;m2-!o3!+*NESxegEZH zM~`-Q(cLKiueyaUF82SJ-;J>Sr`|Ons7H1i{r~m9^WLlLW5t3A9Ww_jk`DxiBsd=CjLPY_sR5j~|;oG8nUo|9UnZf2q2>PM_jb z@24^B!u_ByF+PYY5s}W+SNN02+PCVZGOa@$m?{c#KfeDu!bxq8s_DHk))O*q$a9UU z)nG`MJk1LBq9{5b7ZN|5S=zz?EZJWh`gYc$*{}aFjb4izzL8JS;SMy*tmimC^j6@2 zVh4*eQ<8a9iJq#eieYcx0gU`al=H<^^gT9@5gw0+{IC&!b3k`NgIAIW<8zATd>LeMO}e<*`K}>bxIdz|SPj0}e7S>P zsSDWJ;+91vkVf_mtbzvAN~dC2S3FpSz1;nQAdx?3Pr;oQPZusLHfTH<#`YvXk-WHD zYN}@T`@n~A{?Q-lEk!!Fh!F>4HFfd>7*CD>^hGCfQ8d(y5iB5!DKrZEg$+kyibmzh zM92RFckTThrf1=n@;ZBDZ&axwb1H!ROhges)~YaheqEm>p!OeieNR|LivhWG@u!{x z!Dsas5mXd1G``ef2qMs5U@1LAtoP0j?wrEr&Y^nv9gZ}g%9XDv_qFjCb?pen9q^oF zDO$7(9LuE;9ziM+4ixHoaM=w4MQ2tJvL2FyK1ZTUa*M;n2wgaWsSVB`u zNpYKGmifS7Jg19-AvKMwMm`DR#N!y3UYF^oLL29~fmXa`oM_wnXwY_t`Nmco8Dq8# zZp9lBjm`I6YBGd#o^AsC>2HKlA{&D*c5VKYW!>Z~D?K2&mu3LGqCaM{c9)K^LtmVh z_}MjeF{9ZPnap@G6`pkiHe`bpoXO!&M0wO=tK*-bK+uM!%MGnhN?kI{F$p=LGYtGQ zTo%4m!Q<}Bcr>JHxi$2jal4GB-itQ1C31w06Ho%zJKn!$>1>r|5cq0KD(tWnEsA_{ z2dt(|xc$2y@!D<2s*gJ;ItAlyX9kVrG*r%WtMWqhJHp0cZ3^`};knTxuWj7;eQO~X ztT4kh)HkqX){bCU+8qfQQwl-I8#hMzz)#oB~_ulb$(sMpyNK@ehie0nCy}P?>a= z*b7Oq9nQB2xwHsBHRWG!+lcuT&s<+F&n%I8*>73N6DuNYXM5)suxKEMmSImG*|f-L zTkhJ%O=cX!kSll*7+P3oU2X)M-Dj(;kWn%xTtU<>X#{Lk{;) zW<1eib{Dm|##8sPNnKD)fHIkHJziMn9HsV;$$iy0*M7QBr<{CTha)=f$myQY!$+%a0*`8P}GnSe7-RFP>V`c)d+|6hM*f53T%xpo`i&J&9`)~$rL}2=}Qke z;ohIa!dE(PHpcHOUk;J%=&=^t#Uw;Ls0e7FLSfw(;-mX~x5)c)8&?G2U{sA7k#e!)_Lh~C<%l0j}H<-d&Qbl#y+ zB>=p`ogE5I zMhiF|H)t8WqID^47|hs}lVath0D(B2#dUM%CvdI^)&em1B&panaS?XAEXP`=A1%x)Evp2{O5L7;6P3)AR29p2E z9u97@?M!f$>2q~$kz+QW>Va*RE zdWLJytw1d4LerFTLq!XrFNjXViumrTrBD+vbZFupFqdz|W_Z&ICh>&7Qm4KobC=PR zZ6NE!nO=$Pl1({IOOlu^6d@XiC#zXqyg`v^N~Q~Y$IB1|2$*qznS6(c0f#2KJVemh z)4#B!b)!bKDH%zaI!yb3&P;PV#5PvGax~|h$iB*mhXMy`nxl=ToP4q4)sj32n0T4Z z*)JpE0h7`8&~(H<16Y(P)B#SJYObyP;~Tj=H?WFrEwQ7KFULN%$P-X??|$?%&-b7z z(mn!005>J#A-+5{!NEV}3zwZ`wI1?}ux=A$z^9Z{EU#jUZ-9&K^ii!kk2w_y#Qpj$ z{OjdjM8qV>i#VL_r@YjOcvfOz(O~j7J4q7qJgQdh!3zNQ`X{Or=i4ipIXDciTAn=E zECKYFiJEX561x?akMH7+Z-V{jW|iC~-clJ67p#IUW&@CIAV?7kaZ)O@8DMGp!+USg zhSCq(g;84iCb?Wpz(jWQ>@eseBCH#%mU{;x{%Z2_{uJ!Exuf!u4 zx`x3x$4EE5KY}IhN9JcrLMul76ygYV$1Kb-D#}!K*>j*xP?p1C(|i>6PX9j27rBXT zxlv^6NKi?t0zE;kJo(nv9FUjz#yx$kuUo1q%!9r>P~7job~%OL+ay(|Zl6_m!a_gC zL8~FPn)@T!a?B#`?x;Nv^jBY-_(!e84V!a4I)x4q%JZe|V2~cso1wH!o}4Yds^R7u zF`E%rTucU93qr9$bL~jCN%do~IKcY;syf$Z??2ULbp7Fh?(xT6a1e*SzV*%v2Tde( z;ZOsF+E5{h#m8#*%x9RpF-AZK*Q$x42C*rwz{NC6Gf;SDJWov=r=g3e{(?Wco^fjh zTO2!_7%t`SA~xvnLGaXrh9Bi0Ex`AwVN`EQRd?rVL}~w|pTkFvF78q0QkYhfkpNG0 zoM5K%M<906jnZO$8b4xz7R}4Zp)e^^3330Fdg@-c@K-ob7Y7oVJaIfgm3Y&(d9=k1Nw)3u_}qQu4i&bU!EKZvnv)clCTPq1BpNL~S$QqF=LpXLM2(0<25 zN2J+VUbxH>lParDk1hZ4HmjkY_BPrk)2KY-^1YzRJeWAwX>2|v*U2(jQ8kP8fL_W5 zpjzF=2zmgVCc%HV7m72puL)%A+3WPYiVbUl>eQ&4KPE%Ps9j}jbr5c|81?b)Z(Mbz zcG&6A>qgyWx@DHBuMRI9aL}p==}J@23DAjDhjw|6PN%;5)y)&{uwlr|IC4d&X`fko zGy;j=#xJ&N;-;e;t5uA zWKd7e{upPnb@;G{5x+WGQQJI16SOp`WTBAhMWr^gmVA#2lC;R-YI+hgup|v0G=HvL zafP$6C-W7R5BR=sA|u`yCg$pRzQNT9gJAJEd;j8#3|E|p`_Q=i$NCP|A~#q?8^y(YVKP#EsZ_pbbUGppO8fWTq~6 zkT)}=TabEd31AcIb3+ApJZ3?EZGEeD*k_HI4lnKyJ0Y}tN%CbM7&PnVKI}VxJ)7wD z^pTwA?yr~tP1HvSyEVvO_cJX>Nsm7gQ|ic*L8c8+o{cp>vgFsjf|_xBsPh|96-GLp zUWY@Ik6oKX3byUrwdN^*mZMoPPV1AuYH29)rjr?!8pH{i?k0WbWdRg5x+%~A{ia-R zU#|{@^M=M0n+{29@ILn_R|$3`;=Iouz>F*2jEQxL5I@j;Rb*6`){+~-g$0OhUmZ1b zou&q*Y>#U7nETq!*4U*o$0h@cWg@(e91?sygcZV52HSoX`a7meetl5L4uh_qD}L{# z=fj2wpTVvFDI;lzbM~#>#DJePTw{gkWl__??o;X}v_=ZedS_k6tf@JPBHkB0^FnP= zEdL9&V=3w^?TumXMZ3tpzs1EH06h@e_5H;&;s@ZhXgO(K!#9)V1$H~1bCK!rVC3>X zF?dK;XgpI~dUW8d^l2vXXRo$IkvnwfTm-%t;B8uO+6Y_fACU>LCS+RPWV`{#2J3;P zJ%ZE-U~i{|^aPHTkJ`tQp7(H*5K=M_Fh-GQhNY7vB(|+(iiVQE8EFUf^;Ka#h#iIn6 zpNn3Z2fAZ!{;tZ@xt=rQu^{qhmiH!bp7HV6jmVr=znvhEVd-M$b6K+y7n9}FAAwCD zCVs4!M@}p-tN567qm8#3A(q5Gu!>DKqa+nqLAE%w7Xo{UNL z4sT}1V!E3IT9leyUpRa2#`hitR|-G3`-}>qLjjADWZ*mkf{m^rDiJn;|9k%Ro>vqVK{-lv@&bPB6=rLFq!@K3&i@75EAf!dvIXOa_vvjMnsRADa|8wvv}j*5m#wl;jOz85Hq! z?ksWb1MBe3G=4Q}8R2VBQC9jf)Bdo;Y~43UP;Y`UIdE08BR-+WhL7MfNK9d5Zk$0) z6&WeJ@XC*O*UHa8!zDo|YW4Bw@3`=;qa=&`UpA)l42cDz4vTd%W2V(-$_4mxdrdP$D;K*~$6Kl@JkbSp^VHFPi)z<`=FftLJ$;0R!j6e^_ zRJ0sXNFeI{YK9jv2)WMn1I7?hyoWvqAWU3rx0sY#(aY*Dq*jsgf7 zSy(eQ_~s}9Yln$HwtZC$bC_U-$s^lzk{CEBd%VUkwxdULo({pwC2f$z{^`!PqR3<^ zL+;8p*L^Qxj}fE0>6Io0_$6_yeH_jYVP8BZ(q`@LofQv zhI^E^=9H0Bj&@LsImkFn<3lDxK@MrO;gSp7$BQa= zA4X)&j*{_$nv{8{uYL=q?MSL4jlOrro==q-_tq})dbcZa+&jsx)r_?4qxVV?JA-AT`!7Io0)_`N$zOlGuI?$dL# zOz6fjDY*-i??E;#oBw^=S6#atj?6a(C~34xRBHA9`aLd{n~Jo3hc=%xI#_oo+L3$r z_3%Qx2-n}<8bu{vi})CRRyFPko<;=DQuxj)C*)CDkG4-=upI;uE}}k0y)73Gub{E# zk(y-<#{F}5uxkQ&vY#`-ssJv}>&xquK-S0_PF}r^OU@Ty{->VWx>LSH&k4zVwG4W2 z`X4Zp3Ic@Y%*nVFavkmZ{)l@8ccC?XU~o|xv$`EYV8n1_}a(Zm3o44JtTxk7A3!m1%^ZqJkYRvUF(>?w9M=pI)_| znbR*iWZj?1A!@T zDzcKnvvp4vuM71JC8v*|u`10NUA?th*j2x+b8G)x1t|-%{up)x_`gO%{J&$N6mUgN z6m0|cr}UeWzgjV(l{;6ij0@_wmMZPMr^FTl{4R=q|LKPM0=-{i3Z5?Nhy)gRsNwlh z&<4qxOAM=5kN_B_V{Y|A(OiihwJ7nzcNy*KiyA84z4c9d(_E_Boo8hJL)J3FzEbIj zb)bM7Xi!CYBle$+|1Mu5-%n?JC^QpjKtk?jwf{4y|JfV=3Gh}gwr+w0@P7RiUx%@( zjkM5qL?A#W&|_W0{+RSqxgB;vCMC9kN| ztV#d#8d-dF#v`wR{>-%B!`P4!ZDjcHJg;+W>bi-?Gesxy`5DDi&3b z|L;k~jE3j{H0};p(VA4JywddkFru{-w;VBdR#!nBAasJkCMw7@KF2d5h&AG;brUiJ zwO5h>z|tpE-1a!FSB+J^bDT~UmVTA%Js9Ow)t0{6XBj=d%u^8C!~}`Y<6l%l?1vgF zA`};FqOx}34wu6gQ^>%{+xNrrG%TJVM-g5;E*a}r!Q$!69Ft@o+ZNU(H^H~TIeg3| zKF*6H?XNlF8<=-%f66n>;2L+cPwGyrK%UF?ER>1ufrL#nMfU@q=J@G9ylf$Waj}k5RR{2az3bl z4$cD-eb81Bqk%H5az7D~>6zlS4>8l&ZiD(LCSBzyzsLrAbIrVkeKMt0Q|=k^<866a z22O`XD?+Nt+YG|Gcd+0wBxAj zvxfQxz4*e~R*&b&tDGcjmetLRatvmh<24|{X^pMUJ5(mZ2On&5?L5R!lNzR@hVhgw ziuCSPGoF2^kKi+@g;8m*tWStDzVdayWvCMdYG~7s{=yiALqj^%rX`9tQ*d{~nNunG z9_iFV_(D|oHxMScw3eemWFKnBAi*J}B9gc~H%otIf3skuQU7sPwsxIOC5wG`V+ucW zJRgRiUCN;IqpX-yG^~l2ODja)LfhuJ%Ow*8isIm*EdEG{sOIHaCrO5axkyp&-tLUd zJ#~@yX^7m>kOzv`Y{yswnXZ%3#HMxfI{L9@T88LfgaF_H{=PD~LQphm)D{y>TapWt z6IU#Bb1#L!C{5*JsEYUv8O@=u>U|{sldd3eP2hhvPz1*+ z(XBZJXqJloZfg*mz1Sv4%EI{=qnG=9nx%w@a6m8wN&T)o|Lu=^wmtB&B^*BzhwA^b zuCyIYX1=ou0#y>@Lv-JB9UQ_Crvo#_qg%sP@pM&(1F*u=Firhas?e$^s0_`8L6ant zXkdufip>@+_!o51A-TDKNnIQ~A3%p0%qeT$NC^ z2D&^P8~%Lk$uNXDM=y#enmDnL5)Xt8)48y(XloKTSrL-;HB-OovUBx%qzK`8wO+9O zLW{>++s=ZT7$upnJ7lO6CG+W=#gHy&VPZBwMQ7=hR%OuBT0S0YVs9N_P09r|)0T@u zdfZDChcNY`nZ0z5F6fu}rS&WLG-!j&tpt3x73Vd$wtyAfLStr1UDBBG6{`;er9(7= z++R}Deex;uMSPTu_4?7<@Nhb^b>t5xwz@rRkB`Id(y0#Ihls3+`~el<`h={#;BKampStAVKh|C01@b8U!7Os^g9ObBCI>x znHeY~@JaS(Js8%NqD@JGPR$GzuaG5k^XRUvEn*8adwFVsX6!>y=ro>zMxtXG-XS07 zSt))nwqb7IYT>K)!aiH_l*&(FR<=R1L>FI!HcENP19)}~5P=N^s%u-w zc+FO&tagS~wORnIB?o|8vZ_i3uu`F!k(x<%zlM2kdtzGz(K@W1B`T1|sUr2@GAw(p z0I^&ESxIr>(rgj2RN>H4&n#--K`Q+(rjjqK`XE!9Qf=iz`SG$6?GZXecQ|<#Yka#o zZbJ;Bfhqg|{ND*?Y-TEw5`;BYu5G5Ls`cGz@1&-c9jA0qw0mTW-CJNa_P(EyKy-0{ zWS{x5Zebj!BV_dD7iEuS{ShPY8S{Glz{v5o)VOtH^DPBs)k^O{P{i77UBneG5T^l9 zo9gKc!N@4@ux;YlP29R8M9bdqf>$C@KWhmCw|iUVmb-MWZkN_9Ps46vaEd+TyjoAblJ9bE3!_q*PIljVCN z6=uK>RK&bz6QbJlCh}R$@(zFp3MLy;5VodFu&vx-!H`|SSG2LC&og+>zTG59j>Z}f zodhg;gYZUBoOI81Zi7S1Nq-ULw~8N0WCUd5I`MZg7*2uxhQMRyrXCzZ6mVTtV&`U+ zVw|~h79#UWd7c5NUui#D`vst{I3PjWI$V-o=d3m;)sUQ`O}}yZ(2zpWh0a$CQ@ZDo z;<`OB>(G@^#4G_R$fy{7X~)8WkzCS7a+ck!=6uziU_2V{oFlDlF!~_R(5>A14=0s?{P1}7-$hP-4i&Cs zv=E=U!5r!9e&Fup+j(EngttG-?{6fzw1tBSvR2dBC1G1gaXS=Da3M>tuL2iyJWimq zjYGH<^3-2#Y@``ZZe+YyJ(}#636@7@yW710bJj zxH9kv`UJ_@H^a(Ld^w^S%?b+{3O9!v|&*r)|!t40>>_csSU1wsR6Dg3TRkz z4KstIF=K}r8G~hm6zp?ID$${f zSpF1z%FIrs_0al?0p&Y|H6E-w&TrCAf`3wGZ3w6h<~;^yOo06L^$l6Zp7q%8f;k*v z*;uMJ>z=?efAMdE4FvMD^_`X?>6#y=g6y^t_)6hZV{@pr}KZ_3tOr)waF zM>Ko4+*ghtNjHH3Sd};+eo0OB^l3JMkj;!s9Ifl z85eEA?=APA6L;hRzqA27As865fR8kjXOWEAJEkMp%_yfiLGR|AwjNT&AS1;u;k=>; z3UruXi#=CkZ3%F-*+t3+X6e-6T)hp5jx(P8B)QWb)K@t1o(){O|ML@D{)qPZ&Auei z=gY&ji_}>#gFsqqFrRa6zfydYeMe$Z8)*ye=xOPm%PJajQ-N0LMJ$y_K_rDmb? zX2v|`_rnSeFack*7Zv>i%R9z{>+q=Mu0M-px4)2DS33JZIRqZHOQsBy zv+6zmt?u2$g;FFXT!i48ns3T0J;!PzilehqY9~g%ALi)lgQNYNUMIjf5B(=4tnnZr z<`hT==i)UZthHF>T(l9jW-10%zk!BFTO)>gHX|ti!NE+%#8BtTn0G%cc~*Q`Uv&$e zAn?GCfZv^?~301inFE>OyM)=I(7&!WB`OdjJ)Ux$22GXPrQ;YfEzM{ zO;B0UAwq!0#dn+P36MShn#DL7m^ z=J(SG&UJ;5R2@u0BVY>f;YP_{*aWaiP_I!aa-)UT&rlGuE|&_~Xsn044#!|G&zC(9 zq3Ub%Ola_9^j~@3bJg{r)f=JDdbB)3#Kn>&=d zoR}1`fU3CtC6#3EgAe1ZB(r(*gSS=+?XCbJfhGQNt}ZL`JPMSK&fScB>k^EudvzKp zAK)L$b4|~&3k(1hS7CCwDaf=k&&ZPsf(-XHC*ojvC*5TsTc#vi(G^?&wY2z!X!&QV zYKFcc%zDvh+b!T@s8v0*NMVa?1r!12fO8ZU-M}yKfa6~xGr!mo%L(MWn2!UlFt7iR zZ0E$TkB!~X!aQ+D)rnH0w|VU_CQ2-dqU`o0_t%wBB!jWpHSDm-Ect4VanW)>rn(r6+!_lYhH9y24PM6dWIlFJSypr zljeT8FLQq-Q5s(pvQ;Hm1dO?Uu3rwy{OS-h_RwRX=oDnuqLNx^XzdML$?pR`A2P~u zR?(QlzHOcdE6Pa#a`1TS!(^-5_txi9VQjK$+?*J!WuIq)$(BSQ3dizZBx0=)VS=&@p-*5In zwRU*ZJUXk>?|>To_fIvm8JDhJ6wG}Da$V1RlB!lTfNZAMPwAb(9M2qMIJbZq;~?$N zuLrOQe4SE-t)Q>Q5CRmtf>+OD)|#T-on zVzY1G#h(Bzc%MMcDFjWW$EOeKU-o0B(yb|!S24VhOr7xBqwQZ5bJy1niP|uU?4sVR zzDRHLC*>!}dAzqsW%+4C4HM?rG>8>V_!J4_`1<=6c5(07li8Mlpjn)k#H_u7)eP_@ zX>|jO3Q_%S?p&4(J$jmSNO2pK7j<)|jc+Zgc~yjIFIhPg+HJbz zH0IhWh43ryhL~|OnBpUIf?zqiJj9#;z4HlZ5XFmr5Z(6{#?s6C*8z!{X%SgR4%Dt& z$2=1Q&w#yW0YuNy?hl8L7++MfHkG+wQVM2NhqF}nhF=6+msZsEK7|@vU5&o9X6BC9 z-_fLEV>&FKx#jIS;xUO%S-Rox|M&}U$Y(Q3SjgU)+dcMlh_}-M-z8_9m*VJR92Z-j zj>aSwy8xcr(&w#})@PV#192I8Bpe)GMu#$7FP3xv>Z9>zx>wUQtPqH#9} zCEgJ~bo%rSN=%V~u5&lyrrs9)Tls`vaM)D`<;zcmHE}37tB|L#o+O;WIUUkGcgMVe zm8HxZ3ZF2N-kH@OF$XfNVw%2(!|R9gt-|<`w;vn`$&wb*)H~kdnfzRL3xNYOAeSH5 z$7FWDtW8_u*+(eGCygZetpv1k`r66cQmEBSFlymSR&4RQ4!5YpbXD)^I&#c{D>Sm2 zm4&efO)_4jixiIUZM0H`{_-mVpYmH!JE!fS^h%?)zNEs5$Wi!OaQl6oFN|j7bkdj7 z3O?;}q+-NmwlTHTvPrhw>Ww>oYxNkY#y5oolqXxXsg5DG3#)eoDw2~Pyw$0Y<(?LJ zcBRe$f9<^HP{6f?7heC|X_X@fhnlD#OwF`py?alR2cAuhA`KRi$n3pr5pVfaiX>Ya z;mqW0IrJ=)BTz-c9pnWBF>Um3@RSj(5nS@pc%`PZ26>te~8_F+2ijHos zD?u;iPW7}6_oP=td}TQXKGn`PgmbGpze1zv_*-gys$W&^wMt3N&V4~$2(F~QGw+-&UhU{&KMsp= zlxnAYT&nxPi*G;qN$4?)qLb#|o;YjKa9a=0YZB}fDG2bnn)&B}0vU~k;U9N7;o68` zWgEwjA&7iFve}RZi1UKG9dTGCWWwnBWechDyaD^|(@CU&=^e07>!;}^Aph9bg+Xl< z@_x*O9b(Pk=gKmpmSkl*Adsk-XWpz=^Y>#JmZBM>j}@ePKH4>>)WUE-`}D!z)1;<* za?6<786EAGfO$sQak_O%Wf4+L&LQu~=AQt_Cp0E)k19rXdXgfOIAH z-Bj>u2(GloFws1xc!xcg=)0XH)+3_W3w?Z+{~|xBVrlRa?3j@Vpku9W}Dw^lP?t1>?dQzUfqz1GO17nq(LI~i_%CllP#Dc&YM;hH1-HF}? zGk`7f%wx(1!!nRCFKCo~mT-&!1BVvaT~o&4$wE#Qv#j;%^2ZL1Z9wNlPq9KU2~$XV zwnci(g_@%|Gs6=0tTdt8I5#z+0cga=%7u2D@+UR?7!;|+L*$)z7@D^8$`8NvhbAE{ z4_~q^$rCR3%SrQWnToqdKE{({Q5HInNPP}E&rdMmvVdz<ZyZDSWhTk zLhc?`A=waQ9ukNi6QzDC)e`1CJQV#3Xe)(5`cp6BZ_{Ko$dMGqB~q}y?_z3*@DPI7 z8}9~4l@N8w;L2Z<6)N~w(IfU?uNeHEJ*Jl}?l0z1Qq{vdA17Y5&rzQqzhZ`znK>bI zSk2D2Sl3^HK(kFLD`u75j(juHN))es?JJJ=y>69Bn$la}zT!ZOfPlR0h65-613HOl z7v9XTXNy;-;0^M|4nUUdGge{K*qfMpjRehXCJv>F)AI2)laez5@Lt_zmg{C?He%sF{9t;a3ggI7I-YwE#Lzlv^ADbgVT{i(=?#c zo)D4p)zf18%V=w`jkRjUlRp;V@d(eb_2%+Bpkzdxti9mD5?=P#B9Z(EMoorDQO3eO z6NP0*!b->p@hm7~F@`&&W7y@YAmyi$Zb$p~z;;i@P7T2Hm$A#FE!SNUXK#Uf++wXp zy8(&PDO}!uGU=DxSfJ(O0o0{uXsgeIqg;5ldKcYL6ZDF9=HHcy95M#A8rWq|F{H<# zwQl7V1{6h-m1|HZC(=E)e^rFx*-dI}rQuP-41uzOPI_kBU!!8%4C_n=37r>^WNb)V z|56KtRMXdgf2F<}yQOlZK%ng_R9$(ki=MW42SPAzB>V z+AQ#zDilt`l49j?s3w%^{wcj6GjJmA6LYQc2P6j)>^tI^h2@suyef+ujPo7KT~{Bp z!5yFLIMiV@%F91)C{m4l^;wv28(qo~5piy-*Qxm8{^k^3oU+yxy> z-}2yfJ;_n+g2e^UtU*Zc0J)OPoX*CW(&{kp#X|@UlsFV>d257>oUkW{p+yZwpd`#) z=rcchv|kkzyvRre5r>TkPY12%(%}}UR5sz$W1fmc!DrxBNE~hQPGlskoOVP=mheT8 zK+Q?uJ$bqa@fCF27HGYkv7IJ4eeCy3` z4vF2r0y!&4-x;7xhPZ2=hvidUoqR{MSMOYK>DT%6`YL1rDoAme1)jb>bcVd3l6~=*U%wm*G$Y){BnnB&Xjopb z*|>Q6W4Rj>fz~EOuqMF)_&R=)Q+=whpZ+hDJU>65Q zi|3TTODZO@_9Rv~ANCeAYWIUwnSL?L-dfH_R_y{j?Ylm*vB}R@%H1iI;>=xaJ}! zNPBT3MWwbtWTgPR1NDU&H$V?fLJ-1qx>S-Sdw?S(8()1gB(q=mEnrGj9l=0jWyqqdI!;Yw9uG z#J47SP6U;r7lmIT%j@8PHYqTKe613hZo`J8!pFT8M8-f8iq7~O0m`a!OpnX_e*t|! zg1`9OYbxK-%nWC{jLYO=S63~UPv-i!qa6+v0Nuw6(Q-Cb4%Lyd#L#`r*oJVzP;;bT zm`Mz?>e}}z4^W-&F$f1Ba2s0Z?BjtS_1*N;L`km!^GznnmJ%c2KP-GVXtA({Pa3cf zyJexuhrTaZGp1l#T&GhwmL&w`GrlGw6E9GD84z17J;NI z!^$yrt}(oB(R{E0&;xfCObIS(XWDrqJtqu2)zK3Pqv^J<=6%mHGOip=iXB@P{Gx-KV* zq7VBpSGdewe1pwQ6l;p&D@?+xdR*rz7ZT6jo5nRP$2@0qTN_<}y(+-F?%ZGveUh!L zv>U-TVTEw2mcW* zOH~*>APASxW&Qpcitl3(n!CSqK2&&vUHtNq-I-#<&RxfVZa_6V?po>+xpJDR3Yfv2 z$IvjecQYs9b1g*Kg(f2FF@rJ*z@<{Bb^dHb-+2a=JICW!Vkj_m6-$Ad*5S+ga=~D| zmn<6jTkn6{EBQaX*xE@;R9gQ(_<+7K-^$1fstU2o-410pvMi(54nzKjzw>K((FQjQ z!2A)l5xp$aW@|CDh(8I_>&`Yn0HE#}9GyAvXG$cP=zuVkN;6-Yciu-1HoVqz4M(Rh z5_qsvKIW?sd*0a7EfGwN2Rb)ylr^*#Y~B~tDZ%9+PV#+!w69rKsA5x6ztdk}_&JR} zxf>nzXsl0txIWTE* zc0}5xPtUJtmfRuPy4Af@UmaNKg6%Rilu5v3w5RG%{>EQn&pGyi;+l7tvrbMho8v!X z@DvrGXvcprUHc0#oMSA!I8ktKa2`NAc@IOU$(5JPYsg=}FHaB0$a#smoUz+s1v3;> zAY}WV(J~aYbj#1WP$_RxBDgW$UZS!xI7S{tN=3j0ri8E*f+ea}7gbt7q~G*8fPw%D zX4I+h@eHm0#uYat70EQ;*kDdKf(iB}QnR2z;B3Yynf4!3hH*VS#j3(kgIxGcpPc|0 zGwCmZhAu}VY69$*Q5csVsZ<@J1Z?~bR(!6(xTCEwpDTO*_ysaWL7X<2El29ybu-~T zRF?je2fxi=Mb0yD|7(RY#%wGXvp(c@Gs-PMwk4}v(N)!sRR<6n=!VaG_32?>PjQ$f z#EDoJn*LrM*=e3qDS18otv9tinX2E+U>w!EubD&ujX4s-AXU`A!WbVt&}a= zHBkAI4QGk9s_)?DeL3CEcglivP>t{4(@~*sXr?DNKw(pzGf6g$*aC6VwR_MAw?(^R zFQOFbT+H+68ArQZSkZuQi*)9#CY2$z!wWN5(}s*#SH={Q00@DPKtprn>2BQYT_d(> zD?Cf;R6oQys0;C6Ih-J!Fy+Mp>hM34p%cA9&eVQQNqj!QPW=a8573X~zIVg5Uk|$- z@cm@|PU-$l1il@w@@&2h@^s>SK8Wk#*FPqT{QZpl{=097>6&*!B?_X=R|3kIk52o|KOn-;z0`1p3WqdyQcf<9Ed_Kf}O6qrJ z{F+SQmE!9D8Jo{vR_CgkrK!LTra-H>U9PSuJ6YqvRR^>F?3=9kplWOeL6Oi5#mmJ= z$mj@@_mHq3-(}ZiWJ{3f_6N8mGVW6ZGK*bX+W0a`w|Dh#iS*;po6l3`*5D-luw29@ z$9@pRkHgS@XTrqq`({B#)$$lOB^gijaep0mn`zFGjm+6%i}do2fvc1-h4Q#HF`M0rjEO++eT<&0p*P!Pe7G(z#AnAcCLZT(=9cyQNK2MWIc zmE#&})8cIN=Yy1uR_9iNc<%jgX$o7Tln+k{Aa+HTVW8nLJdurPI2A_nAU@LMvgv(# z)o1;7She~#V&F`K5u_ja*7!|Yure@EGQuPz)QpODFWRvkw@LubD|r*P^4IV17>4+) zsyqWN5{=O}!4k}VsL(?{g6EUVCf&sb+QqQq zd=p?f=1)y$$L%QOD?d6xmYhuPyc&l48X(4)+bKa*4jp8<3+=gV!}tBBDNgh zcrnL0ObvJd_N0^hUdjkx(9Ew+PQ74=+F%f>=vRYQ>GS~Y7j1P!vBtY&RdI=M0*x$# z`gCf}a zhP6@oEHo`^PN1ecGm4LhDm7wH8AN64BzU|IR5l)hkaVP`dKHIi=7NQ2h3DDO|8>;BZ~9{??udv2Xi z%ce;Ui!#`4PNSb@1253gB+xIG43Pg@wOlR(`DZN((phes^Yy$C%K5S{<`CpT6{vS7 zWdtfQ62kHSfUAESdKo2hm!L%S1!cStK#W}aKZ)=XxgJzWxaR*$kQxU5WdOY$RL}m~ zn(W5M;v}C-biz9JDnE$PqbM7hjnrP-4O_)}QlJnHPPNRRK zeC__DnUaAhsUrw*Nja|PQ7Cg`W(p6PprZdou)M#Fx+X^}?7P$55+no_ngHwdev~12 ziYb-S40^v&(xf-uVv-yHnsG4U(kN~t^eRs|Nk@9CH?jr{ok(jhZ?M7he6f68O33Q2 zkDYbFWaCaYOOX~1dQ_K}5er^4(TJ|A6l2g!h{SM?@A!CUV^#Nsdp`*J#hS{Bd)`x- z$t3(+@}D}Fz<_?tCkTTYV_x;;V1T|y7k_T>zAsaU(AA2ThGtia93&PJ310jrlPSdh zUtq1-SC=*pEDBdD|78<1F+*TB{=;07c#Ed1!N+ zy4*Yf{say3nhql!MJ|0z2T_xpYumbv5yer3>)0y8t@&(M<5&7kTn3ed|0~&QJtqO zts6>j?!x#Y0}{P3((Qxhl!z%J7>Bu>%_ouxm~}Z zp&YK1`$+m2*-@S;Q;~2FZr2Zk9^pucCJ0UKJSm5b-DBbtGxdVX2s-9du*QbSh^YRh zi~|}c*K&#fShf`jnlRZM1ZFW?S5=u1!wc@aa`tAyD^Y9)p{$U!);Alf(0L=z!RMwtXZs( zw_UWuW9D^DTf@4N%@u(2{byn6YwF?tv)#=D*eA*xW2nr1JGj*zegmPcK4XPv%8`d? zJ(KBh->Cx}{>6h{UK$9j|5c$o_O~J1U)2>zduU>}`c0}=Z%*0-etR1D6i>(JNE5Huf6# z`@x!sfN^r54rNes;a_>BF=u9lTSIxJ^!04UIIzB&1Dm&4?T*f$j{)zEQ-$(_7MZ(~ zZY?~{>oR$h!27l9aspqxz7sB6@XYBfb`idjm6 zL^S#))U9p2RH@e-NVWDaK)fPMF>7`6eBU?CtJMOjA?0>MTPnF3U^xr_03*b@j{kdR zJP)$fK7Y6$zX8ycAd8u1#}{i7vCyq-iRpCC8xj1M06>%&9gQGB60y!^PS^_qW;OVL z6{yrqQz3nfHhlj7W4*bec+JtnC37z?4VR!vp6abJ(y>jjWp*n~SIf8}bmcp@ZLqT7 zE>Ke0?L*pS01P9}?czL|*vT=AXC-}q6A76(r~?yh*mLGsb{FISJ6E&VeSW9XGs9B? zCEEL;51d_W!Hlr+qvsk)^eOII%Zn$rf+4Mndoxfui7Wsgy2)+T|7x@psM^l|d#HjI zMB?+WBWI0y83{S~O1s1@bW=i7q=fyg%x(jSQ8=(H0c?&|>IIlz^7fLkV(;X@$)rO* z1{a_11#PsmOZW3?q7yJvf7TQtaHXWr`tE*pI*hY-f>2nN{DHzUsb`a{{21e=j?+*? znr$4IHV@5Z9~uv;s6QWA5ba;TI86&9ueh1HC+1HGkFxE8Z>6fu#p*iBtx-vdA^&|3 z5{-_;4N9wz@Mz{&nYqntdbBCE{b5_N@>e-~qY~nc7FNJYJity&3k#uo1kTp&_}^_e zqPI}Xe__;9vLfyXlYWGfKqOkn1b{-7TBt{HV5MG?uUbHC_^|Wtuc>y5Zc?KdhVqgT zj%Z*t2?{rvGeh@V!j}|<1Z30B@p3F|xr=jp`4PV*Q6xSk9S7qvdUDt&&p)N1n4pe_JvH)ngZXuhQ>WYani^k*k^1X> zZs-gX&f#_Xpbx*Di#qR2^vNaop#Z>F!24{(wm@p3*WOqlRB(m5a-``h=f(Qi$urj< zQmj|WpA4$4hKgJM;J|`x4Mrj!amrfU0E;{oDId_RIt*|-Fr{jyeVw4M`wbXe?A9jG z!z~Q(i}JB>Go0Lw*4#eh_!xL=E7kHnCmN3wV+mQ#xN^SRkPJ!frjezSmR(ypCW*U0 z+Z`3U#2kILs8HI_rjTl^q-PfeZyS;Jh&gR01i_f|HRX+>t~_FkF~?lVryIe$k5NYv zeOu$_yu`787l1i1+2WHhz5KHd@wi$AB}G8QIvF5hF`m1JocM_~maMU~a~IuN6u^r0 zc3tzj2qXI22{_&wf868;8njmPnnr;!8`?EEbzU)ML%+@`agmM6*h>b^If!`gH#iV~%9B7r;V;d*7l z%;|aJqSFrU7QIhxCM%knpsjTLmV;UR3G*&IX^72iI}{yNtt#5_O{@&KD{nc0au(yN zkc0=SI-wCc_eb9DGKkJ}1+l)?(NA#f$kT3Ah*q5>=j)yn*r?PaO|z6|h|wY8`<<)S zz4GWNcO$$#Vuqkaqw4_!y89T>bjO{HZ4ezAz$g05wK0Xt25y|_C$k0*n1e_zh%g_A zRGwckPyBMA3~6UTP)-^6GnNh!zM;iY4A?*4-3nV4DyI?TSA9y=pD5?(TPBS0KaS#y zV*q-o(BVUtDt^ct!CmUtm8nrSw2fIdLOm^-Nb%SA72=n7Ytj5AFx?lamPd%wKZWj( zat)AGxd{X*7)*;CRcoYdRGKQW==4@IySi8dQGm1yYUp2hRAuY{XVt)wa^EuVIFW~? zR@y*OXk|w5+j|FLi9_?OJX*8qLd86%2e8EM)F0o*Qc$8L(&MM!wp@$Hr8%O zpj*3z-!5wtb`{F>BZvPC^o8VlKc`A?i#)l~H)RcgGnr~(PGzy9~mf(U|es@Sspssln`O|Hwa&I>nKJ^BIcwsN>xfrtduB-n4^1WS^k0#3VSd2md7~9R@&Hv=9w!9DqW% zMi0h^Xei~#CqSxa{}VU=Tt#brdPBPntUu&UvrNqz3nh(YCVtDT`KFOB$ZZfruILLd zxmq%oK3|)m)8M>qn~t*Z{hHQ7J(Qw} zIim#-(UVNS!$5WtckHFSN>BkZS!0LlY>%-#f*eF809KM%RGDK-FGZkJ*(EG1fXP*x zR}3E;R0f*5eHr~%i>;6%N=w{=F}-Z5tf8`ul`H}1eLi`v*hHqoDcI((8XxnzQ^bH| z?ZhO7DBmWtZGr@<+T`nvTnU+i*-<%AiyEHRodDGD3x!HVk1;tf+T;R$9?oPU zIdsFg*XjRao&qba{W0T7vrPWJ&YPfE(hcs_y8{go+S7tMxcn3@j@*i?7_&_|Vs&7} za-xcAgjsPhgj=}r05o)>ONnATH5E^voLp0Tqh`FJEo#Fv9n%rdDwUt zrrVh`9|z~s+Gv_RTbOHhycr_)DXaaxvfqT_EU@K#6hgocQDx%m1eJxdX@tBPbDUaZ zESt`#A&g@f#xaWZChF^G{0J3Or(Bk+lzszG{6d$7T4oJJ0gT1|IhL7Pmt?d6eVYGf zC_pf=2C}oOJ%8Qqga=k8V4(6ZNag~J%*f%p`^X4PO3$#w^0Oo9ZRnE9G~vtte3PrI zv;f*rh7bi*H0MWSlE7CLu8c6Bc3T7VW=KoJ)Dk%H)xFf@W5AS#lwQ*omZHKRd1=j~ zydB&=asJQa4^Tmmcs7+OOPBeZqUcYsAuPD%nBRI5JATdGo`=uFk<#xm)xB@&`L&~X zxKYX|1FxTO*+-ysdohcD2Yt>DxW!se84sb6b-;mx;n{_vNnC9`4^&^faseQxpjv%a z1Hfl^=4wtee`k_mpyYo~kK6GI>SCxj)@n+Bjw>Oy57#DG+*+NP7Hqi%RaI40RaI40 zRaI4!S6S60+QFudMI`)8m9~x_sMEX!B7^>pVfdqIU;ielLd?kFyZw}gvZDVVBZZKr z0{*Jzp2P7Ssq3gkJ~8mKM!4p)2Z@lLLJ0poGaI%P7a8%tQ^2=0ylH~#XA|WGTx4$y z?Ol_yhxJueRaI40RaI40q8m^#$*5O69oT@T1=k}uo0V_w^Y*~j z?t^mIyI~9UwfXb|COlcXZK#V*N$SJg1aFWfzb-{haXzpn>%!sKsNlwQcGPQX6B005vL@M8~l@?KouOF3w#cc(a4`utmB?Xd>pUYEHd>4Y}+= z^olETWbE1iL%PGU zj=4_m_a5=&k|Y+6-x<5=>*PoERQ6FE>Fsa_Aa@!q-7O~YrHk%akPdNUSV*rIxxN!^ zspcN=(MMqt+F4?Hym~iD5rFTF;zMg9&VpvFkOy<3br#$D>%(X0SlCR zrv*f-m{auW(p?e4&^1ZU6T_B#&OP1jRHu7gZ-ty8qhMf-akrlPRU&?=7<<&3^Rvh{ z3k+i4wB4nk-ilq9=m9VU?;5O4l~l%YheV_iVaSFR`EuKA)9(xj$x%8J+4Ht};yTJ% z0(hMmCNaolN!a5kbBu^4SqCi(O08Kw z*w5~qu670D-V!gX@jLqS)u2f`o>)(uoV@Y25(e}fSX1E(0(?}{o;;1smSNsJ*ZwX? zHy&%{IFpJ->Pa*BOJWlR@`q+$?@mhTuTt_V@2(Ade6>QdpZo{P@2Iu zFuCSPj}g+pfVYPU0(eXrs#A`Ta&~B#UvNPWR6Bd8L#c0!!}tq~Epxss)X)z`(0Uh= zmD5)Yz@x=<7M{TqI0Lj(7hb@NPK>h%Gye_4#k>JM#X<>s^0 zNYnD|J-{e?*MA;UP?N%v31%w^)L z6>`ad#AV{j;6WfKQ2-X#e|Xa5J}h9I>m*9}o!l1?-@D^t=__bwA6*>aDI)~wwiKC= zJCw~|IfqyAj`@5=}afx0O1L?Rw2ZRPu^)n!MH_ zh3IriH_LzBGDH3thHrsNOQr~Pyh4OSAMHLfYLve_y|LaUX#~;dE)AoJsZ04)+9l>W zICW`%1A(98RVf}88!9{{UN-JD1orumOZmg>l)D8Vu*bl}6(iFB9}p}MNA0nbO>^5M zn8cZyf$} zT$a=DW!5}eg_zrNCi0d>n$GGYj?6A%AOyu)r9{H~84{Vk>D(Z@)@}~$6VD2Xa)ngw z4I{RLKRh0*5l&nM0tCJ@InzHR`MY8(P5Ga6?~qx={A#42Lx_4v<2J_+!RR&m&U17I zR&uQ-H(55XeLRkk!KA@gBP`Q5q{e-%t)EJvlOPs%#)_^=geBX%MSf;AMNw zwh~K%$2okz)5#~Qd{?4u33S7_( zUIHy6f`s2X!_)s}hHJZi+(aFKrt}%NTlggtzwH?zf!7XhD1*~dmv*|v>EBb&E!rL5 z2pw@wsb$DD&h9zv*EkU|<~Mp*pmSucdzm4wq~CI}x#3n?+D82xdB-lL@@eVTswmXq zY;-N&`^zZ}IN;FHcu1pklbGh_;12R|X8qRI`r@}lwz5|h&=-$UnxsYU3;i~OQV#Qa z#-vgLP~k(RT9dKAd=BFMx9y^AAf#b9Mjt=YB5soz*b{+iR^#p?yHoE!syK)QOJAG< z*j_tk!fbxb$kDIBnfJ87`p&I?(2R1n=~b$`IL=bg2ZSX5So_3`x}bfkdW!9VMGzYr zm>JlQLgr^@7)|NSt+t_eRgTuH<| zB9-a~JiIBKJZ{d$GTp03!M3fROZH z&MA1WW<(y}gN_cN&95gw0OP~?X7uX6NbyPye#q|Z5ptU=uS;^T`3$^eJLuN?D!}+s znL0-#dk8ilr0e4kS4T#;LS+)F0{cG;;YS{+OO(d6kXzvYF67|wx|V|A1S@KM!9B;+ zejrMg{Zv@nm;98nBL%gktsiKx0W>-D|4b_Suc0v1hUURIB5CjIx0F;A%Pd+mHbHym z2;}*W$s27+5BSIF&C3DiYh!{g%6oU298uPMn^+k{8rcrj@}xFoG)c zWa&9QC;4ba?8-tfdEoGNuC)vDDZXlFVcQaSIpWhl(QUSnJ~^nGuoRWzK?wjG{p+n3 zl84X#cmhxRcjW~QD@UuIg8sS7$QIX810Rls6tS*;90?mlG7qN!`b%3etgtpnpJtZ$2EJ6Ds!`UwdSkGO0%=`DqfIp#ZNy&Ty&HZRKY<4^Lj3YOJ(81eYUroKtpbtn{2a}yB~}22?uj*x z0${ai;g4*|oJqScWk+&?71{CAX=+ZtXm7$CQkWnu0EtOeJbx%O99i#f2qpPJ>8i!! zsFSsTqd?Z~m3T7}a5Idtr9~x%rH2_Y9*ztfXJaX^A)fW?+<3B~pT}iNh7F~{Zja5A z#8bu`p==s7UaeC8#&@@QTR-6fxqshZC;DIhkg*XTTY^7gKYuEs?Wyp%ZFSFb!#h~#%CB5 zn(DRo#CzQJ@ANC1I~|szHH5XRbD$2muvDYuxl1X5|8Q0ywnJX`DvKtKJqM6slcH(6 zc}^HWL1FnN$vD^)FGC>Z8YP=P?l%mdkL~i-czA91f}SnS7ubI})ZPc6M|_w+kYG6! zcE*u$kJ56YxBi>spp|+a1a@7Bj6g)M7X+7dypOocdEN&m@ob={2@R?`!mB74vg0}v zGG;g-h!QuKDE&_uB0ylZpZ$OuZORVzMcSA>S$)fhp@~hG;QiU9*v!L$g8FYdvu1X# z86)=vRW_0^%1BRS*Y} zFh~LX+>C+-72cuCA|+Wn^4<--yCXLCp2vMwP>KcX@>%DJd_$JSqf+V_=Tt@vm==2$?K#qTrueVjG z@xkDh4aBVI#F70=2J}$@F<|~7TK_$_jS3UJ)K#WjR|YMHtb3w-0C(Z4njM2cP196Kc^>R#Y*akj?hL2CBx3}s?}b`ERIw6BT;$dpB{s*&e-=B z+FNu6p)KZVP?4O3-vEKR`x&q_lby z+=KYR%_?>VQ(zx`z^eI)V-A4h8ufM8O2#j!!%FhZa*p8A z+uOGa!7NCQ2Om|BX}c+0=E|SJ6it)yH`c66%whZrR6Z|f>oYlU`<`9)8@mgcM*R2| zkBmh(lYf+d%rTAwe_XZpKmY&$000CA#OpCi*E=~4UvhDQN1ir&bnw2! zVZa;Lcyzx&5+ddIG(zB?oqhJ^)25^7!QK|ucbTPd-+16`j51UJ000000000000#Ev z)25^7!O~6KWx;q~Yp{h1Ut78#h3HCY-<&j28}hhB#REc}n0C&3)#@6-Bok@7-^u&o zl`)0!^dBJo^5G~vHXyFkJk+geu_^C6?sJYAF`!LX7HJR;0+z}cn^9g8F`c&#q-cPx z7>aw8{N`@{9Qu2&V*Z+V2fB$Fk0yAY&>&w148zT&r00000000000000aU0zh$ zk}zhp2PXj-mwhz$n|GyYM*4AU)0x+S8z!_mqu<^OW0QJ#ARo4AQ2;a8L0w@{rHirb zenM?2R?Yb$hKrwV&xKQ*saDO4qQ0=+!PGzde|4fgD#&A<&$DV1Elc_ecCz1$E_CO zw3)*;a_YV&X;7;|ypKsd@dvL*zyUlA=gB(Xf>Qr?i=Bf9pd}sSJ^vb%L9+Ow5UZ%4 z_`up=jruggepm?L#OKmy0pnOiR=z~RX@mO$q4Nj~&4?4{FRFeVsATt(eRc@SzaYd~>_KVh-lFagO||75VOq;N|F@n7D+RGUpm6W|4YF39O1v zg#B$d7K&DCBE^#ILs`uSZYMnQWsdqv@%Y@j znhXYRewNKnZw7*{C%kW?E;Qz0W$DUNgUJ9$8+95K*f4BMo1*N2z_Hj0YgK4gXg>jw zdN28c^#Jrc;GN^ffQ?5ag>F!*bEbXI;?#Y~-W;o!4u@MdBEz2{9q-k(&-;wHKH;Vw zPMY_Fnu#Otd=*D+TBZy`q#}a@?7U#1YgsNqdp8o*sLuBKH;SK-yyRa!A@z*wvhwZU zjXLtgVxbyJiEXlC!-u4M9tHmXx$(5Xd@YV4w|uOlcfOT{|8CO)ke}Lb?ilih5Bhje+kV|P z0W`hkmy$hTU)E1V+qWVaiCG=cf*gEhbrib;Mc8~xqV$b=Bt{vE4U^{^1J*w;tIV{! z0qqf_prL>Va)Ld+uDQfr7k##+AET&Z0gn_!>X=#w$wk}E#2FXn+jv|g9YLL|NW*7? zA@2{{i!SRB7C9?2BJ8GI#s2N9_633gGR!X$DAuL?ak+A;FtW$C@>tnSGfo^aVe^Sv5*g)HTZcr~4$-sIx6n0H)z3BU)Yd>?t8<{Ic1{5NcKUp^#N^R@cs~G#Z(P!r z?IUIeBZWWqXS{7lCTpY+aR>ig3|NC5UI}828ZX2_LbF{WclvW4^Qnz`o~DzfaNLAl zz$=({1ATU@jRq-U9^OT?wo)V59{xJ-AR8)?u;#G$SMKS4zD$B17t=X&ise_tDe#Pz z2O5cS;=g@is?A{Ft4{+TUM}twP^XE)2!B@}SzTw*F2X)?{Z>)QqqZ91YFjK!{C3Tr zS}NF^lU=pwNaCtU&J~McEe3AEy*lQ36w0dzwscMoeBizxKWWm=lMvr|Y zP?qrIXdYaoBh0#I;fh0C2+xxUG9MeGu~8><4Fi>WmiZ21t{v;vK!Lbwo^}K4WYaO& z+_liz747@gM+&6H!LACTn@dK2bXmghUpU?ys8$892a6AU@>^aO}?`av40siGO9 zWVa|h|3>lyzeRBRN-2}EG0I{X2KD~Kl55a4NIgVgeB|5o^}};5n9BhtmWg8A%`gYl z3eoJWZCQZ;T)cQ&|2NJ6Kdt47NNf<~H#EoEC&bLKy8$$`0WtmE*;mBPfhBcwPL`H` zyFuwUd~C6SdJ=fsp0YmI(xqRIz+R-)>MZ=Io|F~8V8n0IbKnK@(*<=(E_Yw<>1l3$ z4S1Up4lB5PRgX{4&x*7>>ii-+>2Fe=+T7Y#Fn=))cd)vQRX^@DQazEayqpHFD418H)&) zcstD+!b|zNqNNtULl~QPgji;$WY7@bYy_aTq|ZiY+jdpouzeiF^*g`F0Tuf#AI_I$ z>ChtjXn+|^z(Oifv@QG112=HQt)KVLD)&5p?60S4zOE^sYqa-v=&&Xfeg;5U#>&5q z(*z8q!B5~OGC$3cj}M;8Vk#mp>$qVKPz)eN90aiy(9?j9@X@&7bFw-D1Od~TU2zFq z(Qb4}sHA0h+5)pd#;EWWK+8LO-(IVUuQTcS)(Pn{gOhQohAk;#ev8yFhwMe7f$^`m znPXm#(7%O*$Z?)3RfI1Wac`D^$_pHb{_jIn?=y(VEDH+Pv*(v#eDmKXoD zn&cA0$5POp8U>@ppR)NrC+|_;5<%zK90Bub3uQJMg5z!Td+M`O;yBo0^E)YtVBr5j zYt6Q2icqH?aZZ(NOs9Kq{POY^quQ|)!1?>+t;no)z&?q8c!u;8dz^o4k{DCIwxP7o zMA55;6i8L`kn^ChHC}n=`Pu^CMtM1K-TTK$KpxSuyo54C;?~84Psf(l9g`EcU+^iF zU0|u}@L*+xJLf@a>;p}{TivLd?T1FKgWARP{rQWqP~_cPcRAbhJhG}xKj0ee{AP~t z$X(LzMZsnR9`n`s-Qpdz_b8D!_!;U}NG2Uz(x4h3%HP|{ z6}`ND{fm0|Gfe1_@GNr?j^?al>3(_JBr;IQ&<)JPu{?2fiV+FM%E^p6ZAbaGzf+<1 zm<(khb@StMVx)^_sd6G4DY6wyJ=^905>j`v{}Vk#Z$ZX3TQlmeC07~T!tXGy1Dn_3 z?@ZF}PZq9C6wqWRyMd?ei1b+tB9=Gb$lkd85ULRUd6nHbuRs85-?9i4<;oqcub<~e zkYYv4?A8-h6uECZh=wvnFsy+9sW;sP@k^-_UBLYG%}@(sV1t_^Mf^FaEtQ{#u{{de z%(aH2)(YN6Lgl;V9x2?&9L|^XGV2rMaXNk0?JSiZ&6uVu6ahl%1ISEk{pX;2M#WNa zUP)|SdMspRYG-k2r>CQq5=aZ`?$qN_8ZV-YqL4t^@gM6YR0^f~pE zO7{+D%-#+oTNsQ4KNytFi7?vE@fL77q0vLszPLIME?cYBQhJzB?WL}_aUV|%iG_4C zw!?Y#tC@Bi2KHL|w6>%NlH4q+AsL zB9?G&I=KxS(Wrnf1RDPCLdmqa0x!6yZq*SCWmyI;Z*8u(n8%-9X+{9mQXj17t z_6SdkVFB4zu`LQx>6)3K04f)^t(#fW-^ceFA1jUL>*~rT=nY0#bZa5dF=72s@h%8$ z3wZlb&lnc%-64YMEfc?G+l`W1MqOow?yH8vkGxMu8~Yn^+Ka7?(%73V5N=ZW2uH-) z9nG|X_2Iv};oe%P7)1C5QgwuJ@v(0KY$Kz02Q4n$8q+99F7}vdyzyGr?Gr4Uj-q(6 zAx6w}_gMYTOvz$$uWw56-0o!)eZE?iNbHQ=5Lnb!@{nuVHKh^3ymZD;!Lj2|E;|Aj zU|qomex-htaZ9NZqVQd^Ol{n%QFb*f%sJQ;y({eBEhY8mX>;L|6UJ+lngV8a-C-ZF+@ zn!^HY<3#%uTteo~VeKOl|2+CPchKdxDRSySOmMwRoR8J;nf|LRh!sUxSBGd?qWoMT zVNZicnXR4##SV~OON~?FRYl9nk3(3+@8kE&4ta5=Bpd2fue`+_h7-MwN^rU1JSEtj zRLBKBKENeLX6iX%><4X_e5|uzu~S`y@P^NtLj)9;E*pw%v`jEBw2s#*-qsgS34%`5E&7PM*)ilpFA>3;Vlu z-=F>0ua*zc@mzMT?r0$82|6K%7Gu_5(0oxHIW1p}W3yH>g%7^=PKug}^CXZHh#~A$ z#%@^}tyP?^H`ztBPzF*Oluh18L*fa_pTI8>Xh{Y_e~|S53-i;A zMP0xZ${YMATG#Vwc_Gj<3#**|%@fy~_8P*wk3n%SFc zN?-p3t{~Q~)I8pYGQ-t64p= z;R-74?~`mtWu^kaG=a_q$I*}F9?XNW`%+5oy=2ELwyy#C}J|)Vp`?NT|-ktysqi#HmPc$O!9Xupol}D!_y|&=(bG zRqmur2DFp;TI_rFn=5hpPGoUCK~JXm1n{)HD*m3T=Jt*d?S{c_0H~Z$uoxoUzvm8) z!t7aZ*GBbKD#gfLb8zh5qu=D#LeciRYvQJ5)a^*S=a1Jin`k<8*Q!pLRNTQOmNubM zz*x|Kf@a!wS19-Z31(oB@MX zI79F^!`)N84X)CD9)tXySe^GH@cjmU9nXFpfAIU8zYo>7;r9dZ?oY$8{vN8}Ux&QE z4|Q+Drv4qn@cNnfex&~g=|=8{&e?uXL_6^PPTlps_;zdIFYxp);ppB0yV!Sn+q+fx zbbmc(*L3CGg6`_k&=86%7xPz~^Y(pTNf@P^4DVh3-%c|}^UDY?8J4u_ z%{q%&N%Y4NB2tX9&E<~LxxA`Vm=bq)qifN1Z!Jv!KFMZH`At@Txf5pVYDzaj^0QmV zxh`a{dm^T;TK_E%kh;vzK*u1kS8r;>F;378a^p7v50f2EE2HIFhX=QIZ|HJoKFZnz zderj$bkcH#cyqB?<1~CZ^VpFdxR36o>&PW($oeboUP+Ohik7I5_8k%rjqb(~LBTeh|7*NoxxFFiu4}&yHFNI^T zVD)dnl39W96x#fQX=8wS?_UCax<$CzSf((I!OtP}>R^Km+Q9SEzZ)Nmmus7I-BfFk z7Pm36TS)$eWU_4Yq#9psf54V$Mo|FJuWp2i!l2=0EN(E#5K&n;W$tx;#z5qf{5W+n zth{`bY}P)#T|J6zHpz(n6a@k#g4ImS6ve>pqVahFCk2;I_PM@u*!RCE^FxaVX@p3c zvkjNkJw39PIFLd~y}u#`_8ui}RtqArnnK*Ku`Zw`;YXNcPuj``>_QUVUBWy|1NSbU zGF&>d6|h}Hb3J>)1dFODC9DbYOV^K-4eN7o{P?Qu(b>Ee{wHl325y_Ok)nqg|8O{D zo1zVJi~oW0C%!FSN(N{GIyf9>dr7+J-imlh$-F+^iSK}%7r&Fg4X=bu%!e3iyyy+p z%0~SKob_U?V3RhFcryAmU$r`i?{-_K6S_0ADGIVYg}gOn)m`>yVh_ZR(!RG*dc zssR22cv0Zy6Agr)hrb!70%AuQO*xFVo*yXHonwTwnZS&4Kb^gRnJ||VHQb|>6uf3k$Tb`Z;s>SZO9XbMyntz-u{Y>)+2bvoXb*opM z(lHgdV|H+9e7j{SPB9vGkGddh0T?N%p$s!RJBq2}h}(i6U{Qm#fqdA$(+{H%OEVd< zfoqp43WJ<&y16kkRNl^k8&K^2?WW?g=~g4q9qwz5%%a{zt6DPE>|;a)&D2WA2-8=| z{B)9I;ewXtxRe;+8gbfs@lhu#&JCh-D9K(+D~qjw*-S3oiFO-tX&=TTAsxXtAsdWC z5gE2(IH6-!RRpAB~R@&^SRQsXl99Pm| zU%M;6BP?$_5LIMn z%l_KsK*|EgBVhfxFkwm3?%1QnH%~IK}hJg4pV3V4x`9aBf7(+H+350fD{t-PR zjGfHGYvuXW`Ti?Vhf1USA<*aMa%P|+R?y=Fdt|qk)q}ARj%&;-A$2h(eE{K|>>Lhi z)q;Btc(bfdJ?jt6y*sd-q<`TYV1lxP)-DOga4R{mn4Svk2;EMle{+b<^@Fzg!651d zYK4%=gK_y81<2D2i;6iq!%U1wyq06KNx&VkyR1*zbEz$7u5D`;a_m#i2_c8a#X$u< z!hesY!0+yan7r?H(c_wa_x|6d9<84C+eocvP|7jW*G%whbFQT*R4Dd&|J$d z{Z47ukt5J+DC7PtD|&@k?U5birTDtxs|xs_4Y zTqh+}`&m6nE?Jzu1T&(9_^<@}+tLK9`{a3&z>?l}!nHMEjrM~{$9V~>Zl3B=y4mi& zXTnV-3)9vIqCsO%2unCo-43Q&CMEcSGkb3#75N}h+N;F^6-PkO^eeZB@;=j|=O1nY zf8OE#^Fx2ej@U$cOD0DrHyuy#$M-{}1PIh^bq;SYx|OAeM!Qj@zqvL(j3x_d2-t1* zhe1BWLA5%)+^-x(C23R|Iz#syGmX0$rJw#sRY3mHA2Mp{0(aw|kJ+N@e`8>YRq0=8 zG$^3_J@)Le=Y|=`KrJYjEGH~LKTF;14&oR1d6i_4P8_pYQ3gNssx_Stc2Z(>Rwt$4 zvN@A#b{SKUKWV4wdH-1g5Ss<&G8L5qUmGI0(Gwq&!cAR2^ij{>9q@Qb!9b@wo+h#% z2DE~|2M3nB`tOn_>Ia9RQb9RPh+Xv%t6{m-I4HX2DYdyW6r$+7KYzAG{W8JLRdhDdc|y& z9`Z5RL34Xja7S1&mX)QEfx2OL>XErL6sMNvayXEzXvyvVb~Tk?EZ z3fRWtsC$(G>hg9#3cHg51kA-e#ODtUq~8H--}}Fi0ej{_RqHe=xlDMQ40M*U`fiG&zUYqi!6MgN_K>q)kRC7 z=sko{6bcYWtoM_)|#M#G_Bk7Qraj^X{h1%36NLg(+v=0xlFjNVz0 z-xt(Ilk2#Sa++Kt&<7C7>_^k6uAtnz4!#hV9u|y^?>iTbdiAV}LX{Y!&5~c71qM&| zk;lfOwq@3Mldgcevh|Xhmj9F&i(^?<)hA7GA`PO=Es^;d$A>7Q0fjlFqap^Dlb+flr6H@P3 z4dc7Q8Fvl&2}WCnrPZGqzBh=EfK#q3{wBz~t0-BsS1I_X*C(xM!s@F45@T>~`J@P4 zd0Z6EWanr4&-N+DHPDP?z7|l(;afZcCa*VPmEa zPZ22xYkdCrr;op}W%lnUvY-9EzIR>Ip}z-%f4$k4qv*C4 zgcm~8?AcIVhyvCby28_U$=HOvPBd=ze~+ryK_;lqCG(1f^b`?ph7i|tX}ae@>l;Gf zzAvAtAbX7b?G`nZT3a7aO0)lqUtd$=R}5@;cYEi6TR}WJ(hsrGzZjiUb|7 zkd(7B%H%&gmJ!hEIe&tp(+`L{N+L3Ypp%1^FHCFv`Sp-^!;v!)LDv4DW2GB0Fd?WF ztR+NYVPpxs>}6C#{|k8Rgj_0nkz)@Ac~*LxMLuuQhVLOWTjmRGA)Mjynn&?(ucW6i zT3er95<4|*_FMx5h`A5nbRv98j>G1TQJp)+o+7FO;~eg=<-$xcYDp~45JS0}W%0D- z#K$2jrWx@XRPRv2#&N){mE-0z!a}Ao_xsJ z$_eK72od|uWG3F&ep-5*8;V5_zx&DhC}UP?OL6S9gU{*2n#*(o6xLEmTxBXGUjf*G zkSOZUNL6xK8`1H921#0Gr~z&EzN5*+*Bf1(YN9MkBI|DGMJ4Bnawu@p_uu)2lK}1w zrJv>JF-}0)hFj@83=w2==1^zL#B-IJg^S`TesmX4Ix*E7a@14EfTo7-EsZe1KdGTv zCZ%y**;#}KFu?QOEd#KKxsyk=aJ7Ve--6XN%D6!0_K*gd;-+s_{qqla zqZsA3Ytlr?4RQr3!q_#;IX2il20=T0z6xyl#{ICpa7EKUrqj29I1kB>&O{O<{mU~C zZl+FDfmjOZ$fHVD8D-H<@Ep2j=XHY1QiO`mAV7!q*pS%FCMMiyX_U*x1>^srV2E;c z9J7riAI`^#(2C%T%u1VaSO+@)`e6!!Gpl93B8wGg`DC*sV+FxJsaei==Iztoy3FR{ z-72hiLgE$7+z$vS)(GYczc>Zk400qQ9KQn-R~s%+JbYSuNlTU1?&tt3)^ITb$Tb1U zJP?t#_dWu4tHk@2e(`>~ zJ{0HXo^l~Py@kW*T$B0n7|t6-8Gtf=w+$fA9Dl(ZYVw`ba0Ia{S#=1}Q(Gydz2=4v zv}3}dJV2Y1L+%HjUV76P^M(d9sYKx>>?SRSy5O4(1i2zdoUnK`Jc&b%mW*JFqrjAN z#q`;+mbTT=M6WNWdmM2hie!(y80ALsTm=|9RCE8O%Tmq#;=gtz+dY4VkPzS7qPktF zWfowxYK53)IFDB}AhqL4!J=dg!$X?mR9ROb-K1ozd64*Pi5BC+LQN223o&o)k%%f9>FqPtxCTU*z5UIyzF};L_*=}=)3Sh3h^~sCL z>^sg;Fc#Ja~4IGfcx&(too1!gw)nt49sywD%D!gyX z04q?h33(MHFt8@JCW3qRdpJZ2NO8fF7MuGeD0d+JfBOGB%c_eyQF$J7*8Oe-oph^u z`|bWxZO6V&kuDfbjA>FBQ}n9(6#hr)7kF~E8o>jezj0>z-Qc=ldK<`+P{YfW3G6gP?1#H!N*4ixBc_rIMk%NbMe^~*&6*^G%aeuF&y zNpFx0m4VvLbf-FbH1dk>?j_2E- z*hld-O+2rwY7vP9Fn5uUAM|ZKu=BH)0_7W~ovUM=d_;k19q+oZbu{}D0TvJ0nfSMG z&eE`4$bP3B>~+(Rv=7>pM+VXbJmdDc1qrSmK*!m<;`m`wpdb|+fvN{ctXCIh*qdUL zI@+W4yeAhA_En@?Iyf>s<$i$*$I&+GmxT-s66faZ<>EXnXJ0d$Dwj}uu~3NJLzoCW z*KF(5804h&c@`}hh|%`21s8S`Lpa4Lht9dAQNl?QceQ%WxQgaI=!ZbV&d!>czgO@) z5vsBp9jZK6!G!+MCv$ig%kD5P5#8!KGz0z9{Y;^Jkrn=r>#TF-LT1RL@W3tRwUXbm zb$r%ppegV)g(%i3)7|{*i=)y?5e!;7;l1o&jphi|PK9O&spY@me?L1_*_8$7!jIX# zb+vM4B9<+{?0>pZc$lS2w?9)64|{6_Bc0!797fgj<}YHX*#UM**o8cb6Lb7di?w2qE!r z9a)tVcaQNF`Mx#F;;E-Ut@Hb;b>m zU8rT6CWXwOUZyAFjZDt%JrnO%?<6?}pq&9QDa`&yq#sR!)>%nTSD5rrA}qb@r*}{1 zEn~A`gAZJ0c+C;gt0lFAhrI<-YJ`CR)oo=4vVaFfTR#ip$CZuZ3fUEA+l_N=Yo>(_ zd1A$wf83rywLina)#{W_u5h20d~?KP8izXagVK~c5|rk?FN?>@JyN_?w$hbmL2<)- zOY)i(ZxojtMji>fuCU0%6` zS=R_OUyS@E35vw{ICy}_Nu_)=xP~aFQ;~K8I)`fds7*rlrfITtJwG4H(;3vyivFSJ z9B{g;1U0ZZi;i#ydoI1em|`V-m8=Je#EU2Ih_PcO(f$T(dW&+Q*QJ!fwT@NLLH|KvP-7h9lhTPpj^!)l~BVoztV-KcCw@5L*7MH$wOt{BDjX!8!m zQ+&HKEvG?HqUZK_H3}BwEx<*1RM$0x3XnHM4qwa&O@K~x8V%_HtoD6WiEXM{qSVC6z&G(Lbg*%aMz zsh^M2>=V7O!tjda-{B1&kQ&^(&7O-gaTwzknireh-(`y9L(Yd+eo0Pw7v# z!Hl_oz_;LIszN9tRf5VHN||`jo$4<^?Q3AYd+0=vLqK4r7+3FY`tkf;f3IFjxmpn4 z?MlSwLMpQz>l(?-Zy`(&C0C2)qQOFy7I;-Odj< zw341beu=pYd8oXG^lj$W@*GO53E{z4P|(Z+R>X5-fulR3iwhIKq=d5tBkFM%f6fRC zaSvD{)xHc*s_1Q>9yn==X4;mhLE|R~LmP(-WE**d!cH%*vjoP0Ylu}YyoZyuQy8SQ zbvmI#D1Lbs?ybqT@Rs9ZpbNZsVj*W~Dj4?uBU6KYTyFR39t-a2RI5xc_iVa^o@2~H z^SR|OcOu-Outb>tq4NO_PYoTW_Yd<%Ss~1_{{C6GXLpGmEXtJ9tM6D;zcE3SwyXM^tO##5&OrSa-zoLyfq5q$hW;x*&ZU}Tz8Q{Vd~q2q3j)8np^xd4;^k0 zkZK*cT8LBldrFCkw3ih)3UTa@>+lIup0q)}+Z5?@uXNN*r*R$@VH!RQ0=?IHd$YEFHh^FZtYzD|aVk2$rH(YqN8baGy0UfTJdF&5lk{efH8Hae^EvxL0)PwHXxx2sz56`B?!2<3=rh^~rZ;onXoL z8>AlYRqv{ZoUZMRbnrDl%ey z6{I47%@w&zgwCN3ldeF=a?b{X$xoAVdj!l+&Jujh+h^LH6~S^F_sD`ZFX^59I|#(yx6LGN&#|a4vrZZH8DOii$bk5 zezKo7^4b}{mGyvXjp?U^3f_k&p@@#_$on_eehu9YS&Ff zuZl)RZVl}#`}D9R(lg*q8n;b+sTX4vco8Pj<1d}S#(u$36;eHTY<(=C`z(gJRL&1GcZ^HLUt(dv9o*B7eFg(jEu(`*wJucek3oxZ6 z{4_pDMIOigYyBh0U&Kh?vO#AV>_F@GFIx23Cc1apBxq$rIutcbM3eHbGi}{Oqrcs! zl9C3J$%a(R%8GyqX>1qP`y&fH5}LM^T*;w6nv@Yt+;egu!EQq~>O$*av7K3Y_#W|m zp1l)`E`}urX)oDYjT;lh>!El8;9Ttv-enJ^6zCeII5iBX5bi}8S-TrrtUDW<*YrG5K z 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index 9ca82b17..138689de 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -1,7 +1,6 @@ # ------------------------------------------------- # Project created by QtCreator 2008-12-11T11:01:36 # ------------------------------------------------- -TARGET = TelldusCenter TEMPLATE = app SOURCES += main.cpp \ mainwindow.cpp \ @@ -13,9 +12,9 @@ HEADERS += mainwindow.h \ autoupdater.h \ CocoaInitializer.h \ systrayicon.h -FORMS += RESOURCES += resource.qrc -macx { +TARGET = TelldusCenter +macx { HEADERS += sparkleautoupdater.h LIBS += -framework \ TelldusGui \ @@ -26,8 +25,11 @@ macx { OBJECTIVE_SOURCES += SparkleAutoUpdater.mm \ CocoaInitializer.mm QMAKE_INFO_PLIST = Info.plist + ICON = TelldusCenter.icns +} +!macx { + LIBS += -ltelldus-gui } -!macx:LIBS += -ltelldus-gui win32:LIBS += -L \ . VERSION = 1.3.0 From f0ae35eeb8dd3c7a389fcf37131b5e6e12b7dd69 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 6 Feb 2009 09:07:22 +0000 Subject: [PATCH 0779/2215] Bugfix, returned the wrong type in Device::methodId() --- telldus-core/driver/libtelldus-core/Device.cpp | 2 +- telldus-core/driver/libtelldus-core/Device.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 0e24795c..bae0f778 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -52,7 +52,7 @@ int Device::dim(unsigned char level){ return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } -bool Device::methodId( const std::string &methodName ) { +int Device::methodId( const std::string &methodName ) { if (methodName.compare("turnon") == 0) { return TELLSTICK_TURNON; } diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 421a7395..1e2aadd5 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -28,7 +28,7 @@ namespace TelldusCore { int getModel() const; void setModel( int intModel ); - static bool methodId( const std::string &methodName ); + static int methodId( const std::string &methodName ); #ifdef _LINUX void setDevice(const std::string &device); From 13ba790a033ba6e8b9a8c044a48f55a28ba3f913 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 6 Feb 2009 09:09:44 +0000 Subject: [PATCH 0780/2215] Added documentation for the functions tdInit() and tdClose() --- docs/telldus-core.dox | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index 969f247a..63eec9df 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -32,6 +32,11 @@ * * Telldus provides a non-gui library to list, query and control the devices * called telldus-core. + * To initiate the library a call to tdInit() must be made. This call will + * open up all controllers (e.g. a TellStick) and start listen for events from + * them. + * When you are done with telldus-core, call tdClose() to allow the library to + * clean up after itself. * * \subsection sec_bu_listing Listing devices * @@ -42,6 +47,7 @@ * int id = tdGetDeviceId( index ); * char *name = tdGetName( id ); * printf("%d\t%s\n", id, name); + * free(name); * } * \endcode * @@ -60,7 +66,9 @@ * the rest of the program. * * The next two lines of code queries the device for it's name with a call to - * tdGetName() and then displays it to stdout. + * tdGetName() and then displays it to stdout. Since telldus-core gives up the + * ownership of the string we must manualy free up the resource after we are + * done with it. * * \subsection sec_bu_sending Sending commands to TellStick * From 9b9dd8c876f9947f0e218c0e848e34c67c102e42 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 6 Feb 2009 09:36:42 +0000 Subject: [PATCH 0781/2215] Fixed a small typo in documentation --- telldus-core/driver/libtelldus-core/telldus-core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 2448631e..ef954c83 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -61,7 +61,7 @@ inline char *wrapStdString( const std::string &string); * Error code. The supplied device id was not found. * * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - * Error code. The requested method is not supported device. + * Error code. The requested method is not supported by the device. * This should be avoided by a call to tdMethods(). * * @def TELLSTICK_ERROR_UNKNOWN From 25f9a4f6458956037063ad9ac1e0d80e8b829b84 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 6 Feb 2009 16:15:23 +0000 Subject: [PATCH 0782/2215] Suppressed the output if there isn't any errors --- telldus-core/driver/libtelldus-core/TellStickDuo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp index bf76f837..e21e09eb 100644 --- a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp +++ b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp @@ -66,9 +66,9 @@ TellStickDuo::TellStickDuo(const std::string &serial) char message[] = "V+"; DWORD bytesWritten; FT_Write(ftHandle, message, sizeof(message), &bytesWritten); + } else { + printf("Open: %d - %d\n", (int)ftStatus, connected()); } - - printf("Open: %d - %d\n", (int)ftStatus, connected()); } From 224a4a2dcacf740f3904bf58aa25e8b6963db65b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 6 Feb 2009 16:16:43 +0000 Subject: [PATCH 0783/2215] Bugfix, send the real method to the client program --- telldus-core/driver/libtelldus-core/Manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index a0796f97..b267294b 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -195,7 +195,7 @@ void Manager::parseMessage( const std::string &message ) { } if (found) { for(CallbackList::const_iterator callback_it = callbacks.begin(); callback_it != callbacks.end(); ++callback_it) { - (*callback_it).event(it->first, 1, message.c_str(), (*callback_it).id, (*callback_it).context); + (*callback_it).event(it->first, method, message.c_str(), (*callback_it).id, (*callback_it).context); } } } From a8608e014618ba4f1b420ebd462b07815028d142 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 6 Feb 2009 16:42:01 +0000 Subject: [PATCH 0784/2215] Added receiving from TellStick Duo --- .../tellduscenterapplication.cpp | 34 +++++++++++++++++++ .../TelldusCenter/tellduscenterapplication.h | 8 +++++ 2 files changed, 42 insertions(+) diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 68735146..b73c2756 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -1,6 +1,7 @@ #include "tellduscenterapplication.h" #include #include +#include TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) :QApplication(argc, argv), @@ -9,9 +10,15 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) connect(&systrayIcon, SIGNAL(showEventMessage(const QString &, const QString &, const QString &)), this, SLOT(showMessage(QString,QString,QString))); setQuitOnLastWindowClosed( false ); + + //We use queued connection since it is called from another thread + connect(this, SIGNAL(sigDeviceEvent(int, int, const QString &)), this, SLOT(deviceEvent(int, int, const QString &)), Qt::QueuedConnection); + tdInit(); + tdRegisterDeviceEvent( &TelldusCenterApplication::deviceEvent, 0 ); } TelldusCenterApplication::~TelldusCenterApplication() { + tdClose(); } void TelldusCenterApplication::showMainWindow() { @@ -57,6 +64,33 @@ void TelldusCenterApplication::showMessage( const QString &title, const QString } } +void TelldusCenterApplication::deviceEvent(int deviceId, int method, const char *data, int /*callbackId*/, void */*context*/) { + TelldusCenterApplication *app = TelldusCenterApplication::instance(); + emit app->sigDeviceEvent(deviceId, method, data); +} + +void TelldusCenterApplication::deviceEvent(int deviceId, int method, const QString &/*data*/) { + char *name = tdGetName(deviceId); + QString deviceName(name); + free(name); + QString methodName; + switch( method ) { + case TELLSTICK_TURNON: + methodName = "turned on"; + break; + case TELLSTICK_TURNOFF: + methodName = "turned off"; + break; + case TELLSTICK_BELL: + methodName = "belled"; + break; + case TELLSTICK_DIM: + methodName = "dimmed to level x%"; + break; + } + showMessage("", QString("%1 %2").arg(deviceName).arg(methodName), ""); +} + TelldusCenterApplication *TelldusCenterApplication::instance() { return (static_cast(QCoreApplication::instance())); } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index d72d313d..2dd00328 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -23,11 +23,19 @@ public: static TelldusCenterApplication *instance(); +signals: + void sigDeviceEvent(int deviceId, int method, const QString &data); + public slots: void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); void eventTriggered( const QString &name, const QString &title ); +private slots: + void deviceEvent(int deviceId, int method, const QString &data); + private: + static void deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); + SystrayIcon systrayIcon; QPointer mainWindow; }; From 2ffcb62c9bb969b5d173c27c585ed7843d6daf6a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 7 Feb 2009 12:52:26 +0000 Subject: [PATCH 0785/2215] Fixed compiler-warning --- telldus-core/driver/libtelldus-core/Device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 1e2aadd5..07503d68 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -16,7 +16,7 @@ namespace TelldusCore { { public: Device(int model); - ~Device(void); + virtual ~Device(void); virtual int turnOn(void); virtual int turnOff(void); From 0bedf64ff7bcfad7875e1632fa0ad7fb3c96953f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 7 Feb 2009 12:53:55 +0000 Subject: [PATCH 0786/2215] Fixed compiler-warnings --- telldus-core/driver/libtelldus-core/Manager.cpp | 2 ++ telldus-core/driver/libtelldus-core/TellStickDuo.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index b267294b..fd7a7e0a 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -132,6 +132,8 @@ bool Manager::setProtocol(int intDeviceId, const std::string &strProtocol) { devices.erase( iterator ); delete device; } + + return retval; } bool Manager::setModel(int intDeviceId, int intModel) { diff --git a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp index e21e09eb..eb704b2e 100644 --- a/telldus-core/driver/libtelldus-core/TellStickDuo.cpp +++ b/telldus-core/driver/libtelldus-core/TellStickDuo.cpp @@ -87,6 +87,7 @@ int TellStickDuo::firmwareVersion() { } int TellStickDuo::send( const std::string &message ) { + return TELLSTICK_SUCCESS; } bool TellStickDuo::connected() const { @@ -149,7 +150,7 @@ void PrivateTellStickDuoListener::run() { } void PrivateTellStickDuoListener::processData( const std::string &data ) { - for (int i = 0; i < data.length(); ++i) { + for (uint i = 0; i < data.length(); ++i) { if (data[i] == 13) { // Skip \r continue; } else if (data[i] == 10) { // \n found From e92d54ede8b4be273d768467393643c77a72970a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 7 Feb 2009 14:21:01 +0000 Subject: [PATCH 0787/2215] Fixed compiler-warnings --- telldus-core/driver/libtelldus-core/DeviceGroup.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp index f763fb6d..23e5e10e 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -47,7 +47,7 @@ int DeviceGroup::turnOn(void) { for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { int methods = (*it)->methods(ALL_METHODS); - if (ALL_METHODS & TELLSTICK_TURNON) { + if (methods & TELLSTICK_TURNON) { int success = (*it)->turnOn(); if (retVal != TELLSTICK_SUCCESS) { retVal = success; @@ -65,7 +65,7 @@ int DeviceGroup::turnOff(void) { for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { int methods = (*it)->methods(ALL_METHODS); - if (ALL_METHODS & TELLSTICK_TURNOFF) { + if (methods & TELLSTICK_TURNOFF) { int success = (*it)->turnOff(); if (retVal != TELLSTICK_SUCCESS) { retVal = success; @@ -83,7 +83,7 @@ int DeviceGroup::bell(void){ for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { int methods = (*it)->methods(ALL_METHODS); - if (ALL_METHODS & TELLSTICK_BELL) { + if (methods & TELLSTICK_BELL) { int success = (*it)->bell(); if (retVal != TELLSTICK_SUCCESS) { retVal = success; From d7a3cab903c9e2b8f26b34d93237238d9d1a2337 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 7 Feb 2009 14:27:09 +0000 Subject: [PATCH 0788/2215] Fixed compiler-warnings --- telldus-core/driver/libtelldus-core/telldus-core.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index ef954c83..45e61817 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -104,7 +104,6 @@ int WINAPI tdTurnOn(int intDeviceId){ Manager *manager = Manager::getInstance(); Device* dev = manager->getDevice(intDeviceId); if(dev != NULL){ - int model = dev->getModel(); int methods = dev->methods( TELLSTICK_TURNON ); int retval = 0; @@ -138,7 +137,6 @@ int WINAPI tdTurnOff(int intDeviceId){ Manager *manager = Manager::getInstance(); Device* dev = manager->getDevice(intDeviceId); if(dev != NULL){ - int model = dev->getModel( ); int methods = dev->methods( TELLSTICK_TURNOFF ); int retval = 0; From 19b2684fda1215ca08ba5a5a899a94eb3886785f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 7 Feb 2009 14:30:14 +0000 Subject: [PATCH 0789/2215] Fixed compiler-warnings --- telldus-core/driver/libtelldus-core/DeviceGroup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp index 23e5e10e..abfef43c 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -101,7 +101,7 @@ int DeviceGroup::dim(unsigned char level){ for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { int methods = (*it)->methods(ALL_METHODS); - if (ALL_METHODS & TELLSTICK_DIM) { + if (methods & TELLSTICK_DIM) { int success = (*it)->dim(level); if (retVal != TELLSTICK_SUCCESS) { retVal = success; From 419c9abffc1a5960f81c7a853b758a6226f76ad5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 7 Feb 2009 15:06:47 +0000 Subject: [PATCH 0790/2215] Added functions Settings::setDeviceState(), Settings::getDeviceState() and Settings::getDeviceStateValue() --- .../driver/libtelldus-core/Settings.cpp | 18 ++++ .../driver/libtelldus-core/Settings.h | 84 ++++++++++--------- 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Settings.cpp b/telldus-core/driver/libtelldus-core/Settings.cpp index 52f3cd58..5d9405de 100644 --- a/telldus-core/driver/libtelldus-core/Settings.cpp +++ b/telldus-core/driver/libtelldus-core/Settings.cpp @@ -55,3 +55,21 @@ bool Settings::setDeviceParameter(int intDeviceId, const std::string &strName, c std::string Settings::getDeviceParameter(int intDeviceId, const std::string &strName) const { return getStringSetting(intDeviceId, strName, true); } + +#ifndef _LINUX + +bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { + bool retval = setIntSetting( intDeviceId, "state", intDeviceState, true ); + setStringSetting( intDeviceId, "stateValue", strDeviceStateValue, true ); + return retval; +} + +int Settings::getDeviceState( int intDeviceId ) const { + return getIntSetting( intDeviceId, "state", true ); +} + +std::string Settings::getDeviceStateValue( int intDeviceId ) const { + return getStringSetting( intDeviceId, "state", true ); +} + +#endif diff --git a/telldus-core/driver/libtelldus-core/Settings.h b/telldus-core/driver/libtelldus-core/Settings.h index e09d7ed8..92993cd4 100644 --- a/telldus-core/driver/libtelldus-core/Settings.h +++ b/telldus-core/driver/libtelldus-core/Settings.h @@ -1,40 +1,44 @@ -#ifndef SETTINGS_H -#define SETTINGS_H - -#include "Device.h" - -class privateVars; - -class Settings -{ -public: - Settings(void); - std::string getSetting(const std::string &strName) const; - int getNumberOfDevices(void) const; - std::string getName(int intDeviceId) const; - bool setName(int intDeviceId, const std::string &strNewName); - std::string getProtocol(int intDeviceId) const; - bool setProtocol(int intDeviceId, const std::string &strVendor); - int getModel(int intDeviceId) const; - bool setModel(int intDeviceId, int intModel); - std::string getDeviceParameter(int intDeviceId, const std::string &strName) const; - bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); - int addDevice(); - int getDeviceId(int intDeviceIndex) const; - bool removeDevice(int intDeviceId); - - ~Settings(void); - -protected: - std::string getStringSetting(int intDeviceId, const std::string &name, bool parameter) const; - bool setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter); - int getIntSetting(int intDeviceId, const std::string &name, bool parameter) const; - bool setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter); - -private: - int getNextDeviceId() const; - - privateVars *d; -}; - -#endif +#ifndef SETTINGS_H +#define SETTINGS_H + +#include "Device.h" + +class privateVars; + +class Settings +{ +public: + Settings(void); + std::string getSetting(const std::string &strName) const; + int getNumberOfDevices(void) const; + std::string getName(int intDeviceId) const; + bool setName(int intDeviceId, const std::string &strNewName); + std::string getProtocol(int intDeviceId) const; + bool setProtocol(int intDeviceId, const std::string &strVendor); + int getModel(int intDeviceId) const; + bool setModel(int intDeviceId, int intModel); + std::string getDeviceParameter(int intDeviceId, const std::string &strName) const; + bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); + bool setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ); + int getDeviceState( int intDeviceId ) const; + std::string getDeviceStateValue( int intDeviceId ) const; + + int addDevice(); + int getDeviceId(int intDeviceIndex) const; + bool removeDevice(int intDeviceId); + + ~Settings(void); + +protected: + std::string getStringSetting(int intDeviceId, const std::string &name, bool parameter) const; + bool setStringSetting(int intDeviceId, const std::string &name, const std::string &value, bool parameter); + int getIntSetting(int intDeviceId, const std::string &name, bool parameter) const; + bool setIntSetting(int intDeviceId, const std::string &name, int value, bool parameter); + +private: + int getNextDeviceId() const; + + privateVars *d; +}; + +#endif From 8aa49ce0f282e77db76c3f6bac3203313658e1da Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sat, 7 Feb 2009 15:39:52 +0000 Subject: [PATCH 0791/2215] Refactored to make Device::turnOn(), Device::turnOff(), Device::bell() and Device::dim() protected --- .../driver/libtelldus-core/Device.cpp | 152 +-- telldus-core/driver/libtelldus-core/Device.h | 95 +- .../driver/libtelldus-core/DeviceGroup.cpp | 266 ++-- .../driver/libtelldus-core/telldus-core.cpp | 1072 ++++++++--------- 4 files changed, 800 insertions(+), 785 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index bae0f778..6686f94f 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -1,69 +1,83 @@ -#include "Device.h" -#include - -using namespace TelldusCore; -/* -* Constructor -*/ -Device::Device(int m) - : model(m) -{ -} - -/* -* Destructor -*/ -Device::~Device(void) { -} - -int Device::getModel() const { - return model; -} - -void Device::setModel( int intModel ) { - model = intModel; -} - -/* -* Turn on, virtual -*/ -int Device::turnOn(void){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -/* -* Turn off, virtual -*/ -int Device::turnOff(void){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -/* -* Bell, virtual -*/ -int Device::bell(void){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -/* -* Dim, virtual -*/ -int Device::dim(unsigned char level){ - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; -} - -int Device::methodId( const std::string &methodName ) { - if (methodName.compare("turnon") == 0) { - return TELLSTICK_TURNON; - } - if (methodName.compare("turnoff") == 0) { - return TELLSTICK_TURNOFF; - } - if (methodName.compare("bell") == 0) { - return TELLSTICK_BELL; - } - if (methodName.compare("dim") == 0) { - return TELLSTICK_DIM; - } - return 0; -} +#include "Device.h" +#include + +using namespace TelldusCore; +/* +* Constructor +*/ +Device::Device(int m) + : model(m) +{ +} + +/* +* Destructor +*/ +Device::~Device(void) { +} + +int Device::switchState( int newState, const std::string &value ) { + switch (newState) { + case TELLSTICK_TURNON: + return turnOn(); + case TELLSTICK_TURNOFF: + return turnOff(); + case TELLSTICK_BELL: + return bell(); + case TELLSTICK_DIM: + return dim( value[0] ); + } + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +int Device::getModel() const { + return model; +} + +void Device::setModel( int intModel ) { + model = intModel; +} + +/* +* Turn on, virtual +*/ +int Device::turnOn(void){ + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +/* +* Turn off, virtual +*/ +int Device::turnOff(void){ + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +/* +* Bell, virtual +*/ +int Device::bell(void){ + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +/* +* Dim, virtual +*/ +int Device::dim(unsigned char level){ + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; +} + +int Device::methodId( const std::string &methodName ) { + if (methodName.compare("turnon") == 0) { + return TELLSTICK_TURNON; + } + if (methodName.compare("turnoff") == 0) { + return TELLSTICK_TURNOFF; + } + if (methodName.compare("bell") == 0) { + return TELLSTICK_BELL; + } + if (methodName.compare("dim") == 0) { + return TELLSTICK_DIM; + } + return 0; +} diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 07503d68..b6684265 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -1,47 +1,48 @@ -#pragma once - -#include "telldus-core.h" -#include -//#include - -namespace TelldusCore { - - const int ALL_METHODS = - TELLSTICK_TURNON | - TELLSTICK_TURNOFF | - TELLSTICK_BELL | - TELLSTICK_DIM; - - class Device - { - public: - Device(int model); - virtual ~Device(void); - - virtual int turnOn(void); - virtual int turnOff(void); - virtual int bell(void); - virtual int dim(unsigned char level); - virtual int methods(int methodsSupported) = 0; - virtual std::string getProtocol() const = 0; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const = 0; - int getModel() const; - void setModel( int intModel ); - - static int methodId( const std::string &methodName ); - - #ifdef _LINUX - void setDevice(const std::string &device); - protected: - std::string strDevice; - #endif - - protected: - int send(const std::string &strMessage); - - private: - int model; - // static QMutex deviceMutex; - }; - -} +#pragma once + +#include "telldus-core.h" +#include +//#include + +namespace TelldusCore { + + const int ALL_METHODS = + TELLSTICK_TURNON | + TELLSTICK_TURNOFF | + TELLSTICK_BELL | + TELLSTICK_DIM; + + class Device + { + public: + Device(int model); + virtual ~Device(void); + + int switchState( int newState, const std::string &value = "" ); + virtual int methods(int methodsSupported) = 0; + virtual std::string getProtocol() const = 0; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const = 0; + int getModel() const; + void setModel( int intModel ); + + static int methodId( const std::string &methodName ); + + #ifdef _LINUX + void setDevice(const std::string &device); + protected: + std::string strDevice; + #endif + + protected: + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); + virtual int dim(unsigned char level); + int send(const std::string &strMessage); + + private: + int model; + // static QMutex deviceMutex; + }; + +} diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp index abfef43c..ab00a00b 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -1,133 +1,133 @@ -#include - -#include "DeviceGroup.h" -#include "Manager.h" - -using namespace TelldusCore; - -/* -* Constructor -*/ -DeviceGroup::DeviceGroup(int model, const std::string &strDevices) - :Device(model) -{ - if (strDevices.length() > 0) { - char *tempDevices = new char[strDevices.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempDevices, strDevices.size()+1, strDevices.c_str()); -#else - strcpy(tempDevices, strDevices.c_str()); -#endif - - Manager *manager = Manager::getInstance(); - char *strToken = strtok(tempDevices, ","); - do { - int intDevice = atoi(strToken); - Device *device = manager->getDevice(intDevice); - if (device != NULL) { - deviceList.push_back( device ); - } - } while ( (strToken = strtok(NULL, ",")) != NULL ); - - free(tempDevices); - } -} - -/* -* Destructor -*/ -DeviceGroup::~DeviceGroup(void) { -} - -/* -* Turn on this device -*/ -int DeviceGroup::turnOn(void) { - int retVal = TELLSTICK_ERROR_UNKNOWN; - - for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(ALL_METHODS); - if (methods & TELLSTICK_TURNON) { - int success = (*it)->turnOn(); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - } - return retVal; -} - -/* -* Turn off this device -*/ -int DeviceGroup::turnOff(void) { - int retVal = TELLSTICK_ERROR_UNKNOWN; - - for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(ALL_METHODS); - if (methods & TELLSTICK_TURNOFF) { - int success = (*it)->turnOff(); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - } - return retVal; -} - -/* -* Send a bell -*/ -int DeviceGroup::bell(void){ - int retVal = TELLSTICK_ERROR_UNKNOWN; - - for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(ALL_METHODS); - if (methods & TELLSTICK_BELL) { - int success = (*it)->bell(); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - } - return retVal; -} - -/* -* Turn off this device -*/ -int DeviceGroup::dim(unsigned char level){ - int retVal = TELLSTICK_ERROR_UNKNOWN; - - for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - int methods = (*it)->methods(ALL_METHODS); - if (methods & TELLSTICK_DIM) { - int success = (*it)->dim(level); - if (retVal != TELLSTICK_SUCCESS) { - retVal = success; - } - } - } - return retVal; -} - -bool DeviceGroup::parameterMatches( const std::string &name, const std::string &value ) const { - return false; -} - -/* -* Has the device got the method? -*/ -int DeviceGroup::methods(int supportedMethods){ - int retVal = 0; - - for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { - retVal = retVal | (*it)->methods(supportedMethods); - } - - return retVal; -} - -std::string DeviceGroup::getProtocol() const { - return "group"; -} +#include + +#include "DeviceGroup.h" +#include "Manager.h" + +using namespace TelldusCore; + +/* +* Constructor +*/ +DeviceGroup::DeviceGroup(int model, const std::string &strDevices) + :Device(model) +{ + if (strDevices.length() > 0) { + char *tempDevices = new char[strDevices.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempDevices, strDevices.size()+1, strDevices.c_str()); +#else + strcpy(tempDevices, strDevices.c_str()); +#endif + + Manager *manager = Manager::getInstance(); + char *strToken = strtok(tempDevices, ","); + do { + int intDevice = atoi(strToken); + Device *device = manager->getDevice(intDevice); + if (device != NULL) { + deviceList.push_back( device ); + } + } while ( (strToken = strtok(NULL, ",")) != NULL ); + + free(tempDevices); + } +} + +/* +* Destructor +*/ +DeviceGroup::~DeviceGroup(void) { +} + +/* +* Turn on this device +*/ +int DeviceGroup::turnOn(void) { + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (methods & TELLSTICK_TURNON) { + int success = (*it)->switchState( TELLSTICK_TURNON ); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +/* +* Turn off this device +*/ +int DeviceGroup::turnOff(void) { + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (methods & TELLSTICK_TURNOFF) { + int success = (*it)->switchState( TELLSTICK_TURNOFF ); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +/* +* Send a bell +*/ +int DeviceGroup::bell(void){ + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (methods & TELLSTICK_BELL) { + int success = (*it)->switchState( TELLSTICK_BELL ); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +/* +* Turn off this device +*/ +int DeviceGroup::dim(unsigned char level){ + int retVal = TELLSTICK_ERROR_UNKNOWN; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + int methods = (*it)->methods(ALL_METHODS); + if (methods & TELLSTICK_DIM) { + int success = (*it)->switchState( TELLSTICK_DIM, (char*)&level); + if (retVal != TELLSTICK_SUCCESS) { + retVal = success; + } + } + } + return retVal; +} + +bool DeviceGroup::parameterMatches( const std::string &name, const std::string &value ) const { + return false; +} + +/* +* Has the device got the method? +*/ +int DeviceGroup::methods(int supportedMethods){ + int retVal = 0; + + for (DeviceList::const_iterator it = deviceList.begin(); it != deviceList.end(); ++it) { + retVal = retVal | (*it)->methods(supportedMethods); + } + + return retVal; +} + +std::string DeviceGroup::getProtocol() const { + return "group"; +} diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 45e61817..46a93efa 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -1,536 +1,536 @@ -/** - * @defgroup core telldus-core - * Telldus Core is the base module used to interface a Telldus TellStick. - * @{ - */ - -#ifdef _WINDOWS - #include "stdafx.h" - #include -#endif -#include "telldus-core.h" -#include "Manager.h" -#include "Device.h" -#include "DeviceGroup.h" -#include "TellStickDuo.h" -#include -#include -#include -#include -#include - -void handleException(std::exception e); -using namespace std; -using namespace TelldusCore; - -inline char *wrapStdString( const std::string &string); - -/** - * @def TELLSTICK_TURNON - * Device-flag for devices supporting the tdTurnOn() call. - * - * @def TELLSTICK_TURNOFF - * Device-flag for devices supporting the tdTurnOff() call. - * - * @def TELLSTICK_BELL - * Device-flag for devices supporting the tdBell() call. - * - * @def TELLSTICK_TOGGLE - * This method is currently unimplemented. - * - * @def TELLSTICK_DIM - * Device-flag for devices supporting the tdDim() call. - * - * @def TELLSTICK_TYPE_DEVICE - * Device type of a single device. - * - * @def TELLSTICK_TYPE_GROUP - * Device type of a device which contains other devices. - * - * @def TELLSTICK_SUCCESS - * Error code. Returned when the command succeeded. - * - * @def TELLSTICK_ERROR_NOT_FOUND - * Error code. Returned if a TellStick was not found on the system. - * - * @def TELLSTICK_ERROR_PERMISSION_DENIED - * Error code. Returned if the user doesn't have privileges to open - * the TellStick device. - * - * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND - * Error code. The supplied device id was not found. - * - * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - * Error code. The requested method is not supported by the device. - * This should be avoided by a call to tdMethods(). - * - * @def TELLSTICK_ERROR_UNKNOWN - * Error code. An unkown error has occurred. - */ - -#define MAX_LOADSTRING 100 - -void WINAPI tdInit(void) { - Manager::getInstance(); //Create the manager-object -} - -int WINAPI tdRegisterDeviceEvent( deviceEvent eventFunction, void *context ) { - Manager *manager = Manager::getInstance(); - return manager->registerDeviceEvent( eventFunction, context ); -} - -int WINAPI tdRegisterRawDeviceEvent( rawDeviceEvent eventFunction, void *context ) { - Manager *manager = Manager::getInstance(); - return manager->registerRawDeviceEvent( eventFunction, context ); -} - -/** - * Close the library and clean up the cache it uses. - * This should be called when the library is not supposed to be used anymore - **/ -void WINAPI tdClose(void) { - Manager::close(); -} - -/** - * Turns a device on. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to turn on. - **/ -int WINAPI tdTurnOn(int intDeviceId){ - - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if(dev != NULL){ - int methods = dev->methods( TELLSTICK_TURNON ); - - int retval = 0; - - if ( !(methods & TELLSTICK_TURNON) ) { - retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } else { - retval = dev->turnOn(); - } - - return retval; - } else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Turns a device off. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to turn off. - */ -int WINAPI tdTurnOff(int intDeviceId){ - - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if(dev != NULL){ - int methods = dev->methods( TELLSTICK_TURNOFF ); - int retval = 0; - - if ( !(methods & TELLSTICK_TURNOFF) ) { - retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } else { - retval = dev->turnOff(); - } - - return retval; - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Sends bell command to devices supporting this. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to send bell to - */ -int WINAPI tdBell(int intDeviceId){ - - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if(dev != NULL){ - int methods = dev->methods( TELLSTICK_BELL ); - int retval = 0; - - if ( !(methods & TELLSTICK_BELL) ) { - retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } else { - retval = dev->bell(); - } - - return retval; - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * Dims a device. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. - * @param intDeviceId The device id to dim - * @param level The level the device should dim to. This value should be 0-255 - */ -int WINAPI tdDim(int intDeviceId, unsigned char level){ - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if(dev != NULL){ - int methods = dev->methods( TELLSTICK_DIM ); - int retval = 0; - - if ( !(methods & TELLSTICK_DIM) ) { - retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } else { - if (level == 0) { - retval = dev->turnOff(); - } else if (level == 255) { - retval = dev->turnOn(); - } else { - retval = dev->dim(level); - } - } - - return retval; - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -/** - * This function returns the number of devices configured - * @returns an integer of the total number of devices configured - */ -int WINAPI tdGetNumberOfDevices(void){ - int intReturn = -1; - try{ - Settings ts; - intReturn = ts.getNumberOfDevices(); - } - catch(exception e){ - intReturn = -1; - handleException(e); - } - return intReturn; -} - -/** - * This function returns the unique id of a device with a specific index. - * To get all the id numbers you should loop over all the devices: - * \code - * int intNumberOfDevices = tdGetNumberOfDevices(); - * for (int i = 0; i < intNumberOfDevices; i++) { - * int id = tdGetDeviceId( i ); - * // id now contains the id number of the device with index of i - * } - * \endcode - * @param intDeviceIndex The device index to query. The index starts from 0. - * @returns the unique id for the device or -1 if the device is not found. - */ -int WINAPI tdGetDeviceId(int intDeviceIndex){ - int intReturn = -1; - try{ - Settings ts; - intReturn = ts.getDeviceId(intDeviceIndex); - } - catch(exception e){ - intReturn = -1; - handleException(e); - } - return intReturn; -} - -/** - * Returns which type the device is. The device could be either - * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP - */ -int WINAPI tdGetDeviceType(int intDeviceId) { - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if (dev != NULL) { - DeviceGroup *deviceGroup = dynamic_cast(dev); - if (deviceGroup) { - return TELLSTICK_TYPE_GROUP; - } - } - } - catch(exception e){ - handleException(e); - } - return TELLSTICK_TYPE_DEVICE; -} - -/** - * Query a device for it's name. - * @param intDeviceId The unique id of the device to query - * @returns The name of the device or an empty string if the device is not found. - */ -char * WINAPI tdGetName(int intDeviceId){ - std::string strReturn; - try{ - Settings ts; - strReturn = ts.getName(intDeviceId); - } - catch(exception e){ - strReturn = ""; - handleException(e); - } - return wrapStdString(strReturn); -} - -bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ - bool blnSuccess = false; - try{ - Settings ts; - blnSuccess = ts.setName(intDeviceId, strNewName); - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -char* WINAPI tdGetProtocol(int intDeviceId){ - std::string strReturn = ""; - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if (dev != NULL) { - strReturn = dev->getProtocol(); - } - } - catch(exception e){ - handleException(e); - } - return wrapStdString(strReturn); -} - -bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ - bool blnSuccess = false; - try{ - Manager *manager = Manager::getInstance(); - blnSuccess = manager->setProtocol(intDeviceId, strProtocol); - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -int WINAPI tdGetModel(int intDeviceId){ - int intReturn = 0; - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(intDeviceId); - if (dev != NULL) { - intReturn = dev->getModel(); - } - } - catch(exception e){ - intReturn = 0; - handleException(e); - } - return intReturn; -} - -bool WINAPI tdSetModel(int intDeviceId, int intModel){ - bool blnSuccess = false; - try{ - Manager *manager = Manager::getInstance(); - manager->setModel(intDeviceId, intModel); - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ - - try{ - Settings ts; - return ts.setDeviceParameter(intDeviceId, strName, strValue); - } - catch(exception e){ - handleException(e); - } - return false; -} - -char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ - std::string strReturn = ""; - try{ - Settings ts; - strReturn = ts.getDeviceParameter(intDeviceId, strName); - if (strReturn.empty()) { - strReturn = defaultValue; - } - } - catch(exception e){ - handleException(e); - } - return wrapStdString(strReturn); -} - -int WINAPI tdAddDevice(){ - int intNewDeviceId = -1; - try{ - Settings ts; - intNewDeviceId = ts.addDevice(); - } - catch(exception e){ - intNewDeviceId = -1; - handleException(e); - } - return intNewDeviceId; -} - -bool WINAPI tdRemoveDevice(int intDeviceId){ - bool blnSuccess = false; - try{ - Settings ts; - blnSuccess = ts.removeDevice(intDeviceId); - } - catch(exception e){ - blnSuccess = false; - handleException(e); - } - return blnSuccess; -} - -/** - * Query a device for which methods it supports. By supplying the methods you support - * the library could remap the methods a device support for better fit the application. - * Example of querying a device supporting TELLSTICK_BELL: - * \code - * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); - * //methods is now TELLSTICK_BELL - * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); - * //methods is now TELLSTICK_TURNON because the client application doesn't support TELLSTICK_BELL - * \endcode - * @param id The device id to query - * @param methodsSupported The methods the client application supports - * @returns The method-flags OR'ed into an integer. - * @sa TELLSTICK_TURNON - * @sa TELLSTICK_TURNOFF - * @sa TELLSTICK_BELL - * @sa TELLSTICK_TOGGLE - * @sa TELLSTICK_DIM - */ -int WINAPI tdMethods(int id, int methodsSupported){ - - int intMethods = 0; - try{ - Manager *manager = Manager::getInstance(); - Device* dev = manager->getDevice(id); - if (dev != NULL) { - intMethods = dev->methods(methodsSupported); - } - } - catch(exception e){ - intMethods = 0; - handleException(e); - } - intMethods = intMethods & methodsSupported; //Strip the methods not supported by client. - return intMethods; -} - -/** - * Get a human readable string from an error code returned - * from a function in telldus-core. - * @param intErrorNo The error code to translate. - * @returns a string ready to show to the user. - * @sa TELLSTICK_SUCCESS - * @sa TELLSTICK_ERROR_NOT_FOUND - * @sa TELLSTICK_ERROR_PERMISSION_DENIED - * @sa TELLSTICK_ERROR_DEVICE_NOT_FOUND - * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - * @sa TELLSTICK_ERROR_UNKNOWN - */ -char * WINAPI tdGetErrorString(int intErrorNo) { - const int numResponses = 5; - const char *responses[numResponses] = { - "Success", - "TellStick not found", - "Permission denied", - "Device not found", - "The method you tried to use is not supported by the device" - }; - std::string strReturn; - intErrorNo = abs(intErrorNo); //We don't use negative values here. - if (intErrorNo >= numResponses) { - strReturn = "Unknown error"; - } else { - // Copy the error string to strReturn - strReturn = responses[intErrorNo]; - } - return wrapStdString(strReturn); -} - - -//******** -//* Error management, set strLogName to "" to turn off -//* -void handleException(exception e){ - -// std::string strLogName = "errorlog.txt"; - std::string strLogName = ""; - - if(strLogName.length() > 0){ - ofstream errorfile(strLogName.c_str(), ios::app); - if(errorfile){ - errorfile << e.what() << endl; - errorfile.close(); - } - } -} - -inline char *wrapStdString( const std::string &string) { - char *returnVal; -#ifdef _WINDOWS - returnVal = (char *)SysAllocStringByteLen(string.c_str(), string.size()); -#else - returnVal = (char *)malloc(sizeof(char) * (string.size()+1)); - strcpy(returnVal, string.c_str()); -#endif - return returnVal; -} - -/*\@}*/ +/** + * @defgroup core telldus-core + * Telldus Core is the base module used to interface a Telldus TellStick. + * @{ + */ + +#ifdef _WINDOWS + #include "stdafx.h" + #include +#endif +#include "telldus-core.h" +#include "Manager.h" +#include "Device.h" +#include "DeviceGroup.h" +#include "TellStickDuo.h" +#include +#include +#include +#include +#include + +void handleException(std::exception e); +using namespace std; +using namespace TelldusCore; + +inline char *wrapStdString( const std::string &string); + +/** + * @def TELLSTICK_TURNON + * Device-flag for devices supporting the tdTurnOn() call. + * + * @def TELLSTICK_TURNOFF + * Device-flag for devices supporting the tdTurnOff() call. + * + * @def TELLSTICK_BELL + * Device-flag for devices supporting the tdBell() call. + * + * @def TELLSTICK_TOGGLE + * This method is currently unimplemented. + * + * @def TELLSTICK_DIM + * Device-flag for devices supporting the tdDim() call. + * + * @def TELLSTICK_TYPE_DEVICE + * Device type of a single device. + * + * @def TELLSTICK_TYPE_GROUP + * Device type of a device which contains other devices. + * + * @def TELLSTICK_SUCCESS + * Error code. Returned when the command succeeded. + * + * @def TELLSTICK_ERROR_NOT_FOUND + * Error code. Returned if a TellStick was not found on the system. + * + * @def TELLSTICK_ERROR_PERMISSION_DENIED + * Error code. Returned if the user doesn't have privileges to open + * the TellStick device. + * + * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND + * Error code. The supplied device id was not found. + * + * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + * Error code. The requested method is not supported by the device. + * This should be avoided by a call to tdMethods(). + * + * @def TELLSTICK_ERROR_UNKNOWN + * Error code. An unkown error has occurred. + */ + +#define MAX_LOADSTRING 100 + +void WINAPI tdInit(void) { + Manager::getInstance(); //Create the manager-object +} + +int WINAPI tdRegisterDeviceEvent( deviceEvent eventFunction, void *context ) { + Manager *manager = Manager::getInstance(); + return manager->registerDeviceEvent( eventFunction, context ); +} + +int WINAPI tdRegisterRawDeviceEvent( rawDeviceEvent eventFunction, void *context ) { + Manager *manager = Manager::getInstance(); + return manager->registerRawDeviceEvent( eventFunction, context ); +} + +/** + * Close the library and clean up the cache it uses. + * This should be called when the library is not supposed to be used anymore + **/ +void WINAPI tdClose(void) { + Manager::close(); +} + +/** + * Turns a device on. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to turn on. + **/ +int WINAPI tdTurnOn(int intDeviceId){ + + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if(dev != NULL){ + int methods = dev->methods( TELLSTICK_TURNON ); + + int retval = 0; + + if ( !(methods & TELLSTICK_TURNON) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } else { + retval = dev->switchState(TELLSTICK_TURNON); + } + + return retval; + } else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + catch(exception e){ + handleException(e); + } + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Turns a device off. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to turn off. + */ +int WINAPI tdTurnOff(int intDeviceId){ + + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if(dev != NULL){ + int methods = dev->methods( TELLSTICK_TURNOFF ); + int retval = 0; + + if ( !(methods & TELLSTICK_TURNOFF) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } else { + retval = dev->switchState(TELLSTICK_TURNOFF); + } + + return retval; + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + catch(exception e){ + handleException(e); + } + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Sends bell command to devices supporting this. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to send bell to + */ +int WINAPI tdBell(int intDeviceId){ + + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if(dev != NULL){ + int methods = dev->methods( TELLSTICK_BELL ); + int retval = 0; + + if ( !(methods & TELLSTICK_BELL) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } else { + retval = dev->switchState( TELLSTICK_BELL ); + } + + return retval; + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + catch(exception e){ + handleException(e); + } + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * Dims a device. + * Make sure the device supports this by calling tdMethods() before any + * call to this function. + * @param intDeviceId The device id to dim + * @param level The level the device should dim to. This value should be 0-255 + */ +int WINAPI tdDim(int intDeviceId, unsigned char level){ + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if(dev != NULL){ + int methods = dev->methods( TELLSTICK_DIM ); + int retval = 0; + + if ( !(methods & TELLSTICK_DIM) ) { + retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } else { + if (level == 0) { + retval = dev->switchState( TELLSTICK_TURNOFF ); + } else if (level == 255) { + retval = dev->switchState( TELLSTICK_TURNON ); + } else { + retval = dev->switchState( TELLSTICK_DIM, (char *)&level); + } + } + + return retval; + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + catch(exception e){ + handleException(e); + } + return TELLSTICK_ERROR_UNKNOWN; +} + +/** + * This function returns the number of devices configured + * @returns an integer of the total number of devices configured + */ +int WINAPI tdGetNumberOfDevices(void){ + int intReturn = -1; + try{ + Settings ts; + intReturn = ts.getNumberOfDevices(); + } + catch(exception e){ + intReturn = -1; + handleException(e); + } + return intReturn; +} + +/** + * This function returns the unique id of a device with a specific index. + * To get all the id numbers you should loop over all the devices: + * \code + * int intNumberOfDevices = tdGetNumberOfDevices(); + * for (int i = 0; i < intNumberOfDevices; i++) { + * int id = tdGetDeviceId( i ); + * // id now contains the id number of the device with index of i + * } + * \endcode + * @param intDeviceIndex The device index to query. The index starts from 0. + * @returns the unique id for the device or -1 if the device is not found. + */ +int WINAPI tdGetDeviceId(int intDeviceIndex){ + int intReturn = -1; + try{ + Settings ts; + intReturn = ts.getDeviceId(intDeviceIndex); + } + catch(exception e){ + intReturn = -1; + handleException(e); + } + return intReturn; +} + +/** + * Returns which type the device is. The device could be either + * TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP + */ +int WINAPI tdGetDeviceType(int intDeviceId) { + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if (dev != NULL) { + DeviceGroup *deviceGroup = dynamic_cast(dev); + if (deviceGroup) { + return TELLSTICK_TYPE_GROUP; + } + } + } + catch(exception e){ + handleException(e); + } + return TELLSTICK_TYPE_DEVICE; +} + +/** + * Query a device for it's name. + * @param intDeviceId The unique id of the device to query + * @returns The name of the device or an empty string if the device is not found. + */ +char * WINAPI tdGetName(int intDeviceId){ + std::string strReturn; + try{ + Settings ts; + strReturn = ts.getName(intDeviceId); + } + catch(exception e){ + strReturn = ""; + handleException(e); + } + return wrapStdString(strReturn); +} + +bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ + bool blnSuccess = false; + try{ + Settings ts; + blnSuccess = ts.setName(intDeviceId, strNewName); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +char* WINAPI tdGetProtocol(int intDeviceId){ + std::string strReturn = ""; + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if (dev != NULL) { + strReturn = dev->getProtocol(); + } + } + catch(exception e){ + handleException(e); + } + return wrapStdString(strReturn); +} + +bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ + bool blnSuccess = false; + try{ + Manager *manager = Manager::getInstance(); + blnSuccess = manager->setProtocol(intDeviceId, strProtocol); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +int WINAPI tdGetModel(int intDeviceId){ + int intReturn = 0; + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(intDeviceId); + if (dev != NULL) { + intReturn = dev->getModel(); + } + } + catch(exception e){ + intReturn = 0; + handleException(e); + } + return intReturn; +} + +bool WINAPI tdSetModel(int intDeviceId, int intModel){ + bool blnSuccess = false; + try{ + Manager *manager = Manager::getInstance(); + manager->setModel(intDeviceId, intModel); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ + + try{ + Settings ts; + return ts.setDeviceParameter(intDeviceId, strName, strValue); + } + catch(exception e){ + handleException(e); + } + return false; +} + +char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ + std::string strReturn = ""; + try{ + Settings ts; + strReturn = ts.getDeviceParameter(intDeviceId, strName); + if (strReturn.empty()) { + strReturn = defaultValue; + } + } + catch(exception e){ + handleException(e); + } + return wrapStdString(strReturn); +} + +int WINAPI tdAddDevice(){ + int intNewDeviceId = -1; + try{ + Settings ts; + intNewDeviceId = ts.addDevice(); + } + catch(exception e){ + intNewDeviceId = -1; + handleException(e); + } + return intNewDeviceId; +} + +bool WINAPI tdRemoveDevice(int intDeviceId){ + bool blnSuccess = false; + try{ + Settings ts; + blnSuccess = ts.removeDevice(intDeviceId); + } + catch(exception e){ + blnSuccess = false; + handleException(e); + } + return blnSuccess; +} + +/** + * Query a device for which methods it supports. By supplying the methods you support + * the library could remap the methods a device support for better fit the application. + * Example of querying a device supporting TELLSTICK_BELL: + * \code + * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); + * //methods is now TELLSTICK_BELL + * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); + * //methods is now TELLSTICK_TURNON because the client application doesn't support TELLSTICK_BELL + * \endcode + * @param id The device id to query + * @param methodsSupported The methods the client application supports + * @returns The method-flags OR'ed into an integer. + * @sa TELLSTICK_TURNON + * @sa TELLSTICK_TURNOFF + * @sa TELLSTICK_BELL + * @sa TELLSTICK_TOGGLE + * @sa TELLSTICK_DIM + */ +int WINAPI tdMethods(int id, int methodsSupported){ + + int intMethods = 0; + try{ + Manager *manager = Manager::getInstance(); + Device* dev = manager->getDevice(id); + if (dev != NULL) { + intMethods = dev->methods(methodsSupported); + } + } + catch(exception e){ + intMethods = 0; + handleException(e); + } + intMethods = intMethods & methodsSupported; //Strip the methods not supported by client. + return intMethods; +} + +/** + * Get a human readable string from an error code returned + * from a function in telldus-core. + * @param intErrorNo The error code to translate. + * @returns a string ready to show to the user. + * @sa TELLSTICK_SUCCESS + * @sa TELLSTICK_ERROR_NOT_FOUND + * @sa TELLSTICK_ERROR_PERMISSION_DENIED + * @sa TELLSTICK_ERROR_DEVICE_NOT_FOUND + * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + * @sa TELLSTICK_ERROR_UNKNOWN + */ +char * WINAPI tdGetErrorString(int intErrorNo) { + const int numResponses = 5; + const char *responses[numResponses] = { + "Success", + "TellStick not found", + "Permission denied", + "Device not found", + "The method you tried to use is not supported by the device" + }; + std::string strReturn; + intErrorNo = abs(intErrorNo); //We don't use negative values here. + if (intErrorNo >= numResponses) { + strReturn = "Unknown error"; + } else { + // Copy the error string to strReturn + strReturn = responses[intErrorNo]; + } + return wrapStdString(strReturn); +} + + +//******** +//* Error management, set strLogName to "" to turn off +//* +void handleException(exception e){ + +// std::string strLogName = "errorlog.txt"; + std::string strLogName = ""; + + if(strLogName.length() > 0){ + ofstream errorfile(strLogName.c_str(), ios::app); + if(errorfile){ + errorfile << e.what() << endl; + errorfile.close(); + } + } +} + +inline char *wrapStdString( const std::string &string) { + char *returnVal; +#ifdef _WINDOWS + returnVal = (char *)SysAllocStringByteLen(string.c_str(), string.size()); +#else + returnVal = (char *)malloc(sizeof(char) * (string.size()+1)); + strcpy(returnVal, string.c_str()); +#endif + return returnVal; +} + +/*\@}*/ From ba12417c79b637cf37f5afac2819ec016d389c28 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 8 Feb 2009 17:54:02 +0000 Subject: [PATCH 0792/2215] Made the device save it last sent command --- .../driver/libtelldus-core/Device.cpp | 27 ++- telldus-core/driver/libtelldus-core/Device.h | 4 +- .../driver/libtelldus-core/DeviceGroup.cpp | 4 +- .../driver/libtelldus-core/DeviceGroup.h | 17 +- .../driver/libtelldus-core/DeviceIkea.cpp | 4 +- .../driver/libtelldus-core/DeviceIkea.h | 57 ++--- .../driver/libtelldus-core/DeviceNexa.cpp | 4 +- .../driver/libtelldus-core/DeviceNexa.h | 55 ++--- .../driver/libtelldus-core/DeviceSartano.cpp | 4 +- .../driver/libtelldus-core/DeviceSartano.h | 49 ++-- .../driver/libtelldus-core/DeviceWaveman.cpp | 4 +- .../driver/libtelldus-core/DeviceWaveman.h | 6 +- .../driver/libtelldus-core/Manager.cpp | 21 +- telldus-core/driver/libtelldus-core/Manager.h | 3 + .../driver/libtelldus-core/telldus-core.cpp | 6 + .../driver/libtelldus-core/telldus-core.h | 223 +++++++++--------- 16 files changed, 264 insertions(+), 224 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 6686f94f..e740b357 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -1,12 +1,14 @@ #include "Device.h" +#include "Manager.h" #include using namespace TelldusCore; /* * Constructor */ -Device::Device(int m) - : model(m) +Device::Device(int id, int m) + : deviceId(id), + model(m) { } @@ -17,17 +19,28 @@ Device::~Device(void) { } int Device::switchState( int newState, const std::string &value ) { + int retVal = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; switch (newState) { case TELLSTICK_TURNON: - return turnOn(); + retVal = turnOn(); + break; case TELLSTICK_TURNOFF: - return turnOff(); + retVal = turnOff(); + break; case TELLSTICK_BELL: - return bell(); + retVal = bell(); + break; case TELLSTICK_DIM: - return dim( value[0] ); + retVal = dim( value[0] ); + break; } - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + if (retVal == TELLSTICK_SUCCESS) { + if (newState != TELLSTICK_BELL) { //Bell doesn't toggle any state + Manager *manager = Manager::getInstance(); + manager->setDeviceState(deviceId, newState, ""); + } + } + return retVal; } int Device::getModel() const { diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index b6684265..36acf44f 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -15,7 +15,7 @@ namespace TelldusCore { class Device { public: - Device(int model); + Device(int id, int model); virtual ~Device(void); int switchState( int newState, const std::string &value = "" ); @@ -41,7 +41,7 @@ namespace TelldusCore { int send(const std::string &strMessage); private: - int model; + int deviceId, model; // static QMutex deviceMutex; }; diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp index ab00a00b..71c52670 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -8,8 +8,8 @@ using namespace TelldusCore; /* * Constructor */ -DeviceGroup::DeviceGroup(int model, const std::string &strDevices) - :Device(model) +DeviceGroup::DeviceGroup(int id, int model, const std::string &strDevices) + :Device(id, model) { if (strDevices.length() > 0) { char *tempDevices = new char[strDevices.size()+1]; diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.h b/telldus-core/driver/libtelldus-core/DeviceGroup.h index 11f08229..5666e056 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.h +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.h @@ -12,17 +12,18 @@ namespace TelldusCore { class DeviceGroup : public Device { public: - DeviceGroup(int model, const std::string &strDevices); - virtual int turnOn(void); - virtual int turnOff(void); - virtual int bell(void); - virtual int dim(unsigned char level); + DeviceGroup(int id, int model, const std::string &strDevices); + ~DeviceGroup(void); + virtual int methods(int methodsSupported); virtual std::string getProtocol() const; virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - public: - ~DeviceGroup(void); + + protected: + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); + virtual int dim(unsigned char level); private: DeviceList deviceList; diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index c9ec6c6a..a034389e 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -15,8 +15,8 @@ using namespace TelldusCore; /* * Constructor */ -DeviceIkea::DeviceIkea(int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle) - :Device(model) +DeviceIkea::DeviceIkea(int id, int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle) + :Device(id, model) { if (strSystem.length() > 0) { intSystem = atoi(strSystem.c_str()) - 1; diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index 54de3521..fbe5cc87 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -1,28 +1,29 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceIkea : public Device - { - public: - DeviceIkea(int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); - virtual int turnOn(void); - virtual int turnOff(void); - virtual int dim(unsigned char level); - virtual int methods(int methodsSupported); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - public: - ~DeviceIkea(void); - - protected: - int intSystem; - int intUnits; - int intFadeStyle; - std::string getStringCode(unsigned char); - }; - -} +#pragma once +#include "Device.h" +#include + +namespace TelldusCore { + + class DeviceIkea : public Device + { + public: + DeviceIkea(int id, int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); + virtual int methods(int methodsSupported); + virtual std::string getProtocol() const; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const; + + public: + ~DeviceIkea(void); + + protected: + virtual int turnOn(void); + virtual int turnOff(void); + virtual int dim(unsigned char level); + + int intSystem; + int intUnits; + int intFadeStyle; + std::string getStringCode(unsigned char); + }; + +} diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 46fcccd1..07751d98 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -11,8 +11,8 @@ using namespace TelldusCore; /* * Constructor */ -DeviceNexa::DeviceNexa(int model, const std::string &strHouse, const std::string &strCode) - :Device(model) +DeviceNexa::DeviceNexa(int id, int model, const std::string &strHouse, const std::string &strCode) + :Device(id, model) { if (strHouse.length() > 0) { intHouse = strHouse[0] - 'A'; diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 48b37e53..27e134fe 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -1,27 +1,28 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceNexa : public Device - { - public: - DeviceNexa(int model, const std::string &strHouse, const std::string &strCode); - virtual int turnOn(void); - virtual int turnOff(void); - virtual int bell(void); - virtual int methods(int methodsSupported); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - public: - ~DeviceNexa(void); - - protected: - int intHouse; - int intCode; - std::string getStringCode(int); - }; - -} +#pragma once +#include "Device.h" +#include + +namespace TelldusCore { + + class DeviceNexa : public Device + { + public: + DeviceNexa(int id, int model, const std::string &strHouse, const std::string &strCode); + virtual int methods(int methodsSupported); + virtual std::string getProtocol() const; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const; + + public: + ~DeviceNexa(void); + + protected: + virtual int turnOn(void); + virtual int turnOff(void); + virtual int bell(void); + + int intHouse; + int intCode; + std::string getStringCode(int); + }; + +} diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index 580a49e3..d8066b6e 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -10,8 +10,8 @@ using namespace TelldusCore; /* * Constructor */ -DeviceSartano::DeviceSartano(int model, const std::string &strNewCode) - :Device(model) +DeviceSartano::DeviceSartano(int id, int model, const std::string &strNewCode) + :Device(id, model) { strCode = strNewCode; } diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index 5da531be..d3fb0734 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -1,24 +1,25 @@ -#pragma once -#include "Device.h" -#include - -namespace TelldusCore { - - class DeviceSartano : public Device - { - public: - DeviceSartano(int model, const std::string &strCode); - virtual int turnOn(void); - virtual int turnOff(void); - virtual int methods(int methodsSupported); - virtual std::string getProtocol() const; - virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - - ~DeviceSartano(void); - - protected: - std::string getStringCode(void); - std::string strCode; - }; - -} +#pragma once +#include "Device.h" +#include + +namespace TelldusCore { + + class DeviceSartano : public Device + { + public: + DeviceSartano(int id, int model, const std::string &strCode); + virtual int methods(int methodsSupported); + virtual std::string getProtocol() const; + virtual bool parameterMatches( const std::string &name, const std::string &value ) const; + + ~DeviceSartano(void); + + protected: + virtual int turnOn(void); + virtual int turnOff(void); + + std::string getStringCode(void); + std::string strCode; + }; + +} diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index a5f27ef4..7bd35829 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -11,8 +11,8 @@ using namespace TelldusCore; /* * Constructor */ -DeviceWaveman::DeviceWaveman(int model, const std::string &strHouse, const std::string &strCode) - :DeviceNexa(model, strHouse, strCode){ +DeviceWaveman::DeviceWaveman(int id, int model, const std::string &strHouse, const std::string &strCode) + :DeviceNexa(id, model, strHouse, strCode){ } /* diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index 2a9f1c16..0a99912f 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -7,9 +7,11 @@ namespace TelldusCore { class DeviceWaveman : public DeviceNexa { public: - DeviceWaveman(int model, const std::string &strHouse, const std::string &strCode); - virtual int turnOff(void); + DeviceWaveman(int id, int model, const std::string &strHouse, const std::string &strCode); virtual int methods(int methodsSupported); + + protected: + virtual int turnOff(void); }; } diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index fd7a7e0a..9f684938 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -74,26 +74,26 @@ Device *Manager::getDevice(int intDeviceId){ if (strcasecmp(protocol.c_str(), "arctech") == 0){ std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceNexa(intModel, strHouse, strCode); + dev = new DeviceNexa(intDeviceId, intModel, strHouse, strCode); } else if (strcasecmp(protocol.c_str(), "group") == 0) { std::string strDevices = settings.getDeviceParameter(intDeviceId, "devices"); - dev = new DeviceGroup(intModel, strDevices); + dev = new DeviceGroup(intDeviceId, intModel, strDevices); } else if (strcasecmp(protocol.c_str(), "Waveman") == 0) { std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceWaveman(intModel, strHouse, strCode); + dev = new DeviceWaveman(intDeviceId, intModel, strHouse, strCode); } else if (strcasecmp(protocol.c_str(), "Sartano") == 0) { std::string strCode = settings.getDeviceParameter(intDeviceId, "sartano_code"); - dev = new DeviceSartano(intModel, strCode); + dev = new DeviceSartano(intDeviceId, intModel, strCode); } else if (strcasecmp(protocol.c_str(), "Ikea") == 0) { std::string strSystem = settings.getDeviceParameter(intDeviceId, "ikea_system"); std::string strUnits = settings.getDeviceParameter(intDeviceId, "ikea_units"); std::string strFade = settings.getDeviceParameter(intDeviceId, "ikea_fade"); - dev = new DeviceIkea(intModel, strSystem, strUnits, strFade); + dev = new DeviceIkea(intDeviceId, intModel, strSystem, strUnits, strFade); } else { return NULL; @@ -147,6 +147,17 @@ bool Manager::setModel(int intDeviceId, int intModel) { return retval; } +bool Manager::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { + return settings.setDeviceState(intDeviceId, intDeviceState, strDeviceStateValue); +} + +int Manager::getDeviceState( int intDeviceId ) const { + return settings.getDeviceState(intDeviceId); +} + +std::string Manager::getDeviceStateValue( int intDeviceId ) const { + return settings.getDeviceStateValue(intDeviceId); +} bool Manager::deviceLoaded(int deviceId) const { DeviceMap::const_iterator iterator = devices.find(deviceId); diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index 898c0563..7494f9b4 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -51,6 +51,9 @@ namespace TelldusCore { // bool setName(int intDeviceId, const std::string &strNewName); bool setModel(int intDeviceId, int intModel); // bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); + bool setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ); + int getDeviceState( int intDeviceId ) const; + std::string getDeviceStateValue( int intDeviceId ) const; static Manager *getInstance(); static void close(); diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 46a93efa..9d94663c 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -230,6 +230,12 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ return TELLSTICK_ERROR_UNKNOWN; } +int WINAPI tdLastSentCommand( int intDeviceId ) { + Manager *manager = Manager::getInstance(); + int lastSentCommand = manager->getDeviceState( intDeviceId ); + return (lastSentCommand > 0 ? lastSentCommand : TELLSTICK_TURNOFF ); +} + /** * This function returns the number of devices configured * @returns an integer of the total number of devices configured diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index 3e5afe49..d6c2a259 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -1,111 +1,112 @@ -#ifndef TELLDUSCORE_H -#define TELLDUSCORE_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// TELLSTICK_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef _WINDOWS - #ifdef TELLDUSCORE_EXPORTS - #define TELLSTICK_API __declspec(dllexport) - #else - #define TELLSTICK_API __declspec(dllimport) - #endif - #define WINAPI __stdcall -#else - #define WINAPI - #define TELLSTICK_API -#endif - -typedef void (WINAPI *deviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); -typedef void (WINAPI *rawDeviceEvent)(const char *data, int callbackId, void *context); - -#ifdef __cplusplus -extern "C" { -#endif - TELLSTICK_API void WINAPI tdInit(void); - TELLSTICK_API int WINAPI tdRegisterDeviceEvent( deviceEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( rawDeviceEvent eventFunction, void *context ); - TELLSTICK_API void WINAPI tdClose(void); - TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); - TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); - TELLSTICK_API int WINAPI tdBell(int intDeviceId); - TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); - TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); - - TELLSTICK_API int WINAPI tdGetNumberOfDevices(); - TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); - TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); - - TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); - - TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); - TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); - TELLSTICK_API int WINAPI tdGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, int intModel); - - TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); - TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); - - TELLSTICK_API int WINAPI tdAddDevice(); - TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); -#ifdef __cplusplus -} -#endif - -//Device methods -#define TELLSTICK_TURNON 1 -#define TELLSTICK_TURNOFF 2 -#define TELLSTICK_BELL 4 -#define TELLSTICK_TOGGLE 8 -#define TELLSTICK_DIM 16 - -//Error codes -#define TELLSTICK_SUCCESS 0 -#define TELLSTICK_ERROR_NOT_FOUND -1 -#define TELLSTICK_ERROR_PERMISSION_DENIED -2 -#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 -#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 -#define TELLSTICK_ERROR_UNKNOWN -99 - -//Device typedef -#define TELLSTICK_TYPE_DEVICE 1 -#define TELLSTICK_TYPE_GROUP 2 - -//Protocol Nexa -#define TELLSTICK_DEVICE_YCR3500 1 -#define TELLSTICK_DEVICE_YCR300D 2 -#define TELLSTICK_DEVICE_WSR1000 3 -#define TELLSTICK_DEVICE_CMR1000 4 -#define TELLSTICK_DEVICE_CMR300 5 -#define TELLSTICK_DEVICE_PA33300 6 -#define TELLSTICK_DEVICE_EL2000 8 -#define TELLSTICK_DEVICE_EL2005 9 -#define TELLSTICK_DEVICE_EL2006 10 -#define TELLSTICK_DEVICE_SYCR3500 12 -#define TELLSTICK_DEVICE_SYCR300 13 -#define TELLSTICK_DEVICE_HDR105 14 -#define TELLSTICK_DEVICE_ML7100 15 -#define TELLSTICK_DEVICE_EL2004 16 -#define TELLSTICK_DEVICE_EL2016 17 -#define TELLSTICK_DEVICE_EL2010 18 -#define TELLSTICK_DEVICE_LYCR1000 20 -#define TELLSTICK_DEVICE_LYCR300 21 -#define TELLSTICK_DEVICE_LCMR1000 22 -#define TELLSTICK_DEVICE_LCMR300 23 -#define TELLSTICK_DEVICE_EL2023 24 -#define TELLSTICK_DEVICE_EL2024 25 -#define TELLSTICK_DEVICE_EL2021 26 -#define TELLSTICK_DEVICE_EL2017 27 -#define TELLSTICK_DEVICE_EL2019 28 - -//Protocol Ikea -#define TELLSTICK_DEVICE_KOPPLA 19 - -#endif +#ifndef TELLDUSCORE_H +#define TELLDUSCORE_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLSTICK_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef _WINDOWS + #ifdef TELLDUSCORE_EXPORTS + #define TELLSTICK_API __declspec(dllexport) + #else + #define TELLSTICK_API __declspec(dllimport) + #endif + #define WINAPI __stdcall +#else + #define WINAPI + #define TELLSTICK_API +#endif + +typedef void (WINAPI *deviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); +typedef void (WINAPI *rawDeviceEvent)(const char *data, int callbackId, void *context); + +#ifdef __cplusplus +extern "C" { +#endif + TELLSTICK_API void WINAPI tdInit(void); + TELLSTICK_API int WINAPI tdRegisterDeviceEvent( deviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( rawDeviceEvent eventFunction, void *context ); + TELLSTICK_API void WINAPI tdClose(void); + TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); + TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); + TELLSTICK_API int WINAPI tdBell(int intDeviceId); + TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); + TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId ); + + TELLSTICK_API int WINAPI tdGetNumberOfDevices(); + TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); + TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); + + TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); + + TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); + TELLSTICK_API int WINAPI tdGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, int intModel); + + TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); + + TELLSTICK_API int WINAPI tdAddDevice(); + TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); +#ifdef __cplusplus +} +#endif + +//Device methods +#define TELLSTICK_TURNON 1 +#define TELLSTICK_TURNOFF 2 +#define TELLSTICK_BELL 4 +#define TELLSTICK_TOGGLE 8 +#define TELLSTICK_DIM 16 + +//Error codes +#define TELLSTICK_SUCCESS 0 +#define TELLSTICK_ERROR_NOT_FOUND -1 +#define TELLSTICK_ERROR_PERMISSION_DENIED -2 +#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 +#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 +#define TELLSTICK_ERROR_UNKNOWN -99 + +//Device typedef +#define TELLSTICK_TYPE_DEVICE 1 +#define TELLSTICK_TYPE_GROUP 2 + +//Protocol Nexa +#define TELLSTICK_DEVICE_YCR3500 1 +#define TELLSTICK_DEVICE_YCR300D 2 +#define TELLSTICK_DEVICE_WSR1000 3 +#define TELLSTICK_DEVICE_CMR1000 4 +#define TELLSTICK_DEVICE_CMR300 5 +#define TELLSTICK_DEVICE_PA33300 6 +#define TELLSTICK_DEVICE_EL2000 8 +#define TELLSTICK_DEVICE_EL2005 9 +#define TELLSTICK_DEVICE_EL2006 10 +#define TELLSTICK_DEVICE_SYCR3500 12 +#define TELLSTICK_DEVICE_SYCR300 13 +#define TELLSTICK_DEVICE_HDR105 14 +#define TELLSTICK_DEVICE_ML7100 15 +#define TELLSTICK_DEVICE_EL2004 16 +#define TELLSTICK_DEVICE_EL2016 17 +#define TELLSTICK_DEVICE_EL2010 18 +#define TELLSTICK_DEVICE_LYCR1000 20 +#define TELLSTICK_DEVICE_LYCR300 21 +#define TELLSTICK_DEVICE_LCMR1000 22 +#define TELLSTICK_DEVICE_LCMR300 23 +#define TELLSTICK_DEVICE_EL2023 24 +#define TELLSTICK_DEVICE_EL2024 25 +#define TELLSTICK_DEVICE_EL2021 26 +#define TELLSTICK_DEVICE_EL2017 27 +#define TELLSTICK_DEVICE_EL2019 28 + +//Protocol Ikea +#define TELLSTICK_DEVICE_KOPPLA 19 + +#endif From 1f68ee74a90c214dea3d3074c6754a130c1e37ff Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Sun, 8 Feb 2009 17:55:24 +0000 Subject: [PATCH 0793/2215] Showed the last sent command in the the list of devices --- telldus-gui/TelldusGui/device.cpp | 8 ++++++-- telldus-gui/TelldusGui/device.h | 2 +- telldus-gui/TelldusGui/devicemodel.cpp | 19 ++++++++++++++++-- telldus-gui/TelldusGui/devicemodel.h | 2 ++ .../images/{turn-on.png => state_1.png} | Bin .../images/{turn-off.png => state_2.png} | Bin telldus-gui/TelldusGui/methodwidget.cpp | 4 ++-- telldus-gui/TelldusGui/telldusgui.qrc | 4 ++-- 8 files changed, 30 insertions(+), 9 deletions(-) rename telldus-gui/TelldusGui/images/{turn-on.png => state_1.png} (100%) rename telldus-gui/TelldusGui/images/{turn-off.png => state_2.png} (100%) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 96399e54..b38beaca 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -21,7 +21,7 @@ Device::Device(int id) p_model = tdGetModel(id); char *protocol = tdGetProtocol(id); - p_protocol = QString::fromUtf8( protocol ); + p_protocol = QString::fromLocal8Bit( protocol ); free( protocol ); } } @@ -121,7 +121,7 @@ void Device::save() { } if (p_protocolChanged) { - tdSetProtocol(p_id, p_protocol.toUtf8()); + tdSetProtocol(p_id, p_protocol.toLocal8Bit()); p_protocolChanged = false; } @@ -142,6 +142,10 @@ void Device::bell() { triggerEvent( tdBell( p_id ) ); } +int Device::lastSentCommand() const { + return tdLastSentCommand( p_id ); +} + void Device::updateMethods() { int methods = tdMethods(p_id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM); if (p_methods != methods) { diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index f61b6b7b..7d1df0a0 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -32,6 +32,7 @@ public: const QString &protocol(); int deviceType() const; + int lastSentCommand() const; int methods() const; @@ -41,7 +42,6 @@ public slots: void turnOn(); void bell(); - signals: void deviceAdded( int id ); void methodsChanged( int newMethods ); diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index b1117cac..c7e918f5 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -29,9 +29,20 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const { if (index.column() == 0) { if (role == Qt::DisplayRole) { - return tr("on"); + Device *device = this->device( index ); + switch( device->lastSentCommand() ) { + case TELLSTICK_TURNON: + return tr("on"); + case TELLSTICK_TURNOFF: + return tr("off"); + case TELLSTICK_DIM: + return tr("dimmed"); + } + return tr("unknown %1").arg(device->lastSentCommand()); } else if (role == Qt::DecorationRole) { - return QIcon( ":/images/devices.png" ); + Device *device = this->device( index ); + int lastSentCommand = device->lastSentCommand(); + return QIcon( QString(":/images/state_%1.png").arg(lastSentCommand) ); } else if (role == Qt::TextAlignmentRole) { return Qt::AlignCenter; } @@ -134,3 +145,7 @@ int DeviceModel::deviceId( int index ) const { indexToId[index] = id; return id; } + +void DeviceModel::deviceEvent(int /*deviceId*/, int /*method*/, const char */*data*/, int /*callbackId*/, void */*context*/) { + //TODO: +} diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index ff65899a..a7c2f76f 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -33,6 +33,8 @@ private slots: void deviceAdded( int id ); private: + static void deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); + int deviceId( const QModelIndex &index ) const; int deviceId( int index ) const; diff --git a/telldus-gui/TelldusGui/images/turn-on.png b/telldus-gui/TelldusGui/images/state_1.png similarity index 100% rename from telldus-gui/TelldusGui/images/turn-on.png rename to telldus-gui/TelldusGui/images/state_1.png diff --git a/telldus-gui/TelldusGui/images/turn-off.png b/telldus-gui/TelldusGui/images/state_2.png similarity index 100% rename from telldus-gui/TelldusGui/images/turn-off.png rename to telldus-gui/TelldusGui/images/state_2.png diff --git a/telldus-gui/TelldusGui/methodwidget.cpp b/telldus-gui/TelldusGui/methodwidget.cpp index 87a57a86..fca40cc1 100644 --- a/telldus-gui/TelldusGui/methodwidget.cpp +++ b/telldus-gui/TelldusGui/methodwidget.cpp @@ -18,11 +18,11 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) layout->setMargin(0); layout->setSpacing(0); - turnOff->setIcon( QIcon(":/images/turn-off.png") ); + turnOff->setIcon( QIcon(":/images/state_2.png") ); turnOff->setVisible( false ); layout->addWidget( turnOff ); - turnOn->setIcon( QIcon(":/images/turn-on.png") ); + turnOn->setIcon( QIcon(":/images/state_1.png") ); turnOn->setVisible( false ); layout->addWidget( turnOn ); diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index d486cd7c..c9d4e773 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -19,8 +19,6 @@ images/list-add.png images/list-edit.png images/list-remove.png - images/turn-off.png - images/turn-on.png images/vendors/ikea.png images/vendors/intertechno.jpg images/vendors/nexa.png @@ -28,5 +26,7 @@ images/vendors/sartano.png images/vendors/telldus.jpg images/vendors/waveman.png + images/state_1.png + images/state_2.png From 8ad60eabc54771beb87cadb30e5eee25fd9200bf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 9 Feb 2009 10:32:55 +0000 Subject: [PATCH 0794/2215] Emited a signal and updated the state in the device list when the state of a device changes --- telldus-gui/TelldusGui/device.cpp | 20 ++++++++++++++++---- telldus-gui/TelldusGui/device.h | 3 ++- telldus-gui/TelldusGui/devicemodel.cpp | 23 +++++++++++++++++++---- telldus-gui/TelldusGui/devicemodel.h | 2 ++ 4 files changed, 39 insertions(+), 9 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index b38beaca..4726fad1 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -6,6 +6,7 @@ QHash Device::devices; Device::Device(int id) :p_id(id), p_model(0), + p_state(0), p_name(""), p_protocol(""), p_modelChanged(false), @@ -23,6 +24,8 @@ Device::Device(int id) char *protocol = tdGetProtocol(id); p_protocol = QString::fromLocal8Bit( protocol ); free( protocol ); + + p_state = tdLastSentCommand(id); } } @@ -143,7 +146,7 @@ void Device::bell() { } int Device::lastSentCommand() const { - return tdLastSentCommand( p_id ); + return p_state; } void Device::updateMethods() { @@ -158,7 +161,16 @@ void Device::updateMethods() { } void Device::triggerEvent( int messageId ) { - char *message = tdGetErrorString( messageId ); - emit showMessage( "", message, "" ); - free( message ); + if (messageId == TELLSTICK_SUCCESS) { + //Update the last sent command + int lastSentCommand = tdLastSentCommand( p_id ); + if (lastSentCommand != p_state) { + p_state = lastSentCommand; + emit stateChanged(p_id, p_state); + } + } else { + char *message = tdGetErrorString( messageId ); + emit showMessage( "", message, "" ); + free( message ); + } } diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index 7d1df0a0..6654aff0 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -45,6 +45,7 @@ public slots: signals: void deviceAdded( int id ); void methodsChanged( int newMethods ); + void stateChanged( int deviceId, int newState ); void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); void eventTriggered( const QString &name, const QString &title ); @@ -55,7 +56,7 @@ private: static QHash devices; QHash p_settings; - int p_id, p_model; + int p_id, p_model, p_state; QString p_name, p_protocol; bool p_modelChanged, p_nameChanged, p_protocolChanged; mutable int p_methods; diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index c7e918f5..8425f3e1 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -112,8 +112,7 @@ Device *DeviceModel::device( const QModelIndex &index ) const { bool loaded = Device::deviceLoaded( id ); Device *device = Device::getDevice( id ); if (!loaded) { - connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); - connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); + connectDeviceSignals( device ); } return device; } @@ -121,8 +120,7 @@ Device *DeviceModel::device( const QModelIndex &index ) const { Device *DeviceModel::newDevice() const { Device *device = Device::newDevice(); connect(device, SIGNAL(deviceAdded(int)), this, SLOT(deviceAdded(int))); - connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); - connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); + connectDeviceSignals(device); return device; } @@ -133,6 +131,17 @@ void DeviceModel::deviceAdded( int id ) { endInsertRows(); } +void DeviceModel::deviceStateChanged( int deviceId, int /*newState*/ ) { + int deviceCount = rowCount(); + for (int i = 0; i < deviceCount; ++i) { + if (this->deviceId(i) == deviceId) { + QModelIndex index = this->index(i, 0); + emit dataChanged( index, index ); + break; + } + } +} + int DeviceModel::deviceId( const QModelIndex &index ) const { return deviceId( index.row() ); } @@ -149,3 +158,9 @@ int DeviceModel::deviceId( int index ) const { void DeviceModel::deviceEvent(int /*deviceId*/, int /*method*/, const char */*data*/, int /*callbackId*/, void */*context*/) { //TODO: } + +void DeviceModel::connectDeviceSignals( Device *device ) const { + connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); + connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); + connect(device, SIGNAL(stateChanged(int, int)), this, SLOT(deviceStateChanged(int,int))); +} diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index a7c2f76f..fd24eb52 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -31,10 +31,12 @@ signals: private slots: void deviceAdded( int id ); + void deviceStateChanged( int deviceId, int newState ); private: static void deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); + void connectDeviceSignals( Device *device ) const; int deviceId( const QModelIndex &index ) const; int deviceId( int index ) const; From 9ae117990801262b77cc27ba277f015ff11c8dd5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 9 Feb 2009 11:25:44 +0000 Subject: [PATCH 0795/2215] Saved the new state received from TellStick Duo --- telldus-core/driver/libtelldus-core/Device.cpp | 6 ++---- telldus-core/driver/libtelldus-core/Manager.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index e740b357..02cef74d 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -35,10 +35,8 @@ int Device::switchState( int newState, const std::string &value ) { break; } if (retVal == TELLSTICK_SUCCESS) { - if (newState != TELLSTICK_BELL) { //Bell doesn't toggle any state - Manager *manager = Manager::getInstance(); - manager->setDeviceState(deviceId, newState, ""); - } + Manager *manager = Manager::getInstance(); + manager->setDeviceState(deviceId, newState, ""); } return retVal; } diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index 9f684938..001ddd06 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -148,7 +148,10 @@ bool Manager::setModel(int intDeviceId, int intModel) { } bool Manager::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { - return settings.setDeviceState(intDeviceId, intDeviceState, strDeviceStateValue); + if (intDeviceState != TELLSTICK_BELL) { + return settings.setDeviceState(intDeviceId, intDeviceState, strDeviceStateValue); + } + return true; } int Manager::getDeviceState( int intDeviceId ) const { @@ -207,6 +210,8 @@ void Manager::parseMessage( const std::string &message ) { } } if (found) { + //First save the last sent command + setDeviceState(it->first, method, ""); for(CallbackList::const_iterator callback_it = callbacks.begin(); callback_it != callbacks.end(); ++callback_it) { (*callback_it).event(it->first, method, message.c_str(), (*callback_it).id, (*callback_it).context); } From 830e6dc70483a1a714b552cce45e7547a945f3ed Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 9 Feb 2009 11:27:47 +0000 Subject: [PATCH 0796/2215] Started to listen for device events from telldus-core --- telldus-gui/TelldusGui/device.cpp | 26 ++++++++++++++++++++------ telldus-gui/TelldusGui/device.h | 6 +++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 4726fad1..e1691211 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -2,6 +2,7 @@ #include QHash Device::devices; +int Device::callbackId = tdRegisterDeviceEvent( &Device::deviceEvent, 0); Device::Device(int id) :p_id(id), @@ -25,7 +26,7 @@ Device::Device(int id) p_protocol = QString::fromLocal8Bit( protocol ); free( protocol ); - p_state = tdLastSentCommand(id); + updateState(); } } @@ -160,17 +161,30 @@ void Device::updateMethods() { } } +void Device::updateState() { + int lastSentCommand = tdLastSentCommand( p_id ); + if (lastSentCommand != p_state) { + p_state = lastSentCommand; + emit stateChanged(p_id, p_state); + } +} + void Device::triggerEvent( int messageId ) { if (messageId == TELLSTICK_SUCCESS) { //Update the last sent command - int lastSentCommand = tdLastSentCommand( p_id ); - if (lastSentCommand != p_state) { - p_state = lastSentCommand; - emit stateChanged(p_id, p_state); - } + updateState(); } else { char *message = tdGetErrorString( messageId ); emit showMessage( "", message, "" ); free( message ); } } + +void Device::deviceEvent(int deviceId, int, const char *, int, void *) { + if (Device::deviceLoaded( deviceId )) { + Device *device = Device::getDevice( deviceId ); + if (device) { + device->updateState(); + } + } +} diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index 6654aff0..904c849c 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -1,7 +1,7 @@ #ifndef DEVICE_H #define DEVICE_H -#include "telldus-core.h" +#include #include #include @@ -52,9 +52,13 @@ signals: private: Device(int id); void updateMethods(); + void updateState(); void triggerEvent( int message ); static QHash devices; + static void deviceEvent(int deviceId, int, const char *, int, void *); + + static int callbackId; QHash p_settings; int p_id, p_model, p_state; QString p_name, p_protocol; From f770dcec234bed0874fc40fd93888e4dd929a3a1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 9 Feb 2009 14:14:42 +0000 Subject: [PATCH 0797/2215] Saved the current device state on Linux --- .../libtelldus-core/SettingsConfuse.cpp | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp index f002dc23..133d9210 100644 --- a/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp +++ b/telldus-core/driver/libtelldus-core/SettingsConfuse.cpp @@ -19,11 +19,14 @@ using namespace std; class privateVars { public: cfg_t *cfg; + cfg_t *var_cfg; }; bool readConfig(cfg_t **cfg); +bool readVarConfig(cfg_t **cfg); const char* CONFIG_FILE = "/etc/tellstick.conf"; +const char* VAR_CONFIG_FILE = "/var/state/telldus-core.conf"; /* * Constructor @@ -32,6 +35,7 @@ Settings::Settings(void) { d = new privateVars(); readConfig(&d->cfg); + readVarConfig(&d->var_cfg); } /* @@ -141,6 +145,56 @@ bool Settings::removeDevice(int intDeviceId){ return blnSuccess; } +bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { + if (d->var_cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->var_cfg, "device", i); + int deviceId = atoi(cfg_title(cfg_device)); + if (deviceId == intDeviceId) { + cfg_setint(cfg_device, "state", intDeviceState); + cfg_setstr(cfg_device, "stateValue", strDeviceStateValue.c_str()); + + FILE *fp = fopen(VAR_CONFIG_FILE, "w"); + cfg_print(d->var_cfg, fp); + fclose(fp); + return true; + } + } + // The device is not found in the file, we must create it manualy... + FILE *fp = fopen(VAR_CONFIG_FILE, "w"); + cfg_print(d->var_cfg, fp); //Print the config-file + fprintf(fp, "device %d {\n}\n", intDeviceId); //Print the new device + fclose(fp); + + //Re-read config-file + cfg_free(d->var_cfg); + readVarConfig(&d->var_cfg); + + return false; +} + +int Settings::getDeviceState( int intDeviceId ) const { + if (d->var_cfg == 0) { + return false; + } + cfg_t *cfg_device; + for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) { + cfg_device = cfg_getnsec(d->var_cfg, "device", i); + int deviceId = atoi(cfg_title(cfg_device)); + if (deviceId == intDeviceId) { + return cfg_getint(cfg_device, "state"); + } + } + return TELLSTICK_TURNOFF; +} + +std::string Settings::getDeviceStateValue( int intDeviceId ) const { + return ""; +} + std::string Settings::getStringSetting(int intDeviceId, const std::string &name, bool parameter) const { if (d->cfg == 0) { return ""; @@ -274,3 +328,25 @@ bool readConfig(cfg_t **cfg) { return true; } + +bool readVarConfig(cfg_t **cfg) { + + cfg_opt_t device_opts[] = { + CFG_INT("state", 0, CFGF_NONE), + CFG_STR("stateValue", "", CFGF_NONE), + CFG_END() + }; + + cfg_opt_t opts[] = { + CFG_SEC("device", device_opts, CFGF_MULTI | CFGF_TITLE), + CFG_END() + }; + + (*cfg) = cfg_init(opts, CFGF_NOCASE); + if (cfg_parse((*cfg), VAR_CONFIG_FILE) == CFG_PARSE_ERROR) { + (*cfg) = 0; + return false; + } + + return true; +} From ac436ba7ef867fe0e8691b6df40fe2cb3564f0d5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 Feb 2009 16:05:37 +0000 Subject: [PATCH 0798/2215] Major refactoring --- .../driver/libtelldus-core/Device.cpp | 35 +++++++- telldus-core/driver/libtelldus-core/Device.h | 10 ++- .../driver/libtelldus-core/DeviceGroup.cpp | 55 ++++++++----- .../driver/libtelldus-core/DeviceGroup.h | 6 +- .../driver/libtelldus-core/DeviceIkea.cpp | 29 ++++++- .../driver/libtelldus-core/DeviceIkea.h | 11 ++- .../driver/libtelldus-core/DeviceNexa.cpp | 44 +++++++--- .../driver/libtelldus-core/DeviceNexa.h | 6 +- .../driver/libtelldus-core/DeviceSartano.cpp | 15 +++- .../driver/libtelldus-core/DeviceSartano.h | 8 +- .../driver/libtelldus-core/DeviceWaveman.cpp | 4 +- .../driver/libtelldus-core/DeviceWaveman.h | 2 +- .../driver/libtelldus-core/Manager.cpp | 82 +++++++++++++------ telldus-core/driver/libtelldus-core/Manager.h | 16 ++-- .../driver/libtelldus-core/telldus-core.cpp | 52 +++++++----- 15 files changed, 268 insertions(+), 107 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/Device.cpp b/telldus-core/driver/libtelldus-core/Device.cpp index 02cef74d..dce73dc3 100644 --- a/telldus-core/driver/libtelldus-core/Device.cpp +++ b/telldus-core/driver/libtelldus-core/Device.cpp @@ -6,9 +6,10 @@ using namespace TelldusCore; /* * Constructor */ -Device::Device(int id, int m) +Device::Device(int id, int m, const std::string &name) : deviceId(id), - model(m) + model(m), + deviceName(name) { } @@ -45,8 +46,21 @@ int Device::getModel() const { return model; } -void Device::setModel( int intModel ) { - model = intModel; +bool Device::setModel( int intModel ) { + Manager *manager = Manager::getInstance(); + if (manager->setDeviceModel( deviceId, intModel )) { + model = intModel; + return true; + } + return false; +} + +bool Device::setParameter(const std::string &strName, const std::string &strValue) { + if (setDeviceParameter( strName, strValue )) { + Manager *manager = Manager::getInstance(); + return manager->setDeviceParameter(deviceId, strName, strValue); + } + return false; } /* @@ -92,3 +106,16 @@ int Device::methodId( const std::string &methodName ) { } return 0; } + +std::string Device::getName() const { + return deviceName; +} + +bool Device::setName(const std::string & newName) { + Manager *manager = Manager::getInstance(); + if (manager->setDeviceName(deviceId, newName)) { + deviceName = newName; + return true; + } + return false; +} diff --git a/telldus-core/driver/libtelldus-core/Device.h b/telldus-core/driver/libtelldus-core/Device.h index 36acf44f..e9c603af 100644 --- a/telldus-core/driver/libtelldus-core/Device.h +++ b/telldus-core/driver/libtelldus-core/Device.h @@ -15,15 +15,19 @@ namespace TelldusCore { class Device { public: - Device(int id, int model); + Device(int id, int model, const std::string &name); virtual ~Device(void); int switchState( int newState, const std::string &value = "" ); virtual int methods(int methodsSupported) = 0; virtual std::string getProtocol() const = 0; virtual bool parameterMatches( const std::string &name, const std::string &value ) const = 0; + bool setParameter(const std::string &strName, const std::string &strValue); + int getModel() const; - void setModel( int intModel ); + bool setModel( int intModel ); + std::string getName() const; + bool setName( const std::string &newName ); static int methodId( const std::string &methodName ); @@ -34,6 +38,7 @@ namespace TelldusCore { #endif protected: + virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue) = 0; virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); @@ -42,6 +47,7 @@ namespace TelldusCore { private: int deviceId, model; + std::string deviceName; // static QMutex deviceMutex; }; diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp index 71c52670..4d75ead6 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.cpp @@ -8,29 +8,9 @@ using namespace TelldusCore; /* * Constructor */ -DeviceGroup::DeviceGroup(int id, int model, const std::string &strDevices) - :Device(id, model) +DeviceGroup::DeviceGroup(int id, int model, const std::string &name) + :Device(id, model, name) { - if (strDevices.length() > 0) { - char *tempDevices = new char[strDevices.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempDevices, strDevices.size()+1, strDevices.c_str()); -#else - strcpy(tempDevices, strDevices.c_str()); -#endif - - Manager *manager = Manager::getInstance(); - char *strToken = strtok(tempDevices, ","); - do { - int intDevice = atoi(strToken); - Device *device = manager->getDevice(intDevice); - if (device != NULL) { - deviceList.push_back( device ); - } - } while ( (strToken = strtok(NULL, ",")) != NULL ); - - free(tempDevices); - } } /* @@ -39,6 +19,36 @@ DeviceGroup::DeviceGroup(int id, int model, const std::string &strDevices) DeviceGroup::~DeviceGroup(void) { } +bool DeviceGroup::setDeviceParameter(const std::string &strName, const std::string &strValue) { + if (strName.compare("devices") == 0) { + return setDevices(strValue); + } + return false; +} + +bool DeviceGroup::setDevices(const std::string &newDevices) { +/* if (strDevices.length() > 0) { + char *tempDevices = new char[strDevices.size()+1]; + #ifdef _WINDOWS + strcpy_s(tempDevices, strDevices.size()+1, strDevices.c_str()); + #else + strcpy(tempDevices, strDevices.c_str()); + #endif + + Manager *manager = Manager::getInstance(); + char *strToken = strtok(tempDevices, ","); + do { + int intDevice = atoi(strToken); + Device *device = manager->getDevice(intDevice); + if (device != NULL) { + deviceList.push_back( device ); + } + } while ( (strToken = strtok(NULL, ",")) != NULL ); + + free(tempDevices); + }*/ +} + /* * Turn on this device */ @@ -131,3 +141,4 @@ int DeviceGroup::methods(int supportedMethods){ std::string DeviceGroup::getProtocol() const { return "group"; } + diff --git a/telldus-core/driver/libtelldus-core/DeviceGroup.h b/telldus-core/driver/libtelldus-core/DeviceGroup.h index 5666e056..71df3512 100644 --- a/telldus-core/driver/libtelldus-core/DeviceGroup.h +++ b/telldus-core/driver/libtelldus-core/DeviceGroup.h @@ -12,14 +12,18 @@ namespace TelldusCore { class DeviceGroup : public Device { public: - DeviceGroup(int id, int model, const std::string &strDevices); + DeviceGroup(int id, int model, const std::string &name); ~DeviceGroup(void); virtual int methods(int methodsSupported); virtual std::string getProtocol() const; virtual bool parameterMatches( const std::string &name, const std::string &value ) const; + + bool setDevices(const std::string &newDevices); protected: + virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); + virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp index a034389e..d5d00670 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.cpp @@ -15,14 +15,21 @@ using namespace TelldusCore; /* * Constructor */ -DeviceIkea::DeviceIkea(int id, int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle) - :Device(id, model) +DeviceIkea::DeviceIkea(int id, int model, const std::string &name) + :Device(id, model, name) { +} + +bool DeviceIkea::setSystem(const std::string &strSystem) { if (strSystem.length() > 0) { intSystem = atoi(strSystem.c_str()) - 1; } else { intSystem = 0; } + return true; +} + +bool DeviceIkea::setUnits(const std::string &strUnits) { if (strUnits.length() > 0) { intUnits = 0; //Start without any units @@ -44,11 +51,16 @@ DeviceIkea::DeviceIkea(int id, int model, const std::string &strSystem, const st free(tempUnits); } - if (strUnits.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { + return true; +} + +bool DeviceIkea::setFade(const std::string &strFadeStyle) { + if (strFadeStyle.length() > 0 && strcasecmp(strFadeStyle.c_str(), "true") == 0) { intFadeStyle = 1; } else { intFadeStyle = 0; } + return true; } /* @@ -61,6 +73,17 @@ DeviceIkea::~DeviceIkea(void) intFadeStyle = -1; } +bool DeviceIkea::setDeviceParameter(const std::string &strName, const std::string &strValue) { + if (strName.compare("ikea_system") == 0) { + return setSystem(strValue); + } else if (strName.compare("ikea_units") == 0) { + return setUnits(strValue); + } else if (strName.compare("ikea_fade") == 0) { + return setFade(strValue); + } + return false; +} + /* * Turn on this device */ diff --git a/telldus-core/driver/libtelldus-core/DeviceIkea.h b/telldus-core/driver/libtelldus-core/DeviceIkea.h index fbe5cc87..bfcd10f2 100644 --- a/telldus-core/driver/libtelldus-core/DeviceIkea.h +++ b/telldus-core/driver/libtelldus-core/DeviceIkea.h @@ -7,15 +7,20 @@ namespace TelldusCore { class DeviceIkea : public Device { public: - DeviceIkea(int id, int model, const std::string &strSystem, const std::string &strUnits, const std::string &strFadeStyle); + DeviceIkea(int id, int model, const std::string &name); + virtual ~DeviceIkea(void); + virtual int methods(int methodsSupported); virtual std::string getProtocol() const; virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - public: - ~DeviceIkea(void); + bool setSystem(const std::string &strSystem); + bool setUnits(const std::string &strUnits); + bool setFade(const std::string &strFade); protected: + virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); + virtual int turnOn(void); virtual int turnOff(void); virtual int dim(unsigned char level); diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp index 07751d98..6ac4efa0 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.cpp @@ -11,20 +11,11 @@ using namespace TelldusCore; /* * Constructor */ -DeviceNexa::DeviceNexa(int id, int model, const std::string &strHouse, const std::string &strCode) - :Device(id, model) +DeviceNexa::DeviceNexa(int id, int model, const std::string &name) + :Device(id, model, name), + intHouse(0), + intCode(0) { - if (strHouse.length() > 0) { - intHouse = strHouse[0] - 'A'; - } else { - intHouse = 0; - } - - if (strCode.length() > 0) { - intCode = atoi(strCode.c_str()) - 1; - } else { - intCode = 0; - } } /* @@ -33,6 +24,33 @@ DeviceNexa::DeviceNexa(int id, int model, const std::string &strHouse, const std DeviceNexa::~DeviceNexa(void) {} +bool DeviceNexa::setHouse(const std::string &newHouse) { + if (newHouse.length() > 0) { + intHouse = newHouse[0] - 'A'; + } else { + intHouse = 0; + } + return true; +} + +bool DeviceNexa::setUnit(const std::string &newUnit) { + if (newUnit.length() > 0) { + intCode = atoi(newUnit.c_str()) - 1; + } else { + intCode = 0; + } + return true; +} + +bool DeviceNexa::setDeviceParameter(const std::string &strName, const std::string &strValue) { + if (strName.compare("nexa_house") == 0) { + return setHouse(strValue); + } else if (strName.compare("nexa_unit") == 0) { + return setUnit(strValue); + } + return false; +} + /* * Turn on this device */ diff --git a/telldus-core/driver/libtelldus-core/DeviceNexa.h b/telldus-core/driver/libtelldus-core/DeviceNexa.h index 27e134fe..1857ecb6 100644 --- a/telldus-core/driver/libtelldus-core/DeviceNexa.h +++ b/telldus-core/driver/libtelldus-core/DeviceNexa.h @@ -7,15 +7,19 @@ namespace TelldusCore { class DeviceNexa : public Device { public: - DeviceNexa(int id, int model, const std::string &strHouse, const std::string &strCode); + DeviceNexa(int id, int model, const std::string &name); virtual int methods(int methodsSupported); virtual std::string getProtocol() const; virtual bool parameterMatches( const std::string &name, const std::string &value ) const; + bool setHouse(const std::string &newHouse); + bool setUnit(const std::string &newUnit); + public: ~DeviceNexa(void); protected: + virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); virtual int turnOn(void); virtual int turnOff(void); virtual int bell(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp index d8066b6e..1b00ae27 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.cpp @@ -10,10 +10,9 @@ using namespace TelldusCore; /* * Constructor */ -DeviceSartano::DeviceSartano(int id, int model, const std::string &strNewCode) - :Device(id, model) +DeviceSartano::DeviceSartano(int id, int model, const std::string &name) + :Device(id, model, name) { - strCode = strNewCode; } @@ -21,6 +20,16 @@ DeviceSartano::~DeviceSartano(void) { } +bool DeviceSartano::setCode(const std::string &strNewCode) { + strCode = strNewCode; +} + +bool DeviceSartano::setDeviceParameter(const std::string &strName, const std::string &strValue) { + if (strName.compare("sartano_code") == 0) { + return setCode(strValue); + } + return false; +} /* * Turn on this device diff --git a/telldus-core/driver/libtelldus-core/DeviceSartano.h b/telldus-core/driver/libtelldus-core/DeviceSartano.h index d3fb0734..9bedb8ba 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSartano.h +++ b/telldus-core/driver/libtelldus-core/DeviceSartano.h @@ -7,14 +7,18 @@ namespace TelldusCore { class DeviceSartano : public Device { public: - DeviceSartano(int id, int model, const std::string &strCode); + DeviceSartano(int id, int model, const std::string &name); + virtual ~DeviceSartano(void); + virtual int methods(int methodsSupported); virtual std::string getProtocol() const; virtual bool parameterMatches( const std::string &name, const std::string &value ) const; - ~DeviceSartano(void); + bool setCode(const std::string &strNewCode); protected: + virtual bool setDeviceParameter(const std::string &strName, const std::string &strValue); + virtual int turnOn(void); virtual int turnOff(void); diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp index 7bd35829..d51a3fec 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.cpp @@ -11,8 +11,8 @@ using namespace TelldusCore; /* * Constructor */ -DeviceWaveman::DeviceWaveman(int id, int model, const std::string &strHouse, const std::string &strCode) - :DeviceNexa(id, model, strHouse, strCode){ +DeviceWaveman::DeviceWaveman(int id, int model, const std::string &name) + :DeviceNexa(id, model, name){ } /* diff --git a/telldus-core/driver/libtelldus-core/DeviceWaveman.h b/telldus-core/driver/libtelldus-core/DeviceWaveman.h index 0a99912f..72bf8d93 100644 --- a/telldus-core/driver/libtelldus-core/DeviceWaveman.h +++ b/telldus-core/driver/libtelldus-core/DeviceWaveman.h @@ -7,7 +7,7 @@ namespace TelldusCore { class DeviceWaveman : public DeviceNexa { public: - DeviceWaveman(int id, int model, const std::string &strHouse, const std::string &strCode); + DeviceWaveman(int id, int model, const std::string &name); virtual int methods(int methodsSupported); protected: diff --git a/telldus-core/driver/libtelldus-core/Manager.cpp b/telldus-core/driver/libtelldus-core/Manager.cpp index 001ddd06..1b0d7afb 100644 --- a/telldus-core/driver/libtelldus-core/Manager.cpp +++ b/telldus-core/driver/libtelldus-core/Manager.cpp @@ -69,31 +69,32 @@ Device *Manager::getDevice(int intDeviceId){ return NULL; } int intModel = settings.getModel(intDeviceId); + std::string strName = settings.getName(intDeviceId); //each new brand must be added here if (strcasecmp(protocol.c_str(), "arctech") == 0){ - std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); - std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceNexa(intDeviceId, intModel, strHouse, strCode); + dev = new DeviceNexa(intDeviceId, intModel, strName); + ((DeviceNexa*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "nexa_house")); + ((DeviceNexa*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "nexa_unit")); } else if (strcasecmp(protocol.c_str(), "group") == 0) { - std::string strDevices = settings.getDeviceParameter(intDeviceId, "devices"); - dev = new DeviceGroup(intDeviceId, intModel, strDevices); + dev = new DeviceGroup(intDeviceId, intModel, strName); + ((DeviceGroup*)dev)->setDevices(settings.getDeviceParameter(intDeviceId, "devices")); } else if (strcasecmp(protocol.c_str(), "Waveman") == 0) { - std::string strHouse = settings.getDeviceParameter(intDeviceId, "nexa_house"); - std::string strCode = settings.getDeviceParameter(intDeviceId, "nexa_unit"); - dev = new DeviceWaveman(intDeviceId, intModel, strHouse, strCode); + dev = new DeviceWaveman(intDeviceId, intModel, strName); + ((DeviceWaveman*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "nexa_house")); + ((DeviceWaveman*)dev)->setUnit(settings.getDeviceParameter(intDeviceId, "nexa_unit")); } else if (strcasecmp(protocol.c_str(), "Sartano") == 0) { - std::string strCode = settings.getDeviceParameter(intDeviceId, "sartano_code"); - dev = new DeviceSartano(intDeviceId, intModel, strCode); + dev = new DeviceSartano(intDeviceId, intModel, strName); + ((DeviceSartano*)dev)->setCode(settings.getDeviceParameter(intDeviceId, "sartano_code")); } else if (strcasecmp(protocol.c_str(), "Ikea") == 0) { - std::string strSystem = settings.getDeviceParameter(intDeviceId, "ikea_system"); - std::string strUnits = settings.getDeviceParameter(intDeviceId, "ikea_units"); - std::string strFade = settings.getDeviceParameter(intDeviceId, "ikea_fade"); - dev = new DeviceIkea(intDeviceId, intModel, strSystem, strUnits, strFade); + dev = new DeviceIkea(intDeviceId, intModel, strName); + ((DeviceIkea*)dev)->setSystem(settings.getDeviceParameter(intDeviceId, "ikea_system")); + ((DeviceIkea*)dev)->setUnits(settings.getDeviceParameter(intDeviceId, "ikea_units")); + ((DeviceIkea*)dev)->setFade(settings.getDeviceParameter(intDeviceId, "ikea_fade")); } else { return NULL; @@ -112,8 +113,16 @@ Device *Manager::getDevice(int intDeviceId){ return dev; } +int Manager::getNumberOfDevices(void) const { + return settings.getNumberOfDevices(); +} + +int Manager::getDeviceId(int intDeviceIndex) const { + return settings.getDeviceId(intDeviceIndex); +} + void Manager::loadAllDevices() { - int numberOfDevices = settings.getNumberOfDevices(); + int numberOfDevices = getNumberOfDevices(); for (int i = 0; i < numberOfDevices; ++i) { int id = settings.getDeviceId(i); if (!deviceLoaded(id)) { @@ -122,7 +131,7 @@ void Manager::loadAllDevices() { } } -bool Manager::setProtocol(int intDeviceId, const std::string &strProtocol) { +bool Manager::setDeviceProtocol(int intDeviceId, const std::string &strProtocol) { bool retval = settings.setProtocol( intDeviceId, strProtocol ); // Delete the device to reload it when the protocol changes @@ -136,15 +145,8 @@ bool Manager::setProtocol(int intDeviceId, const std::string &strProtocol) { return retval; } -bool Manager::setModel(int intDeviceId, int intModel) { - bool retval = settings.setModel(intDeviceId, intModel); - if (deviceLoaded(intDeviceId)) { - Device *device = getDevice(intDeviceId); - if (device) { - device->setModel( intModel ); - } - } - return retval; +bool Manager::setDeviceModel(int intDeviceId, int intModel) { + return settings.setModel(intDeviceId, intModel); } bool Manager::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) { @@ -250,3 +252,33 @@ void Manager::close() { } } +bool TelldusCore::Manager::setDeviceParameter(int intDeviceId, const std::string & strName, const std::string & strValue) { + return settings.setDeviceParameter(intDeviceId, strName, strValue); +} + +std::string TelldusCore::Manager::getDeviceParameter(int intDeviceId, const std::string & strName) const { + return settings.getDeviceParameter( intDeviceId, strName ); +} + +int TelldusCore::Manager::addDevice() { + return settings.addDevice(); +} + +bool TelldusCore::Manager::removeDevice(int intDeviceId) { + if (deviceLoaded(intDeviceId)) { + DeviceMap::iterator iterator = devices.find(intDeviceId); + if (iterator == devices.end()) { // Should not be possible since deviceLoaded() returned true + return false; + } + Device *dev = iterator->second; + devices.erase(iterator); + delete dev; + } + + return settings.removeDevice(intDeviceId); +} + +bool TelldusCore::Manager::setDeviceName(int intDeviceId, const std::string & strNewName) { + return settings.setName(intDeviceId, strNewName); +} + diff --git a/telldus-core/driver/libtelldus-core/Manager.h b/telldus-core/driver/libtelldus-core/Manager.h index 7494f9b4..56166c9d 100644 --- a/telldus-core/driver/libtelldus-core/Manager.h +++ b/telldus-core/driver/libtelldus-core/Manager.h @@ -47,13 +47,19 @@ namespace TelldusCore { bool deviceLoaded(int deviceId) const; - bool setProtocol(int intDeviceId, const std::string &strProtocol); -// bool setName(int intDeviceId, const std::string &strNewName); - bool setModel(int intDeviceId, int intModel); -// bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); + int getNumberOfDevices(void) const; + int getDeviceId(int intDeviceIndex) const; + bool setDeviceProtocol(int intDeviceId, const std::string &strProtocol); + bool setDeviceName(int intDeviceId, const std::string &strNewName); + bool setDeviceModel(int intDeviceId, int intModel); + bool setDeviceParameter(int intDeviceId, const std::string &strName, const std::string &strValue); + std::string getDeviceParameter(int intDeviceId, const std::string &strName) const; bool setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ); int getDeviceState( int intDeviceId ) const; - std::string getDeviceStateValue( int intDeviceId ) const; + std::string getDeviceStateValue( int intDeviceId ) const; + + int addDevice(); + bool removeDevice(int intDeviceId); static Manager *getInstance(); static void close(); diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index 9d94663c..f314867e 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -243,8 +243,8 @@ int WINAPI tdLastSentCommand( int intDeviceId ) { int WINAPI tdGetNumberOfDevices(void){ int intReturn = -1; try{ - Settings ts; - intReturn = ts.getNumberOfDevices(); + Manager *manager = Manager::getInstance(); + intReturn = manager->getNumberOfDevices(); } catch(exception e){ intReturn = -1; @@ -269,8 +269,8 @@ int WINAPI tdGetNumberOfDevices(void){ int WINAPI tdGetDeviceId(int intDeviceIndex){ int intReturn = -1; try{ - Settings ts; - intReturn = ts.getDeviceId(intDeviceIndex); + Manager *manager = Manager::getInstance(); + intReturn = manager->getDeviceId(intDeviceIndex); } catch(exception e){ intReturn = -1; @@ -306,10 +306,13 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * @returns The name of the device or an empty string if the device is not found. */ char * WINAPI tdGetName(int intDeviceId){ - std::string strReturn; - try{ - Settings ts; - strReturn = ts.getName(intDeviceId); + std::string strReturn = ""; + try { + Manager *manager = Manager::getInstance(); + Device *dev = manager->getDevice( intDeviceId ); + if (dev != NULL) { + strReturn = dev->getName(); + } } catch(exception e){ strReturn = ""; @@ -321,8 +324,11 @@ char * WINAPI tdGetName(int intDeviceId){ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ bool blnSuccess = false; try{ - Settings ts; - blnSuccess = ts.setName(intDeviceId, strNewName); + Manager *manager = Manager::getInstance(); + Device *dev = manager->getDevice( intDeviceId ); + if (dev != NULL) { + blnSuccess = dev->setName(strNewName); + } } catch(exception e){ blnSuccess = false; @@ -350,7 +356,7 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ bool blnSuccess = false; try{ Manager *manager = Manager::getInstance(); - blnSuccess = manager->setProtocol(intDeviceId, strProtocol); + blnSuccess = manager->setDeviceProtocol(intDeviceId, strProtocol); } catch(exception e){ blnSuccess = false; @@ -379,7 +385,10 @@ bool WINAPI tdSetModel(int intDeviceId, int intModel){ bool blnSuccess = false; try{ Manager *manager = Manager::getInstance(); - manager->setModel(intDeviceId, intModel); + Device* dev = manager->getDevice(intDeviceId); + if (dev != NULL) { + blnSuccess = dev->setModel(intModel); + } } catch(exception e){ blnSuccess = false; @@ -391,8 +400,11 @@ bool WINAPI tdSetModel(int intDeviceId, int intModel){ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ try{ - Settings ts; - return ts.setDeviceParameter(intDeviceId, strName, strValue); + Manager *manager = Manager::getInstance(); + Device *dev = manager->getDevice( intDeviceId ); + if (dev != NULL) { + return dev->setParameter(strName, strValue); + } } catch(exception e){ handleException(e); @@ -403,8 +415,8 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ std::string strReturn = ""; try{ - Settings ts; - strReturn = ts.getDeviceParameter(intDeviceId, strName); + Manager *manager = Manager::getInstance(); + strReturn = manager->getDeviceParameter(intDeviceId, strName); if (strReturn.empty()) { strReturn = defaultValue; } @@ -418,8 +430,8 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c int WINAPI tdAddDevice(){ int intNewDeviceId = -1; try{ - Settings ts; - intNewDeviceId = ts.addDevice(); + Manager *manager = Manager::getInstance(); + intNewDeviceId = manager->addDevice(); } catch(exception e){ intNewDeviceId = -1; @@ -431,8 +443,8 @@ int WINAPI tdAddDevice(){ bool WINAPI tdRemoveDevice(int intDeviceId){ bool blnSuccess = false; try{ - Settings ts; - blnSuccess = ts.removeDevice(intDeviceId); + Manager *manager = Manager::getInstance(); + blnSuccess = manager->removeDevice(intDeviceId); } catch(exception e){ blnSuccess = false; From b78ed4576f1920c7c9e8058e4ab441a9e0a943e7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 Feb 2009 16:08:10 +0000 Subject: [PATCH 0799/2215] Update the methods if model and/or protocol changes --- telldus-gui/TelldusGui/device.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index e1691211..7d0ae667 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -107,7 +107,7 @@ bool Device::deviceLoaded( int id ) { } void Device::save() { - bool deviceIsAdded = false; + bool deviceIsAdded = false, methodsChanged = false; if (p_id == 0) { //This is a new device p_id = tdAddDevice(); deviceIsAdded = true; @@ -120,15 +120,20 @@ void Device::save() { if (p_modelChanged) { tdSetModel(p_id, p_model); - updateMethods(); + methodsChanged = true; p_modelChanged = false; } if (p_protocolChanged) { tdSetProtocol(p_id, p_protocol.toLocal8Bit()); + methodsChanged = true; p_protocolChanged = false; } + if (methodsChanged) { + updateMethods(); + } + if (deviceIsAdded) { emit deviceAdded(p_id); } From b654b68642ef1da5a90b89a17d2a33d429466b44 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 23 Feb 2009 10:33:27 +0000 Subject: [PATCH 0800/2215] Enabled to use libusb and libftdi to control TellStick instead of the kernel-driver. Thanks to Tapani Rintala --- telldus-core/rfcmd/rfcmd.c | 187 ++++++++++++++----------------------- 1 file changed, 69 insertions(+), 118 deletions(-) diff --git a/telldus-core/rfcmd/rfcmd.c b/telldus-core/rfcmd/rfcmd.c index bdf6b42b..ea94f90d 100644 --- a/telldus-core/rfcmd/rfcmd.c +++ b/telldus-core/rfcmd/rfcmd.c @@ -3,7 +3,7 @@ **************************************************************************** * * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick - USB interface + * USB interface * * Copyright (C) 2007 Tord Andersson * @@ -13,6 +13,8 @@ * Tord Andersson * Micke Prag * Gudmund Berggren + * + * Tapani Rintala / userspace libusb / libftdi - version 02-2009 */ /******************************************************************************* @@ -43,7 +45,7 @@ #include #define PROG_NAME "rfcmd" -#define PROG_VERSION "2.0" +#define PROG_VERSION "2.0.1" /* #define RFCMD_DEBUG */ /* Local function declarations */ @@ -57,50 +59,40 @@ int createIkeaString(const char * pSystemStr, const char * pChannelStr, void printUsage(void); +int usbWriteFtdi(char *cmdstr); + + int main( int argc, char **argv ) { struct termios tio; int fd = -1; char txStr[100]; - if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) - { - if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) - { + if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) { + if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) { printUsage(); exit(1); } /* else - a send cmd string was created */ - } - else if( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) - { - if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) - { + } else if( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) { + if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) { printUsage(); exit(1); } - } - else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) - { - if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) - { + } else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) { + if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) { printUsage(); exit(1); } /* else - a send cmd string was created */ - } - else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) - { + } else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) { // System, Channel, Level, DimStyle, TXString - if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) - { + if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) { printUsage(); exit(1); } /* else - a send cmd string was created */ - } - else /* protocol or parameters not recognized */ - { + } else { /* protocol or parameters not recognized */ printUsage(); exit(1); } @@ -109,28 +101,30 @@ int main( int argc, char **argv ) printf("txStr: %s\n", txStr); #endif - if( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) - { - fprintf(stderr, "%s - Error opening %s\n", PROG_NAME, *(argv+1)); - exit(1); + if(strlen(txStr) > 0) { + if (strcmp(*(argv+1), "LIBUSB") != 0) { + if( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) { + fprintf(stderr, "%s - Error opening %s\n", PROG_NAME, *(argv+1)); + exit(1); + } + + /* adjust serial port parameters */ + bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ + tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ + tio.c_iflag = IGNPAR; + tio.c_oflag = 0; + tcflush(fd, TCIFLUSH); + tcsetattr(fd,TCSANOW,&tio); + + write(fd, txStr, strlen(txStr)); + + sleep(1); /* one second sleep to avoid device 'choking' */ + close(fd); /* Modified : Close fd to make a clean exit */ + } else { + usbWriteFtdi( txStr ); + } } - - if(strlen(txStr) > 0) - { - /* adjust serial port parameters */ - bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ - tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ - tio.c_iflag = IGNPAR; - tio.c_oflag = 0; - tcflush(fd, TCIFLUSH); - tcsetattr(fd,TCSANOW,&tio); - - write(fd, txStr, strlen(txStr)); - - sleep(1); /* one second sleep to avoid device 'choking' */ - close(fd); /* Modified : Close fd to make a clean exit */ - } - exit(0); + exit(0); } @@ -160,9 +154,7 @@ int createNexaString(const char * pHouseStr, const char * pChannelStr, (on_offCode < 0) || (on_offCode > 1)) { - } - else - { + } else { /* b0..b11 txCode where 'X' will be represented by 1 for simplicity. b0 will be sent first */ txCode = houseCode; @@ -177,14 +169,11 @@ int createNexaString(const char * pHouseStr, const char * pChannelStr, strcat(pTxStr,"S"); for(bit=0;bit<12;bit++) { - if((bitmask & txCode) == 0) - { + if((bitmask & txCode) == 0) { /* bit timing might need further refinement */ strcat(pTxStr," ` `"); /* 320 us high, 960 us low, 320 us high, 960 us low */ /* strcat(pTxStr,"$k$k"); *//* 360 us high, 1070 us low, 360 us high, 1070 us low */ - } - else /* add 'X' (floating bit) */ - { + } else { /* add 'X' (floating bit) */ strcat(pTxStr," `` "); /* 320 us high, 960 us low, 960 us high, 320 us low */ /*strcat(pTxStr,"$kk$"); *//* 360 us high, 1070 us low, 1070 us high, 360 us low */ } @@ -217,23 +206,16 @@ int createSartanoString(const char * pChannelStr, const char * pOn_offStr, /* check converted parameters for validity */ if((strlen(pChannelStr) != 10) || - (on_offCode < 0) || (on_offCode > 1)) - { - - } - else - { + (on_offCode < 0) || (on_offCode > 1)) { + } else { strcat(pTxStr,"S"); for(bit=0;bit<=9;bit++) { - if(strncmp(pChannelStr+bit, "1", 1) == 0) //If it is a "1" - { + if(strncmp(pChannelStr+bit, "1", 1) == 0) { //If it is a "1" strcat(pTxStr,"$k$k"); - } - else - { + } else { strcat(pTxStr,"$kk$"); - } + } } if (on_offCode >= 1) strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code @@ -249,7 +231,6 @@ int createSartanoString(const char * pChannelStr, const char * pOn_offStr, #endif return strlen(pTxStr); - } int createIkeaString( const char * pSystemStr, const char * pChannelStr, const char * pLevelStr, const char *pDimStyle, char * pStrReturn) @@ -279,8 +260,7 @@ int createIkeaString( const char * pSystemStr, const char * pChannelStr, const c return 0; } - if (channelCode == 10) - { + if (channelCode == 10) { channelCode = 0; } rawChannelCode = (1<<(9-channelCode)); @@ -288,50 +268,34 @@ int createIkeaString( const char * pSystemStr, const char * pChannelStr, const c strcat(pStrReturn, STARTCODE ) ; //Startcode, always like this; intCode = (systemCode << 10) | rawChannelCode; - for ( i = 13; i >= 0; --i) - { - if ((intCode>>i) & 1) - { + for ( i = 13; i >= 0; --i) { + if ((intCode>>i) & 1) { strcat(pStrReturn, TT ); - if (i % 2 == 0) - { + if (i % 2 == 0) { checksum2++; - } - else - { + } else { checksum1++; } - } - else - { + } else { strcat(pStrReturn,A); } } - if (checksum1 %2 == 0) - { + if (checksum1 %2 == 0) { strcat(pStrReturn, TT ); - } - else - { + } else { strcat(pStrReturn, A) ; //1st checksum } - if (checksum2 %2 == 0) - { + if (checksum2 %2 == 0) { strcat(pStrReturn, TT ); - } - else - { + } else { strcat(pStrReturn, A ) ; //2nd checksum } - if (DimStyle == 1) - { + if (DimStyle == 1) { intFade = 11 << 4; //Smooth - } - else - { + } else { intFade = 1 << 4; //Instant } @@ -376,42 +340,29 @@ int createIkeaString( const char * pSystemStr, const char * pChannelStr, const c checksum1 = 0; checksum2 = 0; - for (i = 0; i < 6; ++i) - { - if ((intCode>>i) & 1) - { + for (i = 0; i < 6; ++i) { + if ((intCode>>i) & 1) { strcat(pStrReturn, TT); - if (i % 2 == 0) - { + if (i % 2 == 0) { checksum1++; - } - else - { + } else { checksum2++; } - } - else - { + } else { strcat(pStrReturn, A ); } } - if (checksum1 %2 == 0) - { + if (checksum1 %2 == 0) { strcat(pStrReturn, TT); - } - else - { + } else { strcat(pStrReturn, A ) ; //2nd checksum } - if (checksum2 %2 == 0) - { + if (checksum2 %2 == 0) { strcat(pStrReturn, TT ); - } - else - { + } else { strcat(pStrReturn, A ) ; //2nd checksum } @@ -425,7 +376,7 @@ void printUsage(void) { printf("%s v%s - Send RF remote commands\n", PROG_NAME, PROG_VERSION); printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n"); - printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); + printf("\t DEVICE: /dev/ttyUSB[0..n] | LIBUSB\n" ); printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA\n" ); printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n"); printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" ); From 55edd0c099895dd37eedd00c97798837128adf7f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 23 Feb 2009 10:38:49 +0000 Subject: [PATCH 0801/2215] Updated Makefile and CMakeLists.txt to use libftdi. Thanks to Tapani Rintala --- telldus-core/rfcmd/CMakeLists.txt | 7 +++++ telldus-core/rfcmd/Makefile | 25 ++++++++++----- telldus-core/rfcmd/ftdi.c | 51 +++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 telldus-core/rfcmd/ftdi.c diff --git a/telldus-core/rfcmd/CMakeLists.txt b/telldus-core/rfcmd/CMakeLists.txt index bed9007f..e45f25e0 100644 --- a/telldus-core/rfcmd/CMakeLists.txt +++ b/telldus-core/rfcmd/CMakeLists.txt @@ -4,6 +4,7 @@ PROJECT(rfcmd) SET(rfcmd_SRCS rfcmd.c + ftdi.c ) IF(${RFCMD_DEBUG}) @@ -14,8 +15,14 @@ INCLUDE_DIRECTORIES( /usr/src/linux/include ) +FIND_LIBRARY(FTDI_LIBRARY ftdi) + ADD_EXECUTABLE(rfcmd ${rfcmd_SRCS} ) +TARGET_LINK_LIBRARIES(rfcmd + ${FTDI_LIBRARY} +) + INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) diff --git a/telldus-core/rfcmd/Makefile b/telldus-core/rfcmd/Makefile index 63eab51a..4836075a 100644 --- a/telldus-core/rfcmd/Makefile +++ b/telldus-core/rfcmd/Makefile @@ -1,13 +1,22 @@ -FILES = rfcmd -INCLUDEDIR = /usr/src/linux/include +SRCS= rfcmd.c ftdi.c +CFLAGS=-O2 -Wall -I/usr/local/include +LFLAGS= -L/usr/local/lib -R/usr/local/lib +#linux:LFLAGS=-Wl,-rpath,/usr/local/lib +LIBS= -lftdi -lusb +PROG= rfcmd +FT= find_telldus +OBJS= $(SRCS:.c=.o) +CC= gcc -CFLAGS = -O2 -Wall +all: $(PROG) $(FT) -all: $(FILES) +$(PROG): $(OBJS) + $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LFLAGS) $(LIBS) -clean: - rm -f $(FILES) *~ core +rfcmd.o: rfcmd.c -install: - cp rfcmd /usr/local/bin +ftdi.o: ftdi.c + +$(FT): $(FT).c + $(CC) $(CFLAGS) -o $@ $(FT).c $(LFLAGS) $(LIBS) diff --git a/telldus-core/rfcmd/ftdi.c b/telldus-core/rfcmd/ftdi.c new file mode 100644 index 00000000..399bc469 --- /dev/null +++ b/telldus-core/rfcmd/ftdi.c @@ -0,0 +1,51 @@ +/* + * TellStick libftdi libusb version + * tested with 0.15 : http://www.intra2net.com/en/developer/libftdi + */ + +#include +#include +#include +#include + +#define BAUD 4800 + +/* + * use libftdi and libusb to send command + * no kernel driver needed + */ +int usbWriteFtdi(char *cmdstr) +{ + struct ftdi_context ctx; + int device=0x0c30, vendor=0x1781; + + if (ftdi_init( &ctx )) { + fprintf(stderr, "usb - init error !\n"); + return 1; + } + + if (ftdi_usb_open(&ctx, vendor, device)) { + fprintf(stderr, "usb - open error (cannot find?) !\n"); + ftdi_deinit( &ctx ); + return 2; + } + + if (ftdi_usb_reset( &ctx )) { + fprintf(stderr, "usb - reset error !\n"); + ftdi_usb_close( &ctx ); + ftdi_deinit( &ctx ); + return 3; + } + + ftdi_disable_bitbang( &ctx ); + ftdi_set_baudrate(&ctx, BAUD); + + ftdi_write_data( &ctx, cmdstr, strlen(cmdstr) ); + sleep(1); /* just for sure */ + ftdi_usb_close( &ctx ); + ftdi_deinit( &ctx ); + + return 0; +} + + From 1fcd9c7fd585377b1b34f422ea8e0ec073ca764f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 23 Feb 2009 10:53:57 +0000 Subject: [PATCH 0802/2215] Added utility to find a connected TellStick with libusb. Thanks to Tapani Rintala --- telldus-core/rfcmd/CMakeLists.txt | 28 ++++++++++++++++----- telldus-core/rfcmd/find_telldus.c | 42 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 telldus-core/rfcmd/find_telldus.c diff --git a/telldus-core/rfcmd/CMakeLists.txt b/telldus-core/rfcmd/CMakeLists.txt index e45f25e0..0044bbc6 100644 --- a/telldus-core/rfcmd/CMakeLists.txt +++ b/telldus-core/rfcmd/CMakeLists.txt @@ -1,7 +1,13 @@ cmake_minimum_required(VERSION 2.4) +INCLUDE_DIRECTORIES( + /usr/src/linux/include +) + PROJECT(rfcmd) +FIND_LIBRARY(FTDI_LIBRARY ftdi) + SET(rfcmd_SRCS rfcmd.c ftdi.c @@ -11,12 +17,6 @@ IF(${RFCMD_DEBUG}) ADD_DEFINITIONS( -DRFCMD_DEBUG ) ENDIF(${RFCMD_DEBUG}) -INCLUDE_DIRECTORIES( - /usr/src/linux/include -) - -FIND_LIBRARY(FTDI_LIBRARY ftdi) - ADD_EXECUTABLE(rfcmd ${rfcmd_SRCS} ) @@ -26,3 +26,19 @@ TARGET_LINK_LIBRARIES(rfcmd ) INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) + +PROJECT(find_telldus) + +SET(find_telldus_SRCS + find_telldus.c +) + +ADD_EXECUTABLE(find_telldus + ${find_telldus_SRCS} +) + +TARGET_LINK_LIBRARIES(find_telldus + ${FTDI_LIBRARY} +) + +INSTALL(TARGETS find_telldus RUNTIME DESTINATION bin) diff --git a/telldus-core/rfcmd/find_telldus.c b/telldus-core/rfcmd/find_telldus.c new file mode 100644 index 00000000..5c44915e --- /dev/null +++ b/telldus-core/rfcmd/find_telldus.c @@ -0,0 +1,42 @@ +/* find_all.c + + Example for ftdi_usb_find_all() + + This program is distributed under the GPL, version 2 +*/ + +#include +#include + +int main(int argc, char **argv) +{ + int ret, i; + struct ftdi_context ftdic; + struct ftdi_device_list *devlist, *curdev; + char manufacturer[128], description[128]; + + ftdi_init(&ftdic); + + if((ret = ftdi_usb_find_all(&ftdic, &devlist, 0x1781, 0x0c30)) < 0) { + fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + + printf("Number of FTDI devices (telldus) found: %d\n", ret); + + i = 0; + for (curdev = devlist; curdev != NULL; i++) { + printf("Checking device: %d\n", i); + if((ret = ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) { + fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + printf("Manufacturer: %s, Description: %s\n\n", manufacturer, description); + curdev = curdev->next; + } + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + + return EXIT_SUCCESS; +} From b39d9d08fc9b3479eef0a10b9587fc658416bdd5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 24 Feb 2009 09:43:28 +0000 Subject: [PATCH 0803/2215] Added function stub tdSendRawCommand() --- telldus-core/driver/libtelldus-core/telldus-core.cpp | 9 +++++++++ telldus-core/driver/libtelldus-core/telldus-core.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/telldus-core/driver/libtelldus-core/telldus-core.cpp b/telldus-core/driver/libtelldus-core/telldus-core.cpp index f314867e..0e56fb02 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.cpp +++ b/telldus-core/driver/libtelldus-core/telldus-core.cpp @@ -522,6 +522,15 @@ char * WINAPI tdGetErrorString(int intErrorNo) { return wrapStdString(strReturn); } +/** + * Send a raw command to TellStick. Please read the TellStick protocol + * definition on how the command should be constructed. + * @param command The command for TellStick in its native format + * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure + */ +int WINAPI tdSendRawCommand(const char *command, int reserved) { + //TODO: to be implemented +} //******** //* Error management, set strLogName to "" to turn off diff --git a/telldus-core/driver/libtelldus-core/telldus-core.h b/telldus-core/driver/libtelldus-core/telldus-core.h index d6c2a259..444efd19 100644 --- a/telldus-core/driver/libtelldus-core/telldus-core.h +++ b/telldus-core/driver/libtelldus-core/telldus-core.h @@ -56,6 +56,9 @@ extern "C" { TELLSTICK_API int WINAPI tdAddDevice(); TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); + + TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); + #ifdef __cplusplus } #endif From 4152e71fb13981c520a58eaa0a48813d7fbc1087 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 10 Mar 2009 11:25:04 +0000 Subject: [PATCH 0804/2215] Fixed some layouts for hildon windowmanager --- telldus-gui/TelldusGui/editdevicedialog.cpp | 32 ++++++++++++++++++++- telldus-gui/TelldusGui/editdevicedialog.h | 4 +++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 9a979ad8..5a33c61b 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -31,6 +31,10 @@ EditDeviceDialog::EditDeviceDialog(Device *d, QWidget *parent, Qt::WFlags flags) selection(0) { QVBoxLayout *layout = new QVBoxLayout(this); +#ifdef Q_WS_HILDON + stacked_layout = new QStackedLayout; + layout->addLayout(stacked_layout); +#endif QHBoxLayout *deviceLayout = new QHBoxLayout; @@ -51,7 +55,11 @@ EditDeviceDialog::EditDeviceDialog(Device *d, QWidget *parent, Qt::WFlags flags) QGroupBox *deviceGroupBox = new QGroupBox(this); deviceGroupBox->setTitle( tr("Device") ); deviceGroupBox->setLayout(deviceLayout); +#ifdef Q_WS_HILDON + stacked_layout->addWidget(deviceGroupBox); +#else layout->addWidget(deviceGroupBox); +#endif QVBoxLayout *addressLayout = new QVBoxLayout; @@ -74,12 +82,16 @@ EditDeviceDialog::EditDeviceDialog(Device *d, QWidget *parent, Qt::WFlags flags) QGroupBox *settingsGroupBox = new QGroupBox(this); settingsGroupBox->setTitle( tr("Addresscode") ); settingsGroupBox->setLayout( addressLayout ); +#ifdef Q_WS_HILDON + stacked_layout->addWidget(settingsGroupBox); +#else layout->addWidget( settingsGroupBox ); +#endif QDialogButtonBox *buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons( QDialogButtonBox::Save | QDialogButtonBox::Cancel ); connect(buttonBox, SIGNAL(accepted()), this, SLOT(okClicked())); - connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); + connect(buttonBox, SIGNAL(rejected()), this, SLOT(cancelClicked())); layout->addWidget(buttonBox); deviceSettings[1] = new DeviceSettingNexa(device, this); @@ -118,6 +130,7 @@ void EditDeviceDialog::selectionChanged( const QModelIndex & index ) { } void EditDeviceDialog::okClicked() { + VendorDeviceTreeItem* const item = model->item( selection->currentIndex() ); if (!item || !item->isDevice()) { QMessageBox msgBox; @@ -129,6 +142,13 @@ void EditDeviceDialog::okClicked() { return; } +#ifdef Q_WS_HILDON + if (stacked_layout->currentIndex() == 0) { + stacked_layout->setCurrentIndex(1); + return; + } +#endif + if (nameLineEdit->text().trimmed() == "") { QMessageBox msgBox; msgBox.setText( tr("The device must have a name.") ); @@ -151,3 +171,13 @@ void EditDeviceDialog::okClicked() { this->accept(); } + +void EditDeviceDialog::cancelClicked() { +#ifdef Q_WS_HILDON + if (stacked_layout->currentIndex() > 0) { + stacked_layout->setCurrentIndex(stacked_layout->currentIndex()-1); + return; + } +#endif + this->reject(); +} diff --git a/telldus-gui/TelldusGui/editdevicedialog.h b/telldus-gui/TelldusGui/editdevicedialog.h index bc19ad0b..c0031394 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.h +++ b/telldus-gui/TelldusGui/editdevicedialog.h @@ -23,6 +23,7 @@ public: private slots: void selectionChanged( const QModelIndex & ); void okClicked(); + void cancelClicked(); private: VendorDeviceModel *model; @@ -32,6 +33,9 @@ private: QLineEdit *nameLineEdit; QItemSelectionModel *selection; QHash deviceSettings; +#ifdef Q_WS_HILDON + QStackedLayout *stacked_layout; +#endif }; #endif // EDITDEVICEDIALOG_H From d34eb306784410fe5fb55920072bd81522f9bf56 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 10 Mar 2009 11:33:10 +0000 Subject: [PATCH 0805/2215] Added messagewidget in MainWindow --- telldus-gui/TelldusCenter/TelldusCenter.pro | 12 ++++---- telldus-gui/TelldusCenter/mainwindow.cpp | 26 ++++++++++++---- telldus-gui/TelldusCenter/mainwindow.h | 5 ++++ telldus-gui/TelldusCenter/message.cpp | 30 +++++++++++++++++++ telldus-gui/TelldusCenter/message.h | 26 ++++++++++++++++ .../tellduscenterapplication.cpp | 7 +---- 6 files changed, 88 insertions(+), 18 deletions(-) create mode 100644 telldus-gui/TelldusCenter/message.cpp create mode 100644 telldus-gui/TelldusCenter/message.h diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index 138689de..f4960ea7 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -6,15 +6,17 @@ SOURCES += main.cpp \ mainwindow.cpp \ tellduscenterapplication.cpp \ autoupdater.cpp \ - systrayicon.cpp + systrayicon.cpp \ + message.cpp HEADERS += mainwindow.h \ tellduscenterapplication.h \ autoupdater.h \ CocoaInitializer.h \ - systrayicon.h + systrayicon.h \ + message.h RESOURCES += resource.qrc TARGET = TelldusCenter -macx { +macx { HEADERS += sparkleautoupdater.h LIBS += -framework \ TelldusGui \ @@ -27,9 +29,7 @@ macx { QMAKE_INFO_PLIST = Info.plist ICON = TelldusCenter.icns } -!macx { - LIBS += -ltelldus-gui -} +!macx:LIBS += -ltelldus-gui win32:LIBS += -L \ . VERSION = 1.3.0 diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index ac18cdc2..c760275b 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -7,13 +7,16 @@ #include #include #include +#include #include "tellduscenterapplication.h" +#include "message.h" #include "../TelldusGui/telldusgui.h" MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) - : QMainWindow(parent, flags) - , m_pagesBar(0) + : QMainWindow(parent, flags), + m_pagesBar(0), + p_message(new Message(this)) { setAttribute(Qt::WA_DeleteOnClose, true); @@ -26,13 +29,20 @@ MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) setupMenu(); setupToolBar(); + QWidget *centralWidget = new QWidget(this); + QVBoxLayout *layout = new QVBoxLayout; + centralWidget->setLayout(layout); + + layout->addWidget(p_message); + //QStackedWidget *centralWidget = new QStackedWidget(this); TelldusCenterApplication *app = TelldusCenterApplication::instance(); - QWidget *centralWidget = tdDeviceWidget(this); - setCentralWidget(centralWidget); - connect(centralWidget, SIGNAL(showMessage(const QString &, const QString &, const QString &)), app, SLOT(showMessage(const QString &, const QString &, const QString &))); - connect(centralWidget, SIGNAL(eventTriggered(const QString &, const QString &)), app, SLOT(eventTriggered(const QString &, const QString &))); + QWidget *deviceWidget = tdDeviceWidget(this); + connect(deviceWidget, SIGNAL(showMessage(const QString &, const QString &, const QString &)), app, SLOT(showMessage(const QString &, const QString &, const QString &))); + connect(deviceWidget, SIGNAL(eventTriggered(const QString &, const QString &)), app, SLOT(eventTriggered(const QString &, const QString &))); + layout->addWidget(deviceWidget); + setCentralWidget(centralWidget); setWindowTitle( tr("Telldus Center") ); } @@ -42,6 +52,10 @@ MainWindow::~MainWindow() } +void MainWindow::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { + p_message->showMessage( title, message, detailedMessage ); +} + void MainWindow::closeEvent( QCloseEvent */*event*/ ) { QSettings settings; settings.setValue("Size", size()); diff --git a/telldus-gui/TelldusCenter/mainwindow.h b/telldus-gui/TelldusCenter/mainwindow.h index 0221aeb5..87c78547 100644 --- a/telldus-gui/TelldusCenter/mainwindow.h +++ b/telldus-gui/TelldusCenter/mainwindow.h @@ -4,6 +4,7 @@ #include class QToolBar; +class Message; class MainWindow : public QMainWindow { @@ -13,6 +14,9 @@ public: MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0); ~MainWindow(); +public slots: + void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); + protected: virtual void closeEvent( QCloseEvent *event ); @@ -25,6 +29,7 @@ private: private: QToolBar *m_pagesBar; + Message *p_message; }; #endif // MAINWINDOW_H diff --git a/telldus-gui/TelldusCenter/message.cpp b/telldus-gui/TelldusCenter/message.cpp new file mode 100644 index 00000000..00b2fdc2 --- /dev/null +++ b/telldus-gui/TelldusCenter/message.cpp @@ -0,0 +1,30 @@ +#include "message.h" +#include +#include +#include + +Message::Message(QWidget *parent) + :QWidget(parent), + p_label( new QLabel(this) ), + p_timer( new QTimer(this) ) +{ + p_timer->setInterval( 3000 ); + p_timer->setSingleShot(true); + connect(p_timer, SIGNAL(timeout()), this, SLOT(hideMessage())); + + this->setVisible(false); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(p_label); +} + +void Message::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { + p_label->setText( message ); + this->setVisible( true ); + p_timer->start(); +} + +void Message::hideMessage() { + p_label->setText(""); + this->setVisible(false); +} diff --git a/telldus-gui/TelldusCenter/message.h b/telldus-gui/TelldusCenter/message.h new file mode 100644 index 00000000..9bbd7e78 --- /dev/null +++ b/telldus-gui/TelldusCenter/message.h @@ -0,0 +1,26 @@ +#ifndef MESSAGE_H +#define MESSAGE_H + +#include + +class QLabel; +class QTimer; + +class Message : public QWidget +{ + Q_OBJECT +public: + Message( QWidget *parent = 0 ); + +public slots: + void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); + +private slots: + void hideMessage(); + +private: + QLabel *p_label; + QTimer *p_timer; +}; + +#endif // MESSAGE_H diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index b73c2756..95bfa872 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -53,12 +53,7 @@ void TelldusCenterApplication::eventTriggered( const QString &name, const QStrin void TelldusCenterApplication::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { if (isMainWindowShown()) { - QMessageBox msgBox( mainWindow ); - msgBox.setText( message ); - msgBox.setInformativeText( detailedMessage ); - msgBox.setIcon( QMessageBox::Warning ); - msgBox.setStandardButtons( QMessageBox::Ok ); - msgBox.exec(); + mainWindow->showMessage(title, message, detailedMessage); } else { systrayIcon.showMessage((title != "" ? title : "Telldus Center"), message, QSystemTrayIcon::Warning); } From f7f24d305da26648e40bc49b024f6b150d7ea0c5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 10 Mar 2009 16:36:53 +0000 Subject: [PATCH 0806/2215] Made TelldusCenter load plugins --- telldus-gui/TelldusCenter/TelldusCenter.pro | 4 +- telldus-gui/TelldusCenter/mainwindow.cpp | 78 +++++++++++++++---- telldus-gui/TelldusCenter/mainwindow.h | 7 +- .../tellduscenterapplication.cpp | 44 +++++++++++ .../TelldusCenter/tellduscenterapplication.h | 9 +++ .../TelldusCenter/tellduscenterplugin.h | 17 ++++ 6 files changed, 143 insertions(+), 16 deletions(-) create mode 100644 telldus-gui/TelldusCenter/tellduscenterplugin.h diff --git a/telldus-gui/TelldusCenter/TelldusCenter.pro b/telldus-gui/TelldusCenter/TelldusCenter.pro index f4960ea7..b60f4971 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.pro +++ b/telldus-gui/TelldusCenter/TelldusCenter.pro @@ -2,6 +2,7 @@ # Project created by QtCreator 2008-12-11T11:01:36 # ------------------------------------------------- TEMPLATE = app + SOURCES += main.cpp \ mainwindow.cpp \ tellduscenterapplication.cpp \ @@ -13,7 +14,8 @@ HEADERS += mainwindow.h \ autoupdater.h \ CocoaInitializer.h \ systrayicon.h \ - message.h + message.h \ + tellduscenterplugin.h RESOURCES += resource.qrc TARGET = TelldusCenter macx { diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index c760275b..97e0c41b 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -2,22 +2,33 @@ #include #include -#include +#include #include #include #include #include #include +#include + #include "tellduscenterapplication.h" +#include "tellduscenterplugin.h" #include "message.h" #include "../TelldusGui/telldusgui.h" +class MainWindowPrivate { +public: + QToolBar *pagesBar; + Message *message; + QStackedLayout *stackedLayout; +}; + MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) - : QMainWindow(parent, flags), - m_pagesBar(0), - p_message(new Message(this)) + : QMainWindow(parent, flags) { + d = new MainWindowPrivate; + d->message = new Message(this); + setAttribute(Qt::WA_DeleteOnClose, true); // Restore size and position @@ -27,33 +38,36 @@ MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) statusBar()->setSizeGripEnabled(true); setupMenu(); - setupToolBar(); QWidget *centralWidget = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout; centralWidget->setLayout(layout); - layout->addWidget(p_message); + layout->addWidget(d->message); + + d->stackedLayout = new QStackedLayout; + layout->addLayout(d->stackedLayout); - //QStackedWidget *centralWidget = new QStackedWidget(this); TelldusCenterApplication *app = TelldusCenterApplication::instance(); QWidget *deviceWidget = tdDeviceWidget(this); connect(deviceWidget, SIGNAL(showMessage(const QString &, const QString &, const QString &)), app, SLOT(showMessage(const QString &, const QString &, const QString &))); connect(deviceWidget, SIGNAL(eventTriggered(const QString &, const QString &)), app, SLOT(eventTriggered(const QString &, const QString &))); - layout->addWidget(deviceWidget); + d->stackedLayout->addWidget(deviceWidget); setCentralWidget(centralWidget); + setupToolBar(); + setWindowTitle( tr("Telldus Center") ); } MainWindow::~MainWindow() { - + delete d; } void MainWindow::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { - p_message->showMessage( title, message, detailedMessage ); + d->message->showMessage( title, message, detailedMessage ); } void MainWindow::closeEvent( QCloseEvent */*event*/ ) { @@ -79,16 +93,47 @@ void MainWindow::setupMenu() void MainWindow::setupToolBar() { setUnifiedTitleAndToolBarOnMac(true); - m_pagesBar = addToolBar(tr("Pages")); - m_pagesBar->setIconSize(QSize(32, 32)); + d->pagesBar = addToolBar(tr("Pages")); + d->pagesBar->setIconSize(QSize(32, 32)); QActionGroup *ag = new QActionGroup(this); + QSet toolbarIcons; QAction *actionDevices = new QAction( QIcon(":/images/devices.png"), tr("Devices"), this ); actionDevices->setCheckable( true ); actionDevices->setChecked( true ); + actionDevices->setData(0); + connect(actionDevices, SIGNAL(triggered()), this, SLOT(slotPagesClick())); ag->addAction(actionDevices); - m_pagesBar->addActions( ag->actions() ); + toolbarIcons.insert("devices"); + + TelldusCenterApplication *app = TelldusCenterApplication::instance(); + PluginList plugins = app->plugins(); + foreach( TelldusCenterPlugin *plugin, plugins ) { + + QStringList widgets = plugin->widgets(); + foreach( QString widget, widgets ) { + QString page = widget.section('.', 0, 0); + if (!toolbarIcons.contains( page )) { + QWidget *pageWidget = plugin->widget( page, this ); + if (!pageWidget) { + continue; + } + QAction *action = new QAction( plugin->iconForPage( page ), page, this ); + action->setCheckable( true ); + action->setChecked( false ); + + int index = d->stackedLayout->addWidget( pageWidget ); + action->setData( index ); + + connect(action, SIGNAL(triggered()), this, SLOT(slotPagesClick())); + ag->addAction( action ); + toolbarIcons.insert(page); + } + } + + } + d->pagesBar->addActions( ag->actions() ); } void MainWindow::slotAboutApplication() { @@ -97,3 +142,10 @@ void MainWindow::slotAboutApplication() { "

private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmSplash)); - this.label3 = new System.Windows.Forms.Label(); - this.label1 = new System.Windows.Forms.Label(); - this.timer1 = new System.Windows.Forms.Timer(this.components); - this.lblVersion = new System.Windows.Forms.Label(); - this.SuspendLayout(); - // - // label3 - // - this.label3.AutoSize = true; - this.label3.BackColor = System.Drawing.Color.Transparent; - this.label3.Location = new System.Drawing.Point(114, 280); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(341, 13); - this.label3.TabIndex = 6; - this.label3.Text = "© Copyright Telldus Technologies AB 2007. Alla rättigheter förbehålles."; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.BackColor = System.Drawing.Color.Transparent; - this.label1.Location = new System.Drawing.Point(242, 195); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(45, 13); - this.label1.TabIndex = 7; - this.label1.Text = "Version:"; - // - // timer1 - // - this.timer1.Interval = 1500; - this.timer1.Tick += new System.EventHandler(this.timer1_Tick); - // - // lblVersion - // - this.lblVersion.AutoSize = true; - this.lblVersion.BackColor = System.Drawing.Color.Transparent; - this.lblVersion.Location = new System.Drawing.Point(293, 195); - this.lblVersion.Name = "lblVersion"; - this.lblVersion.Size = new System.Drawing.Size(45, 13); - this.lblVersion.TabIndex = 8; - this.lblVersion.Text = "Version:"; - // - // frmSplash - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage"))); - this.ClientSize = new System.Drawing.Size(522, 300); - this.Controls.Add(this.lblVersion); - this.Controls.Add(this.label1); - this.Controls.Add(this.label3); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; - this.Name = "frmSplash"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Load += new System.EventHandler(this.frmSplash_Load); - this.ResumeLayout(false); - this.PerformLayout(); + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(frmSplash)); + this.label3 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.lblVersion = new System.Windows.Forms.Label(); + this.SuspendLayout(); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.BackColor = System.Drawing.Color.Transparent; + this.label3.Location = new System.Drawing.Point(114, 280); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(341, 13); + this.label3.TabIndex = 6; + this.label3.Text = "© Copyright Telldus Technologies AB 2010. Alla rättigheter förbehålles."; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.BackColor = System.Drawing.Color.Transparent; + this.label1.Location = new System.Drawing.Point(242, 195); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(45, 13); + this.label1.TabIndex = 7; + this.label1.Text = "Version:"; + // + // timer1 + // + this.timer1.Interval = 1500; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // lblVersion + // + this.lblVersion.AutoSize = true; + this.lblVersion.BackColor = System.Drawing.Color.Transparent; + this.lblVersion.Location = new System.Drawing.Point(293, 195); + this.lblVersion.Name = "lblVersion"; + this.lblVersion.Size = new System.Drawing.Size(45, 13); + this.lblVersion.TabIndex = 8; + this.lblVersion.Text = "Version:"; + // + // frmSplash + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackgroundImage = ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage"))); + this.ClientSize = new System.Drawing.Size(522, 300); + this.Controls.Add(this.lblVersion); + this.Controls.Add(this.label1); + this.Controls.Add(this.label3); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; + this.Name = "frmSplash"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Load += new System.EventHandler(this.frmSplash_Load); + this.ResumeLayout(false); + this.PerformLayout(); } diff --git a/scheduler/DeviceScheduler/frmSplash.resx b/scheduler/DeviceScheduler/frmSplash.resx index 3d25f107..4e02b590 100644 --- a/scheduler/DeviceScheduler/frmSplash.resx +++ b/scheduler/DeviceScheduler/frmSplash.resx @@ -124,777 +124,777 @@ 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 + 5JJlCbQggQz3FoR0iS4pwR1t2tgDmt2D7yjgRnw0DjCH8IFvvuQa/V7c9ATKscZok3E1VVcZDTLuY+J6 + nXPCGnOJqp4fmyWQJTBZCdRYcMtpZkqAtrVgfAjjjK7uEf7XI7DTc/hEPDHCMKmj3XvQh4HDgD4/qbOn + 1phYRw0PmehWM1MyuVRZAlkCY0ogw31MEV3iC4Kzklf9Xb6jcXtQKhBHDQ/EGwASlONIgwXGYL84yfCv + dnaud++S56aq4GeyX+KWzo/PEmirBDLc2yrOdmeWTsxU3lP7uweAiHg1dLV4TC6o7TrSGE+GD9Xl09Ec + H31ou6uS88sSyBKYVgnUXHPLaYZLIDqF5E2tNEabCVt8gN5Dt+Po7YgU5qHY4cyuZb9K8xkukFy8LIEs + geYSyHDvsB6iCV6+p16SEVPMgzh0qkmTTHfVVCNMYD1V1TtMHLm4WQJZAqNIIMO9w7pGVYUPymuxcTtr + xKKJI5bScDGq6lXzS4fJIhc3SyBLYHQJ1NjqklMHSaBhU6aWvCb+U3FZmkkH1T0XNUsgS6B1CWS4ty6r + GXrlBHSXGVqTXKwsgSyB9kkgw719ssw5ZQlkCWQJzBgJZLjPmKbIBckSyBLIEmifBGpEhc0pSyBLIEsg + S2CWSSDDfZY1aK5OlkCWQJZAIYEM99wPsgSyBLIEZqEEah7pkFOWQJZAlkCWwGySQIb7bGrNXJcsgSyB + LIFzEshwz10hSyBLIEtgFkqg9rc5ZQlkCWQJZAnMOglkuM+6Js0VyhLIEsgS+Nu/zXDPvSBLIEsgS2AW + SqD2dzllCWQJZAlkCcw6CWS4z7omzRXKEsgSyBL4u7/LcM+9IEsgSyBLYBZKoPZfc8oSyBLIEsgSmHUS + yHCfdU2aK5QlkCWQJfBf/+v/Dwd7hDXySmYBAAAAAElFTkSuQmCC \ No newline at end of file From e0251738624a93f6684c6e84ccb4a163401f3805 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 29 Oct 2010 14:28:30 +0000 Subject: [PATCH 1435/2215] Version info changed --- scheduler/DeviceHandler/Properties/AssemblyInfo.cs | 6 +++--- scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scheduler/DeviceHandler/Properties/AssemblyInfo.cs b/scheduler/DeviceHandler/Properties/AssemblyInfo.cs index 44d0571e..5c428954 100644 --- a/scheduler/DeviceHandler/Properties/AssemblyInfo.cs +++ b/scheduler/DeviceHandler/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Telldus Technologies")] [assembly: AssemblyProduct("DeviceHandler")] -[assembly: AssemblyCopyright("Copyright © Telldus Technologies 2009")] +[assembly: AssemblyCopyright("Copyright © Telldus Technologies 2010")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("2009.2.0.0")] -[assembly: AssemblyFileVersion("2009.2.0.0")] +[assembly: AssemblyVersion("2010.10.0.0")] +[assembly: AssemblyFileVersion("2010.10.0.0")] diff --git a/scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs b/scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs index 1a4f9af7..4eecb077 100644 --- a/scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs +++ b/scheduler/DeviceSchedulerAgent/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Telldus Technologies")] [assembly: AssemblyProduct("DeviceSchedulerAgent")] -[assembly: AssemblyCopyright("Copyright © Telldus Technologies 2009")] +[assembly: AssemblyCopyright("Copyright © Telldus Technologies 2010")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("2009.2.0.0")] -[assembly: AssemblyFileVersion("2009.2.0.0")] +[assembly: AssemblyVersion("2010.10.0.0")] +[assembly: AssemblyFileVersion("2010.10.0.0")] From ca6fe302765573fc75d643801b6851b5b767fad3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 4 Nov 2010 15:42:08 +0000 Subject: [PATCH 1436/2215] .Net-Wrapper for 2.1-line added --- .../Properties/AssemblyInfo.cs | 36 + .../TelldusNETWrapper/TelldusNETWrapper.cs | 783 ++++++++++++++++++ .../TelldusNETWrapper.csproj | 56 ++ .../TelldusNETWrapper/TelldusNETWrapper.sln | 20 + .../TelldusNETWrapper/TelldusNETWrapper.suo | Bin 0 -> 10752 bytes bindings/dotnet/TelldusNETWrapper/app.config | 3 + 6 files changed, 898 insertions(+) create mode 100644 bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs create mode 100644 bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs create mode 100644 bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj create mode 100644 bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.sln create mode 100644 bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.suo create mode 100644 bindings/dotnet/TelldusNETWrapper/app.config diff --git a/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..f7acaacc --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +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("ClassLibrary1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("ClassLibrary1")] +[assembly: AssemblyCopyright("Copyright © Microsoft 2010")] +[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("a66028f7-b342-4dc0-9504-9e07c462ec15")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs new file mode 100644 index 00000000..f00acb30 --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs @@ -0,0 +1,783 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace TelldusWrapper +{ + public sealed class TelldusNETWrapper //don't allow inheritance + { + int lastEventID = 0; + Dictionary callbackFunctionReferenceList = new Dictionary(); //this prevents errors in "unknown module" due to callback functions being garbage collected since there are no reference to them + + //TODO: reference the correct DLL + //TODO: compile towards correct platform (x86/64?) "Any" working? + //TODO: kommentera... bÃ¥de wrapper och exempel... + //TODO: kommentera i början av filen... + //error handling? Or just throw it upwards? + //close och init (om den skulle göras alls) görs här i wrappern, de exporteras inte vidare... eller ska de? Inte heller connected/disconnected tellstick + //TODO, use getNumberOfDevices as an example, outside the wrapper, service not running = -6, handle this here or later? Negative values = error + //throwing System.DllNotFoundException if dll's not ready... Handle here or in program? Might aswell keep that error message + + + //Device methods + public const int TELLSTICK_TURNON = 1; + public const int TELLSTICK_TURNOFF = 2; + public const int TELLSTICK_BELL = 4; + public const int TELLSTICK_TOGGLE = 8; + public const int TELLSTICK_DIM = 16; + public const int TELLSTICK_LEARN = 32; + + //Error codes + public const int TELLSTICK_SUCCESS = 0; + public const int TELLSTICK_ERROR_NOT_FOUND = -1; + public const int TELLSTICK_ERROR_PERMISSION_DENIED = -2; + public const int TELLSTICK_ERROR_DEVICE_NOT_FOUND = -3; + public const int TELLSTICK_ERROR_METHOD_NOT_SUPPORTED = -4; + public const int TELLSTICK_ERROR_COMMUNICATION = -5; + public const int TELLSTICK_ERROR_CONNECTING_SERVICE = -6; + public const int TELLSTICK_ERROR_UNKNOWN_RESPONSE = -7; + public const int TELLSTICK_ERROR_UNKNOWN = -99; + + //Device typedef + public const int TELLSTICK_TYPE_DEVICE = 1; + public const int TELLSTICK_TYPE_GROUP = 2; + + //Device changes + public const int TELLSTICK_DEVICE_ADDED = 1; + public const int TELLSTICK_DEVICE_CHANGED = 2; + public const int TELLSTICK_DEVICE_REMOVED = 3; + public const int TELLSTICK_DEVICE_STATE_CHANGED = 4; + + //Change types + public const int TELLSTICK_CHANGE_NAME = 1; + public const int TELLSTICK_CHANGE_PROTOCOL = 2; + public const int TELLSTICK_CHANGE_MODEL = 3; + + + //variables for event callback (e.g. turnon, turnoff) + public delegate int EventCallbackFunction(int deviceId, int method, string data, int callbackId, Object obj); + Dictionary eventList = new Dictionary(); + GCHandle eventContextHandle; + int registeredEventFunctionId = -1; + + //variables for device event callback (e.g. change of name/protocol) + public delegate int DeviceChangeEventCallbackFunction(int deviceId, int changeEvent, int changeType, int callbackId, Object obj); + Dictionary deviceChangeEventList = new Dictionary(); + GCHandle deviceChangeEventContextHandle; + int registeredDeviceChangeEventFunctionId = -1; + + //variables for raw controller listening callback (e.g. Tellstick Duo receives data) + public delegate int RawListeningCallbackFunction(string data, int controllerId, int callbackId, Object obj); + Dictionary rawListenerList = new Dictionary(); + GCHandle rawListenerContextHandle; + int registeredRawListenerFunctionId = -1; + + + public TelldusNETWrapper() + { + } + + ~TelldusNETWrapper() + { + //clean up + if (registeredEventFunctionId != -1) + { + UnmanagedImport.tdUnregisterCallback(registeredEventFunctionId); + } + if (registeredDeviceChangeEventFunctionId != -1) + { + UnmanagedImport.tdUnregisterCallback(registeredDeviceChangeEventFunctionId); + } + if (registeredRawListenerFunctionId != -1) + { + UnmanagedImport.tdUnregisterCallback(registeredRawListenerFunctionId); + } + UnmanagedImport.tdClose(); //Close the library and clean up the cache it uses. + if (eventContextHandle.IsAllocated) + { + eventContextHandle.Free(); + } + if (deviceChangeEventContextHandle.IsAllocated) + { + deviceChangeEventContextHandle.Free(); + } + if (rawListenerContextHandle.IsAllocated) + { + rawListenerContextHandle.Free(); + } + } + + /// + /// Imported functions from TelldusCore.dll + /// + private sealed class UnmanagedImport + { + private UnmanagedImport() { } //cannot instantiate this class + + #region Unmanaged Code + [DllImport("TelldusCore.dll")] + public static extern int tdGetNumberOfDevices(); + + [DllImport("TelldusCore.dll")] + public static extern int tdGetDeviceId(int value); + + [DllImport("TelldusCore.dll")] + public static unsafe extern char* tdGetName(int deviceId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern char* tdGetProtocol(int deviceId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern char* tdGetModel(int deviceId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern char* tdGetDeviceParameter(int deviceId, char* name, char* defaultValue); + + [DllImport("TelldusCore.dll")] + public static unsafe extern bool tdSetName(int deviceId, char* name); + + [DllImport("TelldusCore.dll")] + public static unsafe extern bool tdSetProtocol(int deviceId, char* protocol); + + [DllImport("TelldusCore.dll")] + public static unsafe extern bool tdSetModel(int deviceId, char* model); + + [DllImport("TelldusCore.dll")] + public static unsafe extern bool tdSetDeviceParameter(int deviceId, char* name, char* value); + + [DllImport("TelldusCore.dll")] + public static unsafe extern int tdAddDevice(); + + [DllImport("TelldusCore.dll")] + public static unsafe extern bool tdRemoveDevice(int deviceId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern int tdMethods(int deviceId, int methodsSupported); + + [DllImport("TelldusCore.dll")] + public static extern int tdTurnOn(int deviceId); + + [DllImport("TelldusCore.dll")] + public static extern int tdTurnOff(int deviceId); + + [DllImport("TelldusCore.dll")] + public static extern int tdBell(int deviceId); + + [DllImport("TelldusCore.dll")] + public static extern int tdDim(int deviceId, char level); + + [DllImport("TelldusCore.dll")] + public static unsafe extern char* tdGetErrorString(int errorNo); + + [DllImport("TelldusCore.dll")] + public static extern void tdClose(); + + [DllImport("TelldusCore.dll")] + public static extern void tdInit(); + + [DllImport("TelldusCore.dll")] + public static unsafe extern int tdRegisterDeviceEvent(Delegate eventFunction, void* context); + + [DllImport("TelldusCore.dll")] + public static extern int tdLastSentCommand(int deviceId, int methods); + + [DllImport("TelldusCore.dll")] + public static extern int tdGetDeviceType(int deviceId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern int tdSendRawCommand(char* command, int reserved); + + [DllImport("TelldusCore.dll")] + public static unsafe extern int tdRegisterRawDeviceEvent(Delegate rawListeningFunction, void* context); + + [DllImport("TelldusCore.dll")] + public static extern int tdLearn(int deviceId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern char* tdLastSentValue(int deviceId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern void tdReleaseString(char* value); + + [DllImport("TelldusCore.dll")] + public static unsafe extern int tdUnregisterCallback(int eventId); + + [DllImport("TelldusCore.dll")] + public static unsafe extern int tdRegisterDeviceChangeEvent(Delegate deviceEventFunction, void* context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public unsafe delegate int EventFunctionDelegate(int deviceId, int method, char* data, int callbackId, void* context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public unsafe delegate int DeviceChangeEventFunctionDelegate(int deviceId, int changeEvent, int changeType, int callbackId, void* context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public unsafe delegate int RawListeningDelegate(char* data, int controllerId, int callbackId, void* context); + + #endregion + } + + #region Public Methods + + /// + /// Add a new device to the global database of devices. This function must be called first before + /// any call to tdSetName(), tdSetProtocol() and similar functions. + /// + /// The device id for the newly created device. If the creation fails it returnes a + /// negative value. + public static int tdAddDevice() + { + return UnmanagedImport.tdAddDevice(); + } + + /// + /// Sends bell command to devices supporting this. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// Id of device to sound the bell on + /// Success or error code + public static int tdBell(int deviceId) + { + return UnmanagedImport.tdBell(deviceId); + } + + /// + /// Dims a device. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// The device id to dim + /// The level the device should dim to. This value should be 0-255 + /// Success or error code + public static int tdDim(int deviceId, char level) + { + return UnmanagedImport.tdDim(deviceId, level); + } + + /// + /// This function returns the unique id of a device with a specific index. + /// To get all the id numbers you should loop over all the devices, use tdGetNumberOfDevices() to get the number of devices + /// + /// Device index + /// Id of device at that position + public static int tdGetDeviceId(int order) + { + return UnmanagedImport.tdGetDeviceId(order); + } + + /// + /// Get a protocol specific device parameter + /// + /// The id of the device to query + /// The name of the parameter to query + /// A defaultValue to return if the current parameter hasn't previously been set + /// Any protocol specific parameter specified by "name" + public static unsafe string tdGetDeviceParameter(int deviceId, string name, string defaultValue) + { + return getString(UnmanagedImport.tdGetDeviceParameter(deviceId, stringToChar(name), stringToChar(defaultValue))); + } + + /// + /// Returns which type the device is + /// + /// Id of the device + /// TELLSTICK_TYPE_DEVICE or TELLSTICK_TYPE_GROUP + public static int tdGetDeviceType(int deviceId) + { + return UnmanagedImport.tdGetDeviceType(deviceId); + } + + /// + /// Get a human readable string from an error code returned from a function in telldus-core + /// + /// The error code to translate + /// A string ready to show to the user. + /// TELLSTICK_SUCCESS + /// TELLSTICK_ERROR_NOT_FOUND + /// TELLSTICK_ERROR_PERMISSION_DENIED + /// TELLSTICK_ERROR_DEVICE_NOT_FOUND + /// TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + /// TELLSTICK_ERROR_COMMUNICATION + /// TELLSTICK_ERROR_CONNECTING_SERVICE + /// TELLSTICK_ERROR_UNKNOWN_RESPONSE + /// TELLSTICK_ERROR_UNKNOWN + /// + public static unsafe string tdGetErrorString(int errorNo) + { + return getString(UnmanagedImport.tdGetErrorString(errorNo)); + } + + /// + /// Query a device for it’s name + /// + /// Id of device to query + /// The name of the device or an empty string if the device is not found + public static unsafe string tdGetName(int deviceId) + { + return getString(UnmanagedImport.tdGetName(deviceId)); + } + + /// + /// Query a device for which methods it supports. By supplying the methods you support + /// the library could remap the methods a device support for better fit the application. + /// + /// Id of device to query + /// Methods that the client application supports + /// Supported (both by client application and by device) method-flags OR'ed into an integer + /// TELLSTICK_TURNON + /// TELLSTICK_TURNOFF + /// TELLSTICK_BELL + /// TELLSTICK_TOGGLE + /// TELLSTICK_DIM + /// TELLSTICK_LEARN + /// + public static int tdMethods(int deviceId, int methodsSupported) + { + return UnmanagedImport.tdMethods(deviceId, methodsSupported); + } + + /// + /// Query a device for it’s model + /// + /// Id of device to query + /// The model for a device. Not all protocols use this. + public static unsafe string tdGetModel(int deviceId) + { + return getString(UnmanagedImport.tdGetModel(deviceId)); + } + + /// + /// This function returns the number of devices configured + /// + /// The total number of devices configured + public static int tdGetNumberOfDevices() + { + return UnmanagedImport.tdGetNumberOfDevices(); + } + + /// + /// Query a device for it’s protocol + /// + /// Id of device to query + /// The protocol for a device. + public static unsafe string tdGetProtocol(int deviceId) + { + return getString(UnmanagedImport.tdGetProtocol(deviceId)); + } + + /// + /// Returns the last sent command to a specific device + /// + /// Id of device to query + /// The methods supported by the client. See tdMethods() for more information. + /// The last sent command as integer, for example TELLSTICK_TURNON or TELLSTICK_TURNOFF + public static int tdLastSentCommand(int deviceId, int methods) + { + return UnmanagedImport.tdLastSentCommand(deviceId, methods); + } + + /// + /// If the last sent command it TELLSTICK_DIM this returns the dimmed value + /// + /// Id of device to query + /// The the value as a human readable string, for example "128" for 50% + public static unsafe string tdLastSentValue(int deviceId) + { + return getString(UnmanagedImport.tdLastSentValue(deviceId)); + } + + /// + /// Sends a special learn command to some devices that need a special learn-command to be used from TellStick + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// Id of device to learn + /// Success or error code + public static int tdLearn(int deviceId) + { + return UnmanagedImport.tdLearn(deviceId); + } + + /// + /// Register a callback event function to be called when a device event (e.g. turn on, turn off) occurs + /// + /// Callback function to be called + /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. + /// Callback event id + public unsafe int tdRegisterDeviceEvent(EventCallbackFunction eventFunc, Object obj) + { + int returnValue = 0; + + if (eventList.Count == 0) + { + //first added, register with dll too + //only the context object of the first event will be registered + UnmanagedImport.EventFunctionDelegate eventFunctionDelegate = new UnmanagedImport.EventFunctionDelegate(eventFunction); + if (obj != null) + { + eventContextHandle = GCHandle.Alloc(obj); + registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(eventFunctionDelegate, (void*)GCHandle.ToIntPtr(eventContextHandle)); //context here or above? + } + else + { + registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(eventFunctionDelegate, (void*)null); //context here or above? + } + callbackFunctionReferenceList.Add(registeredEventFunctionId, eventFunctionDelegate); + } + + ++lastEventID; + returnValue = lastEventID; + eventList.Add(returnValue, eventFunc); + + return returnValue; + } + + /// + /// Register a callback device change event function to be called when a device change event (e.g. change of name, device added) occurs + /// + /// Callback function to be called + /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. + /// Callback event id + public unsafe int tdRegisterDeviceChangeEvent(DeviceChangeEventCallbackFunction deviceEventFunc, Object obj) + { + int returnValue = 0; + if (deviceChangeEventList.Count == 0) + { + //first added, register with dll too + //only the context object of the first event will be registered + UnmanagedImport.DeviceChangeEventFunctionDelegate deviceChangeEventFunctionDelegate = new UnmanagedImport.DeviceChangeEventFunctionDelegate(deviceEventFunction); + + if (obj != null) + { + deviceChangeEventContextHandle = GCHandle.Alloc(obj); + registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)GCHandle.ToIntPtr(deviceChangeEventContextHandle)); + } + else + { + registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)null); + } + callbackFunctionReferenceList.Add(registeredDeviceChangeEventFunctionId, deviceChangeEventFunctionDelegate); + + } + ++lastEventID; + returnValue = lastEventID; + deviceChangeEventList.Add(returnValue, deviceEventFunc); + + return returnValue; + } + + /// + /// Register a callback listening function to be called when a listening event (e.g. data is received with Tellstick Duo) occurs + /// + /// Callback function to be called + /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. + /// Callback event id + public unsafe int tdRegisterRawDeviceEvent(RawListeningCallbackFunction listeningFunc, Object obj) + { + int returnValue = 0; + if (rawListenerList.Count == 0) + { + //first added, register with dll too + //only the context object of the first event will be registered + UnmanagedImport.RawListeningDelegate listeningFunctionDelegate = new UnmanagedImport.RawListeningDelegate(rawListeningFunction); + + if (obj != null) + { + rawListenerContextHandle = GCHandle.Alloc(obj); + + registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)GCHandle.ToIntPtr(rawListenerContextHandle)); //TODO context here or above? + } + else + { + registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)null); + } + callbackFunctionReferenceList.Add(registeredRawListenerFunctionId, listeningFunctionDelegate); + } + ++lastEventID; + returnValue = lastEventID; + rawListenerList.Add(returnValue, listeningFunc); + return returnValue; + } + + /// + /// Removes a device. + /// + /// Id of device to remove + /// True on success, false otherwise + public static bool tdRemoveDevice(int deviceId) + { + return UnmanagedImport.tdRemoveDevice(deviceId); + } + + /// + /// Send a raw command to TellStick. Please read the TellStick protocol definition on how the command should be constructed. + /// + /// The command for TellStick in its native format + /// + /// Success or error code + public static unsafe int tdSendRawCommand(string command, int reserved) + { + char* commandChar = stringToChar(command); + int returnValue = UnmanagedImport.tdSendRawCommand(commandChar, reserved); + Marshal.FreeHGlobal((IntPtr)commandChar); + return returnValue; + } + + /// + /// Sets a new protocol specific parameter. Please see the documentation of the protocols before setting any parameter. + /// + /// Id of device to change + /// The name of the parameter to change + /// The new value for the parameter + /// Success or error code + public static unsafe bool tdSetDeviceParameter(int deviceId, string name, string value) + { + char* nameChar = stringToChar(name); + char* valueChar = stringToChar(value); + bool returnValue = UnmanagedImport.tdSetDeviceParameter(deviceId, nameChar, valueChar); + Marshal.FreeHGlobal((IntPtr)nameChar); + Marshal.FreeHGlobal((IntPtr)valueChar); + return returnValue; + } + + /// + /// Sets a new model for a device. Which model to set depends on the current protocol. + /// + /// Id of device to change + /// The new model + /// Success or error code + public static unsafe bool tdSetModel(int deviceId, string model) + { + char* modelChar = stringToChar(model); + bool returnValue = UnmanagedImport.tdSetModel(deviceId, modelChar); + Marshal.FreeHGlobal((IntPtr)modelChar); + return returnValue; + } + + /// + /// Sets a new name for a device. + /// + /// Id of device to change + /// The new name + /// Success or error code + public static unsafe bool tdSetName(int deviceId, string name) + { + char* nameChar = stringToChar(name); + bool returnValue = UnmanagedImport.tdSetName(deviceId, nameChar); + Marshal.FreeHGlobal((IntPtr)nameChar); + return returnValue; + } + + /// + /// This changes the current protocol used by a device. After changing the protocol, setting new parameters is required. + /// + /// Id of device to change + /// The new protocol to use + /// Success or error code + public static unsafe bool tdSetProtocol(int deviceId, string protocol) + { + char* protocolChar = stringToChar(protocol); + bool returnValue = UnmanagedImport.tdSetProtocol(deviceId, protocolChar); + Marshal.FreeHGlobal((IntPtr)protocolChar); + return returnValue; + } + + /// + /// Turns a device on. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// Id of device to turn on + /// Success or error code + public static unsafe int tdTurnOn(int deviceId) + { + return UnmanagedImport.tdTurnOn(deviceId); + } + + /// + /// Turns a device off. + /// Make sure the device supports this by calling tdMethods() before any calls to this function. + /// + /// Id of device to turn off + /// Success or error code + public static unsafe int tdTurnOff(int deviceId) + { + return UnmanagedImport.tdTurnOff(deviceId); + } + + /// + /// Unregister a callback function. All functions will be unregistered automatically when this objekt is deleted. + /// + /// Id of callback even to unregister + public void unregisterCallback(int eventId) + { + eventList.Remove(eventId); + if (eventList.Count == 0) + { + //no more events in list + UnmanagedImport.tdUnregisterCallback(registeredEventFunctionId); + callbackFunctionReferenceList.Remove(registeredEventFunctionId); + if (eventContextHandle.IsAllocated) + { + eventContextHandle.Free(); + } + } + + deviceChangeEventList.Remove(eventId); + if (deviceChangeEventList.Count == 0) + { + //no more events in list + UnmanagedImport.tdUnregisterCallback(registeredDeviceChangeEventFunctionId); + callbackFunctionReferenceList.Remove(registeredDeviceChangeEventFunctionId); + if (deviceChangeEventContextHandle.IsAllocated) + { + deviceChangeEventContextHandle.Free(); + } + } + + rawListenerList.Remove(eventId); + if (rawListenerList.Count == 0) + { + //no more events in list + UnmanagedImport.tdUnregisterCallback(registeredRawListenerFunctionId); + callbackFunctionReferenceList.Remove(registeredRawListenerFunctionId); + if (rawListenerContextHandle.IsAllocated) + { + rawListenerContextHandle.Free(); + } + } + } + + #endregion + + + #region Private Methods + + /// + /// Convert char* to correctly encoded string, clean up received char* + /// + /// Char* to convert + /// Converted string + private static unsafe string getString(char* input) + { + return getString(input, true); + } + + /// + /// Convert char* to correctly encoded string, clean up of received char* is optional + /// + /// Char* to convert + /// Clean up char* or not (don't do that if it is still should be used somewhere) + /// Converted string + private static unsafe string getString(char* input, bool release) + { + string returnString = System.Text.Encoding.UTF8.GetString(System.Text.Encoding.Unicode.GetBytes(new string(input))); + if (release) + { + UnmanagedImport.tdReleaseString(input); + } + return returnString; + } + + /// + /// Convert string to correctly encoded char* + /// + /// String to convert + /// Converted char* + private static unsafe char* stringToChar(string input) + { + input = String.Concat(input, char.MinValue); //add null terminator + byte[] inputByte = System.Text.Encoding.UTF8.GetBytes(input); + int size = Marshal.SystemDefaultCharSize * inputByte.Length; + IntPtr inputPointer = Marshal.AllocHGlobal(size); + + Marshal.Copy(inputByte, 0, inputPointer, inputByte.Length); + return (char*)inputPointer; + } + + /// + /// Event function wrapper that will call all registered event functions with C#-arguments when + /// this event function is called from telldus core, with C++-style arguments. This function will + /// be registered with telldus core when the first event callback function is added. + /// + /// Id of affected device + /// Method that was executed on device + /// Optional data that was sent to the method (e.g. dim value) + /// Callback event id + /// Context (optional) + /// 0 + private unsafe int eventFunction(int deviceId, int method, char* data, int callbackId, void* context) + { + foreach (EventCallbackFunction eventFunc in eventList.Values) + { + if (context != null) + { + GCHandle eventContextHandle = GCHandle.FromIntPtr((IntPtr)context); + eventFunc(deviceId, method, getString(data, false), callbackId, (Object)eventContextHandle.Target); + } + else + { + eventFunc(deviceId, method, getString(data, false), callbackId, null); + } + } + + return 0; + } + + /// + /// Event function wrapper that will call all registered device change event functions with C#-arguments when + /// this device change event function is called from telldus core, with C++-style arguments. This function will + /// be registered with telldus core when the first device change event callback function is added. + /// + /// Id of affected device + /// Method that was executed, TELLSTICK_DEVICE_ADDED, TELLSTICK_DEVICE_CHANGED, TELLSTICK_DEVICE_REMOVED, TELLSTICK_DEVICE_STATE_CHANGED + /// Type of change TELLSTICK_CHANGE_NAME, TELLSTICK_CHANGE_PROTOCOL, TELLSTICK_CHANGE_MODEL + /// Callback event id + /// Context (optional) + /// 0 + private unsafe int deviceEventFunction(int deviceId, int changeEvent, int changeType, int callbackId, void* context) + { + foreach (DeviceChangeEventCallbackFunction deviceEventFunc in deviceChangeEventList.Values) + { + if (context != null) + { + GCHandle deviceChangeEventContextHandle = GCHandle.FromIntPtr((IntPtr)context); + deviceEventFunc(deviceId, changeEvent, changeType, callbackId, (Object)deviceChangeEventContextHandle.Target); + } + else + { + deviceEventFunc(deviceId, changeEvent, changeType, callbackId, null); + } + } + + return 0; + } + + /// + /// Event function wrapper that will call all registered listening functions with C#-arguments when + /// this listening function is called from telldus core, with C++-style arguments. This function will + /// be registered with telldus core when the first listening callback function is added. + /// + /// Received data + /// Id of receiving controller + /// Callback event id + /// Context (optional) + /// 0 + private unsafe int rawListeningFunction(char* data, int controllerId, int callbackId, void* context) + { + foreach (RawListeningCallbackFunction rawListeningFunc in rawListenerList.Values) + { + if (context != null) + { + GCHandle rawListenerContextHandle = GCHandle.FromIntPtr((IntPtr)context); + rawListeningFunc(getString(data, false), controllerId, callbackId, (Object)rawListenerContextHandle.Target); //strings cannot be released here, since they are still in use by calling core (sent to other clients aswell), let the core take care of it with shared pointer + } + else + { + rawListeningFunc(getString(data, false), controllerId, callbackId, null); + } + } + + return 0; + } + + #endregion + } +} diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj new file mode 100644 index 00000000..255d47bb --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.csproj @@ -0,0 +1,56 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43} + Library + Properties + ClassLibrary1 + TelldusNETWrapper + v2.0 + 512 + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.sln b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.sln new file mode 100644 index 00000000..28bb73d2 --- /dev/null +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelldusNETWrapper", "TelldusNETWrapper.csproj", "{675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {675C494F-7D3B-4F6F-AB7A-98BA9E2B2B43}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.suo b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.suo new file mode 100644 index 0000000000000000000000000000000000000000..61636ea27bae5661a6ed4a26267e46f8b7e0a0cc GIT binary patch literal 10752 zcmeI2TWnNC7{_O;C<=;zqT+2uR1{gu{Zd7{+ZL)VEwo%>)|f)KYhh`dUVw@k8XIdBWG0=N~>o+AQgC9n!u9rP`trC%cz4jeLr{6lpXd?QU=<7zfQs(+c)J?wZZH8ncu?UV{}1 zZ)Ew?=$2$xrQ7tF5p&A4nSQRL<}h^*ntcC=8x~owH+6}-c`BU|9gzb=4`ef?Un)ny z*KPNpV2*P=XSyu@GthH_yIN%(>z6)y9@HAI=d#<R%u?q}fnTo~qdi1@-1ZK0H-O#9((dQ3*VcLaPA_^qN?(pTi*|=+IDmw8o1@_A zVYZ>79?oVBdRO}VIuKq*-eNgzl1OwvYsf)e(rm!S>_SH#gSK{LKF12iOrD?Y-cjfp zW%V!H(VDq>NzTCj%KiuDe-i#QG~}S+6ucRr#mkroo*)y+u(IZPw#H+W0X65?j ze`I%u;6gtX3{=G~TUD13ZpBTymas(M`S?mBD)DQlBu!o59)lOPe1OLq_DxCnh@~^jY~t#4C2%$r zNLCBxG?bqR(c#+*g&s%c{PRbWbpn2AKXdSFu1X+EWz)^3uWX_k4e1i)7ughZhk5Gy zcN3&66BD1*6;st+FaGYMEtAaZzOLBz`E6g~JSK4`;X{TnVmHuYHqmY(ut;;K_72CeJq7F+RQHWxc8KMH|ZoJ192oP+8wAawb zUUSxJX$fzKwO(PYiq@v4E!zH!qgRSZ3%na$us=oH8`u6QR`N4e;%`SXPlHu?$kD(S z4zj{1AMgbD6|*Wgjf-D<)*TQadoLe9jBd!{l{{s6ERcaFHDBlBjJbxmyZPkmi|-VA722WsN26Q`A4V^oWBlewr>VI$3En2a}3F zPuS>l2q{!9JeSdDdHm{P(zD=k(Ps_=7cGB27jCi~?SbCOC58Mc1CZ>gOdc`0N3ow` zFcrl)@R|UyV!;(FSL*l?n?Y7$ zEN_#4CzSunro>(UeT?<~F~jO5%Of`K%3Dd;(QZ5!!-zi|I=RogUop` zQ2F)vOPv6pLTaUVr&zOczHSX&eiOX)BMO~*aw{dB^1x;8)01hPcZfkK*d=SAM;9@mGR`UhSKcX zMfml7LEj?c;!iPF@tR7t^>1-Qs@B3Uy!yTo7yt8&eJ7Z;8vd=puxjr z^u;QAJw9vDIYJ-$t@D26)J@ogG+E_7&TYEMJR9MWz7IKRZ@@b2w6?@7Xs-1gLHyELkZAWsHm(wn&%68>f8CdEYt@-Z zEq}W(_FL4xFz?isqM-O$KvQ#DtEks^NXP5&iI1{~b|jxgncVzHgpiqEkgXHXnS_X + + From e254bf98ca7e370dbd0aa8401f080ecbac7429df Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 4 Nov 2010 15:54:40 +0000 Subject: [PATCH 1437/2215] Code cleanup --- .../dotnet/TelldusNETWrapper/TelldusNETWrapper.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs index f00acb30..b2f212a7 100644 --- a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs @@ -9,15 +9,6 @@ namespace TelldusWrapper int lastEventID = 0; Dictionary callbackFunctionReferenceList = new Dictionary(); //this prevents errors in "unknown module" due to callback functions being garbage collected since there are no reference to them - //TODO: reference the correct DLL - //TODO: compile towards correct platform (x86/64?) "Any" working? - //TODO: kommentera... bÃ¥de wrapper och exempel... - //TODO: kommentera i början av filen... - //error handling? Or just throw it upwards? - //close och init (om den skulle göras alls) görs här i wrappern, de exporteras inte vidare... eller ska de? Inte heller connected/disconnected tellstick - //TODO, use getNumberOfDevices as an example, outside the wrapper, service not running = -6, handle this here or later? Negative values = error - //throwing System.DllNotFoundException if dll's not ready... Handle here or in program? Might aswell keep that error message - //Device methods public const int TELLSTICK_TURNON = 1; @@ -483,7 +474,7 @@ namespace TelldusWrapper { rawListenerContextHandle = GCHandle.Alloc(obj); - registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)GCHandle.ToIntPtr(rawListenerContextHandle)); //TODO context here or above? + registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)GCHandle.ToIntPtr(rawListenerContextHandle)); } else { From e72a3b285a5177d745c2118f58bf93ac146c2ba3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 4 Nov 2010 16:07:39 +0000 Subject: [PATCH 1438/2215] Added tdClose-method, to be called after use of static methods. --- bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs index b2f212a7..9f46353a 100644 --- a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs @@ -232,6 +232,16 @@ namespace TelldusWrapper return UnmanagedImport.tdBell(deviceId); } + /// + /// Close the library and clean up the cache it uses. + /// This should be called when the library is not supposed to be used anymore. + /// Do not use when this has been instantiated, will be closed in destructor then, only on static methods. + /// + public static void tdClose() + { + UnmanagedImport.tdClose(); + } + /// /// Dims a device. /// Make sure the device supports this by calling tdMethods() before any calls to this function. From b4abbbe3bb05385504bd8ceecb665826f63f35fe Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Nov 2010 10:55:55 +0000 Subject: [PATCH 1439/2215] Added settingswidget DeviceSettingUnitcode --- telldus-gui/TelldusGui/CMakeLists.txt | 4 ++ .../TelldusGui/devicesettingunitcode.cpp | 67 +++++++++++++++++++ .../TelldusGui/devicesettingunitcode.h | 43 ++++++++++++ telldus-gui/TelldusGui/editdevicedialog.cpp | 4 +- 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 telldus-gui/TelldusGui/devicesettingunitcode.cpp create mode 100644 telldus-gui/TelldusGui/devicesettingunitcode.h diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 1ab91840..eb1f1229 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -24,6 +24,7 @@ SET( telldus-gui_SRCS devicesettingnexabell.cpp devicesettingrisingsun.cpp devicesettingsartano.cpp + devicesettingunitcode.cpp devicesettingupm.cpp devicesetting.cpp methodwidget.cpp @@ -50,6 +51,7 @@ SET( telldus-gui_MOC_HDRS devicesettingnexabell.h devicesettingrisingsun.h devicesettingsartano.h + devicesettingunitcode.h devicesettingupm.h devicesetting.h methodwidget.h @@ -60,6 +62,8 @@ QT4_WRAP_CPP( telldus-gui_MOC_SRCS ${telldus-gui_MOC_HDRS} ) QT4_AUTOMOC ( ${telldus-gui_SRCS} ) QT4_ADD_RESOURCES (telldus-gui_RSRCS telldusgui.qrc data/${BRANDING}/resources.qrc ) +LIST(APPEND telldus-gui_RSRCS data/${BRANDING}/devices.xml) + SET( telldus-gui_LIBRARIES ${QT_LIBRARIES} ) diff --git a/telldus-gui/TelldusGui/devicesettingunitcode.cpp b/telldus-gui/TelldusGui/devicesettingunitcode.cpp new file mode 100644 index 00000000..cd920767 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingunitcode.cpp @@ -0,0 +1,67 @@ +// +// C++ Implementation: devicesettingnexa +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "devicesettingunitcode.h" +#include "device.h" +#include +#include +#include +#include + +DeviceSettingUnitcode::DeviceSettingUnitcode(Device *device, QWidget *parent) + : DeviceSetting(device, parent), + dialCode(0) +{ + QGridLayout *gridLayout = new QGridLayout(this); + + QLabel *labelCodeTitle = new QLabel(this); + labelCodeTitle->setObjectName(QString::fromUtf8("labelCodeTitle")); + labelCodeTitle->setAlignment(Qt::AlignCenter); + labelCodeTitle->setText( tr("Unit code") ); + gridLayout->addWidget(labelCodeTitle, 0, 0, 1, 1); + + dialCode = new QDial(this); + dialCode->setObjectName(QString::fromUtf8("dialCode")); + dialCode->setMinimum(1); + dialCode->setMaximum(4); + dialCode->setPageStep(1); + dialCode->setOrientation(Qt::Horizontal); + dialCode->setNotchesVisible(true); + gridLayout->addWidget(dialCode, 1, 0, 1, 1); + connect(dialCode, SIGNAL(valueChanged(int)), this, SLOT(codeChanged(int) ) ); + + + labelCode = new QLabel(this); + labelCode->setObjectName(QString::fromUtf8("labelCode")); + labelCode->setAlignment(Qt::AlignCenter); + labelCode->setText( "1" ); + gridLayout->addWidget(labelCode, 2, 0, 1, 1); + + this->setValue( "unit", device->parameter("unit", "1") ); +} + + +DeviceSettingUnitcode::~DeviceSettingUnitcode() { +} + +void DeviceSettingUnitcode::saveParameters() { + p_device->setParameter( "unit", QString::number(dialCode->value()) ); +} + +void DeviceSettingUnitcode::setValue( const QString &name, const QString &value ) { + if (name == "unit") { + dialCode->setValue(value.toInt()); + } +} + +void DeviceSettingUnitcode::codeChanged(int code) { + labelCode->setText(QString("%1").arg(dialCode->value())); +} diff --git a/telldus-gui/TelldusGui/devicesettingunitcode.h b/telldus-gui/TelldusGui/devicesettingunitcode.h new file mode 100644 index 00000000..8ba16600 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingunitcode.h @@ -0,0 +1,43 @@ +// +// C++ Interface: devicesettingnexa +// +// Description: +// +// +// Author: Micke Prag , (C) 2007 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DEVICESETTINGUNITCODE_H +#define DEVICESETTINGUNITCODE_H + +#include "devicesetting.h" + +class QDial; +class QLabel; + +/** + @author Micke Prag +*/ +class DeviceSettingUnitcode : public DeviceSetting +{ +Q_OBJECT +public: + DeviceSettingUnitcode(Device *device, QWidget *parent = 0); + + virtual ~DeviceSettingUnitcode(); + +public slots: + virtual void saveParameters(); + virtual void setValue( const QString &name, const QString &value ); + +private slots: + void codeChanged(int); + +protected: + QDial *dialCode; + QLabel *labelCode; +}; + +#endif diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 8053d534..eeb336fa 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -12,6 +12,7 @@ #include "devicesettingnexabell.h" #include "devicesettingrisingsun.h" #include "devicesettingsartano.h" +#include "devicesettingunitcode.h" #include "devicesettingupm.h" #include @@ -157,7 +158,8 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f d->deviceSettings[12] = new DeviceSettingArctechSelflearning(device, this); ((DeviceSettingArctechSelflearning *)d->deviceSettings[12])->setRemoteMinMax(1,33554432); ((DeviceSettingArctechSelflearning *)d->deviceSettings[12])->setUnitMinMax(1,16); - + d->deviceSettings[13] = new DeviceSettingUnitcode(device, this); + foreach( DeviceSetting *s, d->deviceSettings ) { connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&)), s, SLOT(setValue(const QString&, const QString&))); d->settingsLayout->addWidget( s ); From 75af4fb7fa8cbd88f54da7017a86aab3b03a51fd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 9 Nov 2010 11:12:11 +0000 Subject: [PATCH 1440/2215] Added device Goobay --- .../TelldusGui/data/telldus/devices.xml | 3 + .../TelldusGui/data/telldus/resources.qrc | 88 +++++++++--------- .../TelldusGui/images/devices/goobay.png | Bin 0 -> 21396 bytes .../TelldusGui/images/vendors/goobay.png | Bin 0 -> 5059 bytes 4 files changed, 48 insertions(+), 43 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/goobay.png create mode 100644 telldus-gui/TelldusGui/images/vendors/goobay.png diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index 8cd60896..f6f6a403 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -29,6 +29,9 @@ Code Switch Self Learning on/off + + Code Switch + Code Switch diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index 5835c38f..f7f64a46 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -1,45 +1,47 @@ - - devices.xml - ../../images/devices/arctech_cs.png - ../../images/devices/arctech_sl.png - ../../images/devices/bell.png - ../../images/devices/conrad-rsl888.png - ../../images/devices/elro.png - ../../images/devices/elro-ab600.png - ../../images/devices/fr004r.png - ../../images/devices/gao_cs.png - ../../images/devices/gao_sl.png - ../../images/devices/hq_cs.png - ../../images/devices/koppla.png - ../../images/devices/otio.png - ../../images/devices/projectorscreen.png - ../../images/devices/risingsun_cs.png - ../../images/devices/sartano.png - ../../images/devices/upm_sl.png - ../../images/devices/waveman_cs.png - ../../images/devices/x10.png - ../../images/devices/zke-2603.png - ../../images/vendors/chacon.png - ../../images/vendors/coco.png - ../../images/vendors/conrad.png - ../../images/vendors/elro.png - ../../images/vendors/gao.png - ../../images/vendors/homeeasy.png - ../../images/vendors/hq.png - ../../images/vendors/ikea.png - ../../images/vendors/intertechno.png - ../../images/vendors/kappa.png - ../../images/vendors/kjelloco.png - ../../images/vendors/klikaanklikuit.png - ../../images/vendors/nexa.png - ../../images/vendors/otio.png - ../../images/vendors/proove.png - ../../images/vendors/roxcore.png - ../../images/vendors/rusta.png - ../../images/vendors/sartano.png - ../../images/vendors/upm.png - ../../images/vendors/waveman.png - ../../images/vendors/x10.png - + + devices.xml + ../../images/devices/arctech_cs.png + ../../images/devices/arctech_sl.png + ../../images/devices/bell.png + ../../images/devices/conrad-rsl888.png + ../../images/devices/elro.png + ../../images/devices/elro-ab600.png + ../../images/devices/fr004r.png + ../../images/devices/gao_cs.png + ../../images/devices/gao_sl.png + ../../images/devices/goobay.png + ../../images/devices/hq_cs.png + ../../images/devices/koppla.png + ../../images/devices/otio.png + ../../images/devices/projectorscreen.png + ../../images/devices/risingsun_cs.png + ../../images/devices/sartano.png + ../../images/devices/upm_sl.png + ../../images/devices/waveman_cs.png + ../../images/devices/x10.png + ../../images/devices/zke-2603.png + ../../images/vendors/chacon.png + ../../images/vendors/coco.png + ../../images/vendors/conrad.png + ../../images/vendors/elro.png + ../../images/vendors/gao.png + ../../images/vendors/goobay.png + ../../images/vendors/homeeasy.png + ../../images/vendors/hq.png + ../../images/vendors/ikea.png + ../../images/vendors/intertechno.png + ../../images/vendors/kappa.png + ../../images/vendors/kjelloco.png + ../../images/vendors/klikaanklikuit.png + ../../images/vendors/nexa.png + ../../images/vendors/otio.png + ../../images/vendors/proove.png + ../../images/vendors/roxcore.png + ../../images/vendors/rusta.png + ../../images/vendors/sartano.png + ../../images/vendors/upm.png + ../../images/vendors/waveman.png + ../../images/vendors/x10.png + diff --git a/telldus-gui/TelldusGui/images/devices/goobay.png b/telldus-gui/TelldusGui/images/devices/goobay.png new file mode 100644 index 0000000000000000000000000000000000000000..6f7f4702779110eedebc8a7aea8ac73756205261 GIT binary patch literal 21396 zcmV*hKu*7jP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2igk> z3k4^kfknLl002m7R9JLFZ*6U5ZgcjPf|J{XJjpEaAjv8b}=q6ASiWn zX>MmANlHf`N>D{dAa*t~DJ&plWoBV@Y;+)Tbzy92ba@Ke+t8K(03ZNKL_t(|+U&hq ztYvAI-}PJHw}*4ionp?2jEu~ztjemcs;+KVch}HuTU|}dl0ibk7SLe8VlXxsEIj*sjIko@408#d+jy+*MI#NJUgBp&yHuuv*X$E?09xOJDwfSj%UZSHHo*lpU5BW*HxS4GLHDG5vY#}1evrF~NupT<@?=4F2Sn^vN@~%#>TXMy{?M)-o3SZ@by=(>$A)F z{{zD^GxyrtA51lJaZ*oz^%i$)}()SY5zZBSY}qe{{H)m@WdR~+jD#3Xqlu@Zq@%8jBj@x# zyn1Q-*MI7TE3ZGh%zqym*6Z(n_zyL0_;>CfG=DItQIwU5II-x6eUU<&^Ed&;Wg{9q zl#HPf5kwp!g1WHuV#e}&jJ}VEIJ|d=ruU`4rHtO=$vrGPTj^g9~ z;g8-s_%m&<|3Mc3nc$rohNwlnI7|e!n7xgS`I2`o=Sd1OShlU1xVK~IgX(BtstRTZ zAo+2Ifr7b$AQizB#6(MP3+qLXx?lV5Yd1UKk3YNQPv>wS%c$Pj{iBD6M}Ibih~N@P zU?PJzvg`{*a-}EB{An<>;b$j)jsGz|pFuLJGn}nM@Gcpza}Fm6rWU%uqG|u(-+Jxc zUwd}Re~%j0t^13g>O%ML%@@rCFiFRXVfbVc=Ekr${BG6A1_K+uQdrC1OZtkee3_2l zs|YGQ^aX}9!=bqRdYDI5Y1;1G2Y2rOi44jd^7i4fB7Tn>enu?b!AXd>jwvqy4d&BiQhVgx77^PS&( z?Y(~m_|HBjq$2s86~IKH`XqU(#xq`P^&4Rwj!_$L+A$T#VL~+$LO3y%7N9Ij#HI7) zoQU^M3z1ttQNuDb_r|+-FKSd=QDEXl@>Pxb>4bJ~h=F}8* z4=3(2Vpuwc+GQfYG-hJ`R{!H{&PF${)Joj=6~fIUwLV9VXM-o?Xf1}<%MXPlJ9)> zG@m{*#YBjbko1CbwV+GLd-ga>&og+pWH4q%@cEgY8$A!Qa*0-OEmrb6CxSSLQL&hS zu$<;&hJ(wSx8`t8-O# zdbz%mlMV&WXdhz9Tf6017#|M=Tb`TY#!Vi-VDrLdqV@!B>9rxm-nvFF9L^v7PqnYw zH{QAZCxHLD1)Ji;1PxrA`Z_BsDa@KF;Y4y&jfpKKX~!xhj;&r`};?~Fz?h{HI?2R zhDRkCmN-HDN@)MMkj@&1z0c*k3B@aD@%lW%-zdd-IE!B6nM6f41^ zSlh+=2XEi`Z~o5fAAa!jU%vK#J~hK?yS`A>^Wq%d3UD4ZL!%)MoG%g(s-P%Q1EKF} z+m^oXM~^ii=IbfI@*LjRBZh!9>d?9JH0-N+MQ^WgZDiVaujg-P$stW zC^^B>WpH(9tWXJjPcCKvfALtiud&<_Ry3{cbhsUq?#8VnlPxs1Q$CI6`h6ITh3(n&B+HPZ2jUv*M&a zqM7+0zV*R5RY9E>#DlN!QXr|;%qV~M&aB{Qrx?~*-b{S_SdexRS8u};Oz713D@0ci z0d)c{IRME8STU(gBhq(^Fa3}I+u#0||FJ*(3xED;8CHr|Id9RN91ccerlTRn7}1#M zFvIVULk_1_ORE=ZxH$RoPFC(n8@xjLLFo%B1d+s|P=hG8(g^n;HUp->!3i&2inteo z0nX!GiSrejArxm|mJG^~t5pH}n87fe139fwIvpdDsnH3 zEBQn+(tKhxKW{d+Du1AeQ7A;`mKB@0942IA(ZtP@3~TqGokZgcQH4TMs23>*EF*a+ z1Id>}P|PHG?@zU(CZ`(KkeoX^{VC;mlC^4-)~7a`Q`984=Y(K_1jWpu&f|-!czU5w za=ULeJONHTQ521q!jcHiJBqS==mZT3_i3TffD*SJ`i_N^p?XYbSF#rqoG8w~4?knb z(>zAN%ptIIcYm=Be0cn|4~`bo811Ww1Mib3a)Tdm7!eUg)H1B1IVCvVPn<=K6_Ybh zww+>%2E;R}&C|l67*xrZBbLDAm?~z>gr*C)sAA@*C)25!O+GGr_lXQE#^}v#!`6WN zgo2wb?=tTT#5;6Iz>me#hubsj7s4OAOl!&evAn zs0p(W`B}u_TtUQPY6K0K31~ztg7u&&%!hQDP7hmWCGW8~BTSzDcOk=skAf;5HY}sm zE;ar|i3ZUeAqpX+YuWb!!Kmtb`^WEma1D6tGdC(O*ozTBC>d+D}dNHDN^ax#q&^yXv zN@s>QK}62Ib8GL#r(#%y5~AX;999&iMNrB@h-$=6F)N`G`s#=>I*RBiRPdT`pddo; zz)DYR0Wc*Tn0m-6o*Pi-W5br*fJt$ zj}vGXyC;6Urk&FUBT`A|1ofU?B2kP^Te{d0L&TZGQGpc?RfO(%1$%~P@irgt6 zY{km0r4mD9ynNL1Mc}V}_J(E3 zl54;U?L|&W6dkgXf0(2bXih;K-ov!;ph97WQ>BPX3?AETu8)-XzEQk3^mDYlGK`0Gh%9nN>DAHieW`HpJ*rc7=^UqH5u4Y{a7|A%{@Jh z9caXdKoylK!o(MdE9v?U>mpJl+(wWVi3v`V*BaXi*{IBc_d<*Tk1}<_G{96NlL)Pw zP`QeL5zH``3W8o^%B5BTLP-YZ4V(jWvh-LhCt3z0Fgv3IBWoTcS|n%&dRKaxYmmnZ z=j^15c^1%_-Y`o9KX)=D^ZfPHs@YCS&mSEM6DBuM!fmakX1bj1Jo9~j`Z?D6J@qK) z&)d-U7{Xz4yC#;O1)mo{BXtkWqgAoFVaI&j&J2S&}% znw-)uI`cJG+lVU_xv8P(3g=5c@sv&RaqViAhMbJYJ(L#=TrD~FcooZdkm3a_1orRV z;pX>W=hoZrvh%f`SBo!kzMc?6BoOg+iI;+q@grG@6D}Lps>z>3KFqC)BHGEhgZC~v z9q?aSX=Ca7#ma!}@x=Wk4|rDVsvn4rwsOAmnR3pr0n-D5;>IHCWDoVI*IZ%LEc3~s z_q$pUh4DTJz`SH#k_~wJx9WM6JCoIa6q9}ZW ztI3IXnJ=Put{*(rs^?keVK$Qc(sR3qn6ay0XC2<9^EkA@M#NpS#~Rq9x|~SzMUh@- zh0k`JT6C6C4a{C!y#-f{Xq_%@Psd}$s9x1=ty^;9K%Imf`?4VCh^g9$N*@C%hVw3$ z*Mhl%$>t{KE?;I=PG~M%px&5*PklI-2P8@-G;N!Dk!nneDjCsm$H|Go=Gb>&XXDln zWiMy8Wn>-reRMTAz6V0=5uorcQwVb|sQKAkqF;+oDTQJwFICO_DtoA4SY?r%b}k4{7AfPItm1%W~l2pY#|f8D}*<^CPDRA`XYcsikT!_c|rr z$T`-ho682yKcAJF%c`8gQ_QiR;O*rE-3X?5wQ-=U@IJK^LO^hYpcKwAo6VSAy~@;; zP)+e=K_3&ZD-7Ua43u?^!zIi~ZR|ZtA!!D~9`U};s0zJvQA8gA&+#c$M`w8m5yguj z8WOQFDh`)sFA+>5m=P_t&JrucGWGP+F@Uw4IOh`S29r~%IX^MOGE%5>MFG8GL32p- zh-u~pIz&o(3miowicmO*7LK`72pus-48^+w?+Z%rGp#u!IKUa=T!JIKPafdRib#l2 zrH@vg64neMJU&0+lN}BN4WQs9<*OdS=Mqs=a>F@+$mHpo#Iyg5+-UY#@-#!CJm#5} z914R*icF#L;&A54okqMFMVUw(rb-YYkOnat5--~qLgA{MdnE59mS%xO98wk-(1$>) zffA@rZTd=r5zHinI6KXw$x7CAmUsJf3`=uZ7QFL#h1j+%+745ttSX90Md2KMo+?l8 z&V44qaMUBqT@~YLCGTq9uo5{b7hDICqD8vcgLy0nG#%ZdW3lLHG&0@UX5t+YD7?pc zH_i*jDu*qFt_yTWbDG0BUE3vYdr>f%PT1JqqMX)H_>~c<_4l=of+K3iY33p#3LKqq zGc8BVj(=2JPP#qmO)5@CQlqKTc7eSI_ql)f9x+6A&Y$PP<%^WlNd~-hBud&t2$wwk z#vTT_PW| z^2X=!Wkm=^NlD1G=2DAvB4fl6AkBQw@xM2*yi zL%TUn40&1}%ZVedv@kd}Lce+&v`q_o#B4evgr2UOvw!e_wrTLrF_RfyTQ-WCgLy*; zJ@sS;Wl0DT4SixW7%YzVxPAM5b{{-QiLLiszkY)k?F(#foo70mf_P#d81Rk3t=sA? zXe3US#Zy8-N@4~oNzCZJ88{t!jd_YFkNG=$@_yamK3zS1?R`5W}H#S7GDQngnJ zJf}yf6*zG@RQoZCuty=_D$to?QE5exjTz;I9em%WY4M#c+|~x6D(EzE&!U6ESevTQ1B3Z!Q}ioE`I(M&R>6yzUz=`ikv$~S9(HJ zs0zdvSd5=ZwVH~RPp2q&Vvn^P96Fr>D+o~|ZEvUwuBe&JW>iIibEzfay{D||B-U0| z_^QM!_^QTNH8Dnl84*WWO=!D@McZ<;XqiqY6h(~`9d|BWM2ioySt`g=>4)tW* zJA)?2dxW2M73KtA*2EZi(6*GJg~Bu4InPF2bJ(^#2rcaawBA#c6QU~RXY`(Ig|zlb zandJjLYq8Z{hbhH6Jxry$xAQ2jK;{}-afu8nbs4kdcyP1U+4MjH`v(PL~;1qbNz)E zD9W0?@9Cp*na(y5U(j{|#N*4F zt5>gcbaaGs9w&~=SFUjR@&%3#zRKS2Jw$}A3v6zm$o6BNOPHkELv4mYHP z*PS-ukRpA*-ge;(-~5TLA`%pe0_QxF=>}F+gucbO^eMcQR7HvSlCrGvt{{mOK6w@T z_?WMJD&X*wC+{afArE)*lLkAgESd#XS+Tvn#n$E~zJO9Z^F>QhRfM2SW)oad(s#;Y zF=slRAp&hTr*Avz(y_6*$=22e+gqFL9US3(NmI~_iVb1p+M^2q19aVADw4z205u#Z;Hesg za}?s;$;o?R&iR<^QV5|RS)yZZ>D;neE00-aor3aDM6f<2PFgfV449J@Y4Xhdw}i|~ zREn%cremJ_#GRAnRC=c04oWo6Ir_dECymaUiTrc{(qo_G7AEy&` zmteywrBC6V0`sM|)XMCmJb92fD=f(XtY&>NLq?f`RRvZt8L={#r7)v>JSf0UD8e3o zzp^%b@{|Blk;giv0)5|Op<`B0i2`-$a3%zoD#F3dI*h_QHnz7g73OVAJ)02PhPLae zOV8$Xf{0=kX}gB9EGg@nwpY3UF?7`Rj6zBX&6(#sO9Y+xxt&`!p$C{D={*=v%2j#1 zP!dOBxO6cGbIRjogA&Xrm6T}Rr&5C+0m|BwIgzIdH$3*sdFN6SwGi&!zQf&Hx7gd; zWwDs!onvR`952883eR1=&V1g`H!W@7QI!*#qeIM$x^g&_JGXE1{(J9o=guwm5B9lu z;S!fFU*XD?t6aKrooGVaETC`{?oj}nVW)^DRAr$chf5sGKJndq+Qk+i$WYz+CD>_h zsXA?`0!*~z0SVEpi!V=}z(2xT)>x>I!ASiKkoU*2KqK}YyZ7$$JHP$6dHwa*+1q`9 zg^2f_x~}=kSAUvc_~tLNxw(xmDsJBVfWGg!apMLX8=Fij&wKB_$#;L_uk*dX_d6UN z?o(AI)9D7TsQALGU*tRA`9qw)_#75{RMMWF#|Q_-DR+&@DE*~iPk1*y3HmM&Bmge+ z^;bCNmS^Z)md})gO_(Sq5sCgxuGHzT`FPzwk*7RN@g#@ON_$<~@ZiBNM@NU$MM*iG z;hkeXpY!fJ@9^S_FS7HcZ7y6q$ITBuVE5>d!^1-g2cZ-0-@C`%JGbe(hRc^OqEQJk zaPRg?r)+O*QB^fwjLof0cFvvS&aEk3+tG)P&5doYJ-^A- ztJkROn%D=NFEg_=uDFqHnz^dYWR`avdGg?)T#wnLBzrrv6 zff*OC{D7M`ZxS^!oz!e@Zt?1?ukzxHFEX8Ou$Z@OZC~cWgI%PY(gwpJoWFR3U;L#% z#I>tm;H@{`q-hpRr!$^^;RRm#{O7rJ^%|3U3eM37D5=0Hjt-G7aTLUWBDI&ar0_+Z zKYRa>VM%BcJn6t3B1PtIq801CCJIiwf$IGTCV!i_jX3i zvPUV_*lCyNY(+phe(}clXXC`xP?i23%ds-SPGiEKN{5pIBke475vJ2AAoN`l+wi`i zSQ%yV-sOp!q)p`o%BrA}GJ&D4K)k1q5mm#NRZ`tMrMEXQx%2rhb1Bw89M|XvcF9s> z{cNCfC^CnLC~IM9psNgTVyO>smZG0<2D0-QIM!*olC2qTwx^{i1k34Jes5NVY6=93 zqDZUaVvlOTIioB+O*5w~D~iJ7{Ujsfk*@1dgQ6%X3y<>!76TT0LeLRacj6Gq1E1PM zgu+$GBOQ1aeLp2(GOU+1X6D((C7FpSoW$R>Wh+Tm5~(5OlCz%sk)PsB$iPk!sS{&V zNj}bMPyOGluPXM5u&gICEbm?MxbD$Ahnb`6+T?M35&}tv&{0+;-U%TDLLbv|ryR=a zNtMQ)Vjx(=i%}Gg!WXDTG?MZfbBIeu=u3~oVc~4Wl3eZ8G4v3rFeGR)Xa9@)82|l(nZQJbiDey(3Ub z@fazmxzMXSImgP1XCr&`$(pftEWKM_wkNDg)yXMR-dQ!^%vX?8n$Ty4L0c{uSR+V` zIhHPs=@Zh0K91VVBXM{U2z|h;rK(E~4vu*1tv9%N^F2ZgOs5lW+_=Go3m4hm-od*P zFhcCGK2uv<(l!XOP{y!pl(y!qyjQB`KM4X!=^JTHCj6)s$Qj-n`6aH2?iOUtA!MiIg7?+s?8A zbDlO=BMnkGu%AToKBf%EnGQMWGgazI&Aoef`SoA_pLy@ScMxaH=X1zQ1-|yRpW!>- z`4zUe&QTNv-}~P8STm0~~*XaA65PC!$-~0aexpw^p ze(4YVGGF?sFXIqGh5{Md%|u@SIGg&XG`eHXZQ?>>izhj{Oq zPBz%s*kEgGo6XHFZr!@g4}b6@_V)JK-riwn`#fFOWtEr`5l7c`%#Y^ueJTVtH@BEh zr>MgI{yz8a-DQ7oKT)x~I~B*VwasiMdWwd2(=4o6G^lDeLbu`-9_G}GTW*mZ)Mp0o z<%UhKxqqn|h_NSxj;J9k?-XNGe#yj1Vaf8CnsW~CeJW_mazygYY}^7ed<~CZ^2lSz1Hr-@vbBn9bJXACtm^6b-^JYQrZ zG%V_p9^;n!R3hYcG3%jtkfs#pGjwut{&$kTev)o!k}k+Q6~c<~b67a&3i ziQwm*V`uw3=YD#JuYUDw08~{)h(=JQs48MKOw+|l2)v!z6wY=qX?s0U7^JGo!@_qo z&7lO$sP%B&p>Wpz84^J!a03TI0L+L+8v)VMlcza+(7Eya*m*}!pRVD(Vl5>WXCdLqnKZ`u}n|ssGj8d6cU1W-;daPP0VQ%Ek;Ea<64RMSKPd}oO7^9*=sjCS%XxpTFh_!2Kd42nijF9eOrV6s+&FMPU~Az-We@(;aJ z!;D$i#}hr)jq}q7A0FDjyVu|r{n4N9gNhd!8!>LJZ;wOcDC|z z@6_h%`zY%jfIFCCyU%@8R8~5UuGjMsj7;iC`J#~b^YkQ)(tfa z{MvfoJEp}9=6oTS&u#p#Uw!4upZdy`$<3#RW0^XjKjT(~wr_T9Qc$ zp{LPES!7gMBZVqOBrn6v>)5J_=wsOgJ(Ur7ZBvf^j}PqM{7TuDZ@&HBzZh*IQf!#| zsf6gE@JTB|BNNwAxj-Kx-Z|>Yl-X=bUDtSDfcAXJIlIS#xNgU7?xS~YG6Y>&1?HjZ9 zNM5+S`G5J%D}VeeS0;BqX-n@3aV+tp`j?*Msg}Vpx%UpWh&b5XoB_(w{D3~RT)A?I zy}f<9wxem3dNN^B)y(IM^z^ED2US&4I0Xwptg!+wl@BQ(4--=j8RZr=G5F%As;7Lmmrgg=1 zI;EaYDa#TksX;zJoTo)ks`McwPp&EK_k*H~8E%-mw)M)+VxlCQb7{+%NZt*k#0Vh> zAuRK@!O*}c%L3;lKPIUL)^*9e3&|HaM<0R}+RN1ovp1jLw14F5U)_1|Y4nPp#IQt! z+SYhjr$h0EQP(wPRdDOpN4)vtH`v|1Punf1s*3IHZEn19gLCIDqS~V|QDqj31=HD1 zZUcGLTHbsAJ>Guv4esB+L)$jQ06XU|@ah-8%nL7mp4n_h9~A2q=j3e0Ps&TCA!_*; zAJ~9@_HTUe{rbo6J@~c5=8#!gNm-P{(52yifvT$6+S+C|n_($eVbQiUT}!iQ!62CC zbtZ{6V<;wJTp*xkS>Fc4l5jw@#GNu6qLP+kiJ}9aDu=juY)`iLo~o)S%W`dSC5Avm z5}@lHre?8k>lwKpMzj(hj+@teQ(n|%NKf0u)U zy#$nQ)Mzxm`HgS!jcD>Q!|`-}Sux_S?Mq=9`2NxOnkmPGEa5<&8Jq;M}?MeB~=&qbMp4 z4-a|&{hR#MmmA8`6H#_|_qccO9wA09Uc8iN4lCL&@X<#f^7`wqbK(4DE?>Ednt#Mv z%JJl%Z!}DwX!-}>Fd|LzBGzW-~XKXTifJCtQjT~8>Bk`MxmMZ;n-r)_&o zGDs{gWyrdu6ODyMjKoZ?OY5G7CUCC2hpoezXO`w1b(qsx0Yqh`dQ3m-`;b~(KID0T z67L<|EahtR`JrsoE?&E|{j1;p;`!G;ZQ9fmhC?U-O%`##USUyIY;B+C=;(m1@0k_u-}r-HI{(-B42~xSNOf&5;2B-S&?j8wx#ynaYhU{r zZr%QnTem)>Z5y_>HdBsu<3(=VcnK#SRk(clGTYlbgqU(AGvnO3^Ze}3ex2toUE=ob zTg(@8oOrf&cDV84=XmLJpJz6k(zN|!_c&wJjhB;)7AKdw;=N+GW{<%vOwWn*2 zIG6_(jnef!F{WKV4wtsF##D*vSl6r!q&i_z`pm9MLbqOqCFTQVD{rdRq>w+%A9Y=e zYFv}NG*e=C_Gm4`lD)K1ZFS51ycD`>S^a5fV2)Ghr>STXEtk$}&}J-lvf-0a2yv5|CWF zM2<`X9htb|l5Aw*3ryUoN-I}Ln2Nd9x|&-Ceta_gg>$0bbr;% z{(BLzpO9g70!&2QfMKs}1GSMc>5zxkeiTKCNI_NAc~suUJOC0iG~J1PZkK3YnUdF{ z#1tm#dYZx0VU0>U!AaviC&O-aW!6%tWSo>2L7Wp*>c{=;yG{7zw?5eY^WvN@i^}GU zM(*$K(#IaPI?pPn>6@UM$EOm#rt8z-NLf|st1MF(i*T^FPl$oOYdAdE$3j|Se*5-E zEEWqkx3)QV?mX3WhAT>{dct(NK|QG`%Yw3WIi2Y94Y%wGnt|&2;!<%!j6GeeRHd_s z$l<*CPrm!T_x>vI;ZMY{WZ4)S`%HP0E}Am~=Oi^Z*BAh+LSec>Us-Ap*xIb(${Me6 zmtVSQx-!gZvd&#fOix+%Rsnj2b4Y_Sh=??|g9g&xKGtH<`?=4J!MG4T~;} z@_&L$oq-|g9_5mRvMedeilQtrGY$`q*x%pd=xEO3=!iwLK>I-GJ4|~PM~A%o&fDC- zcb^w-+~CH`FH=u8XqpalE>n)COePhx*#?`Nn+et_OPZ!hi2DkUYq)U3suZlp#4sum zSK6X$ZuF7==r{h}dw=SezILO3>W0-v6*C)gEE%_W)F4aAMxfp8xJ^@4e)T3Zs;R`JBC@hBgS| zJTb3k8%TV~YnJ%JGnq`8OlQm&b9Q(4IN0Ck!QLMG`}-`KhRT(6ZHxCpRTN1z8klWu zvwi*on;V;`IYKmWo~X+1-aZc=+{Zg%GMTcqy~X)+=h@!gW;WZvOlg{SOxoSbHnx-{ zcW5+XNU4Xpio5gh&%Jte>)!(IJ$1thA!68M)rYC-+KP3}3&T|u=N*MFGrd(uU~t)3 zV^B(9$#Ba%WSnFzgQfAv8Z$C4)m&p+TFxUPZjDZI@`eR@%o&uM503tf_vLnPj(OX$ zKksQfP+zAoZE+}TvbQWL%GAFD;qKi#?C$Mx|K5ELj*jR<7#SK~DoPw>;gH-jbiQVL zD;bK3!+D1|&$ONqEiD-kO=Ayj+tS=_*x%dd+`02yzI=(Ttu3mm8W*FlZUYm*6Nn0Z z@4y!#uClqBbjlwA{=!eBDjb*%OP;rlrSNe-kOm%xrQ*8uRuadGC3!zta&U4>BgU9L zOs1Y#o=h6_s-7XPpbL=@6(fP2g-c*)+qTT-b3zETZNsHYm$-1@!pMvmm=gwgF-nQ33ekGh z1jS~=SrfICXvbl?}V!KR8>vWG}QH! zs-B=~bRnXa*1f2L`=QGPJpYG3jI+IZtYPtAS{JQ|THbVg=0~_RC22 zW@@r#u&gk`R2Y@_)>+fKoM5uk2|i~g?YHN@)|-2A(FK|=(wku}X*j5cygx9esg|tq z&~<^mgCp+TyU+gN!SV(g>7$R5^BQcR)v|+^&v4D>Is$eY1>&Z zOI00%q9lW%fy1LYP1|84qpRy0UnJvlkf=Jta&b#oTR;U1{P2T=e;@d#o^JBq2clwD zlvpmMU0x4j7I7%0CBRQCE7f^psUt9iJ~viyt3Lex%2`edNF1$@%*B!2=5sF|UZu@uqC}h!Y`Nz*h;A zTQtf?clNk_f0wp5VmSk!NRFzY!Gl$ZR7l~8@g7A{<{Lo}Dd_;p=^A-N*3t{5wGwd? zeAZso5HndUP)s)vjoi7ni-~ddxyuxlpj}H)Mau0IF+?b|N43SN;04<~)IVls|4d$1 z^@)zh1_@J|ZdF=X{IDXiognIEC!_ZdH?`NmRXHX}Y%3L@92;Y|@$0l5EN6(@o$0h% zwa;tluQttM`Sf`@KYi9T&`^{Uz;SqZ#O{M#4i68BG2jF$?o>L^~w56xK0u zI!=DCit&z`G%IX{RV3Xx$Huh4(a|^il%mY01!ZArjEf{;;GAP`caPh*Zzp19QKbfT z3~Pl=;?yM^u8#1iDSL_(c)M8 zuK(I1Em$YoIuJb6l)fnFA{-nXaPPq(heu7CV)lSWqBfMy@RDRK#e~@R^oy2a>XvKi zWLk2bt_rV^`qGvkYNZ^ZE7HwJemT4Vg+lLo| z*{e^pD#Vm}*@KghkW2xE}&M@wkgy(C)D*6Ri$Zr+AiRI8s><(6~@Shkj(QE%(Q&{%{#vg{O;2+ ztQeh{Yz=>6pU|@mpxr8fw;F1mLMS}-v%h;O`_?Je<5r*a(3`>TB)c0!10!)m_6AIbqm=vC=r z%E6*ZZt)m`BlH~~-n_}}TOTo^``i=)po-JLY5zg*YLaj{mQ@ z;jdzd_uRbsE^q$$M;z?k$4O*w_bxyB-PhRLeLz(f6fWUieV537v)PQYtXVADgtd`8 zrJ1Fsyd)Zr;)rU+o%@GB_tbK%x~?hnK%86ACpbQGK300FXr{^PINlV;Hp6MkCzh7npUmU6&j7h z!}$nyiU=BIq$0OYJ!COwE|grk_}l z?@6jcr)C$|wtAjW$pj&B*NQw2N8T}HQE|?RCcN?K z8CGtW=r~>e2}9FyqZ)zI6L#hqOD4@aSLR`pvNfZ!C9{Eb#TgMPIbqbu%!=Q9?Y*5e zah-A+aXG~0AyDro0zeXo17M`_M-=rrTV-bd7V@ zu5-_1T!=IZd91D$TfwfxIfeoM=dRsAL&MR$p$$r1Z*cvUmw4q1U!tCD5VgsIcNyM@ z5zXYki>xQ+q#o5k4HpfC$ z)@1cY8qF~k;EZFP^i)$!FZF%EtQhC-Ecfa}(tvCzuNl;)*(j?y+mJj09#(-~RC4OTcGuSW(TX zu`?>Cd`hb!A2zZR@Utgf@{O!*v6ofx{w2a)on%<^XqyNx#LNU`3Av|kRGykq4M~Vs z6<;{KOT2W+lR4%rOd(>6Iv}oA~J!MgiQVA}HO4BgpIMv=^bLFYh zW=8VeCoI-Z%B@D_x#J#d8QIR1Llk5!CXO`SwRb#v&hn(H5PzNQOCG|$%dd0bHw`ovx>ifUZ^Sq{S+0)Bk%MB!PLkzB2HoOAuww7UP4l6M4T z!--qb8~yke7D71DxLoFrujNcDjwr59->h_`m+R+c1ThmwYiP~-6sDZvq{5fwi3(qv zrQh9W_M`n${=trlh*4^wb^#Xy&cGElhrI%u_?a->oDmhe#T-{u6eXZWB?WX)noqQ% z-q@BBKi_9!VD21POena^ZGJovk5D4f;iKRzP)LW+_?kumV$0-!)99HC?+OE^XKQPsL+>+TG#f%5`I6 z&-zmHaj8R2Xh+dl%Z4MCdupt0)>{7UAm1}$Btxhz;9-p{5jkpmJ_1KHR#*jsXw2I- zjKX>9dct%zV=|jkRaF*TTjgoUidetov3UWFdE$BC`Y#jq#GDue(LAC{)ZGs=h_YOs zIj9Oc$rK@%e=keLzrq(x>Iqd{Q`TiN!ZmgYD3Ky*rlV?MW43YdwBQCYqy97vYaL>+ zaSO!pUBrXSmenx4x@P3bvb!PlOq%AzB?9yz?m1#s5h`&kWzW?V(FB-I>KgUJWHQ0g zsgyiU-Wft>lj~vPF`}NSbI)MibZ5hS8w1Xzt2Ka%7!$b0cLuE!6T% zCKKwqW@|RV>Ajo}k}Jaeo}wjoYHZQaN8spbHKCnZUS9ACJlAp5{djJ5k_f&%4)Xq( zHZ?FbPNOU*)Y~0a9u{4o@Wr_C-Ed=3Fi46QnZqs;*2>z|JaOHNF|Lyvpc9t^`S`uW z|F^w!kF~6-@A&t(UVEQ&?rUDm3=GTwGQfx^RiPj#*r3%~jr9)`H8qB`Qva}NnkN3& z)})EiG$uC2RMNCHO^w>LL>rBdDlt}3#9=@{MR_O;!#uh7p2yyMt@Zo$kG1wWXYSmQ zd0YmIcO@s2+}GT*_wWApTEE}-_xWax|0MfRRym}`u^tC7kWIsoa7~iyZIXHI#t=H) z0`oI7h_Qqp)-c8)G$D`bCt)Uwz-fi(8^jnR5!L7FQMl$}snsgWD^Ege_J2+737K1@ z(CTaVwuOCNtM(dV7({8A?4%S#Wpi+0AVzQq>6M$w#1n&~Nx^gKeX3Lxoj9Iw4xE&& z2myo$#Suj5a~hQESPIa3{4*wjJNZ}T_)|2=@WhN51DFGB=>Srxm^*#IkqDL`5<;fl zoTFZ$(VDeV%V%4Mbck?OxAW-MVWA1kWKBU(6Zh0=`wBG1FS?S3NVOCr`o1Etsq)s+5uMOLSL)7 zY-ccYKNJLp4-E#x0s8$ulrrEvY6bx`wfIX0VjvNg(&_!@EU=U!CPmM#RR&otxTazI ztDYESG9fKk;fQg%H8hc;^6{kEw`b{rQcJC3lge32AqpYHWP53hLAP|NFq)@~$5|wg zq4Ctda4g!(>IJBFlr3c|g$PX%Mx_9=#F;?Tz9<0|Nsn7K#8Z1t;tA6sCZV6T8l`hE zMghWz!H*RfJSA3~kPjmip?}$h=Y8@VW-KLIsUs6>WjU)XvYMv5-PleX9agwL-jqq6hvh;!jxO=#2O`YO0$oPwH9UJG8r(y`x?e} zP&x}JgW3<#_yD7`eTpy)2_y#Ive5nfT0D_XIj}S-RwPSj+aEk#*G@TJlF+uP*QQtb z9KXt?J2u_<@Z$$>X2ea3id?)zLN_u)V)FMXoJHe33{+A#7=wZ|n&309YVsDeQi%dh z3T06MQbCDeG#cW-{$JtIM}7+S5rhI8H*Cg^3ol0DEPS?H2^^EJGfT=)`Gl&|kpfC7 zSZm>&1vnrChEjr#HE>0VVPyD_(BFy}MyFv{#Uf2T!fS7Q*+t()8fa1|ixS4zv8j`W8k;vMt-)DE5JN-=S@6ga zjrXXk3UyN<_!`kyFo>9+DKS$T%+K{O(<>m7z-~bVK1zbx`S$0e3cAv1n%X&o!s^t% z(F#Rj&?`GA3JYTtMxzEH#8%js9>pBN9LQ=M-7s4|cCG`9L3H%R6IL>}nrGq4D*ToW z^A8ImhZreJ$}~!+7EO#k?Pr`twatCb=8WQ$RbNAA1gkO^mEIa~iEt6a{9wC5j@^X9j}-eBeYDG&c2K zqZbi@)xdRoF8J(PU0icofrU6Y`D103xt&#N^v`vIdrrLR$zV@X%ZvXBh{VyJ?xI+&NyQ^r-TTLsTv%oxL7JTB6Q9H zsWCimL!3gH;rJrr6xQg3T7j%EU7mUo<9M9&TZBwPK4jjN(gtN=Q4|id za|@WA+l0A=^H6l>5MkgtU5G;V3`z$DC4w?<%&oI+jc&Jtvh0GP zF|0iLqXxAXkSd^+OVirI!l9wL%@*~pe4aU5Y1vE$uxD7T5 z5X6LxjQR{4Kyj5cCS%Oez0E39Yb5BF$Gns1E)QxX;Ah1(9UA6Q=;b_mIrRkih!}b%O!mPU~X6e9ueX zci$rizI$YOv8Ow;;!HtCl0%swLZToxfYJuD-4fOi7W)HOB8brlPzlqRN8H&*^g12* zs*m6soVRr&c5L5@P}i94_E1=Z5Imp*if#wCQ-ZWXM{8J0k3Opeh1M{dpp~F-1I0jgypd7$TFd7UnGgF`$jL zU*~eJboDN|$au!EWfqAf#&c@&Mv0+9RoBDQMNnUU;fDL?XNo`R*a)fn*uLe~-s&2UQKjG$W>%+K`DD+_RFFd8glu)K(->Vr7IXa%Q|`&X|} z66!t`I^Ml7>ppes4SW1r--}bHCKJg+zj&$!3q&Oxqsn|LwBVWXCRx2;p~aM^mRnIE z6qHcbfCmsFS&PbQoRJ^j8()3#=kEN@PcJyKH2fG>$#*fS4Fpjb%pTH2M2WD@VXo`Y zc%W_s-V6MANHuXDj3N{Zb8wo$!DI30QLqG%0(zY;7B+5xF1jF7K-mIN1|14;ieR*b z)dX!6tkO^~RC{+?=6uFOy_UD^`5bLo?WjT{3XMFJRO#>ey5Dg@H6wU&^#IeKAVENgj zaK->pV4Xp)*M%*6VA4?9f{aDU3WXt*WdUa_m?Nsu2>sZR@M0ZTI(uCDU*Ddp^(sq?W2$+;UndohSWG;jV+oa z&Bdpn%G5y)9!dfR!}`8W8+&JLp|)*fZ|R8xOMm~fM<2WLndSJpAVDBPgo&38BPlqm zs)BWCxFPlM3fSz1>cpY01~8hyje)ail#7|MWy==K&nHuMV-27UlyM+R?IKM;WMEL$ z@bw78(Fmi_D7jQ94Q(vQn5_R-h>=AkQcu^%wr*bdi`QRs`M*A&_u{ky>zXTeKDPJa zC;q01{E>FZk@6#PY%Fk!@pQ6!)=InLc8>DIde~~;EK}ZDlpJC6Mp>AJV?||Ye!O`@ z_d92M;dXAD`}y7n9{9Uw8+}n#$;HA9rLx6|Qpxa(lggp;5p@{C7>B|oZ)n@G=oyQ; zG9UmQXRt6k18Y^5y-@Oyc4cCa8V7A$LXeBVH>uz`=nqiW_1Ioc*%I1VD3zvgf-pji z0tgvp4qv!Yf8fSzF8{*w-!41N_3a=1dPXu1O@*S*C|E01#;~3qnjc77&EcfMW%&2WW;%cii@l zTmE#-vZToQ|M9(FetL0va5F%?q9_mn@r_SdP~!keZI}>~)53uT zu*QrbY>|NwBbpH5Lqy{lb>mT2bsCm1Ci@anA~Q>p^=PGph^g@&1UazhqPg2{x^nB6 z&&AW@wBZjoU32*l?|JA~|F}H#A7s|hwn)?ywAl-J7=Ta6PAf%y(;uJKR!vh_PQ;x~ zh6-8&lFo-f5 zR+muLrU8oJ;p+y*Xz9&#iKD0Cav!nr58Zm*OWwbG+u3L8=PhFaz`ma!eAD5hi=Sx% zZ7#~5SXU5@<-_U4Q?!SXI)^rfY70lrAFqqJ|blPUD>FttwnPvTfg*;^V^(UycBq%2Nn@f^ zJ~5-W{yQcs-cIT6e%H;r|CWfJIk(D@GrNHF ztsgvcN9E-<(nWS`&xpkFRIdW(V4Du8l~XvY5ob;etd=0C#$YpK%WdK50aiin8&tyx zi5e0$IC@d=WOTK-&~fv#pnB?e*dBUxBO!N;rBD+oizi{4oVk7X*!x%(u6cZ zb>h%&PSY{dXH0P3NnLYaOs5g0lQ9}r3#jqu)bX42abSr`h5?c$oTE&@Zo&dD z9)oHGUkfbtpkUEd6%Yqu^9J>)cl_SfA3RqVc5!()^FR0g;%!Rn>uZm94eGcd2tjEF z(ndgPT%Aou3^X3wpV-6Y5SoIS00b2)KmwRWm?J>|s};JXd0Gj7!fF1>+g^LsKD>bI ztZD*xKXmBdmX}BG9#%E9PQj(xDPFCivaif)fY#&PL01HsrsJn{^VBnV;+Py`YS519 zf00ph(i?#-oSB1S17B6>6!P?Y-#B+Ex${To`T~zeVdiT;eB>np?2ZxdUat79PzKsq zRHD+vVkYdRG6jyKcF}ak7lr`RMMa7|A}0se4Rht4&blu}<{!N2x=SBg3j=@`G_Xcd zwtRozfqR}^?(Y<4an6zwN=_BVK-0XFf^J8_@IbUcJDjy;eGO$Zqy3HTV` zgHHxWks&IkeFr-zbP*dRT9{t*ifz}uV)w!iUg(Q`*S(K#I5KE9Z(f+W>8XQ@e|^;3 zi&Tr-CIz&aOETOI0*L|0r($pdq-}Qf;R`l){)x2y@`1z4Pwm>V@#w2|Z(saP2&gp) zEC2{17k=y84?d)Hcg9nRWBm%G9m;Nr$iuAjMw%E_ImO42XeZ-Yt|=gzaMpKAHhPkb z#BKvkr6YF}5QB`-Lc)xZb{K)+h%r-Y;o%Zpw7K}iAKY~HpW`=ZJ$7JO{qW%@%bh#6 zZ0b6i36Z7UD+Zy8g}5DqV-XoOT(@+>Va2iPFIE?CovE+6Vn@Jl=vtHVIE(E5$~PZ; zU=+3M^ft)QGYv)qSc^PW+Zr;aVFE>zKHgS8+X`s*{%fXOAea**Hrdc7?oe)Zq`{0vzkTM%}QD9IF1t4nO){}o=rVjJOI;8c|i@8lCacZt` zd?L&zBvRR>t*yW(!JjaTE(`^(L81Eb4Oi`Y{VT7$@X-1#eh~x~0Q~IngE#-=(Pusx zKzpi?!2&`Qm=Pl*1V*Hmen(?lIBu~z5Gb*~=9iVJ+K;qt8xaU8c$7ALW9NDE?|H*( zu6}0y_P%gy&4p9Dcb#|FuJb#;?~MFs$7v>JlHf%{V6r|t`L^Ubmr`J*!ODP@L4*Op z0dOF=Y%pmuw?Iw6Y$9L@iI5_ZtWh%CG5@~BEUpLDi!o!h>&ZiY?uq^TKXCZy;)nXf zYMzu9QUoK?G&HHbM{@GYwpDZ4n0(gm&_lrkt@9jg3HHjpj`Yy^m}^Z}Z1* z+_UBI`fYs?2UgxA>3e?s#A^>6Joe9v%l(~E6qGAOn}Ql(qoY+dBDUN(AB+c{>TuH;OM~|5u-=pjD)5lLBy4p?)bB( z4;{Pny>Gq#!1}HHEex!jz0`l-wRd*=mW6AdKJ@GzM-~S=85&Sppfm|-L>5GesFz02 zN<$kBW0Y8>G6`G2(PPs>?^{jNyzknV?RxUU?OWpdZTu|`tmF1yPao0C!{&x34<7x8 zLq`^0KCElRw)`N3UZ;x?0=%yfLxk1{3$wj@wr-yP;sx6_f89B^Z|C-nVg2^42i9|D zGXM+6mPT8TF7uY_jul2RQ n*4O%4U+Zgqt*`a9*6aTO1ioN%hSIFW00000NkvXXu0mjfA$|Km literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/goobay.png b/telldus-gui/TelldusGui/images/vendors/goobay.png new file mode 100644 index 0000000000000000000000000000000000000000..cd1a1c93a7d85dd01af5ccea52cb4fd54804a948 GIT binary patch literal 5059 zcmbuD`6E@EdA^}RD@ErKSao5yP4>s9-dhgQ%fZCGQ*FI1Pgb8xP--^&f%T)3Y~ zX#IKAoAyBKrxAMmQW!Hm6PN=ZaBO^Ok(1?{KUXS%{&#Tw4?7o3J%}JYPbOJ&xi9q#XxX3zcVW!BFzM+lO2 zH*ZO5v+_l%?M3Qg3ky3E8nw z&Q4TTQ`_XER@q-gt=D8oS{xp~7!w?eu5_XD4=N^#TAGa95F00x_sC@O(R=q{Ck(M3 zPH-*y@h8jj3cQqnsrPrenf_)fvmcAYja;l7i_lz;u(z`-5sX_E(cueG6#UC#!WpZk zu(-GwO(rWSb*`0_m5HWw+!aw%Q?t8U`Ri#;PR{i=^Lu-n^Yo`I08D>Kj&LDG@4|Lr z_)Xh@bR!9(X?lB>EM_ef;DhP!CQ;_G^i36_3yM2>+%0D-!-Y!3#H#<2NtgI^nui0` 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 DR!) Date: Thu, 18 Nov 2010 16:22:32 +0000 Subject: [PATCH 1441/2215] Execute, up and down methods added to Telldus Center --- telldus-gui/TelldusGui/device.cpp | 12 ++++++++++ telldus-gui/TelldusGui/device.h | 3 +++ telldus-gui/TelldusGui/devicemodel.cpp | 6 ++++- telldus-gui/TelldusGui/methodwidget.cpp | 32 ++++++++++++++++++++++++- telldus-gui/TelldusGui/telldusgui.qrc | 3 +++ 5 files changed, 54 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index b46bffc4..58d4e568 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -159,6 +159,18 @@ void Device::bell() { triggerEvent( tdBell( d->id ) ); } +void Device::execute() { + triggerEvent( tdExecute( d->id ) ); +} + +void Device::up() { + triggerEvent( tdUp( d->id ) ); +} + +void Device::down() { + triggerEvent( tdDown( d->id ) ); +} + void Device::dim(unsigned char level) { triggerEvent( tdDim( d->id, level ) ); } diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index 2e48bf15..38f370bf 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -44,6 +44,9 @@ public slots: void turnOn(); void bell(); void dim(unsigned char level); + void execute(); + void up(); + void down(); void learn(); signals: diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index a2b50989..ade2ff80 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -13,7 +13,7 @@ inline double round(double x) { } #endif -const int SUPPORTED_METHODS = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM | TELLSTICK_LEARN; +const int SUPPORTED_METHODS = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_UP | TELLSTICK_DOWN; DeviceModel::DeviceModel(QObject *parent) @@ -64,6 +64,10 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const { return tr("on"); case TELLSTICK_TURNOFF: return tr("off"); + case TELLSTICK_UP: + return tr("up"); + case TELLSTICK_DOWN: + return tr("down"); case TELLSTICK_DIM: int value = (int)round(device->lastSentValue().toFloat()/255*100); return tr("%1%").arg(value); diff --git a/telldus-gui/TelldusGui/methodwidget.cpp b/telldus-gui/TelldusGui/methodwidget.cpp index 2001f757..3b0c7186 100644 --- a/telldus-gui/TelldusGui/methodwidget.cpp +++ b/telldus-gui/TelldusGui/methodwidget.cpp @@ -12,7 +12,8 @@ class MethodWidget::PrivateData { public: Device *device; QToolButton *turnOff, *turnOn, *bell, *learn, - *dim25, *dim50, *dim75; + *dim25, *dim50, *dim75, + *execute, *up, *down, *stop; }; MethodWidget::MethodWidget( Device *device, QWidget *parent ) @@ -27,6 +28,10 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) d->turnOn = new QToolButton( this ); d->bell = new QToolButton( this ); d->learn = new QToolButton( this ); + d->execute = new QToolButton( this ); + d->up = new QToolButton( this ); + d->down = new QToolButton( this ); + d->stop = new QToolButton( this ); // this->setAutoFillBackground( true ); QHBoxLayout *layout = new QHBoxLayout(this); @@ -57,6 +62,22 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) d->bell->setIcon( QIcon(":/images/bell.png") ); d->bell->setVisible( false ); layout->addWidget( d->bell ); + + d->execute->setIcon( QIcon(":/images/execute.png") ); + d->execute->setVisible( false ); + layout->addWidget( d->execute ); + + d->up->setIcon( QIcon(":/images/up.png") ); + d->up->setVisible( false ); + layout->addWidget( d->up ); + + d->down->setIcon( QIcon(":/images/down.png") ); + d->down->setVisible( false ); + layout->addWidget( d->down ); + + d->stop->setIcon( QIcon(":/images/state_2.png") ); //TODO + d->stop->setVisible( false ); + layout->addWidget( d->stop ); layout->addStretch(); @@ -72,6 +93,11 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) connect(d->turnOn, SIGNAL(clicked()), device, SLOT(turnOn())); connect(d->bell, SIGNAL(clicked()), device, SLOT(bell())); connect(d->learn, SIGNAL(clicked()), device, SLOT(learn())); + connect(d->execute, SIGNAL(clicked()), device, SLOT(execute())); + connect(d->up, SIGNAL(clicked()), device, SLOT(up())); + connect(d->down, SIGNAL(clicked()), device, SLOT(down())); + connect(d->stop, SIGNAL(clicked()), device, SLOT(turnOff())); + updateMethods(device->methods()); } @@ -88,6 +114,10 @@ void MethodWidget::updateMethods(int newMethods) { d->turnOn->setVisible( newMethods & TELLSTICK_TURNON ); d->bell->setVisible( newMethods & TELLSTICK_BELL ); d->learn->setVisible( newMethods & TELLSTICK_LEARN ); + d->execute->setVisible( newMethods & TELLSTICK_EXECUTE ); + d->up->setVisible( newMethods & TELLSTICK_UP ); + d->down->setVisible( newMethods & TELLSTICK_DOWN ); + d->stop->setVisible( newMethods & TELLSTICK_STOP ); } void MethodWidget::dim() { diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index 3cada74a..418c89b8 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -10,5 +10,8 @@ images/state_dimmed_25.png images/state_dimmed_50.png images/state_dimmed_75.png + images/execute.png + images/up.png + images/down.png From 1244d0b22cf623d8d26666bdf66c78f609934505 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 18 Nov 2010 16:23:40 +0000 Subject: [PATCH 1442/2215] Images for up, down and execute added. --- telldus-gui/TelldusGui/images/down.png | Bin 0 -> 502 bytes telldus-gui/TelldusGui/images/execute.png | Bin 0 -> 1149 bytes telldus-gui/TelldusGui/images/up.png | Bin 0 -> 490 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/down.png create mode 100644 telldus-gui/TelldusGui/images/execute.png create mode 100644 telldus-gui/TelldusGui/images/up.png diff --git a/telldus-gui/TelldusGui/images/down.png b/telldus-gui/TelldusGui/images/down.png new file mode 100644 index 0000000000000000000000000000000000000000..06cfe7e5dd3f8da8036d3f76896c66ebb91863a3 GIT binary patch literal 502 zcmVS92Ptil{2331v@K@8o!KeP+k7?C%=f)d@AE$I`wm1F zvRNjZYGI@eW*Xo=_U(`@s62-{-9811ItjxE;5a#J9M1H*tdO%}VN>wG09XcjWeUKF zCJqIuLxg2eMO!P`o5|Uwry9YE>D(v zv%RZ#S?JO8qi1yL`D06P?c`~_UYDFZ18`ge%|;>WfYb`ym^gpd8d3xk&{-5u0x`7? zw}m(t2hOMll;lU)i#LIoO+(fzfC;5aBlP;3u>!HM19yKppM=XM=nrIw6^P|Mc=*Zr z99*@)V4#z{kSD8;l&Ii;u{wm@tiY5e|lzAB|iwy9DUv3M7xPgHa^q!3Xv s9Y!TBSF-K5!+ePx#24YJ`L;(K){{a7>y{D4^000SaNLh0L00o}_00o}`q<_h)00007bV*G`2igk~ z4GSNXm3)B!00aF=L_t(o!_AjpY!p=##(#HaZG{w?YDiPjA+EewS_m#ube1&Y2vM|& zNO&-n7oH5&NJ5MTTOy$l4KGBEzFa??jR+kPbcSfxT9gF);+pIN8jEe9ZTg3u zxjt~$&Q7T zW4nJAjX>NoYk`-6#sU&+1KxCO_uO=b`ZVCL10Si33z6l(^G4LrQpxnGf>$7JnYRP& zz*C{AZ-CE$Gr;e_5Kso(2RsZs4Lln1`2yJD*zV|z2*fQj0@&(XXXOO2$FW^^2A|9X zT7dNd^=ZIzY&R3O*Yd>pFa+N0*zSffc=fl{WwB$is<5+TyRKuq8-V73x?aWQh6Li4 zxf9qNP&GNWyEmU>xmRYD+@>F>JF%)E))_0$Lu4<|6i{te@$(aiTjpY*H88i&vE6s3 zT53(QP(yoC*CGc?HT~6CXRMa?+)b_g_XSj~3McOh>;y{GxXZEKT{HNJbpcC+)LtkR z`rB*DA8f3#YbucwdrQUXQm-WnCzn9nGId~Ekm-yI$#t18(BgVTe`6u@_t)7mbLm%0 zOQ(ppP2uINz%#%CH9qIq?&k%UR3S8hs6>kAB1GO@6sc%>=*yK$Xh&D^vPEfu!pkAB zE)c6@Hnm;TvHsI3T? z^n?kV3`}mCCHN>p{^P^GM&f=zIf|h%Mciz^bUGs!|x>?Kik`Pw9gBHZwK}VRIfO;dwj~S zIF(GFF``BdP_0x?7*WGZCDY%92~=*ay5f^@63L&xzVvM0)jYl7YoTmEacpb{nJ&!eoH P00000NkvXXu0mjfAD1Er literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/up.png b/telldus-gui/TelldusGui/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..856309c13b89cfb8f9a47ebf1192d20f41853e78 GIT binary patch literal 490 zcmVY5Qd)|fkY83#7ZztKoAu_5EUy6u~4ki z+4%>o#LCJpot0o=V<*^ZBM2f|BsLN(L~Im65;dS0#Ut^(Vw-S5@A4tSF1*LFv&%EP zJ99e+w*BYU2Xjf-)2q{Rct51p;4TB7W3aETXv^ROu)F~e6{vX1fjbTdGR2w>AB2@n zcrq28x9|Vw4$w83vQH`W+2-E-Hl>LwDPS( zc>M`(RFr1nvJHCbg*&6Ldjh53!j0af1-Q~SB*Vg^UV3GfW Date: Thu, 18 Nov 2010 16:24:23 +0000 Subject: [PATCH 1443/2215] Device group functionallity added to Telldus Center. --- telldus-gui/TelldusGui/devicemodel.h | 7 +- telldus-gui/TelldusGui/devicewidget.cpp | 17 ++-- telldus-gui/TelldusGui/editgroupdialog.cpp | 95 +++++++++++++++++++--- telldus-gui/TelldusGui/editgroupdialog.h | 6 +- 4 files changed, 101 insertions(+), 24 deletions(-) diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index 87ae5cca..b7a30e70 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -21,20 +21,21 @@ public: Device *device( const QModelIndex & ); int deviceId( const QModelIndex & ); - + signals: void deviceChange(int deviceId, int, int); void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); void eventTriggered( const QString &name, const QString &title ); private slots: - void deviceStateChanged( int deviceId ); void deviceChanged( int deviceId, int, int ); + void deviceStateChanged( int deviceId ); void nameChanged ( int, const QString& ); + private: - void triggerCellUpdate(int row, int column); int rowForId( int deviceId ) const; + void triggerCellUpdate(int row, int column); // static void deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); static void WINAPI deviceChangeEvent(int deviceId, int, int, int, void *); diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 7bd8a60f..0c4cefbe 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -44,8 +44,8 @@ DeviceWidget::DeviceWidget(QWidget *parent) : addToolButton.setIcon( QIcon( ":/images/list-add.png" ) ); addToolButton.setText( tr("New") ); addToolButton.setToolButtonStyle( Qt::ToolButtonTextBesideIcon ); - //addToolButton.setPopupMode( QToolButton::MenuButtonPopup ); - //addToolButton.setMenu( newMenu ); + addToolButton.setPopupMode( QToolButton::MenuButtonPopup ); + addToolButton.setMenu( newMenu ); connect(&addToolButton, SIGNAL(clicked()), this, SLOT(addDevice())); buttonLayout->addWidget( &addToolButton ); @@ -100,16 +100,17 @@ void DeviceWidget::addDevice() { } void DeviceWidget::addGroup() { - /*Device *device = model.newDevice(); - - EditGroupDialog *dialog = new EditGroupDialog(device, &model); + //Device *device = model.newDevice(); + Device device(0, 0); + + EditGroupDialog *dialog = new EditGroupDialog(&device, &model); if (dialog->exec() == QDialog::Accepted) { - device->save(); + device.save(); } else { - delete device; + //delete device; } - delete dialog;*/ + delete dialog; } void DeviceWidget::deleteDevice() { diff --git a/telldus-gui/TelldusGui/editgroupdialog.cpp b/telldus-gui/TelldusGui/editgroupdialog.cpp index 83387d2a..b41f06f4 100644 --- a/telldus-gui/TelldusGui/editgroupdialog.cpp +++ b/telldus-gui/TelldusGui/editgroupdialog.cpp @@ -13,6 +13,12 @@ #include #include +#include +#include +#include +#include + + class ProxyModel : public QSortFilterProxyModel { public: ProxyModel( QObject * parent = 0 ); @@ -22,21 +28,41 @@ public: void showAllRows(); void hideRow( int row ); void showRow( int row ); + QString getShownIds(); + protected: virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const; private: QSet rows; }; -EditGroupDialog::EditGroupDialog(Device *d, DeviceModel *m, QWidget *parent, Qt::WFlags flags) +class EditGroupDialog::PrivateData { +public: + QLineEdit *nameLineEdit; + +}; + + +EditGroupDialog::EditGroupDialog(Device *devicein, DeviceModel *m, QWidget *parent, Qt::WFlags flags) :QDialog(parent, flags), - device(d), - model(m) + device(devicein), + model(m), + d(new PrivateData) { QVBoxLayout *layout = new QVBoxLayout(this); QHBoxLayout *mainLayout = new QHBoxLayout; + QHBoxLayout *nameLayout = new QHBoxLayout; + QLabel *nameLabel = new QLabel(this); + nameLabel->setText( tr("&Name:") ); + d->nameLineEdit = new QLineEdit(device->name(), this ); + nameLabel->setBuddy(d->nameLineEdit); + nameLayout->addWidget(nameLabel); + nameLayout->addWidget(d->nameLineEdit); + nameLayout->addStretch(); + layout->addLayout(nameLayout); + availableProxyModel = new ProxyModel( this ); availableProxyModel->setSourceModel( model ); availableProxyModel->showAllRows(); @@ -72,6 +98,7 @@ EditGroupDialog::EditGroupDialog(Device *d, DeviceModel *m, QWidget *parent, Qt: addedProxyModel = new ProxyModel( this ); addedProxyModel->setSourceModel( model ); + setDevicesVisible(); addedListView = new QTableView( this ); addedListView->setAlternatingRowColors( true ); @@ -97,9 +124,31 @@ EditGroupDialog::EditGroupDialog(Device *d, DeviceModel *m, QWidget *parent, Qt: EditGroupDialog::~EditGroupDialog() { } +void EditGroupDialog::setDevicesVisible(){ + QString devicesstring = device->parameter("devices", ""); + QList devices; + foreach(QString device, devicesstring.split(",")) { + devices << device.toInt(); + } + + for (int i = 0; i < model->rowCount(); ++i){ + int id = model->deviceId(model->index(i, 0)); + if (id == device->id()) { + //shouldnt be able to add itself, check that here + availableProxyModel->hideRow(i); + } else if (devices.contains(id)) { + availableProxyModel->hideRow(i); + addedProxyModel->showRow(i); + } + } + + +} + void EditGroupDialog::addClicked() { int row = availableProxyModel->mapToSource( availableListView->currentIndex() ).row(); availableProxyModel->hideRow(row); + addedProxyModel->showRow(row); } @@ -111,15 +160,21 @@ void EditGroupDialog::removeClicked() { void EditGroupDialog::okClicked() { -// if (!item || !item->isDevice()) { -// QMessageBox msgBox; -// msgBox.setText( tr("You must choose a device") ); -// msgBox.setInformativeText( tr("Please select the device you have.") ); -// msgBox.setIcon( QMessageBox::Critical ); -// msgBox.setStandardButtons( QMessageBox::Ok ); -// msgBox.exec(); -// return; -// } + if (d->nameLineEdit->text().trimmed() == "") { + QMessageBox msgBox; + msgBox.setText( tr("The device must have a name.") ); + msgBox.setInformativeText( tr("Please fill in a name in the field under 'Name'") ); + msgBox.setIcon( QMessageBox::Critical ); + msgBox.setStandardButtons( QMessageBox::Ok ); + msgBox.exec(); + d->nameLineEdit->setFocus(); + return; + } + device->setName( d->nameLineEdit->text().trimmed() ); + device->setModel("group"); + device->setProtocol("group"); + QString shownIds = addedProxyModel->getShownIds(); + device->setParameter("devices", shownIds); this->accept(); } @@ -145,6 +200,21 @@ void ProxyModel::showAllRows() { } } +QString ProxyModel::getShownIds(){ + QStringList addedIds; + foreach (int index, rows){ //TODO why does this crash when debugging? Unsafe? + if(index >= 0){ //TODO why can this be + DeviceModel *model = reinterpret_cast(this->sourceModel()); + if (model) { + int deviceId = model->deviceId(model->index(index, 0)); + addedIds << QString::number(deviceId); + } + } + } + + return addedIds.join(","); +} + void ProxyModel::hideRow( int row ) { if (rows.contains(row)) { rows.remove(row); @@ -153,6 +223,7 @@ void ProxyModel::hideRow( int row ) { } void ProxyModel::showRow( int row ) { + if (!rows.contains(row)) { rows.insert(row); invalidateFilter(); diff --git a/telldus-gui/TelldusGui/editgroupdialog.h b/telldus-gui/TelldusGui/editgroupdialog.h index 6ad58544..270a9bed 100644 --- a/telldus-gui/TelldusGui/editgroupdialog.h +++ b/telldus-gui/TelldusGui/editgroupdialog.h @@ -16,13 +16,14 @@ class EditGroupDialog : public QDialog public: EditGroupDialog(Device *device, DeviceModel *model, QWidget *parent = 0, Qt::WFlags flags = 0); virtual ~EditGroupDialog(); - + private slots: void availableListActivated(const QModelIndex &); void addedListActivated(const QModelIndex &); void addClicked(); void removeClicked(); void okClicked(); + void setDevicesVisible(); private: QToolButton *addToolButton, *removeToolButton; @@ -30,6 +31,9 @@ private: Device *device; DeviceModel *model; ProxyModel *availableProxyModel, *addedProxyModel; + + class PrivateData; + PrivateData *d; }; #endif // EDITGROUPDIALOG_H From e5ea0d0ce5ab04269156f22f3fe4674293a88edc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 19 Nov 2010 12:41:40 +0000 Subject: [PATCH 1444/2215] Called the function directly instead of emitting our signal by mistake... --- telldus-gui/TelldusGui/devicemodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index ade2ff80..7b0886cf 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -187,7 +187,7 @@ void WINAPI DeviceModel::deviceChangeEvent(int deviceId, int eventId, int change if (!model) { return; } - emit model->deviceChanged(deviceId, eventId, changeType); + emit model->deviceChange(deviceId, eventId, changeType); } /*void DeviceModel::connectDeviceSignals( Device *device ) const { From 5d413b9b993251bf416dcce5797d6aa20dfeee36 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 19 Nov 2010 16:37:55 +0000 Subject: [PATCH 1445/2215] Documentation updated --- docs/telldus-core.dox | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index 80e10ce9..b3f7fb73 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -66,7 +66,7 @@ * in the rest of the program. * * The next two lines of code queries the device for it's name with a call to - * tdGetName() and then displays it to stdout. Finally we must relase the + * tdGetName() and then displays it to stdout. Finally we must release the * resource after we are done with it by calling tdReleaseString() on any * \c char pointer returned by telldus-core. * @@ -165,10 +165,11 @@ * * \subsection sec_bu_device_state Device states * - * Since TellStick only has a transmitter and not a receiver the communation is + * Since controllable devices only have a receiver and not a transmitter the communication is * one-way. This means that telldus-core will never know for sure which * state a reciever has. Instead, the library remembers which command was last - * sent. In this way it "emulates" a two-way communication. + * sent. Either sent from the TellStick itself, or sent from another controller (e.g. a remote control) + * captured by the Tellstick Duo. In this way it "emulates" a two-way communication. * * To query the device state, use the function tdLastSentCommand() * @@ -255,8 +256,6 @@ * * \subsection sec_events_example Example * - * \example events/main.cpp - * * \section sec_other_languages Notes using other languages than C/C++ * * \subsection sec_ol_pyhon Python From bbf0b016cc22472657c1237c3990aa2979c23036 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 22 Nov 2010 09:41:53 +0000 Subject: [PATCH 1446/2215] TELLSTICK_STOP-method added (although untested) --- telldus-gui/TelldusGui/device.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 58d4e568..a0d65349 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -171,6 +171,11 @@ void Device::down() { triggerEvent( tdDown( d->id ) ); } +void Device::stops() { + triggerEvent( tdStop( d->id ) ); +} + + void Device::dim(unsigned char level) { triggerEvent( tdDim( d->id, level ) ); } From 1b42b965a9b9824f2064e57d8148dcf2374c8096 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 22 Nov 2010 09:42:33 +0000 Subject: [PATCH 1447/2215] "Group"-type divided into group and scene. --- telldus-gui/TelldusGui/editgroupdialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-gui/TelldusGui/editgroupdialog.cpp b/telldus-gui/TelldusGui/editgroupdialog.cpp index b41f06f4..582b0b38 100644 --- a/telldus-gui/TelldusGui/editgroupdialog.cpp +++ b/telldus-gui/TelldusGui/editgroupdialog.cpp @@ -171,7 +171,6 @@ void EditGroupDialog::okClicked() { return; } device->setName( d->nameLineEdit->text().trimmed() ); - device->setModel("group"); device->setProtocol("group"); QString shownIds = addedProxyModel->getShownIds(); device->setParameter("devices", shownIds); From 7637e539afff6fbc2a4bfa135518a72919c11f8b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 3 Dec 2010 16:31:26 +0000 Subject: [PATCH 1448/2215] Merged -r1315 from 2.0 into trunk --- .../TelldusGui/data/telldus/devices.xml | 6 +- .../TelldusGui/data/telldus/resources.qrc | 92 +++++++++--------- .../TelldusGui/images/devices/byebye.png | Bin 0 -> 15998 bytes .../TelldusGui/images/vendors/byebyelogo.png | Bin 0 -> 4037 bytes 4 files changed, 52 insertions(+), 46 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/byebye.png create mode 100644 telldus-gui/TelldusGui/images/vendors/byebyelogo.png diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index f6f6a403..fa71510b 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -1,7 +1,11 @@ - + + + + Code Switch + Code Switch diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index f7f64a46..822c60b3 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -1,47 +1,49 @@ - - devices.xml - ../../images/devices/arctech_cs.png - ../../images/devices/arctech_sl.png - ../../images/devices/bell.png - ../../images/devices/conrad-rsl888.png - ../../images/devices/elro.png - ../../images/devices/elro-ab600.png - ../../images/devices/fr004r.png - ../../images/devices/gao_cs.png - ../../images/devices/gao_sl.png - ../../images/devices/goobay.png - ../../images/devices/hq_cs.png - ../../images/devices/koppla.png - ../../images/devices/otio.png - ../../images/devices/projectorscreen.png - ../../images/devices/risingsun_cs.png - ../../images/devices/sartano.png - ../../images/devices/upm_sl.png - ../../images/devices/waveman_cs.png - ../../images/devices/x10.png - ../../images/devices/zke-2603.png - ../../images/vendors/chacon.png - ../../images/vendors/coco.png - ../../images/vendors/conrad.png - ../../images/vendors/elro.png - ../../images/vendors/gao.png - ../../images/vendors/goobay.png - ../../images/vendors/homeeasy.png - ../../images/vendors/hq.png - ../../images/vendors/ikea.png - ../../images/vendors/intertechno.png - ../../images/vendors/kappa.png - ../../images/vendors/kjelloco.png - ../../images/vendors/klikaanklikuit.png - ../../images/vendors/nexa.png - ../../images/vendors/otio.png - ../../images/vendors/proove.png - ../../images/vendors/roxcore.png - ../../images/vendors/rusta.png - ../../images/vendors/sartano.png - ../../images/vendors/upm.png - ../../images/vendors/waveman.png - ../../images/vendors/x10.png - + + devices.xml + ../../images/devices/arctech_cs.png + ../../images/devices/arctech_sl.png + ../../images/devices/bell.png + ../../images/devices/byebye.png + ../../images/devices/conrad-rsl888.png + ../../images/devices/elro.png + ../../images/devices/elro-ab600.png + ../../images/devices/fr004r.png + ../../images/devices/goobay.png + ../../images/devices/gao_cs.png + ../../images/devices/gao_sl.png + ../../images/devices/hq_cs.png + ../../images/devices/koppla.png + ../../images/devices/otio.png + ../../images/devices/projectorscreen.png + ../../images/devices/risingsun_cs.png + ../../images/devices/sartano.png + ../../images/devices/upm_sl.png + ../../images/devices/waveman_cs.png + ../../images/devices/x10.png + ../../images/devices/zke-2603.png + ../../images/vendors/byebyelogo.png + ../../images/vendors/chacon.png + ../../images/vendors/coco.png + ../../images/vendors/conrad.png + ../../images/vendors/elro.png + ../../images/vendors/goobay.png + ../../images/vendors/gao.png + ../../images/vendors/homeeasy.png + ../../images/vendors/hq.png + ../../images/vendors/ikea.png + ../../images/vendors/intertechno.png + ../../images/vendors/kappa.png + ../../images/vendors/kjelloco.png + ../../images/vendors/klikaanklikuit.png + ../../images/vendors/nexa.png + ../../images/vendors/otio.png + ../../images/vendors/proove.png + ../../images/vendors/roxcore.png + ../../images/vendors/rusta.png + ../../images/vendors/sartano.png + ../../images/vendors/upm.png + ../../images/vendors/waveman.png + ../../images/vendors/x10.png + diff --git a/telldus-gui/TelldusGui/images/devices/byebye.png b/telldus-gui/TelldusGui/images/devices/byebye.png new file mode 100644 index 0000000000000000000000000000000000000000..4296a5a12101b0776de78951b5f355d1cf421f9e GIT binary patch literal 15998 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 Gp#K9EF31T0 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/byebyelogo.png b/telldus-gui/TelldusGui/images/vendors/byebyelogo.png new file mode 100644 index 0000000000000000000000000000000000000000..2b09abc115ef7de1fc87aa386e960b0c674812bb GIT binary patch literal 4037 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 Date: Tue, 14 Dec 2010 16:04:18 +0000 Subject: [PATCH 1449/2215] Merged -r1331 from branches/2.0 --- telldus-gui/Plugins/Live/__init__.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 49d62fab..af71360c 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -43,7 +43,7 @@ com.telldus.live = function() { } else if (msg.name() == "turnoff") { com.telldus.core.turnOff( msg.argument(0).intVal() ); } else if (msg.name() == "dim") { - com.telldus.core.dim( msg.argument(0).intVal(), msg.argument(0).intVal() ); + com.telldus.core.dim( msg.argument(0).intVal(), msg.argument(1).intVal() ); } else if (msg.name() == "bell") { com.telldus.core.bell( msg.argument(0).intVal() ); } From 393ee4eb021f7ac70623659f1b00f0d1826c133f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 14 Dec 2010 16:10:16 +0000 Subject: [PATCH 1450/2215] Merged -r1332 from branches/2.0 --- telldus-gui/Plugins/Live/__init__.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index af71360c..d37feb3c 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -3,6 +3,7 @@ __setupPackage__( __extension__ ); com.telldus.live = function() { var socket = null; var menuId = 0; + var separatorId = 0; var isRegistered = false; var supportedMethods = 0; @@ -17,12 +18,11 @@ com.telldus.live = function() { } function notRegistered() { - isRegistered = false; - if (com.telldus.systray) { - com.telldus.systray.addSeparator(); + isRegistered = false; + if (com.telldus.systray && !menuId) { + separatorId = com.telldus.systray.addSeparator(); menuId = com.telldus.systray.addMenuItem( "Activate Telldus Live!" ); com.telldus.systray.menuItem(menuId).triggered.connect(socket.activate); - com.telldus.systray.addSeparator(); } } @@ -53,7 +53,9 @@ com.telldus.live = function() { function registered(msg) { if (menuId > 0) { com.telldus.systray.removeMenuItem(menuId); + com.telldus.systray.removeMenuItem(separatorId); menuId = 0; + separatorId = 0; } supportedMethods = msg.getInt('supportedMethods'); isRegistered = true; From fae8606d23309599962c52cef4ca7d70e1b71173 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 16 Dec 2010 12:51:33 +0000 Subject: [PATCH 1451/2215] Refactored and added new class ScriptEnvironment --- telldus-gui/TelldusCenter/CMakeLists.txt | 2 + .../TelldusCenter/scriptenvironment.cpp | 37 ++++++++++++++++ telldus-gui/TelldusCenter/scriptenvironment.h | 29 ++++++++++++ .../tellduscenterapplication.cpp | 44 +++++++------------ .../TelldusCenter/tellduscenterapplication.h | 5 +-- 5 files changed, 86 insertions(+), 31 deletions(-) create mode 100644 telldus-gui/TelldusCenter/scriptenvironment.cpp create mode 100644 telldus-gui/TelldusCenter/scriptenvironment.h diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 47c8e363..3d706849 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -11,6 +11,7 @@ endif(COMMAND cmake_policy) SET( telldus-center_SRCS main.cpp mainwindow.cpp + scriptenvironment.cpp tellduscenterapplication.cpp AutoUpdater.cpp message.cpp @@ -26,6 +27,7 @@ SET( telldus-center_HDRS SET( telldus-center_MOC_HDRS mainwindow.h + scriptenvironment.h tellduscenterapplication.h message.h ) diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp new file mode 100644 index 00000000..d50f7409 --- /dev/null +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -0,0 +1,37 @@ +#include "scriptenvironment.h" +#include +#include + +#include + +class ScriptEnvironment::PrivateData { +public: + QScriptEngine scriptEngine; +}; + +ScriptEnvironment::ScriptEnvironment(QObject *parent) : + QObject(parent) +{ + d = new PrivateData; + + connect(&d->scriptEngine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(scriptException(const QScriptValue&))); + d->scriptEngine.installTranslatorFunctions(); + +} + +ScriptEnvironment::~ScriptEnvironment() { + delete d; +} + +QScriptEngine *ScriptEnvironment::engine() const { + return &d->scriptEngine; +} + +void ScriptEnvironment::scriptException(const QScriptValue & exception) { + qDebug() << "ScriptException:" << d->scriptEngine.uncaughtExceptionLineNumber() << exception.toString(); + qDebug() << "Backtrace:"; + foreach( QString row, d->scriptEngine.uncaughtExceptionBacktrace() ) { + qDebug() << row; + } + d->scriptEngine.clearExceptions(); +} diff --git a/telldus-gui/TelldusCenter/scriptenvironment.h b/telldus-gui/TelldusCenter/scriptenvironment.h new file mode 100644 index 00000000..a4bdac9a --- /dev/null +++ b/telldus-gui/TelldusCenter/scriptenvironment.h @@ -0,0 +1,29 @@ +#ifndef SCRIPTENVIRONMENT_H +#define SCRIPTENVIRONMENT_H + +#include +#include + +class ScriptEnvironment : public QObject +{ + Q_OBJECT +public: + ScriptEnvironment(QObject *parent = 0); + ~ScriptEnvironment(); + + QScriptEngine *engine() const; + +signals: + +public slots: + +private slots: + void scriptException( const QScriptValue &exception ); + +private: + class PrivateData; + PrivateData *d; + +}; + +#endif // SCRIPTENVIRONMENT_H diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 379ab462..35fceaad 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -3,12 +3,13 @@ #include #include #include -#include #include +#include #include #include "tellduscenterplugin.h" #include "plugintree.h" +#include "scriptenvironment.h" class TelldusCenterPlugin; @@ -19,7 +20,7 @@ class TelldusCenterApplicationPrivate { public: PluginList plugins; MainWindow *mainWindow; - QScriptEngine scriptEngine; + ScriptEnvironment scriptEnvironment; }; TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) @@ -36,11 +37,8 @@ TelldusCenterApplication::~TelldusCenterApplication() { void TelldusCenterApplication::initialize() { d->mainWindow = new MainWindow( ); - + this->setActivationWindow(d->mainWindow, false); - - connect(&d->scriptEngine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(scriptException(const QScriptValue&))); - d->scriptEngine.installTranslatorFunctions(); loadPlugins(); loadScripts(); @@ -57,7 +55,7 @@ PluginList TelldusCenterApplication::plugins() const { } QScriptValue TelldusCenterApplication::mainWindow() { - QScriptValue value = d->scriptEngine.newQObject(d->mainWindow); + QScriptValue value = d->scriptEnvironment.engine()->newQObject(d->mainWindow); return value; } @@ -102,11 +100,11 @@ void TelldusCenterApplication::loadPlugins() { this->setLibraryPaths( QStringList(pluginsDir.absolutePath()) ); - QScriptValue object = d->scriptEngine.newQObject(this); - d->scriptEngine.globalObject().setProperty("application", object); + QScriptValue object = d->scriptEnvironment.engine()->newQObject(this); + d->scriptEnvironment.engine()->globalObject().setProperty("application", object); - QScriptValue mainWindowObject = d->scriptEngine.newQObject(d->mainWindow); - d->scriptEngine.globalObject().property("application").setProperty("mainwindow", mainWindowObject); + QScriptValue mainWindowObject = d->scriptEnvironment.engine()->newQObject(d->mainWindow); + d->scriptEnvironment.engine()->globalObject().property("application").setProperty("mainwindow", mainWindowObject); foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); @@ -132,7 +130,7 @@ void TelldusCenterApplication::loadPlugin(QObject *plugin) { } void TelldusCenterApplication::loadScripts() { - foreach (QString extension, d->scriptEngine.availableExtensions()) { + foreach (QString extension, d->scriptEnvironment.engine()->availableExtensions()) { if (extension.startsWith("...")) { continue; } @@ -151,13 +149,13 @@ void TelldusCenterApplication::loadScripts() { } this->installTranslator(translator); } - - d->scriptEngine.importExtension( extension ); - if (d->scriptEngine.hasUncaughtException()) { - qDebug() << QString("Error in %1:%2:").arg(extension).arg(d->scriptEngine.uncaughtExceptionLineNumber()) - << d->scriptEngine.uncaughtException().toString(); + + d->scriptEnvironment.engine()->importExtension( extension ); + if (d->scriptEnvironment.engine()->hasUncaughtException()) { + qDebug() << QString("Error in %1:%2:").arg(extension).arg(d->scriptEnvironment.engine()->uncaughtExceptionLineNumber()) + << d->scriptEnvironment.engine()->uncaughtException().toString(); } - d->scriptEngine.clearExceptions(); + d->scriptEnvironment.engine()->clearExceptions(); } } @@ -185,16 +183,6 @@ TelldusCenterApplication *TelldusCenterApplication::instance() { return (static_cast(QCoreApplication::instance())); } - -void TelldusCenterApplication::scriptException(const QScriptValue & exception) { - qDebug() << "ScriptException:" << d->scriptEngine.uncaughtExceptionLineNumber() << exception.toString(); - qDebug() << "Backtrace:"; - foreach( QString row, d->scriptEngine.uncaughtExceptionBacktrace() ) { - qDebug() << row; - } - d->scriptEngine.clearExceptions(); -} - void TelldusCenterApplication::msgReceived(const QString & message) { this->showMainWindow(); } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.h b/telldus-gui/TelldusCenter/tellduscenterapplication.h index cfb98ffd..d1df59da 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.h +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.h @@ -18,7 +18,7 @@ class TelldusCenterApplication : public QtSingleApplication public: TelldusCenterApplication(int &argc, char **argv); virtual ~TelldusCenterApplication(); - + void initialize(); #if defined(Q_WS_MAC) @@ -32,7 +32,7 @@ public: void loadToolbar(); static TelldusCenterApplication *instance(); - + signals: void allDoneLoading(); @@ -47,7 +47,6 @@ public slots: void showMainWindow(); private slots: - void scriptException( const QScriptValue &exception ); void msgReceived ( const QString & message ); private: From ead14293d2490ec35dfffc895b359bd55216576f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 16 Dec 2010 13:23:27 +0000 Subject: [PATCH 1452/2215] Added the functions setTimeout(), setInterval(), clearTimeout() and clearInterval() to the global script context --- .../TelldusCenter/scriptenvironment.cpp | 67 +++++++++++++++++++ telldus-gui/TelldusCenter/scriptenvironment.h | 8 +++ 2 files changed, 75 insertions(+) diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index d50f7409..13e69375 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -1,12 +1,16 @@ #include "scriptenvironment.h" #include +#include #include +#include #include class ScriptEnvironment::PrivateData { public: QScriptEngine scriptEngine; + QHash intervalHash; + QHash timeoutHash; }; ScriptEnvironment::ScriptEnvironment(QObject *parent) : @@ -17,6 +21,22 @@ ScriptEnvironment::ScriptEnvironment(QObject *parent) : connect(&d->scriptEngine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(scriptException(const QScriptValue&))); d->scriptEngine.installTranslatorFunctions(); + //Self is our new global object + QScriptValue self = d->scriptEngine.newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeSuperClassContents); + + { + //Copy everything from our old global object + QScriptValueIterator it(d->scriptEngine.globalObject()); + while (it.hasNext()) { + it.next(); + self.setProperty(it.scriptName(), it.value(), it.flags()); + } + } + self.setProperty("self", self); + d->scriptEngine.setGlobalObject(self); + + //Collect garbage (ie our old global object) + d->scriptEngine.collectGarbage(); } ScriptEnvironment::~ScriptEnvironment() { @@ -35,3 +55,50 @@ void ScriptEnvironment::scriptException(const QScriptValue & exception) { } d->scriptEngine.clearExceptions(); } + +void ScriptEnvironment::timerEvent(QTimerEvent *event) { + int id = event->timerId(); + + QScriptValue expression = d->intervalHash.value(id); + if (!expression.isValid()) { + expression = d->timeoutHash.value(id); + if (expression.isValid()) { + //Clear oneshot + this->clearTimeout(id); + } + } + + if (expression.isString()) { + d->scriptEngine.evaluate(expression.toString()); + } else if (expression.isFunction()) { + expression.call(); + } +} + +int ScriptEnvironment::setTimeout(const QScriptValue &expression, int delay) { + if (expression.isString() || expression.isFunction()) { + int timerId = startTimer(delay); + d->timeoutHash.insert(timerId, expression); + return timerId; + } + return -1; +} + +void ScriptEnvironment::clearTimeout(int timerId) { + killTimer(timerId); + d->timeoutHash.remove(timerId); +} + +int ScriptEnvironment::setInterval(const QScriptValue &expression, int delay) { + if (expression.isString() || expression.isFunction()) { + int timerId = startTimer(delay); + d->intervalHash.insert(timerId, expression); + return timerId; + } + return -1; +} + +void ScriptEnvironment::clearInterval(int timerId) { + killTimer(timerId); + d->intervalHash.remove(timerId); +} diff --git a/telldus-gui/TelldusCenter/scriptenvironment.h b/telldus-gui/TelldusCenter/scriptenvironment.h index a4bdac9a..45474e93 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.h +++ b/telldus-gui/TelldusCenter/scriptenvironment.h @@ -16,6 +16,14 @@ public: signals: public slots: + int setInterval(const QScriptValue &expression, int delay); + void clearInterval(int timerId); + + int setTimeout(const QScriptValue &expression, int delay); + void clearTimeout(int timerId); + +protected: + void timerEvent(QTimerEvent *event); private slots: void scriptException( const QScriptValue &exception ); From ceb857919267e77ad2f0c13097de3bf59fd06f00 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 16 Dec 2010 14:36:53 +0000 Subject: [PATCH 1453/2215] Accept negative delays (equals to zero delay, run immediately) --- telldus-gui/TelldusCenter/scriptenvironment.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index 13e69375..093a4ff6 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -77,6 +77,9 @@ void ScriptEnvironment::timerEvent(QTimerEvent *event) { int ScriptEnvironment::setTimeout(const QScriptValue &expression, int delay) { if (expression.isString() || expression.isFunction()) { + if (delay < 0) { + delay = 0; + } int timerId = startTimer(delay); d->timeoutHash.insert(timerId, expression); return timerId; @@ -91,6 +94,9 @@ void ScriptEnvironment::clearTimeout(int timerId) { int ScriptEnvironment::setInterval(const QScriptValue &expression, int delay) { if (expression.isString() || expression.isFunction()) { + if (delay < 0) { + delay = 0; + } int timerId = startTimer(delay); d->intervalHash.insert(timerId, expression); return timerId; From 1c2d4c1c8cd469e65d306033b1452308804daa7b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 Dec 2010 14:38:01 +0000 Subject: [PATCH 1454/2215] First messy not at all finished version of scheduler --- telldus-gui/Plugins/CMakeLists.txt | 9 + telldus-gui/Plugins/Scheduler/CMakeLists.txt | 5 + telldus-gui/Plugins/Scheduler/__init__.js | 597 +++++++++++++++++++ 3 files changed, 611 insertions(+) create mode 100644 telldus-gui/Plugins/Scheduler/CMakeLists.txt create mode 100644 telldus-gui/Plugins/Scheduler/__init__.js diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 815cab88..ca727ddb 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -11,6 +11,7 @@ ENDIF (BUILD_LIBTELLDUS-GUI) SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") +SET(BUILD_PLUGIN_SCHEDULER FALSE CACHE BOOL "Build plugin 'Scheduler'") ADD_SUBDIRECTORY(telldus) @@ -37,3 +38,11 @@ ENDIF(BUILD_PLUGIN_LIVE) IF(BUILD_PLUGIN_XPL) ADD_SUBDIRECTORY(xPL) ENDIF(BUILD_PLUGIN_XPL) + +IF(BUILD_PLUGIN_SCHEDULER) + ADD_SUBDIRECTORY(Scheduler) +ENDIF(BUILD_PLUGIN_SCHEDULER) + +IF(BUILD_PLUGIN_SCHEDULER) + ADD_SUBDIRECTORY(SunCalculator) +ENDIF(BUILD_PLUGIN_SCHEDULER) diff --git a/telldus-gui/Plugins/Scheduler/CMakeLists.txt b/telldus-gui/Plugins/Scheduler/CMakeLists.txt new file mode 100644 index 00000000..db20e396 --- /dev/null +++ b/telldus-gui/Plugins/Scheduler/CMakeLists.txt @@ -0,0 +1,5 @@ +SET( Plugin_NAME "scheduler" ) + +SET( Plugin_PATH "com.telldus.scheduler" ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) \ No newline at end of file diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js new file mode 100644 index 00000000..c16fbaaf --- /dev/null +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -0,0 +1,597 @@ +__setupPackage__( __extension__ ); + +com.telldus.scheduler = function() { + + var JOBTYPE_ABSOLUTE = 0; + + var EVENTTYPE_ABSOLUTE = 0; + var EVENTTYPE_SUNRISE = 1; + var EVENTTYPE_SUNSET = 2; + + //SUNRISE + + var PI = Math.PI; + +var DR = PI/180; +var K1 = 15*DR*1.0027379 + +var Sunrise = false; +var Sunset = false; + +var Rise_time = [0, 0]; +var Set_time = [0, 0]; +var Rise_az = 0.0; +var Set_az = 0.0; + +var Sky = [0.0, 0.0]; +var RAn = [0.0, 0.0, 0.0]; +var Dec = [0.0, 0.0, 0.0]; +var VHz = [0.0, 0.0, 0.0]; + + //1. hämta redan satta jobb + //(kolla om nÃ¥got jobb borde ha körts sedan förra ggn (och att det inte kördes dÃ¥)) + //2. räkna ut när de ska köras nästa ggn, inkludera solens upp/nergÃ¥ng, fuzziness etc + //3. ordna i lista, spara undan första tidsvärdet enkelt Ã¥tkomligt + //4. kör tills tidsvärdet <= timestamp, kolla en ggn/sekund... + + // räkna om varje ggn ngn ändring sker med tider, läggs till/tas bort... + + + //hur ska jobb sparas? + //vilka typer av tider ska finnas? + // absoluta värden - ett enda tillfälle + // fr.o.m viss tidpunkt: + // Ã¥terkommande, viss tid varje dag + // Ã¥terkommande, viss tid vissa veckodagar (ev. var x:e vecka) (samlat i ett jobb, eller samma tid för alla markerade dagar?) + // Ã¥terkommande, viss tid vissa dagar i mÃ¥naden (datum och "siste", eventuellt (är detta nÃ¥gonsin intressant för tellstickstyrning?) första-andra-tredje-fjärde-sista veckodagen i mÃ¥naden) + // Ã¥terkommande, viss tid var x:e dag (hyfsat enkelt att implementera, men är detta intressant för tellstickstyrning?) + // fuzzy pÃ¥ alla, x min före och x min efter (kan klart sättas till noll), vid TelldusCenter-start slumpas ett absolutvärde inom detta intervall fram + // solens upp/nedgÃ¥ng kan väljas som tidpunkt pÃ¥ alla dagar + // viss tid frÃ¥n viss action bestäms frÃ¥n den actionen, om t.ex. en scen ska utföra ngt efter en viss tid sÃ¥ fÃ¥r den göra ett exakt-tid-tillägg (hur det ska fungera vet jag inte, + //men tycker att scener ska kunna innehÃ¥lla tidsfördröjningar mha detta... Men hur Ã¥teruppta scen liksom? Kanske kunde man lÃ¥ta "värde" i en scen vara from vilket steg det ska + //Ã¥terupptas? Varför inte? I framtiden alltsÃ¥. Execute fÃ¥r alltsÃ¥ ett värde (default inget = frÃ¥n start)) + // varje jobbtidpunkt mÃ¥ste alltsÃ¥ lagras som: + // ---------------------------- + // typ - dagintervall (det normala, 1), - viss veckodag (lista med aktiva veckodagar), - viss dag i mÃ¥naden, speciellt värde för "den siste", - speciella tidpunkt(er) + // varje dag/tidpunkt kan ha följande värden (om man gör det per dag): + // fuzzy innan + // fuzzy efter + // använd solens uppgÃ¥ng/nedgÃ¥ng/absolut tidpunkt + // pÃ¥/avdrag frÃ¥n solens upp/nedgÃ¥ng + // startdag + // tid för föregÃ¥ende körning, om nÃ¥gon + // ------------------------------- + // Framtidssäkring: condition för t.ex. väderstation - nej, inga conditions finns ännu... vill man ha det i framtiden? + // typ, när schemat ska exekveras, kolla om ngt är uppfyllt... Nej, det fÃ¥r i sÃ¥ fall ske i en scen (inte scen, nÃ¥got annat mellansteg i TelldusCenter (inte tellduscore)... + // när scenen körs, kolla väderdata, om det är grÃ¥mulet=tänd, annars kör scen som pausar i 30 minuter och tänder dÃ¥... + // Samma sak med villkoret "hemma" och "borta"... Det fÃ¥r vara per scen (mellanstegsscen). Andra events (t.ex. rörelsekontrollevents) vill ju vara villkorade pÃ¥ precis samma sätt, + // alltsÃ¥ kör scenen om villkoret är "borta" eller temperatur < -10... + // Och en mellanstegsscen kan (ska kunna innehÃ¥lla) en "stopscen" som ska köras en viss tid senare (t.ex. lÃ¥ta ljuset vara igÃ¥ng i 2 minuter, sedan släcka), dÃ¥ skapar scenen + // ett nytt schemajobb med argumentet +2 minuter... + // solen gÃ¥r upp/ner +/- visst antal minuter... + // hur kommer net:en + schemaläggare att fungera? Kommer det att finnas en webvariant? + //jobben i listan = deviceid (även grupp/scen sÃ¥klart), action, värde. En enda / jobb, fÃ¥r grupperas med grupper/scener om man vill att mer ska hända pÃ¥ en ggn + + + // gränssnittet... hur...? + // + var joblist = loadJobs(); //reload jobs on every job change + //skicka första tidpunkten (+ id för säkerhetsskull?) till c++ som mÃ¥ste ha hand om timern (verkar det som) + //hur den biten gÃ¥r till, hur ska kommunikationen fram och tillbaka (callback? vänta?) fungera? TrÃ¥den mÃ¥ste kunna + //avbrytas om jobblistan uppdateras eller om programmet stängs av... + var nextRunTime = joblist[0].nextRunTime; + print("Next: " + nextRunTime); + + var runid = 1; //id som kommer tillbaka frÃ¥n c++ (timer)-delen + var runJobFunc = function(){ runJob(joblist[0].id); }; + print("Hm"); + function runJob(runid) { + //should be the first one, but do a check + print("RunJob: " + runid); + var runJob = null; + for(var i=0;i 1)||(e < 0)) + e = (-b - d)/(2*a); + + time = k + e + 1/120; // time of an event + + hr = Math.floor(time); + min = Math.floor((time - hr)*60); + + hz = ha[0] + e*(ha[2] - ha[0]); // azimuth of the sun at the event + nz = -Math.cos(Dec[1])*Math.sin(hz); + dz = c*Math.sin(Dec[1]) - s*Math.cos(Dec[1])*Math.cos(hz); + az = Math.atan2(nz, dz)/DR; + if (az < 0) az = az + 360; + + if ((VHz[0] < 0)&&(VHz[2] > 0)) + { + Rise_time[0] = hr; + Rise_time[1] = min; + Rise_az = az; + Sunrise = true; + } + + if ((VHz[0] > 0)&&(VHz[2] < 0)) + { + Set_time[0] = hr; + Set_time[1] = min; + Set_az = az; + Sunset = true; + } + + return VHz[2]; +} + +// check for no sunrise and/or no sunset +function special_message() +{ + if ((!Sunrise)&&(!Sunset)) // neither sunrise nor sunset + { + if (VHz[2] < 0){ + return "Sun down all day"; + } + else{ + return "Sun up all day"; + } + + return ""; + } + else // sunrise or sunset + { + if (!Sunrise) + return "No sunrise this date"; + else if (!Sunset) + return "No sunset this date"; + } +} + +// sun's position using fundamental arguments +// (Van Flandern & Pulkkinen, 1979) +function sun( jd, ct ) +{ + jd = 4001.4583333333335; + ct = 1.109555099247091; + var g, lo, s, u, v, w; + + lo = 0.779072 + 0.00273790931*jd; + lo = lo - Math.floor(lo); + lo = lo*2*PI; + + g = 0.993126 + 0.0027377785*jd; + g = g - Math.floor(g); + g = g*2*PI; + + v = 0.39785*Math.sin(lo); + v = v - 0.01*Math.sin(lo - g); + v = v + 0.00333*Math.sin(lo + g); + v = v - 0.00021*ct * Math.sin(lo); + + u = 1 - 0.03349*Math.cos(g); + u = u - 0.00014*Math.cos(2*lo); + u = u + 0.00008*Math.cos(lo); + + w = -0.0001 - 0.04129*Math.sin(2*lo); + w = w + 0.03211*Math.sin(g ); + w = w + 0.00104*Math.sin(2*lo - g); + w = w - 0.00035*Math.sin(2*lo + g); + w = w - 0.00008*ct*Math.sin(g); + + s = w/Math.sqrt(u - v*v); // compute sun's right ascension + Sky[0] = lo + Math.atan(s/Math.sqrt(1 - s*s)); + + s = v/Math.sqrt(u); // ...and declination + Sky[1] = Math.atan(s/Math.sqrt(1 - s*s)); +} + +// determine Julian day from calendar date +// (Jean Meeus, "Astronomical Algorithms", Willmann-Bell, 1991) +function julian_day(date) +{ + var a, b, jd; + var gregorian; + + var month = date.getMonth() + 1; + var day = date.getDate(); + var year = date.getFullYear(); + + gregorian = (year < 1583) ? false : true; + + if ((month == 1)||(month == 2)) + { + year = year - 1; + month = month + 12; + } + + a = Math.floor(year/100); + if (gregorian) b = 2 - a + Math.floor(a/4); + else b = 0.0; + + jd = Math.floor(365.25*(year + 4716)) + + Math.floor(30.6001*(month + 1)) + + day + b - 1524.5; + + return jd; +} + +// returns value for sign of argument +function sgn( x ) +{ + var rv; + if (x > 0.0) rv = 1; + else if (x < 0.0) rv = -1; + else rv = 0; + return rv; +} + +// format a positive integer with leading zeroes +function zintstr( num, width ) +{ + var str = num.toString(10); + var len = str.length; + var intgr = ""; + var i; + + for (i = 0; i < width - len; i++) // append leading zeroes + intgr += '0'; + + for (i = 0; i < len; i++) // append digits + intgr += str.charAt(i); + + return intgr; +} + +// format an integer +function cintstr( num, width ) +{ + var str = num.toString(10); + var len = str.length; + var intgr = ""; + var i; + + for (i = 0; i < width - len; i++) // append leading spaces + intgr += ' '; + + for (i = 0; i < len; i++) // append digits + intgr += str.charAt(i); + + return intgr; +} + +// format a real number +function frealstr( num, width, fract ) +{ + var str = num.toFixed(fract); + var len = str.length; + var real = ""; + var i; + + for (i = 0; i < width - len; i++) // append leading spaces + real += ' '; + + for (i = 0; i < len; i++) // append digits + real += str.charAt(i); + + return real; +} + + + +//----------------------------- + + + + return { //Public functions + addTime: addTime, + jobList: loadJobs + } +}(); + +function compareTime(a, b) { + return a.nextRunTime - b.nextRunTime; +} + +__postInit__ = function() { + print("Hello from scheduler"); +} + From 84836a688826698ee02ee4cf379cbc28e1df6796 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 Dec 2010 15:07:02 +0000 Subject: [PATCH 1455/2215] Moved sunrise/sunset functionallity from Scheduler to own plugin --- telldus-gui/Plugins/Scheduler/__init__.js | 398 ++---------------- .../Plugins/SunCalculator/CMakeLists.txt | 5 + telldus-gui/Plugins/SunCalculator/__init__.js | 318 ++++++++++++++ 3 files changed, 348 insertions(+), 373 deletions(-) create mode 100644 telldus-gui/Plugins/SunCalculator/CMakeLists.txt create mode 100644 telldus-gui/Plugins/SunCalculator/__init__.js diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index c16fbaaf..3f0ca5fe 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -1,5 +1,9 @@ __setupPackage__( __extension__ ); +__postInit__ = function() { + application.allDoneLoading.connect( com.telldus.scheduler.init ); +} + com.telldus.scheduler = function() { var JOBTYPE_ABSOLUTE = 0; @@ -7,26 +11,7 @@ com.telldus.scheduler = function() { var EVENTTYPE_ABSOLUTE = 0; var EVENTTYPE_SUNRISE = 1; var EVENTTYPE_SUNSET = 2; - - //SUNRISE - - var PI = Math.PI; - -var DR = PI/180; -var K1 = 15*DR*1.0027379 -var Sunrise = false; -var Sunset = false; - -var Rise_time = [0, 0]; -var Set_time = [0, 0]; -var Rise_az = 0.0; -var Set_az = 0.0; - -var Sky = [0.0, 0.0]; -var RAn = [0.0, 0.0, 0.0]; -var Dec = [0.0, 0.0, 0.0]; -var VHz = [0.0, 0.0, 0.0]; //1. hämta redan satta jobb //(kolla om nÃ¥got jobb borde ha körts sedan förra ggn (och att det inte kördes dÃ¥)) @@ -75,16 +60,23 @@ var VHz = [0.0, 0.0, 0.0]; // gränssnittet... hur...? // - var joblist = loadJobs(); //reload jobs on every job change - //skicka första tidpunkten (+ id för säkerhetsskull?) till c++ som mÃ¥ste ha hand om timern (verkar det som) - //hur den biten gÃ¥r till, hur ska kommunikationen fram och tillbaka (callback? vänta?) fungera? TrÃ¥den mÃ¥ste kunna - //avbrytas om jobblistan uppdateras eller om programmet stängs av... - var nextRunTime = joblist[0].nextRunTime; - print("Next: " + nextRunTime); + function init(){ + var joblist = loadJobs(); //reload jobs on every job change + //skicka första tidpunkten (+ id för säkerhetsskull?) till c++ som mÃ¥ste ha hand om timern (verkar det som) + //hur den biten gÃ¥r till, hur ska kommunikationen fram och tillbaka (callback? vänta?) fungera? TrÃ¥den mÃ¥ste kunna + //avbrytas om jobblistan uppdateras eller om programmet stängs av... + var nextRunTime = joblist[0].nextRunTime; + + var runid = 1; //id som kommer tillbaka frÃ¥n c++ (timer)-delen + var runJobFunc = function(){ runJob(joblist[0].id); }; + var now = new Date().getTime(); + print ("Now:" + new Date(now)); + print("Then:" + new Date(nextRunTime)); + var delay = nextRunTime - now; + print("Delay: " + delay); + setTimeout(runJobFunc, delay); + } - var runid = 1; //id som kommer tillbaka frÃ¥n c++ (timer)-delen - var runJobFunc = function(){ runJob(joblist[0].id); }; - print("Hm"); function runJob(runid) { //should be the first one, but do a check print("RunJob: " + runid); @@ -109,19 +101,6 @@ var VHz = [0.0, 0.0, 0.0]; } } }; - print("Ham"); - var now = new Date().getTime(); - print ("Now:" + new Date(now)); - print("Then:" + new Date(nextRunTime)); - var delay = nextRunTime - now; - if(delay < 0){ - delay = 0; - } - print("Delay: " + delay); - setTimeout(runJobFunc, delay); - - function addTime() { - } function loadJobs(){ print("Loading jobs"); @@ -202,7 +181,8 @@ var VHz = [0.0, 0.0, 0.0]; //date = "Thu Dec 16 2010 12:57:47 GMT+0100 (CET)"; print("Date: " + date); //print(new Date(date)); - var timevalues = riseset(date, long, lat); + print(com.telldus.suncalculator); + var timevalues = com.telldus.suncalculator.riseset(date, long, lat); if(timevalues[2] && timevalues[2] != ""){ return ""; //no sun up or down, do nothing } @@ -255,335 +235,11 @@ var VHz = [0.0, 0.0, 0.0]; this.device = device; this.method = method; this.value = value; - } - - - //MOVE - //---------------- - //------------------- - - //sunrise/sunset calculator by Stephen R. Schmitt -//moved up: -/* -var PI = Math.PI; - -var DR = PI/180; -var K1 = 15*DR*1.0027379 - -var Sunrise = false; -var Sunset = false; - -var Rise_time = [0, 0]; -var Set_time = [0, 0]; -var Rise_az = 0.0; -var Set_az = 0.0; - -var Sky = [0.0, 0.0]; -var RAn = [0.0, 0.0, 0.0]; -var Dec = [0.0, 0.0, 0.0]; -var VHz = [0.0, 0.0, 0.0]; -*/ - -// calculate sunrise and sunset times -function riseset(date, lat, lon ) -{ - var k; - var zone = Math.round(date.getTimezoneOffset()/60); - var jd = julian_day(date) - 2451545; // Julian day relative to Jan 1.5, 2000 - - if ((sgn(zone) == sgn(lon))&&(zone != 0)) - print("WARNING: time zone and longitude are incompatible!"); - - lon = lon/360; - var tz = zone/24; - var ct = jd/36525 + 1; // centuries since 1900.0 - var t0 = lst(lon, jd, tz); // local sidereal time - - jd = jd + tz; // get sun position at start of day - sun(jd, ct); - var ra0 = Sky[0]; - var dec0 = Sky[1]; - - jd = jd + 1; // get sun position at end of day - sun(jd, ct); - var ra1 = Sky[0]; - var dec1 = Sky[1]; - - if (ra1 < ra0) // make continuous - ra1 = ra1 + 2*PI; - - Sunrise = false; // initialize - Sunset = false; - RAn[0] = ra0; - Dec[0] = dec0; - - for (k = 0; k < 24; k++) // check each hour of this day - { - ph = (k + 1)/24; - - RAn[2] = ra0 + (k + 1)*(ra1 - ra0)/24; - Dec[2] = dec0 + (k + 1)*(dec1 - dec0)/24; - VHz[2] = test_hour(k, zone, t0, lat); - - RAn[0] = RAn[2]; // advance to next hour - Dec[0] = Dec[2]; - VHz[0] = VHz[2]; - } - - // display results - var sunrisevalue = zintstr(Rise_time[0], 2) + ":" + zintstr(Rise_time[1], 2); - var sunsetvalue = zintstr( Set_time[0], 2) + ":" + zintstr( Set_time[1], 2); - - var message = special_message(); - - var values = new Array(); - values.push(sunrisevalue); - values.push(sunsetvalue); - values.push(message); - return values; -} - -// Local Sidereal Time for zone -function lst( lon, jd, z ) -{ - var s = 24110.5 + 8640184.812999999*jd/36525 + 86636.6*z + 86400*lon; - s = s/86400; - s = s - Math.floor(s); - return s*360*DR; -} - -// test an hour for an event -function test_hour( k, zone, t0, lat ) -{ - var ha = new Array(3); - var a, b, c, d, e, s, z; - var hr, min, time; - var az, dz, hz, nz; - - ha[0] = t0 - RAn[0] + k*K1; - ha[2] = t0 - RAn[2] + k*K1 + K1; - - ha[1] = (ha[2] + ha[0])/2; // hour angle at half hour - Dec[1] = (Dec[2] + Dec[0])/2 ; // declination at half hour - - s = Math.sin(lat*DR); - c = Math.cos(lat*DR); - z = Math.cos(90.833*DR); // refraction + sun semidiameter at horizon - - if (k <= 0) - VHz[0] = s*Math.sin(Dec[0]) + c*Math.cos(Dec[0])*Math.cos(ha[0]) - z; - - VHz[2] = s*Math.sin(Dec[2]) + c*Math.cos(Dec[2])*Math.cos(ha[2]) - z; - - if (sgn(VHz[0]) == sgn(VHz[2])) - return VHz[2]; // no event this hour - - VHz[1] = s*Math.sin(Dec[1]) + c*Math.cos(Dec[1])*Math.cos(ha[1]) - z; - - a = 2* VHz[0] - 4*VHz[1] + 2*VHz[2]; - b = -3* VHz[0] + 4*VHz[1] - VHz[2]; - d = b*b - 4*a*VHz[0]; - - if (d < 0) - return VHz[2]; // no event this hour - - d = Math.sqrt(d); - e = (-b + d)/(2 * a); - - if ((e > 1)||(e < 0)) - e = (-b - d)/(2*a); - - time = k + e + 1/120; // time of an event - - hr = Math.floor(time); - min = Math.floor((time - hr)*60); - - hz = ha[0] + e*(ha[2] - ha[0]); // azimuth of the sun at the event - nz = -Math.cos(Dec[1])*Math.sin(hz); - dz = c*Math.sin(Dec[1]) - s*Math.cos(Dec[1])*Math.cos(hz); - az = Math.atan2(nz, dz)/DR; - if (az < 0) az = az + 360; - - if ((VHz[0] < 0)&&(VHz[2] > 0)) - { - Rise_time[0] = hr; - Rise_time[1] = min; - Rise_az = az; - Sunrise = true; - } - - if ((VHz[0] > 0)&&(VHz[2] < 0)) - { - Set_time[0] = hr; - Set_time[1] = min; - Set_az = az; - Sunset = true; - } - - return VHz[2]; -} - -// check for no sunrise and/or no sunset -function special_message() -{ - if ((!Sunrise)&&(!Sunset)) // neither sunrise nor sunset - { - if (VHz[2] < 0){ - return "Sun down all day"; - } - else{ - return "Sun up all day"; - } - - return ""; - } - else // sunrise or sunset - { - if (!Sunrise) - return "No sunrise this date"; - else if (!Sunset) - return "No sunset this date"; - } -} - -// sun's position using fundamental arguments -// (Van Flandern & Pulkkinen, 1979) -function sun( jd, ct ) -{ - jd = 4001.4583333333335; - ct = 1.109555099247091; - var g, lo, s, u, v, w; - - lo = 0.779072 + 0.00273790931*jd; - lo = lo - Math.floor(lo); - lo = lo*2*PI; - - g = 0.993126 + 0.0027377785*jd; - g = g - Math.floor(g); - g = g*2*PI; - - v = 0.39785*Math.sin(lo); - v = v - 0.01*Math.sin(lo - g); - v = v + 0.00333*Math.sin(lo + g); - v = v - 0.00021*ct * Math.sin(lo); - - u = 1 - 0.03349*Math.cos(g); - u = u - 0.00014*Math.cos(2*lo); - u = u + 0.00008*Math.cos(lo); - - w = -0.0001 - 0.04129*Math.sin(2*lo); - w = w + 0.03211*Math.sin(g ); - w = w + 0.00104*Math.sin(2*lo - g); - w = w - 0.00035*Math.sin(2*lo + g); - w = w - 0.00008*ct*Math.sin(g); - - s = w/Math.sqrt(u - v*v); // compute sun's right ascension - Sky[0] = lo + Math.atan(s/Math.sqrt(1 - s*s)); - - s = v/Math.sqrt(u); // ...and declination - Sky[1] = Math.atan(s/Math.sqrt(1 - s*s)); -} - -// determine Julian day from calendar date -// (Jean Meeus, "Astronomical Algorithms", Willmann-Bell, 1991) -function julian_day(date) -{ - var a, b, jd; - var gregorian; - - var month = date.getMonth() + 1; - var day = date.getDate(); - var year = date.getFullYear(); - - gregorian = (year < 1583) ? false : true; - - if ((month == 1)||(month == 2)) - { - year = year - 1; - month = month + 12; - } - - a = Math.floor(year/100); - if (gregorian) b = 2 - a + Math.floor(a/4); - else b = 0.0; - - jd = Math.floor(365.25*(year + 4716)) - + Math.floor(30.6001*(month + 1)) - + day + b - 1524.5; - - return jd; -} - -// returns value for sign of argument -function sgn( x ) -{ - var rv; - if (x > 0.0) rv = 1; - else if (x < 0.0) rv = -1; - else rv = 0; - return rv; -} - -// format a positive integer with leading zeroes -function zintstr( num, width ) -{ - var str = num.toString(10); - var len = str.length; - var intgr = ""; - var i; - - for (i = 0; i < width - len; i++) // append leading zeroes - intgr += '0'; - - for (i = 0; i < len; i++) // append digits - intgr += str.charAt(i); - - return intgr; -} - -// format an integer -function cintstr( num, width ) -{ - var str = num.toString(10); - var len = str.length; - var intgr = ""; - var i; - - for (i = 0; i < width - len; i++) // append leading spaces - intgr += ' '; - - for (i = 0; i < len; i++) // append digits - intgr += str.charAt(i); - - return intgr; -} - -// format a real number -function frealstr( num, width, fract ) -{ - var str = num.toFixed(fract); - var len = str.length; - var real = ""; - var i; - - for (i = 0; i < width - len; i++) // append leading spaces - real += ' '; - - for (i = 0; i < len; i++) // append digits - real += str.charAt(i); - - return real; -} - - - -//----------------------------- - - + } return { //Public functions - addTime: addTime, - jobList: loadJobs + jobList: loadJobs, + init:init } }(); @@ -591,7 +247,3 @@ function compareTime(a, b) { return a.nextRunTime - b.nextRunTime; } -__postInit__ = function() { - print("Hello from scheduler"); -} - diff --git a/telldus-gui/Plugins/SunCalculator/CMakeLists.txt b/telldus-gui/Plugins/SunCalculator/CMakeLists.txt new file mode 100644 index 00000000..0528086f --- /dev/null +++ b/telldus-gui/Plugins/SunCalculator/CMakeLists.txt @@ -0,0 +1,5 @@ +SET( Plugin_NAME "suncalculator" ) + +SET( Plugin_PATH "com.telldus.suncalculator" ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SunCalculator/__init__.js b/telldus-gui/Plugins/SunCalculator/__init__.js new file mode 100644 index 00000000..630268d1 --- /dev/null +++ b/telldus-gui/Plugins/SunCalculator/__init__.js @@ -0,0 +1,318 @@ +__setupPackage__( __extension__ ); + +com.telldus.suncalculator = function() { + + //sunrise/sunset calculator, derived from the work of Stephen R. Schmitt + var PI = Math.PI; + + var DR = PI/180; + var K1 = 15*DR*1.0027379 + + var Sunrise = false; + var Sunset = false; + + var Rise_time = [0, 0]; + var Set_time = [0, 0]; + var Rise_az = 0.0; + var Set_az = 0.0; + + var Sky = [0.0, 0.0]; + var RAn = [0.0, 0.0, 0.0]; + var Dec = [0.0, 0.0, 0.0]; + var VHz = [0.0, 0.0, 0.0]; + + // calculate sunrise and sunset times + function riseset(date, lat, lon ) + { + var k; + var zone = Math.round(date.getTimezoneOffset()/60); + var jd = julian_day(date) - 2451545; // Julian day relative to Jan 1.5, 2000 + + if ((sgn(zone) == sgn(lon))&&(zone != 0)) + print("WARNING: time zone and longitude are incompatible!"); + + lon = lon/360; + var tz = zone/24; + var ct = jd/36525 + 1; // centuries since 1900.0 + var t0 = lst(lon, jd, tz); // local sidereal time + + jd = jd + tz; // get sun position at start of day + sun(jd, ct); + var ra0 = Sky[0]; + var dec0 = Sky[1]; + + jd = jd + 1; // get sun position at end of day + sun(jd, ct); + var ra1 = Sky[0]; + var dec1 = Sky[1]; + + if (ra1 < ra0) // make continuous + ra1 = ra1 + 2*PI; + + Sunrise = false; // initialize + Sunset = false; + RAn[0] = ra0; + Dec[0] = dec0; + + for (k = 0; k < 24; k++) // check each hour of this day + { + ph = (k + 1)/24; + + RAn[2] = ra0 + (k + 1)*(ra1 - ra0)/24; + Dec[2] = dec0 + (k + 1)*(dec1 - dec0)/24; + VHz[2] = test_hour(k, zone, t0, lat); + + RAn[0] = RAn[2]; // advance to next hour + Dec[0] = Dec[2]; + VHz[0] = VHz[2]; + } + + // display results + var sunrisevalue = zintstr(Rise_time[0], 2) + ":" + zintstr(Rise_time[1], 2); + var sunsetvalue = zintstr( Set_time[0], 2) + ":" + zintstr( Set_time[1], 2); + + var message = special_message(); + + var values = new Array(); + values.push(sunrisevalue); + values.push(sunsetvalue); + values.push(message); + return values; + } + + // Local Sidereal Time for zone + function lst( lon, jd, z ) + { + var s = 24110.5 + 8640184.812999999*jd/36525 + 86636.6*z + 86400*lon; + s = s/86400; + s = s - Math.floor(s); + return s*360*DR; + } + + // test an hour for an event + function test_hour( k, zone, t0, lat ) + { + var ha = new Array(3); + var a, b, c, d, e, s, z; + var hr, min, time; + var az, dz, hz, nz; + + ha[0] = t0 - RAn[0] + k*K1; + ha[2] = t0 - RAn[2] + k*K1 + K1; + + ha[1] = (ha[2] + ha[0])/2; // hour angle at half hour + Dec[1] = (Dec[2] + Dec[0])/2 ; // declination at half hour + + s = Math.sin(lat*DR); + c = Math.cos(lat*DR); + z = Math.cos(90.833*DR); // refraction + sun semidiameter at horizon + + if (k <= 0) + VHz[0] = s*Math.sin(Dec[0]) + c*Math.cos(Dec[0])*Math.cos(ha[0]) - z; + + VHz[2] = s*Math.sin(Dec[2]) + c*Math.cos(Dec[2])*Math.cos(ha[2]) - z; + + if (sgn(VHz[0]) == sgn(VHz[2])) + return VHz[2]; // no event this hour + + VHz[1] = s*Math.sin(Dec[1]) + c*Math.cos(Dec[1])*Math.cos(ha[1]) - z; + + a = 2* VHz[0] - 4*VHz[1] + 2*VHz[2]; + b = -3* VHz[0] + 4*VHz[1] - VHz[2]; + d = b*b - 4*a*VHz[0]; + + if (d < 0) + return VHz[2]; // no event this hour + + d = Math.sqrt(d); + e = (-b + d)/(2 * a); + + if ((e > 1)||(e < 0)) + e = (-b - d)/(2*a); + + time = k + e + 1/120; // time of an event + + hr = Math.floor(time); + min = Math.floor((time - hr)*60); + + hz = ha[0] + e*(ha[2] - ha[0]); // azimuth of the sun at the event + nz = -Math.cos(Dec[1])*Math.sin(hz); + dz = c*Math.sin(Dec[1]) - s*Math.cos(Dec[1])*Math.cos(hz); + az = Math.atan2(nz, dz)/DR; + if (az < 0) az = az + 360; + + if ((VHz[0] < 0)&&(VHz[2] > 0)) + { + Rise_time[0] = hr; + Rise_time[1] = min; + Rise_az = az; + Sunrise = true; + } + + if ((VHz[0] > 0)&&(VHz[2] < 0)) + { + Set_time[0] = hr; + Set_time[1] = min; + Set_az = az; + Sunset = true; + } + + return VHz[2]; + } + + // check for no sunrise and/or no sunset + function special_message() + { + if ((!Sunrise)&&(!Sunset)) // neither sunrise nor sunset + { + if (VHz[2] < 0){ + return "Sun down all day"; + } + else{ + return "Sun up all day"; + } + + return ""; + } + else // sunrise or sunset + { + if (!Sunrise) + return "No sunrise this date"; + else if (!Sunset) + return "No sunset this date"; + } + } + + // sun's position using fundamental arguments + // (Van Flandern & Pulkkinen, 1979) + function sun( jd, ct ) + { + jd = 4001.4583333333335; + ct = 1.109555099247091; + var g, lo, s, u, v, w; + + lo = 0.779072 + 0.00273790931*jd; + lo = lo - Math.floor(lo); + lo = lo*2*PI; + + g = 0.993126 + 0.0027377785*jd; + g = g - Math.floor(g); + g = g*2*PI; + + v = 0.39785*Math.sin(lo); + v = v - 0.01*Math.sin(lo - g); + v = v + 0.00333*Math.sin(lo + g); + v = v - 0.00021*ct * Math.sin(lo); + + u = 1 - 0.03349*Math.cos(g); + u = u - 0.00014*Math.cos(2*lo); + u = u + 0.00008*Math.cos(lo); + + w = -0.0001 - 0.04129*Math.sin(2*lo); + w = w + 0.03211*Math.sin(g ); + w = w + 0.00104*Math.sin(2*lo - g); + w = w - 0.00035*Math.sin(2*lo + g); + w = w - 0.00008*ct*Math.sin(g); + + s = w/Math.sqrt(u - v*v); // compute sun's right ascension + Sky[0] = lo + Math.atan(s/Math.sqrt(1 - s*s)); + + s = v/Math.sqrt(u); // ...and declination + Sky[1] = Math.atan(s/Math.sqrt(1 - s*s)); + } + + // determine Julian day from calendar date + // (Jean Meeus, "Astronomical Algorithms", Willmann-Bell, 1991) + function julian_day(date) + { + var a, b, jd; + var gregorian; + + var month = date.getMonth() + 1; + var day = date.getDate(); + var year = date.getFullYear(); + + gregorian = (year < 1583) ? false : true; + + if ((month == 1)||(month == 2)) + { + year = year - 1; + month = month + 12; + } + + a = Math.floor(year/100); + if (gregorian) b = 2 - a + Math.floor(a/4); + else b = 0.0; + + jd = Math.floor(365.25*(year + 4716)) + + Math.floor(30.6001*(month + 1)) + + day + b - 1524.5; + + return jd; + } + + // returns value for sign of argument + function sgn( x ) + { + var rv; + if (x > 0.0) rv = 1; + else if (x < 0.0) rv = -1; + else rv = 0; + return rv; + } + + // format a positive integer with leading zeroes + function zintstr( num, width ) + { + var str = num.toString(10); + var len = str.length; + var intgr = ""; + var i; + + for (i = 0; i < width - len; i++) // append leading zeroes + intgr += '0'; + + for (i = 0; i < len; i++) // append digits + intgr += str.charAt(i); + + return intgr; + } + + // format an integer + function cintstr( num, width ) + { + var str = num.toString(10); + var len = str.length; + var intgr = ""; + var i; + + for (i = 0; i < width - len; i++) // append leading spaces + intgr += ' '; + + for (i = 0; i < len; i++) // append digits + intgr += str.charAt(i); + + return intgr; + } + + // format a real number + function frealstr( num, width, fract ) + { + var str = num.toFixed(fract); + var len = str.length; + var real = ""; + var i; + + for (i = 0; i < width - len; i++) // append leading spaces + real += ' '; + + for (i = 0; i < len; i++) // append digits + real += str.charAt(i); + + return real; + } + + return { //Public functions + riseset: riseset + } +}(); \ No newline at end of file From a2cdb31aa935ea31212810ea8b1933bdca7783e6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 16 Dec 2010 16:36:26 +0000 Subject: [PATCH 1456/2215] Added variable 'Plugin_EXTRA' to plugins --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 659a2fec..92a2db86 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -46,7 +46,10 @@ IF(Plugin_PATH) "${CMAKE_CURRENT_SOURCE_DIR}/__init__.js" ) LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/__init__.js") - + #Add all extra files + FOREACH(_FILE ${Plugin_EXTRA}) + LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}") + ENDFOREACH(_FILE) ENDIF(Plugin_PATH) IF (UPDATE_TRANSLATIONS) From 441d30dbf2ba91512f5972564de4a16abc875a7e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Dec 2010 08:27:46 +0000 Subject: [PATCH 1457/2215] Added plugin QML --- telldus-gui/Plugins/CMakeLists.txt | 4 ++ telldus-gui/Plugins/QML/CMakeLists.txt | 16 ++++++++ telldus-gui/Plugins/QML/__init__.js | 5 +++ telldus-gui/Plugins/QML/qmlplugin.cpp | 51 ++++++++++++++++++++++++++ telldus-gui/Plugins/QML/qmlplugin.h | 19 ++++++++++ 5 files changed, 95 insertions(+) create mode 100644 telldus-gui/Plugins/QML/CMakeLists.txt create mode 100644 telldus-gui/Plugins/QML/__init__.js create mode 100644 telldus-gui/Plugins/QML/qmlplugin.cpp create mode 100644 telldus-gui/Plugins/QML/qmlplugin.h diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index ca727ddb..2ebbaad8 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -46,3 +46,7 @@ ENDIF(BUILD_PLUGIN_SCHEDULER) IF(BUILD_PLUGIN_SCHEDULER) ADD_SUBDIRECTORY(SunCalculator) ENDIF(BUILD_PLUGIN_SCHEDULER) + +IF(BUILD_PLUGIN_SCHEDULER) + ADD_SUBDIRECTORY(QML) +ENDIF(BUILD_PLUGIN_SCHEDULER) diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt new file mode 100644 index 00000000..9ed959af --- /dev/null +++ b/telldus-gui/Plugins/QML/CMakeLists.txt @@ -0,0 +1,16 @@ +SET(QT_USE_QTDECLARATIVE TRUE) + +SET( Plugin_NAME "QMLLoader" ) + + +SET( Plugin_SRCS + qmlplugin.cpp +) + +SET( Plugin_HDRS + qmlplugin.h +) + +SET( Plugin_PATH "com.telldus.qml" ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/QML/__init__.js b/telldus-gui/Plugins/QML/__init__.js new file mode 100644 index 00000000..c368546c --- /dev/null +++ b/telldus-gui/Plugins/QML/__init__.js @@ -0,0 +1,5 @@ + +__setupPackage__( __extension__ ); + +__postInit__ = function() { +} diff --git a/telldus-gui/Plugins/QML/qmlplugin.cpp b/telldus-gui/Plugins/QML/qmlplugin.cpp new file mode 100644 index 00000000..714f0d84 --- /dev/null +++ b/telldus-gui/Plugins/QML/qmlplugin.cpp @@ -0,0 +1,51 @@ +#include "qmlplugin.h" +#include +#include +#include +#include +#include + +#include + +QMLPlugin::QMLPlugin ( QObject * parent ) + :QScriptExtensionPlugin( parent ) +{ +} + +QMLPlugin::~QMLPlugin() { +} + +QScriptValue QMLLoadFunction(QScriptContext *context, QScriptEngine *engine) +{ + qDebug() << "Tried to load qml-file"; + if (context->argumentCount() < 1) { + return context->throwError("QML constructor takes one parameters"); + } + + QString filename = context->argument(0).toString(); + + //Find out the filename so we have a relative directory to load from + QScriptContextInfo info(context->parentContext()); + QFileInfo fileinfo(info.fileName()); + QDir dir = fileinfo.dir(); + qDebug() << dir.filePath(filename); + + QDeclarativeView *view = new QDeclarativeView(); + view->setSource(dir.filePath(filename)); + QScriptValue value = engine->newQObject(view, QScriptEngine::ScriptOwnership); + return value; +} + +void QMLPlugin::initialize ( const QString & key, QScriptEngine * engine ) { + if (key == "com.telldus.qml") { + qDebug() << "Hello from QML"; + + engine->globalObject().property("com").property("telldus").property("qml").setProperty("load", engine->newFunction(QMLLoadFunction)); + } +} + +QStringList QMLPlugin::keys () const { + return QStringList() << "com.telldus.qml"; +} + +Q_EXPORT_PLUGIN2(QMLInterface, QMLPlugin) diff --git a/telldus-gui/Plugins/QML/qmlplugin.h b/telldus-gui/Plugins/QML/qmlplugin.h new file mode 100644 index 00000000..2ee2c6d3 --- /dev/null +++ b/telldus-gui/Plugins/QML/qmlplugin.h @@ -0,0 +1,19 @@ +#ifndef QMLPLUGIN_H +#define QMLPLUGIN_H + +#include + +class QMLPlugin : public QScriptExtensionPlugin { +public: + QMLPlugin ( QObject * parent = 0 ); + ~QMLPlugin (); + + virtual void initialize ( const QString & key, QScriptEngine * engine ); + virtual QStringList keys () const; + +private: + +}; + + +#endif // SYSTRAYPLUGIN_H From e71ef601c3f75a4b6cfd0519bded519f6d904f89 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 17 Dec 2010 09:10:46 +0000 Subject: [PATCH 1458/2215] Fuzziness routines updated --- telldus-gui/Plugins/Scheduler/__init__.js | 32 ++++++++++++++--------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 3f0ca5fe..e6de8d67 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -11,6 +11,7 @@ com.telldus.scheduler = function() { var EVENTTYPE_ABSOLUTE = 0; var EVENTTYPE_SUNRISE = 1; var EVENTTYPE_SUNSET = 2; + var EVENTTYPE_RELOAD = 3; //1. hämta redan satta jobb @@ -57,6 +58,9 @@ com.telldus.scheduler = function() { // hur kommer net:en + schemaläggare att fungera? Kommer det att finnas en webvariant? //jobben i listan = deviceid (även grupp/scen sÃ¥klart), action, värde. En enda / jobb, fÃ¥r grupperas med grupper/scener om man vill att mer ska hända pÃ¥ en ggn + //TODO obs, om nÃ¥got jobb existerar, lägg till 1 nytt jobb som körs vid nästa sommartid/vintertid och bara laddar om befintliga jobb... Listan mÃ¥ste ju göras om dÃ¥. (EVENTTYPE_RELOAD) + //TODO fem-minuter-bakÃ¥t-grejen + //"repeat", t.ex. om villkor inte uppfylls sÃ¥ vill man göra ett nytt försök, även det fÃ¥r vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... // gränssnittet... hur...? // @@ -120,12 +124,8 @@ com.telldus.scheduler = function() { var currentEventRuntimeTimestamp = 0; if(events[i].type == EVENTTYPE_ABSOLUTE){ - //var fuzzinessinterval = events[i].fuzzinessBefore + events[i].fuzzinessAfter; currentEventRuntimeTimestamp = events[i].time; - if(events[i].fuzzinessAfter != 0 || events[i].fuzzinessBefore != 0){ - var fuzziness = Math.floor((events[i].fuzzinessAfter - events[i].fuzzinessBefore)*Math.random()) + events[i].fuzzinessBefore + 1; //TODO check when result is a negative value - currentEventRuntimeTimestamp += (fuzziness * 1000); - } + currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, events[i].fuzzinessBefore, events[i].fuzzinessAfter); } else if(events[i].type == EVENTTYPE_SUNRISE || events[i].type == EVENTTYPE_SUNSET){ @@ -134,10 +134,8 @@ com.telldus.scheduler = function() { currentEventRuntimeTimestamp += (events[i].offset * 1000); print("Timestampet: " + currentEventRuntimeTimestamp); - if(events[i].fuzzinessAfter != 0 || events[i].fuzzinessBefore != 0){ - var fuzziness = Math.floor((events[i].fuzzinessAfter - events[i].fuzzinessBefore)*Math.random()) + events[i].fuzzinessBefore + 1; //TODO check when result is a negative value - currentEventRuntimeTimestamp += (fuzziness * 1000); - } + currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, events[i].fuzzinessBefore, events[i].fuzzinessAfter); + print("Timestampet: " + currentEventRuntimeTimestamp); } @@ -175,6 +173,16 @@ com.telldus.scheduler = function() { return joblist; } + function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter){ + if(fuzzinessAfter != 0 || fuzzinessBefore != 0){ + var interval = fuzzinessAfter + fuzzinessBefore; + var rand = Math.random(); //TODO random enough? + var fuzziness = Math.floor((interval+1) * rand); + currentTimestamp += (fuzziness * 1000); + } + return currentTimestamp; + } + function getSunUpDownForDate(datetimestamp, sun, long, lat){ date = new Date(datetimestamp); @@ -221,10 +229,10 @@ com.telldus.scheduler = function() { function Event(id){ this.id = 1; this.value = new Date("December 16, 2010").getTime(); //day of week, day of month, day interval or specific date... - this.fuzzinessBefore = 60; - this.fuzzinessAfter = 60; + this.fuzzinessBefore = 2; + this.fuzzinessAfter = 0; this.type = EVENTTYPE_SUNSET; - this.offset = -800; + this.offset = 0; this.time = ""; //"" since using sunset... } From 622968422aaf12959403e5670ba22599ab0bb330 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Dec 2010 10:23:34 +0000 Subject: [PATCH 1459/2215] Added class QMLView --- telldus-gui/Plugins/QML/CMakeLists.txt | 5 ++++ telldus-gui/Plugins/QML/qmlplugin.cpp | 23 +++++------------ telldus-gui/Plugins/QML/qmlview.cpp | 34 ++++++++++++++++++++++++++ telldus-gui/Plugins/QML/qmlview.h | 27 ++++++++++++++++++++ 4 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 telldus-gui/Plugins/QML/qmlview.cpp create mode 100644 telldus-gui/Plugins/QML/qmlview.h diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt index 9ed959af..da3d745b 100644 --- a/telldus-gui/Plugins/QML/CMakeLists.txt +++ b/telldus-gui/Plugins/QML/CMakeLists.txt @@ -5,12 +5,17 @@ SET( Plugin_NAME "QMLLoader" ) SET( Plugin_SRCS qmlplugin.cpp + qmlview.cpp ) SET( Plugin_HDRS qmlplugin.h ) +SET( Plugin_MOC_HDRS + qmlview.h +) + SET( Plugin_PATH "com.telldus.qml" ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/QML/qmlplugin.cpp b/telldus-gui/Plugins/QML/qmlplugin.cpp index 714f0d84..8b203988 100644 --- a/telldus-gui/Plugins/QML/qmlplugin.cpp +++ b/telldus-gui/Plugins/QML/qmlplugin.cpp @@ -1,12 +1,10 @@ #include "qmlplugin.h" +#include "qmlview.h" #include -#include #include #include #include -#include - QMLPlugin::QMLPlugin ( QObject * parent ) :QScriptExtensionPlugin( parent ) { @@ -15,32 +13,23 @@ QMLPlugin::QMLPlugin ( QObject * parent ) QMLPlugin::~QMLPlugin() { } -QScriptValue QMLLoadFunction(QScriptContext *context, QScriptEngine *engine) -{ - qDebug() << "Tried to load qml-file"; - if (context->argumentCount() < 1) { - return context->throwError("QML constructor takes one parameters"); +QScriptValue QMLLoadFunction(QScriptContext *context, QScriptEngine *engine) { + if (!context->isCalledAsConstructor()) { + return engine->undefinedValue(); } - QString filename = context->argument(0).toString(); //Find out the filename so we have a relative directory to load from QScriptContextInfo info(context->parentContext()); QFileInfo fileinfo(info.fileName()); QDir dir = fileinfo.dir(); - qDebug() << dir.filePath(filename); - QDeclarativeView *view = new QDeclarativeView(); - view->setSource(dir.filePath(filename)); - QScriptValue value = engine->newQObject(view, QScriptEngine::ScriptOwnership); - return value; + return engine->newQObject(new QMLView(dir), QScriptEngine::ScriptOwnership); } void QMLPlugin::initialize ( const QString & key, QScriptEngine * engine ) { if (key == "com.telldus.qml") { - qDebug() << "Hello from QML"; - - engine->globalObject().property("com").property("telldus").property("qml").setProperty("load", engine->newFunction(QMLLoadFunction)); + engine->globalObject().property("com").property("telldus").property("qml").setProperty("view", engine->newFunction(QMLLoadFunction)); } } diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp new file mode 100644 index 00000000..146d8f54 --- /dev/null +++ b/telldus-gui/Plugins/QML/qmlview.cpp @@ -0,0 +1,34 @@ +#include "qmlview.h" +#include +#include +#include + +class QMLView::PrivateData { +public: + QDir baseDir; +}; + +QMLView::QMLView(const QDir &dir) : + QDeclarativeView() +{ + d = new PrivateData; + d->baseDir = dir; +} + +QMLView::~QMLView() { + delete d; +} + +void QMLView::load(const QString &filename) { + this->setSource(d->baseDir.filePath(filename)); +} + +void QMLView::setProperty( const QString & name, const QScriptValue &value ) { + qDebug() << "Setting property" << name << "to" << value.toString(); + + QDeclarativeContext *context = this->rootContext(); + context->setContextProperty(name, value.toVariant()); + + //QVariant v = value.toVariant(); + //qDebug() << v; +} diff --git a/telldus-gui/Plugins/QML/qmlview.h b/telldus-gui/Plugins/QML/qmlview.h new file mode 100644 index 00000000..ff84f866 --- /dev/null +++ b/telldus-gui/Plugins/QML/qmlview.h @@ -0,0 +1,27 @@ +#ifndef QMLVIEW_H +#define QMLVIEW_H + +#include +#include +#include + +class QMLView : public QDeclarativeView +{ + Q_OBJECT +public: + QMLView(const QDir &dir); + virtual ~QMLView(); + +signals: + +public slots: + void load(const QString &url); + void setProperty( const QString & name, const QScriptValue &value ); + +private: + class PrivateData; + PrivateData *d; + +}; + +#endif // QMLVIEW_H From 3965534942981db1cb8c7a41df7c7e48a9ab08b4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 17 Dec 2010 13:15:48 +0000 Subject: [PATCH 1460/2215] New jobtype JOBTYPE_RECURRING_DAY added --- telldus-gui/Plugins/Scheduler/__init__.js | 156 +++++++++++++--------- 1 file changed, 93 insertions(+), 63 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index e6de8d67..73d9970a 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -7,12 +7,15 @@ __postInit__ = function() { com.telldus.scheduler = function() { var JOBTYPE_ABSOLUTE = 0; - + var JOBTYPE_RECURRING_DAY = 1; + var JOBTYPE_RECURRING_WEEK = 2; + var JOBTYPE_RECURRING_MONTH = 3; + var JOBTYPE_RELOAD = 4; //for summer/winter time, any better ideas? + var EVENTTYPE_ABSOLUTE = 0; var EVENTTYPE_SUNRISE = 1; var EVENTTYPE_SUNSET = 2; - var EVENTTYPE_RELOAD = 3; - + //1. hämta redan satta jobb //(kolla om nÃ¥got jobb borde ha körts sedan förra ggn (och att det inte kördes dÃ¥)) @@ -103,7 +106,8 @@ com.telldus.scheduler = function() { default: break; } - } + } + //TODO set som last run (i lagringen) }; function loadJobs(){ @@ -113,58 +117,56 @@ com.telldus.scheduler = function() { //Hur hämta!?!?! (eller snarare, var spara?) var job1 = new Job(1); var job2 = new Job(2); - //foreach job: - var nextRunTime = 0; - if(job1.type == JOBTYPE_ABSOLUTE){ - //hämta alla events i detta jobb - //kan man bryta ut och Ã¥teranvända en del kanske? - //fuzzinessiseringen kan bli en metod iaf... - var events = job1.events; - for(var i=0;i 0){ + var event = events[0]; + var lastRun = job.lastRun; + var date = new Date(0,0,0); + var lastRunDate = new Date(0,0,0); //TODO, this correct? "empty" date... + + if(lastRun > 0){ + lastRunDate = new Date(lastRun); + } + else{ + lastRunDate = new Date(); //Now + } + + date.setYear(lastRunDate.getFullYear()); + date.setMonth(lastRunDate.getMonth()); + date.setDay(lastRunDate.getDate()); + + date = date.getTime() + event.value; //add interval TODO obs, kan ju bli idag eller i morgon om tiden redan har passerats idag... + nextRunTime = getNextEventRunTime(0, event, date); + if(nextRunTime < new Date().getTime()){ + nextRunTime = getNextEventRunTime(0, event, new Date(date).addDay(interval).getTime()); //already passed this time today, try again after "interval" days + } + } + } + + print("NEXTRUNTIME: " + nextRunTime); + + joblist.push(new RunJob(job.id, nextRunTime, job.type, job.device, job.method, job.value)); } - - //nextRunTime = nextRunTime.setDate('2010-01-01 23:59:00'); - //nextRunTime = new Date("July 27, 2010 23:59:00"); - //nextRunTime = nextRunTime.getTime(); - - var nextRunTime1 = new Date("July 27, 2012 23:59:00"); - nextRunTime1 = nextRunTime1.getTime(); - var nextRunTime2 = new Date("July 27, 2011 23:59:00"); - nextRunTime2 = nextRunTime2.getTime(); - - print("NEXTRUNTIME: " + nextRunTime); - - //listan ska vara ordnad - joblist.push(new RunJob(job1.id, nextRunTime, job1.device, job1.method, job1.value)); - joblist.push(new RunJob(2, nextRunTime1, job1.device, job1.method, job1.value)); - joblist.push(new RunJob(3, nextRunTime2, job1.device, job1.method, job1.value)); - - for(var i=0;i new Date().getTime()){ //earlier than other events, but later than "now" + nextRunTime = currentEventRuntimeTimestamp; + } + + return nextRunTime; + } + function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter){ if(fuzzinessAfter != 0 || fuzzinessBefore != 0){ var interval = fuzzinessAfter + fuzzinessBefore; @@ -186,13 +213,10 @@ com.telldus.scheduler = function() { function getSunUpDownForDate(datetimestamp, sun, long, lat){ date = new Date(datetimestamp); - //date = "Thu Dec 16 2010 12:57:47 GMT+0100 (CET)"; print("Date: " + date); - //print(new Date(date)); - print(com.telldus.suncalculator); var timevalues = com.telldus.suncalculator.riseset(date, long, lat); if(timevalues[2] && timevalues[2] != ""){ - return ""; //no sun up or down, do nothing + return ""; //no sun up or down this day, do nothing } print("Time values: " + timevalues[0]); var hourminute; @@ -216,30 +240,36 @@ com.telldus.scheduler = function() { this.name = "testnamn"; this.type = JOBTYPE_ABSOLUTE; this.startdate = "2010-01-01"; //format? - this.lastrun = ""; + this.lastrun = 0; this.device = 1; this.method = 1; this.value = ""; var events = new Array(); //foreach stored event... - events.push(new Event()); + events.push(new Event(1)); + events.push(new Event(2)); this.events = events; } function Event(id){ - this.id = 1; - this.value = new Date("December 16, 2010").getTime(); //day of week, day of month, day interval or specific date... + this.id = id; + if(id == 1){ + this.value = new Date("December 16, 2010").getTime(); //day of week, day of month, day interval or specific date... + } + else{ + this.value = new Date("December 17, 2010").getTime(); //day of week, day of month, day interval or specific date... + } this.fuzzinessBefore = 2; this.fuzzinessAfter = 0; this.type = EVENTTYPE_SUNSET; this.offset = 0; - this.time = ""; //"" since using sunset... + this.time = 0; //"" since using sunset... Timestamp } - function RunJob(id, nextRunTime, device, method, value){ - print (nextRunTime); + function RunJob(id, nextRunTime, type, device, method, value){ this.id = id; this.nextRunTime = nextRunTime; + this.type = type; this.device = device; this.method = method; this.value = value; From b6581e2380de339cb45c14a9cf965c16669ce80a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 17 Dec 2010 15:15:48 +0000 Subject: [PATCH 1461/2215] Added new jobtype JOBTYPE_RECURRING_WEEK --- telldus-gui/Plugins/Scheduler/__init__.js | 81 +++++++++++++++++------ 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 73d9970a..d86cfd5c 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -108,6 +108,7 @@ com.telldus.scheduler = function() { } } //TODO set som last run (i lagringen) + loadJobs(); }; function loadJobs(){ @@ -136,33 +137,59 @@ com.telldus.scheduler = function() { //varje dag eller varannan dag eller sÃ¥... //känns som att max ett event är aktuellt här (kör detta jobb en ggn varje/varannan/var x:e dag alltsÃ¥) //kan väl ändras i framtiden annars + //TODO test this var events = job.events; if(events.length > 0){ var event = events[0]; var lastRun = job.lastRun; - var date = new Date(0,0,0); - var lastRunDate = new Date(0,0,0); //TODO, this correct? "empty" date... + var date; if(lastRun > 0){ - lastRunDate = new Date(lastRun); + var lastRunDate = new Date(lastRun); + date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); + date = date.getTime() + event.value; //add interval } else{ - lastRunDate = new Date(); //Now + var now = new Date(); //Now + date = new Date(now.getFullYear(), now.getMonth(), now.getDate()); } - date.setYear(lastRunDate.getFullYear()); - date.setMonth(lastRunDate.getMonth()); - date.setDay(lastRunDate.getDate()); - - date = date.getTime() + event.value; //add interval TODO obs, kan ju bli idag eller i morgon om tiden redan har passerats idag... nextRunTime = getNextEventRunTime(0, event, date); if(nextRunTime < new Date().getTime()){ - nextRunTime = getNextEventRunTime(0, event, new Date(date).addDay(interval).getTime()); //already passed this time today, try again after "interval" days + var runTime = new Date(date); + runTime.setDate(runTime.getDate() + event.value); + nextRunTime = getNextEventRunTime(0, event, runTime.getTime()); //already passed this time today, try again after "interval" days } } } + else if(job.type == JOBTYPE_RECURRING_WEEK){ + //TODO test this + var events = job.events; + for(var i=0;i new Date().getTime()){ //earlier than other events, but later than "now" + print("Timestampet: " + new Date(currentEventRuntimeTimestamp)); + + if((nextRunTime == 0 || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > new Date().getTime()){ //earlier than other events, but later than "now" + print("currentEventRuntimeTimestamp: " + currentEventRuntimeTimestamp); nextRunTime = currentEventRuntimeTimestamp; } @@ -238,8 +275,8 @@ com.telldus.scheduler = function() { //one job can have several events... more occurencies... this.id = 1; this.name = "testnamn"; - this.type = JOBTYPE_ABSOLUTE; - this.startdate = "2010-01-01"; //format? + this.type = JOBTYPE_RECURRING_DAY; + this.startdate = "2010-01-01"; //format? Gör om till timestamp. Obs, används inte ännu, om det ska användas, se till att kolla detta ocksÃ¥ överallt this.lastrun = 0; this.device = 1; this.method = 1; @@ -247,23 +284,23 @@ com.telldus.scheduler = function() { var events = new Array(); //foreach stored event... events.push(new Event(1)); - events.push(new Event(2)); + //events.push(new Event(2)); this.events = events; } function Event(id){ this.id = id; if(id == 1){ - this.value = new Date("December 16, 2010").getTime(); //day of week, day of month, day interval or specific date... + this.value = 4; //day of week, day of month, day interval or specific date... } else{ - this.value = new Date("December 17, 2010").getTime(); //day of week, day of month, day interval or specific date... + this.value = 1; //day of week, day of month, day interval or specific date... } this.fuzzinessBefore = 2; this.fuzzinessAfter = 0; this.type = EVENTTYPE_SUNSET; - this.offset = 0; - this.time = 0; //"" since using sunset... Timestamp + this.offset = -7000; + this.time = 300000; //"" since using sunset... Timestamp } function RunJob(id, nextRunTime, type, device, method, value){ From a9b68f553e1b8c6d7ddc01ce68785cadc33292d6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Dec 2010 15:18:02 +0000 Subject: [PATCH 1462/2215] Added class ScriptFunctionWrapper to allow QML-scripts to call functions in our normal scripts --- telldus-gui/Plugins/QML/CMakeLists.txt | 2 ++ telldus-gui/Plugins/QML/qmlplugin.cpp | 4 +-- telldus-gui/Plugins/QML/qmlview.cpp | 22 +++++++++++----- telldus-gui/Plugins/QML/qmlview.h | 2 +- .../Plugins/QML/scriptfunctionwrapper.cpp | 23 ++++++++++++++++ .../Plugins/QML/scriptfunctionwrapper.h | 26 +++++++++++++++++++ 6 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp create mode 100644 telldus-gui/Plugins/QML/scriptfunctionwrapper.h diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt index da3d745b..772d1a62 100644 --- a/telldus-gui/Plugins/QML/CMakeLists.txt +++ b/telldus-gui/Plugins/QML/CMakeLists.txt @@ -4,6 +4,7 @@ SET( Plugin_NAME "QMLLoader" ) SET( Plugin_SRCS + scriptfunctionwrapper.cpp qmlplugin.cpp qmlview.cpp ) @@ -13,6 +14,7 @@ SET( Plugin_HDRS ) SET( Plugin_MOC_HDRS + scriptfunctionwrapper.h qmlview.h ) diff --git a/telldus-gui/Plugins/QML/qmlplugin.cpp b/telldus-gui/Plugins/QML/qmlplugin.cpp index 8b203988..5d8746c2 100644 --- a/telldus-gui/Plugins/QML/qmlplugin.cpp +++ b/telldus-gui/Plugins/QML/qmlplugin.cpp @@ -17,14 +17,14 @@ QScriptValue QMLLoadFunction(QScriptContext *context, QScriptEngine *engine) { if (!context->isCalledAsConstructor()) { return engine->undefinedValue(); } - QString filename = context->argument(0).toString(); + QScriptValue p = context->argument(0); //Find out the filename so we have a relative directory to load from QScriptContextInfo info(context->parentContext()); QFileInfo fileinfo(info.fileName()); QDir dir = fileinfo.dir(); - return engine->newQObject(new QMLView(dir), QScriptEngine::ScriptOwnership); + return engine->newQObject(new QMLView(dir, context->argument(0)), QScriptEngine::ScriptOwnership); } void QMLPlugin::initialize ( const QString & key, QScriptEngine * engine ) { diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp index 146d8f54..ab7bd026 100644 --- a/telldus-gui/Plugins/QML/qmlview.cpp +++ b/telldus-gui/Plugins/QML/qmlview.cpp @@ -1,18 +1,31 @@ #include "qmlview.h" +#include "scriptfunctionwrapper.h" #include +#include #include -#include class QMLView::PrivateData { public: QDir baseDir; }; -QMLView::QMLView(const QDir &dir) : +QMLView::QMLView(const QDir &dir, const QScriptValue &object) : QDeclarativeView() { d = new PrivateData; d->baseDir = dir; + + QDeclarativeContext *context = this->rootContext(); + QScriptValueIterator it(object); + + while (it.hasNext()) { + it.next(); + if (it.value().isFunction()) { + context->setContextProperty(it.name(), new ScriptFunctionWrapper(object, it.name(), this)); + } else { + context->setContextProperty(it.name(), it.value().toVariant()); + } + } } QMLView::~QMLView() { @@ -24,11 +37,6 @@ void QMLView::load(const QString &filename) { } void QMLView::setProperty( const QString & name, const QScriptValue &value ) { - qDebug() << "Setting property" << name << "to" << value.toString(); - QDeclarativeContext *context = this->rootContext(); context->setContextProperty(name, value.toVariant()); - - //QVariant v = value.toVariant(); - //qDebug() << v; } diff --git a/telldus-gui/Plugins/QML/qmlview.h b/telldus-gui/Plugins/QML/qmlview.h index ff84f866..8db88f42 100644 --- a/telldus-gui/Plugins/QML/qmlview.h +++ b/telldus-gui/Plugins/QML/qmlview.h @@ -9,7 +9,7 @@ class QMLView : public QDeclarativeView { Q_OBJECT public: - QMLView(const QDir &dir); + QMLView(const QDir &dir, const QScriptValue &object); virtual ~QMLView(); signals: diff --git a/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp b/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp new file mode 100644 index 00000000..5108ff77 --- /dev/null +++ b/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp @@ -0,0 +1,23 @@ +#include "scriptfunctionwrapper.h" + +class ScriptFunctionWrapper::PrivateData { +public: + QScriptValue object; + QString name; +}; + +ScriptFunctionWrapper::ScriptFunctionWrapper(const QScriptValue &object, const QString &name, QObject *parent) : + QObject(parent) +{ + d = new PrivateData; + d->object = object; + d->name = name; +} + +ScriptFunctionWrapper::~ScriptFunctionWrapper() { + delete d; +} + +QVariant ScriptFunctionWrapper::call() { + return d->object.property(d->name).call().toVariant(); +} diff --git a/telldus-gui/Plugins/QML/scriptfunctionwrapper.h b/telldus-gui/Plugins/QML/scriptfunctionwrapper.h new file mode 100644 index 00000000..2a6b1693 --- /dev/null +++ b/telldus-gui/Plugins/QML/scriptfunctionwrapper.h @@ -0,0 +1,26 @@ +#ifndef SCRIPTFUNCTIONWRAPPER_H +#define SCRIPTFUNCTIONWRAPPER_H + +#include +#include +#include + +class ScriptFunctionWrapper : public QObject +{ + Q_OBJECT +public: + explicit ScriptFunctionWrapper(const QScriptValue &object, const QString &name, QObject *parent = 0); + virtual ~ScriptFunctionWrapper(); + +signals: + void titleChanged(); + +public slots: + QVariant call(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif // SCRIPTFUNCTIONWRAPPER_H From eac200a3066125bba83f766cc15215c5d5fd449f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Dec 2010 16:10:57 +0000 Subject: [PATCH 1463/2215] Added require-variables to include other plugins --- telldus-gui/Plugins/CMakeLists.txt | 8 ++++---- telldus-gui/Plugins/Scheduler/CMakeLists.txt | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 2ebbaad8..83665ef1 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -43,10 +43,10 @@ IF(BUILD_PLUGIN_SCHEDULER) ADD_SUBDIRECTORY(Scheduler) ENDIF(BUILD_PLUGIN_SCHEDULER) -IF(BUILD_PLUGIN_SCHEDULER) +IF(REQUIRE_PLUGIN_SUNCALCULATOR) ADD_SUBDIRECTORY(SunCalculator) -ENDIF(BUILD_PLUGIN_SCHEDULER) +ENDIF(REQUIRE_PLUGIN_SUNCALCULATOR) -IF(BUILD_PLUGIN_SCHEDULER) +IF(REQUIRE_PLUGIN_QML) ADD_SUBDIRECTORY(QML) -ENDIF(BUILD_PLUGIN_SCHEDULER) +ENDIF(REQUIRE_PLUGIN_QML) diff --git a/telldus-gui/Plugins/Scheduler/CMakeLists.txt b/telldus-gui/Plugins/Scheduler/CMakeLists.txt index db20e396..dd1c6419 100644 --- a/telldus-gui/Plugins/Scheduler/CMakeLists.txt +++ b/telldus-gui/Plugins/Scheduler/CMakeLists.txt @@ -1,5 +1,9 @@ +SET(REQUIRE_PLUGIN_QML TRUE PARENT_SCOPE) +SET(REQUIRE_PLUGIN_SETTINGS TRUE PARENT_SCOPE) +SET(REQUIRE_PLUGIN_SUNCALCULATOR TRUE PARENT_SCOPE) + SET( Plugin_NAME "scheduler" ) SET( Plugin_PATH "com.telldus.scheduler" ) -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) \ No newline at end of file +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) From e8f0547236469b8ae95f838858b9981913da2fd0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 17 Dec 2010 16:21:36 +0000 Subject: [PATCH 1464/2215] Code cleanup and dim/bell added --- telldus-gui/Plugins/Scheduler/__init__.js | 34 ++++++++--------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index d86cfd5c..3e50d54e 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -77,8 +77,6 @@ com.telldus.scheduler = function() { var runid = 1; //id som kommer tillbaka frÃ¥n c++ (timer)-delen var runJobFunc = function(){ runJob(joblist[0].id); }; var now = new Date().getTime(); - print ("Now:" + new Date(now)); - print("Then:" + new Date(nextRunTime)); var delay = nextRunTime - now; print("Delay: " + delay); setTimeout(runJobFunc, delay); @@ -96,13 +94,18 @@ com.telldus.scheduler = function() { } if(runJob != null){ switch(runJob.method){ - case 1: - //TODO: get constants from somewhere + case com.telldus.core.TELLSTICK_TURNON: com.telldus.core.turnOn(runJob.id); break; - case 2: + case com.telldus.core.TELLSTICK_TURNOFF: com.telldus.core.turnOff(runJob.id); break; + case com.telldus.core.TELLSTICK_DIM: + com.telldus.core.dim(runJob.id, runJob.value); + break; + case com.telldus.core.TELLSTICK_BELL: + com.telldus.core.bell(runJob.id); + break; default: break; } @@ -176,28 +179,25 @@ com.telldus.scheduler = function() { returnDate = zeroTime(returnDate); nextTempRunTime = getNextEventRunTime(0, events[i], returnDate.getTime()); - print(nextTempRunTime); if(nextTempRunTime < new Date().getTime()){ //event happened today, already passed, add to next week instead - print("NEXT WEEK: " + returnDate); returnDate.setDate(returnDate.getDate() + 7); nextRunTime = getNextEventRunTime(nextRunTime, events[i], returnDate.getTime()); } else{ nextRunTime = nextTempRunTime; } - } } + else if(job.type == JOBTYPE_RECURRING_MONTH){ + //TODO + } - print("NEXTRUNTIME: " + new Date(nextRunTime)); + print("Runtime for job: " + new Date(nextRunTime)); joblist.push(new RunJob(job.id, nextRunTime, job.type, job.device, job.method, job.value)); } joblist.sort(compareTime); - for(var i=0;i new Date().getTime()){ //earlier than other events, but later than "now" - print("currentEventRuntimeTimestamp: " + currentEventRuntimeTimestamp); nextRunTime = currentEventRuntimeTimestamp; } @@ -250,12 +243,10 @@ com.telldus.scheduler = function() { function getSunUpDownForDate(datetimestamp, sun, long, lat){ date = new Date(datetimestamp); - print("Date: " + date); var timevalues = com.telldus.suncalculator.riseset(date, long, lat); if(timevalues[2] && timevalues[2] != ""){ return ""; //no sun up or down this day, do nothing } - print("Time values: " + timevalues[0]); var hourminute; if(sun == EVENTTYPE_SUNRISE){ hourminute = timevalues[0].split(':'); @@ -265,7 +256,6 @@ com.telldus.scheduler = function() { } date.setHours(hourminute[0]); date.setMinutes(hourminute[1]); - print("Date after:" + date); return date.getTime(); } From d2edf4362f01640a4c18d11820e4abb3f672caff Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 20 Dec 2010 10:45:24 +0000 Subject: [PATCH 1465/2215] Added plugin settings --- telldus-gui/Plugins/CMakeLists.txt | 4 +++ telldus-gui/Plugins/Settings/CMakeLists.txt | 17 +++++++++ telldus-gui/Plugins/Settings/settings.cpp | 31 ++++++++++++++++ telldus-gui/Plugins/Settings/settings.h | 25 +++++++++++++ .../Plugins/Settings/settingsplugin.cpp | 36 +++++++++++++++++++ telldus-gui/Plugins/Settings/settingsplugin.h | 19 ++++++++++ 6 files changed, 132 insertions(+) create mode 100644 telldus-gui/Plugins/Settings/CMakeLists.txt create mode 100644 telldus-gui/Plugins/Settings/settings.cpp create mode 100644 telldus-gui/Plugins/Settings/settings.h create mode 100644 telldus-gui/Plugins/Settings/settingsplugin.cpp create mode 100644 telldus-gui/Plugins/Settings/settingsplugin.h diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 83665ef1..620ae266 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -50,3 +50,7 @@ ENDIF(REQUIRE_PLUGIN_SUNCALCULATOR) IF(REQUIRE_PLUGIN_QML) ADD_SUBDIRECTORY(QML) ENDIF(REQUIRE_PLUGIN_QML) + +IF(REQUIRE_PLUGIN_SETTINGS) + ADD_SUBDIRECTORY(Settings) +ENDIF(REQUIRE_PLUGIN_SETTINGS) diff --git a/telldus-gui/Plugins/Settings/CMakeLists.txt b/telldus-gui/Plugins/Settings/CMakeLists.txt new file mode 100644 index 00000000..4c04e4d5 --- /dev/null +++ b/telldus-gui/Plugins/Settings/CMakeLists.txt @@ -0,0 +1,17 @@ +SET( Plugin_NAME "Settings" ) + + +SET( Plugin_SRCS + settings.cpp + settingsplugin.cpp +) + +SET( Plugin_HDRS + settingsplugin.h +) + +SET( Plugin_MOC_HDRS + settings.h +) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Settings/settings.cpp b/telldus-gui/Plugins/Settings/settings.cpp new file mode 100644 index 00000000..c7975f2a --- /dev/null +++ b/telldus-gui/Plugins/Settings/settings.cpp @@ -0,0 +1,31 @@ +#include "settings.h" +#include +#include + +class Settings::PrivateData { +public: + QString extension; +}; + +Settings::Settings(const QString &extensionName) : + QObject() +{ + d = new PrivateData; + d->extension = extensionName; +} + +Settings::~Settings() { + delete d; +} + +void Settings::setValue( const QString & key, const QVariant & value ) { + QSettings s; + s.beginGroup(d->extension); + s.setValue(key, value); +} + +QVariant Settings::value( const QString &key, const QVariant &defaultValue ) const { + QSettings s; + s.beginGroup(d->extension); + return s.value(key, defaultValue); +} diff --git a/telldus-gui/Plugins/Settings/settings.h b/telldus-gui/Plugins/Settings/settings.h new file mode 100644 index 00000000..7b089f45 --- /dev/null +++ b/telldus-gui/Plugins/Settings/settings.h @@ -0,0 +1,25 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include + +class Settings : public QObject +{ + Q_OBJECT +public: + explicit Settings(const QString &extensionName); + ~Settings(); + +signals: + +public slots: + void setValue( const QString & key, const QVariant & value ); + QVariant value( const QString & key, const QVariant & defaultValue = QVariant() ) const; + +private: + class PrivateData; + PrivateData *d; + +}; + +#endif // SETTINGS_H diff --git a/telldus-gui/Plugins/Settings/settingsplugin.cpp b/telldus-gui/Plugins/Settings/settingsplugin.cpp new file mode 100644 index 00000000..49efda79 --- /dev/null +++ b/telldus-gui/Plugins/Settings/settingsplugin.cpp @@ -0,0 +1,36 @@ +#include "settingsplugin.h" +#include "settings.h" +#include +#include +#include + +#include + +SettingsPlugin::SettingsPlugin ( QObject * parent ) + :QScriptExtensionPlugin( parent ) +{ +} + +SettingsPlugin::~SettingsPlugin() { +} + +QScriptValue SettingsConstructorFunction(QScriptContext *context, QScriptEngine *engine) { + if (!context->isCalledAsConstructor()) { + return engine->undefinedValue(); + } + + QString extension = engine->evaluate("__extension__").toString(); + return engine->newQObject(new Settings(extension), QScriptEngine::ScriptOwnership); +} + +void SettingsPlugin::initialize ( const QString & key, QScriptEngine * engine ) { + if (key == "com.telldus.settings") { + engine->globalObject().property("com").property("telldus").setProperty("settings", engine->newFunction(SettingsConstructorFunction)); + } +} + +QStringList SettingsPlugin::keys () const { + return QStringList() << "com.telldus.settings"; +} + +Q_EXPORT_PLUGIN2(SettingsInterface, SettingsPlugin) diff --git a/telldus-gui/Plugins/Settings/settingsplugin.h b/telldus-gui/Plugins/Settings/settingsplugin.h new file mode 100644 index 00000000..e4580a17 --- /dev/null +++ b/telldus-gui/Plugins/Settings/settingsplugin.h @@ -0,0 +1,19 @@ +#ifndef SETTINGSPLUGIN_H +#define SETTINGSPLUGIN_H + +#include + +class SettingsPlugin : public QScriptExtensionPlugin { +public: + SettingsPlugin ( QObject * parent = 0 ); + ~SettingsPlugin (); + + virtual void initialize ( const QString & key, QScriptEngine * engine ); + virtual QStringList keys () const; + +private: + +}; + + +#endif // SETTINGSPLUGIN_H From c6273b197c635a1ffd121fa85049cd238133adcd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 20 Dec 2010 11:33:24 +0000 Subject: [PATCH 1466/2215] Allow reading and writing of arrays --- telldus-gui/Plugins/Settings/settings.cpp | 37 +++++++++++++++++------ 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/telldus-gui/Plugins/Settings/settings.cpp b/telldus-gui/Plugins/Settings/settings.cpp index c7975f2a..d220e0e0 100644 --- a/telldus-gui/Plugins/Settings/settings.cpp +++ b/telldus-gui/Plugins/Settings/settings.cpp @@ -1,17 +1,17 @@ #include "settings.h" #include -#include +#include class Settings::PrivateData { public: - QString extension; + QSettings s; }; Settings::Settings(const QString &extensionName) : QObject() { d = new PrivateData; - d->extension = extensionName; + d->s.beginGroup(extensionName); } Settings::~Settings() { @@ -19,13 +19,32 @@ Settings::~Settings() { } void Settings::setValue( const QString & key, const QVariant & value ) { - QSettings s; - s.beginGroup(d->extension); - s.setValue(key, value); + if (value.type() == QVariant::List) { + QVariantList list = value.toList(); + d->s.beginWriteArray(key); + for (int i = 0; i < list.size(); ++i) { + d->s.setArrayIndex(i); + this->setValue(QString::number(i), list.at(i)); + } + d->s.endArray(); + + } else { + d->s.setValue(key, value); + } } QVariant Settings::value( const QString &key, const QVariant &defaultValue ) const { - QSettings s; - s.beginGroup(d->extension); - return s.value(key, defaultValue); + //First, find out if it is an array + if (d->s.childGroups().contains(key)) { + //Array or dict + QVariantList list; + int size = d->s.beginReadArray(key); + for (int i = 0; i < size; ++i) { + d->s.setArrayIndex(i); + list.append(d->s.value(QString::number(i))); + } + d->s.endArray(); + return list; + } + return d->s.value(key, defaultValue); } From a5730e02207ad9d4afe2ba43c1db5c49d10ba6d9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 20 Dec 2010 11:35:23 +0000 Subject: [PATCH 1467/2215] The function should call itself to allow structured data --- telldus-gui/Plugins/Settings/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Settings/settings.cpp b/telldus-gui/Plugins/Settings/settings.cpp index d220e0e0..babdaf41 100644 --- a/telldus-gui/Plugins/Settings/settings.cpp +++ b/telldus-gui/Plugins/Settings/settings.cpp @@ -41,7 +41,7 @@ QVariant Settings::value( const QString &key, const QVariant &defaultValue ) con int size = d->s.beginReadArray(key); for (int i = 0; i < size; ++i) { d->s.setArrayIndex(i); - list.append(d->s.value(QString::number(i))); + list.append(this->value(QString::number(i))); } d->s.endArray(); return list; From 6588c5ee94bd5aac6feebf00ef7c55718fe6f7e3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 20 Dec 2010 12:19:03 +0000 Subject: [PATCH 1468/2215] Recurring month events added --- telldus-gui/Plugins/Scheduler/__init__.js | 79 ++++++++++++++++++++--- 1 file changed, 69 insertions(+), 10 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 3e50d54e..cc842472 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -77,6 +77,7 @@ com.telldus.scheduler = function() { var runid = 1; //id som kommer tillbaka frÃ¥n c++ (timer)-delen var runJobFunc = function(){ runJob(joblist[0].id); }; var now = new Date().getTime(); + print("Next: " + new Date(nextRunTime)); var delay = nextRunTime - now; print("Delay: " + delay); setTimeout(runJobFunc, delay); @@ -189,7 +190,41 @@ com.telldus.scheduler = function() { } } else if(job.type == JOBTYPE_RECURRING_MONTH){ - //TODO + //TODO test this + var events = job.events; + var time; + if(events.length > 0){ + time = getEventRunTime(events[0], new Date(0)); //get time-timestamp only, same for every day + } + for(var i=0;i nextdate){ + nextRunTime = nextdate; + } + } } print("Runtime for job: " + new Date(nextRunTime)); @@ -202,6 +237,25 @@ com.telldus.scheduler = function() { return joblist; } + function getNextLeapYearSafeDate(year, month, day, time){ + if(month == 1 && day == 29){ + //get leap year + for(var i=0;i<5;i++){ + if(new Date(year+i,1,29).getDate() == 29){ + //this is a leap year + datetimestamp = new Date(year+1, 1, 29).getTime() + time; //add time of day + if(datetimestamp > new Date().getTime()){ //else, this was a leap year, but already passed for this year + return datetimestamp; + } + } + } + } + else{ + print("TIME: " + time); + return new Date(year, month, day).getTime() + time; //add time of day + } + } + function zeroTime(date){ date.setHours(0); date.setMinutes(0); @@ -211,6 +265,16 @@ com.telldus.scheduler = function() { } function getNextEventRunTime(nextRunTime, event, date){ + + var currentEventRuntimeTimestamp = getEventRunTime(event, date); + if((nextRunTime == 0 || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > new Date().getTime()){ //earlier than other events, but later than "now" + nextRunTime = currentEventRuntimeTimestamp; + } + + return nextRunTime; + } + + function getEventRunTime(event, date){ var currentEventRuntimeTimestamp = 0; if(event.type == EVENTTYPE_ABSOLUTE){ currentEventRuntimeTimestamp = event.time + date; @@ -219,15 +283,10 @@ com.telldus.scheduler = function() { else if(event.type == EVENTTYPE_SUNRISE || event.type == EVENTTYPE_SUNSET){ currentEventRuntimeTimestamp = getSunUpDownForDate(date, event.type, 55.7, 13.1833); //TODO Long/lat currentEventRuntimeTimestamp += (event.offset * 1000); - currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.fuzzinessBefore, event.fuzzinessAfter); } - if((nextRunTime == 0 || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > new Date().getTime()){ //earlier than other events, but later than "now" - nextRunTime = currentEventRuntimeTimestamp; - } - - return nextRunTime; + return currentEventRuntimeTimestamp; } function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter){ @@ -265,7 +324,7 @@ com.telldus.scheduler = function() { //one job can have several events... more occurencies... this.id = 1; this.name = "testnamn"; - this.type = JOBTYPE_RECURRING_DAY; + this.type = JOBTYPE_RECURRING_MONTH; this.startdate = "2010-01-01"; //format? Gör om till timestamp. Obs, används inte ännu, om det ska användas, se till att kolla detta ocksÃ¥ överallt this.lastrun = 0; this.device = 1; @@ -281,10 +340,10 @@ com.telldus.scheduler = function() { function Event(id){ this.id = id; if(id == 1){ - this.value = 4; //day of week, day of month, day interval or specific date... + this.value = "05-10"; //day of week, day of month, day interval or specific date... Individual values for each type instead? } else{ - this.value = 1; //day of week, day of month, day interval or specific date... + this.value = "12-12"; //day of week, day of month, day interval or specific date... } this.fuzzinessBefore = 2; this.fuzzinessAfter = 0; From 6281cf8b95ec1887b0cddc536d1d90282b967dcc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 20 Dec 2010 13:37:28 +0000 Subject: [PATCH 1469/2215] Allow reading and writing of both arrays and dictionaries --- telldus-gui/Plugins/Settings/settings.cpp | 54 +++++++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/telldus-gui/Plugins/Settings/settings.cpp b/telldus-gui/Plugins/Settings/settings.cpp index babdaf41..d0f7097b 100644 --- a/telldus-gui/Plugins/Settings/settings.cpp +++ b/telldus-gui/Plugins/Settings/settings.cpp @@ -19,14 +19,30 @@ Settings::~Settings() { } void Settings::setValue( const QString & key, const QVariant & value ) { + d->s.remove(key); + if (value.type() == QVariant::List) { QVariantList list = value.toList(); - d->s.beginWriteArray(key); + d->s.beginGroup(key); + d->s.setValue("size", list.size()); + d->s.setValue("type", "array"); for (int i = 0; i < list.size(); ++i) { d->s.setArrayIndex(i); this->setValue(QString::number(i), list.at(i)); } - d->s.endArray(); + d->s.endGroup(); + + } else if (value.type() == QVariant::Map) { + QVariantMap list = value.toMap(); + d->s.beginGroup(key); + d->s.setValue("type", "dict"); + d->s.beginGroup("values"); + QVariantMap::const_iterator it = list.constBegin(); + for (; it != list.constEnd(); ++it) { + this->setValue(it.key(), it.value()); + } + d->s.endGroup(); + d->s.endGroup(); } else { d->s.setValue(key, value); @@ -35,16 +51,36 @@ void Settings::setValue( const QString & key, const QVariant & value ) { QVariant Settings::value( const QString &key, const QVariant &defaultValue ) const { //First, find out if it is an array - if (d->s.childGroups().contains(key)) { - //Array or dict + if (!d->s.childGroups().contains(key)) { + //Normal value + return d->s.value(key, defaultValue); + } + + QVariant retval = QVariant::Invalid; + + //Find out the type + d->s.beginGroup(key); + QString type = d->s.value("type").toString(); + if (type == "dict") { + QVariantMap dict; + d->s.beginGroup("values"); + QStringList keys; + keys << d->s.childGroups() << d->s.childKeys(); + foreach(QString key, keys) { + dict[key] = this->value(key); + } + + d->s.endGroup(); + retval = dict; + } else { QVariantList list; - int size = d->s.beginReadArray(key); + int size = d->s.value("size", 0).toInt(); for (int i = 0; i < size; ++i) { - d->s.setArrayIndex(i); list.append(this->value(QString::number(i))); } - d->s.endArray(); - return list; + retval = list; } - return d->s.value(key, defaultValue); + d->s.endGroup(); + + return retval; } From 68f55ac85de63156f6162cfab6eafda39d662e90 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 20 Dec 2010 14:52:54 +0000 Subject: [PATCH 1470/2215] Added configuration dialog --- telldus-gui/TelldusCenter/CMakeLists.txt | 2 ++ .../TelldusCenter/configurationdialog.cpp | 11 ++++++++ .../TelldusCenter/configurationdialog.h | 19 ++++++++++++++ telldus-gui/TelldusCenter/mainwindow.cpp | 12 ++++++++- telldus-gui/TelldusCenter/mainwindow.h | 4 ++- .../TelldusCenter/scriptenvironment.cpp | 8 ++++++ .../tellduscenterapplication.cpp | 26 +++++++++---------- 7 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 telldus-gui/TelldusCenter/configurationdialog.cpp create mode 100644 telldus-gui/TelldusCenter/configurationdialog.h diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 3d706849..2de68625 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -9,6 +9,7 @@ endif(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-center_SRCS + configurationdialog.cpp main.cpp mainwindow.cpp scriptenvironment.cpp @@ -26,6 +27,7 @@ SET( telldus-center_HDRS ) SET( telldus-center_MOC_HDRS + configurationdialog.h mainwindow.h scriptenvironment.h tellduscenterapplication.h diff --git a/telldus-gui/TelldusCenter/configurationdialog.cpp b/telldus-gui/TelldusCenter/configurationdialog.cpp new file mode 100644 index 00000000..9ee4b734 --- /dev/null +++ b/telldus-gui/TelldusCenter/configurationdialog.cpp @@ -0,0 +1,11 @@ +#include "configurationdialog.h" +#include + +ConfigurationDialog::ConfigurationDialog(QWidget *parent) : + QDialog(parent) +{ +} + +void ConfigurationDialog::open() { + this->exec(); +} diff --git a/telldus-gui/TelldusCenter/configurationdialog.h b/telldus-gui/TelldusCenter/configurationdialog.h new file mode 100644 index 00000000..d516ce42 --- /dev/null +++ b/telldus-gui/TelldusCenter/configurationdialog.h @@ -0,0 +1,19 @@ +#ifndef CONFIGURATIONDIALOG_H +#define CONFIGURATIONDIALOG_H + +#include + +class ConfigurationDialog : public QDialog +{ + Q_OBJECT +public: + explicit ConfigurationDialog(QWidget *parent = 0); + +signals: + +public slots: + void open(); + +}; + +#endif // CONFIGURATIONDIALOG_H diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 06aebd89..07fa0b8d 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -9,12 +9,14 @@ #include #include #include +#include #include #include "tellduscenterapplication.h" #include "tellduscenterplugin.h" #include "message.h" #include "plugintree.h" +#include "scriptenvironment.h" #define VERSION_STRING_HELPER(X) #X #define VERSION_STRING(X) VERSION_STRING_HELPER(X) @@ -26,15 +28,17 @@ public: QStackedLayout *stackedLayout; PluginTree pluginTree; QActionGroup *pagesActionGroup; + ScriptEnvironment *env; }; -MainWindow::MainWindow(QWidget *parent, Qt::WFlags flags) +MainWindow::MainWindow(ScriptEnvironment *env, QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { d = new MainWindowPrivate; d->pagesActionGroup = new QActionGroup( this ); d->message = new Message(); connect(qApp, SIGNAL(showMessage(QString,QString,QString)), d->message, SLOT(showMessage(QString,QString,QString))); + d->env = env; //setAttribute(Qt::WA_DeleteOnClose, true); @@ -81,6 +85,8 @@ void MainWindow::setupMenu() { // File QMenu *fileMenu = menuBar()->addMenu(tr("&File")); + QAction *config = fileMenu->addAction(tr("&Configure"), this, SLOT(slotConfigure())); + fileMenu->addSeparator(); QAction *quit = fileMenu->addAction(tr("&Quit"), qApp, SLOT(quit())); quit->setMenuRole( QAction::QuitRole ); @@ -130,6 +136,10 @@ void MainWindow::slotAboutApplication() { "

Copyright © 2010 Telldus Technologies AB

").arg(VERSION_STRING(VERSION))); } +void MainWindow::slotConfigure() { + d->env->engine()->evaluate("application.configuration.open();"); +} + void MainWindow::slotPagesClick() { QAction *action = qobject_cast(sender()); if (action) { diff --git a/telldus-gui/TelldusCenter/mainwindow.h b/telldus-gui/TelldusCenter/mainwindow.h index 8a08f3cb..bc073723 100644 --- a/telldus-gui/TelldusCenter/mainwindow.h +++ b/telldus-gui/TelldusCenter/mainwindow.h @@ -6,6 +6,7 @@ class QToolBar; class Message; +class ScriptEnvironment; class MainWindowPrivate; @@ -14,7 +15,7 @@ class MainWindow : public QMainWindow Q_OBJECT public: - MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0); + MainWindow(ScriptEnvironment *env, QWidget *parent = 0, Qt::WFlags flags = 0); ~MainWindow(); public slots: @@ -25,6 +26,7 @@ protected: private slots: void slotAboutApplication(); + void slotConfigure(); void slotPagesClick(); private: diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index 093a4ff6..c64989c6 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -1,4 +1,5 @@ #include "scriptenvironment.h" +#include "configurationdialog.h" #include #include #include @@ -35,6 +36,13 @@ ScriptEnvironment::ScriptEnvironment(QObject *parent) : self.setProperty("self", self); d->scriptEngine.setGlobalObject(self); + QScriptValue application = d->scriptEngine.newQObject(parent); + d->scriptEngine.globalObject().setProperty("application", application); + + //Create configuration dialog + QScriptValue configurationDialogObject = d->scriptEngine.newQObject(new ConfigurationDialog(), QScriptEngine::ScriptOwnership, QScriptEngine::ExcludeSuperClassContents); + d->scriptEngine.globalObject().property("application").setProperty("configuration", configurationDialogObject); + //Collect garbage (ie our old global object) d->scriptEngine.collectGarbage(); } diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 35fceaad..2890237c 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -20,7 +20,7 @@ class TelldusCenterApplicationPrivate { public: PluginList plugins; MainWindow *mainWindow; - ScriptEnvironment scriptEnvironment; + ScriptEnvironment *scriptEnvironment; }; TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) @@ -28,6 +28,7 @@ TelldusCenterApplication::TelldusCenterApplication(int &argc, char **argv) { d = new TelldusCenterApplicationPrivate; connect(this, SIGNAL(messageReceived(const QString &)), this, SLOT(msgReceived(const QString &))); + d->scriptEnvironment = new ScriptEnvironment(this); } TelldusCenterApplication::~TelldusCenterApplication() { @@ -36,7 +37,7 @@ TelldusCenterApplication::~TelldusCenterApplication() { } void TelldusCenterApplication::initialize() { - d->mainWindow = new MainWindow( ); + d->mainWindow = new MainWindow( d->scriptEnvironment ); this->setActivationWindow(d->mainWindow, false); @@ -55,7 +56,7 @@ PluginList TelldusCenterApplication::plugins() const { } QScriptValue TelldusCenterApplication::mainWindow() { - QScriptValue value = d->scriptEnvironment.engine()->newQObject(d->mainWindow); + QScriptValue value = d->scriptEnvironment->engine()->newQObject(d->mainWindow); return value; } @@ -100,11 +101,8 @@ void TelldusCenterApplication::loadPlugins() { this->setLibraryPaths( QStringList(pluginsDir.absolutePath()) ); - QScriptValue object = d->scriptEnvironment.engine()->newQObject(this); - d->scriptEnvironment.engine()->globalObject().setProperty("application", object); - - QScriptValue mainWindowObject = d->scriptEnvironment.engine()->newQObject(d->mainWindow); - d->scriptEnvironment.engine()->globalObject().property("application").setProperty("mainwindow", mainWindowObject); + QScriptValue mainWindowObject = d->scriptEnvironment->engine()->newQObject(d->mainWindow); + d->scriptEnvironment->engine()->globalObject().property("application").setProperty("mainwindow", mainWindowObject); foreach (QString fileName, pluginsDir.entryList(QDir::Files)) { QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); @@ -130,7 +128,7 @@ void TelldusCenterApplication::loadPlugin(QObject *plugin) { } void TelldusCenterApplication::loadScripts() { - foreach (QString extension, d->scriptEnvironment.engine()->availableExtensions()) { + foreach (QString extension, d->scriptEnvironment->engine()->availableExtensions()) { if (extension.startsWith("...")) { continue; } @@ -150,12 +148,12 @@ void TelldusCenterApplication::loadScripts() { this->installTranslator(translator); } - d->scriptEnvironment.engine()->importExtension( extension ); - if (d->scriptEnvironment.engine()->hasUncaughtException()) { - qDebug() << QString("Error in %1:%2:").arg(extension).arg(d->scriptEnvironment.engine()->uncaughtExceptionLineNumber()) - << d->scriptEnvironment.engine()->uncaughtException().toString(); + d->scriptEnvironment->engine()->importExtension( extension ); + if (d->scriptEnvironment->engine()->hasUncaughtException()) { + qDebug() << QString("Error in %1:%2:").arg(extension).arg(d->scriptEnvironment->engine()->uncaughtExceptionLineNumber()) + << d->scriptEnvironment->engine()->uncaughtException().toString(); } - d->scriptEnvironment.engine()->clearExceptions(); + d->scriptEnvironment->engine()->clearExceptions(); } } From 2c45b2d9f5637396f2e416d11fa35fbe3e5450c9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 20 Dec 2010 16:37:01 +0000 Subject: [PATCH 1471/2215] Implemented the configuration dialog --- telldus-gui/TelldusCenter/CMakeLists.txt | 1 + .../TelldusCenter/configurationdialog.cpp | 104 +++++++++++++++++- .../TelldusCenter/configurationdialog.h | 21 +++- .../TelldusCenter/scriptenvironment.cpp | 2 +- 4 files changed, 124 insertions(+), 4 deletions(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 2de68625..34a3b329 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -1,6 +1,7 @@ FIND_PACKAGE( Qt4 REQUIRED ) SET(QT_USE_QTSCRIPT TRUE) SET(QT_USE_QTNETWORK TRUE) +SET(QT_USE_QTUITOOLS TRUE) INCLUDE( ${QT_USE_FILE} ) if(COMMAND cmake_policy) diff --git a/telldus-gui/TelldusCenter/configurationdialog.cpp b/telldus-gui/TelldusCenter/configurationdialog.cpp index 9ee4b734..ba42034d 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.cpp +++ b/telldus-gui/TelldusCenter/configurationdialog.cpp @@ -1,11 +1,111 @@ #include "configurationdialog.h" -#include -ConfigurationDialog::ConfigurationDialog(QWidget *parent) : +#include +#include +#include +#include +#include + +#include +#include +#include + +class ConfigurationDialog::PrivateData { +public: + QScriptEngine *engine; + QStackedLayout *stackedLayout; + QListWidget *listWidget; + QHash widgetIndex; + QPushButton *applyButton; +}; + +ConfigurationDialog::ConfigurationDialog(QScriptEngine *engine, QWidget *parent) : QDialog(parent) { + d = new PrivateData; + d->engine = engine; + + QVBoxLayout *layout = new QVBoxLayout(this); + + QHBoxLayout *mainLayout = new QHBoxLayout(); + + d->listWidget = new QListWidget(this); + connect(d->listWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(currentItemChanged(QListWidgetItem*,QListWidgetItem*))); + mainLayout->addWidget(d->listWidget); + + d->stackedLayout = new QStackedLayout(this); + mainLayout->addLayout(d->stackedLayout); + + layout->addLayout(mainLayout); + + QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply, Qt::Horizontal, this); + d->applyButton = buttons->button(QDialogButtonBox::Apply); + d->applyButton->setEnabled(false); + connect(d->applyButton, SIGNAL(clicked()), this, SLOT(doSave())); + connect(buttons, SIGNAL(accepted()), this, SLOT(okClicked())); + connect(buttons, SIGNAL(rejected()), this, SLOT(reject())); + + layout->addWidget(buttons); + + this->setLayout(layout); +} + +ConfigurationDialog::~ConfigurationDialog() { + delete d; +} + +QScriptValue ConfigurationDialog::addPage( const QString &name, const QString &filename ) { + QDir dir = this->baseDir(); + + QUiLoader loader; + QFile file(dir.filePath(filename)); + file.open(QFile::ReadOnly); + QWidget *widget = loader.load(&file, this); + file.close(); + + int index = d->stackedLayout->addWidget(widget); + + QListWidgetItem *item = new QListWidgetItem(QIcon(":images/TelldusCenter_128.png"), name, d->listWidget); + QString plugin = this->currentPlugin(); + item->setData(Qt::UserRole, plugin); + d->listWidget->addItem(item); + d->widgetIndex[plugin] = index; + + return d->engine->newQObject(widget, QScriptEngine::QtOwnership); +} + +QDir ConfigurationDialog::baseDir() const { + QScriptContextInfo info(d->engine->currentContext()->parentContext()); + QFileInfo fileinfo(info.fileName()); + return fileinfo.dir(); +} + +void ConfigurationDialog::currentItemChanged( QListWidgetItem * current, QListWidgetItem * ) { + QString plugin = current->data(Qt::UserRole).toString(); + if (d->widgetIndex.contains(plugin)) { + d->stackedLayout->setCurrentIndex(d->widgetIndex[plugin]); + } +} + +QString ConfigurationDialog::currentPlugin() const { + return d->engine->evaluate("__extension__").toString(); +} + +void ConfigurationDialog::doSave() { + emit save(); + d->applyButton->setEnabled(false); +} + +void ConfigurationDialog::okClicked() { + this->doSave(); + this->accept(); } void ConfigurationDialog::open() { this->exec(); } + +void ConfigurationDialog::valueChanged() { + d->applyButton->setEnabled(true); +} + diff --git a/telldus-gui/TelldusCenter/configurationdialog.h b/telldus-gui/TelldusCenter/configurationdialog.h index d516ce42..e5ea9572 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.h +++ b/telldus-gui/TelldusCenter/configurationdialog.h @@ -2,18 +2,37 @@ #define CONFIGURATIONDIALOG_H #include +#include +#include + +class QScriptEngine; +class QListWidgetItem; class ConfigurationDialog : public QDialog { Q_OBJECT public: - explicit ConfigurationDialog(QWidget *parent = 0); + explicit ConfigurationDialog(QScriptEngine *engine, QWidget *parent = 0); + ~ConfigurationDialog(); signals: + void save(); public slots: + QScriptValue addPage( const QString &name, const QString &file ); void open(); + void valueChanged(); +private slots: + void currentItemChanged( QListWidgetItem * current, QListWidgetItem * previous ); + void doSave(); + void okClicked(); + +private: + QDir baseDir() const; + QString currentPlugin() const; + class PrivateData; + PrivateData *d; }; #endif // CONFIGURATIONDIALOG_H diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index c64989c6..09d5cbd4 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -40,7 +40,7 @@ ScriptEnvironment::ScriptEnvironment(QObject *parent) : d->scriptEngine.globalObject().setProperty("application", application); //Create configuration dialog - QScriptValue configurationDialogObject = d->scriptEngine.newQObject(new ConfigurationDialog(), QScriptEngine::ScriptOwnership, QScriptEngine::ExcludeSuperClassContents); + QScriptValue configurationDialogObject = d->scriptEngine.newQObject(new ConfigurationDialog(&d->scriptEngine), QScriptEngine::ScriptOwnership, QScriptEngine::ExcludeSuperClassContents); d->scriptEngine.globalObject().property("application").setProperty("configuration", configurationDialogObject); //Collect garbage (ie our old global object) From 290fa41ab5d175146fb0b5fa3382f2a83203440d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 21 Dec 2010 09:25:35 +0000 Subject: [PATCH 1472/2215] Added global include function to the script engine --- .../TelldusCenter/scriptenvironment.cpp | 18 ++++++++++++++++++ telldus-gui/TelldusCenter/scriptenvironment.h | 1 + 2 files changed, 19 insertions(+) diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index 09d5cbd4..8ccebb2d 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -2,6 +2,7 @@ #include "configurationdialog.h" #include #include +#include #include #include @@ -64,6 +65,23 @@ void ScriptEnvironment::scriptException(const QScriptValue & exception) { d->scriptEngine.clearExceptions(); } +void ScriptEnvironment::include(const QString &filename) { + QScriptContextInfo info(d->scriptEngine.currentContext()->parentContext()); + QFileInfo fileinfo(info.fileName()); + QDir dir = fileinfo.dir(); + + QFile file(dir.filePath(filename)); + file.open(QFile::ReadOnly); + QString fileContents = file.readAll(); + file.close(); + + QScriptContext *ctx = d->scriptEngine.currentContext(); + + ctx->setActivationObject(ctx->parentContext()->activationObject()); + + d->scriptEngine.evaluate(fileContents, dir.filePath(filename)); +} + void ScriptEnvironment::timerEvent(QTimerEvent *event) { int id = event->timerId(); diff --git a/telldus-gui/TelldusCenter/scriptenvironment.h b/telldus-gui/TelldusCenter/scriptenvironment.h index 45474e93..ca0f68e0 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.h +++ b/telldus-gui/TelldusCenter/scriptenvironment.h @@ -16,6 +16,7 @@ public: signals: public slots: + void include(const QString &filename); int setInterval(const QScriptValue &expression, int delay); void clearInterval(int timerId); From e920e23f6d3f56a72118ebc38ac6a3a330cad3ed Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 21 Dec 2010 09:51:11 +0000 Subject: [PATCH 1473/2215] Debug changes --- telldus-gui/Plugins/SunCalculator/__init__.js | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/SunCalculator/__init__.js b/telldus-gui/Plugins/SunCalculator/__init__.js index 630268d1..9da446be 100644 --- a/telldus-gui/Plugins/SunCalculator/__init__.js +++ b/telldus-gui/Plugins/SunCalculator/__init__.js @@ -22,8 +22,24 @@ com.telldus.suncalculator = function() { var VHz = [0.0, 0.0, 0.0]; // calculate sunrise and sunset times - function riseset(date, lat, lon ) + function riseset(date) { + var settings = new com.telldus.settings(); + var lat = 56.1488; //55.6893; //default + var lon = 13.3538; //13.2123; //default + lat = settings.value("latitude", lat); + lon = settings.value("longitude", lon); + date = new Date(2010, 11, 20); + print("DATET" + date); + + lat = 55 + 68.93/60.0; + lon = 13 + 21.23/60.0; + + lat = 56 + 14.88/60.0; + lon = 13 + 35.38/60.0; + + print("FOR 1: " + lat + "_____" + lon); + var k; var zone = Math.round(date.getTimezoneOffset()/60); var jd = julian_day(date) - 2451545; // Julian day relative to Jan 1.5, 2000 @@ -76,6 +92,8 @@ com.telldus.suncalculator = function() { var values = new Array(); values.push(sunrisevalue); values.push(sunsetvalue); + print("SUNSETVALUE: " + sunsetvalue); + print("FOR: " + lat + "_____" + lon*360); values.push(message); return values; } @@ -312,7 +330,13 @@ com.telldus.suncalculator = function() { return real; } + function setLocation(longitude, latitude){ + settings.setValue("longitude", longitude); + settings.setValue("latitude", latitude); + } + return { //Public functions - riseset: riseset + riseset: riseset, + setLocation: setLocation } }(); \ No newline at end of file From 244de2c8a7c22c9818708f28e0460c1dba6c8534 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 21 Dec 2010 10:31:17 +0000 Subject: [PATCH 1474/2215] Getting jobs from permanent storage --- telldus-gui/Plugins/Scheduler/__init__.js | 349 +++++++++++++--------- 1 file changed, 215 insertions(+), 134 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index cc842472..b64bc8a4 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -63,24 +63,28 @@ com.telldus.scheduler = function() { //TODO obs, om något jobb existerar, lägg till 1 nytt jobb som körs vid nästa sommartid/vintertid och bara laddar om befintliga jobb... Listan måste ju göras om då. (EVENTTYPE_RELOAD) //TODO fem-minuter-bakåt-grejen + //TODO reload...? + //TODO ordna upp + //TODO funktionerna, rätt placerade nu, eller ngn som eg. tillhör bara en subklass? //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... // gränssnittet... hur...? // function init(){ - var joblist = loadJobs(); //reload jobs on every job change - //skicka första tidpunkten (+ id för säkerhetsskull?) till c++ som måste ha hand om timern (verkar det som) - //hur den biten går till, hur ska kommunikationen fram och tillbaka (callback? vänta?) fungera? Tråden måste kunna - //avbrytas om jobblistan uppdateras eller om programmet stängs av... + var joblist = loadJobs(); //TODO reload jobs on every job change + if(joblist.length <= 0){ + return; //no jobs, abort + } var nextRunTime = joblist[0].nextRunTime; + //TODO: var runid = 1; //id som kommer tillbaka från c++ (timer)-delen var runJobFunc = function(){ runJob(joblist[0].id); }; var now = new Date().getTime(); print("Next: " + new Date(nextRunTime)); var delay = nextRunTime - now; print("Delay: " + delay); - setTimeout(runJobFunc, delay); + setTimeout(runJobFunc, delay); //start the timer } function runJob(runid) { @@ -93,141 +97,76 @@ com.telldus.scheduler = function() { break; } } + var success = 0; if(runJob != null){ switch(runJob.method){ case com.telldus.core.TELLSTICK_TURNON: - com.telldus.core.turnOn(runJob.id); + success = com.telldus.core.turnOn(runJob.id); break; case com.telldus.core.TELLSTICK_TURNOFF: - com.telldus.core.turnOff(runJob.id); + success = com.telldus.core.turnOff(runJob.id); break; case com.telldus.core.TELLSTICK_DIM: - com.telldus.core.dim(runJob.id, runJob.value); + success = com.telldus.core.dim(runJob.id, runJob.value); break; case com.telldus.core.TELLSTICK_BELL: - com.telldus.core.bell(runJob.id); + success = com.telldus.core.bell(runJob.id); break; default: break; } } - //TODO set som last run (i lagringen) + + if(success){ + updateLastRun(runid, new Date().getTime()); + } loadJobs(); }; + function saveJob(id){ + var job = new Job(id); + //TODO set properties + var settings = new com.telldus.settings(); + var storedJobs = settings.value("jobs", ""); + + if(!storedJobs){ + storedJobs = {}; //initialize new + } + + storedJobs[id] = job; + + settings.setValue("jobs", storedJobs); + } + + function updateLastRun(id, lastRun){ + var settings = new com.telldus.settings(); + var storedJobs = settings.value("jobs", ""); + storedJobs[id].lastrun = lastRun; + settings.setValue("jobs", storedJobs); + } + function loadJobs(){ + /* + saveJob(1); //TODO, do this when saving something... + saveJob(2); + saveJob(3); + updateLastRun(2, "2005-05-05"); + */ print("Loading jobs"); + var joblist = new Array(); //get all jobs from permanent storage - //Hur hämta!?!?! (eller snarare, var spara?) - var job1 = new Job(1); - var job2 = new Job(2); - var storedJobs = new Array(); - storedJobs.push(job1); //TODO - storedJobs.push(job2); + var settings = new com.telldus.settings(); + var storedJobs = settings.value("jobs", ""); - for(var j=0;j 0){ - var event = events[0]; - var lastRun = job.lastRun; - var date; - - if(lastRun > 0){ - var lastRunDate = new Date(lastRun); - date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); - date = date.getTime() + event.value; //add interval - } - else{ - var now = new Date(); //Now - date = new Date(now.getFullYear(), now.getMonth(), now.getDate()); - } - - nextRunTime = getNextEventRunTime(0, event, date); - if(nextRunTime < new Date().getTime()){ - var runTime = new Date(date); - runTime.setDate(runTime.getDate() + event.value); - nextRunTime = getNextEventRunTime(0, event, runTime.getTime()); //already passed this time today, try again after "interval" days - } - } - } - else if(job.type == JOBTYPE_RECURRING_WEEK){ - //TODO test this - var events = job.events; - for(var i=0;i 0){ - time = getEventRunTime(events[0], new Date(0)); //get time-timestamp only, same for every day - } - for(var i=0;i nextdate){ - nextRunTime = nextdate; - } - } - } - - print("Runtime for job: " + new Date(nextRunTime)); + //print("Runtime for job: " + new Date(nextRunTime)); joblist.push(new RunJob(job.id, nextRunTime, job.type, job.device, job.method, job.value)); } @@ -237,13 +176,13 @@ com.telldus.scheduler = function() { return joblist; } - function getNextLeapYearSafeDate(year, month, day, time){ + function getNextLeapYearSafeDate(year, month, day, event){ if(month == 1 && day == 29){ //get leap year for(var i=0;i<5;i++){ if(new Date(year+i,1,29).getDate() == 29){ //this is a leap year - datetimestamp = new Date(year+1, 1, 29).getTime() + time; //add time of day + datetimestamp = getEventRunTime(event, new Date(year+1, 1, 29).getTime()); if(datetimestamp > new Date().getTime()){ //else, this was a leap year, but already passed for this year return datetimestamp; } @@ -251,8 +190,8 @@ com.telldus.scheduler = function() { } } else{ - print("TIME: " + time); - return new Date(year, month, day).getTime() + time; //add time of day + var date = new Date(year, month, day); + return getEventRunTime(event, date.getTime()); } } @@ -281,7 +220,9 @@ com.telldus.scheduler = function() { currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.fuzzinessBefore, event.fuzzinessAfter); } else if(event.type == EVENTTYPE_SUNRISE || event.type == EVENTTYPE_SUNSET){ - currentEventRuntimeTimestamp = getSunUpDownForDate(date, event.type, 55.7, 13.1833); //TODO Long/lat + print("NEW DATE: " + new Date(date)); + currentEventRuntimeTimestamp = getSunUpDownForDate(date, event.type); + print("NEW DATE: " + new Date(currentEventRuntimeTimestamp)); currentEventRuntimeTimestamp += (event.offset * 1000); currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.fuzzinessBefore, event.fuzzinessAfter); } @@ -299,10 +240,10 @@ com.telldus.scheduler = function() { return currentTimestamp; } - function getSunUpDownForDate(datetimestamp, sun, long, lat){ + function getSunUpDownForDate(datetimestamp, sun){ date = new Date(datetimestamp); - var timevalues = com.telldus.suncalculator.riseset(date, long, lat); + var timevalues = com.telldus.suncalculator.riseset(date); if(timevalues[2] && timevalues[2] != ""){ return ""; //no sun up or down this day, do nothing } @@ -315,6 +256,7 @@ com.telldus.scheduler = function() { } date.setHours(hourminute[0]); date.setMinutes(hourminute[1]); + print("Formatted date: " + date); return date.getTime(); } @@ -325,31 +267,171 @@ com.telldus.scheduler = function() { this.id = 1; this.name = "testnamn"; this.type = JOBTYPE_RECURRING_MONTH; - this.startdate = "2010-01-01"; //format? Gör om till timestamp. Obs, används inte ännu, om det ska användas, se till att kolla detta också överallt + this.startdate = "2010-01-01"; //TODO enforce:a där det är relevant. Format? Gör om till timestamp. Obs, används inte ännu, om det ska användas, se till att kolla detta också överallt this.lastrun = 0; this.device = 1; this.method = 1; this.value = ""; + + } + + Job.prototype.getNextRunTime = function(){ + return 0; //default + } + + function JobAbsolute(id){ + this.Job(id); + this.type = JOBTYPE_ABSOLUTE; //TODO, remove this, shouldnt be neccessary later on var events = new Array(); //foreach stored event... - events.push(new Event(1)); + events.push(new Event(1)); //TODO //events.push(new Event(2)); - this.events = events; + this.events = events; } - + + function JobRecurringDay(id){ + this.Job(id); + this.type = JOBTYPE_RECURRING_DAY; + this.event = new Event(1); //TODO id + } + + function JobRecurringWeek(id){ + this.Job(id); + this.type = JOBTYPE_RECURRING_WEEK; + var events = new Array(); + //foreach stored event... + events.push(new Event(1)); //TODO + //events.push(new Event(2)); + this.events = events; + } + + function JobRecurringMonth(id){ + this.Job(id); + this.type = JOBTYPE_RECURRING_MONTH; + var events = new Array(); + //foreach stored event... + events.push(new Event(1)); //TODO + //events.push(new Event(2)); + this.events = events; + //this.time = 30000; hm, using events instead for now + } + + JobAbsolute.prototype = Job.prototype; + JobRecurringDay.prototype = Job.prototype; + JobRecurringWeek.prototype = Job.prototype; + JobRecurringMonth.prototype = Job.prototype; + + JobAbsolute.prototype.getNextRunTime = function(){ + //TODO like this, or more like this.getNextRunTime = function(name){ inside the class? + //Get all events in this job (absolute = + //kan vara flera absoluta datum och tidpunkter på ett jobb) + //var events = job.events; + var nextRunTime = 0; + for(var i=0;i 0){ + var lastRunDate = new Date(this.lastRun); + date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); + date = date.getTime() + this.event.value; //add interval + } + else{ + var now = new Date(); //Now + date = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + } + + nextRunTime = getNextEventRunTime(0, this.event, date); + if(nextRunTime < new Date().getTime()){ + var runTime = new Date(date); + runTime.setDate(runTime.getDate() + this.event.value); + nextRunTime = getNextEventRunTime(0, this.event, runTime.getTime()); //already passed this time today, try again after "interval" days + } + return nextRunTime; + } + + JobRecurringWeek.prototype.getNextRunTime = function(){ + var nextRunTime = 0; + for(var i=0;i nextdate){ + nextRunTime = nextdate; + } + } + return nextRunTime; + } + + function Event(id){ this.id = id; if(id == 1){ - this.value = "05-10"; //day of week, day of month, day interval or specific date... Individual values for each type instead? + this.value = "11-21"; //day of week, day of month, day interval or specific date... Individual values for each type instead? } else{ - this.value = "12-12"; //day of week, day of month, day interval or specific date... + this.value = new Date().getTime(); //day of week, day of month, day interval or specific date... } - this.fuzzinessBefore = 2; + this.fuzzinessBefore = 0; this.fuzzinessAfter = 0; this.type = EVENTTYPE_SUNSET; - this.offset = -7000; - this.time = 300000; //"" since using sunset... Timestamp + this.offset = 0; + this.time = 0; //"" since using sunset... Timestamp } function RunJob(id, nextRunTime, type, device, method, value){ @@ -370,4 +452,3 @@ com.telldus.scheduler = function() { function compareTime(a, b) { return a.nextRunTime - b.nextRunTime; } - From 63cd97c011e627c7df3dc9b649d28adfd3435175 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 21 Dec 2010 10:53:18 +0000 Subject: [PATCH 1475/2215] Removed hardcoded values --- telldus-gui/Plugins/SunCalculator/__init__.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/telldus-gui/Plugins/SunCalculator/__init__.js b/telldus-gui/Plugins/SunCalculator/__init__.js index 9da446be..5fd1a3c9 100644 --- a/telldus-gui/Plugins/SunCalculator/__init__.js +++ b/telldus-gui/Plugins/SunCalculator/__init__.js @@ -35,9 +35,6 @@ com.telldus.suncalculator = function() { lat = 55 + 68.93/60.0; lon = 13 + 21.23/60.0; - lat = 56 + 14.88/60.0; - lon = 13 + 35.38/60.0; - print("FOR 1: " + lat + "_____" + lon); var k; @@ -205,8 +202,6 @@ com.telldus.suncalculator = function() { // (Van Flandern & Pulkkinen, 1979) function sun( jd, ct ) { - jd = 4001.4583333333335; - ct = 1.109555099247091; var g, lo, s, u, v, w; lo = 0.779072 + 0.00273790931*jd; From 16230b1000eaf33101abb3acca13cac5d52ca226 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 21 Dec 2010 11:29:32 +0000 Subject: [PATCH 1476/2215] Added new class CategoryListWidget to allow more fine-grained tuning of thing such as size. --- .../TelldusCenter/configurationdialog.cpp | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/configurationdialog.cpp b/telldus-gui/TelldusCenter/configurationdialog.cpp index ba42034d..5dbb3727 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.cpp +++ b/telldus-gui/TelldusCenter/configurationdialog.cpp @@ -5,11 +5,32 @@ #include #include #include +#include #include #include #include +/** + * Special version of a QListWidget that has the width of the first column as + * minimum size. + */ +class CategoryListWidget : public QListWidget { +public: + CategoryListWidget(QWidget *parent = 0) : QListWidget(parent) { + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + setSelectionMode(QAbstractItemView::SingleSelection); + setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); + } + + virtual QSize sizeHint() const { + int width = sizeHintForColumn(0) + frameWidth() * 2 + 5; + if (verticalScrollBar()->isVisible()) + width += verticalScrollBar()->width(); + return QSize(width, 100); + } +}; + class ConfigurationDialog::PrivateData { public: QScriptEngine *engine; @@ -29,7 +50,7 @@ ConfigurationDialog::ConfigurationDialog(QScriptEngine *engine, QWidget *parent) QHBoxLayout *mainLayout = new QHBoxLayout(); - d->listWidget = new QListWidget(this); + d->listWidget = new CategoryListWidget(this); connect(d->listWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(currentItemChanged(QListWidgetItem*,QListWidgetItem*))); mainLayout->addWidget(d->listWidget); From e7e175227be573f111d852c1f64f3db76c7c9192 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 21 Dec 2010 15:21:25 +0000 Subject: [PATCH 1477/2215] Object save and load from settings --- telldus-gui/Plugins/Scheduler/__init__.js | 305 +++++++++++++--------- 1 file changed, 188 insertions(+), 117 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index b64bc8a4..542ae71d 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -10,12 +10,14 @@ com.telldus.scheduler = function() { var JOBTYPE_RECURRING_DAY = 1; var JOBTYPE_RECURRING_WEEK = 2; var JOBTYPE_RECURRING_MONTH = 3; - var JOBTYPE_RELOAD = 4; //for summer/winter time, any better ideas? + var JOBTYPE_RELOAD = 4; //TODO for summer/winter time, any better ideas? var EVENTTYPE_ABSOLUTE = 0; var EVENTTYPE_SUNRISE = 1; var EVENTTYPE_SUNSET = 2; + var storedJobs; + //1. hämta redan satta jobb //(kolla om något jobb borde ha körts sedan förra ggn (och att det inte kördes då)) @@ -66,39 +68,31 @@ com.telldus.scheduler = function() { //TODO reload...? //TODO ordna upp //TODO funktionerna, rätt placerade nu, eller ngn som eg. tillhör bara en subklass? + //TODO ta bort absoluta events efter att de har passerats? //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... // gränssnittet... hur...? // + //new job, v: + /* + * id: 1, + name: "testnamn", + type: JOBTYPE_RECURRING_MONTH, + startdate: "2010-01-01", //TODO enforce:a där det är relevant. Format? Gör om till timestamp. Obs, används inte ännu, om det ska användas, se till att kolla detta också överallt + lastrun: 0, + device: 1, + method: 1, + value: "" + */ + function init(){ - var joblist = loadJobs(); //TODO reload jobs on every job change - if(joblist.length <= 0){ - return; //no jobs, abort - } - var nextRunTime = joblist[0].nextRunTime; - - //TODO: - var runid = 1; //id som kommer tillbaka från c++ (timer)-delen - var runJobFunc = function(){ runJob(joblist[0].id); }; - var now = new Date().getTime(); - print("Next: " + new Date(nextRunTime)); - var delay = nextRunTime - now; - print("Delay: " + delay); - setTimeout(runJobFunc, delay); //start the timer + loadJobs(); //load jobs from permanent storage + calculateJobs(); //TODO recalculate jobs on every run/change, reload jobs on every job change } - function runJob(runid) { - //should be the first one, but do a check - print("RunJob: " + runid); - var runJob = null; - for(var i=0;i new Date().getTime()){ //earlier than other events, but later than "now" + //TODO later than "now" could be later than "now - 5 minutes" if settings says so, if reboot for example (and in that case check last run) nextRunTime = currentEventRuntimeTimestamp; } @@ -261,65 +291,86 @@ com.telldus.scheduler = function() { } - function Job(id) { - //hämta detta - //one job can have several events... more occurencies... - this.id = 1; - this.name = "testnamn"; - this.type = JOBTYPE_RECURRING_MONTH; - this.startdate = "2010-01-01"; //TODO enforce:a där det är relevant. Format? Gör om till timestamp. Obs, används inte ännu, om det ska användas, se till att kolla detta också överallt - this.lastrun = 0; - this.device = 1; - this.method = 1; - this.value = ""; - + function Job(jobdata) { + if(jobdata){ + this.v = jobdata; + } + else{ + this.v = {}; + } + } + + Job.prototype.addEvent = function(event){ + if(!this.v.events){ + this.v.events = {}; + } + this.v.events[event.id] = event; } Job.prototype.getNextRunTime = function(){ return 0; //default } - function JobAbsolute(id){ - this.Job(id); - this.type = JOBTYPE_ABSOLUTE; //TODO, remove this, shouldnt be neccessary later on + Job.prototype.save = function(){ + //TODO set properties + var settings = new com.telldus.settings(); + var jobs = settings.value("jobs", ""); + + if(!jobs){ + jobs = {}; //initialize new + } + + jobs[this.v.id] = this.v; + + settings.setValue("jobs", jobs); + } + + function JobAbsolute(jobdata){ + //this.Job(jobdata); + /* + this.v.type = JOBTYPE_ABSOLUTE; var events = new Array(); //foreach stored event... events.push(new Event(1)); //TODO //events.push(new Event(2)); - this.events = events; + this.v.events = events; + */ } - function JobRecurringDay(id){ - this.Job(id); - this.type = JOBTYPE_RECURRING_DAY; - this.event = new Event(1); //TODO id + function JobRecurringDay(jobdata){ + //this.Job(jobdata); + /*this.v.type = JOBTYPE_RECURRING_DAY; + this.v.event = new Event(1); //TODO id + */ } - function JobRecurringWeek(id){ - this.Job(id); - this.type = JOBTYPE_RECURRING_WEEK; + function JobRecurringWeek(jobdata){ + //this.Job(jobdata); + /*this.v.type = JOBTYPE_RECURRING_WEEK; var events = new Array(); //foreach stored event... events.push(new Event(1)); //TODO //events.push(new Event(2)); - this.events = events; + this.v.events = events; + */ } - function JobRecurringMonth(id){ - this.Job(id); - this.type = JOBTYPE_RECURRING_MONTH; + function JobRecurringMonth(jobdata){ + //this.Job(jobdata); + /*this.v.type = JOBTYPE_RECURRING_MONTH; var events = new Array(); //foreach stored event... events.push(new Event(1)); //TODO //events.push(new Event(2)); - this.events = events; + this.v.events = events; //this.time = 30000; hm, using events instead for now + */ } - JobAbsolute.prototype = Job.prototype; - JobRecurringDay.prototype = Job.prototype; - JobRecurringWeek.prototype = Job.prototype; - JobRecurringMonth.prototype = Job.prototype; + JobAbsolute.prototype = new Job(); //Job.prototype; + JobRecurringDay.prototype = new Job(); //Job.prototype; + JobRecurringWeek.prototype = new Job(); //Job.prototype; + JobRecurringMonth.prototype = new Job(); //Job.prototype; JobAbsolute.prototype.getNextRunTime = function(){ //TODO like this, or more like this.getNextRunTime = function(name){ inside the class? @@ -327,9 +378,13 @@ com.telldus.scheduler = function() { //kan vara flera absoluta datum och tidpunkter på ett jobb) //var events = job.events; var nextRunTime = 0; - for(var i=0;i 0){ + if(this.v.lastRun > 0){ var lastRunDate = new Date(this.lastRun); date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); - date = date.getTime() + this.event.value; //add interval + date = date.getTime() + this.v.event.value; //add interval } else{ var now = new Date(); //Now date = new Date(now.getFullYear(), now.getMonth(), now.getDate()); } - nextRunTime = getNextEventRunTime(0, this.event, date); + nextRunTime = getNextEventRunTime(0, this.v.event, date); if(nextRunTime < new Date().getTime()){ var runTime = new Date(date); - runTime.setDate(runTime.getDate() + this.event.value); - nextRunTime = getNextEventRunTime(0, this.event, runTime.getTime()); //already passed this time today, try again after "interval" days + runTime.setDate(runTime.getDate() + this.v.event.value); + nextRunTime = getNextEventRunTime(0, this.v.event, runTime.getTime()); //already passed this time today, try again after "interval" days } + print("Well 2: " + new Date(nextRunTime)); + return nextRunTime; } JobRecurringWeek.prototype.getNextRunTime = function(){ var nextRunTime = 0; - for(var i=0;i Date: Wed, 22 Dec 2010 12:11:52 +0000 Subject: [PATCH 1478/2215] Debugprintouts removed --- telldus-gui/Plugins/SunCalculator/__init__.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/telldus-gui/Plugins/SunCalculator/__init__.js b/telldus-gui/Plugins/SunCalculator/__init__.js index 5fd1a3c9..76a467ab 100644 --- a/telldus-gui/Plugins/SunCalculator/__init__.js +++ b/telldus-gui/Plugins/SunCalculator/__init__.js @@ -30,7 +30,6 @@ com.telldus.suncalculator = function() { lat = settings.value("latitude", lat); lon = settings.value("longitude", lon); date = new Date(2010, 11, 20); - print("DATET" + date); lat = 55 + 68.93/60.0; lon = 13 + 21.23/60.0; @@ -89,8 +88,6 @@ com.telldus.suncalculator = function() { var values = new Array(); values.push(sunrisevalue); values.push(sunsetvalue); - print("SUNSETVALUE: " + sunsetvalue); - print("FOR: " + lat + "_____" + lon*360); values.push(message); return values; } From 82c1ce4177fe887e97b0e3a919a6d29398e52fde Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 22 Dec 2010 12:13:03 +0000 Subject: [PATCH 1479/2215] Fixed loop problem, even if nextRunTime is 0 --- telldus-gui/Plugins/Scheduler/__init__.js | 95 ++++++++++++++--------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 542ae71d..b6814153 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -17,6 +17,7 @@ com.telldus.scheduler = function() { var EVENTTYPE_SUNSET = 2; var storedJobs; + var joblist; //1. hämta redan satta jobb @@ -69,6 +70,12 @@ com.telldus.scheduler = function() { //TODO ordna upp //TODO funktionerna, rätt placerade nu, eller ngn som eg. tillhör bara en subklass? //TODO ta bort absoluta events efter att de har passerats? + //TODO om två jobb är inställda EXAKT samtidigt... så kan de missas vid omkalkylering + //gör istället: inte calculate:a om, utan bara ta nästa i listan... + //kalkylera om - bara vid ngn ändring... + //jo, måste räkna om, för det nyss körda eventet kanske är det som borde köras härnäst igen... + //fast kanske ändå, räkna om det nyss köra eventet, lägg till i listan, ordna listan igen... + //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... // gränssnittet... hur...? @@ -88,10 +95,36 @@ com.telldus.scheduler = function() { function init(){ loadJobs(); //load jobs from permanent storage calculateJobs(); //TODO recalculate jobs on every run/change, reload jobs on every job change + runNextJob(); + } + + function runNextJob(){ + if(joblist.length <= 0){ + print("No jobs"); + return; //no jobs, abort + } + var job = joblist.shift(); //get first job in list (and remove it from the list) + var nextRunTime = job.nextRunTime; + + if(nextRunTime == 0){ + //something is wrong + print("Something is wrong"); + updateJobInList(job.id); //This will just recalculate the job, and probably return 0 again, but updateJobInList won't add it to the list in that case + runNextJob(); + return; + } + + var runJobFunc = function(){ runJob(job); }; + var now = new Date().getTime(); + var delay = nextRunTime - now; + print("Runtime: " + new Date(nextRunTime)); + print("Delay: " + delay); + setTimeout(runJobFunc, delay); //start the timer } function runJob(runJob) { var success = 0; + print("Job id: " + runJob.id); if(runJob){ switch(runJob.method){ case com.telldus.core.TELLSTICK_TURNON: @@ -114,9 +147,9 @@ com.telldus.scheduler = function() { if(success){ updateLastRun(runJob.id, new Date().getTime()); } - sleep(1); - print("Job run"); - calculateJobs(); + print("Job run " + runJob.id); + updateJobInList(runJob.id); + runNextJob(); }; function updateLastRun(id, lastRun){ @@ -128,42 +161,42 @@ com.telldus.scheduler = function() { storedJobs[id].lastrun = lastRun; //update current list } + function updateJobInList(id){ + var job = storedJobs[id]; + var nextRunTime = job.getNextRunTime(); + print("Time updated: " + new Date(nextRunTime)); + + if(nextRunTime == 0){ + return; + } + + joblist.push(new RunJob(job.v.id, nextRunTime, job.v.type, job.v.device, job.v.method, job.v.value)); + + joblist.sort(compareTime); + } + function calculateJobs(){ print("Calculate jobs"); - var joblist = new Array(); + if(!joblist){ + joblist = new Array(); + } for(var key in storedJobs){ var job = storedJobs[key]; - print("Key: " + key); - print("Job: " + job.v.name); var nextRunTime = job.getNextRunTime(); - print(new Date(nextRunTime)); + print("Run time: " + new Date(nextRunTime)); - joblist.push(new RunJob(job.id, nextRunTime, job.type, job.device, job.method, job.value)); + joblist.push(new RunJob(job.v.id, nextRunTime, job.v.type, job.v.device, job.v.method, job.v.value)); } joblist.sort(compareTime); - - if(joblist.length <= 0){ - print("No jobs"); - return; //no jobs, abort - } - var nextRunTime = joblist[0].nextRunTime; - - var runJobFunc = function(){ runJob(joblist[0]); }; - var now = new Date().getTime(); - var delay = nextRunTime - now; - print("Runtime: " + new Date(nextRunTime)); - print("Delay: " + delay); - setTimeout(runJobFunc, delay); //start the timer } function loadJobs(){ print("Loading jobs"); //TODO temp - creating events - var newRecurringMonthJob = getJob({id: 1, name: "testnamn8", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); + var newRecurringMonthJob = getJob({id: 3, name: "testnamn10", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); newRecurringMonthJob.addEvent(new Event(2)); - newRecurringMonthJob.save(); storedJobs = {}; @@ -174,11 +207,9 @@ com.telldus.scheduler = function() { for(var key in storedJobsData){ var jobdata = storedJobsData[key]; var job = getJob(jobdata); - print("Jobbdata: " + jobdata.name); - print("JOBBET: " + job.v.name); storedJobs[key] = job; } - updateLastRun(newRecurringMonthJob.v.id, "2005-05-05"); //TODO remove + //updateLastRun(newRecurringMonthJob.v.id, "2005-05-05"); //TODO remove } function getJob(jobdata){ @@ -250,9 +281,7 @@ com.telldus.scheduler = function() { currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.fuzzinessBefore, event.fuzzinessAfter); } else if(event.type == EVENTTYPE_SUNRISE || event.type == EVENTTYPE_SUNSET){ - print("NEW DATE: " + new Date(date)); currentEventRuntimeTimestamp = getSunUpDownForDate(date, event.type); - print("NEW DATE: " + new Date(currentEventRuntimeTimestamp)); currentEventRuntimeTimestamp += (event.offset * 1000); currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.fuzzinessBefore, event.fuzzinessAfter); } @@ -384,7 +413,6 @@ com.telldus.scheduler = function() { for(var i=0;i nextdate){ nextRunTime = nextdate; } } - print("Well 4: " + new Date(nextRunTime)); return nextRunTime; } @@ -505,6 +526,7 @@ com.telldus.scheduler = function() { } function RunJob(id, nextRunTime, type, device, method, value){ + print("New run job: " + id); this.id = id; this.nextRunTime = nextRunTime; this.type = type; @@ -516,6 +538,7 @@ com.telldus.scheduler = function() { return { //Public functions loadJobs: loadJobs, calculateJobs: calculateJobs, + runNextJob: runNextJob, //TODO which methods should be exposed? Should some of these methods always call another? init:init } }(); From 39cdfe8cae69073187b02f0cc0627409657310ac Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 22 Dec 2010 13:28:29 +0000 Subject: [PATCH 1480/2215] Fixed switch bug, now loading events from permanent storage correctly --- telldus-gui/Plugins/Scheduler/__init__.js | 18 ++++++++++++++---- telldus-gui/Plugins/SunCalculator/__init__.js | 2 -- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index b6814153..1931cc3e 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -105,6 +105,7 @@ com.telldus.scheduler = function() { } var job = joblist.shift(); //get first job in list (and remove it from the list) var nextRunTime = job.nextRunTime; + print("Will run " + storedJobs[job.id].v.name + " when the time is right"); if(nextRunTime == 0){ //something is wrong @@ -126,7 +127,8 @@ com.telldus.scheduler = function() { var success = 0; print("Job id: " + runJob.id); if(runJob){ - switch(runJob.method){ + var method = parseInt(runJob.method); + switch(method){ case com.telldus.core.TELLSTICK_TURNON: success = com.telldus.core.turnOn(runJob.id); break; @@ -195,10 +197,12 @@ com.telldus.scheduler = function() { print("Loading jobs"); //TODO temp - creating events + /* var newRecurringMonthJob = getJob({id: 3, name: "testnamn10", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); newRecurringMonthJob.addEvent(new Event(2)); newRecurringMonthJob.save(); - + */ + storedJobs = {}; //get all jobs from permanent storage var settings = new com.telldus.settings(); @@ -215,7 +219,9 @@ com.telldus.scheduler = function() { function getJob(jobdata){ //factory function... typ var job = new Job(); - switch(jobdata.type){ + var type = parseInt(jobdata.type); + + switch(type){ case JOBTYPE_ABSOLUTE: job = new JobAbsolute(jobdata); break; @@ -337,6 +343,7 @@ com.telldus.scheduler = function() { } Job.prototype.getNextRunTime = function(){ + print("getNextRunTime default"); return 0; //default } @@ -402,7 +409,7 @@ com.telldus.scheduler = function() { JobRecurringMonth.prototype = new Job(); //Job.prototype; JobAbsolute.prototype.getNextRunTime = function(){ - //TODO like this, or more like this.getNextRunTime = function(name){ inside the class? + print("getNextRunTime absolute"); //Get all events in this job (absolute = //kan vara flera absoluta datum och tidpunkter på ett jobb) //var events = job.events; @@ -417,6 +424,7 @@ com.telldus.scheduler = function() { } JobRecurringDay.prototype.getNextRunTime = function(){ + print("getNextRunTime day"); //Recurring day (every day, every other day or every x day) //only one event/job (at the moment at least) //TODO test this @@ -444,6 +452,7 @@ com.telldus.scheduler = function() { } JobRecurringWeek.prototype.getNextRunTime = function(){ + print("getNextRunTime week"); var nextRunTime = 0; if(!this.v.events){ return 0; @@ -472,6 +481,7 @@ com.telldus.scheduler = function() { } JobRecurringMonth.prototype.getNextRunTime = function(){ + print("getNextRunTime month"); //TODO test this var nextRunTime = 0; if(!this.v.events){ diff --git a/telldus-gui/Plugins/SunCalculator/__init__.js b/telldus-gui/Plugins/SunCalculator/__init__.js index 76a467ab..c87c7e0f 100644 --- a/telldus-gui/Plugins/SunCalculator/__init__.js +++ b/telldus-gui/Plugins/SunCalculator/__init__.js @@ -34,8 +34,6 @@ com.telldus.suncalculator = function() { lat = 55 + 68.93/60.0; lon = 13 + 21.23/60.0; - print("FOR 1: " + lat + "_____" + lon); - var k; var zone = Math.round(date.getTimezoneOffset()/60); var jd = julian_day(date) - 2451545; // Julian day relative to Jan 1.5, 2000 From 9cf16c566a4c5a18b240589a6b34166403d90e77 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 22 Dec 2010 17:01:20 +0000 Subject: [PATCH 1481/2215] Removed hard coded debug value for date --- telldus-gui/Plugins/SunCalculator/__init__.js | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-gui/Plugins/SunCalculator/__init__.js b/telldus-gui/Plugins/SunCalculator/__init__.js index c87c7e0f..eb1bf08d 100644 --- a/telldus-gui/Plugins/SunCalculator/__init__.js +++ b/telldus-gui/Plugins/SunCalculator/__init__.js @@ -29,7 +29,6 @@ com.telldus.suncalculator = function() { var lon = 13.3538; //13.2123; //default lat = settings.value("latitude", lat); lon = settings.value("longitude", lon); - date = new Date(2010, 11, 20); lat = 55 + 68.93/60.0; lon = 13 + 21.23/60.0; From 744601119b6ec8ae4c47d202d53422fa083cb9d2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 22 Dec 2010 17:02:51 +0000 Subject: [PATCH 1482/2215] Bug fixes and events to/from storage --- telldus-gui/Plugins/Scheduler/__init__.js | 95 +++++++++++------------ 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 1931cc3e..10431f20 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -67,14 +67,12 @@ com.telldus.scheduler = function() { //TODO obs, om något jobb existerar, lägg till 1 nytt jobb som körs vid nästa sommartid/vintertid och bara laddar om befintliga jobb... Listan måste ju göras om då. (EVENTTYPE_RELOAD) //TODO fem-minuter-bakåt-grejen //TODO reload...? - //TODO ordna upp + //TODO ordna upp, dela upp i flera filer //TODO funktionerna, rätt placerade nu, eller ngn som eg. tillhör bara en subklass? //TODO ta bort absoluta events efter att de har passerats? - //TODO om två jobb är inställda EXAKT samtidigt... så kan de missas vid omkalkylering - //gör istället: inte calculate:a om, utan bara ta nästa i listan... - //kalkylera om - bara vid ngn ändring... - //jo, måste räkna om, för det nyss körda eventet kanske är det som borde köras härnäst igen... - //fast kanske ändå, räkna om det nyss köra eventet, lägg till i listan, ordna listan igen... + //TODO functions for remove event and job + //TODO how to create new jobs and their events? Needs different arguments (all in v) but... + //TODO varför 16:11 för testnamn11? Kolla... //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... @@ -110,7 +108,7 @@ com.telldus.scheduler = function() { if(nextRunTime == 0){ //something is wrong print("Something is wrong"); - updateJobInList(job.id); //This will just recalculate the job, and probably return 0 again, but updateJobInList won't add it to the list in that case + updateJobInList(job.id); //This will just recalculate the job, and probably return 0 again, but updateJobInList won't add it to the list in that case (shouldnt end up here at all now actually) runNextJob(); return; } @@ -186,7 +184,10 @@ com.telldus.scheduler = function() { var job = storedJobs[key]; var nextRunTime = job.getNextRunTime(); print("Run time: " + new Date(nextRunTime)); - + if(nextRunTime == 0){ + print("Will not run"); + return; + } joblist.push(new RunJob(job.v.id, nextRunTime, job.v.type, job.v.device, job.v.method, job.v.value)); } @@ -195,14 +196,19 @@ com.telldus.scheduler = function() { function loadJobs(){ print("Loading jobs"); - + //TODO hur ska id på event och job sättas för nya jobb/events? + //eventid är bara unika inom respektive jobb... //TODO temp - creating events /* - var newRecurringMonthJob = getJob({id: 3, name: "testnamn10", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); - newRecurringMonthJob.addEvent(new Event(2)); + var newRecurringMonthJob = getJob({id: 4, name: "testnamn12", type: JOBTYPE_RECURRING_DAY, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); + newRecurringMonthJob.addEvent(new Event({id: 0, value: 10, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); newRecurringMonthJob.save(); - */ + var newAbsoluteJob = getJob({id: 5, name: "testnamn11", type: JOBTYPE_ABSOLUTE, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); + newAbsoluteJob.addEvent(new Event({id: 1, value: new Date(2010,11,22).getTime(), fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); + newAbsoluteJob.addEvent(new Event({id: 2, value: new Date(2010,11,23).getTime(), fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); + newAbsoluteJob.save(); + */ storedJobs = {}; //get all jobs from permanent storage var settings = new com.telldus.settings(); @@ -213,6 +219,7 @@ com.telldus.scheduler = function() { var job = getJob(jobdata); storedJobs[key] = job; } + //updateLastRun(newRecurringMonthJob.v.id, "2005-05-05"); //TODO remove } @@ -282,14 +289,14 @@ com.telldus.scheduler = function() { function getEventRunTime(event, date){ var currentEventRuntimeTimestamp = 0; - if(event.type == EVENTTYPE_ABSOLUTE){ - currentEventRuntimeTimestamp = event.time + date; - currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.fuzzinessBefore, event.fuzzinessAfter); + if(event.d.type == EVENTTYPE_ABSOLUTE){ + currentEventRuntimeTimestamp = event.d.time + date; + currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.d.fuzzinessBefore, event.d.fuzzinessAfter); } - else if(event.type == EVENTTYPE_SUNRISE || event.type == EVENTTYPE_SUNSET){ - currentEventRuntimeTimestamp = getSunUpDownForDate(date, event.type); - currentEventRuntimeTimestamp += (event.offset * 1000); - currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.fuzzinessBefore, event.fuzzinessAfter); + else if(event.d.type == EVENTTYPE_SUNRISE || event.d.type == EVENTTYPE_SUNSET){ + currentEventRuntimeTimestamp = getSunUpDownForDate(date, event.d.type); + currentEventRuntimeTimestamp += (event.d.offset * 1000); + currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.d.fuzzinessBefore, event.d.fuzzinessAfter); } return currentEventRuntimeTimestamp; @@ -300,6 +307,7 @@ com.telldus.scheduler = function() { var interval = fuzzinessAfter + fuzzinessBefore; var rand = Math.random(); //TODO random enough? var fuzziness = Math.floor((interval+1) * rand); + fuzziness = fuzziness - fuzzinessBefore; currentTimestamp += (fuzziness * 1000); } return currentTimestamp; @@ -321,7 +329,6 @@ com.telldus.scheduler = function() { } date.setHours(hourminute[0]); date.setMinutes(hourminute[1]); - print("Formatted date: " + date); return date.getTime(); } @@ -339,7 +346,7 @@ com.telldus.scheduler = function() { if(!this.v.events){ this.v.events = {}; } - this.v.events[event.id] = event; + this.v.events[event.d.id] = event; } Job.prototype.getNextRunTime = function(){ @@ -417,8 +424,8 @@ com.telldus.scheduler = function() { if(!this.v.events){ return 0; } - for(var i=0;i 0){ var lastRunDate = new Date(this.lastRun); date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); - date = date.getTime() + this.v.event.value; //add interval + date = date.getTime() + this.v.events[0].d.value; //add interval } else{ var now = new Date(); //Now date = new Date(now.getFullYear(), now.getMonth(), now.getDate()); } - - nextRunTime = getNextEventRunTime(0, this.v.event, date); + nextRunTime = getNextEventRunTime(0, this.v.events[0], date.getTime()); if(nextRunTime < new Date().getTime()){ var runTime = new Date(date); - runTime.setDate(runTime.getDate() + this.v.event.value); - nextRunTime = getNextEventRunTime(0, this.v.event, runTime.getTime()); //already passed this time today, try again after "interval" days + runTime.setDate(runTime.getDate() + parseInt(this.v.events[0].d.value)); + nextRunTime = getNextEventRunTime(0, this.v.events[0], runTime.getTime()); //already passed this time today, try again after "interval" days } return nextRunTime; @@ -457,20 +463,20 @@ com.telldus.scheduler = function() { if(!this.v.events){ return 0; } - for(var i=0;i Date: Thu, 23 Dec 2010 10:08:39 +0000 Subject: [PATCH 1483/2215] Fixes for parseInt from storage. Working, but need more testing --- telldus-gui/Plugins/Scheduler/__init__.js | 45 ++++++++++------------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 10431f20..1b04330e 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -72,23 +72,11 @@ com.telldus.scheduler = function() { //TODO ta bort absoluta events efter att de har passerats? //TODO functions for remove event and job //TODO how to create new jobs and their events? Needs different arguments (all in v) but... - //TODO varför 16:11 för testnamn11? Kolla... //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... // gränssnittet... hur...? // - //new job, v: - /* - * id: 1, - name: "testnamn", - type: JOBTYPE_RECURRING_MONTH, - startdate: "2010-01-01", //TODO enforce:a där det är relevant. Format? Gör om till timestamp. Obs, används inte ännu, om det ska användas, se till att kolla detta också överallt - lastrun: 0, - device: 1, - method: 1, - value: "" - */ function init(){ loadJobs(); //load jobs from permanent storage @@ -199,14 +187,15 @@ com.telldus.scheduler = function() { //TODO hur ska id på event och job sättas för nya jobb/events? //eventid är bara unika inom respektive jobb... //TODO temp - creating events + //TODO datum i new date? 11 eller 12? /* - var newRecurringMonthJob = getJob({id: 4, name: "testnamn12", type: JOBTYPE_RECURRING_DAY, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); - newRecurringMonthJob.addEvent(new Event({id: 0, value: 10, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); + var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: JOBTYPE_RECURRING_WEEK, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); + newRecurringMonthJob.addEvent(new Event({id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); newRecurringMonthJob.save(); - var newAbsoluteJob = getJob({id: 5, name: "testnamn11", type: JOBTYPE_ABSOLUTE, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); - newAbsoluteJob.addEvent(new Event({id: 1, value: new Date(2010,11,22).getTime(), fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); - newAbsoluteJob.addEvent(new Event({id: 2, value: new Date(2010,11,23).getTime(), fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); + var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); + newAbsoluteJob.addEvent(new Event({id: 1, value: "11-24", fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 43200})); + newAbsoluteJob.addEvent(new Event({id: 2, value: "11-05", fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); newAbsoluteJob.save(); */ storedJobs = {}; @@ -290,13 +279,13 @@ com.telldus.scheduler = function() { function getEventRunTime(event, date){ var currentEventRuntimeTimestamp = 0; if(event.d.type == EVENTTYPE_ABSOLUTE){ - currentEventRuntimeTimestamp = event.d.time + date; - currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.d.fuzzinessBefore, event.d.fuzzinessAfter); + currentEventRuntimeTimestamp = (event.d.time*1000) + date; + currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); } else if(event.d.type == EVENTTYPE_SUNRISE || event.d.type == EVENTTYPE_SUNSET){ - currentEventRuntimeTimestamp = getSunUpDownForDate(date, event.d.type); + currentEventRuntimeTimestamp = getSunUpDownForDate(date, parseInt(event.d.type)); currentEventRuntimeTimestamp += (event.d.offset * 1000); - currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, event.d.fuzzinessBefore, event.d.fuzzinessAfter); + currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); } return currentEventRuntimeTimestamp; @@ -464,11 +453,16 @@ com.telldus.scheduler = function() { return 0; } for(var key in this.v.events){ - //plocka fram nästa veckodag med nummer x, kan vara idag också + //get next correct day of week, may be today too + var weekday = parseInt(this.v.events[key].d.value); + if(weekday > 6 || weekday <0){ + print("Incorrect weekday value"); + continue; + } var returnDate = new Date(); var returnDay = returnDate.getDay(); - if (this.v.events[key].d.value !== returnDay) { - returnDate.setDate(returnDate.getDate() + (parseInt(this.v.events[key].d.value) + (7 - returnDay)) % 7); + if (weekday !== returnDay) { + returnDate.setDate(returnDate.getDate() + (weekday + (7 - returnDay)) % 7); } returnDate = zeroTime(returnDate); @@ -508,7 +502,7 @@ com.telldus.scheduler = function() { break; //this day doesn't exist for this month (at least not this year (leap year...)) } } - + print("TESTDATE: " + new Date(now.getFullYear(), month, day)); var nextdate = getNextLeapYearSafeDate(now.getFullYear(), month, day, this.v.events[key]); if(nextdate < new Date().getTime()){ //event already happened this year, add to next year instead @@ -516,6 +510,7 @@ com.telldus.scheduler = function() { tempdate.setYear(now.getFullYear() + 1); nextdate = tempdate.getTime(); } + print("Candidate date: " + new Date(nextdate)); if(nextRunTime == 0 || nextRunTime > nextdate){ nextRunTime = nextdate; } From f0fe24c9d44453858f5bd6cb6f63429c3b5c650a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 23 Dec 2010 14:13:27 +0000 Subject: [PATCH 1484/2215] More generic way to add and execute jobs. Still error when waiting for events, gets unresponsive --- telldus-gui/Plugins/Scheduler/__init__.js | 137 ++++++++++++++-------- 1 file changed, 87 insertions(+), 50 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 1b04330e..1f90cbf5 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -18,6 +18,7 @@ com.telldus.scheduler = function() { var storedJobs; var joblist; + var timerid; //1. hämta redan satta jobb @@ -71,7 +72,12 @@ com.telldus.scheduler = function() { //TODO funktionerna, rätt placerade nu, eller ngn som eg. tillhör bara en subklass? //TODO ta bort absoluta events efter att de har passerats? //TODO functions for remove event and job - //TODO how to create new jobs and their events? Needs different arguments (all in v) but... + //TODO how to create new jobs and their events? Needs different arguments (all in v) but... And/or check the correct formatting of data... + //TODO inte ladda jobb här, bara "add job" här... + //TODO hur ska event användas med det här nya? Add event och sådär liksom? + //TODO testa execute-funktionen med annat... + //det enda varje jobb har är en updateLastRun-method (som kan override:as) och en getNextRunTime (som ska override:as) + //Schemaläggaren (denna) exponerar metoderna "addJob", "removeJob" och updateJob? //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... @@ -80,89 +86,78 @@ com.telldus.scheduler = function() { function init(){ loadJobs(); //load jobs from permanent storage - calculateJobs(); //TODO recalculate jobs on every run/change, reload jobs on every job change - runNextJob(); + //calculateJobs(); //TODO recalculate jobs on every run/change, reload jobs on every job change + //runNextJob(); } function runNextJob(){ + clearTimeout(timerid); + print("Timer interrupted"); if(joblist.length <= 0){ print("No jobs"); return; //no jobs, abort } var job = joblist.shift(); //get first job in list (and remove it from the list) var nextRunTime = job.nextRunTime; - print("Will run " + storedJobs[job.id].v.name + " when the time is right"); + print("Will run " + storedJobs[job.id].v.name + " when the time is right"); //Note not all will have a name if(nextRunTime == 0){ //something is wrong print("Something is wrong"); updateJobInList(job.id); //This will just recalculate the job, and probably return 0 again, but updateJobInList won't add it to the list in that case (shouldnt end up here at all now actually) - runNextJob(); return; } - var runJobFunc = function(){ runJob(job); }; + var runJobFunc = function(){ runJob(job.id); }; var now = new Date().getTime(); var delay = nextRunTime - now; print("Runtime: " + new Date(nextRunTime)); print("Delay: " + delay); - setTimeout(runJobFunc, delay); //start the timer + timerid = setTimeout(runJobFunc, delay); //start the timer + print("Has started a job wait"); } - function runJob(runJob) { - var success = 0; - print("Job id: " + runJob.id); - if(runJob){ - var method = parseInt(runJob.method); - switch(method){ - case com.telldus.core.TELLSTICK_TURNON: - success = com.telldus.core.turnOn(runJob.id); - break; - case com.telldus.core.TELLSTICK_TURNOFF: - success = com.telldus.core.turnOff(runJob.id); - break; - case com.telldus.core.TELLSTICK_DIM: - success = com.telldus.core.dim(runJob.id, runJob.value); - break; - case com.telldus.core.TELLSTICK_BELL: - success = com.telldus.core.bell(runJob.id); - break; - default: - break; - } - } - + function runJob(id){ + print("Running job, will execute"); + var success = storedJobs[id].execute(); if(success){ - updateLastRun(runJob.id, new Date().getTime()); + updateLastRun(id, new Date().getTime()); } - print("Job run " + runJob.id); - updateJobInList(runJob.id); - runNextJob(); - }; + print("Job run, after delay " + id); + updateJobInList(id); + } function updateLastRun(id, lastRun){ + /* var settings = new com.telldus.settings(); var jobs = settings.value("jobs", ""); jobs[id].lastrun = lastRun; //update permanent storage settings.setValue("jobs", jobs); - + */ + //TODO... this will not be stored of course, how to do that? storedJobs[id].lastrun = lastRun; //update current list } function updateJobInList(id){ var job = storedJobs[id]; var nextRunTime = job.getNextRunTime(); - print("Time updated: " + new Date(nextRunTime)); + print("Time updated to: " + new Date(nextRunTime)); if(nextRunTime == 0){ return; } - joblist.push(new RunJob(job.v.id, nextRunTime, job.v.type, job.v.device, job.v.method, job.v.value)); + if(!joblist){ + joblist = new Array(); + } + + joblist.push(new RunJob(id, nextRunTime)); //, job.v.type, job.v.device, job.v.method, job.v.value)); joblist.sort(compareTime); + runNextJob(); } + /* function calculateJobs(){ print("Calculate jobs"); if(!joblist){ @@ -180,25 +175,27 @@ com.telldus.scheduler = function() { } joblist.sort(compareTime); + runNextJob(); } + */ function loadJobs(){ print("Loading jobs"); + //TODO detta ska inte göras från denna plugin, utan från respektive... //TODO hur ska id på event och job sättas för nya jobb/events? //eventid är bara unika inom respektive jobb... //TODO temp - creating events - //TODO datum i new date? 11 eller 12? - /* + var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: JOBTYPE_RECURRING_WEEK, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); - newRecurringMonthJob.addEvent(new Event({id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); + newRecurringMonthJob.addEvent(new Event({id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 54760})); newRecurringMonthJob.save(); var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); - newAbsoluteJob.addEvent(new Event({id: 1, value: "11-24", fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 43200})); - newAbsoluteJob.addEvent(new Event({id: 2, value: "11-05", fuzzinessBefore: 0, fuzzinessAfter: 30, type: EVENTTYPE_SUNSET, offset: 0, time: 0})); + newAbsoluteJob.addEvent(new Event({id: 1, value: "11-23", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 54670})); + newAbsoluteJob.addEvent(new Event({id: 2, value: "11-03", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 54730})); newAbsoluteJob.save(); - */ - storedJobs = {}; + + storedJobs = new Array(); //get all jobs from permanent storage var settings = new com.telldus.settings(); var storedJobsData = settings.value("jobs", ""); @@ -206,7 +203,7 @@ com.telldus.scheduler = function() { for(var key in storedJobsData){ var jobdata = storedJobsData[key]; var job = getJob(jobdata); - storedJobs[key] = job; + com.telldus.scheduler.addJob(job); } //updateLastRun(newRecurringMonthJob.v.id, "2005-05-05"); //TODO remove @@ -214,6 +211,7 @@ com.telldus.scheduler = function() { function getJob(jobdata){ //factory function... typ + //TODO Även denna ska bort (iaf härifrån), för denna lagring/hämtning ska ske i respektive plugin eller gui sedan... var job = new Job(); var type = parseInt(jobdata.type); @@ -238,6 +236,22 @@ com.telldus.scheduler = function() { return job; } + function addJob(job){ + var key = storedJobs.push(job)-1; + print("Add job"); + updateJobInList(key); + return key; + } + + function removeJob(id){ + storedJobs.splice(id,1); + } + + function updateJob(key, job){ + storedJobs[key] = job; + updateJobInList(key); + } + function getNextLeapYearSafeDate(year, month, day, event){ if(month == 1 && day == 29){ //get leap year @@ -331,6 +345,30 @@ com.telldus.scheduler = function() { } } + Job.prototype.execute = function(){ + //may be overridden if other than device manipulation should be performed + var success = 0; + print("Job id: " + this.id); + var method = parseInt(this.method); + switch(method){ + case com.telldus.core.TELLSTICK_TURNON: + success = com.telldus.core.turnOn(this.id); + break; + case com.telldus.core.TELLSTICK_TURNOFF: + success = com.telldus.core.turnOff(this.id); + break; + case com.telldus.core.TELLSTICK_DIM: + success = com.telldus.core.dim(this.id, this.value); + break; + case com.telldus.core.TELLSTICK_BELL: + success = com.telldus.core.bell(this.id); + break; + default: + break; + } + return success; + }; + Job.prototype.addEvent = function(event){ if(!this.v.events){ this.v.events = {}; @@ -502,7 +540,6 @@ com.telldus.scheduler = function() { break; //this day doesn't exist for this month (at least not this year (leap year...)) } } - print("TESTDATE: " + new Date(now.getFullYear(), month, day)); var nextdate = getNextLeapYearSafeDate(now.getFullYear(), month, day, this.v.events[key]); if(nextdate < new Date().getTime()){ //event already happened this year, add to next year instead @@ -538,9 +575,9 @@ com.telldus.scheduler = function() { } return { //Public functions - loadJobs: loadJobs, - calculateJobs: calculateJobs, - runNextJob: runNextJob, //TODO which methods should be exposed? Should some of these methods always call another? + addJob: addJob, + removeJob: removeJob, + //runNextJob: runNextJob, //TODO which methods should be exposed? Should some of these methods always call another? init:init } }(); From 62e8b27514a37f3b32be9e69de12227920fb6c46 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 3 Jan 2011 14:01:06 +0000 Subject: [PATCH 1485/2215] Job list is now actually working --- telldus-gui/Plugins/Scheduler/__init__.js | 40 ++++++++++++++++------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 1f90cbf5..8a7ecf12 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -19,6 +19,7 @@ com.telldus.scheduler = function() { var storedJobs; var joblist; var timerid; + var queuedJob; //1. hämta redan satta jobb @@ -97,9 +98,16 @@ com.telldus.scheduler = function() { print("No jobs"); return; //no jobs, abort } + if(queuedJob){ + //put the currently queued job back in the list, so that it can be compared again + print("Queued job is something, put it back in list"); + joblist.push(queuedJob); + joblist.sort(compareTime); + } + var job = joblist.shift(); //get first job in list (and remove it from the list) + queuedJob = job; //put it in list, to keep track of current job var nextRunTime = job.nextRunTime; - print("Will run " + storedJobs[job.id].v.name + " when the time is right"); //Note not all will have a name if(nextRunTime == 0){ //something is wrong @@ -111,7 +119,8 @@ com.telldus.scheduler = function() { var runJobFunc = function(){ runJob(job.id); }; var now = new Date().getTime(); var delay = nextRunTime - now; - print("Runtime: " + new Date(nextRunTime)); + print("Will run " + storedJobs[job.id].v.name + " at " + new Date(nextRunTime)); //Note not all will have a name + print("(Now is " + new Date() + ")"); print("Delay: " + delay); timerid = setTimeout(runJobFunc, delay); //start the timer print("Has started a job wait"); @@ -119,6 +128,7 @@ com.telldus.scheduler = function() { function runJob(id){ print("Running job, will execute"); + queuedJob = null; var success = storedJobs[id].execute(); if(success){ updateLastRun(id, new Date().getTime()); @@ -185,14 +195,20 @@ com.telldus.scheduler = function() { //TODO hur ska id på event och job sättas för nya jobb/events? //eventid är bara unika inom respektive jobb... //TODO temp - creating events + var now = new Date(); + var time1 = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds(); + print(time1); // 48880 + time2 = time1 + 30; + time3 = time1 + 60; + time1 = time1 + 50; var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: JOBTYPE_RECURRING_WEEK, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); - newRecurringMonthJob.addEvent(new Event({id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 54760})); + newRecurringMonthJob.addEvent(new Event({id: 0, value: 1, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time1})); newRecurringMonthJob.save(); var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); - newAbsoluteJob.addEvent(new Event({id: 1, value: "11-23", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 54670})); - newAbsoluteJob.addEvent(new Event({id: 2, value: "11-03", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: 54730})); + newAbsoluteJob.addEvent(new Event({id: 1, value: "00-03", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); + newAbsoluteJob.addEvent(new Event({id: 2, value: "00-03", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); newAbsoluteJob.save(); storedJobs = new Array(); @@ -203,7 +219,7 @@ com.telldus.scheduler = function() { for(var key in storedJobsData){ var jobdata = storedJobsData[key]; var job = getJob(jobdata); - com.telldus.scheduler.addJob(job); + com.telldus.scheduler.addJob(job); //TODO, use different function than this = only sort list afterwards (one time) and dont start timer until all initial are added } //updateLastRun(newRecurringMonthJob.v.id, "2005-05-05"); //TODO remove @@ -348,20 +364,21 @@ com.telldus.scheduler = function() { Job.prototype.execute = function(){ //may be overridden if other than device manipulation should be performed var success = 0; - print("Job id: " + this.id); + print("Job id: " + this.v.id); + id = this.v.id; var method = parseInt(this.method); switch(method){ case com.telldus.core.TELLSTICK_TURNON: - success = com.telldus.core.turnOn(this.id); + success = com.telldus.core.turnOn(id); break; case com.telldus.core.TELLSTICK_TURNOFF: - success = com.telldus.core.turnOff(this.id); + success = com.telldus.core.turnOff(id); break; case com.telldus.core.TELLSTICK_DIM: - success = com.telldus.core.dim(this.id, this.value); + success = com.telldus.core.dim(id, this.v.value); break; case com.telldus.core.TELLSTICK_BELL: - success = com.telldus.core.bell(this.id); + success = com.telldus.core.bell(id); break; default: break; @@ -381,6 +398,7 @@ com.telldus.scheduler = function() { return 0; //default } + //TODO move Job.prototype.save = function(){ //TODO set properties var settings = new com.telldus.settings(); From 49cefee642f4559500e792cb81620d10d129de7b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Jan 2011 11:42:36 +0000 Subject: [PATCH 1486/2215] All events will be updated on entering/leaving daylight saving time. --- telldus-gui/Plugins/Scheduler/CMakeLists.txt | 1 + .../Plugins/Scheduler/DaylightSavingTime.js | 113 +++++++++++ telldus-gui/Plugins/Scheduler/__init__.js | 176 +++++++++++++++--- 3 files changed, 259 insertions(+), 31 deletions(-) create mode 100644 telldus-gui/Plugins/Scheduler/DaylightSavingTime.js diff --git a/telldus-gui/Plugins/Scheduler/CMakeLists.txt b/telldus-gui/Plugins/Scheduler/CMakeLists.txt index dd1c6419..e481529a 100644 --- a/telldus-gui/Plugins/Scheduler/CMakeLists.txt +++ b/telldus-gui/Plugins/Scheduler/CMakeLists.txt @@ -5,5 +5,6 @@ SET(REQUIRE_PLUGIN_SUNCALCULATOR TRUE PARENT_SCOPE) SET( Plugin_NAME "scheduler" ) SET( Plugin_PATH "com.telldus.scheduler" ) +SET( Plugin_EXTRA "DaylightSavingTime.js") INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Scheduler/DaylightSavingTime.js b/telldus-gui/Plugins/Scheduler/DaylightSavingTime.js new file mode 100644 index 00000000..d5f439ae --- /dev/null +++ b/telldus-gui/Plugins/Scheduler/DaylightSavingTime.js @@ -0,0 +1,113 @@ +/* +Copyright (C) 2009 by Michael Khalili + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +function TimezoneDetect(){ + var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear()); + var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt + var intMonth; + var intHoursUtc; + var intHours; + var intDaysMultiplyBy; + + //go through each month to find the lowest offset to account for DST + for (intMonth=0;intMonth<12;intMonth++){ + //go to the next month + dtDate.setUTCMonth(dtDate.getUTCMonth() + 1); + + //To ignore daylight saving time look for the lowest offset. + //Since, during DST, the clock moves forward, it'll be a bigger number. + if (intOffset > (dtDate.getTimezoneOffset() * (-1))){ + intOffset = (dtDate.getTimezoneOffset() * (-1)); + } + } + + return intOffset; +} + +//Find start and end of DST +function DstDetect(){ + var dtDstDetect = new Date(); + var dtDstStart = ''; + var dtDstEnd = ''; + var dtDstStartHold = ''; //Temp date hold + var intYearDayCount = 732; //366 (include leap year) * 2 (for two years) + var intHourOfYear = 1; + var intDayOfYear; + var intOffset = TimezoneDetect(); //Custom function. Make sure you include it. + + //Start from a year ago to make sure we include any previously starting DST + dtDstDetect = new Date() + dtDstDetect.setUTCFullYear(dtDstDetect.getUTCFullYear() - 1); + dtDstDetect.setUTCHours(0,0,0,0); + + //Going hour by hour through the year will detect DST with shorter code but that could result in 8760 + //FOR loops and several seconds of script execution time. Longer code narrows this down a little. + //Go one day at a time and find out approx time of DST and if there even is DST on this computer. + //Also need to make sure we catch the most current start and end cycle. + for(intDayOfYear = 1; intDayOfYear <= intYearDayCount; intDayOfYear++){ + dtDstDetect.setUTCDate(dtDstDetect.getUTCDate() + 1); + + if ((dtDstDetect.getTimezoneOffset() * (-1)) != intOffset && dtDstStartHold == ''){ + dtDstStartHold = new Date(dtDstDetect); + } + if ((dtDstDetect.getTimezoneOffset() * (-1)) == intOffset && dtDstStartHold != ''){ + dtDstStart = new Date(dtDstStartHold); + dtDstEnd = new Date(dtDstDetect); + dtDstStartHold = ''; + + //DST is being used in this timezone. Narrow the time down to the exact hour the change happens + //Remove 48 hours (a few extra to be on safe side) from the start/end date and find the exact change point + //Go hour by hour until a change in the timezone offset is detected. + dtDstStart.setUTCHours(dtDstStart.getUTCHours() - 48); + dtDstEnd.setUTCHours(dtDstEnd.getUTCHours() - 48); + + //First find when DST starts + for(intHourOfYear=1; intHourOfYear <= 48; intHourOfYear++){ + dtDstStart.setUTCHours(dtDstStart.getUTCHours() + 1); + + //If we found it then exit the loop. dtDstStart will have the correct value left in it. + if ((dtDstStart.getTimezoneOffset() * (-1)) != intOffset){ + break; + } + } + + //Now find out when DST ends + for(intHourOfYear=1; intHourOfYear <= 48; intHourOfYear++){ + dtDstEnd.setUTCHours(dtDstEnd.getUTCHours() + 1); + + //If we found it then exit the loop. dtDstEnd will have the correct value left in it. + if ((dtDstEnd.getTimezoneOffset() * (-1)) != (intOffset + 60)){ + break; + } + } + + //Check if DST is currently on for this time frame. If it is then return these values. + //If not then keep going. The function will either return the last values collected + //or another value that is currently in effect + if ((new Date()).getTime() >= dtDstStart.getTime() && (new Date()).getTime() <= dtDstEnd.getTime()){ + return new Array(dtDstStart,dtDstEnd); + } + + } + } + return new Array(dtDstStart,dtDstEnd); +} \ No newline at end of file diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 8a7ecf12..b96024e2 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -1,5 +1,7 @@ __setupPackage__( __extension__ ); +include("DaylightSavingTime.js"); + __postInit__ = function() { application.allDoneLoading.connect( com.telldus.scheduler.init ); } @@ -77,6 +79,8 @@ com.telldus.scheduler = function() { //TODO inte ladda jobb här, bara "add job" här... //TODO hur ska event användas med det här nya? Add event och sådär liksom? //TODO testa execute-funktionen med annat... + //TODO borde inte använda associative arrays... Objects istället... + //TODO startdate //det enda varje jobb har är en updateLastRun-method (som kan override:as) och en getNextRunTime (som ska override:as) //Schemaläggaren (denna) exponerar metoderna "addJob", "removeJob" och updateJob? @@ -86,9 +90,7 @@ com.telldus.scheduler = function() { // function init(){ - loadJobs(); //load jobs from permanent storage - //calculateJobs(); //TODO recalculate jobs on every run/change, reload jobs on every job change - //runNextJob(); + loadJobs(); //load jobs from permanent storage TODO move } function runNextJob(){ @@ -119,7 +121,7 @@ com.telldus.scheduler = function() { var runJobFunc = function(){ runJob(job.id); }; var now = new Date().getTime(); var delay = nextRunTime - now; - print("Will run " + storedJobs[job.id].v.name + " at " + new Date(nextRunTime)); //Note not all will have a name + print("Will run " + storedJobs.get(job.id).v.name + " at " + new Date(nextRunTime)); //Note not all will have a name print("(Now is " + new Date() + ")"); print("Delay: " + delay); timerid = setTimeout(runJobFunc, delay); //start the timer @@ -129,7 +131,7 @@ com.telldus.scheduler = function() { function runJob(id){ print("Running job, will execute"); queuedJob = null; - var success = storedJobs[id].execute(); + var success = storedJobs.get(id).execute(); if(success){ updateLastRun(id, new Date().getTime()); } @@ -145,28 +147,47 @@ com.telldus.scheduler = function() { settings.setValue("jobs", jobs); */ //TODO... this will not be stored of course, how to do that? - storedJobs[id].lastrun = lastRun; //update current list + storedJobs.get(id).lastrun = lastRun; //update current list } function updateJobInList(id){ - var job = storedJobs[id]; + if(!joblist){ + joblist = new Array(); + } + + if(!storedJobs.contains(id)){ + removeFromJobList(id); + runNextJob(); + return; + } + var job = storedJobs.get(id); var nextRunTime = job.getNextRunTime(); print("Time updated to: " + new Date(nextRunTime)); if(nextRunTime == 0){ + removeFromJobList(id); //remove from joblist if it exists there (run time may have been updated to something invalid/already passed) + runNextJob(); //resort list (may have changed), run next return; } - if(!joblist){ - joblist = new Array(); - } - joblist.push(new RunJob(id, nextRunTime)); //, job.v.type, job.v.device, job.v.method, job.v.value)); joblist.sort(compareTime); runNextJob(); } + function removeFromJobList(id){ + if(!joblist){ + return; + } + for(i=0;i time){ + //already passed + time = dst[1].getTime(); + } + return time; + } + + JobDaylightSavingReload.prototype.execute = function(){ + //override default + print("Daylight savings job"); + //1. Make sure this job is run "last", if other jobs are set to be runt the same second + //2. sleep for one second, to avoid strange calculations + setTimeout(recalculateAllJobs(), 1); + //this may lead to that things that should be executed exactly at 3.00 when moving time forward one hour won't run, but that + //is the only case + //TODO recalculate all stored jobs + return 0; + }; JobAbsolute.prototype.getNextRunTime = function(){ print("getNextRunTime absolute"); @@ -545,7 +630,7 @@ com.telldus.scheduler = function() { } for(var key in this.v.events){ //get next x day of month, may be today, for the current month - if(this.v.events[key].d.value.toString().indexOf("-") == -1){ //make sure value is of correct format + if(!this.v.events[key].d.value || this.v.events[key].d.value.toString().indexOf("-") == -1){ //make sure value is of correct format continue; } var daymonth = this.v.events[key].d.value.split('-'); //month-day @@ -582,6 +667,36 @@ com.telldus.scheduler = function() { this.d = {}; } } + + function MappedList() { + this.container = {}; + this.length = 0; + } + + MappedList.prototype.push = function(element){ + //TODO reusing keys at the moment, that's ok, right? + var length = this.length; + this.container[length] = element; + this.length = length + 1; + return length; + } + + MappedList.prototype.get = function(key){ + return this.container[key]; + } + + MappedList.prototype.update = function(key, element){ + this.container[key] = element; + } + + MappedList.prototype.remove = function(key){ + delete this.container[key]; + this.length--; + } + + MappedList.prototype.contains = function(key){ + return !(this.container[key] === undefined); + } function RunJob(id, nextRunTime, type, device, method, value){ this.id = id; @@ -595,8 +710,7 @@ com.telldus.scheduler = function() { return { //Public functions addJob: addJob, removeJob: removeJob, - //runNextJob: runNextJob, //TODO which methods should be exposed? Should some of these methods always call another? - init:init + init:init //TODO change this } }(); From e79cd741c6423f10ee3f934b432c31bea9db2c5a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Jan 2011 15:32:17 +0000 Subject: [PATCH 1487/2215] Added option to run jobs that should have been run in the last x ms, but was missed (for example due to reboot). --- telldus-gui/Plugins/Scheduler/__init__.js | 188 ++++++++++------------ 1 file changed, 88 insertions(+), 100 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index b96024e2..279cf240 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -8,11 +8,11 @@ __postInit__ = function() { com.telldus.scheduler = function() { - var JOBTYPE_ABSOLUTE = 0; + var JOBTYPE_ABSOLUTE = 0; //jobtypes? Not here at least... var JOBTYPE_RECURRING_DAY = 1; var JOBTYPE_RECURRING_WEEK = 2; var JOBTYPE_RECURRING_MONTH = 3; - var JOBTYPE_RELOAD = 4; //TODO for summer/winter time, any better ideas? + //var JOBTYPE_RELOAD = 4; //for summer/winter time var EVENTTYPE_ABSOLUTE = 0; var EVENTTYPE_SUNRISE = 1; @@ -67,25 +67,14 @@ com.telldus.scheduler = function() { // solen går upp/ner +/- visst antal minuter... // hur kommer net:en + schemaläggare att fungera? Kommer det att finnas en webvariant? //jobben i listan = deviceid (även grupp/scen såklart), action, värde. En enda / jobb, får grupperas med grupper/scener om man vill att mer ska hända på en ggn - - //TODO obs, om något jobb existerar, lägg till 1 nytt jobb som körs vid nästa sommartid/vintertid och bara laddar om befintliga jobb... Listan måste ju göras om då. (EVENTTYPE_RELOAD) - //TODO fem-minuter-bakåt-grejen - //TODO reload...? - //TODO ordna upp, dela upp i flera filer - //TODO funktionerna, rätt placerade nu, eller ngn som eg. tillhör bara en subklass? - //TODO ta bort absoluta events efter att de har passerats? - //TODO functions for remove event and job - //TODO how to create new jobs and their events? Needs different arguments (all in v) but... And/or check the correct formatting of data... - //TODO inte ladda jobb här, bara "add job" här... - //TODO hur ska event användas med det här nya? Add event och sådär liksom? - //TODO testa execute-funktionen med annat... - //TODO borde inte använda associative arrays... Objects istället... - //TODO startdate - //det enda varje jobb har är en updateLastRun-method (som kan override:as) och en getNextRunTime (som ska override:as) - //Schemaläggaren (denna) exponerar metoderna "addJob", "removeJob" och updateJob? - //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... + //TODO ordna upp, dela upp i flera filer, inte ladda jobb här (per plugin istället), bara "add job" här... + //TODO ta bort absoluta events efter att de har passerats? Kan inte göras härifrån, får på ngt sätt ske därifrån de sparas/laddas + //TODO startdate + //det enda varje jobb har är getNextRunTime (som ska override:as) + + // gränssnittet... hur...? // @@ -132,9 +121,10 @@ com.telldus.scheduler = function() { print("Running job, will execute"); queuedJob = null; var success = storedJobs.get(id).execute(); - if(success){ + //if(success){ + //update last run even if not successful, else it may become an infinite loop (if using pastGracePeriod) updateLastRun(id, new Date().getTime()); - } + //} print("Job run, after delay " + id); updateJobInList(id); } @@ -147,7 +137,8 @@ com.telldus.scheduler = function() { settings.setValue("jobs", jobs); */ //TODO... this will not be stored of course, how to do that? - storedJobs.get(id).lastrun = lastRun; //update current list + print("Update last run: " + id + " to " + lastRun); + storedJobs.get(id).v.lastRun = lastRun; //update current list } function updateJobInList(id){ @@ -188,28 +179,6 @@ com.telldus.scheduler = function() { } } - /* - function calculateJobs(){ - print("Calculate jobs"); - if(!joblist){ - joblist = new Array(); - } - for(var key in storedJobs){ - var job = storedJobs[key]; - var nextRunTime = job.getNextRunTime(); - print("Run time: " + new Date(nextRunTime)); - if(nextRunTime == 0){ - print("Will not run"); - return; - } - joblist.push(new RunJob(job.v.id, nextRunTime, job.v.type, job.v.device, job.v.method, job.v.value)); - } - - joblist.sort(compareTime); - runNextJob(); - } - */ - function recalculateAllJobs(){ print("Recalculating all jobs"); @@ -239,15 +208,15 @@ com.telldus.scheduler = function() { var now = new Date(); var time1 = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds(); print(time1); // 48880 - time2 = time1 + 300; - time3 = time1 + 600; - time1 = time1 + 500; + time2 = time1 + 30; + time3 = time1 - 60; + time1 = time1 + 50; - var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: JOBTYPE_RECURRING_WEEK, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); + var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: JOBTYPE_RECURRING_WEEK, startdate: "2010-01-01", lastRun: 0, device: 1, method: 1, value: ""}); newRecurringMonthJob.addEvent(new Event({id: 0, value: 2, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time1})); newRecurringMonthJob.save(); - var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastrun: 0, device: 1, method: 1, value: ""}); + var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 90000}); newAbsoluteJob.addEvent(new Event({id: 1, value: "00-04", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); newAbsoluteJob.addEvent(new Event({id: 2, value: "00-04", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); newAbsoluteJob.save(); @@ -303,6 +272,14 @@ com.telldus.scheduler = function() { return key; } + function updateJob(key, job){ + if(!storedJobs.contains(key)){ + return; + } + storedJobs.update(key, job); + updateJobInList(key); + } + function removeJob(id){ storedJobs.remove(id); updateJobInList(id); @@ -351,11 +328,18 @@ com.telldus.scheduler = function() { return date; } - function getNextEventRunTime(nextRunTime, event, date){ + /* + * pastGracePeriod - optional, run events that should have been run, for example, 5 minutes ago, + * but wasn't, because of a reboot or similar (in ms) + * note, must in that case have checked last run + */ + function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod){ + if(!pastGracePeriod){ + var pastGracePeriod = 0; + } var currentEventRuntimeTimestamp = getEventRunTime(event, date); - if((nextRunTime == 0 || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > new Date().getTime()){ //earlier than other events, but later than "now" - //TODO later than "now" could be later than "now - 5 minutes" if settings says so, if reboot for example (and in that case check last run) + if((nextRunTime == 0 || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > (new Date().getTime() - pastGracePeriod)){ //earlier than other events, but later than "now" nextRunTime = currentEventRuntimeTimestamp; } @@ -469,56 +453,49 @@ com.telldus.scheduler = function() { settings.setValue("jobs", jobs); } + function getGracePeriod(v){ + var pastGracePeriod = 0; + var lastRun = 0; + if(v.lastRun){ + lastRun = v.lastRun; + } + if(v.pastGracePeriod){ + var timeSinceLastRun = (new Date().getTime() - lastRun); + if(timeSinceLastRun > v.pastGracePeriod){ + pastGracePeriod = v.pastGracePeriod; + } + else{ + pastGracePeriod = timeSinceLastRun; + } + } + + return pastGracePeriod; + } + function JobAbsolute(jobdata){ - //this.Job(jobdata); - /* - this.v.type = JOBTYPE_ABSOLUTE; - var events = new Array(); - //foreach stored event... - events.push(new Event(1)); //TODO - //events.push(new Event(2)); - this.v.events = events; - */ + } function JobRecurringDay(jobdata){ - //this.Job(jobdata); - /*this.v.type = JOBTYPE_RECURRING_DAY; - this.v.event = new Event(1); //TODO id - */ + } function JobRecurringWeek(jobdata){ - //this.Job(jobdata); - /*this.v.type = JOBTYPE_RECURRING_WEEK; - var events = new Array(); - //foreach stored event... - events.push(new Event(1)); //TODO - //events.push(new Event(2)); - this.v.events = events; - */ + } function JobRecurringMonth(jobdata){ - //this.Job(jobdata); - /*this.v.type = JOBTYPE_RECURRING_MONTH; - var events = new Array(); - //foreach stored event... - events.push(new Event(1)); //TODO - //events.push(new Event(2)); - this.v.events = events; - //this.time = 30000; hm, using events instead for now - */ + } - //keep here + //keep this here function JobDaylightSavingReload(){ } - JobAbsolute.prototype = new Job(); //Job.prototype; - JobRecurringDay.prototype = new Job(); //Job.prototype; - JobRecurringWeek.prototype = new Job(); //Job.prototype; - JobRecurringMonth.prototype = new Job(); //Job.prototype; + JobAbsolute.prototype = new Job(); + JobRecurringDay.prototype = new Job(); + JobRecurringWeek.prototype = new Job(); + JobRecurringMonth.prototype = new Job(); JobDaylightSavingReload.prototype = new Job(); JobDaylightSavingReload.prototype.getNextRunTime = function(){ @@ -536,12 +513,10 @@ com.telldus.scheduler = function() { JobDaylightSavingReload.prototype.execute = function(){ //override default print("Daylight savings job"); - //1. Make sure this job is run "last", if other jobs are set to be runt the same second - //2. sleep for one second, to avoid strange calculations - setTimeout(recalculateAllJobs(), 1); - //this may lead to that things that should be executed exactly at 3.00 when moving time forward one hour won't run, but that - //is the only case - //TODO recalculate all stored jobs + //TODO Make sure this job is run "last", if other jobs are set to be runt the same second + setTimeout(recalculateAllJobs(), 1); //sleep for one ms, to avoid strange calculations + //this may lead to that things that should be executed exactly at 3.00 when + //moving time forward one hour won't run, but that should be the only case return 0; }; @@ -551,11 +526,15 @@ com.telldus.scheduler = function() { //kan vara flera absoluta datum och tidpunkter på ett jobb) //var events = job.events; var nextRunTime = 0; + if(!this.v.events){ return 0; } + + var pastGracePeriod = getGracePeriod(this.v); + for(var key in this.v.events){ - nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], parseInt(this.v.events[key].d.value)); + nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], parseInt(this.v.events[key].d.value), pastGracePeriod); } return nextRunTime; } @@ -566,8 +545,9 @@ com.telldus.scheduler = function() { //only one event/job (at the moment at least) //TODO test this var nextRunTime = 0; + var pastGracePeriod = getGracePeriod(this.v); var date; - + if(this.v.lastRun > 0){ var lastRunDate = new Date(this.lastRun); date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); @@ -577,11 +557,11 @@ com.telldus.scheduler = function() { var now = new Date(); //Now date = new Date(now.getFullYear(), now.getMonth(), now.getDate()); } - nextRunTime = getNextEventRunTime(0, this.v.events[0], date.getTime()); + nextRunTime = getNextEventRunTime(0, this.v.events[0], date.getTime(), pastGracePeriod); if(nextRunTime < new Date().getTime()){ var runTime = new Date(date); runTime.setDate(runTime.getDate() + parseInt(this.v.events[0].d.value)); - nextRunTime = getNextEventRunTime(0, this.v.events[0], runTime.getTime()); //already passed this time today, try again after "interval" days + nextRunTime = getNextEventRunTime(0, this.v.events[0], runTime.getTime(), pastGracePeriod); //already passed this time today, try again after "interval" days } return nextRunTime; @@ -593,6 +573,9 @@ com.telldus.scheduler = function() { if(!this.v.events){ return 0; } + + var pastGracePeriod = getGracePeriod(this.v); + for(var key in this.v.events){ //get next correct day of week, may be today too var weekday = parseInt(this.v.events[key].d.value); @@ -608,10 +591,10 @@ com.telldus.scheduler = function() { returnDate = zeroTime(returnDate); - nextTempRunTime = getNextEventRunTime(0, this.v.events[key], returnDate.getTime()); + nextTempRunTime = getNextEventRunTime(0, this.v.events[key], returnDate.getTime(), pastGracePeriod); if(nextTempRunTime < new Date().getTime()){ //event happened today, already passed, add to next week instead returnDate.setDate(returnDate.getDate() + 7); - nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime()); + nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); } else{ nextRunTime = nextTempRunTime; @@ -628,6 +611,9 @@ com.telldus.scheduler = function() { if(!this.v.events){ return 0; } + + var pastGracePeriod = getGracePeriod(this.v); + for(var key in this.v.events){ //get next x day of month, may be today, for the current month if(!this.v.events[key].d.value || this.v.events[key].d.value.toString().indexOf("-") == -1){ //make sure value is of correct format @@ -645,7 +631,7 @@ com.telldus.scheduler = function() { } var nextdate = getNextLeapYearSafeDate(now.getFullYear(), month, day, this.v.events[key]); - if(nextdate < new Date().getTime()){ //event already happened this year, add to next year instead + if((nextdate + pastGracePeriod) < new Date().getTime()){ //event already happened this year, add to next year instead var tempdate = new Date(nextdate); tempdate.setYear(now.getFullYear() + 1); nextdate = tempdate.getTime(); @@ -710,6 +696,8 @@ com.telldus.scheduler = function() { return { //Public functions addJob: addJob, removeJob: removeJob, + updateJob: updateJob, + //TODO getNextRunForJob? For all? init:init //TODO change this } }(); From e0ee9f061b62607884d143a1eefd968e1ba918d7 Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Tue, 4 Jan 2011 18:22:30 +0000 Subject: [PATCH 1488/2215] Added images for Brennenstuhl --- .../images/devices/brennenstuhl_cs.png | Bin 0 -> 14441 bytes .../TelldusGui/images/vendors/brennenstuhl.png | Bin 0 -> 3272 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/brennenstuhl_cs.png create mode 100644 telldus-gui/TelldusGui/images/vendors/brennenstuhl.png diff --git a/telldus-gui/TelldusGui/images/devices/brennenstuhl_cs.png b/telldus-gui/TelldusGui/images/devices/brennenstuhl_cs.png new file mode 100644 index 0000000000000000000000000000000000000000..1647d76e94eeb9e221978c615b4cc2e3c1f095b2 GIT binary patch literal 14441 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 KqY6XkhyMk!1{^>D literal 0 HcmV?d00001 From 156944005035c5296c781517370a3932ebc832f4 Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Tue, 4 Jan 2011 18:25:20 +0000 Subject: [PATCH 1489/2215] Added Brennenstuhl to resources --- telldus-gui/TelldusGui/data/telldus/resources.qrc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index 822c60b3..5dfca93a 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -5,6 +5,7 @@ ../../images/devices/arctech_sl.png ../../images/devices/bell.png ../../images/devices/byebye.png + ../../images/devices/brennenstuhl_cs.png ../../images/devices/conrad-rsl888.png ../../images/devices/elro.png ../../images/devices/elro-ab600.png @@ -26,6 +27,7 @@ ../../images/vendors/chacon.png ../../images/vendors/coco.png ../../images/vendors/conrad.png + ../../images/vendors/brennenstuhl.png ../../images/vendors/elro.png ../../images/vendors/goobay.png ../../images/vendors/gao.png From 5b352af190e1134bd08a7333b63e13f3e5ea286e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Jan 2011 10:08:35 +0000 Subject: [PATCH 1490/2215] Start date (do not use schedule until) implemented. --- telldus-gui/Plugins/Scheduler/__init__.js | 64 +++++++++++++---------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 279cf240..1a2f77af 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -71,12 +71,9 @@ com.telldus.scheduler = function() { //TODO ordna upp, dela upp i flera filer, inte ladda jobb här (per plugin istället), bara "add job" här... //TODO ta bort absoluta events efter att de har passerats? Kan inte göras härifrån, får på ngt sätt ske därifrån de sparas/laddas - //TODO startdate - //det enda varje jobb har är getNextRunTime (som ska override:as) - - - // gränssnittet... hur...? - // + //TODO update last run, i respektive executemetod... bara? + //det enda varje jobb har är getNextRunTime (som ska override:as) (och ev. updateLastRun) + function init(){ loadJobs(); //load jobs from permanent storage TODO move @@ -130,13 +127,7 @@ com.telldus.scheduler = function() { } function updateLastRun(id, lastRun){ - /* - var settings = new com.telldus.settings(); - var jobs = settings.value("jobs", ""); - jobs[id].lastrun = lastRun; //update permanent storage - settings.setValue("jobs", jobs); - */ - //TODO... this will not be stored of course, how to do that? + //TODO... this will not be stored of course, how to do that? Maybe in the execute function per job too... print("Update last run: " + id + " to " + lastRun); storedJobs.get(id).v.lastRun = lastRun; //update current list } @@ -212,13 +203,16 @@ com.telldus.scheduler = function() { time3 = time1 - 60; time1 = time1 + 50; - var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: JOBTYPE_RECURRING_WEEK, startdate: "2010-01-01", lastRun: 0, device: 1, method: 1, value: ""}); - newRecurringMonthJob.addEvent(new Event({id: 0, value: 2, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time1})); + var startdate1 = new Date(2011,0,5).getTime(); + var startdate2 = new Date(2011,0,5).getTime(); + + var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: JOBTYPE_RECURRING_WEEK, startdate: startdate1, lastRun: 0, device: 1, method: 1, value: ""}); + newRecurringMonthJob.addEvent(new Event({id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time1})); newRecurringMonthJob.save(); - var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: JOBTYPE_RECURRING_MONTH, startdate: "2010-01-01", lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 90000}); - newAbsoluteJob.addEvent(new Event({id: 1, value: "00-04", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); - newAbsoluteJob.addEvent(new Event({id: 2, value: "00-04", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); + var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: JOBTYPE_RECURRING_MONTH, startdate: startdate2, lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 0}); + newAbsoluteJob.addEvent(new Event({id: 1, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); + newAbsoluteJob.addEvent(new Event({id: 2, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); newAbsoluteJob.save(); storedJobs = new MappedList(); @@ -334,6 +328,7 @@ com.telldus.scheduler = function() { * note, must in that case have checked last run */ function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod){ + if(!pastGracePeriod){ var pastGracePeriod = 0; } @@ -543,7 +538,6 @@ com.telldus.scheduler = function() { print("getNextRunTime day"); //Recurring day (every day, every other day or every x day) //only one event/job (at the moment at least) - //TODO test this var nextRunTime = 0; var pastGracePeriod = getGracePeriod(this.v); var date; @@ -554,8 +548,14 @@ com.telldus.scheduler = function() { date = date.getTime() + this.v.events[0].d.value; //add interval } else{ - var now = new Date(); //Now - date = new Date(now.getFullYear(), now.getMonth(), now.getDate()); + var startTime = new Date(); //Now + var minStartTime = new Date(this.v.startdate); + + if(minStartTime > startTime){ + //next run not until startTime is passed + startTime = minStartTime; + } + date = new Date(startTime.getFullYear(), startTime.getMonth(), startTime.getDate()); } nextRunTime = getNextEventRunTime(0, this.v.events[0], date.getTime(), pastGracePeriod); if(nextRunTime < new Date().getTime()){ @@ -584,6 +584,11 @@ com.telldus.scheduler = function() { continue; } var returnDate = new Date(); + var minStartTime = new Date(this.v.startdate); + if(minStartTime > returnDate){ + //next run not until startTime is passed + returnDate = minStartTime; + } var returnDay = returnDate.getDay(); if (weekday !== returnDay) { returnDate.setDate(returnDate.getDate() + (weekday + (7 - returnDay)) % 7); @@ -606,7 +611,6 @@ com.telldus.scheduler = function() { JobRecurringMonth.prototype.getNextRunTime = function(){ print("getNextRunTime month"); - //TODO test this var nextRunTime = 0; if(!this.v.events){ return 0; @@ -622,18 +626,22 @@ com.telldus.scheduler = function() { var daymonth = this.v.events[key].d.value.split('-'); //month-day var month = daymonth[0]; var day = daymonth[1]; - var now = new Date(); + var startTime = new Date(); //Now + var minStartTime = new Date(this.v.startdate); - if((32 - new Date(now.getFullYear(), month, 32).getDate()) < day){ //check that day exists for this month + if((32 - new Date(startTime.getFullYear(), month, 32).getDate()) < day){ //check that day exists for this month if(month != 1 && day != 29){ break; //this day doesn't exist for this month (at least not this year (leap year...)) } } - var nextdate = getNextLeapYearSafeDate(now.getFullYear(), month, day, this.v.events[key]); + var nextdate = getNextLeapYearSafeDate(startTime.getFullYear(), month, day, this.v.events[key]); - if((nextdate + pastGracePeriod) < new Date().getTime()){ //event already happened this year, add to next year instead + if((nextdate + pastGracePeriod) < new Date().getTime() || (nextdate + pastGracePeriod) < minStartTime){ //event already happened this year, or startTime not reached yet, add to next year instead var tempdate = new Date(nextdate); - tempdate.setYear(now.getFullYear() + 1); + tempdate.setYear(startTime.getFullYear() + 1); + if(tempdate < minStartTime){ + tempdate.setYear(tempdate.getFullYear() + 1); //no need to check if start date is reached this time, will always be recalculated before that, if nothing else at least by daylight saving time + } nextdate = tempdate.getTime(); } print("Candidate date: " + new Date(nextdate)); @@ -697,7 +705,7 @@ com.telldus.scheduler = function() { addJob: addJob, removeJob: removeJob, updateJob: updateJob, - //TODO getNextRunForJob? For all? + //TODO getNextRunForJob? For all? (to see when job is due to run next) init:init //TODO change this } }(); From 739f82bf363add2ca7065b46cb69ab7d0bbe19ba Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Jan 2011 10:19:25 +0000 Subject: [PATCH 1491/2215] Moved updateLastRun to be called by the jobs' execute function --- telldus-gui/Plugins/Scheduler/__init__.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 1a2f77af..7bbd0b46 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -107,7 +107,7 @@ com.telldus.scheduler = function() { var runJobFunc = function(){ runJob(job.id); }; var now = new Date().getTime(); var delay = nextRunTime - now; - print("Will run " + storedJobs.get(job.id).v.name + " at " + new Date(nextRunTime)); //Note not all will have a name + print("Will run " + storedJobs.get(job.id).v.name + " (" + job.id + ") at " + new Date(nextRunTime)); //Note not all will have a name print("(Now is " + new Date() + ")"); print("Delay: " + delay); timerid = setTimeout(runJobFunc, delay); //start the timer @@ -118,10 +118,6 @@ com.telldus.scheduler = function() { print("Running job, will execute"); queuedJob = null; var success = storedJobs.get(id).execute(); - //if(success){ - //update last run even if not successful, else it may become an infinite loop (if using pastGracePeriod) - updateLastRun(id, new Date().getTime()); - //} print("Job run, after delay " + id); updateJobInList(id); } @@ -418,6 +414,11 @@ com.telldus.scheduler = function() { default: break; } + //if(success){ + //update last run even if not successful, else it may become an infinite loop (if using pastGracePeriod) + com.telldus.scheduler.updateLastRun(id, new Date().getTime()); + //TODO update storage too + //} return success; }; @@ -702,9 +703,10 @@ com.telldus.scheduler = function() { } return { //Public functions - addJob: addJob, - removeJob: removeJob, - updateJob: updateJob, + addJob: addJob, //job, returns: storage id + removeJob: removeJob, //storage id + updateJob: updateJob, //storage id, job + updateLastRun: updateLastRun, //id, datetimestamp //TODO getNextRunForJob? For all? (to see when job is due to run next) init:init //TODO change this } From 399980f907b74be90122507e8fe273d9feceed0b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Jan 2011 10:40:06 +0000 Subject: [PATCH 1492/2215] Make sure the daylight saving time-job won't run in countries without dst --- telldus-gui/Plugins/Scheduler/__init__.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 7bbd0b46..7f0d229d 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -71,7 +71,6 @@ com.telldus.scheduler = function() { //TODO ordna upp, dela upp i flera filer, inte ladda jobb här (per plugin istället), bara "add job" här... //TODO ta bort absoluta events efter att de har passerats? Kan inte göras härifrån, får på ngt sätt ske därifrån de sparas/laddas - //TODO update last run, i respektive executemetod... bara? //det enda varje jobb har är getNextRunTime (som ska override:as) (och ev. updateLastRun) @@ -497,6 +496,11 @@ com.telldus.scheduler = function() { JobDaylightSavingReload.prototype.getNextRunTime = function(){ print("getNextRunTime DaylightSaving"); var dst = DstDetect(); + if(dst[0] == ""){ + //not using dst in this timezone, still add it to the lists to keep it consistent (will be added as 1/1 1970) + print("Not using timezone"); + return 0; + } var now = new Date().getTime(); var time = dst[0].getTime(); if(now > time){ From 2bda18960a12a1305b6519b4e04d703e97c3f328 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Jan 2011 13:31:57 +0000 Subject: [PATCH 1493/2215] Added vendor 'Brennenstuhl' --- telldus-gui/TelldusGui/data/telldus/devices.xml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index fa71510b..2ccffaac 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -2,10 +2,13 @@ - - - Code Switch - + + Code Switch + + + + Code Switch + Code Switch From 82db7d6cb9d450973302c2fbbd564ed7261fd6d7 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Jan 2011 14:56:45 +0000 Subject: [PATCH 1494/2215] Restructuring of scheduler files and their content --- telldus-gui/Plugins/Scheduler/CMakeLists.txt | 1 + .../Plugins/Scheduler/DefaultJobTypes.js | 357 +++++++++ telldus-gui/Plugins/Scheduler/__init__.js | 711 +++++------------- 3 files changed, 534 insertions(+), 535 deletions(-) create mode 100644 telldus-gui/Plugins/Scheduler/DefaultJobTypes.js diff --git a/telldus-gui/Plugins/Scheduler/CMakeLists.txt b/telldus-gui/Plugins/Scheduler/CMakeLists.txt index e481529a..02fb0d24 100644 --- a/telldus-gui/Plugins/Scheduler/CMakeLists.txt +++ b/telldus-gui/Plugins/Scheduler/CMakeLists.txt @@ -6,5 +6,6 @@ SET( Plugin_NAME "scheduler" ) SET( Plugin_PATH "com.telldus.scheduler" ) SET( Plugin_EXTRA "DaylightSavingTime.js") +SET( Plugin_EXTRA "DefaultJobTypes.js") INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js new file mode 100644 index 00000000..9cb89bea --- /dev/null +++ b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js @@ -0,0 +1,357 @@ +com.telldus.scheduler.JOBTYPE_ABSOLUTE = 0; +com.telldus.scheduler.JOBTYPE_RECURRING_DAY = 1; +com.telldus.scheduler.JOBTYPE_RECURRING_WEEK = 2; +com.telldus.scheduler.JOBTYPE_RECURRING_MONTH = 3; + +com.telldus.scheduler.EVENTTYPE_ABSOLUTE = 0; +com.telldus.scheduler.EVENTTYPE_SUNRISE = 1; +com.telldus.scheduler.EVENTTYPE_SUNSET = 2; + + +function getEventRunTime(event, date){ + var currentEventRuntimeTimestamp = null; + if(event.d.type == com.telldus.scheduler.EVENTTYPE_ABSOLUTE){ + currentEventRuntimeTimestamp = (event.d.time*1000) + date; + currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); + } + else if(event.d.type == com.telldus.scheduler.EVENTTYPE_SUNRISE || event.d.type == com.telldus.scheduler.EVENTTYPE_SUNSET){ + currentEventRuntimeTimestamp = getSunUpDownForDate(date, parseInt(event.d.type)); + currentEventRuntimeTimestamp += (event.d.offset * 1000); + currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); + } + + return currentEventRuntimeTimestamp; +} + +function getGracePeriod(v){ + var pastGracePeriod = 0; + var lastRun = 0; + if(v.lastRun){ + lastRun = v.lastRun; + } + if(v.pastGracePeriod){ + var timeSinceLastRun = (new Date().getTime() - lastRun); + if(timeSinceLastRun > v.pastGracePeriod){ + pastGracePeriod = v.pastGracePeriod; + } + else{ + pastGracePeriod = timeSinceLastRun; + } + } + + return pastGracePeriod; +} + + +function getJob(jobdata){ + //factory function... typ + var job = new com.telldus.scheduler.Job(); + var type = parseInt(jobdata.type); + + switch(type){ + case com.telldus.scheduler.JOBTYPE_ABSOLUTE: + job = new com.telldus.scheduler.JobAbsolute(jobdata); + break; + case com.telldus.scheduler.JOBTYPE_RECURRING_DAY: + job = new com.telldus.scheduler.JobRecurringDay(jobdata); + break; + case com.telldus.scheduler.JOBTYPE_RECURRING_WEEK: + job = new com.telldus.scheduler.JobRecurringWeek(jobdata); + break; + case com.telldus.scheduler.JOBTYPE_RECURRING_MONTH: + job = new com.telldus.scheduler.JobRecurringMonth(jobdata); + break; + default: + break; + } + job.v = jobdata; + return job; +} + +/* +* pastGracePeriod - optional, run events that should have been run, for example, 5 minutes ago, +* but wasn't, because of a reboot or similar (in ms) +* note, must in that case have checked last run +*/ +function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod){ + + if(!pastGracePeriod){ + var pastGracePeriod = 0; + } + + var currentEventRuntimeTimestamp = getEventRunTime(event, date); + if((nextRunTime === null || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > (new Date().getTime() - pastGracePeriod)){ //earlier than other events, but later than "now" + nextRunTime = currentEventRuntimeTimestamp; + } + + return nextRunTime; +} + +function getNextLeapYearSafeDate(year, month, day, event){ + if(month == 1 && day == 29){ + //get leap year + for(var i=0;i<5;i++){ + if(new Date(year+i,1,29).getDate() == 29){ + //this is a leap year + datetimestamp = getEventRunTime(event, new Date(year+1, 1, 29).getTime()); + if(datetimestamp > new Date().getTime()){ //else, this was a leap year, but already passed for this year + return datetimestamp; + } + } + } + } + else{ + var date = new Date(year, month, day); + return getEventRunTime(event, date.getTime()); + } +} + +function getSunUpDownForDate(datetimestamp, sun){ + date = new Date(datetimestamp); + var timevalues = com.telldus.suncalculator.riseset(date); + if(timevalues[2] && timevalues[2] != ""){ + return ""; //no sun up or down this day, do nothing + } + var hourminute; + if(sun == com.telldus.scheduler.EVENTTYPE_SUNRISE){ + hourminute = timevalues[0].split(':'); + } + else{ + hourminute = timevalues[1].split(':'); + } + date.setHours(hourminute[0]); + date.setMinutes(hourminute[1]); + return date.getTime(); +} + +function loadJobs(){ + print("Loading jobs"); + //TODO detta ska inte göras från denna plugin, utan från respektive... + //TODO hur ska id på event och job sättas för nya jobb/events? + //eventid är bara unika inom respektive jobb... + //TODO temp - creating events + var now = new Date(); + var time1 = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds(); + print(time1); // 48880 + time2 = time1 + 30; + time3 = time1 - 60; + time1 = time1 + 50; + + var startdate1 = new Date(2011,0,5).getTime(); + var startdate2 = new Date(2011,0,5).getTime(); + + var newRecurringMonthJob = getJob({id: 4, deviceid: 11, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate1, lastRun: 0, device: 1, method: 1, value: ""}); + newRecurringMonthJob.addEvent(new Event({id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time1})); + newRecurringMonthJob.save(); + + var newAbsoluteJob = getJob({id: 5, deviceid: 12, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_MONTH, startdate: startdate2, lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 90000}); + newAbsoluteJob.addEvent(new Event({id: 1, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); + newAbsoluteJob.addEvent(new Event({id: 2, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); + newAbsoluteJob.save(); + + //get all jobs from permanent storage + var settings = new com.telldus.settings(); + var storedJobsData = settings.value("jobs", ""); + + for(var key in storedJobsData){ + var jobdata = storedJobsData[key]; + var job = getJob(jobdata); + var tempkey = com.telldus.scheduler.addJob(job); //TODO, use different function than this = only sort list afterwards (one time) and dont start timer until all initial are added + } +} + +/* + Job.prototype.updateJobLastRun(){ + var timestamp = new Date().getTime(); + com.telldus.scheduler.updateLastRun(this.key, timestamp); + //override this to save last run to storage too, but don't forget to call the above method too + var jobs = settings.value("jobs", ""); + jobs[this.v.id].v.lastRun = timestamp; + settings.setValue("jobs", jobs); +} +*/ + +function zeroTime(date){ + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + date.setMilliseconds(0); + return date; +} + + +com.telldus.scheduler.Job.prototype.addEvent = function(event){ + if(!this.v.events){ + this.v.events = {}; + } + this.v.events[event.d.id] = event; +} + +com.telldus.scheduler.Job.prototype.save = function(){ + //TODO set properties + var settings = new com.telldus.settings(); + var jobs = settings.value("jobs", ""); + + if(!jobs){ + jobs = {}; //initialize new + } + + jobs[this.v.id] = this.v; + + settings.setValue("jobs", jobs); +} + + +com.telldus.scheduler.JobAbsolute = function(jobdata){} +com.telldus.scheduler.JobRecurringDay = function(jobdata){} +com.telldus.scheduler.JobRecurringWeek = function(jobdata){} +com.telldus.scheduler.JobRecurringMonth = function(jobdata){} + +com.telldus.scheduler.JobAbsolute.prototype = new com.telldus.scheduler.Job(); +com.telldus.scheduler.JobRecurringDay.prototype = new com.telldus.scheduler.Job(); +com.telldus.scheduler.JobRecurringWeek.prototype = new com.telldus.scheduler.Job(); +com.telldus.scheduler.JobRecurringMonth.prototype = new com.telldus.scheduler.Job(); + +com.telldus.scheduler.JobAbsolute.prototype.getNextRunTime = function(){ + print("getNextRunTime absolute"); + var nextRunTime = null; + + if(!this.v.events){ + return null; + } + + var pastGracePeriod = getGracePeriod(this.v); + + for(var key in this.v.events){ + nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], parseInt(this.v.events[key].d.value), pastGracePeriod); + } + return nextRunTime; +} + +com.telldus.scheduler.JobRecurringDay.prototype.getNextRunTime = function(){ + print("getNextRunTime day"); + //Recurring day (every day, every other day or every x day) + //only one event/job (at the moment at least) + var nextRunTime = null; + var pastGracePeriod = getGracePeriod(this.v); + var date; + + if(this.v.lastRun > 0){ + var lastRunDate = new Date(this.lastRun); + date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); + date = date.getTime() + this.v.events[0].d.value; //add interval + } + else{ + var startTime = new Date(); //Now + var minStartTime = new Date(this.v.startdate); + + if(minStartTime > startTime){ + //next run not until startTime is passed + startTime = minStartTime; + } + date = new Date(startTime.getFullYear(), startTime.getMonth(), startTime.getDate()); + } + nextRunTime = getNextEventRunTime(0, this.v.events[0], date.getTime(), pastGracePeriod); + if(nextRunTime < new Date().getTime()){ + var runTime = new Date(date); + runTime.setDate(runTime.getDate() + parseInt(this.v.events[0].d.value)); + nextRunTime = getNextEventRunTime(0, this.v.events[0], runTime.getTime(), pastGracePeriod); //already passed this time today, try again after "interval" days + } + + return nextRunTime; +} + +com.telldus.scheduler.JobRecurringWeek.prototype.getNextRunTime = function(){ + print("getNextRunTime week"); + var nextRunTime = null; + if(!this.v.events){ + return null; + } + + var pastGracePeriod = getGracePeriod(this.v); + + for(var key in this.v.events){ + //get next correct day of week, may be today too + var weekday = parseInt(this.v.events[key].d.value); + if(weekday > 6 || weekday <0){ + print("Incorrect weekday value"); + continue; + } + var returnDate = new Date(); + var minStartTime = new Date(this.v.startdate); + if(minStartTime > returnDate){ + //next run not until startTime is passed + returnDate = minStartTime; + } + var returnDay = returnDate.getDay(); + if (weekday !== returnDay) { + returnDate.setDate(returnDate.getDate() + (weekday + (7 - returnDay)) % 7); + } + + returnDate = zeroTime(returnDate); + + nextTempRunTime = getNextEventRunTime(0, this.v.events[key], returnDate.getTime(), pastGracePeriod); + if(nextTempRunTime < new Date().getTime()){ //event happened today, already passed, add to next week instead + returnDate.setDate(returnDate.getDate() + 7); + nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); + } + else{ + nextRunTime = nextTempRunTime; + } + } + + return nextRunTime; +} + +com.telldus.scheduler.JobRecurringMonth.prototype.getNextRunTime = function(){ + print("getNextRunTime month"); + var nextRunTime = null; + if(!this.v.events){ + return null; + } + + var pastGracePeriod = getGracePeriod(this.v); + + for(var key in this.v.events){ + //get next x day of month, may be today, for the current month + if(!this.v.events[key].d.value || this.v.events[key].d.value.toString().indexOf("-") == -1){ //make sure value is of correct format + continue; + } + var daymonth = this.v.events[key].d.value.split('-'); //month-day + var month = daymonth[0]; + var day = daymonth[1]; + var startTime = new Date(); //Now + var minStartTime = new Date(this.v.startdate); + + if((32 - new Date(startTime.getFullYear(), month, 32).getDate()) < day){ //check that day exists for this month + if(month != 1 && day != 29){ + break; //this day doesn't exist for this month (at least not this year (leap year...)) + } + } + var nextdate = getNextLeapYearSafeDate(startTime.getFullYear(), month, day, this.v.events[key]); + + if((nextdate + pastGracePeriod) < new Date().getTime() || (nextdate + pastGracePeriod) < minStartTime){ //event already happened this year, or startTime not reached yet, add to next year instead + var tempdate = new Date(nextdate); + tempdate.setYear(startTime.getFullYear() + 1); + if(tempdate < minStartTime){ + tempdate.setYear(tempdate.getFullYear() + 1); //no need to check if start date is reached this time, will always be recalculated before that, if nothing else at least by daylight saving time + } + nextdate = tempdate.getTime(); + } + print("Candidate date: " + new Date(nextdate)); + if(nextRunTime === null || nextRunTime > nextdate){ + nextRunTime = nextdate; + } + } + + return nextRunTime; +} + +function Event(data){ + if(data){ + this.d = data; + } + else{ + this.d = {}; + } +} diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 7f0d229d..f2e5ca75 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -1,24 +1,12 @@ __setupPackage__( __extension__ ); -include("DaylightSavingTime.js"); - __postInit__ = function() { application.allDoneLoading.connect( com.telldus.scheduler.init ); } - -com.telldus.scheduler = function() { - - var JOBTYPE_ABSOLUTE = 0; //jobtypes? Not here at least... - var JOBTYPE_RECURRING_DAY = 1; - var JOBTYPE_RECURRING_WEEK = 2; - var JOBTYPE_RECURRING_MONTH = 3; - //var JOBTYPE_RELOAD = 4; //for summer/winter time - - var EVENTTYPE_ABSOLUTE = 0; - var EVENTTYPE_SUNRISE = 1; - var EVENTTYPE_SUNSET = 2; - var storedJobs; +com.telldus.scheduler = function() { + + var storedJobs = new MappedList(); var joblist; var timerid; var queuedJob; @@ -70,14 +58,101 @@ com.telldus.scheduler = function() { //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... //TODO ordna upp, dela upp i flera filer, inte ladda jobb här (per plugin istället), bara "add job" här... + //var ska "job" och "event" vara? Går det att ha inne i scheduler på ngt sätt? (och ändå kunna ärva utifrån) + //eller ha dem som egna "klasser"? + //ta bort loadJobs + //updateLastRun... måste anpassas för storage... på defaultjobben alltså... //TODO ta bort absoluta events efter att de har passerats? Kan inte göras härifrån, får på ngt sätt ske därifrån de sparas/laddas //det enda varje jobb har är getNextRunTime (som ska override:as) (och ev. updateLastRun) + //TODO nextRunTime = 0 ska ju inte köras, men negativa värden ska ju köras ibland (med graceTime) function init(){ + JobDaylightSavingReload.prototype = new com.telldus.scheduler.Job(); loadJobs(); //load jobs from permanent storage TODO move } + + function addJob(job){ + if(storedJobs.length == 0){ + print("Adding daylight saving time"); + var daylightSavingReloadKey = storedJobs.push(getDaylightSavingReloadJob()); + updateJobInList(daylightSavingReloadKey); + } + var key = storedJobs.push(job); + job.key = key; + print("Add job"); + updateJobInList(key); + return key; + } + + function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter){ + if(fuzzinessAfter != 0 || fuzzinessBefore != 0){ + var interval = fuzzinessAfter + fuzzinessBefore; + var rand = Math.random(); //Random enough at the moment + var fuzziness = Math.floor((interval+1) * rand); + fuzziness = fuzziness - fuzzinessBefore; + currentTimestamp += (fuzziness * 1000); + } + return currentTimestamp; + } + + function getDaylightSavingReloadJob(){ + return new JobDaylightSavingReload(); + } + + function recalculateAllJobs(){ + print("Recalculating all jobs"); + + joblist = new Array(); + + for(var key in storedJobs.container){ + var job = storedJobs.get(key); + var nextRunTime = job.getNextRunTime(); + print("Run time: " + new Date(nextRunTime)); + if(nextRunTime === null){ + print("Will not run"); + continue; + } + joblist.push(new RunJob(key, nextRunTime)); + } + + joblist.sort(compareTime); + runNextJob(); + } + + function removeFromJobList(id){ + if(!joblist){ + return; + } + for(i=0;i new Date().getTime()){ //else, this was a leap year, but already passed for this year - return datetimestamp; - } - } - } - } - else{ - var date = new Date(year, month, day); - return getEventRunTime(event, date.getTime()); - } - } - - function zeroTime(date){ - date.setHours(0); - date.setMinutes(0); - date.setSeconds(0); - date.setMilliseconds(0); - return date; - } - - /* - * pastGracePeriod - optional, run events that should have been run, for example, 5 minutes ago, - * but wasn't, because of a reboot or similar (in ms) - * note, must in that case have checked last run - */ - function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod){ - - if(!pastGracePeriod){ - var pastGracePeriod = 0; - } - - var currentEventRuntimeTimestamp = getEventRunTime(event, date); - if((nextRunTime == 0 || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > (new Date().getTime() - pastGracePeriod)){ //earlier than other events, but later than "now" - nextRunTime = currentEventRuntimeTimestamp; - } - - return nextRunTime; - } - - function getEventRunTime(event, date){ - var currentEventRuntimeTimestamp = 0; - if(event.d.type == EVENTTYPE_ABSOLUTE){ - currentEventRuntimeTimestamp = (event.d.time*1000) + date; - currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); - } - else if(event.d.type == EVENTTYPE_SUNRISE || event.d.type == EVENTTYPE_SUNSET){ - currentEventRuntimeTimestamp = getSunUpDownForDate(date, parseInt(event.d.type)); - currentEventRuntimeTimestamp += (event.d.offset * 1000); - currentEventRuntimeTimestamp = fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); - } - - return currentEventRuntimeTimestamp; - } - - function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter){ - if(fuzzinessAfter != 0 || fuzzinessBefore != 0){ - var interval = fuzzinessAfter + fuzzinessBefore; - var rand = Math.random(); //Random enough at the moment - var fuzziness = Math.floor((interval+1) * rand); - fuzziness = fuzziness - fuzzinessBefore; - currentTimestamp += (fuzziness * 1000); - } - return currentTimestamp; - } - - function getSunUpDownForDate(datetimestamp, sun){ - - date = new Date(datetimestamp); - var timevalues = com.telldus.suncalculator.riseset(date); - if(timevalues[2] && timevalues[2] != ""){ - return ""; //no sun up or down this day, do nothing - } - var hourminute; - if(sun == EVENTTYPE_SUNRISE){ - hourminute = timevalues[0].split(':'); - } - else{ - hourminute = timevalues[1].split(':'); - } - date.setHours(hourminute[0]); - date.setMinutes(hourminute[1]); - return date.getTime(); - - } - - function Job(jobdata) { - if(jobdata){ - this.v = jobdata; - } - else{ - this.v = {}; - } - } - - Job.prototype.execute = function(){ - //may be overridden if other than device manipulation should be performed - var success = 0; - print("Job id: " + this.v.id); - id = this.v.id; - var method = parseInt(this.method); - switch(method){ - case com.telldus.core.TELLSTICK_TURNON: - success = com.telldus.core.turnOn(id); - break; - case com.telldus.core.TELLSTICK_TURNOFF: - success = com.telldus.core.turnOff(id); - break; - case com.telldus.core.TELLSTICK_DIM: - success = com.telldus.core.dim(id, this.v.value); - break; - case com.telldus.core.TELLSTICK_BELL: - success = com.telldus.core.bell(id); - break; - default: - break; - } - //if(success){ - //update last run even if not successful, else it may become an infinite loop (if using pastGracePeriod) - com.telldus.scheduler.updateLastRun(id, new Date().getTime()); - //TODO update storage too - //} - return success; - }; - - Job.prototype.addEvent = function(event){ - if(!this.v.events){ - this.v.events = {}; - } - this.v.events[event.d.id] = event; - } - - Job.prototype.getNextRunTime = function(){ - print("getNextRunTime default"); - return 0; //default - } - - //TODO move (or? maybe this could be here as default? maybe not, but keep the concept) - Job.prototype.save = function(){ - //TODO set properties - var settings = new com.telldus.settings(); - var jobs = settings.value("jobs", ""); - - if(!jobs){ - jobs = {}; //initialize new - } - - jobs[this.v.id] = this.v; - - settings.setValue("jobs", jobs); - } - - function getGracePeriod(v){ - var pastGracePeriod = 0; - var lastRun = 0; - if(v.lastRun){ - lastRun = v.lastRun; - } - if(v.pastGracePeriod){ - var timeSinceLastRun = (new Date().getTime() - lastRun); - if(timeSinceLastRun > v.pastGracePeriod){ - pastGracePeriod = v.pastGracePeriod; - } - else{ - pastGracePeriod = timeSinceLastRun; - } - } - - return pastGracePeriod; - } - - function JobAbsolute(jobdata){ - - } - - function JobRecurringDay(jobdata){ - - } - - function JobRecurringWeek(jobdata){ - - } - - function JobRecurringMonth(jobdata){ - - } - - //keep this here - function JobDaylightSavingReload(){ - } - - JobAbsolute.prototype = new Job(); - JobRecurringDay.prototype = new Job(); - JobRecurringWeek.prototype = new Job(); - JobRecurringMonth.prototype = new Job(); - JobDaylightSavingReload.prototype = new Job(); - - JobDaylightSavingReload.prototype.getNextRunTime = function(){ - print("getNextRunTime DaylightSaving"); - var dst = DstDetect(); - if(dst[0] == ""){ - //not using dst in this timezone, still add it to the lists to keep it consistent (will be added as 1/1 1970) - print("Not using timezone"); - return 0; - } - var now = new Date().getTime(); - var time = dst[0].getTime(); - if(now > time){ - //already passed - time = dst[1].getTime(); - } - return time; - } + function JobDaylightSavingReload(){} JobDaylightSavingReload.prototype.execute = function(){ //override default @@ -520,158 +241,37 @@ com.telldus.scheduler = function() { return 0; }; - JobAbsolute.prototype.getNextRunTime = function(){ - print("getNextRunTime absolute"); - //Get all events in this job (absolute = - //kan vara flera absoluta datum och tidpunkter på ett jobb) - //var events = job.events; - var nextRunTime = 0; - - if(!this.v.events){ - return 0; + JobDaylightSavingReload.prototype.getNextRunTime = function(){ + print("getNextRunTime DaylightSaving"); + var dst = DstDetect(); + if(dst[0] == ""){ + //not using dst in this timezone, still add it to the lists to keep it consistent (will be added as 1/1 1970) + print("Not using timezone"); + return null; } - - var pastGracePeriod = getGracePeriod(this.v); - - for(var key in this.v.events){ - nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], parseInt(this.v.events[key].d.value), pastGracePeriod); + var now = new Date().getTime(); + var time = dst[0].getTime(); + if(now > time){ + //already passed + time = dst[1].getTime(); } - return nextRunTime; + return time; } - JobRecurringDay.prototype.getNextRunTime = function(){ - print("getNextRunTime day"); - //Recurring day (every day, every other day or every x day) - //only one event/job (at the moment at least) - var nextRunTime = 0; - var pastGracePeriod = getGracePeriod(this.v); - var date; - - if(this.v.lastRun > 0){ - var lastRunDate = new Date(this.lastRun); - date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); - date = date.getTime() + this.v.events[0].d.value; //add interval - } - else{ - var startTime = new Date(); //Now - var minStartTime = new Date(this.v.startdate); - - if(minStartTime > startTime){ - //next run not until startTime is passed - startTime = minStartTime; - } - date = new Date(startTime.getFullYear(), startTime.getMonth(), startTime.getDate()); - } - nextRunTime = getNextEventRunTime(0, this.v.events[0], date.getTime(), pastGracePeriod); - if(nextRunTime < new Date().getTime()){ - var runTime = new Date(date); - runTime.setDate(runTime.getDate() + parseInt(this.v.events[0].d.value)); - nextRunTime = getNextEventRunTime(0, this.v.events[0], runTime.getTime(), pastGracePeriod); //already passed this time today, try again after "interval" days - } - - return nextRunTime; - } - - JobRecurringWeek.prototype.getNextRunTime = function(){ - print("getNextRunTime week"); - var nextRunTime = 0; - if(!this.v.events){ - return 0; - } - - var pastGracePeriod = getGracePeriod(this.v); - - for(var key in this.v.events){ - //get next correct day of week, may be today too - var weekday = parseInt(this.v.events[key].d.value); - if(weekday > 6 || weekday <0){ - print("Incorrect weekday value"); - continue; - } - var returnDate = new Date(); - var minStartTime = new Date(this.v.startdate); - if(minStartTime > returnDate){ - //next run not until startTime is passed - returnDate = minStartTime; - } - var returnDay = returnDate.getDay(); - if (weekday !== returnDay) { - returnDate.setDate(returnDate.getDate() + (weekday + (7 - returnDay)) % 7); - } - - returnDate = zeroTime(returnDate); - - nextTempRunTime = getNextEventRunTime(0, this.v.events[key], returnDate.getTime(), pastGracePeriod); - if(nextTempRunTime < new Date().getTime()){ //event happened today, already passed, add to next week instead - returnDate.setDate(returnDate.getDate() + 7); - nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); - } - else{ - nextRunTime = nextTempRunTime; - } - } - - return nextRunTime; - } - - JobRecurringMonth.prototype.getNextRunTime = function(){ - print("getNextRunTime month"); - var nextRunTime = 0; - if(!this.v.events){ - return 0; - } - - var pastGracePeriod = getGracePeriod(this.v); - - for(var key in this.v.events){ - //get next x day of month, may be today, for the current month - if(!this.v.events[key].d.value || this.v.events[key].d.value.toString().indexOf("-") == -1){ //make sure value is of correct format - continue; - } - var daymonth = this.v.events[key].d.value.split('-'); //month-day - var month = daymonth[0]; - var day = daymonth[1]; - var startTime = new Date(); //Now - var minStartTime = new Date(this.v.startdate); - - if((32 - new Date(startTime.getFullYear(), month, 32).getDate()) < day){ //check that day exists for this month - if(month != 1 && day != 29){ - break; //this day doesn't exist for this month (at least not this year (leap year...)) - } - } - var nextdate = getNextLeapYearSafeDate(startTime.getFullYear(), month, day, this.v.events[key]); - - if((nextdate + pastGracePeriod) < new Date().getTime() || (nextdate + pastGracePeriod) < minStartTime){ //event already happened this year, or startTime not reached yet, add to next year instead - var tempdate = new Date(nextdate); - tempdate.setYear(startTime.getFullYear() + 1); - if(tempdate < minStartTime){ - tempdate.setYear(tempdate.getFullYear() + 1); //no need to check if start date is reached this time, will always be recalculated before that, if nothing else at least by daylight saving time - } - nextdate = tempdate.getTime(); - } - print("Candidate date: " + new Date(nextdate)); - if(nextRunTime == 0 || nextRunTime > nextdate){ - nextRunTime = nextdate; - } - } - - return nextRunTime; - } - - function Event(data){ - if(data){ - this.d = data; - } - else{ - this.d = {}; - } - } function MappedList() { this.container = {}; this.length = 0; } + MappedList.prototype.contains = function(key){ + return !(this.container[key] === undefined); + } + + MappedList.prototype.get = function(key){ + return this.container[key]; + } + MappedList.prototype.push = function(element){ //TODO reusing keys at the moment, that's ok, right? var length = this.length; @@ -680,42 +280,83 @@ com.telldus.scheduler = function() { return length; } - MappedList.prototype.get = function(key){ - return this.container[key]; - } - - MappedList.prototype.update = function(key, element){ - this.container[key] = element; - } - MappedList.prototype.remove = function(key){ delete this.container[key]; this.length--; } - MappedList.prototype.contains = function(key){ - return !(this.container[key] === undefined); + MappedList.prototype.update = function(key, element){ + this.container[key] = element; } - function RunJob(id, nextRunTime, type, device, method, value){ + function RunJob(id, nextRunTime){ //, type, device, method, value){ this.id = id; this.nextRunTime = nextRunTime; - this.type = type; - this.device = device; - this.method = method; - this.value = value; } return { //Public functions addJob: addJob, //job, returns: storage id + fuzzify: fuzzify, //timestamp, max fuzziness before, max fuzziness after, returns: new random timestamp within min/max fuzziness-boundries removeJob: removeJob, //storage id updateJob: updateJob, //storage id, job updateLastRun: updateLastRun, //id, datetimestamp //TODO getNextRunForJob? For all? (to see when job is due to run next) - init:init //TODO change this + init:init } }(); function compareTime(a, b) { return a.nextRunTime - b.nextRunTime; } + +com.telldus.scheduler.Job = function(jobdata) { + if(jobdata){ + this.v = jobdata; + } + else{ + this.v = {}; + } +} + +com.telldus.scheduler.Job.prototype.execute = function(){ + //may be overridden if other than device manipulation should be performed + var success = 0; + print("Job id: " + this.v.deviceid); + deviceid = this.v.deviceid; + var method = parseInt(this.method); + switch(method){ + case com.telldus.core.TELLSTICK_TURNON: + success = com.telldus.core.turnOn(deviceid); + break; + case com.telldus.core.TELLSTICK_TURNOFF: + success = com.telldus.core.turnOff(deviceid); + break; + case com.telldus.core.TELLSTICK_DIM: + success = com.telldus.core.dim(deviceid, this.v.value); + break; + case com.telldus.core.TELLSTICK_BELL: + success = com.telldus.core.bell(deviceid); + break; + default: + break; + } + //if(success){ + //update last run even if not successful, else it may become an infinite loop (if using pastGracePeriod) + this.updateJobLastRun(); + //} + return success; +}; + +com.telldus.scheduler.Job.prototype.getNextRunTime = function(){ + print("getNextRunTime default"); + return null; //default +} + +com.telldus.scheduler.Job.prototype.updateJobLastRun = function(){ + var timestamp = new Date().getTime(); + com.telldus.scheduler.updateLastRun(this.key, timestamp); + //override this to save last run to storage too, but don't forget to call the above method too +} + +include("DefaultJobTypes.js"); +include("DaylightSavingTime.js"); \ No newline at end of file From b8bc3a870f8b78dcaf4b1c0708059446f60896d6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 7 Jan 2011 11:50:29 +0000 Subject: [PATCH 1495/2215] Code cleanup, small fix for recurring_week --- .../Plugins/Scheduler/DefaultJobTypes.js | 91 +++++++++++-- telldus-gui/Plugins/Scheduler/__init__.js | 128 ++++++------------ 2 files changed, 118 insertions(+), 101 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js index 9cb89bea..2db1a7e7 100644 --- a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js +++ b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js @@ -10,13 +10,21 @@ com.telldus.scheduler.EVENTTYPE_SUNSET = 2; function getEventRunTime(event, date){ var currentEventRuntimeTimestamp = null; + var offset = event.d.offset; + if(isNaN(offset)){ + offset = 0; + } if(event.d.type == com.telldus.scheduler.EVENTTYPE_ABSOLUTE){ - currentEventRuntimeTimestamp = (event.d.time*1000) + date; + if(isNaN(date)){ + date = 0; + } + currentEventRuntimeTimestamp = (event.d.time * 1000) + date; + currentEventRuntimeTimestamp += (offset * 1000); //this is really not useful for absolute values, but exists for consistency currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); } else if(event.d.type == com.telldus.scheduler.EVENTTYPE_SUNRISE || event.d.type == com.telldus.scheduler.EVENTTYPE_SUNSET){ currentEventRuntimeTimestamp = getSunUpDownForDate(date, parseInt(event.d.type)); - currentEventRuntimeTimestamp += (event.d.offset * 1000); + currentEventRuntimeTimestamp += (offset * 1000); currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); } @@ -31,8 +39,8 @@ function getGracePeriod(v){ } if(v.pastGracePeriod){ var timeSinceLastRun = (new Date().getTime() - lastRun); - if(timeSinceLastRun > v.pastGracePeriod){ - pastGracePeriod = v.pastGracePeriod; + if(timeSinceLastRun > (v.pastGracePeriod * 1000)){ + pastGracePeriod = (v.pastGracePeriod * 1000); } else{ pastGracePeriod = timeSinceLastRun; @@ -70,7 +78,7 @@ function getJob(jobdata){ /* * pastGracePeriod - optional, run events that should have been run, for example, 5 minutes ago, -* but wasn't, because of a reboot or similar (in ms) +* but wasn't, because of a reboot or similar (in seconds) * note, must in that case have checked last run */ function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod){ @@ -127,8 +135,6 @@ function getSunUpDownForDate(datetimestamp, sun){ function loadJobs(){ print("Loading jobs"); //TODO detta ska inte göras från denna plugin, utan från respektive... - //TODO hur ska id på event och job sättas för nya jobb/events? - //eventid är bara unika inom respektive jobb... //TODO temp - creating events var now = new Date(); var time1 = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds(); @@ -140,11 +146,13 @@ function loadJobs(){ var startdate1 = new Date(2011,0,5).getTime(); var startdate2 = new Date(2011,0,5).getTime(); - var newRecurringMonthJob = getJob({id: 4, deviceid: 11, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate1, lastRun: 0, device: 1, method: 1, value: ""}); - newRecurringMonthJob.addEvent(new Event({id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time1})); + //ID = ID for storage + //Key is position in list, returned from "addJob" + var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_ABSOLUTE, startdate: startdate1, lastRun: 0, device: 1, method: 1, value: ""}); + newRecurringMonthJob.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 50})); newRecurringMonthJob.save(); - var newAbsoluteJob = getJob({id: 5, deviceid: 12, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_MONTH, startdate: startdate2, lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 90000}); + var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_MONTH, startdate: startdate2, lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 90}); newAbsoluteJob.addEvent(new Event({id: 1, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); newAbsoluteJob.addEvent(new Event({id: 2, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); newAbsoluteJob.save(); @@ -161,6 +169,7 @@ function loadJobs(){ } /* + * updateLastRun-example: Job.prototype.updateJobLastRun(){ var timestamp = new Date().getTime(); com.telldus.scheduler.updateLastRun(this.key, timestamp); @@ -201,10 +210,62 @@ com.telldus.scheduler.Job.prototype.save = function(){ settings.setValue("jobs", jobs); } - +/* + * Job for device manipulation on absolute run times (i.e. one time jobs). Job will run at one or several occations, where each occation is added as a separate event + * To control more than one device, create a scene and run that one in the job. + * Job properties: + * id - id for storage purposes (e.g. removal/update), name - optional, + * lastRun - 0 for all new jobs, device - id of device to perform action on, + * method - action to perform on device, value - optional value to pass to method, + * pastGracePeriod - if job run time has been missed (for example due to a reboot), run it on program startup, if it should have run + * within the last "pastGracePeriod" seconds + * type is com.telldus.scheduler.JOBTYPE_ABSOLUTE + * Event properties: + * id - for storage purposes (e.g. removal/update) + * fuzzinessBefore/fuzzinessAfter - an interval (in seconds) in which the runtime will be randomized, if the job should run at slightly different times each time + * type - EVENTTYPE_ABSOLUTE, EVENTTYPE_SUNRISE or EVENTTYPE_SUNSET + * time - time and date for event run, in seconds since 1970-01-01 + * offset - time (in seconds, positive or negative) to adjust the runtime, useful if something for example should occur 20 minutes past sunrise + */ com.telldus.scheduler.JobAbsolute = function(jobdata){} + +/* + * Recurring job for device manipulation, same time every day or every x day ("value") + * To control more than one device, create a scene and run that one in the job. + * Schedule will not come into effect until "startdate" (timestamp) is passed + * Extra/different job properties: + * startdate - when schedule will come into effect, + * pastGracePeriod - if job run time has been missed (for example due to a reboot), run it on program startup, if it should have run + * within the last "pastGracePeriod" seconds + * type is com.telldus.scheduler.JOBTYPE_RECURRING_DAY + * Extra/different event properties: + * value - repeat every "value" day, starting from startdate, + */ com.telldus.scheduler.JobRecurringDay = function(jobdata){} + +/* + * Recurring job for device manipulation, can have several events, each event has a time of day ("time") and weekday ("value", 0-6) when to run + * To control more than one device, create a scene and run that one in the job. + * If a job should run every weekday, 5 events are needed with values from 1-5 + * Schedule will not come into effect until "startdate" (timestamp) is passed + * Extra/different job properties: + * type is com.telldus.scheduler.JOBTYPE_RECURRING_WEEK + * Extra/different event properties: + * value - day of week + */ com.telldus.scheduler.JobRecurringWeek = function(jobdata){} + +/* + * Recurring job for device manipulation, each event runs on a certain date of a certain month (i.e. next run for an event will be a year later) + * To control more than one device, create a scene and run that one in the job. + * If a job should run on a special day each month, 12 events will have to be created + * Event value should be stored in the format "00-05", 00 being the month (January, 0-11) and 05 the day of the month + * Schedule will not come into effect until "startdate" (timestamp) is passed + * Extra/different job properties: + * type is com.telldus.scheduler.JOBTYPE_RECURRING_MONTH + * Extra/different event properties: + * value - "month-day" + */ com.telldus.scheduler.JobRecurringMonth = function(jobdata){} com.telldus.scheduler.JobAbsolute.prototype = new com.telldus.scheduler.Job(); @@ -223,7 +284,7 @@ com.telldus.scheduler.JobAbsolute.prototype.getNextRunTime = function(){ var pastGracePeriod = getGracePeriod(this.v); for(var key in this.v.events){ - nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], parseInt(this.v.events[key].d.value), pastGracePeriod); + nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], 0, pastGracePeriod); } return nextRunTime; } @@ -251,11 +312,11 @@ com.telldus.scheduler.JobRecurringDay.prototype.getNextRunTime = function(){ } date = new Date(startTime.getFullYear(), startTime.getMonth(), startTime.getDate()); } - nextRunTime = getNextEventRunTime(0, this.v.events[0], date.getTime(), pastGracePeriod); + nextRunTime = getNextEventRunTime(null, this.v.events[0], date.getTime(), pastGracePeriod); if(nextRunTime < new Date().getTime()){ var runTime = new Date(date); runTime.setDate(runTime.getDate() + parseInt(this.v.events[0].d.value)); - nextRunTime = getNextEventRunTime(0, this.v.events[0], runTime.getTime(), pastGracePeriod); //already passed this time today, try again after "interval" days + nextRunTime = getNextEventRunTime(null, this.v.events[0], runTime.getTime(), pastGracePeriod); //already passed this time today, try again after "interval" days } return nextRunTime; @@ -290,7 +351,7 @@ com.telldus.scheduler.JobRecurringWeek.prototype.getNextRunTime = function(){ returnDate = zeroTime(returnDate); - nextTempRunTime = getNextEventRunTime(0, this.v.events[key], returnDate.getTime(), pastGracePeriod); + nextTempRunTime = getNextEventRunTime(null, this.v.events[key], returnDate.getTime(), pastGracePeriod); if(nextTempRunTime < new Date().getTime()){ //event happened today, already passed, add to next week instead returnDate.setDate(returnDate.getDate() + 7); nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index f2e5ca75..672c86be 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -6,70 +6,24 @@ __postInit__ = function() { com.telldus.scheduler = function() { - var storedJobs = new MappedList(); - var joblist; - var timerid; - var queuedJob; + var storedJobs = new MappedList(); //all jobs, added by "addJob" + var joblist; //sorted list containing next run time (and id) for all storedJobs + var timerid; //id of currently running timer, used when timer should be aborted + var queuedJob; //job currently in running timer, is already removed from joblist - - //1. hämta redan satta jobb - //(kolla om något jobb borde ha körts sedan förra ggn (och att det inte kördes då)) - //2. räkna ut när de ska köras nästa ggn, inkludera solens upp/nergång, fuzziness etc - //3. ordna i lista, spara undan första tidsvärdet enkelt åtkomligt - //4. kör tills tidsvärdet <= timestamp, kolla en ggn/sekund... - - // räkna om varje ggn ngn ändring sker med tider, läggs till/tas bort... - - - //hur ska jobb sparas? - //vilka typer av tider ska finnas? - // absoluta värden - ett enda tillfälle - // fr.o.m viss tidpunkt: - // återkommande, viss tid varje dag - // återkommande, viss tid vissa veckodagar (ev. var x:e vecka) (samlat i ett jobb, eller samma tid för alla markerade dagar?) - // återkommande, viss tid vissa dagar i månaden (datum och "siste", eventuellt (är detta någonsin intressant för tellstickstyrning?) första-andra-tredje-fjärde-sista veckodagen i månaden) - // återkommande, viss tid var x:e dag (hyfsat enkelt att implementera, men är detta intressant för tellstickstyrning?) - // fuzzy på alla, x min före och x min efter (kan klart sättas till noll), vid TelldusCenter-start slumpas ett absolutvärde inom detta intervall fram - // solens upp/nedgång kan väljas som tidpunkt på alla dagar - // viss tid från viss action bestäms från den actionen, om t.ex. en scen ska utföra ngt efter en viss tid så får den göra ett exakt-tid-tillägg (hur det ska fungera vet jag inte, - //men tycker att scener ska kunna innehålla tidsfördröjningar mha detta... Men hur återuppta scen liksom? Kanske kunde man låta "värde" i en scen vara from vilket steg det ska - //återupptas? Varför inte? I framtiden alltså. Execute får alltså ett värde (default inget = från start)) - // varje jobbtidpunkt måste alltså lagras som: - // ---------------------------- - // typ - dagintervall (det normala, 1), - viss veckodag (lista med aktiva veckodagar), - viss dag i månaden, speciellt värde för "den siste", - speciella tidpunkt(er) - // varje dag/tidpunkt kan ha följande värden (om man gör det per dag): - // fuzzy innan - // fuzzy efter - // använd solens uppgång/nedgång/absolut tidpunkt - // på/avdrag från solens upp/nedgång - // startdag - // tid för föregående körning, om någon - // ------------------------------- - // Framtidssäkring: condition för t.ex. väderstation - nej, inga conditions finns ännu... vill man ha det i framtiden? - // typ, när schemat ska exekveras, kolla om ngt är uppfyllt... Nej, det får i så fall ske i en scen (inte scen, något annat mellansteg i TelldusCenter (inte tellduscore)... - // när scenen körs, kolla väderdata, om det är gråmulet=tänd, annars kör scen som pausar i 30 minuter och tänder då... - // Samma sak med villkoret "hemma" och "borta"... Det får vara per scen (mellanstegsscen). Andra events (t.ex. rörelsekontrollevents) vill ju vara villkorade på precis samma sätt, - // alltså kör scenen om villkoret är "borta" eller temperatur < -10... - // Och en mellanstegsscen kan (ska kunna innehålla) en "stopscen" som ska köras en viss tid senare (t.ex. låta ljuset vara igång i 2 minuter, sedan släcka), då skapar scenen - // ett nytt schemajobb med argumentet +2 minuter... - // solen går upp/ner +/- visst antal minuter... - // hur kommer net:en + schemaläggare att fungera? Kommer det att finnas en webvariant? - //jobben i listan = deviceid (även grupp/scen såklart), action, värde. En enda / jobb, får grupperas med grupper/scener om man vill att mer ska hända på en ggn - //"repeat", t.ex. om villkor inte uppfylls så vill man göra ett nytt försök, även det får vara en funktion i extended scen/makro. if->false->tryAgainAfterXSeconds... - - //TODO ordna upp, dela upp i flera filer, inte ladda jobb här (per plugin istället), bara "add job" här... - //var ska "job" och "event" vara? Går det att ha inne i scheduler på ngt sätt? (och ändå kunna ärva utifrån) - //eller ha dem som egna "klasser"? - //ta bort loadJobs - //updateLastRun... måste anpassas för storage... på defaultjobben alltså... - //TODO ta bort absoluta events efter att de har passerats? Kan inte göras härifrån, får på ngt sätt ske därifrån de sparas/laddas - //det enda varje jobb har är getNextRunTime (som ska override:as) (och ev. updateLastRun) - //TODO nextRunTime = 0 ska ju inte köras, men negativa värden ska ju köras ibland (med graceTime) - + //TODO (perhaps) run something on the LAST day of the month? + //TODO remove absolute events after being run... Cannot do that from here, must be done from loading/saving plugin + //TODO Logic in future extended scenes/macros (not here, but somewhere in telldus center): Delays - job that then continues a scene from a certain step after the delay + //TODO Logic in future extended scenes/macros (not here, but somewhere in telldus center): Conditions, see if certain condition is fulfilled when the schedule should + // run, for example engine heater if the temperature is below 5 degrees, or turn on light if it is cloudy (if not cloudy, wait 20 minutes + // Not only for schedule, other input (for example motion detectors) can be conditioned in the same way (for example, house inhabitants are set as "Gone"). + // Repeat, if condition is not fulfilled, try again in x seconds + //TODO Logic in future extended scenes/macros (not here, but somewhere in telldus center): "Stop scene", i. e. when device is turned on, automatically turn it off again after x seconds function init(){ JobDaylightSavingReload.prototype = new com.telldus.scheduler.Job(); - loadJobs(); //load jobs from permanent storage TODO move + setDaylightSavingJobFunctions(); + loadJobs(); //TODO remove this after testing is done } @@ -231,34 +185,36 @@ com.telldus.scheduler = function() { function JobDaylightSavingReload(){} - JobDaylightSavingReload.prototype.execute = function(){ - //override default - print("Daylight savings job"); - //TODO Make sure this job is run "last", if other jobs are set to be runt the same second - setTimeout(recalculateAllJobs(), 1); //sleep for one ms, to avoid strange calculations - //this may lead to that things that should be executed exactly at 3.00 when - //moving time forward one hour won't run, but that should be the only case - return 0; - }; + function setDaylightSavingJobFunctions(){ - JobDaylightSavingReload.prototype.getNextRunTime = function(){ - print("getNextRunTime DaylightSaving"); - var dst = DstDetect(); - if(dst[0] == ""){ - //not using dst in this timezone, still add it to the lists to keep it consistent (will be added as 1/1 1970) - print("Not using timezone"); - return null; + JobDaylightSavingReload.prototype.execute = function(){ + //override default + print("Daylight savings job"); + //TODO Make sure this job is run "last", if other jobs are set to be runt the same second + setTimeout(recalculateAllJobs(), 1); //sleep for one ms, to avoid strange calculations + //this may lead to that things that should be executed exactly at 3.00 when + //moving time forward one hour won't run, but that should be the only case + return 0; + }; + + JobDaylightSavingReload.prototype.getNextRunTime = function(){ + print("getNextRunTime DaylightSaving"); + var dst = DstDetect(); + if(dst[0] == ""){ + //not using dst in this timezone, still add it to the lists to keep it consistent (will be added as 1/1 1970) + print("Not using timezone");; + return null; + } + var now = new Date().getTime(); + var time = dst[0].getTime(); + if(now > time){ + //already passed + time = dst[1].getTime(); + } + return time; } - var now = new Date().getTime(); - var time = dst[0].getTime(); - if(now > time){ - //already passed - time = dst[1].getTime(); - } - return time; } - function MappedList() { this.container = {}; this.length = 0; @@ -321,8 +277,8 @@ com.telldus.scheduler.Job = function(jobdata) { com.telldus.scheduler.Job.prototype.execute = function(){ //may be overridden if other than device manipulation should be performed var success = 0; - print("Job id: " + this.v.deviceid); - deviceid = this.v.deviceid; + print("Job id: " + this.v.device); + deviceid = this.v.device; var method = parseInt(this.method); switch(method){ case com.telldus.core.TELLSTICK_TURNON: From 016502d3001c3c2e274a3ba6a75a49aba7c16014 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 11 Jan 2011 08:49:09 +0000 Subject: [PATCH 1496/2215] Don't clear timer when no timer has been initialized yet. --- telldus-gui/Plugins/Scheduler/__init__.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 672c86be..e23e3cbc 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -8,7 +8,7 @@ com.telldus.scheduler = function() { var storedJobs = new MappedList(); //all jobs, added by "addJob" var joblist; //sorted list containing next run time (and id) for all storedJobs - var timerid; //id of currently running timer, used when timer should be aborted + var timerid = null; //id of currently running timer, used when timer should be aborted var queuedJob; //job currently in running timer, is already removed from joblist //TODO (perhaps) run something on the LAST day of the month? @@ -108,8 +108,10 @@ com.telldus.scheduler = function() { } function runNextJob(){ - clearTimeout(timerid); - print("Timer interrupted"); + if(timerid != null){ + clearTimeout(timerid); + print("Timer interrupted"); + } if(joblist.length <= 0){ print("No jobs"); return; //no jobs, abort @@ -139,6 +141,7 @@ com.telldus.scheduler = function() { print("(Now is " + new Date() + ")"); print("Delay: " + delay); timerid = setTimeout(runJobFunc, delay); //start the timer + print("Has started a job wait"); } @@ -183,7 +186,9 @@ com.telldus.scheduler = function() { } - function JobDaylightSavingReload(){} + function JobDaylightSavingReload(){ + this.v.name = "Daylight Saving Time job"; + } function setDaylightSavingJobFunctions(){ From 5f1bfacc51bd8ae5900695945c87507d29176910 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 11 Jan 2011 08:56:45 +0000 Subject: [PATCH 1497/2215] setTimeout now accepts values greater than ordinary integers (quint64). --- .../TelldusCenter/scriptenvironment.cpp | 76 +++++++++++++++++-- telldus-gui/TelldusCenter/scriptenvironment.h | 4 +- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index 8ccebb2d..5f747e9d 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -1,5 +1,6 @@ #include "scriptenvironment.h" #include "configurationdialog.h" +#include #include #include #include @@ -8,11 +9,18 @@ #include +class ScriptEnvironment::TimerObj{ +public: + int originalTimerId; + qint64 remainingDelay; + QScriptValue expression; +}; + class ScriptEnvironment::PrivateData { public: QScriptEngine scriptEngine; QHash intervalHash; - QHash timeoutHash; + QHash timeoutHash; }; ScriptEnvironment::ScriptEnvironment(QObject *parent) : @@ -49,6 +57,9 @@ ScriptEnvironment::ScriptEnvironment(QObject *parent) : } ScriptEnvironment::~ScriptEnvironment() { + foreach(TimerObj *tim, d->timeoutHash){ + delete tim; + } delete d; } @@ -87,11 +98,26 @@ void ScriptEnvironment::timerEvent(QTimerEvent *event) { QScriptValue expression = d->intervalHash.value(id); if (!expression.isValid()) { - expression = d->timeoutHash.value(id); - if (expression.isValid()) { - //Clear oneshot - this->clearTimeout(id); + qint64 remainingDelay = d->timeoutHash.value(id)->remainingDelay; + if(remainingDelay > 0){ + qint64 delay = remainingDelay; + remainingDelay = delay - std::numeric_limits::max(); + d->timeoutHash.value(id)->remainingDelay = remainingDelay; + if(remainingDelay > 0){ + return; //just run same timer again with same interval (max int) + } + + TimerObj *to = d->timeoutHash.value(id); + d->timeoutHash.remove(to->originalTimerId); + int newTimerId = startTimer(delay); //delay differs from last time, start a new timer + killTimer(id); + + d->timeoutHash.insert(newTimerId, to); + return; } + + expression = d->timeoutHash.value(id)->expression; + this->clearTimeout(d->timeoutHash.value(id)->originalTimerId); } if (expression.isString()) { @@ -101,24 +127,58 @@ void ScriptEnvironment::timerEvent(QTimerEvent *event) { } } -int ScriptEnvironment::setTimeout(const QScriptValue &expression, int delay) { +int ScriptEnvironment::setTimeout(const QScriptValue &expression, qint64 delay) { if (expression.isString() || expression.isFunction()) { + if (delay < 0) { delay = 0; } + + TimerObj *to = new TimerObj; + to->expression = expression; + to->remainingDelay = delay - std::numeric_limits::max(); + if(to->remainingDelay > 0){ + delay = std::numeric_limits::max(); + } int timerId = startTimer(delay); - d->timeoutHash.insert(timerId, expression); + to->originalTimerId = timerId; + + d->timeoutHash.insert(timerId, to); return timerId; } return -1; } void ScriptEnvironment::clearTimeout(int timerId) { + bool found = true; + if(!d->timeoutHash.contains(timerId) || d->timeoutHash.value(timerId)->originalTimerId != timerId){ + //not original timer id, find the key + found = false; + if(d->timeoutHash.count() > 0){ + QHashIterator i(d->timeoutHash); + while(i.hasNext()){ + i.next(); + if(i.value()->originalTimerId == timerId){ + timerId = i.key(); + found = true; + break; + } + } + } + } + killTimer(timerId); + if(!found){ + return; + } + delete d->timeoutHash.value(timerId); d->timeoutHash.remove(timerId); } int ScriptEnvironment::setInterval(const QScriptValue &expression, int delay) { + //not safe for longer intervals (as setTimeout is) + //if it has to be done in the future, maybe do something like this: + //delay/((delay/maxint)+1)=new timer that can be run over and over again, and every ((delay/maxint)+1) time, run "expression" if (expression.isString() || expression.isFunction()) { if (delay < 0) { delay = 0; @@ -133,4 +193,4 @@ int ScriptEnvironment::setInterval(const QScriptValue &expression, int delay) { void ScriptEnvironment::clearInterval(int timerId) { killTimer(timerId); d->intervalHash.remove(timerId); -} +} \ No newline at end of file diff --git a/telldus-gui/TelldusCenter/scriptenvironment.h b/telldus-gui/TelldusCenter/scriptenvironment.h index ca0f68e0..d5a892c3 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.h +++ b/telldus-gui/TelldusCenter/scriptenvironment.h @@ -20,7 +20,7 @@ public slots: int setInterval(const QScriptValue &expression, int delay); void clearInterval(int timerId); - int setTimeout(const QScriptValue &expression, int delay); + int setTimeout(const QScriptValue &expression, qint64 delay); void clearTimeout(int timerId); protected: @@ -32,7 +32,7 @@ private slots: private: class PrivateData; PrivateData *d; - + class TimerObj; }; #endif // SCRIPTENVIRONMENT_H From b2ac9cd635981de0a0dfb75322666b69123bced5 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 11 Jan 2011 14:48:34 +0000 Subject: [PATCH 1498/2215] Corrected javascript inheritance --- .../Plugins/Scheduler/DefaultJobTypes.js | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js index 2db1a7e7..25759d17 100644 --- a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js +++ b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js @@ -53,9 +53,8 @@ function getGracePeriod(v){ function getJob(jobdata){ //factory function... typ - var job = new com.telldus.scheduler.Job(); + var job; var type = parseInt(jobdata.type); - switch(type){ case com.telldus.scheduler.JOBTYPE_ABSOLUTE: job = new com.telldus.scheduler.JobAbsolute(jobdata); @@ -70,9 +69,10 @@ function getJob(jobdata){ job = new com.telldus.scheduler.JobRecurringMonth(jobdata); break; default: + job = new com.telldus.scheduler.Job(jobdata); break; } - job.v = jobdata; + return job; } @@ -148,15 +148,20 @@ function loadJobs(){ //ID = ID for storage //Key is position in list, returned from "addJob" - var newRecurringMonthJob = getJob({id: 4, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_ABSOLUTE, startdate: startdate1, lastRun: 0, device: 1, method: 1, value: ""}); - newRecurringMonthJob.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 50})); - newRecurringMonthJob.save(); + var execFunc = function(){ print("Custom execute function running"); return 42; }; + var newRecurringMonthJob = getJob({id: 4, executeFunc: execFunc, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_ABSOLUTE, startdate: startdate1, lastRun: 0, device: 1, method: 1, value: ""}); + newRecurringMonthJob.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 20})); + com.telldus.scheduler.addJob(newRecurringMonthJob); + //newRecurringMonthJob.save(); var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_MONTH, startdate: startdate2, lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 90}); newAbsoluteJob.addEvent(new Event({id: 1, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); newAbsoluteJob.addEvent(new Event({id: 2, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); - newAbsoluteJob.save(); - + //newAbsoluteJob.save(); + com.telldus.scheduler.addJob(newAbsoluteJob); + + + /* //get all jobs from permanent storage var settings = new com.telldus.settings(); var storedJobsData = settings.value("jobs", ""); @@ -166,6 +171,7 @@ function loadJobs(){ var job = getJob(jobdata); var tempkey = com.telldus.scheduler.addJob(job); //TODO, use different function than this = only sort list afterwards (one time) and dont start timer until all initial are added } + */ } /* @@ -219,6 +225,7 @@ com.telldus.scheduler.Job.prototype.save = function(){ * method - action to perform on device, value - optional value to pass to method, * pastGracePeriod - if job run time has been missed (for example due to a reboot), run it on program startup, if it should have run * within the last "pastGracePeriod" seconds + * executeFunc - optional, override default execute function with this one * type is com.telldus.scheduler.JOBTYPE_ABSOLUTE * Event properties: * id - for storage purposes (e.g. removal/update) @@ -227,7 +234,7 @@ com.telldus.scheduler.Job.prototype.save = function(){ * time - time and date for event run, in seconds since 1970-01-01 * offset - time (in seconds, positive or negative) to adjust the runtime, useful if something for example should occur 20 minutes past sunrise */ -com.telldus.scheduler.JobAbsolute = function(jobdata){} +com.telldus.scheduler.JobAbsolute = function(jobdata){ com.telldus.scheduler.Job.call(this, jobdata); } /* * Recurring job for device manipulation, same time every day or every x day ("value") @@ -241,7 +248,7 @@ com.telldus.scheduler.JobAbsolute = function(jobdata){} * Extra/different event properties: * value - repeat every "value" day, starting from startdate, */ -com.telldus.scheduler.JobRecurringDay = function(jobdata){} +com.telldus.scheduler.JobRecurringDay = function(jobdata){ com.telldus.scheduler.Job.call(this, jobdata); } /* * Recurring job for device manipulation, can have several events, each event has a time of day ("time") and weekday ("value", 0-6) when to run @@ -253,7 +260,7 @@ com.telldus.scheduler.JobRecurringDay = function(jobdata){} * Extra/different event properties: * value - day of week */ -com.telldus.scheduler.JobRecurringWeek = function(jobdata){} +com.telldus.scheduler.JobRecurringWeek = function(jobdata){ com.telldus.scheduler.Job.call(this, jobdata); } /* * Recurring job for device manipulation, each event runs on a certain date of a certain month (i.e. next run for an event will be a year later) @@ -266,7 +273,7 @@ com.telldus.scheduler.JobRecurringWeek = function(jobdata){} * Extra/different event properties: * value - "month-day" */ -com.telldus.scheduler.JobRecurringMonth = function(jobdata){} +com.telldus.scheduler.JobRecurringMonth = function(jobdata){ com.telldus.scheduler.Job.call(this, jobdata); } com.telldus.scheduler.JobAbsolute.prototype = new com.telldus.scheduler.Job(); com.telldus.scheduler.JobRecurringDay.prototype = new com.telldus.scheduler.Job(); From 0d54d224e1caf7d0db4108585d66b3291992ec1f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 11 Jan 2011 14:49:06 +0000 Subject: [PATCH 1499/2215] Possibility to have custom execute functions --- telldus-gui/Plugins/Scheduler/__init__.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index e23e3cbc..5c4357ff 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -282,9 +282,15 @@ com.telldus.scheduler.Job = function(jobdata) { com.telldus.scheduler.Job.prototype.execute = function(){ //may be overridden if other than device manipulation should be performed var success = 0; - print("Job id: " + this.v.device); + if(this.v.executeFunc != null){ + success = this.v.executeFunc(); + this.updateJobLastRun(); + return success; + } + deviceid = this.v.device; - var method = parseInt(this.method); + var method = parseInt(this.v.method); + print("Job id: " + this.v.device + " Method: " + method); switch(method){ case com.telldus.core.TELLSTICK_TURNON: success = com.telldus.core.turnOn(deviceid); From a156408c78c10cd4fc7b38aa16d7fc4fe52d76fc Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 11 Jan 2011 15:28:59 +0000 Subject: [PATCH 1500/2215] Custom job execute function now receives the job as an argument --- telldus-gui/Plugins/Scheduler/DefaultJobTypes.js | 2 +- telldus-gui/Plugins/Scheduler/__init__.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js index 25759d17..5f3c4b22 100644 --- a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js +++ b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js @@ -148,7 +148,7 @@ function loadJobs(){ //ID = ID for storage //Key is position in list, returned from "addJob" - var execFunc = function(){ print("Custom execute function running"); return 42; }; + var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; var newRecurringMonthJob = getJob({id: 4, executeFunc: execFunc, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_ABSOLUTE, startdate: startdate1, lastRun: 0, device: 1, method: 1, value: ""}); newRecurringMonthJob.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 20})); com.telldus.scheduler.addJob(newRecurringMonthJob); diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 5c4357ff..e813cb7f 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -283,7 +283,7 @@ com.telldus.scheduler.Job.prototype.execute = function(){ //may be overridden if other than device manipulation should be performed var success = 0; if(this.v.executeFunc != null){ - success = this.v.executeFunc(); + success = this.v.executeFunc(this); this.updateJobLastRun(); return success; } From d0beb114b8e92772910d4cc8dcc4445bcfc5b4d6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 12 Jan 2011 11:47:44 +0000 Subject: [PATCH 1501/2215] Moved class Device to it own file --- telldus-gui/Plugins/TelldusCore/CMakeLists.txt | 6 +++++- telldus-gui/Plugins/TelldusCore/Device.js | 4 ++++ telldus-gui/Plugins/TelldusCore/__init__.js | 11 ++++------- 3 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 telldus-gui/Plugins/TelldusCore/Device.js diff --git a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt index 49dd0b0d..9ba02867 100644 --- a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt +++ b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt @@ -14,6 +14,10 @@ SET( Plugin_MOC_HDRS tellduscoreobject.h ) +SET( Plugin_EXTRA + Device.js +) + FIND_PACKAGE(TelldusCore REQUIRED) SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ) INCLUDE_DIRECTORIES( @@ -21,4 +25,4 @@ INCLUDE_DIRECTORIES( ) -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) \ No newline at end of file +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/TelldusCore/Device.js b/telldus-gui/Plugins/TelldusCore/Device.js new file mode 100644 index 00000000..0640057e --- /dev/null +++ b/telldus-gui/Plugins/TelldusCore/Device.js @@ -0,0 +1,4 @@ +function Device(id) { + this.id = id; + this.name = com.telldus.core.getName(id); +} diff --git a/telldus-gui/Plugins/TelldusCore/__init__.js b/telldus-gui/Plugins/TelldusCore/__init__.js index fb847651..c92e59a2 100644 --- a/telldus-gui/Plugins/TelldusCore/__init__.js +++ b/telldus-gui/Plugins/TelldusCore/__init__.js @@ -1,9 +1,11 @@ /** TELLDUS CORE **/ __setupPackage__( __extension__ ); +include("Device.js"); + __postInit__ = function() { com.telldus.core.errorOccurred.connect( errorOccurred ); - + com.telldus.core.deviceList = function() { var devices = new Array(); //Load all the devices @@ -44,7 +46,7 @@ __postInit__ = function() { return; } } - + // function deviceEvent(deviceId, method, data) { // } @@ -82,8 +84,3 @@ __postInit__ = function() { function errorOccurred( deviceId, errorId, errorString ) { application.showMessage("", errorString, ""); } - -function Device(id) { - this.id = id; - this.name = com.telldus.core.getName(id); -} From 052df06fb49d7df09af3038b6f330f2fcc6cbfda Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 12 Jan 2011 12:08:34 +0000 Subject: [PATCH 1502/2215] Added class DeviceCommand --- .../Plugins/TelldusCore/CMakeLists.txt | 1 + .../Plugins/TelldusCore/DeviceCommands.js | 35 +++++++++++++++++++ telldus-gui/Plugins/TelldusCore/__init__.js | 1 + 3 files changed, 37 insertions(+) create mode 100644 telldus-gui/Plugins/TelldusCore/DeviceCommands.js diff --git a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt index 9ba02867..01821e4f 100644 --- a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt +++ b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt @@ -16,6 +16,7 @@ SET( Plugin_MOC_HDRS SET( Plugin_EXTRA Device.js + DeviceCommands.js ) FIND_PACKAGE(TelldusCore REQUIRED) diff --git a/telldus-gui/Plugins/TelldusCore/DeviceCommands.js b/telldus-gui/Plugins/TelldusCore/DeviceCommands.js new file mode 100644 index 00000000..1cd58ba9 --- /dev/null +++ b/telldus-gui/Plugins/TelldusCore/DeviceCommands.js @@ -0,0 +1,35 @@ +/** Base **/ +com.telldus.core.DeviceCommand = function() { +} + +com.telldus.core.DeviceCommand.prototype.execute = function() { + print("DeviceCommand::execute is not implemented for this type!"); +} + +/** ON **/ +com.telldus.core.DeviceOnCommand = function() {} +com.telldus.core.DeviceOnCommand.prototype = new com.telldus.core.DeviceCommand(); + +com.telldus.core.DeviceOnCommand.prototype.execute = function(deviceId) { + return com.telldus.core.turnOn(deviceId); +} + +/** OFF **/ +com.telldus.core.DeviceOffCommand = function() {} +com.telldus.core.DeviceOffCommand.prototype = new com.telldus.core.DeviceCommand(); + +com.telldus.core.DeviceOffCommand.prototype.execute = function(deviceId) { + return com.telldus.core.turnOff(deviceId); +} + +/** DIM **/ +com.telldus.core.DeviceDimCommand = function(value) { + this.value = value; +} +com.telldus.core.DeviceDimCommand.prototype = new com.telldus.core.DeviceCommand(); + +com.telldus.core.DeviceDimCommand.prototype.execute = function(deviceId) { + return com.telldus.core.dim(deviceId, this.value); +} + + diff --git a/telldus-gui/Plugins/TelldusCore/__init__.js b/telldus-gui/Plugins/TelldusCore/__init__.js index c92e59a2..fcbcd38b 100644 --- a/telldus-gui/Plugins/TelldusCore/__init__.js +++ b/telldus-gui/Plugins/TelldusCore/__init__.js @@ -4,6 +4,7 @@ __setupPackage__( __extension__ ); include("Device.js"); __postInit__ = function() { + include("DeviceCommands.js"); com.telldus.core.errorOccurred.connect( errorOccurred ); com.telldus.core.deviceList = function() { From c6e8caec7356d32aa4e8caf7eeb45b55adbe61e9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 12 Jan 2011 12:09:12 +0000 Subject: [PATCH 1503/2215] Added functions Device::pushCommand() and Device::popCommand() --- telldus-gui/Plugins/TelldusCore/Device.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCore/Device.js b/telldus-gui/Plugins/TelldusCore/Device.js index 0640057e..315ffe44 100644 --- a/telldus-gui/Plugins/TelldusCore/Device.js +++ b/telldus-gui/Plugins/TelldusCore/Device.js @@ -1,4 +1,20 @@ function Device(id) { this.id = id; this.name = com.telldus.core.getName(id); + this.commandStack = new Array(); +} + +Device.prototype.pushCommand = function(command) { + this.commandStack.push(command); + command.execute(this.id); +} + +Device.prototype.popCommand = function(command) { + + this.commandStack.pop(); + if (this.commandStack.length) { + var command = this.commandStack[this.commandStack.length-1].execute(this.id); + } else { + com.telldus.core.turnOff(this.id); + } } From 594a51acce3c5adabc3ee9b2ff93952317d44968 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 14 Jan 2011 11:12:32 +0000 Subject: [PATCH 1504/2215] Added basic structure for SchedulerGUISimple --- telldus-gui/Plugins/CMakeLists.txt | 10 +- telldus-gui/Plugins/QML/qmlplugin.cpp | 1 - .../SchedulerGUISimple/ActionPoint.qml | 50 ++++ .../Plugins/SchedulerGUISimple/CMakeLists.txt | 10 + .../Plugins/SchedulerGUISimple/Dialog.qml | 34 +++ .../Plugins/SchedulerGUISimple/__init__.js | 23 ++ .../Plugins/SchedulerGUISimple/main.qml | 269 ++++++++++++++++++ 7 files changed, 393 insertions(+), 4 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/__init__.js create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/main.qml diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 620ae266..2eb95b96 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -11,7 +11,7 @@ ENDIF (BUILD_LIBTELLDUS-GUI) SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") -SET(BUILD_PLUGIN_SCHEDULER FALSE CACHE BOOL "Build plugin 'Scheduler'") +SET(BUILD_PLUGIN_SCHEDULERGUISIMPLE FALSE CACHE BOOL "Build plugin 'Simple Scheduler GUI'") ADD_SUBDIRECTORY(telldus) @@ -39,9 +39,13 @@ IF(BUILD_PLUGIN_XPL) ADD_SUBDIRECTORY(xPL) ENDIF(BUILD_PLUGIN_XPL) -IF(BUILD_PLUGIN_SCHEDULER) +IF(BUILD_PLUGIN_SCHEDULERGUISIMPLE) + ADD_SUBDIRECTORY(SchedulerGUISimple) +ENDIF(BUILD_PLUGIN_SCHEDULERGUISIMPLE) + +IF(REQUIRE_PLUGIN_SCHEDULER) ADD_SUBDIRECTORY(Scheduler) -ENDIF(BUILD_PLUGIN_SCHEDULER) +ENDIF(REQUIRE_PLUGIN_SCHEDULER) IF(REQUIRE_PLUGIN_SUNCALCULATOR) ADD_SUBDIRECTORY(SunCalculator) diff --git a/telldus-gui/Plugins/QML/qmlplugin.cpp b/telldus-gui/Plugins/QML/qmlplugin.cpp index 5d8746c2..7773ea01 100644 --- a/telldus-gui/Plugins/QML/qmlplugin.cpp +++ b/telldus-gui/Plugins/QML/qmlplugin.cpp @@ -17,7 +17,6 @@ QScriptValue QMLLoadFunction(QScriptContext *context, QScriptEngine *engine) { if (!context->isCalledAsConstructor()) { return engine->undefinedValue(); } - QScriptValue p = context->argument(0); //Find out the filename so we have a relative directory to load from QScriptContextInfo info(context->parentContext()); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml new file mode 100644 index 00000000..ed796128 --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -0,0 +1,50 @@ +import Qt 4.7 + +Rectangle{ + id: pointRect + property variant xposition + //x: xposition + + /* + states: State { + name: "myState"; when: xposition != undefined + PropertyChanges { target: pointRect; x: myListView.width - xposition } + } + */ + + width: 30 + height: 50 + border.color: "black" + opacity: 0.8 + z: 100 + MouseArea { + onClicked: { + //pointRect.border.color: "red" + dialog.show("Id: " + myListView.children[0].width) + } + //onPositionChange... maybe emit signal to change in row... + anchors.fill: parent + drag.target: pointRect + drag.axis: Drag.XAxis + drag.minimumX: 0 + drag.maximumX: actionPoint.width - pointRect.width //TODO this doesn't work + //TODO make it impossible to overlap (on release) + } + + Column{ + spacing: 10 + Image { + //opacity: 1 + id: actionImage + width: 20; height: 20 + source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" + } + + Image { + //triggerImage, antingen sol upp, sol ned, eller inte bild utan text m. klockslag + id: triggerImage + width: 20; height: 20 + source: "/home/stefan/Downloads/11949889941371111141clock_michael_breuer_01.svg.hi.png" + } + } +} diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt new file mode 100644 index 00000000..33a952e9 --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -0,0 +1,10 @@ +SET(REQUIRE_PLUGIN_QML TRUE PARENT_SCOPE) +SET(REQUIRE_PLUGIN_SETTINGS TRUE PARENT_SCOPE) +SET(REQUIRE_PLUGIN_SCHEDULER TRUE PARENT_SCOPE) + +SET( Plugin_NAME "schedulerguisimple" ) + +SET( Plugin_PATH "com.telldus.schedulerguisimple" ) +SET( Plugin_EXTRA main.qml Dialog.qml ActionPoint.qml ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml new file mode 100644 index 00000000..7a39d96b --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -0,0 +1,34 @@ + import Qt 4.7 + + Rectangle { + id: container + + function show(text) { + dialogText.text = text; + container.opacity = 1; + container.border.color = "black" + container.border.width = 2 + } + + function hide() { + container.opacity = 0; + container.border.width = 0 + } + + smooth: true + radius: 5 + width: dialogText.width + 120 + height: dialogText.height + 120 + opacity: 0 + + Text { + id: dialogText + anchors.centerIn: parent + text: "" + } + + MouseArea { + anchors.fill: parent + onClicked: hide(); + } + } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js new file mode 100644 index 00000000..bfa2fc9d --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -0,0 +1,23 @@ +/** SchedulerGUISimple **/ +__setupPackage__( __extension__ ); + +__postInit__ = function() { + application.allDoneLoading.connect( com.telldus.schedulersimplegui.init ); +} + +com.telldus.schedulersimplegui = function() { + + function init() { + print("START"); + var v = new com.telldus.qml.view({}); + v.load("main.qml"); + //var v = new com.telldus.qml.view(""); + application.addWidget("scheduler.simple", ":/images/devices.png", v); + + } + + return { //Public functions + init:init + } + +}(); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml new file mode 100644 index 00000000..fb18bb0f --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -0,0 +1,269 @@ +//import QtQuick 1.0 TODO not until 4.7.1 +import Qt 4.7 + + + + Item{ + id: main + width: 800 //TODO how? + height: 600 //TODO how? + + //height: 200 + + /* + Rectangle { + width:200 + height: 200 + id: testRectangle + border.color: "red" + //anchors.fill: parent + color: "blue" + MouseArea { + anchors.fill: parent + //onClicked: container.clicked(testGrid.) + } + } + + + Text{ + id: testItem + text: "Hello world!" + //anchors.left: main.left + anchors.centerIn: parent + anchors.verticalCenter: main.verticalCenter + } + + Column { + id: testColumn + width: parent.width + height: parent.height + //anchors.bottom: page.bottom; anchors.bottomMargin: 4 + //rows: 6; columns: 1; spacing: 3 + + Repeater{ + model: 3 + Row{ + id: row1 + width: parent.width; + height: 50 + //color: "red" + Rectangle { border.color: "blue"; width: 100; height:parent.height; + Text{ + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + text: "Device " + index + } + } + Rectangle { border.color: "blue"; width: parent.width-100; height:parent.height; } + } + } + + Rectangle { color: "green"; width: parent.width; height:50; id: row2 } + Rectangle { color: "blue"; } + Rectangle { color: "yellow"; } + Rectangle { color: "steelblue"; } + Rectangle { color: "black"; } + } + */ + + Component{ + id: listRow + Row{ + id: row1 + width: parent.width; //TODO relative + height: 50 + //color: "red" + Rectangle { border.color: "red"; width: 100; height:parent.height; + Text{ + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + //text: "Device " + (index + 1) + "Name: " + name + + text: devicename + height + } + } + Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width-100; height:parent.height; + + MouseArea { + id: deviceMouseArea + anchors.fill: parent + hoverEnabled: true + + //TODO ändra muspekaren kanske? + //onEntered: parent.border.color = onHoverColor + //onExited: parent.border.color = borderColor + onClicked: { + //ny point här + + var component = Qt.createComponent("ActionPoint.qml") + var dynamicPoint = component.createObject(deviceRow) + //dynamicPoint.x = mouseX (blir inte kvar) + //dynamicPoint. + dynamicPoint.x = mouseX - dynamicPoint.width/2 //xposition + //dynamicPoint.width = mouseX- + dynamicPoint.border.color = "blue" + + var dynamicBar = actionBar.createObject(deviceRow) + dynamicBar.hangOnToPoint = dynamicPoint + //dynamicBar.color = "blue" //TODO dependent of point type + //dynamicBar.anchors.left = dynamicPoint.right + //dynamicBar.width = 100 //TODO dependent of this and next point position + + //deviceRow.add(point) + //TODO destroy? (only to remove them if needed) + //TODO komponenter med stor bokstav kanske? + //om detta inte fungerar, testa med pathview... + } + } + + } + + ListView.onAdd: SequentialAnimation { + PropertyAction { target: row1; property: "height"; value: 0 } + NumberAnimation { target: row1; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } + } + } + } + + ListModel { + id: myModel + ListElement { + devicename: "Storsalen" + } + ListElement { + devicename: "Förstugan" + } + ListElement { + devicename: "Västra uthuset" + } + } + + ListView { + id: myListView + anchors.fill: parent + model: myModel + delegate: listRow + //snapMode: ListView.SnapToItem + //highlight: Rectangle { color: "lightsteelblue"; radius: 5 } + focus: true + footer: addButtonComponent + header: timeline + } + + Component{ + id: timeline + Item{ + width: parent.width + Rectangle{ + width: parent.width + height: 30 + border.color: "red" + anchors.verticalCenter: parent.verticalCenter + + Row{ + //x: 100 + anchors.horizontalCenter: parent.horizontalCenter + anchors.horizontalCenterOffset: parent.width/24 + + width: listRow.width + height: listRow.height + spacing: (parent.width-124)/24 + Repeater{ + model:24 + Rectangle{ + width: 1 + height: 15 + color: "green" + } + } + } + } + } + } + + Component{ + id: addButtonComponent + //anchors { left: myListView.left; top: myListView.top; margins: 20 } + Row { + id: addButton + //anchors.fill: parent + //spacing: 10 + + Rectangle { + height: 20 + width: 100 + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 30 + + property color buttonColor: "lightgrey" + + Text{ + text: "Add an item" + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.margins: 2 + + } + MouseArea { + id: buttonMouseArea + anchors.fill: parent + hoverEnabled: true + //onEntered: parent.border.color = onHoverColor + //onExited: parent.border.color = borderColor + onClicked: { + myModel.append({ + "devicename": "Stället" + }) + } + } + + color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor + + } + } + } + + Component{ + id: actionBar + Rectangle{ + id: barRectangle + property variant hangOnToPoint + width: 100 //TODO dependent on hangOnToPoint and next point positions + height: 10 + color: "blue" //TODO, dependent on hangOnToPoint + anchors.verticalCenter: hangOnToPoint.verticalCenter + anchors.left: hangOnToPoint.horizontalCenter + + z: 110 + /* couldnt get this to work: + * (if it works later on, try to set opacity for actionPoint in this way too) + states: State { + name: "myState"; when: hangOnToPoint != undefined + PropertyChanges { target: barRectangle; anchors.verticalCenter: hangOnToPoint.verticalCenter; anchors.left: hangOnToPoint.horizontalCenter } + //anchors.verticalCenter: hangOnToPoint.verticalCenter + //anchors.left: hangOnToPoint.horizontalCenter + } + */ + } + } + + Dialog { + id: dialog + anchors.centerIn: parent + z: 150 + } + + //opacity vid dimning? + //linjens färg etc (state) beror ju på närmaste punkt föres sort... Punkten kan finnas osynlig (tidigare dag) också... + //kan man liksom göra hela linjen (från en vecka tillbaka) men inte visa den? Om det är vettigt... Då hade man tom kunnat zooma en vacker dag + //properties, ställa in dem... + //fuzziness + /* + * Dialog { + id: dialog + anchors.centerIn: parent + z: 100 + } + */ + +} From 30713febc2c8041081162b4d0b5d41e756ad7f86 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 14 Jan 2011 11:45:17 +0000 Subject: [PATCH 1505/2215] Added function ScriptEnvironment::currentDir() --- .../TelldusCenter/scriptenvironment.cpp | 28 +++++++++++-------- telldus-gui/TelldusCenter/scriptenvironment.h | 2 ++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index 5f747e9d..fdc172e7 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -63,6 +63,12 @@ ScriptEnvironment::~ScriptEnvironment() { delete d; } +QDir ScriptEnvironment::currentDir() const { + QScriptContextInfo info(d->scriptEngine.currentContext()->parentContext()); + QFileInfo fileinfo(info.fileName()); + return fileinfo.dir(); +} + QScriptEngine *ScriptEnvironment::engine() const { return &d->scriptEngine; } @@ -77,9 +83,7 @@ void ScriptEnvironment::scriptException(const QScriptValue & exception) { } void ScriptEnvironment::include(const QString &filename) { - QScriptContextInfo info(d->scriptEngine.currentContext()->parentContext()); - QFileInfo fileinfo(info.fileName()); - QDir dir = fileinfo.dir(); + QDir dir = this->currentDir(); QFile file(dir.filePath(filename)); file.open(QFile::ReadOnly); @@ -106,18 +110,18 @@ void ScriptEnvironment::timerEvent(QTimerEvent *event) { if(remainingDelay > 0){ return; //just run same timer again with same interval (max int) } - + TimerObj *to = d->timeoutHash.value(id); d->timeoutHash.remove(to->originalTimerId); int newTimerId = startTimer(delay); //delay differs from last time, start a new timer killTimer(id); - + d->timeoutHash.insert(newTimerId, to); return; } - + expression = d->timeoutHash.value(id)->expression; - this->clearTimeout(d->timeoutHash.value(id)->originalTimerId); + this->clearTimeout(d->timeoutHash.value(id)->originalTimerId); } if (expression.isString()) { @@ -129,11 +133,11 @@ void ScriptEnvironment::timerEvent(QTimerEvent *event) { int ScriptEnvironment::setTimeout(const QScriptValue &expression, qint64 delay) { if (expression.isString() || expression.isFunction()) { - + if (delay < 0) { delay = 0; } - + TimerObj *to = new TimerObj; to->expression = expression; to->remainingDelay = delay - std::numeric_limits::max(); @@ -142,7 +146,7 @@ int ScriptEnvironment::setTimeout(const QScriptValue &expression, qint64 delay) } int timerId = startTimer(delay); to->originalTimerId = timerId; - + d->timeoutHash.insert(timerId, to); return timerId; } @@ -166,7 +170,7 @@ void ScriptEnvironment::clearTimeout(int timerId) { } } } - + killTimer(timerId); if(!found){ return; @@ -193,4 +197,4 @@ int ScriptEnvironment::setInterval(const QScriptValue &expression, int delay) { void ScriptEnvironment::clearInterval(int timerId) { killTimer(timerId); d->intervalHash.remove(timerId); -} \ No newline at end of file +} diff --git a/telldus-gui/TelldusCenter/scriptenvironment.h b/telldus-gui/TelldusCenter/scriptenvironment.h index d5a892c3..8ff9ee23 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.h +++ b/telldus-gui/TelldusCenter/scriptenvironment.h @@ -3,6 +3,7 @@ #include #include +#include class ScriptEnvironment : public QObject { @@ -12,6 +13,7 @@ public: ~ScriptEnvironment(); QScriptEngine *engine() const; + QDir currentDir() const; signals: From 4944334f4c6c80328a02f7f3dd78b771ce6f4a5d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 14 Jan 2011 11:45:46 +0000 Subject: [PATCH 1506/2215] Allow icon loading from the plugin script path --- .../TelldusCenter/tellduscenterapplication.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 2890237c..32570409 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -170,7 +170,16 @@ void TelldusCenterApplication::loadToolbar() { } void TelldusCenterApplication::addWidget( const QString &page, const QString &icon, QWidget *widget ) { - d->mainWindow->addWidget(page, QIcon(icon), widget); + QString path; + QFileInfo info(icon); + if (info.isRelative()) { + QDir dir = d->scriptEnvironment->currentDir(); + path = dir.filePath(icon); + } else { + path = icon; + } + + d->mainWindow->addWidget(page, QIcon(path), widget); } void TelldusCenterApplication::addWidget( const QString &page, const QIcon &icon, QWidget *widget ) { From 042508033eb19b6de4aa10f26f7322cc380233e9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 14 Jan 2011 12:56:08 +0000 Subject: [PATCH 1507/2215] Added icon for scheduler --- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 7 ++++++- telldus-gui/Plugins/SchedulerGUISimple/icon.png | Bin 0 -> 2399 bytes 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/icon.png diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 33a952e9..64b247ba 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -5,6 +5,11 @@ SET(REQUIRE_PLUGIN_SCHEDULER TRUE PARENT_SCOPE) SET( Plugin_NAME "schedulerguisimple" ) SET( Plugin_PATH "com.telldus.schedulerguisimple" ) -SET( Plugin_EXTRA main.qml Dialog.qml ActionPoint.qml ) +SET( Plugin_EXTRA + ActionPoint.qml + Dialog.qml + icon.png + main.qml +) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/icon.png b/telldus-gui/Plugins/SchedulerGUISimple/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..85daef3b0b519c8d4fe6cc1efc1c67e660e0f8e9 GIT binary patch literal 2399 zcmV-l3840gP)4588HS&8xA82V&3hc%v6C1lA)yHbN)}Qer39sbN+U{J z3I#+(p(+&!T2NL0L9OUcM60qXq*bc~iV~f!Do!l&Q7KOM0T~Rs$Y{*Ugt`80TM4r5W-Z1=#!58 zhZO8==?Hw#+1crSmb&8825i~#18+dnz6bJ0bq#e!^TM`@Xib%(>pHro;kYhl&SY}Z zBoT|bLuUqZ#p2eT+kahyt5;LhbX3Pg+QXuf*k=N`_m0PI6$;NUUfNN) zeANn%K#)wQNu|cIObat-;z|ciRZ&zGzu$|`AD~buGTMK{@>P7CzxJB$KVQDOZv3Bsg8O)it4>T92B)sL|H8h?;O7VfRolhpDW;3C%kn)65f##TXk)P{?;d z@fgw2D2?+R73I=;v*3$*J)L?e-u}KJ%v^?O zq{ymO%UD?3gW2Cnrtc3(S!BpuO*-eHuC^XcQwaux)YsQiT{TEu?I7V`Kbo-&qhhU4 z)a9BhLz=2gx{v^zQG__9ohQDrG8B4z{k7}7y{FEAVp3OYu;!``Mh<_U(aF<9o3>z7 zwu3B?81n(3C<*|s>mr08;8)NU9ZfNiq7I>Upcz+Sn}4q;I>)`5P(nxosII3Buw}~@ zRiM0h&GldK4-SrE7qZN6^s?^iC7ga|6TZmjs9yF2(zS7&ain9jAeyCm;g`z7=h6eh zgQ^Imn!|O5DcT1>Cdpf7z;8%PsM11FC(8hpYV*A<3tMYY6=Ja%%}oYt*R0|fKWyQ{ zo?3pt^#)wW1lL45d0fZBmCO>J4p)Yeq6$aWpvqGy0_>azL;}Y?tqdpq%Dje&5dyim zQf^0~JhgP?a_^bGL8_uED_5?-QxV|4hn^-Fs^#{(e?}@9!zqm86fzX;6pl4EOMLp= zaTic@S}8b-C>C`n9zfw8vYCU#5>avB;Jgl7nr{n%tpMD8`y*FGYpXp1ftkw^3VEoj zs|5u0?f0{N$9~qXxtiPV`W*uULpXK@w*)a)NP-mH6%?EmSjCm(iFREm-@W(2V0j%73SVt(ZuTb=DZD;Gb93YDz7&F|fAs>jbx(5p{V(wR)9Yw%P;s3+ zQc9$h=fq3ruB^v$Hy~(5FpOI)kjf5o_=vzXJ>H_ye;e?=GUdOrDO?p+GN}yVut7sZ zL%G<@eDv|B=&0ZyF#TkF$C6%_I^D)~#KK z-|y#{XMR&2cRomK%fj+~Aq1MPQ?P9$(mdA%f_`%{w_MRwibaWKS$I623#^aF6Wnsk zt(-V$cXKY%i2AA3@-n_!%!xOBZ5STj+kcQiB*H{8=}IB?lmP_18XF$Tdi?>0 zhf*YynOOx~*Tr!hLZKj6Ub&jrUi&MNNMugP^MTHNLXG#|Jw&9shKW=yzKbn>ohN1%wS(%4%dBhx;3T& z$Z_VyiBvjKu=05QA@=|KV`8z?ECI)HX640%r;owP2-}`}1%IRpJD(#rF_C&}|BgRR z>y~#!U0q%J{KmFE$0}}~-`c9jM&ej`lbX6Hx~|W;G@tH2Njj4x6bxVROb9_ZT*aHO z@8igklQg!r(c68(JUiI?$l+rj^aB>)&fJpuKRIpwln$lw^Q zi<;0>1<7oYbS4czWgs}~zRwq+vNFWB=XP@R*lAjqET!k@5o>JZ>|gf&>y=%A0~7&! zCV&s{o#^?fdtp<@GBca4Z)#hljb|qL?>h&ms;MFxji9J1AaNXrU}cD4WvJZeKA)d} zKS=M%GyL}FFHvxH8k(BvIdara#>YO|y?6W8(wk3be&&Bc5QqR_AbQirJ07gBZTfOc zd%NKa1Q=V&x@V`T5I;R)wjks6bH^3WXx6WSV#XbC3_-JA|rxX>41_@ae zQdm|V+pwn& z7yzzx3bt(}#xu#T{-K_CyH6eNavUcI`~YGyltUCMk3AYBr-=MwqUzvCG&dP%sVbgs_;aG7eW0_SG9UAlMC_#ZE!mKFGu RQpNxP002ovPDHLkV1kVygbx4! literal 0 HcmV?d00001 From 2b2cb019fabf79501be71b6fd27502d0bd033988 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 14 Jan 2011 12:56:52 +0000 Subject: [PATCH 1508/2215] Use the real devices from telldus-core instead of hardcoded values --- .../Plugins/SchedulerGUISimple/__init__.js | 5 +- .../Plugins/SchedulerGUISimple/main.qml | 130 +++++++++--------- 2 files changed, 67 insertions(+), 68 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index bfa2fc9d..c6172104 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -8,11 +8,10 @@ __postInit__ = function() { com.telldus.schedulersimplegui = function() { function init() { - print("START"); var v = new com.telldus.qml.view({}); + v.setProperty('deviceModel', com.telldus.core.deviceList.getList()); v.load("main.qml"); - //var v = new com.telldus.qml.view(""); - application.addWidget("scheduler.simple", ":/images/devices.png", v); + application.addWidget("scheduler.simple", "icon.png", v); } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index fb18bb0f..9b002bd9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -2,14 +2,14 @@ import Qt 4.7 - + Item{ id: main width: 800 //TODO how? height: 600 //TODO how? - + //height: 200 - + /* Rectangle { width:200 @@ -22,23 +22,23 @@ import Qt 4.7 anchors.fill: parent //onClicked: container.clicked(testGrid.) } - } - - - Text{ + } + + + Text{ id: testItem text: "Hello world!" //anchors.left: main.left anchors.centerIn: parent anchors.verticalCenter: main.verticalCenter } - + Column { - id: testColumn - width: parent.width + id: testColumn + width: parent.width height: parent.height - //anchors.bottom: page.bottom; anchors.bottomMargin: 4 - //rows: 6; columns: 1; spacing: 3 + //anchors.bottom: page.bottom; anchors.bottomMargin: 4 + //rows: 6; columns: 1; spacing: 3 Repeater{ model: 3 @@ -47,7 +47,7 @@ import Qt 4.7 width: parent.width; height: 50 //color: "red" - Rectangle { border.color: "blue"; width: 100; height:parent.height; + Rectangle { border.color: "blue"; width: 100; height:parent.height; Text{ anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter @@ -57,44 +57,44 @@ import Qt 4.7 Rectangle { border.color: "blue"; width: parent.width-100; height:parent.height; } } } - - Rectangle { color: "green"; width: parent.width; height:50; id: row2 } - Rectangle { color: "blue"; } - Rectangle { color: "yellow"; } - Rectangle { color: "steelblue"; } - Rectangle { color: "black"; } - } - */ - - Component{ + + Rectangle { color: "green"; width: parent.width; height:50; id: row2 } + Rectangle { color: "blue"; } + Rectangle { color: "yellow"; } + Rectangle { color: "steelblue"; } + Rectangle { color: "black"; } + } + */ + + Component{ id: listRow Row{ id: row1 width: parent.width; //TODO relative height: 50 //color: "red" - Rectangle { border.color: "red"; width: 100; height:parent.height; + Rectangle { border.color: "red"; width: 100; height:parent.height; Text{ anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter //text: "Device " + (index + 1) + "Name: " + name - - text: devicename + height + + text: modelData.name + height } } Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width-100; height:parent.height; - + MouseArea { id: deviceMouseArea anchors.fill: parent hoverEnabled: true - + //TODO ändra muspekaren kanske? //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { //ny point här - + var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) //dynamicPoint.x = mouseX (blir inte kvar) @@ -102,30 +102,30 @@ import Qt 4.7 dynamicPoint.x = mouseX - dynamicPoint.width/2 //xposition //dynamicPoint.width = mouseX- dynamicPoint.border.color = "blue" - + var dynamicBar = actionBar.createObject(deviceRow) dynamicBar.hangOnToPoint = dynamicPoint //dynamicBar.color = "blue" //TODO dependent of point type //dynamicBar.anchors.left = dynamicPoint.right //dynamicBar.width = 100 //TODO dependent of this and next point position - + //deviceRow.add(point) //TODO destroy? (only to remove them if needed) //TODO komponenter med stor bokstav kanske? //om detta inte fungerar, testa med pathview... } - } - + } + } - + ListView.onAdd: SequentialAnimation { PropertyAction { target: row1; property: "height"; value: 0 } NumberAnimation { target: row1; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } } - } + } } - - ListModel { + + ListModel { id: myModel ListElement { devicename: "Storsalen" @@ -137,20 +137,20 @@ import Qt 4.7 devicename: "Västra uthuset" } } - + ListView { id: myListView anchors.fill: parent - model: myModel + model: deviceModel delegate: listRow //snapMode: ListView.SnapToItem //highlight: Rectangle { color: "lightsteelblue"; radius: 5 } focus: true footer: addButtonComponent header: timeline - } - - Component{ + } + + Component{ id: timeline Item{ width: parent.width @@ -159,12 +159,12 @@ import Qt 4.7 height: 30 border.color: "red" anchors.verticalCenter: parent.verticalCenter - + Row{ //x: 100 anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenterOffset: parent.width/24 - + width: listRow.width height: listRow.height spacing: (parent.width-124)/24 @@ -180,8 +180,8 @@ import Qt 4.7 } } } - - Component{ + + Component{ id: addButtonComponent //anchors { left: myListView.left; top: myListView.top; margins: 20 } Row { @@ -194,15 +194,15 @@ import Qt 4.7 width: 100 anchors.verticalCenter: parent.verticalCenter anchors.verticalCenterOffset: 30 - + property color buttonColor: "lightgrey" - + Text{ text: "Add an item" anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter anchors.margins: 2 - + } MouseArea { id: buttonMouseArea @@ -216,13 +216,13 @@ import Qt 4.7 }) } } - + color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor - + } } } - + Component{ id: actionBar Rectangle{ @@ -233,37 +233,37 @@ import Qt 4.7 color: "blue" //TODO, dependent on hangOnToPoint anchors.verticalCenter: hangOnToPoint.verticalCenter anchors.left: hangOnToPoint.horizontalCenter - - z: 110 - /* couldnt get this to work: + + z: 110 + /* couldnt get this to work: * (if it works later on, try to set opacity for actionPoint in this way too) states: State { name: "myState"; when: hangOnToPoint != undefined - PropertyChanges { target: barRectangle; anchors.verticalCenter: hangOnToPoint.verticalCenter; anchors.left: hangOnToPoint.horizontalCenter } + PropertyChanges { target: barRectangle; anchors.verticalCenter: hangOnToPoint.verticalCenter; anchors.left: hangOnToPoint.horizontalCenter } //anchors.verticalCenter: hangOnToPoint.verticalCenter //anchors.left: hangOnToPoint.horizontalCenter } */ } } - + Dialog { id: dialog anchors.centerIn: parent z: 150 } - + //opacity vid dimning? //linjens färg etc (state) beror ju på närmaste punkt föres sort... Punkten kan finnas osynlig (tidigare dag) också... //kan man liksom göra hela linjen (från en vecka tillbaka) men inte visa den? Om det är vettigt... Då hade man tom kunnat zooma en vacker dag //properties, ställa in dem... - //fuzziness + //fuzziness /* * Dialog { - id: dialog - anchors.centerIn: parent - z: 100 - } - */ - + id: dialog + anchors.centerIn: parent + z: 100 + } + */ + } From 3738b3c7129433ccfee600cf5d4dbf9e9a46e2b2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 14 Jan 2011 16:12:29 +0000 Subject: [PATCH 1509/2215] Added class QMLArray() --- telldus-gui/Plugins/QML/CMakeLists.txt | 2 ++ telldus-gui/Plugins/QML/qmlarray.cpp | 36 ++++++++++++++++++++++++++ telldus-gui/Plugins/QML/qmlarray.h | 28 ++++++++++++++++++++ telldus-gui/Plugins/QML/qmlplugin.cpp | 14 +++++++++- telldus-gui/Plugins/QML/qmlview.cpp | 15 ++++++----- 5 files changed, 87 insertions(+), 8 deletions(-) create mode 100644 telldus-gui/Plugins/QML/qmlarray.cpp create mode 100644 telldus-gui/Plugins/QML/qmlarray.h diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt index 772d1a62..5d0830d8 100644 --- a/telldus-gui/Plugins/QML/CMakeLists.txt +++ b/telldus-gui/Plugins/QML/CMakeLists.txt @@ -5,6 +5,7 @@ SET( Plugin_NAME "QMLLoader" ) SET( Plugin_SRCS scriptfunctionwrapper.cpp + qmlarray.cpp qmlplugin.cpp qmlview.cpp ) @@ -15,6 +16,7 @@ SET( Plugin_HDRS SET( Plugin_MOC_HDRS scriptfunctionwrapper.h + qmlarray.h qmlview.h ) diff --git a/telldus-gui/Plugins/QML/qmlarray.cpp b/telldus-gui/Plugins/QML/qmlarray.cpp new file mode 100644 index 00000000..48f32a42 --- /dev/null +++ b/telldus-gui/Plugins/QML/qmlarray.cpp @@ -0,0 +1,36 @@ +#include "qmlarray.h" + +#include + +class QMLArray::PrivateData { +public: + QList list; +}; + +QMLArray::QMLArray(QObject *parent) : + QAbstractListModel(parent) +{ + d = new PrivateData; + + QHash roles; + roles[Qt::UserRole+1] = "modelData"; + setRoleNames(roles); +} + +QMLArray::~QMLArray() { + delete d; +} + +int QMLArray::rowCount(const QModelIndex &parent) const { + return d->list.size(); +} + +QVariant QMLArray::data(const QModelIndex &index, int role) const { + return d->list.at(index.row()).toVariant(); +} + +void QMLArray::push(const QScriptValue &v) { + beginInsertRows( QModelIndex(), d->list.size(), d->list.size() ); + d->list << v; + endInsertRows(); +} diff --git a/telldus-gui/Plugins/QML/qmlarray.h b/telldus-gui/Plugins/QML/qmlarray.h new file mode 100644 index 00000000..e8279cb7 --- /dev/null +++ b/telldus-gui/Plugins/QML/qmlarray.h @@ -0,0 +1,28 @@ +#ifndef QMLARRAY_H +#define QMLARRAY_H + +#include +#include + +class QMLArray : public QAbstractListModel +{ + Q_OBJECT +public: + explicit QMLArray(QObject *parent = 0); + ~QMLArray(); + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +signals: + +public slots: + void push(const QScriptValue &v); + +private: + class PrivateData; + PrivateData *d; + +}; + +#endif // QMLARRAY_H diff --git a/telldus-gui/Plugins/QML/qmlplugin.cpp b/telldus-gui/Plugins/QML/qmlplugin.cpp index 7773ea01..c30e442b 100644 --- a/telldus-gui/Plugins/QML/qmlplugin.cpp +++ b/telldus-gui/Plugins/QML/qmlplugin.cpp @@ -1,10 +1,13 @@ #include "qmlplugin.h" +#include "qmlarray.h" #include "qmlview.h" #include #include #include #include +#include + QMLPlugin::QMLPlugin ( QObject * parent ) :QScriptExtensionPlugin( parent ) { @@ -26,9 +29,18 @@ QScriptValue QMLLoadFunction(QScriptContext *context, QScriptEngine *engine) { return engine->newQObject(new QMLView(dir, context->argument(0)), QScriptEngine::ScriptOwnership); } +QScriptValue QMLArrayFunction(QScriptContext *context, QScriptEngine *engine) { + if (!context->isCalledAsConstructor()) { + return engine->undefinedValue(); + } + return engine->newQObject(new QMLArray(), QScriptEngine::ScriptOwnership); +} + void QMLPlugin::initialize ( const QString & key, QScriptEngine * engine ) { if (key == "com.telldus.qml") { - engine->globalObject().property("com").property("telldus").property("qml").setProperty("view", engine->newFunction(QMLLoadFunction)); + QScriptValue qml = engine->globalObject().property("com").property("telldus").property("qml"); + qml.setProperty("view", engine->newFunction(QMLLoadFunction)); + qml.setProperty("array", engine->newFunction(QMLArrayFunction)); } } diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp index ab7bd026..185eddd1 100644 --- a/telldus-gui/Plugins/QML/qmlview.cpp +++ b/telldus-gui/Plugins/QML/qmlview.cpp @@ -7,6 +7,7 @@ class QMLView::PrivateData { public: QDir baseDir; + QScriptValue object; }; QMLView::QMLView(const QDir &dir, const QScriptValue &object) : @@ -14,17 +15,13 @@ QMLView::QMLView(const QDir &dir, const QScriptValue &object) : { d = new PrivateData; d->baseDir = dir; + d->object = object; - QDeclarativeContext *context = this->rootContext(); QScriptValueIterator it(object); while (it.hasNext()) { it.next(); - if (it.value().isFunction()) { - context->setContextProperty(it.name(), new ScriptFunctionWrapper(object, it.name(), this)); - } else { - context->setContextProperty(it.name(), it.value().toVariant()); - } + this->setProperty(it.name(), it.value()); } } @@ -38,5 +35,9 @@ void QMLView::load(const QString &filename) { void QMLView::setProperty( const QString & name, const QScriptValue &value ) { QDeclarativeContext *context = this->rootContext(); - context->setContextProperty(name, value.toVariant()); + if (value.isFunction()) { + context->setContextProperty(name, new ScriptFunctionWrapper(d->object, name, this)); + } else { + context->setContextProperty(name, value.toVariant()); + } } From 1de1cee8c59cfdaa721d76874640aed6f420a943 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 14 Jan 2011 16:30:30 +0000 Subject: [PATCH 1510/2215] Scheduler simple GUI development --- .../SchedulerGUISimple/ActionPoint.qml | 29 ++++++++++++++++--- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 1 + .../Plugins/SchedulerGUISimple/main.qml | 28 ++++++++++++------ .../SchedulerGUISimple/schedulerscripts.js | 16 ++++++++++ 4 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index ed796128..c0b36348 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -2,7 +2,9 @@ import Qt 4.7 Rectangle{ id: pointRect - property variant xposition + //property variant xposition + property string actionType: "blue" + property string isPoint: "true" //x: xposition /* @@ -11,7 +13,8 @@ Rectangle{ PropertyChanges { target: pointRect; x: myListView.width - xposition } } */ - + + //use item instead of rectangle (no border then though) to make it invisible (opacity: 0) width: 30 height: 50 border.color: "black" @@ -19,15 +22,33 @@ Rectangle{ z: 100 MouseArea { onClicked: { + if(actionType == "red"){ + actionType = "blue" + } + else{ + actionType = "red" + } //pointRect.border.color: "red" - dialog.show("Id: " + myListView.children[0].width) + //Fungerar inte: for(var child in myListView.children){ + // dialog.show("hej?") + //} + //listmodel har iaf en count-property man kan testa om vi gör om detta till en listmodel... + /*var continue = true; + while(continue){ + dialog.show("Count: " + parent.parent.children[2]) //myListView.children[0].children[0].x), parent.x = punktens x, parent.parent.children = siblings... starting from 1 + continue = false; + } + */ + //dialog.show("Width: " + Scripts.getBarWidth(pointRect, parent.parent.children)); + + dialog.show("Nice dialog with possibility to set type of action, exact time, fuzziness, offset etc") //myListView.children[0].children[0].x), parent.x = punktens x, parent.parent.children = siblings... starting from 1 } //onPositionChange... maybe emit signal to change in row... anchors.fill: parent drag.target: pointRect drag.axis: Drag.XAxis drag.minimumX: 0 - drag.maximumX: actionPoint.width - pointRect.width //TODO this doesn't work + drag.maximumX: 685 //TODO make relative!! //TODO make it impossible to overlap (on release) } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 64b247ba..62df1df1 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -10,6 +10,7 @@ SET( Plugin_EXTRA Dialog.qml icon.png main.qml + schedulerscripts.js ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 9b002bd9..43aed258 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -1,7 +1,6 @@ //import QtQuick 1.0 TODO not until 4.7.1 import Qt 4.7 - - +import "schedulerscripts.js" as Scripts Item{ id: main @@ -105,6 +104,7 @@ import Qt 4.7 var dynamicBar = actionBar.createObject(deviceRow) dynamicBar.hangOnToPoint = dynamicPoint + //dynamicBar.width = Scripts.getBarWidth(dynamicPoint, deviceRow.children) //dynamicBar.color = "blue" //TODO dependent of point type //dynamicBar.anchors.left = dynamicPoint.right //dynamicBar.width = 100 //TODO dependent of this and next point position @@ -228,22 +228,32 @@ import Qt 4.7 Rectangle{ id: barRectangle property variant hangOnToPoint - width: 100 //TODO dependent on hangOnToPoint and next point positions + //width: 100 //TODO dependent on hangOnToPoint and next point positions + height: 10 - color: "blue" //TODO, dependent on hangOnToPoint + /* + color: hangOnToPoint.actionType //"blue" //TODO, dependent on hangOnToPoint anchors.verticalCenter: hangOnToPoint.verticalCenter anchors.left: hangOnToPoint.horizontalCenter - + */ z: 110 - /* couldnt get this to work: - * (if it works later on, try to set opacity for actionPoint in this way too) + + //state actionType + // couldnt get this to work: + // (if it works later on, try to set opacity for actionPoint in this way too) states: State { name: "myState"; when: hangOnToPoint != undefined - PropertyChanges { target: barRectangle; anchors.verticalCenter: hangOnToPoint.verticalCenter; anchors.left: hangOnToPoint.horizontalCenter } + PropertyChanges { + target: barRectangle + anchors.verticalCenter: hangOnToPoint.verticalCenter + anchors.left: hangOnToPoint.horizontalCenter + color: hangOnToPoint.actionType + width: Scripts.getBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children) + } //anchors.verticalCenter: hangOnToPoint.verticalCenter //anchors.left: hangOnToPoint.horizontalCenter } - */ + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js new file mode 100644 index 00000000..e730fac8 --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -0,0 +1,16 @@ + +function getBarWidth(currentBar, currentPointRect, pointList){ + + var maxWidth = currentPointRect.parent.width; + var nextX = maxWidth + var halfPointWidth = currentPointRect.width / 2 + for(var i=1;i (currentPointRect.x + halfPointWidth)){ + nextX = pointList[i].x + halfPointWidth; + } + } + } + + return nextX - (currentPointRect.x + halfPointWidth); +} From 2449553928098191827f88cf851d176ed340148e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 17 Jan 2011 11:31:30 +0000 Subject: [PATCH 1511/2215] Handle sizes in qmlviews. If set, this becomes the minimum size. If not set, the rootobject resizes to fit the window --- telldus-gui/Plugins/QML/qmlview.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp index 185eddd1..95b8c5f8 100644 --- a/telldus-gui/Plugins/QML/qmlview.cpp +++ b/telldus-gui/Plugins/QML/qmlview.cpp @@ -31,6 +31,13 @@ QMLView::~QMLView() { void QMLView::load(const QString &filename) { this->setSource(d->baseDir.filePath(filename)); + QSize size = this->initialSize(); + if (size.isNull()) { + this->setResizeMode(QDeclarativeView::SizeRootObjectToView); + } else { + this->setResizeMode(QDeclarativeView::SizeViewToRootObject); + this->setMinimumSize(size); + } } void QMLView::setProperty( const QString & name, const QScriptValue &value ) { From f8d307a9c5ee50a11501506a293c12124fca2eed Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 17 Jan 2011 11:49:45 +0000 Subject: [PATCH 1512/2215] Fixed timeline positioning bug --- telldus-gui/Plugins/SchedulerGUISimple/main.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 43aed258..26448f9c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -154,11 +154,10 @@ import "schedulerscripts.js" as Scripts id: timeline Item{ width: parent.width + height: 15 Rectangle{ width: parent.width - height: 30 border.color: "red" - anchors.verticalCenter: parent.verticalCenter Row{ //x: 100 From f5032da87d80310f70105043f1b8c57597af1407 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 17 Jan 2011 11:53:18 +0000 Subject: [PATCH 1513/2215] Implemented the devicelist using a QMLArray instead --- .../Plugins/SchedulerGUISimple/__init__.js | 27 ++++++++++++++----- .../Plugins/SchedulerGUISimple/main.qml | 23 +++------------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index c6172104..6051aa61 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -6,17 +6,30 @@ __postInit__ = function() { } com.telldus.schedulersimplegui = function() { - + var deviceList; + var view; + function init() { - var v = new com.telldus.qml.view({}); - v.setProperty('deviceModel', com.telldus.core.deviceList.getList()); - v.load("main.qml"); - application.addWidget("scheduler.simple", "icon.png", v); + view = new com.telldus.qml.view({ + addDevice: addDevice + }); + deviceList = new com.telldus.qml.array(); + var list = com.telldus.core.deviceList.getList(); + for(var i=0; i < list.length; ++i) { + deviceList.push(list[i]); + } + view.setProperty('deviceModel', deviceList); + view.load("main.qml"); + application.addWidget("scheduler.simple", "icon.png", view); } - + + function addDevice() { + deviceList.push({name:'Stallet'}); + } + return { //Public functions init:init } - + }(); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 26448f9c..a5bc7087 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -125,19 +125,6 @@ import "schedulerscripts.js" as Scripts } } - ListModel { - id: myModel - ListElement { - devicename: "Storsalen" - } - ListElement { - devicename: "Förstugan" - } - ListElement { - devicename: "Västra uthuset" - } - } - ListView { id: myListView anchors.fill: parent @@ -210,9 +197,7 @@ import "schedulerscripts.js" as Scripts //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { - myModel.append({ - "devicename": "Stället" - }) + addDevice.call() } } @@ -228,7 +213,7 @@ import "schedulerscripts.js" as Scripts id: barRectangle property variant hangOnToPoint //width: 100 //TODO dependent on hangOnToPoint and next point positions - + height: 10 /* color: hangOnToPoint.actionType //"blue" //TODO, dependent on hangOnToPoint @@ -236,7 +221,7 @@ import "schedulerscripts.js" as Scripts anchors.left: hangOnToPoint.horizontalCenter */ z: 110 - + //state actionType // couldnt get this to work: // (if it works later on, try to set opacity for actionPoint in this way too) @@ -252,7 +237,7 @@ import "schedulerscripts.js" as Scripts //anchors.verticalCenter: hangOnToPoint.verticalCenter //anchors.left: hangOnToPoint.horizontalCenter } - + } } From 4887e4e90a9b459adb66d59c32ad54e45fe01d8f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 17 Jan 2011 12:42:54 +0000 Subject: [PATCH 1514/2215] Toggle states --- .../SchedulerGUISimple/ActionPoint.qml | 83 +++++++++++++++++-- .../Plugins/SchedulerGUISimple/Dialog.qml | 73 ++++++++++++++-- .../Plugins/SchedulerGUISimple/main.qml | 7 +- .../SchedulerGUISimple/schedulerscripts.js | 2 +- 4 files changed, 145 insertions(+), 20 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index c0b36348..34c7de61 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -3,8 +3,16 @@ import Qt 4.7 Rectangle{ id: pointRect //property variant xposition - property string actionType: "blue" + property string actionTypeColor: "blue" //TODO default value + property int actionType: 1 //TODO default value + property double actionTypeOpacity: 1 property string isPoint: "true" + property variant isLoaded + + Component.onCompleted: { + //TODO useless really, still gets Cannot anchor to a null item-warning... + isLoaded = "true" + } //x: xposition /* @@ -20,14 +28,12 @@ Rectangle{ border.color: "black" opacity: 0.8 z: 100 + state: "on" + //actionTypeColor: getColor() + MouseArea { onClicked: { - if(actionType == "red"){ - actionType = "blue" - } - else{ - actionType = "red" - } + //pointRect.border.color: "red" //Fungerar inte: for(var child in myListView.children){ // dialog.show("hej?") @@ -40,8 +46,8 @@ Rectangle{ } */ //dialog.show("Width: " + Scripts.getBarWidth(pointRect, parent.parent.children)); - - dialog.show("Nice dialog with possibility to set type of action, exact time, fuzziness, offset etc") //myListView.children[0].children[0].x), parent.x = punktens x, parent.parent.children = siblings... starting from 1 + dialog.show(pointRect) //TODO om inte redan i visandes läge.... + //dialog.show("Nice dialog with possibility to set type of action, exact time, fuzziness, offset etc") //myListView.children[0].children[0].x), parent.x = punktens x, parent.parent.children = siblings... starting from 1 } //onPositionChange... maybe emit signal to change in row... anchors.fill: parent @@ -68,4 +74,63 @@ Rectangle{ source: "/home/stefan/Downloads/11949889941371111141clock_michael_breuer_01.svg.hi.png" } } + + states: [ + State { + name: "on" + PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } + }, + State{ + name: "off" + PropertyChanges { target: pointRect; actionTypeColor: "red"; actionTypeOpacity: 1 } + }, + State{ + name: "dim" + PropertyChanges { target: pointRect; actionTypeColor: "green"; actionTypeOpacity: 1 } + //something opacity = dim for example + }, + State{ + name: "bell" + PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } + } + ] + + function toggleType(){ + print(pointRect.state); + if(pointRect.state == "on"){ + pointRect.state = "off" + } + else if(pointRect.state == "off"){ + pointRect.state = "dim" + } + else if(pointRect.state == "dim"){ + pointRect.state = "bell" + } + else if(pointRect.state == "bell"){ + pointRect.state = "on" + } + } + + function getLastPointColor(){ + //get previous point: + var prevPoint = null; + var pointList = pointRect.parent.children; + for(var i=1;i prevPoint.x)){ + prevPoint = pointList[i]; + } + } + } + + //TODO Binding loop here when moving transperent point over other point + if(prevPoint == null || prevPoint.actionTypeOpacity == 0){ + //no point before, no bar after either + actionTypeOpacity = 0 + return "papayawhip" //just return a color, will not be used + } + + actionTypeOpacity = 1 + return prevPoint.actionTypeColor + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 7a39d96b..982b018d 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -2,23 +2,25 @@ Rectangle { id: container + property ActionPoint actionPoint - function show(text) { - dialogText.text = text; + function show(actionPoint) { + dialogText.text = "Nice dialog with possibility to set type of action, exact time, fuzziness, offset etc" container.opacity = 1; container.border.color = "black" container.border.width = 2 + container.actionPoint = actionPoint } function hide() { container.opacity = 0; container.border.width = 0 } - + smooth: true radius: 5 width: dialogText.width + 120 - height: dialogText.height + 120 + height: dialogText.height + 220 opacity: 0 Text { @@ -26,9 +28,64 @@ anchors.centerIn: parent text: "" } + + Rectangle { + id: circleType //TODO only types this device has... + height: 20 + width: 100 + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: 0 - MouseArea { - anchors.fill: parent - onClicked: hide(); - } + property color buttonColor: "lightgrey" + + Text{ + text: "Toggle type" + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.margins: 2 + + } + MouseArea { + id: buttonMouseAreaType + anchors.fill: parent + hoverEnabled: true + //onEntered: parent.border.color = onHoverColor + //onExited: parent.border.color = borderColor + onClicked: { + container.actionPoint.toggleType(); + } + } + + color: buttonMouseAreaType.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor + } + + Rectangle { //TODO create common button-class + id: closeButton + height: 20 + width: 100 + anchors.horizontalCenter: circleType.right + anchors.horizontalCenterOffset: 30 + + property color buttonColor: "lightgrey" + + Text{ + text: "Close" + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.margins: 2 + + } + MouseArea { + id: buttonMouseAreaClose + anchors.fill: parent + hoverEnabled: true + //onEntered: parent.border.color = onHoverColor + //onExited: parent.border.color = borderColor + onClicked: { + hide(); + } + } + + color: buttonMouseAreaClose.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index a5bc7087..e1bdff93 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -104,6 +104,8 @@ import "schedulerscripts.js" as Scripts var dynamicBar = actionBar.createObject(deviceRow) dynamicBar.hangOnToPoint = dynamicPoint + + dialog.show(dynamicPoint) //dynamicBar.width = Scripts.getBarWidth(dynamicPoint, deviceRow.children) //dynamicBar.color = "blue" //TODO dependent of point type //dynamicBar.anchors.left = dynamicPoint.right @@ -226,12 +228,13 @@ import "schedulerscripts.js" as Scripts // couldnt get this to work: // (if it works later on, try to set opacity for actionPoint in this way too) states: State { - name: "myState"; when: hangOnToPoint != undefined + name: "myState"; when: hangOnToPoint.isLoaded != undefined && hangOnToPoint.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning PropertyChanges { target: barRectangle anchors.verticalCenter: hangOnToPoint.verticalCenter anchors.left: hangOnToPoint.horizontalCenter - color: hangOnToPoint.actionType + color: hangOnToPoint.actionTypeColor + opacity: hangOnToPoint.actionTypeOpacity width: Scripts.getBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children) } //anchors.verticalCenter: hangOnToPoint.verticalCenter diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index e730fac8..bf8f9f1c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -1,6 +1,6 @@ function getBarWidth(currentBar, currentPointRect, pointList){ - + var maxWidth = currentPointRect.parent.width; var nextX = maxWidth var halfPointWidth = currentPointRect.width / 2 From f74dfbf8b8de5ef081c4780657fd57cb20e8d9d1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 17 Jan 2011 14:21:39 +0000 Subject: [PATCH 1515/2215] No action point drag when using sunrise/sunset --- .../SchedulerGUISimple/ActionPoint.qml | 77 +++++++++++++------ .../Plugins/SchedulerGUISimple/Dialog.qml | 40 +++++++++- 2 files changed, 91 insertions(+), 26 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 34c7de61..080c3d21 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -32,22 +32,9 @@ Rectangle{ //actionTypeColor: getColor() MouseArea { + id: pointRectMouseArea onClicked: { - - //pointRect.border.color: "red" - //Fungerar inte: for(var child in myListView.children){ - // dialog.show("hej?") - //} - //listmodel har iaf en count-property man kan testa om vi gör om detta till en listmodel... - /*var continue = true; - while(continue){ - dialog.show("Count: " + parent.parent.children[2]) //myListView.children[0].children[0].x), parent.x = punktens x, parent.parent.children = siblings... starting from 1 - continue = false; - } - */ - //dialog.show("Width: " + Scripts.getBarWidth(pointRect, parent.parent.children)); dialog.show(pointRect) //TODO om inte redan i visandes läge.... - //dialog.show("Nice dialog with possibility to set type of action, exact time, fuzziness, offset etc") //myListView.children[0].children[0].x), parent.x = punktens x, parent.parent.children = siblings... starting from 1 } //onPositionChange... maybe emit signal to change in row... anchors.fill: parent @@ -56,46 +43,79 @@ Rectangle{ drag.minimumX: 0 drag.maximumX: 685 //TODO make relative!! //TODO make it impossible to overlap (on release) + //onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; } } Column{ spacing: 10 Image { - //opacity: 1 - id: actionImage - width: 20; height: 20 - source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" - } + //opacity: 1 + id: actionImage + width: 20; height: 20 + source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" + } + + Rectangle{ + id: trigger + + state: "absolute" + width: 20; height: 20 + + //TODO state should move the point to correct place... (sunrisetime, sunsettime or absolute (stored value, the one that is dragged) + //drag not permitted depending on state... + states: [ + State { + name: "sunrise" + PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunrise.png" } //TODO: images!! + PropertyChanges { target: pointRectMouseArea; drag.target: undefined } + }, + State { + name: "sunset" + PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunset.png" } //TODO: images!! + PropertyChanges { target: pointRectMouseArea; drag.target: undefined } + }, + State { + name: "absolute" + PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/11949889941371111141clock_michael_breuer_01.svg.hi.png" } //TODO: images!! + PropertyChanges { target: pointRectMouseArea; drag.target: parent } + } + ] Image { //triggerImage, antingen sol upp, sol ned, eller inte bild utan text m. klockslag id: triggerImage + anchors.fill: parent width: 20; height: 20 source: "/home/stefan/Downloads/11949889941371111141clock_michael_breuer_01.svg.hi.png" } + } } states: [ State { name: "on" - PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } + PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } //TODO: images!! + PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" } }, State{ name: "off" - PropertyChanges { target: pointRect; actionTypeColor: "red"; actionTypeOpacity: 1 } + PropertyChanges { target: pointRect; actionTypeColor: "gainsboro"; actionTypeOpacity: 0 } + PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices-bw.png" } }, State{ name: "dim" PropertyChanges { target: pointRect; actionTypeColor: "green"; actionTypeOpacity: 1 } + PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/TelldusCenter_128.png" } //something opacity = dim for example }, State{ name: "bell" PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } + PropertyChanges { target: actionImage; source: "icon.png" } } ] - function toggleType(){ + function toggleType(){ //TODO other kind of selection method print(pointRect.state); if(pointRect.state == "on"){ pointRect.state = "off" @@ -111,6 +131,19 @@ Rectangle{ } } + function toggleTrigger(){ //TODO other kind of selection method + print(trigger.state); + if(trigger.state == "sunrise"){ + trigger.state = "sunset"; + } + else if(trigger.state == "sunset"){ + trigger.state = "absolute"; + } + else if(trigger.state == "absolute"){ + trigger.state = "sunrise"; + } + } + function getLastPointColor(){ //get previous point: var prevPoint = null; diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 982b018d..89a2652e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -39,7 +39,7 @@ property color buttonColor: "lightgrey" Text{ - text: "Toggle type" + text: "Toggle Action Type" anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter anchors.margins: 2 @@ -58,13 +58,45 @@ color: buttonMouseAreaType.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor } + + Rectangle { + id: circleTrigger + height: 20 + width: 100 + anchors.horizontalCenter: circleType.horizontalCenter + y: circleType.y + 30 + + property color buttonColor: "lightgrey" + + Text{ + text: "Toggle Trigger Type" + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.margins: 2 + + } + MouseArea { + id: buttonMouseAreaTrigger + anchors.fill: parent + hoverEnabled: true + //onEntered: parent.border.color = onHoverColor + //onExited: parent.border.color = borderColor + onClicked: { + container.actionPoint.toggleTrigger(); + } + } + + color: buttonMouseAreaTrigger.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor + } - Rectangle { //TODO create common button-class + + Rectangle { //TODO create common button-class id: closeButton height: 20 width: 100 - anchors.horizontalCenter: circleType.right - anchors.horizontalCenterOffset: 30 + //anchors.horizontalCenter: circleTrigger.right + //anchors.horizontalCenterOffset: 30 + y: circleTrigger.y + 30 property color buttonColor: "lightgrey" From 4d507ed6c772f4be8f1658b872a16f4ab7eb7025 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 17 Jan 2011 16:34:00 +0000 Subject: [PATCH 1516/2215] Basic sunrise/sunset functionality structure --- .../SchedulerGUISimple/ActionPoint.qml | 36 ++++++++++++++++--- .../Plugins/SchedulerGUISimple/__init__.js | 33 ++++++++++++++++- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 080c3d21..19fef4bd 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -8,6 +8,7 @@ Rectangle{ property double actionTypeOpacity: 1 property string isPoint: "true" property variant isLoaded + property int xvalue Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... @@ -40,7 +41,7 @@ Rectangle{ anchors.fill: parent drag.target: pointRect drag.axis: Drag.XAxis - drag.minimumX: 0 + drag.minimumX: -15 //TODO make relative drag.maximumX: 685 //TODO make relative!! //TODO make it impossible to overlap (on release) //onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; } @@ -62,25 +63,39 @@ Rectangle{ width: 20; height: 20 //TODO state should move the point to correct place... (sunrisetime, sunsettime or absolute (stored value, the one that is dragged) - //drag not permitted depending on state... states: [ State { + //TODO if no sunrise/sunset exists (arctic circle...), check so it works anyway name: "sunrise" - PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunrise.png" } //TODO: images!! + PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunrise.png"; opacity: 1 } //TODO: images!! + PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } + PropertyChanges { target: pointRect; x: getSunRiseTime.call(pointRect.parent.width, pointRect.width) } }, State { name: "sunset" - PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunset.png" } //TODO: images!! + PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunset.png"; opacity: 1 } //TODO: images!! + PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } + PropertyChanges { target: pointRect; x: getSunSetTime.call(pointRect.parent.width, pointRect.width) } }, State { name: "absolute" - PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/11949889941371111141clock_michael_breuer_01.svg.hi.png" } //TODO: images!! + PropertyChanges { target: triggerImage; opacity: 0; } //TODO: images!! + PropertyChanges { target: triggerTime; opacity: 1 } PropertyChanges { target: pointRectMouseArea; drag.target: parent } + PropertyChanges { target: pointRect; x: xvalue } } ] + Rectangle{ + id: triggerTime + width: 20; height: 20 + Text{ + text: getTime(pointRect.x, pointRect.width) + } + } + Image { //triggerImage, antingen sol upp, sol ned, eller inte bild utan text m. klockslag id: triggerImage @@ -140,6 +155,7 @@ Rectangle{ trigger.state = "absolute"; } else if(trigger.state == "absolute"){ + pointRect.xvalue = pointRect.x; //TODO right place to set it? trigger.state = "sunrise"; } } @@ -166,4 +182,14 @@ Rectangle{ actionTypeOpacity = 1 return prevPoint.actionTypeColor } + + function getTime(){ + var timeOfDay = pointRect.x + (pointRect.width/2); + var hourSize = pointRect.parent.width / 24; + print(hourSize); + print(timeOfDay); + var partOfHour = (timeOfDay % hourSize) * hourSize //TODO delar, gör om till minuter + print("Part: " + partOfHour); + return Math.floor(timeOfDay / hourSize) + ":" + partOfHour + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 6051aa61..4300facd 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -11,7 +11,9 @@ com.telldus.schedulersimplegui = function() { function init() { view = new com.telldus.qml.view({ - addDevice: addDevice + addDevice: addDevice, + getSunRiseTime: getSunRiseTime, + getSunSetTime: getSunSetTime }); deviceList = new com.telldus.qml.array(); var list = com.telldus.core.deviceList.getList(); @@ -27,6 +29,35 @@ com.telldus.schedulersimplegui = function() { function addDevice() { deviceList.push({name:'Stallet'}); } + + function getSun(riseset, rowWidth, pointWidth){ + var date = new Date(); + var timevalues = com.telldus.suncalculator.riseset(date); + var hourminute; + if(riseset == "rise"){ + hourminute = timevalues[0].split(':'); + } + else{ + hourminute = timevalues[1].split(':'); + } + print("Hourminute: " + hourminute[0]); + var hourSize = rowWidth/24; + print("Size: " + hourSize); + return hourSize*hourminute[0]; //TODO Only hour for now... + } + + function getSunRiseTime(rowWidth, pointWidth){ + //TODO turn into one method + rowWidth = 700 //TODO + pointWidth = 30 //TODO + return getSun("rise", rowWidth, pointWidth); + } + + function getSunSetTime(rowWidth, pointWidth){ + rowWidth = 700 //TODO + pointWidth = 30 //TODO + return getSun("set", rowWidth, pointWidth); + } return { //Public functions init:init From 255bacae018a5115d147f7ee6c650a1ca1acff4e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 18 Jan 2011 10:05:29 +0000 Subject: [PATCH 1517/2215] Correct minutes in absolute and sunset/sunrise times --- .../SchedulerGUISimple/ActionPoint.qml | 43 +++++++++--- .../Plugins/SchedulerGUISimple/Dialog.qml | 7 +- .../Plugins/SchedulerGUISimple/__init__.js | 5 +- .../Plugins/SchedulerGUISimple/main.qml | 67 ++----------------- .../SchedulerGUISimple/schedulerscripts.js | 10 +++ 5 files changed, 56 insertions(+), 76 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 19fef4bd..5ae24b02 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -1,4 +1,5 @@ import Qt 4.7 +import "schedulerscripts.js" as Scripts Rectangle{ id: pointRect @@ -30,13 +31,29 @@ Rectangle{ opacity: 0.8 z: 100 state: "on" + focus: true //actionTypeColor: getColor() + //TODO make this work: + /*Keys.onLeftPressed: { + pointRect.x = pointRect.x - 1 + } + Keys.onRightPressed: { + pointRect.x = pointRect.x + 1 + } + + Text { + //focus: true + text: pointRect.activeFocus ? "I HAVE active focus!" : "I do NOT have active focus" + } + */ MouseArea { id: pointRectMouseArea onClicked: { + //pointRect.focus = true dialog.show(pointRect) //TODO om inte redan i visandes läge.... } + //onPositionChange... maybe emit signal to change in row... anchors.fill: parent drag.target: pointRect @@ -49,6 +66,8 @@ Rectangle{ Column{ spacing: 10 + anchors.horizontalCenter: parent.horizontalCenter + Image { //opacity: 1 id: actionImage @@ -58,7 +77,8 @@ Rectangle{ Rectangle{ id: trigger - + anchors.horizontalCenter: parent.horizontalCenter + state: "absolute" width: 20; height: 20 @@ -91,13 +111,14 @@ Rectangle{ Rectangle{ id: triggerTime width: 20; height: 20 + anchors.horizontalCenter: parent.horizontalCenter + anchors.verticalCenter: parent.verticalCenter Text{ - text: getTime(pointRect.x, pointRect.width) + text: getTime(pointRect.x, pointRect.width); font.pointSize: 6; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignBottom } } Image { - //triggerImage, antingen sol upp, sol ned, eller inte bild utan text m. klockslag id: triggerImage anchors.fill: parent width: 20; height: 20 @@ -184,12 +205,18 @@ Rectangle{ } function getTime(){ + if(pointRect.parent == null){ + return ""; + } var timeOfDay = pointRect.x + (pointRect.width/2); var hourSize = pointRect.parent.width / 24; - print(hourSize); - print(timeOfDay); - var partOfHour = (timeOfDay % hourSize) * hourSize //TODO delar, gör om till minuter - print("Part: " + partOfHour); - return Math.floor(timeOfDay / hourSize) + ":" + partOfHour + var hours = Math.floor(timeOfDay / hourSize); + var partOfHour = ((timeOfDay - (hourSize * hours))/hourSize) * 60 + partOfHour = Math.floor(partOfHour); + partOfHour = Scripts.pad(partOfHour, 2); + hours = Scripts.pad(hours, 2); + //print("Hours: " + hours); + //print("Minutes? " + partOfHour); + return hours + ":" + partOfHour; } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 89a2652e..4db1685b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -28,7 +28,7 @@ anchors.centerIn: parent text: "" } - + Rectangle { id: circleType //TODO only types this device has... height: 20 @@ -38,6 +38,11 @@ property color buttonColor: "lightgrey" + Keys.onLeftPressed: { + debug("Left pressed"); + + } + Text{ text: "Toggle Action Type" anchors.verticalCenter: parent.verticalCenter diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 4300facd..e41bf510 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -40,14 +40,11 @@ com.telldus.schedulersimplegui = function() { else{ hourminute = timevalues[1].split(':'); } - print("Hourminute: " + hourminute[0]); var hourSize = rowWidth/24; - print("Size: " + hourSize); - return hourSize*hourminute[0]; //TODO Only hour for now... + return hourSize*hourminute[0] + hourSize * (hourminute[1]/60) - pointWidth/2; } function getSunRiseTime(rowWidth, pointWidth){ - //TODO turn into one method rowWidth = 700 //TODO pointWidth = 30 //TODO return getSun("rise", rowWidth, pointWidth); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index e1bdff93..c7baecf5 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -7,68 +7,12 @@ import "schedulerscripts.js" as Scripts width: 800 //TODO how? height: 600 //TODO how? - //height: 200 - - /* - Rectangle { - width:200 - height: 200 - id: testRectangle - border.color: "red" - //anchors.fill: parent - color: "blue" - MouseArea { - anchors.fill: parent - //onClicked: container.clicked(testGrid.) - } - } - - - Text{ - id: testItem - text: "Hello world!" - //anchors.left: main.left - anchors.centerIn: parent - anchors.verticalCenter: main.verticalCenter - } - - Column { - id: testColumn - width: parent.width - height: parent.height - //anchors.bottom: page.bottom; anchors.bottomMargin: 4 - //rows: 6; columns: 1; spacing: 3 - - Repeater{ - model: 3 - Row{ - id: row1 - width: parent.width; - height: 50 - //color: "red" - Rectangle { border.color: "blue"; width: 100; height:parent.height; - Text{ - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - text: "Device " + index - } - } - Rectangle { border.color: "blue"; width: parent.width-100; height:parent.height; } - } - } - - Rectangle { color: "green"; width: parent.width; height:50; id: row2 } - Rectangle { color: "blue"; } - Rectangle { color: "yellow"; } - Rectangle { color: "steelblue"; } - Rectangle { color: "black"; } - } - */ - - Component{ + Component{ id: listRow + Row{ id: row1 + width: parent.width; //TODO relative height: 50 //color: "red" @@ -132,9 +76,7 @@ import "schedulerscripts.js" as Scripts anchors.fill: parent model: deviceModel delegate: listRow - //snapMode: ListView.SnapToItem - //highlight: Rectangle { color: "lightsteelblue"; radius: 5 } - focus: true + //focus: true footer: addButtonComponent header: timeline } @@ -262,5 +204,4 @@ import "schedulerscripts.js" as Scripts z: 100 } */ - } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index bf8f9f1c..9e337828 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -14,3 +14,13 @@ function getBarWidth(currentBar, currentPointRect, pointList){ return nextX - (currentPointRect.x + halfPointWidth); } + +function pad(number, length) { + + var str = '' + number; + while (str.length < length) { + str = '0' + str; + } + + return str; +} From 944b9f217a1f9854a24430164d4dc6fa60fb381f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 18 Jan 2011 12:15:28 +0000 Subject: [PATCH 1518/2215] Added dark/light-bar at top --- .../Plugins/SchedulerGUISimple/__init__.js | 9 +- .../Plugins/SchedulerGUISimple/main.qml | 91 ++++++++++++++++++- .../SchedulerGUISimple/schedulerscripts.js | 16 ++++ 3 files changed, 114 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index e41bf510..3051d799 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -13,7 +13,8 @@ com.telldus.schedulersimplegui = function() { view = new com.telldus.qml.view({ addDevice: addDevice, getSunRiseTime: getSunRiseTime, - getSunSetTime: getSunSetTime + getSunSetTime: getSunSetTime, + getSunData: getSunData }); deviceList = new com.telldus.qml.array(); var list = com.telldus.core.deviceList.getList(); @@ -44,6 +45,12 @@ com.telldus.schedulersimplegui = function() { return hourSize*hourminute[0] + hourSize * (hourminute[1]/60) - pointWidth/2; } + //Raw sun data + function getSunData(){ + var date = new Date; + return com.telldus.suncalculator.riseset(date); + } + function getSunRiseTime(rowWidth, pointWidth){ rowWidth = 700 //TODO pointWidth = 30 //TODO diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index c7baecf5..9009863b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -6,6 +6,7 @@ import "schedulerscripts.js" as Scripts id: main width: 800 //TODO how? height: 600 //TODO how? + property variant sunData; Component{ id: listRow @@ -86,6 +87,27 @@ import "schedulerscripts.js" as Scripts Item{ width: parent.width height: 15 + + Rectangle{ + id: morningDark + color: "black" + height: parent.height + border.width: 0 + width: getMorningDarkWidth() + opacity: 0.1 + x: getMorningDarkStart() + } + + Rectangle{ + id: eveningDark + color: "black" + height: parent.height + border.width: 0 + width: getEveningDarkWidth() + opacity: 0.1 + x: getEveningDarkStart() + } + Rectangle{ width: parent.width border.color: "red" @@ -96,7 +118,7 @@ import "schedulerscripts.js" as Scripts anchors.horizontalCenterOffset: parent.width/24 width: listRow.width - height: listRow.height + height: parent.height spacing: (parent.width-124)/24 Repeater{ model:24 @@ -191,7 +213,74 @@ import "schedulerscripts.js" as Scripts anchors.centerIn: parent z: 150 } + + //TODO move functions: + function getEveningDarkStart(){ + if(!willSunSet){ + return 0; + } + if(Scripts.isMidnightDark()){ + return sunToTimeUnits(main.sunData[1]) + 100; + } + else{ + return 0; + } + } + + function getMorningDarkStart(){ + //TODO the day of the year when the sun "begins" not to set, will it work then? + if(!willSunSet){ + return 0; + } + if(Scripts.isMidnightDark()){ + return 100; //TODO constants + } + else{ + return sunToTimeUnits(main.sunData[1]) + 100; //TODO constants + } + } + + function getEveningDarkWidth(){ + if(!willSunSet){ + return 0; + } + if(Scripts.isMidnightDark()){ + return (main.width - 100) - sunToTimeUnits(main.sunData[1]); //TODO constant or something + } + else{ + return 0; + } + + } + + function getMorningDarkWidth(){ + if(!willSunSet){ + return 0; + } + if(Scripts.isMidnightDark()){ + return sunToTimeUnits(main.sunData[0]); + } + else{ + return sunToTimeUnits(main.sunData[1]) - sunToTimeUnits(main.sunData[0]); + } + } + + function willSunSet(){ + if(main.sunData == undefined){ + main.sunData = getSunData.call(); + } + + return !(main.sunData[2] && main.sunData[2] != "") + } + function sunToTimeUnits(suntime){ + suntime = suntime.split(':'); + var hourSize = (main.width - 100)/24; //TODO constant or something? + print("Units: " + (hourSize * suntime[0] + suntime[1]/hourSize * 60)); + print("Size: " + hourSize); + print("Hour: " + suntime[0]); + return hourSize * suntime[0] + hourSize * suntime[1]/60; + } //opacity vid dimning? //linjens färg etc (state) beror ju på närmaste punkt föres sort... Punkten kan finnas osynlig (tidigare dag) också... //kan man liksom göra hela linjen (från en vecka tillbaka) men inte visa den? Om det är vettigt... Då hade man tom kunnat zooma en vacker dag diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 9e337828..567f7447 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -24,3 +24,19 @@ function pad(number, length) { return str; } + +function isMidnightDark(){ + if(main.sunData == undefined){ + main.sunData = getSunData.call(); + } + + var sunrise = main.sunData[0].split(':');; + var sunset = main.sunData[1].split(':'); + + if(sunset[0] < sunrise[0] || (sunset[0] == sunrise[0] && sunset[1] < sunrise[1])){ + print("Rise: " + sunrise); + print("Set: " + sunset); + return false; + } + return true; +} From eb463ca09fab3b5e4a901a2237de58538d940e16 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 18 Jan 2011 14:14:54 +0000 Subject: [PATCH 1519/2215] Different states can be added to a point --- .../SchedulerGUISimple/ActionPoint.qml | 43 ++++++++++++++++--- .../Plugins/SchedulerGUISimple/Dialog.qml | 11 ++++- .../Plugins/SchedulerGUISimple/main.qml | 11 ++--- .../SchedulerGUISimple/schedulerscripts.js | 9 ++++ 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 5ae24b02..82e322fe 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -10,6 +10,7 @@ Rectangle{ property string isPoint: "true" property variant isLoaded property int xvalue + //property variant activeStates: [] Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... @@ -49,9 +50,16 @@ Rectangle{ */ MouseArea { id: pointRectMouseArea + acceptedButtons: Qt.LeftButton | Qt.RightButton + onClicked: { //pointRect.focus = true - dialog.show(pointRect) //TODO om inte redan i visandes läge.... + if (mouse.button == Qt.RightButton){ + pointRect.toggleType() + } + else{ + dialog.show(pointRect) //TODO om inte redan i visandes läge.... + } } //onPositionChange... maybe emit signal to change in row... @@ -111,8 +119,9 @@ Rectangle{ Rectangle{ id: triggerTime width: 20; height: 20 - anchors.horizontalCenter: parent.horizontalCenter - anchors.verticalCenter: parent.verticalCenter + anchors.centerIn: parent + //anchors.horizontalCenter: parent.horizontalCenter + //anchors.verticalCenter: parent.verticalCenter Text{ text: getTime(pointRect.x, pointRect.width); font.pointSize: 6; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignBottom } @@ -152,7 +161,27 @@ Rectangle{ ] function toggleType(){ //TODO other kind of selection method - print(pointRect.state); + var index = 0; + + var activeStates = Scripts.getActiveStates(); + if(activeStates == undefined || activeStates.length == 0){ + return; + } + + for(var i=0;i Date: Wed, 19 Jan 2011 10:47:56 +0000 Subject: [PATCH 1520/2215] State of added point will depend on already added points state --- .../SchedulerGUISimple/ActionPoint.qml | 58 +++++++++-- .../Plugins/SchedulerGUISimple/Dialog.qml | 99 ++++++++++++++++--- .../Plugins/SchedulerGUISimple/main.qml | 34 +++---- .../SchedulerGUISimple/schedulerscripts.js | 34 +++++-- 4 files changed, 178 insertions(+), 47 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 82e322fe..8f9365b0 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -7,6 +7,7 @@ Rectangle{ property string actionTypeColor: "blue" //TODO default value property int actionType: 1 //TODO default value property double actionTypeOpacity: 1 + property string actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" property string isPoint: "true" property variant isLoaded property int xvalue @@ -80,7 +81,7 @@ Rectangle{ //opacity: 1 id: actionImage width: 20; height: 20 - source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" + source: pointRect.actionTypeImage } Rectangle{ @@ -140,29 +141,29 @@ Rectangle{ State { name: "on" PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } //TODO: images!! - PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" } + PropertyChanges { target: pointRect; actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" } }, State{ name: "off" PropertyChanges { target: pointRect; actionTypeColor: "gainsboro"; actionTypeOpacity: 0 } - PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices-bw.png" } + PropertyChanges { target: pointRect; actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices-bw.png" } + //PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices-bw.png" } }, State{ name: "dim" PropertyChanges { target: pointRect; actionTypeColor: "green"; actionTypeOpacity: 1 } - PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/TelldusCenter_128.png" } + PropertyChanges { target: pointRect; actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/TelldusCenter_128.png" } //something opacity = dim for example }, State{ name: "bell" PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } - PropertyChanges { target: actionImage; source: "icon.png" } + PropertyChanges { target: pointRect; actionTypeImage: "icon.png" } } ] function toggleType(){ //TODO other kind of selection method var index = 0; - var activeStates = Scripts.getActiveStates(); if(activeStates == undefined || activeStates.length == 0){ return; @@ -197,6 +198,11 @@ Rectangle{ */ } + function setType(name){ + print("setting state to " + name); + pointRect.state = name; + } + function toggleTrigger(){ //TODO other kind of selection method if(trigger.state == "sunrise"){ trigger.state = "sunset"; @@ -252,4 +258,44 @@ Rectangle{ function addState(state){ Scripts.addState(state); } + + function setFirstState(firstState){ + + var activeStates = Scripts.getActiveStates(); + + if(activeStates == null || activeStates.length == 0){ + //nothing to do + return; + } + + //state may already be set: + if(firstState != undefined && firstState != ""){ + pointRect.state = firstState; + return; + } + + //check that device has the "off" state: + var exists = false; + for(var i=1;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic + prevPoint = pointList[i]; + } + } + } + + if(prevPoint == null){ + return ""; + } + + return prevPoint.state; } function isMidnightDark(){ @@ -49,3 +57,13 @@ function isMidnightDark(){ } return true; } + +function pad(number, length) { + + var str = '' + number; + while (str.length < length) { + str = '0' + str; + } + + return str; +} From 5e073647e9ee65ef6a3929714542d9a977557123 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 19 Jan 2011 11:35:54 +0000 Subject: [PATCH 1521/2215] Action points can be removed --- .../SchedulerGUISimple/ActionPoint.qml | 13 ++++++ .../Plugins/SchedulerGUISimple/Dialog.qml | 43 +++++++++++++++++-- .../Plugins/SchedulerGUISimple/main.qml | 3 +- .../SchedulerGUISimple/schedulerscripts.js | 17 ++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 8f9365b0..986a672c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -11,6 +11,7 @@ Rectangle{ property string isPoint: "true" property variant isLoaded property int xvalue + property variant hangOnToBar //property variant activeStates: [] Component.onCompleted: { @@ -298,4 +299,16 @@ Rectangle{ pointRect.state = "off"; //previous point should be "on" or "dim" } + + function remove(){ + //TODO kanske inte här, utan i listan? + //destroy den här, men också ta bort linjen samt räkna om linjen från punkten före... + if(pointRect.hangOnToBar != null){ + hangOnToBar.destroy(); + } + var x = pointRect.x; + var pointList = pointRect.parent.children; + pointRect.destroy(); + Scripts.recalculateWidth(x, pointList); + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index c41ad6b4..89150a4c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -94,9 +94,38 @@ color: buttonMouseAreaTrigger.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor } - - - Rectangle { //TODO create common button-class + + Rectangle { + id: removePoint + height: 20 + width: 100 + anchors.horizontalCenter: circleTrigger.horizontalCenter + y: circleTrigger.y + 30 + + property color buttonColor: "lightgrey" + + Text{ + text: "Remove action" + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.margins: 2 + + } + MouseArea { + id: buttonMouseAreaRemovePoint + anchors.fill: parent + hoverEnabled: true + //onEntered: parent.border.color = onHoverColor + //onExited: parent.border.color = borderColor + onClicked: { + container.actionPoint.remove(); + } + } + + color: buttonMouseAreaRemovePoint.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor + } + + Rectangle { //TODO create common button-class (but how to differentiate action?) id: closeButton height: 20 width: 100 @@ -174,7 +203,13 @@ height: 120 Image{ anchors.fill: parent - source: actionPoint.actionTypeImage //TODO, set only when defined... + id: mainImage + states: State { + name: "typeLoaded"; when: actionPoint.actionTypeImage != undefined + PropertyChanges { target: mainImage + source: actionPoint.actionTypeImage + } + } } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index ec72850c..0021eec7 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -56,6 +56,7 @@ import "schedulerscripts.js" as Scripts var dynamicBar = actionBar.createObject(deviceRow) dynamicBar.hangOnToPoint = dynamicPoint + dynamicPoint.hangOnToBar = dynamicBar dialog.show(dynamicPoint) @@ -195,7 +196,7 @@ import "schedulerscripts.js" as Scripts // couldnt get this to work: // (if it works later on, try to set opacity for actionPoint in this way too) states: State { - name: "myState"; when: hangOnToPoint.isLoaded != undefined && hangOnToPoint.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning + name: "pointLoaded"; when: hangOnToPoint.isLoaded != undefined && hangOnToPoint.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning PropertyChanges { target: barRectangle anchors.verticalCenter: hangOnToPoint.verticalCenter diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 8ee07a7b..bb867020 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -67,3 +67,20 @@ function pad(number, length) { return str; } + +function recalculateWidth(currentx, pointList){ + var prevPoint = null; + for(var i=0;i prevPoint.x)){ + prevPoint = pointList[i]; + } + } + } + + if(prevPoint == null){ + return; + } + + prevPoint.width = getBarWidth(prevPoint.hangOnToBar, prevPoint, pointList); +} From 5fd725a0107b5c80d73c6d3afc7446602abd2d01 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 20 Jan 2011 10:47:06 +0000 Subject: [PATCH 1522/2215] Remove actionpoint-fix. Some fuzziness development --- .../SchedulerGUISimple/ActionPoint.qml | 14 +- .../Plugins/SchedulerGUISimple/Dialog.qml | 208 ++++++++++++++++-- .../Plugins/SchedulerGUISimple/main.qml | 6 +- .../SchedulerGUISimple/schedulerscripts.js | 24 +- 4 files changed, 218 insertions(+), 34 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 986a672c..762c7893 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -12,8 +12,9 @@ Rectangle{ property variant isLoaded property int xvalue property variant hangOnToBar - //property variant activeStates: [] - + property int fuzzyBefore: 0 + property int fuzzyAfter: 55 + Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... isLoaded = "true" @@ -71,7 +72,6 @@ Rectangle{ drag.minimumX: -15 //TODO make relative drag.maximumX: 685 //TODO make relative!! //TODO make it impossible to overlap (on release) - //onPositionChanged: { value = (maximum - minimum) * (handle.x-2) / slider.xMax + minimum; } } Column{ @@ -125,7 +125,7 @@ Rectangle{ //anchors.horizontalCenter: parent.horizontalCenter //anchors.verticalCenter: parent.verticalCenter Text{ - text: getTime(pointRect.x, pointRect.width); font.pointSize: 6; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignBottom + text: fuzzyAfter //TODO debug getTime(pointRect.x, pointRect.width); font.pointSize: 6; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignBottom } } @@ -229,7 +229,10 @@ Rectangle{ } } + var test = "" //TODO Binding loop here when moving transperent point over other point + //...or just changing state to transparent + //something with point depending on point depending on point? if(prevPoint == null || prevPoint.actionTypeOpacity == 0){ //no point before, no bar after either actionTypeOpacity = 0 @@ -307,8 +310,9 @@ Rectangle{ hangOnToBar.destroy(); } var x = pointRect.x; + pointRect.isPoint = "false" var pointList = pointRect.parent.children; pointRect.destroy(); - Scripts.recalculateWidth(x, pointList); + //Scripts.recalculateWidth(x, pointList); } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 89150a4c..0521a968 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -1,21 +1,40 @@ import Qt 4.7 Rectangle { - id: container - property ActionPoint actionPoint + id: container + property ActionPoint actionPoint + + Component.onCompleted: { + //create default actionPoint, to avoid null values and binding errors + var component = Qt.createComponent("ActionPoint.qml") + var dynamicPoint = component.createObject(container) + dynamicPoint.opacity = 0 + dynamicPoint.width = 0 + dynamicPoint.height = 0 + container.actionPoint = dynamicPoint + } + + /* + states: State{ + name: "visible"; when: actionPoint.fuzzyAfter != undefined + PropertyChanges{ + target: container; fuzzyAfter: actionPoint.fuzzyAfter + } + } + */ - function show(actionPoint) { - container.opacity = 1; - container.border.color = "black" - container.border.width = 2 - container.actionPoint = actionPoint - - var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); - //container.x = rootCoordinates.x + actionPoint.parent.width/2 - container.width/2; - container.y = rootCoordinates.y + actionPoint.height + 10; - container.width = actionPoint.parent.width; - container.x = (actionPoint.parent.parent.width - container.width)/2; - } + function show(actionPoint) { + container.opacity = 1; + container.border.color = "black" + container.border.width = 2 + container.actionPoint = actionPoint + + var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); + //container.x = rootCoordinates.x + actionPoint.parent.width/2 - container.width/2; + container.y = rootCoordinates.y + actionPoint.height + 10; + container.width = actionPoint.parent.width; + container.x = (actionPoint.parent.parent.width - container.width)/2; + } function hide() { container.opacity = 0; @@ -54,7 +73,7 @@ MouseArea { id: buttonMouseAreaType anchors.fill: parent - hoverEnabled: true + //hoverEnabled: true //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { @@ -84,7 +103,7 @@ MouseArea { id: buttonMouseAreaTrigger anchors.fill: parent - hoverEnabled: true + //hoverEnabled: true //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { @@ -114,7 +133,7 @@ MouseArea { id: buttonMouseAreaRemovePoint anchors.fill: parent - hoverEnabled: true + //hoverEnabled: true //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { @@ -125,6 +144,155 @@ color: buttonMouseAreaRemovePoint.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor } + Rectangle{ + id: fuzzyPanel + height: 100 + width: 80 + + anchors.left: removePoint.right + anchors.leftMargin: 10 + anchors.top: parent.top + anchors.topMargin: 10 + + Text{ + id: textFuzzyBefore + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.top: parent.top + anchors.topMargin: 5 + text: "Fuzzy before:" + } + + Text{ + id: textFuzzyBeforeUnit + anchors.left: inputFuzzyBefore.right + anchors.leftMargin: 5 + anchors.verticalCenter: textFuzzyBefore.verticalCenter + text: "seconds" + } + + Text{ + id: textFuzzyAfter + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.top: textFuzzyBefore.bottom + anchors.topMargin: 5 + text: "Fuzzy after:" + } + + Text{ + id: textFuzzyAfterUnit + anchors.left: inputFuzzyBefore.right + anchors.leftMargin: 5 + anchors.verticalCenter: textFuzzyAfter.verticalCenter + text: "seconds" + } + + Rectangle{ + id: inputFuzzyBefore + anchors.left: textFuzzyBefore.right + anchors.leftMargin: 5 + anchors.verticalCenter: textFuzzyBefore.verticalCenter + width: 35 + height: textFuzzyBefore.height + border.width: 1 + + TextInput{ + id: inputFuzzyBeforeText + anchors.fill: parent + maximumLength: 5 + selectByMouse: true + color: "#151515"; selectionColor: "mediumseagreen" + text: "0" //container.actionPoint.fuzzyBefore + } + } + + Rectangle{ + id: inputFuzzyAfter + anchors.left: textFuzzyAfter.right + anchors.leftMargin: 5 + anchors.verticalCenter: textFuzzyAfter.verticalCenter + width: 35 + height: textFuzzyAfter.height + border.width: 1 + + TextInput{ + id: inputFuzzyAfterText + anchors.fill: parent + maximumLength: 5 + selectByMouse: true + color: "#151515"; selectionColor: "mediumseagreen" + text: actionPoint.fuzzyAfter + } + + Binding { + target: actionPoint + property: "fuzzyAfter" + value: inputFuzzyAfterText.text + } + } + + Image{ + //TODO turn into component? + anchors.left: textFuzzyBeforeUnit.right + anchors.leftMargin: 5 + anchors.verticalCenter: textFuzzyBeforeUnit.verticalCenter + + source: "icon.png" //TODO info-icon + + MouseArea{ + anchors.fill: parent + hoverEnabled: true + onEntered: { + infobox.opacity = 1 + infobox.infoboxtext = "Enter a value indicating how many seconds before the set value that the action may be executed. The action will be executed at a random time within the interval." + } + onExited: { + infobox.opacity = 0 + } + } + } + + Image{ + //TODO turn into component? + anchors.left: textFuzzyAfterUnit.right + anchors.leftMargin: 5 + anchors.verticalCenter: textFuzzyAfterUnit.verticalCenter + + source: "icon.png" //TODO info-icon + + MouseArea{ + anchors.fill: parent + hoverEnabled: true + onEntered: { + infobox.opacity = 1 + infobox.infoboxtext = "Enter a value indicating how many seconds after the set value that the action may be executed. The action will be executed at a random time within the interval." + } + onExited: { + infobox.opacity = 0 + } + } + } + + Rectangle{ + id: infobox + property alias infoboxtext: infoboxtext.text + opacity: 0 + color: "antiquewhite" + width: infoboxtext.width + 4 + height: infoboxtext.height + 4 + border.color: "black" + border.width: 1 + Text{ + id: infoboxtext + anchors.centerIn: parent + width: 200 + wrapMode: Text.WordWrap + text: "" + } + } + } + Rectangle { //TODO create common button-class (but how to differentiate action?) id: closeButton height: 20 @@ -145,7 +313,7 @@ MouseArea { id: buttonMouseAreaClose anchors.fill: parent - hoverEnabled: true + //hoverEnabled: true //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { @@ -204,12 +372,14 @@ Image{ anchors.fill: parent id: mainImage - states: State { + source: actionPoint.actionTypeImage + /*states: State { name: "typeLoaded"; when: actionPoint.actionTypeImage != undefined PropertyChanges { target: mainImage source: actionPoint.actionTypeImage } } + */ } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 0021eec7..0d0f3570 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -34,7 +34,7 @@ import "schedulerscripts.js" as Scripts MouseArea { id: deviceMouseArea anchors.fill: parent - hoverEnabled: true + //hoverEnabled: true //TODO ändra muspekaren kanske? //onEntered: parent.border.color = onHoverColor @@ -163,7 +163,7 @@ import "schedulerscripts.js" as Scripts MouseArea { id: buttonMouseArea anchors.fill: parent - hoverEnabled: true + //hoverEnabled: true //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { @@ -203,7 +203,7 @@ import "schedulerscripts.js" as Scripts anchors.left: hangOnToPoint.horizontalCenter color: hangOnToPoint.actionTypeColor opacity: hangOnToPoint.actionTypeOpacity - width: Scripts.getBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children) + width: Scripts.getNextAndPrevBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children); //getBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children) } //anchors.verticalCenter: hangOnToPoint.verticalCenter //anchors.left: hangOnToPoint.horizontalCenter diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index bb867020..bd731015 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -13,14 +13,13 @@ function getBarWidth(currentBar, currentPointRect, pointList){ var maxWidth = currentPointRect.parent.width; var nextX = maxWidth var halfPointWidth = currentPointRect.width / 2 - for(var i=1;i (currentPointRect.x + halfPointWidth)){ nextX = pointList[i].x + halfPointWidth; } } } - return nextX - (currentPointRect.x + halfPointWidth); } @@ -28,7 +27,7 @@ function getPreviousState(currentPointRect, pointList){ var prevPoint = null; for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic prevPoint = pointList[i]; } @@ -68,19 +67,30 @@ function pad(number, length) { return str; } +function getNextAndPrevBarWidth(currentBar, currentPointRect, pointList){ + //TODO error whn < 30 (width) + //recalculateWidth(currentPointRect.x, pointList); + return getBarWidth(currentBar, currentPointRect, pointList); +} + +/* function recalculateWidth(currentx, pointList){ var prevPoint = null; for(var i=0;i prevPoint.x)){ prevPoint = pointList[i]; } } } - if(prevPoint == null){ + if(prevPoint == null || prevPoint.hangOnToBar == undefined){ return; } - prevPoint.width = getBarWidth(prevPoint.hangOnToBar, prevPoint, pointList); + var temp = getBarWidth(prevPoint.hangOnToBar, prevPoint, pointList); + print(temp); + + //prevPoint.hangOnToBar.width = temp; } +*/ From 14485794d9543defcf01b04f8b745befdc194de0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 20 Jan 2011 11:16:11 +0000 Subject: [PATCH 1523/2215] Fixed bar width-bug --- telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml | 10 +++++----- .../Plugins/SchedulerGUISimple/schedulerscripts.js | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 0521a968..83f1c11d 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -168,7 +168,7 @@ anchors.left: inputFuzzyBefore.right anchors.leftMargin: 5 anchors.verticalCenter: textFuzzyBefore.verticalCenter - text: "seconds" + text: "minutes" } Text{ @@ -182,10 +182,10 @@ Text{ id: textFuzzyAfterUnit - anchors.left: inputFuzzyBefore.right + anchors.left: inputFuzzyAfter.right anchors.leftMargin: 5 anchors.verticalCenter: textFuzzyAfter.verticalCenter - text: "seconds" + text: "minutes" } Rectangle{ @@ -245,7 +245,7 @@ hoverEnabled: true onEntered: { infobox.opacity = 1 - infobox.infoboxtext = "Enter a value indicating how many seconds before the set value that the action may be executed. The action will be executed at a random time within the interval." + infobox.infoboxtext = "Enter a value indicating how many minutes before the set value that the action may be executed. The action will be executed at a random time within the interval." } onExited: { infobox.opacity = 0 @@ -266,7 +266,7 @@ hoverEnabled: true onEntered: { infobox.opacity = 1 - infobox.infoboxtext = "Enter a value indicating how many seconds after the set value that the action may be executed. The action will be executed at a random time within the interval." + infobox.infoboxtext = "Enter a value indicating how many minutes after the set value that the action may be executed. The action will be executed at a random time within the interval." } onExited: { infobox.opacity = 0 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index bd731015..4d6f611c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -11,16 +11,16 @@ function getActiveStates(){ function getBarWidth(currentBar, currentPointRect, pointList){ var maxWidth = currentPointRect.parent.width; - var nextX = maxWidth - var halfPointWidth = currentPointRect.width / 2 + var nextX = maxWidth - currentPointRect.width / 2 for(var i=0;i (currentPointRect.x + halfPointWidth)){ - nextX = pointList[i].x + halfPointWidth; + if(pointList[i].x < nextX && pointList[i].x > currentPointRect.x){ + nextX = pointList[i].x; } } } - return nextX - (currentPointRect.x + halfPointWidth); + + return (nextX - currentPointRect.x); } function getPreviousState(currentPointRect, pointList){ From 0c9babe203deac3fa5f9f6890a86cc1f867640c5 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 20 Jan 2011 11:48:08 +0000 Subject: [PATCH 1524/2215] Images added --- .../SchedulerGUISimple/ActionPoint.qml | 20 ++++++------- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 8 ++++++ .../Plugins/SchedulerGUISimple/Dialog.qml | 27 ++++++++---------- .../Plugins/SchedulerGUISimple/__init__.js | 10 +++++++ .../Plugins/SchedulerGUISimple/absolute.png | Bin 0 -> 32273 bytes .../Plugins/SchedulerGUISimple/bell.png | Bin 0 -> 2399 bytes .../Plugins/SchedulerGUISimple/dim.png | Bin 0 -> 11651 bytes .../Plugins/SchedulerGUISimple/info.png | Bin 0 -> 32273 bytes .../Plugins/SchedulerGUISimple/main.qml | 3 +- .../Plugins/SchedulerGUISimple/off.png | Bin 0 -> 1453 bytes telldus-gui/Plugins/SchedulerGUISimple/on.png | Bin 0 -> 1483 bytes .../Plugins/SchedulerGUISimple/sunrise.png | Bin 0 -> 10787 bytes .../Plugins/SchedulerGUISimple/sunset.png | Bin 0 -> 11004 bytes 13 files changed, 39 insertions(+), 29 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/absolute.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/bell.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/dim.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/info.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/off.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/on.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/sunrise.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/sunset.png diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 762c7893..02b44feb 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -97,21 +97,21 @@ Rectangle{ State { //TODO if no sunrise/sunset exists (arctic circle...), check so it works anyway name: "sunrise" - PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunrise.png"; opacity: 1 } //TODO: images!! + PropertyChanges { target: triggerImage; source: imageTriggerSunrise; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } PropertyChanges { target: pointRect; x: getSunRiseTime.call(pointRect.parent.width, pointRect.width) } }, State { name: "sunset" - PropertyChanges { target: triggerImage; source: "/home/stefan/Downloads/sunset.png"; opacity: 1 } //TODO: images!! + PropertyChanges { target: triggerImage; source: imageTriggerSunset; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } PropertyChanges { target: pointRect; x: getSunSetTime.call(pointRect.parent.width, pointRect.width) } }, State { name: "absolute" - PropertyChanges { target: triggerImage; opacity: 0; } //TODO: images!! + PropertyChanges { target: triggerImage; opacity: 0; } PropertyChanges { target: triggerTime; opacity: 1 } PropertyChanges { target: pointRectMouseArea; drag.target: parent } PropertyChanges { target: pointRect; x: xvalue } @@ -122,8 +122,6 @@ Rectangle{ id: triggerTime width: 20; height: 20 anchors.centerIn: parent - //anchors.horizontalCenter: parent.horizontalCenter - //anchors.verticalCenter: parent.verticalCenter Text{ text: fuzzyAfter //TODO debug getTime(pointRect.x, pointRect.width); font.pointSize: 6; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignBottom } @@ -133,7 +131,7 @@ Rectangle{ id: triggerImage anchors.fill: parent width: 20; height: 20 - source: "/home/stefan/Downloads/11949889941371111141clock_michael_breuer_01.svg.hi.png" + source: imageTriggerAbsolute } } } @@ -142,24 +140,22 @@ Rectangle{ State { name: "on" PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } //TODO: images!! - PropertyChanges { target: pointRect; actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" } + PropertyChanges { target: pointRect; actionTypeImage: imageActionOn } }, State{ name: "off" PropertyChanges { target: pointRect; actionTypeColor: "gainsboro"; actionTypeOpacity: 0 } - PropertyChanges { target: pointRect; actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices-bw.png" } - //PropertyChanges { target: actionImage; source: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices-bw.png" } + PropertyChanges { target: pointRect; actionTypeImage: imageActionOff } }, State{ name: "dim" PropertyChanges { target: pointRect; actionTypeColor: "green"; actionTypeOpacity: 1 } - PropertyChanges { target: pointRect; actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/TelldusCenter_128.png" } - //something opacity = dim for example + PropertyChanges { target: pointRect; actionTypeImage: imageActionDim } }, State{ name: "bell" PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } - PropertyChanges { target: pointRect; actionTypeImage: "icon.png" } + PropertyChanges { target: pointRect; actionTypeImage: imageActionBell } } ] diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 62df1df1..73a23024 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -11,6 +11,14 @@ SET( Plugin_EXTRA icon.png main.qml schedulerscripts.js + absolute.png + sunrise.png + sunset.png + on.png + off.png + dim.png + bell.png + info.png ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 83f1c11d..bcde3683 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -200,7 +200,7 @@ TextInput{ id: inputFuzzyBeforeText anchors.fill: parent - maximumLength: 5 + maximumLength: 4 selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" text: "0" //container.actionPoint.fuzzyBefore @@ -219,7 +219,7 @@ TextInput{ id: inputFuzzyAfterText anchors.fill: parent - maximumLength: 5 + maximumLength: 4 selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" text: actionPoint.fuzzyAfter @@ -238,7 +238,9 @@ anchors.leftMargin: 5 anchors.verticalCenter: textFuzzyBeforeUnit.verticalCenter - source: "icon.png" //TODO info-icon + source: imageInfo + width: 15 + height: 15 MouseArea{ anchors.fill: parent @@ -259,7 +261,9 @@ anchors.leftMargin: 5 anchors.verticalCenter: textFuzzyAfterUnit.verticalCenter - source: "icon.png" //TODO info-icon + source: imageInfo + width: 15 + height: 15 MouseArea{ anchors.fill: parent @@ -342,19 +346,19 @@ id: typeSelection ListElement{ name: "on" - imagesource: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" + imagesource: "on.png" //TODO cannot use javascript properties here... do in some other way, maybe a list with names here? } ListElement{ name: "off" - imagesource: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices-bw.png" + imagesource: "off.png" } ListElement{ name: "dim" - imagesource: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/TelldusCenter_128.png" + imagesource: "dim.png" } ListElement{ name: "bell" - imagesource: "icon.png" + imagesource: "bell.png" } } } @@ -373,13 +377,6 @@ anchors.fill: parent id: mainImage source: actionPoint.actionTypeImage - /*states: State { - name: "typeLoaded"; when: actionPoint.actionTypeImage != undefined - PropertyChanges { target: mainImage - source: actionPoint.actionTypeImage - } - } - */ } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 3051d799..844b904a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -22,6 +22,16 @@ com.telldus.schedulersimplegui = function() { deviceList.push(list[i]); } view.setProperty('deviceModel', deviceList); + //set images: + view.setProperty("imageTriggerSunrise", "sunrise.png"); + view.setProperty("imageTriggerSunset", "sunset.png"); + view.setProperty("imageTriggerAbsolute", "absolute.png"); + view.setProperty("imageActionOn", "on.png"); + view.setProperty("imageActionOff", "off.png"); + view.setProperty("imageActionDim", "dim.png"); + view.setProperty("imageActionBell", "bell.png"); + view.setProperty("imageInfo", "info.png"); + view.load("main.qml"); application.addWidget("scheduler.simple", "icon.png", view); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/absolute.png b/telldus-gui/Plugins/SchedulerGUISimple/absolute.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f0020097d3236ddca46bb903b1040476606e55 GIT binary patch literal 32273 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/bell.png b/telldus-gui/Plugins/SchedulerGUISimple/bell.png new file mode 100644 index 0000000000000000000000000000000000000000..85daef3b0b519c8d4fe6cc1efc1c67e660e0f8e9 GIT binary patch literal 2399 zcmV-l3840gP)4588HS&8xA82V&3hc%v6C1lA)yHbN)}Qer39sbN+U{J z3I#+(p(+&!T2NL0L9OUcM60qXq*bc~iV~f!Do!l&Q7KOM0T~Rs$Y{*Ugt`80TM4r5W-Z1=#!58 zhZO8==?Hw#+1crSmb&8825i~#18+dnz6bJ0bq#e!^TM`@Xib%(>pHro;kYhl&SY}Z zBoT|bLuUqZ#p2eT+kahyt5;LhbX3Pg+QXuf*k=N`_m0PI6$;NUUfNN) zeANn%K#)wQNu|cIObat-;z|ciRZ&zGzu$|`AD~buGTMK{@>P7CzxJB$KVQDOZv3Bsg8O)it4>T92B)sL|H8h?;O7VfRolhpDW;3C%kn)65f##TXk)P{?;d z@fgw2D2?+R73I=;v*3$*J)L?e-u}KJ%v^?O zq{ymO%UD?3gW2Cnrtc3(S!BpuO*-eHuC^XcQwaux)YsQiT{TEu?I7V`Kbo-&qhhU4 z)a9BhLz=2gx{v^zQG__9ohQDrG8B4z{k7}7y{FEAVp3OYu;!``Mh<_U(aF<9o3>z7 zwu3B?81n(3C<*|s>mr08;8)NU9ZfNiq7I>Upcz+Sn}4q;I>)`5P(nxosII3Buw}~@ zRiM0h&GldK4-SrE7qZN6^s?^iC7ga|6TZmjs9yF2(zS7&ain9jAeyCm;g`z7=h6eh zgQ^Imn!|O5DcT1>Cdpf7z;8%PsM11FC(8hpYV*A<3tMYY6=Ja%%}oYt*R0|fKWyQ{ zo?3pt^#)wW1lL45d0fZBmCO>J4p)Yeq6$aWpvqGy0_>azL;}Y?tqdpq%Dje&5dyim zQf^0~JhgP?a_^bGL8_uED_5?-QxV|4hn^-Fs^#{(e?}@9!zqm86fzX;6pl4EOMLp= zaTic@S}8b-C>C`n9zfw8vYCU#5>avB;Jgl7nr{n%tpMD8`y*FGYpXp1ftkw^3VEoj zs|5u0?f0{N$9~qXxtiPV`W*uULpXK@w*)a)NP-mH6%?EmSjCm(iFREm-@W(2V0j%73SVt(ZuTb=DZD;Gb93YDz7&F|fAs>jbx(5p{V(wR)9Yw%P;s3+ zQc9$h=fq3ruB^v$Hy~(5FpOI)kjf5o_=vzXJ>H_ye;e?=GUdOrDO?p+GN}yVut7sZ zL%G<@eDv|B=&0ZyF#TkF$C6%_I^D)~#KK z-|y#{XMR&2cRomK%fj+~Aq1MPQ?P9$(mdA%f_`%{w_MRwibaWKS$I623#^aF6Wnsk zt(-V$cXKY%i2AA3@-n_!%!xOBZ5STj+kcQiB*H{8=}IB?lmP_18XF$Tdi?>0 zhf*YynOOx~*Tr!hLZKj6Ub&jrUi&MNNMugP^MTHNLXG#|Jw&9shKW=yzKbn>ohN1%wS(%4%dBhx;3T& z$Z_VyiBvjKu=05QA@=|KV`8z?ECI)HX640%r;owP2-}`}1%IRpJD(#rF_C&}|BgRR z>y~#!U0q%J{KmFE$0}}~-`c9jM&ej`lbX6Hx~|W;G@tH2Njj4x6bxVROb9_ZT*aHO z@8igklQg!r(c68(JUiI?$l+rj^aB>)&fJpuKRIpwln$lw^Q zi<;0>1<7oYbS4czWgs}~zRwq+vNFWB=XP@R*lAjqET!k@5o>JZ>|gf&>y=%A0~7&! zCV&s{o#^?fdtp<@GBca4Z)#hljb|qL?>h&ms;MFxji9J1AaNXrU}cD4WvJZeKA)d} zKS=M%GyL}FFHvxH8k(BvIdara#>YO|y?6W8(wk3be&&Bc5QqR_AbQirJ07gBZTfOc zd%NKa1Q=V&x@V`T5I;R)wjks6bH^3WXx6WSV#XbC3_-JA|rxX>41_@ae zQdm|V+pwn& z7yzzx3bt(}#xu#T{-K_CyH6eNavUcI`~YGyltUCMk3AYBr-=MwqUzvCG&dP%sVbgs_;aG7eW0_SG9UAlMC_#ZE!mKFGu RQpNxP002ovPDHLkV1kVygbx4! literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/dim.png b/telldus-gui/Plugins/SchedulerGUISimple/dim.png new file mode 100644 index 0000000000000000000000000000000000000000..7b001d243fabdce6e03a686da5271bd85dd7bcc7 GIT binary patch literal 11651 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 N002ovPDHLkV1mDXB3b|d literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/info.png b/telldus-gui/Plugins/SchedulerGUISimple/info.png new file mode 100644 index 0000000000000000000000000000000000000000..e0f0020097d3236ddca46bb903b1040476606e55 GIT binary patch literal 32273 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 0d0f3570..2f980f30 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -7,8 +7,7 @@ import "schedulerscripts.js" as Scripts width: 800 //TODO how? height: 600 //TODO how? property variant sunData - property string dimImageSource: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/TelldusCenter_128.png" //TODO use this somehow? - + Component{ id: listRow diff --git a/telldus-gui/Plugins/SchedulerGUISimple/off.png b/telldus-gui/Plugins/SchedulerGUISimple/off.png new file mode 100644 index 0000000000000000000000000000000000000000..007a177832a03e7c3cc84a343591e8bf67f79cd1 GIT binary patch literal 1453 zcmV;e1ycHnP)( z`eLz)g$4=+(L!7LAhGmDAEc$wry}&thf;;~2BJi$Vv$+`F*P<;EgFlL+>?{bo;`c^ z%*@}1J$rJZC$$|Ic9-4noA00R`)7%n@$eub08lGdJeORxYW=gR)Pl82sVc4g>#m!= zdj9;$2LNjuDwG< z-!XH34nA6ih^V=F&(mABZ24yI-j=lu4Rw-800`elVwf4sjQ;-n!G#N#`>tN?ef{|H zFK$LWDk^c~#vRLAT3-IGt?kw7L?Q-&05F(ClG1x-VEOW;vE93C)+r?~3=Y1wfrti} zxma>+-MSY~wzlr9ipL!g0pT{Hpm3JVS}rP0CgZey`{ueJ$anPgTzm;YP7o38+jscw zZQGjHRa7JiAP@-uPBnz(=)`rj3)eA&px3?LjGpL?VV%Dis%9T|f7Eo-Y7EYlCbyhak|zQfDi&oi9)&gY=02@7B&?XNCl*n(Awnk zdB5Y}!TqA_BBOG-08$D#jzTQv0DwO*F!Xs-)0$5?Z0y;zm(CYn*tD>>_b>O( zod@i?9=oo`>GTW_4^Qye*d$L*&amrxJTWmf)6%l7=3#uXxEro zisgs<%eT&+?aVxke}oW#aoy=3l@h)&ws@R5jx1(R2w^-ga|S^Ev4qUb7cc&D#&MKp zw#HgxUDwq^Lqq!R-Fv#f|Bk+Q?|#0g=kgC+=C@Z)A&wk5JUTj>&S`C>wGjC{t4zkI z(b0?=8_TLom;RhNdi2b%02HK@2m-6;!_BAAW-?hLB|&SA$;l}U3=G5bvWUlH@O|IW+L-@C==Jyi{mID4 z#Cw&MPNU~#oWa2%WV6P&uDv@lGWK;}-^Jl_Kq?cZ@C6aAT)DF9z=0$0YHi-iWe7q zgU|;lC7z9#1PZePHfAVnIx0p%=OHi z%bYoL_I2&G*XP6DV<*!YgBw2fX2but{@?elZ!IMv?0l3`0N(gGwQru_qjw(S6Rxno z(`5SE4DWt*oMpi5rbR?<3Ba44<{^`Oc}239wAFvjB%89L-?272t!?*5XT_}qq=84fv*r#<@d*3n)N9a*zzffYl&nO?o@+KAdkQVU^Y?1_v{<4@i5?ffbZG6Mj-_Olmn`Si2}0HVGg!*XyXEyhlSf@ z4$pG;=kH^mbNYG4l-w;yTC9#L+^HHUw^#&QrmP_^Q{HkI*CAd-gzSe8bKE&n-LdG=RK(OYnk4DvphRj`|7L?B7ogt8HN z1SW)d9-6O0&;bofFYSf^@A2ts&8%ffyS_`~yfG z!2D}QUXc3v1hWCA16dnPtNdPvtOuqKSpX)2G=?OBB!!}^!5g#u7%*NrDOdWx{pY#C zk>d}l58UBErPzY#U?ZTzrfOHe$K12b8VX<{%;&anHQ}nqQ2}+mOy7x{0ZurR9BOD&~u?lQn%&dt( z_aW{JkpNNRv&hXgr zyndY^3B$?S(%(PJkw=PVG%v%_Sx8;b4w!vpy=eAN*9dp&ot-~`yxF#Ykokp#%{pWj z`s)x{h%yLM*y!dPz4W!>D7p<$MC8v?ycWl!CSC34X;ib#<$Y#$am36lkC>~?5i=Xy znZ3ET&r@eFJZVTK7_NvwD lUA0>6V7J?y0rdaU{0Bermul{N&(r__002ovPDHLkV1oL5&JzFt literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/sunrise.png b/telldus-gui/Plugins/SchedulerGUISimple/sunrise.png new file mode 100644 index 0000000000000000000000000000000000000000..20be4041c58ca55d3b6d39a68cbced06f3ac6029 GIT binary patch literal 10787 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 DGU+a0 literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/sunset.png b/telldus-gui/Plugins/SchedulerGUISimple/sunset.png new file mode 100644 index 0000000000000000000000000000000000000000..5b741342d4f41f91451e9a644ed1823b58db8948 GIT binary patch literal 11004 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 Date: Thu, 20 Jan 2011 11:52:02 +0000 Subject: [PATCH 1525/2215] Not possible to 'click through' dialog anymore --- telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index bcde3683..d2aeabc0 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -4,6 +4,10 @@ id: container property ActionPoint actionPoint + MouseArea{ + anchors.fill: parent + } + Component.onCompleted: { //create default actionPoint, to avoid null values and binding errors var component = Qt.createComponent("ActionPoint.qml") From 5abf7e70460523735b7a1303314c3a98eda087d0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 20 Jan 2011 11:54:48 +0000 Subject: [PATCH 1526/2215] Hiding settings dialog when removing a point --- telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 02b44feb..e8d53742 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -309,6 +309,7 @@ Rectangle{ pointRect.isPoint = "false" var pointList = pointRect.parent.children; pointRect.destroy(); + dialog.hide(); //Scripts.recalculateWidth(x, pointList); } } From 372ee9537fb9d6fb8330b3f1837abd4f1403c05b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 20 Jan 2011 14:41:45 +0000 Subject: [PATCH 1527/2215] Somewhat showing fuzzy-interval on bars now --- .../SchedulerGUISimple/ActionPoint.qml | 52 +++++++++++++++--- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 1 + .../Plugins/SchedulerGUISimple/Dialog.qml | 16 ++++-- .../Plugins/SchedulerGUISimple/__init__.js | 2 + .../Plugins/SchedulerGUISimple/main.qml | 54 ++----------------- 5 files changed, 66 insertions(+), 59 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index e8d53742..2736c81a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -11,13 +11,16 @@ Rectangle{ property string isPoint: "true" property variant isLoaded property int xvalue - property variant hangOnToBar - property int fuzzyBefore: 0 + //property variant hangOnToBar + property int fuzzyBefore: 100 property int fuzzyAfter: 55 Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... isLoaded = "true" + var dynamicBar = actionBar.createObject(pointRect) + dynamicBar.hangOnToPoint = pointRect + //pointRect.hangOnToBar = dynamicBar } //x: xposition @@ -32,7 +35,7 @@ Rectangle{ width: 30 height: 50 border.color: "black" - opacity: 0.8 + opacity: 1 //0.8 z: 100 state: "on" focus: true @@ -123,7 +126,7 @@ Rectangle{ width: 20; height: 20 anchors.centerIn: parent Text{ - text: fuzzyAfter //TODO debug getTime(pointRect.x, pointRect.width); font.pointSize: 6; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignBottom + text: getTime(pointRect.x, pointRect.width); font.pointSize: 6; horizontalAlignment: Text.AlignHCenter; verticalAlignment: Text.AlignBottom } } @@ -159,6 +162,45 @@ Rectangle{ } ] + Rectangle{ + width: fuzzyAfter + fuzzyBefore + height: constBarHeight + anchors.verticalCenter: parent.verticalCenter + x: parent.width/2 - fuzzyBefore + opacity: 0.2 + z: 140 + + Image{ + anchors.fill: parent + fillMode: Image.Tile + source: "fuzzy.png" + } + } + + Component{ + id: actionBar + Rectangle{ + id: barRectangle + property variant hangOnToPoint + + height: constBarHeight + z: 110 + + states: State { + name: "pointLoaded"; when: pointRect.parent != null && pointRect.isLoaded != undefined && pointRect.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning + PropertyChanges { + target: barRectangle + anchors.verticalCenter: pointRect.verticalCenter + anchors.left: pointRect.horizontalCenter + color: pointRect.actionTypeColor + opacity: pointRect.actionTypeOpacity + width: Scripts.getNextAndPrevBarWidth(actionBar, pointRect, pointRect.parent.children); //getBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children) + } + } + + } + } + function toggleType(){ //TODO other kind of selection method var index = 0; var activeStates = Scripts.getActiveStates(); @@ -300,8 +342,6 @@ Rectangle{ } function remove(){ - //TODO kanske inte här, utan i listan? - //destroy den här, men också ta bort linjen samt räkna om linjen från punkten före... if(pointRect.hangOnToBar != null){ hangOnToBar.destroy(); } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 73a23024..3b62eb68 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -19,6 +19,7 @@ SET( Plugin_EXTRA dim.png bell.png info.png + fuzzy.png ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index d2aeabc0..9fc226e4 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -12,7 +12,7 @@ //create default actionPoint, to avoid null values and binding errors var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(container) - dynamicPoint.opacity = 0 + dynamicPoint.opacity = 0 //TODO why not use "visible"? Test that... dynamicPoint.width = 0 dynamicPoint.height = 0 container.actionPoint = dynamicPoint @@ -204,10 +204,17 @@ TextInput{ id: inputFuzzyBeforeText anchors.fill: parent - maximumLength: 4 + maximumLength: 5 + validator: IntValidator{bottom: 0; top: 10080;} //0 to a week... selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" - text: "0" //container.actionPoint.fuzzyBefore + text: actionPoint.fuzzyBefore + } + + Binding { + target: actionPoint + property: "fuzzyBefore" + value: inputFuzzyBeforeText.text } } @@ -223,7 +230,8 @@ TextInput{ id: inputFuzzyAfterText anchors.fill: parent - maximumLength: 4 + maximumLength: 5 + validator: IntValidator{bottom: 0; top: 10080;} //0 to a week... selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" text: actionPoint.fuzzyAfter diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 844b904a..d2aed35a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -32,6 +32,8 @@ com.telldus.schedulersimplegui = function() { view.setProperty("imageActionBell", "bell.png"); view.setProperty("imageInfo", "info.png"); + view.setProperty("constBarHeight", 10); + view.load("main.qml"); application.addWidget("scheduler.simple", "icon.png", view); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 2f980f30..83eb3677 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -22,8 +22,7 @@ import "schedulerscripts.js" as Scripts Text{ anchors.verticalCenter: parent.verticalCenter anchors.horizontalCenter: parent.horizontalCenter - //text: "Device " + (index + 1) + "Name: " + name - + text: modelData.name } } @@ -53,16 +52,15 @@ import "schedulerscripts.js" as Scripts //dynamicPoint.setFirstState("dim"); //when type is a stored value dynamicPoint.setFirstState(); + /* var dynamicBar = actionBar.createObject(deviceRow) dynamicBar.hangOnToPoint = dynamicPoint dynamicPoint.hangOnToBar = dynamicBar + */ dialog.show(dynamicPoint) - //deviceRow.add(point) - //TODO destroy? (only to remove them if needed) //TODO komponenter med stor bokstav kanske? - //om detta inte fungerar, testa med pathview... } } @@ -137,13 +135,10 @@ import "schedulerscripts.js" as Scripts } Component{ - id: addButtonComponent - //anchors { left: myListView.left; top: myListView.top; margins: 20 } + id: addButtonComponent Row { id: addButton - //anchors.fill: parent - //spacing: 10 - + Rectangle { height: 20 width: 100 @@ -162,9 +157,6 @@ import "schedulerscripts.js" as Scripts MouseArea { id: buttonMouseArea anchors.fill: parent - //hoverEnabled: true - //onEntered: parent.border.color = onHoverColor - //onExited: parent.border.color = borderColor onClicked: { addDevice.call() } @@ -176,44 +168,8 @@ import "schedulerscripts.js" as Scripts } } - Component{ - id: actionBar - Rectangle{ - id: barRectangle - property variant hangOnToPoint - //width: 100 //TODO dependent on hangOnToPoint and next point positions - - height: 10 - /* - color: hangOnToPoint.actionType //"blue" //TODO, dependent on hangOnToPoint - anchors.verticalCenter: hangOnToPoint.verticalCenter - anchors.left: hangOnToPoint.horizontalCenter - */ - z: 110 - - //state actionType - // couldnt get this to work: - // (if it works later on, try to set opacity for actionPoint in this way too) - states: State { - name: "pointLoaded"; when: hangOnToPoint.isLoaded != undefined && hangOnToPoint.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning - PropertyChanges { - target: barRectangle - anchors.verticalCenter: hangOnToPoint.verticalCenter - anchors.left: hangOnToPoint.horizontalCenter - color: hangOnToPoint.actionTypeColor - opacity: hangOnToPoint.actionTypeOpacity - width: Scripts.getNextAndPrevBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children); //getBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children) - } - //anchors.verticalCenter: hangOnToPoint.verticalCenter - //anchors.left: hangOnToPoint.horizontalCenter - } - - } - } - Dialog { id: dialog - //anchors.centerIn: parent z: 150 } From 3dea1462339770a41ce735410402a43d68866d2f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 20 Jan 2011 14:44:22 +0000 Subject: [PATCH 1528/2215] Fuzzy-image --- telldus-gui/Plugins/SchedulerGUISimple/fuzzy.png | Bin 0 -> 187 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/fuzzy.png diff --git a/telldus-gui/Plugins/SchedulerGUISimple/fuzzy.png b/telldus-gui/Plugins/SchedulerGUISimple/fuzzy.png new file mode 100644 index 0000000000000000000000000000000000000000..a0c71fd98b23facf34eb670ab3a92ff2ab40d050 GIT binary patch literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^tU%1g!3HF2ET{XE)7O>#HlqlSuA$xyo>ricWQl7;iF1B# zZfaf$gL6@8Vo7R>LV0FMhJw4NZ$Nk>pEyvFn5Ts0goK12=NTAZm?SnHTp`5Z XE+O&agmL?Mpb7?0S3j3^P6 Date: Thu, 20 Jan 2011 15:24:58 +0000 Subject: [PATCH 1529/2215] Cutting bars moving outside the listview, and preventing flicking in the listviews --- telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml | 2 ++ telldus-gui/Plugins/SchedulerGUISimple/main.qml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 9fc226e4..8b7ab9a6 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -352,6 +352,8 @@ model: typeSelection delegate: typeSelectionRow highlight: Rectangle { color: "lightsteelblue"; radius: 5 } + snapMode: ListView.SnapToItem + interactive: false //TODO can these paths be turned into some kind of constants? Import from common file or something? ListModel{ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 83eb3677..758f6d42 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -28,7 +28,7 @@ import "schedulerscripts.js" as Scripts } Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width-100; height:parent.height; - + clip: true MouseArea { id: deviceMouseArea anchors.fill: parent @@ -81,6 +81,8 @@ import "schedulerscripts.js" as Scripts //focus: true footer: addButtonComponent header: timeline + snapMode: ListView.SnapToItem + interactive: false } Component{ From 9b299d8ea606b892e8b1d50f31890225c3ed24fb Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 20 Jan 2011 16:15:29 +0000 Subject: [PATCH 1530/2215] Somwhat able to use arrow keys to move action point with time line --- .../Plugins/SchedulerGUISimple/Dialog.qml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 8b7ab9a6..1887056f 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -3,6 +3,19 @@ Rectangle { id: container property ActionPoint actionPoint + + focus: true + Keys.onPressed: { + if (event.key == Qt.Key_Left) { + actionPoint.x = actionPoint.x - 1 + event.accepted = true; + } + else if (event.key == Qt.Key_Right) { + actionPoint.x = actionPoint.x + 1 + event.accepted = true; + } + tryme(event, "container"); + } MouseArea{ anchors.fill: parent @@ -423,4 +436,8 @@ } } + function tryme(event, origin){ + print("KEY: " + event.key + " Från: " + origin); + } + } From 81376f3a17bf460a4b353bd21bc1e03237dfa501 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 20 Jan 2011 16:35:08 +0000 Subject: [PATCH 1531/2215] Added 'overloaded' member ScriptFunctionWrapper::callWith() --- .../Plugins/QML/scriptfunctionwrapper.cpp | 20 +++++++++++++++++-- .../Plugins/QML/scriptfunctionwrapper.h | 5 +++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp b/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp index 5108ff77..a3596341 100644 --- a/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp +++ b/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp @@ -1,5 +1,9 @@ #include "scriptfunctionwrapper.h" +#include +#include +#include + class ScriptFunctionWrapper::PrivateData { public: QScriptValue object; @@ -18,6 +22,18 @@ ScriptFunctionWrapper::~ScriptFunctionWrapper() { delete d; } -QVariant ScriptFunctionWrapper::call() { - return d->object.property(d->name).call().toVariant(); +QScriptValue ScriptFunctionWrapper::call() { + return d->object.property(d->name).call(); } + +QScriptValue ScriptFunctionWrapper::callWith(const QScriptValue &val) { + qDebug() << "Call called" << d->name; + QScriptEngine *eng = val.engine(); + if (!eng) { + qDebug() << "We cannot access the script-engine, fail!"; + return QScriptValue(); + } + QScriptContext *ctx = eng->currentContext(); + return d->object.property(d->name).call(QScriptValue(), ctx->argumentsObject()); +} + diff --git a/telldus-gui/Plugins/QML/scriptfunctionwrapper.h b/telldus-gui/Plugins/QML/scriptfunctionwrapper.h index 2a6b1693..db5cae83 100644 --- a/telldus-gui/Plugins/QML/scriptfunctionwrapper.h +++ b/telldus-gui/Plugins/QML/scriptfunctionwrapper.h @@ -3,7 +3,6 @@ #include #include -#include class ScriptFunctionWrapper : public QObject { @@ -16,7 +15,9 @@ signals: void titleChanged(); public slots: - QVariant call(); + QScriptValue call(); + QScriptValue callWith(const QScriptValue &val); + private: class PrivateData; From ff1e24d14f7bf867ef27f0f82d2d6aff5786c1d0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 21 Jan 2011 10:52:27 +0000 Subject: [PATCH 1532/2215] Fixed fuzzinessbinding between dialog and timeline --- .../Plugins/SchedulerGUISimple/Dialog.qml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 1887056f..f226972a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -41,22 +41,24 @@ */ function show(actionPoint) { - container.opacity = 1; + container.opacity = 0; container.border.color = "black" container.border.width = 2 + inputFuzzyBeforeText.text = actionPoint.fuzzyBefore + inputFuzzyAfterText.text = actionPoint.fuzzyAfter container.actionPoint = actionPoint var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); - //container.x = rootCoordinates.x + actionPoint.parent.width/2 - container.width/2; container.y = rootCoordinates.y + actionPoint.height + 10; container.width = actionPoint.parent.width; container.x = (actionPoint.parent.parent.width - container.width)/2; + container.opacity = 1; } - function hide() { - container.opacity = 0; + function hide() { + container.opacity = 0; container.border.width = 0 - } + } smooth: true radius: 5 @@ -221,13 +223,14 @@ validator: IntValidator{bottom: 0; top: 10080;} //0 to a week... selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" - text: actionPoint.fuzzyBefore + //text: actionPoint.fuzzyBefore } Binding { target: actionPoint property: "fuzzyBefore" value: inputFuzzyBeforeText.text + when: container.opacity == 1 } } @@ -247,13 +250,14 @@ validator: IntValidator{bottom: 0; top: 10080;} //0 to a week... selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" - text: actionPoint.fuzzyAfter + //text: actionPoint.fuzzyAfter } Binding { target: actionPoint property: "fuzzyAfter" value: inputFuzzyAfterText.text + when: container.opacity == 1 } } From c235310e5398973915908e64270d0439ebb06c8c Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 21 Jan 2011 14:51:31 +0000 Subject: [PATCH 1533/2215] Possibility to add offset to sunrise/sunset values --- .../SchedulerGUISimple/ActionPoint.qml | 61 +++------ .../Plugins/SchedulerGUISimple/Dialog.qml | 128 ++++++++++++++++-- .../Plugins/SchedulerGUISimple/__init__.js | 2 +- .../SchedulerGUISimple/schedulerscripts.js | 27 ---- 4 files changed, 140 insertions(+), 78 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 2736c81a..c0aae316 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -3,17 +3,17 @@ import "schedulerscripts.js" as Scripts Rectangle{ id: pointRect - //property variant xposition property string actionTypeColor: "blue" //TODO default value property int actionType: 1 //TODO default value property double actionTypeOpacity: 1 - property string actionTypeImage: "/home/stefan/Projects/tellstick/trunk/telldus-gui/TelldusCenter/images/devices.png" + property string actionTypeImage: imageActionOn property string isPoint: "true" property variant isLoaded property int xvalue - //property variant hangOnToBar - property int fuzzyBefore: 100 - property int fuzzyAfter: 55 + property int fuzzyBefore: 0 + property int fuzzyAfter: 0 + property int offset: -100 + property alias triggerstate: trigger.state Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... @@ -22,14 +22,6 @@ Rectangle{ dynamicBar.hangOnToPoint = pointRect //pointRect.hangOnToBar = dynamicBar } - //x: xposition - - /* - states: State { - name: "myState"; when: xposition != undefined - PropertyChanges { target: pointRect; x: myListView.width - xposition } - } - */ //use item instead of rectangle (no border then though) to make it invisible (opacity: 0) width: 30 @@ -103,14 +95,16 @@ Rectangle{ PropertyChanges { target: triggerImage; source: imageTriggerSunrise; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunRiseTime.call(pointRect.parent.width, pointRect.width) } + PropertyChanges { target: pointRect; x: getSunRiseTime.call(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO se nedan + PropertyChanges { target: dialog; offsetPanelOpacity: 1 } }, State { name: "sunset" PropertyChanges { target: triggerImage; source: imageTriggerSunset; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunSetTime.call(pointRect.parent.width, pointRect.width) } + PropertyChanges { target: pointRect; x: getSunSetTime.call(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits + PropertyChanges { target: dialog; offsetPanelOpacity: 1 } }, State { name: "absolute" @@ -118,6 +112,7 @@ Rectangle{ PropertyChanges { target: triggerTime; opacity: 1 } PropertyChanges { target: pointRectMouseArea; drag.target: parent } PropertyChanges { target: pointRect; x: xvalue } + PropertyChanges { target: dialog; offsetPanelOpacity: 0 } } ] @@ -142,7 +137,7 @@ Rectangle{ states: [ State { name: "on" - PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } //TODO: images!! + PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } PropertyChanges { target: pointRect; actionTypeImage: imageActionOn } }, State{ @@ -163,10 +158,10 @@ Rectangle{ ] Rectangle{ - width: fuzzyAfter + fuzzyBefore + width: minutesToTimelineUnits(fuzzyAfter + fuzzyBefore) height: constBarHeight anchors.verticalCenter: parent.verticalCenter - x: parent.width/2 - fuzzyBefore + x: parent.width/2 - minutesToTimelineUnits(fuzzyBefore) opacity: 0.2 z: 140 @@ -194,7 +189,7 @@ Rectangle{ anchors.left: pointRect.horizontalCenter color: pointRect.actionTypeColor opacity: pointRect.actionTypeOpacity - width: Scripts.getNextAndPrevBarWidth(actionBar, pointRect, pointRect.parent.children); //getBarWidth(actionBar, hangOnToPoint, hangOnToPoint.parent.children) + width: Scripts.getNextAndPrevBarWidth(actionBar, pointRect, pointRect.parent.children); } } @@ -220,21 +215,6 @@ Rectangle{ } pointRect.state = activeStates[index]; - - /* - if(pointRect.state == "on"){ - pointRect.state = "off" - } - else if(pointRect.state == "off"){ - pointRect.state = "dim" - } - else if(pointRect.state == "dim"){ - pointRect.state = "bell" - } - else if(pointRect.state == "bell"){ - pointRect.state = "on" - } - */ } function setType(name){ @@ -250,7 +230,7 @@ Rectangle{ trigger.state = "absolute"; } else if(trigger.state == "absolute"){ - pointRect.xvalue = pointRect.x; //TODO right place to set it? + pointRect.xvalue = pointRect.x; trigger.state = "sunrise"; } } @@ -267,7 +247,6 @@ Rectangle{ } } - var test = "" //TODO Binding loop here when moving transperent point over other point //...or just changing state to transparent //something with point depending on point depending on point? @@ -292,8 +271,6 @@ Rectangle{ partOfHour = Math.floor(partOfHour); partOfHour = Scripts.pad(partOfHour, 2); hours = Scripts.pad(hours, 2); - //print("Hours: " + hours); - //print("Minutes? " + partOfHour); return hours + ":" + partOfHour; } @@ -350,6 +327,12 @@ Rectangle{ var pointList = pointRect.parent.children; pointRect.destroy(); dialog.hide(); - //Scripts.recalculateWidth(x, pointList); + } + + function minutesToTimelineUnits(minutes){ + if(pointRect.parent == null){ + return 0; + } + return pointRect.parent.width/24 * (minutes/60); } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index f226972a..f4dfa33f 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -3,6 +3,7 @@ Rectangle { id: container property ActionPoint actionPoint + property alias offsetPanelOpacity: offsetPanel.opacity focus: true Keys.onPressed: { @@ -31,21 +32,13 @@ container.actionPoint = dynamicPoint } - /* - states: State{ - name: "visible"; when: actionPoint.fuzzyAfter != undefined - PropertyChanges{ - target: container; fuzzyAfter: actionPoint.fuzzyAfter - } - } - */ - function show(actionPoint) { - container.opacity = 0; + container.opacity = 0; //needed for fuzz/offset unbinding container.border.color = "black" container.border.width = 2 inputFuzzyBeforeText.text = actionPoint.fuzzyBefore inputFuzzyAfterText.text = actionPoint.fuzzyAfter + inputOffsetText.text = actionPoint.offset container.actionPoint = actionPoint var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); @@ -250,7 +243,6 @@ validator: IntValidator{bottom: 0; top: 10080;} //0 to a week... selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" - //text: actionPoint.fuzzyAfter } Binding { @@ -326,6 +318,85 @@ } } + Rectangle{ + id: offsetPanel + height: 50 + width: 80 + + opacity: 0 + + anchors.left: removePoint.right + anchors.leftMargin: 10 + anchors.top: fuzzyPanel.bottom + anchors.topMargin: 10 + + Text{ + id: textOffset + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.top: parent.top + anchors.topMargin: 5 + text: "Offset:" + } + + Text{ + id: textOffsetUnit + anchors.left: inputOffset.right + anchors.leftMargin: 5 + anchors.verticalCenter: textOffset.verticalCenter + text: "minutes" + } + + Rectangle{ + id: inputOffset + property alias offsetText: inputOffsetText.text + anchors.left: textOffset.right + anchors.leftMargin: 5 + anchors.verticalCenter: textOffset.verticalCenter + width: 35 + height: textOffset.height + border.width: 1 + + TextInput{ + id: inputOffsetText + anchors.fill: parent + maximumLength: 4 + validator: IntValidator{bottom: getMinimumOffset(actionPoint.triggerstate); top: getMaximumOffset(actionPoint.triggerstate);} // +/- 12 hours + selectByMouse: true + color: "#151515"; selectionColor: "mediumseagreen" + } + + Binding { + target: actionPoint + property: "offset" + value: inputOffsetText.text + when: container.opacity == 1 + } + } + + Image{ + anchors.left: textOffsetUnit.right + anchors.leftMargin: 5 + anchors.verticalCenter: textOffsetUnit.verticalCenter + + source: imageInfo + width: 15 + height: 15 + + MouseArea{ + anchors.fill: parent + hoverEnabled: true + onEntered: { + infobox.opacity = 1 + infobox.infoboxtext = "Enter a positive or negative value for how many minutes before or after sunset/sunrise this action will be executed." + } + onExited: { + infobox.opacity = 0 + } + } + } + } + Rectangle { //TODO create common button-class (but how to differentiate action?) id: closeButton height: 20 @@ -444,4 +515,39 @@ print("KEY: " + event.key + " Från: " + origin); } + function getMinimumOffset(state){ + //TODO this will not work if a value is set to the highest limit, then not reentering scheduler until the sunrise/set has changed so much that the device will be hidden anyway... Not common though + var minutes = 0; + var time; + if(state == "sunrise"){ + time = main.sunData[0].split(':'); + } + else if(state == "sunset"){ + time = main.sunData[1].split(':'); + } + else{ + return 0 ; + } + + return -1 * (parseInt(time[0], 10) * 60 + parseInt(time[1], 10)); + } + + function getMaximumOffset(state){ + print("state: " + state); + var minutes = 0; + var time; + if(state == "sunrise"){ + time = main.sunData[0].split(':'); + } + else if(state == "sunset"){ + time = main.sunData[1].split(':'); + } + else{ + return 0 ; + } + + return 24 * 60 - (parseInt(time[0], 10) * 60 + parseInt(time[1], 10)); + } + + } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index d2aed35a..f1425378 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -40,7 +40,7 @@ com.telldus.schedulersimplegui = function() { } function addDevice() { - deviceList.push({name:'Stallet'}); + deviceList.push({name:'Stallet istallet'}); } function getSun(riseset, rowWidth, pointWidth){ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 4d6f611c..ac31b032 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -19,7 +19,6 @@ function getBarWidth(currentBar, currentPointRect, pointList){ } } } - return (nextX - currentPointRect.x); } @@ -50,8 +49,6 @@ function isMidnightDark(){ var sunset = main.sunData[1].split(':'); if(sunset[0] < sunrise[0] || (sunset[0] == sunrise[0] && sunset[1] < sunrise[1])){ - print("Rise: " + sunrise); - print("Set: " + sunset); return false; } return true; @@ -68,29 +65,5 @@ function pad(number, length) { } function getNextAndPrevBarWidth(currentBar, currentPointRect, pointList){ - //TODO error whn < 30 (width) - //recalculateWidth(currentPointRect.x, pointList); return getBarWidth(currentBar, currentPointRect, pointList); } - -/* -function recalculateWidth(currentx, pointList){ - var prevPoint = null; - for(var i=0;i prevPoint.x)){ - prevPoint = pointList[i]; - } - } - } - - if(prevPoint == null || prevPoint.hangOnToBar == undefined){ - return; - } - - var temp = getBarWidth(prevPoint.hangOnToBar, prevPoint, pointList); - print(temp); - - //prevPoint.hangOnToBar.width = temp; -} -*/ From 9d982c5e6d49cbbefcc2be68203f3be6f508920c Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 21 Jan 2011 16:02:03 +0000 Subject: [PATCH 1534/2215] Dim values can be added to action, visiblie in GUI --- .../SchedulerGUISimple/ActionPoint.qml | 9 +- .../Plugins/SchedulerGUISimple/Dialog.qml | 86 +++++++++++++++++-- 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index c0aae316..208ef780 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -5,6 +5,7 @@ Rectangle{ id: pointRect property string actionTypeColor: "blue" //TODO default value property int actionType: 1 //TODO default value + property int dimvalue: 50 //percent, recalucluate it before use property double actionTypeOpacity: 1 property string actionTypeImage: imageActionOn property string isPoint: "true" @@ -96,7 +97,6 @@ Rectangle{ PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } PropertyChanges { target: pointRect; x: getSunRiseTime.call(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO se nedan - PropertyChanges { target: dialog; offsetPanelOpacity: 1 } }, State { name: "sunset" @@ -104,7 +104,6 @@ Rectangle{ PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } PropertyChanges { target: pointRect; x: getSunSetTime.call(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits - PropertyChanges { target: dialog; offsetPanelOpacity: 1 } }, State { name: "absolute" @@ -112,7 +111,6 @@ Rectangle{ PropertyChanges { target: triggerTime; opacity: 1 } PropertyChanges { target: pointRectMouseArea; drag.target: parent } PropertyChanges { target: pointRect; x: xvalue } - PropertyChanges { target: dialog; offsetPanelOpacity: 0 } } ] @@ -147,7 +145,7 @@ Rectangle{ }, State{ name: "dim" - PropertyChanges { target: pointRect; actionTypeColor: "green"; actionTypeOpacity: 1 } + PropertyChanges { target: pointRect; actionTypeColor: "green"; actionTypeOpacity: dimvalue/100 } PropertyChanges { target: pointRect; actionTypeImage: imageActionDim } }, State{ @@ -218,7 +216,6 @@ Rectangle{ } function setType(name){ - print("setting state to " + name); pointRect.state = name; } @@ -256,7 +253,7 @@ Rectangle{ return "papayawhip" //just return a color, will not be used } - actionTypeOpacity = 1 + actionTypeOpacity = prevPoint.actionTypeOpacity return prevPoint.actionTypeColor } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index f4dfa33f..137334e1 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -3,7 +3,6 @@ Rectangle { id: container property ActionPoint actionPoint - property alias offsetPanelOpacity: offsetPanel.opacity focus: true Keys.onPressed: { @@ -39,6 +38,7 @@ inputFuzzyBeforeText.text = actionPoint.fuzzyBefore inputFuzzyAfterText.text = actionPoint.fuzzyAfter inputOffsetText.text = actionPoint.offset + inputDimText.text = actionPoint.dimvalue container.actionPoint = actionPoint var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); @@ -323,7 +323,7 @@ height: 50 width: 80 - opacity: 0 + opacity: actionPoint.triggerstate == "sunrise" || actionPoint.triggerstate == "sunset" anchors.left: removePoint.right anchors.leftMargin: 10 @@ -397,6 +397,84 @@ } } + Rectangle{ + id: dimPanel + height: 50 + width: 80 + + opacity: actionPoint.state == "dim" + + anchors.left: removePoint.right + anchors.leftMargin: 10 + anchors.top: offsetPanel.bottom + anchors.topMargin: 10 + + Text{ + id: textDim + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.top: parent.top + anchors.topMargin: 5 + text: "Dim value:" + } + + Text{ + id: textDimUnit + anchors.left: inputDim.right + anchors.leftMargin: 5 + anchors.verticalCenter: textDim.verticalCenter + text: "%" + } + + Rectangle{ + id: inputDim + anchors.left: textDim.right + anchors.leftMargin: 5 + anchors.verticalCenter: textDim.verticalCenter + width: 35 + height: textDim.height + border.width: 1 + + TextInput{ + id: inputDimText + anchors.fill: parent + maximumLength: 4 + validator: IntValidator{bottom: 0; top: 100;} + selectByMouse: true + color: "#151515"; selectionColor: "mediumseagreen" + } + + Binding { + target: actionPoint + property: "dimvalue" + value: inputDimText.text + when: container.opacity == 1 + } + } + + Image{ + anchors.left: inputDim.right + anchors.leftMargin: 5 + anchors.verticalCenter: inputDim.verticalCenter + + source: imageInfo + width: 15 + height: 15 + + MouseArea{ + anchors.fill: parent + hoverEnabled: true + onEntered: { + infobox.opacity = 1 + infobox.infoboxtext = "Enter a dim percent value between 0 (no light) and 100 (full light)" + } + onExited: { + infobox.opacity = 0 + } + } + } + } + Rectangle { //TODO create common button-class (but how to differentiate action?) id: closeButton height: 20 @@ -436,7 +514,6 @@ anchors.leftMargin: 10 width: 100 //TODO relative height: 100 //TODO relative - //anchors.fill: parent model: typeSelection delegate: typeSelectionRow highlight: Rectangle { color: "lightsteelblue"; radius: 5 } @@ -533,7 +610,6 @@ } function getMaximumOffset(state){ - print("state: " + state); var minutes = 0; var time; if(state == "sunrise"){ @@ -548,6 +624,4 @@ return 24 * 60 - (parseInt(time[0], 10) * 60 + parseInt(time[1], 10)); } - - } From e2f749a012c62f714221da7b99d26057a4fdc691 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 24 Jan 2011 09:51:39 +0000 Subject: [PATCH 1535/2215] Turned buttons into reusable component --- .../Plugins/SchedulerGUISimple/Button.qml | 27 ++++ .../Plugins/SchedulerGUISimple/CMakeLists.txt | 1 + .../Plugins/SchedulerGUISimple/Dialog.qml | 131 ++++-------------- 3 files changed, 57 insertions(+), 102 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/Button.qml diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Button.qml b/telldus-gui/Plugins/SchedulerGUISimple/Button.qml new file mode 100644 index 00000000..8b6b258f --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/Button.qml @@ -0,0 +1,27 @@ +import Qt 4.7 + +Rectangle { + id: buttonRect + height: 20 + width: buttonText.width + 20 + + property color buttonColor: "lightgrey" + property alias text: buttonText.text + signal clicked() + //property alias event: buttonMouseArea.onClicked + + Text{ + id: buttonText + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.margins: 2 + + } + MouseArea { + id: buttonMouseArea + anchors.fill: parent + onClicked: buttonRect.clicked() + } + + color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor +} diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 3b62eb68..6fb65de4 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -7,6 +7,7 @@ SET( Plugin_NAME "schedulerguisimple" ) SET( Plugin_PATH "com.telldus.schedulerguisimple" ) SET( Plugin_EXTRA ActionPoint.qml + Button.qml Dialog.qml icon.png main.qml diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 137334e1..03a42f0b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -59,101 +59,41 @@ height: 500 // typelist.height * 2 + 50 opacity: 0 - Rectangle { - id: circleType //TODO only types this device has... - height: 20 - width: 100 + Button{ + id: circleType + text: "Toggle Action Type" anchors.verticalCenter: parent.verticalCenter anchors.verticalCenterOffset: 0 anchors.left: typeList.right anchors.leftMargin: 50 - - property color buttonColor: "lightgrey" - + onClicked: { + container.actionPoint.toggleType(); + } + Keys.onLeftPressed: { debug("Left pressed"); //TODO make it work - } - - Text{ - text: "Toggle Action Type" - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - anchors.margins: 2 } - - MouseArea { - id: buttonMouseAreaType - anchors.fill: parent - //hoverEnabled: true - //onEntered: parent.border.color = onHoverColor - //onExited: parent.border.color = borderColor - onClicked: { - container.actionPoint.toggleType(); - } - } - - color: buttonMouseAreaType.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor } - Rectangle { + Button{ id: circleTrigger - height: 20 - width: 100 + text: "Toggle Trigger Type" anchors.horizontalCenter: circleType.horizontalCenter y: circleType.y + 30 - - property color buttonColor: "lightgrey" - - Text{ - text: "Toggle Trigger Type" - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - anchors.margins: 2 - + onClicked: { + container.actionPoint.toggleTrigger(); } - MouseArea { - id: buttonMouseAreaTrigger - anchors.fill: parent - //hoverEnabled: true - //onEntered: parent.border.color = onHoverColor - //onExited: parent.border.color = borderColor - onClicked: { - container.actionPoint.toggleTrigger(); - } - } - - color: buttonMouseAreaTrigger.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor } - Rectangle { + Button{ id: removePoint - height: 20 - width: 100 + text: "Remove action" anchors.horizontalCenter: circleTrigger.horizontalCenter y: circleTrigger.y + 30 - - property color buttonColor: "lightgrey" - - Text{ - text: "Remove action" - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - anchors.margins: 2 - + onClicked: { + container.actionPoint.remove(); } - MouseArea { - id: buttonMouseAreaRemovePoint - anchors.fill: parent - //hoverEnabled: true - //onEntered: parent.border.color = onHoverColor - //onExited: parent.border.color = borderColor - onClicked: { - container.actionPoint.remove(); - } - } - - color: buttonMouseAreaRemovePoint.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor } Rectangle{ @@ -216,7 +156,11 @@ validator: IntValidator{bottom: 0; top: 10080;} //0 to a week... selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" - //text: actionPoint.fuzzyBefore + + Keys.onTabPressed: { + event.accepted = true; + inputFuzzyAfterText.focus = true; + } } Binding { @@ -243,6 +187,10 @@ validator: IntValidator{bottom: 0; top: 10080;} //0 to a week... selectByMouse: true color: "#151515"; selectionColor: "mediumseagreen" + Keys.onTabPressed: { + event.accepted = true; + inputFuzzyBeforeText.focus = true; + } } Binding { @@ -475,35 +423,14 @@ } } - Rectangle { //TODO create common button-class (but how to differentiate action?) + Button{ id: closeButton - height: 20 - width: 100 - //anchors.horizontalCenter: circleTrigger.right - //anchors.horizontalCenterOffset: 30 + text: "Close" y: circleTrigger.y + 30 - - property color buttonColor: "lightgrey" - - Text{ - text: "Close" - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - anchors.margins: 2 - + x: parent.x + 30 + onClicked: { + hide(); } - MouseArea { - id: buttonMouseAreaClose - anchors.fill: parent - //hoverEnabled: true - //onEntered: parent.border.color = onHoverColor - //onExited: parent.border.color = borderColor - onClicked: { - hide(); - } - } - - color: buttonMouseAreaClose.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor } ListView{ From 472e5be28f0986c81e90281d76b4a4edd9409ab6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 24 Jan 2011 15:28:51 +0000 Subject: [PATCH 1536/2215] Added absolute time setting, and changed to positioning based on time values instead of width, a few things left to solve --- .../SchedulerGUISimple/ActionPoint.qml | 66 +++++++++-- .../Plugins/SchedulerGUISimple/Button.qml | 1 - .../Plugins/SchedulerGUISimple/Dialog.qml | 107 ++++++++++++++++++ .../Plugins/SchedulerGUISimple/main.qml | 6 +- 4 files changed, 170 insertions(+), 10 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 208ef780..f8e8de5c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -10,10 +10,12 @@ Rectangle{ property string actionTypeImage: imageActionOn property string isPoint: "true" property variant isLoaded - property int xvalue + //property int xvalue property int fuzzyBefore: 0 property int fuzzyAfter: 0 property int offset: -100 + property int absoluteHour: parseInt(dialog.absoluteHour, 10) + property int absoluteMinute: parseInt(dialog.absoluteMinute, 10) property alias triggerstate: trigger.state Component.onCompleted: { @@ -51,23 +53,49 @@ Rectangle{ id: pointRectMouseArea acceptedButtons: Qt.LeftButton | Qt.RightButton + onPressed:{ + + } + onClicked: { //pointRect.focus = true if (mouse.button == Qt.RightButton){ pointRect.toggleType() + dialog.show(pointRect) } else{ - dialog.show(pointRect) //TODO om inte redan i visandes läge.... + dialog.show(pointRect) } } - //onPositionChange... maybe emit signal to change in row... + onPositionChanged: { + var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); + var hourMinute = getTimeFromPosition(rootCoordinates.x) + pointRect.absoluteHour = hourMinute[0] + pointRect.absoluteMinute = hourMinute[1] + } + + onReleased: { + dialog.show(pointRect) + //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); + //var hourMinute = getTimeFromPosition(rootCoordinates.x) + dialog.absoluteHour = Scripts.pad(pointRect.absoluteHour, 2) //Scripts.pad(hourMinute[0], 2) + dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) //Scripts.pad(hourMinute[1], 2) + } + anchors.fill: parent drag.target: pointRect drag.axis: Drag.XAxis drag.minimumX: -15 //TODO make relative drag.maximumX: 685 //TODO make relative!! + drag.filterChildren: true //TODO testing this //TODO make it impossible to overlap (on release) + + states: State{ + id: "hidden"; when: pointRectMouseArea.drag.active + PropertyChanges { target: pointRect; opacity: 0.5; } + //PropertyChanges { target: triggerTime; opacity: 0; } + } } Column{ @@ -106,16 +134,18 @@ Rectangle{ PropertyChanges { target: pointRect; x: getSunSetTime.call(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits }, State { - name: "absolute" + name: "absolute"; when: !pointRectMouseArea.drag.active PropertyChanges { target: triggerImage; opacity: 0; } PropertyChanges { target: triggerTime; opacity: 1 } PropertyChanges { target: pointRectMouseArea; drag.target: parent } - PropertyChanges { target: pointRect; x: xvalue } + //PropertyChanges { target: pointRect; x: xvalue } + PropertyChanges { target: pointRect; x: getAbsoluteXValue() } } ] Rectangle{ id: triggerTime + opacity: 1 width: 20; height: 20 anchors.centerIn: parent Text{ @@ -125,6 +155,7 @@ Rectangle{ Image { id: triggerImage + opacity: 0 anchors.fill: parent width: 20; height: 20 source: imageTriggerAbsolute @@ -194,6 +225,14 @@ Rectangle{ } } + function getAbsoluteXValue(){ + if(pointRect.parent == null){ + return 0; + } + var hourSize = pointRect.parent.width / 24; + return pointRect.absoluteHour * hourSize + hourSize * (pointRect.absoluteMinute/60) - pointRect.width/2; + } + function toggleType(){ //TODO other kind of selection method var index = 0; var activeStates = Scripts.getActiveStates(); @@ -225,9 +264,10 @@ Rectangle{ } else if(trigger.state == "sunset"){ trigger.state = "absolute"; + pointRect.x = getAbsoluteXValue(); } else if(trigger.state == "absolute"){ - pointRect.xvalue = pointRect.x; + //pointRect.xvalue = pointRect.x; trigger.state = "sunrise"; } } @@ -261,14 +301,24 @@ Rectangle{ if(pointRect.parent == null){ return ""; } - var timeOfDay = pointRect.x + (pointRect.width/2); + + var hours = Scripts.pad(pointRect.absoluteHour, 2); + var minutes = Scripts.pad(pointRect.absoluteMinute, 2); + return hours + ":" + minutes; + } + + function getTimeFromPosition(mouseX){ + if(pointRect.parent == null){ + return [0,0]; + } + var timeOfDay = mouseX; // + (pointRect.width/2); var hourSize = pointRect.parent.width / 24; var hours = Math.floor(timeOfDay / hourSize); var partOfHour = ((timeOfDay - (hourSize * hours))/hourSize) * 60 partOfHour = Math.floor(partOfHour); partOfHour = Scripts.pad(partOfHour, 2); hours = Scripts.pad(hours, 2); - return hours + ":" + partOfHour; + return [hours, partOfHour]; } function addState(state){ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Button.qml b/telldus-gui/Plugins/SchedulerGUISimple/Button.qml index 8b6b258f..d34645ba 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Button.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Button.qml @@ -8,7 +8,6 @@ Rectangle { property color buttonColor: "lightgrey" property alias text: buttonText.text signal clicked() - //property alias event: buttonMouseArea.onClicked Text{ id: buttonText diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 03a42f0b..42b4dd87 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -1,8 +1,11 @@ import Qt 4.7 + import "schedulerscripts.js" as Scripts Rectangle { id: container property ActionPoint actionPoint + property alias absoluteHour: inputAbsoluteHourText.text + property alias absoluteMinute: inputAbsoluteMinuteText.text focus: true Keys.onPressed: { @@ -39,6 +42,8 @@ inputFuzzyAfterText.text = actionPoint.fuzzyAfter inputOffsetText.text = actionPoint.offset inputDimText.text = actionPoint.dimvalue + inputAbsoluteHourText.text = Scripts.pad(actionPoint.absoluteHour, 2) + inputAbsoluteMinuteText.text = Scripts.pad(actionPoint.absoluteMinute, 2) container.actionPoint = actionPoint var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); @@ -345,6 +350,108 @@ } } + Rectangle{ + id: absolutePanel + height: 50 + width: 80 + + opacity: actionPoint.triggerstate == "absolute" + + anchors.left: removePoint.right + anchors.leftMargin: 10 + anchors.top: fuzzyPanel.bottom + anchors.topMargin: 10 + //property alias absoluteHourText: inputAbsoluteHourText.text + //property alias absoluteMinuteText: inputAbsoluteMinuteText.text + + Row{ + Text{ + /*id: textAbsolute + anchors.left: parent.left + anchors.leftMargin: 5 + anchors.top: parent.top + anchors.topMargin: 5 + */ + text: "Time:" + } + + Rectangle{ + id: inputAbsoluteHour + //property alias absoluteHour: inputAbsoluteHourText.text + /*anchors.left: textOffset.right + anchors.leftMargin: 5 + anchors.verticalCenter: textOffset.verticalCenter + */ + width: 35 + height: inputAbsoluteHourText.height + border.width: 1 + + TextInput{ + id: inputAbsoluteHourText + anchors.fill: parent + maximumLength: 4 + validator: IntValidator{bottom: 0; top: 23;} + selectByMouse: true + color: "#151515"; selectionColor: "mediumseagreen" + Keys.onTabPressed: { + event.accepted = true; + inputAbsoluteMinuteText.focus = true; + } + text: "0" + } + + Binding { + target: actionPoint + property: "absoluteHour" + value: inputAbsoluteHourText.text + when: container.opacity == 1 + } + } + + Text{ + /*id: textOffsetUnit + anchors.left: inputOffset.right + anchors.leftMargin: 5 + anchors.verticalCenter: textOffset.verticalCenter + */ + text: ":" + } + + Rectangle{ + id: inputAbsoluteMinute + property alias absoluteMinute: inputAbsoluteMinuteText.text + /*anchors.left: textOffset.right + anchors.leftMargin: 5 + anchors.verticalCenter: textOffset.verticalCenter + */ + width: 35 + height: inputAbsoluteMinuteText.height + border.width: 1 + + TextInput{ + id: inputAbsoluteMinuteText + anchors.fill: parent + maximumLength: 4 + validator: IntValidator{bottom: 0; top: 59;} + selectByMouse: true + color: "#151515"; selectionColor: "mediumseagreen" + Keys.onTabPressed: { + event.accepted = true; + inputAbsoluteHourText.focus = true; + } + text: "0" + } + + Binding { + target: actionPoint + property: "absoluteMinute" + value: inputAbsoluteMinuteText.text + when: container.opacity == 1 + } + } + } + } + Rectangle{ id: dimPanel height: 50 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 758f6d42..6e4f01b8 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -41,7 +41,11 @@ import "schedulerscripts.js" as Scripts var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) - dynamicPoint.x = mouseX - dynamicPoint.width/2 //xposition + //dynamicPoint.x = mouseX - dynamicPoint.width/2 //xposition + var hourMinute = dynamicPoint.getTimeFromPosition(mouse.x) + dynamicPoint.absoluteHour = hourMinute[0] + dynamicPoint.absoluteMinute = hourMinute[1] + dynamicPoint.x = dynamicPoint.getAbsoluteXValue(); dynamicPoint.border.color = "blue" //TODO different states depending on the device From 5c2a2981600f2356c5c0b90a7ce9cde7f046bd59 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 24 Jan 2011 15:55:17 +0000 Subject: [PATCH 1537/2215] Stopped moving of point beyond border and added arrow keys movement --- .../SchedulerGUISimple/ActionPoint.qml | 9 +++-- .../Plugins/SchedulerGUISimple/Dialog.qml | 40 +++++++++++++++++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index f8e8de5c..c7662e4e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -69,10 +69,13 @@ Rectangle{ } onPositionChanged: { + //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); - var hourMinute = getTimeFromPosition(rootCoordinates.x) - pointRect.absoluteHour = hourMinute[0] - pointRect.absoluteMinute = hourMinute[1] + var hourMinute = getTimeFromPosition(rootCoordinates.x - mouse.x + pointRect.width/2) + if((hourMinute[0] >= 0) && hourMinute[0] < 24){ + pointRect.absoluteHour = hourMinute[0] + pointRect.absoluteMinute = hourMinute[1] + } } onReleased: { diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 42b4dd87..0d41b24c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -9,15 +9,49 @@ focus: true Keys.onPressed: { + + tryme(event, "container"); + + var hours = 0; + var minutes = 0; if (event.key == Qt.Key_Left) { - actionPoint.x = actionPoint.x - 1 + //actionPoint.x = actionPoint.x - 1 + var minutes = parseInt(inputAbsoluteMinuteText.text, 10); + var hours = parseInt(inputAbsoluteHourText.text, 10); + if(minutes == 0){ + if(hours == 0){ + return; //do nothing, border reached + } + hours = hours - 1; + minutes = 59; + } + else{ + minutes = minutes - 1; + } event.accepted = true; } else if (event.key == Qt.Key_Right) { - actionPoint.x = actionPoint.x + 1 + //actionPoint.x = actionPoint.x + 1 + var minutes = parseInt(inputAbsoluteMinuteText.text, 10); + var hours = parseInt(inputAbsoluteHourText.text, 10); + if(minutes == 59){ + if(hours == 23){ + return; //do nothing, border reached + } + hours = hours + 1; + minutes = 0; + } + else{ + minutes = minutes + 1; + } event.accepted = true; } - tryme(event, "container"); + else{ + return; + } + + inputAbsoluteHourText.text = Scripts.pad(hours, 2); + inputAbsoluteMinuteText.text = Scripts.pad(minutes, 2); } MouseArea{ From 1e8fe109b437a2897045eaa256b77c9f6e44f7ae Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 24 Jan 2011 16:03:16 +0000 Subject: [PATCH 1538/2215] Relative max/min drag --- .../Plugins/SchedulerGUISimple/ActionPoint.qml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index c7662e4e..3a2869c0 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -53,12 +53,7 @@ Rectangle{ id: pointRectMouseArea acceptedButtons: Qt.LeftButton | Qt.RightButton - onPressed:{ - - } - onClicked: { - //pointRect.focus = true if (mouse.button == Qt.RightButton){ pointRect.toggleType() dialog.show(pointRect) @@ -89,15 +84,15 @@ Rectangle{ anchors.fill: parent drag.target: pointRect drag.axis: Drag.XAxis - drag.minimumX: -15 //TODO make relative - drag.maximumX: 685 //TODO make relative!! + drag.minimumX: -1 * pointRect.width/2 + drag.maximumX: pointRect.parent.width - pointRect.width/2 drag.filterChildren: true //TODO testing this //TODO make it impossible to overlap (on release) + //TODO drag to most right - jumps back, why? states: State{ id: "hidden"; when: pointRectMouseArea.drag.active PropertyChanges { target: pointRect; opacity: 0.5; } - //PropertyChanges { target: triggerTime; opacity: 0; } } } From ec7d5db109638d168d684f9679e3563ac16c680b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 25 Jan 2011 10:32:19 +0000 Subject: [PATCH 1539/2215] Device list moved into day list --- .../SchedulerGUISimple/ActionPoint.qml | 10 +- .../Plugins/SchedulerGUISimple/__init__.js | 9 +- .../Plugins/SchedulerGUISimple/main.qml | 138 ++++++++++++------ 3 files changed, 107 insertions(+), 50 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 3a2869c0..97a010e4 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -27,8 +27,8 @@ Rectangle{ } //use item instead of rectangle (no border then though) to make it invisible (opacity: 0) - width: 30 - height: 50 + width: constPointWidth + height: constDeviceRowHeight border.color: "black" opacity: 1 //0.8 z: 100 @@ -85,7 +85,7 @@ Rectangle{ drag.target: pointRect drag.axis: Drag.XAxis drag.minimumX: -1 * pointRect.width/2 - drag.maximumX: pointRect.parent.width - pointRect.width/2 + drag.maximumX: pointRect.parent.width - pointRect.width/2 //TODO: om pointRect.parent == null, då bara 0... drag.filterChildren: true //TODO testing this //TODO make it impossible to overlap (on release) //TODO drag to most right - jumps back, why? @@ -122,14 +122,14 @@ Rectangle{ PropertyChanges { target: triggerImage; source: imageTriggerSunrise; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunRiseTime.call(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO se nedan + PropertyChanges { target: pointRect; x: getSunRiseTime.callWith(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO se nedan }, State { name: "sunset" PropertyChanges { target: triggerImage; source: imageTriggerSunset; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunSetTime.call(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits + PropertyChanges { target: pointRect; x: getSunSetTime.callWith(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits }, State { name: "absolute"; when: !pointRectMouseArea.drag.active diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index f1425378..cc74318b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -32,7 +32,11 @@ com.telldus.schedulersimplegui = function() { view.setProperty("imageActionBell", "bell.png"); view.setProperty("imageInfo", "info.png"); + //height/width constants view.setProperty("constBarHeight", 10); + view.setProperty("constDeviceRowHeight", 50); + view.setProperty("constDeviceRowWidth", 600); + view.setProperty("constPointWidth", 30); view.load("main.qml"); application.addWidget("scheduler.simple", "icon.png", view); @@ -64,14 +68,11 @@ com.telldus.schedulersimplegui = function() { } function getSunRiseTime(rowWidth, pointWidth){ - rowWidth = 700 //TODO - pointWidth = 30 //TODO + return getSun("rise", rowWidth, pointWidth); } function getSunSetTime(rowWidth, pointWidth){ - rowWidth = 700 //TODO - pointWidth = 30 //TODO return getSun("set", rowWidth, pointWidth); } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 6e4f01b8..265980a0 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -5,18 +5,94 @@ import "schedulerscripts.js" as Scripts Item{ id: main width: 800 //TODO how? - height: 600 //TODO how? + height: 700 //TODO how? property variant sunData + property int dayListHeaderHeight: 15 + + Rectangle{ + id: mainTop + height: 75 + width: parent.width + anchors.top: parent.top + anchors.left: parent.left + Text{ + anchors.centerIn: parent + text: "TESTAR" + } + } + + ListView{ + id: mainListView + anchors.top: mainTop.bottom + anchors.topMargin: 10 + anchors.left: parent.left + height: parent.height //TODO + width: parent.width + //anchors.left: dayListView.left + header: mainListViewHeader + model: 1 + orientation: ListView.Horizontal + delegate: listDayRow //Text { text: "TEST - per modell" } + interactive: false //no scroll between days in this way + + //TODO transitions: + } + + Component{ + id: listDayRow + ListView { + id: dayListView + //anchors.top: mainListView.bottom + //anchors.left: parent.left + width: parent.width + height: 700 //TODO + + //anchors.fill: parent + model: deviceModel + delegate: listRow + //focus: true + //footer: addButtonComponent //TODO move... + header: timeline + snapMode: ListView.SnapToItem + interactive: false //no scroll between devices at the moment + } + } + + Component{ + id: mainListViewHeader + Column{ + id: mainListViewHeaderColumn + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: dayListHeaderHeight + width: main.width - constDeviceRowWidth + + spacing: 0 + + Repeater{ + model: deviceModel + Rectangle{ + width: parent.width + height: constDeviceRowHeight + border.color: "green" + Text{ + anchors.centerIn: parent + text: modelData.name + } + } + } + } + } Component{ id: listRow Row{ - id: row1 + id: mainRow - width: parent.width; //TODO relative - height: 50 - //color: "red" + width: constDeviceRowWidth //parent.width; //TODO relative + height: constDeviceRowHeight + /* Rectangle { border.color: "red"; width: 100; height:parent.height; Text{ @@ -26,8 +102,8 @@ import "schedulerscripts.js" as Scripts text: modelData.name } } - - Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width-100; height:parent.height; + */ + Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width; height: parent.height; clip: true MouseArea { id: deviceMouseArea @@ -56,44 +132,24 @@ import "schedulerscripts.js" as Scripts //dynamicPoint.setFirstState("dim"); //when type is a stored value dynamicPoint.setFirstState(); - /* - var dynamicBar = actionBar.createObject(deviceRow) - dynamicBar.hangOnToPoint = dynamicPoint - dynamicPoint.hangOnToBar = dynamicBar - */ - dialog.show(dynamicPoint) - - //TODO komponenter med stor bokstav kanske? } } } ListView.onAdd: SequentialAnimation { - PropertyAction { target: row1; property: "height"; value: 0 } - NumberAnimation { target: row1; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } + PropertyAction { target: mainRow; property: "height"; value: 0 } + NumberAnimation { target: mainRow; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } } } - } - - ListView { - id: myListView - anchors.fill: parent - model: deviceModel - delegate: listRow - //focus: true - footer: addButtonComponent - header: timeline - snapMode: ListView.SnapToItem - interactive: false - } - - Component{ + } + + Component{ id: timeline Item{ - width: parent.width - height: 15 + width: constDeviceRowWidth //TODO parent.width + height: dayListHeaderHeight Rectangle{ id: morningDark @@ -124,9 +180,9 @@ import "schedulerscripts.js" as Scripts anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenterOffset: parent.width/24 - width: listRow.width + width: parent.width //listRow.width height: parent.height - spacing: (parent.width-124)/24 + spacing: (parent.width-24)/24 //before: -124 Repeater{ model:24 Rectangle{ @@ -185,7 +241,7 @@ import "schedulerscripts.js" as Scripts return 0; } if(Scripts.isMidnightDark()){ - return sunToTimeUnits(main.sunData[1]) + 100; + return sunToTimeUnits(main.sunData[1]); // + 100; } else{ return 0; @@ -198,10 +254,10 @@ import "schedulerscripts.js" as Scripts return 0; } if(Scripts.isMidnightDark()){ - return 100; //TODO constants + return 0; //100; //TODO constants } else{ - return sunToTimeUnits(main.sunData[1]) + 100; //TODO constants + return sunToTimeUnits(main.sunData[1]); // + 100; //TODO constants } } @@ -210,7 +266,7 @@ import "schedulerscripts.js" as Scripts return 0; } if(Scripts.isMidnightDark()){ - return (main.width - 100) - sunToTimeUnits(main.sunData[1]); //TODO constant or something + return constDeviceRowWidth - sunToTimeUnits(main.sunData[1]); //(main.width - 100) - sunToTimeUnits(main.sunData[1]); //TODO constant or something } else{ return 0; @@ -240,7 +296,7 @@ import "schedulerscripts.js" as Scripts function sunToTimeUnits(suntime){ suntime = suntime.split(':'); - var hourSize = (main.width - 100)/24; //TODO constant or something? + var hourSize = constDeviceRowWidth/24; //(main.width - 100)/24; //TODO constant or something? return hourSize * suntime[0] + hourSize * suntime[1]/60; } //opacity vid dimning? From ead8016cdd2c686cd4fe21a1a5f505944e87de7e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 26 Jan 2011 09:29:37 +0000 Subject: [PATCH 1540/2215] Preparing for storage and connection to scheduling, but have to turn pointList into model now --- .../SchedulerGUISimple/ActionPoint.qml | 4 +- .../Plugins/SchedulerGUISimple/main.qml | 160 ++++++++++++++---- .../SchedulerGUISimple/schedulerscripts.js | 33 +++- 3 files changed, 163 insertions(+), 34 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 97a010e4..fc3c7160 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -32,7 +32,7 @@ Rectangle{ border.color: "black" opacity: 1 //0.8 z: 100 - state: "on" + //state: "on" focus: true //actionTypeColor: getColor() @@ -216,7 +216,7 @@ Rectangle{ anchors.left: pointRect.horizontalCenter color: pointRect.actionTypeColor opacity: pointRect.actionTypeOpacity - width: Scripts.getNextAndPrevBarWidth(actionBar, pointRect, pointRect.parent.children); + width: Scripts.getBarWidth(actionBar, pointRect, pointRect.parent.children, weekModel.get(mainListView.currentIndex)); //getNextAndPrevBarWidth } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 265980a0..30d564cb 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -15,9 +15,54 @@ import "schedulerscripts.js" as Scripts width: parent.width anchors.top: parent.top anchors.left: parent.left + Rectangle{ + anchors.right: weekDayText.left + anchors.verticalCenter: weekDayText.verticalCenter + height: 20 + width: 20 + border.color: "red" + Text{ + anchors.centerIn: parent + text: "<-" + } + MouseArea{ + anchors.fill: parent + onClicked: { + //step to prev weekday + //Scripts.updateEndsWith() + mainListView.decrementCurrentIndex() + //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) + //mainListView.currentIndex = mainListView.currentIndex - 1 + } + } + } Text{ + id: weekDayText anchors.centerIn: parent - text: "TESTAR" + text: mainListView.cacheBuffer + " - " + weekModel.get(mainListView.currentIndex).name + " " + weekModel.get(mainListView.currentIndex).endsWith + " " + mainListView.currentIndex //TODO, do nicer... mainListView.currentItem.test.get(0) // test //.name //mainListView.model[mainListView.currentIndex] //currentItem.name + //TODO test with http://doc.qt.nokia.com/4.7-snapshot/declarative-ui-components-spinner-content-spinner-qml.html alias instead + + } + Rectangle{ + anchors.left: weekDayText.right + anchors.verticalCenter: weekDayText.verticalCenter + height: 20 + width: 20 + border.color: "red" + Text{ + anchors.centerIn: parent + text: "->" + } + MouseArea{ + anchors.fill: parent + onClicked: { + //step to next weekday + //Scripts.updateEndsWith(mainListView) + mainListView.incrementCurrentIndex() + //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) + //mainListView.currentIndex = mainListView.currentIndex + 1 + } + } } } @@ -27,24 +72,54 @@ import "schedulerscripts.js" as Scripts anchors.topMargin: 10 anchors.left: parent.left height: parent.height //TODO - width: parent.width - //anchors.left: dayListView.left - header: mainListViewHeader - model: 1 + width: constDeviceRowWidth + //header: mainListViewHeader + model: weekModel orientation: ListView.Horizontal - delegate: listDayRow //Text { text: "TEST - per modell" } - interactive: false //no scroll between days in this way + //delegate: Rectangle{ width: 600; height: 500; border.color: "black"; Text{text: "koll" + model.name} } //listDayRow + delegate: listDayRow + interactive: false //false //TODO //no scroll between days in this way + clip: true + currentIndex: count-1 + //cacheBuffer: 100000 //TODO remove + + onCurrentIndexChanged: { + + myScript(currentIndex) + } + //highlight: Rectangle { color: "yellow" } + //currentIndex: root.current + //preferredHighlightBegin: 80; preferredHighlightEnd: 220 + //highlightRangeMode: ListView.ApplyRange + //TODO transitions: } + ListModel{ + id: weekModel + ListElement{ + name: "Monday" + endsWith: "" + } + ListElement{ + name: "Tuesday" + endsWith: "" + } + ListElement{ + name: "Wednesday" + endsWith: "" + } + } + Component{ id: listDayRow ListView { id: dayListView + //property variant test: model //anchors.top: mainListView.bottom //anchors.left: parent.left - width: parent.width + width: constDeviceRowWidth //TODO//parent.width height: 700 //TODO //anchors.fill: parent @@ -55,33 +130,44 @@ import "schedulerscripts.js" as Scripts header: timeline snapMode: ListView.SnapToItem interactive: false //no scroll between devices at the moment + + //keyNavigationWraps: true + + /* + states: State { + name: "currentItem"; when: ListView.isCurrentItem + PropertyChanges { target: dayListView; height: myScript(ListView.) } //TODO better way... + //ScriptAction { scriptName: "myScript" } + } + */ } } - Component{ - id: mainListViewHeader - Column{ - id: mainListViewHeaderColumn - anchors.left: parent.left - anchors.top: parent.top - anchors.topMargin: dayListHeaderHeight - width: main.width - constDeviceRowWidth - - spacing: 0 - - Repeater{ - model: deviceModel - Rectangle{ - width: parent.width - height: constDeviceRowHeight - border.color: "green" - Text{ - anchors.centerIn: parent - text: modelData.name - } + //Component{ + // id: mainListViewHeader + Column{ + id: mainListViewHeaderColumn + anchors.right: mainListView.left + anchors.top: mainListView.top + anchors.topMargin: dayListHeaderHeight + + width: main.width - constDeviceRowWidth + + spacing: 0 + + Repeater{ + model: deviceModel + Rectangle{ + width: parent.width + height: constDeviceRowHeight + border.color: "green" + Text{ + anchors.centerIn: parent + text: modelData.name } } } + //} } Component{ @@ -105,6 +191,7 @@ import "schedulerscripts.js" as Scripts */ Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width; height: parent.height; clip: true + MouseArea { id: deviceMouseArea anchors.fill: parent @@ -299,6 +386,21 @@ import "schedulerscripts.js" as Scripts var hourSize = constDeviceRowWidth/24; //(main.width - 100)/24; //TODO constant or something? return hourSize * suntime[0] + hourSize * suntime[1]/60; } + + //TODO SPARA POINTLISTAN OCKSÅ! Kanske inte här, utan att man addar points till modellen och inte den fysiska listan? + function myScript(index){ + + if(index == 0){ + return; + } + index = index - 1; //prev index + var pointList = "TODO" //TODO !!!! förra dagens pointlist... + weekModel.setProperty(index, "endsWith", Scripts.getEndsWith(pointList, "on")) //TODO previousDayEndsWith, vad förra dagen endade med... + + //return 700; + print(index); + print("LYCKATS!!!"); + } //opacity vid dimning? //linjens färg etc (state) beror ju på närmaste punkt föres sort... Punkten kan finnas osynlig (tidigare dag) också... //kan man liksom göra hela linjen (från en vecka tillbaka) men inte visa den? Om det är vettigt... Då hade man tom kunnat zooma en vacker dag diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index ac31b032..a34d04f5 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -8,10 +8,11 @@ function getActiveStates(){ return activeStates; } -function getBarWidth(currentBar, currentPointRect, pointList){ +function getBarWidth(currentBar, currentPointRect, pointList, currentDay){ + //TODO REMOVE currentDay too, currentDay.endsWith = ""; //reset var maxWidth = currentPointRect.parent.width; - var nextX = maxWidth - currentPointRect.width / 2 + var nextX = maxWidth - currentPointRect.width / 2; for(var i=0;i currentPointRect.x){ @@ -19,6 +20,12 @@ function getBarWidth(currentBar, currentPointRect, pointList){ } } } + /* TODO + if(nextX == maxWidth - currentPointRect.width/2 && currentPointRect.state != "" && currentPointRect.state != "off"){ + currentDay.endsWith = currentPointRect.state; + print("Ends with: " + currentDay.endsWith); + } + */ return (nextX - currentPointRect.x); } @@ -40,6 +47,25 @@ function getPreviousState(currentPointRect, pointList){ return prevPoint.state; } +function getEndsWith(pointList, previousDayEndsWith){ + var prevPoint = null; + for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic + prevPoint = pointList[i]; + } + } + } + + if(prevPoint == null){ + return previousDayEndsWith; + } + if(prevPoint.state == "off"){ + return ""; + } + return prevPoint.state; //only on or dim +} + function isMidnightDark(){ if(main.sunData == undefined){ main.sunData = getSunData.call(); @@ -63,7 +89,8 @@ function pad(number, length) { return str; } - +/* function getNextAndPrevBarWidth(currentBar, currentPointRect, pointList){ return getBarWidth(currentBar, currentPointRect, pointList); } +*/ \ No newline at end of file From cb18500d4412aea252afb83a2b3527af49f2187f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 27 Jan 2011 09:53:05 +0000 Subject: [PATCH 1541/2215] Reverted daylist and poinList-as-model changes --- .../SchedulerGUISimple/ActionPoint.qml | 4 +- .../Plugins/SchedulerGUISimple/main.qml | 160 ++++-------------- .../SchedulerGUISimple/schedulerscripts.js | 33 +--- 3 files changed, 34 insertions(+), 163 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index fc3c7160..97a010e4 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -32,7 +32,7 @@ Rectangle{ border.color: "black" opacity: 1 //0.8 z: 100 - //state: "on" + state: "on" focus: true //actionTypeColor: getColor() @@ -216,7 +216,7 @@ Rectangle{ anchors.left: pointRect.horizontalCenter color: pointRect.actionTypeColor opacity: pointRect.actionTypeOpacity - width: Scripts.getBarWidth(actionBar, pointRect, pointRect.parent.children, weekModel.get(mainListView.currentIndex)); //getNextAndPrevBarWidth + width: Scripts.getNextAndPrevBarWidth(actionBar, pointRect, pointRect.parent.children); } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 30d564cb..265980a0 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -15,54 +15,9 @@ import "schedulerscripts.js" as Scripts width: parent.width anchors.top: parent.top anchors.left: parent.left - Rectangle{ - anchors.right: weekDayText.left - anchors.verticalCenter: weekDayText.verticalCenter - height: 20 - width: 20 - border.color: "red" - Text{ - anchors.centerIn: parent - text: "<-" - } - MouseArea{ - anchors.fill: parent - onClicked: { - //step to prev weekday - //Scripts.updateEndsWith() - mainListView.decrementCurrentIndex() - //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) - //mainListView.currentIndex = mainListView.currentIndex - 1 - } - } - } Text{ - id: weekDayText anchors.centerIn: parent - text: mainListView.cacheBuffer + " - " + weekModel.get(mainListView.currentIndex).name + " " + weekModel.get(mainListView.currentIndex).endsWith + " " + mainListView.currentIndex //TODO, do nicer... mainListView.currentItem.test.get(0) // test //.name //mainListView.model[mainListView.currentIndex] //currentItem.name - //TODO test with http://doc.qt.nokia.com/4.7-snapshot/declarative-ui-components-spinner-content-spinner-qml.html alias instead - - } - Rectangle{ - anchors.left: weekDayText.right - anchors.verticalCenter: weekDayText.verticalCenter - height: 20 - width: 20 - border.color: "red" - Text{ - anchors.centerIn: parent - text: "->" - } - MouseArea{ - anchors.fill: parent - onClicked: { - //step to next weekday - //Scripts.updateEndsWith(mainListView) - mainListView.incrementCurrentIndex() - //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) - //mainListView.currentIndex = mainListView.currentIndex + 1 - } - } + text: "TESTAR" } } @@ -72,54 +27,24 @@ import "schedulerscripts.js" as Scripts anchors.topMargin: 10 anchors.left: parent.left height: parent.height //TODO - width: constDeviceRowWidth - //header: mainListViewHeader - model: weekModel + width: parent.width + //anchors.left: dayListView.left + header: mainListViewHeader + model: 1 orientation: ListView.Horizontal - //delegate: Rectangle{ width: 600; height: 500; border.color: "black"; Text{text: "koll" + model.name} } //listDayRow - delegate: listDayRow - interactive: false //false //TODO //no scroll between days in this way - clip: true - currentIndex: count-1 - //cacheBuffer: 100000 //TODO remove - - onCurrentIndexChanged: { - - myScript(currentIndex) - } - //highlight: Rectangle { color: "yellow" } - //currentIndex: root.current - //preferredHighlightBegin: 80; preferredHighlightEnd: 220 - //highlightRangeMode: ListView.ApplyRange - + delegate: listDayRow //Text { text: "TEST - per modell" } + interactive: false //no scroll between days in this way //TODO transitions: } - ListModel{ - id: weekModel - ListElement{ - name: "Monday" - endsWith: "" - } - ListElement{ - name: "Tuesday" - endsWith: "" - } - ListElement{ - name: "Wednesday" - endsWith: "" - } - } - Component{ id: listDayRow ListView { id: dayListView - //property variant test: model //anchors.top: mainListView.bottom //anchors.left: parent.left - width: constDeviceRowWidth //TODO//parent.width + width: parent.width height: 700 //TODO //anchors.fill: parent @@ -130,44 +55,33 @@ import "schedulerscripts.js" as Scripts header: timeline snapMode: ListView.SnapToItem interactive: false //no scroll between devices at the moment - - //keyNavigationWraps: true - - /* - states: State { - name: "currentItem"; when: ListView.isCurrentItem - PropertyChanges { target: dayListView; height: myScript(ListView.) } //TODO better way... - //ScriptAction { scriptName: "myScript" } - } - */ } } - //Component{ - // id: mainListViewHeader - Column{ - id: mainListViewHeaderColumn - anchors.right: mainListView.left - anchors.top: mainListView.top - anchors.topMargin: dayListHeaderHeight - - width: main.width - constDeviceRowWidth - - spacing: 0 - - Repeater{ - model: deviceModel - Rectangle{ - width: parent.width - height: constDeviceRowHeight - border.color: "green" - Text{ - anchors.centerIn: parent - text: modelData.name + Component{ + id: mainListViewHeader + Column{ + id: mainListViewHeaderColumn + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: dayListHeaderHeight + width: main.width - constDeviceRowWidth + + spacing: 0 + + Repeater{ + model: deviceModel + Rectangle{ + width: parent.width + height: constDeviceRowHeight + border.color: "green" + Text{ + anchors.centerIn: parent + text: modelData.name + } } } } - //} } Component{ @@ -191,7 +105,6 @@ import "schedulerscripts.js" as Scripts */ Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width; height: parent.height; clip: true - MouseArea { id: deviceMouseArea anchors.fill: parent @@ -386,21 +299,6 @@ import "schedulerscripts.js" as Scripts var hourSize = constDeviceRowWidth/24; //(main.width - 100)/24; //TODO constant or something? return hourSize * suntime[0] + hourSize * suntime[1]/60; } - - //TODO SPARA POINTLISTAN OCKSÅ! Kanske inte här, utan att man addar points till modellen och inte den fysiska listan? - function myScript(index){ - - if(index == 0){ - return; - } - index = index - 1; //prev index - var pointList = "TODO" //TODO !!!! förra dagens pointlist... - weekModel.setProperty(index, "endsWith", Scripts.getEndsWith(pointList, "on")) //TODO previousDayEndsWith, vad förra dagen endade med... - - //return 700; - print(index); - print("LYCKATS!!!"); - } //opacity vid dimning? //linjens färg etc (state) beror ju på närmaste punkt föres sort... Punkten kan finnas osynlig (tidigare dag) också... //kan man liksom göra hela linjen (från en vecka tillbaka) men inte visa den? Om det är vettigt... Då hade man tom kunnat zooma en vacker dag diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index a34d04f5..ac31b032 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -8,11 +8,10 @@ function getActiveStates(){ return activeStates; } -function getBarWidth(currentBar, currentPointRect, pointList, currentDay){ +function getBarWidth(currentBar, currentPointRect, pointList){ - //TODO REMOVE currentDay too, currentDay.endsWith = ""; //reset var maxWidth = currentPointRect.parent.width; - var nextX = maxWidth - currentPointRect.width / 2; + var nextX = maxWidth - currentPointRect.width / 2 for(var i=0;i currentPointRect.x){ @@ -20,12 +19,6 @@ function getBarWidth(currentBar, currentPointRect, pointList, currentDay){ } } } - /* TODO - if(nextX == maxWidth - currentPointRect.width/2 && currentPointRect.state != "" && currentPointRect.state != "off"){ - currentDay.endsWith = currentPointRect.state; - print("Ends with: " + currentDay.endsWith); - } - */ return (nextX - currentPointRect.x); } @@ -47,25 +40,6 @@ function getPreviousState(currentPointRect, pointList){ return prevPoint.state; } -function getEndsWith(pointList, previousDayEndsWith){ - var prevPoint = null; - for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic - prevPoint = pointList[i]; - } - } - } - - if(prevPoint == null){ - return previousDayEndsWith; - } - if(prevPoint.state == "off"){ - return ""; - } - return prevPoint.state; //only on or dim -} - function isMidnightDark(){ if(main.sunData == undefined){ main.sunData = getSunData.call(); @@ -89,8 +63,7 @@ function pad(number, length) { return str; } -/* + function getNextAndPrevBarWidth(currentBar, currentPointRect, pointList){ return getBarWidth(currentBar, currentPointRect, pointList); } -*/ \ No newline at end of file From b79b5999c2bb7098fdde41849aecd99f9bb6d436 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 27 Jan 2011 12:11:58 +0000 Subject: [PATCH 1542/2215] Started implementation of own day view --- .../Plugins/SchedulerGUISimple/main.qml | 156 +++++++++++++++--- .../SchedulerGUISimple/schedulerscripts.js | 31 ++++ 2 files changed, 162 insertions(+), 25 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 265980a0..a354412c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -9,18 +9,123 @@ import "schedulerscripts.js" as Scripts property variant sunData property int dayListHeaderHeight: 15 + Component.onCompleted: { + var dynamicDay = 0; + for(var i=0;i<7;i++){ //One week, TODO dynamic + dynamicDay = dayListViewComponent.createObject(mainContent) + dynamicDay.state = "hiddenLeft"; + Scripts.addDay(dynamicDay) + //även spara datum... ev. veckodag, eller räkna fram + } + dynamicDay.state = "visible" //set last one as visible + } + Rectangle{ id: mainTop height: 75 width: parent.width anchors.top: parent.top anchors.left: parent.left + Rectangle{ + anchors.right: weekDayText.left + anchors.verticalCenter: weekDayText.verticalCenter + height: 20 + width: 20 + border.color: "red" + Text{ + anchors.centerIn: parent + text: "<-" + } + MouseArea{ + anchors.fill: parent + onClicked: { + //step to prev weekday + //Scripts.updateEndsWith() + Scripts.decrementCurrentDay() + //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) + //mainListView.currentIndex = mainListView.currentIndex - 1 + } + } + } Text{ + id: weekDayText anchors.centerIn: parent text: "TESTAR" + + } + Rectangle{ + anchors.left: weekDayText.right + anchors.verticalCenter: weekDayText.verticalCenter + height: 20 + width: 20 + border.color: "red" + Text{ + anchors.centerIn: parent + text: "->" + } + MouseArea{ + anchors.fill: parent + onClicked: { + //step to next weekday + //Scripts.updateEndsWith(mainListView) + Scripts.incrementCurrentDay() + //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) + //mainListView.currentIndex = mainListView.currentIndex + 1 + } + } } } + Row{ + id: mainRow + width: parent.width + anchors.top: mainTop.bottom + anchors.left: parent.left + + Column{ + id: mainHeader + //anchors.left: parent.left + //anchors.top: parent.top + //anchors.topMargin: dayListHeaderHeight + width: main.width - constDeviceRowWidth + + spacing: 0 + z: 60 + Rectangle{ + id: filler + height: dayListHeaderHeight + width: parent.width + border.color: "red" + } + + Repeater{ + + model: deviceModel + Rectangle{ + width: parent.width + height: constDeviceRowHeight + border.color: "green" + Text{ + anchors.centerIn: parent + text: modelData.name + } + } + } + } + + Rectangle{ + id: mainContent + height: 700 //TODO + width: constDeviceRowWidth //TODO + //anchors.top: parent.top + //anchors.left: mainListViewHeaderColumn.right + clip: true + z: 50 + } + + } + + /* ListView{ id: mainListView anchors.top: mainTop.bottom @@ -37,14 +142,15 @@ import "schedulerscripts.js" as Scripts //TODO transitions: } + */ Component{ - id: listDayRow + id: dayListViewComponent ListView { id: dayListView //anchors.top: mainListView.bottom //anchors.left: parent.left - width: parent.width + width: constDeviceRowWidth height: 700 //TODO //anchors.fill: parent @@ -55,32 +161,32 @@ import "schedulerscripts.js" as Scripts header: timeline snapMode: ListView.SnapToItem interactive: false //no scroll between devices at the moment - } - } - - Component{ - id: mainListViewHeader - Column{ - id: mainListViewHeaderColumn - anchors.left: parent.left - anchors.top: parent.top - anchors.topMargin: dayListHeaderHeight - width: main.width - constDeviceRowWidth + //anchors.top: parent.top; + //state: "hidden" //default - spacing: 0 - - Repeater{ - model: deviceModel - Rectangle{ - width: parent.width - height: constDeviceRowHeight - border.color: "green" - Text{ - anchors.centerIn: parent - text: modelData.name - } + states: [ + State { + name: "hiddenRight"; //when: parent.left != null + AnchorChanges { target: dayListView; anchors.left: parent.right; anchors.right: undefined } + //PropertyChanges { target: dayListView; opacity: 0 } + }, + State { + name: "hiddenLeft"; //when: parent.left != null + AnchorChanges { target: dayListView; anchors.left: undefined; anchors.right: parent.left } + //PropertyChanges { target: dayListView; opacity: 0 } + }, + State { + name: "visible"; //when: parent.left != null + AnchorChanges { target: dayListView; anchors.right: undefined; anchors.left: parent.left } + PropertyChanges { target: dayListView; opacity: 1 } } + ] + + transitions: Transition { + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } } + //TODO transition between state, animation + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index ac31b032..23f39fd5 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -8,6 +8,37 @@ function getActiveStates(){ return activeStates; } +//Days: +var currentDayIndex = 6; //Today... +var days = new Array(); + +function addDay(day){ + days.push(day); +} + +function getDays(){ + return days; +} + +function decrementCurrentDay(){ + if(currentDayIndex == 0){ //TODO in the future, add new day instead (if 7 days) + return; + } + days[currentDayIndex].state = "hiddenRight"; + currentDayIndex--; + days[currentDayIndex].state = "visible"; +} + +function incrementCurrentDay(){ + if(currentDayIndex == days.length){ + return; //TODO add day instead + } + days[currentDayIndex].state = "hiddenLeft"; + currentDayIndex++; + days[currentDayIndex].state = "visible"; +} + +//Other: function getBarWidth(currentBar, currentPointRect, pointList){ var maxWidth = currentPointRect.parent.width; From 65381c0a2bcb03b830ee27b5d8888fbce4e16175 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 27 Jan 2011 15:10:48 +0000 Subject: [PATCH 1543/2215] Continued implementation of own day view --- .../Plugins/SchedulerGUISimple/main.qml | 23 ++++++++++++++++--- .../SchedulerGUISimple/schedulerscripts.js | 15 ++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index a354412c..50ee094d 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -11,13 +11,22 @@ import "schedulerscripts.js" as Scripts Component.onCompleted: { var dynamicDay = 0; + var startday = new Date(); + startday.setDate(startday.getDate() - 6); + var weekday_name_array = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday") for(var i=0;i<7;i++){ //One week, TODO dynamic dynamicDay = dayListViewComponent.createObject(mainContent) dynamicDay.state = "hiddenLeft"; + var currentDay = new Date(startday); + currentDay.setDate(startday.getDate() + i); + var day = currentDay.getDay(); + dynamicDay.dayName = weekday_name_array[day]; Scripts.addDay(dynamicDay) - //även spara datum... ev. veckodag, eller räkna fram + //även spara datum...? ev. räkna fram veckodag? } dynamicDay.state = "visible" //set last one as visible + weekDayText.text = Scripts.getCurrentDay().dayName + //weekDayText.state = "loaded" } Rectangle{ @@ -42,6 +51,7 @@ import "schedulerscripts.js" as Scripts //step to prev weekday //Scripts.updateEndsWith() Scripts.decrementCurrentDay() + weekDayText.text = Scripts.getCurrentDay().dayName //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) //mainListView.currentIndex = mainListView.currentIndex - 1 } @@ -50,7 +60,12 @@ import "schedulerscripts.js" as Scripts Text{ id: weekDayText anchors.centerIn: parent - text: "TESTAR" + //text: "" + /*states: State{ + name: "loaded"; + PropertyChanges{ target: weekDayText; text: Scripts.getCurrentDay().dayName } + } + */ } Rectangle{ @@ -69,6 +84,7 @@ import "schedulerscripts.js" as Scripts //step to next weekday //Scripts.updateEndsWith(mainListView) Scripts.incrementCurrentDay() + weekDayText.text = Scripts.getCurrentDay().dayName //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) //mainListView.currentIndex = mainListView.currentIndex + 1 } @@ -148,6 +164,7 @@ import "schedulerscripts.js" as Scripts id: dayListViewComponent ListView { id: dayListView + property string dayName: "" //anchors.top: mainListView.bottom //anchors.left: parent.left width: constDeviceRowWidth @@ -220,7 +237,7 @@ import "schedulerscripts.js" as Scripts //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { - + //print("Mainrow: " + mainRow.parent.children[0].height); var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) //dynamicPoint.x = mouseX - dynamicPoint.width/2 //xposition diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 23f39fd5..51a47e88 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -20,6 +20,21 @@ function getDays(){ return days; } +function getCurrentDay(){ + return days[currentDayIndex]; +} + +/* +function getCurrentDayName(){ + print("Hittat rätt" + currentDayIndex); + var day = days[currentDayIndex]; + if(day == null){ + return "TOMT-omt-omt"; + } + return day.dayName; +} +*/ + function decrementCurrentDay(){ if(currentDayIndex == 0){ //TODO in the future, add new day instead (if 7 days) return; From 90e3adcd8158ef1ee28457f3f65b3fc7eb910904 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Jan 2011 15:42:01 +0000 Subject: [PATCH 1544/2215] Added property QMLArray.length --- telldus-gui/Plugins/QML/qmlarray.h | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/Plugins/QML/qmlarray.h b/telldus-gui/Plugins/QML/qmlarray.h index e8279cb7..cf9ed8d7 100644 --- a/telldus-gui/Plugins/QML/qmlarray.h +++ b/telldus-gui/Plugins/QML/qmlarray.h @@ -7,6 +7,7 @@ class QMLArray : public QAbstractListModel { Q_OBJECT + Q_PROPERTY(int length READ rowCount) public: explicit QMLArray(QObject *parent = 0); ~QMLArray(); From 20d662b209112becccdabc676ea29c29a4e90847 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Jan 2011 16:20:31 +0000 Subject: [PATCH 1545/2215] Added function QMLArray::get() --- telldus-gui/Plugins/QML/qmlarray.cpp | 12 ++++++++---- telldus-gui/Plugins/QML/qmlarray.h | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/QML/qmlarray.cpp b/telldus-gui/Plugins/QML/qmlarray.cpp index 48f32a42..b36bfac8 100644 --- a/telldus-gui/Plugins/QML/qmlarray.cpp +++ b/telldus-gui/Plugins/QML/qmlarray.cpp @@ -21,16 +21,20 @@ QMLArray::~QMLArray() { delete d; } -int QMLArray::rowCount(const QModelIndex &parent) const { - return d->list.size(); -} - QVariant QMLArray::data(const QModelIndex &index, int role) const { return d->list.at(index.row()).toVariant(); } +QVariant QMLArray::get(int index) const { + return this->data(this->index(index), Qt::DisplayRole); +} + void QMLArray::push(const QScriptValue &v) { beginInsertRows( QModelIndex(), d->list.size(), d->list.size() ); d->list << v; endInsertRows(); } + +int QMLArray::rowCount(const QModelIndex &parent) const { + return d->list.size(); +} diff --git a/telldus-gui/Plugins/QML/qmlarray.h b/telldus-gui/Plugins/QML/qmlarray.h index cf9ed8d7..8c29b798 100644 --- a/telldus-gui/Plugins/QML/qmlarray.h +++ b/telldus-gui/Plugins/QML/qmlarray.h @@ -19,6 +19,8 @@ signals: public slots: void push(const QScriptValue &v); + QVariant get(int index) const; + private: class PrivateData; From c346f7bee5648035b8d0dddd5a97edc6d2939ba3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 28 Jan 2011 15:29:55 +0000 Subject: [PATCH 1546/2215] Navigation between days implemented --- .../SchedulerGUISimple/ActionPoint.qml | 28 ++++++- .../Plugins/SchedulerGUISimple/main.qml | 80 +++++++++++-------- .../SchedulerGUISimple/schedulerscripts.js | 72 +++++++++++++---- 3 files changed, 130 insertions(+), 50 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 97a010e4..daca4ea8 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -17,6 +17,8 @@ Rectangle{ property int absoluteHour: parseInt(dialog.absoluteHour, 10) property int absoluteMinute: parseInt(dialog.absoluteMinute, 10) property alias triggerstate: trigger.state + property variant parentPoint + property int parentPointAbsoluteHour: 0 Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... @@ -49,6 +51,13 @@ Rectangle{ text: pointRect.activeFocus ? "I HAVE active focus!" : "I do NOT have active focus" } */ + + onParentPointAbsoluteHourChanged: { + print("Nja"); + //pointRect.absoluteHour = parentPoint.absolutHour + dialog.absoluteHour = parentPointAbsoluteHour; + } + MouseArea { id: pointRectMouseArea acceptedButtons: Qt.LeftButton | Qt.RightButton @@ -74,11 +83,17 @@ Rectangle{ } onReleased: { - dialog.show(pointRect) + + dialog.show(pointRect) //TODO not pointRect, but parentPoint if such exists //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); //var hourMinute = getTimeFromPosition(rootCoordinates.x) dialog.absoluteHour = Scripts.pad(pointRect.absoluteHour, 2) //Scripts.pad(hourMinute[0], 2) dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) //Scripts.pad(hourMinute[1], 2) + + print("TESTAR!!! " + parentPoint); + if(parentPoint != undefined){ + parentPoint.absoluteHour = dialog.absoluteHour; + } } anchors.fill: parent @@ -181,6 +196,10 @@ Rectangle{ name: "bell" PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } PropertyChanges { target: pointRect; actionTypeImage: imageActionBell } + }, + State{ + name: "test"; when: pointRect.parentPoint != undefined + PropertyChanges{ target: pointRect; parentPointAbsoluteHour: pointRect.parentPoint.absoluteHour } } ] @@ -228,7 +247,12 @@ Rectangle{ return 0; } var hourSize = pointRect.parent.width / 24; - return pointRect.absoluteHour * hourSize + hourSize * (pointRect.absoluteMinute/60) - pointRect.width/2; + var point = pointRect; + if(pointRect.parentPoint != undefined){ + print("Different x"); + point = pointRect.parentPoint; + } + return point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2; } function toggleType(){ //TODO other kind of selection method diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 50ee094d..62ff9007 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -13,20 +13,17 @@ import "schedulerscripts.js" as Scripts var dynamicDay = 0; var startday = new Date(); startday.setDate(startday.getDate() - 6); - var weekday_name_array = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday") for(var i=0;i<7;i++){ //One week, TODO dynamic dynamicDay = dayListViewComponent.createObject(mainContent) dynamicDay.state = "hiddenLeft"; var currentDay = new Date(startday); currentDay.setDate(startday.getDate() + i); - var day = currentDay.getDay(); - dynamicDay.dayName = weekday_name_array[day]; + dynamicDay.daydate = currentDay; Scripts.addDay(dynamicDay) - //även spara datum...? ev. räkna fram veckodag? } dynamicDay.state = "visible" //set last one as visible - weekDayText.text = Scripts.getCurrentDay().dayName - //weekDayText.state = "loaded" + weekDayText.text = Scripts.getCurrentDayName() + Scripts.updateDeviceIndex(); } Rectangle{ @@ -51,7 +48,7 @@ import "schedulerscripts.js" as Scripts //step to prev weekday //Scripts.updateEndsWith() Scripts.decrementCurrentDay() - weekDayText.text = Scripts.getCurrentDay().dayName + weekDayText.text = Scripts.getCurrentDayName() //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) //mainListView.currentIndex = mainListView.currentIndex - 1 } @@ -84,7 +81,7 @@ import "schedulerscripts.js" as Scripts //step to next weekday //Scripts.updateEndsWith(mainListView) Scripts.incrementCurrentDay() - weekDayText.text = Scripts.getCurrentDay().dayName + weekDayText.text = Scripts.getCurrentDayName() //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) //mainListView.currentIndex = mainListView.currentIndex + 1 } @@ -141,30 +138,11 @@ import "schedulerscripts.js" as Scripts } - /* - ListView{ - id: mainListView - anchors.top: mainTop.bottom - anchors.topMargin: 10 - anchors.left: parent.left - height: parent.height //TODO - width: parent.width - //anchors.left: dayListView.left - header: mainListViewHeader - model: 1 - orientation: ListView.Horizontal - delegate: listDayRow //Text { text: "TEST - per modell" } - interactive: false //no scroll between days in this way - - //TODO transitions: - } - */ - Component{ id: dayListViewComponent ListView { id: dayListView - property string dayName: "" + property date daydate //anchors.top: mainListView.bottom //anchors.left: parent.left width: constDeviceRowWidth @@ -194,14 +172,33 @@ import "schedulerscripts.js" as Scripts }, State { name: "visible"; //when: parent.left != null - AnchorChanges { target: dayListView; anchors.right: undefined; anchors.left: parent.left } PropertyChanges { target: dayListView; opacity: 1 } + AnchorChanges { target: dayListView; anchors.right: undefined; anchors.left: parent.left } } ] - transitions: Transition { - AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } - } + transitions: [ + Transition { + from: "hiddenLeft" + to: "visible" + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + }, + Transition { + from: "visible" + to: "hiddenRight" + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + }, + Transition { + from: "visible" + to: "hiddenLeft" + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + }, + Transition { + from: "hiddenRight" + to: "visible" + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + } + ] //TODO transition between state, animation } @@ -255,6 +252,25 @@ import "schedulerscripts.js" as Scripts //dynamicPoint.setFirstState("dim"); //when type is a stored value dynamicPoint.setFirstState(); + + //TEST, proof of concept for repeat-everyday-points: + //if deleted, must check if parent exists before deletion + //in that case, parent must have list of all its children and delete them too... + /* + var dynamicPoint2 = component.createObject(deviceRow.parent.parent.children[1]) + dynamicPoint2.absoluteHour = dynamicPoint.absoluteHour + dynamicPoint2.absoluteMinute = 30 + dynamicPoint2.parentPoint = dynamicPoint + dynamicPoint2.x = dynamicPoint2.getAbsoluteXValue(); + dynamicPoint2.border.color = "blue" + dynamicPoint2.addState("on"); + dynamicPoint2.addState("off"); + dynamicPoint2.addState("dim"); + dynamicPoint2.addState("bell"); + dynamicPoint2.setFirstState(); + */ + //SLUT TEST + dialog.show(dynamicPoint) } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 51a47e88..08954931 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -1,3 +1,6 @@ +//TODO pragma instead? Which is best in this case? + +var deviceIndex = []; var activeStates = new Array(); function addState(state){ @@ -9,6 +12,7 @@ function getActiveStates(){ } //Days: +var weekday_name_array = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday") var currentDayIndex = 6; //Today... var days = new Array(); @@ -24,32 +28,39 @@ function getCurrentDay(){ return days[currentDayIndex]; } -/* function getCurrentDayName(){ - print("Hittat rätt" + currentDayIndex); - var day = days[currentDayIndex]; - if(day == null){ - return "TOMT-omt-omt"; - } - return day.dayName; + var day = getCurrentDay().daydate; + return weekday_name_array[day.getDay()] + " " + day.getDate(); } -*/ + function decrementCurrentDay(){ - if(currentDayIndex == 0){ //TODO in the future, add new day instead (if 7 days) - return; - } days[currentDayIndex].state = "hiddenRight"; - currentDayIndex--; + var workDate = days[currentDayIndex].daydate; + workDate.setDate(workDate.getDate() - 7); + days[currentDayIndex].daydate = workDate; + if(currentDayIndex == 0){ + currentDayIndex = days.length - 1; + } + else{ + currentDayIndex--; + } + days[currentDayIndex].state = "hiddenLeft"; //place on right side of center, for correct slid days[currentDayIndex].state = "visible"; } function incrementCurrentDay(){ - if(currentDayIndex == days.length){ - return; //TODO add day instead - } days[currentDayIndex].state = "hiddenLeft"; - currentDayIndex++; + var workDate = days[currentDayIndex].daydate; + workDate.setDate(workDate.getDate() + 1); + if(currentDayIndex == (days.length - 1)){ + currentDayIndex = 0; + } + else{ + currentDayIndex++; + } + days[currentDayIndex].daydate = workDate; + days[currentDayIndex].state = "hiddenRight"; //place on right side of center, for correct slide days[currentDayIndex].state = "visible"; } @@ -113,3 +124,32 @@ function pad(number, length) { function getNextAndPrevBarWidth(currentBar, currentPointRect, pointList){ return getBarWidth(currentBar, currentPointRect, pointList); } + +function updateDeviceIndex(){ + deviceIndex = []; //empty list + for(var i=0;i från __init__.js + for(var i=0;i Date: Fri, 28 Jan 2011 16:26:15 +0000 Subject: [PATCH 1547/2215] Dummy points added on start --- .../Plugins/SchedulerGUISimple/main.qml | 1 + .../SchedulerGUISimple/schedulerscripts.js | 30 +++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 62ff9007..63057906 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -24,6 +24,7 @@ import "schedulerscripts.js" as Scripts dynamicDay.state = "visible" //set last one as visible weekDayText.text = Scripts.getCurrentDayName() Scripts.updateDeviceIndex(); + Scripts.initiatePointsInGUI(); } Rectangle{ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 08954931..5330a857 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -134,12 +134,18 @@ function updateDeviceIndex(){ //} } -function initiatePointsInGUI(pointList){ +function initiatePointsInGUI(){ //weekPointList){ //för varje point, addPointToGUI, men ju även lägga till schemajobb... alltså i __init__.js... men därifrån kan inte denna anropas... //så det får väl bli varsin iteration då... //weekPointList -> från __init__.js + var weekPointList = new Array(); + var dummypoint = [] + dummypoint["day"] = 3; + dummypoint["deviceId"] = 1; + weekPointList.push(dummypoint); for(var i=0;i Date: Tue, 1 Feb 2011 11:45:15 +0000 Subject: [PATCH 1548/2215] Started with continuing-bar-from-previous-page-logic --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 37 +++ .../SchedulerGUISimple/ActionPoint.qml | 30 +-- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 1 + .../Plugins/SchedulerGUISimple/main.qml | 59 ++++- .../SchedulerGUISimple/schedulerscripts.js | 247 +++++++++++++++--- 5 files changed, 304 insertions(+), 70 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml new file mode 100644 index 00000000..0e0f5b78 --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -0,0 +1,37 @@ +import Qt 4.7 +import "schedulerscripts.js" as Scripts + +Rectangle{ + id: barRectangle + property variant hangOnToPoint + property variant days + property int currentDay + + height: constBarHeight + z: 110 + + states: [ + State{ + name: "continuing" + PropertyChanges { + target: barRectangle + anchors.verticalCenter: hangOnToPoint.verticalCenter + anchors.left: hangOnToPoint.left + color: Scripts.getPreviousDayColor(currentDay, days) //not really point, but deviceRow TODO + opacity: 100 //TODO + width: 50 //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before + } + }, + State { + name: "pointLoaded" //; when: hangOnToPoint != undefined && hangOnToPoint.isLoaded != undefined && hangOnToPoint.parent != null && hangOnToPoint.parent != undefined && hangOnToPoint.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning, used hangOnToPoint.isLoaded too before, remove this? + PropertyChanges { + target: barRectangle + anchors.verticalCenter: hangOnToPoint.verticalCenter + anchors.left: hangOnToPoint.horizontalCenter + color: hangOnToPoint.actionTypeColor + opacity: hangOnToPoint.actionTypeOpacity + width: Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children) //TEST getNextAndPrevBarWidth before + } + } + ] +} diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index daca4ea8..a1607aa2 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -23,8 +23,10 @@ Rectangle{ Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... isLoaded = "true" + var actionBar = Qt.createComponent("ActionBar.qml") var dynamicBar = actionBar.createObject(pointRect) dynamicBar.hangOnToPoint = pointRect + dynamicBar.state = "pointLoaded" //pointRect.hangOnToBar = dynamicBar } @@ -197,7 +199,7 @@ Rectangle{ PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } PropertyChanges { target: pointRect; actionTypeImage: imageActionBell } }, - State{ + State{ //TODO test name: "test"; when: pointRect.parentPoint != undefined PropertyChanges{ target: pointRect; parentPointAbsoluteHour: pointRect.parentPoint.absoluteHour } } @@ -218,30 +220,6 @@ Rectangle{ } } - Component{ - id: actionBar - Rectangle{ - id: barRectangle - property variant hangOnToPoint - - height: constBarHeight - z: 110 - - states: State { - name: "pointLoaded"; when: pointRect.parent != null && pointRect.isLoaded != undefined && pointRect.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning - PropertyChanges { - target: barRectangle - anchors.verticalCenter: pointRect.verticalCenter - anchors.left: pointRect.horizontalCenter - color: pointRect.actionTypeColor - opacity: pointRect.actionTypeOpacity - width: Scripts.getNextAndPrevBarWidth(actionBar, pointRect, pointRect.parent.children); - } - } - - } - } - function getAbsoluteXValue(){ if(pointRect.parent == null){ return 0; @@ -377,7 +355,7 @@ Rectangle{ return; } - var previousState = Scripts.getPreviousState(pointRect, pointRect.parent.children); + var previousState = Scripts.getPreviousState(pointRect); if(previousState == "" || previousState == "off"){ //nothing on/dimmed at the moment, use first added state pointRect.state = activeStates[0]; diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 6fb65de4..6f1d9698 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -6,6 +6,7 @@ SET( Plugin_NAME "schedulerguisimple" ) SET( Plugin_PATH "com.telldus.schedulerguisimple" ) SET( Plugin_EXTRA + ActionBar.qml ActionPoint.qml Button.qml Dialog.qml diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 63057906..462d0e51 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -11,6 +11,7 @@ import "schedulerscripts.js" as Scripts Component.onCompleted: { var dynamicDay = 0; + var previousDayEndsWithPoint = null; //previous day, nothing to begin with var startday = new Date(); startday.setDate(startday.getDate() - 6); for(var i=0;i<7;i++){ //One week, TODO dynamic @@ -19,12 +20,15 @@ import "schedulerscripts.js" as Scripts var currentDay = new Date(startday); currentDay.setDate(startday.getDate() + i); dynamicDay.daydate = currentDay; - Scripts.addDay(dynamicDay) + //TODO previousDayEndsWith = + Scripts.addDay(dynamicDay); + Scripts.updateDeviceIndex(); //TODO, don't run in every iteration } dynamicDay.state = "visible" //set last one as visible weekDayText.text = Scripts.getCurrentDayName() - Scripts.updateDeviceIndex(); + //Scripts.updateDeviceIndex(); Scripts.initiatePointsInGUI(); + Scripts.updateEndsWith(); } Rectangle{ @@ -47,7 +51,7 @@ import "schedulerscripts.js" as Scripts anchors.fill: parent onClicked: { //step to prev weekday - //Scripts.updateEndsWith() + Scripts.updateEndsWith() Scripts.decrementCurrentDay() weekDayText.text = Scripts.getCurrentDayName() //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) @@ -80,7 +84,7 @@ import "schedulerscripts.js" as Scripts anchors.fill: parent onClicked: { //step to next weekday - //Scripts.updateEndsWith(mainListView) + Scripts.updateEndsWith() //mainListView) Scripts.incrementCurrentDay() weekDayText.text = Scripts.getCurrentDayName() //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) @@ -144,6 +148,9 @@ import "schedulerscripts.js" as Scripts ListView { id: dayListView property date daydate + //property alias devices2: dayListView.children + //property alias devices: dayListView.devices2[0] + //property string endsWith //anchors.top: mainListView.bottom //anchors.left: parent.left width: constDeviceRowWidth @@ -200,6 +207,7 @@ import "schedulerscripts.js" as Scripts AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } } ] + //TODO transition between state, animation } @@ -208,6 +216,7 @@ import "schedulerscripts.js" as Scripts Component{ id: listRow + /* Row{ id: mainRow @@ -224,8 +233,11 @@ import "schedulerscripts.js" as Scripts } } */ - Rectangle { id: "deviceRow"; border.color: "blue"; width: parent.width; height: parent.height; + Rectangle { id: "deviceRow"; border.color: "blue"; width: constDeviceRowWidth; height: constDeviceRowHeight; clip: true + property variant endPoint: undefined //: Scripts.getEndsWith(deviceRow.children, index, modelData.id); + property int deviceId: modelData.id; + MouseArea { id: deviceMouseArea anchors.fill: parent @@ -235,6 +247,8 @@ import "schedulerscripts.js" as Scripts //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { + print("ENDPOINT: " + deviceRow.endPoint); + /* //print("Mainrow: " + mainRow.parent.children[0].height); var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) @@ -272,17 +286,38 @@ import "schedulerscripts.js" as Scripts */ //SLUT TEST - dialog.show(dynamicPoint) + //dialog.show(dynamicPoint) + } + } + + ActionBar{ + id: "continuingBar" + hangOnToPoint: deviceRow + days: Scripts.getDays() + currentDay: Scripts.currentDayIndex + + state: "continuing" + } + + Item{ + //TODO eller ska detta VARA början-rektanglen? + id: previousDay + states: State{ + name: "isFirst"; when: daydate > getPreviousDayDate() + PropertyChanges{ target: dayListView; endsWith: "NÅGOT" } } } + ListView.onAdd: SequentialAnimation { + PropertyAction { target: mainRow; property: "height"; value: 0 } + NumberAnimation { target: mainRow; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } + } + + function hasPoints(){ + return Scripts.hasPoints(deviceRow.children); + } } - - ListView.onAdd: SequentialAnimation { - PropertyAction { target: mainRow; property: "height"; value: 0 } - NumberAnimation { target: mainRow; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } - } - } + //} } Component{ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 5330a857..458bc0fd 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -1,6 +1,8 @@ -//TODO pragma instead? Which is best in this case? +//TODO pragma library instead? Which is best in this case? "pad" can be moved there var deviceIndex = []; + +//TODO active states - move to actionPoint-only-js file var activeStates = new Array(); function addState(state){ @@ -20,20 +22,6 @@ function addDay(day){ days.push(day); } -function getDays(){ - return days; -} - -function getCurrentDay(){ - return days[currentDayIndex]; -} - -function getCurrentDayName(){ - var day = getCurrentDay().daydate; - return weekday_name_array[day.getDay()] + " " + day.getDate(); -} - - function decrementCurrentDay(){ days[currentDayIndex].state = "hiddenRight"; var workDate = days[currentDayIndex].daydate; @@ -49,6 +37,19 @@ function decrementCurrentDay(){ days[currentDayIndex].state = "visible"; } +function getCurrentDay(){ + return days[currentDayIndex]; +} + +function getCurrentDayName(){ + var day = getCurrentDay().daydate; + return weekday_name_array[day.getDay()] + " " + day.getDate(); +} + +function getDays(){ + return days; +} + function incrementCurrentDay(){ days[currentDayIndex].state = "hiddenLeft"; var workDate = days[currentDayIndex].daydate; @@ -79,8 +80,57 @@ function getBarWidth(currentBar, currentPointRect, pointList){ return (nextX - currentPointRect.x); } -function getPreviousState(currentPointRect, pointList){ +function hasPoints(pointList){ + for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic + prevPoint = pointList[i]; + } + } + } + + if(prevPoint == null){ + dayIndex = dayIndex - 1; + if(dayIndex == -1){ //too far, begin from end again + dayIndex = days.length - 1; + } + + //TODO Avoid loop here! + var prevDayDevice = getDeviceRow(dayIndex, deviceId); + print("PREVDAYHERE: index: " + dayIndex + " id: " + deviceId + " Daydevice: " + prevDayDevice); + //print("Test1: " + prevDayDevice.children.length); + //print("Test2: " + prevDayDevice.children[0]); + if(prevDayDevice == undefined){ // || prevDayDevice.endPoint == undefined){ //TODO this is due to an error, but in the future use it to avoid loops + print("DayDeviceUndefined...................."); + return null; + } + print("RETURNING A PREV POINT"); + print("Prev day: " + days[dayIndex].daydate.getDate()); + print("Containing: " + prevDayDevice.endPoint); + return prevDayDevice.endPoint; // previousDayEndsWithPoint; + } + if(prevPoint.state == "off"){ + return null; + } + print("RETURNING A POINT"); + return prevPoint; //.state, only on or dim +} + +function getPreviousState(currentPointRect){ + var pointList = currentPointRect.parent.children var prevPoint = null; for(var i=0;i days[currentDay]){ + + } + */ + //print("Current day index: " + dayIndex); + //print("Days count: " + daysLocal.length); + var prevDay = daysLocal[dayIndex]; //TODO Kan ju inte vara per dag! Ska vara per device... + if(prevDay == undefined || prevDay.endPoint == undefined){ + //no previous end point exists + return "white"; + } + var prevEndPoint = prevDay.endPoint; + return prevEndPoint.actionTypeColor; +} + function isMidnightDark(){ if(main.sunData == undefined){ main.sunData = getSunData.call(); @@ -121,26 +193,126 @@ function pad(number, length) { return str; } -function getNextAndPrevBarWidth(currentBar, currentPointRect, pointList){ - return getBarWidth(currentBar, currentPointRect, pointList); -} - -function updateDeviceIndex(){ +function updateDeviceIndex(){ //TODO, better way, please... deviceIndex = []; //empty list - for(var i=0;i days.length-1){ + dayIndex = dayIndex - days.length; + } + + var deviceRow = days[dayIndex].children[0].children[parseInt(deviceIndex[device])]; //+1 TODO property somehow? + if(deviceRow.hasPoints()){ + deviceRow.endPoint = getEndsWith(deviceRow.children, days[dayIndex].daydate.getDay(), deviceRow.deviceId); + previousEndPoint = deviceRow.endPoint; + } + else{ + deviceRow.endPoint = previousEndPoint; + } + } + } + + + /* + + for(var i=0;i days.length-1){ + dayindex = dayindex - days.length; + } + print("Day: " + dayindex); + + + var day = days[dayindex]; + print("Day length: " + day.children[0].children.length); + for(var j=1;j från __init__.js var weekPointList = new Array(); var dummypoint = [] - dummypoint["day"] = 3; + dummypoint["day"] = 5; dummypoint["deviceId"] = 1; weekPointList.push(dummypoint); for(var i=0;i Date: Tue, 1 Feb 2011 14:54:12 +0000 Subject: [PATCH 1549/2215] More on continuing bars --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 12 +- .../Plugins/SchedulerGUISimple/main.qml | 8 +- .../SchedulerGUISimple/schedulerscripts.js | 129 +++++++----------- 3 files changed, 54 insertions(+), 95 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml index 0e0f5b78..f11a4c03 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -4,8 +4,9 @@ import "schedulerscripts.js" as Scripts Rectangle{ id: barRectangle property variant hangOnToPoint - property variant days - property int currentDay + property color prevDayColor + property double prevDayOpacity + property int prevDayWidth height: constBarHeight z: 110 @@ -17,9 +18,10 @@ Rectangle{ target: barRectangle anchors.verticalCenter: hangOnToPoint.verticalCenter anchors.left: hangOnToPoint.left - color: Scripts.getPreviousDayColor(currentDay, days) //not really point, but deviceRow TODO - opacity: 100 //TODO - width: 50 //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before + color: barRectangle.prevDayColor + //getPreviousDayColor(barRectangle.currentDay, barRectangle.days, hangOnToPoint.deviceId, barRectangle.deviceIndex) + opacity: barRectangle.prevDayOpacity + width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before } }, State { diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 462d0e51..658afbf9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -148,11 +148,6 @@ import "schedulerscripts.js" as Scripts ListView { id: dayListView property date daydate - //property alias devices2: dayListView.children - //property alias devices: dayListView.devices2[0] - //property string endsWith - //anchors.top: mainListView.bottom - //anchors.left: parent.left width: constDeviceRowWidth height: 700 //TODO @@ -237,6 +232,7 @@ import "schedulerscripts.js" as Scripts clip: true property variant endPoint: undefined //: Scripts.getEndsWith(deviceRow.children, index, modelData.id); property int deviceId: modelData.id; + property alias continuingBar: continuingBar MouseArea { id: deviceMouseArea @@ -293,8 +289,6 @@ import "schedulerscripts.js" as Scripts ActionBar{ id: "continuingBar" hangOnToPoint: deviceRow - days: Scripts.getDays() - currentDay: Scripts.currentDayIndex state: "continuing" } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 458bc0fd..ba4eda1e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -109,10 +109,8 @@ function getEndsWith(pointList, dayIndex, deviceId){ //previousDayEndsWithPoint) } //TODO Avoid loop here! - var prevDayDevice = getDeviceRow(dayIndex, deviceId); + var prevDayDevice = getDeviceRow(dayIndex, deviceId, days, deviceIndex); print("PREVDAYHERE: index: " + dayIndex + " id: " + deviceId + " Daydevice: " + prevDayDevice); - //print("Test1: " + prevDayDevice.children.length); - //print("Test2: " + prevDayDevice.children[0]); if(prevDayDevice == undefined){ // || prevDayDevice.endPoint == undefined){ //TODO this is due to an error, but in the future use it to avoid loops print("DayDeviceUndefined...................."); return null; @@ -147,28 +145,6 @@ function getPreviousState(currentPointRect){ return prevPoint.state; } -//TODO: move this to separate js library (pragma?) -function getPreviousDayColor(currentDayIndexLocal, daysLocal){ - var dayIndex = currentDayIndexLocal - 1; - if(dayIndex == -1){ //too far, begin from end again - dayIndex = daysLocal.length - 1; - } - /* TODO have too avoid binding loop... - if(days[dayIndex].daydate > days[currentDay]){ - - } - */ - //print("Current day index: " + dayIndex); - //print("Days count: " + daysLocal.length); - var prevDay = daysLocal[dayIndex]; //TODO Kan ju inte vara per dag! Ska vara per device... - if(prevDay == undefined || prevDay.endPoint == undefined){ - //no previous end point exists - return "white"; - } - var prevEndPoint = prevDay.endPoint; - return prevEndPoint.actionTypeColor; -} - function isMidnightDark(){ if(main.sunData == undefined){ main.sunData = getSunData.call(); @@ -224,11 +200,14 @@ function updateEndsWith(){ var startIndex = 0; for(var dayIndex=0;dayIndex days.length-1){ - dayindex = dayindex - days.length; - } - print("Day: " + dayindex); - - - var day = days[dayindex]; - print("Day length: " + day.children[0].children.length); - for(var j=1;j Date: Tue, 1 Feb 2011 15:19:28 +0000 Subject: [PATCH 1550/2215] Adding additional points results in correct color of continuing bar --- .../Plugins/SchedulerGUISimple/main.qml | 4 +-- .../SchedulerGUISimple/schedulerscripts.js | 26 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 658afbf9..b95a17b9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -244,7 +244,7 @@ import "schedulerscripts.js" as Scripts //onExited: parent.border.color = borderColor onClicked: { print("ENDPOINT: " + deviceRow.endPoint); - /* + //print("Mainrow: " + mainRow.parent.children[0].height); var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) @@ -282,7 +282,7 @@ import "schedulerscripts.js" as Scripts */ //SLUT TEST - //dialog.show(dynamicPoint) + dialog.show(dynamicPoint) } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index ba4eda1e..961f01ac 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -247,6 +247,17 @@ function updateEndsWith(){ function assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, firstRow){ var barWidth = 0; + + if(previousEndPoint == undefined){ //the first has no point to bind to + deviceRow.continuingBar.prevDayColor = "white"; + deviceRow.continuingBar.prevDayOpacity = 0; + deviceRow.continuingBar.prevDayWidth = 0; + } + else{ + deviceRow.continuingBar.prevDayColor = previousEndPoint.actionTypeColor; + deviceRow.continuingBar.prevDayOpacity = previousEndPoint.actionTypeOpacity; + } + if(deviceRow.hasPoints()){ print("A Point!!"); //TODO barWidth here... Must depend on first point... bind... somehow... @@ -259,19 +270,8 @@ function assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, fi deviceRow.endPoint = previousEndPoint; barWidth = deviceRow.width; } - - if(!firstRow){ //all but the first (have no point to bind to) - if(previousEndPoint == undefined){ - deviceRow.continuingBar.prevDayColor = "white"; - deviceRow.continuingBar.prevDayOpacity = 0; - deviceRow.continuingBar.prevDayWidth = 0; - } - else{ - deviceRow.continuingBar.prevDayColor = previousEndPoint.actionTypeColor; - deviceRow.continuingBar.prevDayOpacity = previousEndPoint.actionTypeOpacity; - deviceRow.continuingBar.prevDayWidth = barWidth; - } - } + deviceRow.continuingBar.prevDayWidth = barWidth; + return previousEndPoint; } From b1bae4a649e9a3eaa833b727192ff7b2d9e4cb73 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 1 Feb 2011 15:59:57 +0000 Subject: [PATCH 1551/2215] Continuing bar looping all days of the week now --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 25 ++++++++++++++---- .../Plugins/SchedulerGUISimple/main.qml | 2 ++ .../SchedulerGUISimple/schedulerscripts.js | 26 +++++++++++++++---- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml index f11a4c03..71907583 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -4,13 +4,18 @@ import "schedulerscripts.js" as Scripts Rectangle{ id: barRectangle property variant hangOnToPoint - property color prevDayColor - property double prevDayOpacity - property int prevDayWidth + property color prevDayColor: "white" //default + property double prevDayOpacity: 0 //default + property int prevDayWidth: 0 //default height: constBarHeight z: 110 + color: barRectangle.prevDayColor + opacity: barRectangle.prevDayOpacity + width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before + + states: [ State{ name: "continuing" @@ -18,13 +23,23 @@ Rectangle{ target: barRectangle anchors.verticalCenter: hangOnToPoint.verticalCenter anchors.left: hangOnToPoint.left - color: barRectangle.prevDayColor + /*color: barRectangle.prevDayColor //getPreviousDayColor(barRectangle.currentDay, barRectangle.days, hangOnToPoint.deviceId, barRectangle.deviceIndex) opacity: barRectangle.prevDayOpacity width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before + */ } }, - State { + State{ + name: "continuingWithLimitedWidth" + PropertyChanges { + target: barRectangle + anchors.verticalCenter: hangOnToPoint.verticalCenter + anchors.left: hangOnToPoint.left + width: Scripts.getFirstPointWidth(hangOnToPoint) + } + }, + State{ name: "pointLoaded" //; when: hangOnToPoint != undefined && hangOnToPoint.isLoaded != undefined && hangOnToPoint.parent != null && hangOnToPoint.parent != undefined && hangOnToPoint.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning, used hangOnToPoint.isLoaded too before, remove this? PropertyChanges { target: barRectangle diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index b95a17b9..83433e9f 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -51,6 +51,7 @@ import "schedulerscripts.js" as Scripts anchors.fill: parent onClicked: { //step to prev weekday + dialog.hide() Scripts.updateEndsWith() Scripts.decrementCurrentDay() weekDayText.text = Scripts.getCurrentDayName() @@ -84,6 +85,7 @@ import "schedulerscripts.js" as Scripts anchors.fill: parent onClicked: { //step to next weekday + dialog.hide() Scripts.updateEndsWith() //mainListView) Scripts.incrementCurrentDay() weekDayText.text = Scripts.getCurrentDayName() diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 961f01ac..126a3d6a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -246,7 +246,6 @@ function updateEndsWith(){ } function assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, firstRow){ - var barWidth = 0; if(previousEndPoint == undefined){ //the first has no point to bind to deviceRow.continuingBar.prevDayColor = "white"; @@ -263,15 +262,16 @@ function assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, fi //TODO barWidth here... Must depend on first point... bind... somehow... deviceRow.endPoint = getEndsWith(deviceRow.children, days[dayIndex].daydate.getDay(), deviceRow.deviceId); previousEndPoint = deviceRow.endPoint; - barWidth = 100; + deviceRow.continuingBar.prevDayWidth = 0; + deviceRow.continuingBar.state = "continuingWithLimitedWidth"; } else{ //print("NO points"); + deviceRow.continuingBar.state = "continuing"; deviceRow.endPoint = previousEndPoint; - barWidth = deviceRow.width; + deviceRow.continuingBar.prevDayWidth = deviceRow.width; } - deviceRow.continuingBar.prevDayWidth = barWidth; - + return previousEndPoint; } @@ -324,4 +324,20 @@ function addWeekPointToGUI(point){ dynamicPoint.addState("dim"); dynamicPoint.addState("bell"); dynamicPoint.setFirstState("dim"); +} + +//TODO move, pragma safe: +function getFirstPointWidth(deviceRow){ + var pointList = deviceRow.children; + var firstX = deviceRow.width; + var pointWidth = 0; + for(var i=0;i Date: Tue, 1 Feb 2011 16:36:50 +0000 Subject: [PATCH 1552/2215] Continuing bar updated on point added, removed and state changed --- .../Plugins/SchedulerGUISimple/ActionPoint.qml | 15 ++++++++++++++- telldus-gui/Plugins/SchedulerGUISimple/main.qml | 5 +++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index a1607aa2..8b4e49a0 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -19,6 +19,7 @@ Rectangle{ property alias triggerstate: trigger.state property variant parentPoint property int parentPointAbsoluteHour: 0 + property alias deviceRow: pointRect.parent Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... @@ -85,7 +86,7 @@ Rectangle{ } onReleased: { - + pointRect.deviceRow.updateContinuingBars() dialog.show(pointRect) //TODO not pointRect, but parentPoint if such exists //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); //var hourMinute = getTimeFromPosition(rootCoordinates.x) @@ -183,21 +184,25 @@ Rectangle{ name: "on" PropertyChanges { target: pointRect; actionTypeColor: "blue"; actionTypeOpacity: 1 } PropertyChanges { target: pointRect; actionTypeImage: imageActionOn } + StateChangeScript{ name: "updateBars"; script: updateBars(); } }, State{ name: "off" PropertyChanges { target: pointRect; actionTypeColor: "gainsboro"; actionTypeOpacity: 0 } PropertyChanges { target: pointRect; actionTypeImage: imageActionOff } + StateChangeScript{ name: "updateBars"; script: updateBars(); } }, State{ name: "dim" PropertyChanges { target: pointRect; actionTypeColor: "green"; actionTypeOpacity: dimvalue/100 } PropertyChanges { target: pointRect; actionTypeImage: imageActionDim } + StateChangeScript{ name: "updateBars"; script: updateBars(); } }, State{ name: "bell" PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } PropertyChanges { target: pointRect; actionTypeImage: imageActionBell } + StateChangeScript{ name: "updateBars"; script: updateBars(); } }, State{ //TODO test name: "test"; when: pointRect.parentPoint != undefined @@ -220,6 +225,12 @@ Rectangle{ } } + function updateBars(){ + if(pointRect.deviceRow != undefined){ + pointRect.deviceRow.updateContinuingBars(); + } + } + function getAbsoluteXValue(){ if(pointRect.parent == null){ return 0; @@ -372,8 +383,10 @@ Rectangle{ var x = pointRect.x; pointRect.isPoint = "false" var pointList = pointRect.parent.children; + var deviceRow = pointRect.deviceRow; pointRect.destroy(); dialog.hide(); + deviceRow.updateContinuingBars() } function minutesToTimelineUnits(minutes){ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 83433e9f..9be298c5 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -284,6 +284,7 @@ import "schedulerscripts.js" as Scripts */ //SLUT TEST + deviceRow.updateContinuingBars(); dialog.show(dynamicPoint) } } @@ -312,6 +313,10 @@ import "schedulerscripts.js" as Scripts function hasPoints(){ return Scripts.hasPoints(deviceRow.children); } + + function updateContinuingBars(){ + Scripts.updateEndsWith(); + } } //} } From f9c9e17c399de8fbc53c086a10fc6b2b461fa67c Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 2 Feb 2011 09:38:38 +0000 Subject: [PATCH 1553/2215] Continuing bar updated with dim values --- .../Plugins/SchedulerGUISimple/ActionPoint.qml | 4 ++++ telldus-gui/Plugins/SchedulerGUISimple/main.qml | 9 --------- .../Plugins/SchedulerGUISimple/schedulerscripts.js | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 8b4e49a0..01324591 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -61,6 +61,10 @@ Rectangle{ dialog.absoluteHour = parentPointAbsoluteHour; } + onDimvalueChanged: { + updateBars(); + } + MouseArea { id: pointRectMouseArea acceptedButtons: Qt.LeftButton | Qt.RightButton diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 9be298c5..8649e331 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -296,15 +296,6 @@ import "schedulerscripts.js" as Scripts state: "continuing" } - Item{ - //TODO eller ska detta VARA början-rektanglen? - id: previousDay - states: State{ - name: "isFirst"; when: daydate > getPreviousDayDate() - PropertyChanges{ target: dayListView; endsWith: "NÅGOT" } - } - } - ListView.onAdd: SequentialAnimation { PropertyAction { target: mainRow; property: "height"; value: 0 } NumberAnimation { target: mainRow; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 126a3d6a..a330e266 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -218,7 +218,8 @@ function updateEndsWith(){ */ if(deviceRow.hasPoints()){ - print("HAS POINTS .........."); + print("Dayindex " + dayIndex + " HAS POINTS .........."); + print("Current day index: " + currentDayIndex); startIndex = dayIndex; break; } @@ -239,6 +240,7 @@ function updateEndsWith(){ if(i == days.length-1){ //last one, bind the first one too then deviceRow = days[startIndex].children[0].children[parseInt(deviceIndex[device])]; + print("In last one"); assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, false); } } @@ -253,8 +255,16 @@ function assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, fi deviceRow.continuingBar.prevDayWidth = 0; } else{ + print("Color: " + previousEndPoint.actionTypeColor); + print("Opacity: " + previousEndPoint.actionTypeOpacity); deviceRow.continuingBar.prevDayColor = previousEndPoint.actionTypeColor; - deviceRow.continuingBar.prevDayOpacity = previousEndPoint.actionTypeOpacity; + if(previousEndPoint.state == "dim"){ + deviceRow.continuingBar.prevDayOpacity = previousEndPoint.dimvalue/100; + } + else{ + deviceRow.continuingBar.prevDayOpacity = previousEndPoint.actionTypeOpacity; + } + } if(deviceRow.hasPoints()){ From 9bc2aaf90c84788fa288bdce27fb460b0bbfa77e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 2 Feb 2011 10:00:21 +0000 Subject: [PATCH 1554/2215] Continuing bar ignores bell --- telldus-gui/Plugins/SchedulerGUISimple/main.qml | 2 +- telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 8649e331..752e5cd9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -302,7 +302,7 @@ import "schedulerscripts.js" as Scripts } function hasPoints(){ - return Scripts.hasPoints(deviceRow.children); + return Scripts.hasBarChangingPoints(deviceRow.children); } function updateContinuingBars(){ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index a330e266..d8df81a5 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -80,10 +80,10 @@ function getBarWidth(currentBar, currentPointRect, pointList){ return (nextX - currentPointRect.x); } -function hasPoints(pointList){ +function hasBarChangingPoints(pointList){ for(var i=0;i Date: Wed, 2 Feb 2011 15:29:56 +0000 Subject: [PATCH 1555/2215] Correct initial state on added points --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 5 +- .../SchedulerGUISimple/ActionPoint.qml | 5 +- .../Plugins/SchedulerGUISimple/main.qml | 15 +++- .../SchedulerGUISimple/schedulerscripts.js | 72 +++++++++++++------ 4 files changed, 69 insertions(+), 28 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml index 71907583..0be54a2e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -7,6 +7,7 @@ Rectangle{ property color prevDayColor: "white" //default property double prevDayOpacity: 0 //default property int prevDayWidth: 0 //default + property string firstBar: "false" height: constBarHeight z: 110 @@ -26,7 +27,7 @@ Rectangle{ /*color: barRectangle.prevDayColor //getPreviousDayColor(barRectangle.currentDay, barRectangle.days, hangOnToPoint.deviceId, barRectangle.deviceIndex) opacity: barRectangle.prevDayOpacity - width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before + width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); */ } }, @@ -47,7 +48,7 @@ Rectangle{ anchors.left: hangOnToPoint.horizontalCenter color: hangOnToPoint.actionTypeColor opacity: hangOnToPoint.actionTypeOpacity - width: Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children) //TEST getNextAndPrevBarWidth before + width: Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children) } } ] diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 01324591..f8eeb287 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -337,11 +337,13 @@ Rectangle{ } function addState(state){ + print("Adding state: " + state); Scripts.addState(state); } function setFirstState(firstState){ + //print("SETTING FIRST STATE"); var activeStates = Scripts.getActiveStates(); if(activeStates == null || activeStates.length == 0){ @@ -366,12 +368,13 @@ Rectangle{ if(!exists){ //no "off", just set state to the first added state + pointRect.state = activeStates[0]; return; } var previousState = Scripts.getPreviousState(pointRect); - if(previousState == "" || previousState == "off"){ + if(previousState == undefined || previousState == "" || previousState == "off"){ //nothing on/dimmed at the moment, use first added state pointRect.state = activeStates[0]; return; diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 752e5cd9..542b5e46 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -182,6 +182,11 @@ import "schedulerscripts.js" as Scripts } ] + onChildrenChanged: { + //TODO REMOVE + print("-------------- CHILDREN CHANGED ----------------"); + } + transitions: [ Transition { from: "hiddenLeft" @@ -245,8 +250,8 @@ import "schedulerscripts.js" as Scripts //onEntered: parent.border.color = onHoverColor //onExited: parent.border.color = borderColor onClicked: { - print("ENDPOINT: " + deviceRow.endPoint); - + //Scripts.debugPrintDeviceIndex(); + Scripts.updateDeviceIndex(); //TODO why is this needed here? (but it is, adding points to empty device will get wrong state otherwise) //print("Mainrow: " + mainRow.parent.children[0].height); var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) @@ -292,6 +297,7 @@ import "schedulerscripts.js" as Scripts ActionBar{ id: "continuingBar" hangOnToPoint: deviceRow + firstBar: "true" state: "continuing" } @@ -308,6 +314,11 @@ import "schedulerscripts.js" as Scripts function updateContinuingBars(){ Scripts.updateEndsWith(); } + + function getDeviceRow(dayIndex, deviceId){ + print("CALLING getDeviceRow"); + return Scripts.getDeviceRow(dayIndex, deviceId); + } } //} } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index d8df81a5..03ec1a2e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -91,8 +91,8 @@ function hasBarChangingPoints(pointList){ } function getEndsWith(pointList, dayIndex, deviceId){ //previousDayEndsWithPoint){ - print("DAY INDEX: " + dayIndex); - print("DEVICEID: " + deviceId); + //print("DAY INDEX: " + dayIndex); + //print("DEVICEID: " + deviceId); var prevPoint = null; for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic prevPoint = pointList[i]; } } + else if(pointList[i].firstBar != undefined && pointList[i].firstBar == "true"){ + firstBarStateIndex = i; + } } if(prevPoint == null){ + //no previous point,see if state continues from previous day + if(firstBarStateIndex != undefined && pointList[firstBarStateIndex].firstBar != undefined){ + //print("ENDPOINT!!"); + + var dayIndex = currentDayIndex - 1; + if(dayIndex == -1){ //too far, begin from end again + dayIndex = days.length - 1; + } + //print("CORRECT DEVICE ID? : " + currentPointRect.deviceRow.deviceId); + var prevDayDevice = currentPointRect.parent.getDeviceRow(dayIndex, currentPointRect.deviceRow.deviceId); + if(prevDayDevice != undefined){ + //print("Setting end point: ** " + prevDayDevice.endPoint); + return prevDayDevice.endPoint; + } + } + return ""; } - return prevPoint.state; } @@ -184,17 +203,27 @@ function updateDeviceIndex(){ //TODO, better way, please... for(var i=0;i Date: Thu, 3 Feb 2011 09:22:22 +0000 Subject: [PATCH 1556/2215] Corrected which day stored points are inserted. Proof of concept for disabled schedule for devices --- .../Plugins/SchedulerGUISimple/__init__.js | 4 ++- .../Plugins/SchedulerGUISimple/main.qml | 32 +++++++++++++++++++ .../SchedulerGUISimple/schedulerscripts.js | 28 ++++++++++++++-- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index cc74318b..5d4128aa 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -19,7 +19,9 @@ com.telldus.schedulersimplegui = function() { deviceList = new com.telldus.qml.array(); var list = com.telldus.core.deviceList.getList(); for(var i=0; i < list.length; ++i) { - deviceList.push(list[i]); + var item = list[i]; + item.isEnabled = "enabled"; + deviceList.push(item); } view.setProperty('deviceModel', deviceList); //set images: diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 542b5e46..0eef4626 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -122,13 +122,33 @@ import "schedulerscripts.js" as Scripts model: deviceModel Rectangle{ + id: deviceNameRect + property string isEnabled: modelData.isEnabled width: parent.width height: constDeviceRowHeight border.color: "green" Text{ + id: "deviceNameText" anchors.centerIn: parent text: modelData.name } + Rectangle{ + width: 10 + height: 10 + anchors.top: deviceNameText.bottom + anchors.horizontalCenter: parent.horizontalCenter + color: deviceNameRect.isEnabled == "enabled" ? "red" : "blue" //TODO use same as in script? + MouseArea{ + anchors.fill: parent + onClicked: { + //TODO implement setProperty if this is to be stored... or do something else... modelData.setProperty(index, isEnabled, modelData.isEnabled == "enabled" ? "disabled" : "enabled"); + //TODO also implement disabled/enabled for all (deviceEnabled=false on all) and per point (set isPoint=false and opacity=0.4)... + //take that value into consideration when saving and sending jobs for execution + deviceNameRect.isEnabled = deviceNameRect.isEnabled == "enabled" ? "disabled" : "enabled" + Scripts.deviceEnabled(modelData.id, deviceNameRect.isEnabled); + } + } + } } } } @@ -240,7 +260,19 @@ import "schedulerscripts.js" as Scripts property variant endPoint: undefined //: Scripts.getEndsWith(deviceRow.children, index, modelData.id); property int deviceId: modelData.id; property alias continuingBar: continuingBar + state: "enabled" + states: [ + State{ + name: "enabled" + PropertyChanges{ target: deviceRow; opacity: 1 } + }, + State{ + name: "disabled" + PropertyChanges{ target: deviceRow; opacity: 0.4 } + } + ] + MouseArea { id: deviceMouseArea anchors.fill: parent diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 03ec1a2e..2da72ec2 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -204,6 +204,11 @@ function updateDeviceIndex(){ //TODO, better way, please... deviceIndex[deviceModel.get(i).id] = i + startIndex; } //TODO !!!!!! are devices reordered sometimes? Or even different for different days? Check that! + //Kan det vara så här: + // days[0].children[0].children består av alla delegat-element, plus header och footer + //header, footer och delegaternas ordning kan skifta, men delegaternas interna ordning är (FÖRHOPPNINGSVIS!) alltid samma + //och samma som i modellen: Delegaternas börjar antingen på 0 (delegater, header, footer eller delegater, footer, header) + //eller 1 (header/footer, delegater, header/footer) eller 2 (header/footer, header/footer, delegater) } function debugPrintDeviceIndex(){ @@ -315,7 +320,7 @@ function initiatePointsInGUI(){ //weekPointList){ //weekPointList -> från __init__.js var weekPointList = new Array(); var dummypoint = [] - dummypoint["day"] = 5; + dummypoint["day"] = 0; dummypoint["deviceId"] = 1; weekPointList.push(dummypoint); for(var i=0;i days.length-1){ + dayOfWeek = dayOfWeek - days.length; + } + print("Inserting point at: " + weekday_name_array[days[dayOfWeek].daydate.getDay()]); var pointParent = getDeviceRow(dayOfWeek, deviceId); var component = Qt.createComponent("ActionPoint.qml") @@ -374,4 +388,12 @@ function getFirstPointWidth(deviceRow){ } } return firstX + pointWidth/2; +} + +function deviceEnabled(deviceId, enabled){ + updateDeviceIndex(); //TODO make this unnessessary + for(var i=0;i Date: Thu, 3 Feb 2011 15:23:16 +0000 Subject: [PATCH 1557/2215] Updated png icon for TelldusCenter --- .../images/TelldusCenter_128.png | Bin 11651 -> 6974 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/telldus-gui/TelldusCenter/images/TelldusCenter_128.png b/telldus-gui/TelldusCenter/images/TelldusCenter_128.png index 7b001d243fabdce6e03a686da5271bd85dd7bcc7..fd8dc13bf64c39ffd01362fd0cbbfec38fc8a6c3 100644 GIT binary patch literal 6974 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 QlmGw#07*qoM6N<$f&q_8g8%>k literal 11651 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 N002ovPDHLkV1mDXB3b|d From a81cd9370a536498c3db71d5f6dc5d5b91b8883d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 4 Feb 2011 09:32:33 +0000 Subject: [PATCH 1558/2215] Implemented basic functions for adding point to additional weekdays --- .../SchedulerGUISimple/ActionPoint.qml | 98 ++++++++++++++++-- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 3 + .../Plugins/SchedulerGUISimple/Dialog.qml | 63 ++++++++++- .../SchedulerGUISimple/alwaysticked.png | Bin 0 -> 193 bytes .../Plugins/SchedulerGUISimple/main.qml | 14 +-- .../SchedulerGUISimple/schedulerscripts.js | 41 ++++++-- .../Plugins/SchedulerGUISimple/ticked.png | Bin 0 -> 215 bytes .../Plugins/SchedulerGUISimple/unticked.png | Bin 0 -> 179 bytes 8 files changed, 193 insertions(+), 26 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/alwaysticked.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/ticked.png create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/unticked.png diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index f8eeb287..68eda0a6 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -18,7 +18,8 @@ Rectangle{ property int absoluteMinute: parseInt(dialog.absoluteMinute, 10) property alias triggerstate: trigger.state property variant parentPoint - property int parentPointAbsoluteHour: 0 + property int parentPointAbsoluteHour //TEST changed from int, want "undefined" + property variant childPoints: [] property alias deviceRow: pointRect.parent Component.onCompleted: { @@ -55,12 +56,28 @@ Rectangle{ } */ - onParentPointAbsoluteHourChanged: { - print("Nja"); - //pointRect.absoluteHour = parentPoint.absolutHour - dialog.absoluteHour = parentPointAbsoluteHour; + onAbsoluteHourChanged: { + print("ABSOLUTE HOUR CHANGED"); //TEST NYTT TEST + pointRect.x = getAbsoluteXValue(); } + /* + onParentPointAbsoluteHourChanged: { + //pointRect.absoluteHour = parentPoint.absolutHour + print("IN ABSOLUTEHOURCHANGED..."); + if(parentPoint == undefined){ //TODO this is not correct, must remove, but... + print("PP UNDEFINED!"); //Should never happen + dialog.absoluteHour = absoluteHour; //this is needed for update + print("Absolute hour changed from " + dialog.absoluteHour + " to " + absoluteHour); + } + else if(parentPointAbsoluteHour != undefined){ + print("PPABSOLUTE HOUR NOT UNDEFINED!"); + dialog.absoluteHour = parentPointAbsoluteHour; //this is needed for update + print("Absolute hour changed from " + dialog.absoluteHour + " to " + parentPointAbsoluteHour); + } + } + */ + onDimvalueChanged: { updateBars(); } @@ -83,6 +100,7 @@ Rectangle{ //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); var hourMinute = getTimeFromPosition(rootCoordinates.x - mouse.x + pointRect.width/2) + print("Position changed reporting in"); if((hourMinute[0] >= 0) && hourMinute[0] < 24){ pointRect.absoluteHour = hourMinute[0] pointRect.absoluteMinute = hourMinute[1] @@ -94,12 +112,14 @@ Rectangle{ dialog.show(pointRect) //TODO not pointRect, but parentPoint if such exists //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); //var hourMinute = getTimeFromPosition(rootCoordinates.x) + print("Released reporting in"); dialog.absoluteHour = Scripts.pad(pointRect.absoluteHour, 2) //Scripts.pad(hourMinute[0], 2) dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) //Scripts.pad(hourMinute[1], 2) print("TESTAR!!! " + parentPoint); if(parentPoint != undefined){ - parentPoint.absoluteHour = dialog.absoluteHour; + print("Not undefined reporting in"); + parentPoint.absoluteHour = parseInt(dialog.absoluteHour, 10); } } @@ -117,6 +137,19 @@ Rectangle{ PropertyChanges { target: pointRect; opacity: 0.5; } } } + /* + ListModel{ + id: daysOfWeek + ListElement{ + name: "on" + imagesource: "on.png" //TODO cannot use javascript properties here... do in some other way, maybe a list with names here? + } + ListElement{ + name: "off" + imagesource: "off.png" + } + } + */ Column{ spacing: 10 @@ -207,11 +240,14 @@ Rectangle{ PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } PropertyChanges { target: pointRect; actionTypeImage: imageActionBell } StateChangeScript{ name: "updateBars"; script: updateBars(); } - }, + }//, + /* State{ //TODO test - name: "test"; when: pointRect.parentPoint != undefined + name: "test"; when: pointRect.parentPoint != undefined //&& pointRect.parentPoint.absoluteHour != undefined + StateChangeScript{ name: "updateBars"; script: print("CHANGED TO TEST, " + pointRect.parentPoint.absoluteHour); } PropertyChanges{ target: pointRect; parentPointAbsoluteHour: pointRect.parentPoint.absoluteHour } } + */ ] Rectangle{ @@ -245,6 +281,9 @@ Rectangle{ print("Different x"); point = pointRect.parentPoint; } + //TODO point.width är (ofta/alltid?) 0 här) + print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); + print("AbsoluteHour: " +point.absoluteHour+ " hourSize: " + hourSize + " AbsoluteMinute: " + point.absoluteMinute + " Width: " + point.width); return point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2; } @@ -337,7 +376,7 @@ Rectangle{ } function addState(state){ - print("Adding state: " + state); + //print("Adding state: " + state); Scripts.addState(state); } @@ -402,4 +441,45 @@ Rectangle{ } return pointRect.parent.width/24 * (minutes/60); } + + function getTickedImageSource(index){ + //3 fall + //alwaysticked, unticked, ticked + if(pointRect.deviceRow.parent == undefined || pointRect.deviceRow.parent.parent == undefined){ //to get rid of warnings on initialization + return ""; + } + var originalDay = pointRect.deviceRow.parent.parent.daydate.getDay(); + if(pointRect.parentPoint != undefined){ + originalDay = pointRect.parentPoint.deviceRow.parent.parent.daydate.getDay(); + } + if(index == originalDay){ //TODO change, must be stored with the point insted, it's "original day" (if clicked on on another day for instance) + //current day (where the point was originally placed) should always be ticked + return "alwaysticked.png"; + } + else if(pointRect.childPoints[index] == undefined){ + return "unticked.png"; + } + else{ + return "ticked.png"; + } + } + + function toggleTickedWeekDay(index){ + var originalPointDay = pointRect.deviceRow.parent.parent.daydate.getDay(); //TODO change, must be stored with the point insted, it's "original day" (if clicked on on another day for instance) + if(pointRect.parentPoint != undefined){ + originalPointDay = pointRect.parentPoint.deviceRow.parent.parent.daydate.getDay(); + } + if(index == originalPointDay){ + //cannot change this, do nothing + return; + } + if(pointRect.childPoints[index] == undefined){ + print("CREATE NEW POINT"); + pointRect.childPoints = deviceRow.createChildPoint(index, pointRect, deviceRow.deviceId); + } + else{ + print("REMOVE A POINT"); + pointRect.childPoints[index].remove(); + } + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 6f1d9698..0da7b175 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -22,6 +22,9 @@ SET( Plugin_EXTRA bell.png info.png fuzzy.png + ticked.png + unticked.png + alwaysticked.png ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 0d41b24c..e63c1349 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -431,7 +431,11 @@ event.accepted = true; inputAbsoluteMinuteText.focus = true; } - text: "0" + //text: "0" + //onChanged:{ + // print("DIALOG HOUR CHANGED"); + //} + } Binding { @@ -564,11 +568,64 @@ } } + Rectangle{ + id: weekDayPanel + anchors.left: currentType.left + anchors.top: currentType.bottom + anchors.topMargin: 40 + height: weekColumn.height + width: weekColumn.width + Column{ + id: "weekColumn" + //anchors.verticalCenter: parent.verticalCenter + //anchors.fill: parent + spacing: 2 + Repeater{ + id: weekRepeater + model: 7 //actionPoint.daysOfWeek + //delegate: weekDayDelegate + Rectangle{ + width: 30 + height: 30 + Image{ + id: tickBox + height: 14 + width: 14 + source: actionPoint.getTickedImageSource(index) + MouseArea{ + anchors.fill: parent + onClicked: { + actionPoint.toggleTickedWeekDay(index) + } + } + } + Text{ + //anchors.fill: parent + anchors.left: tickBox.right + anchors.leftMargin: 10 + text: Scripts.weekday_name_array[index] //TODO start on monday + } + } + } + } + } + + Component{ + id: weekDayDelegate + Rectangle{ + width: 10 + height: 20 + color: "red" + } + } + Button{ id: closeButton text: "Close" - y: circleTrigger.y + 30 - x: parent.x + 30 + anchors.top: weekDayPanel.bottom + anchors.horizontalCenter: weekDayPanel.right //horizontalCenter + //y: circleTrigger.y + 30 + //x: parent.x + 30 onClicked: { hide(); } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/alwaysticked.png b/telldus-gui/Plugins/SchedulerGUISimple/alwaysticked.png new file mode 100644 index 0000000000000000000000000000000000000000..3a29be36d5a41597892b10a01dc8a84df5596730 GIT binary patch literal 193 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#Ihk44ofy`glX(f`a29w(7Bet# z3xhBt!>lS|xv6<249-QVi6yBi3gww4 z84B*6z5(HleBwYwdY&$hArhC96Bck*e0w9w%*-q-XUW3e+OO7o%ze7EnA7BB7vZUs gCM7Ankx^n~*zGL)<8{`P2|%3;p00i_>zopr0L)=A`v3p{ literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 0eef4626..dcabd13c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -351,6 +351,11 @@ import "schedulerscripts.js" as Scripts print("CALLING getDeviceRow"); return Scripts.getDeviceRow(dayIndex, deviceId); } + + function createChildPoint(index, pointRect, deviceId){ + print("CREATING child point"); + return Scripts.createChildPoint(index, pointRect, deviceId); + } } //} } @@ -406,6 +411,7 @@ import "schedulerscripts.js" as Scripts } } + /* Not in use, adding all devices always instead Component{ id: addButtonComponent Row { @@ -439,7 +445,8 @@ import "schedulerscripts.js" as Scripts } } } - + */ + Dialog { id: dialog z: 150 @@ -509,9 +516,4 @@ import "schedulerscripts.js" as Scripts var hourSize = constDeviceRowWidth/24; //(main.width - 100)/24; //TODO constant or something? return hourSize * suntime[0] + hourSize * suntime[1]/60; } - //opacity vid dimning? - //linjens färg etc (state) beror ju på närmaste punkt föres sort... Punkten kan finnas osynlig (tidigare dag) också... - //kan man liksom göra hela linjen (från en vecka tillbaka) men inte visa den? Om det är vettigt... Då hade man tom kunnat zooma en vacker dag - //properties, ställa in dem... - //fuzziness } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 2da72ec2..247d944a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -350,14 +350,7 @@ function addWeekPointToGUI(point){ var deviceId = point.deviceId; var dayOfWeek = point.day; //set dayOfWeek to correct index in the days-table - var offset = days[0].daydate.getDay(); - dayOfWeek = days.length - offset + dayOfWeek; - if(dayOfWeek == -1){ - dayOfWeek = days.length - 1; - } - if(dayOfWeek > days.length-1){ - dayOfWeek = dayOfWeek - days.length; - } + dayOfWeek = getDayIndexForDayOfWeek(dayOfWeek); print("Inserting point at: " + weekday_name_array[days[dayOfWeek].daydate.getDay()]); var pointParent = getDeviceRow(dayOfWeek, deviceId); @@ -374,6 +367,19 @@ function addWeekPointToGUI(point){ dynamicPoint.setFirstState("dim"); } +//must be run in "main" +function getDayIndexForDayOfWeek(dayOfWeek){ + var offset = days[0].daydate.getDay(); + dayOfWeek = days.length - offset + dayOfWeek; + if(dayOfWeek == -1){ + dayOfWeek = days.length - 1; + } + if(dayOfWeek > days.length-1){ + dayOfWeek = dayOfWeek - days.length; + } + return dayOfWeek; +} + //TODO move, pragma safe: function getFirstPointWidth(deviceRow){ var pointList = deviceRow.children; @@ -396,4 +402,23 @@ function deviceEnabled(deviceId, enabled){ var deviceRow = days[i].children[0].children[deviceIndex[deviceId]]; deviceRow.state = enabled; //TODO connect directly instead... if possible } +} + +function createChildPoint(index, pointRect, deviceId){ + index = getDayIndexForDayOfWeek(index); + var deviceRow = getDeviceRow(index, deviceId); //TODO correct index? + var component = Qt.createComponent("ActionPoint.qml") + var dynamicPoint = component.createObject(deviceRow) + dynamicPoint.absoluteHour = pointRect.absoluteHour + print("The absolute hour is: " + pointRect.absoluteHour); + dynamicPoint.absoluteMinute = 30 //TODO + dynamicPoint.parentPoint = pointRect + dynamicPoint.x = dynamicPoint.getAbsoluteXValue(); + dynamicPoint.border.color = "blue" + dynamicPoint.addState("on"); //TODO, add same states as in pointRect + dynamicPoint.addState("off"); + dynamicPoint.addState("dim"); + dynamicPoint.addState("bell"); + dynamicPoint.setFirstState(pointRect.state); + return dynamicPoint; } \ No newline at end of file diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ticked.png b/telldus-gui/Plugins/SchedulerGUISimple/ticked.png new file mode 100644 index 0000000000000000000000000000000000000000..0ba262a2dadc71e612d9892c43f0c21082ed936a GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V6Od#Ihk44ofy`glX(f`a29w(7Bet# z3xhBt!>lS|xv6<249-QVi6yBi3gww4 z84B*6z5(HleBwYwE}kxqArhBs`w#LmC~z=mKNi{kKj+LtXXl=-zm5y1d&Qf23V!^; z5MJM)Qokpa*>btsMRVyBz3*@Q-6g+A`K0yAtcWZIO?3&OM~xxsK=T+pUHx3vIVCg! E0IFak44ofy`glX(f`a29w(7Bet# z3xhBt!>lbCYGe8D3oWG zWGJ|M`UZqI@`(c#DR{a#hDcmaPB_3VAt@m-&$hZP)X&SSi*x_Gh1$MA1(r*g1zopr0D`$JPXGV_ literal 0 HcmV?d00001 From 3dbcf5f331dc5c7d5019e2e5d1981402ec690434 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 4 Feb 2011 13:25:59 +0000 Subject: [PATCH 1559/2215] Checkboxes updated (correctly?) when adding points to additional weekdays --- .../SchedulerGUISimple/ActionPoint.qml | 43 ++++++++++++------- .../Plugins/SchedulerGUISimple/Dialog.qml | 5 +++ .../SchedulerGUISimple/schedulerscripts.js | 26 ++++++++++- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 68eda0a6..283f41b2 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -19,7 +19,6 @@ Rectangle{ property alias triggerstate: trigger.state property variant parentPoint property int parentPointAbsoluteHour //TEST changed from int, want "undefined" - property variant childPoints: [] property alias deviceRow: pointRect.parent Component.onCompleted: { @@ -422,7 +421,7 @@ Rectangle{ pointRect.state = "off"; //previous point should be "on" or "dim" } - function remove(){ + function remove(keepDialogOpen){ if(pointRect.hangOnToBar != null){ hangOnToBar.destroy(); } @@ -431,7 +430,9 @@ Rectangle{ var pointList = pointRect.parent.children; var deviceRow = pointRect.deviceRow; pointRect.destroy(); - dialog.hide(); + if(keepDialogOpen == undefined){ + dialog.hide(); + } deviceRow.updateContinuingBars() } @@ -443,20 +444,19 @@ Rectangle{ } function getTickedImageSource(index){ - //3 fall - //alwaysticked, unticked, ticked if(pointRect.deviceRow.parent == undefined || pointRect.deviceRow.parent.parent == undefined){ //to get rid of warnings on initialization - return ""; + print("UNDEFINED, should only be in beginning"); + return "unticked.png"; } - var originalDay = pointRect.deviceRow.parent.parent.daydate.getDay(); + var originalPoint = pointRect; // pointRect.deviceRow.parent.parent; if(pointRect.parentPoint != undefined){ - originalDay = pointRect.parentPoint.deviceRow.parent.parent.daydate.getDay(); + originalPoint = pointRect.parentPoint; //.deviceRow.parent.parent; } - if(index == originalDay){ //TODO change, must be stored with the point insted, it's "original day" (if clicked on on another day for instance) + if(index == originalPoint.deviceRow.parent.parent.daydate.getDay()){ //TODO property or so //current day (where the point was originally placed) should always be ticked return "alwaysticked.png"; } - else if(pointRect.childPoints[index] == undefined){ + else if(originalPoint.getChildPoint(index) == undefined){ return "unticked.png"; } else{ @@ -465,21 +465,32 @@ Rectangle{ } function toggleTickedWeekDay(index){ - var originalPointDay = pointRect.deviceRow.parent.parent.daydate.getDay(); //TODO change, must be stored with the point insted, it's "original day" (if clicked on on another day for instance) + var originalPoint = pointRect; if(pointRect.parentPoint != undefined){ - originalPointDay = pointRect.parentPoint.deviceRow.parent.parent.daydate.getDay(); + originalPoint = pointRect.parentPoint; } - if(index == originalPointDay){ + if(index == originalPoint.deviceRow.parent.parent.daydate.getDay()){ //cannot change this, do nothing return; } - if(pointRect.childPoints[index] == undefined){ + if(originalPoint.getChildPoint(index) == undefined){ print("CREATE NEW POINT"); - pointRect.childPoints = deviceRow.createChildPoint(index, pointRect, deviceRow.deviceId); + originalPoint.addChildPoint(index, deviceRow.createChildPoint(index, pointRect, deviceRow.deviceId)); } else{ print("REMOVE A POINT"); - pointRect.childPoints[index].remove(); + originalPoint.removeChildPoint(index); } } + + function getChildPoint(index){ + return Scripts.getChildPoint(index); + } + + function addChildPoint(index, point){ + Scripts.addChildPoint(index, point); + } + function removeChildPoint(index){ + Scripts.removeChildPoint(index); + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index e63c1349..391be3f2 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -589,6 +589,10 @@ height: 30 Image{ id: tickBox + property int dialogOpacity: container.opacity + onDialogOpacityChanged: { + tickBox.source = actionPoint.getTickedImageSource(index) + } height: 14 width: 14 source: actionPoint.getTickedImageSource(index) @@ -596,6 +600,7 @@ anchors.fill: parent onClicked: { actionPoint.toggleTickedWeekDay(index) + tickBox.source = actionPoint.getTickedImageSource(index) } } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 247d944a..5e63a90a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -367,6 +367,29 @@ function addWeekPointToGUI(point){ dynamicPoint.setFirstState("dim"); } +//per point +var childPoints = []; + +function getChildPoint(index){ + //print("INDEX"); + //print(index + ": " + childPoints[index]); + return childPoints[index]; +} + +function addChildPoint(index, point){ + childPoints[index] = point; +} + +function removeChildPoint(index){ + print("INDEX BEFORE REMOVE: " + childPoints[index]); + var test = childPoints[index]; + childPoints[index] = undefined; + test.remove("true"); + print("INDEX AFTER REMOVE: " + childPoints[index]); +} + +//end per point + //must be run in "main" function getDayIndexForDayOfWeek(dayOfWeek){ var offset = days[0].daydate.getDay(); @@ -382,7 +405,7 @@ function getDayIndexForDayOfWeek(dayOfWeek){ //TODO move, pragma safe: function getFirstPointWidth(deviceRow){ - var pointList = deviceRow.children; + var pointList = deviceRow.children; //TODO should really try to avoid using "children"... make own list instead? var firstX = deviceRow.width; var pointWidth = 0; for(var i=0;i Date: Fri, 4 Feb 2011 16:00:16 +0000 Subject: [PATCH 1560/2215] Added qmldir file --- telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt | 1 + telldus-gui/Plugins/SchedulerGUISimple/qmldir | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/qmldir diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 0da7b175..7f70b17e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -25,6 +25,7 @@ SET( Plugin_EXTRA ticked.png unticked.png alwaysticked.png + qmldir ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/qmldir b/telldus-gui/Plugins/SchedulerGUISimple/qmldir new file mode 100644 index 00000000..bcfa10af --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/qmldir @@ -0,0 +1,4 @@ +ActionBar 1.0 ActionBar.qml +ActionPoint 1.0 ActionPoint.qml +Button 1.0 Button.qml +Dialog 1.0 Dialog.qml \ No newline at end of file From e093f97f537729a2518cc903e7d8201c6c3a36ee Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Feb 2011 16:00:43 +0000 Subject: [PATCH 1561/2215] Fixed Plugin_EXTRA variable --- telldus-gui/Plugins/Scheduler/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/CMakeLists.txt b/telldus-gui/Plugins/Scheduler/CMakeLists.txt index 02fb0d24..80f57939 100644 --- a/telldus-gui/Plugins/Scheduler/CMakeLists.txt +++ b/telldus-gui/Plugins/Scheduler/CMakeLists.txt @@ -5,7 +5,9 @@ SET(REQUIRE_PLUGIN_SUNCALCULATOR TRUE PARENT_SCOPE) SET( Plugin_NAME "scheduler" ) SET( Plugin_PATH "com.telldus.scheduler" ) -SET( Plugin_EXTRA "DaylightSavingTime.js") -SET( Plugin_EXTRA "DefaultJobTypes.js") +SET( Plugin_EXTRA + "DaylightSavingTime.js" + "DefaultJobTypes.js" + ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) From d539461b8450a4e34081ee1fcef8c6f208c5b178 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 4 Feb 2011 16:19:45 +0000 Subject: [PATCH 1562/2215] Original point can now be removed from additional weekday-points --- .../SchedulerGUISimple/ActionPoint.qml | 37 +++++++++++++------ .../Plugins/SchedulerGUISimple/Dialog.qml | 1 + .../SchedulerGUISimple/schedulerscripts.js | 32 ++++++++++++++-- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 283f41b2..e2c27b1d 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -111,11 +111,10 @@ Rectangle{ dialog.show(pointRect) //TODO not pointRect, but parentPoint if such exists //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); //var hourMinute = getTimeFromPosition(rootCoordinates.x) - print("Released reporting in"); + //print("Released reporting in"); dialog.absoluteHour = Scripts.pad(pointRect.absoluteHour, 2) //Scripts.pad(hourMinute[0], 2) dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) //Scripts.pad(hourMinute[1], 2) - print("TESTAR!!! " + parentPoint); if(parentPoint != undefined){ print("Not undefined reporting in"); parentPoint.absoluteHour = parseInt(dialog.absoluteHour, 10); @@ -277,12 +276,11 @@ Rectangle{ var hourSize = pointRect.parent.width / 24; var point = pointRect; if(pointRect.parentPoint != undefined){ - print("Different x"); + //print("Different x"); point = pointRect.parentPoint; } - //TODO point.width är (ofta/alltid?) 0 här) - print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); - print("AbsoluteHour: " +point.absoluteHour+ " hourSize: " + hourSize + " AbsoluteMinute: " + point.absoluteMinute + " Width: " + point.width); + //print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); + //print("AbsoluteHour: " +point.absoluteHour+ " hourSize: " + hourSize + " AbsoluteMinute: " + point.absoluteMinute + " Width: " + point.width); return point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2; } @@ -422,6 +420,7 @@ Rectangle{ } function remove(keepDialogOpen){ + //TODO Check if point has children, remove them too in that case! if(pointRect.hangOnToBar != null){ hangOnToBar.destroy(); } @@ -444,6 +443,7 @@ Rectangle{ } function getTickedImageSource(index){ + print("GETTING TICKED"); if(pointRect.deviceRow.parent == undefined || pointRect.deviceRow.parent.parent == undefined){ //to get rid of warnings on initialization print("UNDEFINED, should only be in beginning"); return "unticked.png"; @@ -452,14 +452,15 @@ Rectangle{ if(pointRect.parentPoint != undefined){ originalPoint = pointRect.parentPoint; //.deviceRow.parent.parent; } - if(index == originalPoint.deviceRow.parent.parent.daydate.getDay()){ //TODO property or so - //current day (where the point was originally placed) should always be ticked + if(index == pointRect.deviceRow.parent.parent.daydate.getDay()){ //TODO property or so + //current day should always be ticked return "alwaysticked.png"; } - else if(originalPoint.getChildPoint(index) == undefined){ + else if(originalPoint.getChildPoint(index) == undefined && index != originalPoint.deviceRow.parent.parent.daydate.getDay()){ //TODO turn this parent-parent into a property return "unticked.png"; } else{ + print("Well, index? " + index + " or index: " + originalPoint.deviceRow.parent.parent.daydate.getDay()); return "ticked.png"; } } @@ -469,11 +470,15 @@ Rectangle{ if(pointRect.parentPoint != undefined){ originalPoint = pointRect.parentPoint; } - if(index == originalPoint.deviceRow.parent.parent.daydate.getDay()){ + if(index == pointRect.deviceRow.parent.parent.daydate.getDay()){ //cannot change this, do nothing return; } - if(originalPoint.getChildPoint(index) == undefined){ + if(index == originalPoint.deviceRow.parent.parent.daydate.getDay()){ + //trying to remove the parentPoint, special removal procedure needed + originalPoint.removeParentPoint(pointRect); + } + else if(originalPoint.getChildPoint(index) == undefined){ print("CREATE NEW POINT"); originalPoint.addChildPoint(index, deviceRow.createChildPoint(index, pointRect, deviceRow.deviceId)); } @@ -486,11 +491,19 @@ Rectangle{ function getChildPoint(index){ return Scripts.getChildPoint(index); } - + function getChildPoints(){ + return Scripts.getChildPoints(); + } function addChildPoint(index, point){ Scripts.addChildPoint(index, point); } function removeChildPoint(index){ Scripts.removeChildPoint(index); } + function removeParentPoint(newParentPoint){ + Scripts.removeParentPoint(newParentPoint); + } + function setChildPoints(childPoints){ + Scripts.setChildPoints(childPoints); + } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 391be3f2..6f3a6743 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -600,6 +600,7 @@ anchors.fill: parent onClicked: { actionPoint.toggleTickedWeekDay(index) + print("Just toggled, now update image: " + actionPoint); tickBox.source = actionPoint.getTickedImageSource(index) } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 5e63a90a..96d4e44f 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -376,18 +376,42 @@ function getChildPoint(index){ return childPoints[index]; } +function getChildPoints(){ + return childPoints; +} + function addChildPoint(index, point){ childPoints[index] = point; } function removeChildPoint(index){ print("INDEX BEFORE REMOVE: " + childPoints[index]); - var test = childPoints[index]; + var toBeRemoved = childPoints[index]; childPoints[index] = undefined; - test.remove("true"); + toBeRemoved.remove("true"); print("INDEX AFTER REMOVE: " + childPoints[index]); } +function removeParentPoint(newParentPoint){ + print("Removing parent point..."); + newParentPoint.setChildPoints(childPoints); //copy child list to current child (making it a parent) + newParentPoint.parentPoint = undefined; + childPoints[newParentPoint.deviceRow.parent.parent.daydate.getDay()] = undefined; //remove the current point from the child list + updateParentsInChildList(newParentPoint); //update all other child points (if any) with the current point as their parent + pointRect.remove("true"); +} + +function setChildPoints(newChildPoints){ + childPoints = newChildPoints; +} + +function updateParentsInChildList(newParentPoint){ + var children = newParentPoint.getChildPoints() + for(var point in children){ + point.pointParent = newParentPoint; + } +} + //end per point //must be run in "main" @@ -433,7 +457,7 @@ function createChildPoint(index, pointRect, deviceId){ var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) dynamicPoint.absoluteHour = pointRect.absoluteHour - print("The absolute hour is: " + pointRect.absoluteHour); + //print("The absolute hour is: " + pointRect.absoluteHour); dynamicPoint.absoluteMinute = 30 //TODO dynamicPoint.parentPoint = pointRect dynamicPoint.x = dynamicPoint.getAbsoluteXValue(); @@ -443,6 +467,6 @@ function createChildPoint(index, pointRect, deviceId){ dynamicPoint.addState("dim"); dynamicPoint.addState("bell"); dynamicPoint.setFirstState(pointRect.state); - print("RETURNING " + dynamicPoint); + //print("RETURNING " + dynamicPoint); return dynamicPoint; } \ No newline at end of file From 4a7af70009fbcfa8a31ea6485854b40426e3f706 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 7 Feb 2011 08:17:18 +0000 Subject: [PATCH 1563/2215] List of days of week starts with monday --- .../Plugins/SchedulerGUISimple/ActionPoint.qml | 4 +++- telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml | 2 +- .../Plugins/SchedulerGUISimple/schedulerscripts.js | 13 +++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index e2c27b1d..99014e2b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -443,7 +443,8 @@ Rectangle{ } function getTickedImageSource(index){ - print("GETTING TICKED"); + //print("GETTING TICKED"); + index = Scripts.getOffsetWeekday(index); if(pointRect.deviceRow.parent == undefined || pointRect.deviceRow.parent.parent == undefined){ //to get rid of warnings on initialization print("UNDEFINED, should only be in beginning"); return "unticked.png"; @@ -466,6 +467,7 @@ Rectangle{ } function toggleTickedWeekDay(index){ + index = Scripts.getOffsetWeekday(index); var originalPoint = pointRect; if(pointRect.parentPoint != undefined){ originalPoint = pointRect.parentPoint; diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 6f3a6743..09cd1b9b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -609,7 +609,7 @@ //anchors.fill: parent anchors.left: tickBox.right anchors.leftMargin: 10 - text: Scripts.weekday_name_array[index] //TODO start on monday + text: Scripts.getOffsetWeekdayName(index) } } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 96d4e44f..044a8c15 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -427,6 +427,19 @@ function getDayIndexForDayOfWeek(dayOfWeek){ return dayOfWeek; } +function getOffsetWeekdayName(index){ + index = getOffsetWeekday(index); + return weekday_name_array[index]; +} + +function getOffsetWeekday(index){ + index = index + 1; + if(index == weekday_name_array.length){ + index = 0; + } + return index; +} + //TODO move, pragma safe: function getFirstPointWidth(deviceRow){ var pointList = deviceRow.children; //TODO should really try to avoid using "children"... make own list instead? From 131b5a990ad8e6906528f1ed7bb09c0de77e9995 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 7 Feb 2011 10:30:14 +0000 Subject: [PATCH 1564/2215] Drag and absolute-hour-change changes both parents and children, no matter which point (parent or child) that is moved --- .../SchedulerGUISimple/ActionPoint.qml | 5 +++-- .../SchedulerGUISimple/schedulerscripts.js | 19 ++++++++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 99014e2b..34c498d4 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -56,7 +56,9 @@ Rectangle{ */ onAbsoluteHourChanged: { - print("ABSOLUTE HOUR CHANGED"); //TEST NYTT TEST + //print("ABSOLUTE HOUR CHANGED"); + Scripts.updateParentAbsoluteHour(); + Scripts.updateChildPoints(); pointRect.x = getAbsoluteXValue(); } @@ -461,7 +463,6 @@ Rectangle{ return "unticked.png"; } else{ - print("Well, index? " + index + " or index: " + originalPoint.deviceRow.parent.parent.daydate.getDay()); return "ticked.png"; } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 044a8c15..b86a53e8 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -394,9 +394,9 @@ function removeChildPoint(index){ function removeParentPoint(newParentPoint){ print("Removing parent point..."); + delete childPoints[newParentPoint.deviceRow.parent.parent.daydate.getDay()]; //TODO remove this: = undefined; //remove the current point from the child list newParentPoint.setChildPoints(childPoints); //copy child list to current child (making it a parent) newParentPoint.parentPoint = undefined; - childPoints[newParentPoint.deviceRow.parent.parent.daydate.getDay()] = undefined; //remove the current point from the child list updateParentsInChildList(newParentPoint); //update all other child points (if any) with the current point as their parent pointRect.remove("true"); } @@ -406,9 +406,21 @@ function setChildPoints(newChildPoints){ } function updateParentsInChildList(newParentPoint){ - var children = newParentPoint.getChildPoints() + var children = newParentPoint.getChildPoints(); for(var point in children){ - point.pointParent = newParentPoint; + children[point].parentPoint = newParentPoint; + } +} + +function updateChildPoints(parentPoint){ + for(var point in childPoints){ + childPoints[point].absoluteHour = pointRect.absoluteHour; + } +} + +function updateParentAbsoluteHour(){ + if(pointRect.parentPoint != undefined){ + pointRect.parentPoint.absoluteHour = pointRect.absoluteHour; //TODO check if this can be done with binding without loops... } } @@ -433,6 +445,7 @@ function getOffsetWeekdayName(index){ } function getOffsetWeekday(index){ + //TODO this can be modified based on locale, not adding 1 of week should start with sunday index = index + 1; if(index == weekday_name_array.length){ index = 0; From 984f0f88206e4703b10831654c7d9c3d7b12f6c0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 7 Feb 2011 10:54:44 +0000 Subject: [PATCH 1565/2215] Removing all child/parent-points too when remvoing a point --- .../Plugins/SchedulerGUISimple/ActionPoint.qml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 34c498d4..8ac46670 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -101,7 +101,6 @@ Rectangle{ //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); var hourMinute = getTimeFromPosition(rootCoordinates.x - mouse.x + pointRect.width/2) - print("Position changed reporting in"); if((hourMinute[0] >= 0) && hourMinute[0] < 24){ pointRect.absoluteHour = hourMinute[0] pointRect.absoluteMinute = hourMinute[1] @@ -118,7 +117,6 @@ Rectangle{ dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) //Scripts.pad(hourMinute[1], 2) if(parentPoint != undefined){ - print("Not undefined reporting in"); parentPoint.absoluteHour = parseInt(dialog.absoluteHour, 10); } } @@ -421,8 +419,12 @@ Rectangle{ pointRect.state = "off"; //previous point should be "on" or "dim" } - function remove(keepDialogOpen){ - //TODO Check if point has children, remove them too in that case! + function remove(keepDialogOpen, ignoreParent){ + if(ignoreParent == undefined && pointRect.parentPoint != undefined){ + //remove from parent instead + pointRect.parentPoint.remove(); + return; + } if(pointRect.hangOnToBar != null){ hangOnToBar.destroy(); } @@ -430,11 +432,16 @@ Rectangle{ pointRect.isPoint = "false" var pointList = pointRect.parent.children; var deviceRow = pointRect.deviceRow; + var childPoints = Scripts.getChildPoints(); + for(var child in childPoints){ + childPoints[child].remove(keepDialogOpen, "ignoreParent"); + delete childPoints[child]; + } pointRect.destroy(); if(keepDialogOpen == undefined){ dialog.hide(); } - deviceRow.updateContinuingBars() + deviceRow.updateContinuingBars(); } function minutesToTimelineUnits(minutes){ From 8c788c7b07faa9c60a7af595abdaa98cd1420be9 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 7 Feb 2011 11:04:35 +0000 Subject: [PATCH 1566/2215] Updating continuing bar when adding/removing child points --- telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml | 4 +++- telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 8ac46670..a9ce33a3 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -420,7 +420,7 @@ Rectangle{ } function remove(keepDialogOpen, ignoreParent){ - if(ignoreParent == undefined && pointRect.parentPoint != undefined){ + if(keepDialogOpen == undefined && ignoreParent == undefined && pointRect.parentPoint != undefined){ //remove from parent instead pointRect.parentPoint.remove(); return; @@ -491,10 +491,12 @@ Rectangle{ else if(originalPoint.getChildPoint(index) == undefined){ print("CREATE NEW POINT"); originalPoint.addChildPoint(index, deviceRow.createChildPoint(index, pointRect, deviceRow.deviceId)); + pointRect.deviceRow.updateContinuingBars(); } else{ print("REMOVE A POINT"); originalPoint.removeChildPoint(index); + pointRect.deviceRow.updateContinuingBars(); } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index b86a53e8..9c0939d9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -387,7 +387,7 @@ function addChildPoint(index, point){ function removeChildPoint(index){ print("INDEX BEFORE REMOVE: " + childPoints[index]); var toBeRemoved = childPoints[index]; - childPoints[index] = undefined; + delete childPoints[index]; // = undefined; toBeRemoved.remove("true"); print("INDEX AFTER REMOVE: " + childPoints[index]); } From e48387c22c14ac05d9d3c6afa981057e17e815f4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 7 Feb 2011 13:13:50 +0000 Subject: [PATCH 1567/2215] All properties updated when parent/child/sibling is updated --- .../SchedulerGUISimple/ActionPoint.qml | 61 ++++++++++--- .../Plugins/SchedulerGUISimple/Dialog.qml | 27 ------ .../SchedulerGUISimple/schedulerscripts.js | 86 +++++++++---------- 3 files changed, 89 insertions(+), 85 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index a9ce33a3..984743d9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -18,7 +18,7 @@ Rectangle{ property int absoluteMinute: parseInt(dialog.absoluteMinute, 10) property alias triggerstate: trigger.state property variant parentPoint - property int parentPointAbsoluteHour //TEST changed from int, want "undefined" + //property int parentPointAbsoluteHour //TEST changed from int, want "undefined" property alias deviceRow: pointRect.parent Component.onCompleted: { @@ -55,11 +55,36 @@ Rectangle{ } */ + + //reflect changes on parent/siblings: onAbsoluteHourChanged: { + updateChanges(); //print("ABSOLUTE HOUR CHANGED"); - Scripts.updateParentAbsoluteHour(); - Scripts.updateChildPoints(); - pointRect.x = getAbsoluteXValue(); + } + + onAbsoluteMinuteChanged: { + updateChanges(); + } + + onFuzzyBeforeChanged: { + updateChanges(); + } + + onFuzzyAfterChanged: { + updateChanges(); + } + + onOffsetChanged: { + updateChanges(); + } + + onDimvalueChanged: { + updateChanges(); + updateBars(); + } + + onStateChanged: { + updateChanges(); } /* @@ -79,10 +104,6 @@ Rectangle{ } */ - onDimvalueChanged: { - updateBars(); - } - MouseArea { id: pointRectMouseArea acceptedButtons: Qt.LeftButton | Qt.RightButton @@ -118,6 +139,7 @@ Rectangle{ if(parentPoint != undefined){ parentPoint.absoluteHour = parseInt(dialog.absoluteHour, 10); + parentPoint.absoluteMinute = parseInt(dialog.absoluteMinute, 10); } } @@ -249,6 +271,7 @@ Rectangle{ ] Rectangle{ + //TODO continue fuzzy too into next/prev day width: minutesToTimelineUnits(fuzzyAfter + fuzzyBefore) height: constBarHeight anchors.verticalCenter: parent.verticalCenter @@ -321,6 +344,14 @@ Rectangle{ //pointRect.xvalue = pointRect.x; trigger.state = "sunrise"; } + Scripts.updateParentWithCurrentValues(); + Scripts.updateChildPoints(); + } + + function updateChanges(){ + Scripts.updateParentWithCurrentValues(); + Scripts.updateChildPoints(); + pointRect.x = getAbsoluteXValue(); } function getLastPointColor(){ @@ -377,6 +408,14 @@ Rectangle{ Scripts.addState(state); } + function setActiveStates(activeStates){ + Scripts.setActiveStates(activeStates); + } + + function getActiveStates(){ + return Scripts.getActiveStates(); + } + function setFirstState(firstState){ //print("SETTING FIRST STATE"); @@ -455,12 +494,12 @@ Rectangle{ //print("GETTING TICKED"); index = Scripts.getOffsetWeekday(index); if(pointRect.deviceRow.parent == undefined || pointRect.deviceRow.parent.parent == undefined){ //to get rid of warnings on initialization - print("UNDEFINED, should only be in beginning"); + //undefined, should only be in the beginning return "unticked.png"; } - var originalPoint = pointRect; // pointRect.deviceRow.parent.parent; + var originalPoint = pointRect; if(pointRect.parentPoint != undefined){ - originalPoint = pointRect.parentPoint; //.deviceRow.parent.parent; + originalPoint = pointRect.parentPoint; } if(index == pointRect.deviceRow.parent.parent.daydate.getDay()){ //TODO property or so //current day should always be ticked diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 09cd1b9b..5379f635 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -395,27 +395,14 @@ anchors.leftMargin: 10 anchors.top: fuzzyPanel.bottom anchors.topMargin: 10 - //property alias absoluteHourText: inputAbsoluteHourText.text - //property alias absoluteMinuteText: inputAbsoluteMinuteText.text Row{ Text{ - /*id: textAbsolute - anchors.left: parent.left - anchors.leftMargin: 5 - anchors.top: parent.top - anchors.topMargin: 5 - */ text: "Time:" } Rectangle{ id: inputAbsoluteHour - //property alias absoluteHour: inputAbsoluteHourText.text - /*anchors.left: textOffset.right - anchors.leftMargin: 5 - anchors.verticalCenter: textOffset.verticalCenter - */ width: 35 height: inputAbsoluteHourText.height border.width: 1 @@ -431,11 +418,6 @@ event.accepted = true; inputAbsoluteMinuteText.focus = true; } - //text: "0" - //onChanged:{ - // print("DIALOG HOUR CHANGED"); - //} - } Binding { @@ -447,21 +429,12 @@ } Text{ - /*id: textOffsetUnit - anchors.left: inputOffset.right - anchors.leftMargin: 5 - anchors.verticalCenter: textOffset.verticalCenter - */ text: ":" } Rectangle{ id: inputAbsoluteMinute property alias absoluteMinute: inputAbsoluteMinuteText.text - /*anchors.left: textOffset.right - anchors.leftMargin: 5 - anchors.verticalCenter: textOffset.verticalCenter - */ width: 35 height: inputAbsoluteMinuteText.height border.width: 1 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 9c0939d9..b9351431 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -13,6 +13,10 @@ function getActiveStates(){ return activeStates; } +function setActiveStates(newActiveStates){ + activeStates = newActiveStates; +} + //Days: var weekday_name_array = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday") var currentDayIndex = 6; //Today... @@ -108,23 +112,16 @@ function getEndsWith(pointList, dayIndex, deviceId){ //previousDayEndsWithPoint) dayIndex = days.length - 1; } - //TODO Avoid loop here! var prevDayDevice = getDeviceRow(dayIndex, deviceId); - //print("PREVDAYHERE: index: " + dayIndex + " id: " + deviceId + " Daydevice: " + prevDayDevice); if(prevDayDevice == undefined){ // || prevDayDevice.endPoint == undefined){ //TODO this is due to an error, but in the future use it to avoid loops - print("DayDeviceUndefined...................."); return null; } - //print("RETURNING A PREV POINT"); - //print("Prev day: " + days[dayIndex].daydate.getDate()); - //print("Containing: " + prevDayDevice.endPoint); return prevDayDevice.endPoint; // previousDayEndsWithPoint; } if(prevPoint.state == "off"){ return null; } - //print("RETURNING A POINT"); - return prevPoint; //.state, only on or dim + return prevPoint; //only on or dim } function getPreviousState(currentPointRect){ @@ -145,16 +142,13 @@ function getPreviousState(currentPointRect){ if(prevPoint == null){ //no previous point,see if state continues from previous day if(firstBarStateIndex != undefined && pointList[firstBarStateIndex].firstBar != undefined){ - //print("ENDPOINT!!"); var dayIndex = currentDayIndex - 1; if(dayIndex == -1){ //too far, begin from end again dayIndex = days.length - 1; } - //print("CORRECT DEVICE ID? : " + currentPointRect.deviceRow.deviceId); var prevDayDevice = currentPointRect.parent.getDeviceRow(dayIndex, currentPointRect.deviceRow.deviceId); if(prevDayDevice != undefined){ - //print("Setting end point: ** " + prevDayDevice.endPoint); return prevDayDevice.endPoint; } } @@ -193,10 +187,8 @@ function updateDeviceIndex(){ //TODO, better way, please... var startIndex = 0; for(var i=0;i Date: Mon, 7 Feb 2011 13:52:30 +0000 Subject: [PATCH 1568/2215] Two warnings fixe --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 6 +++--- .../Plugins/SchedulerGUISimple/ActionPoint.qml | 17 ++--------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml index 0be54a2e..b70d281a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -41,14 +41,14 @@ Rectangle{ } }, State{ - name: "pointLoaded" //; when: hangOnToPoint != undefined && hangOnToPoint.isLoaded != undefined && hangOnToPoint.parent != null && hangOnToPoint.parent != undefined && hangOnToPoint.verticalCenter != undefined //TODO might aswell use hangOnToPoint != undefined, still get null item warning, used hangOnToPoint.isLoaded too before, remove this? + name: "pointLoaded" PropertyChanges { target: barRectangle - anchors.verticalCenter: hangOnToPoint.verticalCenter + anchors.verticalCenter: hangOnToPoint.verticalCenter //TODO Warning on this and the line below... cannot fix, warning even if setting to undefined directly anchors.left: hangOnToPoint.horizontalCenter color: hangOnToPoint.actionTypeColor opacity: hangOnToPoint.actionTypeOpacity - width: Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children) + width: hangOnToPoint.parent == null ? 0 : Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children) } } ] diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 984743d9..dc72e15e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -147,9 +147,9 @@ Rectangle{ drag.target: pointRect drag.axis: Drag.XAxis drag.minimumX: -1 * pointRect.width/2 - drag.maximumX: pointRect.parent.width - pointRect.width/2 //TODO: om pointRect.parent == null, då bara 0... + drag.maximumX: pointRect.parent == null ? 0 : pointRect.parent.width - pointRect.width/2 drag.filterChildren: true //TODO testing this - //TODO make it impossible to overlap (on release) + //TODO make it impossible to overlap (on release) (why?) //TODO drag to most right - jumps back, why? states: State{ @@ -157,19 +157,6 @@ Rectangle{ PropertyChanges { target: pointRect; opacity: 0.5; } } } - /* - ListModel{ - id: daysOfWeek - ListElement{ - name: "on" - imagesource: "on.png" //TODO cannot use javascript properties here... do in some other way, maybe a list with names here? - } - ListElement{ - name: "off" - imagesource: "off.png" - } - } - */ Column{ spacing: 10 From f80f37dd18cdf4f45b6713cbb264bead06d11c11 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 8 Feb 2011 09:01:26 +0000 Subject: [PATCH 1569/2215] Fixed parent/child/sibling bug on sunset/sunrise-trigger --- .../SchedulerGUISimple/ActionPoint.qml | 4 +- .../Plugins/SchedulerGUISimple/__init__.js | 46 +++++++++++++++++++ .../SchedulerGUISimple/schedulerscripts.js | 13 ++---- 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index dc72e15e..f7240ec6 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -338,7 +338,9 @@ Rectangle{ function updateChanges(){ Scripts.updateParentWithCurrentValues(); Scripts.updateChildPoints(); - pointRect.x = getAbsoluteXValue(); + if(pointRect.triggerstate == "absolute"){ + pointRect.x = getAbsoluteXValue(); + } } function getLastPointColor(){ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 5d4128aa..89dc5368 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -16,6 +16,8 @@ com.telldus.schedulersimplegui = function() { getSunSetTime: getSunSetTime, getSunData: getSunData }); + + //devices: deviceList = new com.telldus.qml.array(); var list = com.telldus.core.deviceList.getList(); for(var i=0; i < list.length; ++i) { @@ -24,6 +26,50 @@ com.telldus.schedulersimplegui = function() { deviceList.push(item); } view.setProperty('deviceModel', deviceList); + + //points: + //from storage... + var weekPointList = new com.telldus.qml.array(); + var dummypoint = {}; + dummypoint["day"] = 0; + dummypoint["deviceId"] = 1; + weekPointList.push(dummypoint); + dummypoint = {}; + dummypoint["day"] = 1; + dummypoint["deviceId"] = 2; + weekPointList.push(dummypoint); + + var now = new Date(); + var time1 = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds(); + print(time1); // 48880 + time2 = time1 + 30; + time3 = time1 - 60; + time1 = time1 + 50; + + var startdate = now; //new Date(2011,0,5).getTime(); + //var startdate2 = new Date(2011,0,5).getTime(); + + //ID = ID for storage + //Key is position in list, returned from "addJob" + var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; + var job = new com.telldus.scheduler.JobRecurringWeek({id: 4, executeFunc: execFunc, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate, lastRun: 0, device: 1, method: 1, value: ""}); + var event = {}; + event.d = {id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: 300}; //(new Date().getTime())/1000 + 20 + job.addEvent(event); + //job.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 20})); + com.telldus.scheduler.addJob(job); + //newRecurringMonthJob.save(); + /* + var newAbsoluteJob = getJob({id: 5, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_MONTH, startdate: startdate2, lastRun: 0, device: 1, method: 1, value: "", pastGracePeriod: 90}); + newAbsoluteJob.addEvent(new Event({id: 1, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time2})); + newAbsoluteJob.addEvent(new Event({id: 2, value: "00-05", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: time3})); + //newAbsoluteJob.save(); + com.telldus.scheduler.addJob(newAbsoluteJob); + */ + //END FROM STORAGE + + view.setProperty('weekPointList', weekPointList); + //set images: view.setProperty("imageTriggerSunrise", "sunrise.png"); view.setProperty("imageTriggerSunset", "sunset.png"); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index b9351431..007c89e6 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -287,14 +287,9 @@ function initiatePointsInGUI(){ //weekPointList){ //för varje point, addPointToGUI, men ju även lägga till schemajobb... alltså i __init__.js... men därifrån kan inte denna anropas... //så det får väl bli varsin iteration då... //weekPointList -> från __init__.js - var weekPointList = new Array(); - var dummypoint = [] - dummypoint["day"] = 0; - dummypoint["deviceId"] = 1; - weekPointList.push(dummypoint); + //for(var i in weekPointList){ for(var i=0;i Date: Tue, 8 Feb 2011 12:46:19 +0000 Subject: [PATCH 1570/2215] Listen for deviceChange and add new devices if new ones are created --- .../Plugins/SchedulerGUISimple/__init__.js | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 89dc5368..5a30aae4 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -16,7 +16,7 @@ com.telldus.schedulersimplegui = function() { getSunSetTime: getSunSetTime, getSunData: getSunData }); - + //devices: deviceList = new com.telldus.qml.array(); var list = com.telldus.core.deviceList.getList(); @@ -26,7 +26,9 @@ com.telldus.schedulersimplegui = function() { deviceList.push(item); } view.setProperty('deviceModel', deviceList); - + //Listen for device-change + com.telldus.core.deviceChange.connect(deviceChange); + //points: //from storage... var weekPointList = new com.telldus.qml.array(); @@ -38,17 +40,17 @@ com.telldus.schedulersimplegui = function() { dummypoint["day"] = 1; dummypoint["deviceId"] = 2; weekPointList.push(dummypoint); - + var now = new Date(); var time1 = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds(); print(time1); // 48880 time2 = time1 + 30; time3 = time1 - 60; time1 = time1 + 50; - + var startdate = now; //new Date(2011,0,5).getTime(); //var startdate2 = new Date(2011,0,5).getTime(); - + //ID = ID for storage //Key is position in list, returned from "addJob" var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; @@ -67,9 +69,9 @@ com.telldus.schedulersimplegui = function() { com.telldus.scheduler.addJob(newAbsoluteJob); */ //END FROM STORAGE - + view.setProperty('weekPointList', weekPointList); - + //set images: view.setProperty("imageTriggerSunrise", "sunrise.png"); view.setProperty("imageTriggerSunset", "sunset.png"); @@ -79,13 +81,13 @@ com.telldus.schedulersimplegui = function() { view.setProperty("imageActionDim", "dim.png"); view.setProperty("imageActionBell", "bell.png"); view.setProperty("imageInfo", "info.png"); - + //height/width constants view.setProperty("constBarHeight", 10); view.setProperty("constDeviceRowHeight", 50); view.setProperty("constDeviceRowWidth", 600); view.setProperty("constPointWidth", 30); - + view.load("main.qml"); application.addWidget("scheduler.simple", "icon.png", view); @@ -94,7 +96,15 @@ com.telldus.schedulersimplegui = function() { function addDevice() { deviceList.push({name:'Stallet istallet'}); } - + + function deviceChange( deviceId, eventType ) { + if (eventType == com.telldus.core.TELLSTICK_DEVICE_ADDED) { + var item = com.telldus.core.deviceList.getDevice(deviceId); + item.isEnabled = "enabled"; + deviceList.push(item); + } + } + function getSun(riseset, rowWidth, pointWidth){ var date = new Date(); var timevalues = com.telldus.suncalculator.riseset(date); @@ -108,18 +118,18 @@ com.telldus.schedulersimplegui = function() { var hourSize = rowWidth/24; return hourSize*hourminute[0] + hourSize * (hourminute[1]/60) - pointWidth/2; } - + //Raw sun data function getSunData(){ var date = new Date; return com.telldus.suncalculator.riseset(date); } - + function getSunRiseTime(rowWidth, pointWidth){ - + return getSun("rise", rowWidth, pointWidth); } - + function getSunSetTime(rowWidth, pointWidth){ return getSun("set", rowWidth, pointWidth); } From a7d4c323d88a62296040943fb3d1a95583c236f7 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 8 Feb 2011 16:26:57 +0000 Subject: [PATCH 1571/2215] Points added to schedule when clicking save --- .../Plugins/Scheduler/DefaultJobTypes.js | 8 +- telldus-gui/Plugins/Scheduler/__init__.js | 34 +++- .../Plugins/SchedulerGUISimple/__init__.js | 142 +++++++++++++++- .../Plugins/SchedulerGUISimple/main.qml | 155 +++++++++++++++++- .../SchedulerGUISimple/schedulerscripts.js | 2 +- 5 files changed, 330 insertions(+), 11 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js index 5f3c4b22..5f4ed2f0 100644 --- a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js +++ b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js @@ -19,8 +19,11 @@ function getEventRunTime(event, date){ date = 0; } currentEventRuntimeTimestamp = (event.d.time * 1000) + date; + print("currentEventRuntimeTimestamp: " + new Date(currentEventRuntimeTimestamp)); currentEventRuntimeTimestamp += (offset * 1000); //this is really not useful for absolute values, but exists for consistency + print("currentEventRuntimeTimestamp1: " + new Date(currentEventRuntimeTimestamp)); currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); + print("currentEventRuntimeTimestamp2: " + new Date(currentEventRuntimeTimestamp)); } else if(event.d.type == com.telldus.scheduler.EVENTTYPE_SUNRISE || event.d.type == com.telldus.scheduler.EVENTTYPE_SUNSET){ currentEventRuntimeTimestamp = getSunUpDownForDate(date, parseInt(event.d.type)); @@ -88,6 +91,7 @@ function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod){ } var currentEventRuntimeTimestamp = getEventRunTime(event, date); + print("EventRunTime: " + new Date(currentEventRuntimeTimestamp)); if((nextRunTime === null || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > (new Date().getTime() - pastGracePeriod)){ //earlier than other events, but later than "now" nextRunTime = currentEventRuntimeTimestamp; } @@ -259,6 +263,7 @@ com.telldus.scheduler.JobRecurringDay = function(jobdata){ com.telldus.scheduler * type is com.telldus.scheduler.JOBTYPE_RECURRING_WEEK * Extra/different event properties: * value - day of week + * time - seconds into the day */ com.telldus.scheduler.JobRecurringWeek = function(jobdata){ com.telldus.scheduler.Job.call(this, jobdata); } @@ -337,7 +342,6 @@ com.telldus.scheduler.JobRecurringWeek.prototype.getNextRunTime = function(){ } var pastGracePeriod = getGracePeriod(this.v); - for(var key in this.v.events){ //get next correct day of week, may be today too var weekday = parseInt(this.v.events[key].d.value); @@ -345,6 +349,7 @@ com.telldus.scheduler.JobRecurringWeek.prototype.getNextRunTime = function(){ print("Incorrect weekday value"); continue; } + print("Weekday... " + weekday); var returnDate = new Date(); var minStartTime = new Date(this.v.startdate); if(minStartTime > returnDate){ @@ -367,7 +372,6 @@ com.telldus.scheduler.JobRecurringWeek.prototype.getNextRunTime = function(){ nextRunTime = nextTempRunTime; } } - return nextRunTime; } diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index e813cb7f..f2b9b052 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -23,7 +23,7 @@ com.telldus.scheduler = function() { function init(){ JobDaylightSavingReload.prototype = new com.telldus.scheduler.Job(); setDaylightSavingJobFunctions(); - loadJobs(); //TODO remove this after testing is done + //loadJobs(); //TODO remove this after testing is done } @@ -40,6 +40,28 @@ com.telldus.scheduler = function() { return key; } + //add several jobs at once, withou recalculating timer between each + function addJobs(jobs){ + if(storedJobs.length == 0){ + print("Adding daylight saving time"); + var daylightSavingReloadKey = storedJobs.push(getDaylightSavingReloadJob()); + updateJobInList(daylightSavingReloadKey, true); //waitForMore = don't sort array and recalculate timer yet + } + var returnKeys = new Array(); + for(var i=0;i 0){ + //var timerkeys = addJobsToSchedule.callWith(jobs); + //} + if(points.length > 0){ + /* + print("Nerifrån: " + points[0].absoluteHour); + var koll = {"TEST": 55}; + print("Koll: " + koll["TEST"]); + var underarray = new Array(); + underarray.push("hejsan"); + underarray.push("hoppsan"); + koll = new Array(); + koll.push(underarray); + koll.push(8); + */ + addJobsToSchedule.callWith(points); //{"TEST": 55}); //points); + } + //1. for each device (som har hasChanged set): + //2. ta bort alla timers med keys till denna device + //3. om disabled = gör inte mer... annars: + //4. alla punkter på alla dagar här, gå igenom: + //5. om punkt, om inte har parentPoint, och inte disabled (senare): + //6. gör om punkt till jobb (pointToJob), lägg till array, med events för alla childPoints (och sig själv) + //7. skicka in denna array till schedulern (addJobs) + //8. få tillbaka ny array med timerkeys, spara denna på devicen + } + + function pointToArray(point){ //TODO another way than using arrays... + var deviceId = point.deviceRow.deviceId; //not really in use yet + var pointName = "Job_" + deviceId; + var lastrun = 0; //TODO + var startdate = new Date(); //startdate, not in use, always "now" + var pointDimValue = point.dimvalue; + var pointMethod = getMethodFromState.callWith(point.state); + + var pointTime = point.absoluteHour * 3600 + point.absoluteMinute * 60; + var pointType = getTypeFromTriggerstate.callWith(point.triggerstate); + if(point.triggerstate == "sunrise"){ + var suntime = main.sunData[0].split(':'); + pointTime = suntime[0] * 3600 + suntime[1] * 60; + } + else if(point.triggerstate == "sunset"){ + var suntime = main.sunData[1].split(':'); + pointTime = suntime[0] * 3600 + suntime[1] * 60; + } + var pointFuzzinessBefore = point.fuzzyBefore; + var pointFuzzinessAfter = point.fuzzyAfter; + var pointOffset = point.triggerstate == "absolute" ? 0 : point.offset; + + var pointDays = new Array(); + pointDays.push(point.deviceRow.parent.parent.daydate.getDay()); + for(var childPoint in point.childPoints){ + pointDays.push(point.childPoints[childPoint].deviceRow.parent.parent.daydate.getDay()); //different per event + } + return new Array(deviceId, pointName, startdate, lastrun, pointMethod, pointDimValue, pointTime, pointType, pointFuzzinessBefore, pointFuzzinessAfter, pointOffset, pointDays); + } + + /* + function pointToJob(point){ + + var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; //TODO default later + + var deviceId = point.deviceRow.deviceId; //not really in use yet + var pointName = "Job_" + deviceId; + var lastrun = 0; //TODO + var startdate = new Date(); //startdate, not in use, always "now" + var pointDimValue = point.dimvalue; + var pointMethod = getMethodFromState.callWith(point.state); + + var job = getJob.callWith(deviceId, execFunc, pointName, startdate, lastrun, deviceId, pointMethod, pointDimValue); //ERROR here, cannot return this + print("Jobtest: " + job); + + var pointTime = point.absoluteHour * 3600 + point.absoluteMinute * 60; + var pointType = getTypeFromTriggerstate.callWith(point.triggerstate); + if(point.triggerstate == "sunrise"){ + var suntime = main.sunData[0].split(':'); + pointTime = suntime[0] * 3600 + suntime[1] * 60; + } + else if(point.triggerstate == "sunset"){ + var suntime = main.sunData[1].split(':'); + pointTime = suntime[0] * 3600 + suntime[1] * 60; + } + var pointFuzzinessBefore = point.fuzzyBefore; + var pointFuzzinessAfter = point.fuzzyAfter; + var pointOffset = point.offset; + + var pointDay = point.deviceRow.parent.parent.daydate.getDay(); //different per event + var event = {}; + + event.d = {id: deviceId, value: pointDay, fuzzinessBefore: pointFuzzinessBefore, fuzzinessAfter: pointFuzzinessAfter, type: pointType, offset: pointOffset, time: pointTime}; + print("Job: " + job.v.name); + job.addEvent(event); + for(var childPoint in point.childPoints){ + event = {}; + pointDay = point.childPoints[childPoint].deviceRow.parent.parent.daydate.getDay(); //different per event + event.d = {id: deviceId, value: pointDay, fuzzinessBefore: pointFuzzinessBefore, fuzzinessAfter: pointFuzzinessAfter, type: pointType, offset: pointOffset, time: pointTime}; + job.addEvent(event); + } + + //job.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 20})); + + return job; + + /* + var jobs = new Array(); + jobs.push(job); + + //hm, timerkeys... kommer ju få tillbaka alla på en ggn, eller iaf per device... (om ett addjob/device) + //tänkte ändå alltid uppdatera alla (dvs ta bort/lägga till) för varje device, om den alls har ändrats... + //man kunde klart koppla en key till en point, men isf måste man på ngt sätt lagra när den tas bort... + //och jämför när man lägger till nya (iofs bara kolla om ngn key finns på pointen, annars är den ny) + //ett jobb/punkt (med flera events, per dag) + //lägga till alla jobb/device (för alla dagar) på en ggn (om device hasChanged), ta bort alla tidigare... + //alla timers kommer ju att ha försvunnit vid avstängning, så det behöver man inte bry sig om... + var timerkeys = com.telldus.scheduler.addJobs(jobs); + */ + //} + } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 007c89e6..90a0c716 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -303,7 +303,7 @@ function getDeviceRow(dayOfWeek, deviceId){ if(dayListViewComp.children.length == undefined){ return null; } - print("DeviceIndex: " + currentDeviceIndex + " och " + deviceId + ", och sedan " + days.length); + //print("DeviceIndex: " + currentDeviceIndex + " och " + deviceId + ", och sedan " + days.length); var pointParent = dayListViewComp.children[0].children[currentDeviceIndex]; return pointParent; } From 1eb837511a8b004fcd29fc21e097e2971ad4ae11 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 8 Feb 2011 16:45:10 +0000 Subject: [PATCH 1572/2215] Child points also added to schedule --- telldus-gui/Plugins/SchedulerGUISimple/main.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 1e98bd58..54e9c530 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -602,8 +602,9 @@ import "schedulerscripts.js" as Scripts var pointDays = new Array(); pointDays.push(point.deviceRow.parent.parent.daydate.getDay()); - for(var childPoint in point.childPoints){ - pointDays.push(point.childPoints[childPoint].deviceRow.parent.parent.daydate.getDay()); //different per event + var childPoints = point.getChildPoints(); + for(var child in childPoints){ + pointDays.push(childPoints[child].deviceRow.parent.parent.daydate.getDay()); //different per event } return new Array(deviceId, pointName, startdate, lastrun, pointMethod, pointDimValue, pointTime, pointType, pointFuzzinessBefore, pointFuzzinessAfter, pointOffset, pointDays); } From c2670869c1f3a0733c1d1a3da32d22000c1bede4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 9 Feb 2011 12:58:25 +0000 Subject: [PATCH 1573/2215] Removing old schedules before adding new ones --- .../Plugins/Scheduler/DefaultJobTypes.js | 8 +++--- telldus-gui/Plugins/Scheduler/__init__.js | 14 +++++------ .../Plugins/SchedulerGUISimple/__init__.js | 21 ++++++++++------ .../Plugins/SchedulerGUISimple/main.qml | 25 ++++--------------- .../SchedulerGUISimple/schedulerscripts.js | 21 ++++++++++++++++ 5 files changed, 51 insertions(+), 38 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js index 5f4ed2f0..3a8eaca8 100644 --- a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js +++ b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js @@ -19,11 +19,11 @@ function getEventRunTime(event, date){ date = 0; } currentEventRuntimeTimestamp = (event.d.time * 1000) + date; - print("currentEventRuntimeTimestamp: " + new Date(currentEventRuntimeTimestamp)); + //print("currentEventRuntimeTimestamp: " + new Date(currentEventRuntimeTimestamp)); currentEventRuntimeTimestamp += (offset * 1000); //this is really not useful for absolute values, but exists for consistency - print("currentEventRuntimeTimestamp1: " + new Date(currentEventRuntimeTimestamp)); + //print("currentEventRuntimeTimestamp1: " + new Date(currentEventRuntimeTimestamp)); currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); - print("currentEventRuntimeTimestamp2: " + new Date(currentEventRuntimeTimestamp)); + //print("currentEventRuntimeTimestamp2: " + new Date(currentEventRuntimeTimestamp)); } else if(event.d.type == com.telldus.scheduler.EVENTTYPE_SUNRISE || event.d.type == com.telldus.scheduler.EVENTTYPE_SUNSET){ currentEventRuntimeTimestamp = getSunUpDownForDate(date, parseInt(event.d.type)); @@ -363,7 +363,7 @@ com.telldus.scheduler.JobRecurringWeek.prototype.getNextRunTime = function(){ returnDate = zeroTime(returnDate); - nextTempRunTime = getNextEventRunTime(null, this.v.events[key], returnDate.getTime(), pastGracePeriod); + nextTempRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); if(nextTempRunTime < new Date().getTime()){ //event happened today, already passed, add to next week instead returnDate.setDate(returnDate.getDate() + 7); nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index f2b9b052..eb1c3e7b 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -52,7 +52,6 @@ com.telldus.scheduler = function() { var job = jobs[i]; var key = storedJobs.push(job); job.key = key; - print("Adding job"); updateJobInList(key, true); //waitForMore = don't sort array and recalculate timer yet returnKeys.push(key); } @@ -109,9 +108,13 @@ com.telldus.scheduler = function() { } } - function removeJob(id){ + function removeJob(id, waitForMore){ + if(queuedJob.id == id){ + queuedJob = undefined; + } + storedJobs.remove(id); - updateJobInList(id); + updateJobInList(id, waitForMore); //wait for more if(storedJobs.length == 1){ //only one job left, it's only the DaylightSaving reload job, remove that too for(var key in storedJobs.container){ @@ -144,7 +147,6 @@ com.telldus.scheduler = function() { joblist.push(queuedJob); joblist.sort(compareTime); } - var job = joblist.shift(); //get first job in list (and remove it from the list) queuedJob = job; //put it in list, to keep track of current job var nextRunTime = job.nextRunTime; @@ -155,13 +157,11 @@ com.telldus.scheduler = function() { updateJobInList(job.id); //This will just recalculate the job, and probably return 0 again, but updateJobInList won't add it to the list in that case (shouldnt end up here at all now actually) return; } - var runJobFunc = function(){ runJob(job.id); }; var now = new Date().getTime(); var delay = nextRunTime - now; print("Will run " + storedJobs.get(job.id).v.name + " (" + job.id + ") at " + new Date(nextRunTime)); //Note not all will have a name print("(Now is " + new Date() + ")"); - print("Delay: " + delay); timerid = setTimeout(runJobFunc, delay); //start the timer print("Has started a job wait"); @@ -171,12 +171,12 @@ com.telldus.scheduler = function() { if(!joblist){ joblist = new Array(); } - if(!storedJobs.contains(id)){ removeFromJobList(id); runNextJob(); return; } + var job = storedJobs.get(id); var nextRunTime = job.getNextRunTime(); print("Time updated to: " + new Date(nextRunTime)); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index abe876d0..75beec2d 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -131,12 +131,18 @@ com.telldus.schedulersimplegui = function() { } - function addJobsToSchedule(points){ - //print("Uppe: " + points["TEST"]); + function addJobsToSchedule(points, deviceTimerKeys){ + //delete all current schedules for this device: + for(var i=0;i 0){ + var deviceTimerKeys = Scripts.getDeviceTimerKeys(deviceId); + deviceTimerKeys = addJobsToSchedule.callWith(points, deviceTimerKeys); //remove all schedules for this device, and add them again + Scripts.setDeviceTimerKeys(deviceId, deviceTimerKeys); + } } - print("after loops"); - //if(jobs.length > 0){ - //var timerkeys = addJobsToSchedule.callWith(jobs); - //} - if(points.length > 0){ - /* - print("Nerifrån: " + points[0].absoluteHour); - var koll = {"TEST": 55}; - print("Koll: " + koll["TEST"]); - var underarray = new Array(); - underarray.push("hejsan"); - underarray.push("hoppsan"); - koll = new Array(); - koll.push(underarray); - koll.push(8); - */ - addJobsToSchedule.callWith(points); //{"TEST": 55}); //points); - } //1. for each device (som har hasChanged set): //2. ta bort alla timers med keys till denna device //3. om disabled = gör inte mer... annars: diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 90a0c716..92709088 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -17,6 +17,27 @@ function setActiveStates(newActiveStates){ activeStates = newActiveStates; } +//from main: +var deviceProperties = {}; + +function getDeviceTimerKeys(deviceId){ + var device = deviceProperties[deviceId]; + return device == undefined ? {} : device["timerkeys"]; +} + +function setDeviceTimerKeys(deviceId, deviceTimerKeys){ + if(deviceProperties[deviceId] == undefined){ + deviceProperties[deviceId] = {}; + } + deviceProperties[deviceId]["timerkeys"] = deviceTimerKeys; +} + +function hasChanged(deviceId){ + var hasChanged = deviceProperties[deviceId]["hasChanged"]; + print("Do some thingys here"); + return hasChanged == true; +} + //Days: var weekday_name_array = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday") var currentDayIndex = 6; //Today... From ab7caa2c748ef1e1f0501c0aaf3c0ecf02bc4c31 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 9 Feb 2011 14:20:13 +0000 Subject: [PATCH 1574/2215] Only updating schedule for devices that have changed in some way --- .../SchedulerGUISimple/ActionPoint.qml | 21 +--- .../Plugins/SchedulerGUISimple/__init__.js | 80 ++----------- .../Plugins/SchedulerGUISimple/main.qml | 111 +++++------------- .../SchedulerGUISimple/schedulerscripts.js | 18 ++- 4 files changed, 50 insertions(+), 180 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index f7240ec6..de8fe820 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -87,23 +87,6 @@ Rectangle{ updateChanges(); } - /* - onParentPointAbsoluteHourChanged: { - //pointRect.absoluteHour = parentPoint.absolutHour - print("IN ABSOLUTEHOURCHANGED..."); - if(parentPoint == undefined){ //TODO this is not correct, must remove, but... - print("PP UNDEFINED!"); //Should never happen - dialog.absoluteHour = absoluteHour; //this is needed for update - print("Absolute hour changed from " + dialog.absoluteHour + " to " + absoluteHour); - } - else if(parentPointAbsoluteHour != undefined){ - print("PPABSOLUTE HOUR NOT UNDEFINED!"); - dialog.absoluteHour = parentPointAbsoluteHour; //this is needed for update - print("Absolute hour changed from " + dialog.absoluteHour + " to " + parentPointAbsoluteHour); - } - } - */ - MouseArea { id: pointRectMouseArea acceptedButtons: Qt.LeftButton | Qt.RightButton @@ -129,11 +112,9 @@ Rectangle{ } onReleased: { + pointRect.deviceRow.setChanged(); pointRect.deviceRow.updateContinuingBars() dialog.show(pointRect) //TODO not pointRect, but parentPoint if such exists - //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); - //var hourMinute = getTimeFromPosition(rootCoordinates.x) - //print("Released reporting in"); dialog.absoluteHour = Scripts.pad(pointRect.absoluteHour, 2) //Scripts.pad(hourMinute[0], 2) dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) //Scripts.pad(hourMinute[1], 2) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 75beec2d..d429b3bb 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -74,25 +74,6 @@ com.telldus.schedulersimplegui = function() { job.addEvent(event); jobs.push(job); - //hm, timerkeys... kommer ju få tillbaka alla på en ggn, eller iaf per device... (om ett addjob/device) - //tänkte ändå alltid uppdatera alla (dvs ta bort/lägga till) för varje device, om den alls har ändrats... - //man kunde klart koppla en key till en point, men isf måste man på ngt sätt lagra när den tas bort... - //och jämför när man lägger till nya (iofs bara kolla om ngn key finns på pointen, annars är den ny) - //ett jobb/punkt (med flera events, per dag) - //lägga till alla jobb/device (för alla dagar) på en ggn (om device hasChanged), ta bort alla tidigare... - //alla timers kommer ju att ha försvunnit vid avstängning, så det behöver man inte bry sig om... - // var timerkeys = com.telldus.scheduler.addJobs(jobs); - // for(var i=0;i 0){ - var deviceTimerKeys = Scripts.getDeviceTimerKeys(deviceId); - deviceTimerKeys = addJobsToSchedule.callWith(points, deviceTimerKeys); //remove all schedules for this device, and add them again - Scripts.setDeviceTimerKeys(deviceId, deviceTimerKeys); - } - } - - //1. for each device (som har hasChanged set): - //2. ta bort alla timers med keys till denna device - //3. om disabled = gör inte mer... annars: - //4. alla punkter på alla dagar här, gå igenom: - //5. om punkt, om inte har parentPoint, och inte disabled (senare): - //6. gör om punkt till jobb (pointToJob), lägg till array, med events för alla childPoints (och sig själv) - //7. skicka in denna array till schedulern (addJobs) - //8. få tillbaka ny array med timerkeys, spara denna på devicen + + var deviceTimerKeys = Scripts.getDeviceTimerKeys(deviceId); //get timer keys for this device, for removal + deviceTimerKeys = addJobsToSchedule.callWith(points, deviceTimerKeys); //remove all schedules for this device, and add them again + Scripts.setDeviceTimerKeys(deviceId, deviceTimerKeys); //save the new timer keys + } } function pointToArray(point){ //TODO another way than using arrays... @@ -593,66 +598,4 @@ import "schedulerscripts.js" as Scripts } return new Array(deviceId, pointName, startdate, lastrun, pointMethod, pointDimValue, pointTime, pointType, pointFuzzinessBefore, pointFuzzinessAfter, pointOffset, pointDays); } - - /* - function pointToJob(point){ - - var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; //TODO default later - - var deviceId = point.deviceRow.deviceId; //not really in use yet - var pointName = "Job_" + deviceId; - var lastrun = 0; //TODO - var startdate = new Date(); //startdate, not in use, always "now" - var pointDimValue = point.dimvalue; - var pointMethod = getMethodFromState.callWith(point.state); - - var job = getJob.callWith(deviceId, execFunc, pointName, startdate, lastrun, deviceId, pointMethod, pointDimValue); //ERROR here, cannot return this - print("Jobtest: " + job); - - var pointTime = point.absoluteHour * 3600 + point.absoluteMinute * 60; - var pointType = getTypeFromTriggerstate.callWith(point.triggerstate); - if(point.triggerstate == "sunrise"){ - var suntime = main.sunData[0].split(':'); - pointTime = suntime[0] * 3600 + suntime[1] * 60; - } - else if(point.triggerstate == "sunset"){ - var suntime = main.sunData[1].split(':'); - pointTime = suntime[0] * 3600 + suntime[1] * 60; - } - var pointFuzzinessBefore = point.fuzzyBefore; - var pointFuzzinessAfter = point.fuzzyAfter; - var pointOffset = point.offset; - - var pointDay = point.deviceRow.parent.parent.daydate.getDay(); //different per event - var event = {}; - - event.d = {id: deviceId, value: pointDay, fuzzinessBefore: pointFuzzinessBefore, fuzzinessAfter: pointFuzzinessAfter, type: pointType, offset: pointOffset, time: pointTime}; - print("Job: " + job.v.name); - job.addEvent(event); - for(var childPoint in point.childPoints){ - event = {}; - pointDay = point.childPoints[childPoint].deviceRow.parent.parent.daydate.getDay(); //different per event - event.d = {id: deviceId, value: pointDay, fuzzinessBefore: pointFuzzinessBefore, fuzzinessAfter: pointFuzzinessAfter, type: pointType, offset: pointOffset, time: pointTime}; - job.addEvent(event); - } - - //job.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 20})); - - return job; - - /* - var jobs = new Array(); - jobs.push(job); - - //hm, timerkeys... kommer ju få tillbaka alla på en ggn, eller iaf per device... (om ett addjob/device) - //tänkte ändå alltid uppdatera alla (dvs ta bort/lägga till) för varje device, om den alls har ändrats... - //man kunde klart koppla en key till en point, men isf måste man på ngt sätt lagra när den tas bort... - //och jämför när man lägger till nya (iofs bara kolla om ngn key finns på pointen, annars är den ny) - //ett jobb/punkt (med flera events, per dag) - //lägga till alla jobb/device (för alla dagar) på en ggn (om device hasChanged), ta bort alla tidigare... - //alla timers kommer ju att ha försvunnit vid avstängning, så det behöver man inte bry sig om... - var timerkeys = com.telldus.scheduler.addJobs(jobs); - */ - //} - } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 92709088..24c28cd5 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -33,9 +33,16 @@ function setDeviceTimerKeys(deviceId, deviceTimerKeys){ } function hasChanged(deviceId){ - var hasChanged = deviceProperties[deviceId]["hasChanged"]; - print("Do some thingys here"); - return hasChanged == true; + var device = deviceProperties[deviceId]; + var hasChanged = device == undefined ? false : device["hasChanged"]; + return hasChanged; +} + +function setChanged(deviceId, change){ + if(deviceProperties[deviceId] == undefined){ + deviceProperties[deviceId] = {}; + } + deviceProperties[deviceId]["hasChanged"] = change; } //Days: @@ -474,6 +481,11 @@ function deviceEnabled(deviceId, enabled){ var deviceRow = days[i].children[0].children[deviceIndex[deviceId]]; deviceRow.state = enabled; //TODO connect directly instead... if possible } + setChanged(deviceId, true); +} + +function deviceIsEnabled(deviceId){ + return days[0].children[0].children[deviceIndex[deviceId]].state == "enabled"; } function createChildPoint(index, pointRect, deviceId){ From f4cf1635307403fa36262528a41632a6dad625e1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 9 Feb 2011 14:44:40 +0000 Subject: [PATCH 1575/2215] Now running actual TellStick controlling events on scheduled times --- telldus-gui/Plugins/SchedulerGUISimple/__init__.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index d429b3bb..faf87129 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -58,8 +58,8 @@ com.telldus.schedulersimplegui = function() { //ID = ID for storage //Key is position in list, returned from "addJob" - var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; - var job = new com.telldus.scheduler.JobRecurringWeek({id: 4, executeFunc: execFunc, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate, lastRun: 0, device: 1, method: 1, value: ""}); + //var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; + var job = new com.telldus.scheduler.JobRecurringWeek({id: 4, executeFunc: null, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate, lastRun: 0, device: 1, method: 1, value: ""}); var event = {}; event.d = {id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: 300}; //(new Date().getTime())/1000 + 20 job.addEvent(event); @@ -68,7 +68,7 @@ com.telldus.schedulersimplegui = function() { var jobs = new Array(); jobs.push(job); - job = new com.telldus.scheduler.JobRecurringWeek({id: 4, executeFunc: execFunc, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate, lastRun: 0, device: 1, method: 1, value: ""}); + job = new com.telldus.scheduler.JobRecurringWeek({id: 4, executeFunc: null, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate, lastRun: 0, device: 1, method: 1, value: ""}); var event = {}; event.d = {id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: 100}; //(new Date().getTime())/1000 + 20 job.addEvent(event); @@ -133,9 +133,9 @@ com.telldus.schedulersimplegui = function() { function getJob(pointArray){ //deviceId, pointName, startdate, lastrun, pointMethod, pointDimValue, pointTime, pointType, pointFuzzinessBefore, pointFuzzinessAfter, pointOffset, pointDays - var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; //TODO default later + //var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; //TODO default later //TODO dimValue 0-100 ok? Or other number expected? - var job = new com.telldus.scheduler.JobRecurringWeek({id: pointArray[0], executeFunc: execFunc, name: pointArray[1], type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: pointArray[2], lastRun: pointArray[3], device: pointArray[0], method: pointArray[4], value: pointArray[5]}); + var job = new com.telldus.scheduler.JobRecurringWeek({id: pointArray[0], executeFunc: null, name: pointArray[1], type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: pointArray[2], lastRun: pointArray[3], device: pointArray[0], method: pointArray[4], value: pointArray[5]}); var event = {}; var pointFuzzinessBefore = (pointArray[8]*60); var pointFuzzinessAfter = (pointArray[9]*60); From 9e54aa619c0e3feeaf9140df8a2c6d3c65afacee Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 9 Feb 2011 15:18:40 +0000 Subject: [PATCH 1576/2215] Updating schedule for devices having dialog open --- telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml | 1 + telldus-gui/Plugins/SchedulerGUISimple/main.qml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 5379f635..647e2b6a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -6,6 +6,7 @@ property ActionPoint actionPoint property alias absoluteHour: inputAbsoluteHourText.text property alias absoluteMinute: inputAbsoluteMinuteText.text + property alias dialogOpacity: container.opacity focus: true Keys.onPressed: { diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index d56acbef..a3639bf8 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -539,6 +539,9 @@ import "schedulerscripts.js" as Scripts //var jobs = new Array(); var points = new Array(); var days = Scripts.getDays(); + if(dialog.dialogOpacity == 1){ + Scripts.setChanged(dialog.actionPoint.deviceRow.deviceId, true); //set the devicerow that the currently visible dialog is connected to as dirty + } for(var i=0;i Date: Thu, 10 Feb 2011 16:28:27 +0000 Subject: [PATCH 1577/2215] Can save and load jobs now. Needs a lot of testing... --- .../SchedulerGUISimple/ActionPoint.qml | 13 +- .../Plugins/SchedulerGUISimple/Dialog.qml | 1 - .../Plugins/SchedulerGUISimple/__init__.js | 116 +++++++----- .../Plugins/SchedulerGUISimple/main.qml | 37 ++-- .../SchedulerGUISimple/schedulerscripts.js | 170 +++++++++++++----- 5 files changed, 222 insertions(+), 115 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index de8fe820..0ed7ce65 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -94,10 +94,10 @@ Rectangle{ onClicked: { if (mouse.button == Qt.RightButton){ pointRect.toggleType() - dialog.show(pointRect) + //dialog.show(pointRect) } else{ - dialog.show(pointRect) + //dialog.show(pointRect) } } @@ -288,11 +288,9 @@ Rectangle{ break; } } - if(index == activeStates.length){ index = 0; //return to beginning again } - pointRect.state = activeStates[index]; } @@ -317,6 +315,9 @@ Rectangle{ } function updateChanges(){ + if(pointRect.deviceRow == null || (pointRect.deviceRow.isLoading != undefined && pointRect.deviceRow.isLoading())){ + return; //loading values from storage, wait until everything is in place + } Scripts.updateParentWithCurrentValues(); Scripts.updateChildPoints(); if(pointRect.triggerstate == "absolute"){ @@ -373,9 +374,9 @@ Rectangle{ return [hours, partOfHour]; } - function addState(state){ + function addActiveState(state){ //print("Adding state: " + state); - Scripts.addState(state); + Scripts.addActiveState(state); } function setActiveStates(activeStates){ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 647e2b6a..cef48f3c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -435,7 +435,6 @@ Rectangle{ id: inputAbsoluteMinute - property alias absoluteMinute: inputAbsoluteMinuteText.text width: 35 height: inputAbsoluteMinuteText.height border.width: 1 diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index faf87129..c3e59e4a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -15,10 +15,12 @@ com.telldus.schedulersimplegui = function() { addJobsToSchedule: addJobsToSchedule, getJob: getJob, getMethodFromState: getMethodFromState, + getStateFromMethod: getStateFromMethod, getSunRiseTime: getSunRiseTime, getSunSetTime: getSunSetTime, getSunData: getSunData, - getTypeFromTriggerstate: getTypeFromTriggerstate + getTypeFromTriggerstate: getTypeFromTriggerstate, + getTriggerstateFromType: getTriggerstateFromType }); //devices: @@ -34,49 +36,8 @@ com.telldus.schedulersimplegui = function() { //Listen for device-change com.telldus.core.deviceChange.connect(deviceChange); - //points: - //from storage... - var weekPointList = new com.telldus.qml.array(); - var dummypoint = {}; - dummypoint["day"] = 0; - dummypoint["deviceId"] = 1; - weekPointList.push(dummypoint); - dummypoint = {}; - dummypoint["day"] = 1; - dummypoint["deviceId"] = 2; - weekPointList.push(dummypoint); - - var now = new Date(); - var time1 = now.getHours() * 3600 + now.getMinutes() * 60 + now.getSeconds(); - print(time1); // 48880 - time2 = time1 + 30; - time3 = time1 - 60; - time1 = time1 + 50; - - var startdate = now; //new Date(2011,0,5).getTime(); - //var startdate2 = new Date(2011,0,5).getTime(); - - //ID = ID for storage - //Key is position in list, returned from "addJob" - //var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); return 42; }; - var job = new com.telldus.scheduler.JobRecurringWeek({id: 4, executeFunc: null, name: "testnamn14", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate, lastRun: 0, device: 1, method: 1, value: ""}); - var event = {}; - event.d = {id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: 300}; //(new Date().getTime())/1000 + 20 - job.addEvent(event); - //job.addEvent(new Event({id: 0, value: "", fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 10, time: (new Date().getTime())/1000 + 20})); - - var jobs = new Array(); - jobs.push(job); - - job = new com.telldus.scheduler.JobRecurringWeek({id: 4, executeFunc: null, name: "testnamn15", type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: startdate, lastRun: 0, device: 1, method: 1, value: ""}); - var event = {}; - event.d = {id: 0, value: 3, fuzzinessBefore: 0, fuzzinessAfter: 0, type: com.telldus.scheduler.EVENTTYPE_ABSOLUTE, offset: 0, time: 100}; //(new Date().getTime())/1000 + 20 - job.addEvent(event); - jobs.push(job); - - //END FROM STORAGE - - view.setProperty('weekPointList', weekPointList); + var storedPoints = loadJobs(); + view.setProperty('storedPoints', storedPoints); //set images: view.setProperty("imageTriggerSunrise", "sunrise.png"); @@ -110,9 +71,8 @@ com.telldus.schedulersimplegui = function() { deviceList.push(item); } } - - function addJobsToSchedule(points, deviceTimerKeys){ + function addJobsToSchedule(deviceId, points, deviceTimerKeys){ //delete all current schedules for this device: if(deviceTimerKeys != undefined){ for(var i=0;i från __init__.js - //for(var i in weekPointList){ - for(var i=0;i Date: Mon, 14 Feb 2011 13:04:42 +0000 Subject: [PATCH 1578/2215] Added icon to ConfigurationDialog::addPage() --- telldus-gui/TelldusCenter/configurationdialog.cpp | 4 ++-- telldus-gui/TelldusCenter/configurationdialog.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-gui/TelldusCenter/configurationdialog.cpp b/telldus-gui/TelldusCenter/configurationdialog.cpp index 5dbb3727..c608f111 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.cpp +++ b/telldus-gui/TelldusCenter/configurationdialog.cpp @@ -75,7 +75,7 @@ ConfigurationDialog::~ConfigurationDialog() { delete d; } -QScriptValue ConfigurationDialog::addPage( const QString &name, const QString &filename ) { +QScriptValue ConfigurationDialog::addPage( const QString &name, const QString &filename, const QString &icon ) { QDir dir = this->baseDir(); QUiLoader loader; @@ -86,7 +86,7 @@ QScriptValue ConfigurationDialog::addPage( const QString &name, const QString &f int index = d->stackedLayout->addWidget(widget); - QListWidgetItem *item = new QListWidgetItem(QIcon(":images/TelldusCenter_128.png"), name, d->listWidget); + QListWidgetItem *item = new QListWidgetItem(QIcon(dir.filePath(icon)), name, d->listWidget); QString plugin = this->currentPlugin(); item->setData(Qt::UserRole, plugin); d->listWidget->addItem(item); diff --git a/telldus-gui/TelldusCenter/configurationdialog.h b/telldus-gui/TelldusCenter/configurationdialog.h index e5ea9572..171500fc 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.h +++ b/telldus-gui/TelldusCenter/configurationdialog.h @@ -19,7 +19,7 @@ signals: void save(); public slots: - QScriptValue addPage( const QString &name, const QString &file ); + QScriptValue addPage( const QString &name, const QString &file, const QString &icon ); void open(); void valueChanged(); From 0ec9cc99cf1ae9a873c44eb7986bd04019551462 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 14 Feb 2011 13:06:11 +0000 Subject: [PATCH 1579/2215] Added configuration dialog that shows current status for Live --- telldus-gui/Plugins/Live/CMakeLists.txt | 5 ++ telldus-gui/Plugins/Live/LiveObject.cpp | 27 ++++-- telldus-gui/Plugins/Live/LiveObject.h | 10 ++- telldus-gui/Plugins/Live/__init__.js | 96 ++++++++++++---------- telldus-gui/Plugins/Live/configuration.ui | 45 ++++++++++ telldus-gui/Plugins/Live/icon.png | Bin 0 -> 1516 bytes 6 files changed, 129 insertions(+), 54 deletions(-) create mode 100644 telldus-gui/Plugins/Live/configuration.ui create mode 100755 telldus-gui/Plugins/Live/icon.png diff --git a/telldus-gui/Plugins/Live/CMakeLists.txt b/telldus-gui/Plugins/Live/CMakeLists.txt index 5869b291..7afa0a3e 100644 --- a/telldus-gui/Plugins/Live/CMakeLists.txt +++ b/telldus-gui/Plugins/Live/CMakeLists.txt @@ -22,6 +22,11 @@ SET( Plugin_MOC_HDRS LiveObject.h ) +SET( Plugin_EXTRA + configuration.ui + icon.png +) + CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/parsed/config.h diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 7ed8c44e..bf75d4ad 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -87,7 +87,8 @@ void LiveObject::connectToServer() { } else { d->socket->abort(); PrivateData::Server server = d->serverList.takeFirst(); - qDebug() << "Connecting to" << server.address; + emit errorChanged(""); + emit statusChanged("Connecting to server " + server.address); d->socket->connectToHostEncrypted(server.address, server.port); } } @@ -115,6 +116,7 @@ void LiveObject::readyRead() { } else if (msg->name() == "registered") { d->registered = true; emit registered(msg->argument(0)); + emit errorChanged("Registered"); } else if (msg->name() == "notregistered") { LiveMessageToken token = msg->arg(0); if (token.valueType != LiveMessageToken::Dictionary) { @@ -125,12 +127,15 @@ void LiveObject::readyRead() { QSettings s; s.setValue("Live/UUID", d->uuid); emit notRegistered(); + emit errorChanged("Not registered"); } else { emit messageReceived(msg.data()); } } void LiveObject::refreshServerList() { + emit errorChanged(""); + emit statusChanged("Discover servers"); d->serverList.clear(); QUrl url(TELLDUS_LIVE_URI); QPair version("protocolVersion", "1"); @@ -183,6 +188,8 @@ void LiveObject::p_connected() { msg.append(generateVersionToken()); this->sendMessage(msg); + emit errorChanged(""); + emit statusChanged("Connected"); emit connected(); } @@ -192,15 +199,16 @@ void LiveObject::p_disconnected() { } void LiveObject::error( QAbstractSocket::SocketError socketError ) { - qDebug() << "Error:" << socketError; + emit errorChanged(d->socket->errorString()); } void LiveObject::stateChanged( QAbstractSocket::SocketState socketState ) { if (socketState == QAbstractSocket::UnconnectedState) { - QTimer::singleShot(10000, this, SLOT(connectToServer())); - qDebug() << "Reconnect in 10 seconds..."; + int timeout = rand() % 20 + 10; //Random timeout from 10-30s to avoid flooding the servers + QTimer::singleShot(timeout*1000, this, SLOT(connectToServer())); + emit statusChanged("Reconnecting in " + QString::number(timeout) + " seconds..."); } else if (socketState == QAbstractSocket::ConnectingState) { - qDebug() << "Connecting..."; + emit statusChanged("Connecting..."); } else { //qDebug() << "State:" << socketState; } @@ -214,7 +222,8 @@ void LiveObject::sslErrors( const QList & errors ) { continue; default: everythingOK = false; - qDebug() << "SSLErrors" << error; + emit statusChanged("SSL Error"); + emit errorChanged(error.errorString()); break; } } @@ -246,8 +255,10 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { d->serverRefreshTime = QDateTime::currentDateTime(); QTimer::singleShot(0, this, SLOT(connectToServer())); } else { - QTimer::singleShot(10000, this, SLOT(connectToServer())); - qDebug() << "No server found, retry in 10 seconds..."; + int timeout = rand() % 20 + 10; //Random timeout from 10-30s to avoid flooding the servers + emit errorChanged("No servers found"); + emit statusChanged("Retrying in " + QString::number(timeout) + " seconds..."); + QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer())); } r->deleteLater(); } diff --git a/telldus-gui/Plugins/Live/LiveObject.h b/telldus-gui/Plugins/Live/LiveObject.h index 597d5863..a0b93089 100644 --- a/telldus-gui/Plugins/Live/LiveObject.h +++ b/telldus-gui/Plugins/Live/LiveObject.h @@ -32,12 +32,14 @@ signals: void messageReceived(LiveMessage *message); void notRegistered(); void registered(LiveMessageTokenScriptWrapper *params); + void errorChanged(const QString &message); + void statusChanged(const QString &message); private slots: - void p_connected(); - void p_disconnected(); - void readyRead(); - void error( QAbstractSocket::SocketError socketError ); + void p_connected(); + void p_disconnected(); + void readyRead(); + void error( QAbstractSocket::SocketError socketError ); void stateChanged( QAbstractSocket::SocketState socketState ); void sslErrors( const QList & errors ); void serverAssignReply(QNetworkReply*); diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index d37feb3c..a255ee79 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -1,22 +1,26 @@ __setupPackage__( __extension__ ); com.telldus.live = function() { - var socket = null; - var menuId = 0; - var separatorId = 0; - var isRegistered = false; - var supportedMethods = 0; - + var socket = null; + var menuId = 0; + var separatorId = 0; + var isRegistered = false; + var supportedMethods = 0; + var configUI = null; + function init() { + configUI = application.configuration.addPage('Telldus Live!', 'configuration.ui', 'icon.png'); socket = new LiveSocket(); + socket.errorChanged.connect(errorChanged); + socket.statusChanged.connect(statusChanged); socket.notRegistered.connect(notRegistered); socket.registered.connect(registered); socket.messageReceived.connect(messageReceived); socket.connectToServer(); - com.telldus.core.deviceEvent.connect(deviceEvent); - com.telldus.core.deviceChange.connect(sendDevicesReport); + com.telldus.core.deviceEvent.connect(deviceEvent); + com.telldus.core.deviceChange.connect(sendDevicesReport); } - + function notRegistered() { isRegistered = false; if (com.telldus.systray && !menuId) { @@ -25,18 +29,18 @@ com.telldus.live = function() { com.telldus.systray.menuItem(menuId).triggered.connect(socket.activate); } } - + function deviceEvent(deviceId, method, data) { - msg = new LiveMessage("DeviceEvent"); - msg.append(deviceId); - msg.append(method); - msg.append(data); - socket.sendMessage(msg); + msg = new LiveMessage("DeviceEvent"); + msg.append(deviceId); + msg.append(method); + msg.append(data); + socket.sendMessage(msg); } - + function deviceChangeEvent() { } - + function messageReceived(msg) { if (msg.name() == "turnon") { com.telldus.core.turnOn( msg.argument(0).intVal() ); @@ -49,39 +53,47 @@ com.telldus.live = function() { } print("Received: " + msg.name()); } - + function registered(msg) { - if (menuId > 0) { - com.telldus.systray.removeMenuItem(menuId); - com.telldus.systray.removeMenuItem(separatorId); - menuId = 0; - separatorId = 0; - } - supportedMethods = msg.getInt('supportedMethods'); - isRegistered = true; - sendDevicesReport(); + if (menuId > 0) { + com.telldus.systray.removeMenuItem(menuId); + com.telldus.systray.removeMenuItem(separatorId); + menuId = 0; + separatorId = 0; + } + supportedMethods = msg.getInt('supportedMethods'); + isRegistered = true; + sendDevicesReport(); } - + function sendDevicesReport() { - if (!isRegistered) { - return; - } - msg = new LiveMessage("DevicesReport"); - var deviceList = com.telldus.core.deviceList.getList(); - list = new LiveMessageToken(); + if (!isRegistered) { + return; + } + msg = new LiveMessage("DevicesReport"); + var deviceList = com.telldus.core.deviceList.getList(); + list = new LiveMessageToken(); for( i in deviceList ) { - device = new LiveMessageToken(); - device.set('id', deviceList[i].id); - device.set('name', deviceList[i].name); - device.set('methods', com.telldus.core.methods(deviceList[i].id, supportedMethods) ); - device.set('state', com.telldus.core.lastSentCommand(deviceList[i].id, supportedMethods) ); - device.set('stateValue', com.telldus.core.lastSentValue(deviceList[i].id, supportedMethods) ); - list.add(device); + device = new LiveMessageToken(); + device.set('id', deviceList[i].id); + device.set('name', deviceList[i].name); + device.set('methods', com.telldus.core.methods(deviceList[i].id, supportedMethods) ); + device.set('state', com.telldus.core.lastSentCommand(deviceList[i].id, supportedMethods) ); + device.set('stateValue', com.telldus.core.lastSentValue(deviceList[i].id, supportedMethods) ); + list.add(device); } msg.appendToken(list); socket.sendMessage(msg); } - + + function errorChanged(msg) { + configUI.findChild('errorLabel').text = msg; + } + + function statusChanged(msg) { + configUI.findChild('statusLabel').text = msg; + } + return { //Public functions init:init } diff --git a/telldus-gui/Plugins/Live/configuration.ui b/telldus-gui/Plugins/Live/configuration.ui new file mode 100644 index 00000000..608ffc5a --- /dev/null +++ b/telldus-gui/Plugins/Live/configuration.ui @@ -0,0 +1,45 @@ + + + Form + + + + 0 + 0 + 323 + 263 + + + + Form + + + + + + Status: + + + + + + + unknown + + + + + + + + + + true + + + + + + + + diff --git a/telldus-gui/Plugins/Live/icon.png b/telldus-gui/Plugins/Live/icon.png new file mode 100755 index 0000000000000000000000000000000000000000..1686c14f4be40a44eb749f4487caddcd736c4d3d GIT binary patch literal 1516 zcmVw zV!?r;Sb3#FHAn?Q@R0}~s00kZBGa-v&faUUwf8>v3g7o}KZnkLj8GXI z+rpA3nwyq3u3j~KWgz6=V`M@ISyMaD>gqUtvg7oT6S`p{O+E$tp@(Aa^ILar-u~7{ z;qquyN^M%Abv+kWGLblRV9y6FKknb{d%mXt%&l)|dguMUM-4L+wi(ql(an?^rU}pU z(x2_xvHnue*;XaN{705Io8f3UF+Rdv1uLgxkZCuSLV2XpSg@#ZE!_zKkUYBOIB;Aa zC3zP)p_MRf*MX4I$R?rZ`M&EBx)KdpwgX9w8G30s<0xN2k_P}N1lRY}ELKaG&^FAk z#z?|O|4}>#T1Y0dD(UP?VH6jkWRaJxV92opIZz~O8ow3KUz-rB4xY8hAgNE zMUMPQlZqU=l{kXcHV6oscl8%;w; z=f&&Tz5fIbwO&A)L~V#wW81TjQ*sHlrjVV?2mtsQ7VbVBkEs*bvc3VYZ*IiA*)wqP z=y`n8(xoC=yr3GZm(L{@oWk~UTQQjpBq*R>lC*DntQIR9YSndpT@}9k=`Z}+)`vOO zQEXTl!x{q6);)wVN={vuceIo1M+W6AR0Hzp*G2F%^{TLayFsm}GfLW~bBpVsqs@aJg07=)yxZ}d72SNeK*NdHpOaoiiEyAX! z7h*V`!siFuF?ekZm5~ruEqMr+ZzRxnbyOLxtC^9dIWzs>KvKCDx5%IE<^Uk)1EWa{ zjU_Qk`f;ORFiIZ5oy)~D%j&R!vi(Vt;LVpBVbPvb-B;9_xiuBa$uLy~kBV}WEDN=l zBjsl)s`HyE8<)w)AWgo`=71(7BsGzg?ID%2pwqRf3xw!Y)akxrAe3zx2ov=h>FZ2r z$rAb^Ut^ndigLy#M;1*kT`oTcWK!qUrML}1N}(EvFtlugAS|RKwOWU0qmAF4>P1yW z2sJapIB@KOqOj@F*=p@SloxTjuB7KYu8yWKOi36v1A9y+H!MvHr01aMESLm9qq9NN z^A8&CSQCq`k6HNS`*zHEAfiCLO)|tN`M4GT(m8;cRbeccU8%PA4Udr%p(4eEl(_|F zP#=*ZmjSw9RK6ysJoWg%Nmywtq!zq$$^_y)D*nb8ogjihjXFplz& zK{oGvNHN7Tw6FA#{11Eci5e@73_INK&Ubu>ll$@KIVroqbv2kI18~}~h_1zf9SFIOu zE0IPIwPoHPE;EXHJu@^-`OGUrj$SWHf(av(5AFT86wOhJT9oiA&0r^$p%h$ZzE;}1 zT{I(EiSLp+OTce3Sqb2~CLK1eErXMB8VBcxLB7bRlLhc!cl#f%ov_1^h?%ymlISeS zIWeWvhl%f|y?@W0X;r~zKF!u_+41g+uf4Y`6p5Dko;NK3IPvUc(*Akhryn2wde4XS zg%o_6(I*+4w2j!370vUPHZ@a85{P^LaVp54-S>CfvEGhTNAo^T@8|emfB^uU)7&#) SZ+N)?0000 Date: Mon, 14 Feb 2011 13:16:30 +0000 Subject: [PATCH 1580/2215] Better handling of fuzzify allowing events to be run in fuzzy interval, even if job is loaded after the execution time, and not rerun if already executed in the interval already (implementing lastRun) --- .../Plugins/Scheduler/DefaultJobTypes.js | 27 ++--- telldus-gui/Plugins/Scheduler/__init__.js | 31 ++++-- .../SchedulerGUISimple/ActionPoint.qml | 2 + .../Plugins/SchedulerGUISimple/Dialog.qml | 5 + .../Plugins/SchedulerGUISimple/__init__.js | 100 +++++++++++++----- .../Plugins/SchedulerGUISimple/main.qml | 21 +++- .../SchedulerGUISimple/schedulerscripts.js | 34 ++++-- 7 files changed, 163 insertions(+), 57 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js index 3a8eaca8..4f4dcd2d 100644 --- a/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js +++ b/telldus-gui/Plugins/Scheduler/DefaultJobTypes.js @@ -8,7 +8,7 @@ com.telldus.scheduler.EVENTTYPE_SUNRISE = 1; com.telldus.scheduler.EVENTTYPE_SUNSET = 2; -function getEventRunTime(event, date){ +function getEventRunTime(event, date, lastRun){ var currentEventRuntimeTimestamp = null; var offset = event.d.offset; if(isNaN(offset)){ @@ -22,13 +22,13 @@ function getEventRunTime(event, date){ //print("currentEventRuntimeTimestamp: " + new Date(currentEventRuntimeTimestamp)); currentEventRuntimeTimestamp += (offset * 1000); //this is really not useful for absolute values, but exists for consistency //print("currentEventRuntimeTimestamp1: " + new Date(currentEventRuntimeTimestamp)); - currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); + currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter), lastRun); //print("currentEventRuntimeTimestamp2: " + new Date(currentEventRuntimeTimestamp)); } else if(event.d.type == com.telldus.scheduler.EVENTTYPE_SUNRISE || event.d.type == com.telldus.scheduler.EVENTTYPE_SUNSET){ currentEventRuntimeTimestamp = getSunUpDownForDate(date, parseInt(event.d.type)); currentEventRuntimeTimestamp += (offset * 1000); - currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter)); + currentEventRuntimeTimestamp = com.telldus.scheduler.fuzzify(currentEventRuntimeTimestamp, parseInt(event.d.fuzzinessBefore), parseInt(event.d.fuzzinessAfter), lastRun); } return currentEventRuntimeTimestamp; @@ -84,14 +84,15 @@ function getJob(jobdata){ * but wasn't, because of a reboot or similar (in seconds) * note, must in that case have checked last run */ -function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod){ +function getNextEventRunTime(nextRunTime, event, date, pastGracePeriod, lastRun){ if(!pastGracePeriod){ var pastGracePeriod = 0; } - var currentEventRuntimeTimestamp = getEventRunTime(event, date); + var currentEventRuntimeTimestamp = getEventRunTime(event, date, lastRun); print("EventRunTime: " + new Date(currentEventRuntimeTimestamp)); + if((nextRunTime === null || currentEventRuntimeTimestamp < nextRunTime) && currentEventRuntimeTimestamp > (new Date().getTime() - pastGracePeriod)){ //earlier than other events, but later than "now" nextRunTime = currentEventRuntimeTimestamp; } @@ -136,6 +137,7 @@ function getSunUpDownForDate(datetimestamp, sun){ return date.getTime(); } +/* function loadJobs(){ print("Loading jobs"); //TODO detta ska inte göras från denna plugin, utan från respektive... @@ -176,7 +178,8 @@ function loadJobs(){ var tempkey = com.telldus.scheduler.addJob(job); //TODO, use different function than this = only sort list afterwards (one time) and dont start timer until all initial are added } */ -} +//} + /* * updateLastRun-example: @@ -296,7 +299,7 @@ com.telldus.scheduler.JobAbsolute.prototype.getNextRunTime = function(){ var pastGracePeriod = getGracePeriod(this.v); for(var key in this.v.events){ - nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], 0, pastGracePeriod); + nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], 0, pastGracePeriod, this.v.lastRun); } return nextRunTime; } @@ -310,7 +313,7 @@ com.telldus.scheduler.JobRecurringDay.prototype.getNextRunTime = function(){ var date; if(this.v.lastRun > 0){ - var lastRunDate = new Date(this.lastRun); + var lastRunDate = new Date(this.v.lastRun); //TEST changed from this.lastRun, test this! date = new Date(lastRunDate.getFullYear(), lastRunDate.getMonth(), lastRunDate.getDate()); date = date.getTime() + this.v.events[0].d.value; //add interval } @@ -324,11 +327,11 @@ com.telldus.scheduler.JobRecurringDay.prototype.getNextRunTime = function(){ } date = new Date(startTime.getFullYear(), startTime.getMonth(), startTime.getDate()); } - nextRunTime = getNextEventRunTime(null, this.v.events[0], date.getTime(), pastGracePeriod); + nextRunTime = getNextEventRunTime(null, this.v.events[0], date.getTime(), pastGracePeriod, this.v.lastRun); if(nextRunTime < new Date().getTime()){ var runTime = new Date(date); runTime.setDate(runTime.getDate() + parseInt(this.v.events[0].d.value)); - nextRunTime = getNextEventRunTime(null, this.v.events[0], runTime.getTime(), pastGracePeriod); //already passed this time today, try again after "interval" days + nextRunTime = getNextEventRunTime(null, this.v.events[0], runTime.getTime(), pastGracePeriod, this.v.lastRun); //already passed this time today, try again after "interval" days } return nextRunTime; @@ -363,10 +366,10 @@ com.telldus.scheduler.JobRecurringWeek.prototype.getNextRunTime = function(){ returnDate = zeroTime(returnDate); - nextTempRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); + nextTempRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod, this.v.lastRun); if(nextTempRunTime < new Date().getTime()){ //event happened today, already passed, add to next week instead returnDate.setDate(returnDate.getDate() + 7); - nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod); + nextRunTime = getNextEventRunTime(nextRunTime, this.v.events[key], returnDate.getTime(), pastGracePeriod, this.v.lastRun); } else{ nextRunTime = nextTempRunTime; diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index eb1c3e7b..32549a40 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -35,7 +35,6 @@ com.telldus.scheduler = function() { } var key = storedJobs.push(job); job.key = key; - print("Add job"); updateJobInList(key); return key; } @@ -61,8 +60,19 @@ com.telldus.scheduler = function() { return returnKeys; } - function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter){ + function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter, lastRun){ if(fuzzinessAfter != 0 || fuzzinessBefore != 0){ + var now = new Date().getTime(); + if(currentTimestamp - (fuzzinessBefore*1000) < now){ + fuzzinessBefore = (currentTimestamp - now)/1000; //we have already entered the fuzzy-interval, move the start point to "now"... + } + //print("LASTRUN: " + new Date(lastRun)); + //print("COMPARE: " + new Date(currentTimestamp - (fuzzinessBefore*1000))); + if(lastRun != undefined && lastRun >= (currentTimestamp - (fuzzinessBefore*1000))){ + //print("JUST RETURNING"); + return 0; //job already run in this interval, don't run it again... + } + //print("CONTINUING HAPPILY"); var interval = fuzzinessAfter + fuzzinessBefore; var rand = Math.random(); //Random enough at the moment var fuzziness = Math.floor((interval+1) * rand); @@ -312,9 +322,20 @@ com.telldus.scheduler.Job.prototype.execute = function(){ return success; } + success = this.executeDefault(); + + //if(success){ + //update last run even if not successful, else it may become an infinite loop (if using pastGracePeriod) + this.updateJobLastRun(); + //} + return success; +}; + +com.telldus.scheduler.Job.prototype.executeDefault = function(){ + var success = 0; deviceid = this.v.device; var method = parseInt(this.v.method); - print("Job id: " + this.v.device + " Method: " + method); + //print("Job id: " + this.v.device + " Method: " + method); switch(method){ case com.telldus.core.TELLSTICK_TURNON: success = com.telldus.core.turnOn(deviceid); @@ -331,10 +352,6 @@ com.telldus.scheduler.Job.prototype.execute = function(){ default: break; } - //if(success){ - //update last run even if not successful, else it may become an infinite loop (if using pastGracePeriod) - this.updateJobLastRun(); - //} return success; }; diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 0ed7ce65..25900747 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -18,6 +18,8 @@ Rectangle{ property int absoluteMinute: parseInt(dialog.absoluteMinute, 10) property alias triggerstate: trigger.state property variant parentPoint + property variant pointId + property variant lastRun: 0; //property int parentPointAbsoluteHour //TEST changed from int, want "undefined" property alias deviceRow: pointRect.parent diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index cef48f3c..bda80d72 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -47,6 +47,11 @@ } event.accepted = true; } + else if( event.key == Qt.Key_Delete){ + //TODO warning? + container.actionPoint.remove(); + + } else{ return; } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index c3e59e4a..765d735d 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -20,7 +20,8 @@ com.telldus.schedulersimplegui = function() { getSunSetTime: getSunSetTime, getSunData: getSunData, getTypeFromTriggerstate: getTypeFromTriggerstate, - getTriggerstateFromType: getTriggerstateFromType + getTriggerstateFromType: getTriggerstateFromType, + restoreJobs: restoreJobs }); //devices: @@ -36,8 +37,8 @@ com.telldus.schedulersimplegui = function() { //Listen for device-change com.telldus.core.deviceChange.connect(deviceChange); - var storedPoints = loadJobs(); - view.setProperty('storedPoints', storedPoints); + //var storedPoints = loadJobs(); + //view.setProperty('storedPoints', storedPoints); //set images: view.setProperty("imageTriggerSunrise", "sunrise.png"); @@ -72,7 +73,7 @@ com.telldus.schedulersimplegui = function() { } } - function addJobsToSchedule(deviceId, points, deviceTimerKeys){ + function addJobsToSchedule(deviceId, points, deviceTimerKeys, callbackFunc){ //delete all current schedules for this device: if(deviceTimerKeys != undefined){ for(var i=0;i Date: Mon, 14 Feb 2011 13:55:36 +0000 Subject: [PATCH 1581/2215] Fuzzy-fix --- telldus-gui/Plugins/Scheduler/__init__.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 32549a40..9c1ba873 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -63,12 +63,15 @@ com.telldus.scheduler = function() { function fuzzify(currentTimestamp, fuzzinessBefore, fuzzinessAfter, lastRun){ if(fuzzinessAfter != 0 || fuzzinessBefore != 0){ var now = new Date().getTime(); + var fuzzinessBeforeOrig = fuzzinessBefore*1000; if(currentTimestamp - (fuzzinessBefore*1000) < now){ + //print("Already in interval"); fuzzinessBefore = (currentTimestamp - now)/1000; //we have already entered the fuzzy-interval, move the start point to "now"... } - //print("LASTRUN: " + new Date(lastRun)); - //print("COMPARE: " + new Date(currentTimestamp - (fuzzinessBefore*1000))); - if(lastRun != undefined && lastRun >= (currentTimestamp - (fuzzinessBefore*1000))){ + //print("LASTRUN: " + lastRun + " - " + new Date(lastRun)); + //print("COMPARE: " + (currentTimestamp - (fuzzinessBefore*1000)) + " - " + new Date(currentTimestamp - (fuzzinessBefore*1000))); + //print("COMPARE: " + (currentTimestamp - fuzzinessBeforeOrig) + " - " + new Date(currentTimestamp - fuzzinessBeforeOrig)); + if(lastRun != undefined && lastRun >= (currentTimestamp - fuzzinessBeforeOrig)){ //print("JUST RETURNING"); return 0; //job already run in this interval, don't run it again... } From 0e157f9fb9454097f5e3f6add38951cd85219ec2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 14 Feb 2011 15:10:35 +0000 Subject: [PATCH 1582/2215] Daylight savings time-job only added if other jobs exists. --- telldus-gui/Plugins/Scheduler/__init__.js | 5 ++++- .../Plugins/SchedulerGUISimple/Dialog.qml | 8 ++++++-- .../Plugins/SchedulerGUISimple/main.qml | 19 ------------------- .../SchedulerGUISimple/schedulerscripts.js | 2 ++ 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index 9c1ba873..b749cf7f 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -41,12 +41,15 @@ com.telldus.scheduler = function() { //add several jobs at once, withou recalculating timer between each function addJobs(jobs){ + var returnKeys = new Array(); + if(jobs == undefined || jobs.length == 0){ + return returnKeys; + } if(storedJobs.length == 0){ print("Adding daylight saving time"); var daylightSavingReloadKey = storedJobs.push(getDaylightSavingReloadJob()); updateJobInList(daylightSavingReloadKey, true); //waitForMore = don't sort array and recalculate timer yet } - var returnKeys = new Array(); for(var i=0;i Date: Wed, 16 Feb 2011 10:58:30 +0000 Subject: [PATCH 1583/2215] Code cleanup --- telldus-gui/Plugins/Scheduler/__init__.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/Scheduler/__init__.js b/telldus-gui/Plugins/Scheduler/__init__.js index b749cf7f..2cfeba79 100644 --- a/telldus-gui/Plugins/Scheduler/__init__.js +++ b/telldus-gui/Plugins/Scheduler/__init__.js @@ -23,7 +23,6 @@ com.telldus.scheduler = function() { function init(){ JobDaylightSavingReload.prototype = new com.telldus.scheduler.Job(); setDaylightSavingJobFunctions(); - //loadJobs(); //TODO remove this after testing is done } @@ -59,7 +58,6 @@ com.telldus.scheduler = function() { } joblist.sort(compareTime); runNextJob(); - return returnKeys; } @@ -234,7 +232,7 @@ com.telldus.scheduler = function() { JobDaylightSavingReload.prototype.execute = function(){ //override default print("Daylight savings job"); - //TODO Make sure this job is run "last", if other jobs are set to be runt the same second + //TODO Make sure this job is run "last", if other jobs are set to be run at the same second setTimeout(recalculateAllJobs(), 1); //sleep for one ms, to avoid strange calculations //this may lead to that things that should be executed exactly at 3.00 when //moving time forward one hour won't run, but that should be the only case @@ -301,7 +299,6 @@ com.telldus.scheduler = function() { removeJob: removeJob, //storage id updateJob: updateJob, //storage id, job updateLastRun: updateLastRun, //id, datetimestamp - //TODO getNextRunForJob? For all? (to see when job is due to run next) init:init } }(); From 84d6008dee337aa50e80412ba9a8fa1e8b5e45ed Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 16 Feb 2011 11:03:41 +0000 Subject: [PATCH 1584/2215] Code cleanup, refactoring --- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 2 + .../Plugins/SchedulerGUISimple/NavButton.qml | 24 ++++ .../Plugins/SchedulerGUISimple/mainscripts.js | 129 ++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/NavButton.qml create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 7f70b17e..4ad22112 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -12,6 +12,8 @@ SET( Plugin_EXTRA Dialog.qml icon.png main.qml + mainscripts.js + NavButton.qml schedulerscripts.js absolute.png sunrise.png diff --git a/telldus-gui/Plugins/SchedulerGUISimple/NavButton.qml b/telldus-gui/Plugins/SchedulerGUISimple/NavButton.qml new file mode 100644 index 00000000..0156cf8c --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/NavButton.qml @@ -0,0 +1,24 @@ +import Qt 4.7 + +Rectangle{ + id: navButton + property string arrowText: "" + signal clicked() + height: 20 + width: 20 + border.color: "red" + Text{ + anchors.centerIn: parent + text: arrowText + } + MouseArea{ + anchors.fill: parent + onClicked: { + //step to prev weekday + dialog.hide() + main.updateEndsWith() + navButton.clicked() + main.updateCurrentDay() + } + } +} diff --git a/telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js new file mode 100644 index 00000000..7880e935 --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js @@ -0,0 +1,129 @@ +var calculatedSunData; + +function getEveningDarkStart(){ + if(!willSunSet()){ + return 0; + } + if(isMidnightDark()){ + var sunData = getSunData(); + return sunToTimeUnits(sunData[1]); + } + else{ + return 0; + } +} + +function getEveningDarkWidth(){ + if(!willSunSet()){ + return 0; + } + if(isMidnightDark()){ + var sunData = getSunData(); + return constDeviceRowWidth - sunToTimeUnits(sunData[1]); + } + else{ + return 0; + } +} + +function getMorningDarkStart(){ + //TODO the day of the year when the sun "begins" not to set, will it work then? + if(!willSunSet()){ + return 0; + } + if(isMidnightDark()){ + return 0; + } + else{ + var sunData = getSunData(); + var start = sunToTimeUnits(sunData[1]); + if(start == undefined){ + return 0; + } + return start; + } +} + +function getMorningDarkWidth(){ + if(!willSunSet()){ + return 0; + } + var sunData = getSunData(); + if(isMidnightDark()){ + return sunToTimeUnits(sunData[0]); + } + else{ + return sunToTimeUnits(sunData[1]) - sunToTimeUnits(sunData[0]); + } +} + +function getSunData(){ + if(calculatedSunData == undefined){ + main.updateCurrentDay(); + } + if(calculatedSunData[0] == undefined){ + return ["0:0","0:0","0:0"]; //TODO + } + return calculatedSunData; +} + +function updateSunData(sunData){ + calculatedSunData = sunData; +} + +function isMidnightDark(){ + var sunData = getSunData(); + + var sunrise = sunData[0].split(':');; + var sunset = sunData[1].split(':'); + + if(sunset[0] < sunrise[0] || (sunset[0] == sunrise[0] && sunset[1] < sunrise[1])){ + return false; + } + return true; +} + +function pointToArray(point){ //TODO another way than using arrays... + var deviceId = point.deviceRow.deviceId; + var pointName = "Job_" + deviceId; + var startdate = new Date(); //startdate, not in use, always "now" + var pointDimValue = point.dimvalue * (255/100); + var pointMethod = main.mainGetMethodFromState(point.state); + var pointId = point.pointId; + var lastRun = point.lastRun; + + var pointTime = point.absoluteHour * 3600 + point.absoluteMinute * 60; + var absolutePointTime = pointTime; + var pointType = main.mainGetTypeFromTriggerstate(point.triggerstate); + var sunData = getSunData(); + if(point.triggerstate == "sunrise"){ + var suntime = sunData[0].split(':'); + pointTime = suntime[0] * 3600 + suntime[1] * 60; + } + else if(point.triggerstate == "sunset"){ + var suntime = sunData[1].split(':'); + pointTime = suntime[0] * 3600 + suntime[1] * 60; + } + var pointFuzzinessBefore = point.fuzzyBefore; + var pointFuzzinessAfter = point.fuzzyAfter; + var pointOffset = point.triggerstate == "absolute" ? 0 : point.offset; + + var pointDays = new Array(); + pointDays.push(point.deviceRow.parent.parent.daydate.getDay()); + var childPoints = point.getChildPoints(); + for(var child in childPoints){ + pointDays.push(childPoints[child].deviceRow.parent.parent.daydate.getDay()); //value (day) different per event + } + return new Array(deviceId, pointName, startdate, lastRun, pointMethod, pointDimValue, pointTime, pointType, pointFuzzinessBefore, pointFuzzinessAfter, pointOffset, pointDays, absolutePointTime, pointId); +} + +function sunToTimeUnits(suntime){ + suntime = suntime.split(':'); + var hourSize = constDeviceRowWidth/24; //24 hours... + return hourSize * suntime[0] + hourSize * suntime[1]/60; +} + +function willSunSet(){ + var sunData = getSunData(); + return !(sunData[2] && sunData[2] != "") +} From f808e3b079fb7941b78e8ce3c7069ecbc4ee55d7 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 16 Feb 2011 11:09:38 +0000 Subject: [PATCH 1585/2215] Code cleanup and small fixes: *Sun data is updated when browsing between days (dark/light areas, point positions), *More efficient reuse of sun data, *Moving points with keys only available in state 'absolute', *Removing timers from jobs loaded from storage correctly --- .../SchedulerGUISimple/ActionPoint.qml | 26 +- .../Plugins/SchedulerGUISimple/Dialog.qml | 51 +- .../Plugins/SchedulerGUISimple/__init__.js | 64 +-- .../Plugins/SchedulerGUISimple/main.qml | 487 ++++++------------ .../SchedulerGUISimple/schedulerscripts.js | 26 +- 5 files changed, 207 insertions(+), 447 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 25900747..fd440e4e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -22,6 +22,7 @@ Rectangle{ property variant lastRun: 0; //property int parentPointAbsoluteHour //TEST changed from int, want "undefined" property alias deviceRow: pointRect.parent + property variant selectedDate: (deviceRow == null || deviceRow == undefined) ? new Date() : deviceRow.selectedDate Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... @@ -41,27 +42,10 @@ Rectangle{ z: 100 state: "on" focus: true - //actionTypeColor: getColor() - - //TODO make this work: - /*Keys.onLeftPressed: { - pointRect.x = pointRect.x - 1 - } - Keys.onRightPressed: { - pointRect.x = pointRect.x + 1 - } - - Text { - //focus: true - text: pointRect.activeFocus ? "I HAVE active focus!" : "I do NOT have active focus" - } - */ - //reflect changes on parent/siblings: onAbsoluteHourChanged: { updateChanges(); - //print("ABSOLUTE HOUR CHANGED"); } onAbsoluteMinuteChanged: { @@ -167,14 +151,14 @@ Rectangle{ PropertyChanges { target: triggerImage; source: imageTriggerSunrise; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunRiseTime.callWith(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO se nedan + PropertyChanges { target: pointRect; x: getSunRiseTime.callWith(pointRect.parent.width, pointRect.width, pointRect.selectedDate) + minutesToTimelineUnits(pointRect.offset) } //TODO se nedan }, State { name: "sunset" PropertyChanges { target: triggerImage; source: imageTriggerSunset; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunSetTime.callWith(pointRect.parent.width, pointRect.width) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits + PropertyChanges { target: pointRect; x: getSunSetTime.callWith(pointRect.parent.width, pointRect.width, pointRect.selectedDate) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits }, State { name: "absolute"; when: !pointRectMouseArea.drag.active @@ -272,8 +256,8 @@ Rectangle{ //print("Different x"); point = pointRect.parentPoint; } - //print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); - //print("AbsoluteHour: " +point.absoluteHour+ " hourSize: " + hourSize + " AbsoluteMinute: " + point.absoluteMinute + " Width: " + point.width); + print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); + print("AbsoluteHour: " +point.absoluteHour+ " hourSize: " + hourSize + " AbsoluteMinute: " + point.absoluteMinute + " Width: " + point.width); return point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2; } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index f3f5f3fd..7e75f866 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -11,12 +11,9 @@ focus: true Keys.onPressed: { - tryme(event, "container"); - var hours = 0; var minutes = 0; - if (event.key == Qt.Key_Left) { - //actionPoint.x = actionPoint.x - 1 + if (event.key == Qt.Key_Left && actionPoint.triggerstate == "absolute") { //step left, 1 min var minutes = parseInt(inputAbsoluteMinuteText.text, 10); var hours = parseInt(inputAbsoluteHourText.text, 10); if(minutes == 0){ @@ -31,8 +28,7 @@ } event.accepted = true; } - else if (event.key == Qt.Key_Right) { - //actionPoint.x = actionPoint.x + 1 + else if (event.key == Qt.Key_Right && actionPoint.triggerstate == "absolute") { //step right, 1 min var minutes = parseInt(inputAbsoluteMinuteText.text, 10); var hours = parseInt(inputAbsoluteHourText.text, 10); if(minutes == 59){ @@ -49,9 +45,7 @@ } else if( event.key == Qt.Key_Delete){ //TODO warning? - print("DELETING"); container.actionPoint.remove(); - } else{ return; @@ -69,7 +63,7 @@ //create default actionPoint, to avoid null values and binding errors var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(container) - dynamicPoint.opacity = 0 //TODO why not use "visible"? Test that... + dynamicPoint.opacity = 0 dynamicPoint.width = 0 dynamicPoint.height = 0 container.actionPoint = dynamicPoint @@ -88,7 +82,7 @@ container.actionPoint = actionPoint var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); - container.y = rootCoordinates.y + actionPoint.height + 10; + container.y = rootCoordinates.y + actionPoint.height + 10; //TODO poistion in other way, too far down in some cases now container.width = actionPoint.parent.width; container.x = (actionPoint.parent.parent.width - container.width)/2; container.opacity = 1; @@ -104,8 +98,7 @@ smooth: true radius: 5 - //width: 500 //TODO - height: 500 // typelist.height * 2 + 50 + height: 500 opacity: 0 Button{ @@ -118,11 +111,6 @@ onClicked: { container.actionPoint.toggleType(); } - - Keys.onLeftPressed: { - debug("Left pressed"); //TODO make it work - - } } Button{ @@ -559,13 +547,10 @@ width: weekColumn.width Column{ id: "weekColumn" - //anchors.verticalCenter: parent.verticalCenter - //anchors.fill: parent spacing: 2 Repeater{ id: weekRepeater - model: 7 //actionPoint.daysOfWeek - //delegate: weekDayDelegate + model: 7 //7 days, one week... Rectangle{ width: 30 height: 30 @@ -582,13 +567,11 @@ anchors.fill: parent onClicked: { actionPoint.toggleTickedWeekDay(index) - print("Just toggled, now update image: " + actionPoint); tickBox.source = actionPoint.getTickedImageSource(index) } } } Text{ - //anchors.fill: parent anchors.left: tickBox.right anchors.leftMargin: 10 text: Scripts.getOffsetWeekdayName(index) @@ -611,9 +594,7 @@ id: closeButton text: "Close" anchors.top: weekDayPanel.bottom - anchors.horizontalCenter: weekDayPanel.right //horizontalCenter - //y: circleTrigger.y + 30 - //x: parent.x + 30 + anchors.horizontalCenter: weekDayPanel.right onClicked: { hide(); } @@ -625,20 +606,19 @@ anchors.topMargin: 20 anchors.left: currentType.right anchors.leftMargin: 10 - width: 100 //TODO relative - height: 100 //TODO relative + width: 100 + height: 100 model: typeSelection delegate: typeSelectionRow highlight: Rectangle { color: "lightsteelblue"; radius: 5 } snapMode: ListView.SnapToItem interactive: false - //TODO can these paths be turned into some kind of constants? Import from common file or something? ListModel{ id: typeSelection ListElement{ name: "on" - imagesource: "on.png" //TODO cannot use javascript properties here... do in some other way, maybe a list with names here? + imagesource: "on.png" } ListElement{ name: "off" @@ -683,17 +663,12 @@ width: 30; height: 30 Image{ anchors.fill: parent - //anchors.left: typeSelectionText.right - //anchors.leftMargin: 10 - //anchors.centerIn: parent source: imagesource MouseArea{ anchors.fill: parent onClicked: { - //pointRect.focus = true container.actionPoint.setType(name) - //typeList.highlight = name } } } @@ -701,10 +676,6 @@ } } - function tryme(event, origin){ - print("KEY: " + event.key + " Från: " + origin); - } - function getMinimumOffset(state){ //TODO this will not work if a value is set to the highest limit, then not reentering scheduler until the sunrise/set has changed so much that the device will be hidden anyway... Not common though var minutes = 0; @@ -735,6 +706,6 @@ return 0 ; } - return 24 * 60 - (parseInt(time[0], 10) * 60 + parseInt(time[1], 10)); + return 24 * 60 - (parseInt(time[0], 10) * 60 + parseInt(time[1], 10)); } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 765d735d..3e31376a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -8,10 +8,11 @@ __postInit__ = function() { com.telldus.schedulersimplegui = function() { var deviceList; var view; + var restoredJobsTimerKeys; + var sunData; function init() { view = new com.telldus.qml.view({ - addDevice: addDevice, addJobsToSchedule: addJobsToSchedule, getJob: getJob, getMethodFromState: getMethodFromState, @@ -21,7 +22,8 @@ com.telldus.schedulersimplegui = function() { getSunData: getSunData, getTypeFromTriggerstate: getTypeFromTriggerstate, getTriggerstateFromType: getTriggerstateFromType, - restoreJobs: restoreJobs + restoreJobs: restoreJobs, + updateSunData: updateSunData }); //devices: @@ -37,9 +39,8 @@ com.telldus.schedulersimplegui = function() { //Listen for device-change com.telldus.core.deviceChange.connect(deviceChange); - //var storedPoints = loadJobs(); - //view.setProperty('storedPoints', storedPoints); - + updateSunData(new Date()); //default + //set images: view.setProperty("imageTriggerSunrise", "sunrise.png"); view.setProperty("imageTriggerSunset", "sunset.png"); @@ -55,16 +56,14 @@ com.telldus.schedulersimplegui = function() { view.setProperty("constDeviceRowHeight", 50); view.setProperty("constDeviceRowWidth", 600); view.setProperty("constPointWidth", 30); + view.setProperty("mainHeight", 700); //TODO get this from somewhere + view.setProperty("mainWidth", 800); //TODO get this from somewhere view.load("main.qml"); application.addWidget("scheduler.simple", "icon.png", view); } - function addDevice() { - deviceList.push({name:'Stallet istallet'}); - } - function deviceChange( deviceId, eventType ) { if (eventType == com.telldus.core.TELLSTICK_DEVICE_ADDED) { var item = com.telldus.core.deviceList.getDevice(deviceId); @@ -81,6 +80,13 @@ com.telldus.schedulersimplegui = function() { com.telldus.scheduler.removeJob(deviceTimerKeys[i]); } } + if(restoredJobsTimerKeys != undefined && restoredJobsTimerKeys[deviceId] != undefined){ + for(var i=0;i 0){ + deviceTimerKeys[devicekey] = com.telldus.scheduler.addJobs(jobs); //have to do this per device, so that the timerkeys are stored for each device + } } - return com.telldus.scheduler.addJobs(jobs) + return deviceTimerKeys; } function restoreJob(storedJob, updateLastRunInGUI){ @@ -141,7 +149,6 @@ com.telldus.schedulersimplegui = function() { function getJob(pointArray, updateLastRunInGUI){ //deviceId, pointName, startdate, lastrun, pointMethod, pointDimValue, pointTime, pointType, pointFuzzinessBefore, pointFuzzinessAfter, pointOffset, pointDays //updateLastRunInGUI: deviceId, day of week, id var execFunc = function(job){ print("Custom execute function running"); print("Job: " + job.v.name); var lastRun = new Date().getTime(); updateLastRun(job, lastRun); updateLastRunInGUI(job.v.device, job.v.events[job.v.id + "_0"].d.value, job.v.id, lastRun); return job.executeDefault();}; - print("POINTARRAY3: " + pointArray[3]); var job = new com.telldus.scheduler.JobRecurringWeek({id: pointArray[13], executeFunc: execFunc, name: pointArray[1], type: com.telldus.scheduler.JOBTYPE_RECURRING_WEEK, startdate: pointArray[2], lastRun: pointArray[3], device: pointArray[0], method: pointArray[4], value: pointArray[5], absoluteTime: pointArray[12]}); var event = {}; var pointFuzzinessBefore = (pointArray[8]*60); @@ -160,20 +167,13 @@ com.telldus.schedulersimplegui = function() { return job; } + //Update last run for this job from storage, then store it again function updateLastRun(job, lastRun){ - //TODO uppdatera både storage och värdet i pointen... var settings = new com.telldus.settings(); var storedjobs = settings.value("jobs", ""); - //settings.setValue("test", "TESTAR"); - print("UPDATING LAST RUN 3 " + storedjobs); for(var devicekey in storedjobs){ - print("Key: " + devicekey); if(devicekey == job.v.device){ - print("En bra bit"); - for(var i=0;i" - } - MouseArea{ - anchors.fill: parent - onClicked: { - //step to next weekday - dialog.hide() - Scripts.updateEndsWith() //mainListView) - Scripts.incrementCurrentDay() - weekDayText.text = Scripts.getCurrentDayName() - //mainListView.positionViewAtIndex(mainListView.currentIndex, ListView.Center) - //mainListView.currentIndex = mainListView.currentIndex + 1 - } + arrowText: "->" + onClicked: { + Scripts.incrementCurrentDay(); } } } @@ -108,9 +73,6 @@ import "schedulerscripts.js" as Scripts Column{ id: mainHeader - //anchors.left: parent.left - //anchors.top: parent.top - //anchors.topMargin: dayListHeaderHeight width: main.width - constDeviceRowWidth spacing: 0 @@ -148,6 +110,7 @@ import "schedulerscripts.js" as Scripts //TODO implement setProperty if this is to be stored... or do something else... modelData.setProperty(index, isEnabled, modelData.isEnabled == "enabled" ? "disabled" : "enabled"); //TODO also implement disabled/enabled for all (deviceEnabled=false on all) and per point (set isPoint=false and opacity=0.4)... //take that value into consideration when saving and sending jobs for execution + //else, remove this button deviceNameRect.isEnabled = deviceNameRect.isEnabled == "enabled" ? "disabled" : "enabled" Scripts.deviceEnabled(modelData.id, deviceNameRect.isEnabled); } @@ -159,10 +122,8 @@ import "schedulerscripts.js" as Scripts Rectangle{ id: mainContent - height: 700 //TODO - width: constDeviceRowWidth //TODO - //anchors.top: parent.top - //anchors.left: mainListViewHeaderColumn.right + height: mainHeight + width: constDeviceRowWidth clip: true z: 50 } @@ -175,200 +136,173 @@ import "schedulerscripts.js" as Scripts id: dayListView property date daydate width: constDeviceRowWidth - height: 700 //TODO + height: mainHeight - //anchors.fill: parent model: deviceModel delegate: listRow - //focus: true - //footer: addButtonComponent //TODO move... header: timeline snapMode: ListView.SnapToItem interactive: false //no scroll between devices at the moment - //anchors.top: parent.top; - //state: "hidden" //default states: [ State { - name: "hiddenRight"; //when: parent.left != null + name: "hiddenRight"; AnchorChanges { target: dayListView; anchors.left: parent.right; anchors.right: undefined } - //PropertyChanges { target: dayListView; opacity: 0 } }, State { - name: "hiddenLeft"; //when: parent.left != null + name: "hiddenLeft"; AnchorChanges { target: dayListView; anchors.left: undefined; anchors.right: parent.left } - //PropertyChanges { target: dayListView; opacity: 0 } }, State { - name: "visible"; //when: parent.left != null + name: "visible"; PropertyChanges { target: dayListView; opacity: 1 } AnchorChanges { target: dayListView; anchors.right: undefined; anchors.left: parent.left } } ] - onChildrenChanged: { - //TODO REMOVE - print("-------------- CHILDREN CHANGED ----------------"); - } - transitions: [ Transition { from: "hiddenLeft" to: "visible" - AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } }, Transition { from: "visible" to: "hiddenRight" - AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } }, Transition { from: "visible" to: "hiddenLeft" - AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } }, Transition { from: "hiddenRight" to: "visible" - AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } //PropertyAnimation { properties: "x"; duration: 1000; easing.type: Easing.InOutQuad } + AnchorAnimation { easing.type: Easing.InOutQuad; duration: 1000 } } ] - - //TODO transition between state, animation - } } Component{ id: listRow - /* - Row{ - id: mainRow + Rectangle { id: "deviceRow"; border.color: "blue"; width: constDeviceRowWidth; height: constDeviceRowHeight; + clip: true + property variant endPoint: undefined + property int deviceId: modelData.id; + property alias continuingBar: continuingBar + property variant selectedDate: main.selectedDate + state: "enabled" - width: constDeviceRowWidth //parent.width; //TODO relative - height: constDeviceRowHeight - /* - Rectangle { - border.color: "red"; width: 100; height:parent.height; - Text{ - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - - text: modelData.name + states: [ + State{ + name: "enabled" + PropertyChanges{ target: deviceRow; opacity: 1 } + }, + State{ + name: "disabled" + PropertyChanges{ target: deviceRow; opacity: 0.4 } } - } - */ - Rectangle { id: "deviceRow"; border.color: "blue"; width: constDeviceRowWidth; height: constDeviceRowHeight; - clip: true - property variant endPoint: undefined //: Scripts.getEndsWith(deviceRow.children, index, modelData.id); - property int deviceId: modelData.id; - property alias continuingBar: continuingBar - state: "enabled" - - states: [ - State{ - name: "enabled" - PropertyChanges{ target: deviceRow; opacity: 1 } - }, - State{ - name: "disabled" - PropertyChanges{ target: deviceRow; opacity: 0.4 } - } - ] - - MouseArea { - id: deviceMouseArea - anchors.fill: parent - //hoverEnabled: true - - //TODO ändra muspekaren kanske? - //onEntered: parent.border.color = onHoverColor - //onExited: parent.border.color = borderColor - onClicked: { - //Scripts.debugPrintDeviceIndex(); - Scripts.setChanged(deviceId, true); - Scripts.updateDeviceIndex(); //TODO why is this needed here? (but it is, adding points to empty device will get wrong state otherwise) - //print("Mainrow: " + mainRow.parent.children[0].height); - var component = Qt.createComponent("ActionPoint.qml") - var dynamicPoint = component.createObject(deviceRow) - //dynamicPoint.x = mouseX - dynamicPoint.width/2 //xposition - var hourMinute = dynamicPoint.getTimeFromPosition(mouse.x) - dynamicPoint.absoluteHour = hourMinute[0] - dynamicPoint.absoluteMinute = hourMinute[1] - dynamicPoint.x = dynamicPoint.getAbsoluteXValue(); - dynamicPoint.border.color = "blue" - - //TODO different states depending on the device - dynamicPoint.addActiveState("on"); - dynamicPoint.addActiveState("off"); - dynamicPoint.addActiveState("dim"); - dynamicPoint.addActiveState("bell"); - //dynamicPoint.setFirstState("dim"); //when type is a stored value - dynamicPoint.setFirstState(); - dynamicPoint.pointId = new Date().getTime(); //just needed for storage update - - deviceRow.updateContinuingBars(); - dialog.show(dynamicPoint) - } - } - - ActionBar{ - id: "continuingBar" - hangOnToPoint: deviceRow - firstBar: "true" - - state: "continuing" - } - - ListView.onAdd: SequentialAnimation { - PropertyAction { target: mainRow; property: "height"; value: 0 } - NumberAnimation { target: mainRow; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } - } - - function hasPoints(){ - return Scripts.hasBarChangingPoints(deviceRow.children); - } - - function updateContinuingBars(){ - Scripts.updateEndsWith(); - } - - function getDeviceRow(dayIndex, deviceId){ - print("CALLING getDeviceRow"); - return Scripts.getDeviceRow(dayIndex, deviceId); - } - - function createChildPoint(index, pointRect, deviceId){ - print("CREATING child point"); - return Scripts.createChildPoint(index, pointRect, deviceId); - } - - function setChanged(){ + ] + + MouseArea { + id: deviceMouseArea + anchors.fill: parent + onClicked: { Scripts.setChanged(deviceId, true); - } - - function isLoading(){ - return Scripts.isLoading(); + //TODO really needed? Scripts.updateDeviceIndex(); //needed here, adding points to empty device will get wrong state otherwise + var component = Qt.createComponent("ActionPoint.qml") + var dynamicPoint = component.createObject(deviceRow) + var hourMinute = dynamicPoint.getTimeFromPosition(mouse.x) + dynamicPoint.absoluteHour = hourMinute[0] + dynamicPoint.absoluteMinute = hourMinute[1] + dynamicPoint.x = dynamicPoint.getAbsoluteXValue(); + dynamicPoint.border.color = "blue" + + //TODO different states depending on the device + dynamicPoint.addActiveState("on"); + dynamicPoint.addActiveState("off"); + dynamicPoint.addActiveState("dim"); + dynamicPoint.addActiveState("bell"); + dynamicPoint.setFirstState(); + dynamicPoint.pointId = new Date().getTime(); //just needed for storage update + + deviceRow.updateContinuingBars(); + dialog.show(dynamicPoint) } } - //} + + ActionBar{ + id: "continuingBar" + hangOnToPoint: deviceRow + firstBar: "true" + + state: "continuing" + } + + ListView.onAdd: SequentialAnimation { + PropertyAction { target: mainRow; property: "height"; value: 0 } + NumberAnimation { target: mainRow; property: "height"; to: 50; duration: 250; easing.type: Easing.InOutQuad } + } + + //device functions: + function createChildPoint(index, pointRect, deviceId){ + return Scripts.createChildPoint(index, pointRect, deviceId); + } + + function getDeviceRow(dayIndex, deviceId){ + return Scripts.getDeviceRow(dayIndex, deviceId); + } + + function hasPoints(){ + return Scripts.hasBarChangingPoints(deviceRow.children); + } + + function isLoading(){ + return Scripts.isLoading(); + } + + function setChanged(){ + Scripts.setChanged(deviceId, true); + } + + function updateContinuingBars(){ + Scripts.updateEndsWith(); + } + } } Component{ id: timeline Item{ - width: constDeviceRowWidth //TODO parent.width + id: timelinerange + width: constDeviceRowWidth height: dayListHeaderHeight + property int morningDarkWidth: MainScripts.getMorningDarkWidth() + property double morningDarkStart: MainScripts.getMorningDarkStart() + property int eveningDarkWidth: MainScripts.getEveningDarkWidth() + property double eveningDarkStart: MainScripts.getEveningDarkStart() + property variant currentDate: main.selectedDate; + + onCurrentDateChanged: { + //update values + timelinerange.morningDarkWidth = MainScripts.getMorningDarkWidth() + timelinerange.morningDarkStart = MainScripts.getMorningDarkStart() + timelinerange.eveningDarkWidth = MainScripts.getEveningDarkWidth() + timelinerange.eveningDarkStart = MainScripts.getEveningDarkStart() + } + Rectangle{ id: morningDark color: "black" height: parent.height border.width: 0 - width: getMorningDarkWidth() + width: timelinerange.morningDarkWidth opacity: 0.1 - x: getMorningDarkStart() + x: timelinerange.morningDarkStart } Rectangle{ @@ -376,9 +310,9 @@ import "schedulerscripts.js" as Scripts color: "black" height: parent.height border.width: 0 - width: getEveningDarkWidth() + width: timelinerange.eveningDarkWidth opacity: 0.1 - x: getEveningDarkStart() + x: timelinerange.eveningDarkStart } Rectangle{ @@ -386,13 +320,12 @@ import "schedulerscripts.js" as Scripts border.color: "red" Row{ - //x: 100 anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenterOffset: parent.width/24 - width: parent.width //listRow.width + width: parent.width height: parent.height - spacing: (parent.width-24)/24 //before: -124 + spacing: (parent.width-24)/24 Repeater{ model:24 Rectangle{ @@ -418,116 +351,20 @@ import "schedulerscripts.js" as Scripts } } - /* Not in use, adding all devices always instead - Component{ - id: addButtonComponent - Row { - id: addButton - - Rectangle { - height: 20 - width: 100 - anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: 30 - - property color buttonColor: "lightgrey" - - Text{ - text: "Add an item" - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - anchors.margins: 2 - - } - MouseArea { - id: buttonMouseArea - anchors.fill: parent - onClicked: { - addDevice.call() - } - } - - color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor - - } - } - } - */ - Dialog { id: dialog z: 150 } - //TODO move functions, and test odd cases: - function getEveningDarkStart(){ - if(!willSunSet){ - return 0; - } - if(Scripts.isMidnightDark()){ - return sunToTimeUnits(main.sunData[1]); // + 100; - } - else{ - return 0; - } + function mainGetMethodFromState(state){ + return getMethodFromState.callWith(state); } - function getMorningDarkStart(){ - //TODO the day of the year when the sun "begins" not to set, will it work then? - if(!willSunSet){ - return 0; - } - if(Scripts.isMidnightDark()){ - return 0; //100; //TODO constants - } - else{ - return sunToTimeUnits(main.sunData[1]); // + 100; //TODO constants - } + function mainGetTypeFromTriggerstate(triggerstate){ + return getTypeFromTriggerstate.callWith(triggerstate); } - - function getEveningDarkWidth(){ - if(!willSunSet){ - return 0; - } - if(Scripts.isMidnightDark()){ - return constDeviceRowWidth - sunToTimeUnits(main.sunData[1]); //(main.width - 100) - sunToTimeUnits(main.sunData[1]); //TODO constant or something - } - else{ - return 0; - } - } - - function getMorningDarkWidth(){ - if(!willSunSet){ - return 0; - } - if(Scripts.isMidnightDark()){ - return sunToTimeUnits(main.sunData[0]); - } - else{ - return sunToTimeUnits(main.sunData[1]) - sunToTimeUnits(main.sunData[0]); - } - } - - function willSunSet(){ - if(main.sunData == undefined){ - main.sunData = getSunData.call(); - } - - return !(main.sunData[2] && main.sunData[2] != "") - } - - function sunToTimeUnits(suntime){ - suntime = suntime.split(':'); - var hourSize = constDeviceRowWidth/24; //(main.width - 100)/24; //TODO constant or something? - return hourSize * suntime[0] + hourSize * suntime[1]/60; - } - function saveAll(){ - print("Save all and reset jobs"); - //var jobs = new Array(); - //var points = new Array(); var days = Scripts.getDays(); if(dialog.dialogOpacity == 1){ Scripts.setChanged(dialog.actionPoint.deviceRow.deviceId, true); //set the devicerow that the currently visible dialog is connected to as dirty @@ -537,20 +374,17 @@ import "schedulerscripts.js" as Scripts var deviceId = deviceModel.get(i).id; if(!Scripts.hasChanged(deviceId)){ //no point has been updated, removed or added, ignore this device - print("Not updated: " + deviceId); continue; } Scripts.setChanged(deviceId, false); //reset hasChanged-status - print("Updated: " + deviceId); if(Scripts.deviceIsEnabled(deviceId)){ //if device is disabled, don't add any points to schedule (but remove current) - print("Device is enabled: " + deviceId); for(var j=0;j Date: Wed, 16 Feb 2011 13:56:29 +0000 Subject: [PATCH 1586/2215] More code cleanup/refactoring, fixed bug with removal of parent points --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 1 + .../SchedulerGUISimple/ActionPoint.qml | 43 +- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 1 + .../SchedulerGUISimple/actionpointscripts.js | 133 +++++ .../Plugins/SchedulerGUISimple/main.qml | 18 +- .../Plugins/SchedulerGUISimple/mainscripts.js | 41 +- .../SchedulerGUISimple/schedulerscripts.js | 501 ++++++------------ 7 files changed, 363 insertions(+), 375 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml index b70d281a..0b686b9d 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -16,6 +16,7 @@ Rectangle{ opacity: barRectangle.prevDayOpacity width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before + //TODO test this with binding to created functions onX states: [ State{ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index fd440e4e..4bf71841 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -1,5 +1,6 @@ import Qt 4.7 import "schedulerscripts.js" as Scripts +import "actionpointscripts.js" as ActionPointScripts Rectangle{ id: pointRect @@ -256,14 +257,14 @@ Rectangle{ //print("Different x"); point = pointRect.parentPoint; } - print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); - print("AbsoluteHour: " +point.absoluteHour+ " hourSize: " + hourSize + " AbsoluteMinute: " + point.absoluteMinute + " Width: " + point.width); + //print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); + //print("AbsoluteHour: " +point.absoluteHour+ " hourSize: " + hourSize + " AbsoluteMinute: " + point.absoluteMinute + " Width: " + point.width); return point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2; } function toggleType(){ //TODO other kind of selection method var index = 0; - var activeStates = Scripts.getActiveStates(); + var activeStates = ActionPointScripts.getActiveStates(); if(activeStates == undefined || activeStates.length == 0){ return; } @@ -296,16 +297,16 @@ Rectangle{ //pointRect.xvalue = pointRect.x; trigger.state = "sunrise"; } - Scripts.updateParentWithCurrentValues(); - Scripts.updateChildPoints(); + ActionPointScripts.updateParentWithCurrentValues(); + ActionPointScripts.updateChildPoints(); } function updateChanges(){ if(pointRect.deviceRow == null || (pointRect.deviceRow.isLoading != undefined && pointRect.deviceRow.isLoading())){ return; //loading values from storage, wait until everything is in place } - Scripts.updateParentWithCurrentValues(); - Scripts.updateChildPoints(); + ActionPointScripts.updateParentWithCurrentValues(); + ActionPointScripts.updateChildPoints(); if(pointRect.triggerstate == "absolute"){ pointRect.x = getAbsoluteXValue(); } @@ -362,21 +363,20 @@ Rectangle{ function addActiveState(state){ //print("Adding state: " + state); - Scripts.addActiveState(state); + ActionPointScripts.addActiveState(state); } function setActiveStates(activeStates){ - Scripts.setActiveStates(activeStates); + ActionPointScripts.setActiveStates(activeStates); } function getActiveStates(){ - return Scripts.getActiveStates(); + return ActionPointScripts.getActiveStates(); } function setFirstState(firstState){ - //print("SETTING FIRST STATE"); - var activeStates = Scripts.getActiveStates(); + var activeStates = ActionPointScripts.getActiveStates(); if(activeStates == null || activeStates.length == 0){ //nothing to do @@ -405,7 +405,7 @@ Rectangle{ return; } - var previousState = Scripts.getPreviousState(pointRect); + var previousState = ActionPointScripts.getPreviousState(pointRect); if(previousState == undefined || previousState == "" || previousState == "off"){ //nothing on/dimmed at the moment, use first added state pointRect.state = activeStates[0]; @@ -428,7 +428,7 @@ Rectangle{ pointRect.isPoint = "false" var pointList = pointRect.parent.children; var deviceRow = pointRect.deviceRow; - var childPoints = Scripts.getChildPoints(); + var childPoints = ActionPointScripts.getChildPoints(); for(var child in childPoints){ childPoints[child].remove(keepDialogOpen, "ignoreParent"); delete childPoints[child]; @@ -497,21 +497,24 @@ Rectangle{ } function getChildPoint(index){ - return Scripts.getChildPoint(index); + return ActionPointScripts.getChildPoint(index); } function getChildPoints(){ - return Scripts.getChildPoints(); + return ActionPointScripts.getChildPoints(); } function addChildPoint(index, point){ - Scripts.addChildPoint(index, point); + ActionPointScripts.addChildPoint(index, point); } function removeChildPoint(index){ - Scripts.removeChildPoint(index); + ActionPointScripts.removeChildPoint(index); } function removeParentPoint(newParentPoint){ - Scripts.removeParentPoint(newParentPoint); + ActionPointScripts.removeParentPoint(newParentPoint); } function setChildPoints(childPoints){ - Scripts.setChildPoints(childPoints); + ActionPointScripts.setChildPoints(childPoints); + } + function updateChildPoints(){ + ActionPointScripts.updateChildPoints(); } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index 4ad22112..b6d08fb9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -8,6 +8,7 @@ SET( Plugin_PATH "com.telldus.schedulerguisimple" ) SET( Plugin_EXTRA ActionBar.qml ActionPoint.qml + actionpointscripts.js Button.qml Dialog.qml icon.png diff --git a/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js new file mode 100644 index 00000000..f144b528 --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js @@ -0,0 +1,133 @@ +//STATES: +var activeStates = new Array(); + +function addActiveState(state){ + activeStates.push(state); +} + +function getActiveStates(){ + return activeStates; +} + +function getPreviousState(currentPointRect){ + var pointList = currentPointRect.parent.children + var prevPoint = null; + var firstBarStateIndex; + for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic + prevPoint = pointList[i]; + } + } + else if(pointList[i].firstBar != undefined && pointList[i].firstBar == "true"){ + firstBarStateIndex = i; + } + } + + if(prevPoint == null){ + //no previous point,see if state continues from previous day + if(firstBarStateIndex != undefined && pointList[firstBarStateIndex].firstBar != undefined){ + + var dayIndex = currentPointRect.deviceRow.currentDayIndex - 1; + if(dayIndex == -1){ //too far, begin from end again + dayIndex = 6; //week length - 1 + } + var prevDayDevice = currentPointRect.parent.getDeviceRow(dayIndex, currentPointRect.deviceRow.deviceId); + if(prevDayDevice != undefined){ + return prevDayDevice.endPoint; + } + } + + return ""; + } + return prevPoint.state; +} + +function setActiveStates(newActiveStates){ + activeStates = newActiveStates; +} + + +//CHILD POINTS: + +var childPoints = {}; + +function addChildPoint(index, point){ + childPoints[index] = point; +} + +function getChildPoint(index){ + return childPoints[index]; +} + +function getChildPoints(){ + return childPoints; +} + +function removeChildPoint(index){ + var toBeRemoved = childPoints[index]; + delete childPoints[index]; + toBeRemoved.remove("true"); +} + +function removeParentPoint(newParentPoint){ + delete childPoints[newParentPoint.deviceRow.parent.parent.daydate.getDay()]; //remove the current point from the child list + newParentPoint.setChildPoints(childPoints); //copy child list to current child (making it a parent) + newParentPoint.lastRun = newParentPoint.parentPoint.lastRun; + newParentPoint.pointId = newParentPoint.parentPoint.pointId; + newParentPoint.parentPoint = undefined; + updateParentsInChildList(newParentPoint); //update all other child points (if any) with the current point as their parent + childPoints = {}; + pointRect.remove("true"); +} + +function setChildPoints(newChildPoints){ + childPoints = newChildPoints; +} + +function updateParentsInChildList(newParentPoint){ + var children = newParentPoint.getChildPoints(); + for(var point in children){ + children[point].parentPoint = newParentPoint; + } +} + +function updateChildPoints(){ + + var children; + if(pointRect.parentPoint != undefined){ + children = pointRect.parentPoint.getChildPoints(); + parentPoint = pointRect.parentPoint; + } + else{ + children = getChildPoints(); + parentPoint = pointRect; + } + + for(var point in children){ + children[point].absoluteHour = parentPoint.absoluteHour; + children[point].absoluteMinute = parentPoint.absoluteMinute; + children[point].fuzzyBefore = parentPoint.fuzzyBefore; + children[point].fuzzyAfter = parentPoint.fuzzyAfter; + children[point].offset = parentPoint.offset; + children[point].triggerstate = parentPoint.triggerstate; + children[point].dimvalue = parentPoint.dimvalue; + children[point].state = parentPoint.state; + if(children[point].triggerstate == "absolute"){ + children[point].x = children[point].getAbsoluteXValue(); + } + } +} + +function updateParentWithCurrentValues(){ + if(pointRect.parentPoint != undefined){ + pointRect.parentPoint.absoluteHour = pointRect.absoluteHour; //TODO check if this can be done with binding without loops... + pointRect.parentPoint.absoluteMinute = pointRect.absoluteMinute; + pointRect.parentPoint.fuzzyBefore = pointRect.fuzzyBefore; + pointRect.parentPoint.fuzzyAfter = pointRect.fuzzyAfter; + pointRect.parentPoint.offset = pointRect.offset; + pointRect.parentPoint.triggerstate = pointRect.triggerstate; + pointRect.parentPoint.dimvalue = pointRect.dimvalue; + pointRect.parentPoint.state = pointRect.state; + } +} \ No newline at end of file diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 1c4171aa..1b0168bd 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -112,7 +112,7 @@ import "mainscripts.js" as MainScripts //take that value into consideration when saving and sending jobs for execution //else, remove this button deviceNameRect.isEnabled = deviceNameRect.isEnabled == "enabled" ? "disabled" : "enabled" - Scripts.deviceEnabled(modelData.id, deviceNameRect.isEnabled); + MainScripts.deviceEnabled(modelData.id, deviceNameRect.isEnabled); } } } @@ -194,6 +194,8 @@ import "mainscripts.js" as MainScripts property int deviceId: modelData.id; property alias continuingBar: continuingBar property variant selectedDate: main.selectedDate + property int currentDayIndex: Scripts.getCurrentDayIndex(main.selectedDate) + state: "enabled" states: [ @@ -211,7 +213,7 @@ import "mainscripts.js" as MainScripts id: deviceMouseArea anchors.fill: parent onClicked: { - Scripts.setChanged(deviceId, true); + MainScripts.setChanged(deviceId, true); //TODO really needed? Scripts.updateDeviceIndex(); //needed here, adding points to empty device will get wrong state otherwise var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) @@ -265,7 +267,7 @@ import "mainscripts.js" as MainScripts } function setChanged(){ - Scripts.setChanged(deviceId, true); + MainScripts.setChanged(deviceId, true); } function updateContinuingBars(){ @@ -367,16 +369,16 @@ import "mainscripts.js" as MainScripts function saveAll(){ var days = Scripts.getDays(); if(dialog.dialogOpacity == 1){ - Scripts.setChanged(dialog.actionPoint.deviceRow.deviceId, true); //set the devicerow that the currently visible dialog is connected to as dirty + MainScripts.setChanged(dialog.actionPoint.deviceRow.deviceId, true); //set the devicerow that the currently visible dialog is connected to as dirty } for(var i=0;i currentPointRect.x){ - nextX = pointList[i].x; - } - } - } - return (nextX - currentPointRect.x); -} - -function hasBarChangingPoints(pointList){ - - for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic - prevPoint = pointList[i]; - } - } - } - - if(prevPoint == null){ - dayIndex = dayIndex - 1; - if(dayIndex == -1){ //too far, begin from end again - dayIndex = days.length - 1; - } - - var prevDayDevice = getDeviceRow(dayIndex, deviceId); - if(prevDayDevice == undefined){ // || prevDayDevice.endPoint == undefined){ //TODO this is due to an error, but in the future use it to avoid loops - return null; - } - return prevDayDevice.endPoint; // previousDayEndsWithPoint; - } - if(prevPoint.state == "off"){ - return null; - } - return prevPoint; //only on or dim -} - -function getPreviousState(currentPointRect){ - var pointList = currentPointRect.parent.children - var prevPoint = null; - var firstBarStateIndex; - for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic - prevPoint = pointList[i]; - } - } - else if(pointList[i].firstBar != undefined && pointList[i].firstBar == "true"){ - firstBarStateIndex = i; - } - } - - if(prevPoint == null){ - //no previous point,see if state continues from previous day - if(firstBarStateIndex != undefined && pointList[firstBarStateIndex].firstBar != undefined){ - - var dayIndex = currentDayIndex - 1; - if(dayIndex == -1){ //too far, begin from end again - dayIndex = days.length - 1; - } - var prevDayDevice = currentPointRect.parent.getDeviceRow(dayIndex, currentPointRect.deviceRow.deviceId); - if(prevDayDevice != undefined){ - return prevDayDevice.endPoint; - } - } - - return ""; - } - return prevPoint.state; -} -function pad(number, length) { - - var str = '' + number; - while (str.length < length) { - str = '0' + str; - } - - return str; -} + + + + function updateDeviceIndex(){ //TODO, better way, please... deviceIndex = []; //empty list @@ -221,22 +92,6 @@ function updateDeviceIndex(){ //TODO, better way, please... for(var i=0;i days.length-1){ - dayOfWeek = dayOfWeek - days.length; - } - return dayOfWeek; -} - -function getOffsetWeekdayName(index){ - index = getOffsetWeekday(index); - return weekday_name_array[index]; -} - -function getOffsetWeekday(index){ - //TODO this can be modified based on locale, not adding 1 if week should start with sunday - index = parseInt(index); - index = index + 1; - if(index == weekday_name_array.length){ - index = 0; - } - return index; -} - -function updateLastRun(deviceId, day, pointId, lastRun){ - print("0"); - day = getDayIndexForDayOfWeek(day); - print("1: " + day); - var row = getDeviceRow(day,deviceId); - print("2: " + row); - for(var k=0;k days.length-1){ + dayOfWeek = dayOfWeek - days.length; + } + return dayOfWeek; +} + +function updateLastRun(deviceId, day, pointId, lastRun){ + day = getDayIndexForDayOfWeek(day); + var row = getDeviceRow(day,deviceId); + for(var k=0;k currentPointRect.x){ + nextX = pointList[i].x; + } + } + } + return (nextX - currentPointRect.x); +} + +function hasBarChangingPoints(pointList){ + + for(var i=0;i prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic + prevPoint = pointList[i]; + } + } + } + + if(prevPoint == null){ + dayIndex = dayIndex - 1; + if(dayIndex == -1){ //too far, begin from end again + dayIndex = days.length - 1; + } + + var prevDayDevice = getDeviceRow(dayIndex, deviceId); + if(prevDayDevice == undefined){ + return null; + } + return prevDayDevice.endPoint; + } + if(prevPoint.state == "off"){ + return null; + } + return prevPoint; //only on or dim +} + +function getTimeFromSeconds(seconds){ + var totalMinutes = seconds/60; + var minutes = totalMinutes%60; + var hours = Math.floor(totalMinutes/60); + return [hours, minutes]; +} + +function getFirstPointWidth(deviceRow){ + var pointList = deviceRow.children; //TODO should really try to avoid using "children"... make own list instead? + var firstX = deviceRow.width; + var pointWidth = 0; + for(var i=0;i Date: Wed, 16 Feb 2011 15:23:47 +0000 Subject: [PATCH 1587/2215] Code refactoring and few bug fixes --- .../SchedulerGUISimple/ActionPoint.qml | 5 +- .../SchedulerGUISimple/actionpointscripts.js | 21 +- .../Plugins/SchedulerGUISimple/main.qml | 46 +- .../Plugins/SchedulerGUISimple/mainscripts.js | 344 +++++++++++++++ .../SchedulerGUISimple/schedulerscripts.js | 404 ++---------------- 5 files changed, 404 insertions(+), 416 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 4bf71841..57b29081 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -18,10 +18,9 @@ Rectangle{ property int absoluteHour: parseInt(dialog.absoluteHour, 10) property int absoluteMinute: parseInt(dialog.absoluteMinute, 10) property alias triggerstate: trigger.state - property variant parentPoint + property variant parentPoint: undefined property variant pointId property variant lastRun: 0; - //property int parentPointAbsoluteHour //TEST changed from int, want "undefined" property alias deviceRow: pointRect.parent property variant selectedDate: (deviceRow == null || deviceRow == undefined) ? new Date() : deviceRow.selectedDate @@ -32,7 +31,6 @@ Rectangle{ var dynamicBar = actionBar.createObject(pointRect) dynamicBar.hangOnToPoint = pointRect dynamicBar.state = "pointLoaded" - //pointRect.hangOnToBar = dynamicBar } //use item instead of rectangle (no border then though) to make it invisible (opacity: 0) @@ -418,6 +416,7 @@ Rectangle{ function remove(keepDialogOpen, ignoreParent){ if(keepDialogOpen == undefined && ignoreParent == undefined && pointRect.parentPoint != undefined){ //remove from parent instead + print(pointRect.parentPoint); pointRect.parentPoint.remove(); return; } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js index f144b528..e5b3f44e 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js @@ -95,24 +95,25 @@ function updateParentsInChildList(newParentPoint){ function updateChildPoints(){ var children; + var localParentPoint; if(pointRect.parentPoint != undefined){ children = pointRect.parentPoint.getChildPoints(); - parentPoint = pointRect.parentPoint; + localParentPoint = pointRect.parentPoint; } else{ children = getChildPoints(); - parentPoint = pointRect; + localParentPoint = pointRect; } for(var point in children){ - children[point].absoluteHour = parentPoint.absoluteHour; - children[point].absoluteMinute = parentPoint.absoluteMinute; - children[point].fuzzyBefore = parentPoint.fuzzyBefore; - children[point].fuzzyAfter = parentPoint.fuzzyAfter; - children[point].offset = parentPoint.offset; - children[point].triggerstate = parentPoint.triggerstate; - children[point].dimvalue = parentPoint.dimvalue; - children[point].state = parentPoint.state; + children[point].absoluteHour = localParentPoint.absoluteHour; + children[point].absoluteMinute = localParentPoint.absoluteMinute; + children[point].fuzzyBefore = localParentPoint.fuzzyBefore; + children[point].fuzzyAfter = localParentPoint.fuzzyAfter; + children[point].offset = localParentPoint.offset; + children[point].triggerstate = localParentPoint.triggerstate; + children[point].dimvalue = localParentPoint.dimvalue; + children[point].state = localParentPoint.state; if(children[point].triggerstate == "absolute"){ children[point].x = children[point].getAbsoluteXValue(); } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 1b0168bd..e1299875 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -8,7 +8,7 @@ import "mainscripts.js" as MainScripts width: mainWidth height: mainHeight property int dayListHeaderHeight: 15 - property variant selectedDate: Scripts.getCurrentDate(); //Maybe just today + property variant selectedDate: MainScripts.getCurrentDate(); //Maybe just today property variant sunData: MainScripts.getSunData(); Component.onCompleted: { @@ -22,17 +22,17 @@ import "mainscripts.js" as MainScripts var currentDay = new Date(startday); currentDay.setDate(startday.getDate() + i); dynamicDay.daydate = currentDay; - Scripts.addDay(dynamicDay); + MainScripts.addDay(dynamicDay); } dynamicDay.state = "visible" //set last day (today) as visible - weekDayText.text = Scripts.getCurrentDayName() - Scripts.updateDeviceIndex(); - Scripts.setLoading(); + weekDayText.text = MainScripts.getCurrentDayName() + MainScripts.updateDeviceIndex(); + MainScripts.setLoading(); var updateLastRunFunc = updateLastRun; restoreJobs.callWith(updateLastRunFunc); - Scripts.initiateStoredPointsInGUI(); - Scripts.endLoading(); - Scripts.updateEndsWith(); + MainScripts.initiateStoredPointsInGUI(); + MainScripts.endLoading(); + MainScripts.updateEndsWith(); } Rectangle{ @@ -47,7 +47,7 @@ import "mainscripts.js" as MainScripts anchors.verticalCenter: weekDayText.verticalCenter arrowText: "<-" onClicked: { - Scripts.decrementCurrentDay(); + MainScripts.decrementCurrentDay(); } } Text{ @@ -60,7 +60,7 @@ import "mainscripts.js" as MainScripts anchors.verticalCenter: weekDayText.verticalCenter arrowText: "->" onClicked: { - Scripts.incrementCurrentDay(); + MainScripts.incrementCurrentDay(); } } } @@ -194,7 +194,7 @@ import "mainscripts.js" as MainScripts property int deviceId: modelData.id; property alias continuingBar: continuingBar property variant selectedDate: main.selectedDate - property int currentDayIndex: Scripts.getCurrentDayIndex(main.selectedDate) + property int currentDayIndex: MainScripts.getCurrentDayIndex(main.selectedDate) state: "enabled" @@ -230,9 +230,9 @@ import "mainscripts.js" as MainScripts dynamicPoint.addActiveState("bell"); dynamicPoint.setFirstState(); dynamicPoint.pointId = new Date().getTime(); //just needed for storage update - deviceRow.updateContinuingBars(); dialog.show(dynamicPoint) + } } @@ -251,11 +251,11 @@ import "mainscripts.js" as MainScripts //device functions: function createChildPoint(index, pointRect, deviceId){ - return Scripts.createChildPoint(index, pointRect, deviceId); + return MainScripts.createChildPoint(index, pointRect, deviceId); } function getDeviceRow(dayIndex, deviceId){ - return Scripts.getDeviceRow(dayIndex, deviceId); + return MainScripts.getDeviceRow(dayIndex, deviceId); } function hasPoints(){ @@ -263,7 +263,7 @@ import "mainscripts.js" as MainScripts } function isLoading(){ - return Scripts.isLoading(); + return MainScripts.isLoading(); } function setChanged(){ @@ -271,7 +271,7 @@ import "mainscripts.js" as MainScripts } function updateContinuingBars(){ - Scripts.updateEndsWith(); + MainScripts.updateEndsWith(); } } } @@ -367,7 +367,7 @@ import "mainscripts.js" as MainScripts } function saveAll(){ - var days = Scripts.getDays(); + var days = MainScripts.getDays(); if(dialog.dialogOpacity == 1){ MainScripts.setChanged(dialog.actionPoint.deviceRow.deviceId, true); //set the devicerow that the currently visible dialog is connected to as dirty } @@ -380,9 +380,9 @@ import "mainscripts.js" as MainScripts } MainScripts.setChanged(deviceId, false); //reset hasChanged-status - if(Scripts.deviceIsEnabled(deviceId)){ //if device is disabled, don't add any points to schedule (but remove current) + if(MainScripts.deviceIsEnabled(deviceId)){ //if device is disabled, don't add any points to schedule (but remove current) for(var j=0;j prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic + prevPoint = pointList[i]; + } + } + } + + if(prevPoint == null){ + dayIndex = dayIndex - 1; + if(dayIndex == -1){ //too far, begin from end again + dayIndex = days.length - 1; + } + + var prevDayDevice = getDeviceRow(dayIndex, deviceId); + if(prevDayDevice == undefined){ + return null; + } + return prevDayDevice.endPoint; + } + if(prevPoint.state == "off"){ + return null; + } + return prevPoint; //only on or dim +} + +function updateDeviceIndex(){ //TODO, better way, please... + deviceIndex = []; //empty list + var startIndex = 0; + for(var i=0;i days.length-1){ + dayIndex = dayIndex - days.length; + } + + var deviceRow = days[dayIndex].children[0].children[parseInt(deviceIndex[device])]; + + previousEndPoint = assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, i==0); + + if(i == days.length-1){ + //last one, bind the first one too then + deviceRow = days[startIndex].children[0].children[parseInt(deviceIndex[device])]; + assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, false); + } + } + } +} + + +//DAYS: + +var weekday_name_array = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"); +var currentDayIndex = 6; //Today... +var days = new Array(); + +function addDay(day){ + days.push(day); +} + +function decrementCurrentDay(){ + days[currentDayIndex].state = "hiddenRight"; + var workDate = days[currentDayIndex].daydate; + workDate.setDate(workDate.getDate() - 7); + days[currentDayIndex].daydate = workDate; + if(currentDayIndex == 0){ + currentDayIndex = days.length - 1; + } + else{ + currentDayIndex--; + } + days[currentDayIndex].state = "hiddenLeft"; //place on right side of center, for correct slid + days[currentDayIndex].state = "visible"; +} + +function getCurrentDay(){ + return days[currentDayIndex]; +} + +function getCurrentDayIndex(dummyvalue){ + //by sending in this dummyvalue, this function will be evaluated when that value is changed... + return currentDayIndex; +} + +function getCurrentDate(){ + if(days.length < 7){ + //not initiated yet + return new Date(); //now + } + var date = new Date(days[currentDayIndex].daydate); + return date; +} + +function getCurrentDayName(){ + var day = getCurrentDay().daydate; + return weekday_name_array[day.getDay()] + " " + day.getDate(); +} + +function getDayIndexForDayOfWeek(dayOfWeek){ + var offset = days[0].daydate.getDay(); + dayOfWeek = days.length - offset + parseInt(dayOfWeek); + if(dayOfWeek == -1){ + dayOfWeek = days.length - 1; + } + if(dayOfWeek > days.length-1){ + dayOfWeek = dayOfWeek - days.length; + } + return dayOfWeek; +} + +function getDays(){ + return days; +} + +function incrementCurrentDay(){ + days[currentDayIndex].state = "hiddenLeft"; + var workDate = days[currentDayIndex].daydate; + workDate.setDate(workDate.getDate() + 1); + if(currentDayIndex == (days.length - 1)){ + currentDayIndex = 0; + } + else{ + currentDayIndex++; + } + days[currentDayIndex].daydate = workDate; + days[currentDayIndex].state = "hiddenRight"; //place on right side of center, for correct slide + days[currentDayIndex].state = "visible"; +} + +function updateLastRun(deviceId, day, pointId, lastRun){ + day = getDayIndexForDayOfWeek(day); + var row = getDeviceRow(day,deviceId); + for(var k=0;k days.length-1){ - dayIndex = dayIndex - days.length; - } - - var deviceRow = days[dayIndex].children[0].children[parseInt(deviceIndex[device])]; - - previousEndPoint = assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, i==0); - - if(i == days.length-1){ - //last one, bind the first one too then - deviceRow = days[startIndex].children[0].children[parseInt(deviceIndex[device])]; - assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, false); - } - } - } -} - -function assignContinuingBarProperties(deviceRow, previousEndPoint, dayIndex, firstRow){ - - if(previousEndPoint == undefined){ //the first has no point to bind to - deviceRow.continuingBar.prevDayColor = "white"; - deviceRow.continuingBar.prevDayOpacity = 0; - deviceRow.continuingBar.prevDayWidth = 0; - } - else{ - deviceRow.continuingBar.prevDayColor = previousEndPoint.actionTypeColor; - if(previousEndPoint.state == "dim"){ - deviceRow.continuingBar.prevDayOpacity = previousEndPoint.dimvalue/100; - } - else{ - deviceRow.continuingBar.prevDayOpacity = previousEndPoint.actionTypeOpacity; - } - - } - - if(deviceRow.hasPoints()){ - deviceRow.endPoint = getEndsWith(deviceRow.children, days[dayIndex].daydate.getDay(), deviceRow.deviceId); - previousEndPoint = deviceRow.endPoint; - deviceRow.continuingBar.prevDayWidth = 0; - deviceRow.continuingBar.state = "continuingWithLimitedWidth"; - } - else{ - deviceRow.continuingBar.state = "continuing"; - deviceRow.endPoint = previousEndPoint; - deviceRow.continuingBar.prevDayWidth = deviceRow.width; - } - - return previousEndPoint; -} - -//Init: -function initiateStoredPointsInGUI(){ - for(var devicekey in storedPoints){ - for(var i=0;i days.length-1){ - dayOfWeek = dayOfWeek - days.length; - } - return dayOfWeek; -} - -function updateLastRun(deviceId, day, pointId, lastRun){ - day = getDayIndexForDayOfWeek(day); - var row = getDeviceRow(day,deviceId); - for(var k=0;k prevPoint.x) && pointList[i].state != "bell"){ //TODO when more than "bell", make dynamic - prevPoint = pointList[i]; - } - } - } - - if(prevPoint == null){ - dayIndex = dayIndex - 1; - if(dayIndex == -1){ //too far, begin from end again - dayIndex = days.length - 1; - } - - var prevDayDevice = getDeviceRow(dayIndex, deviceId); - if(prevDayDevice == undefined){ - return null; - } - return prevDayDevice.endPoint; - } - if(prevPoint.state == "off"){ - return null; - } - return prevPoint; //only on or dim -} - -function getTimeFromSeconds(seconds){ - var totalMinutes = seconds/60; - var minutes = totalMinutes%60; - var hours = Math.floor(totalMinutes/60); - return [hours, minutes]; -} - function getFirstPointWidth(deviceRow){ var pointList = deviceRow.children; //TODO should really try to avoid using "children"... make own list instead? var firstX = deviceRow.width; @@ -392,21 +30,6 @@ function getFirstPointWidth(deviceRow){ return firstX + pointWidth/2; } -function pad(number, length) { - - var str = '' + number; - while (str.length < length) { - str = '0' + str; - } - - return str; -} - -function getOffsetWeekdayName(index){ - index = getOffsetWeekday(index); - return weekday_name_array[index]; -} - function getOffsetWeekday(index){ //TODO this can be modified based on locale, not adding 1 if week should start with sunday index = parseInt(index); @@ -417,7 +40,28 @@ function getOffsetWeekday(index){ return index; } -function deviceIsEnabled(deviceId){ - return days[0].children[0].children[deviceIndex[deviceId]].state == "enabled"; +function getOffsetWeekdayName(index){ + index = getOffsetWeekday(index); + return weekday_name_array[index]; +} + +function hasBarChangingPoints(pointList){ + + for(var i=0;i Date: Wed, 16 Feb 2011 16:00:25 +0000 Subject: [PATCH 1588/2215] Workaround for warnings about 'cannot anchor...' in ActionBar.qml. Binding loop for actionTypeColor remains. --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml index 0b686b9d..a886dc57 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -14,10 +14,16 @@ Rectangle{ color: barRectangle.prevDayColor opacity: barRectangle.prevDayOpacity - width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); //TEST getNextAndPrevBarWidth before + width: barRectangle.prevDayWidth - //TODO test this with binding to created functions onX - + onStateChanged: { + //cannot bind these values as state change properties for some reason, do it here instead + if(state == "pointLoaded"){ + anchors.verticalCenter = hangOnToPoint.verticalCenter; + anchors.left = hangOnToPoint.horizontalCenter; + } + } + states: [ State{ name: "continuing" @@ -25,11 +31,6 @@ Rectangle{ target: barRectangle anchors.verticalCenter: hangOnToPoint.verticalCenter anchors.left: hangOnToPoint.left - /*color: barRectangle.prevDayColor - //getPreviousDayColor(barRectangle.currentDay, barRectangle.days, hangOnToPoint.deviceId, barRectangle.deviceIndex) - opacity: barRectangle.prevDayOpacity - width: barRectangle.prevDayWidth //TODO Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children); - */ } }, State{ @@ -45,8 +46,8 @@ Rectangle{ name: "pointLoaded" PropertyChanges { target: barRectangle - anchors.verticalCenter: hangOnToPoint.verticalCenter //TODO Warning on this and the line below... cannot fix, warning even if setting to undefined directly - anchors.left: hangOnToPoint.horizontalCenter + //anchors.verticalCenter: hangOnToPoint.verticalCenter //TODO Warning on this and the line below... cannot fix, warning even if setting to undefined directly + //anchors.left: hangOnToPoint.horizontalCenter color: hangOnToPoint.actionTypeColor opacity: hangOnToPoint.actionTypeOpacity width: hangOnToPoint.parent == null ? 0 : Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children) From a9ba4ccf86539d3e7b9333bee32c26f8b6d387d2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 16 Feb 2011 16:23:00 +0000 Subject: [PATCH 1589/2215] Fixed --- telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml | 1 - .../Plugins/SchedulerGUISimple/actionpointscripts.js | 6 ++++-- telldus-gui/Plugins/SchedulerGUISimple/main.qml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 57b29081..38eecb9a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -395,7 +395,6 @@ Rectangle{ break; } } - if(!exists){ //no "off", just set state to the first added state diff --git a/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js index e5b3f44e..6d083c4c 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/actionpointscripts.js @@ -25,6 +25,7 @@ function getPreviousState(currentPointRect){ } if(prevPoint == null){ + //no previous point,see if state continues from previous day if(firstBarStateIndex != undefined && pointList[firstBarStateIndex].firstBar != undefined){ @@ -33,13 +34,14 @@ function getPreviousState(currentPointRect){ dayIndex = 6; //week length - 1 } var prevDayDevice = currentPointRect.parent.getDeviceRow(dayIndex, currentPointRect.deviceRow.deviceId); - if(prevDayDevice != undefined){ - return prevDayDevice.endPoint; + if(prevDayDevice != undefined && prevDayDevice.endPoint != undefined){ + return prevDayDevice.endPoint.state; } } return ""; } + return prevPoint.state; } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index e1299875..69f42f93 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -214,7 +214,7 @@ import "mainscripts.js" as MainScripts anchors.fill: parent onClicked: { MainScripts.setChanged(deviceId, true); - //TODO really needed? Scripts.updateDeviceIndex(); //needed here, adding points to empty device will get wrong state otherwise + MainScripts.updateDeviceIndex(); //needed here, adding points to empty device will get wrong state otherwise (test with one "on", put new device on the row below = off) var component = Qt.createComponent("ActionPoint.qml") var dynamicPoint = component.createObject(deviceRow) var hourMinute = dynamicPoint.getTimeFromPosition(mouse.x) From 9d290f632a77462b600de3abe86898e1a5790fc8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Feb 2011 11:02:33 +0000 Subject: [PATCH 1590/2215] Added non-working function TellStick::convertSToT() --- .../driver/libtelldus-core/TellStick.cpp | 36 +++++++++++++++++++ .../driver/libtelldus-core/TellStick.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/telldus-core/driver/libtelldus-core/TellStick.cpp b/telldus-core/driver/libtelldus-core/TellStick.cpp index 47a17ccd..d8b93d61 100644 --- a/telldus-core/driver/libtelldus-core/TellStick.cpp +++ b/telldus-core/driver/libtelldus-core/TellStick.cpp @@ -385,3 +385,39 @@ bool TelldusCore::TellStick::stillConnected() const { return false; #endif } + +std::string TelldusCore::TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ) { + unsigned char dataByte = 0; + std::string retString = "R\1T"; + retString.append(1, t0); + retString.append(1, t1); + retString.append(1, t2); + retString.append(1, t3); + + if (data.length() > 255) { + return ""; + } + unsigned char length = (unsigned char)data.length(); + retString.append(1, length); + + for (size_t i = 0; i < data.length(); ++i) { + dataByte <<= 2; + if (data.at(i) == '1') { + dataByte |= 1; + } else if (data.at(i) == '2') { + dataByte |= 2; + } else if (data.at(i) == '3') { + dataByte |= 3; + } + if ( (i+1) % 4 == 0) { + retString.append(1, dataByte); + dataByte = 0; + } + } + if (data.length() % 4 != 0) { + retString.append(1, dataByte); + } + + retString.append("+"); + return retString; +} diff --git a/telldus-core/driver/libtelldus-core/TellStick.h b/telldus-core/driver/libtelldus-core/TellStick.h index e654feec..7dce4ad7 100644 --- a/telldus-core/driver/libtelldus-core/TellStick.h +++ b/telldus-core/driver/libtelldus-core/TellStick.h @@ -43,6 +43,8 @@ namespace TelldusCore { static TellStick *findFirstDevice(int vid = 0, int pid = 0); static TellStick *loadBy(int vid, int pid, const std::string &serial); + + static std::string convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ); protected: TellStick(const TellStickDescriptor &d); From 3990d9ca66d0459eca735a5831f40ddb65e503dd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 21 Feb 2011 11:04:43 +0000 Subject: [PATCH 1591/2215] Converted using function TellStick::convertSToT() instead. --- .../libtelldus-core/DeviceSilvanChip.cpp | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/telldus-core/driver/libtelldus-core/DeviceSilvanChip.cpp b/telldus-core/driver/libtelldus-core/DeviceSilvanChip.cpp index c0abe0f3..adf040db 100644 --- a/telldus-core/driver/libtelldus-core/DeviceSilvanChip.cpp +++ b/telldus-core/driver/libtelldus-core/DeviceSilvanChip.cpp @@ -1,4 +1,5 @@ #include "DeviceSilvanChip.h" +#include "TellStick.h" #include using namespace TelldusCore; @@ -65,39 +66,41 @@ int DeviceSilvanChip::methods(){ } std::string DeviceSilvanChip::getStringCode(Controller *controller, int method){ - const unsigned char S = 100; - const unsigned char L = 255; - const std::string LONG = "\255\1\200"; - const std::string ONE = LONG + "\100"; - const std::string ZERO = "\100" + LONG; - std::string strReturn = "R\1S"; + std::string times = "\255\1\200\100"; + const unsigned char S = '3'; + const unsigned char L = '0'; + const std::string LONG = "012"; + + const std::string ONE = LONG + "3"; + const std::string ZERO = "3" + LONG; + std::string strReturn; strReturn.append(1, S); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, L); - strReturn.append(1, 1); + strReturn.append(1, '1'); strReturn.append(1, S); for( int i = 19; i >= 0; --i ) { @@ -126,8 +129,8 @@ std::string DeviceSilvanChip::getStringCode(Controller *controller, int method){ } strReturn.append(ZERO); - strReturn.append("+"); - return strReturn; + + return TellStick::convertSToT( 255, 1, 200, 100, strReturn); } From 8624770f602b566d6c519b4b31d2d470def62885 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 21 Feb 2011 11:35:24 +0000 Subject: [PATCH 1592/2215] Code cleanup --- .../Plugins/SchedulerGUISimple/CMakeLists.txt | 1 + .../Plugins/SchedulerGUISimple/Dialog.qml | 98 ++----------------- .../Plugins/SchedulerGUISimple/InfoBox.qml | 44 +++++++++ 3 files changed, 54 insertions(+), 89 deletions(-) create mode 100644 telldus-gui/Plugins/SchedulerGUISimple/InfoBox.qml diff --git a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt index b6d08fb9..5becd70b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt +++ b/telldus-gui/Plugins/SchedulerGUISimple/CMakeLists.txt @@ -12,6 +12,7 @@ SET( Plugin_EXTRA Button.qml Dialog.qml icon.png + InfoBox.qml main.qml mainscripts.js NavButton.qml diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 7e75f866..bd690c16 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -238,68 +238,18 @@ } } - Image{ - //TODO turn into component? + InfoBox{ anchors.left: textFuzzyBeforeUnit.right - anchors.leftMargin: 5 anchors.verticalCenter: textFuzzyBeforeUnit.verticalCenter - source: imageInfo - width: 15 - height: 15 - - MouseArea{ - anchors.fill: parent - hoverEnabled: true - onEntered: { - infobox.opacity = 1 - infobox.infoboxtext = "Enter a value indicating how many minutes before the set value that the action may be executed. The action will be executed at a random time within the interval." - } - onExited: { - infobox.opacity = 0 - } - } + infotext: "Enter a value indicating how many minutes before the set value that the action may be executed. The action will be executed at a random time within the interval." } - Image{ - //TODO turn into component? + InfoBox{ anchors.left: textFuzzyAfterUnit.right - anchors.leftMargin: 5 anchors.verticalCenter: textFuzzyAfterUnit.verticalCenter - source: imageInfo - width: 15 - height: 15 - - MouseArea{ - anchors.fill: parent - hoverEnabled: true - onEntered: { - infobox.opacity = 1 - infobox.infoboxtext = "Enter a value indicating how many minutes after the set value that the action may be executed. The action will be executed at a random time within the interval." - } - onExited: { - infobox.opacity = 0 - } - } - } - - Rectangle{ - id: infobox - property alias infoboxtext: infoboxtext.text - opacity: 0 - color: "antiquewhite" - width: infoboxtext.width + 4 - height: infoboxtext.height + 4 - border.color: "black" - border.width: 1 - Text{ - id: infoboxtext - anchors.centerIn: parent - width: 200 - wrapMode: Text.WordWrap - text: "" - } + infotext: "Enter a value indicating how many minutes after the set value that the action may be executed. The action will be executed at a random time within the interval." } } @@ -359,26 +309,11 @@ } } - Image{ + InfoBox{ anchors.left: textOffsetUnit.right - anchors.leftMargin: 5 anchors.verticalCenter: textOffsetUnit.verticalCenter - - source: imageInfo - width: 15 - height: 15 - - MouseArea{ - anchors.fill: parent - hoverEnabled: true - onEntered: { - infobox.opacity = 1 - infobox.infoboxtext = "Enter a positive or negative value for how many minutes before or after sunset/sunrise this action will be executed." - } - onExited: { - infobox.opacity = 0 - } - } + z: 200 //No use, but wait until, the correct design is set, add them in correct order or something then + infotext: "Enter a positive or negative value for how many minutes before or after sunset/sunrise this action will be executed." } } @@ -515,26 +450,11 @@ } } - Image{ + InfoBox{ anchors.left: inputDim.right - anchors.leftMargin: 5 anchors.verticalCenter: inputDim.verticalCenter - source: imageInfo - width: 15 - height: 15 - - MouseArea{ - anchors.fill: parent - hoverEnabled: true - onEntered: { - infobox.opacity = 1 - infobox.infoboxtext = "Enter a dim percent value between 0 (no light) and 100 (full light)" - } - onExited: { - infobox.opacity = 0 - } - } + infotext: "Enter a dim percent value between 0 (no light) and 100 (full light)" } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/InfoBox.qml b/telldus-gui/Plugins/SchedulerGUISimple/InfoBox.qml new file mode 100644 index 00000000..e223e4cd --- /dev/null +++ b/telldus-gui/Plugins/SchedulerGUISimple/InfoBox.qml @@ -0,0 +1,44 @@ +import Qt 4.7 + +Image{ + property string infotext: "" + anchors.leftMargin: 5 + + source: imageInfo + width: 15 + height: 15 + z: 200 + + MouseArea{ + anchors.fill: parent + hoverEnabled: true + onEntered: { + infobox.opacity = 1 + infobox.infoboxtext = parent.infotext + infobox.anchors.top = parent.bottom + infobox.anchors.horizontalCenter = parent.horizontalCenter + } + onExited: { + infobox.opacity = 0 + } + } + + Rectangle{ + id: infobox + property alias infoboxtext: infoboxtext.text + opacity: 0 + color: "antiquewhite" + width: infoboxtext.width + 4 + height: infoboxtext.height + 4 + border.color: "black" + border.width: 1 + z: 200 + Text{ + id: infoboxtext + anchors.centerIn: parent + width: 200 + wrapMode: Text.WordWrap + text: "" + } + } +} \ No newline at end of file From 2b4aa09551c1972d5d7fbc52a9c2d725e6a8fdb1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 21 Feb 2011 12:44:45 +0000 Subject: [PATCH 1593/2215] Code cleanup --- .../SchedulerGUISimple/ActionPoint.qml | 34 +++++-------------- .../Plugins/SchedulerGUISimple/Dialog.qml | 2 +- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 38eecb9a..0d4d5844 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -23,6 +23,8 @@ Rectangle{ property variant lastRun: 0; property alias deviceRow: pointRect.parent property variant selectedDate: (deviceRow == null || deviceRow == undefined) ? new Date() : deviceRow.selectedDate + property int daydate: (deviceRow == null || deviceRow == undefined || deviceRow.parent == undefined || deviceRow.parent.parent == undefined) ? -1 : deviceRow.parent.parent.daydate.getDay() + Component.onCompleted: { //TODO useless really, still gets Cannot anchor to a null item-warning... @@ -79,15 +81,10 @@ Rectangle{ onClicked: { if (mouse.button == Qt.RightButton){ pointRect.toggleType() - //dialog.show(pointRect) - } - else{ - //dialog.show(pointRect) } } onPositionChanged: { - //var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); var rootCoordinates = pointRect.mapToItem(pointRect.parent, mouse.x, mouse.y); var hourMinute = getTimeFromPosition(rootCoordinates.x - mouse.x + pointRect.width/2) if((hourMinute[0] >= 0) && hourMinute[0] < 24){ @@ -100,8 +97,8 @@ Rectangle{ pointRect.deviceRow.setChanged(); pointRect.deviceRow.updateContinuingBars() dialog.show(pointRect) //TODO not pointRect, but parentPoint if such exists - dialog.absoluteHour = Scripts.pad(pointRect.absoluteHour, 2) //Scripts.pad(hourMinute[0], 2) - dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) //Scripts.pad(hourMinute[1], 2) + dialog.absoluteHour = Scripts.pad(pointRect.absoluteHour, 2) + dialog.absoluteMinute = Scripts.pad(pointRect.absoluteMinute, 2) if(parentPoint != undefined){ parentPoint.absoluteHour = parseInt(dialog.absoluteHour, 10); @@ -213,14 +210,7 @@ Rectangle{ PropertyChanges { target: pointRect; actionTypeColor: getLastPointColor() } PropertyChanges { target: pointRect; actionTypeImage: imageActionBell } StateChangeScript{ name: "updateBars"; script: updateBars(); } - }//, - /* - State{ //TODO test - name: "test"; when: pointRect.parentPoint != undefined //&& pointRect.parentPoint.absoluteHour != undefined - StateChangeScript{ name: "updateBars"; script: print("CHANGED TO TEST, " + pointRect.parentPoint.absoluteHour); } - PropertyChanges{ target: pointRect; parentPointAbsoluteHour: pointRect.parentPoint.absoluteHour } } - */ ] Rectangle{ @@ -252,7 +242,6 @@ Rectangle{ var hourSize = pointRect.parent.width / 24; var point = pointRect; if(pointRect.parentPoint != undefined){ - //print("Different x"); point = pointRect.parentPoint; } //print("ABSOLUTE X-value: " + (point.absoluteHour * hourSize + hourSize * (point.absoluteMinute/60) - point.width/2)); @@ -322,9 +311,6 @@ Rectangle{ } } - //TODO Binding loop here when moving transperent point over other point - //...or just changing state to transparent - //something with point depending on point depending on point? if(prevPoint == null || prevPoint.actionTypeOpacity == 0){ //no point before, no bar after either actionTypeOpacity = 0 @@ -349,7 +335,7 @@ Rectangle{ if(pointRect.parent == null){ return [0,0]; } - var timeOfDay = mouseX; // + (pointRect.width/2); + var timeOfDay = mouseX; var hourSize = pointRect.parent.width / 24; var hours = Math.floor(timeOfDay / hourSize); var partOfHour = ((timeOfDay - (hourSize * hours))/hourSize) * 60 @@ -360,7 +346,6 @@ Rectangle{ } function addActiveState(state){ - //print("Adding state: " + state); ActionPointScripts.addActiveState(state); } @@ -446,7 +431,6 @@ Rectangle{ } function getTickedImageSource(index){ - //print("GETTING TICKED"); index = Scripts.getOffsetWeekday(index); if(pointRect.deviceRow.parent == undefined || pointRect.deviceRow.parent.parent == undefined){ //to get rid of warnings on initialization //undefined, should only be in the beginning @@ -456,11 +440,11 @@ Rectangle{ if(pointRect.parentPoint != undefined){ originalPoint = pointRect.parentPoint; } - if(index == pointRect.deviceRow.parent.parent.daydate.getDay()){ //TODO property or so + if(index == pointRect.daydate){ //current day should always be ticked return "alwaysticked.png"; } - else if(originalPoint.getChildPoint(index) == undefined && index != originalPoint.deviceRow.parent.parent.daydate.getDay()){ //TODO turn this parent-parent into a property + else if(originalPoint.getChildPoint(index) == undefined && index != originalPoint.daydate){ return "unticked.png"; } else{ @@ -474,11 +458,11 @@ Rectangle{ if(pointRect.parentPoint != undefined){ originalPoint = pointRect.parentPoint; } - if(index == pointRect.deviceRow.parent.parent.daydate.getDay()){ + if(index == pointRect.daydate){ //cannot change this, do nothing return; } - if(index == originalPoint.deviceRow.parent.parent.daydate.getDay()){ + if(index == originalPoint.daydate){ //trying to remove the parentPoint, special removal procedure needed originalPoint.removeParentPoint(pointRect); } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index bd690c16..703b9dda 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -312,7 +312,7 @@ InfoBox{ anchors.left: textOffsetUnit.right anchors.verticalCenter: textOffsetUnit.verticalCenter - z: 200 //No use, but wait until, the correct design is set, add them in correct order or something then + z: 200 //TODO No use, but wait until, the correct design is set, add them in correct order or something then infotext: "Enter a positive or negative value for how many minutes before or after sunset/sunrise this action will be executed." } } From 5485d6194ec7f158ec62c547d8fda0fedbee33c3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 21 Feb 2011 16:20:02 +0000 Subject: [PATCH 1594/2215] Active states now depends on which methods the device supports --- .../SchedulerGUISimple/ActionPoint.qml | 6 ++--- .../Plugins/SchedulerGUISimple/Dialog.qml | 25 +++---------------- .../Plugins/SchedulerGUISimple/__init__.js | 2 ++ .../Plugins/SchedulerGUISimple/main.qml | 13 +++++----- .../Plugins/SchedulerGUISimple/mainscripts.js | 17 +++++++++++-- .../SchedulerGUISimple/schedulerscripts.js | 9 +++++++ 6 files changed, 38 insertions(+), 34 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml index 0d4d5844..e81795c6 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionPoint.qml @@ -111,7 +111,7 @@ Rectangle{ drag.axis: Drag.XAxis drag.minimumX: -1 * pointRect.width/2 drag.maximumX: pointRect.parent == null ? 0 : pointRect.parent.width - pointRect.width/2 - drag.filterChildren: true //TODO testing this + drag.filterChildren: true //TODO make it impossible to overlap (on release) (why?) //TODO drag to most right - jumps back, why? @@ -147,14 +147,14 @@ Rectangle{ PropertyChanges { target: triggerImage; source: imageTriggerSunrise; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunRiseTime.callWith(pointRect.parent.width, pointRect.width, pointRect.selectedDate) + minutesToTimelineUnits(pointRect.offset) } //TODO se nedan + PropertyChanges { target: pointRect; x: getSunRiseTime.callWith(pointRect.parent.width, pointRect.width, pointRect.selectedDate) + minutesToTimelineUnits(pointRect.offset) } }, State { name: "sunset" PropertyChanges { target: triggerImage; source: imageTriggerSunset; opacity: 1 } PropertyChanges { target: triggerTime; opacity: 0 } PropertyChanges { target: pointRectMouseArea; drag.target: undefined } - PropertyChanges { target: pointRect; x: getSunSetTime.callWith(pointRect.parent.width, pointRect.width, pointRect.selectedDate) + minutesToTimelineUnits(pointRect.offset) } //TODO räkna om till tidsunits + PropertyChanges { target: pointRect; x: getSunSetTime.callWith(pointRect.parent.width, pointRect.width, pointRect.selectedDate) + minutesToTimelineUnits(pointRect.offset) } }, State { name: "absolute"; when: !pointRectMouseArea.drag.active diff --git a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml index 703b9dda..f4218e2a 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/Dialog.qml @@ -7,6 +7,7 @@ property alias absoluteHour: inputAbsoluteHourText.text property alias absoluteMinute: inputAbsoluteMinuteText.text property alias dialogOpacity: container.opacity + property ListModel typeListModel: ListModel {} focus: true Keys.onPressed: { @@ -82,9 +83,10 @@ container.actionPoint = actionPoint var rootCoordinates = actionPoint.mapToItem(null, actionPoint.x, actionPoint.y); - container.y = rootCoordinates.y + actionPoint.height + 10; //TODO poistion in other way, too far down in some cases now + container.y = rootCoordinates.y + actionPoint.height + 10; //TODO position in other way, too far down in some cases now container.width = actionPoint.parent.width; container.x = (actionPoint.parent.parent.width - container.width)/2; + typeList.model = Scripts.setActionTypeModel(actionPoint.getActiveStates(), typeListModel); container.opacity = 1; } @@ -528,31 +530,10 @@ anchors.leftMargin: 10 width: 100 height: 100 - model: typeSelection delegate: typeSelectionRow highlight: Rectangle { color: "lightsteelblue"; radius: 5 } snapMode: ListView.SnapToItem interactive: false - - ListModel{ - id: typeSelection - ListElement{ - name: "on" - imagesource: "on.png" - } - ListElement{ - name: "off" - imagesource: "off.png" - } - ListElement{ - name: "dim" - imagesource: "dim.png" - } - ListElement{ - name: "bell" - imagesource: "bell.png" - } - } } Rectangle{ diff --git a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js index 3e31376a..f53e2ef1 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/__init__.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/__init__.js @@ -27,10 +27,12 @@ com.telldus.schedulersimplegui = function() { }); //devices: + var supportedMethods = com.telldus.core.TELLSTICK_TURNON | com.telldus.core.TELLSTICK_TURNOFF | com.telldus.core.TELLSTICK_DIM | com.telldus.core.TELLSTICK_BELL deviceList = new com.telldus.qml.array(); var list = com.telldus.core.deviceList.getList(); for(var i=0; i < list.length; ++i) { var item = list[i]; + item.methods = com.telldus.core.methods(item.id, supportedMethods); item.isEnabled = "enabled"; item.hasChanged = "false"; deviceList.push(item); diff --git a/telldus-gui/Plugins/SchedulerGUISimple/main.qml b/telldus-gui/Plugins/SchedulerGUISimple/main.qml index 69f42f93..b4bb846b 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/main.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/main.qml @@ -195,6 +195,11 @@ import "mainscripts.js" as MainScripts property alias continuingBar: continuingBar property variant selectedDate: main.selectedDate property int currentDayIndex: MainScripts.getCurrentDayIndex(main.selectedDate) + property variant activeStates + + Component.onCompleted: { + activeStates = MainScripts.getStates(modelData.methods) + } state: "enabled" @@ -222,17 +227,11 @@ import "mainscripts.js" as MainScripts dynamicPoint.absoluteMinute = hourMinute[1] dynamicPoint.x = dynamicPoint.getAbsoluteXValue(); dynamicPoint.border.color = "blue" - - //TODO different states depending on the device - dynamicPoint.addActiveState("on"); - dynamicPoint.addActiveState("off"); - dynamicPoint.addActiveState("dim"); - dynamicPoint.addActiveState("bell"); + dynamicPoint.setActiveStates(deviceRow.activeStates); dynamicPoint.setFirstState(); dynamicPoint.pointId = new Date().getTime(); //just needed for storage update deviceRow.updateContinuingBars(); dialog.show(dynamicPoint) - } } diff --git a/telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js index c3ea5d07..276d86b9 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/mainscripts.js @@ -57,6 +57,20 @@ function getMorningDarkWidth(){ } } +function getStates(methods){ + var activeStates = new Array(); + + var i = 1; + while(i <= methods){ + if(methods & i){ + activeStates.push(getStateFromMethod.callWith(i)); + } + i = i<<1; + } + + return activeStates; +} + function getSunData(){ if(calculatedSunData == undefined){ main.updateCurrentDay(); @@ -145,7 +159,6 @@ function addPointToGUI(key, job){ var deviceId = key; var jobdata = job.v; var state = getStateFromMethod.callWith(jobdata.method); - var activeStates = new Array("on", "off", "dim", "bell"); //TODO get dynamically, depending on device... var dimvalue = jobdata.value; var absoluteTime = jobdata.absoluteTime; var pointId = jobdata.id; @@ -180,7 +193,7 @@ function addPointToGUI(key, job){ if(dynamicPoint.triggerstate == "absolute"){ dynamicPoint.x = dynamicPoint.getAbsoluteXValue(); } - dynamicPoint.setActiveStates(activeStates); //TODO: active states depending on the device (get this from __init__ etc) + dynamicPoint.setActiveStates(pointParentDevice.activeStates); dynamicPoint.setFirstState(state); dynamicPoint.dimvalue = dimvalue * (100/255); dynamicPoint.pointId = pointId; diff --git a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js index 919d19b2..ee2bacc2 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js +++ b/telldus-gui/Plugins/SchedulerGUISimple/schedulerscripts.js @@ -65,3 +65,12 @@ function pad(number, length) { return str; } +function setActionTypeModel(activeStates, typeListModel){ + + typeListModel.clear(); + for(var i=0;i Date: Tue, 22 Feb 2011 10:39:34 +0000 Subject: [PATCH 1595/2215] Removed last(?) anchor-warnings --- .../Plugins/SchedulerGUISimple/ActionBar.qml | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml index a886dc57..7b44bebc 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml +++ b/telldus-gui/Plugins/SchedulerGUISimple/ActionBar.qml @@ -17,28 +17,26 @@ Rectangle{ width: barRectangle.prevDayWidth onStateChanged: { - //cannot bind these values as state change properties for some reason, do it here instead + //cannot bind these values as state change properties for some reason (will generate anchor-to-null-item warnings), do it here instead if(state == "pointLoaded"){ anchors.verticalCenter = hangOnToPoint.verticalCenter; anchors.left = hangOnToPoint.horizontalCenter; } + else if(state == "continuingWithLimitedWidth"){ + anchors.verticalCenter = hangOnToPoint.verticalCenter; + anchors.left = hangOnToPoint.left; + } + else if(state == "continuing"){ + anchors.verticalCenter = hangOnToPoint.verticalCenter + anchors.left = hangOnToPoint.left + } } states: [ - State{ - name: "continuing" - PropertyChanges { - target: barRectangle - anchors.verticalCenter: hangOnToPoint.verticalCenter - anchors.left: hangOnToPoint.left - } - }, State{ name: "continuingWithLimitedWidth" PropertyChanges { target: barRectangle - anchors.verticalCenter: hangOnToPoint.verticalCenter - anchors.left: hangOnToPoint.left width: Scripts.getFirstPointWidth(hangOnToPoint) } }, @@ -46,8 +44,6 @@ Rectangle{ name: "pointLoaded" PropertyChanges { target: barRectangle - //anchors.verticalCenter: hangOnToPoint.verticalCenter //TODO Warning on this and the line below... cannot fix, warning even if setting to undefined directly - //anchors.left: hangOnToPoint.horizontalCenter color: hangOnToPoint.actionTypeColor opacity: hangOnToPoint.actionTypeOpacity width: hangOnToPoint.parent == null ? 0 : Scripts.getBarWidth(barRectangle, hangOnToPoint, hangOnToPoint.parent.children) From f2d63f39761c0054ab7302b6ab09ee65e40a2bff Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 09:58:53 +0000 Subject: [PATCH 1596/2215] Updated icon on Mac OS X --- telldus-gui/TelldusCenter/TelldusCenter.icns | Bin 113971 -> 104676 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/telldus-gui/TelldusCenter/TelldusCenter.icns b/telldus-gui/TelldusCenter/TelldusCenter.icns index 6c6419ba2d2cafd908a8fb3cd3bb723ecfa9bdf7..d22cb52a416da595fd98237050098e681c592916 100644 GIT binary patch literal 104676 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

O%4-WtS%jw_QLVy+l=dVE-{>BRj|A+I} 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

Glxl`u#A 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 literal 113971 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 sjAD?nb>Q9fPf%~+<<`mACJPqbpQYW From 9df813267fbd7a9d9cc6e0b425283fb8ba29719c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 10:05:07 +0000 Subject: [PATCH 1597/2215] Some fixes for OS X since the Qt uitools doesn't seem to be found correctly --- telldus-gui/TelldusCenter/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 34a3b329..71295563 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -62,6 +62,12 @@ ADD_DEFINITIONS( -DVERSION=${DISPLAYED_VERSION} ) SET( telldus-center_TARGET TelldusCenter ) IF (APPLE) #### Mac OS X #### + LIST(APPEND telldus-center_LIBRARIES + /usr/lib/libQtUiTools.a + ) + INCLUDE_DIRECTORIES( + /usr/include/QtUiTools + ) ELSEIF (WIN32) #### Windows #### ADD_DEFINITIONS( -DUNICODE ) From 3d55d4b922c7ce3f70605bbd6e2fef3504a30d6e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 10:22:26 +0000 Subject: [PATCH 1598/2215] Fixed some naming of TelldusCenter --- telldus-gui/TelldusCenter/Info.plist | 4 ++-- telldus-gui/TelldusCenter/main.cpp | 2 +- telldus-gui/TelldusCenter/mainwindow.cpp | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/telldus-gui/TelldusCenter/Info.plist b/telldus-gui/TelldusCenter/Info.plist index c6f34d9e..e6d0072b 100644 --- a/telldus-gui/TelldusCenter/Info.plist +++ b/telldus-gui/TelldusCenter/Info.plist @@ -15,9 +15,9 @@ CFBundleInfoDictionaryVersion 6.0 CFBundleName - Telldus Center + TelldusCenter CFBundleShortVersionString - Telldus Center 2.0.0 + TelldusCenter 2.0.0 CFBundleVersion 2.0.0 diff --git a/telldus-gui/TelldusCenter/main.cpp b/telldus-gui/TelldusCenter/main.cpp index b97611c8..6750bf3f 100644 --- a/telldus-gui/TelldusCenter/main.cpp +++ b/telldus-gui/TelldusCenter/main.cpp @@ -16,7 +16,7 @@ int main(int argc, char *argv[]) QCoreApplication::setOrganizationName("Telldus"); QCoreApplication::setOrganizationDomain("www.telldus.se"); - QCoreApplication::setApplicationName("Telldus Center"); + QCoreApplication::setApplicationName("TelldusCenter"); bool showMinimized = false; for( int i = 1; i < argc; ++i ) { diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 07fa0b8d..1578d4d9 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -63,7 +63,7 @@ MainWindow::MainWindow(ScriptEnvironment *env, QWidget *parent, Qt::WFlags flags setupToolBar(); - setWindowTitle( tr("Telldus Center") ); + setWindowTitle( tr("TelldusCenter") ); } MainWindow::~MainWindow() @@ -95,7 +95,7 @@ void MainWindow::setupMenu() { helpMenu->addSeparator(); QAction *aboutQt = helpMenu->addAction(tr("About &Qt"), qApp, SLOT(aboutQt())); aboutQt->setMenuRole( QAction::AboutQtRole ); - QAction *aboutTelldusCenter = helpMenu->addAction(tr("About &Telldus Center"), this, SLOT(slotAboutApplication())); + QAction *aboutTelldusCenter = helpMenu->addAction(tr("About &TelldusCenter"), this, SLOT(slotAboutApplication())); aboutTelldusCenter->setMenuRole( QAction::AboutRole ); } @@ -131,8 +131,8 @@ void MainWindow::addWidget( const QString &page, const QIcon &icon, QWidget *wid } void MainWindow::slotAboutApplication() { - QMessageBox::about(this, tr("About Telldus Center"), - tr("

").arg(VERSION_STRING(VERSION))); } void MainWindow::slotConfigure() { From d210476e13a3653cbfe62b7f3c1d41f269ca7d59 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 11:59:04 +0000 Subject: [PATCH 1662/2215] Add the possibility to supply the variable TELLDUSCORE_INCLUDE_PATH for custom location of telldus-core.h --- telldus-gui/cmake/FindTelldusCore.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-gui/cmake/FindTelldusCore.cmake b/telldus-gui/cmake/FindTelldusCore.cmake index e3bf13fa..6046ae72 100644 --- a/telldus-gui/cmake/FindTelldusCore.cmake +++ b/telldus-gui/cmake/FindTelldusCore.cmake @@ -13,7 +13,9 @@ ELSEIF (WINDOWS) ELSE (APPLE) FIND_LIBRARY( TELLDUSCORE_LIBRARY telldus-core ) - ENDIF(APPLE) +IF(TELLDUSCORE_INCLUDE_PATH) + INCLUDE_DIRECTORIES(${TELLDUSCORE_INCLUDE_PATH}) +ENDIF() From da2308b29c877fa7a5cfd7249659b632f7208864 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 13:01:37 +0000 Subject: [PATCH 1663/2215] Copy the public headers to the target directory on Windows. --- telldus-core/client/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index a4ad7778..f6b12681 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -85,6 +85,17 @@ ADD_LIBRARY(${telldus-core_TARGET} SHARED ${telldus-core_PUB_HDRS} ) +#Copy public headers files on windows +IF (WIN32) + FOREACH(_FILE ${telldus-core_PUB_HDRS}) + ADD_CUSTOM_COMMAND( TARGET ${telldus-core_TARGET} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}" "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}" + COMMENT "Copy ${_FILE}" + ) + ENDFOREACH(_FILE) +ENDIF () + ADD_DEPENDENCIES(${telldus-core_TARGET} TelldusCommon) IF (UNIX) From 5f0d1b3c7272e42d375512ca85c918451354233f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 13:03:20 +0000 Subject: [PATCH 1664/2215] Find the telldus-core.h header in the output directory on Windows. --- telldus-gui/CMakeLists.txt | 6 +-- .../Plugins/TelldusCore/CMakeLists.txt | 4 -- telldus-gui/TelldusGui/CMakeLists.txt | 5 +-- telldus-gui/cmake/FindTelldusCore.cmake | 42 +++++++++---------- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index b5236e92..6de4f891 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -24,12 +24,10 @@ SET(BUILD_TELLDUS-CENTER TRUE CACHE BOOL "Build TelldusCenter") SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") -IF (WIN32) - SET(TELLDUSCORE_INCLUDE_DIR "" CACHE PATH "Path to the directory which contains telldus-core.h") -ELSEIF(UNIX) +IF(UNIX) SET(PLUGIN_LIB_PATH "lib" CACHE STRING "Relative path to the directory to install TelldusCenter plugin libraries into") SET(PLUGIN_LIB_FULL_PATH "${PLUGIN_LIB_PATH}/telldus/tellduscenter/plugins") -ENDIF (WIN32) +ENDIF () if(BUILD_LIBTELLDUS-GUI) ADD_SUBDIRECTORY(TelldusGui) diff --git a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt index 01821e4f..c5375aed 100644 --- a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt +++ b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt @@ -21,9 +21,5 @@ SET( Plugin_EXTRA FIND_PACKAGE(TelldusCore REQUIRED) SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ) -INCLUDE_DIRECTORIES( - ${TELLDUSCORE_INCLUDE_DIR} -) - INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 89d7ec60..73f39c67 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -71,7 +71,7 @@ SET( telldus-gui_LIBRARIES ) FIND_PACKAGE(TelldusCore REQUIRED) -list(APPEND telldus-gui_LIBRARIES ${TELLDUSCORE_LIBRARY} ) +LIST(APPEND telldus-gui_LIBRARIES ${TELLDUSCORE_LIBRARY} ) ######## Configurable options for the platform ######## @@ -96,9 +96,6 @@ ELSEIF (WIN32) -D_WINDOWS -DTELLDUSGUI_EXPORTS ) - INCLUDE_DIRECTORIES( - ${TELLDUSCORE_INCLUDE_DIR} - ) ELSE (APPLE) #### Linux #### SET( telldus-gui_TARGET telldus-gui ) diff --git a/telldus-gui/cmake/FindTelldusCore.cmake b/telldus-gui/cmake/FindTelldusCore.cmake index 6046ae72..3bedd638 100644 --- a/telldus-gui/cmake/FindTelldusCore.cmake +++ b/telldus-gui/cmake/FindTelldusCore.cmake @@ -1,21 +1,21 @@ - -IF (APPLE) - FIND_LIBRARY( TELLDUSCORE_LIBRARY TelldusCore ) - - INCLUDE_DIRECTORIES( - ${TELLDUSCORE_LIBRARY}/Headers - ) - -ELSEIF (WINDOWS) - SET(TELLDUSCORE_LIBRARY ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCore.lib) - - -ELSE (APPLE) - FIND_LIBRARY( TELLDUSCORE_LIBRARY telldus-core ) - -ENDIF(APPLE) - -IF(TELLDUSCORE_INCLUDE_PATH) - INCLUDE_DIRECTORIES(${TELLDUSCORE_INCLUDE_PATH}) -ENDIF() - + +IF (APPLE) + FIND_LIBRARY( TELLDUSCORE_LIBRARY TelldusCore ) + + INCLUDE_DIRECTORIES( + ${TELLDUSCORE_LIBRARY}/Headers + ) + +ELSEIF (WIN32) + SET(TELLDUSCORE_LIBRARY ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCore.lib) + SET(TELLDUSCORE_INCLUDE_PATH ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/) + +ELSE (APPLE) + FIND_LIBRARY( TELLDUSCORE_LIBRARY telldus-core ) + +ENDIF(APPLE) + +IF(TELLDUSCORE_INCLUDE_PATH) + INCLUDE_DIRECTORIES(${TELLDUSCORE_INCLUDE_PATH}) +ENDIF() + From 9bcf456c14590a268b7a915f7954e1bdfe19cf7b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:44 +0000 Subject: [PATCH 1665/2215] Converted several SET_PROPERTY(TARGET) to one SET_TARGET_PROPERTIES() --- telldus-core/client/CMakeLists.txt | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index f6b12681..235cec12 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -104,18 +104,11 @@ ENDIF (UNIX) TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY FRAMEWORK TRUE -) -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY PUBLIC_HEADER ${telldus-core_PUB_HDRS} -) - -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY VERSION ${PACKAGE_VERSION} -) -SET_PROPERTY(TARGET ${telldus-core_TARGET} - PROPERTY SOVERSION ${PACKAGE_SOVERSION} +SET_TARGET_PROPERTIES(${telldus-core_TARGET} PROPERTIES + FRAMEWORK TRUE + PUBLIC_HEADER ${telldus-core_PUB_HDRS} + VERSION ${PACKAGE_VERSION} + SOVERSION ${PACKAGE_SOVERSION} ) IF (NOT LIBRARY_DIR) From de9a27b956a3d005efbbebaea4acf62ff379753e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:47 +0000 Subject: [PATCH 1666/2215] Give the client library correct INSTALL_NAME on Mac OS X --- telldus-core/client/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 235cec12..e03e5331 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -106,6 +106,7 @@ TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) SET_TARGET_PROPERTIES(${telldus-core_TARGET} PROPERTIES FRAMEWORK TRUE + INSTALL_NAME_DIR "/Library/Frameworks" PUBLIC_HEADER ${telldus-core_PUB_HDRS} VERSION ${PACKAGE_VERSION} SOVERSION ${PACKAGE_SOVERSION} From ce3e9fabe509caf31bc1382e8cccaf9327842033 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:49 +0000 Subject: [PATCH 1667/2215] Don't install files already included in the bundle on Mac OS X --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 4 +++- telldus-gui/TelldusCenter/CMakeLists.txt | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 7647675c..c89f4556 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -112,7 +112,9 @@ IF(Plugin_PATH) COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${Plugin_PATH} COMMENT "Copy ${_FILENAME} for plugin ${Plugin_NAME}" ) - INSTALL(FILES ${_FILE} DESTINATION "${PLUGIN_LIB_FULL_PATH}/script/${Plugin_PATH_relative}") + IF (NOT APPLE) + INSTALL(FILES ${_FILE} DESTINATION "${PLUGIN_LIB_FULL_PATH}/script/${Plugin_PATH_relative}") + ENDIF () ENDFOREACH(_FILE) ENDIF(Plugin_PATH) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index d69723c6..f2c20fd9 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -171,8 +171,10 @@ IF (UNIX) ) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.1 DESTINATION share/man/man1) ENDIF (GENERATE_MAN) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/images/tellduscenter.xpm DESTINATION share/pixmaps) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.desktop DESTINATION share/applications) + IF (NOT APPLE) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/images/tellduscenter.xpm DESTINATION share/pixmaps) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.desktop DESTINATION share/applications) + ENDIF () ENDIF (UNIX) From 47998b0d5e1d75e41a30578fcd8f13f51b9a7b4f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:51 +0000 Subject: [PATCH 1668/2215] Add .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..567609b1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ From 83245b16e1046598ab3a75fd7e0bc7295669302d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:53 +0000 Subject: [PATCH 1669/2215] Add BUNDLE DESTINATION to TelldusCenter --- telldus-gui/TelldusCenter/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index f2c20fd9..b8513b94 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -180,5 +180,6 @@ ENDIF (UNIX) INSTALL(TARGETS ${telldus-center_TARGET} RUNTIME DESTINATION bin + BUNDLE DESTINATION "/Applications" ) From 74d8b813ae4541c84604d2607f22915e60fc460f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:54 +0000 Subject: [PATCH 1670/2215] Add FRAMEWORK DESTINATION to TelldusGui --- telldus-gui/TelldusGui/CMakeLists.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 73f39c67..8e651c19 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -154,9 +154,10 @@ SET_PROPERTY(TARGET ${telldus-gui_TARGET} PROPERTY SOVERSION ${PACKAGE_SOVERSION} ) -if (UNIX) -INSTALL(TARGETS ${telldus-gui_TARGET} - LIBRARY DESTINATION lib -# PUBLIC_HEADER DESTINATION ${HEADER_DIR} -) -endif (UNIX) +IF (UNIX) + INSTALL(TARGETS ${telldus-gui_TARGET} + LIBRARY DESTINATION lib + FRAMEWORK DESTINATION /Applications/TelldusCenter.app/Contents/Frameworks + # PUBLIC_HEADER DESTINATION ${HEADER_DIR} + ) +ENDIF (UNIX) From ae8aea78567ec662e435e8c3a6ac88e40f02d095 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:56 +0000 Subject: [PATCH 1671/2215] Install the translation files for TelldusCenter as part of the install target. The target directory might not be setup earlier --- telldus-gui/TelldusCenter/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index b8513b94..e4f68655 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -120,16 +120,15 @@ ENDFOREACH(lang) IF (UPDATE_TRANSLATIONS) QT4_CREATE_TRANSLATION( QM_FILES ${telldus-center_SRCS} ${telldus-center_TS} ) ELSE (UPDATE_TRANSLATIONS) - IF (APPLE) - SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Resources - ) - ELSEIF (UNIX) + IF (UNIX) SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter ) ENDIF (APPLE) QT4_ADD_TRANSLATION(telldus-center_QM ${telldus-center_TS}) + IF (APPLE) + INSTALL(FILES ${telldus-center_QM} DESTINATION /Applications/TelldusCenter.app/Contents/Resources) + ENDIF () ENDIF (UPDATE_TRANSLATIONS) From 891d8dfdb60441da91ea6d90dcc0f99ee21bb5a4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 6 Sep 2011 15:25:58 +0000 Subject: [PATCH 1672/2215] Build TelldusCenter before any of the plugins --- telldus-gui/TelldusGui/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 8e651c19..bfed69d0 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -133,6 +133,7 @@ ADD_LIBRARY(${telldus-gui_TARGET} SHARED ${telldus-gui_TS} ${telldus-gui_QM} ) +ADD_DEPENDENCIES(${telldus-gui_TARGET} TelldusCenter) IF (UNIX) SET_TARGET_PROPERTIES( ${telldus-gui_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") From ad60a819de482372def9b0b1dafa5e8d3d10667f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Sep 2011 13:34:59 +0000 Subject: [PATCH 1673/2215] Fix mismatching IF-block --- telldus-gui/TelldusCenter/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index e4f68655..0cc1e0a8 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -124,7 +124,7 @@ ELSE (UPDATE_TRANSLATIONS) SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter ) - ENDIF (APPLE) + ENDIF () QT4_ADD_TRANSLATION(telldus-center_QM ${telldus-center_TS}) IF (APPLE) INSTALL(FILES ${telldus-center_QM} DESTINATION /Applications/TelldusCenter.app/Contents/Resources) From bc7466cbc222cda5b76795f2044abc72507a9c68 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Sep 2011 13:35:01 +0000 Subject: [PATCH 1674/2215] Use BundleUtilities to fix and copy frameworks to our bundle --- telldus-gui/TelldusCenter/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 0cc1e0a8..b8356b54 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -176,9 +176,16 @@ IF (UNIX) ENDIF () ENDIF (UNIX) - INSTALL(TARGETS ${telldus-center_TARGET} RUNTIME DESTINATION bin BUNDLE DESTINATION "/Applications" ) +IF (APPLE) + SET(bundle "/Users/micke/Documents/dev/telldus-pub/telldus-gui/build/distr/Applications/TelldusCenter.app") #TODO + INSTALL(CODE " + INCLUDE(BundleUtilities) + FIXUP_BUNDLE(\"${bundle}\" \"\" \"\") + ") +ENDIF () + From 0e0e6888170af291c1f412f0916fcf209c19b0cc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Sep 2011 13:35:03 +0000 Subject: [PATCH 1675/2215] Fix the plugins with install_tool_name using BundleUtilities --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index c89f4556..eda74bb9 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -81,6 +81,32 @@ IF(Plugin_SRCS) LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script PREFIX "../" ) + INSTALL(CODE " + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") + GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) + SET(plugin \"\${bundle}/Contents/Plugins/script/${Plugin_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}\") + + GET_ITEM_KEY(\"\${plugin}\" pkey) + SET(prereqs \"\") + GET_PREREQUISITES(\${plugin} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\") + FOREACH(pr \${prereqs}) + GET_ITEM_KEY(\"\${pr}\" rkey) + + #Don't change the path to our own libraries + IF (NOT \"\${rkey}\" MATCHES \"^Telldus\") + #Check to see if this is ourself + IF (NOT \${pkey} STREQUAL \${rkey}) + SET(kv \"\") + SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exe}\" \"\${bundle}/Contents/Frameworks/\" 0) + EXECUTE_PROCESS(COMMAND install_name_tool + -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${plugin}\" + ) + ENDIF () + ENDIF () + + ENDFOREACH() + ") ELSEIF (WIN32) SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES PREFIX "Plugins/script/" From 9e1bcc5edd3acdba7f665b2344589e061a49c967 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Sep 2011 13:35:05 +0000 Subject: [PATCH 1676/2215] Convert several SET_PROPERTY(TARGET) to one SET_TARGET_PROPERTIES() --- telldus-gui/TelldusGui/CMakeLists.txt | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index bfed69d0..97fa9e1d 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -141,18 +141,11 @@ ENDIF (UNIX) TARGET_LINK_LIBRARIES( ${telldus-gui_TARGET} ${telldus-gui_LIBRARIES} ) -SET_PROPERTY(TARGET ${telldus-gui_TARGET} - PROPERTY FRAMEWORK TRUE -) -#SET_PROPERTY(TARGET ${telldus-gui_TARGET} -# PROPERTY PUBLIC_HEADER ${telldus-gui_HDRS} -#) - -SET_PROPERTY(TARGET ${telldus-gui_TARGET} - PROPERTY VERSION ${PACKAGE_VERSION} -) -SET_PROPERTY(TARGET ${telldus-gui_TARGET} - PROPERTY SOVERSION ${PACKAGE_SOVERSION} +SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES + FRAMEWORK TRUE +# PUBLIC_HEADER ${telldus-gui_HDRS} + VERSION ${PACKAGE_VERSION} + SOVERSION ${PACKAGE_SOVERSION} ) IF (UNIX) From 5c595414fa470596319eef543e8493a7c5dab97e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Sep 2011 13:35:07 +0000 Subject: [PATCH 1677/2215] Add INSTALL_NAME_DIR property to target TelldusGui --- telldus-gui/TelldusGui/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 97fa9e1d..9db1e681 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -146,6 +146,7 @@ SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES # PUBLIC_HEADER ${telldus-gui_HDRS} VERSION ${PACKAGE_VERSION} SOVERSION ${PACKAGE_SOVERSION} + INSTALL_NAME_DIR "/Library/Frameworks" ) IF (UNIX) From 27cc14dcd0f4c0b905ecf9ed55bbd9cd83ce2013 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Sep 2011 13:52:52 +0000 Subject: [PATCH 1678/2215] Use correct path to the bundle --- telldus-gui/TelldusCenter/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index b8356b54..30bcb4c4 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -182,10 +182,12 @@ INSTALL(TARGETS ${telldus-center_TARGET} ) IF (APPLE) - SET(bundle "/Users/micke/Documents/dev/telldus-pub/telldus-gui/build/distr/Applications/TelldusCenter.app") #TODO INSTALL(CODE " INCLUDE(BundleUtilities) - FIXUP_BUNDLE(\"${bundle}\" \"\" \"\") + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") + GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) + FIXUP_BUNDLE(\"\${bundle}\" \"\" \"\") ") ENDIF () From a7c2e8501516e56f65e2af450856ee5dac13ac64 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 7 Sep 2011 14:35:12 +0000 Subject: [PATCH 1679/2215] We should rewrite the path to TelldusGui also. Only TelldusCore should be left untouched --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index eda74bb9..9a70e198 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -93,8 +93,8 @@ IF(Plugin_SRCS) FOREACH(pr \${prereqs}) GET_ITEM_KEY(\"\${pr}\" rkey) - #Don't change the path to our own libraries - IF (NOT \"\${rkey}\" MATCHES \"^Telldus\") + #Don't change the path to TelldusCore + IF (NOT \"\${rkey}\" STREQUAL \"TelldusCore\") #Check to see if this is ourself IF (NOT \${pkey} STREQUAL \${rkey}) SET(kv \"\") From b373e9e454bbf4e2071c291073798082f7cc21b3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 9 Sep 2011 09:23:56 +0000 Subject: [PATCH 1680/2215] Updated language files --- telldus-gui/TelldusCenter/TelldusCenter_sv.ts | 16 ++++++++-------- telldus-gui/TelldusGui/TelldusGui_sv.ts | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/telldus-gui/TelldusCenter/TelldusCenter_sv.ts b/telldus-gui/TelldusCenter/TelldusCenter_sv.ts index 8f144e01..260c425e 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter_sv.ts +++ b/telldus-gui/TelldusCenter/TelldusCenter_sv.ts @@ -19,38 +19,38 @@ &Inställningar - + &Quit &Avsluta - + &Help &Hjälp - + About &Qt Om &Qt - + About &TelldusCenter Om &TelldusCenter - + Pages Sidor - + About TelldusCenter Om TelldusCenter - - <center><img src=':/images/TelldusCenter_128.png' width=128 height=128 /><h2>TelldusCenter %1</h2><p>Copyright &copy; 2010 Telldus Technologies AB<p></center> + + <center><img src=':/images/TelldusCenter_128.png' width=128 height=128 /><h2>TelldusCenter %1</h2><p>Copyright &copy; 2011 Telldus Technologies AB<p></center> diff --git a/telldus-gui/TelldusGui/TelldusGui_sv.ts b/telldus-gui/TelldusGui/TelldusGui_sv.ts index a72a7f8f..f66810ab 100644 --- a/telldus-gui/TelldusGui/TelldusGui_sv.ts +++ b/telldus-gui/TelldusGui/TelldusGui_sv.ts @@ -240,32 +240,32 @@ Adresskod - + Please press a button on your remote Tryck en knapp pÃ¥ din fjärrkontroll - + If you have a TellStick Duo connected,<br>you can use it to scan the code of the remote control Om du har en TellStick Duo ansluten,<br>kan du använda den för att hitta rätt enhet och inställningar - + You must choose a device Du mÃ¥ste välja en enhet - + Please select the device you have. Välj den enhet du har. - + The device must have a name. Enheten mÃ¥ste ha ett namn. - + Please fill in a name in the field under 'Name' Skriv in ett namn i fältet 'Namn' From e2537733cb77b99dc8dfc355a7fe027d808e2ac8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Sep 2011 10:37:34 +0000 Subject: [PATCH 1681/2215] Install qt_menu.nib as part of our install target --- telldus-gui/TelldusCenter/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 30bcb4c4..41415b4f 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -182,6 +182,11 @@ INSTALL(TARGETS ${telldus-center_TARGET} ) IF (APPLE) + INSTALL( + DIRECTORY ${QT_QTGUI_LIBRARY}/Resources/qt_menu.nib + DESTINATION /Applications/TelldusCenter.app/Contents/Resources + ) + INSTALL(CODE " INCLUDE(BundleUtilities) GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) From 20d568cb4447dfd3d2b78d98ca5b50a3feacca38 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Sep 2011 10:37:37 +0000 Subject: [PATCH 1682/2215] Fix install_name for TelldusGui --- telldus-gui/TelldusGui/CMakeLists.txt | 29 ++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 9db1e681..5534233a 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -155,4 +155,31 @@ IF (UNIX) FRAMEWORK DESTINATION /Applications/TelldusCenter.app/Contents/Frameworks # PUBLIC_HEADER DESTINATION ${HEADER_DIR} ) -ENDIF (UNIX) + IF (APPLE) + INSTALL(CODE " + INCLUDE(BundleUtilities) + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + SET(lib \"\${DESTDIR}/Applications/TelldusCenter.app/Contents/Frameworks/${telldus-gui_TARGET}.framework/${telldus-gui_TARGET}\") + + GET_ITEM_KEY(\"\${lib}\" pkey) + SET(prereqs \"\") + GET_PREREQUISITES(\${lib} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\") + FOREACH(pr \${prereqs}) + GET_ITEM_KEY(\"\${pr}\" rkey) + + #Don't change the path to TelldusCore + IF (NOT \"\${rkey}\" STREQUAL \"TelldusCore\") + #Check to see if this is ourself + IF (NOT \${pkey} STREQUAL \${rkey}) + SET(kv \"\") + SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exe}\" \"\${bundle}/Contents/Frameworks/\" 0) + EXECUTE_PROCESS(COMMAND install_name_tool + -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${lib}\" + ) + ENDIF () + ENDIF () + + ENDFOREACH() + ") + ENDIF () +ENDIF () From 23d870061a2a8e11e5daf90277e39dcbcb43146b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Sep 2011 13:11:52 +0000 Subject: [PATCH 1683/2215] Add empty qt.conf on Mac OS X to make sure correct Qt-libs are loaded --- telldus-gui/TelldusCenter/CMakeLists.txt | 5 ++++- telldus-gui/TelldusCenter/qt.conf | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 telldus-gui/TelldusCenter/qt.conf diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 41415b4f..7b71568b 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -186,7 +186,10 @@ IF (APPLE) DIRECTORY ${QT_QTGUI_LIBRARY}/Resources/qt_menu.nib DESTINATION /Applications/TelldusCenter.app/Contents/Resources ) - + INSTALL( + FILES qt.conf + DESTINATION /Applications/TelldusCenter.app/Contents/Resources + ) INSTALL(CODE " INCLUDE(BundleUtilities) GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) diff --git a/telldus-gui/TelldusCenter/qt.conf b/telldus-gui/TelldusCenter/qt.conf new file mode 100644 index 00000000..4924a520 --- /dev/null +++ b/telldus-gui/TelldusCenter/qt.conf @@ -0,0 +1 @@ +[Paths] From fa131eed2ee5373fe173e00dbc29a4da037ded30 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 9 Sep 2011 13:39:53 +0000 Subject: [PATCH 1684/2215] Fixed copying of translation files for windows --- telldus-gui/TelldusCenter/CMakeLists.txt | 8 ++++++++ telldus-gui/TelldusGui/CMakeLists.txt | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 7b71568b..1194b4eb 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -176,6 +176,14 @@ IF (UNIX) ENDIF () ENDIF (UNIX) +IF (WIN32) + ADD_CUSTOM_COMMAND( TARGET ${telldus-center_TARGET} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${telldus-center_QM} ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR} VERBATIM + COMMENT "Copying translation for TelldusCenter" + ) +ENDIF() + INSTALL(TARGETS ${telldus-center_TARGET} RUNTIME DESTINATION bin BUNDLE DESTINATION "/Applications" diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 5534233a..03293b49 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -149,6 +149,14 @@ SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES INSTALL_NAME_DIR "/Library/Frameworks" ) +IF (WIN32) + ADD_CUSTOM_COMMAND( TARGET ${telldus-gui_TARGET} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${telldus-gui_QM} ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR} VERBATIM + COMMENT "Copying translation for TelldusGUI" + ) +ENDIF() + IF (UNIX) INSTALL(TARGETS ${telldus-gui_TARGET} LIBRARY DESTINATION lib From b59edb9411456a79ae6f2f129c253b4ccbaf3bfa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Sep 2011 14:19:39 +0000 Subject: [PATCH 1685/2215] Add file com.telldus.service.plist to describe and start our service on Mac OS X --- telldus-core/service/CMakeLists.txt | 1 + telldus-core/service/com.telldus.service.plist | 14 ++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 telldus-core/service/com.telldus.service.plist diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index dc0bcf4d..41be1c5f 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -185,6 +185,7 @@ IF (APPLE) SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} ) + INSTALL(FILES com.telldus.service.plist DESTINATION /Library/LaunchDaemons) ENDIF (APPLE) IF (UNIX) diff --git a/telldus-core/service/com.telldus.service.plist b/telldus-core/service/com.telldus.service.plist new file mode 100644 index 00000000..eb07a78b --- /dev/null +++ b/telldus-core/service/com.telldus.service.plist @@ -0,0 +1,14 @@ + + + + + Label + com.telldus.service + OnDemand + + ProgramArguments + + /Library/Telldus/TelldusService + + + From f8543db6b183b5ab188655c7f1bbc366565f3338 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Sep 2011 14:19:42 +0000 Subject: [PATCH 1686/2215] Install and copy necessary dependencies for TelldusService on Mac OS X --- telldus-core/service/CMakeLists.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 41be1c5f..3d116b2b 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -182,9 +182,25 @@ SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ) IF (APPLE) + SET(TELLDUS_SERVICE_TARGET_PATH "/Library/Telldus" CACHE STRING "Path to install TelldusService") SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} ) + INSTALL(TARGETS ${telldus-service_TARGET} + RUNTIME DESTINATION ${TELLDUS_SERVICE_TARGET_PATH} + ) + INSTALL(CODE " + INCLUDE(GetPrerequisites) + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + GET_PREREQUISITES(\"${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" prereqs 1 0 \"\$\" \"\$\") + FOREACH(pr \${prereqs}) + GET_FILENAME_COMPONENT(lib \${pr} NAME) + FILE(INSTALL \${pr} DESTINATION ${TELLDUS_SERVICE_TARGET_PATH}) + EXECUTE_PROCESS(COMMAND install_name_tool + -change \"\${pr}\" \"${TELLDUS_SERVICE_TARGET_PATH}/\${lib}\" \"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" + ) + ENDFOREACH () + ") INSTALL(FILES com.telldus.service.plist DESTINATION /Library/LaunchDaemons) ENDIF (APPLE) From af6cc739494e19e11dd01aa2f7587c6f753b11a9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 9 Sep 2011 14:28:15 +0000 Subject: [PATCH 1687/2215] Update copyright year --- telldus-core/tdtool/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index b6fbd87b..fe9f369e 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -71,7 +71,7 @@ void print_usage( char *name ) { void print_version() { printf("tdtool " VERSION "\n"); printf("\n"); - printf("Copyright (C) 2009 Telldus Technologies AB\n"); + printf("Copyright (C) 2011 Telldus Technologies AB\n"); printf("\n"); printf("Written by Micke Prag \n"); } From f834adcb3070425699cbafbb567d393a2ed599e0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Sep 2011 09:33:07 +0000 Subject: [PATCH 1688/2215] Sign files after build on Windows --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 2 ++ telldus-gui/TelldusCenter/CMakeLists.txt | 3 +++ telldus-gui/TelldusGui/CMakeLists.txt | 4 ++++ telldus-gui/cmake/FindSignTool.cmake | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+) create mode 100644 telldus-gui/cmake/FindSignTool.cmake diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 9a70e198..20ab8c6a 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -1,6 +1,7 @@ FIND_PACKAGE( Qt4 REQUIRED ) SET(QT_USE_QTSCRIPT TRUE) INCLUDE( ${QT_USE_FILE} ) +FIND_PACKAGE( SignTool REQUIRED ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) @@ -119,6 +120,7 @@ IF(Plugin_SRCS) LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script" ) ENDIF (APPLE) + SIGN(${Plugin_NAME}) ELSE(Plugin_SRCS) ADD_CUSTOM_TARGET(${Plugin_NAME} ALL SOURCES ${Plugin_FILES} diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 1194b4eb..7aa29d22 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -4,6 +4,8 @@ SET(QT_USE_QTNETWORK TRUE) SET(QT_USE_QTUITOOLS TRUE) INCLUDE( ${QT_USE_FILE} ) +FIND_PACKAGE( SignTool REQUIRED ) + if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) cmake_policy(SET CMP0005 NEW) @@ -148,6 +150,7 @@ TARGET_LINK_LIBRARIES( ${telldus-center_TARGET} ${telldus-center_LIBRARIES} ) SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist ) +SIGN(${telldus-center_TARGET}) IF (APPLE) SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 03293b49..fe7f5a5e 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -1,6 +1,8 @@ FIND_PACKAGE( Qt4 REQUIRED ) INCLUDE( ${QT_USE_FILE} ) +FIND_PACKAGE( SignTool REQUIRED ) + if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) endif(COMMAND cmake_policy) @@ -141,6 +143,8 @@ ENDIF (UNIX) TARGET_LINK_LIBRARIES( ${telldus-gui_TARGET} ${telldus-gui_LIBRARIES} ) +SIGN(${telldus-gui_TARGET}) + SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES FRAMEWORK TRUE # PUBLIC_HEADER ${telldus-gui_HDRS} diff --git a/telldus-gui/cmake/FindSignTool.cmake b/telldus-gui/cmake/FindSignTool.cmake new file mode 100644 index 00000000..002bca60 --- /dev/null +++ b/telldus-gui/cmake/FindSignTool.cmake @@ -0,0 +1,19 @@ + +IF(WIN32) + SET(SIGN_FILES FALSE CACHE BOOL "Sign files ofter build") +ENDIF() + +FUNCTION(SIGN TARGET) + IF (NOT WIN32) + RETURN() + ENDIF() + IF (NOT SIGN_FILES) + RETURN() + ENDIF() + GET_TARGET_PROPERTY(file ${TARGET} LOCATION) + GET_FILENAME_COMPONENT(filename ${file} NAME) + ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD + COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} + COMMENT "Signing file ${filename}" + ) +ENDFUNCTION() From 30f9ecb402d3fd5d3ec15c7bff15bb3f3f2f850b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Sep 2011 09:58:08 +0000 Subject: [PATCH 1689/2215] Sign files after build on Windows --- telldus-core/CMakeLists.txt | 5 ++--- telldus-core/client/CMakeLists.txt | 3 +++ telldus-core/cmake/FindSignTool.cmake | 19 +++++++++++++++++++ telldus-core/service/CMakeLists.txt | 4 ++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 telldus-core/cmake/FindSignTool.cmake diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index f6add68f..dfa2a942 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -16,6 +16,8 @@ SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE SET(PACKAGE_SUBVERSION) SET(PACKAGE_SOVERSION 2) +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + IF (PACKAGE_SUBVERSION) SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_${PACKAGE_SUBVERSION}") ELSE (PACKAGE_SUBVERSION) @@ -25,9 +27,6 @@ ENDIF(PACKAGE_SUBVERSION) SET(BUILD_LIBTELLDUS-CORE TRUE CACHE BOOL "Build libtelldus-core") SET(USE_QT_SETTINGS_BACKEND FALSE CACHE BOOL "Use QT as settings backend instead of the native one") -IF (WIN32) - SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") -ENDIF (WIN32) IF (WIN32) SET(TDTOOL_DEFAULT FALSE) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index e03e5331..1d5d3b1f 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -2,6 +2,8 @@ IF(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) ENDIF(COMMAND cmake_policy) +FIND_PACKAGE( SignTool REQUIRED ) + ######## Non configurable options ######## SET( telldus-core_SRCS CallbackDispatcher.cpp @@ -111,6 +113,7 @@ SET_TARGET_PROPERTIES(${telldus-core_TARGET} PROPERTIES VERSION ${PACKAGE_VERSION} SOVERSION ${PACKAGE_SOVERSION} ) +SIGN(${telldus-core_TARGET}) IF (NOT LIBRARY_DIR) SET(LIBRARY_DIR "lib") diff --git a/telldus-core/cmake/FindSignTool.cmake b/telldus-core/cmake/FindSignTool.cmake new file mode 100644 index 00000000..5ea02930 --- /dev/null +++ b/telldus-core/cmake/FindSignTool.cmake @@ -0,0 +1,19 @@ + +IF(WIN32) + SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") +ENDIF() + +FUNCTION(SIGN TARGET) + IF (NOT WIN32) + RETURN() + ENDIF() + IF (NOT SIGN_FILES) + RETURN() + ENDIF() + GET_TARGET_PROPERTY(file ${TARGET} LOCATION) + GET_FILENAME_COMPONENT(filename ${file} NAME) + ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD + COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} + COMMENT "Signing file ${filename}" + ) +ENDFUNCTION() diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 3d116b2b..e876dfc0 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -2,6 +2,8 @@ IF(COMMAND cmake_policy) CMAKE_POLICY(SET CMP0003 NEW) ENDIF(COMMAND cmake_policy) +FIND_PACKAGE( SignTool REQUIRED ) + SET (telldusd_DESCRIPTION "background service for Telldus TellStick, must be running to control TellStick" ) @@ -178,6 +180,8 @@ SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKA TARGET_LINK_LIBRARIES( ${telldus-service_TARGET} ${telldus-service_LIBRARIES} ) +SIGN(${telldus-service_TARGET}) + SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ) From cb072ca70e248ace37f089f92b9234a9b1c01cf1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Sep 2011 09:59:07 +0000 Subject: [PATCH 1690/2215] Removed obsolete settings for qt-dependency. --- telldus-core/CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index dfa2a942..4165ec69 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -26,8 +26,6 @@ ENDIF(PACKAGE_SUBVERSION) SET(BUILD_LIBTELLDUS-CORE TRUE CACHE BOOL "Build libtelldus-core") -SET(USE_QT_SETTINGS_BACKEND FALSE CACHE BOOL "Use QT as settings backend instead of the native one") - IF (WIN32) SET(TDTOOL_DEFAULT FALSE) SET(TDADMIN_DEFAULT FALSE) @@ -49,11 +47,6 @@ SET(BUILD_TDADMIN ${TDADMIN_DEFAULT} CACHE BOOL "Build tdadmin") SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") -# Lets figure if we need to build against Qt or not -IF(USE_QT_SETTINGS_BACKEND) - SET(BUILD_WITH_QT TRUE) -ENDIF(USE_QT_SETTINGS_BACKEND) - ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(service) ADD_SUBDIRECTORY(client) From 64306bd7d615db9eddec6fca613f8a3db432b5a3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 20 Sep 2011 13:13:01 +0000 Subject: [PATCH 1691/2215] License version corrected. README updated. --- telldus-core/LICENSE | 667 ++++++++++++++++++++++++++++++++----------- telldus-core/README | 6 +- 2 files changed, 505 insertions(+), 168 deletions(-) diff --git a/telldus-core/LICENSE b/telldus-core/LICENSE index f0156c53..4362b491 100644 --- a/telldus-core/LICENSE +++ b/telldus-core/LICENSE @@ -1,165 +1,502 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. \ No newline at end of file + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/telldus-core/README b/telldus-core/README index 5778ee2b..dd80b5bf 100644 --- a/telldus-core/README +++ b/telldus-core/README @@ -10,7 +10,7 @@ INSTALLING Telldus Core On Windows, if you want to install the precompiles binary packages, simply launch the package and follow the instructions in the installation wizard. -If you have a source package (a .tag.gz file), follow the instruction in the +If you have a source package (a .tar.gz file), follow the instruction in the INSTALL file. @@ -19,8 +19,8 @@ CONFIGURATION AND TOOLS Once Telldus Core is installed, we suggest that you start by adding the devices you want to control. -On Windows, this is done with the tool TelldusSetup. On Linux this is done in -the file /etc/tellstick.conf. +On Windows, this is done by installing TelldusCenter. On Linux it's done by +editing the file /etc/tellstick.conf directly, or in TelldusCenter. Telldus Core installs the tool tdtool for controlling devices with TellStick. Have a look in the man page for a description how to use it: From e89d0a29f8238b64c4110c803126ffad8625a5ea Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 23 Sep 2011 12:21:21 +0000 Subject: [PATCH 1692/2215] Possible to specify a path to tdadmin in the udev.sh script --- telldus-core/tdadmin/CMakeLists.txt | 10 ++++++++-- telldus-core/tdadmin/udev.sh | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt index 7118bca2..dc616b95 100644 --- a/telldus-core/tdadmin/CMakeLists.txt +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -32,7 +32,7 @@ ELSEIF (APPLE) ) ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") # FreeBSD does not have argp in base libc; port devel/argp-standalone is required. - FIND_LIBRARY(ARGP_LIBRARY argp) + FIND_LIBRARY(ARGP_LIBRARY argp) TARGET_LINK_LIBRARIES(tdadmin ${CMAKE_BINARY_DIR}/client/libtelldus-core.so ${ARGP_LIBRARY} @@ -60,14 +60,20 @@ INSTALL(TARGETS tdadmin RUNTIME DESTINATION sbin) IF (UNIX AND NOT APPLE) SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) + SET(TDADMIN_PATH "" CACHE STRING "The directory where tdadmin is stored" ) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/05-tellstick.rules ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules ) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/udev.sh + ${CMAKE_BINARY_DIR}/parsed/udev.sh + @ONLY + ) INSTALL(FILES ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules DESTINATION ${UDEV_RULES_DIR} ) - INSTALL(PROGRAMS udev.sh + INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/parsed/udev.sh DESTINATION share/telldus-core/helpers/ ) ENDIF (UNIX AND NOT APPLE) diff --git a/telldus-core/tdadmin/udev.sh b/telldus-core/tdadmin/udev.sh index 5ff565f3..ae05df75 100755 --- a/telldus-core/tdadmin/udev.sh +++ b/telldus-core/tdadmin/udev.sh @@ -2,8 +2,8 @@ if [ "${ID_VENDOR_ID}" == "1781" ]; then if [ "${ACTION}" == "add" ]; then - tdadmin controller connect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} + @TDADMIN_PATH@tdadmin controller connect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} elif [ "${ACTION}" == "remove" ]; then - tdadmin controller disconnect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} + @TDADMIN_PATH@tdadmin controller disconnect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} fi fi From c364302037cb157366c48d9c9e86c86c758a24d8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Oct 2011 11:02:41 +0000 Subject: [PATCH 1693/2215] Fix to allow storage of more than 127 devices in Windows. Closes #95 --- telldus-core/service/SettingsWinRegistry.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index d5bb1473..939f6152 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -120,28 +120,16 @@ int Settings::getNextDeviceId() const { if(lnExists == ERROR_SUCCESS){ DWORD dwLength; - char *Buff = new char[intMaxRegValueLength]; + DWORD nResult(0); - long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); - - if(lngStatus == ERROR_MORE_DATA){ - //The buffer is to small, recreate it - delete Buff; - Buff = new char[dwLength]; - lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, (LPBYTE)Buff, &dwLength); - } + long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); //(LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_SUCCESS){ - - int intLast = (int)Buff[0]; - intReturn = intLast + 1; + intReturn = nResult + 1; } else { intReturn = 1; } - delete Buff; - DWORD dwVal = intReturn; - RegSetValueEx (hk, L"LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); } From 4ee0542c11a861e4734bdc91e5f91c04d0e9bc72 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Oct 2011 11:59:36 +0000 Subject: [PATCH 1694/2215] Set tdadmin path in script automatically --- telldus-core/tdadmin/CMakeLists.txt | 1 - telldus-core/tdadmin/udev.sh | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt index dc616b95..8bc06e9f 100644 --- a/telldus-core/tdadmin/CMakeLists.txt +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -60,7 +60,6 @@ INSTALL(TARGETS tdadmin RUNTIME DESTINATION sbin) IF (UNIX AND NOT APPLE) SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) - SET(TDADMIN_PATH "" CACHE STRING "The directory where tdadmin is stored" ) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/05-tellstick.rules ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules diff --git a/telldus-core/tdadmin/udev.sh b/telldus-core/tdadmin/udev.sh index ae05df75..77f8364d 100755 --- a/telldus-core/tdadmin/udev.sh +++ b/telldus-core/tdadmin/udev.sh @@ -2,8 +2,8 @@ if [ "${ID_VENDOR_ID}" == "1781" ]; then if [ "${ACTION}" == "add" ]; then - @TDADMIN_PATH@tdadmin controller connect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} + @CMAKE_INSTALL_PREFIX@/sbin/tdadmin controller connect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} elif [ "${ACTION}" == "remove" ]; then - @TDADMIN_PATH@tdadmin controller disconnect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} + @CMAKE_INSTALL_PREFIX@/sbin/tdadmin controller disconnect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} fi fi From 9535ecd0ae22d358427d6342d3b85fd717a0a7ad Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 6 Oct 2011 14:12:55 +0000 Subject: [PATCH 1695/2215] Merge branch t102, this closes #102 --- telldus-core/client/CallbackDispatcher.cpp | 28 +++++- telldus-core/client/CallbackDispatcher.h | 8 ++ telldus-core/client/Client.cpp | 112 +++++++++++++++------ telldus-core/client/Client.h | 1 + 4 files changed, 117 insertions(+), 32 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index f23cfbf4..d167a72d 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -12,7 +12,7 @@ using namespace TelldusCore; TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct *data, int id, int m, const std::string &strD) -:Thread(), d(data), deviceId(id), method(m), strData(strD) +:Thread(), d(data), deviceId(id), method(m), strData(strD), doneRunning(false) { d->mutex.lock(); this->start(); @@ -23,13 +23,18 @@ TDDeviceEventDispatcher::~TDDeviceEventDispatcher() { d->mutex.unlock(); } +bool TDDeviceEventDispatcher::done() const { + return doneRunning; +} + void TDDeviceEventDispatcher::run() { d->event(deviceId, method, strData.c_str(), d->id, d->context); + doneRunning = true; } TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStruct *data, int id, int event, int type) -:Thread(), d(data), deviceId(id), changeEvent(event), changeType(type) +:Thread(), d(data), deviceId(id), changeEvent(event), changeType(type), doneRunning(false) { d->mutex.lock(); this->start(); @@ -40,12 +45,17 @@ TDDeviceChangeEventDispatcher::~TDDeviceChangeEventDispatcher() { d->mutex.unlock(); } +bool TDDeviceChangeEventDispatcher::done() const { + return doneRunning; +} + void TDDeviceChangeEventDispatcher::run() { d->event(deviceId, changeEvent, changeType, d->id, d->context); + doneRunning = true; } TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id) -:Thread(), d(data), controllerId(id), strData(strD) +:Thread(), d(data), controllerId(id), strData(strD), doneRunning(false) { d->mutex.lock(); this->start(); @@ -56,12 +66,17 @@ TDRawDeviceEventDispatcher::~TDRawDeviceEventDispatcher() { d->mutex.unlock(); } +bool TDRawDeviceEventDispatcher::done() const { + return doneRunning; +} + void TDRawDeviceEventDispatcher::run() { d->event(strData.c_str(), controllerId, d->id, d->context); + doneRunning = true; } TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, int type, const std::string &v, int t) - :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t) + :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t), doneRunning(false) { d->mutex.lock(); this->start(); @@ -72,6 +87,11 @@ TDSensorEventDispatcher::~TDSensorEventDispatcher() { d->mutex.unlock(); } +bool TDSensorEventDispatcher::done() const { + return doneRunning; +} + void TDSensorEventDispatcher::run() { d->event(protocol.c_str(), model.c_str(), sensorId, dataType, value.c_str(), timestamp, d->id, d->context); + doneRunning = true; } diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index a355b44f..8cc24add 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -27,8 +27,10 @@ namespace TelldusCore { public: TDDeviceEventDispatcher(CallbackStruct *data, int deviceId, int method, const std::string &strData); virtual ~TDDeviceEventDispatcher(); + bool done() const; protected: virtual void run(); + bool doneRunning; private: CallbackStruct *d; int deviceId, method; @@ -38,8 +40,10 @@ namespace TelldusCore { public: TDDeviceChangeEventDispatcher(CallbackStruct *data, int deviceId, int changeEvent, int changeType); virtual ~TDDeviceChangeEventDispatcher(); + bool done() const; protected: virtual void run(); + bool doneRunning; public: CallbackStruct *d; int deviceId, changeEvent, changeType; @@ -48,8 +52,10 @@ namespace TelldusCore { public: TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strData, int controllerId); virtual ~TDRawDeviceEventDispatcher(); + bool done() const; protected: virtual void run(); + bool doneRunning; private: CallbackStruct *d; int controllerId; @@ -59,8 +65,10 @@ namespace TelldusCore { public: TDSensorEventDispatcher( CallbackStruct *data, const std::string &protocol, const std::string &model, int id, int dataType, const std::string &value, int timestamp); virtual ~TDSensorEventDispatcher(); + bool done() const; protected: virtual void run(); + bool doneRunning; private: CallbackStruct *d; std::string protocol; diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index acfe68e8..c93bf37a 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -35,6 +35,11 @@ public: bool running, sensorCached; std::wstring sensorCache; TelldusCore::Mutex mutex; + + std::list > deviceEventThreadList; + std::list > deviceChangeEventThreadList; + std::list > rawDeviceEventThreadList; + std::list > sensorEventThreadList; }; Client *Client::instance = 0; @@ -72,46 +77,34 @@ Client *Client::getInstance() { } void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue){ - std::list > list; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDDeviceEventDispatcher(*callback_it, deviceId, deviceState, TelldusCore::wideToString(deviceStateValue))); - list.push_back(ptr); - } + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDDeviceEventDispatcher(*callback_it, deviceId, deviceState, TelldusCore::wideToString(deviceStateValue))); + d->deviceEventThreadList.push_back(ptr); } } void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType){ - std::list > list; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDDeviceChangeEventDispatcher(*callback_it, deviceId, eventDeviceChanges, eventChangeType)); - list.push_back(ptr); - } + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDDeviceChangeEventDispatcher(*callback_it, deviceId, eventDeviceChanges, eventChangeType)); + d->deviceChangeEventThreadList.push_back(ptr); } } void Client::callbackRawEvent(std::wstring command, int controllerId) { - std::list > list; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDRawDeviceEventDispatcher(*callback_it, TelldusCore::wideToString(command), controllerId)); - list.push_back(ptr); - } + TelldusCore::MutexLocker locker(&d->mutex); + for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDRawDeviceEventDispatcher(*callback_it, TelldusCore::wideToString(command), controllerId)); + d->rawDeviceEventThreadList.push_back(ptr); } } void Client::callbackSensorEvent(const std::wstring &protocol, const std::wstring &model, int id, int dataType, const std::wstring &value, int timestamp) { - std::list > list; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(SensorEventList::iterator callback_it = d->sensorEventList.begin(); callback_it != d->sensorEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDSensorEventDispatcher(*callback_it, TelldusCore::wideToString(protocol), TelldusCore::wideToString(model), id, dataType, TelldusCore::wideToString(value), timestamp)); - list.push_back(ptr); - } + TelldusCore::MutexLocker locker(&d->mutex); + for(SensorEventList::iterator callback_it = d->sensorEventList.begin(); callback_it != d->sensorEventList.end(); ++callback_it) { + std::tr1::shared_ptr ptr(new TDSensorEventDispatcher(*callback_it, TelldusCore::wideToString(protocol), TelldusCore::wideToString(model), id, dataType, TelldusCore::wideToString(value), timestamp)); + d->sensorEventThreadList.push_back(ptr); } } @@ -222,9 +215,72 @@ void Client::run(){ clientMessage = L""; //cleanup, if message contained garbage/unhandled data } } + + //Clean up finished callbacks + this->cleanupCallbacks(); } } +void Client::cleanupCallbacks() { + bool again = false; + + //Device Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->deviceEventThreadList.begin(); + for (;it != d->deviceEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->deviceEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); + + //Device Change Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->deviceChangeEventThreadList.begin(); + for (;it != d->deviceChangeEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->deviceChangeEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); + + //Raw Device Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->rawDeviceEventThreadList.begin(); + for (;it != d->rawDeviceEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->rawDeviceEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); + + //Sensor Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->sensorEventThreadList.begin(); + for (;it != d->sensorEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->sensorEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); +} + std::wstring Client::sendToService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index b7261318..4287f83c 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -37,6 +37,7 @@ namespace TelldusCore { private: Client(); static std::wstring sendToService(const Message &msg); + void cleanupCallbacks(); class PrivateData; PrivateData *d; From ffeb0b79d45b3af9e627f1aa155b6b3de4d917fa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 7 Oct 2011 07:57:55 +0000 Subject: [PATCH 1696/2215] Wait for the event to be signaled, even if we already have waited this seems to do the trick. See #93 and #94 --- telldus-core/common/Socket_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 023b5e94..f78b274d 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -145,7 +145,7 @@ void Socket::write(const std::wstring &msg){ d->connected = false; return; } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, false); + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); CloseHandle(writeEvent); if (!fSuccess) { CancelIo(d->hPipe); From 184d2ee315544c67b34d6b34b50cac0ed3a7af0e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 7 Oct 2011 07:58:18 +0000 Subject: [PATCH 1697/2215] Don't wait infinite. Windows doesn't like that for some reason. See #93 and #94 --- telldus-core/service/ConnectionListener_win.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 03919f6e..992e1a87 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -113,13 +113,17 @@ void ConnectionListener::run() { ConnectNamedPipe(hPipe, &oOverlap); - WaitForSingleObject(oOverlap.hEvent, INFINITE); + DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000); if (!d->running) { break; } - + if(result == WAIT_TIMEOUT){ + CloseHandle(hPipe); + continue; + } BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); + if (!connected) { CloseHandle(hPipe); return; From 27ddbb9eb8f6ef6588ab77e223ddf3d7359ee24c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 7 Oct 2011 09:37:13 +0000 Subject: [PATCH 1698/2215] Add done() getter to DeviceChangeEventDispatcher --- telldus-core/client/CallbackDispatcher.h | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 8cc24add..e37df9ca 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -47,6 +47,7 @@ namespace TelldusCore { public: CallbackStruct *d; int deviceId, changeEvent, changeType; + bool doneRunning; }; class TDRawDeviceEventDispatcher : public Thread { public: From a7a59302efe1376da60a4be2ed854d63560d4a76 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 7 Oct 2011 09:37:16 +0000 Subject: [PATCH 1699/2215] Implement done() for all callbackdispatchers --- telldus-core/client/CallbackDispatcher.h | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index e37df9ca..8cc24add 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -47,7 +47,6 @@ namespace TelldusCore { public: CallbackStruct *d; int deviceId, changeEvent, changeType; - bool doneRunning; }; class TDRawDeviceEventDispatcher : public Thread { public: From 901ddebe01b3323d213d1a6b7fd1ce29746b48cc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 7 Oct 2011 09:37:20 +0000 Subject: [PATCH 1700/2215] =?UTF-8?q?Rename=20variable=20LIBRARY=5FDIR=20t?= =?UTF-8?q?o=20LIB=5FINSTALL=5FDIR.=20This=20seems=20to=20match=20differen?= =?UTF-8?q?t=20distributions=20better.=20Thanks=20to=20Per=20=C3=98yvind?= =?UTF-8?q?=20Karlsen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- telldus-core/client/CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 1d5d3b1f..5f328c63 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -115,14 +115,14 @@ SET_TARGET_PROPERTIES(${telldus-core_TARGET} PROPERTIES ) SIGN(${telldus-core_TARGET}) -IF (NOT LIBRARY_DIR) - SET(LIBRARY_DIR "lib") -ENDIF (NOT LIBRARY_DIR) +IF (NOT LIB_INSTALL_DIR) + SET(LIB_INSTALL_DIR "lib") +ENDIF (NOT LIB_INSTALL_DIR) IF (UNIX) INSTALL(TARGETS ${telldus-core_TARGET} - LIBRARY DESTINATION ${LIBRARY_DIR} - ARCHIVE DESTINATION ${LIBRARY_DIR} + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${LIB_INSTALL_DIR} FRAMEWORK DESTINATION "/Library/Frameworks" PUBLIC_HEADER DESTINATION include ) From eb073d9fd0d4dbac597f5d39c9fa9ff9300564c9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 7 Oct 2011 09:37:23 +0000 Subject: [PATCH 1701/2215] =?UTF-8?q?Use=20PKG=5FSEARCH=5FMODULE()=20to=20?= =?UTF-8?q?find=20libftdi.h=20on=20distributions=20not=20having=20it=20in?= =?UTF-8?q?=20the=20standard=20directories.=20Thanks=20to=20Per=20=C3=98yv?= =?UTF-8?q?ind=20Karlsen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- telldus-core/service/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index e876dfc0..a3e724b2 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -161,6 +161,9 @@ IF (FTDI_ENGINE STREQUAL "ftd2xx") LIST(APPEND telldus-service_LIBRARIES ${FTD2XX_LIBRARY}) ELSE (FTDI_ENGINE STREQUAL "ftd2xx") FIND_LIBRARY(FTDI_LIBRARY ftdi) + INCLUDE(FindPkgConfig) + PKG_SEARCH_MODULE(FTDI libftdi) + INCLUDE_DIRECTORIES( ${FTDI_INCLUDEDIR} ) ADD_DEFINITIONS( -DLIBFTDI ) LIST(APPEND telldus-service_SRCS TellStick_libftdi.cpp ) LIST(APPEND telldus-service_LIBRARIES ${FTDI_LIBRARY}) From 273ee15ed8a0c578450b8f2f2d3701c6d16ff81b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 7 Oct 2011 10:58:40 +0000 Subject: [PATCH 1702/2215] Fixed missing implementation of deviceCallbackEvents, and added different handling of contexts. --- .../TelldusNETWrapper/TelldusNETWrapper.cs | 170 +++++++----------- 1 file changed, 63 insertions(+), 107 deletions(-) diff --git a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs index 82164cb8..0d476504 100644 --- a/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs +++ b/bindings/dotnet/TelldusNETWrapper/TelldusNETWrapper.cs @@ -51,23 +51,37 @@ namespace TelldusWrapper public const int TELLSTICK_CHANGE_PROTOCOL = 2; public const int TELLSTICK_CHANGE_MODEL = 3; - //variables for event callback (e.g. turnon, turnoff) public delegate int EventCallbackFunction(int deviceId, int method, string data, int callbackId, Object obj); - Dictionary eventList = new Dictionary(); - GCHandle eventContextHandle; + private struct DeviceEventFunctionContext + { + public EventCallbackFunction eventCallbackFunc; + public Object context; + public int callbackId; + } + Dictionary deviceEventList = new Dictionary(); int registeredEventFunctionId = -1; //variables for device event callback (e.g. change of name/protocol) public delegate int DeviceChangeEventCallbackFunction(int deviceId, int changeEvent, int changeType, int callbackId, Object obj); - Dictionary deviceChangeEventList = new Dictionary(); - GCHandle deviceChangeEventContextHandle; + private struct DeviceChangeEventFunctionContext + { + public DeviceChangeEventCallbackFunction changeEventCallbackFunc; + public Object context; + public int callbackId; + } + Dictionary deviceChangeEventList = new Dictionary(); int registeredDeviceChangeEventFunctionId = -1; //variables for raw controller listening callback (e.g. Tellstick Duo receives data) public delegate int RawListeningCallbackFunction(string data, int controllerId, int callbackId, Object obj); - Dictionary rawListenerList = new Dictionary(); - GCHandle rawListenerContextHandle; + private struct RawEventFunctionContext + { + public RawListeningCallbackFunction rawCallbackFunc; + public Object context; + public int callbackId; + } + Dictionary rawListenerList = new Dictionary(); int registeredRawListenerFunctionId = -1; public TelldusNETWrapper() @@ -90,18 +104,6 @@ namespace TelldusWrapper UnmanagedImport.tdUnregisterCallback(registeredRawListenerFunctionId); } UnmanagedImport.tdClose(); //Close the library and clean up the cache it uses. - if (eventContextHandle.IsAllocated) - { - eventContextHandle.Free(); - } - if (deviceChangeEventContextHandle.IsAllocated) - { - deviceChangeEventContextHandle.Free(); - } - if (rawListenerContextHandle.IsAllocated) - { - rawListenerContextHandle.Free(); - } } /// @@ -185,7 +187,7 @@ namespace TelldusWrapper public static extern void tdInit(); [DllImport("TelldusCore.dll")] - public static unsafe extern int tdRegisterDeviceEvent(Delegate eventFunction, void* context); + public static unsafe extern int tdRegisterDeviceEvent(Delegate deviceEventFunction, void* context); [DllImport("TelldusCore.dll")] public static extern int tdLastSentCommand(int deviceId, int methods); @@ -212,10 +214,10 @@ namespace TelldusWrapper public static unsafe extern int tdUnregisterCallback(int eventId); [DllImport("TelldusCore.dll")] - public static unsafe extern int tdRegisterDeviceChangeEvent(Delegate deviceEventFunction, void* context); + public static unsafe extern int tdRegisterDeviceChangeEvent(Delegate deviceChangeEventFunction, void* context); [UnmanagedFunctionPointer(CallingConvention.StdCall)] - public unsafe delegate void EventFunctionDelegate(); //int deviceId, int method, int callbackId, void* context [MarshalAs(UnmanagedType.LPStr)]string data, + public unsafe delegate void EventFunctionDelegate(int deviceId, int method, char* data, int callbackId, void* context); [UnmanagedFunctionPointer(CallingConvention.StdCall)] public unsafe delegate void DeviceChangeEventFunctionDelegate(int deviceId, int changeEvent, int changeType, int callbackId, void* context); @@ -447,31 +449,27 @@ namespace TelldusWrapper /// Callback function to be called /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. /// Callback event id - public unsafe int tdRegisterDeviceEvent(EventCallbackFunction eventFunc, Object obj) + public unsafe int tdRegisterDeviceEvent(EventCallbackFunction deviceEventFunc, Object obj) { int returnValue = 0; - - if (eventList.Count == 0) + + if (deviceEventList.Count == 0) { //first added, register with dll too - //only the context object of the first event will be registered - UnmanagedImport.EventFunctionDelegate eventFunctionDelegate = new UnmanagedImport.EventFunctionDelegate(eventFunction); - if (obj != null) - { - eventContextHandle = GCHandle.Alloc(obj); - registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(eventFunctionDelegate, (void*)GCHandle.ToIntPtr(eventContextHandle)); //context here or above? - } - else - { - registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(eventFunctionDelegate, (void*)null); //context here or above? - } + UnmanagedImport.EventFunctionDelegate deviceEventFunctionDelegate = new UnmanagedImport.EventFunctionDelegate(deviceEventFunction); + + registeredEventFunctionId = UnmanagedImport.tdRegisterDeviceEvent(deviceEventFunctionDelegate, (void*)null); //context here or above? GC.Collect(); - callbackFunctionReferenceList.Add(registeredEventFunctionId, eventFunctionDelegate); + callbackFunctionReferenceList.Add(registeredEventFunctionId, deviceEventFunctionDelegate); } ++lastEventID; returnValue = lastEventID; - eventList.Add(returnValue, eventFunc); + DeviceEventFunctionContext deviceEventFuncContext = new DeviceEventFunctionContext(); + deviceEventFuncContext.eventCallbackFunc = deviceEventFunc; + deviceEventFuncContext.context = obj; + deviceEventFuncContext.callbackId = returnValue; + deviceEventList.Add(returnValue, deviceEventFuncContext); return returnValue; } @@ -482,31 +480,26 @@ namespace TelldusWrapper /// Callback function to be called /// Context object that will be echoed back when function is called. Only the object when the first function is registered will be used. Set to null if not used. /// Callback event id - public unsafe int tdRegisterDeviceChangeEvent(DeviceChangeEventCallbackFunction deviceEventFunc, Object obj) + public unsafe int tdRegisterDeviceChangeEvent(DeviceChangeEventCallbackFunction deviceChangeEventFunc, Object obj) { int returnValue = 0; if (deviceChangeEventList.Count == 0) { //first added, register with dll too //only the context object of the first event will be registered - UnmanagedImport.DeviceChangeEventFunctionDelegate deviceChangeEventFunctionDelegate = new UnmanagedImport.DeviceChangeEventFunctionDelegate(deviceEventFunction); + UnmanagedImport.DeviceChangeEventFunctionDelegate deviceChangeEventFunctionDelegate = new UnmanagedImport.DeviceChangeEventFunctionDelegate(deviceChangeEventFunction); - if (obj != null) - { - deviceChangeEventContextHandle = GCHandle.Alloc(obj); - registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)GCHandle.ToIntPtr(deviceChangeEventContextHandle)); - } - else - { - registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)null); - } + registeredDeviceChangeEventFunctionId = UnmanagedImport.tdRegisterDeviceChangeEvent(deviceChangeEventFunctionDelegate, (void*)null); GC.Collect(); callbackFunctionReferenceList.Add(registeredDeviceChangeEventFunctionId, deviceChangeEventFunctionDelegate); - } ++lastEventID; returnValue = lastEventID; - deviceChangeEventList.Add(returnValue, deviceEventFunc); + DeviceChangeEventFunctionContext deviceChangeEventFuncContext = new DeviceChangeEventFunctionContext(); + deviceChangeEventFuncContext.changeEventCallbackFunc = deviceChangeEventFunc; + deviceChangeEventFuncContext.context = obj; + deviceChangeEventFuncContext.callbackId = returnValue; + deviceChangeEventList.Add(returnValue, deviceChangeEventFuncContext); return returnValue; } @@ -526,22 +519,17 @@ namespace TelldusWrapper //only the context object of the first event will be registered UnmanagedImport.RawListeningDelegate listeningFunctionDelegate = new UnmanagedImport.RawListeningDelegate(rawListeningFunction); - if (obj != null) - { - rawListenerContextHandle = GCHandle.Alloc(obj); - - registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)GCHandle.ToIntPtr(rawListenerContextHandle)); - } - else - { - registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)null); - } + registeredRawListenerFunctionId = UnmanagedImport.tdRegisterRawDeviceEvent(listeningFunctionDelegate, (void*)null); GC.Collect(); callbackFunctionReferenceList.Add(registeredRawListenerFunctionId, listeningFunctionDelegate); } ++lastEventID; returnValue = lastEventID; - rawListenerList.Add(returnValue, listeningFunc); + RawEventFunctionContext rawEventFuncContext = new RawEventFunctionContext(); + rawEventFuncContext.rawCallbackFunc = listeningFunc; + rawEventFuncContext.context = obj; + rawEventFuncContext.callbackId = returnValue; + rawListenerList.Add(returnValue, rawEventFuncContext); return returnValue; } @@ -667,16 +655,18 @@ namespace TelldusWrapper /// Id of callback even to unregister public void unregisterCallback(int eventId) { - eventList.Remove(eventId); - if (eventList.Count == 0) + deviceEventList.Remove(eventId); + if (deviceEventList.Count == 0) { //no more events in list UnmanagedImport.tdUnregisterCallback(registeredEventFunctionId); callbackFunctionReferenceList.Remove(registeredEventFunctionId); + /* if (eventContextHandle.IsAllocated) { eventContextHandle.Free(); } + */ } deviceChangeEventList.Remove(eventId); @@ -685,10 +675,6 @@ namespace TelldusWrapper //no more events in list UnmanagedImport.tdUnregisterCallback(registeredDeviceChangeEventFunctionId); callbackFunctionReferenceList.Remove(registeredDeviceChangeEventFunctionId); - if (deviceChangeEventContextHandle.IsAllocated) - { - deviceChangeEventContextHandle.Free(); - } } rawListenerList.Remove(eventId); @@ -697,10 +683,6 @@ namespace TelldusWrapper //no more events in list UnmanagedImport.tdUnregisterCallback(registeredRawListenerFunctionId); callbackFunctionReferenceList.Remove(registeredRawListenerFunctionId); - if (rawListenerContextHandle.IsAllocated) - { - rawListenerContextHandle.Free(); - } } } @@ -780,26 +762,16 @@ namespace TelldusWrapper /// Callback event id /// Context (optional) /// 0 - private unsafe void eventFunction() //int deviceId, int method, int callbackId, void* context[MarshalAs(UnmanagedType.LPStr)]string data + private unsafe void deviceEventFunction(int deviceId, int method, char* data, int callbackId, void* context) { - foreach (EventCallbackFunction eventFunc in eventList.Values) + foreach (DeviceEventFunctionContext deviceEventFuncContext in deviceEventList.Values) { - /* - if (context != null) - { - GCHandle eventContextHandle = GCHandle.FromIntPtr((IntPtr)context); - eventFunc(deviceId, method, "", callbackId, (Object)eventContextHandle.Target); //data - } - else - { - eventFunc(deviceId, method, "", callbackId, null); - } - */ - eventFunc(1, 1, "", 1, null); + deviceEventFuncContext.eventCallbackFunc(deviceId, method, getString(data, false), deviceEventFuncContext.callbackId, deviceEventFuncContext.context); GC.Collect(); } } + /// /// Event function wrapper that will call all registered device change event functions with C#-arguments when /// this device change event function is called from telldus core, with C++-style arguments. This function will @@ -811,19 +783,11 @@ namespace TelldusWrapper /// Callback event id /// Context (optional) /// 0 - private unsafe void deviceEventFunction(int deviceId, int changeEvent, int changeType, int callbackId, void* context) + private unsafe void deviceChangeEventFunction(int deviceId, int changeEvent, int changeType, int callbackId, void* context) { - foreach (DeviceChangeEventCallbackFunction deviceEventFunc in deviceChangeEventList.Values) + foreach (DeviceChangeEventFunctionContext deviceChangeEventFuncContext in deviceChangeEventList.Values) { - if (context != null) - { - GCHandle deviceChangeEventContextHandle = GCHandle.FromIntPtr((IntPtr)context); - deviceEventFunc(deviceId, changeEvent, changeType, callbackId, (Object)deviceChangeEventContextHandle.Target); - } - else - { - deviceEventFunc(deviceId, changeEvent, changeType, callbackId, null); - } + deviceChangeEventFuncContext.changeEventCallbackFunc(deviceId, changeEvent, changeType, deviceChangeEventFuncContext.callbackId, deviceChangeEventFuncContext.context); GC.Collect(); } } @@ -840,17 +804,9 @@ namespace TelldusWrapper /// 0 private unsafe void rawListeningFunction(char* data, int controllerId, int callbackId, void* context) { - foreach (RawListeningCallbackFunction rawListeningFunc in rawListenerList.Values) + foreach (RawEventFunctionContext rawListeningFuncContext in rawListenerList.Values) { - if (context != null) - { - GCHandle rawListenerContextHandle = GCHandle.FromIntPtr((IntPtr)context); - rawListeningFunc(getString(data, false), controllerId, callbackId, (Object)rawListenerContextHandle.Target); //strings cannot be released here, since they are still in use by calling core (sent to other clients aswell), let the core take care of it with shared pointer - } - else - { - rawListeningFunc(getString(data, false), controllerId, callbackId, null); - } + rawListeningFuncContext.rawCallbackFunc(getString(data, false), controllerId, rawListeningFuncContext.callbackId, rawListeningFuncContext.context); GC.Collect(); } } From 6c325fd0e6b4d2640fa0b59796f06cdf2c41538e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 25 Oct 2011 11:08:29 +0000 Subject: [PATCH 1703/2215] Create branch, see #96 From 486753d4118908f1ce2a352d62a01767a5b51f51 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Oct 2011 15:48:29 +0200 Subject: [PATCH 1704/2215] Add function com.telldus.core.sensor() to script as wrapper for tdSensor(). See #96 --- .../Plugins/TelldusCore/tellduscoreobject.cpp | 20 +++++++++++++++++++ .../Plugins/TelldusCore/tellduscoreobject.h | 3 +++ 2 files changed, 23 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp index cb6c925b..704e9138 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp @@ -103,6 +103,26 @@ int TelldusCoreObject::stop(int deviceId) { return retval; } +QVariant TelldusCoreObject::sensor() const { + const int DATA_LENGTH = 20; + char protocol[DATA_LENGTH], model[DATA_LENGTH]; + int sensorId = 0, dataTypes = 0; + + + if (tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes) != TELLSTICK_SUCCESS) { + return 0; + } + + QVariantMap retval; + + retval["protocol"] = protocol; + retval["model"] = model; + retval["sensorId"] = sensorId; + retval["dataTypes"] = dataTypes; + + return retval; +} + void TelldusCoreObject::triggerError(int deviceId, int errorId) { char *errorString = tdGetErrorString( errorId ); QString message = QString::fromUtf8( errorString ); diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h index 83515258..6ccfa17f 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h @@ -2,6 +2,7 @@ #define TELLDUSCOREOBJECT_H #include +#include #include class TelldusCoreObject : public QObject @@ -27,6 +28,8 @@ public slots: QString lastSentValue( int deviceId ); int methods( int deviceId, int methodsSupported ); + QVariant sensor() const; + int turnOn( int deviceId ); int turnOff( int deviceId ); int up( int deviceId ); From b9fbd3a90990c43cdbed11a11e2b35d59351e115 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Oct 2011 15:55:03 +0200 Subject: [PATCH 1705/2215] Add function com.telldus.core.sensorValue() to script as wrapper for tdSensorValue(). See #96 --- .../Plugins/TelldusCore/tellduscoreobject.cpp | 13 +++++++++++++ telldus-gui/Plugins/TelldusCore/tellduscoreobject.h | 1 + 2 files changed, 14 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp index 704e9138..3362fb8b 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp @@ -1,4 +1,5 @@ #include "tellduscoreobject.h" +#include #include TelldusCoreObject::TelldusCoreObject( QObject * parent ) @@ -123,6 +124,18 @@ QVariant TelldusCoreObject::sensor() const { return retval; } +QVariant TelldusCoreObject::sensorValue(const QString &protocol, const QString &model, int id, int dataType) const { + const int DATA_LENGTH = 20; + char value[DATA_LENGTH]; + time_t timestamp = 0; + + tdSensorValue(protocol.toUtf8(), model.toUtf8(), id, dataType, value, DATA_LENGTH, (int *)×tamp); + QVariantMap retval; + retval["value"] = value; + retval["timestamp"] = QDateTime::fromTime_t(timestamp); + return retval; +} + void TelldusCoreObject::triggerError(int deviceId, int errorId) { char *errorString = tdGetErrorString( errorId ); QString message = QString::fromUtf8( errorString ); diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h index 6ccfa17f..98a7f842 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h @@ -29,6 +29,7 @@ public slots: int methods( int deviceId, int methodsSupported ); QVariant sensor() const; + QVariant sensorValue(const QString &protocol, const QString &model, int id, int dataType) const; int turnOn( int deviceId ); int turnOff( int deviceId ); From 7738dc69d0f6bd2331449d44a39fd985999e7cd1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Oct 2011 15:55:29 +0200 Subject: [PATCH 1706/2215] Add sensor constants to script --- telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp index cdc8d9b6..131e1ee0 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp @@ -30,6 +30,9 @@ void TelldusCorePlugin::initialize ( const QString & key, QScriptEngine * engine value.setProperty("TELLSTICK_DEVICE_REMOVED", TELLSTICK_DEVICE_REMOVED); value.setProperty("TELLSTICK_DEVICE_STATE_CHANGED", TELLSTICK_DEVICE_STATE_CHANGED); + value.setProperty("TELLSTICK_TEMPERATURE", TELLSTICK_TEMPERATURE); + value.setProperty("TELLSTICK_HUMIDITY", TELLSTICK_HUMIDITY); + engine->globalObject().property("com").property("telldus").setProperty("core", value); } } From 51e87ffa88138a54bc2cfde8575153facede324b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Oct 2011 16:02:33 +0200 Subject: [PATCH 1707/2215] Add initial version of Sensors plugin, see #96 --- telldus-gui/Plugins/CMakeLists.txt | 5 + telldus-gui/Plugins/Sensors/CMakeLists.txt | 28 +++++ telldus-gui/Plugins/Sensors/__init__.js | 79 ++++++++++++++ telldus-gui/Plugins/Sensors/icon.png | Bin 0 -> 3885 bytes telldus-gui/Plugins/Sensors/main.qml | 20 ++++ telldus-gui/Plugins/Sensors/qmldir | 0 telldus-gui/Plugins/Sensors/sensor.cpp | 97 ++++++++++++++++++ telldus-gui/Plugins/Sensors/sensor.h | 66 ++++++++++++ telldus-gui/Plugins/Sensors/sensorsplugin.cpp | 31 ++++++ telldus-gui/Plugins/Sensors/sensorsplugin.h | 16 +++ 10 files changed, 342 insertions(+) create mode 100644 telldus-gui/Plugins/Sensors/CMakeLists.txt create mode 100644 telldus-gui/Plugins/Sensors/__init__.js create mode 100644 telldus-gui/Plugins/Sensors/icon.png create mode 100644 telldus-gui/Plugins/Sensors/main.qml create mode 100644 telldus-gui/Plugins/Sensors/qmldir create mode 100644 telldus-gui/Plugins/Sensors/sensor.cpp create mode 100644 telldus-gui/Plugins/Sensors/sensor.h create mode 100644 telldus-gui/Plugins/Sensors/sensorsplugin.cpp create mode 100644 telldus-gui/Plugins/Sensors/sensorsplugin.h diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 2eb95b96..f6a1b8ab 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -12,6 +12,7 @@ SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") SET(BUILD_PLUGIN_SCHEDULERGUISIMPLE FALSE CACHE BOOL "Build plugin 'Simple Scheduler GUI'") +SET(BUILD_PLUGIN_SENSORS FALSE CACHE BOOL "Build plugin 'Sensors'") ADD_SUBDIRECTORY(telldus) @@ -35,6 +36,10 @@ IF(BUILD_PLUGIN_LIVE) ADD_SUBDIRECTORY(Live) ENDIF(BUILD_PLUGIN_LIVE) +IF(BUILD_PLUGIN_SENSORS) + ADD_SUBDIRECTORY(Sensors) +ENDIF() + IF(BUILD_PLUGIN_XPL) ADD_SUBDIRECTORY(xPL) ENDIF(BUILD_PLUGIN_XPL) diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt new file mode 100644 index 00000000..065b7d97 --- /dev/null +++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt @@ -0,0 +1,28 @@ +SET(REQUIRE_PLUGIN_QML TRUE PARENT_SCOPE) +SET(REQUIRE_PLUGIN_SETTINGS TRUE PARENT_SCOPE) + +SET( Plugin_NAME "sensors" ) + + +SET( Plugin_SRCS + sensor.cpp + sensorsplugin.cpp +) + +SET( Plugin_HDRS + sensorsplugin.h +) + +SET( Plugin_MOC_HDRS + sensor.h +) + +SET( Plugin_PATH "com.telldus.sensors" ) + +SET( Plugin_EXTRA + icon.png + main.qml + qmldir +) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js new file mode 100644 index 00000000..b6b11054 --- /dev/null +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -0,0 +1,79 @@ +/** Sensors **/ +__setupPackage__( __extension__ ); + +__postInit__ = function() { + application.allDoneLoading.connect( com.telldus.sensors.init ); +} + +com.telldus.sensors = function() { + var sensorList = new com.telldus.qml.array(); + + function init() { + var sensorData = 0; + while(sensorData = com.telldus.core.sensor()) { + var p = sensorData["protocol"]; + var m = sensorData["model"]; + var id = sensorData["sensorId"]; + var types = sensorData["dataTypes"]; + + var tryFetchValue = function(p, m, id, types, type) { + if (types & type) { + sensorValue = com.telldus.core.sensorValue(p, m, id, type); + sensorEvent(p, m, id, type, sensorValue["value"], sensorValue["timestamp"]); + } + } + tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_TEMPERATURE); + tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_HUMIDITY); + + } + + //com.telldus.core.sensorEvent.connect(sensorEvent); + view = new com.telldus.qml.view({ + }); + + view.setProperty('sensorModel', sensorList); + view.load("main.qml"); + application.addWidget("sensors.gui", "icon.png", view); + } + + function sensorEvent(protocol, model, id, dataType, value, timestamp) { + var sensor = 0; + for (var i = 0; i < sensorList.length; ++i) { + if (sensorList.get(i).protocol != protocol) { + continue; + } + if (sensorList.get(i).model != model) { + continue; + } + if (sensorList.get(i).id != id) { + continue; + } + sensor = sensorList.get(i); + break; + } + + if (!sensor) { + sensor = new com.telldus.sensors.sensor(); + sensor.protocol = protocol; + sensor.model = model; + sensor.id = id; + sensorList.push(sensor); + print("Create new"); + } else { + print("Update"); + } + + if (dataType == com.telldus.core.TELLSTICK_TEMPERATURE) { + sensor.temperature = value; + } else if (dataType == com.telldus.core.TELLSTICK_HUMIDITY) { + sensor.humidity = value; + } + + print("Sensor event", protocol, model, id, dataType, value, timestamp); + } + + return { //Public functions + init:init + } + +}(); diff --git a/telldus-gui/Plugins/Sensors/icon.png b/telldus-gui/Plugins/Sensors/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e71391cf9ca6f7ff541022a80aa33646af3ad6dd GIT binary patch literal 3885 zcmV+|57O|7P)EX>4Tx0C?J+Q+HUC_ZB|i_hk=OLfG)Jmu!ImA|tE_$Pihg5Rw34gb)%y#f69p zRumNxoJdu~g4GI0orvO~D7a@qiilc^Ra`jkAKa(4eR}Wh?fcjJyyu+f{LXpL4}cL8 zCXwc%Y5+M>g*-agACFH+#L2yY0u@N$1RxOR%fe>`#Q*^C19^CUbg)1C0k3ZW0swH; zE+i7i;s1lWP$pLZAdvvzA`<5d0gzGv$SzdK6adH=0I*ZDWC{S3003-xd_p1ssto|_ z^hrJi0NAOM+!p}Yq8zCR0F40vnJ7mj0zkU}U{!%qECRs70HCZuA}$2Lt^t5qwlYTo zfV~9(c8*w(4?ti5fSE!p%m5%b0suoE6U_r4Oaq`W(!b!TUvP!ENC5!A%azTSOVTqG zxRuZvck=My;vwR~Y_URN7by^C3FIQ2mzyIKNaq7g&I|wm8u`(|{y0C7=jP<$=4R(? z@ASo@{%i1WB0eGU-~POe0t5gMPS5Y!U*+Z218~Oyuywy{sapWrRsd+<`CT*H37}dE z(0cicc{uz)9-g64$UGe!3JVMEC1RnyFyo6p|1;rl;ER6t{6HT5+j{T-ahgDxt-zy$ z{c&M#cCJ#6=gR~_F>d$gBmT#QfBlXr(c(0*Tr3re@mPttP$EsodAU-NL?OwQ;u7h9 zGVvdl{RxwI4FIf$Pry#L2er#=z<%xl0*ek<(slqqe)BDi8VivC5N9+pdG`PSlfU_o zKq~;2Moa!tiTSO!5zH77Xo1hL_iEAz&sE_ z2IPPo3ZWR5K^auQI@koYumc*P5t`u;w81er4d>tzT!HIw7Y1M$p28Tsh6w~g$Osc* zAv%Z=Vvg7%&IlKojszlMNHmgwq#)^t6j36@$a16tsX}UzT}UJHEpik&ja)$bklV;0 zGK&0)yhkyVfwEBp)B<%txu_o+ipHRG(R4HqU4WLNYtb6C9zB4zqNmYI=yh}eeTt4_ zfYC7yW{lZkT#ScBV2M~7CdU?I?5=ix(HVZgM=}{CnA%mPqZa^68Xe5gFH?u96Et<2 zCC!@_L(8Nsqt(!wX=iEoXfNq>x(VHb9z~bXm(pwK2kGbOgYq4YG!XMxcgB zqf}$J#u<$v7REAV@mNCEa#jQDENhreVq3EL>`ZnA`x|yIdrVV9bE;;nW|3x{=5fsd z4#u(I@HyF>O3oq94bFQl11&!-vDRv>X03j$H`;pIzS?5#a_tuF>)P*iaGgM%ES>c_ zZ94aL3A#4AQM!e?+jYlFJ5+DSzi0S9#6BJCZ5(XZOGfi zTj0IRdtf>~J!SgN=>tB-J_4V5pNGDtz9Qc}z9W9tewls;{GR(e`pf-~_`l(K@)q$< z1z-We0p$U`ff|9c18V~x1epY-2Q>wa1-k|>3_cY?3<(WcA99m#z!&lx`C~KOXDpi0 z70L*m6G6C?@k ziR8rC#65}Qa{}jVnlqf_npBo_W3J`gqPZ95>CVfZcRX1&S&)1jiOPpx423?lIEROmG(H@JAFg?XogQlb;dIZPf{y+kr|S? zBlAsGMAqJ{&)IR=Ejg5&l$@hd4QZCNE7vf$D7Q~$D=U)?Nn}(WA6du22pZOfRS_cv~1-c(_QtNLti0-)8>m`6CO07JR*suu!$(^sg%jf zZm#rNxnmV!m1I@#YM0epR(~oNm0zrItf;Q|utvD%;#W>z)qM4NZQ9!2O1H}G>qzUQ z>u#*~S--DJy=p<#(1!30tsC);y-IHSJr>wyfLop*ExT zdYyk=%U1oZtGB+{Cfe4&-FJKQ4uc&PJKpb5^_C@dOYIJXG+^@gCvI%WcHjN%gI&kHifN$EH?V5MBa9S!3!a?Q1 zC*P)gd*e{(q0YnH!_D8Bf4B7r>qvPk(mKC&tSzH$pgp0z@92!9ogH2sN4~fJe(y2k zV|B+hk5`_cohUu=`Q(C=R&z?UQbnZ;IU-!xL z-sg{9@Vs#JBKKn3CAUkhJ+3`ResKNaNUvLO>t*-L?N>ambo5Q@JJIjcfBI^`)pOVQ z*DhV3dA;w(>>IakCfyvkCA#(acJ}QTcM9%I++BK)c(44v+WqPW`VZ=VwEnSWz-{38 zV8CF{!&wjS4he^z{*?dIhvCvk%tzHDMk9@nogW_?4H~`jWX_Y}r?RIL&&qyQ|9R_k ztLNYS;`>X_Sp3-V3;B!Bzpi@JsGmcu#U+m9||O%j&_y?@X1e$R8B_eNlm;g=`54<0i6`TBpk}BEOs8!|B%M@sKam2;((-Z-h?C}hErH9!Uk#B0wDcHI zD)aG7@k08NS--cU?is6Vl7IJHDQ(xAasTCp&u5b-S_!^t@9!No3~B_9gK__$iEg7M z_|sj9?*GbT#30Z5y6#kjk3`copodi&4NUSv>TJkG5s+C@9sAA z+S1#d^|Q@iuz-{`nq%CE87Ku90vYH`BL_MU?V(E|;I(fWcB*7-a#d>=Xw)jwJZw9B z`q?d=b9rOl0#b^uDAunGDYscH5UUD8J1gsyGUS7~zB6wD2~p}}ae;nboxS}S7QLEW z?dm^zYG?f9lFa;xdTm&}PLD^*zQxMxEtp-|RQ+!_n^R9lT^_mU4m^PTwF&zOc=I0c zc=@;!BSX^ui80%3aZ;(`J3@r_#@ud|XaYX2`8oUPhgXE_1_m)TAs+OOvGB>$}Kol*(i@vhrD^^W-A6MmE_B=LF@R~aKXJ8tHYTB4EY2A z00|+4QVD{jP80_imObOkxm3euGm$ETV2q>NPCl3R*UX!o_8cT|2>=Kogdk!yA|}aw zWv&G`-b-aQiS>O3{HVB$UTf*V<5 zADV6u-_RB0_K@ko7rT>&25lC}fYowdpu#JN2$WKwNY4f<6j=d&e!OVsxadX)vIZR} z0|H<`>fdy5)7tpEW`m3(Q$YZdfe>UEhDZo=SRELcC;BFo5CXo+K=4zCbM<|Ow{^n? zRuG_uQkqN=0TBrx9-1rptOOLc_HCZDn!qacsXpD*wyQK_V?U3ynMb1V1_)s#lH`cxs;c=;*NhH~ zw6|vPg7BDICeO^ zTxDFeb9?k`N!<0ec6|Pw{QccV!tC5wLVa|??T_PmvMd6aW) vxYcuqw&;3`;s1!+J>BP;d+)rum>jhasTemperature = false; + d->hasHumidity = false; + d->id = 0; +} + +Sensor::~Sensor() { + delete d; +} + +QString Sensor::humidity() const { + return d->humidity; +} + +void Sensor::setHumidity(const QString &humidity) { + d->humidity = humidity; + d->hasHumidity = true; + emit humidityChanged(); + emit hasHumidityChanged(); +} + +bool Sensor::hasHumidity() const { + return d->hasHumidity; +} + +int Sensor::id() const { + return d->id; +} + +void Sensor::setId(int id) { + d->id = id; + emit idChanged(); +} + +QDateTime Sensor::lastUpdated() const { + return d->lastUpdated; +} + +void Sensor::setLastUpdated(const QDateTime &lastUpdated) { + d->lastUpdated = lastUpdated; + emit lastUpdatedChanged(); +} + +QString Sensor::model() const { + return d->model; +} + +void Sensor::setModel(const QString &model) { + d->model = model; + emit modelChanged(); +} + +QString Sensor::name() const { + return d->name; +} + +void Sensor::setName(const QString &name) { + d->name = name; + emit nameChanged(); +} + +QString Sensor::protocol() const { + return d->protocol; +} + +void Sensor::setProtocol(const QString &protocol) { + d->protocol = protocol; + emit protocolChanged(); +} + +QString Sensor::temperature() const { + return d->temperature; +} + +void Sensor::setTemperature(const QString &temperature) { + d->temperature = temperature; + d->hasTemperature = true; + emit temperatureChanged(); + emit hasTemperatureChanged(); +} + +bool Sensor::hasTemperature() const { + return d->hasTemperature; +} diff --git a/telldus-gui/Plugins/Sensors/sensor.h b/telldus-gui/Plugins/Sensors/sensor.h new file mode 100644 index 00000000..41c2260f --- /dev/null +++ b/telldus-gui/Plugins/Sensors/sensor.h @@ -0,0 +1,66 @@ +#ifndef SENSOR_H +#define SENSOR_H + +#include +#include +#include +#include + +class Sensor : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool hasHumidity READ hasHumidity NOTIFY hasHumidityChanged) + Q_PROPERTY(bool hasTemperature READ hasTemperature NOTIFY hasTemperatureChanged) + Q_PROPERTY(QString humidity READ humidity WRITE setHumidity NOTIFY humidityChanged) + Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) + Q_PROPERTY(QDateTime lastUpdated READ lastUpdated WRITE setLastUpdated NOTIFY lastUpdatedChanged) + Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString protocol READ protocol WRITE setProtocol NOTIFY protocolChanged) + Q_PROPERTY(QString temperature READ temperature WRITE setTemperature NOTIFY temperatureChanged) +public: + explicit Sensor(QObject *parent = 0); + ~Sensor(); + + QString humidity() const; + void setHumidity(const QString &humidity); + bool hasHumidity() const; + + int id() const; + void setId(int id); + + QDateTime lastUpdated() const; + void setLastUpdated(const QDateTime &lastUpdated); + + QString model() const; + void setModel(const QString &model); + + QString name() const; + void setName(const QString &name); + + QString protocol() const; + void setProtocol(const QString &protocol); + + QString temperature() const; + void setTemperature(const QString &temperature); + bool hasTemperature() const; + +signals: + void idChanged(); + void hasHumidityChanged(); + void hasTemperatureChanged(); + void humidityChanged(); + void lastUpdatedChanged(); + void modelChanged(); + void nameChanged(); + void protocolChanged(); + void temperatureChanged(); + +private: + class PrivateData; + PrivateData *d; +}; + +Q_DECLARE_METATYPE(Sensor*) + +#endif // SENSOR_H diff --git a/telldus-gui/Plugins/Sensors/sensorsplugin.cpp b/telldus-gui/Plugins/Sensors/sensorsplugin.cpp new file mode 100644 index 00000000..51d869c3 --- /dev/null +++ b/telldus-gui/Plugins/Sensors/sensorsplugin.cpp @@ -0,0 +1,31 @@ +#include "sensorsplugin.h" +#include "sensor.h" +#include + +QScriptValue SensorCTor(QScriptContext *context, QScriptEngine *engine) { + if (!context->isCalledAsConstructor()) { + return engine->undefinedValue(); + } + return engine->newQObject(new Sensor(), QScriptEngine::ScriptOwnership); +} + +SensorsPlugin::SensorsPlugin ( QObject * parent ) + :QScriptExtensionPlugin( parent ) +{ +} + +SensorsPlugin::~SensorsPlugin() { +} + +void SensorsPlugin::initialize ( const QString & key, QScriptEngine * engine ) { + if (key == "com.telldus.sensors") { + QScriptValue qml = engine->globalObject().property("com").property("telldus").property("sensors"); + qml.setProperty("sensor", engine->newFunction(SensorCTor)); + } +} + +QStringList SensorsPlugin::keys () const { + return QStringList() << "com.telldus.sensors"; +} + +Q_EXPORT_PLUGIN2(SensorsInterface, SensorsPlugin) diff --git a/telldus-gui/Plugins/Sensors/sensorsplugin.h b/telldus-gui/Plugins/Sensors/sensorsplugin.h new file mode 100644 index 00000000..a473e466 --- /dev/null +++ b/telldus-gui/Plugins/Sensors/sensorsplugin.h @@ -0,0 +1,16 @@ +#ifndef SENSORSPLUGIN_H +#define SENSORSPLUGIN_H + +#include + +class SensorsPlugin : public QScriptExtensionPlugin { +public: + SensorsPlugin ( QObject * parent = 0 ); + ~SensorsPlugin (); + + virtual void initialize ( const QString & key, QScriptEngine * engine ); + virtual QStringList keys () const; +}; + + +#endif // SENSORSPLUGIN_H From 61331e7da39c6773975ee34eccb457fe57bf2c00 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Oct 2011 11:43:26 +0200 Subject: [PATCH 1708/2215] Give the qml-widget transparent background --- telldus-gui/Plugins/QML/qmlview.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp index 95b8c5f8..dea06628 100644 --- a/telldus-gui/Plugins/QML/qmlview.cpp +++ b/telldus-gui/Plugins/QML/qmlview.cpp @@ -13,6 +13,9 @@ public: QMLView::QMLView(const QDir &dir, const QScriptValue &object) : QDeclarativeView() { + setAttribute(Qt::WA_TranslucentBackground); + setStyleSheet("background:transparent;"); + d = new PrivateData; d->baseDir = dir; d->object = object; From c41a84b5825cf6744ea2a5c13c8a3b799ce14432 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Oct 2011 16:00:21 +0200 Subject: [PATCH 1709/2215] Move the sensor values to a own class SensorValue --- telldus-gui/Plugins/Sensors/CMakeLists.txt | 4 ++ telldus-gui/Plugins/Sensors/sensor.cpp | 64 +++++++++------------ telldus-gui/Plugins/Sensors/sensor.h | 18 ++---- telldus-gui/Plugins/Sensors/sensorvalue.cpp | 35 +++++++++++ telldus-gui/Plugins/Sensors/sensorvalue.h | 36 ++++++++++++ 5 files changed, 108 insertions(+), 49 deletions(-) create mode 100644 telldus-gui/Plugins/Sensors/sensorvalue.cpp create mode 100644 telldus-gui/Plugins/Sensors/sensorvalue.h diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt index 065b7d97..bfd56a32 100644 --- a/telldus-gui/Plugins/Sensors/CMakeLists.txt +++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt @@ -1,12 +1,15 @@ SET(REQUIRE_PLUGIN_QML TRUE PARENT_SCOPE) SET(REQUIRE_PLUGIN_SETTINGS TRUE PARENT_SCOPE) +SET(QT_USE_QTDECLARATIVE TRUE) + SET( Plugin_NAME "sensors" ) SET( Plugin_SRCS sensor.cpp sensorsplugin.cpp + sensorvalue.cpp ) SET( Plugin_HDRS @@ -15,6 +18,7 @@ SET( Plugin_HDRS SET( Plugin_MOC_HDRS sensor.h + sensorvalue.h ) SET( Plugin_PATH "com.telldus.sensors" ) diff --git a/telldus-gui/Plugins/Sensors/sensor.cpp b/telldus-gui/Plugins/Sensors/sensor.cpp index b07c6a56..6a39b006 100644 --- a/telldus-gui/Plugins/Sensors/sensor.cpp +++ b/telldus-gui/Plugins/Sensors/sensor.cpp @@ -1,19 +1,20 @@ #include "sensor.h" +#include "sensorvalue.h" +#include class Sensor::PrivateData { public: bool hasTemperature, hasHumidity; int id; - QString model, name, protocol, temperature, humidity; + QString model, name, protocol; QDateTime lastUpdated; + QMap values; }; Sensor::Sensor(QObject *parent) : QObject(parent) { d = new PrivateData; - d->hasTemperature = false; - d->hasHumidity = false; d->id = 0; } @@ -21,19 +22,8 @@ Sensor::~Sensor() { delete d; } -QString Sensor::humidity() const { - return d->humidity; -} - -void Sensor::setHumidity(const QString &humidity) { - d->humidity = humidity; - d->hasHumidity = true; - emit humidityChanged(); - emit hasHumidityChanged(); -} - bool Sensor::hasHumidity() const { - return d->hasHumidity; + return d->values.contains(TELLSTICK_HUMIDITY); } int Sensor::id() const { @@ -45,15 +35,6 @@ void Sensor::setId(int id) { emit idChanged(); } -QDateTime Sensor::lastUpdated() const { - return d->lastUpdated; -} - -void Sensor::setLastUpdated(const QDateTime &lastUpdated) { - d->lastUpdated = lastUpdated; - emit lastUpdatedChanged(); -} - QString Sensor::model() const { return d->model; } @@ -81,17 +62,28 @@ void Sensor::setProtocol(const QString &protocol) { emit protocolChanged(); } -QString Sensor::temperature() const { - return d->temperature; -} - -void Sensor::setTemperature(const QString &temperature) { - d->temperature = temperature; - d->hasTemperature = true; - emit temperatureChanged(); - emit hasTemperatureChanged(); -} - bool Sensor::hasTemperature() const { - return d->hasTemperature; + return d->values.contains(TELLSTICK_TEMPERATURE); +} + +SensorValue * Sensor::sensorValue(int type) { + return (d->values.contains(type) ? d->values[type] : 0); +} + +void Sensor::setValue(int type, const QString &value, const QDateTime ×tamp) { + SensorValue *sensorValue; + if (d->values.contains(type)) { + sensorValue = d->values[type]; + } else { + sensorValue = new SensorValue(this); + d->values[type] = sensorValue; + } + sensorValue->setValue(value); + sensorValue->setLastUpdated(timestamp); + + if (type == TELLSTICK_TEMPERATURE) { + emit hasTemperatureChanged(); + } else if (type == TELLSTICK_HUMIDITY) { + emit hasHumidityChanged(); + } } diff --git a/telldus-gui/Plugins/Sensors/sensor.h b/telldus-gui/Plugins/Sensors/sensor.h index 41c2260f..fc70468d 100644 --- a/telldus-gui/Plugins/Sensors/sensor.h +++ b/telldus-gui/Plugins/Sensors/sensor.h @@ -6,32 +6,26 @@ #include #include +class SensorValue; + class Sensor : public QObject { Q_OBJECT Q_PROPERTY(bool hasHumidity READ hasHumidity NOTIFY hasHumidityChanged) Q_PROPERTY(bool hasTemperature READ hasTemperature NOTIFY hasTemperatureChanged) - Q_PROPERTY(QString humidity READ humidity WRITE setHumidity NOTIFY humidityChanged) Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) - Q_PROPERTY(QDateTime lastUpdated READ lastUpdated WRITE setLastUpdated NOTIFY lastUpdatedChanged) Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString protocol READ protocol WRITE setProtocol NOTIFY protocolChanged) - Q_PROPERTY(QString temperature READ temperature WRITE setTemperature NOTIFY temperatureChanged) public: explicit Sensor(QObject *parent = 0); ~Sensor(); - QString humidity() const; - void setHumidity(const QString &humidity); bool hasHumidity() const; int id() const; void setId(int id); - QDateTime lastUpdated() const; - void setLastUpdated(const QDateTime &lastUpdated); - QString model() const; void setModel(const QString &model); @@ -41,20 +35,18 @@ public: QString protocol() const; void setProtocol(const QString &protocol); - QString temperature() const; - void setTemperature(const QString &temperature); bool hasTemperature() const; + Q_INVOKABLE SensorValue *sensorValue(int type); + Q_INVOKABLE void setValue(int type, const QString &value, const QDateTime ×tamp); + signals: void idChanged(); void hasHumidityChanged(); void hasTemperatureChanged(); - void humidityChanged(); - void lastUpdatedChanged(); void modelChanged(); void nameChanged(); void protocolChanged(); - void temperatureChanged(); private: class PrivateData; diff --git a/telldus-gui/Plugins/Sensors/sensorvalue.cpp b/telldus-gui/Plugins/Sensors/sensorvalue.cpp new file mode 100644 index 00000000..108e0f99 --- /dev/null +++ b/telldus-gui/Plugins/Sensors/sensorvalue.cpp @@ -0,0 +1,35 @@ +#include "sensorvalue.h" + +class SensorValue::PrivateData { +public: + QString value; + QDateTime lastUpdated; +}; + +SensorValue::SensorValue(QObject *parent) : + QObject(parent) +{ + d = new PrivateData; +} + +SensorValue::~SensorValue() { + delete d; +} + +QDateTime SensorValue::lastUpdated() const { + return d->lastUpdated; +} + +void SensorValue::setLastUpdated(const QDateTime &lastUpdated) { + d->lastUpdated = lastUpdated; + emit lastUpdatedChanged(); +} + +QString SensorValue::value() const { + return d->value; +} + +void SensorValue::setValue(const QString &value) { + d->value = value; + emit valueChanged(); +} diff --git a/telldus-gui/Plugins/Sensors/sensorvalue.h b/telldus-gui/Plugins/Sensors/sensorvalue.h new file mode 100644 index 00000000..9cac8c8c --- /dev/null +++ b/telldus-gui/Plugins/Sensors/sensorvalue.h @@ -0,0 +1,36 @@ +#ifndef SENSORVALUE_H +#define SENSORVALUE_H + +#include +#include +#include +#include + +class SensorValue : public QObject +{ + Q_OBJECT + Q_PROPERTY(QDateTime lastUpdated READ lastUpdated WRITE setLastUpdated NOTIFY lastUpdatedChanged) + Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged) + +public: + explicit SensorValue(QObject *parent = 0); + ~SensorValue(); + + QDateTime lastUpdated() const; + void setLastUpdated(const QDateTime &lastUpdated); + + QString value() const; + void setValue(const QString &model); + +signals: + void lastUpdatedChanged(); + void valueChanged(); + +private: + class PrivateData; + PrivateData *d; +}; + +Q_DECLARE_METATYPE(SensorValue*) + +#endif // SENSORVALUE_H From 12fdaf2d7725243ce1e11adf043b16aeec6ccd72 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Oct 2011 16:06:35 +0200 Subject: [PATCH 1710/2215] Send sensor events as QDateTime instead of just an int --- telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp | 2 +- telldus-gui/Plugins/TelldusCore/tellduscoreobject.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp index 3362fb8b..5500bbf0 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp @@ -160,6 +160,6 @@ void WINAPI TelldusCoreObject::deviceEventCallback(int deviceId, int method, con void WINAPI TelldusCoreObject::sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context) { TelldusCoreObject *parent = static_cast(context); if (parent) { - emit parent->sensorEvent(QString::fromUtf8(protocol), QString::fromUtf8(model), id, dataType, QString::fromUtf8(value), timestamp); + emit parent->sensorEvent(QString::fromUtf8(protocol), QString::fromUtf8(model), id, dataType, QString::fromUtf8(value), QDateTime::fromTime_t(timestamp)); } } diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h index 98a7f842..a7bac7ee 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h @@ -3,6 +3,7 @@ #include #include +#include #include class TelldusCoreObject : public QObject @@ -15,7 +16,7 @@ public: signals: void deviceChange( int deviceId, int eventId ); void deviceEvent( int deviceId, int method, const QString &data ); - void sensorEvent( const QString &protocol, const QString &model, int id, int dataType, const QString &value, int timestamp); + void sensorEvent( const QString &protocol, const QString &model, int id, int dataType, const QString &value, const QDateTime timestamp); void errorOccurred( int deviceId, int errorId, const QString &errorString ); public slots: From 194579cd2b6a39e0de825e0dee79dc6800098006 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Oct 2011 16:20:13 +0200 Subject: [PATCH 1711/2215] Updated icon for plugin Sensors --- telldus-gui/Plugins/Sensors/icon.png | Bin 3885 -> 754 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/telldus-gui/Plugins/Sensors/icon.png b/telldus-gui/Plugins/Sensors/icon.png index e71391cf9ca6f7ff541022a80aa33646af3ad6dd..4badd42f0dafbb110ec9bb0c2ebe1ed0d957c1ec 100644 GIT binary patch delta 731 zcmV<10wn#d9`Xf{BYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU! zlu1NERCwCNmtSa&VI0TLnGGRngvR^{8B+46wPBhwQEny|k}PT^$;DjEF8qtwI?df; z%+fAIODGiCxfqI+tL?(gmefLt&Fn&ly*@vEPn}k4=Q;0t-hVyy>A5)Xd4J#c`Tm~Y z^LwJ6=S5sbG*&;0=`_^9To{DAaM?@52P2Ln>LNhFU%)Cj2R*PFF2E0{M8r220eOys zFTzsT1clHHYoP+B!Ihk?0AD|y=_8zn#c(F==Ns@6T3|V=FqEl)dUH z&<$2_;1_I$zhPQn8NVNPNWh9Pw_(bHvy*K>F>{f2!GFrI>Oi4ty)Abe>`wcwN8$?f zT(HM6UtG%c3f@64%oy{Cos@mh4GEs#8Q5{m%WR*&g@^LG2@WV9(uXxFr=S*&*(ph` zybnUaYk7Sfx|H?f4eN%gpdQv+sYNUCE5KT?FR;i_z(V*AGyMwqtu6P{QNW10Jc1<6lI^%ABgjm4)YSC}OHG-cA`f7HR>AK2o zhw{R{+Agf6x-Hu=T}SYiT-}ZrFdcz?3Ra+obO0VhJHZEBw#z>O1^|ha%K4IKj935w N002ovPDHLkV1ijOS=#^r literal 3885 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 vxYcuqw&;3`;s1!+J>BP;d+)rum>j Date: Thu, 27 Oct 2011 16:33:54 +0200 Subject: [PATCH 1712/2215] Added graphics for sensors. A first version without support for edit or remove sensors --- telldus-gui/Plugins/Sensors/CMakeLists.txt | 6 ++ telldus-gui/Plugins/Sensors/HeaderTitle.qml | 10 +++ telldus-gui/Plugins/Sensors/SensorValue.qml | 32 ++++++++ telldus-gui/Plugins/Sensors/__init__.js | 12 +-- telldus-gui/Plugins/Sensors/header_bg.png | Bin 0 -> 526 bytes telldus-gui/Plugins/Sensors/icon_humidity.png | Bin 0 -> 1684 bytes telldus-gui/Plugins/Sensors/icon_temp.png | Bin 0 -> 1644 bytes telldus-gui/Plugins/Sensors/main.qml | 71 ++++++++++++++++-- telldus-gui/Plugins/Sensors/qmldir | 2 + telldus-gui/Plugins/Sensors/row_bg.png | Bin 0 -> 346 bytes telldus-gui/Plugins/Sensors/sensorsplugin.cpp | 3 + 11 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 telldus-gui/Plugins/Sensors/HeaderTitle.qml create mode 100644 telldus-gui/Plugins/Sensors/SensorValue.qml create mode 100644 telldus-gui/Plugins/Sensors/header_bg.png create mode 100644 telldus-gui/Plugins/Sensors/icon_humidity.png create mode 100644 telldus-gui/Plugins/Sensors/icon_temp.png create mode 100644 telldus-gui/Plugins/Sensors/row_bg.png diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt index bfd56a32..535ccc85 100644 --- a/telldus-gui/Plugins/Sensors/CMakeLists.txt +++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt @@ -24,9 +24,15 @@ SET( Plugin_MOC_HDRS SET( Plugin_PATH "com.telldus.sensors" ) SET( Plugin_EXTRA + header_bg.png icon.png + icon_humidity.png + icon_temp.png main.qml + HeaderTitle.qml + row_bg.png qmldir + SensorValue.qml ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Sensors/HeaderTitle.qml b/telldus-gui/Plugins/Sensors/HeaderTitle.qml new file mode 100644 index 00000000..0d7ae213 --- /dev/null +++ b/telldus-gui/Plugins/Sensors/HeaderTitle.qml @@ -0,0 +1,10 @@ +import Qt 4.7 + +Text { + id: headerTitle + text: "Name" + color: "white" + font.weight: Font.Bold + height: parent.height + verticalAlignment: Text.AlignVCenter +} diff --git a/telldus-gui/Plugins/Sensors/SensorValue.qml b/telldus-gui/Plugins/Sensors/SensorValue.qml new file mode 100644 index 00000000..7198c9ff --- /dev/null +++ b/telldus-gui/Plugins/Sensors/SensorValue.qml @@ -0,0 +1,32 @@ +import Qt 4.7 + +Item { + property alias text: text.text + property alias icon: icon.source + property date lastUpdated: new Date() + + id: sensorValue + width: parent.width + height: 40 + Image { + id: icon + anchors.verticalCenter: parent.verticalCenter + } + Text { + id: text + anchors.left: icon.right + anchors.leftMargin: 10 + anchors.verticalCenter: parent.verticalCenter + color: "#004275" + } + Text { + id: timestamp + anchors.right: parent.right + anchors.rightMargin: 10 + anchors.verticalCenter: parent.verticalCenter + text: Qt.formatDateTime(lastUpdated, Qt.DefaultLocaleShortDate); + color: "#004275" + font.pointSize: text.font.pointSize - 1 + font.italic: true + } +} diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js index b6b11054..c20bfb67 100644 --- a/telldus-gui/Plugins/Sensors/__init__.js +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -27,9 +27,8 @@ com.telldus.sensors = function() { } - //com.telldus.core.sensorEvent.connect(sensorEvent); - view = new com.telldus.qml.view({ - }); + com.telldus.core.sensorEvent.connect(sensorEvent); + view = new com.telldus.qml.view({}); view.setProperty('sensorModel', sensorList); view.load("main.qml"); @@ -63,13 +62,8 @@ com.telldus.sensors = function() { print("Update"); } - if (dataType == com.telldus.core.TELLSTICK_TEMPERATURE) { - sensor.temperature = value; - } else if (dataType == com.telldus.core.TELLSTICK_HUMIDITY) { - sensor.humidity = value; - } - print("Sensor event", protocol, model, id, dataType, value, timestamp); + sensor.setValue(dataType, value, timestamp); } return { //Public functions diff --git a/telldus-gui/Plugins/Sensors/header_bg.png b/telldus-gui/Plugins/Sensors/header_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..564a158b5d9c69a045712278b45085512e0474f7 GIT binary patch literal 526 zcmV+p0`dKcP)J)aLLt2t;vW#y(ps?7Lexe~5Cei*7!%YKMm-bF*WIl%r;#8> zyemZKc-hqp|drJ&7&)e zm~n;=Rwjo=Ov}d3SsIsF14gleD$R9OL8v)^4sy82zU*t{(ch#i*h*X@o_cU1*32S@ z63y9}Y=GfVGV_RwyC)RORk&G+zpGk^VPtZ7@-EYxL?d%x-nwd9Kd~RMZQGFc4`dCN zpHCwbHQ3>#$HpQhKfp`7aLWuaJDh zzf(xRmWJPZmXLq=rzj-Dl(Mc&T_m{XP+&M|n2J+^UkCjr(bUGPafV~(dEL_WfIF;e zP{L7e6EWqp6U9V03enO|i|WVLH1eE4jv6EGP`I?VAyOA9OFFJ^ZSMjM08uy&f`RU1 Q`v3p{07*qoM6N<$f)*X<_5c6? literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/Sensors/icon_humidity.png b/telldus-gui/Plugins/Sensors/icon_humidity.png new file mode 100644 index 0000000000000000000000000000000000000000..29b02e26676f112bf67aec6d5438028f90622ed3 GIT binary patch literal 1684 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/Sensors/sensorsplugin.cpp b/telldus-gui/Plugins/Sensors/sensorsplugin.cpp index 51d869c3..4891b7ad 100644 --- a/telldus-gui/Plugins/Sensors/sensorsplugin.cpp +++ b/telldus-gui/Plugins/Sensors/sensorsplugin.cpp @@ -1,6 +1,8 @@ #include "sensorsplugin.h" #include "sensor.h" +#include "sensorvalue.h" #include +#include QScriptValue SensorCTor(QScriptContext *context, QScriptEngine *engine) { if (!context->isCalledAsConstructor()) { @@ -12,6 +14,7 @@ QScriptValue SensorCTor(QScriptContext *context, QScriptEngine *engine) { SensorsPlugin::SensorsPlugin ( QObject * parent ) :QScriptExtensionPlugin( parent ) { + qmlRegisterType("Telldus", 1, 0, "SensorValue"); } SensorsPlugin::~SensorsPlugin() { From ebfc9666eb8bddbb4df87f50dc0ec2bb21ea0cd4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 09:49:34 +0200 Subject: [PATCH 1713/2215] Show protocol and id as name for now. Editing of sensors is currently not implemented. --- telldus-gui/Plugins/Sensors/sensor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/Plugins/Sensors/sensor.cpp b/telldus-gui/Plugins/Sensors/sensor.cpp index 6a39b006..cb04f2fc 100644 --- a/telldus-gui/Plugins/Sensors/sensor.cpp +++ b/telldus-gui/Plugins/Sensors/sensor.cpp @@ -45,6 +45,7 @@ void Sensor::setModel(const QString &model) { } QString Sensor::name() const { + return QString("%1 %2").arg(this->protocol()).arg(this->id()); //TODO: Remove when name is fully implemented return d->name; } From cb6b3099d5508d464dc75a2c9d9d6893bf9f717c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 09:50:17 +0200 Subject: [PATCH 1714/2215] Add Sensors plugins as default --- telldus-gui/Plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index f6a1b8ab..366d2f0d 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -12,7 +12,7 @@ SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") SET(BUILD_PLUGIN_SCHEDULERGUISIMPLE FALSE CACHE BOOL "Build plugin 'Simple Scheduler GUI'") -SET(BUILD_PLUGIN_SENSORS FALSE CACHE BOOL "Build plugin 'Sensors'") +SET(BUILD_PLUGIN_SENSORS TRUE CACHE BOOL "Build plugin 'Sensors'") ADD_SUBDIRECTORY(telldus) From e7ec37aa607de19850994a141622526fb4efaa30 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 10:31:07 +0200 Subject: [PATCH 1715/2215] Add includepath to telldus-core for plugin Sensors --- telldus-gui/Plugins/Sensors/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt index 535ccc85..cf97f98c 100644 --- a/telldus-gui/Plugins/Sensors/CMakeLists.txt +++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt @@ -35,4 +35,7 @@ SET( Plugin_EXTRA SensorValue.qml ) +FIND_PACKAGE(TelldusCore REQUIRED) +SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ) + INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) From 1bbff2a0ecab738a302aaec33c1e6460a35421f4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Oct 2011 11:12:37 +0200 Subject: [PATCH 1716/2215] Fix ending doxygen block --- telldus-core/client/telldus-core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index d859701a..f88b5c1d 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -562,4 +562,4 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da } -/*\@}*/ +/* @} */ From fc626ef7094410ba93e3fd82a9392bd307924d99 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Oct 2011 11:14:31 +0200 Subject: [PATCH 1717/2215] Add some ignored documentation files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 567609b1..609fb881 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ build/ +Doxyfile +html/ +latex/ From df58f9df15d8551e3b071a88a758ac5d092fc277 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 14:15:39 +0200 Subject: [PATCH 1718/2215] Make sure lines not exceeding 80 chars --- docs/telldus-core.dox | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index a34afe64..515f57d5 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -212,9 +212,10 @@ * * Many devices (for example motion detectors) resends their messages many times * to ensure that they are received correctly. If a deviceeventcallback or - * rawdeviceeventcallback in turn is calling a controlling function, for example tdTurnOn, - * it may be neccessary to implement some solution to wait for the device to finish its - * resending, before executing the controlling function. See how this can be done in the python example. + * rawdeviceeventcallback in turn is calling a controlling function, for example + * tdTurnOn, it may be neccessary to implement some solution to wait for the + * device to finish its resending, before executing the controlling function. + * See how this can be done in the python example. * * \subsection sec_events_callbacks Callbacks * From 478e8cdb738ff0945da80362da00a28e17746150 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 14:17:51 +0200 Subject: [PATCH 1719/2215] Fixed correct references --- docs/telldus-core.dox | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index 515f57d5..9ffd6d42 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -235,9 +235,10 @@ * - const char *data - For some methods this contains data. For TELLSTICK_DIM * this hold the current value. * - int callbackId - id of callback - * - void *context - see "Registering for callbacks" for description + * - void *context - see \ref sec_events_registering for description * * \subsubsection sec_events_callbacks_devicechangeevent DeviceChangeEvent + * * This event is fired when the data around a device is changed. It can only be * triggered by another software. Use this callback to keep your list of devices * in sync. @@ -257,7 +258,7 @@ * - TELLSTICK_CHANGE_PROTOCOL - Use tdGetProtocol() to read the new value. * - TELLSTICK_CHANGE_MODEL - Use tdGetModel() to read the new value. * - int callbackId - id of callback - * - void *context - see "Registering for callbacks" for description + * - void *context - see \ref sec_events_registering for description * * \subsubsection sec_events_callbacks_rawdeviceevent RawDeviceEvent * @@ -269,7 +270,7 @@ * - const char *data - raw device data * - int controllerId - id of receiving controller, can identify the TellStick if several exists in the system * - int callbackId - id of callback - * - void *context - see "Registering for callbacks" for description + * - void *context - see \ref sec_events_registering for description * * \subsection sec_events_example Example * From f285c9099e1c4cee330d52d0cf15eaf099beb761 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 14:19:01 +0200 Subject: [PATCH 1720/2215] Use full name 'TellStick Duo' instead of just 'Duo' --- docs/telldus-core.dox | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index 9ffd6d42..d2df6d89 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -262,9 +262,9 @@ * * \subsubsection sec_events_callbacks_rawdeviceevent RawDeviceEvent * - * Use this callback with caution. It outputs everything from the Duo without - * any preprocessing. This can be used to get events from devices not already - * configured. + * Use this callback with caution. It outputs everything from a TellStick Duo + * without any preprocessing. This can be used to get events from devices not + * already configured. * * Parameters: * - const char *data - raw device data From 5ca9d3a7b8e4b2134d12d2f622eb00693f920356 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 15:10:03 +0200 Subject: [PATCH 1721/2215] Add documentation for tdSensor(), see #110 --- telldus-core/client/telldus-core.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index f88b5c1d..1ae3649b 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -534,6 +534,17 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial Client::getWStringFromService(msg); } +/** + * Use this function to iterate over all sensors. Iterate until + * TELLSTICK_SUCCESS is not returned + * @param protocol A byref string where the protocol of the sensor will be placed + * @param protocolLen The length of the \c protocol parameter + * @param model A byref string where the model of the sensor will be placed + * @param modelLen The length of the \c model parameter + * @param id A byref int where the id of the sensor will be placed + * @param dataTypes A byref int with flags for the supported sensor values + * @returns TELLSTICK_SUCCESS if there is more sensors to be fetched + */ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes) { Client *client = Client::getInstance(); return client->getSensor(protocol, protocolLen, model, modelLen, id, dataTypes); From f207af7462b3b50299c33c8d76d6045061bd4455 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 28 Oct 2011 15:10:10 +0200 Subject: [PATCH 1722/2215] Add documentation for tdSensorValue(), see #110 --- telldus-core/client/telldus-core.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 1ae3649b..62e53c40 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -550,6 +550,20 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, return client->getSensor(protocol, protocolLen, model, modelLen, id, dataTypes); } +/** + * Get one of the supported sensor values from a sensor. Make sure it support + * the value type first by calling tdSensor(). The triplet \c protocol, + * \c model, and \c id together identifies a sensor. + * @param protocol The protocol for the sensor + * @param model The model for the sensor + * @param id The id of the sensor + * @param dataType One of the datatype to retrieve + * @param value A byref string where the value will be places + * @param len The length of the \c value parameter + * @param timestamp A byref int where the timestamp of the value will be placed + * @returns TELLSTICK_SUCCESS if the value could be fetched or one of the + * errorcodes on failure + */ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp) { Message msg(L"tdSensorValue"); msg.addArgument(protocol); From 290a805c6bd7bfd54c93831df5acd5e204cc5383 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 27 Oct 2011 11:12:51 +0200 Subject: [PATCH 1723/2215] Added documentation for sensors, this closes #110. --- docs/telldus-core.dox | 65 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index d2df6d89..9185076e 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -187,10 +187,54 @@ * tdReleaseString(name); * \endcode * + * \subsection sec_bu_sensors Sensors + * + * Retrieving sensor values can be done in two ways. Either by a polling + * interface or by callbacks. The client application can implement one or both + * of these interfaces. For callbacks, read more under \ref sec_events. + * + * Each of the sensors can have one or several value types. Currently only + * temperature and humidity are implemented. + * + * There is no API to add, remove or edit sensors. Each sensor that + * TellStick Duo has got any data from is added to an internal list. It is up to + * the client application to filter and only show the sensors your are + * interested in. + * + * To iterate over the list of sensors, call tdSensor() repeatedly as long as it + * returns \c TELLSTICK_SUCCESS. The parameters \c protocol, \c model, + * \c sensorId, and \c dataTypes are sent by reference and will be filled with + * the values. + * + * Example: + * \code + * char protocol[DATA_LENGTH], model[DATA_LENGTH]; + * int sensorId = 0, dataTypes = 0; + * while(tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes) == TELLSTICK_SUCCESS) { + * //Print the sensor + * printf("%s,\t%s,\t%i\n", protocol, model, sensorId); + * } + * \endcode + * + * The type of sensor values the sensor supports are stored as flags in the + * parameter \c sensorId. Call tdSensorValue() for each type. + * + * Example: + * \code + * char value[DATA_LENGTH]; + * char timeBuf[80]; + * time_t timestamp = 0; + * if (dataTypes & TELLSTICK_TEMPERATURE) { + * tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, value, DATA_LENGTH, (int *)×tamp); + * strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + * printf("Temperature:\t%sº\t(%s)\n", value, timeBuf); + * } + * \endcode + * * \section sec_events Events * - * To get events from either a TellStick Duo or if another software changes the - * status of a device you have to register for a callback. + * To get events from either a TellStick Duo, another software changes the + * status of a device, or new sensors values you have to register for a callback. * * \subsection sec_events_registering Registering for callbacks * @@ -198,6 +242,7 @@ * \li tdRegisterDeviceEvent() * \li tdRegisterDeviceChangeEvent() * \li tdRegisterRawDeviceEvent() + * \li tdRegisterSensorEvent() * * These all work in the same way. The first parameter is a function-pointer to * the callback function. The second parameter is an optional void pointer. This @@ -219,7 +264,7 @@ * * \subsection sec_events_callbacks Callbacks * - * telldus-core currently implements three different callback function for + * telldus-core currently implements four different callback function for * different purposes. * * \subsubsection sec_events_callbacks_deviceevent DeviceEvent @@ -272,6 +317,20 @@ * - int callbackId - id of callback * - void *context - see \ref sec_events_registering for description * + * \subsubsection sec_events_callbacks_sensorevent SensorEvent + * + * This event is fired when a new sensor value is retrieved. + * + * Parameters: + * - const char *protocol - The sensors protocol + * - const char *model - The model of the sensor + * - int id - The unique id for the sensor. + * - int dataType - Flags for which types of data the sensor supports + * - const char *value - A human readable string of the data + * - int timestamp - The timestamp when the latest value was received + * - int callbackId - id of callback + * - void *context - See \ref sec_events_registering for description + * * \subsection sec_events_example Example * * \section sec_other_languages Notes using other languages than C/C++ From ef9a201f9052aef710ebaa70b3e4458e014564f0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 1 Nov 2011 14:14:14 +0100 Subject: [PATCH 1724/2215] Possibility to add/remove sensors from list, and change their names. Not yet persistent. --- telldus-gui/Plugins/Sensors/SensorValue.qml | 1 + telldus-gui/Plugins/Sensors/__init__.js | 1 + telldus-gui/Plugins/Sensors/main.qml | 193 +++++++++++++++++--- telldus-gui/Plugins/Sensors/sensor.cpp | 18 +- telldus-gui/Plugins/Sensors/sensor.h | 8 +- 5 files changed, 191 insertions(+), 30 deletions(-) diff --git a/telldus-gui/Plugins/Sensors/SensorValue.qml b/telldus-gui/Plugins/Sensors/SensorValue.qml index 7198c9ff..083830a1 100644 --- a/telldus-gui/Plugins/Sensors/SensorValue.qml +++ b/telldus-gui/Plugins/Sensors/SensorValue.qml @@ -14,6 +14,7 @@ Item { } Text { id: text + font.weight: Font.Bold anchors.left: icon.right anchors.leftMargin: 10 anchors.verticalCenter: parent.verticalCenter diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js index c20bfb67..70283e2b 100644 --- a/telldus-gui/Plugins/Sensors/__init__.js +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -56,6 +56,7 @@ com.telldus.sensors = function() { sensor.protocol = protocol; sensor.model = model; sensor.id = id; + sensor.showInList = false; sensorList.push(sensor); print("Create new"); } else { diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml index 8be6755d..5d240c29 100644 --- a/telldus-gui/Plugins/Sensors/main.qml +++ b/telldus-gui/Plugins/Sensors/main.qml @@ -2,39 +2,116 @@ import Qt 4.7 Item { id: main + state: "VIEW" Component { id: sensorView - BorderImage { - source: "row_bg.png" - border.left: 5; border.top: 5 - border.right: 5; border.bottom: 5 - height: sensorInfo.height + Item{ + id: sensorViewItem + visible: main.state == "EDIT" || modelData.showInList + height: childrenRect.height width: parent.width - Text { - anchors.left: parent.left - anchors.leftMargin: 15 - height: 40 - verticalAlignment: Text.AlignVCenter - text: modelData.name; - color: "#004275" - } - Column { - id: sensorInfo - anchors.right: parent.right - width: 250 - SensorValue { - visible: modelData.hasTemperature - text: visible ? modelData.sensorValue(1).value + '°C' : '' - icon: "icon_temp.png" - lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date() + BorderImage { + source: "row_bg.png" + border.left: 5; border.top: 5 + border.right: 5; border.bottom: 5 + height: sensorInfo.height + width: parent.width + + Text { + visible: main.state == "VIEW" + anchors.left: parent.left + anchors.leftMargin: 15 + height: 40 + verticalAlignment: Text.AlignVCenter + text: modelData.name; + color: "#004275" } - SensorValue { - visible: modelData.hasHumidity - text: visible ? modelData.sensorValue(2).value + '%' : '' - icon: "icon_humidity.png" - lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date() + Rectangle{ + color: "white" + visible: main.state == "EDIT" + anchors.left: parent.left + anchors.leftMargin: 15 + width: nameEdit.width + 4 + height: 22 + TextInput{ + id: nameEdit + anchors.centerIn: parent + text: modelData.name; + color: "#004275" + + onActiveFocusChanged: { + if(!activeFocus){ + //todo other way? + modelData.setName(nameEdit.text); + } + } + onAccepted: { + modelData.setName(nameEdit.text); + } + } + } + Text{ + anchors.right: model.left + visible: main.state == "EDIT" + height: 40 + verticalAlignment: Text.AlignVCenter + text: modelData.id + color: "#004275" + width: 50 + } + Text{ + id: model + anchors.right: visibleinlistcheckbox.left + visible: main.state == "EDIT" + height: 40 + verticalAlignment: Text.AlignVCenter + text: modelData.model + color: "#004275" + width: 100 + } + Item{ + id: visibleinlistcheckbox + anchors.right: sensorInfo.left + visible: main.state == "EDIT" + height: 40 + Rectangle{ + anchors.centerIn: parent + height: 10 + width: 10 + color: "white" + Text{ + anchors.centerIn: parent + color: "#004275" + text: modelData.showInList ? "X" : "" + } + MouseArea{ + anchors.fill: parent + onClicked: { + modelData.setShowInList(!modelData.showInList); + } + } + } + width: 100 + } + + Column { + id: sensorInfo + anchors.right: parent.right + width: 250 + SensorValue { + visible: modelData.hasTemperature + text: visible ? modelData.sensorValue(1).value + '°C' : '' + icon: "icon_temp.png" + lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date() + } + SensorValue { + visible: modelData.hasHumidity + text: visible ? modelData.sensorValue(2).value + '%' : '' + icon: "icon_humidity.png" + lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date() + } } } } @@ -55,6 +132,27 @@ Item { anchors.leftMargin: 15 } HeaderTitle { + text: "ID" + anchors.right: modelTitle.left + visible: main.state == "EDIT" + width: 50 + } + HeaderTitle { + id: modelTitle + text: "Model" + anchors.right: visibleinlistTitle.left + visible: main.state == "EDIT" + width: 100 + } + HeaderTitle { + id: visibleinlistTitle + text: "Visible in list" + anchors.right: sensorinformationTitle.left + visible: main.state == "EDIT" + width: 100 + } + HeaderTitle { + id: sensorinformationTitle text: "Sensor information" width: 150 anchors.right: timestampTitle.left @@ -64,12 +162,53 @@ Item { text: "Last updated" width: 100 anchors.right: parent.right + //horizontalAlignment: Text.AlignRight } } Repeater { model: sensorModel delegate: sensorView } + Row{ + spacing: 20 + Rectangle { + width: 50 + height: 20 + Text{ + anchors.centerIn: parent + text: main.state == "VIEW" ? "Edit" : "View" + } + MouseArea{ + anchors.fill: parent + onClicked: { + if(main.state == "VIEW"){ + main.state = "EDIT" + } + else{ + main.state ="VIEW" + } + } + } + } + /* + Rectangle { + //TODO should this button exist at all, or always save? + width: 50 + height: 20 + visible: main.state == "EDIT" + Text{ + anchors.centerIn: parent + text: "Cancel" + } + MouseArea{ + anchors.fill: parent + onClicked: { + main.state ="VIEW" + } + } + } + */ + } anchors.fill: parent } } diff --git a/telldus-gui/Plugins/Sensors/sensor.cpp b/telldus-gui/Plugins/Sensors/sensor.cpp index cb04f2fc..7a56f46f 100644 --- a/telldus-gui/Plugins/Sensors/sensor.cpp +++ b/telldus-gui/Plugins/Sensors/sensor.cpp @@ -1,10 +1,11 @@ #include "sensor.h" #include "sensorvalue.h" #include +#include class Sensor::PrivateData { public: - bool hasTemperature, hasHumidity; + bool hasTemperature, hasHumidity, showInList; int id; QString model, name, protocol; QDateTime lastUpdated; @@ -45,7 +46,10 @@ void Sensor::setModel(const QString &model) { } QString Sensor::name() const { - return QString("%1 %2").arg(this->protocol()).arg(this->id()); //TODO: Remove when name is fully implemented + //return QString("%1 %2").arg(this->protocol()).arg(this->id()); //TODO: Remove when name is fully implemented + if(d->name == ""){ + return ""; + } return d->name; } @@ -88,3 +92,13 @@ void Sensor::setValue(int type, const QString &value, const QDateTime ×tamp emit hasHumidityChanged(); } } + +bool Sensor::showInList() const{ + //TODO showInList and name must be persistent... + return d->showInList; +} + +void Sensor::setShowInList(bool show){ + d->showInList = show; + emit showInListChanged(); +} diff --git a/telldus-gui/Plugins/Sensors/sensor.h b/telldus-gui/Plugins/Sensors/sensor.h index fc70468d..85164246 100644 --- a/telldus-gui/Plugins/Sensors/sensor.h +++ b/telldus-gui/Plugins/Sensors/sensor.h @@ -17,6 +17,8 @@ class Sensor : public QObject Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString protocol READ protocol WRITE setProtocol NOTIFY protocolChanged) + Q_PROPERTY(bool showInList READ showInList NOTIFY showInListChanged) + public: explicit Sensor(QObject *parent = 0); ~Sensor(); @@ -30,15 +32,18 @@ public: void setModel(const QString &model); QString name() const; - void setName(const QString &name); + //void setName(const QString &name); QString protocol() const; void setProtocol(const QString &protocol); bool hasTemperature() const; + bool showInList() const; Q_INVOKABLE SensorValue *sensorValue(int type); Q_INVOKABLE void setValue(int type, const QString &value, const QDateTime ×tamp); + Q_INVOKABLE void setName(const QString &name); + Q_INVOKABLE void setShowInList(bool show); signals: void idChanged(); @@ -47,6 +52,7 @@ signals: void modelChanged(); void nameChanged(); void protocolChanged(); + void showInListChanged(); private: class PrivateData; From 4b37109f279b3517d8d152423aa0b8d6245954b7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Nov 2011 10:33:09 +0100 Subject: [PATCH 1725/2215] Use FIND_PACKAGE() to find QtUiTools instead of just hardcode the path --- telldus-gui/TelldusCenter/CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 7aa29d22..f610ee08 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -64,9 +64,10 @@ ADD_DEFINITIONS( -DVERSION=${DISPLAYED_VERSION} ) SET( telldus-center_TARGET TelldusCenter ) -IF (APPLE) #### Mac OS X #### +IF (APPLE) #### Mac OS X #### + FIND_PACKAGE(Qt4 COMPONENTS QtUiTools REQUIRED) LIST(APPEND telldus-center_LIBRARIES - /usr/lib/libQtUiTools.a + ${QT_QTUITOOLS_LIBRARY} ) INCLUDE_DIRECTORIES( /usr/include/QtUiTools From 24586433d97e643be27678c00acb0807f48897f4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 4 Nov 2011 14:32:22 +0100 Subject: [PATCH 1726/2215] Windows service, 2.1.0a and new changes for possible new version. --- telldus-core/client/CallbackDispatcher.cpp | 3 + telldus-core/client/Client.cpp | 67 ++++++++++++++++--- telldus-core/common/Message.cpp | 61 +++++++++++++++-- telldus-core/common/Message.h | 3 + telldus-core/common/Socket_win.cpp | 9 +++ telldus-core/common/Strings.cpp | 41 ++++++++++++ telldus-core/common/Strings.h | 1 + .../service/ClientCommunicationHandler.cpp | 4 ++ telldus-core/service/EventHandler_win.cpp | 24 ++++--- telldus-core/service/EventUpdateManager.cpp | 7 +- telldus-core/service/ProtocolNexa.cpp | 1 - telldus-core/service/SettingsWinRegistry.cpp | 47 ++++++++----- 12 files changed, 226 insertions(+), 42 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index d167a72d..2447a43e 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -8,6 +8,7 @@ */ #include "CallbackDispatcher.h" +#include "common.h" using namespace TelldusCore; @@ -28,7 +29,9 @@ bool TDDeviceEventDispatcher::done() const { } void TDDeviceEventDispatcher::run() { + char *str = wrapStdString(strData); d->event(deviceId, method, strData.c_str(), d->id, d->context); + doneRunning = true; } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index c93bf37a..3a4c6fdd 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -130,6 +130,7 @@ int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { callback->id = id; callback->context = context; d->deviceEventList.push_back(callback); + //debuglog(id, "deviceeventadded"); return id; } @@ -141,6 +142,7 @@ int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void * callback->id = id; callback->context = context; d->deviceChangeEventList.push_back(callback); + //debuglog(id, "devicechangeeventadded"); return id; } @@ -176,13 +178,24 @@ void Client::run(){ d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service if(!d->eventSocket.isConnected()){ //reconnect didn't succeed, wait a while and try again + //debuglog(0, "Reconnecting"); msleep(2000); continue; } } std::wstring clientMessage = d->eventSocket.read(5000); //testing 5 second timeout + + //int test = 0; + /*if(clientMessage != L""){ + debuglog(88, "Clientmessage nothing after read"); + }*/ while(clientMessage != L""){ + //debuglog(99, TelldusCore::wideToString(clientMessage)); + //test++; + /*if(test > 5){ + debuglog(test, "Test is getting big"); + }*/ //a message arrived std::wstring type = Message::takeString(&clientMessage); if(type == L"TDDeviceChangeEvent"){ @@ -282,16 +295,53 @@ void Client::cleanupCallbacks() { } std::wstring Client::sendToService(const Message &msg) { - Socket s; - s.connect(L"TelldusClient"); - if (!s.isConnected()) { //Connection failed - TelldusCore::Message msg; - msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); - return msg; + + int tries = 0; + std::wstring readData; + //debuglog(3, "PRETEST"); + while(tries < 20){ + //debuglog(3, "PRETESTINNE"); + tries++; + if(tries == 20){ + TelldusCore::Message msg; + msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); + return msg; + } + Socket s; + s.connect(L"TelldusClient"); + if (!s.isConnected()) { //Connection failed + //debuglog(3, "Ett)"); //deviceeventscallbacks verkar sluta fungera vid/med ett sådant här!? njä, bara ngn ggn... + msleep(500); + continue; //retry + } + s.write(msg.data()); + if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) + //debuglog(3, "Två"); + msleep(500); + continue; //retry + } + readData = s.read(5000); //500 + if(readData == L""){ + //debuglog(3, "Empty result (may be ok?)"); + /* + if this is enabled, all "send" will run 20 times... - NO! That was due to too short timeout in s.read, turnOn didn't havee titme otecxeu + if it's NOT enabled, tdGetName will often return empty... + */ + msleep(500); + continue; //TODO cannot be sure it SHOULD be anything... right? + + } + + if (!s.isConnected()) { //Connection failed sometime during operation... + //debuglog(3, "Not connected"); + msleep(500); + continue; //retry + } + break; } - s.write(msg.data()); - return s.read(5000); + //debuglog(3, "POSTTEST"); + return readData; } void Client::stopThread(){ @@ -300,6 +350,7 @@ void Client::stopThread(){ } bool Client::unregisterCallback( int callbackId ) { + //debuglog(callbackId, "unregistering"); DeviceEventList newDEList; { TelldusCore::MutexLocker locker(&d->mutex); diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 56504d9e..f2820021 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -23,21 +23,70 @@ Message::~Message(void) { } void Message::addArgument(const std::wstring &value) { - std::wstringstream st; - st << (int)value.size(); - this->append(st.str()); + //std::wstringstream st; + //st << (int)value.size(); + this->append(TelldusCore::intToWstring(value.size())); //st.str()); this->append(L":"); this->append(value); } void Message::addArgument(int value) { - std::wstringstream st; - st << (int)value; + //std::wstringstream st; + //st << (int)value; this->append(L"i"); - this->append(st.str()); + this->append(TelldusCore::intToWstring(value)); // st.str()); this->append(L"s"); } +/* +void Message::addSpecialArgument(const std::wstring &value){ + int i = 0; + while(i<1000000){ + i++; + + char numstr[21]; // enough to hold all numbers up to 64-bits + //sprintf(numstr, "%d", value.size()); + //this->append(TelldusCore::charToWstring(numstr)); //.str()); + + itoa(value.size(), numstr, 10); + std::string test(numstr); + std::wstring temp(test.length(), L' '); + std::copy(test.begin(), test.end(), temp.begin()); + + this->append(temp); + this->append(L":"); + this->append(value); + + /* + std::wstringstream st; + st << (int)value.size(); + this->append(st.str()); + this->append(L":"); + this->append(value); + + } +} + +void Message::addSpecialArgument(int value){ + int i = 0; + while(i<1000000){ + i++; + /* + //std::wstringstream st; + //st << (int)value; + this->append(L"i"); + //this->append(st.str()); + this->append(L"s"); + + } +} +*/ +/* +void Message::addSpecialArgument(const char *value){ + this->addSpecialArgument(TelldusCore::charToWstring(value)); +} +*/ + void Message::addArgument(const char *value) { this->addArgument(TelldusCore::charToWstring(value)); } diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index cf63251d..4b13123b 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -11,6 +11,9 @@ namespace TelldusCore { ~Message(void); void addArgument(const std::wstring &); + //void addSpecialArgument(const std::wstring &); + //void addSpecialArgument(int); + //void addSpecialArgument(const char *); void addArgument(int); void addArgument(const char *); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index f78b274d..e0cb50a5 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -1,4 +1,5 @@ #include "Socket.h" +#include "common.h" #include #include @@ -102,18 +103,24 @@ std::wstring Socket::read(int timeout){ if(!d->running){ CancelIo(d->hPipe); CloseHandle(d->readEvent); + //debuglog(1, "Not running"); return L""; } if (result == WAIT_TIMEOUT) { CancelIo(d->hPipe); CloseHandle(d->readEvent); + //debuglog(1, "Wait timeout"); return L""; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); if (!fSuccess) { DWORD err = GetLastError(); + //debuglog(result, "This then?"); + //debuglog(1, "Unsuccessful"); + if (err == ERROR_BROKEN_PIPE) { + //debuglog(1, "Broken pipe"); d->connected = false; } buf[0] = 0; @@ -143,6 +150,7 @@ void Socket::write(const std::wstring &msg){ CancelIo(d->hPipe); CloseHandle(writeEvent); d->connected = false; + //debuglog(2, "Wait timeout"); return; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); @@ -150,6 +158,7 @@ void Socket::write(const std::wstring &msg){ if (!fSuccess) { CancelIo(d->hPipe); d->connected = false; + //debuglog(2, "Unsuccessful"); return; } } diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 83c1384f..cb7e7409 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -91,17 +91,58 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { } std::wstring TelldusCore::intToWstring(int value) { +#ifdef _WINDOWS + //no stream used +//TODO! Make effective and safe... + wchar_t numstr[21]; // enough to hold all numbers up to 64-bits + _itow_s(value, numstr, sizeof(numstr), 10); + std::wstring newstring(numstr); + return newstring; + //return TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp(stdstring.length(), L' '); + //std::copy(stdstring.begin(), stdstring.end(), temp.begin()); + //return temp; +#else std::wstringstream st; st << value; return st.str(); +#endif } std::string TelldusCore::intToString(int value) { +//Not sure if this is neecssary (for ordinary stringstream that is) +#ifdef _WINDOWS + char numstr[21]; // enough to hold all numbers up to 64-bits + _itoa_s(value, numstr, sizeof(numstr), 10); + std::string stdstring(numstr); + return stdstring; +#else std::stringstream st; st << value; return st.str(); +#endif } +/* +std::wstring TelldusCore::intToWStringSafe(int value){ + #ifdef _WINDOWS + //no stream used + //TODO! Make effective and safe... + char numstr[21]; // enough to hold all numbers up to 64-bits + itoa(value, numstr, 10); + std::string stdstring(numstr); + return TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp(stdstring.length(), L' '); + //std::copy(stdstring.begin(), stdstring.end(), temp.begin()); + //return temp; + #else + return TelldusCore::intToWString(value); + #endif +} +*/ + int TelldusCore::wideToInteger(const std::wstring &input){ std::wstringstream inputstream; inputstream << input; diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index aca16060..e972d45c 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -10,6 +10,7 @@ namespace TelldusCore { bool comparei(std::wstring stringA, std::wstring stringB); std::wstring intToWstring(int value); + //std::wstring intToWStringSafe(int value); std::string intToString(int value); std::string wideToString(const std::wstring &input); diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 7f84da27..8946017e 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -81,6 +81,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0); } else if (function == L"tdBell") { + //TelldusCore::Message msg2; + //msg2.addSpecialArgument(18); + //msg2.addSpecialArgument("testgrej"); + int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0); diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index 730b5b40..d138cb85 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -51,15 +51,19 @@ void EventHandler::signal(Event *) { } bool EventHandler::waitForAny() { - int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, INFINITE); - - TelldusCore::MutexLocker locker(&d->mutex); - if (result == WAIT_TIMEOUT) { - return false; + + while(1){ + int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000); //FALSE, INFINITE); + //TODO KANSE ÄNDRA HÄR... Svårt att se effekten säkert, men lite nytta verkade det göra... + if (result == WAIT_TIMEOUT) { + //return false; + continue; + } + TelldusCore::MutexLocker locker(&d->mutex); + int eventIndex = result - WAIT_OBJECT_0; + if (eventIndex >= d->eventCount) { + return false; + } + return true; } - int eventIndex = result - WAIT_OBJECT_0; - if (eventIndex >= d->eventCount) { - return false; - } - return true; } diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index b1175ff6..6200eddd 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -4,6 +4,7 @@ #include "EventHandler.h" #include "Message.h" #include "Socket.h" +//#include "common.h" //debug #include #include @@ -73,10 +74,10 @@ void EventUpdateManager::run(){ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ + int connected = 0; for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();){ - if((*it)->isConnected()){ - + connected++; TelldusCore::Message msg; if(data->messageType == L"TDDeviceEvent"){ @@ -116,4 +117,6 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ it = d->clients.erase(it); } } + //debuglog(connected, " - number of clients"); + //debuglog(temp2, " - number of clients total"); } diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 2b29ced5..993f3ff2 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -3,7 +3,6 @@ #include #include "TellStick.h" #include "Strings.h" -#include "common.h" int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; //TODO, always removing first turnon now, make more flexible (waveman too) diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 939f6152..0ca1fcec 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -1,10 +1,12 @@ #include "Settings.h" +#include "Strings.h" #include #include #include #include #include #include +#include "common.h" #include "../client/telldus-core.h" @@ -93,9 +95,11 @@ int Settings::addDevice() { DWORD dwDisp; intDeviceId = getNextDeviceId(); - std::wostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::wstring strCompleteRegPath = ssRegPath.str(); + //std::wostringstream ssRegPath; + //ssRegPath << d->strRegPathDevice << intDeviceId; + //std::wstring strCompleteRegPath = ssRegPath.str(); + std::wstring strCompleteRegPath = d->strRegPathDevice; + strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) { //fail @@ -143,9 +147,11 @@ int Settings::getNextDeviceId() const { int Settings::removeDevice(int intDeviceId) { TelldusCore::MutexLocker locker(&mutex); - std::wostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::wstring strCompleteRegPath = ssRegPath.str(); + //std::wostringstream ssRegPath; + //ssRegPath << d->strRegPathDevice << intDeviceId; + //std::wstring strCompleteRegPath = ssRegPath.str(); + std::wstring strCompleteRegPath = d->strRegPathDevice; + strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); @@ -161,9 +167,11 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam std::wstring strReturn; HKEY hk; - std::wostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::wstring strCompleteRegPath = ssRegPath.str(); + //std::wostringstream ssRegPath; + //ssRegPath << d->strRegPathDevice << intDeviceId; + //std::wstring strCompleteRegPath = ssRegPath.str(); + std::wstring strCompleteRegPath = d->strRegPathDevice; + strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ @@ -191,9 +199,16 @@ int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const HKEY hk; int ret = TELLSTICK_SUCCESS; - std::wostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::wstring strCompleteRegPath = ssRegPath.str(); + //std::wostringstream ssRegPath; + //ssRegPath << d->strRegPathDevice << intDeviceId; + //std::wstring strCompleteRegPath = ssRegPath.str(); + //debuglog(intDeviceId, "Device id"); + std::wstring bla = TelldusCore::intToWstring(intDeviceId); + //debuglog(888, TelldusCore::wideToString(bla)); + //debuglog(555, TelldusCore::wideToString(d->strRegPathDevice)); + std::wstring strCompleteRegPath = d->strRegPathDevice; + strCompleteRegPath.append(bla); + //debuglog(999, TelldusCore::wideToString(strCompleteRegPath)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS){ @@ -223,9 +238,11 @@ int Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value int intReturn = TELLSTICK_ERROR_UNKNOWN; HKEY hk; - std::wostringstream ssRegPath; - ssRegPath << d->strRegPathDevice << intDeviceId; - std::wstring strCompleteRegPath = ssRegPath.str(); + //std::wostringstream ssRegPath; + //ssRegPath << d->strRegPathDevice << intDeviceId; + //std::wstring strCompleteRegPath = ssRegPath.str(); + std::wstring strCompleteRegPath = d->strRegPathDevice; + strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS) { DWORD dwVal = value; From 1bee70be2c65e320c287a417276e2f41bea134ca Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Nov 2011 10:58:06 +0100 Subject: [PATCH 1727/2215] Move rfcmd out from telldus-core --- rfcmd/CMakeLists.txt | 88 +++++++ rfcmd/COPYING | 340 ++++++++++++++++++++++++++ rfcmd/Makefile | 22 ++ rfcmd/build.sh | 6 + rfcmd/find_telldus.c | 42 ++++ rfcmd/ftdi.c | 110 +++++++++ rfcmd/rfcmd.c | 566 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1174 insertions(+) create mode 100644 rfcmd/CMakeLists.txt create mode 100644 rfcmd/COPYING create mode 100644 rfcmd/Makefile create mode 100644 rfcmd/build.sh create mode 100644 rfcmd/find_telldus.c create mode 100644 rfcmd/ftdi.c create mode 100644 rfcmd/rfcmd.c diff --git a/rfcmd/CMakeLists.txt b/rfcmd/CMakeLists.txt new file mode 100644 index 00000000..af4b4484 --- /dev/null +++ b/rfcmd/CMakeLists.txt @@ -0,0 +1,88 @@ +cmake_minimum_required(VERSION 2.4) + +INCLUDE_DIRECTORIES( + /usr/src/linux/include +) + +#### Project: rfcmd #### + +PROJECT(rfcmd) + +SET(rfcmd_DESCRIPTION + "Sends RF remote commands through a Telldus TellStick" +) + +SET(rfcmd_SRCS + rfcmd.c +) + +IF(${RFCMD_DEBUG}) + ADD_DEFINITIONS( -DRFCMD_DEBUG ) +ENDIF(${RFCMD_DEBUG}) + +IF (BUILD_RFCMD_WITH_LIBFTDI) + ADD_DEFINITIONS( -DLIBFTDI ) + + SET(rfcmd_SRCS + ${rfcmd_SRCS} + ftdi.c + ) +ENDIF (BUILD_RFCMD_WITH_LIBFTDI) +ADD_EXECUTABLE(rfcmd + ${rfcmd_SRCS} +) + +IF (BUILD_RFCMD_WITH_SEMAPHORES) + FIND_LIBRARY(SEM_LIBRARY rt) + TARGET_LINK_LIBRARIES(rfcmd + ${SEM_LIBRARY} + ) +ELSE (BUILD_RFCMD_WITH_SEMAPHORES) + ADD_DEFINITIONS( -DNO_SEMAPHORES ) +ENDIF (BUILD_RFCMD_WITH_SEMAPHORES) + + + +IF (BUILD_RFCMD_WITH_LIBFTDI) + FIND_LIBRARY(FTDI_LIBRARY ftdi) + + TARGET_LINK_LIBRARIES(rfcmd + ${FTDI_LIBRARY} + ) +ENDIF (BUILD_RFCMD_WITH_LIBFTDI) + +INSTALL(TARGETS rfcmd RUNTIME DESTINATION bin) + +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET rfcmd + POST_BUILD + COMMAND help2man -n ${rfcmd_DESCRIPTION} ./rfcmd > rfcmd.1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file rfcmd.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/rfcmd.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + +#### Project: find_telldus #### + +IF (BUILD_RFCMD_WITH_LIBFTDI) + PROJECT(find_telldus) + + SET(find_telldus_SRCS + find_telldus.c + ) + + ADD_EXECUTABLE(find_telldus + ${find_telldus_SRCS} + ) + + TARGET_LINK_LIBRARIES(find_telldus + ${FTDI_LIBRARY} + ) + + INSTALL(TARGETS find_telldus RUNTIME DESTINATION bin) + +ENDIF (BUILD_RFCMD_WITH_LIBFTDI) diff --git a/rfcmd/COPYING b/rfcmd/COPYING new file mode 100644 index 00000000..60549be5 --- /dev/null +++ b/rfcmd/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/rfcmd/Makefile b/rfcmd/Makefile new file mode 100644 index 00000000..4836075a --- /dev/null +++ b/rfcmd/Makefile @@ -0,0 +1,22 @@ + +SRCS= rfcmd.c ftdi.c +CFLAGS=-O2 -Wall -I/usr/local/include +LFLAGS= -L/usr/local/lib -R/usr/local/lib +#linux:LFLAGS=-Wl,-rpath,/usr/local/lib +LIBS= -lftdi -lusb +PROG= rfcmd +FT= find_telldus +OBJS= $(SRCS:.c=.o) +CC= gcc + +all: $(PROG) $(FT) + +$(PROG): $(OBJS) + $(CC) $(CFLAGS) $(OBJS) -o $(PROG) $(LFLAGS) $(LIBS) + +rfcmd.o: rfcmd.c + +ftdi.o: ftdi.c + +$(FT): $(FT).c + $(CC) $(CFLAGS) -o $@ $(FT).c $(LFLAGS) $(LIBS) diff --git a/rfcmd/build.sh b/rfcmd/build.sh new file mode 100644 index 00000000..fb5100b9 --- /dev/null +++ b/rfcmd/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh +set -e +make clean || { echo "Warning: make clean failed"; } +make || { echo "make failed"; exit 1; } +make install || { echo "make install failed"; exit 1; } +echo rfcmd built and installed! diff --git a/rfcmd/find_telldus.c b/rfcmd/find_telldus.c new file mode 100644 index 00000000..5c44915e --- /dev/null +++ b/rfcmd/find_telldus.c @@ -0,0 +1,42 @@ +/* find_all.c + + Example for ftdi_usb_find_all() + + This program is distributed under the GPL, version 2 +*/ + +#include +#include + +int main(int argc, char **argv) +{ + int ret, i; + struct ftdi_context ftdic; + struct ftdi_device_list *devlist, *curdev; + char manufacturer[128], description[128]; + + ftdi_init(&ftdic); + + if((ret = ftdi_usb_find_all(&ftdic, &devlist, 0x1781, 0x0c30)) < 0) { + fprintf(stderr, "ftdi_usb_find_all failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + + printf("Number of FTDI devices (telldus) found: %d\n", ret); + + i = 0; + for (curdev = devlist; curdev != NULL; i++) { + printf("Checking device: %d\n", i); + if((ret = ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) { + fprintf(stderr, "ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic)); + return EXIT_FAILURE; + } + printf("Manufacturer: %s, Description: %s\n\n", manufacturer, description); + curdev = curdev->next; + } + + ftdi_list_free(&devlist); + ftdi_deinit(&ftdic); + + return EXIT_SUCCESS; +} diff --git a/rfcmd/ftdi.c b/rfcmd/ftdi.c new file mode 100644 index 00000000..c229f2cb --- /dev/null +++ b/rfcmd/ftdi.c @@ -0,0 +1,110 @@ +/* + * TellStick libftdi libusb version + * tested with 0.15 : http://www.intra2net.com/en/developer/libftdi + */ + +#include +#include +#include +#include + +#define BAUD 4800 + +void ftdiCleanup(struct ftdi_context *ctx) { + ftdi_usb_close( ctx ); + ftdi_deinit( ctx ); +} + +/* + * use libftdi and libusb to send command + * no kernel driver needed + */ +int usbWriteFtdi(char *cmdstr) +{ + struct ftdi_context ctx; + int device=0x0c30, vendor=0x1781; + int retrycnt; + int retval = 0; + + if (ftdi_init( &ctx )) { + char *err = ftdi_get_error_string(&ctx); + fprintf(stderr, "usb - init error: %s\n", err); + return 1; + } + + retval = ftdi_usb_open(&ctx, vendor, device); + if (retval) { + char *err = ftdi_get_error_string(&ctx); + // FreeBSD says -3 when another rfcmd is running... + // Same on other systems? + if(retval == -3) { + fprintf(stderr, "usb - open error: %s. Is it busy?\n", err); + } else { + fprintf(stderr, "usb - open error: %s\n", err); + } + + ftdi_deinit( &ctx ); + return 2; + } + + if (ftdi_usb_reset( &ctx )) { + char *err = ftdi_get_error_string(&ctx); + fprintf(stderr, "usb - reset error: %s\n", err); + retval = 3; + ftdiCleanup(&ctx); + return retval; + } + + if (ftdi_disable_bitbang( &ctx ) || ftdi_set_baudrate(&ctx, BAUD)) { + char *err = ftdi_get_error_string(&ctx); + fprintf(stderr, "usb - init failed: %s\n", err); + ftdiCleanup(&ctx); + return 4; + } + + retval = ftdi_write_data( &ctx, cmdstr, strlen(cmdstr) ); + if (retval < 0) { + char *err = ftdi_get_error_string(&ctx); + fprintf(stderr, "usb - write failed: %s\n", err); + ftdiCleanup(&ctx); + return 5; + } else if(retval != strlen(cmdstr)) { + fprintf(stderr, "usb - warning: %d bytes written instead of %d\n", + retval, (int)strlen(cmdstr)); + } + + /** + * Wait for Tellstick to be done with cmd, read back until we've received + * a \n indicating end of response. + * Wait max 5000 * 1000uS. + * XXX: Can the tellstick report errors? + */ + retval = 0; + retrycnt = 5000; + while (retrycnt--) { + unsigned char inb; + int bytes; + + bytes = ftdi_read_data(&ctx, &inb, 1); + if (bytes == 0) { + usleep(1000); + } else if (bytes > 0) { + // Done when newline is received + if(inb == '\n') { + ftdiCleanup(&ctx); + return retval; + } + } else { + char *err = ftdi_get_error_string(&ctx); + fprintf(stderr, "usb - read error: %s\n", err); + ftdiCleanup(&ctx); + return 6; + } + } + + // if we get here we failed to readback + fprintf(stderr, "usb - warning: never got newline response, giving up on wait\n"); + return retval; +} + + diff --git a/rfcmd/rfcmd.c b/rfcmd/rfcmd.c new file mode 100644 index 00000000..608b7d67 --- /dev/null +++ b/rfcmd/rfcmd.c @@ -0,0 +1,566 @@ +/**************************************************************************** + ** rfcmd.c *********************************************************** + **************************************************************************** + * + * rfcmd - utility to control NEXA and other RF remote receivers through a TellStick + * USB interface + * + * Copyright (C) 2007 Tord Andersson + * + * License: GPL v. 2 + * + * Authors: + * Tord Andersson + * Micke Prag + * Gudmund Berggren + * + * Tapani Rintala / userspace libusb / libftdi - version 02-2009 + */ + +/******************************************************************************* + * Modifications from rfcmd.c ver 0.2 done by Gudmund + * Added support for IKEA + * Note: + * 1. System code + * 2. Level 0 == Off (For dimmers and non dimmers) + * Level 1== 10%. (for dimmers) + * .... + * Level 9 == 90 % (for dimmers) + * Level 10 == 100 % (or ON for non dimmers) + * 3. Command line syntax: + * /usr/local/bin/rfcmd /dev/ttyUSB0 IKEA 0 1 10 1" + * Arg 1: device + * Arg 2: Protocoll + * Arg 3: System code + * Arg 4: Device code + * Arg 5: Level (0=off, 1 = 10%, 2=20%,...9=90%, 10=100%) + * Arg 6: DimStyle (0=instant change, 1=gradually change) + ******************************************************************************/ + +/******************************************************************************* + * Modifications to rfcmd.c ver 2.1.0 done by Tord Andersson + * Introduced semaphore protection to avoid problems with simultaneous port + * access from several processes (typically cron jobs). Note! Need rt lib. + ******************************************************************************/ + +/******************************************************************************* + * Modifications from rfcmd.c ver 2.1.0 done by Leo + * Added support for RISINGSUN + * Note: + * 1. Command line syntax: + * /usr/local/bin/rfcmd /dev/ttyUSB0 RISINGSUN 4 1 0" + * Arg 1: device + * Arg 2: protocol + * Arg 3: code + * Arg 4: device number + * Arg 5: Level (0=off, 1 = on) + ******************************************************************************/ + +/******************************************************************************* + * Modifications from rfcmd ver 2.1.1 done by Johan Ström + * Default disabled semaphores for FreeBSD. + * Added status readback in ftdi.c, instead of wasting time in sleep. + * + * FreeBSD does not have support in the GENERIC kernel semaphore. + * To enable usage of them, you'll have have the following option in your + * kernel configuration: + * + * options P1003_1B_SEMAPHORES + * + * However, on FreeBSD only libftdi seems to be working (at least on my system), + * since the device is not identified as a ucom device. And as we're accessing it + * via libftdi, libftdi makes sure simultaneous access is impossible. + ******************************************************************************/ + + +#include +#include +#include +#include +#include +#include + +#ifndef NO_SEMAPHORES +#include +#endif + +#define PROG_NAME "rfcmd" +#define PROG_VERSION "2.1.1" +/* #define RFCMD_DEBUG */ + +/* Local function declarations */ +int createNexaString(const char * pHouseStr, const char * pChannelStr, + const char * pOn_offStr, char * pTxStr, int waveman); +int createSartanoString(const char * pChannelStr, const char * pOn_offStr, + char * pTxStr); +int createIkeaString(const char * pSystemStr, const char * pChannelStr, + const char * pLevelStr, const char *pDimStyle, + char * pStrReturn); +int createRisingSunString(const char * pCodeStr, const char* pUnitStr, const char * pOn_offStr, + char * pTxStr); + +void printUsage(void); +void printVersion(void); + +#ifdef LIBFTDI +int usbWriteFtdi(char *cmdstr); +#endif + +int main( int argc, char **argv ) +{ + struct termios tio; + int fd = -1; +#ifndef NO_SEMAPHORES + sem_t * portMutex; + char SEM_NAME[]= "RFCMD_SEM"; /* Semaphore for multiple access ctrl */ +#endif + + + char txStr[100]; + + if( (argc == 6) && (strcmp(*(argv+2), "NEXA") == 0)) { + if (createNexaString(*(argv+3), *(argv+4), *(argv+5), txStr, 0) == 0) { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ + } else if( (argc == 6) && (strcmp(*(argv+2), "WAVEMAN") == 0)) { + if (createNexaString(*(argv+3),*(argv+4), *(argv+5), txStr, 1) == 0) { + printUsage(); + exit(1); + } + } else if( (argc == 5) && (strcmp(*(argv+2), "SARTANO") == 0)) { + if (createSartanoString(*(argv+3), *(argv+4), txStr) == 0) { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ + } else if ( (argc == 7) && (strcmp(*(argv+2),"IKEA")==0) ) { + // System, Channel, Level, DimStyle, TXString + if ( createIkeaString(*(argv+3), *(argv+4), *(argv+5), *(argv+6),txStr) == 0 ) { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ + } else if ( (argc == 6) && (strcmp(*(argv+2),"RISINGSUN")==0) ) { + // Code, Unit, Power + if ( createRisingSunString(*(argv+3), *(argv+4), *(argv+5), txStr) == 0 ) { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ + } else if ( (argc >= 2) && (strcmp(*(argv+1),"--version")==0) ) { + printVersion(); + exit(1); + } else { /* protocol or parameters not recognized */ + printUsage(); + exit(1); + } + +#ifdef RFCMD_DEBUG + printf("txStr: %s\n", txStr); + +#endif + + if(strlen(txStr) > 0) { +#ifndef NO_SEMAPHORES + /* create the semaphore - will reuse an existing one if it exists */ + portMutex = sem_open(SEM_NAME,O_CREAT,0644,1); + if( portMutex == SEM_FAILED) { + fprintf(stderr, "%s - Error creating port semaphore\n", PROG_NAME); + perror("Semaphore open error"); + sem_unlink(SEM_NAME); + exit(1); + } + + /* lock semaphore to protect port from multiple access */ + if(sem_wait(portMutex) != 0) { + fprintf(stderr, "%s - Error aquiring port semaphore\n", PROG_NAME); + sem_unlink(SEM_NAME); + sem_close(portMutex); + exit(1); + } +#endif + + + if (strcmp(*(argv+1), "LIBUSB") != 0) { + if( 0 > ( fd = open( *(argv+1), O_RDWR ) ) ) { +#ifdef __FreeBSD__ + fprintf(stderr, "%s - Error opening %s; You're on a FreeBSD system, you should probably use LIBUSB.\n", PROG_NAME, *(argv+1)); +#else + fprintf(stderr, "%s - Error opening %s\n", PROG_NAME, *(argv+1)); +#endif +#ifndef NO_SEMAPHORES + if(sem_post(portMutex) != 0) { + fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME); + } + sem_unlink(SEM_NAME); + sem_close(portMutex); +#endif + exit(1); + } + + /* adjust serial port parameters */ + bzero(&tio, sizeof(tio)); /* clear struct for new port settings */ + tio.c_cflag = B4800 | CS8 | CLOCAL | CREAD; /* CREAD not used yet */ + tio.c_iflag = IGNPAR; + tio.c_oflag = 0; + tio.c_ispeed = 4800; + tio.c_ospeed = 4800; + tcflush(fd, TCIFLUSH); + tcsetattr(fd,TCSANOW,&tio); + + write(fd, txStr, strlen(txStr)); + + sleep(1); /* one second sleep to avoid device 'choking' */ + close(fd); /* Modified : Close fd to make a clean exit */ + } else { +#ifdef LIBFTDI + usbWriteFtdi( txStr ); +#else + fprintf(stderr, "%s - Support for libftdi is not compiled in, please recompile rfcmd with support for libftdi\n", PROG_NAME); +#endif + } +#ifndef NO_SEMAPHORES + /* Unlock semaphore */ + if (sem_post(portMutex) != 0) { + fprintf(stderr, "%s - Error releasing port semaphore\n", PROG_NAME); + sem_unlink(SEM_NAME); + sem_close(portMutex); + exit(1); + } else { + sem_unlink(SEM_NAME); + sem_close(portMutex); + } +#endif + } + exit(0); +} + + +int createNexaString(const char * pHouseStr, const char * pChannelStr, + const char * pOn_offStr, char * pTxStr, int waveman) +{ + * pTxStr = '\0'; /* Make sure tx string is empty */ + int houseCode; + int channelCode; + int on_offCode; + int txCode = 0; + const int unknownCode = 0x6; + int bit; + int bitmask = 0x0001; + + houseCode = (int)((* pHouseStr) - 65); /* House 'A'..'P' */ + channelCode = atoi(pChannelStr) - 1; /* Channel 1..16 */ + on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ + +#ifdef RFCMD_DEBUG + printf("House: %d, channel: %d, on_off: %d\n", houseCode, channelCode, on_offCode); +#endif + + /* check converted parameters for validity */ + if((houseCode < 0) || (houseCode > 15) || // House 'A'..'P' + (channelCode < 0) || (channelCode > 15) || + (on_offCode < 0) || (on_offCode > 1)) + { + + } else { + /* b0..b11 txCode where 'X' will be represented by 1 for simplicity. + b0 will be sent first */ + txCode = houseCode; + txCode |= (channelCode << 4); + if (waveman && on_offCode == 0) { + } else { + txCode |= (unknownCode << 8); + txCode |= (on_offCode << 11); + } + + /* convert to send cmd string */ + strcat(pTxStr,"S"); + for(bit=0;bit<12;bit++) + { + if((bitmask & txCode) == 0) { + /* bit timing might need further refinement */ + strcat(pTxStr," ` `"); /* 320 us high, 960 us low, 320 us high, 960 us low */ + /* strcat(pTxStr,"$k$k"); *//* 360 us high, 1070 us low, 360 us high, 1070 us low */ + } else { /* add 'X' (floating bit) */ + strcat(pTxStr," `` "); /* 320 us high, 960 us low, 960 us high, 320 us low */ + /*strcat(pTxStr,"$kk$"); *//* 360 us high, 1070 us low, 1070 us high, 360 us low */ + } + bitmask = bitmask<<1; + } + /* add stop/sync bit and command termination char '+'*/ + strcat(pTxStr," }+"); + /* strcat(pTxStr,"$}+"); */ + } + +#ifdef RFCMD_DEBUG + printf("txCode: %04X\n", txCode); +#endif + + return strlen(pTxStr); +} + +int createSartanoString(const char * pChannelStr, const char * pOn_offStr, + char * pTxStr) +{ + * pTxStr = '\0'; /* Make sure tx string is empty */ + int on_offCode; + int bit; + + on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ + +#ifdef RFCMD_DEBUG + printf("Channel: %s, on_off: %d\n", pChannelStr, on_offCode); +#endif + + /* check converted parameters for validity */ + if((strlen(pChannelStr) != 10) || + (on_offCode < 0) || (on_offCode > 1)) { + } else { + strcat(pTxStr,"S"); + for(bit=0;bit<=9;bit++) + { + if(strncmp(pChannelStr+bit, "1", 1) == 0) { //If it is a "1" + strcat(pTxStr,"$k$k"); + } else { + strcat(pTxStr,"$kk$"); + } + } + if (on_offCode >= 1) + strcat(pTxStr,"$k$k$kk$"); //the "turn on"-code + else + strcat(pTxStr,"$kk$$k$k"); //the "turn off"-code + + /* add stop/sync bit and command termination char '+'*/ + strcat(pTxStr,"$k+"); + } + + return strlen(pTxStr); +} + +int createIkeaString( const char * pSystemStr, const char * pChannelStr, const char * pLevelStr, const char *pDimStyle, char * pStrReturn) +{ + *pStrReturn = '\0'; /* Make sure tx string is empty */ + + const char STARTCODE[] = "STTTTTTª"; + const char TT[] = "TT"; + const char A[] = "ª"; + int systemCode = atoi(pSystemStr) - 1; /* System 1..16 */ + int channelCode = atoi(pChannelStr); /* Channel 1..10 */ + int Level = atoi(pLevelStr); /* off,10,20,..,90,on */ + int DimStyle = atoi(pDimStyle); + int intCode = 0; + int checksum1 = 0; + int checksum2 = 0; + int intFade ; + int i ; + int rawChannelCode = 0; + + /* check converted parameters for validity */ + if ( (channelCode <= 0) || (channelCode > 10) || + (systemCode < 0) || (systemCode > 15) || + (Level < 0) || (Level > 10) || + (DimStyle < 0) || (DimStyle > 1)) + { + return 0; + } + + if (channelCode == 10) { + channelCode = 0; + } + rawChannelCode = (1<<(9-channelCode)); + + strcat(pStrReturn, STARTCODE ) ; //Startcode, always like this; + intCode = (systemCode << 10) | rawChannelCode; + + for ( i = 13; i >= 0; --i) { + if ((intCode>>i) & 1) { + strcat(pStrReturn, TT ); + if (i % 2 == 0) { + checksum2++; + } else { + checksum1++; + } + } else { + strcat(pStrReturn,A); + } + } + + if (checksum1 %2 == 0) { + strcat(pStrReturn, TT ); + } else { + strcat(pStrReturn, A) ; //1st checksum + } + + if (checksum2 %2 == 0) { + strcat(pStrReturn, TT ); + } else { + strcat(pStrReturn, A ) ; //2nd checksum + } + + if (DimStyle == 1) { + intFade = 11 << 4; //Smooth + } else { + intFade = 1 << 4; //Instant + } + + switch ( Level ) + { + case 0 : + intCode = (10 | intFade) ; //Concat level and fade + break; + case 1 : + intCode = (1 | intFade) ; //Concat level and fade + break; + case 2 : + intCode = (2 | intFade) ; //Concat level and fade + break; + case 3 : + intCode = (3 | intFade) ; //Concat level and fade + break; + case 4 : + intCode = (4 | intFade) ; //Concat level and fade + break; + case 5 : + intCode = (5 | intFade) ; //Concat level and fade + break; + case 6 : + intCode = (6 | intFade) ; //Concat level and fade + break; + case 7 : + intCode = (7 | intFade) ; //Concat level and fade + break; + case 8 : + intCode = (8 | intFade) ; //Concat level and fade + break; + case 9 : + intCode = (9 | intFade) ; //Concat level and fade + break; + case 10 : + default : + intCode = (0 | intFade) ; //Concat level and fade + break; + } + + checksum1 = 0; + checksum2 = 0; + + for (i = 0; i < 6; ++i) { + if ((intCode>>i) & 1) { + strcat(pStrReturn, TT); + + if (i % 2 == 0) { + checksum1++; + } else { + checksum2++; + } + } else { + strcat(pStrReturn, A ); + } + } + + if (checksum1 %2 == 0) { + strcat(pStrReturn, TT); + } else { + strcat(pStrReturn, A ) ; //2nd checksum + } + + if (checksum2 %2 == 0) { + strcat(pStrReturn, TT ); + } else { + strcat(pStrReturn, A ) ; //2nd checksum + } + + strcat(pStrReturn, "+"); + + return strlen(pStrReturn); +} + +int createRisingSunString(const char * pCodeStr, const char * pUnitStr, const char * pOn_offStr, + char * pTxStr) +{ + * pTxStr = '\0'; /* Make sure tx string is empty */ + int on_offCode; + int unit; + int code; + int i; + + on_offCode = atoi(pOn_offStr); /* ON/OFF 0..1 */ + code = atoi (pCodeStr); + unit = atoi (pUnitStr); + +#ifdef RFCMD_DEBUG + printf("Code: %s, unit: %s, on_off: %d\n", pCodeStr, pUnitStr, on_offCode); +#endif + + /* check converted parameters for validity */ + if((code < 1) || (code > 4) || + (unit < 1) || (unit > 4) || + (on_offCode < 0) || (on_offCode > 1)) { + } else { + strcat(pTxStr,"S.e"); + for (i = 1; i <= 4; ++i) { + if (i == code) { + strcat (pTxStr, ".e.e"); + } else { + strcat (pTxStr, "e..e"); + } + } + for (i = 1; i <= 4; ++i) { + if (i == unit) { + strcat (pTxStr, ".e.e"); + } else { + strcat (pTxStr, "e..e"); + } + } + + if (on_offCode >= 1) { + strcat(pTxStr,"e..ee..ee..ee..e+"); //the "turn on"-code + } else { + strcat(pTxStr,"e..ee..ee..e.e.e+"); //the "turn off"-code + } + } + + return strlen(pTxStr); +} + + +void printUsage(void) +{ + printf("Usage: rfcmd DEVICE PROTOCOL [PROTOCOL_ARGUMENTS] \n"); + printf("\n"); +#ifdef LIBFTDI + printf("\t DEVICE: /dev/ttyUSB[0..n] | LIBUSB\n" ); +#else + printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); +#endif + printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA, RISINGSUN\n" ); + printf("\n"); + printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n"); + printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" ); + printf("\n"); + printf("\t PROTOCOL ARGUMENTS - SARTANO:\n"); + printf("\t\tCHANNEL: 0000000000..1111111111\n\t\tOFF_ON: 0..1\n" ); + printf("\n"); + printf("\t PROTOCOL ARGUMENTS - IKEA:\n"); + printf("\t\tSYSTEM: 1..16\n\t\tDEVICE: 1..10\n"); + printf("\t\tDIM_LEVEL: 0..10\n\t\tDIM_STYLE: 0..1\n" ); + printf("\n"); + printf("\t PROTOCOL ARGUMENTS - RISINGSUN:\n"); + printf("\t\tCODE: 1..4\n\t\tDEVICE: 1..4\n"); + printf("\t\tOFF_ON: 0..1\n" ); + printf("\n"); + printf("Report bugs to \n"); +} + +void printVersion(void) { + printf("%s v%s\n", PROG_NAME, PROG_VERSION); + printf("\n"); + printf("Copyright (C) Tord Andersson 2007\n"); + printf("\n"); + printf("Written by:\n"); + printf("Tord Andersson, Micke Prag, Gudmund Berggren, Tapani Rintala\n"); + printf("and Johan Ström\n"); +} + From 00cb9d9057700b8f3254f29434dd3c3eafa73a3c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Nov 2011 12:01:41 +0100 Subject: [PATCH 1728/2215] Move project TellStick.NET into 3rdparty --- .../tellstick.net}/Properties/AssemblyInfo.cs | 0 {tellstick.net => 3rdparty/tellstick.net}/TellStick.NET.csproj | 0 {tellstick.net => 3rdparty/tellstick.net}/TellStick.cs | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {tellstick.net => 3rdparty/tellstick.net}/Properties/AssemblyInfo.cs (100%) rename {tellstick.net => 3rdparty/tellstick.net}/TellStick.NET.csproj (100%) rename {tellstick.net => 3rdparty/tellstick.net}/TellStick.cs (100%) diff --git a/tellstick.net/Properties/AssemblyInfo.cs b/3rdparty/tellstick.net/Properties/AssemblyInfo.cs similarity index 100% rename from tellstick.net/Properties/AssemblyInfo.cs rename to 3rdparty/tellstick.net/Properties/AssemblyInfo.cs diff --git a/tellstick.net/TellStick.NET.csproj b/3rdparty/tellstick.net/TellStick.NET.csproj similarity index 100% rename from tellstick.net/TellStick.NET.csproj rename to 3rdparty/tellstick.net/TellStick.NET.csproj diff --git a/tellstick.net/TellStick.cs b/3rdparty/tellstick.net/TellStick.cs similarity index 100% rename from tellstick.net/TellStick.cs rename to 3rdparty/tellstick.net/TellStick.cs From 37716bdbe22adb7315e243c22c3bdb2d1c057246 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Nov 2011 12:02:16 +0100 Subject: [PATCH 1729/2215] Move project tellstickcontroller into 3rdparty --- {tellstickcontroller => 3rdparty/tellstickcontroller}/License | 0 {tellstickcontroller => 3rdparty/tellstickcontroller}/Readme | 0 .../tellstickcontroller}/examples/power_off_all_lights | 0 .../tellstickcontroller}/examples/power_off_bedroom_mythtv | 0 .../tellstickcontroller}/examples/power_on_all_lights | 0 .../tellstickcontroller}/examples/power_on_bedroom_mythtv | 0 .../tellstickcontroller}/examples/swap_livingroom_tv_mode | 0 .../tellstickcontroller}/examples/tellstickController.conf | 0 .../tellstickcontroller}/tellstick.conf | 0 .../tellstickcontroller}/tellstickController | 0 .../tellstickcontroller}/tellstickController.conf | 0 .../tellstickcontroller}/tellstickControllerRfcmd | 0 .../tellstickcontroller}/tellstickControllerRfcmd.conf | 0 .../tellstickcontroller}/tellstickControllerTdtool | 0 .../tellstickcontroller}/tellstickControllerTdtool.conf | 0 15 files changed, 0 insertions(+), 0 deletions(-) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/License (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/Readme (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/examples/power_off_all_lights (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/examples/power_off_bedroom_mythtv (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/examples/power_on_all_lights (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/examples/power_on_bedroom_mythtv (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/examples/swap_livingroom_tv_mode (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/examples/tellstickController.conf (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/tellstick.conf (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/tellstickController (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/tellstickController.conf (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/tellstickControllerRfcmd (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/tellstickControllerRfcmd.conf (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/tellstickControllerTdtool (100%) rename {tellstickcontroller => 3rdparty/tellstickcontroller}/tellstickControllerTdtool.conf (100%) diff --git a/tellstickcontroller/License b/3rdparty/tellstickcontroller/License similarity index 100% rename from tellstickcontroller/License rename to 3rdparty/tellstickcontroller/License diff --git a/tellstickcontroller/Readme b/3rdparty/tellstickcontroller/Readme similarity index 100% rename from tellstickcontroller/Readme rename to 3rdparty/tellstickcontroller/Readme diff --git a/tellstickcontroller/examples/power_off_all_lights b/3rdparty/tellstickcontroller/examples/power_off_all_lights similarity index 100% rename from tellstickcontroller/examples/power_off_all_lights rename to 3rdparty/tellstickcontroller/examples/power_off_all_lights diff --git a/tellstickcontroller/examples/power_off_bedroom_mythtv b/3rdparty/tellstickcontroller/examples/power_off_bedroom_mythtv similarity index 100% rename from tellstickcontroller/examples/power_off_bedroom_mythtv rename to 3rdparty/tellstickcontroller/examples/power_off_bedroom_mythtv diff --git a/tellstickcontroller/examples/power_on_all_lights b/3rdparty/tellstickcontroller/examples/power_on_all_lights similarity index 100% rename from tellstickcontroller/examples/power_on_all_lights rename to 3rdparty/tellstickcontroller/examples/power_on_all_lights diff --git a/tellstickcontroller/examples/power_on_bedroom_mythtv b/3rdparty/tellstickcontroller/examples/power_on_bedroom_mythtv similarity index 100% rename from tellstickcontroller/examples/power_on_bedroom_mythtv rename to 3rdparty/tellstickcontroller/examples/power_on_bedroom_mythtv diff --git a/tellstickcontroller/examples/swap_livingroom_tv_mode b/3rdparty/tellstickcontroller/examples/swap_livingroom_tv_mode similarity index 100% rename from tellstickcontroller/examples/swap_livingroom_tv_mode rename to 3rdparty/tellstickcontroller/examples/swap_livingroom_tv_mode diff --git a/tellstickcontroller/examples/tellstickController.conf b/3rdparty/tellstickcontroller/examples/tellstickController.conf similarity index 100% rename from tellstickcontroller/examples/tellstickController.conf rename to 3rdparty/tellstickcontroller/examples/tellstickController.conf diff --git a/tellstickcontroller/tellstick.conf b/3rdparty/tellstickcontroller/tellstick.conf similarity index 100% rename from tellstickcontroller/tellstick.conf rename to 3rdparty/tellstickcontroller/tellstick.conf diff --git a/tellstickcontroller/tellstickController b/3rdparty/tellstickcontroller/tellstickController similarity index 100% rename from tellstickcontroller/tellstickController rename to 3rdparty/tellstickcontroller/tellstickController diff --git a/tellstickcontroller/tellstickController.conf b/3rdparty/tellstickcontroller/tellstickController.conf similarity index 100% rename from tellstickcontroller/tellstickController.conf rename to 3rdparty/tellstickcontroller/tellstickController.conf diff --git a/tellstickcontroller/tellstickControllerRfcmd b/3rdparty/tellstickcontroller/tellstickControllerRfcmd similarity index 100% rename from tellstickcontroller/tellstickControllerRfcmd rename to 3rdparty/tellstickcontroller/tellstickControllerRfcmd diff --git a/tellstickcontroller/tellstickControllerRfcmd.conf b/3rdparty/tellstickcontroller/tellstickControllerRfcmd.conf similarity index 100% rename from tellstickcontroller/tellstickControllerRfcmd.conf rename to 3rdparty/tellstickcontroller/tellstickControllerRfcmd.conf diff --git a/tellstickcontroller/tellstickControllerTdtool b/3rdparty/tellstickcontroller/tellstickControllerTdtool similarity index 100% rename from tellstickcontroller/tellstickControllerTdtool rename to 3rdparty/tellstickcontroller/tellstickControllerTdtool diff --git a/tellstickcontroller/tellstickControllerTdtool.conf b/3rdparty/tellstickcontroller/tellstickControllerTdtool.conf similarity index 100% rename from tellstickcontroller/tellstickControllerTdtool.conf rename to 3rdparty/tellstickcontroller/tellstickControllerTdtool.conf From 85d6323e280f901c9b2185d9f0a959e62b401133 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Nov 2011 12:02:40 +0100 Subject: [PATCH 1730/2215] Move project tellstickd into 3rdparty --- {tellstickd => 3rdparty/tellstickd}/LICENSE | 0 {tellstickd => 3rdparty/tellstickd}/README | 0 {tellstickd => 3rdparty/tellstickd}/init_script/tellstickd | 0 {tellstickd => 3rdparty/tellstickd}/init_script/tellstickd.debian | 0 {tellstickd => 3rdparty/tellstickd}/tellstickd | 0 {tellstickd => 3rdparty/tellstickd}/tellstickd.conf | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename {tellstickd => 3rdparty/tellstickd}/LICENSE (100%) rename {tellstickd => 3rdparty/tellstickd}/README (100%) rename {tellstickd => 3rdparty/tellstickd}/init_script/tellstickd (100%) rename {tellstickd => 3rdparty/tellstickd}/init_script/tellstickd.debian (100%) rename {tellstickd => 3rdparty/tellstickd}/tellstickd (100%) rename {tellstickd => 3rdparty/tellstickd}/tellstickd.conf (100%) diff --git a/tellstickd/LICENSE b/3rdparty/tellstickd/LICENSE similarity index 100% rename from tellstickd/LICENSE rename to 3rdparty/tellstickd/LICENSE diff --git a/tellstickd/README b/3rdparty/tellstickd/README similarity index 100% rename from tellstickd/README rename to 3rdparty/tellstickd/README diff --git a/tellstickd/init_script/tellstickd b/3rdparty/tellstickd/init_script/tellstickd similarity index 100% rename from tellstickd/init_script/tellstickd rename to 3rdparty/tellstickd/init_script/tellstickd diff --git a/tellstickd/init_script/tellstickd.debian b/3rdparty/tellstickd/init_script/tellstickd.debian similarity index 100% rename from tellstickd/init_script/tellstickd.debian rename to 3rdparty/tellstickd/init_script/tellstickd.debian diff --git a/tellstickd/tellstickd b/3rdparty/tellstickd/tellstickd similarity index 100% rename from tellstickd/tellstickd rename to 3rdparty/tellstickd/tellstickd diff --git a/tellstickd/tellstickd.conf b/3rdparty/tellstickd/tellstickd.conf similarity index 100% rename from tellstickd/tellstickd.conf rename to 3rdparty/tellstickd/tellstickd.conf From f13c20c69836c88b44bcd8193c4517f148a13350 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 11 Nov 2011 12:03:27 +0100 Subject: [PATCH 1731/2215] Removed way obsolete project systray --- systray/src/SysTray_sv.ts | 41 ---- systray/src/icon.cpp | 216 ---------------------- systray/src/icon.h | 51 ----- systray/src/images/bell.png | Bin 1803 -> 0 bytes systray/src/images/lamp-off.png | Bin 1453 -> 0 bytes systray/src/images/lamp-on.png | Bin 1478 -> 0 bytes systray/src/images/preferences-system.png | Bin 2129 -> 0 bytes systray/src/images/system-log-out.png | Bin 1725 -> 0 bytes systray/src/images/systray.icns | Bin 161575 -> 0 bytes systray/src/images/systray.ico | Bin 13094 -> 0 bytes systray/src/main.cpp | 47 ----- systray/src/resource.qrc | 9 - systray/src/src.pro | 23 --- systray/src/systray.rc | 1 - systray/systray.pro | 4 - 15 files changed, 392 deletions(-) delete mode 100644 systray/src/SysTray_sv.ts delete mode 100644 systray/src/icon.cpp delete mode 100644 systray/src/icon.h delete mode 100644 systray/src/images/bell.png delete mode 100644 systray/src/images/lamp-off.png delete mode 100644 systray/src/images/lamp-on.png delete mode 100644 systray/src/images/preferences-system.png delete mode 100644 systray/src/images/system-log-out.png delete mode 100644 systray/src/images/systray.icns delete mode 100644 systray/src/images/systray.ico delete mode 100644 systray/src/main.cpp delete mode 100644 systray/src/resource.qrc delete mode 100644 systray/src/src.pro delete mode 100644 systray/src/systray.rc delete mode 100644 systray/systray.pro diff --git a/systray/src/SysTray_sv.ts b/systray/src/SysTray_sv.ts deleted file mode 100644 index 5767f648..00000000 --- a/systray/src/SysTray_sv.ts +++ /dev/null @@ -1,41 +0,0 @@ - - - - Icon - - - TellStick - TellStick - - - - &On - &PÃ¥ - - - - O&ff - &Av - - - - &Configure devices - &Konfigurera enheter - - - - &Quit - &Avsluta - - - - Error - Fel - - - - An error occurred while trying to transmit - Ett fel uppstod vid försök att sända - - - diff --git a/systray/src/icon.cpp b/systray/src/icon.cpp deleted file mode 100644 index ae25de6a..00000000 --- a/systray/src/icon.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// C++ Implementation: icon -// -// Description: -// -// -// Author: Micke Prag , (C) 2007 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#include "icon.h" -#include -#include -#include -#include -#include "telldus-core.h" - -Icon::Icon() - : QObject() -{ - this->setMenu(); - connect( &i, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(activated(QSystemTrayIcon::ActivationReason))); - i.setIcon( QIcon(":/images/lamp-on.png") ); - i.setToolTip( tr("TellStick") ); - i.show(); -} - - -Icon::~Icon() -{ -} - - -/** - * @fn Icon::activated( QSystemTrayIcon::ActivationReason reason ) - */ -void Icon::activated( QSystemTrayIcon::ActivationReason reason ) -{ - if (reason == QSystemTrayIcon::DoubleClick) { - if (hasTelldusSetup()) { - configure(); - } - } -} - -/** - * @fn Icon::bell() - */ -void Icon::bell() -{ - QAction *action = (QAction *) sender(); - int retval = tdBell( action->data().toInt() ); - if (retval != TELLSTICK_SUCCESS) { - char *errorString = tdGetErrorString( retval ); - i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical ); - free( errorString ); - } -} - -/** - * @fn Icon::dim() - */ -void Icon::dim() -{ - QAction *action = (QAction *) sender(); - int intId = action->data().toString().section(":", 0, 0).toInt(); - int intLevel = action->data().toString().section(":", 1, 1).toInt(); - //i.showMessage( "", QString::number(intId)); - int retval = tdDim( intId, intLevel ); - if (retval != TELLSTICK_SUCCESS) { - char *errorString = tdGetErrorString( retval ); - i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical ); - free( errorString ); - } -} - -/** - * @fn Icon::on() - */ -void Icon::on() -{ - QAction *action = (QAction *) sender(); - int retval = tdTurnOn( action->data().toInt() ); - if (retval != TELLSTICK_SUCCESS) { - char *errorString = tdGetErrorString( retval ); - i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical ); - free( errorString ); - } -} - -/** - * @fn Icon::off() - */ -void Icon::off() -{ - QAction *action = (QAction *) sender(); - int retval = tdTurnOff( action->data().toInt() ); - if (retval != TELLSTICK_SUCCESS) { - char *errorString = tdGetErrorString( retval ); - i.showMessage( tr("Error"), tr("An error occurred while trying to transmit!\n\n%1").arg(errorString), QSystemTrayIcon::Critical ); - free( errorString ); - } -} - - -/** - * @fn Icon::configure() - */ -void Icon::configure() -{ - QProcess *process = new QProcess(this); - connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(setMenu())); - process->setWorkingDirectory(QCoreApplication::applicationDirPath()); - process->start("TelldusSetup.exe"); -} - - -/** - * @fn Icon::setMenu() - */ -void Icon::setMenu() -{ - menu.clear(); - - int intNum = tdGetNumberOfDevices(); - int index = 0; - while (index < intNum) { - addDevice(index, &menu); - index++; - } - - menu.addSeparator(); - - if (hasTelldusSetup()) { - QAction *configure = menu.addAction(tr("&Configure devices")); - connect(configure, SIGNAL(triggered()), this, SLOT(configure())); - configure->setIcon( QIcon(":/images/preferences-system.png") ); - } - - QAction *quit = menu.addAction(tr("&Quit")); - quit->setIcon( QIcon(":/images/system-log-out.png") ); - connect(quit, SIGNAL(triggered()), qApp, SLOT(quit())); - - i.setContextMenu(&menu); - -} - -void Icon::addDevice( int index, QMenu *menu ) { - int intId = tdGetDeviceId(index); - QMenu *m = menu->addMenu( tdGetName(intId) ); - - int methods = tdMethods(intId); - if (methods & TELLSTICK_TURNON) { - QAction *on = m->addAction(tr("&On")); - on->setIcon(QIcon(":/images/lamp-on.png")); - on->setData( intId ); - connect( on, SIGNAL(triggered()), this, SLOT(on())); - } - - if (methods & TELLSTICK_DIM) { - QAction *dim = m->addAction(tr("90%")); - dim->setData( QString("%1:230").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("80%")); - dim->setData( QString("%1:204").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("70%")); - dim->setData( QString("%1:179").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("60%")); - dim->setData( QString("%1:153").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("50%")); - dim->setData( QString("%1:128").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("40%")); - dim->setData( QString("%1:102").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("30%")); - dim->setData( QString("%1:77").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("20%")); - dim->setData( QString("%1:51").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - - dim = m->addAction(tr("10%")); - dim->setData( QString("%1:25").arg(intId) ); - connect( dim, SIGNAL(triggered()), this, SLOT(dim())); - } - - if (methods & TELLSTICK_TURNON) { - QAction *off = m->addAction(tr("O&ff")); - off->setData( intId ); - off->setIcon(QIcon(":/images/lamp-off.png")); - connect( off, SIGNAL(triggered()), this, SLOT(off())); - } - - if (methods & TELLSTICK_BELL) { - QAction *bell = m->addAction(tr("&Bell")); - bell->setData( intId ); - bell->setIcon(QIcon(":/images/bell.png")); - connect( bell, SIGNAL(triggered()), this, SLOT(bell())); - } -} - -bool Icon::hasTelldusSetup() { - return QFile::exists("TelldusSetup.exe"); -} diff --git a/systray/src/icon.h b/systray/src/icon.h deleted file mode 100644 index 68243342..00000000 --- a/systray/src/icon.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// C++ Interface: icon -// -// Description: -// -// -// Author: Micke Prag , (C) 2007 -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef ICON_H -#define ICON_H - -#include -#include - -/** - @author Micke Prag -*/ -class Icon : public QObject -{ - Q_OBJECT -public: - Icon(); - - ~Icon(); - -protected: - QSystemTrayIcon i; - QMenu menu; - -protected slots: - void activated( QSystemTrayIcon::ActivationReason reason ); - void setMenu(); - -private slots: - void bell(); - void dim(); - void on(); - void off(); - -public slots: - void configure(); - -private: - void addDevice( int index, QMenu *menu ); - static bool hasTelldusSetup(); -}; - -#endif diff --git a/systray/src/images/bell.png b/systray/src/images/bell.png deleted file mode 100644 index 7876598021f853aa10c9502cc3b260d58d2b08e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1803 zcmV+m2lV)fP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iO7w z5F;6!D73u*00xUmL_t(o!_}8tY+S_|$A2?(=A1pd>-DbhiIX^vO-Lb$b0di;D2>{x z&_)RLBGEqeq4fGdQAHI&C8$)WP=&-(U#eDAl`24`O@so1DpF}^5?V+oPSoHyapL&8 zw%3>S?zx}o14gPqN*y~z>PY{G`E=%+pZ?!>Ml*s{j2C{^y}=8tuO`NBG-+}sG5Xkd ze%>G7NDi^m&7Xg2+ktt%`IwQ7f3dU})QY?P#pzI5?iU_>;?E1q%_CO|kXjv23#a3e z?>=$#(6=5t@%b=h z;H%zI-zz^fdS&ux&ux3H>FJ4@l{&Y7@qwRI{wIGy7``c#vZYtk`KgKI@chi+_t$jP z3P~`>+|&rulamBdvnjOhdaJQ{-Q!z!e*X2F+5?uQ9FW`nntXfs!YhZj+-?_&&7HV~ zUh<_|DV91=!8vj9)RX%!pF95QrSoq-c+*Odrl%y(T3g8fYT(=-dUxN|hiyZgb2F2>v-t^JS0hM}vWgG} zX=N};og|zD6nVSG*zj2^^s3LUx&&!@N&t<4Z-2dBAELdzNNQq0AP`6?5Tqp0Bqpt6 zXI(NG@D@f1z1baqKk;hsY8}vND!L=z>`UV@Y+Ha)7$jg2LINoQA3Kx5(iwzQ)aNe~ z1wJN?_O1#*2;nBN`?)Br+afJvDMgwXAYJ;vAS5Uyuyh8?aZ#2g@Mj6UMT|+etQf$U z(*h`jzPzhe9mBC>gfJv=h)L5AHYY_0fu%Ltaj~?EWoL+z7~fkU3jChcIG~I%MZXs8 z4E+flTOkl6QAnCb2n>i6Ar+RBLpxb4+eK;zDJ5~_K^kpX4S-H!*&9b;%gppJQW%Ue z#BoFtCm53;FbJVgRtD|3*qJQaamhLsNfJ@3R@SZtz=Dlq=o(;1V?z|wiKB=# z6&PbMCPu0Z+IF#>EVi3PYa8F2B@P$!Y3zxWIG~I%#raCOt#Y-WJU*cp5cq;9SR{@D z;#iO-F=|1>WjmmM@z%CfkDpx^`BU| zb~-n8(X+LWHJjRT3kxVEkTOE*9BHaqtik+(AyM<3IQbr#d`k;ZT{gh!)4vtQh^)8h zJ{*Qa;?mXkC>9z>$Eu7Ek5evtj9fFU-5Ao=xsgmZk5{WQH9pMv@Brnpi)cII)*anc zDiiG4(su_iv}}M)UE5W4-gzcioW5gt=wC!}o#w7JOroz76O>EeZedNe^W!>Sczn4iQH_ z9UX0-x$oYCr=LIiw@cS`V03JvTG7?P)`oiT)*XE~xe~}M3zbP0E8}(?UwfH?>e| zUq`9ElZK`y9M=T_0*fd}sm;$)ug;tP^COibuMNEX;*o#+qP-<|VeraK`riQLk}SYp zk^>YP3)!B{x2*ZprmmLWb!&>9ZEeM-QgdUjp)qe4iAE)9vYn2e>mmFI#29N)T@o)CC)0DI&AgBNU002ovPDHLkV1nP8WRU;> diff --git a/systray/src/images/lamp-off.png b/systray/src/images/lamp-off.png deleted file mode 100644 index 007a177832a03e7c3cc84a343591e8bf67f79cd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1453 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 TV_b!o00000NkvXXu0mjf;6OQF diff --git a/systray/src/images/systray.icns b/systray/src/images/systray.icns deleted file mode 100644 index 7cfe1d779c1840b63742c515955893069107ec4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 161575 zcmeFa1zeR$_c;Dsy1PV0?C$RF?p(VIQ4~?Z=U%$I8$r6eyHgO5?(S~x|IBkQuKMn~ zyDz%m&*%65?A=u-&YYf^GiQd&gIiBuU<|VJAG}z-3d2ZaWGXY(Ffi2JqCzD(4wI=2 zW1W~Hm4x-dUt<;U*SRqzD%Jyq%yA_uX#k^8Ne-yghf3HmbhbgQejIAUhET$WD9{Ah z%ExgkX#|53HiA>JUR9t}-S;Ki9u+=yMhDBHLRM!&#B)>#{bX-^M~%veJ-oL-iHg{& z>1ZoSSD~_f=ouaz9&C;RzSyzGkPSs4dCxGd!h4WyL~D3o}FPwN$7q8u`sh zL5{#KGv-lirz4Meifs0=fAe?Q<=lEr0EV++Ptt43b4(-&cGrHXswha0lqV`LOB!nO zqTSy^g#(i-=xfdnFyDb8cCou5HKoydre@7zJKJI8|!V?kURS7^)MMunp8)C3(=DCo{g(m;jyFYeCrNV~6J ztyQAF*zn{L7@rM;59x?=oW3Y35g*R1F)EeX^i=Vi`Ky2N~=?yY4s%o^m+`5 zXy9w3*S%@|44-NB(bu#(c6FF&$YZ6~88T3PSe9PJumgio|HAmS&R7O@r>|9vlr-Ak z`{0{;DD*%4rXCITZ~Cz}t<-`wzxQL<5?c;>^}%B_379=qsW`@6jLkBsru(C5>8YLTlr=29;ra0D}f>6uQRr zprkdX1)yIr7=Y!DYg0+>M6nDNdoXn>DPkM|#w$>9E&&^air5fBAPfkxVghX&rio?{ zU>s9}0e}lIj<*0i0ILSA6dhSr75oR%IEXe?M zqY`ESPM6j_)K{FBo{&P+>*NL^jdNnTy@Nx8eeE^TNaZ}3SI@}U*y!lU@KAf6H3-UwdGwDG4a0+j{XOZ% zfPg`wWdtAP7#SHJ9O&=uZjY8imiXL59_55_1AV>S9c_7DU=jwbYLI9g1h9_QrgEQ~ z8dO2q^1+c&ATm7Aj~eUqee}RQLYP}s-^l3r_~_6;Z&zDWeN~E|CDHC$)jJ67BZGb2 z?alSopTayX!CHbEc|CnYqkyHSv$dfrFT&qR6E%w`cJ=i317BUOb!FM{fgaXU&@6z3 zGh`Ae$RJDw>w(E6KlpE=$z@kDWvX+yhprZLiGy&7W>W!th|&TCe(sx|*u;5{I=I z;T_n%lG<9-P>`FIxE=%V;KL+xt7<@3#rZj@@ln3hK&1j0gH~B}U0rqgmrtp2VSXN` zF>nt7Ofs~rwyCMEydX0n+}GJw2DS2G+XBiOIyxFFK7$@ztPRfK;0F8{cEzQ%sjt7K z{8M6xyN$lmT-3~mVfXD*8u|vBN;0B+91NBBlfl}&*m3K?{HB(wyoA7yCdwySXpPH^ z+#*tQvlByIbf0aV%77YqFhMmd_kaKoYps`8_b(G60|OxDMNKnXTXU^<56*0z$3q4I zxG@nqB@GSbH;*svUp0*x2RXSgZ11y|FQ47Jba>-jJ~H7DyqB(DzjEflrbVJm7#oHh z0$XzU@ctd^7EWQq#5oCvU|k>PqrY#8@bp#lG2{@Kh(=_<)!n;x?_eMtg6X8cgBSxN zvj7+!_9QW1do~JT|J6&P{TD5qKYuwMmL|Za6waNSF zOU7ej(_$hvE&BS+z$CP75&Q3Z#kZ?GhB56=?-?2z7%0EV@_h$UBT2@Lz)pcaLtoa? zcCT;27Icr(dePs#yM6><%m2L>N-g5wj>Rwr3T>a802+;B`VN47VxOD<=#u!Ze|qmk z2mRl!^WXKK==-66+?3%P0Mf(n$pf(WxBb}0o*%{!KKo8Wo*(<$H++L0!&vD1`d2KS z;6&eiNH_bxcA>(c@efvFul%mR69Sy?KBUv%YM@{9JMIxATkbaq+C;t^OjLGue+B53 z`;XxuLL`cGh)>h^%+qmgYo~V)D}1M$2~r#r{hhGp{K1DQfM4R61Qec%FO>V zngC|v`gXn(O%G&H(6;^}ssuwkgY{5#u?DIsRzX$9_)f-uscr4=(jG^moy20v0sZCh|G1=T){xll<%&N!9?u_S3>t2>o6 zUPi{^QB8Bui;A_9u~<}jGVDXe8pv2Qs%#kWqhi%K7KJKY-2qgr1jix(AJ!a1#R_mN z96GQv5OdrO$3hX5;&=!Z>!($)jxZ`#jDs2g$~&COI0j)hQR$DMVx2e^h&nQ&s8|w? z1)%Z}l>2bZAC;YAs0{BgTDdNUidEp4A8H?j@*s}+qOwXHmB9j|mCNI(SRIb}p!Pl} z0}N3fhw>OI!z8;`-x_#`N&(aS{%RICigyij{BlpE>gHYfwnM0*F6 zTj}LSC|A+TB~boEFQ)*`KswG3P==kG;Nf6A6&t7XHU_*6)5}9p?xL5Qp`1%E2gO2w ze-xt$KLWz{&=t`NWv~IEl&EL`x=qs-iDMMh*h^Pw81tHnGzy@GW zqU;h5p0kv0sUEOeC60w4Aiq$E#t)$i7`+cn3mOhX9YJ99vHPe39bMoJ<;XL@0o2C> zfCy|C$Z4=f@R=04105a(ZvwVrP)Ct3IE@pnLgE+%r)$HpIMfsF4Va}+1z`r)1YQyl zW|eUdIKp{g*>HfTC#0@Z$v1HVd1!X{t+#VZnp<>-+EEToKLmArBQMvyk zq3aA(4u!Gn6Tn1%OJ1UcIjoX3V4`DDvp{Lu9 z7)_Lup`46kd2nFEgkhpGj)LAl6Hqn;ZK7NU<$9dfo&&Qv55o$OpV~s%2bE#;v~g=H z!&X!Q5<^y0Yy_v38=wphgW6ekHgt7&c8uv!Sw_1X3UlI~(Ap)RC&f4SwfFaQwzsx4 zH>G7kXcrmi>11nRW@2h#DEICZ9Zn`OuBESQc(A{(r>mniGbt`IEXd!>)y2anAS5DC z{_WWbxP;jJ?7W`d-X0*=nwgRi6A=>N?e6B~7Zes1`0mX~8XU7sTueq>Jl;lXZN*yz zGBeUslM`d3LW4uXBBEk~-pbM8BxPcw(?SE9nwuIM8|v$0W8>lz5|ffsQq$5iGP6?O z$WFjLi-~IK>wp!rrJ=T}+|$$B$Is8#&)?tA*W1g(MfTNKxabIwV`xH-gs6}}A8!v= zHxF-L|3IJDFTcV?g%_8U_x1PnB6+jEmm}bn%u$*gY|kRYvJ#Wp+S|!(g00yZsY&tC zVFBJAgt!4OU(mrMpM{4egoZVNikli68j^mOAtN(0D@o@0SGcf{+S;Pdwq}r`vN9+r zBs3x-JR%}8EG#4_&|CW11l*(0;O4$gniy@3F(Ljwo*r&)t}gB#p5DG5FQmT0g#=dC zH^LEyX zBp>)vK%DC@7(!4x=)8= zx$Endn~~XpcZ+m^H~$Ft@ZJQzyFQ+&F|o~UNQ~yDtn{?B)Rd&S7=p`$ko$MP;`8>% zj18|NHwf3))y30gp!r^U{M|ddXzcOc^>lCO?Hue!=k4kWe|Ox2+tbs_3*64#)y3)V zZ91IfT@N<|M|d7$4>^jjmz$fXw|{V$_nn&)aM#^kvwJ&eCi`BDz`zi*+c$P1x@2sI zle1H7ZCzz)aba#|N=SgOhm(z|o{pZex!p(YJGZWK;1DL@n8XPONBa+P1v#m4;Q?OG z_7+AuY7`|^Eh8(#7k6)8TZv;|0NJ$FW_C7~cEJhJp}y`;Hf9D|%F60mdRlKD-oNwP z0y0(v@rBq!QwuX=BYQ7z7Y9pYT{Tq=P4dg9j~?7QM8Qg-U+AsAk%6wJo|&z=p|-k; z!V77sC-*N{!#6iJ)D*=(r$th1i$Avyp`^`5oj^X3VW0X;q5%ysq+FX?TDa(x(lQEh00R?Bi(6HAoIHRJ^-VPsgIHY zjEunW0ZKo)m$|zoAtL-EZF^_pZ0zYC!pE>tMFJst7$3p`5bwwPNWHyy4|7+2WO$ez zEr4XH=K~w*M~%4=_r}aSxsmE(1_wFnp2E0zra=4Vcvkl z!+ZxTaw5G#f)d3yO_WCFlo%f`FVGY^AF#-jmNa(v4=IhR0BJO7hgpF%oo()~@)Cpb zMsfpNLTsR?r^kKTk%Bd{sHm;Ce-Nmvj*&)zcQ%;P2m!JyKg~X!9caaYtp+xJay?^B zY)lyLfmzUkceb3u(zgEofsqmNs2U9g6M+IB5GDiw7CJkT@Q8iDP>is z!^A=d7`D%!t2+7+4hqZwd>jWyV*o|qLsKTyKobOEfgP_20;xK3E$f$<=qNuoH&BHS zN}-+0{Z!rA*WW*kmM-!bv5?`T5`YM;oy6Jz>nCzJkOu^Uhz#~cat&v7c63yfzpJYY z#GnKwjhyV7&b~g-3rK|nCVWg1t*Ug@AiDq}LM)n8fTtF(W~r)-jf#p0z+D)g(T+vT zc9|JvD`^)A!-P)(GNiYT4jQsXFe8DiysS7TDm*kKDBz=`BRCd1fii}~ zr`F=VY=}D$7km@6w~D~_RaC+ZfQ{x`2wP26Wkq>eX<}3a#G3(rjvqdl($H~x$0SsD z6Ts2#W%$Ho{Ho>mZ+vP(enShRW;12M4;|ct1o&RdvD<0f`F8 z2;JeM%jqVixqVj`LPqS=G-Q>)7af_uuZM$!y%LQxKBI_;vi2Stx&ed^tv@RW??C$* zT6*Z#gcHP9zS4oO(BMFSUvF1?d%Nd!4|yFC{-p))VFliRwSi%L1ZFjPWaWhC(hV@7 zu{zK{A!S-LGA6?2`O(hK_5hj)a6`B@JS?xV8}DJG;~N^L0A~}9i+G!0t%+t#gsdPX z7K}+l=HX~-YeSpmj3J>}^>{Z2T~gp~h%&sKzSz)F!7@izKZGt7<)vAPanTV7m7kB7 zhnu~P4Qxqh#o!DGNv`VZ>h4C!V2$m^2FOFp>FXYN1=@-bDp<0Rivg+vIM~ERh9jpy zsGMzVtif#&E+&_d@Uk|%ivf_~y^4LS`Uk$QzCCEQAQl}$_0?5n`59@+iSf}96Np?s zSX*1+G)&Bj!9jWTop=``Voa@f1)RRVvmYp_t`=^YvNO_Ck`iL!1d6!vba!>OwX(8U z4#^1Q`2K-Ol{jF*yOn!L-QAR~1;2YhQ$uZKX<=S2#8hd?NpaEP!2!r-fWgVi($bK& zr7$}Ogq5^*ARLr#NTzfzCl?dd$C)}?L@sdyDB`F?`+kt??!_DQRqrJJgnE`EQ zXL0fkDy(k=fd)wF(=P}+&XeIGYA0x;mu2EsRjDtH-RKOGXpFFvnSBk z3%Lg%u`n?j_&?BRjQ3kVM{>UA2Aq-0E59HvNORU2pN1lT%ExXb~a{4MuxEFq2wC# z8#mXuyn4k3QhftnzZeaN<+ifo+wq_S@NYO5dJ%?%(t| zo^fBu74v~*L=~(B62r{-1O|gODIS^I-`fL?1)W(K;kp=@3}r1@WE~vB63fc*GE!+N zUNRTy3OI(L*)VBnLt)x^xY5*YVXCWZpuLTj7tAP5nNQu(C5@ zCkr!u9aHUhw2Ub88C%}AV$9`m$0j)xv8#>mDUs5>61m$(%LI1w-7Iw3p^6k5SM94 zKAKGk-GE-rO%1hdwUlWo*=6soZ2hAOh#`bBvtWG&TOfUgfH6E=X~r-&HP*2;*SJVK z4KFdVboR~6%gfFE1p3d)1UisJjHB`Qbqpjj_09Y=6lqD`B`+ ziEvkkoeZUn7dN13bPCuyqd(4c1jVM@uY=>6=)6jL%4K z=|w>vWE>#@m;zJ4!xjI?m`JtfF`qCD9jP7?-xL zu0>>cEucj_l>2-&jj^G=uC}J8HU)==Qz)%IOI1flKRmP)!h6I)nJbz)$R}x#>Z+<_ z$Py5cxVE-dP)IJFeu*QoD0~G}Q>5T8XpnPWXlZGB2Bp%emwW@LqotvyjN|VgV34_E zz_9bUrsRi!Xgcv?w9J^Bniv`AAwU(y_wN|U->n~MxbzF@T_F*CvP*PS=!YPbo0KwlgDJaOxgGLFscWP?5DknW;$Wm0K zP;fE{L6H;`$nw}L8W{fydlN$~<&xqr1^KY1DpC+8();(g0?Rvj1-aMqduVV%^y`Bz zNZ?kKela!B)ra*G*J0B&F#h-Y;NR;5xbyM<_xj-9>x2IXt`Dr?orMm@#KghLOwxp_ z6LpNA=dgl-qkn8>UUI0bx$@oRoD6EPEvaHmY$tW&>hKmyGbdc zU@V*LD&SlJ2Mb2ji8pZ4;(Lg){Vs8;KzyK#F)-YSqcoG6nsDf6o#;n7D~O}B@mb37 zLPHrN?N6mZ!cq+I!|8$+rXv7ay!-hDn-bh%D`5=cZVgI}qy{(%FrYkIjQ|Sg5m*U| zZ6VCe58bK+?>YeVbWy!B92y{rD2@=KzC=0VrvZ z1Skr$C*nvHa@q4LVX+99+q4F+Q>rJ`)#0^bUorm(UN-~~A@|&Ru&jsLah()`)h8RW$8Kx7Q(Pc$^ zea_26QG5ov&`V4p$CDgb72(l=BF0X7SPbte5j`9R&VYf4AQJxT!2`lubd?F0l(8}7 zXiQoO9*pf-e|tiN!5}8Yu8;+ZkA<-) zSr194(}Lt`T` zKY%`cJPJ;7;KmggrwxZ75mF6`ZrB}Vc;EvUf(!H?D zR2l9i6fvG#Mi!C9r3gV|Q%f6Ue&(PEA4QCyiK0Rz2JL)ALjXAfM+aLg3)~Dh$G8y= z3bvkE)5I#M2$0m)H#WDncXSeIJrs3=C?!P&pCMC%xQK!jA>^IV(Zt@y%G{JoV%+N4TY|@I$4!OVN-=?V2ap! zvXP~Oi*HdG+>-&0-hpBG`JF!W0KX2NwSOTbL0Om3Ku7|(ew^S!Lxrq}olpZ56l?>7 zwlU!FPA{#jfvf7S-hmN#t&eat*1-$#LJ;L^?gZ(=&f3Bh1W{Lka32#_hul5|+rpzm z;0PzP zr5(9gS4Ue@1NcS};vyN604N*i=KR6V%FM_>M^jbt{kzvP((AMc3>%p=4a{tu++uW<}@cs`BE(Jn$`)M}w>kWP^|dfJ>5P!*jSnx>1q+9Wu7i!)}~FdtJ;R9wz@J|UQTM82p>BmefTph?*6%hySJ`ev1pEj zC_g8tjaZ-s71gv2Os(u3UEIBV`~vX6+2|qw@=OlauyE+>YAL^yd35{gh0{m(@7%n0 z*@9WqM0k50y1^4b7}t0 zZ(O}(o}{=C4;zCPu|KWeK~~Y!H8i!fv3LCF0-rd5IlwoA(_>6^*s9wzdD@NOqcuvKGXoQdh#?zLI_nM9-f*yl=;*H3Y+a z$Vmc#VXmX^6=9@-v6+RH4eV31Y*DfU)&wneW&EA&i>D86T?LY$CeZO$c7uTCO2N19 z6;(8}^$d+o%`Ge}EiKF;)1^RWIaEiWqBTrURQPT09Z3FZA;81?ubaC!Flp}jjctzEuo&WtI7+^nG05TM3!`jyv9 zoIVE3ZC35^UmDlvrj!BZIY>b2Y({Oyc4Z{%cO%1BE+esK3D8gl&bzMWe)tX{To zw!{=cf((jR7j1g*=;<@*7cwtjzIypm=Ed`8Pai+Lcl*ZGOK8OYUE2_2b0tA@oXlDf z8B;Je)~k0PJbL_8N{ak!y42Grj~?8+bMyLd7tbO1-P<;;U9n{Ttm$F`+(;4>O0zD$ zar@4_`wt%CkETC-_~8EC+c&RYy?o*9sbh!s@7}&?-O8m4fF&Vb4j>Q%1QsxyxO)BO zt=o6*+`V(>_U)TDuKjiyu%9@3Xy2}Fo7Sybwr~#c!_S3m5(D^|XI#Ae+tq87>r<~? z{q4%73+K+9JbvWBUK;G8xihDU0xxi8!blV>4#Dp^cj4ltOZerfmo8nraQ^J+lgE!9 z+P`P#R)l-eyqVL*5HBhiiNsDHAae55nX_l{b5qZrJ#+fhiDO3&0s8G*Hm*hRv!+iG z;^Smt00Kf3cpj{XF>W||?6~3yvE#>%96q>z@9rI2H?3c@a_K?@Dhzxx0&adT3OpXB zV2nHm4j!T$7CUtC!2W%EcJ0`g(%a<&iI}^bYe3KYvQ{Yeqc$e(iyBFUlws-HI z-Me;f-wL2>RxVq-U=9tIoka3>%(WA4T?m+>puMhaxC zfjDXU%$br8k`t0M(B=U9+6`p1Lr0Gv$4@YxJbCIAei{SyXA@}gsRD}<;-bRBqGDka z@&bG9A+*f6fB%64_(9U4^%OX50|QLBh=8yWdSvVaZ+?A^wrtw8dGnSn_*T-kZTNOZ zP&Npk1L_py;pgK!1vkDBN;uhDT@sL3xM~%?nzUvOzLt62y7lYVzz?&bpQFH-aZZj| z#HQ`?!Pas!+}$v8@rzEIy#Qarw0Qo)W#Y64fjlG@7G{=U^t#y@;1;T4tPD&f3=^2k zLV=7lEZ8KdS)!+^s9#JABk_n*Agio`vEvi1Y|zTVNo!@hMQ=6L#z@SJ^u~SkMl(Z5 z;3{Kmi|KW9dYy+}w?K6jjFn!sq*d97YcL>BG9dE5Jk!pto-e^m3n^?ZA)&!S;+`^V z;r>~)gs$Y<+?@7-&i;?o|hYlzADZ68!2mSOa z3g*8+oCG(=QDGsGG4Y8h@unvCXmBiYIay^zrSQZ+qz{e`Ur>~duF1lq;}TQS6HSfj zaLjVqnFZO|co(S?p3eyoDF!&=rlRMz=^05TMz<&EW@Y3j$Du0>^av>{D?2;qQ*K_~ z=lp`g!Y`kV4Zp%=rgsc<4ffIw3E|=B5pq;C{DHfXU|(H>uW%V@AjdFWj)H6y?!kd5 zBs?N2HZICQpAN??m!1lTF?>*zkhkzVIWiIq^yqM`a%m}FKIL}7vjf3SxDwCJCL%y2 zZAOB=?gW%fYI06WYCBxT3xgPtbji*8j70c?{>#+>(AAa!&nv?45RRb0kdV-@$WR?^IyOm}q=fpGHuP+Y zu-W%A#Or9$;aFr6Fw|y32zr{%Lg0e z({f129GO}gbT~Gdgt*F*Jh(}sGzny+rK5-Y$ZF{H8Lz5-g(j+yOnht`2m#FXbhI?Y z!DUlOP!Jx>7U&-k80f2}Mu(Gx9~@}z=|*r!h@uH0A_x`7sjJfASf0g3mlhQE;C&+K znaz)IYASR%Hu%AT&zV_pX29X?d;6DsbQO%=hafILC95ib#TOk}n3dd2ZWV@nKo087 znee=VOeH0_D@6AzLeHWiT0x9KbdqYUiwO-24-E^$!`Wz=5=BKioaD2}a0Eveqc|@+ z9lav~uZxLGNRCpXOu#*i2>UWXf4$t@S^SN-3GqoDisUnhF1!X03JuO`XoBM(Ja5U4 zjf@EPb$7I}wsmmw@N-b2C~(kUgP->g3JA|bF_iC+Hf`K;OeNOtoVKx z{WbVz7e7BA|G3n|=+FR9X9p`&J$(}k8*4+joO-*K{u=zX8+u*g6BOh_U@a=_Eshk{b|A7mWnhdnRpJ)|I!*R(ohfz&k7(gRCxkRAn_i2 zkDe**{?$MOKR59n{K)RZ*B)NpG4n6pgUb*whVAno{V=j}@$w69R)|4g+40?{$>rWW0Uih+|3UgpY+U?e*BxuWBm8@1 zEd7o!A4H}95C=?b-2CD)Rln2wgHqYkDG(R`6INgV>eJsf`~l7Hn`&gmc{!MVxeAy# z_{1qK-;??;wZ=;VaLoLr9FQP7UX}G<=>13YxVbnV$FKAP1~wkSs~!JA=f5}PZiKwa zFVg@c2j3KvZ@!w~ztjEN)B6Mt6~Bl9Mh^aE>0dGb-GZ?oH_IHR&6)f4}%nko)INKw{$)@&5ZXzl9u^66E~pS-{FGZ2T?K|D`;7lb_=! z*8wJOp;!M4$?stYH}SFk)LKkp=U@8c*J6B6;?HY|!n{A_gUmd_j(<+!FM6K}a{hz` zNE`yYM*o7spLe${;G6i`uSqNhEWDyIe~$kzdz}TjCOrojI0di#C4s*H7(d20>FAn; zPc;88(EoLJl+dIVz#*{hukrsC#K>a)NqPVym$1rTVgDQbZv;6ew+4Xs{q2zBPxwd| z;htP5z$UQbf7|r`n2GVVe3M#(7`T3B>HUTmRY7<|`oDjec}1hX!7}+`wlMc(mH<|M zG1`~iOrA1rWS1!KWa0oef%!j6nLd8bq#S@zZG-uK$P&NVark`dYd~)88;$<*^^-t5k zGpWUw2-o5KyYc6a|5R$}l%L3eu=0s|{GF^Xq`LhwTDI?6u>9y zK4}HW{zUSN&Hy8);HvMx*Z1#pQz-t^;$s*K@1*1K3qO_oq$>b&ptJt^*6oj!5-#!+ zOW%b3VHe;Lp435fWQ)Kg6JNj6CQ1;8WdD(Tf6-`WW7~dq(noVJ?t3DCQgi<`EAO`qz&?2BPbhxZHL~#+&be_s8lUkx5;4|CQvlez5=g9|`_Y z-}^89$vigrSO0%U1ONKpzw_^h_2$Rwzw6Jx>;KV` z>kqsMTl<5(f2{8MC(j=khk$s_j}*VF7ft=gvL9&0WZ@B7_-9GD!sS1IIaJ17=KZQ4I{L3nFtPCnYzq64GEvVu2;b!~si)TemD(S4keE4m1<$7Z z2L~lj#RPfT|B1xsk4!Lt5rlU;eVdCMkGu%qvcbvnzdtkm5&7S$GqQ0Dh%6*e{9^iX z`^{oP=xbE|*5F?Pgp43I&9Dc4pX^}cR`g{kZ2#P`?~gbpv2gN>iZ6DpseC<641EjE z9|8TNZSWJJLZag0;#2-Fy#9|Q0YBt}pTFkk`3HX7^^fTNXB+&UHBJuJfBc88|C8|V zEx%^QJ-D@E1BR)40$#3%CnP1gIaJY;U7@=&a?c(UT|K5kH$bPc)Bs?pJ* zBJug5&csS0ef^($3gZGG5{a3K2_sRjV1kk-E?l@i@&APrCoWKLWBeHD@Qp_|Zogdm zYVERB%T`kLFyb|`S`3Ua%#P(_f2=HaiS^9MjnY>v#ILQanl7ZP?aQ`FqrT7~Ceune zY@PW*Qy7OAg zk=rvH*y}7#9_zA+mUEq1y0WP;Rch@PUxwpCm+r6bTCL7EHT-l`^X4_v7i7oS9Tyw> zVqh_MC!^M*)0(&J>pYU@-g_~$VSB<;-|0@{l?Uxa*|F4@`F_ADU!B*&3Z9HNFPRPI zbQs$>k9V*Lo#*K)YqhXn6tL3mxtykbkk5v77Y%3bnv<`s${$?CT-8$W`RI8?zFXbf zmZ;9#&?uB#`D6y!L*Z_v*pp{kt5sH>B6oE!(D!T=uVM)l z+$Z{A-2(jRcJ~swX#0SM(6xs|7Z;7s4DjAN(+__k_;MXb4JG%~eo^}nd)`5PyIh$m z{2Y=Jk8WsMbl+JX@|#*!zo7Grq?WEFwwuSy&jiXAYWla$TDS9UA2~KKRa2|@@%_k* zZc~oSvy!QEx`QwAgg151TBrb9=#)LI?`3x-SN_Hu5Hy3VC+3=TIx5`x*#5`^@?m?f z21he|eC0bF?c^Su=FC`e#&>M(=QSG(`xmZGT|V={^O+_r{hj@0Jck}_!M8k|x#P%s zmF+?z)mF=R3dd zRMK4W6(4)QX{C)_GJeoa?m4KJru_9j%sK$Au_YoDa3mjTh->9+7%ODdyR5BVTe}wxMZ^ zicq~#dh242s};|1=*h>l97)R?yI2?!*{d(Q=CV3% zJ*YhY-kCUVKJr-?4!eLWOR@v~=6qPVX9LS>@fkL;drqGH99?j&YyQj8<;PSVcPzNkA99*;F9{W|QQ1ZJa`co~H?UksT z{c3iV?3v!b`?MvABh)IaM0zf1ZjAgR^&0^yvrayDZpa$et#H6MZ8W`pQASgH^YMrn z>S>a*w#R+uS>roS?YMi)v-HIA9K%Pq-(6TCa;RnV8NthYyd%}CjP-;&EbLCVoqKS& zaFO9GTXFx+Yd5wviEvxBJg;zxO1~~UN9oIrL}uk%FYg&Bzu42TB+Kgg`R>5t+>Aq; zZ>dbL&67*#XxiQ}gI_e?OH298HLKlG3l7>SEJ}Je&*|O11yU9yxy8l1yU!hLU;aAJ zXuGpy{k|R^;TAb21)k9Pe%miQ%j{noc>Hbprpk`zk3Gmi;T+?=H`JfVo9REB{``bQ z<$>L?ITg>IF^w=59?)B)AFe;5DPCS%H}6DQ4F8;gm6yjcAs^mH5}S;+-A{`O+rYU~ zzkJu`E!jm95lbvuV>MZZ^fQ({oZ#E9lrK&`gculw{+Lg?B!$-ezuz`4Uqd(w7X#@jTNobM=^y!AQvsP*=d zH?QYEnjdybtdv*ho@2B4deW4AGx@lC)fhKVe|Tx#3gyK+Zzk+?XB{-V6YK4_=;ZA} zS*2TjD^Kisz?EZE`%rp-UsjN1nbiR|`_eToS6XeC?RYG_up)K#L4}Oiwer?iTGyy} zmwnQGmnkaoIA%tzV<#zkh-F2x-TeyDn^$xl<9EK4E@aMMyg)X4wbTpt;MCz`+m0T# z%DG)Tn}005%_`qj@*3*`iDI)}k3;!a-;~>|R`7~e=&KQKJHGDdp_1Cmpxlj~sY~}kf zd%@z@Lu_l08M}Ds7hF}^bEMeU&JlJDP93 z@WHG_Ge)d9-UL<~&(QX6Xjvwwd^nfyVee^g$$)lob>$;5 z;-Hb3Ro03(L8jyaFT7*Hc@gcNExb2q~3IluO?a zVb~U4Ek9iLSzlK3^s??D54`*R)J*P^qF0}5y6jL`Jf^<)qP+dVZNIS`$u>0pt!8vR z*HwY#M#{I!<`}*cjh-7&{%&7U!JUmSLzUNINt`yxVkMyqZ1s=u&Kk>l`-C^icUW@f z?$_h;`s^QBq?Wvu4am85`(DB-%VK@;9Xul4r?_s+)ULSyMUFlA(oRADYMa&8dvCpP z4iZa0)ty{fwS8TR0{8VfQ`=4J<+mv&TlM0)tPW3Bvv132%UETh+9h+Mk74yI;X1v} zBWH}+@b^nNS5^sH2+#C8Syd^JF7WBMTYc_vf}%|WrqUX-KU`xEblUW}DzccN_w0S= zdB>edgK7$!Hs8O!<>k8BcM4T<+mAP$I&~n#iA{M+ddpHq&%EPzh8#YPdrlvvUjAsj zYh=!ixV+0{k)zQYZKAskJO*CAX*1ET6fS3VWoUc4`cnS9pey^OeRoK{TF{c@x67ku z4PSN0|);~G&^!IEihl>TVm^1aeQZYjOXbYG;tN@N`k7*IAi_jq38(vr?iLLA$(vu`#ucuNnp z;EAtpc^w@(`6TI!;ocMPqF8kr>h;wx=<;P9&i9IxDji>TfX8=HPL=&$JFI)9)AGI5 z^#Mz_bB}&`Ehcf^)^@|RU7B&;kJtvhnGDZ{glu5FXUO~LUCo0`=5y@r2g|dUyGv5m zzY0!Qqwb41x5{v!c&Dz$tv54Mnc2=TF1q^Ay+LSPuQ;l@a*FC+>*+b0yVVTV+&h#Q z*tcTiNi(sn7vGY~c4o!P7x?weJ$huJvMGOc+`W#EY$wURcf%gstzN%yN}%GI0P5o~?FYi*`(@XX@-MXB8qGG$r8CeHoiM!TIcU*GHx7puQ zbWd)teYGw5TJ0K=`V55HkcGKD1q zUipa`G|J{0T|YeVY~Rj4;i9+47G?GA*R;6HVtXf}(mYs-SMssdN)5InPK_rl<@A|0 zwZC1}k))Wg`JU@lGpQCKBSFUUfY0x5PRH~EM8=wHmh&{OU!tOz#eN{!FqB)_XwOWA zJ^r6o?PgW8I*3iNGd?V*@a2$=!}_r8eD7v`7>#b&oxH0qq#&wl6z}~t(>{+O>@6(c#k|GsNU za-C3lZGL8P@~x4V~Fh zk=ZSgFM4^7oX@aR=kdU@0;Wcb9am`0!6aISojYI|hK zJ-^Q))(eFWn7>xI)^~~dm1y5HkL%=>r!BWEHM31R#=5k_Q-Y&1th=m2@74k7Y6|mK zna7L^qeo}#jL(tDCz}NLa_Kxb2#MdVuBb{;W@T#%Y*D7b<0QrZ@;m+YeqAd~l|Xp{t{aXXx4Kvxb(;FRJ1;Z~4q-+Pk#p(Z!v1 zkCQH@+;ZF{*A!^GwR~1n;a=fSORaYu+F1KK?^u?RWvG`nmE1`=dAK~P%Kx5FOHp;Z zTbtXVknzv^^*1kX^;NaUWQDR;vOj#?GRIF)ywxPqw`a?#?7J&ED89)VF_MgytE+=& z&QB7Wqhpq6??rvU6`&S(-QxH~;|*q(0UFioSqgEbBipn0h%X39vGEKEDtx^$xyr?` zC-2K>Z|ycp#Bci@G9OSBjh7hOB^5oYkFsay+fWpP-C7vz9<@`v_Cq1d6opUzoPHU- zd!jWj21Y&_6Od@WSn;YvWq+2V)H}g}T@f#p5|4PDiAyN`cp_8c;D8oqsO=*1R`&Bo)>XIfO(slSzS?Oix)=@KUCyzUG^M#k_X z+h@pU6m2~k6d4kyx2ODQU(k)rJFS!vQ?;2PDLdTm_0KeDk7=~tyL7F@J+0<-Jiezi z!V4vSo7Z&u*y^vXlZlT(7zU=WsD#p^YDWsWParQ#h$$7VpwT^x~xKCq~qx+sC2VR?T#QHo68a3Qx zcT+Cb{T746yxVN!4X0-?bM1Yy-eCt%aoQ%uril2{PwcuIs+q(T7k%2*hBsWu>wVvH zYcJ(VtxHhC-k`GbJs{teRxSt$+m{>9Zx<6g*`?$XK}yV1nt9prJ}iQCfuMT&*u zcJbN99w%?^ySJ|?@T9p(rT&WKoI2V4TW*K(gecowy~QZE$7p{#lX@BB-Y<6k?RR|x z7qvKectl#pTyD8p_1H=(#ro*AIWoCi^8B;iKE846?{9P7?5-;~b#(cYFB&7Z62}j2 z|G>?-s5VhCnyGEWp3Q8hZ$BM!e6f0)#5w8N=RcTSJHP0#|KWy4tBM_ur})jwXuMXi zp~^79`)C2{6D#Z6ayISft#$WXIcq(a$PJO&P-&boT>DP4Jl6AwLCn!U!ObV+rX?C( zyX7jg@9`S>T;=B%rB1Dgyj>PjH}jLU6PH-K3HS8}$2nMv!_NhWm$20mzt~J@LY&@l5@3G5>&ZcC4bR)iLtf6 z%-DX7-yW?}Y+dwpjplFqevVmgyO!FtDK5?I9;qU%yTZw1KIpI z@AY#Q*?V%uRM*8SJ&A7%n%Q5JBOjELnl;r^ddf9%bHn<|s*?F6J{Ny!!6>7rGaj3m zUA?I@N1oy8xsfKTx>yXw~ns8f6UH7fJr&RdNH$G=EJ=o%Tl!-#IEd}Up7bK zfw*kFeA-j4rtZD6Mdm^&jbc-d>gUe-JZ8bGzav{ldDDd~+4m;aTcrIvZjK*W+WsK( zkm&_JllkqE385zPC9ggzcW+4kIFCKbA+zbX%Ntj%cC|J;SV6Mj6RBr!;oEe7%W9Pv zudOP+<>7bjoE9uuym8gbGdE61%)i|nBd@r3ceLHYXJ_|k9rqDYIbFnc>0vzEp0)g2 z@)z07e|~Rg_J?gpwkfZmEIf68T0ixOPrW6-@%c+FT%At0Vup_Ao_>-}{ zDYdKA5>hW8d3WEn$zD0&F_dy>SGd&a`@Z4|a`V+BdY?ru zPqeLP-g=MgZR*zR@<-FHGw$%#EQ?b3qSrk=(z1J6v_PN9j=3T2MKyiLR&?vsTV@5W zo#AZDWvl9+YI4OlQfjkYiP+gfN45(`%uG+4>wXyDSoo&?N`sO>;fiRc_ijV1f@Kaf z_cmKONzZ1hS|z{BfooK>&ANM5_WOrNS7GK!u8*saTlE`8w>=#jyk*Qdb5pA6VrkQq zd-ca7#57N*y*q5x$aH&euhStW*{&wLkB(=yWZbK?mq}Uecl-|TO|R>T81rj!*|$|C z%dWkkh=p<-X_(i|ztB@;r)x9GL93l1dgdH4mpH%QoL-GAE-tMxIdx~l*3WrDvm9;Z zj;yZ}-Pv&cX65K_d*)ATO0Igbzv|ZRPG3yFQDSK7F<0}zZEx>4Jmc;t-Ee_Jd)b+Y zozFb(nkcTD=@UG3@v7Nz*R#?L*Q&FhY!lrzued+Rd4i1B-ne5H?rF;>!=P=dsoLBT)w3B4E z#)I4`_soLo*ybt;q{&K-aTmPYQoy)|yprki%Oz)(6Q>IE@8-UydS%Hf1vk7ZX`lR~ zCCpO2ys;u#rmq~x#!FXiDr32_Yo-eI$t9WD4N_NX^~LR%b#DqkKc&R>!%)f%c}!&* zt))!-4a!so24y z>r(?q#2*j6xj4FJ(E&|%wE`xgtL(q2mC8FDG+EPGYp`qjLgz6Vy{?_}qaO;A_j5IE z3tttx-^HSsf0Orsu&37s)kLjD>_-BXFLJEWXJ@{cY`4J;^E0vO-D$yU=s4@X^8@gUr`#$`*^s4Ltlbwoy{3qo~~aRdd7JtW7azo^V}@ z5h2NZR^2#lDEfigx{skz_uIGcbQ#^;o*hn!Ic#~`U(mD0&B;6>A?}m#2}3elV`9#gHc!j;s~wvzI#!9+ z>oLb3oZ}-QfM@7Uzj*Y-P=Lz04YKNoF8!9mW_F~o`t(s>fx!1t)nUA*lF4I%`1|nM z#fR_C*O=;W^7zPchMt7HoTv2>bx|i>ZNsKTOb_%lUUTUZo6n0P&iQZCE^{V@<>e%E z|9=1%K?p&q1EW|2~_Tp+Gl5U~y< z;XJ7F+as+u%ShXYhQQ=i2=l^?wwfX z)iEvtmyKusRTF)g>|%;i`t}HwDyl(`A;Z@nHO=q19EQo-JR9VCMW9Nw(?4j6eot4_ zt^Zs+KuxiF2qWJbD8`!smU38z5~x~r+UlS5fvx@3W1EvR5JAV38Xd*vzZ*ID;k^bc zTu}$(vghx`g%;9jO_d%wxP!>t5Zj`gv%KP!c&v)3m+Qc(pxRX4YHvT#UtPLu1<+=E z({h0TD`3d24AVvdRqUMX!y4LCtG2qL7r>@gWQ;F0R0~vIcA%>2(64(@=yOcDC;xdV zuQ90M`a*%0ePXxksNUWjjB5z;f>39#dOf@az*)ZpnLQnyPZCaVY6u+4II7JhtN5Bs zbOXK!ZI25G<=~lk=2RVrlnNJHRSQr?A6vTfD4E$3j`$kMaG z_p34(b3g+HFtBcS4LqF_mPgg|dHvhu{^0%(E2B0cQG7|ui)`H0t--5x?N0v?g*_=S z)VO}Z*ZzozlkCeD3`8QhCUm10Lm=7-@+ul?RB%klG^wS&26`zB7L zxGUZEEb2_p==fIeSsW`RpmAW^8x~d(predT9-=yC`-4Kpt`dzOepy0i)x2bTPCj-I6JS9x(7$;guX3e+c8?{4M}r(!7Qs zSzo|sKbHDz`UH09j|AEE{}u5j-@B2k*IQ2!CA{-8f>{OLIhKWLq$Cfl(!5WfE6%xD zaMBnO4xN8=OF3E;0TTYtIs2G@$k}jTpnJ3E0>IM_0w8@!XlRi`fp?c7kZYketm5*& zFIk6|`%8#X_9_1)5rELp9rd8U`Jc(D^yg$LCW?4<)mM-2S45;?VJb=W$k&^~_OH+= z$s2O+(TP6$mrwn->5vWKRQeh4$1k()_UwR)y{Ls0iYK}$rcnvMb9DDO)ytu2%;=Dc z`YHuD$|$ag_Xs@}=1|A4XzK$i*9hQfrZkgM^)y&1JA;ed&sjudHTSPBH~tW(8Wk>L zF%^wPNg&u=(x#U<6H*!)OtzrTCo)w6_LyeDU=gK>!{C@&T_xocjHmS%f?7JJqNs#w zJW)#@IWKD8P3v}Uku0pXx^pjYsyfB95c=|WCMQWj793>!jq@6!OykV)RmHqVRrDhD z^7%Qa!)pE4G4@9jI9PcJdRp>n+Y;%tpdV^D9S+Dnck!-j6Q_H1_fYUMptQDmqhV9B zKdgCt!)ydwe>S*wmAg1&V2bV$_6H%SSVw6$8H&ew7>jR>gQ&*~!%s2aJ5S9mX1Qy^V6&?E?a5I3Da@U!}#7*9^$a{jM zTu`JWo$R`}fEqB^_$1r_sh5FJM6l+plzI|CrOIqzmJEjzPam68KE?5_%xAI|ET{s6 z%YfUn{|0+h4%FUyy{*;wr?%&G0N~RJ^Z=BiHa;+EULMbBI972;T7+yn0?dSGm*kzz@ z|4AJAUxq_N0-rt;Sx_o9_>f z%V|!Io+Y`XXzecah}RdwD`j~Zr1IEu+hS_wq%G1*7LNA861vo$w+A;z2bO_iIABum z3E!F3P~AQ7<78AAA5%??XQtmpL8xFdE@E$Yx`p&zQnSWas23$b*EnxTB02^tq}a(! z09h^*nS8!#rtf!$E=EAU%R7P}ObfORI#0xcWn9Vl>^~f_tDFaK_2zpqzk7rpl+d<8 zQWxeTx~aPxU@(m5fC=vg8*#x&|2TN%LN=wGI*Vdgyc~WB=9Dp*W!vN!I2O26)try! zVFZrGaKrq9#ZG0Jt38K9^QrL6Dk`$ZgmXH~aF>^{JEmh2I+G=^>6Vo-|E4RhBb*5;7tpi5wnfjgE}jd2-9b&8e}IVgrLZ`tR#Y@|bA zQ4L=FTKT+kWW+FqI}SwnY!p0oR+r!;(1RtCc9(FSUsc;{Y?I(Eg6g|%AJfD_`j`_xwz@LF-CHl{sferCFrJ6gK)xSXY6A_a|UPF8oDhgjbYeNI-m_NfXOC z9|(z6Z}nkKz5Wfr9J2ipd2;6RI}o0=fO4z9Y~s=s>l?`w8*|^(ok>G$>bcKOIXzC3 zx5GsA-i|q!Ql{^S0;wbwNn}*!bKXU*$QgkK`zOMQcc5>(C5Jp#r#Yc>>3N^qi`LSS zf+BJA%H;Jm6n0s6;Mft2g7q-}Oxo(Q72Db#WR>t~!|>(_cg&&yMwFisEhC;3#qnW4 zuX?C>!GN`WW!C1=`*od4FmLZaaxfrQx=o)8wNQeJU`P&0byagdrojf$h;n}Qy z9hpbr**MS++~Vr**dJs68;E%io`LjbB?g`N2_7aks7@^2Aft(FXxt@@S)L9d}Wlw=HzU&9X$lhJ4pR{&_HPX5?K6xxR}ogvPy;@rNYaEqC==wcy8;{{NK`sa9BElJsj)G z`nJnL&@tWjh6WK0@Ne_~hRHEF8sb^DCR+M^?ZJ0DCBN21t!Lua)z-?sl-z)Cg+e9^ zJIK?`ZvLK~x}PiDfq_oGg5qRxmvN`(O58VI>3~ zTTm<;WC3CdCuH%#sF3OqY}PpV^7EmPuH~(q8U)t_jd_wt-ZG*Xb9d65<>xkN-TD}5 zW1cEC1}4QR7P8$$=Lv-;7#z6OVlCf@ttzm$vqti_}>1G<0xwux0L0~O`s!o z$*(8Rn%67sQ}ZAkm`Gdj5L3kC8Hsf6$n0`A@hMfV`$4n3Vb#r;apnPlBLoT=E?-=F zv6#?vrXI&MhcDn(!S7t><4X+-qf*uySbXpsW9dWDqyw&-y?gyh9pQWcrZL1)Qz-ZS zZpVcj4|^F*wCNU}oA8I$fczFEw1n??4_^4w=3vWgTKIHfU|pqwrJE4%Vrfcw4<{Y` zAczVQ8_SeI&(YOweU6bjNB#o2$V07pM9`WCd5E%~CKm)BHdHr;`F9a`necpsdd0gR z62LNvekXN))4{#RYHG7kuxs6k=Z)TIwld&00{qn6A$zN4xUYsj=j>d{C1B+u6p#8L zBjNmWG32f@?D&puo>IfjPY_(8yRgcA7NN?Bfn_d)*utkY$lB-AV^4n)odF2 zTx9fWjxGuz3gkfZ2|G_w{g!sBUS`g*RL@u1KxmJ`-w%AoQ9o1wTK@!r@qUm6$q7#h zqPj-xe@z|^OtSYt*!(pZOd$xeoaFdmvBTS<5o!d5on6?4WEM&0E7WtfoQ8?Of^Ia| zzVN6$a%j9by31;gA4|!W zWRM`N_jsokZfW66Yp~cWv;!p?Y>lXMqJ+k>{C~i zUN?R*%374g8(OP0gm?s3mvzgGGBeW=6lTUCt<0q5XDwmmL?U Fx~Q^RMGyfi^+e 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

A~#2g+E&bR#n?4F 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%0AAm9T#kR^-p?$}?aD8~tUtbly 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 diff --git a/systray/src/main.cpp b/systray/src/main.cpp deleted file mode 100644 index 295fc7c2..00000000 --- a/systray/src/main.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Micke Prag * - * micke.prag@telldus.se * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - - -#include -#include -#include -#include "icon.h" - -int main(int argc, char *argv[]) -{ - QApplication a( argc, argv ); - - QCoreApplication::setOrganizationName("Telldus"); - QCoreApplication::setOrganizationDomain("telldus.se"); - QCoreApplication::setApplicationName("SysTray"); - - Q_INIT_RESOURCE(resource); - - QTranslator qtTranslator; - qtTranslator.load("qt_" + QLocale::system().name()); - a.installTranslator(&qtTranslator); - - QTranslator myappTranslator; - myappTranslator.load("SysTray_" + QLocale::system().name()); - a.installTranslator(&myappTranslator); - - Icon icon; - return a.exec(); -} diff --git a/systray/src/resource.qrc b/systray/src/resource.qrc deleted file mode 100644 index 325beebe..00000000 --- a/systray/src/resource.qrc +++ /dev/null @@ -1,9 +0,0 @@ - - - images/bell.png - images/lamp-on.png - images/lamp-off.png - images/preferences-system.png - images/system-log-out.png - - diff --git a/systray/src/src.pro b/systray/src/src.pro deleted file mode 100644 index 2bfbc4cf..00000000 --- a/systray/src/src.pro +++ /dev/null @@ -1,23 +0,0 @@ -TEMPLATE = app - -SOURCES += main.cpp \ -icon.cpp - -!macx:LIBS += -ltelldus-core -L../bin -macx{ - LIBS += -framework telldus-core - ICON = images/systray.icns -} -win32{ - TARGET = ../../bin/SysTray - CONFIG += release -} -unix{ - TARGET = ../bin/systray - CONFIG += debug -} -HEADERS += icon.h -#menu.h -RESOURCES += resource.qrc -RC_FILE = systray.rc -TRANSLATIONS = SysTray_sv.ts diff --git a/systray/src/systray.rc b/systray/src/systray.rc deleted file mode 100644 index 3d90079c..00000000 --- a/systray/src/systray.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "images/systray.ico" diff --git a/systray/systray.pro b/systray/systray.pro deleted file mode 100644 index b2d719f0..00000000 --- a/systray/systray.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = src -CONFIG += warn_on - From b68b4435c77de80bd3eeb1ae49fee9f281cc3532 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 14 Nov 2011 15:34:12 +0100 Subject: [PATCH 1732/2215] Retry fetching server list later if we fail the first time. This closes #117 --- telldus-gui/Plugins/Live/LiveObject.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 4d853d97..9216954a 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -228,8 +228,10 @@ void LiveObject::sslErrors( const QList & errors ) { void LiveObject::serverAssignReply( QNetworkReply *r ) { r->deleteLater(); if (r->error() != QNetworkReply::NoError) { + int timeout = rand() % 300 + 60; //Random timeout from 60s-6min to avoid flooding the servers emit errorChanged(r->errorString()); - emit statusChanged("Error retrieving server list"); + emit statusChanged("Retrying in " + QString::number(timeout) + " seconds..."); + QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer())); return; } QXmlStreamReader xml(r); From af929e53115aedc9810f933cefc12ddda711dbe4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Nov 2011 17:46:48 +0100 Subject: [PATCH 1733/2215] Changed reconnect time and ping timer. --- telldus-gui/Plugins/Live/LiveObject.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 9216954a..f7b425a2 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -46,7 +46,7 @@ LiveObject::LiveObject( QScriptEngine *engine, QObject * parent ) connect(d->socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(stateChanged(QAbstractSocket::SocketState))); connect(d->socket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); - d->timer.setInterval(60000); //Once a minute + d->timer.setInterval(120000); //Two minutes connect(&d->timer, SIGNAL(timeout()), this, SLOT(pingServer())); d->manager = new QNetworkAccessManager(this); @@ -198,7 +198,7 @@ void LiveObject::error( QAbstractSocket::SocketError socketError ) { void LiveObject::stateChanged( QAbstractSocket::SocketState socketState ) { if (socketState == QAbstractSocket::UnconnectedState) { - int timeout = rand() % 20 + 10; //Random timeout from 10-30s to avoid flooding the servers + int timeout = rand() % 40 + 10; //Random timeout from 10-50s to avoid flooding the servers QTimer::singleShot(timeout*1000, this, SLOT(connectToServer())); emit statusChanged("Reconnecting in " + QString::number(timeout) + " seconds..."); } else if (socketState == QAbstractSocket::ConnectingState) { @@ -255,7 +255,7 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { d->serverRefreshTime = QDateTime::currentDateTime(); QTimer::singleShot(0, this, SLOT(connectToServer())); } else { - int timeout = rand() % 20 + 10; //Random timeout from 10-30s to avoid flooding the servers + int timeout = rand() % 40 + 10; //Random timeout from 10-50s to avoid flooding the servers emit errorChanged("No servers found"); emit statusChanged("Retrying in " + QString::number(timeout) + " seconds..."); QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer())); From 2feeb81f376c6c93d42484b2cf81f07b0844d8c5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Nov 2011 17:48:20 +0100 Subject: [PATCH 1734/2215] Implemented listening for pongs, this refs #117 and closes #133 --- telldus-gui/Plugins/Live/LiveObject.cpp | 22 +++++++++++++++++----- telldus-gui/Plugins/Live/LiveObject.h | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index f7b425a2..0797df9a 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -13,7 +13,7 @@ public: class Server; QSslSocket *socket; - QTimer timer; + QTimer pingTimer, pongTimer; bool registered; QUrl registerUrl; QString uuid, hashMethod; @@ -46,8 +46,11 @@ LiveObject::LiveObject( QScriptEngine *engine, QObject * parent ) connect(d->socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(stateChanged(QAbstractSocket::SocketState))); connect(d->socket, SIGNAL(sslErrors(const QList &)), this, SLOT(sslErrors(const QList &))); - d->timer.setInterval(120000); //Two minutes - connect(&d->timer, SIGNAL(timeout()), this, SLOT(pingServer())); + d->pingTimer.setInterval(120000); //Two minutes + d->pongTimer.setInterval(360000); //Six minutes + d->pongTimer.setSingleShot(true); + connect(&d->pingTimer, SIGNAL(timeout()), this, SLOT(pingServer())); + connect(&d->pongTimer, SIGNAL(timeout()), this, SLOT(pongTimeout())); d->manager = new QNetworkAccessManager(this); connect(d->manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serverAssignReply(QNetworkReply*))); @@ -107,6 +110,9 @@ void LiveObject::readyRead() { return; } else if (msg->name() == "disconnect") { this->disconnect(); + } else if (msg->name() == "pong") { + d->pongTimer.stop(); + d->pongTimer.start(); } else if (msg->name() == "registered") { d->registered = true; emit registered(msg->argument(0)); @@ -170,7 +176,8 @@ void LiveObject::p_connected() { QSettings settings; d->uuid = settings.value("Live/UUID", "").toString(); - d->timer.start(); //For pings + d->pingTimer.start(); //For pings + d->pongTimer.start(); //For pongs LiveMessage msg("Register"); LiveMessageToken token; @@ -188,7 +195,8 @@ void LiveObject::p_connected() { } void LiveObject::p_disconnected() { - d->timer.stop(); + d->pingTimer.stop(); + d->pongTimer.stop(); d->registered = false; } @@ -316,3 +324,7 @@ LiveMessageToken LiveObject::generateVersionToken() { #endif return token; } + +void LiveObject::pongTimeout() { + this->disconnect(); +} diff --git a/telldus-gui/Plugins/Live/LiveObject.h b/telldus-gui/Plugins/Live/LiveObject.h index a0b93089..efa8959f 100644 --- a/telldus-gui/Plugins/Live/LiveObject.h +++ b/telldus-gui/Plugins/Live/LiveObject.h @@ -39,6 +39,7 @@ private slots: void p_connected(); void p_disconnected(); void readyRead(); + void pongTimeout(); void error( QAbstractSocket::SocketError socketError ); void stateChanged( QAbstractSocket::SocketState socketState ); void sslErrors( const QList & errors ); From 8e377a12bcba82c009d06b917335d5eaf47d5d1d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 1 Nov 2011 14:14:14 +0100 Subject: [PATCH 1735/2215] Possibility to add/remove sensors from list, and change their names. Not yet persistent. --- telldus-gui/Plugins/Sensors/SensorValue.qml | 1 + telldus-gui/Plugins/Sensors/__init__.js | 1 + telldus-gui/Plugins/Sensors/main.qml | 193 +++++++++++++++++--- telldus-gui/Plugins/Sensors/sensor.cpp | 18 +- telldus-gui/Plugins/Sensors/sensor.h | 8 +- 5 files changed, 191 insertions(+), 30 deletions(-) diff --git a/telldus-gui/Plugins/Sensors/SensorValue.qml b/telldus-gui/Plugins/Sensors/SensorValue.qml index 7198c9ff..083830a1 100644 --- a/telldus-gui/Plugins/Sensors/SensorValue.qml +++ b/telldus-gui/Plugins/Sensors/SensorValue.qml @@ -14,6 +14,7 @@ Item { } Text { id: text + font.weight: Font.Bold anchors.left: icon.right anchors.leftMargin: 10 anchors.verticalCenter: parent.verticalCenter diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js index c20bfb67..70283e2b 100644 --- a/telldus-gui/Plugins/Sensors/__init__.js +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -56,6 +56,7 @@ com.telldus.sensors = function() { sensor.protocol = protocol; sensor.model = model; sensor.id = id; + sensor.showInList = false; sensorList.push(sensor); print("Create new"); } else { diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml index 8be6755d..5d240c29 100644 --- a/telldus-gui/Plugins/Sensors/main.qml +++ b/telldus-gui/Plugins/Sensors/main.qml @@ -2,39 +2,116 @@ import Qt 4.7 Item { id: main + state: "VIEW" Component { id: sensorView - BorderImage { - source: "row_bg.png" - border.left: 5; border.top: 5 - border.right: 5; border.bottom: 5 - height: sensorInfo.height + Item{ + id: sensorViewItem + visible: main.state == "EDIT" || modelData.showInList + height: childrenRect.height width: parent.width - Text { - anchors.left: parent.left - anchors.leftMargin: 15 - height: 40 - verticalAlignment: Text.AlignVCenter - text: modelData.name; - color: "#004275" - } - Column { - id: sensorInfo - anchors.right: parent.right - width: 250 - SensorValue { - visible: modelData.hasTemperature - text: visible ? modelData.sensorValue(1).value + '°C' : '' - icon: "icon_temp.png" - lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date() + BorderImage { + source: "row_bg.png" + border.left: 5; border.top: 5 + border.right: 5; border.bottom: 5 + height: sensorInfo.height + width: parent.width + + Text { + visible: main.state == "VIEW" + anchors.left: parent.left + anchors.leftMargin: 15 + height: 40 + verticalAlignment: Text.AlignVCenter + text: modelData.name; + color: "#004275" } - SensorValue { - visible: modelData.hasHumidity - text: visible ? modelData.sensorValue(2).value + '%' : '' - icon: "icon_humidity.png" - lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date() + Rectangle{ + color: "white" + visible: main.state == "EDIT" + anchors.left: parent.left + anchors.leftMargin: 15 + width: nameEdit.width + 4 + height: 22 + TextInput{ + id: nameEdit + anchors.centerIn: parent + text: modelData.name; + color: "#004275" + + onActiveFocusChanged: { + if(!activeFocus){ + //todo other way? + modelData.setName(nameEdit.text); + } + } + onAccepted: { + modelData.setName(nameEdit.text); + } + } + } + Text{ + anchors.right: model.left + visible: main.state == "EDIT" + height: 40 + verticalAlignment: Text.AlignVCenter + text: modelData.id + color: "#004275" + width: 50 + } + Text{ + id: model + anchors.right: visibleinlistcheckbox.left + visible: main.state == "EDIT" + height: 40 + verticalAlignment: Text.AlignVCenter + text: modelData.model + color: "#004275" + width: 100 + } + Item{ + id: visibleinlistcheckbox + anchors.right: sensorInfo.left + visible: main.state == "EDIT" + height: 40 + Rectangle{ + anchors.centerIn: parent + height: 10 + width: 10 + color: "white" + Text{ + anchors.centerIn: parent + color: "#004275" + text: modelData.showInList ? "X" : "" + } + MouseArea{ + anchors.fill: parent + onClicked: { + modelData.setShowInList(!modelData.showInList); + } + } + } + width: 100 + } + + Column { + id: sensorInfo + anchors.right: parent.right + width: 250 + SensorValue { + visible: modelData.hasTemperature + text: visible ? modelData.sensorValue(1).value + '°C' : '' + icon: "icon_temp.png" + lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date() + } + SensorValue { + visible: modelData.hasHumidity + text: visible ? modelData.sensorValue(2).value + '%' : '' + icon: "icon_humidity.png" + lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date() + } } } } @@ -55,6 +132,27 @@ Item { anchors.leftMargin: 15 } HeaderTitle { + text: "ID" + anchors.right: modelTitle.left + visible: main.state == "EDIT" + width: 50 + } + HeaderTitle { + id: modelTitle + text: "Model" + anchors.right: visibleinlistTitle.left + visible: main.state == "EDIT" + width: 100 + } + HeaderTitle { + id: visibleinlistTitle + text: "Visible in list" + anchors.right: sensorinformationTitle.left + visible: main.state == "EDIT" + width: 100 + } + HeaderTitle { + id: sensorinformationTitle text: "Sensor information" width: 150 anchors.right: timestampTitle.left @@ -64,12 +162,53 @@ Item { text: "Last updated" width: 100 anchors.right: parent.right + //horizontalAlignment: Text.AlignRight } } Repeater { model: sensorModel delegate: sensorView } + Row{ + spacing: 20 + Rectangle { + width: 50 + height: 20 + Text{ + anchors.centerIn: parent + text: main.state == "VIEW" ? "Edit" : "View" + } + MouseArea{ + anchors.fill: parent + onClicked: { + if(main.state == "VIEW"){ + main.state = "EDIT" + } + else{ + main.state ="VIEW" + } + } + } + } + /* + Rectangle { + //TODO should this button exist at all, or always save? + width: 50 + height: 20 + visible: main.state == "EDIT" + Text{ + anchors.centerIn: parent + text: "Cancel" + } + MouseArea{ + anchors.fill: parent + onClicked: { + main.state ="VIEW" + } + } + } + */ + } anchors.fill: parent } } diff --git a/telldus-gui/Plugins/Sensors/sensor.cpp b/telldus-gui/Plugins/Sensors/sensor.cpp index cb04f2fc..7a56f46f 100644 --- a/telldus-gui/Plugins/Sensors/sensor.cpp +++ b/telldus-gui/Plugins/Sensors/sensor.cpp @@ -1,10 +1,11 @@ #include "sensor.h" #include "sensorvalue.h" #include +#include class Sensor::PrivateData { public: - bool hasTemperature, hasHumidity; + bool hasTemperature, hasHumidity, showInList; int id; QString model, name, protocol; QDateTime lastUpdated; @@ -45,7 +46,10 @@ void Sensor::setModel(const QString &model) { } QString Sensor::name() const { - return QString("%1 %2").arg(this->protocol()).arg(this->id()); //TODO: Remove when name is fully implemented + //return QString("%1 %2").arg(this->protocol()).arg(this->id()); //TODO: Remove when name is fully implemented + if(d->name == ""){ + return ""; + } return d->name; } @@ -88,3 +92,13 @@ void Sensor::setValue(int type, const QString &value, const QDateTime ×tamp emit hasHumidityChanged(); } } + +bool Sensor::showInList() const{ + //TODO showInList and name must be persistent... + return d->showInList; +} + +void Sensor::setShowInList(bool show){ + d->showInList = show; + emit showInListChanged(); +} diff --git a/telldus-gui/Plugins/Sensors/sensor.h b/telldus-gui/Plugins/Sensors/sensor.h index fc70468d..85164246 100644 --- a/telldus-gui/Plugins/Sensors/sensor.h +++ b/telldus-gui/Plugins/Sensors/sensor.h @@ -17,6 +17,8 @@ class Sensor : public QObject Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString protocol READ protocol WRITE setProtocol NOTIFY protocolChanged) + Q_PROPERTY(bool showInList READ showInList NOTIFY showInListChanged) + public: explicit Sensor(QObject *parent = 0); ~Sensor(); @@ -30,15 +32,18 @@ public: void setModel(const QString &model); QString name() const; - void setName(const QString &name); + //void setName(const QString &name); QString protocol() const; void setProtocol(const QString &protocol); bool hasTemperature() const; + bool showInList() const; Q_INVOKABLE SensorValue *sensorValue(int type); Q_INVOKABLE void setValue(int type, const QString &value, const QDateTime ×tamp); + Q_INVOKABLE void setName(const QString &name); + Q_INVOKABLE void setShowInList(bool show); signals: void idChanged(); @@ -47,6 +52,7 @@ signals: void modelChanged(); void nameChanged(); void protocolChanged(); + void showInListChanged(); private: class PrivateData; From 2d17564de3b267567d2234d976ed43ecdd2e31b4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 19 Dec 2011 15:48:16 +0100 Subject: [PATCH 1736/2215] Added better filtration when scanning remotes, only update the affected protocols. Closes #88 --- telldus-gui/TelldusGui/devicesetting.cpp | 14 ++++++++++++ telldus-gui/TelldusGui/devicesetting.h | 8 +++++++ telldus-gui/TelldusGui/editdevicedialog.cpp | 22 ++++++++++++++++++- .../TelldusGui/filtereddeviceproxymodel.cpp | 2 +- .../TelldusGui/filtereddeviceproxymodel.h | 2 +- 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/telldus-gui/TelldusGui/devicesetting.cpp b/telldus-gui/TelldusGui/devicesetting.cpp index d83ab775..faae0571 100644 --- a/telldus-gui/TelldusGui/devicesetting.cpp +++ b/telldus-gui/TelldusGui/devicesetting.cpp @@ -21,3 +21,17 @@ DeviceSetting::DeviceSetting(Device *device, QWidget *parent) DeviceSetting::~DeviceSetting() { } + +void DeviceSetting::addProtocolMatch( const QString &protocol, const QString &model ){ + QString protocolmodel; //concat to one string + protocolmodel.append(protocol).append(model); + acceptedProtocolModel << protocolmodel; +} + +void DeviceSetting::setProtocolValue( const QString &name, const QString &value, const QString &protocol, const QString &model ){ + QString protocolmodel; //concat to one string + protocolmodel.append(protocol).append(model); + if(acceptedProtocolModel.contains(protocolmodel)){ //protocol not set yet, or equal + this->setValue(name, value); + } +} diff --git a/telldus-gui/TelldusGui/devicesetting.h b/telldus-gui/TelldusGui/devicesetting.h index 55ff50db..4dc6f91f 100644 --- a/telldus-gui/TelldusGui/devicesetting.h +++ b/telldus-gui/TelldusGui/devicesetting.h @@ -29,10 +29,18 @@ public: public slots: virtual void saveParameters() = 0; + void addProtocolMatch( const QString &protocol, const QString &model ); + +private slots: + void setProtocolValue( const QString &name, const QString &value, const QString &protocol, const QString &model ); virtual void setValue( const QString &name, const QString &value ) = 0; protected: Device *p_device; + +private: + QList acceptedProtocolModel; + }; #endif diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 66afa766..4a211e95 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -173,10 +173,30 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setUnitMinMax(1,15); foreach( DeviceSetting *s, d->deviceSettings ) { - connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&)), s, SLOT(setValue(const QString&, const QString&))); + connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&, const QString&, const QString&)), s, SLOT(setProtocolValue(const QString&, const QString&, const QString&, const QString&))); d->settingsLayout->addWidget( s ); } + for (int i=0; imodel->rowCount(QModelIndex()); ++i){ + QModelIndex index = d->model->index(i, 0, QModelIndex()); + VendorDeviceTreeItem *typeitem = d->model->item(index); + + for(int j=0; jchildCount(); ++j){ + VendorDeviceTreeItem *branditem = typeitem->child(j); //d->model->item(index); + + for(int k=0; kchildCount(); ++k){ + VendorDeviceTreeItem *deviceitem = branditem->child(k); //d->model->item(index); + + int widget = deviceitem->widget(); + QString strModel = deviceitem->deviceModel().section(':', 0, 0); + if (strModel.startsWith("selflearning-")) { + strModel = "selflearning"; + } + d->deviceSettings[widget]->addProtocolMatch(deviceitem->deviceProtocol(), strModel); + } + } + } + expandNodes(deviceView); QModelIndex index = d->filteredModel->mapFromSource(d->model->index( device )); if (index.isValid()) { diff --git a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp index 0e20ec6c..d6faa626 100644 --- a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp +++ b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp @@ -54,7 +54,7 @@ void FilteredDeviceProxyModel::addFilter( const QString &filter ) { return; //don't scan sensors here } else { - emit setParameter(name, value); + emit setParameter(name, value, protocol, model); } } //Make sure we don't add a duplicate diff --git a/telldus-gui/TelldusGui/filtereddeviceproxymodel.h b/telldus-gui/TelldusGui/filtereddeviceproxymodel.h index df91cc9b..5029f49d 100644 --- a/telldus-gui/TelldusGui/filtereddeviceproxymodel.h +++ b/telldus-gui/TelldusGui/filtereddeviceproxymodel.h @@ -17,7 +17,7 @@ public: void addFilter( const QString & ); signals: - void setParameter(const QString &name, const QString &value); + void setParameter(const QString &name, const QString &value, const QString &protocol, const QString &model); protected: virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const; From 808385705fc7a6cf3c1a409e43019aaa88d4ab05 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Dec 2011 17:07:26 +0100 Subject: [PATCH 1737/2215] Increase timeout time --- telldus-gui/Plugins/Live/LiveObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 0797df9a..1d24117f 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -263,7 +263,7 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { d->serverRefreshTime = QDateTime::currentDateTime(); QTimer::singleShot(0, this, SLOT(connectToServer())); } else { - int timeout = rand() % 40 + 10; //Random timeout from 10-50s to avoid flooding the servers + int timeout = rand() % 300 + 60; //Random timeout from 60-6min to avoid flooding the servers emit errorChanged("No servers found"); emit statusChanged("Retrying in " + QString::number(timeout) + " seconds..."); QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer())); From ff7130561cf4120375f662da1d23c44afd25d392 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 20 Dec 2011 14:33:21 +0100 Subject: [PATCH 1738/2215] Implemented decoding of Fineoffset new short format. Hopefully this fixes #92. If not, please reopen. This also requires firmware 5 or later in TellStick Duo. --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 15 +++++-- telldus-core/service/ProtocolFineoffset.cpp | 45 +++++++++++++++++++++ telldus-core/service/ProtocolFineoffset.h | 13 ++++++ 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 telldus-core/service/ProtocolFineoffset.cpp create mode 100644 telldus-core/service/ProtocolFineoffset.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index a3e724b2..5a1e1b8a 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -34,6 +34,8 @@ SET( telldus-service_protocol_SRCS ProtocolComen.cpp ProtocolEverflourish.h ProtocolEverflourish.cpp + ProtocolFineoffset.h + ProtocolFineoffset.cpp ProtocolFuhaote.h ProtocolFuhaote.cpp ProtocolGroup.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index ebcfebb3..8b9a00c2 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -5,6 +5,7 @@ #include "ProtocolBrateck.h" #include "ProtocolComen.h" #include "ProtocolEverflourish.h" +#include "ProtocolFineoffset.h" #include "ProtocolFuhaote.h" #include "ProtocolGroup.h" #include "ProtocolHasta.h" @@ -195,10 +196,10 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"yidong")) { parameters.push_back("unit"); - + } else if (TelldusCore::comparei(protocolName, L"group")) { parameters.push_back("devices"); - + } else if (TelldusCore::comparei(protocolName, L"scene")) { parameters.push_back("devices"); } @@ -209,7 +210,7 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr std::list Protocol::decodeData(const std::string &fullData) { std::list retval; std::string decoded = ""; - + ControllerMessage dataMsg(fullData); if( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) { decoded = ProtocolNexa::decodeData(dataMsg); @@ -231,12 +232,18 @@ std::list Protocol::decodeData(const std::string &fullData) { retval.push_back(decoded); } } + else if(TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) { + decoded = ProtocolFineoffset::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { decoded = ProtocolX10::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); } } - + return retval; } diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp new file mode 100644 index 00000000..4883c92b --- /dev/null +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -0,0 +1,45 @@ +#include "ProtocolFineoffset.h" +#include +#include +#include +#include + +std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + if (data.length() < 8) { + return ""; + } + + uint8_t checksum = strtol(data.substr(data.length()-2).c_str(), NULL, 16); + data = data.substr(0, data.length()-2); + + uint8_t humidity = strtol(data.substr(data.length()-2).c_str(), NULL, 16); + data = data.substr(0, data.length()-2); + + uint16_t value = strtol(data.substr(data.length()-3).c_str(), NULL, 16); + double temperature = (value & 0x7FF)/10.0; + + value >>= 11; + if (value & 1) { + temperature = -temperature; + } + data = data.substr(0, data.length()-3); + + uint16_t id = strtol(data.c_str(), NULL, 16) & 0xFF; + + std::stringstream retString; + retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:"; + + if (humidity <= 100) { + retString << "temperaturehumidity;humidity:" << (int)humidity << ";"; + } else if (humidity == 0xFF) { + retString << "temperature;"; + } else { + return ""; + } + + retString << "temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h new file mode 100644 index 00000000..fbae92c0 --- /dev/null +++ b/telldus-core/service/ProtocolFineoffset.h @@ -0,0 +1,13 @@ +#ifndef PROTOCOLFINEOFFSET_H +#define PROTOCOLFINEOFFSET_H + +#include "ControllerMessage.h" +#include "Protocol.h" + +class ProtocolFineoffset : public Protocol +{ +public: + static std::string decodeData(ControllerMessage &dataMsg); +}; + +#endif //PROTOCOLFINEOFFSET_H From acdf5733a17db8c2c7a45e3d46f685110cb0192e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 20 Dec 2011 15:13:52 +0100 Subject: [PATCH 1739/2215] Fix compilation error using Visual Studio. stdint.h is unfortunately not available --- telldus-core/service/ProtocolFineoffset.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index 4883c92b..31d150a0 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -1,8 +1,13 @@ #include "ProtocolFineoffset.h" #include -#include #include #include +#ifdef _MSC_VER +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +#else +#include +#endif std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) { From 084930a74e47b7352a803319e7c60aa0e57c1f78 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 20 Dec 2011 16:43:41 +0100 Subject: [PATCH 1740/2215] Remove OS X specific finding of QtUiTools. The variable QT_USE_QTUITOOLS seems to work by itself instead --- telldus-gui/TelldusCenter/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index f610ee08..8ec1b15b 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -65,10 +65,6 @@ ADD_DEFINITIONS( -DVERSION=${DISPLAYED_VERSION} ) SET( telldus-center_TARGET TelldusCenter ) IF (APPLE) #### Mac OS X #### - FIND_PACKAGE(Qt4 COMPONENTS QtUiTools REQUIRED) - LIST(APPEND telldus-center_LIBRARIES - ${QT_QTUITOOLS_LIBRARY} - ) INCLUDE_DIRECTORIES( /usr/include/QtUiTools ) From c03018543841758cb1fe3f3083fbe3f54e3eb535 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 21 Dec 2011 13:56:35 +0100 Subject: [PATCH 1741/2215] Implement Oregon short format and sensor 0xEA4C --- telldus-core/service/CMakeLists.txt | 2 + telldus-core/service/Protocol.cpp | 7 +++ telldus-core/service/ProtocolOregon.cpp | 74 +++++++++++++++++++++++++ telldus-core/service/ProtocolOregon.h | 17 ++++++ 4 files changed, 100 insertions(+) create mode 100644 telldus-core/service/ProtocolOregon.cpp create mode 100644 telldus-core/service/ProtocolOregon.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 5a1e1b8a..d402eb11 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -46,6 +46,8 @@ SET( telldus-service_protocol_SRCS ProtocolIkea.cpp ProtocolNexa.h ProtocolNexa.cpp + ProtocolOregon.h + ProtocolOregon.cpp ProtocolRisingSun.h ProtocolRisingSun.cpp ProtocolSartano.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 8b9a00c2..26740f6f 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -11,6 +11,7 @@ #include "ProtocolHasta.h" #include "ProtocolIkea.h" #include "ProtocolNexa.h" +#include "ProtocolOregon.h" #include "ProtocolRisingSun.h" #include "ProtocolSartano.h" #include "ProtocolScene.h" @@ -238,6 +239,12 @@ std::list Protocol::decodeData(const std::string &fullData) { retval.push_back(decoded); } } + else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) { + decoded = ProtocolOregon::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { decoded = ProtocolX10::decodeData(dataMsg); if (decoded != "") { diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp new file mode 100644 index 00000000..1909de9c --- /dev/null +++ b/telldus-core/service/ProtocolOregon.cpp @@ -0,0 +1,74 @@ +#include "ProtocolOregon.h" +#include +#include +#include +#ifdef _MSC_VER +typedef unsigned __int8 uint8_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif + +std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + + std::wstring model = dataMsg.model(); + if (model.compare(L"0xEA4C") == 0) { + return decodeEA4C(data); + } else if (model.compare(L"0x1A2D")) { + return decode1A2D(data); + } + + return ""; +} + +std::string ProtocolOregon::decodeEA4C(const std::string &data) { + uint64_t value = strtol(data.c_str(), NULL, 16); + + uint8_t checksum = 0xE + 0xA + 0x4 + 0xC; + checksum -= (value & 0xF) * 0x10; + checksum -= 0xA; + value >>= 8; + + uint8_t checksumw = (value >> 4) & 0xF; + bool neg = value & (1 << 3); + checksum += (value & 0xF); + value >>= 8; + + uint8_t temp2 = value & 0xF; + uint8_t temp1 = (value >> 4) & 0xF; + checksum += temp2 + temp1; + value >>= 8; + + uint8_t temp3 = (value >> 4) & 0xF; + checksum += (value & 0xF) + temp3; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t address = value & 0xFF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t channel = (value >> 4) & 0x7; + + if (checksum != checksumw) { + return ""; + } + + double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; + if (neg) { + temperature = -temperature; + } + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:EA4C;id:" << (int)address + << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + + return retString.str(); +} + +std::string ProtocolOregon::decode1A2D(const std::string &data) { + //TODO + return ""; +} diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h new file mode 100644 index 00000000..8d8c3c8f --- /dev/null +++ b/telldus-core/service/ProtocolOregon.h @@ -0,0 +1,17 @@ +#ifndef PROTOCOLOREGON_H +#define PROTOCOLOREGON_H + +#include "ControllerMessage.h" +#include "Protocol.h" + +class ProtocolOregon : public Protocol +{ +public: + static std::string decodeData(ControllerMessage &dataMsg); + +protected: + static std::string decodeEA4C(const std::string &data); + static std::string decode1A2D(const std::string &data); +}; + +#endif //PROTOCOLOREGON_H From 16a9b87fb6b5854a5f5d03b98cb7393a367399ef Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 21 Dec 2011 15:57:45 +0100 Subject: [PATCH 1742/2215] Implement sensor Mandolyn, this closes #104 --- telldus-core/service/CMakeLists.txt | 2 ++ telldus-core/service/Protocol.cpp | 7 ++++ telldus-core/service/ProtocolMandolyn.cpp | 44 +++++++++++++++++++++++ telldus-core/service/ProtocolMandolyn.h | 13 +++++++ 4 files changed, 66 insertions(+) create mode 100644 telldus-core/service/ProtocolMandolyn.cpp create mode 100644 telldus-core/service/ProtocolMandolyn.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index d402eb11..f50c8334 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -44,6 +44,8 @@ SET( telldus-service_protocol_SRCS ProtocolHasta.cpp ProtocolIkea.h ProtocolIkea.cpp + ProtocolMandolyn.h + ProtocolMandolyn.cpp ProtocolNexa.h ProtocolNexa.cpp ProtocolOregon.h diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 26740f6f..0a2be23c 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -10,6 +10,7 @@ #include "ProtocolGroup.h" #include "ProtocolHasta.h" #include "ProtocolIkea.h" +#include "ProtocolMandolyn.h" #include "ProtocolNexa.h" #include "ProtocolOregon.h" #include "ProtocolRisingSun.h" @@ -239,6 +240,12 @@ std::list Protocol::decodeData(const std::string &fullData) { retval.push_back(decoded); } } + else if(TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) { + decoded = ProtocolMandolyn::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) { decoded = ProtocolOregon::decodeData(dataMsg); if (decoded != "") { diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp new file mode 100644 index 00000000..420d6bdb --- /dev/null +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -0,0 +1,44 @@ +#include "ProtocolMandolyn.h" +#include +#include +#include + +#ifdef _MSC_VER +typedef unsigned __int8 uint8_t; +typedef unsigned __int32 uint32_t; +#else +#include +#endif + +std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + uint32_t value = strtol(data.c_str(), NULL, 16); + + bool parity = value & 0x1; + value >>= 1; + + double temp = (value & 0x7FFF) - 6400; + temp = temp/128.0; + value >>= 15; + + uint8_t humidity = (value & 0x7F); + value >>= 7; + + bool battOk = value & 0x1; + value >>= 3; + + uint8_t channel = (value & 0x3)+1; + value >>= 2; + + uint8_t house = value & 0xF; + + std::stringstream retString; + retString << "class:sensor;protocol:mandolyn;id:" + << house*10+channel + << ";model:temperaturehumidity;" + << "temp:" << std::fixed << std::setprecision(1) << temp + << ";humidity:" << (int)humidity << ";"; + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h new file mode 100644 index 00000000..a3ff0700 --- /dev/null +++ b/telldus-core/service/ProtocolMandolyn.h @@ -0,0 +1,13 @@ +#ifndef PROTOCOLMANDOLYN_H +#define PROTOCOLMANDOLYN_H + +#include "ControllerMessage.h" +#include "Protocol.h" + +class ProtocolMandolyn : public Protocol +{ +public: + static std::string decodeData(ControllerMessage &dataMsg); +}; + +#endif //PROTOCOLMANDOLYN_H From 319e505509161d34cfda1a65cd7b0eac0841c4e5 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 22 Dec 2011 12:10:48 +0100 Subject: [PATCH 1743/2215] Now possible to activate Telldus Live! from Settings. Closes #101. --- telldus-gui/Plugins/Live/__init__.js | 10 ++ telldus-gui/Plugins/Live/configuration.ui | 136 +++++++++++++++++----- 2 files changed, 119 insertions(+), 27 deletions(-) diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 64a851ea..22d2e6d8 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -19,6 +19,7 @@ com.telldus.live = function() { socket.connectToServer(); com.telldus.core.deviceEvent.connect(deviceEvent); com.telldus.core.deviceChange.connect(sendDevicesReport); + configUI.findChild('registrationLink').visible = false; } function notRegistered() { @@ -28,6 +29,7 @@ com.telldus.live = function() { menuId = com.telldus.systray.addMenuItem( qsTr("Activate Telldus Live!") ); com.telldus.systray.menuItem(menuId).triggered.connect(socket.activate); } + registrationLinkVisible(true); } function deviceEvent(deviceId, method, data) { @@ -63,9 +65,17 @@ com.telldus.live = function() { } supportedMethods = msg.getInt('supportedMethods'); isRegistered = true; + registrationLinkVisible(false); sendDevicesReport(); } + function registrationLinkVisible(visibleParam){ + configUI.findChild('registrationLink').visible = visibleParam; + if(visibleParam){ + configUI.findChild('registrationLink').clicked.connect(socket.activate); + } + } + function sendDevicesReport() { if (!isRegistered) { return; diff --git a/telldus-gui/Plugins/Live/configuration.ui b/telldus-gui/Plugins/Live/configuration.ui index 608ffc5a..07b51802 100644 --- a/telldus-gui/Plugins/Live/configuration.ui +++ b/telldus-gui/Plugins/Live/configuration.ui @@ -7,38 +7,120 @@ 0 0 323 - 263 + 251 + + + 0 + 0 + + Form - - - - - Status: - - - - - - - unknown - - - - - - - - - - true - - - - + + + + 0 + 0 + 331 + 251 + + + + + + + + + Status: + + + + + + + unknown + + + true + + + + + + + + + + true + + + + + + + Activate Telldus Live! + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + From 6f2ea98c5c5d5a9d5963f0d08957b7f523389aa9 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 22 Dec 2011 12:31:17 +0100 Subject: [PATCH 1744/2215] Optimization for #101. --- telldus-gui/Plugins/Live/__init__.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 22d2e6d8..4f292f7e 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -19,6 +19,7 @@ com.telldus.live = function() { socket.connectToServer(); com.telldus.core.deviceEvent.connect(deviceEvent); com.telldus.core.deviceChange.connect(sendDevicesReport); + configUI.findChild('registrationLink').clicked.connect(socket.activate); configUI.findChild('registrationLink').visible = false; } @@ -71,9 +72,6 @@ com.telldus.live = function() { function registrationLinkVisible(visibleParam){ configUI.findChild('registrationLink').visible = visibleParam; - if(visibleParam){ - configUI.findChild('registrationLink').clicked.connect(socket.activate); - } } function sendDevicesReport() { From e3587763eeea11df1605cd14a9d36fef88d29511 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 23 Dec 2011 12:46:17 +0100 Subject: [PATCH 1745/2215] Fixed so that receiving socket has no buffer limit when reading in Linux. See ticket #101. --- telldus-core/common/Socket_unix.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 35045c20..c98e0f94 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -78,9 +78,9 @@ std::wstring Socket::read() { std::wstring Socket::read(int timeout) { struct timeval tv; char inbuf[BUFSIZE]; - memset(inbuf, '\0', sizeof(inbuf)); FD_SET(d->socket, &d->infds); + std::string msg; while(isConnected()) { tv.tv_sec = floor(timeout / 1000.0); tv.tv_usec = timeout % 1000; @@ -93,15 +93,21 @@ std::wstring Socket::read(int timeout) { continue; } - int received = recv(d->socket, inbuf, BUFSIZE - 1, 0); - if (received <= 0) { + int received = BUFSIZE; + while(received >= (BUFSIZE - 1)){ + memset(inbuf, '\0', sizeof(inbuf)); + received = recv(d->socket, inbuf, BUFSIZE - 1, 0); + if(received > 0){ + msg.append(std::string(inbuf)); + } + } + if (received < 0) { TelldusCore::MutexLocker locker(&d->mutex); d->connected = false; } break; } - std::string msg(inbuf); return TelldusCore::charToWstring(msg.c_str()); } From d7e76f1bc1c1fe90714442f13e09c651980b08b5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Oct 2011 17:02:34 +0200 Subject: [PATCH 1746/2215] Show an error message if an unknown option is supplied to telldusd in Linux --- telldus-core/service/main_unix.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 7bfc36c5..db97ccbb 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -46,17 +46,18 @@ int main(int argc, char **argv) { for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--nodaemon") == 0) { deamonize = false; - } - if (strcmp(argv[i], "--help") == 0) { + } else if (strcmp(argv[i], "--help") == 0) { printf("Telldus TellStick background service\n\nStart with --nodaemon to not run as daemon\n\n"); printf("Report bugs to \n"); exit(EXIT_SUCCESS); - } - if (strcmp(argv[i], "--version") == 0) { + } else if (strcmp(argv[i], "--version") == 0) { printf("telldusd " VERSION "\n\n"); printf("Copyright (C) 2011 Telldus Technologies AB\n\n"); printf("Written by Micke Prag \n"); exit(EXIT_SUCCESS); + } else { + printf("Unknown option %s\n", argv[i]); + exit(EXIT_FAILURE); } } From 72188ef02f352e9596781d57280c2bff6dfca357 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 27 Dec 2011 14:47:40 +0100 Subject: [PATCH 1747/2215] Add Log class, only implemented for Linux. See #103 --- telldus-core/service/CMakeLists.txt | 3 + telldus-core/service/Log.cpp | 106 ++++++++++++++++++++++++++++ telldus-core/service/Log.h | 30 ++++++++ 3 files changed, 139 insertions(+) create mode 100644 telldus-core/service/Log.cpp create mode 100644 telldus-core/service/Log.h diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index f50c8334..a3109036 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -19,6 +19,7 @@ SET( telldus-service_SRCS Device.cpp DeviceManager.cpp Event.cpp + Log.cpp Sensor.cpp Settings.cpp TelldusMain.cpp @@ -78,6 +79,7 @@ SET( telldus-service_HDRS DeviceManager.h Event.h EventHandler.h + Log.h Sensor.h Settings.h TelldusMain.h @@ -144,6 +146,7 @@ ELSE (APPLE) #### Linux #### SET(DEFAULT_FTDI_ENGINE "libftdi") FIND_LIBRARY(CONFUSE_LIBRARY confuse) ADD_DEFINITIONS( -D_CONFUSE ) + ADD_DEFINITIONS( -D_LINUX ) SET( telldus-service_TARGET telldusd ) LIST(APPEND telldus-service_SRCS diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp new file mode 100644 index 00000000..318bcb16 --- /dev/null +++ b/telldus-core/service/Log.cpp @@ -0,0 +1,106 @@ +#include "Log.h" +#include + +#ifdef _LINUX +#include +#endif + +class Log::PrivateData { +public: + PrivateData() : logOutput(Log::System) {} + + Log::LogOutput logOutput; + + static Log *instance; +}; + +Log *Log::PrivateData::instance = 0; + +Log::Log() + :d(new PrivateData) +{ +#ifdef _LINUX + setlogmask(LOG_UPTO(LOG_INFO)); + openlog("telldusd", LOG_CONS, LOG_USER); +#endif +} + +Log::~Log() { + delete d; +#ifdef _LINUX + closelog(); +#endif +} + +void Log::debug(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Debug, fmt, ap); + va_end(ap); +} + +void Log::notice(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Notice, fmt, ap); + va_end(ap); +} + +void Log::warning(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Warning, fmt, ap); + va_end(ap); +} + +void Log::error(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Error, fmt, ap); + va_end(ap); +} + +void Log::setLogOutput(LogOutput logOutput) { + Log *log = Log::instance(); + log->d->logOutput = logOutput; +} + +void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const { + if (d->logOutput == StdOut) { + FILE *stream = stdout; + if (logLevel == Warning || logLevel == Error) { + stream = stderr; + } + vfprintf(stream, format, ap); + fprintf(stream, "\n"); + fflush(stream); + } else { +#ifdef _LINUX + switch (logLevel) { + case Debug: + vsyslog(LOG_DEBUG, format, ap); + break; + case Notice: + vsyslog(LOG_NOTICE, format, ap); + break; + case Warning: + vsyslog(LOG_WARNING, format, ap); + break; + case Error: + vsyslog(LOG_ERR, format, ap); + break; + } +#endif + } +} + +Log *Log::instance() { + if (PrivateData::instance == 0) { + PrivateData::instance = new Log(); + } + return PrivateData::instance; +} diff --git a/telldus-core/service/Log.h b/telldus-core/service/Log.h new file mode 100644 index 00000000..3fa199f5 --- /dev/null +++ b/telldus-core/service/Log.h @@ -0,0 +1,30 @@ +#ifndef LOG_H +#define LOG_H + +#include + +class Log { +public: + enum LogLevel { Debug, Notice, Warning, Error }; + enum LogOutput { StdOut, System }; + virtual ~Log(); + + static void debug(const char *fmt, ...); + static void notice(const char *fmt, ...); + static void warning(const char *fmt, ...); + static void error(const char *fmt, ...); + + static void setLogOutput(LogOutput logOutput); + +protected: + Log(); + void message(LogLevel logLevel, const char *format, va_list ap) const; + static Log *instance(); + +private: + class PrivateData; + PrivateData *d; +}; + + +#endif //LOG_H From 83fb477ef48ee16575dfdabd9212625eb2d52be8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 27 Dec 2011 15:46:49 +0100 Subject: [PATCH 1748/2215] Use the log-system in main_unix.cpp --- telldus-core/service/main_unix.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index db97ccbb..b68d13b7 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -12,6 +11,7 @@ #include "Settings.h" #include "Strings.h" +#include "Log.h" #define DAEMON_NAME "telldusd" #define PID_FILE "/var/run/" DAEMON_NAME ".pid" @@ -21,19 +21,19 @@ TelldusMain tm; void signalHandler(int sig) { switch(sig) { case SIGHUP: - syslog(LOG_WARNING, "Received SIGHUP signal."); + Log::warning("Received SIGHUP signal."); break; case SIGTERM: case SIGINT: - syslog(LOG_WARNING, "Received SIGTERM or SIGINT signal."); - syslog(LOG_WARNING, "Shutting down"); + Log::warning("Received SIGTERM or SIGINT signal."); + Log::warning("Shutting down"); tm.stop(); break; case SIGPIPE: - syslog(LOG_WARNING, "Received SIGPIPE signal."); + Log::warning("Received SIGPIPE signal."); break; default: - syslog(LOG_WARNING, "Unhandled signal (%d) %s", sig, strsignal(sig)); + Log::warning("Unhandled signal (%d) %s", sig, strsignal(sig)); break; } } @@ -46,6 +46,7 @@ int main(int argc, char **argv) { for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--nodaemon") == 0) { deamonize = false; + Log::setLogOutput(Log::StdOut); } else if (strcmp(argv[i], "--help") == 0) { printf("Telldus TellStick background service\n\nStart with --nodaemon to not run as daemon\n\n"); printf("Report bugs to \n"); @@ -77,17 +78,14 @@ int main(int argc, char **argv) { fprintf(fd,"%d\n",pid); fclose(fd); } else { - syslog(LOG_ERR, "Could not open pid file %s: %s", PID_FILE, strerror(errno)); + Log::error("Could not open pid file %s: %s", PID_FILE, strerror(errno)); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } } - setlogmask(LOG_UPTO(LOG_INFO)); - openlog(DAEMON_NAME, LOG_CONS, LOG_USER); - - syslog(LOG_NOTICE, "%s daemon starting up", DAEMON_NAME); + Log::notice("%s daemon starting up", DAEMON_NAME); if (deamonize) { /* Change the file mode mask */ @@ -116,14 +114,14 @@ int main(int argc, char **argv) { if (grp) { setgid(grp->gr_gid); } else { - syslog(LOG_WARNING, "Group %s could not be found", group.c_str()); + Log::warning("Group %s could not be found", group.c_str()); exit(EXIT_FAILURE); } struct passwd *pw = getpwnam(user.c_str()); if (pw) { setuid( pw->pw_uid ); } else { - syslog(LOG_WARNING, "User %s could not be found", user.c_str()); + Log::warning("User %s could not be found", user.c_str()); exit(EXIT_FAILURE); } } @@ -140,6 +138,6 @@ int main(int argc, char **argv) { tm.start(); - syslog(LOG_NOTICE, "%s daemon exited", DAEMON_NAME); + Log::notice("%s daemon exited", DAEMON_NAME); exit(EXIT_SUCCESS); } From 81671d160764c227b981ade81be7b91b2a70bc10 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 28 Dec 2011 10:56:44 +0100 Subject: [PATCH 1749/2215] Fixed so that receiving socket has no buffer limit when reading in Windows. Closes #145. --- telldus-core/common/Socket_win.cpp | 69 +++++++++++++++++------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index e0cb50a5..3ed727d3 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -93,42 +93,53 @@ std::wstring Socket::read(int timeout){ d->readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); oOverlap.hEvent = d->readEvent; BOOL fSuccess = false; + std::wstring returnString; + bool moreData = true; - memset(&buf, 0, BUFSIZE); + while(moreData){ + moreData = false; + memset(&buf, 0, sizeof(buf)); - ReadFile( d->hPipe, &buf, sizeof(wchar_t)*BUFSIZE, &cbBytesRead, &oOverlap); - - result = WaitForSingleObject(oOverlap.hEvent, timeout); - - if(!d->running){ - CancelIo(d->hPipe); - CloseHandle(d->readEvent); - //debuglog(1, "Not running"); - return L""; - } - - if (result == WAIT_TIMEOUT) { - CancelIo(d->hPipe); - CloseHandle(d->readEvent); - //debuglog(1, "Wait timeout"); - return L""; - } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); - if (!fSuccess) { - DWORD err = GetLastError(); - //debuglog(result, "This then?"); - //debuglog(1, "Unsuccessful"); + ReadFile( d->hPipe, &buf, sizeof(buf)-sizeof(wchar_t), &cbBytesRead, &oOverlap); - if (err == ERROR_BROKEN_PIPE) { - //debuglog(1, "Broken pipe"); - d->connected = false; + result = WaitForSingleObject(oOverlap.hEvent, timeout); + + if(!d->running){ + CancelIo(d->hPipe); + CloseHandle(d->readEvent); + //debuglog(1, "Not running"); + return L""; } - buf[0] = 0; - } + if (result == WAIT_TIMEOUT) { + CancelIo(d->hPipe); + CloseHandle(d->readEvent); + //debuglog(1, "Wait timeout"); + return L""; + } + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); + + if (!fSuccess) { + DWORD err = GetLastError(); + + //debuglog(result, "This then?"); + //debuglog(1, "Unsuccessful"); + if(err == ERROR_MORE_DATA){ + moreData = true; + } + else{ + buf[0] = 0; + } + if (err == ERROR_BROKEN_PIPE) { + //debuglog(1, "Broken pipe"); + d->connected = false; + } + } + returnString.append(buf); + } CancelIo(d->hPipe); CloseHandle(d->readEvent); - return buf; + return returnString; } void Socket::write(const std::wstring &msg){ From 86554b26ac832b1cd56c33d3731bad312f2177b6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 28 Dec 2011 11:14:59 +0100 Subject: [PATCH 1750/2215] Code cleanup --- telldus-core/client/Client.cpp | 29 ++----------------- telldus-core/common/Socket_win.cpp | 8 ----- .../service/ClientCommunicationHandler.cpp | 5 +--- telldus-core/service/DeviceManager.cpp | 3 +- telldus-core/service/EventUpdateManager.cpp | 3 -- telldus-core/service/SettingsWinRegistry.cpp | 21 +------------- 6 files changed, 5 insertions(+), 64 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 3a4c6fdd..3ddf7f36 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -130,7 +130,6 @@ int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { callback->id = id; callback->context = context; d->deviceEventList.push_back(callback); - //debuglog(id, "deviceeventadded"); return id; } @@ -142,7 +141,6 @@ int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void * callback->id = id; callback->context = context; d->deviceChangeEventList.push_back(callback); - //debuglog(id, "devicechangeeventadded"); return id; } @@ -178,7 +176,6 @@ void Client::run(){ d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service if(!d->eventSocket.isConnected()){ //reconnect didn't succeed, wait a while and try again - //debuglog(0, "Reconnecting"); msleep(2000); continue; } @@ -186,16 +183,7 @@ void Client::run(){ std::wstring clientMessage = d->eventSocket.read(5000); //testing 5 second timeout - //int test = 0; - /*if(clientMessage != L""){ - debuglog(88, "Clientmessage nothing after read"); - }*/ while(clientMessage != L""){ - //debuglog(99, TelldusCore::wideToString(clientMessage)); - //test++; - /*if(test > 5){ - debuglog(test, "Test is getting big"); - }*/ //a message arrived std::wstring type = Message::takeString(&clientMessage); if(type == L"TDDeviceChangeEvent"){ @@ -298,9 +286,7 @@ std::wstring Client::sendToService(const Message &msg) { int tries = 0; std::wstring readData; - //debuglog(3, "PRETEST"); while(tries < 20){ - //debuglog(3, "PRETESTINNE"); tries++; if(tries == 20){ TelldusCore::Message msg; @@ -310,37 +296,27 @@ std::wstring Client::sendToService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); if (!s.isConnected()) { //Connection failed - //debuglog(3, "Ett)"); //deviceeventscallbacks verkar sluta fungera vid/med ett sådant här!? njä, bara ngn ggn... msleep(500); continue; //retry } s.write(msg.data()); if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) - //debuglog(3, "Två"); msleep(500); continue; //retry } - readData = s.read(5000); //500 + readData = s.read(5000); if(readData == L""){ - //debuglog(3, "Empty result (may be ok?)"); - /* - if this is enabled, all "send" will run 20 times... - NO! That was due to too short timeout in s.read, turnOn didn't havee titme otecxeu - if it's NOT enabled, tdGetName will often return empty... - */ msleep(500); - continue; //TODO cannot be sure it SHOULD be anything... right? - + continue; //TODO can we be really sure it SHOULD be anything? } if (!s.isConnected()) { //Connection failed sometime during operation... - //debuglog(3, "Not connected"); msleep(500); continue; //retry } break; } - //debuglog(3, "POSTTEST"); return readData; } @@ -350,7 +326,6 @@ void Client::stopThread(){ } bool Client::unregisterCallback( int callbackId ) { - //debuglog(callbackId, "unregistering"); DeviceEventList newDEList; { TelldusCore::MutexLocker locker(&d->mutex); diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 3ed727d3..52e82a98 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -1,5 +1,4 @@ #include "Socket.h" -#include "common.h" #include #include @@ -107,14 +106,12 @@ std::wstring Socket::read(int timeout){ if(!d->running){ CancelIo(d->hPipe); CloseHandle(d->readEvent); - //debuglog(1, "Not running"); return L""; } if (result == WAIT_TIMEOUT) { CancelIo(d->hPipe); CloseHandle(d->readEvent); - //debuglog(1, "Wait timeout"); return L""; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); @@ -122,8 +119,6 @@ std::wstring Socket::read(int timeout){ if (!fSuccess) { DWORD err = GetLastError(); - //debuglog(result, "This then?"); - //debuglog(1, "Unsuccessful"); if(err == ERROR_MORE_DATA){ moreData = true; } @@ -131,7 +126,6 @@ std::wstring Socket::read(int timeout){ buf[0] = 0; } if (err == ERROR_BROKEN_PIPE) { - //debuglog(1, "Broken pipe"); d->connected = false; } } @@ -161,7 +155,6 @@ void Socket::write(const std::wstring &msg){ CancelIo(d->hPipe); CloseHandle(writeEvent); d->connected = false; - //debuglog(2, "Wait timeout"); return; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); @@ -169,7 +162,6 @@ void Socket::write(const std::wstring &msg){ if (!fSuccess) { CancelIo(d->hPipe); d->connected = false; - //debuglog(2, "Unsuccessful"); return; } } diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 8946017e..d75c674f 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -76,15 +76,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, if (function == L"tdTurnOn") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); + } else if (function == L"tdTurnOff") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0); } else if (function == L"tdBell") { - //TelldusCore::Message msg2; - //msg2.addSpecialArgument(18); - //msg2.addSpecialArgument("testgrej"); - int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 7a17eb12..d33c36a2 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -5,7 +5,6 @@ #include "Settings.h" #include "Strings.h" #include "Message.h" -#include "common.h" #include #include @@ -479,7 +478,7 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c deviceReturnValue = doAction(deviceId, action, data); } else if(childType == TELLSTICK_TYPE_SCENE){ - deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes (and test) infinite loops-safe + deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes infinite loops-safe } else{ //group (in group) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 6200eddd..5594e12a 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -4,7 +4,6 @@ #include "EventHandler.h" #include "Message.h" #include "Socket.h" -//#include "common.h" //debug #include #include @@ -117,6 +116,4 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ it = d->clients.erase(it); } } - //debuglog(connected, " - number of clients"); - //debuglog(temp2, " - number of clients total"); } diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 0ca1fcec..aed7ad3a 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -95,9 +95,6 @@ int Settings::addDevice() { DWORD dwDisp; intDeviceId = getNextDeviceId(); - //std::wostringstream ssRegPath; - //ssRegPath << d->strRegPathDevice << intDeviceId; - //std::wstring strCompleteRegPath = ssRegPath.str(); std::wstring strCompleteRegPath = d->strRegPathDevice; strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); @@ -126,7 +123,7 @@ int Settings::getNextDeviceId() const { DWORD dwLength; DWORD nResult(0); - long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); //(LPBYTE)Buff, &dwLength); + long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); if(lngStatus == ERROR_SUCCESS){ intReturn = nResult + 1; @@ -147,9 +144,6 @@ int Settings::getNextDeviceId() const { int Settings::removeDevice(int intDeviceId) { TelldusCore::MutexLocker locker(&mutex); - //std::wostringstream ssRegPath; - //ssRegPath << d->strRegPathDevice << intDeviceId; - //std::wstring strCompleteRegPath = ssRegPath.str(); std::wstring strCompleteRegPath = d->strRegPathDevice; strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); @@ -167,9 +161,6 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam std::wstring strReturn; HKEY hk; - //std::wostringstream ssRegPath; - //ssRegPath << d->strRegPathDevice << intDeviceId; - //std::wstring strCompleteRegPath = ssRegPath.str(); std::wstring strCompleteRegPath = d->strRegPathDevice; strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); @@ -199,16 +190,9 @@ int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const HKEY hk; int ret = TELLSTICK_SUCCESS; - //std::wostringstream ssRegPath; - //ssRegPath << d->strRegPathDevice << intDeviceId; - //std::wstring strCompleteRegPath = ssRegPath.str(); - //debuglog(intDeviceId, "Device id"); std::wstring bla = TelldusCore::intToWstring(intDeviceId); - //debuglog(888, TelldusCore::wideToString(bla)); - //debuglog(555, TelldusCore::wideToString(d->strRegPathDevice)); std::wstring strCompleteRegPath = d->strRegPathDevice; strCompleteRegPath.append(bla); - //debuglog(999, TelldusCore::wideToString(strCompleteRegPath)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS){ @@ -238,9 +222,6 @@ int Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value int intReturn = TELLSTICK_ERROR_UNKNOWN; HKEY hk; - //std::wostringstream ssRegPath; - //ssRegPath << d->strRegPathDevice << intDeviceId; - //std::wstring strCompleteRegPath = ssRegPath.str(); std::wstring strCompleteRegPath = d->strRegPathDevice; strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); From b6fb5ce106ed038b516319e81b7117b7a36ec8ac Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 28 Dec 2011 14:50:56 +0100 Subject: [PATCH 1751/2215] Sensors now visible in tdtool when running --list. Closes #122. --- telldus-core/tdtool/main.cpp | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index fe9f369e..c81fe550 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "../client/telldus-core.h" const int SUPPORTED_METHODS = @@ -21,7 +22,7 @@ void print_usage( char *name ) { printf(" [ --raw input ]\n"); printf("\n"); printf(" --list (-l short option)\n"); - printf(" List currently configured devices.\n"); + printf(" List currently configured devices and all discovered sensors.\n"); printf("\n"); printf(" --help (-h short option)\n"); printf(" Shows this screen.\n"); @@ -115,6 +116,46 @@ void list_devices() { print_device( i ); i++; } + + int DATA_LENGTH = 20; + char protocol[DATA_LENGTH], model[DATA_LENGTH]; + int sensorId = 0, dataTypes = 0; + + int sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + if(sensorStatus == 0){ + printf("\nSENSORS:\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED"); + } + while(sensorStatus == 0){ + sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + + char tempvalue[DATA_LENGTH]; + tempvalue[0] = 0; + char humidityvalue[DATA_LENGTH]; + humidityvalue[0] = 0; + char timeBuf[80]; + time_t timestamp = 0; + + if (dataTypes & TELLSTICK_TEMPERATURE) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp); + strcat(tempvalue, "°"); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + + if (dataTypes & TELLSTICK_HUMIDITY) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp); + strcat(humidityvalue, "%"); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf); + + printf("\n"); + } + if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){ + char *errorString = tdGetErrorString(sensorStatus); + fprintf(stderr, "Error fetching sensors: %s\n", errorString); + tdReleaseString(errorString); + return; + } } int find_device( char *device ) { From 50e69a476cde16d6a76f84133667182ecc4de8e3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 28 Dec 2011 15:18:31 +0100 Subject: [PATCH 1752/2215] Implement logging using Windows Event Log, see #103 --- telldus-core/service/CMakeLists.txt | 11 +++ telldus-core/service/Log.cpp | 69 ++++++++++++++++-- telldus-core/service/Log.h | 2 + telldus-core/service/Messages.mc | Bin 0 -> 1158 bytes .../service/TelldusWinService_win.cpp | 6 ++ 5 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 telldus-core/service/Messages.mc diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index a3109036..8fc6125c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -137,10 +137,21 @@ ELSEIF (WIN32) #### Windows #### main_win.cpp SettingsWinRegistry.cpp TelldusWinService_win.cpp + Messages.mc + ${CMAKE_CURRENT_BINARY_DIR}/Messages.rc + ${CMAKE_CURRENT_BINARY_DIR}/Messages.h ) LIST(APPEND telldus-service_HDRS TelldusWinService_win.h ) + ADD_CUSTOM_COMMAND( + OUTPUT Messages.rc Messages.h + COMMAND mc.exe -u -r ${CMAKE_CURRENT_BINARY_DIR} -h ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc + DEPENDS Messages.rc + COMMENT "Compiling Messages Resource" + ) + INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ) ELSE (APPLE) #### Linux #### SET(DEFAULT_FTDI_ENGINE "libftdi") diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 318bcb16..0282f9de 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -1,8 +1,12 @@ #include "Log.h" #include -#ifdef _LINUX +#if defined(_LINUX) #include +#elif defined(_WINDOWS) +#include +#include "Strings.h" +#include "Messages.h" #endif class Log::PrivateData { @@ -12,6 +16,9 @@ public: Log::LogOutput logOutput; static Log *instance; +#ifdef _WINDOWS + HANDLE eventSource; +#endif }; Log *Log::PrivateData::instance = 0; @@ -19,17 +26,50 @@ Log *Log::PrivateData::instance = 0; Log::Log() :d(new PrivateData) { -#ifdef _LINUX +#if defined(_LINUX) setlogmask(LOG_UPTO(LOG_INFO)); openlog("telldusd", LOG_CONS, LOG_USER); +#elif defined(_WINDOWS) + //Add ourselves to the registy + HKEY hRegKey = NULL; + DWORD dwError = 0; + TCHAR filePath[MAX_PATH]; + + std::wstring path(L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\TelldusService"); + dwError = RegCreateKey( HKEY_LOCAL_MACHINE, path.c_str(), &hRegKey ); + + GetModuleFileName( NULL, filePath, MAX_PATH ); + dwError = RegSetValueEx( hRegKey, L"EventMessageFile", 0, + REG_EXPAND_SZ, (PBYTE) filePath, + (DWORD)(wcslen(filePath) + 1) * sizeof TCHAR ); + + DWORD dwTypes = LOG_DEBUG | LOG_NOTICE | LOG_WARNING | LOG_ERR; + dwError = RegSetValueEx( hRegKey, L"TypesSupported", + 0, REG_DWORD, (LPBYTE) &dwTypes, sizeof dwTypes ); + + RegCloseKey(hRegKey); + + d->eventSource = RegisterEventSource(NULL, L"TelldusService"); #endif } Log::~Log() { - delete d; -#ifdef _LINUX +#if defined(_LINUX) closelog(); +#elif defined(_WINDOWS) + if (d->eventSource != NULL) { + DeregisterEventSource(d->eventSource); + } #endif + delete d; +} + +void Log::destroy() { + if (PrivateData::instance == 0) { + return; + } + delete PrivateData::instance; + PrivateData::instance = 0; } void Log::debug(const char *fmt, ...) { @@ -79,7 +119,7 @@ void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const fprintf(stream, "\n"); fflush(stream); } else { -#ifdef _LINUX +#if defined(_LINUX) switch (logLevel) { case Debug: vsyslog(LOG_DEBUG, format, ap); @@ -94,6 +134,25 @@ void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const vsyslog(LOG_ERR, format, ap); break; } +#elif defined(_WINDOWS) + LPWSTR pInsertStrings[2] = {NULL, NULL}; + std::wstring str = TelldusCore::charToWstring(format); + pInsertStrings[0] = (LPWSTR)str.c_str(); + + switch (logLevel) { + case Debug: + ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + case Notice: + ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + case Warning: + ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + case Error: + ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + } #endif } } diff --git a/telldus-core/service/Log.h b/telldus-core/service/Log.h index 3fa199f5..4b10728d 100644 --- a/telldus-core/service/Log.h +++ b/telldus-core/service/Log.h @@ -9,6 +9,8 @@ public: enum LogOutput { StdOut, System }; virtual ~Log(); + static void destroy(); + static void debug(const char *fmt, ...); static void notice(const char *fmt, ...); static void warning(const char *fmt, ...); diff --git a/telldus-core/service/Messages.mc b/telldus-core/service/Messages.mc new file mode 100644 index 0000000000000000000000000000000000000000..b7f81b41460477b0b3e06193edfb4e8499597ac5 GIT binary patch literal 1158 zcmdT^!D_-l5PfH%{}2$NrJybJq9KR2hBRPPFiMX>tBnDThp6b!Yu`+=!uFyR50+t> z-Oaq2H!r(;*t@7B!#8qFFr{~p(B9!AradFjS%Np+zd;RxC}T6Cre`4pC!>cEF)7yc zDX|g#g1%rDPa_=8#BQyX+4U7YC*uM$#W;Atmg9+|jSiVhwxY^kkhRY$Lo3^zuF76o zxU88@UCryT`i6{htjNj!W>(^D)*k@F;X>eM?T|G32e0N5UmX8-^I literal 0 HcmV?d00001 diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index a7c48322..3deeba9a 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -1,5 +1,6 @@ #include "TelldusWinService_win.h" #include "TelldusMain.h" +#include "Log.h" #include #include @@ -140,8 +141,13 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW; HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE); + Log::notice("TelldusService started"); + //Start our main-loop instance.tm->start(); + + Log::notice("TelldusService stopping"); + Log::destroy(); // service was stopped instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; From 98624032674044df121f5cf446fa6d9e1e287c1d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 28 Dec 2011 15:23:59 +0100 Subject: [PATCH 1753/2215] Add command line argument to debug output --- telldus-core/service/Log.cpp | 11 ++++++++++- telldus-core/service/Log.h | 1 + telldus-core/service/TelldusWinService_win.cpp | 7 +++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 0282f9de..f15dd92f 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -11,9 +11,10 @@ class Log::PrivateData { public: - PrivateData() : logOutput(Log::System) {} + PrivateData() : logOutput(Log::System), debug(false) {} Log::LogOutput logOutput; + bool debug; static Log *instance; #ifdef _WINDOWS @@ -104,12 +105,20 @@ void Log::error(const char *fmt, ...) { va_end(ap); } +void Log::setDebug() { + Log *log = Log::instance(); + log->d->debug = true; +} + void Log::setLogOutput(LogOutput logOutput) { Log *log = Log::instance(); log->d->logOutput = logOutput; } void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const { + if (logLevel == Debug && d->debug == false) { + return; + } if (d->logOutput == StdOut) { FILE *stream = stdout; if (logLevel == Warning || logLevel == Error) { diff --git a/telldus-core/service/Log.h b/telldus-core/service/Log.h index 4b10728d..a2f547c0 100644 --- a/telldus-core/service/Log.h +++ b/telldus-core/service/Log.h @@ -16,6 +16,7 @@ public: static void warning(const char *fmt, ...); static void error(const char *fmt, ...); + static void setDebug(); static void setLogOutput(LogOutput logOutput); protected: diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 3deeba9a..6a415120 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -112,6 +112,13 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { TelldusWinService instance; + //Enable debug if we hade this supplied + for(unsigned int i = 1; i < argc; ++i) { + if (wcscmp(argv[i], L"--debug") == 0) { + Log::setDebug(); + } + } + // initialise service status instance.serviceStatus.dwServiceType = SERVICE_WIN32; instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; From 554601355239a4a3f88df54be14585afb93a6ed0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 28 Dec 2011 15:45:07 +0100 Subject: [PATCH 1754/2215] Tdtool exiting with error codes on failures. Closes #146. --- telldus-core/client/telldus-core.h | 1 + telldus-core/tdtool/main.cpp | 78 +++++++++++++++++++----------- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 1f25e0f3..9d7ee9c2 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -115,6 +115,7 @@ extern "C" { #define TELLSTICK_ERROR_COMMUNICATION -5 #define TELLSTICK_ERROR_CONNECTING_SERVICE -6 #define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7 +#define TELLSTICK_ERROR_SYNTAX -8 #define TELLSTICK_ERROR_UNKNOWN -99 //Device typedef diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index c81fe550..5358f8d4 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -78,6 +78,7 @@ void print_version() { } void print_device( int index ) { + tdInit(); int intId = tdGetDeviceId(index); char *name = tdGetName(intId); printf("%i\t%s\t", intId, name); @@ -102,13 +103,14 @@ void print_device( int index ) { printf("\n"); } -void list_devices() { +int list_devices() { + tdInit(); int intNum = tdGetNumberOfDevices(); if (intNum < 0) { char *errorString = tdGetErrorString(intNum); fprintf(stderr, "Error fetching devices: %s\n", errorString); tdReleaseString(errorString); - return; + return intNum; } printf("Number of devices: %i\n", intNum); int i = 0; @@ -154,11 +156,13 @@ void list_devices() { char *errorString = tdGetErrorString(sensorStatus); fprintf(stderr, "Error fetching sensors: %s\n", errorString); tdReleaseString(errorString); - return; + return sensorStatus; } + return TELLSTICK_SUCCESS; } int find_device( char *device ) { + tdInit(); int deviceId = atoi(device); if (deviceId == 0) { //Try to find the id from the name int intNum = tdGetNumberOfDevices(); @@ -178,11 +182,12 @@ int find_device( char *device ) { return deviceId; } -void switch_device( bool turnOn, char *device ) { +int switch_device( bool turnOn, char *device ) { + tdInit(); int deviceId = find_device( device ); if (deviceId == 0) { printf("Device '%s', not found!\n", device); - return; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } char *name = tdGetName( deviceId ); @@ -199,17 +204,19 @@ void switch_device( bool turnOn, char *device ) { printf(" - %s\n", errorString); tdReleaseString(errorString); + return retval; } -void dim_device( char *device, int level ) { +int dim_device( char *device, int level ) { + tdInit(); int deviceId = find_device( device ); if (deviceId == 0) { printf("Device '%s', not found!\n", device); - return; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } if (level < 0 || level > 255) { printf("Level %i out of range!\n", level); - return; + return TELLSTICK_ERROR_SYNTAX; } char *name = tdGetName( deviceId ); @@ -218,13 +225,15 @@ void dim_device( char *device, int level ) { printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); tdReleaseString(name); tdReleaseString(errorString); + return retval; } -void bell_device( char *device ) { +int bell_device( char *device ) { + tdInit(); int deviceId = find_device( device ); if (deviceId == 0) { printf("Device '%s', not found!\n", device); - return; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } char *name = tdGetName( deviceId ); @@ -233,13 +242,15 @@ void bell_device( char *device ) { printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); tdReleaseString(name); tdReleaseString(errorString); + return retval; } -void learn_device( char *device ) { +int learn_device( char *device ) { + tdInit(); int deviceId = find_device( device ); if (deviceId == 0) { printf("Device '%s', not found!\n", device); - return; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } char *name = tdGetName( deviceId ); @@ -248,9 +259,11 @@ void learn_device( char *device ) { printf("Learning device: %i %s - %s\n", deviceId, name, errorString); tdReleaseString(name); tdReleaseString(errorString); + return retval; } -void send_raw_command( char *command ) { +int send_raw_command( char *command ) { + tdInit(); const int MAX_LENGTH = 100; char msg[MAX_LENGTH]; @@ -262,7 +275,7 @@ void send_raw_command( char *command ) { fd = fopen(command, "r"); if (fd == NULL) { printf("Error opening file %s\n", command); - return; + return TELLSTICK_ERROR_UNKNOWN; } fgets(msg, MAX_LENGTH, fd); } @@ -271,6 +284,7 @@ void send_raw_command( char *command ) { char *errorString = tdGetErrorString(retval); printf("Sending raw command: %s\n", errorString); tdReleaseString(errorString); + return retval; } int main(int argc, char **argv) @@ -294,48 +308,56 @@ int main(int argc, char **argv) if (argc < 2) { print_usage( argv[0] ); - return -1; + return -TELLSTICK_ERROR_SYNTAX; } - while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ) + int returnSuccess = 0; + while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ){ + int success = 0; switch (optch) { case 'b' : - bell_device( &optarg[0] ); + success = bell_device( &optarg[0] ); break; case 'd' : if (level >= 0) { - dim_device( &optarg[0], level ); + success = dim_device( &optarg[0], level ); + break; } + printf("Dim level missing or incorrect value.\n"); + success = TELLSTICK_ERROR_SYNTAX; break; case 'f' : - switch_device(false, &optarg[0]); + success = switch_device(false, &optarg[0]); break; case 'h' : print_usage( argv[0] ); - break; + success = TELLSTICK_SUCCESS; case 'i' : print_version( ); - break; + success = TELLSTICK_SUCCESS; case 'l' : - list_devices(); + success = list_devices(); break; case 'n' : - switch_device(true, &optarg[0]); + success = switch_device(true, &optarg[0]); break; case 'e' : - learn_device(&optarg[0]); + success = learn_device(&optarg[0]); break; case 'r' : - send_raw_command(&optarg[0]); + success = send_raw_command(&optarg[0]); break; case 'v' : level = atoi( &optarg[0] ); break; default : print_usage( argv[0] ); - return -1; + success = TELLSTICK_ERROR_SYNTAX; } - + if(success != TELLSTICK_SUCCESS){ + returnSuccess = success; //return last error message + } + } tdClose(); //Cleaning up - return 0; + return -returnSuccess; } From 44e5b81a909587475868949602bb06e09d9354f1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 28 Dec 2011 16:02:27 +0100 Subject: [PATCH 1755/2215] Added new error code, Syntax error --- telldus-core/client/telldus-core.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 62e53c40..36abeec5 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -82,6 +82,10 @@ using namespace TelldusCore; * Error code. The client library received a response from the service * it did not understand. * + * @def TELLSTICK_ERROR_SYNTAX + * Error code. Input/command could not be parsed or didn't follow + * input rules. + * * @def TELLSTICK_ERROR_UNKNOWN * Error code. An unkown error has occurred. */ @@ -479,10 +483,14 @@ int WINAPI tdMethods(int id, int methodsSupported){ * @sa TELLSTICK_ERROR_PERMISSION_DENIED * @sa TELLSTICK_ERROR_DEVICE_NOT_FOUND * @sa TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + * @sa TELLSTICK_ERROR_COMMUNICATION + * @sa TELLSTICK_ERROR_CONNECTING_SERVICE + * @sa TELLSTICK_ERROR_UNKNOWN_RESPONSE + * @sa TELLSTICK_ERROR_SYNTAX * @sa TELLSTICK_ERROR_UNKNOWN */ char * WINAPI tdGetErrorString(int intErrorNo) { - const int numResponses = 8; + const int numResponses = 9; const char *responses[numResponses] = { "Success", "TellStick not found", @@ -491,7 +499,8 @@ char * WINAPI tdGetErrorString(int intErrorNo) { "The method you tried to use is not supported by the device", "An error occurred while communicating with TellStick", "Could not connect to the Telldus Service", - "Received an unknown response" + "Received an unknown response", + "Syntax error" }; std::string strReturn; intErrorNo = abs(intErrorNo); //We don't use negative values here. From 05c0ac7f0512c87789a6d17ef38fe63e800a2085 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 28 Dec 2011 16:06:46 +0100 Subject: [PATCH 1756/2215] Add functions formatf() and sformatf() --- telldus-core/common/Strings.cpp | 45 +++++++++++++++++++++++++++++++++ telldus-core/common/Strings.h | 3 +++ 2 files changed, 48 insertions(+) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 83c1384f..720e56f8 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -158,3 +158,48 @@ std::string TelldusCore::wideToString(const std::wstring &input) { return retval; #endif } + +std::string TelldusCore::formatf(const char *format, ...) { + va_list ap; + va_start(ap, format); + std::string retval = sformatf(format, ap); + va_end(ap); + return retval; +} + +std::string TelldusCore::sformatf(const char *format, va_list ap) { + //This code is based on code from the Linux man-pages project (man vsprintf) + int n; + int size = 100; /* Guess we need no more than 100 bytes. */ + char *p, *np; + + if ((p = (char*)malloc(size)) == NULL) { + return ""; + } + + while (1) { + /* Try to print in the allocated space. */ + n = vsnprintf(p, size, format, ap); + + /* If that worked, return the string. */ + if (n > -1 && n < size) { + std::string retval(p); + free(p); + return retval; + } + + /* Else try again with more space. */ + + if (n > -1) { /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + } else { /* glibc 2.0 */ + size *= 2; /* twice the old size */ + } + if ((np = (char *)realloc (p, size)) == NULL) { + free(p); + return ""; + } else { + p = np; + } + } +} diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index aca16060..bdc44263 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -14,6 +14,9 @@ namespace TelldusCore { std::string wideToString(const std::wstring &input); int wideToInteger(const std::wstring &input); + + std::string formatf(const char *format, ...); + std::string sformatf(const char *format, va_list ap); } #endif //STRING_H From 89036564232ea8feec7404f23ea17c96831701ef Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 28 Dec 2011 16:07:29 +0100 Subject: [PATCH 1757/2215] Use sformatf() to format the messages for the Windows Event Log, see #103 --- telldus-core/service/Log.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index f15dd92f..75c1e2a1 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -145,7 +145,7 @@ void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const } #elif defined(_WINDOWS) LPWSTR pInsertStrings[2] = {NULL, NULL}; - std::wstring str = TelldusCore::charToWstring(format); + std::wstring str = TelldusCore::charToWstring(TelldusCore::sformatf(format, ap).c_str()); pInsertStrings[0] = (LPWSTR)str.c_str(); switch (logLevel) { From e1d063bb56696146db880971a062fdccd5f9d6f5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 28 Dec 2011 16:15:22 +0100 Subject: [PATCH 1758/2215] Force stdout on Mac OS X --- telldus-core/service/Log.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 75c1e2a1..f555378a 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -30,6 +30,8 @@ Log::Log() #if defined(_LINUX) setlogmask(LOG_UPTO(LOG_INFO)); openlog("telldusd", LOG_CONS, LOG_USER); +#elif defined(_MACOSX) + d->logOutput = Log::StdOut; #elif defined(_WINDOWS) //Add ourselves to the registy HKEY hRegKey = NULL; @@ -111,6 +113,10 @@ void Log::setDebug() { } void Log::setLogOutput(LogOutput logOutput) { +#ifdef _MACOSX + //Always stdout + return; +#endif Log *log = Log::instance(); log->d->logOutput = logOutput; } From 7272875db52808c05088681e8316941d1e7d4939 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 28 Dec 2011 17:28:30 +0100 Subject: [PATCH 1759/2215] Log connect and disconnect from a TellStick. This closes #103 --- telldus-core/service/TellStick_ftd2xx.cpp | 5 +++++ telldus-core/service/TellStick_libftdi.cpp | 4 ++++ telldus-core/service/main_mac.cpp | 11 +++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 8769cd30..288aff42 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -12,6 +12,7 @@ #include "TellStick.h" #include "Mutex.h" #include "Strings.h" +#include "Log.h" #include "../client/telldus-core.h" #include #include @@ -61,6 +62,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & strcpy(tempSerial, td.serial.c_str()); FT_SetVIDPID(td.vid, td.pid); #endif + Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str()); FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); delete tempSerial; if (ftStatus == FT_OK) { @@ -76,10 +78,13 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & setBaud(4800); } this->start(); + } else { + Log::warning("Failed to open TellStick"); } } TellStick::~TellStick() { + Log::warning("Disconnected TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str()); if (d->running) { TelldusCore::MutexLocker locker(&d->mutex); d->running = false; diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index c5e6c3ae..4b850bbb 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -54,6 +54,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & ftdi_init(&d->ftHandle); ftdi_set_interface(&d->ftHandle, INTERFACE_ANY); + Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str()); int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str()); if (ret < 0) { ftdi_deinit(&d->ftHandle); @@ -71,10 +72,13 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor & this->setBaud(4800); } this->start(); + } else { + Log::warning("Failed to open TellStick"); } } TellStick::~TellStick() { + Log::warning("Disconnected TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str()); if (d->running) { stop(); } diff --git a/telldus-core/service/main_mac.cpp b/telldus-core/service/main_mac.cpp index 4527225e..f87b718a 100644 --- a/telldus-core/service/main_mac.cpp +++ b/telldus-core/service/main_mac.cpp @@ -1,16 +1,16 @@ #include "TelldusMain.h" +#include "Log.h" #include -#include TelldusMain tm; void shutdownHandler(int onSignal) { - printf("Shutting down\n"); + Log::notice("Shutting down"); tm.stop(); } void sigpipeHandler(int onSignal) { - printf("SIGPIPE received\n"); + Log::notice("SIGPIPE received"); } int main(int argc, char **argv) { @@ -19,7 +19,10 @@ int main(int argc, char **argv) { signal(SIGINT, shutdownHandler); signal(SIGPIPE, sigpipeHandler); + Log::notice("telldusd started"); tm.start(); - printf("telldusd stopped gracefully\n"); + Log::notice("telldusd stopped gracefully"); + + Log::destroy(); return 0; } From 8c4c62d9e1ff071d3c1518b6c8124a2a86ea9a3a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 28 Dec 2011 17:57:48 +0100 Subject: [PATCH 1760/2215] Added missing includes --- telldus-core/common/Strings.cpp | 1 + telldus-core/common/Strings.h | 1 + telldus-core/service/TellStick_libftdi.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 720e56f8..c21d3ef1 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #ifdef _WINDOWS #include diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index bdc44263..1ffed8a1 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -2,6 +2,7 @@ #define STRING_H #include +#include namespace TelldusCore { std::wstring charToWstring(const char *value); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 4b850bbb..87827355 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -18,6 +18,7 @@ #include #include "Thread.h" #include "Mutex.h" +#include "Log.h" #include "Strings.h" #include "common.h" From cd6e59baa504b344d527f25d02c2e85ced7f231a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 29 Dec 2011 17:05:51 +0100 Subject: [PATCH 1761/2215] Changed udev rules, now filtering correctly by vendor. Closes #115 --- telldus-core/tdadmin/05-tellstick.rules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules index 078ff757..7a6ae615 100644 --- a/telldus-core/tdadmin/05-tellstick.rules +++ b/telldus-core/tdadmin/05-tellstick.rules @@ -1,3 +1,3 @@ -ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" -ID_VENDOR_ID=="1781", SUBSYSTEM=="usb", ACTION=="remove" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ATTRS{idVendor}=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ENV{ID_VENDOR_ID}=="1781", SUBSYSTEM=="usb", ACTION=="remove" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" From b8955deed8a6724253ab3380d599792cca4a65a6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 29 Dec 2011 17:28:22 +0100 Subject: [PATCH 1762/2215] Add overloaded constructor to LiveMessageToken to accept an int --- telldus-gui/Plugins/Live/LiveMessageToken.cpp | 5 +++++ telldus-gui/Plugins/Live/LiveMessageToken.h | 1 + 2 files changed, 6 insertions(+) diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.cpp b/telldus-gui/Plugins/Live/LiveMessageToken.cpp index 03b204ce..3c807c5e 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.cpp +++ b/telldus-gui/Plugins/Live/LiveMessageToken.cpp @@ -11,6 +11,11 @@ LiveMessageToken::LiveMessageToken(const QString &value) { stringVal = value; } +LiveMessageToken::LiveMessageToken(int value) { + valueType = Int; + intVal = value; +} + QByteArray LiveMessageToken::toByteArray() const { if (valueType == Int) { return QString("i%1s").arg(intVal, 0, 16).toUtf8(); diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.h b/telldus-gui/Plugins/Live/LiveMessageToken.h index 48699457..5a7c0177 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.h +++ b/telldus-gui/Plugins/Live/LiveMessageToken.h @@ -12,6 +12,7 @@ public: LiveMessageToken(); LiveMessageToken(const QString &value); + LiveMessageToken(int value); QByteArray toByteArray() const; static LiveMessageToken parseToken(const QByteArray &string, int* start); From 4517db2048ca916514d3df8b79fb6c4b027caea6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 29 Dec 2011 17:29:42 +0100 Subject: [PATCH 1763/2215] Reset pong timer on all received data (with valid signature). Not only pong messages --- telldus-gui/Plugins/Live/LiveObject.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 1d24117f..e2afa1fb 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -105,14 +105,13 @@ void LiveObject::readyRead() { //qDebug() << "HASH mismatch!" << msg->name(); return; } + d->pongTimer.stop(); + d->pongTimer.start(); if (msg->name() == "") { return; } else if (msg->name() == "disconnect") { this->disconnect(); - } else if (msg->name() == "pong") { - d->pongTimer.stop(); - d->pongTimer.start(); } else if (msg->name() == "registered") { d->registered = true; emit registered(msg->argument(0)); From d86e12f1d35f6954f6f6efdd4db276c31ebbf3fd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 29 Dec 2011 17:32:18 +0100 Subject: [PATCH 1764/2215] LiveMessageTokenScriptWrapper::getInt() should be declared const since it only returnes values --- telldus-gui/Plugins/Live/LiveMessageToken.cpp | 2 +- telldus-gui/Plugins/Live/LiveMessageToken.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.cpp b/telldus-gui/Plugins/Live/LiveMessageToken.cpp index 3c807c5e..0c4ace81 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.cpp +++ b/telldus-gui/Plugins/Live/LiveMessageToken.cpp @@ -127,7 +127,7 @@ void LiveMessageTokenScriptWrapper::add(LiveMessageTokenScriptWrapper *t) { p_token.listVal << t->p_token; } -int LiveMessageTokenScriptWrapper::getInt(const QString &key, int defaultValue) { +int LiveMessageTokenScriptWrapper::getInt(const QString &key, int defaultValue) const { if (p_token.valueType != LiveMessageToken::Dictionary) { return defaultValue; } diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.h b/telldus-gui/Plugins/Live/LiveMessageToken.h index 5a7c0177..5aed1f33 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.h +++ b/telldus-gui/Plugins/Live/LiveMessageToken.h @@ -35,13 +35,13 @@ public: public slots: void add(LiveMessageTokenScriptWrapper *token); - int getInt(const QString &key, int defaultValue = 0); + int getInt(const QString &key, int defaultValue = 0) const; int intVal() const; void set(const QString &key, int value); void set(const QString &key, const QString &value); - + private: LiveMessageToken p_token; }; From 06bf1a867d9ff29e6891fedd2d36598c82a59ab5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 29 Dec 2011 17:32:56 +0100 Subject: [PATCH 1765/2215] Add function LiveMessageTokenScriptWrapper::getString() --- telldus-gui/Plugins/Live/LiveMessageToken.cpp | 10 ++++++++++ telldus-gui/Plugins/Live/LiveMessageToken.h | 1 + 2 files changed, 11 insertions(+) diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.cpp b/telldus-gui/Plugins/Live/LiveMessageToken.cpp index 0c4ace81..9c64f6d0 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.cpp +++ b/telldus-gui/Plugins/Live/LiveMessageToken.cpp @@ -137,6 +137,16 @@ int LiveMessageTokenScriptWrapper::getInt(const QString &key, int defaultValue) return p_token.dictVal[key].intVal; } +QString LiveMessageTokenScriptWrapper::getString(const QString &key, const QString &defaultValue) const { + if (p_token.valueType != LiveMessageToken::Dictionary) { + return defaultValue; + } + if (!p_token.dictVal.contains(key)) { + return defaultValue; + } + return p_token.dictVal[key].stringVal; +} + int LiveMessageTokenScriptWrapper::intVal() const { return p_token.intVal; } diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.h b/telldus-gui/Plugins/Live/LiveMessageToken.h index 5aed1f33..a94f476d 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.h +++ b/telldus-gui/Plugins/Live/LiveMessageToken.h @@ -36,6 +36,7 @@ public slots: void add(LiveMessageTokenScriptWrapper *token); int getInt(const QString &key, int defaultValue = 0) const; + QString getString(const QString &key, const QString &defaultValue = "") const; int intVal() const; From 05d48d1685e596e7c1ccf7eb8dfb9311f25321fd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 29 Dec 2011 17:33:28 +0100 Subject: [PATCH 1766/2215] Reset ping timer on all sent messages --- telldus-gui/Plugins/Live/LiveObject.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index e2afa1fb..d5364280 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -161,6 +161,8 @@ void LiveObject::sendMessage(const LiveMessage &message) { d->socket->write(msg.toByteArray()); d->socket->flush(); + d->pingTimer.stop(); + d->pingTimer.start(); } void LiveObject::sendMessage(LiveMessage *message) { From c56fa6c6f8d3de201a952a79a4526911e84c6a6f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 29 Dec 2011 17:34:41 +0100 Subject: [PATCH 1767/2215] Clear the error and status message when we are dicsonnected --- telldus-gui/Plugins/Live/LiveObject.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index d5364280..126f14d2 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -198,6 +198,10 @@ void LiveObject::p_connected() { void LiveObject::p_disconnected() { d->pingTimer.stop(); d->pongTimer.stop(); + if (d->registered) { + //Clear the registered status + emit errorChanged("Disconnected from server"); + } d->registered = false; } @@ -212,6 +216,7 @@ void LiveObject::stateChanged( QAbstractSocket::SocketState socketState ) { emit statusChanged("Reconnecting in " + QString::number(timeout) + " seconds..."); } else if (socketState == QAbstractSocket::ConnectingState) { emit statusChanged("Connecting..."); + emit errorChanged(""); } } From 5bb60a60c90e2653e7f3ae77fdf9e90911f5eb3c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 29 Dec 2011 17:36:41 +0100 Subject: [PATCH 1768/2215] Implement our new type of command messages and also handle the ACK. This requires us to bump the protocol version. Closes #151 --- telldus-gui/Plugins/Live/LiveObject.cpp | 12 ++++++++++-- telldus-gui/Plugins/Live/__init__.js | 24 +++++++++++++++--------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 126f14d2..27b73280 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -127,6 +127,14 @@ void LiveObject::readyRead() { s.setValue("Live/UUID", d->uuid); emit notRegistered(); emit errorChanged("Not registered"); + } else if (msg->name() == "command") { + if (msg->arg(0).valueType == LiveMessageToken::Dictionary && msg->arg(0).dictVal.contains("ACK")) { + int ack = msg->arg(0).dictVal["ACK"].intVal; + LiveMessage msg("ACK"); + msg.append(ack); + this->sendMessage(msg); + } + emit messageReceived(msg.data()); } else { emit messageReceived(msg.data()); } @@ -137,7 +145,7 @@ void LiveObject::refreshServerList() { emit statusChanged("Discover servers"); d->serverList.clear(); QUrl url(TELLDUS_LIVE_URI); - QPair version("protocolVersion", "1"); + QPair version("protocolVersion", "2"); QList > query; query.append(version); url.setQueryItems(query); @@ -286,7 +294,7 @@ QByteArray LiveObject::signatureForMessage( const QByteArray &message ) { LiveMessageToken LiveObject::generateVersionToken() { LiveMessageToken token; token.valueType = LiveMessageToken::Dictionary; - token.dictVal["protocol"] = LiveMessageToken("1"); + token.dictVal["protocol"] = LiveMessageToken(2); token.dictVal["version"] = LiveMessageToken(TELLDUS_CENTER_VERSION); #if defined(Q_WS_WIN) token.dictVal["os"] = LiveMessageToken("windows"); diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 4f292f7e..2c3f5653 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -45,16 +45,22 @@ com.telldus.live = function() { } function messageReceived(msg) { - if (msg.name() == "turnon") { - com.telldus.core.turnOn( msg.argument(0).intVal() ); - } else if (msg.name() == "turnoff") { - com.telldus.core.turnOff( msg.argument(0).intVal() ); - } else if (msg.name() == "dim") { - com.telldus.core.dim( msg.argument(0).intVal(), msg.argument(1).intVal() ); - } else if (msg.name() == "bell") { - com.telldus.core.bell( msg.argument(0).intVal() ); + if (msg.name() == "command") { + handleCommand(msg.argument(0)); + } + } + + function handleCommand(msg) { + var action = msg.getString('action'); + if (action == "turnon") { + com.telldus.core.turnOn( msg.getInt('id') ); + } else if (action == "turnoff") { + com.telldus.core.turnOff( msg.getInt('id') ); + } else if (action == "dim") { + com.telldus.core.dim( msg.getInt('id'), msg.getInt('value') ); + } else if (action == "bell") { + com.telldus.core.bell( msg.getInt('id') ); } - print("Received: " + msg.name()); } function registered(msg) { From ed502d1660af51f8cc7d9b7ca7548fc3c4978ef4 Mon Sep 17 00:00:00 2001 From: Carl Nettelblad Date: Fri, 30 Dec 2011 14:18:06 +0100 Subject: [PATCH 1769/2215] Fixed for stability in the Windows Service. Mainly changes since CancelIO is not synchronous. Big thanks to Carl Nettelblad for this. See #93 and #94. --- telldus-core/common/Socket_win.cpp | 47 +++++++++++-------- .../service/ConnectionListener_win.cpp | 45 ++++++++++-------- 2 files changed, 54 insertions(+), 38 deletions(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 52e82a98..5fe760e4 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -37,6 +37,7 @@ Socket::~Socket(void){ SetEvent(d->readEvent); //signal for break if (d->hPipe != INVALID_HANDLE_VALUE) { CloseHandle(d->hPipe); + d->hPipe = 0; } delete d; } @@ -89,7 +90,7 @@ std::wstring Socket::read(int timeout){ memset(&oOverlap, 0, sizeof(OVERLAPPED)); - d->readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + d->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL); oOverlap.hEvent = d->readEvent; BOOL fSuccess = false; std::wstring returnString; @@ -105,16 +106,17 @@ std::wstring Socket::read(int timeout){ if(!d->running){ CancelIo(d->hPipe); - CloseHandle(d->readEvent); + WaitForSingleObject(oOverlap.hEvent, INFINITE); + d->readEvent = 0; + CloseHandle(oOverlap.hEvent); return L""; } if (result == WAIT_TIMEOUT) { CancelIo(d->hPipe); - CloseHandle(d->readEvent); - return L""; + // Cancel, we still need to cleanup } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, true); if (!fSuccess) { DWORD err = GetLastError(); @@ -131,8 +133,8 @@ std::wstring Socket::read(int timeout){ } returnString.append(buf); } - CancelIo(d->hPipe); - CloseHandle(d->readEvent); + d->readEvent = 0; + CloseHandle(oOverlap.hEvent); return returnString; } @@ -141,26 +143,33 @@ void Socket::write(const std::wstring &msg){ OVERLAPPED oOverlap; DWORD bytesWritten = 0; int result; - BOOL fSuccess; + BOOL fSuccess = false; memset(&oOverlap, 0, sizeof(OVERLAPPED)); - HANDLE writeEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + HANDLE writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL); oOverlap.hEvent = writeEvent; - WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); - - result = WaitForSingleObject(writeEvent, 500); - if (result == WAIT_TIMEOUT) { - CancelIo(d->hPipe); - CloseHandle(writeEvent); - d->connected = false; - return; + BOOL writeSuccess = WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); + result = GetLastError(); + if (writeSuccess || result == ERROR_IO_PENDING) { + result = WaitForSingleObject(writeEvent, 500); + if (result == WAIT_TIMEOUT) { + CancelIo(d->hPipe); + WaitForSingleObject(oOverlap.hEvent, INFINITE); + CloseHandle(writeEvent); + CloseHandle(d->hPipe); + d->hPipe = 0; + d->connected = false; + return; + } + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); + CloseHandle(writeEvent); if (!fSuccess) { - CancelIo(d->hPipe); + CloseHandle(d->hPipe); + d->hPipe = 0; d->connected = false; return; } diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 992e1a87..192852ea 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -91,35 +91,39 @@ void ConnectionListener::run() { d->hEvent = CreateEvent(NULL, true, false, NULL); oOverlap.hEvent = d->hEvent; + bool recreate = true; while (1) { - hPipe = CreateNamedPipe( - (const wchar_t *)d->pipename.c_str(), // pipe name - PIPE_ACCESS_DUPLEX | // read/write access - FILE_FLAG_OVERLAPPED, //Overlapped mode - PIPE_TYPE_MESSAGE | // message type pipe - PIPE_READMODE_MESSAGE | // message-read mode - PIPE_WAIT, // blocking mode - PIPE_UNLIMITED_INSTANCES, // max. instances - BUFSIZE, // output buffer size - BUFSIZE, // input buffer size - 0, // client time-out - &d->sa); // default security attribute + if (recreate) { + hPipe = CreateNamedPipe( + (const wchar_t *)d->pipename.c_str(), // pipe name + PIPE_ACCESS_DUPLEX | // read/write access + FILE_FLAG_OVERLAPPED, //Overlapped mode + PIPE_TYPE_MESSAGE | // message type pipe + PIPE_READMODE_MESSAGE | // message-read mode + PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max. instances + BUFSIZE, // output buffer size + BUFSIZE, // input buffer size + 0, // client time-out + &d->sa); // default security attribute - if (hPipe == INVALID_HANDLE_VALUE) { - //TelldusCore::logMessage("Could not create named pipe"); - return; + if (hPipe == INVALID_HANDLE_VALUE) { + return; + } + + ConnectNamedPipe(hPipe, &oOverlap); + recreate = false; } - - ConnectNamedPipe(hPipe, &oOverlap); - DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000); if (!d->running) { + CancelIo(hPipe); + WaitForSingleObject(oOverlap.hEvent, INFINITE); break; } if(result == WAIT_TIMEOUT){ - CloseHandle(hPipe); + //CloseHandle(hPipe); continue; } BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); @@ -129,8 +133,11 @@ void ConnectionListener::run() { return; } ConnectionListenerEventData *data = new ConnectionListenerEventData(); + ResetEvent(oOverlap.hEvent); data->socket = new TelldusCore::Socket(hPipe); d->waitEvent->signal(data); + + recreate = true; } CloseHandle(d->hEvent); From e019f416d9aa3212aa5dc3a677eb8e2cf8ad8290 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 30 Dec 2011 16:03:08 +0100 Subject: [PATCH 1770/2215] Increased retry count on ftdi_read_data to avoid TELLSTICK_ERROR_COMMUNICATION on some TellStick/device combinations. Closes #125 --- telldus-core/service/TellStick_libftdi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 87827355..3202b282 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -197,7 +197,7 @@ int TellStick::send( const std::string &strMessage ) { delete[] tempMessage; - int retrycnt = 200; + int retrycnt = 500; unsigned char in; while(c && --retrycnt) { ret = ftdi_read_data( &d->ftHandle, &in, 1); From ed1dc8b2d32c1a7ab77b21cd27d1c300176319ae Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 30 Dec 2011 16:24:26 +0100 Subject: [PATCH 1771/2215] Mask methods to lowest common denominator --- telldus-gui/Plugins/Live/__init__.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 2c3f5653..75ec567d 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -70,7 +70,13 @@ com.telldus.live = function() { menuId = 0; separatorId = 0; } - supportedMethods = msg.getInt('supportedMethods'); + //Mask to lowest common denominator + supportedMethods = + com.telldus.core.TELLSTICK_TURNON | + com.telldus.core.TELLSTICK_TURNOFF | + com.telldus.core.TELLSTICK_DIM | + com.telldus.core.TELLSTICK_BELL; + supportedMethods = supportedMethods & msg.getInt('supportedMethods'); isRegistered = true; registrationLinkVisible(false); sendDevicesReport(); From d3227ebdf855d8b9288f77b24f98ae724aebe4cf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 30 Dec 2011 16:33:12 +0100 Subject: [PATCH 1772/2215] Implement UP/DOWN/STOP in TelldusCenter Live! plugin. This closes #147. --- telldus-gui/Plugins/Live/__init__.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 75ec567d..1fbb20f0 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -60,6 +60,12 @@ com.telldus.live = function() { com.telldus.core.dim( msg.getInt('id'), msg.getInt('value') ); } else if (action == "bell") { com.telldus.core.bell( msg.getInt('id') ); + } else if (action == "up") { + com.telldus.core.up( msg.getInt('id') ); + } else if (action == "down") { + com.telldus.core.down( msg.getInt('id') ); + } else if (action == "stop") { + com.telldus.core.stop( msg.getInt('id') ); } } @@ -75,7 +81,10 @@ com.telldus.live = function() { com.telldus.core.TELLSTICK_TURNON | com.telldus.core.TELLSTICK_TURNOFF | com.telldus.core.TELLSTICK_DIM | - com.telldus.core.TELLSTICK_BELL; + com.telldus.core.TELLSTICK_BELL | + com.telldus.core.TELLSTICK_UP | + com.telldus.core.TELLSTICK_DOWN | + com.telldus.core.TELLSTICK_STOP; supportedMethods = supportedMethods & msg.getInt('supportedMethods'); isRegistered = true; registrationLinkVisible(false); From dd3504ffb8eaad67a83849e195acf91dba52f9a1 Mon Sep 17 00:00:00 2001 From: egil Date: Fri, 30 Dec 2011 17:13:07 +0100 Subject: [PATCH 1773/2215] Applied patch for everflourish in rfcmd. This closes #141. Thanks to egil --- rfcmd/rfcmd.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 3 deletions(-) diff --git a/rfcmd/rfcmd.c b/rfcmd/rfcmd.c index 608b7d67..76901da5 100644 --- a/rfcmd/rfcmd.c +++ b/rfcmd/rfcmd.c @@ -56,6 +56,19 @@ * Arg 5: Level (0=off, 1 = on) ******************************************************************************/ +/******************************************************************************* + * Modifications from rfcmd.c ver 2.1.0 based on marvelous work by Snakehand + * See http://www.telldus.com/forum/viewtopic.php?t=97&start=63 + * Added support for EVERFLOURISH + * Note: + * 1. Command line syntax: + * /usr/local/bin/rfcmd /dev/ttyUSB0 EVERFLOURISH 1 15 + * Arg 1: device + * Arg 2: protocol + * Arg 3: device number (0..65535) + * Arg 4: Level (0=off, 15=on, 10=learn) + ******************************************************************************/ + /******************************************************************************* * Modifications from rfcmd ver 2.1.1 done by Johan Ström * Default disabled semaphores for FreeBSD. @@ -98,7 +111,8 @@ int createIkeaString(const char * pSystemStr, const char * pChannelStr, char * pStrReturn); int createRisingSunString(const char * pCodeStr, const char* pUnitStr, const char * pOn_offStr, char * pTxStr); - +int createEverFlourishString(const char* pUnitStr, const char * pLevelStr, + char * pTxStr); void printUsage(void); void printVersion(void); @@ -148,7 +162,14 @@ int main( int argc, char **argv ) printUsage(); exit(1); } - /* else - a send cmd string was created */ + /* else - a send cmd string was created */ + } else if ( (argc == 5) && (strcmp(*(argv+2),"EVERFLOURISH")==0) ) { + // Unit, Level + if ( createEverFlourishString(*(argv+3), *(argv+4), txStr) == 0 ) { + printUsage(); + exit(1); + } + /* else - a send cmd string was created */ } else if ( (argc >= 2) && (strcmp(*(argv+1),"--version")==0) ) { printVersion(); exit(1); @@ -525,6 +546,78 @@ int createRisingSunString(const char * pCodeStr, const char * pUnitStr, const ch return strlen(pTxStr); } +unsigned int everflourish_find_code(unsigned int x) { + unsigned int bits[16] = { 0xf ,0xa ,0x7 ,0xe, + 0xf ,0xd ,0x9 ,0x1, + 0x1 ,0x2 ,0x4 ,0x8, + 0x3 ,0x6 ,0xc ,0xb }; + unsigned int bit = 1; + unsigned int res = 0x5; + int i; + unsigned int lo,hi; + + if ((x&0x3)==3) { + lo = x & 0x00ff; + hi = x & 0xff00; + lo += 4; + if (lo>0x100) lo = 0x12; + x = lo | hi; + } + + for(i=0;i<16;i++) { + if (x&bit) { + res = res ^ bits[i]; + } + bit = bit << 1; + } + + return res; +} + + +int createEverFlourishString(const char * pUnitStr, const char * pLevelStr, + char * pTxStr) +{ + int len = 0; + int level; + int unit; + unsigned int check; + int i; + + unit = atoi(pUnitStr); + level = atoi(pLevelStr); /* ON=15, OFF=0, LEARN=10 */ + check = everflourish_find_code(unit); + +#ifdef RFCMD_DEBUG + printf("unit: %d, level: %d\n", unit, level); +#endif + + /* check converted parameters for validity */ + if((unit < 0) || (unit > 0xffff) || + (level < 0) || (level > 15)) { + } else { + const char ssss = 85; + const char sssl = 84; // 0 + const char slss = 69; // 1 + + const char bits[2] = {sssl,slss}; + int i; + + char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss}; + memcpy(pTxStr, preamble, sizeof(preamble)); + len += sizeof(preamble); + + for(i=15;i>=0;i--) pTxStr[len++]=bits[(unit>>i)&0x01]; + for(i=3;i>=0;i--) pTxStr[len++]=bits[(check>>i)&0x01]; + for(i=3;i>=0;i--) pTxStr[len++]=bits[(level>>i)&0x01]; + + pTxStr[len++] = ssss; + pTxStr[len++] = '+'; + } + + pTxStr[len] = '\0'; + return strlen(pTxStr); +} void printUsage(void) { @@ -535,7 +628,7 @@ void printUsage(void) #else printf("\t DEVICE: /dev/ttyUSB[0..n]\n" ); #endif - printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA, RISINGSUN\n" ); + printf("\t PROTOCOLS: NEXA, SARTANO, WAVEMAN, IKEA, RISINGSUN, EVERFLOURISH\n" ); printf("\n"); printf("\t PROTOCOL ARGUMENTS - NEXA, WAVEMAN:\n"); printf("\t\tHOUSE_CODE: A..P\n\t\tCHANNEL: 1..16\n\t\tOFF_ON: 0..1\n" ); @@ -551,6 +644,10 @@ void printUsage(void) printf("\t\tCODE: 1..4\n\t\tDEVICE: 1..4\n"); printf("\t\tOFF_ON: 0..1\n" ); printf("\n"); + printf("\t PROTOCOL ARGUMENTS - EVERFLOURISH:\n"); + printf("\t\tDEVICE: 0..65535\n"); + printf("\t\tLEVEL: 0=off, 10=learn, 15=on\n" ); + printf("\n"); printf("Report bugs to \n"); } From 65ef5254dee865537f9db9582421f9faae4931e6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 3 Jan 2012 15:42:23 +0100 Subject: [PATCH 1774/2215] Fixes for stability in Windows Service. Correct handling of ERROR_PIPE_CONNECTED. --- .../service/ConnectionListener_win.cpp | 34 +++++++++++-------- telldus-core/service/EventHandler_win.cpp | 4 +-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 192852ea..f88bac48 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -94,6 +94,7 @@ void ConnectionListener::run() { bool recreate = true; while (1) { + BOOL alreadyConnected = false; if (recreate) { hPipe = CreateNamedPipe( (const wchar_t *)d->pipename.c_str(), // pipe name @@ -113,24 +114,27 @@ void ConnectionListener::run() { } ConnectNamedPipe(hPipe, &oOverlap); + alreadyConnected = GetLastError() == ERROR_PIPE_CONNECTED; recreate = false; } - DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000); + if(!alreadyConnected){ + DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000); + if (!d->running) { + CancelIo(hPipe); + WaitForSingleObject(oOverlap.hEvent, INFINITE); + break; + } + + if(result == WAIT_TIMEOUT){ + //CloseHandle(hPipe); + continue; + } + BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); - if (!d->running) { - CancelIo(hPipe); - WaitForSingleObject(oOverlap.hEvent, INFINITE); - break; - } - if(result == WAIT_TIMEOUT){ - //CloseHandle(hPipe); - continue; - } - BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); - - if (!connected) { - CloseHandle(hPipe); - return; + if (!connected) { + CloseHandle(hPipe); + return; + } } ConnectionListenerEventData *data = new ConnectionListenerEventData(); ResetEvent(oOverlap.hEvent); diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/service/EventHandler_win.cpp index d138cb85..f44fe8c7 100644 --- a/telldus-core/service/EventHandler_win.cpp +++ b/telldus-core/service/EventHandler_win.cpp @@ -53,10 +53,8 @@ void EventHandler::signal(Event *) { bool EventHandler::waitForAny() { while(1){ - int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000); //FALSE, INFINITE); - //TODO KANSE ÄNDRA HÄR... Svårt att se effekten säkert, men lite nytta verkade det göra... + int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000); if (result == WAIT_TIMEOUT) { - //return false; continue; } TelldusCore::MutexLocker locker(&d->mutex); From 2ec2dac46fd94e2a390cc219886a958d4b24b715 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 4 Jan 2012 16:11:08 +0100 Subject: [PATCH 1775/2215] Fix indentation error --- telldus-core/common/Strings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 72c57b9d..fe0b7ca1 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -239,7 +239,7 @@ std::string TelldusCore::sformatf(const char *format, va_list ap) { } if ((np = (char *)realloc (p, size)) == NULL) { free(p); - return ""; + return ""; } else { p = np; } From 36bfa0ba8baa13017fdb0a8ae34aac2a69182826 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 4 Jan 2012 16:14:50 +0100 Subject: [PATCH 1776/2215] Remove raw events from tdSendRawCommand(). It think this was added by mistake in 464000515c0191622a9b0425996612e3fed6a9a1 --- telldus-core/service/ClientCommunicationHandler.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index d75c674f..d51144ab 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -207,11 +207,6 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, std::wstring command = TelldusCore::Message::takeString(&msg); int reserved = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->sendRawCommand(command, reserved); - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDRawDeviceEvent"; - eventData->controllerId = -1; - eventData->eventValue = command; - d->deviceUpdateEvent->signal(eventData); } else if (function == L"tdConnectTellStickController") { int vid = TelldusCore::Message::takeInt(&msg); From 265daf4714ea69f99888ef035f64ea240f1115e9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 4 Jan 2012 16:18:01 +0100 Subject: [PATCH 1777/2215] iconv() cannot convert ascii chacacters > 127. In order for tdSendRawCommand() to work with longer pulses we need to convert to wchar_t manually. This closes #126. --- telldus-core/client/telldus-core.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 36abeec5..18775d56 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -520,8 +520,12 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure */ int WINAPI tdSendRawCommand(const char *command, int reserved) { + std::wstring wcommand; + for(int i = 0; i < strlen(command);++i) { + wcommand.append(1, (unsigned char)command[i]); + } Message msg(L"tdSendRawCommand"); - msg.addArgument(command); + msg.addArgument(wcommand); msg.addArgument(reserved); return Client::getIntegerFromService(msg); } From f58793ca59e38c8fff67be3bcd0ddc3bec074471 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 5 Jan 2012 14:35:18 +0100 Subject: [PATCH 1778/2215] Implement decoding of Oregon 0x1A2D. This closes #144 --- telldus-core/service/ProtocolOregon.cpp | 52 +++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 1909de9c..704ebeeb 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -16,7 +16,7 @@ std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) std::wstring model = dataMsg.model(); if (model.compare(L"0xEA4C") == 0) { return decodeEA4C(data); - } else if (model.compare(L"0x1A2D")) { + } else if (model.compare(L"0x1A2D") == 0) { return decode1A2D(data); } @@ -69,6 +69,52 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { } std::string ProtocolOregon::decode1A2D(const std::string &data) { - //TODO - return ""; + uint64_t value = strtol(data.c_str(), NULL, 16); + uint8_t checksum2 = value & 0xFF; + value >>= 8; + uint8_t checksum1 = value & 0xFF; + value >>= 8; + + uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); + uint8_t hum1 = value & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t neg = value & (1 << 3); + uint8_t hum2 = (value >> 4) & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t temp2 = value & 0xF; + uint8_t temp1 = (value >> 4) & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t temp3 = (value >> 4) & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t address = value & 0xFF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t channel = (value >> 4) & 0x7; + + checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA; + + //TODO: Find out how checksum2 works + if (checksum != checksum1) { + return ""; + } + + double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; + if (neg) { + temperature = -temperature; + } + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:1A2D;id:" << (int)address + << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + + return retString.str(); } From 6fa59e9ca978efd34c2798cd97609d9f956f9bd5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 9 Jan 2012 12:37:41 +0100 Subject: [PATCH 1779/2215] Add Telldus Live! authentication example --- examples/php/live/authentication/common.php | 19 ++++++++ .../live/authentication/getAccessToken.php | 21 +++++++++ .../live/authentication/getRequestToken.php | 13 +++++ examples/php/live/authentication/index.php | 47 +++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 examples/php/live/authentication/common.php create mode 100644 examples/php/live/authentication/getAccessToken.php create mode 100644 examples/php/live/authentication/getRequestToken.php create mode 100644 examples/php/live/authentication/index.php diff --git a/examples/php/live/authentication/common.php b/examples/php/live/authentication/common.php new file mode 100644 index 00000000..05873f77 --- /dev/null +++ b/examples/php/live/authentication/common.php @@ -0,0 +1,19 @@ +getAccessToken(constant('ACCESS_TOKEN')); + + $_SESSION['accessToken'] = $consumer->getToken(); + $_SESSION['accessTokenSecret'] = $consumer->getTokenSecret(); + + header('Location:index.php'); +} catch (Exception $e) { + ?> +

Authorization failed!

+

Go back

+ getRequestToken(constant('REQUEST_TOKEN'), constant('BASE_URL').'/getAccessToken.php'); + +$_SESSION['token'] = $consumer->getToken(); +$_SESSION['tokenSecret'] = $consumer->getTokenSecret(); + +$url = $consumer->getAuthorizeUrl(constant('AUTHORIZE_TOKEN')); +header('Location:'.$url); diff --git a/examples/php/live/authentication/index.php b/examples/php/live/authentication/index.php new file mode 100644 index 00000000..a0a78db9 --- /dev/null +++ b/examples/php/live/authentication/index.php @@ -0,0 +1,47 @@ +We have no access token, connect us +

We have access!

+

+ In your system, store these values to do requests for this user:
+ Token:
+ Secret: +

+

Clear the token and restart

+

List users devices

+ constant('TELLSTICK_TURNON') | constant('TELLSTICK_TURNOFF'), + ); + $response = $consumer->sendRequest(constant('REQUEST_URI').'/devices/list', $params, 'GET'); + echo '
';
+	echo( htmlentities($response->getBody()));
+}
+
+?>

List users clients

sendRequest(constant('REQUEST_URI').'/clients/list', $params, 'GET'); + echo '
';
+	echo( htmlentities($response->getBody()));
+}
+
+

From 988b44381031a74e5e5d9abf406265117e81a636 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Mon, 9 Jan 2012 16:52:15 +0100
Subject: [PATCH 1780/2215] Add class Timer

---
 telldus-core/service/CMakeLists.txt |  4 +-
 telldus-core/service/Timer.cpp      | 94 +++++++++++++++++++++++++++++
 telldus-core/service/Timer.h        | 24 ++++++++
 3 files changed, 121 insertions(+), 1 deletion(-)
 create mode 100644 telldus-core/service/Timer.cpp
 create mode 100644 telldus-core/service/Timer.h

diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt
index 8fc6125c..4943544f 100644
--- a/telldus-core/service/CMakeLists.txt
+++ b/telldus-core/service/CMakeLists.txt
@@ -24,6 +24,7 @@ SET( telldus-service_SRCS
 	Settings.cpp
 	TelldusMain.cpp
 	TellStick.cpp
+	Timer.cpp
 	EventUpdateManager.cpp
 )
 SET( telldus-service_protocol_SRCS
@@ -79,12 +80,13 @@ SET( telldus-service_HDRS
 	DeviceManager.h
 	Event.h
 	EventHandler.h
+	EventUpdateManager.h
 	Log.h
 	Sensor.h
 	Settings.h
 	TelldusMain.h
 	TellStick.h
-	EventUpdateManager.h
+	Timer.h
 )
 FIND_PACKAGE(Threads REQUIRED)
 LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp
new file mode 100644
index 00000000..14181159
--- /dev/null
+++ b/telldus-core/service/Timer.cpp
@@ -0,0 +1,94 @@
+#include "Timer.h"
+#include "Mutex.h"
+#include "Log.h"
+#ifdef _WINDOWS
+#else
+#include 
+#include 
+#endif
+
+class Timer::PrivateData {
+public:
+	PrivateData() : interval(0), running(false) {}
+	EventRef event;
+	int interval;
+	bool running;
+#ifdef _WINDOWS
+#else
+	pthread_mutex_t waitMutex;
+	pthread_cond_t cond;
+#endif
+};
+
+Timer::Timer(EventRef event)
+	:TelldusCore::Thread(), d(new PrivateData)
+{
+	d->event = event;
+#ifdef _WINDOWS
+#else
+	pthread_cond_init(&d->cond, NULL);
+	pthread_mutex_init(&d->waitMutex, NULL);
+#endif
+}
+
+Timer::~Timer() {
+	this->stop();
+	this->wait();
+
+#ifdef _WINDOWS
+#else
+	pthread_mutex_destroy(&d->waitMutex);
+	pthread_cond_destroy(&d->cond);
+	delete d;
+#endif
+}
+
+void Timer::setInterval(int sec) {
+	d->interval = sec;
+}
+
+void Timer::stop() {
+#ifdef _WINDOWS
+#else
+	//Signal event
+	pthread_mutex_lock(&d->waitMutex);
+	if (d->running) {
+		d->running = false;
+		pthread_cond_signal(&d->cond);
+	}
+	pthread_mutex_unlock(&d->waitMutex);
+#endif
+}
+
+void Timer::run() {
+#ifdef _WINDOWS
+		sleep(2); //TODO: Implement me
+#else
+	struct timespec ts;
+	struct timeval tp;
+
+	pthread_mutex_lock(&d->waitMutex);
+	d->running = true;
+	pthread_mutex_unlock(&d->waitMutex);
+
+	while(1) {
+		int rc =  gettimeofday(&tp, NULL);
+
+		ts.tv_sec  = tp.tv_sec;
+		ts.tv_nsec = tp.tv_usec * 1000;
+		ts.tv_sec += d->interval;
+
+		pthread_mutex_lock( &d->waitMutex );
+		if (d->running) {
+			rc = pthread_cond_timedwait(&d->cond, &d->waitMutex, &ts);
+		} else {
+			pthread_mutex_unlock( &d->waitMutex );
+			break;
+		}
+		pthread_mutex_unlock( &d->waitMutex );
+		if (rc == ETIMEDOUT) {
+			d->event->signal();
+		}
+	}
+#endif
+}
diff --git a/telldus-core/service/Timer.h b/telldus-core/service/Timer.h
new file mode 100644
index 00000000..7e8c082a
--- /dev/null
+++ b/telldus-core/service/Timer.h
@@ -0,0 +1,24 @@
+#ifndef TIMER_H
+#define TIMER_H
+
+#include "Event.h"
+#include "Thread.h"
+
+class Timer : public TelldusCore::Thread {
+public:
+	Timer(EventRef event);
+	virtual ~Timer();
+
+	void setInterval(int sec);
+	void stop();
+
+protected:
+	void run();
+
+private:
+	class PrivateData;
+	PrivateData *d;
+};
+
+
+#endif //TIMER_H

From 542d17a45de15d891024fbb5af13ececef77d3ec Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Mon, 9 Jan 2012 16:53:09 +0100
Subject: [PATCH 1781/2215] Add janitor object for regular maintenance and
 cleanups

---
 telldus-core/service/TelldusMain.cpp | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp
index 7a24561d..897264de 100644
--- a/telldus-core/service/TelldusMain.cpp
+++ b/telldus-core/service/TelldusMain.cpp
@@ -6,6 +6,8 @@
 #include "ControllerManager.h"
 #include "ControllerListener.h"
 #include "EventUpdateManager.h"
+#include "Timer.h"
+#include "Log.h"
 
 #include 
 #include 
@@ -39,6 +41,10 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) {
 void TelldusMain::start(void) {
 	EventRef clientEvent = d->eventHandler.addEvent();
 	EventRef dataEvent = d->eventHandler.addEvent();
+	EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups
+	Timer supervisor(janitor); //Tells the janitor to go back to work
+	supervisor.setInterval(60*5); //Every 5 minutes
+	supervisor.start();
 
 	ControllerManager controllerManager(dataEvent.get());
 	EventUpdateManager eventUpdateManager;
@@ -101,7 +107,16 @@ void TelldusMain::start(void) {
 				}
 			}
 		}
+		if (janitor->isSignaled()) {
+			//Clear all of them if there is more than one
+			while(janitor->isSignaled()) {
+				janitor->popSignal();
+			}
+			Log::debug("Do Janitor cleanup");
+		}
 	}
+
+	supervisor.stop();
 }
 
 void TelldusMain::stop(void){

From fb8e978accbe51e1a0923cb57edfd03c8ca531ca Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Mon, 9 Jan 2012 17:40:44 +0100
Subject: [PATCH 1782/2215] Implement class Timer in Windows

---
 telldus-core/service/Timer.cpp | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp
index 14181159..f552a414 100644
--- a/telldus-core/service/Timer.cpp
+++ b/telldus-core/service/Timer.cpp
@@ -1,6 +1,5 @@
 #include "Timer.h"
 #include "Mutex.h"
-#include "Log.h"
 #ifdef _WINDOWS
 #else
 #include 
@@ -14,6 +13,8 @@ public:
 	int interval;
 	bool running;
 #ifdef _WINDOWS
+	HANDLE cond;
+	TelldusCore::Mutex mutex;
 #else
 	pthread_mutex_t waitMutex;
 	pthread_cond_t cond;
@@ -25,6 +26,7 @@ Timer::Timer(EventRef event)
 {
 	d->event = event;
 #ifdef _WINDOWS
+	d->cond = CreateEventW(NULL, false, false, NULL);
 #else
 	pthread_cond_init(&d->cond, NULL);
 	pthread_mutex_init(&d->waitMutex, NULL);
@@ -49,6 +51,9 @@ void Timer::setInterval(int sec) {
 
 void Timer::stop() {
 #ifdef _WINDOWS
+	TelldusCore::MutexLocker(&d->mutex);
+	d->running = false;
+	SetEvent(d->cond);
 #else
 	//Signal event
 	pthread_mutex_lock(&d->waitMutex);
@@ -62,7 +67,22 @@ void Timer::stop() {
 
 void Timer::run() {
 #ifdef _WINDOWS
-		sleep(2); //TODO: Implement me
+	int interval = 0;
+	{
+		TelldusCore::MutexLocker(&d->mutex);
+		d->running = true;
+		interval = d->interval*1000;
+	}
+	while(1) {
+		DWORD retval = WaitForSingleObject(d->cond, interval);
+		if (retval == WAIT_TIMEOUT) {
+			d->event->signal();
+		}
+		TelldusCore::MutexLocker(&d->mutex);
+		if (!d->running) {
+			break;
+		}
+	}
 #else
 	struct timespec ts;
 	struct timeval tp;

From 06ac023b4a4081c2c409979fb0da45b8123ba9d1 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Tue, 10 Jan 2012 09:55:26 +0100
Subject: [PATCH 1783/2215] Resetting USB and retrying send once if TellStick
 is not found, in Linux

---
 telldus-core/service/Controller.h          |  1 +
 telldus-core/service/ControllerManager.cpp | 21 ++++++++
 telldus-core/service/ControllerManager.h   |  3 +-
 telldus-core/service/DeviceManager.cpp     | 56 ++++++++++++++++++++--
 telldus-core/service/TellStick.h           |  4 ++
 telldus-core/service/TellStick_libftdi.cpp | 24 ++++++++++
 6 files changed, 104 insertions(+), 5 deletions(-)

diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h
index a1b92e74..42c47a04 100644
--- a/telldus-core/service/Controller.h
+++ b/telldus-core/service/Controller.h
@@ -16,6 +16,7 @@ public:
 
 	virtual int firmwareVersion() = 0;
 	virtual int send( const std::string &message ) = 0;
+	virtual int reset() = 0;
 
 protected:
 	Controller(int id, Event *event);
diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp
index 6081a421..b29ae718 100644
--- a/telldus-core/service/ControllerManager.cpp
+++ b/telldus-core/service/ControllerManager.cpp
@@ -2,6 +2,7 @@
 #include "Controller.h"
 #include "Mutex.h"
 #include "TellStick.h"
+#include "Log.h"
 
 #include 
 #include 
@@ -90,18 +91,23 @@ void ControllerManager::loadControllers() {
 	std::list list = TellStick::findAll();
 
 	std::list::iterator it = list.begin();
+	Log::notice("Before for-loop");
 	for(; it != list.end(); ++it) {
+		Log::notice("Something in the loop");
 		//Most backend only report non-opened devices.
 		//If they don't make sure we don't open them twice
 		bool found = false;
 		ControllerMap::const_iterator cit = d->controllers.begin();
 		for(; cit != d->controllers.end(); ++cit) {
+			Log::notice("Something in second the loop");
 			TellStick *tellstick = reinterpret_cast(cit->second);
 			if (!tellstick) {
+				Log::notice("No tellstick");
 				continue;
 			}
 			if (tellstick->isSameAsDescriptor(*it)) {
 				found = true;
+				Log::notice("FOUND");
 				break;
 			}
 		}
@@ -111,7 +117,9 @@ void ControllerManager::loadControllers() {
 
 		int controllerId = d->lastControllerId-1;
 		TellStick *controller = new TellStick(controllerId, d->event, *it);
+		Log::notice("Is it open?");
 		if (!controller->isOpen()) {
+			Log::notice("Yes it was");
 			delete controller;
 			continue;
 		}
@@ -119,3 +127,16 @@ void ControllerManager::loadControllers() {
 		d->controllers[d->lastControllerId] = controller;
 	}
 }
+
+int ControllerManager::resetController(Controller *controller) {
+	TellStick *tellstick = reinterpret_cast(controller);
+	if (!tellstick) {
+		return true; //not tellstick, nothing to reset at the moment, just return true
+	}
+	Log::notice("resettingController");
+	int success = controller->reset(); //ehh, här är väl controllern borttagen förresten?
+	Log::notice("Remove device");
+	deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete
+	Log::notice("Device removed");
+	return success;
+}
diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h
index 199f7610..2653e77a 100644
--- a/telldus-core/service/ControllerManager.h
+++ b/telldus-core/service/ControllerManager.h
@@ -14,9 +14,8 @@ public:
 	void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted);
 
 	Controller *getBestControllerById(int id);
-
-protected:
 	void loadControllers();
+	int resetController(Controller *controller);
 
 private:
 	class PrivateData;
diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp
index 7a17eb12..54105a64 100644
--- a/telldus-core/service/DeviceManager.cpp
+++ b/telldus-core/service/DeviceManager.cpp
@@ -6,6 +6,7 @@
 #include "Strings.h"
 #include "Message.h"
 #include "common.h"
+#include "Log.h"
 
 #include 
 #include 
@@ -431,10 +432,40 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){
 		} //devicelist unlocked
 	}
 	else{
+		Log::notice("Getting a controller...");
 		Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
+		Log::notice("Doing action...");
+		if(!controller){
+			Log::warning("No controller found, rescanning USB ports");
+			//no controller found, scan for one, and retry once
+			d->controllerManager->loadControllers();
+			controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
+		}
+
 		if(controller){
+			Log::notice("But now, a controller!");
 			retval = device->doAction(action, data, controller);
+			Log::notice("Retval received, %d.", retval);
+			if(retval == TELLSTICK_ERROR_COMMUNICATION){
+				Log::warning("Error in communication with TellStick, resetting USB");
+				d->controllerManager->resetController(controller);
+				Log::notice("Controller reset");
+			}
+			if(retval == TELLSTICK_ERROR_COMMUNICATION || retval == TELLSTICK_ERROR_NOT_FOUND){
+				Log::warning("Rescanning USB ports");
+				d->controllerManager->loadControllers();
+				Log::notice("Loaded, get one");
+				controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
+				if(!controller){
+					Log::error("No contoller (TellStick) found, even after reset. Giving up.");
+					return TELLSTICK_ERROR_NOT_FOUND;
+				}
+				Log::notice("Got a new, do action");
+				retval = device->doAction(action, data, controller); //retry one more time
+				Log::notice("Did action");
+			}
 		} else {
+			Log::error("No contoller (TellStick) found after one retry. Giving up.");
 			return TELLSTICK_ERROR_NOT_FOUND;
 		}
 	}
@@ -719,10 +750,29 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int da
 int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){
 
 	Controller *controller = d->controllerManager->getBestControllerById(-1);
-	if(controller){
-		return controller->send(TelldusCore::wideToString(command));
+
+	if(!controller){
+		//no controller found, scan for one, and retry once
+		d->controllerManager->loadControllers();
+		controller = d->controllerManager->getBestControllerById(-1);
 	}
-	else{
+
+	int retval = TELLSTICK_ERROR_UNKNOWN;
+	if(controller){
+		retval = controller->send(TelldusCore::wideToString(command));
+		if(retval == TELLSTICK_ERROR_COMMUNICATION){
+			d->controllerManager->resetController(controller);
+		}
+		if(retval == TELLSTICK_ERROR_COMMUNICATION || retval == TELLSTICK_ERROR_NOT_FOUND){
+			d->controllerManager->loadControllers();
+			controller = d->controllerManager->getBestControllerById(-1);
+			if(!controller){
+				return TELLSTICK_ERROR_NOT_FOUND;
+			}
+			retval = controller->send(TelldusCore::wideToString(command));  //retry one more time
+		}
+		return retval;
+	} else {
 		return TELLSTICK_ERROR_NOT_FOUND;
 	}
 }
diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h
index 3824b1d8..db73faab 100644
--- a/telldus-core/service/TellStick.h
+++ b/telldus-core/service/TellStick.h
@@ -29,8 +29,12 @@ public:
 
 	virtual int firmwareVersion();
 	virtual int pid() const;
+	virtual int vid() const;
+	virtual std::string serial() const;
+
 	bool isOpen() const;
 	bool isSameAsDescriptor(const TellStickDescriptor &d) const;
+	virtual int reset();
 	virtual int send( const std::string &message );
 	bool stillConnected() const;
 
diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index 3202b282..bfc7fd22 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -21,6 +21,7 @@
 #include "Log.h"
 #include "Strings.h"
 #include "common.h"
+#include "Log.h"
 
 #include 
 
@@ -99,6 +100,14 @@ int TellStick::pid() const {
 	return d->pid;
 }
 
+int TellStick::vid() const {
+	return d->vid;
+}
+
+std::string TellStick::serial() const {
+	return d->serial;
+}
+
 bool TellStick::isOpen() const {
 	return d->open;
 }
@@ -135,6 +144,16 @@ void TellStick::processData( const std::string &data ) {
 	}
 }
 
+int TellStick::reset(){
+	Log::notice("Resetting one");
+	int success = ftdi_usb_reset( &d->ftHandle );
+	Log::notice("Has reset one");
+	if(success < 0){
+		return TELLSTICK_ERROR_UNKNOWN; //-1 = FTDI reset failed, -2 = USB device unavailable
+	}
+	return success;
+}
+
 void TellStick::run() {
 	int dwBytesRead = 0;
 	unsigned char buf[1024];     // = 0;
@@ -273,10 +292,15 @@ std::list TellStick::findAllByVIDPID( int vid, int pid ) {
 	char serialBuffer[10];
 	ftdi_init(&ftdic);
 
+	Log::notice("Trying to find Duo");
 	int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid);
 	if (ret > 0) {
+		Log::notice("Curdev > 0");
 		for (curdev = devlist; curdev != NULL; curdev = curdev->next) {
+			Log::notice("Something in the loop");
 			ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10);
+			Log::notice("Ret: %d",ret);
+			//blir -9 efter felen, "get serial number failed", även lsusb -v ger annat svar än innan...?
 			if (ret != 0) {
 				continue;
 			}

From 673daf471de0a8094bad2a567b78527158a5f15d Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Tue, 10 Jan 2012 16:00:14 +0100
Subject: [PATCH 1784/2215] Sending noop to TellStick every 5 minutes,
 attempting to reconnect if TellStick is missing. In Linux.

---
 telldus-core/common/Socket_unix.cpp        |  1 +
 telldus-core/service/ControllerManager.cpp | 43 +++++++++++++++++++++-
 telldus-core/service/ControllerManager.h   |  1 +
 telldus-core/service/TellStick_libftdi.cpp |  8 ++++
 telldus-core/service/TelldusMain.cpp       |  3 +-
 5 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp
index c98e0f94..0a2a2639 100644
--- a/telldus-core/common/Socket_unix.cpp
+++ b/telldus-core/common/Socket_unix.cpp
@@ -114,6 +114,7 @@ std::wstring Socket::read(int timeout) {
 void Socket::stopReadWait(){
 	TelldusCore::MutexLocker locker(&d->mutex);
 	d->connected = false;
+	//TODO somehow signal the socket here?
 }
 
 void Socket::write(const std::wstring &msg) {
diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp
index b29ae718..1ad33a20 100644
--- a/telldus-core/service/ControllerManager.cpp
+++ b/telldus-core/service/ControllerManager.cpp
@@ -3,6 +3,7 @@
 #include "Mutex.h"
 #include "TellStick.h"
 #include "Log.h"
+#include "../client/telldus-core.h"
 
 #include 
 #include 
@@ -99,7 +100,7 @@ void ControllerManager::loadControllers() {
 		bool found = false;
 		ControllerMap::const_iterator cit = d->controllers.begin();
 		for(; cit != d->controllers.end(); ++cit) {
-			Log::notice("Something in second the loop");
+			Log::notice("Something in the second loop");
 			TellStick *tellstick = reinterpret_cast(cit->second);
 			if (!tellstick) {
 				Log::notice("No tellstick");
@@ -128,13 +129,51 @@ void ControllerManager::loadControllers() {
 	}
 }
 
+void ControllerManager::queryControllerStatus(){
+
+	std::list tellStickControllers;
+
+	{
+		TelldusCore::MutexLocker locker(&d->mutex);
+		for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
+			Log::notice("found a controller");
+			TellStick *tellstick = reinterpret_cast(it->second);
+			if (tellstick) {
+				Log::notice("found a tellstick");
+				tellStickControllers.push_back(tellstick);
+			}
+		}
+	}
+
+	bool reloadControllers = false;
+	std::string noop = "noop";
+	for(std::list::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) {
+		int success = (*it)->send(noop);
+		if(success == TELLSTICK_ERROR_COMMUNICATION){
+			Log::warning("TellStick query: Error in communication with TellStick, resetting USB");
+			resetController(*it);
+			Log::notice("has reset");
+		}
+		if(success == TELLSTICK_ERROR_COMMUNICATION || success == TELLSTICK_ERROR_NOT_FOUND){
+			reloadControllers = true;
+			Log::notice("Set reload");
+		}
+	}
+
+	if(!tellStickControllers.size() || reloadControllers){
+		//no tellstick at all found, or controller was reset
+		Log::warning("TellStick query: Rescanning USB ports");
+		loadControllers();
+	}
+}
+
 int ControllerManager::resetController(Controller *controller) {
 	TellStick *tellstick = reinterpret_cast(controller);
 	if (!tellstick) {
 		return true; //not tellstick, nothing to reset at the moment, just return true
 	}
 	Log::notice("resettingController");
-	int success = controller->reset(); //ehh, här är väl controllern borttagen förresten?
+	int success = controller->reset();
 	Log::notice("Remove device");
 	deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete
 	Log::notice("Device removed");
diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h
index 2653e77a..bab3525c 100644
--- a/telldus-core/service/ControllerManager.h
+++ b/telldus-core/service/ControllerManager.h
@@ -15,6 +15,7 @@ public:
 
 	Controller *getBestControllerById(int id);
 	void loadControllers();
+	void queryControllerStatus();
 	int resetController(Controller *controller);
 
 private:
diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index bfc7fd22..61badf3c 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -215,6 +215,14 @@ int TellStick::send( const std::string &strMessage ) {
 	}
 
 	delete[] tempMessage;
+	if(strMessage == "noop"){
+		if(c){
+			return TELLSTICK_SUCCESS;
+		}
+		else{
+			return TELLSTICK_ERROR_COMMUNICATION;
+		}
+	}
 
 	int retrycnt = 500;
 	unsigned char in;
diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp
index 897264de..107c9e31 100644
--- a/telldus-core/service/TelldusMain.cpp
+++ b/telldus-core/service/TelldusMain.cpp
@@ -43,7 +43,7 @@ void TelldusMain::start(void) {
 	EventRef dataEvent = d->eventHandler.addEvent();
 	EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups
 	Timer supervisor(janitor); //Tells the janitor to go back to work
-	supervisor.setInterval(60*5); //Every 5 minutes
+	supervisor.setInterval(10); //Every 5 minutes TODO how often? 60*5
 	supervisor.start();
 
 	ControllerManager controllerManager(dataEvent.get());
@@ -113,6 +113,7 @@ void TelldusMain::start(void) {
 				janitor->popSignal();
 			}
 			Log::debug("Do Janitor cleanup");
+			controllerManager.queryControllerStatus();
 		}
 	}
 

From 0c8de249d4250159c0b215c5d806d15d28de3bae Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Tue, 10 Jan 2012 17:35:18 +0100
Subject: [PATCH 1785/2215] Cycling port and trying to reconnect TellStick on
 noop or send when missing

---
 telldus-core/service/TellStick_ftd2xx.cpp | 24 +++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp
index 288aff42..8607aa24 100644
--- a/telldus-core/service/TellStick_ftd2xx.cpp
+++ b/telldus-core/service/TellStick_ftd2xx.cpp
@@ -113,6 +113,14 @@ int TellStick::pid() const {
 	return d->pid;
 }
 
+int TellStick::vid() const {
+	return d->vid;
+}
+
+std::string TellStick::serial() const {
+	return d->serial;
+}
+
 bool TellStick::isOpen() const {
 	return d->open;
 }
@@ -149,6 +157,14 @@ void TellStick::processData( const std::string &data ) {
 	}
 }
 
+int TellStick::reset(){
+	int success = FT_CyclePort( d->ftHandle );
+	if(success == FT_OK){
+		return success;
+	}
+	return TELLSTICK_ERROR_UNKNOWN;
+}
+
 void TellStick::run() {
 	d->running = true;
 	DWORD dwBytesInQueue = 0;
@@ -210,6 +226,14 @@ int TellStick::send( const std::string &strMessage ) {
 	FT_STATUS ftStatus;
 	ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten);
 	free(tempMessage);
+	if(strMessage == "noop"){
+		if(c){
+			return TELLSTICK_SUCCESS;
+		}
+		else{
+			return TELLSTICK_ERROR_COMMUNICATION;
+		}
+	}
 
 	while(c) {
 		ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead);

From 8d22eff5da33b1ab94e7459832a33e1f1ab6587c Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Wed, 11 Jan 2012 11:38:03 +0100
Subject: [PATCH 1786/2215] Added wait for ack on noop-command

---
 telldus-core/service/ControllerManager.cpp | 20 +++-----------------
 telldus-core/service/DeviceManager.cpp     | 16 +++-------------
 telldus-core/service/TellStick_libftdi.cpp | 16 ++++++----------
 telldus-core/service/TelldusMain.cpp       |  2 +-
 4 files changed, 13 insertions(+), 41 deletions(-)

diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp
index 1ad33a20..d9bc0360 100644
--- a/telldus-core/service/ControllerManager.cpp
+++ b/telldus-core/service/ControllerManager.cpp
@@ -92,23 +92,18 @@ void ControllerManager::loadControllers() {
 	std::list list = TellStick::findAll();
 
 	std::list::iterator it = list.begin();
-	Log::notice("Before for-loop");
 	for(; it != list.end(); ++it) {
-		Log::notice("Something in the loop");
 		//Most backend only report non-opened devices.
 		//If they don't make sure we don't open them twice
 		bool found = false;
 		ControllerMap::const_iterator cit = d->controllers.begin();
 		for(; cit != d->controllers.end(); ++cit) {
-			Log::notice("Something in the second loop");
 			TellStick *tellstick = reinterpret_cast(cit->second);
 			if (!tellstick) {
-				Log::notice("No tellstick");
 				continue;
 			}
 			if (tellstick->isSameAsDescriptor(*it)) {
 				found = true;
-				Log::notice("FOUND");
 				break;
 			}
 		}
@@ -118,9 +113,7 @@ void ControllerManager::loadControllers() {
 
 		int controllerId = d->lastControllerId-1;
 		TellStick *controller = new TellStick(controllerId, d->event, *it);
-		Log::notice("Is it open?");
 		if (!controller->isOpen()) {
-			Log::notice("Yes it was");
 			delete controller;
 			continue;
 		}
@@ -136,33 +129,29 @@ void ControllerManager::queryControllerStatus(){
 	{
 		TelldusCore::MutexLocker locker(&d->mutex);
 		for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
-			Log::notice("found a controller");
 			TellStick *tellstick = reinterpret_cast(it->second);
 			if (tellstick) {
-				Log::notice("found a tellstick");
 				tellStickControllers.push_back(tellstick);
 			}
 		}
 	}
 
 	bool reloadControllers = false;
-	std::string noop = "noop";
+	std::string noop = "N+";
 	for(std::list::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) {
 		int success = (*it)->send(noop);
 		if(success == TELLSTICK_ERROR_COMMUNICATION){
 			Log::warning("TellStick query: Error in communication with TellStick, resetting USB");
 			resetController(*it);
-			Log::notice("has reset");
 		}
 		if(success == TELLSTICK_ERROR_COMMUNICATION || success == TELLSTICK_ERROR_NOT_FOUND){
 			reloadControllers = true;
-			Log::notice("Set reload");
 		}
 	}
 
 	if(!tellStickControllers.size() || reloadControllers){
 		//no tellstick at all found, or controller was reset
-		Log::warning("TellStick query: Rescanning USB ports");
+		Log::debug("TellStick query: Rescanning USB ports");  //only log as debug, since this will happen all the time if no TellStick is connected
 		loadControllers();
 	}
 }
@@ -172,10 +161,7 @@ int ControllerManager::resetController(Controller *controller) {
 	if (!tellstick) {
 		return true; //not tellstick, nothing to reset at the moment, just return true
 	}
-	Log::notice("resettingController");
-	int success = controller->reset();
-	Log::notice("Remove device");
+	int success = tellstick->reset();
 	deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete
-	Log::notice("Device removed");
 	return success;
 }
diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp
index fdc71a4b..a6ef8603 100644
--- a/telldus-core/service/DeviceManager.cpp
+++ b/telldus-core/service/DeviceManager.cpp
@@ -5,9 +5,7 @@
 #include "Settings.h"
 #include "Strings.h"
 #include "Message.h"
-
-#include "common.h" //TODO remove?
-#include "Log.h" //TODO remove?
+#include "Log.h"
 
 #include 
 #include 
@@ -433,37 +431,29 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){
 		} //devicelist unlocked
 	}
 	else{
-		Log::notice("Getting a controller...");
 		Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
-		Log::notice("Doing action...");
 		if(!controller){
-			Log::warning("No controller found, rescanning USB ports");
+			Log::warning("Trying to execute action, but no controller found. Rescanning USB ports");
 			//no controller found, scan for one, and retry once
 			d->controllerManager->loadControllers();
 			controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
 		}
 
 		if(controller){
-			Log::notice("But now, a controller!");
 			retval = device->doAction(action, data, controller);
-			Log::notice("Retval received, %d.", retval);
 			if(retval == TELLSTICK_ERROR_COMMUNICATION){
-				Log::warning("Error in communication with TellStick, resetting USB");
+				Log::warning("Error in communication with TellStick when executing action. Resetting USB");
 				d->controllerManager->resetController(controller);
-				Log::notice("Controller reset");
 			}
 			if(retval == TELLSTICK_ERROR_COMMUNICATION || retval == TELLSTICK_ERROR_NOT_FOUND){
 				Log::warning("Rescanning USB ports");
 				d->controllerManager->loadControllers();
-				Log::notice("Loaded, get one");
 				controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
 				if(!controller){
 					Log::error("No contoller (TellStick) found, even after reset. Giving up.");
 					return TELLSTICK_ERROR_NOT_FOUND;
 				}
-				Log::notice("Got a new, do action");
 				retval = device->doAction(action, data, controller); //retry one more time
-				Log::notice("Did action");
 			}
 		} else {
 			Log::error("No contoller (TellStick) found after one retry. Giving up.");
diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index 61badf3c..92cd82fc 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -145,9 +145,7 @@ void TellStick::processData( const std::string &data ) {
 }
 
 int TellStick::reset(){
-	Log::notice("Resetting one");
 	int success = ftdi_usb_reset( &d->ftHandle );
-	Log::notice("Has reset one");
 	if(success < 0){
 		return TELLSTICK_ERROR_UNKNOWN; //-1 = FTDI reset failed, -2 = USB device unavailable
 	}
@@ -210,12 +208,14 @@ int TellStick::send( const std::string &strMessage ) {
 	if(ret < 0) {
 		c = false;
 	} else if(ret != strMessage.length()) {
-		fprintf(stderr, "weird send length? retval %i instead of %d\n",
-		ret, (int)strMessage.length());
+		Log::debug("Weird send length? retval %i instead of %d\n", ret, (int)strMessage.length());
 	}
 
 	delete[] tempMessage;
-	if(strMessage == "noop"){
+	Log::notice("Message: %s", strMessage.c_str());
+	if(strMessage == "N+" && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){
+		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
+		Log::notice("Too old firmware, accepting this");
 		if(c){
 			return TELLSTICK_SUCCESS;
 		}
@@ -223,6 +223,7 @@ int TellStick::send( const std::string &strMessage ) {
 			return TELLSTICK_ERROR_COMMUNICATION;
 		}
 	}
+	Log::warning("Continuing");
 
 	int retrycnt = 500;
 	unsigned char in;
@@ -300,15 +301,10 @@ std::list TellStick::findAllByVIDPID( int vid, int pid ) {
 	char serialBuffer[10];
 	ftdi_init(&ftdic);
 
-	Log::notice("Trying to find Duo");
 	int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid);
 	if (ret > 0) {
-		Log::notice("Curdev > 0");
 		for (curdev = devlist; curdev != NULL; curdev = curdev->next) {
-			Log::notice("Something in the loop");
 			ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10);
-			Log::notice("Ret: %d",ret);
-			//blir -9 efter felen, "get serial number failed", även lsusb -v ger annat svar än innan...?
 			if (ret != 0) {
 				continue;
 			}
diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp
index 107c9e31..5a2b8b4b 100644
--- a/telldus-core/service/TelldusMain.cpp
+++ b/telldus-core/service/TelldusMain.cpp
@@ -43,7 +43,7 @@ void TelldusMain::start(void) {
 	EventRef dataEvent = d->eventHandler.addEvent();
 	EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups
 	Timer supervisor(janitor); //Tells the janitor to go back to work
-	supervisor.setInterval(10); //Every 5 minutes TODO how often? 60*5
+	supervisor.setInterval(10); //TODO Once every minute
 	supervisor.start();
 
 	ControllerManager controllerManager(dataEvent.get());

From d7cce515ff9fca11b5be98bf926bcc355c949294 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Wed, 11 Jan 2012 14:53:46 +0100
Subject: [PATCH 1787/2215] Added setting for 'Not wait for confirmation from
 TellStick', see ticket 98, in Linux

---
 telldus-core/client/Client.cpp                      |  7 ++++++-
 telldus-core/service/ClientCommunicationHandler.cpp |  1 +
 telldus-core/service/SettingsConfuse.cpp            |  1 +
 telldus-core/service/TellStick_libftdi.cpp          | 13 ++++++++++---
 telldus-core/service/tellstick.conf                 |  1 +
 5 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp
index 3ddf7f36..1ec07b29 100644
--- a/telldus-core/client/Client.cpp
+++ b/telldus-core/client/Client.cpp
@@ -296,21 +296,26 @@ std::wstring Client::sendToService(const Message &msg) {
 		Socket s;
 		s.connect(L"TelldusClient");
 		if (!s.isConnected()) { //Connection failed
+			printf("Connection failed\n\r");
 			msleep(500);
 			continue; //retry
 		}
 		s.write(msg.data());
 		if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later)
+			printf("Connection failed after write\n\r");
 			msleep(500);
 			continue; //retry
 		}
-		readData = s.read(5000);
+		readData = s.read(10000);  //TODO changed to 10000 from 5000, how much does this do...?
 		if(readData == L""){
+			printf("Readdata nothing\n\r");
 			msleep(500);
 			continue; //TODO can we be really sure it SHOULD be anything?
+			//TODO perhaps break here instead?
 		}
 		
 		if (!s.isConnected()) { //Connection failed sometime during operation...
+			printf("Connection failed in the end\n\r");
 			msleep(500);
 			continue; //retry
 		}
diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp
index d51144ab..e6f04806 100644
--- a/telldus-core/service/ClientCommunicationHandler.cpp
+++ b/telldus-core/service/ClientCommunicationHandler.cpp
@@ -1,6 +1,7 @@
 #include "ClientCommunicationHandler.h"
 #include "Message.h"
 #include "Strings.h"
+#include "Log.h" //Debug
 
 #include 
 
diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp
index af7e005f..9c0c7084 100644
--- a/telldus-core/service/SettingsConfuse.cpp
+++ b/telldus-core/service/SettingsConfuse.cpp
@@ -375,6 +375,7 @@ bool readConfig(cfg_t **cfg) {
 		CFG_STR(const_cast("user"), const_cast("nobody"), CFGF_NONE),
 		CFG_STR(const_cast("group"), const_cast("plugdev"), CFGF_NONE),
 		CFG_STR(const_cast("deviceNode"), const_cast("/dev/tellstick"), CFGF_NONE),
+		CFG_STR(const_cast("ignoreControllerConfirmation"), const_cast("false"), CFGF_NONE),
 		CFG_SEC(const_cast("device"), device_opts, CFGF_MULTI),
 		CFG_END()
 	};
diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index 92cd82fc..0da58e69 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -19,9 +19,9 @@
 #include "Thread.h"
 #include "Mutex.h"
 #include "Log.h"
+#include "Settings.h"
 #include "Strings.h"
 #include "common.h"
-#include "Log.h"
 
 #include 
 
@@ -33,7 +33,7 @@ typedef int DWORD;
 
 class TellStick::PrivateData {
 public:
-	bool open;
+	bool open, ignoreControllerConfirmation;
 	int vid, pid, fwVersion;
 	std::string serial, message;
 	ftdi_context ftHandle;
@@ -53,6 +53,9 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 	d->serial = td.serial;
 	d->running = false;
 
+	Settings set;
+	d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true";
+
 	ftdi_init(&d->ftHandle);
 	ftdi_set_interface(&d->ftHandle, INTERFACE_ANY);
 
@@ -213,13 +216,15 @@ int TellStick::send( const std::string &strMessage ) {
 
 	delete[] tempMessage;
 	Log::notice("Message: %s", strMessage.c_str());
-	if(strMessage == "N+" && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){
+	if(d->ignoreControllerConfirmation || (strMessage == "N+" && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6)))){
 		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
 		Log::notice("Too old firmware, accepting this");
 		if(c){
+			Log::notice("Success");
 			return TELLSTICK_SUCCESS;
 		}
 		else{
+			Log::notice("Fail");
 			return TELLSTICK_ERROR_COMMUNICATION;
 		}
 	}
@@ -230,7 +235,9 @@ int TellStick::send( const std::string &strMessage ) {
 	while(c && --retrycnt) {
 		ret = ftdi_read_data( &d->ftHandle, &in, 1);
 		if (ret > 0) {
+			Log::notice("Returned %c", in);
 			if (in == '\n') {
+				Log::notice("BREAK");
 				break;
 			}
 		} else if(ret == 0) { // No data available
diff --git a/telldus-core/service/tellstick.conf b/telldus-core/service/tellstick.conf
index 1a1bfe81..fed9c66f 100644
--- a/telldus-core/service/tellstick.conf
+++ b/telldus-core/service/tellstick.conf
@@ -1,5 +1,6 @@
 user = "nobody"
 group = "plugdev"
+ignoreControllerConfirmation = "false"
 device {
   id = 1
   name = "Example device"

From 4068742b254f2b7a11aba2fee7294d136447aa9b Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Wed, 11 Jan 2012 16:16:31 +0100
Subject: [PATCH 1788/2215] Setting for 'Not wait for confirmation from
 TellStick' implemented on windows too. This setting must be set manually.
 Closes #98

---
 telldus-core/service/SettingsWinRegistry.cpp | 27 ++++++++++++++++++++
 telldus-core/service/TellStick_ftd2xx.cpp    |  9 +++++--
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp
index aed7ad3a..5ee83b2c 100644
--- a/telldus-core/service/SettingsWinRegistry.cpp
+++ b/telldus-core/service/SettingsWinRegistry.cpp
@@ -157,6 +157,33 @@ int Settings::removeDevice(int intDeviceId) {
 	return TELLSTICK_ERROR_UNKNOWN;
 }
 
+std::wstring Settings::getSetting(const std::wstring &strName) const{
+	std::wstring strReturn;
+	HKEY hk;
+
+	std::wstring strCompleteRegPath = d->strRegPath;
+	long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk);
+			
+	if(lnExists == ERROR_SUCCESS){
+		wchar_t* Buff = new wchar_t[intMaxRegValueLength];
+		DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength;
+		long lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
+
+		if(lngStatus == ERROR_MORE_DATA){
+			//The buffer is to small, recreate it
+			delete Buff;
+			Buff = new wchar_t[dwLength];
+			lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
+		}
+		if (lngStatus == ERROR_SUCCESS) {
+			strReturn = Buff;
+		}
+		delete Buff;
+	}
+	RegCloseKey(hk);
+	return strReturn;
+}
+
 std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const {
 	std::wstring strReturn;
 	HKEY hk;
diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp
index 8607aa24..2379b13f 100644
--- a/telldus-core/service/TellStick_ftd2xx.cpp
+++ b/telldus-core/service/TellStick_ftd2xx.cpp
@@ -11,6 +11,7 @@
 //
 #include "TellStick.h"
 #include "Mutex.h"
+#include "Settings.h"
 #include "Strings.h"
 #include "Log.h"
 #include "../client/telldus-core.h"
@@ -21,7 +22,7 @@
 
 class TellStick::PrivateData {
 public:
-	bool open, running;
+	bool open, running, ignoreControllerConfirmation;
 	int vid, pid, fwVersion;
 	std::string serial, message;
 	FT_HANDLE ftHandle;
@@ -54,6 +55,8 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 	d->pid = td.pid;
 	d->fwVersion = 0;
 	d->serial = td.serial;
+	Settings set;
+	d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true";
 
 	char *tempSerial = new char[td.serial.size()+1];
 #ifdef _WINDOWS
@@ -226,7 +229,9 @@ int TellStick::send( const std::string &strMessage ) {
 	FT_STATUS ftStatus;
 	ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten);
 	free(tempMessage);
-	if(strMessage == "noop"){
+	
+	if(d->ignoreControllerConfirmation || (strMessage == "N+" && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6)))){
+		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
 		if(c){
 			return TELLSTICK_SUCCESS;
 		}

From b0f092e98d602301ead905292420777c5da7640e Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 10:30:23 +0100
Subject: [PATCH 1789/2215] Lower the read timeout for events in the client.
 This should be reset again when #157 is fixed. See #157.

---
 telldus-core/client/Client.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp
index 1ec07b29..59d68e8e 100644
--- a/telldus-core/client/Client.cpp
+++ b/telldus-core/client/Client.cpp
@@ -181,7 +181,7 @@ void Client::run(){
 			}
 		}
 
-		std::wstring clientMessage = d->eventSocket.read(5000);	//testing 5 second timeout
+		std::wstring clientMessage = d->eventSocket.read(1000);	//testing 5 second timeout
 
 		while(clientMessage != L""){
 			//a message arrived

From 69059b935b81ae1ab0b06c99638a1b837619e05c Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 10:33:11 +0100
Subject: [PATCH 1790/2215] Lower the retry count (again). ftdi_read_data()
 uses the latency times as a timeout. This is set to 16ms so 250 retries take
 about 4s if we don't get a response (worst case). The longest protocol we
 could think of is "learn" for risingsun selflearning. It takes roughly 3s to
 finish.

---
 telldus-core/service/TellStick_libftdi.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index 0da58e69..6410f989 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -68,6 +68,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
 	d->open = true;
 	ftdi_usb_reset( &d->ftHandle );
 	ftdi_disable_bitbang( &d->ftHandle );
+	ftdi_set_latency_timer(&d->ftHandle, 16);
 
 	if (d->open) {
 
@@ -230,7 +231,7 @@ int TellStick::send( const std::string &strMessage ) {
 	}
 	Log::warning("Continuing");
 
-	int retrycnt = 500;
+	int retrycnt = 250;
 	unsigned char in;
 	while(c && --retrycnt) {
 		ret = ftdi_read_data( &d->ftHandle, &in, 1);

From b84e8b3806d9db62cfda5035e274ef6fe0b9f817 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Thu, 12 Jan 2012 11:39:04 +0100
Subject: [PATCH 1791/2215] Added TELLSTICK_ERROR_BROKEN_PIPE to distinguate
 between when communication with TellStick fails due to timeout or actual
 error.

---
 telldus-core/client/Client.cpp                |  2 +-
 telldus-core/client/telldus-core.cpp          |  9 +++--
 telldus-core/client/telldus-core.h            |  1 +
 .../service/ClientCommunicationHandler.cpp    |  1 -
 telldus-core/service/ControllerManager.cpp    |  4 +--
 telldus-core/service/DeviceManager.cpp        |  8 ++---
 telldus-core/service/TellStick_libftdi.cpp    | 34 ++++++++++---------
 telldus-core/service/TelldusMain.cpp          |  2 +-
 8 files changed, 34 insertions(+), 27 deletions(-)

diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp
index 59d68e8e..291f45df 100644
--- a/telldus-core/client/Client.cpp
+++ b/telldus-core/client/Client.cpp
@@ -306,7 +306,7 @@ std::wstring Client::sendToService(const Message &msg) {
 			msleep(500);
 			continue; //retry
 		}
-		readData = s.read(10000);  //TODO changed to 10000 from 5000, how much does this do...?
+		readData = s.read(8000);  //TODO changed to 10000 from 5000, how much does this do...?
 		if(readData == L""){
 			printf("Readdata nothing\n\r");
 			msleep(500);
diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp
index 18775d56..eccd6f0f 100644
--- a/telldus-core/client/telldus-core.cpp
+++ b/telldus-core/client/telldus-core.cpp
@@ -57,6 +57,9 @@ using namespace TelldusCore;
  * @def TELLSTICK_SUCCESS
  * Error code. Returned when the command succeeded.
  *
+ * @def TELLSTICK_ERROR_BROKEN_PIPE
+ * Error code. Pipe broken during communication.
+ *
  * @def TELLSTICK_ERROR_NOT_FOUND
  * Error code. Returned if a TellStick was not found on the system.
  *
@@ -487,10 +490,11 @@ int WINAPI tdMethods(int id, int methodsSupported){
  * @sa TELLSTICK_ERROR_CONNECTING_SERVICE
  * @sa TELLSTICK_ERROR_UNKNOWN_RESPONSE
  * @sa TELLSTICK_ERROR_SYNTAX
+ * @sa TELLSTICK_ERROR_BROKEN_PIPE
  * @sa TELLSTICK_ERROR_UNKNOWN
  */
 char * WINAPI tdGetErrorString(int intErrorNo) {
-	const int numResponses = 9;
+	const int numResponses = 10;
 	const char *responses[numResponses] = {
 		"Success",
 		"TellStick not found",
@@ -500,7 +504,8 @@ char * WINAPI tdGetErrorString(int intErrorNo) {
 		"An error occurred while communicating with TellStick",
 		"Could not connect to the Telldus Service",
 		"Received an unknown response",
-		"Syntax error"
+		"Syntax error",
+		"Broken pipe"
 	};
 	std::string strReturn;
 	intErrorNo = abs(intErrorNo); //We don't use negative values here.
diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h
index 9d7ee9c2..cfa22122 100644
--- a/telldus-core/client/telldus-core.h
+++ b/telldus-core/client/telldus-core.h
@@ -116,6 +116,7 @@ extern "C" {
 #define TELLSTICK_ERROR_CONNECTING_SERVICE -6
 #define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7
 #define TELLSTICK_ERROR_SYNTAX -8
+#define TELLSTICK_ERROR_BROKEN_PIPE -9
 #define TELLSTICK_ERROR_UNKNOWN -99
 
 //Device typedef
diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp
index e6f04806..d51144ab 100644
--- a/telldus-core/service/ClientCommunicationHandler.cpp
+++ b/telldus-core/service/ClientCommunicationHandler.cpp
@@ -1,7 +1,6 @@
 #include "ClientCommunicationHandler.h"
 #include "Message.h"
 #include "Strings.h"
-#include "Log.h" //Debug
 
 #include 
 
diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp
index d9bc0360..6865e450 100644
--- a/telldus-core/service/ControllerManager.cpp
+++ b/telldus-core/service/ControllerManager.cpp
@@ -140,11 +140,11 @@ void ControllerManager::queryControllerStatus(){
 	std::string noop = "N+";
 	for(std::list::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) {
 		int success = (*it)->send(noop);
-		if(success == TELLSTICK_ERROR_COMMUNICATION){
+		if(success == TELLSTICK_ERROR_BROKEN_PIPE){
 			Log::warning("TellStick query: Error in communication with TellStick, resetting USB");
 			resetController(*it);
 		}
-		if(success == TELLSTICK_ERROR_COMMUNICATION || success == TELLSTICK_ERROR_NOT_FOUND){
+		if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND){
 			reloadControllers = true;
 		}
 	}
diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp
index a6ef8603..3930108a 100644
--- a/telldus-core/service/DeviceManager.cpp
+++ b/telldus-core/service/DeviceManager.cpp
@@ -441,11 +441,11 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){
 
 		if(controller){
 			retval = device->doAction(action, data, controller);
-			if(retval == TELLSTICK_ERROR_COMMUNICATION){
+			if(retval == TELLSTICK_ERROR_BROKEN_PIPE){
 				Log::warning("Error in communication with TellStick when executing action. Resetting USB");
 				d->controllerManager->resetController(controller);
 			}
-			if(retval == TELLSTICK_ERROR_COMMUNICATION || retval == TELLSTICK_ERROR_NOT_FOUND){
+			if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){
 				Log::warning("Rescanning USB ports");
 				d->controllerManager->loadControllers();
 				controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
@@ -751,10 +751,10 @@ int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){
 	int retval = TELLSTICK_ERROR_UNKNOWN;
 	if(controller){
 		retval = controller->send(TelldusCore::wideToString(command));
-		if(retval == TELLSTICK_ERROR_COMMUNICATION){
+		if(retval == TELLSTICK_ERROR_BROKEN_PIPE){
 			d->controllerManager->resetController(controller);
 		}
-		if(retval == TELLSTICK_ERROR_COMMUNICATION || retval == TELLSTICK_ERROR_NOT_FOUND){
+		if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){
 			d->controllerManager->loadControllers();
 			controller = d->controllerManager->getBestControllerById(-1);
 			if(!controller){
diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index 6410f989..6a114eb2 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -217,42 +217,44 @@ int TellStick::send( const std::string &strMessage ) {
 
 	delete[] tempMessage;
 	Log::notice("Message: %s", strMessage.c_str());
+	Log::notice("FWVersion: %d", firmwareVersion());
+	Log::notice("Pid: %X", pid());
+
+	if(!c){
+		Log::debug("Broken pipe on send");
+		return TELLSTICK_ERROR_BROKEN_PIPE;
+	}
+
 	if(d->ignoreControllerConfirmation || (strMessage == "N+" && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6)))){
 		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
-		Log::notice("Too old firmware, accepting this");
-		if(c){
-			Log::notice("Success");
-			return TELLSTICK_SUCCESS;
-		}
-		else{
-			Log::notice("Fail");
-			return TELLSTICK_ERROR_COMMUNICATION;
-		}
+		Log::notice("Too old firmware, accepting this, just return success");
+		return TELLSTICK_SUCCESS;
 	}
 	Log::warning("Continuing");
 
 	int retrycnt = 250;
 	unsigned char in;
-	while(c && --retrycnt) {
+	while(--retrycnt) {
 		ret = ftdi_read_data( &d->ftHandle, &in, 1);
 		if (ret > 0) {
-			Log::notice("Returned %c", in);
+			Log::warning("%c", in);
 			if (in == '\n') {
-				Log::notice("BREAK");
+				Log::warning("Received an end");
 				break;
 			}
 		} else if(ret == 0) { // No data available
 			usleep(100);
 		} else { //Error
-			c = false;
+			Log::debug("Broken pipe on read");
+			return TELLSTICK_ERROR_BROKEN_PIPE;
 		}
 	}
+	Log::warning("Retry ready");
 	if (!retrycnt) {
-		c = false;
-	}
-	if (!c) {
+		Log::warning("Error in communication, retrycount ended");
 		return TELLSTICK_ERROR_COMMUNICATION;
 	}
+	Log::warning("Success");
 	return TELLSTICK_SUCCESS;
 }
 
diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp
index 5a2b8b4b..a10f6da8 100644
--- a/telldus-core/service/TelldusMain.cpp
+++ b/telldus-core/service/TelldusMain.cpp
@@ -43,7 +43,7 @@ void TelldusMain::start(void) {
 	EventRef dataEvent = d->eventHandler.addEvent();
 	EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups
 	Timer supervisor(janitor); //Tells the janitor to go back to work
-	supervisor.setInterval(10); //TODO Once every minute
+	supervisor.setInterval(60); //Once every minute
 	supervisor.start();
 
 	ControllerManager controllerManager(dataEvent.get());

From c527223bc420b18a6de5b3037befd935a288597f Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Thu, 12 Jan 2012 14:17:24 +0100
Subject: [PATCH 1792/2215] Made use of TELLSTICK_ERROR_BROKEN_PIPE in windows
 too

---
 telldus-core/service/TellStick_ftd2xx.cpp | 39 ++++++++++++-----------
 1 file changed, 21 insertions(+), 18 deletions(-)

diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp
index 2379b13f..0f55241d 100644
--- a/telldus-core/service/TellStick_ftd2xx.cpp
+++ b/telldus-core/service/TellStick_ftd2xx.cpp
@@ -10,6 +10,7 @@
 //
 //
 #include "TellStick.h"
+#include "common.h"
 #include "Mutex.h"
 #include "Settings.h"
 #include "Strings.h"
@@ -210,8 +211,7 @@ int TellStick::send( const std::string &strMessage ) {
 	if (!d->open) {
 		return TELLSTICK_ERROR_NOT_FOUND;
 	}
-	bool c = true;
-
+	
 	//This lock does two things
 	// 1 Prevents two calls from different threads to this function
 	// 2 Prevents our running thread from receiving the data we are interested in here
@@ -230,35 +230,38 @@ int TellStick::send( const std::string &strMessage ) {
 	ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten);
 	free(tempMessage);
 	
-	if(d->ignoreControllerConfirmation || (strMessage == "N+" && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6)))){
+	if(ftStatus != FT_OK){
+		Log::debug("Broken pipe on send");
+		return TELLSTICK_ERROR_BROKEN_PIPE;
+	}
+
+	if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){
 		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
-		if(c){
-			return TELLSTICK_SUCCESS;
-		}
-		else{
-			return TELLSTICK_ERROR_COMMUNICATION;
-		}
+		return TELLSTICK_SUCCESS;
+	}
+	if(d->ignoreControllerConfirmation){
+		//wait for TellStick to finish its air-sending
+		msleep(1000);
+		return TELLSTICK_SUCCESS;
 	}
 
-	while(c) {
+	while(1) {
 		ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead);
 		if (ftStatus == FT_OK) {
 			if (bytesRead == 1) {
 				if (in == '\n') {
-					break;
+					return TELLSTICK_SUCCESS;
+				} else {
+					continue;
 				}
 			} else { //Timeout
-				c = false;
+				return TELLSTICK_ERROR_COMMUNICATION;
 			}
 		} else { //Error
-			c = false;
+			Log::debug("Broken pipe on read");
+			return TELLSTICK_ERROR_BROKEN_PIPE;
 		}
 	}
-
-	if (!c) {
-		return TELLSTICK_ERROR_COMMUNICATION;
-	}
-	return TELLSTICK_SUCCESS;
 }
 
 bool TellStick::stillConnected() const {

From 3ce58f019fbe42e77592b30166a1f44a732eeee5 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Thu, 12 Jan 2012 14:21:03 +0100
Subject: [PATCH 1793/2215] Added sleep time to allow TellStick to finish air
 sending when ignoring answer from TellStick

---
 telldus-core/service/TellStick_libftdi.cpp | 24 +++++++++++++---------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index 6a114eb2..7c0342f9 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -225,11 +225,19 @@ int TellStick::send( const std::string &strMessage ) {
 		return TELLSTICK_ERROR_BROKEN_PIPE;
 	}
 
-	if(d->ignoreControllerConfirmation || (strMessage == "N+" && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6)))){
+	if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){
 		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
-		Log::notice("Too old firmware, accepting this, just return success");
+		Log::warning("Too old firmware, accepting this, just return success");
 		return TELLSTICK_SUCCESS;
 	}
+
+	if(d->ignoreControllerConfirmation){
+		//allow TellStick to finish its air-sending
+		Log::warning("Sleeping");
+		msleep(1000);
+		return TELLSTICK_SUCCESS;
+	}
+
 	Log::warning("Continuing");
 
 	int retrycnt = 250;
@@ -240,7 +248,7 @@ int TellStick::send( const std::string &strMessage ) {
 			Log::warning("%c", in);
 			if (in == '\n') {
 				Log::warning("Received an end");
-				break;
+				return TELLSTICK_SUCCESS;
 			}
 		} else if(ret == 0) { // No data available
 			usleep(100);
@@ -249,13 +257,9 @@ int TellStick::send( const std::string &strMessage ) {
 			return TELLSTICK_ERROR_BROKEN_PIPE;
 		}
 	}
-	Log::warning("Retry ready");
-	if (!retrycnt) {
-		Log::warning("Error in communication, retrycount ended");
-		return TELLSTICK_ERROR_COMMUNICATION;
-	}
-	Log::warning("Success");
-	return TELLSTICK_SUCCESS;
+
+	Log::warning("Error in communication, retrycount ended");
+	return TELLSTICK_ERROR_COMMUNICATION;
 }
 
 void TellStick::setBaud(int baud) {

From e2e9ba4634204ee09c0868b9088fd15e82ee2139 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Thu, 12 Jan 2012 14:27:15 +0100
Subject: [PATCH 1794/2215] Code cleanup

---
 telldus-core/service/TellStick_libftdi.cpp | 10 ----------
 telldus-core/service/TelldusMain.cpp       |  1 -
 2 files changed, 11 deletions(-)

diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index 7c0342f9..fd3edc26 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -216,9 +216,6 @@ int TellStick::send( const std::string &strMessage ) {
 	}
 
 	delete[] tempMessage;
-	Log::notice("Message: %s", strMessage.c_str());
-	Log::notice("FWVersion: %d", firmwareVersion());
-	Log::notice("Pid: %X", pid());
 
 	if(!c){
 		Log::debug("Broken pipe on send");
@@ -227,27 +224,21 @@ int TellStick::send( const std::string &strMessage ) {
 
 	if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){
 		//these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
-		Log::warning("Too old firmware, accepting this, just return success");
 		return TELLSTICK_SUCCESS;
 	}
 
 	if(d->ignoreControllerConfirmation){
 		//allow TellStick to finish its air-sending
-		Log::warning("Sleeping");
 		msleep(1000);
 		return TELLSTICK_SUCCESS;
 	}
 
-	Log::warning("Continuing");
-
 	int retrycnt = 250;
 	unsigned char in;
 	while(--retrycnt) {
 		ret = ftdi_read_data( &d->ftHandle, &in, 1);
 		if (ret > 0) {
-			Log::warning("%c", in);
 			if (in == '\n') {
-				Log::warning("Received an end");
 				return TELLSTICK_SUCCESS;
 			}
 		} else if(ret == 0) { // No data available
@@ -258,7 +249,6 @@ int TellStick::send( const std::string &strMessage ) {
 		}
 	}
 
-	Log::warning("Error in communication, retrycount ended");
 	return TELLSTICK_ERROR_COMMUNICATION;
 }
 
diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp
index a10f6da8..32202c0b 100644
--- a/telldus-core/service/TelldusMain.cpp
+++ b/telldus-core/service/TelldusMain.cpp
@@ -112,7 +112,6 @@ void TelldusMain::start(void) {
 			while(janitor->isSignaled()) {
 				janitor->popSignal();
 			}
-			Log::debug("Do Janitor cleanup");
 			controllerManager.queryControllerStatus();
 		}
 	}

From 01855cac968f05755723356ac8582602264fbffb Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Mon, 9 Jan 2012 16:43:15 +0100
Subject: [PATCH 1795/2215] Add qtcreator build directory and
 CMakeLists.txt.user file to .gitignore

---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.gitignore b/.gitignore
index 609fb881..2c86bf2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
 build/
+qtcreator-build/
 Doxyfile
 html/
 latex/
+CMakeLists.txt.user

From 5190c42f773010577f33be19f06db2b62d6ea9c4 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 11:20:15 +0100
Subject: [PATCH 1796/2215] Fixed indentation (space to tabs)

---
 telldus-core/tdtool/main.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp
index 5358f8d4..8304d443 100644
--- a/telldus-core/tdtool/main.cpp
+++ b/telldus-core/tdtool/main.cpp
@@ -138,15 +138,15 @@ int list_devices() {
 		time_t timestamp = 0;
 
 		if (dataTypes & TELLSTICK_TEMPERATURE) {
-		  tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp);
-		  strcat(tempvalue, "°");
-		  strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
+			tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp);
+			strcat(tempvalue, "°");
+			strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
 		}
 
 		if (dataTypes & TELLSTICK_HUMIDITY) {
-		  tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp);
-		  strcat(humidityvalue, "%");
-		  strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
+			tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp);
+			strcat(humidityvalue, "%");
+			strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
 		}
 		printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf);
 

From 46d70ad4515a3d73d7e2f1680a0ee348b65ee2fd Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 11:49:12 +0100
Subject: [PATCH 1797/2215] Return TELLSTICK_ERROR_COMMUNICATION_SERVICE if we
 timeout when communicating with the service instead of returning success.
 This closes #152

---
 telldus-core/client/Client.cpp       | 3 +++
 telldus-core/client/telldus-core.cpp | 5 +++++
 telldus-core/client/telldus-core.h   | 1 +
 3 files changed, 9 insertions(+)

diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp
index 291f45df..94845688 100644
--- a/telldus-core/client/Client.cpp
+++ b/telldus-core/client/Client.cpp
@@ -114,6 +114,9 @@ bool Client::getBoolFromService(const Message &msg) {
 
 int Client::getIntegerFromService(const Message &msg) {
 	std::wstring response = sendToService(msg);
+	if (response.compare(L"") == 0) {
+		return TELLSTICK_ERROR_COMMUNICATING_SERVICE;
+	}
 	return Message::takeInt(&response);
 }
 
diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp
index eccd6f0f..88fa6a8d 100644
--- a/telldus-core/client/telldus-core.cpp
+++ b/telldus-core/client/telldus-core.cpp
@@ -89,6 +89,9 @@ using namespace TelldusCore;
  * Error code. Input/command could not be parsed or didn't follow
  * input rules.
  *
+ * @def TELLSTICK_ERROR_COMMUNICATING_SERVICE
+ * Error code. Timeout waiting for response from the Telldus Service.
+ *
  * @def TELLSTICK_ERROR_UNKNOWN
  * Error code. An unkown error has occurred.
  */
@@ -491,6 +494,7 @@ int WINAPI tdMethods(int id, int methodsSupported){
  * @sa TELLSTICK_ERROR_UNKNOWN_RESPONSE
  * @sa TELLSTICK_ERROR_SYNTAX
  * @sa TELLSTICK_ERROR_BROKEN_PIPE
+ * @sa TELLSTICK_ERROR_COMMUNICATING_SERVICE
  * @sa TELLSTICK_ERROR_UNKNOWN
  */
 char * WINAPI tdGetErrorString(int intErrorNo) {
@@ -506,6 +510,7 @@ char * WINAPI tdGetErrorString(int intErrorNo) {
 		"Received an unknown response",
 		"Syntax error",
 		"Broken pipe"
+		"An error occured while communicating with the Telldus Service"
 	};
 	std::string strReturn;
 	intErrorNo = abs(intErrorNo); //We don't use negative values here.
diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h
index cfa22122..87eb6132 100644
--- a/telldus-core/client/telldus-core.h
+++ b/telldus-core/client/telldus-core.h
@@ -117,6 +117,7 @@ extern "C" {
 #define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7
 #define TELLSTICK_ERROR_SYNTAX -8
 #define TELLSTICK_ERROR_BROKEN_PIPE -9
+#define TELLSTICK_ERROR_COMMUNICATING_SERVICE -10
 #define TELLSTICK_ERROR_UNKNOWN -99
 
 //Device typedef

From 915d47dc1c4970c1a8c3abe077af197298a4777f Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Thu, 12 Jan 2012 14:59:29 +0100
Subject: [PATCH 1798/2215] Changed reset method for in ftd2xx for non-windows
 platforms.

---
 telldus-core/service/TellStick_ftd2xx.cpp | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp
index 0f55241d..05ac6c10 100644
--- a/telldus-core/service/TellStick_ftd2xx.cpp
+++ b/telldus-core/service/TellStick_ftd2xx.cpp
@@ -162,11 +162,15 @@ void TellStick::processData( const std::string &data ) {
 }
 
 int TellStick::reset(){
+#ifndef _WINDOWS
+	return TELLSTICK_SUCCESS; //nothing to be done on other platforms
+#else
 	int success = FT_CyclePort( d->ftHandle );
 	if(success == FT_OK){
-		return success;
+		return TELLSTICK_SUCCESS;
 	}
 	return TELLSTICK_ERROR_UNKNOWN;
+#endif
 }
 
 void TellStick::run() {

From d326331538b646bc02f6b87b9391500238901a94 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Thu, 12 Jan 2012 15:01:17 +0100
Subject: [PATCH 1799/2215] Returning correct error code on reset success

---
 telldus-core/service/TellStick_libftdi.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp
index fd3edc26..56b2a5a5 100644
--- a/telldus-core/service/TellStick_libftdi.cpp
+++ b/telldus-core/service/TellStick_libftdi.cpp
@@ -153,7 +153,7 @@ int TellStick::reset(){
 	if(success < 0){
 		return TELLSTICK_ERROR_UNKNOWN; //-1 = FTDI reset failed, -2 = USB device unavailable
 	}
-	return success;
+	return TELLSTICK_SUCCESS;
 }
 
 void TellStick::run() {

From df5e08ff9c47c199049f2337edc41480f90d3bff Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 17:30:23 +0100
Subject: [PATCH 1800/2215] Move SensorView to its own file

---
 telldus-gui/Plugins/Sensors/CMakeLists.txt |   1 +
 telldus-gui/Plugins/Sensors/SensorView.qml | 114 +++++++++++++++++++++
 telldus-gui/Plugins/Sensors/main.qml       | 111 +-------------------
 telldus-gui/Plugins/Sensors/qmldir         |   1 +
 4 files changed, 117 insertions(+), 110 deletions(-)
 create mode 100644 telldus-gui/Plugins/Sensors/SensorView.qml

diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt
index cf97f98c..bb3a4157 100644
--- a/telldus-gui/Plugins/Sensors/CMakeLists.txt
+++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt
@@ -33,6 +33,7 @@ SET( Plugin_EXTRA
 	row_bg.png
 	qmldir
 	SensorValue.qml
+	SensorView.qml
 )
 
 FIND_PACKAGE(TelldusCore REQUIRED)
diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml
new file mode 100644
index 00000000..108c58c4
--- /dev/null
+++ b/telldus-gui/Plugins/Sensors/SensorView.qml
@@ -0,0 +1,114 @@
+import Qt 4.7
+
+Component {
+	id: sensorView
+	Item{
+		id: sensorViewItem
+		visible: main.state == "EDIT" || modelData.showInList
+		height: childrenRect.height
+		width: parent.width
+
+		BorderImage {
+			source: "row_bg.png"
+			border.left: 5; border.top: 5
+			border.right: 5; border.bottom: 5
+			height: sensorInfo.height
+			width: parent.width
+
+			Text {
+				visible: main.state == "VIEW"
+				anchors.left: parent.left
+				anchors.leftMargin: 15
+				height: 40
+				verticalAlignment: Text.AlignVCenter
+				text: modelData.name;
+				color: "#004275"
+			}
+			Rectangle{
+				color: "white"
+				visible: main.state == "EDIT"
+				anchors.left: parent.left
+				anchors.leftMargin: 15
+				width: nameEdit.width + 4
+				height: 22
+				TextInput{
+					id: nameEdit
+					anchors.centerIn: parent
+					text: modelData.name;
+					color: "#004275"
+
+					onActiveFocusChanged: {
+						if(!activeFocus){
+							//todo other way?
+							modelData.setName(nameEdit.text);
+						}
+					}
+					onAccepted: {
+						modelData.setName(nameEdit.text);
+					}
+				}
+			}
+			Text{
+				anchors.right: model.left
+				visible: main.state == "EDIT"
+				height: 40
+				verticalAlignment: Text.AlignVCenter
+				text: modelData.id
+				color: "#004275"
+				width: 50
+			}
+			Text{
+				id: model
+				anchors.right: visibleinlistcheckbox.left
+				visible: main.state == "EDIT"
+				height: 40
+				verticalAlignment: Text.AlignVCenter
+				text: modelData.model
+				color: "#004275"
+				width: 100
+			}
+			Item{
+				id: visibleinlistcheckbox
+				anchors.right: sensorInfo.left
+				visible: main.state == "EDIT"
+				height: 40
+				Rectangle{
+					anchors.centerIn: parent
+					height: 10
+					width: 10
+					color: "white"
+					Text{
+						anchors.centerIn: parent
+						color: "#004275"
+						text: modelData.showInList ? "X" : ""
+					}
+					MouseArea{
+						anchors.fill: parent
+						onClicked: {
+							modelData.setShowInList(!modelData.showInList);
+						}
+					}
+				}
+				width: 100
+			}
+
+			Column {
+				id: sensorInfo
+				anchors.right: parent.right
+				width: 250
+				SensorValue {
+					visible: modelData.hasTemperature
+					text: visible ? modelData.sensorValue(1).value + '°C' : ''
+					icon: "icon_temp.png"
+					lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date()
+				}
+				SensorValue {
+					visible: modelData.hasHumidity
+					text: visible ? modelData.sensorValue(2).value + '%' : ''
+					icon: "icon_humidity.png"
+					lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date()
+				}
+			}
+		}
+	}
+}
diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml
index 5d240c29..c68d3f06 100644
--- a/telldus-gui/Plugins/Sensors/main.qml
+++ b/telldus-gui/Plugins/Sensors/main.qml
@@ -4,117 +4,8 @@ Item {
 	id: main
 	state: "VIEW"
 
-	Component {
+	SensorView {
 		id: sensorView
-		Item{
-			id: sensorViewItem
-			visible: main.state == "EDIT" || modelData.showInList
-			height: childrenRect.height
-			width: parent.width
-
-			BorderImage {
-				source: "row_bg.png"
-				border.left: 5; border.top: 5
-				border.right: 5; border.bottom: 5
-				height: sensorInfo.height
-				width: parent.width
-
-				Text {
-					visible: main.state == "VIEW"
-					anchors.left: parent.left
-					anchors.leftMargin: 15
-					height: 40
-					verticalAlignment: Text.AlignVCenter
-					text: modelData.name;
-					color: "#004275"
-				}
-				Rectangle{
-					color: "white"
-					visible: main.state == "EDIT"
-					anchors.left: parent.left
-					anchors.leftMargin: 15
-					width: nameEdit.width + 4
-					height: 22
-					TextInput{
-						id: nameEdit
-						anchors.centerIn: parent
-						text: modelData.name;
-						color: "#004275"
-
-						onActiveFocusChanged: {
-							if(!activeFocus){
-								//todo other way?
-								modelData.setName(nameEdit.text);
-							}
-						}
-						onAccepted: {
-							modelData.setName(nameEdit.text);
-						}
-					}
-				}
-				Text{
-					anchors.right: model.left
-					visible: main.state == "EDIT"
-					height: 40
-					verticalAlignment: Text.AlignVCenter
-					text: modelData.id
-					color: "#004275"
-					width: 50
-				}
-				Text{
-					id: model
-					anchors.right: visibleinlistcheckbox.left
-					visible: main.state == "EDIT"
-					height: 40
-					verticalAlignment: Text.AlignVCenter
-					text: modelData.model
-					color: "#004275"
-					width: 100
-				}
-				Item{
-					id: visibleinlistcheckbox
-					anchors.right: sensorInfo.left
-					visible: main.state == "EDIT"
-					height: 40
-					Rectangle{
-						anchors.centerIn: parent
-						height: 10
-						width: 10
-						color: "white"
-						Text{
-							anchors.centerIn: parent
-							color: "#004275"
-							text: modelData.showInList ? "X" : ""
-						}
-						MouseArea{
-							anchors.fill: parent
-							onClicked: {
-								modelData.setShowInList(!modelData.showInList);
-							}
-						}
-					}
-					width: 100
-				}
-
-				Column {
-					id: sensorInfo
-					anchors.right: parent.right
-					width: 250
-					SensorValue {
-						visible: modelData.hasTemperature
-						text: visible ? modelData.sensorValue(1).value + '°C' : ''
-						icon: "icon_temp.png"
-						lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date()
-					}
-					SensorValue {
-						visible: modelData.hasHumidity
-						text: visible ? modelData.sensorValue(2).value + '%' : ''
-						icon: "icon_humidity.png"
-						lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date()
-					}
-				}
-			}
-		}
 	}
 
 	Column {
diff --git a/telldus-gui/Plugins/Sensors/qmldir b/telldus-gui/Plugins/Sensors/qmldir
index 19c8cb6f..8c98fd76 100644
--- a/telldus-gui/Plugins/Sensors/qmldir
+++ b/telldus-gui/Plugins/Sensors/qmldir
@@ -1,2 +1,3 @@
 HeaderTitle 1.0 HeaderTitle.qml
 SensorValue 1.0 SensorValue.qml
+SensorView 1.0 SensorView.qml

From 332bf966f52568b7ac890e860f686d984c765309 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 17:32:41 +0100
Subject: [PATCH 1801/2215] Change plugin name to have capital first letter

---
 telldus-gui/Plugins/Sensors/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt
index bb3a4157..74e2750a 100644
--- a/telldus-gui/Plugins/Sensors/CMakeLists.txt
+++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt
@@ -3,7 +3,7 @@ SET(REQUIRE_PLUGIN_SETTINGS TRUE PARENT_SCOPE)
 
 SET(QT_USE_QTDECLARATIVE TRUE)
 
-SET( Plugin_NAME "sensors" )
+SET( Plugin_NAME "Sensors" )
 
 
 SET( Plugin_SRCS

From 3942702881a48f92e0417fe6a63a7d3b3c7e8237 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 17:33:08 +0100
Subject: [PATCH 1802/2215] Move SensorList to its own file

---
 telldus-gui/Plugins/Sensors/CMakeLists.txt |   1 +
 telldus-gui/Plugins/Sensors/SensorList.qml | 102 +++++++++++++++++++++
 telldus-gui/Plugins/Sensors/main.qml       |  99 +-------------------
 telldus-gui/Plugins/Sensors/qmldir         |   1 +
 4 files changed, 106 insertions(+), 97 deletions(-)
 create mode 100644 telldus-gui/Plugins/Sensors/SensorList.qml

diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt
index 74e2750a..45371412 100644
--- a/telldus-gui/Plugins/Sensors/CMakeLists.txt
+++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt
@@ -34,6 +34,7 @@ SET( Plugin_EXTRA
 	qmldir
 	SensorValue.qml
 	SensorView.qml
+	SensorList.qml
 )
 
 FIND_PACKAGE(TelldusCore REQUIRED)
diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml
new file mode 100644
index 00000000..a43a0b93
--- /dev/null
+++ b/telldus-gui/Plugins/Sensors/SensorList.qml
@@ -0,0 +1,102 @@
+import Qt 4.7
+
+Column {
+	id: sensorList
+	spacing: 1
+
+	SensorView {
+		id: sensorView
+	}
+
+	BorderImage {
+		id: header
+		source: "header_bg.png"
+		width: parent.width; height: 40
+		border.left: 5; border.top: 5
+		border.right: 5; border.bottom: 5
+
+		HeaderTitle {
+			text: "Name"
+			anchors.left: parent.left
+			anchors.leftMargin: 15
+		}
+		HeaderTitle {
+			text: "ID"
+			anchors.right: modelTitle.left
+			visible: main.state == "EDIT"
+			width: 50
+		}
+		HeaderTitle {
+			id: modelTitle
+			text: "Model"
+			anchors.right: visibleinlistTitle.left
+			visible: main.state == "EDIT"
+			width: 100
+		}
+		HeaderTitle {
+			id: visibleinlistTitle
+			text: "Visible in list"
+			anchors.right: sensorinformationTitle.left
+			visible: main.state == "EDIT"
+			width: 100
+		}
+		HeaderTitle {
+			id: sensorinformationTitle
+			text: "Sensor information"
+			width: 150
+			anchors.right: timestampTitle.left
+		}
+		HeaderTitle {
+			id: timestampTitle
+			text: "Last updated"
+			width: 100
+			anchors.right: parent.right
+			//horizontalAlignment: Text.AlignRight
+		}
+	}
+	Repeater {
+		model: sensorModel
+		delegate: sensorView
+	}
+	Row{
+		spacing: 20
+		Rectangle {
+			width: 50
+			height: 20
+			Text{
+				anchors.centerIn: parent
+				text: main.state == "VIEW" ? "Edit" : "View"
+			}
+			MouseArea{
+				anchors.fill: parent
+				onClicked: {
+					if(main.state == "VIEW"){
+						main.state = "EDIT"
+					}
+					else{
+						main.state  ="VIEW"
+					}
+				}
+			}
+		}
+		/*
+			Rectangle {
+				//TODO should this button exist at all, or always save?
+				width: 50
+				height: 20
+				visible: main.state == "EDIT"
+				Text{
+					anchors.centerIn: parent
+					text: "Cancel"
+				}
+				MouseArea{
+					anchors.fill: parent
+					onClicked: {
+						main.state  ="VIEW"
+					}
+				}
+			}
+			*/
+	}
+	anchors.fill: parent
+}
diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml
index c68d3f06..523480d6 100644
--- a/telldus-gui/Plugins/Sensors/main.qml
+++ b/telldus-gui/Plugins/Sensors/main.qml
@@ -4,102 +4,7 @@ Item {
 	id: main
 	state: "VIEW"
 
-	SensorView {
-		id: sensorView
-	}
-
-	Column {
-		spacing: 1
-		BorderImage {
-			id: header
-			source: "header_bg.png"
-			width: parent.width; height: 40
-			border.left: 5; border.top: 5
-			border.right: 5; border.bottom: 5
-
-			HeaderTitle {
-				text: "Name"
-				anchors.left: parent.left
-				anchors.leftMargin: 15
-			}
-			HeaderTitle {
-				text: "ID"
-				anchors.right: modelTitle.left
-				visible: main.state == "EDIT"
-				width: 50
-			}
-			HeaderTitle {
-				id: modelTitle
-				text: "Model"
-				anchors.right: visibleinlistTitle.left
-				visible: main.state == "EDIT"
-				width: 100
-			}
-			HeaderTitle {
-				id: visibleinlistTitle
-				text: "Visible in list"
-				anchors.right: sensorinformationTitle.left
-				visible: main.state == "EDIT"
-				width: 100
-			}
-			HeaderTitle {
-				id: sensorinformationTitle
-				text: "Sensor information"
-				width: 150
-				anchors.right: timestampTitle.left
-			}
-			HeaderTitle {
-				id: timestampTitle
-				text: "Last updated"
-				width: 100
-				anchors.right: parent.right
-				//horizontalAlignment: Text.AlignRight
-			}
-		}
-		Repeater {
-			model: sensorModel
-			delegate: sensorView
-		}
-		Row{
-			spacing: 20
-			Rectangle {
-				width: 50
-				height: 20
-				Text{
-					anchors.centerIn: parent
-					text: main.state == "VIEW" ? "Edit" : "View"
-				}
-				MouseArea{
-					anchors.fill: parent
-					onClicked: {
-						if(main.state == "VIEW"){
-							main.state = "EDIT"
-						}
-						else{
-							main.state  ="VIEW"
-						}
-					}
-				}
-			}
-			/*
-			Rectangle {
-				//TODO should this button exist at all, or always save?
-				width: 50
-				height: 20
-				visible: main.state == "EDIT"
-				Text{
-					anchors.centerIn: parent
-					text: "Cancel"
-				}
-				MouseArea{
-					anchors.fill: parent
-					onClicked: {
-						main.state  ="VIEW"
-					}
-				}
-			}
-			*/
-		}
-		anchors.fill: parent
+	SensorList {
+		id: sensorList
 	}
 }
diff --git a/telldus-gui/Plugins/Sensors/qmldir b/telldus-gui/Plugins/Sensors/qmldir
index 8c98fd76..050f9f5b 100644
--- a/telldus-gui/Plugins/Sensors/qmldir
+++ b/telldus-gui/Plugins/Sensors/qmldir
@@ -1,3 +1,4 @@
 HeaderTitle 1.0 HeaderTitle.qml
 SensorValue 1.0 SensorValue.qml
 SensorView 1.0 SensorView.qml
+SensorList 1.0 SensorList.qml

From 1dfacddf1af00dee7813b006dcb4ed554de2b5ac Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Thu, 12 Jan 2012 17:39:11 +0100
Subject: [PATCH 1803/2215] Make the list flickable

---
 telldus-gui/Plugins/Sensors/SensorList.qml |  1 -
 telldus-gui/Plugins/Sensors/main.qml       | 11 +++++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml
index a43a0b93..b6be1003 100644
--- a/telldus-gui/Plugins/Sensors/SensorList.qml
+++ b/telldus-gui/Plugins/Sensors/SensorList.qml
@@ -98,5 +98,4 @@ Column {
 			}
 			*/
 	}
-	anchors.fill: parent
 }
diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml
index 523480d6..599a1ae1 100644
--- a/telldus-gui/Plugins/Sensors/main.qml
+++ b/telldus-gui/Plugins/Sensors/main.qml
@@ -4,7 +4,14 @@ Item {
 	id: main
 	state: "VIEW"
 
-	SensorList {
-		id: sensorList
+	Flickable {
+		anchors.fill: parent
+
+		contentHeight: sensorList.height
+
+		SensorList {
+			width: parent.width
+			id: sensorList
+		}
 	}
 }

From 5db7658a477ef4b3615d7ea90d325404121b7d17 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 12:05:22 +0100
Subject: [PATCH 1804/2215] Add Qt Components for desktop as submodule

---
 .gitmodules                                | 3 +++
 telldus-gui/3rdparty/qt-components-desktop | 1 +
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 telldus-gui/3rdparty/qt-components-desktop

diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..1512eb7b
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "telldus-gui/3rdparty/qt-components-desktop"]
+	path = telldus-gui/3rdparty/qt-components-desktop
+	url = git://gitorious.org/qt-components/desktop.git
diff --git a/telldus-gui/3rdparty/qt-components-desktop b/telldus-gui/3rdparty/qt-components-desktop
new file mode 160000
index 00000000..563fdbc4
--- /dev/null
+++ b/telldus-gui/3rdparty/qt-components-desktop
@@ -0,0 +1 @@
+Subproject commit 563fdbc4d7805c9d9c1d2abde1d52b39e58b4329

From ab436a212fb4158c66b118c557ab4b4f8275033d Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 14:34:53 +0100
Subject: [PATCH 1805/2215] Add cmake build file for QtComponents

---
 .../3rdparty/qt-components-desktop.cmake      | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 telldus-gui/3rdparty/qt-components-desktop.cmake

diff --git a/telldus-gui/3rdparty/qt-components-desktop.cmake b/telldus-gui/3rdparty/qt-components-desktop.cmake
new file mode 100644
index 00000000..7af264c7
--- /dev/null
+++ b/telldus-gui/3rdparty/qt-components-desktop.cmake
@@ -0,0 +1,42 @@
+FIND_PACKAGE( Qt4 REQUIRED )
+
+SET(BASE_PATH "${CMAKE_SOURCE_DIR}/3rdparty/qt-components-desktop")
+FILE(GLOB SRCS ${BASE_PATH}/src/*.cpp)
+FILE(GLOB HDRS ${BASE_PATH}/src/*.h)
+
+FILE(GLOB_RECURSE QML ${BASE_PATH}/components/*.qml)
+FILE(GLOB_RECURSE JS ${BASE_PATH}/components/*.js)
+FILE(GLOB_RECURSE PNG ${BASE_PATH}/components/*.png)
+FILE(GLOB_RECURSE QMLDIR ${BASE_PATH}/components/qmldir)
+SET(EXTRA_FILES ${QML} ${JS} ${PNG} ${QMLDIR})
+
+QT4_WRAP_CPP( MOC_SRCS  ${HDRS} )
+QT4_AUTOMOC ( ${SRCS} )
+
+ADD_LIBRARY(styleplugin SHARED
+	${SRCS}
+	${MOC_SRCS}
+	${QMLS}
+)
+TARGET_LINK_LIBRARIES( styleplugin ${QT_LIBRARIES} )
+
+
+IF (QT_COMPONENTS_OUTPUT_DIR)
+	SET(QT_COMPONENTS_OUTPUT_DIR "${QT_COMPONENTS_OUTPUT_DIR}/QtDesktop")
+ELSE()
+	SET(QT_COMPONENTS_OUTPUT_DIR "QtDesktop")
+ENDIF()
+
+SET_TARGET_PROPERTIES(styleplugin PROPERTIES
+	LIBRARY_OUTPUT_DIRECTORY ${QT_COMPONENTS_OUTPUT_DIR}/plugin
+)
+
+STRING(LENGTH "${BASE_PATH}/components" BASE_LENGTH)
+FOREACH(_FILE ${EXTRA_FILES})
+	STRING(SUBSTRING ${_FILE} ${BASE_LENGTH} -1 _OUT_FILE)
+	GET_FILENAME_COMPONENT(_FILENAME ${_FILE} NAME)
+	ADD_CUSTOM_COMMAND( TARGET ${Plugin_NAME}
+		POST_BUILD
+		COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${QT_COMPONENTS_OUTPUT_DIR}${_OUT_FILE}
+	)
+ENDFOREACH(_FILE)

From 5531d6b3132be7754e7354244a669ac03a22719f Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 14:36:38 +0100
Subject: [PATCH 1806/2215] Add QtComponents to the QML plugin

---
 telldus-gui/Plugins/QML/CMakeLists.txt |  3 +++
 telldus-gui/Plugins/QML/qmlview.cpp    | 18 ++++++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt
index 5d0830d8..e2fe6a94 100644
--- a/telldus-gui/Plugins/QML/CMakeLists.txt
+++ b/telldus-gui/Plugins/QML/CMakeLists.txt
@@ -23,3 +23,6 @@ SET( Plugin_MOC_HDRS
 SET( Plugin_PATH "com.telldus.qml" )
 
 INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE )
+
+SET(QT_COMPONENTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/declarative")
+INCLUDE( ${CMAKE_SOURCE_DIR}/3rdparty/qt-components-desktop.cmake NO_POLICY_SCOPE )
diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp
index dea06628..6d12cc0f 100644
--- a/telldus-gui/Plugins/QML/qmlview.cpp
+++ b/telldus-gui/Plugins/QML/qmlview.cpp
@@ -2,7 +2,9 @@
 #include "scriptfunctionwrapper.h"
 #include 
 #include 
+#include 
 #include 
+#include 
 
 class QMLView::PrivateData {
 public:
@@ -16,6 +18,22 @@ QMLView::QMLView(const QDir &dir, const QScriptValue &object) :
 	setAttribute(Qt::WA_TranslucentBackground);
 	setStyleSheet("background:transparent;");
 
+	QDeclarativeEngine *eng = this->engine();
+	QStringList paths(eng->importPathList());
+	QDir pluginsDir = QDir(qApp->applicationDirPath());
+
+#if defined(Q_OS_MAC)
+	if (pluginsDir.dirName() == "MacOS") {
+		pluginsDir.cdUp();
+	}
+#endif
+
+	if (pluginsDir.cd("Plugins/declarative")) {
+		paths << pluginsDir.absolutePath();
+	}
+
+	eng->setImportPathList(paths);
+
 	d = new PrivateData;
 	d->baseDir = dir;
 	d->object = object;

From aadc4554fc97f0caac4d591e1b9f8197e02d94f0 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 14:37:07 +0100
Subject: [PATCH 1807/2215] Convert the edit button to a qt-component button

---
 telldus-gui/Plugins/Sensors/SensorList.qml | 23 +++++++++-------------
 1 file changed, 9 insertions(+), 14 deletions(-)

diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml
index b6be1003..a26cdd4d 100644
--- a/telldus-gui/Plugins/Sensors/SensorList.qml
+++ b/telldus-gui/Plugins/Sensors/SensorList.qml
@@ -1,4 +1,5 @@
 import Qt 4.7
+import QtDesktop 0.1
 
 Column {
 	id: sensorList
@@ -60,22 +61,16 @@ Column {
 	}
 	Row{
 		spacing: 20
-		Rectangle {
+		Button {
 			width: 50
 			height: 20
-			Text{
-				anchors.centerIn: parent
-				text: main.state == "VIEW" ? "Edit" : "View"
-			}
-			MouseArea{
-				anchors.fill: parent
-				onClicked: {
-					if(main.state == "VIEW"){
-						main.state = "EDIT"
-					}
-					else{
-						main.state  ="VIEW"
-					}
+			text: main.state == "VIEW" ? "Edit" : "View"
+			onClicked: {
+				if(main.state == "VIEW"){
+					main.state = "EDIT"
+				}
+				else{
+					main.state  ="VIEW"
 				}
 			}
 		}

From cc0b37e179d94a87d627d031dd4d857bfeeee297 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Fri, 13 Jan 2012 15:05:22 +0100
Subject: [PATCH 1808/2215] Fix for building if cmake doesn't understand -1
 length in STRING(SUBSTRING)

---
 telldus-gui/3rdparty/qt-components-desktop.cmake | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/telldus-gui/3rdparty/qt-components-desktop.cmake b/telldus-gui/3rdparty/qt-components-desktop.cmake
index 7af264c7..3a1d5bd2 100644
--- a/telldus-gui/3rdparty/qt-components-desktop.cmake
+++ b/telldus-gui/3rdparty/qt-components-desktop.cmake
@@ -33,10 +33,13 @@ SET_TARGET_PROPERTIES(styleplugin PROPERTIES
 
 STRING(LENGTH "${BASE_PATH}/components" BASE_LENGTH)
 FOREACH(_FILE ${EXTRA_FILES})
-	STRING(SUBSTRING ${_FILE} ${BASE_LENGTH} -1 _OUT_FILE)
+	STRING(LENGTH ${_FILE} _FILE_LENGTH)
+	MATH(EXPR _TOP_LENGTH "${_FILE_LENGTH}-${BASE_LENGTH}")
+	STRING(SUBSTRING ${_FILE} ${BASE_LENGTH} ${_TOP_LENGTH} _OUT_FILE)
 	GET_FILENAME_COMPONENT(_FILENAME ${_FILE} NAME)
-	ADD_CUSTOM_COMMAND( TARGET ${Plugin_NAME}
+	ADD_CUSTOM_COMMAND( TARGET styleplugin
 		POST_BUILD
 		COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${QT_COMPONENTS_OUTPUT_DIR}${_OUT_FILE}
+		COMMENT "Copy ${_FILENAME} to destination"
 	)
 ENDFOREACH(_FILE)

From 69b16f0bafc540369d457341523f49302540f21a Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 15:29:55 +0100
Subject: [PATCH 1809/2215] Plugin extra files should be a custom command and
 not built after linking. This fixes the issue that the plugin needed to be
 relinked for new files to be copied to destination

---
 telldus-gui/Plugins/TelldusCenterPlugin.cmake | 45 +++++++++----------
 telldus-gui/Plugins/telldus/__init__.js       |  2 +-
 2 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake
index 20ab8c6a..daae9f1a 100644
--- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake
+++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake
@@ -63,6 +63,21 @@ ELSE (UPDATE_TRANSLATIONS)
 	LIST(APPEND Plugin_FILES ${Plugin_QM})
 ENDIF (UPDATE_TRANSLATIONS)
 
+IF(Plugin_PATH)
+	FOREACH(_FILE ${Plugin_FILES})
+		GET_FILENAME_COMPONENT(_FILENAME ${_FILE} NAME)
+		ADD_CUSTOM_COMMAND( OUTPUT ${Plugin_PATH}/${_FILENAME}
+			COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${Plugin_PATH}/${_FILENAME}
+			DEPENDS ${_FILE}
+			COMMENT "Copy ${_FILENAME} for plugin ${Plugin_NAME}"
+		)
+		LIST(APPEND Plugin_TARGET_FILES "${Plugin_PATH}/${_FILENAME}")
+		IF (NOT APPLE)
+			INSTALL(FILES ${_FILE} DESTINATION "${PLUGIN_LIB_FULL_PATH}/script/${Plugin_PATH_relative}")
+		ENDIF ()
+	ENDFOREACH(_FILE)
+ENDIF(Plugin_PATH)
+
 IF(Plugin_SRCS)
 	ADD_LIBRARY(${Plugin_NAME} SHARED
 		${Plugin_SRCS}
@@ -74,6 +89,7 @@ IF(Plugin_SRCS)
 		${Plugin_FILES}
 		${Plugin_TS}
 		${Plugin_QM}
+		${Plugin_TARGET_FILES}
 	)
 	TARGET_LINK_LIBRARIES( ${Plugin_NAME}	${Plugin_LIBRARIES} )
 
@@ -87,13 +103,13 @@ IF(Plugin_SRCS)
 			SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\")
 			GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid)
 			SET(plugin \"\${bundle}/Contents/Plugins/script/${Plugin_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}\")
-			
+
 			GET_ITEM_KEY(\"\${plugin}\" pkey)
 			SET(prereqs \"\")
 			GET_PREREQUISITES(\${plugin} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\")
 			FOREACH(pr \${prereqs})
 				GET_ITEM_KEY(\"\${pr}\" rkey)
-				
+
 				#Don't change the path to TelldusCore
 				IF (NOT \"\${rkey}\" STREQUAL \"TelldusCore\")
 					#Check to see if this is ourself
@@ -117,33 +133,12 @@ IF(Plugin_SRCS)
 			LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script
 		)
 		INSTALL(TARGETS ${Plugin_NAME}
-			LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script" 
+			LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script"
 		)
 	ENDIF (APPLE)
 	SIGN(${Plugin_NAME})
 ELSE(Plugin_SRCS)
 	ADD_CUSTOM_TARGET(${Plugin_NAME} ALL
-		SOURCES ${Plugin_FILES}
+		SOURCES ${Plugin_FILES} ${Plugin_TARGET_FILES}
 	)
 ENDIF(Plugin_SRCS)
-
-IF(Plugin_PATH)
-	ADD_CUSTOM_COMMAND( TARGET ${Plugin_NAME}
-		POST_BUILD
-		COMMAND ${CMAKE_COMMAND} -E make_directory ${Plugin_PATH}
-		COMMENT "Creating plugin directory ${Plugin_NAME}"
-	)
-	FOREACH(_FILE ${Plugin_FILES})
-		GET_FILENAME_COMPONENT(_FILENAME ${_FILE} NAME)
-		ADD_CUSTOM_COMMAND( TARGET ${Plugin_NAME}
-			POST_BUILD
-			COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${Plugin_PATH}
-			COMMENT "Copy ${_FILENAME} for plugin ${Plugin_NAME}"
-		)
-		IF (NOT APPLE)
-			INSTALL(FILES ${_FILE} DESTINATION "${PLUGIN_LIB_FULL_PATH}/script/${Plugin_PATH_relative}")
-		ENDIF ()
-	ENDFOREACH(_FILE)
-ENDIF(Plugin_PATH)
-
-
diff --git a/telldus-gui/Plugins/telldus/__init__.js b/telldus-gui/Plugins/telldus/__init__.js
index 64493195..a9c88dfb 100644
--- a/telldus-gui/Plugins/telldus/__init__.js
+++ b/telldus-gui/Plugins/telldus/__init__.js
@@ -1 +1 @@
-__setupPackage__( __extension__ );
\ No newline at end of file
+__setupPackage__( __extension__ );

From c90a4c1f1228464d23cf043d910d9c128d5e717f Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 15:50:21 +0100
Subject: [PATCH 1810/2215] Change the flickable area to a ScrollArea. Better
 for the desktop

---
 telldus-gui/Plugins/Sensors/main.qml | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml
index 599a1ae1..41ecb0ac 100644
--- a/telldus-gui/Plugins/Sensors/main.qml
+++ b/telldus-gui/Plugins/Sensors/main.qml
@@ -1,17 +1,21 @@
 import Qt 4.7
+import QtDesktop 0.1
 
 Item {
 	id: main
 	state: "VIEW"
 
-	Flickable {
+	ScrollArea {
+		id: scrollArea
 		anchors.fill: parent
+		frame: false
 
 		contentHeight: sensorList.height
+		contentWidth: sensorList.width
 
 		SensorList {
-			width: parent.width
 			id: sensorList
+			width: main.width-scrollArea.verticalScrollBar.width
 		}
 	}
 }

From 64e2b354af0c1166afff3ea763e1c12b6b1be779 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 16:12:13 +0100
Subject: [PATCH 1811/2215] Convert our checkbox to a qt-component checkbox

---
 telldus-gui/Plugins/Sensors/SensorList.qml |  1 +
 telldus-gui/Plugins/Sensors/SensorView.qml | 31 ++++++++--------------
 2 files changed, 12 insertions(+), 20 deletions(-)

diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml
index a26cdd4d..bd6f03c7 100644
--- a/telldus-gui/Plugins/Sensors/SensorList.qml
+++ b/telldus-gui/Plugins/Sensors/SensorList.qml
@@ -38,6 +38,7 @@ Column {
 			id: visibleinlistTitle
 			text: "Visible in list"
 			anchors.right: sensorinformationTitle.left
+			horizontalAlignment: Text.AlignHCenter
 			visible: main.state == "EDIT"
 			width: 100
 		}
diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml
index 108c58c4..752cbc0f 100644
--- a/telldus-gui/Plugins/Sensors/SensorView.qml
+++ b/telldus-gui/Plugins/Sensors/SensorView.qml
@@ -1,4 +1,5 @@
 import Qt 4.7
+import QtDesktop 0.1
 
 Component {
 	id: sensorView
@@ -67,29 +68,19 @@ Component {
 				color: "#004275"
 				width: 100
 			}
-			Item{
+			Item  {
 				id: visibleinlistcheckbox
-				anchors.right: sensorInfo.left
-				visible: main.state == "EDIT"
 				height: 40
-				Rectangle{
-					anchors.centerIn: parent
-					height: 10
-					width: 10
-					color: "white"
-					Text{
-						anchors.centerIn: parent
-						color: "#004275"
-						text: modelData.showInList ? "X" : ""
-					}
-					MouseArea{
-						anchors.fill: parent
-						onClicked: {
-							modelData.setShowInList(!modelData.showInList);
-						}
-					}
-				}
 				width: 100
+				anchors.right: sensorInfo.left
+				CheckBox {
+					id: checkBox
+					anchors.centerIn: parent
+					width: checkBox.height
+					visible: main.state == "EDIT"
+					checked: modelData.showInList
+					onClicked: modelData.setShowInList(!modelData.showInList)
+				}
 			}
 
 			Column {

From 99c2b0e158d7a587a0b2cba693c0c15a54818171 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 16:47:20 +0100
Subject: [PATCH 1812/2215] Convert the textbox to qt-components as well

---
 telldus-gui/Plugins/Sensors/SensorView.qml | 35 +++++++++-------------
 telldus-gui/Plugins/Sensors/sensor.cpp     |  4 ---
 2 files changed, 14 insertions(+), 25 deletions(-)

diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml
index 752cbc0f..c0492840 100644
--- a/telldus-gui/Plugins/Sensors/SensorView.qml
+++ b/telldus-gui/Plugins/Sensors/SensorView.qml
@@ -9,6 +9,13 @@ Component {
 		height: childrenRect.height
 		width: parent.width
 
+		property string state: main.state
+		onStateChanged: {
+			if (state != "EDIT") {
+				modelData.setName(nameEdit.text)
+			}
+		}
+
 		BorderImage {
 			source: "row_bg.png"
 			border.left: 5; border.top: 5
@@ -22,32 +29,18 @@ Component {
 				anchors.leftMargin: 15
 				height: 40
 				verticalAlignment: Text.AlignVCenter
-				text: modelData.name;
+				text: modelData.name == '' ? '' : modelData.name;
 				color: "#004275"
 			}
-			Rectangle{
-				color: "white"
+			TextField {
+				id: nameEdit
 				visible: main.state == "EDIT"
 				anchors.left: parent.left
 				anchors.leftMargin: 15
-				width: nameEdit.width + 4
-				height: 22
-				TextInput{
-					id: nameEdit
-					anchors.centerIn: parent
-					text: modelData.name;
-					color: "#004275"
-
-					onActiveFocusChanged: {
-						if(!activeFocus){
-							//todo other way?
-							modelData.setName(nameEdit.text);
-						}
-					}
-					onAccepted: {
-						modelData.setName(nameEdit.text);
-					}
-				}
+				anchors.top: parent.top
+				anchors.topMargin: (40-nameEdit.height)/2
+				text: modelData.name;
+				placeholderText: 'Enter a name'
 			}
 			Text{
 				anchors.right: model.left
diff --git a/telldus-gui/Plugins/Sensors/sensor.cpp b/telldus-gui/Plugins/Sensors/sensor.cpp
index 7a56f46f..d800032a 100644
--- a/telldus-gui/Plugins/Sensors/sensor.cpp
+++ b/telldus-gui/Plugins/Sensors/sensor.cpp
@@ -46,10 +46,6 @@ void Sensor::setModel(const QString &model) {
 }
 
 QString Sensor::name() const {
-	//return QString("%1 %2").arg(this->protocol()).arg(this->id()); //TODO: Remove when name is fully implemented
-	if(d->name == ""){
-		return "";
-	}
 	return d->name;
 }
 

From 1e650c7142f7844537be880bdfa4b4229880b6ad Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Fri, 13 Jan 2012 18:22:31 +0100
Subject: [PATCH 1813/2215] Fix compiling issues for qt-components-desktop on
 Windows

---
 .../3rdparty/qt-components-desktop.cmake      | 45 +++++++++++--------
 telldus-gui/Plugins/QML/CMakeLists.txt        |  6 ++-
 2 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/telldus-gui/3rdparty/qt-components-desktop.cmake b/telldus-gui/3rdparty/qt-components-desktop.cmake
index 3a1d5bd2..5018f34f 100644
--- a/telldus-gui/3rdparty/qt-components-desktop.cmake
+++ b/telldus-gui/3rdparty/qt-components-desktop.cmake
@@ -10,36 +10,45 @@ FILE(GLOB_RECURSE PNG ${BASE_PATH}/components/*.png)
 FILE(GLOB_RECURSE QMLDIR ${BASE_PATH}/components/qmldir)
 SET(EXTRA_FILES ${QML} ${JS} ${PNG} ${QMLDIR})
 
-QT4_WRAP_CPP( MOC_SRCS  ${HDRS} )
-QT4_AUTOMOC ( ${SRCS} )
-
-ADD_LIBRARY(styleplugin SHARED
-	${SRCS}
-	${MOC_SRCS}
-	${QMLS}
-)
-TARGET_LINK_LIBRARIES( styleplugin ${QT_LIBRARIES} )
-
-
 IF (QT_COMPONENTS_OUTPUT_DIR)
 	SET(QT_COMPONENTS_OUTPUT_DIR "${QT_COMPONENTS_OUTPUT_DIR}/QtDesktop")
 ELSE()
 	SET(QT_COMPONENTS_OUTPUT_DIR "QtDesktop")
 ENDIF()
 
-SET_TARGET_PROPERTIES(styleplugin PROPERTIES
-	LIBRARY_OUTPUT_DIRECTORY ${QT_COMPONENTS_OUTPUT_DIR}/plugin
-)
-
 STRING(LENGTH "${BASE_PATH}/components" BASE_LENGTH)
 FOREACH(_FILE ${EXTRA_FILES})
 	STRING(LENGTH ${_FILE} _FILE_LENGTH)
 	MATH(EXPR _TOP_LENGTH "${_FILE_LENGTH}-${BASE_LENGTH}")
 	STRING(SUBSTRING ${_FILE} ${BASE_LENGTH} ${_TOP_LENGTH} _OUT_FILE)
 	GET_FILENAME_COMPONENT(_FILENAME ${_FILE} NAME)
-	ADD_CUSTOM_COMMAND( TARGET styleplugin
-		POST_BUILD
-		COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${QT_COMPONENTS_OUTPUT_DIR}${_OUT_FILE}
+	SET(_OUTFILEPATH ${QT_COMPONENTS_OUTPUT_DIR}${_OUT_FILE})
+	LIST(APPEND SRCS ${_OUTFILEPATH})
+	ADD_CUSTOM_COMMAND(
+		OUTPUT ${_OUTFILEPATH}
+		DEPENDS ${_FILE}
+		COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${_OUTFILEPATH}
 		COMMENT "Copy ${_FILENAME} to destination"
 	)
 ENDFOREACH(_FILE)
+
+QT4_WRAP_CPP( MOC_SRCS  ${HDRS} )
+QT4_AUTOMOC ( ${SRCS} )
+
+ADD_LIBRARY(styleplugin SHARED
+	${SRCS}
+	${MOC_SRCS}
+)
+TARGET_LINK_LIBRARIES( styleplugin ${QT_LIBRARIES} )
+
+
+
+IF (WIN32)
+	SET_TARGET_PROPERTIES(styleplugin PROPERTIES
+		PREFIX "Plugins/declarative/QtDesktop/plugin/"
+	)
+ELSE()
+	SET_TARGET_PROPERTIES(styleplugin PROPERTIES
+		LIBRARY_OUTPUT_DIRECTORY ${QT_COMPONENTS_OUTPUT_DIR}/plugin
+	)
+ENDIF()
diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt
index e2fe6a94..719ec69e 100644
--- a/telldus-gui/Plugins/QML/CMakeLists.txt
+++ b/telldus-gui/Plugins/QML/CMakeLists.txt
@@ -24,5 +24,9 @@ SET( Plugin_PATH "com.telldus.qml" )
 
 INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE )
 
-SET(QT_COMPONENTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/declarative")
+IF (WIN32)
+	SET(QT_COMPONENTS_OUTPUT_DIR "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/Plugins/declarative")
+ELSE()
+	SET(QT_COMPONENTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/declarative")
+ENDIF()
 INCLUDE( ${CMAKE_SOURCE_DIR}/3rdparty/qt-components-desktop.cmake NO_POLICY_SCOPE )

From 9afb2cbbacbc788de8372e6c0a2dd60585f0e947 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Mon, 16 Jan 2012 16:53:29 +0100
Subject: [PATCH 1814/2215] Fix for building qt-components on Mac OS X. Master
 branch.

---
 telldus-gui/3rdparty/qt-components-desktop.cmake | 11 ++++++++---
 telldus-gui/Plugins/QML/CMakeLists.txt           |  2 ++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/telldus-gui/3rdparty/qt-components-desktop.cmake b/telldus-gui/3rdparty/qt-components-desktop.cmake
index 5018f34f..ff7deaba 100644
--- a/telldus-gui/3rdparty/qt-components-desktop.cmake
+++ b/telldus-gui/3rdparty/qt-components-desktop.cmake
@@ -35,13 +35,18 @@ ENDFOREACH(_FILE)
 QT4_WRAP_CPP( MOC_SRCS  ${HDRS} )
 QT4_AUTOMOC ( ${SRCS} )
 
+SET(LIBRARIES ${QT_LIBRARIES})
+
+IF (APPLE)
+	FIND_LIBRARY(CARBON_LIBRARY Carbon)
+	LIST(APPEND LIBRARIES ${CARBON_LIBRARY})
+ENDIF ()
+
 ADD_LIBRARY(styleplugin SHARED
 	${SRCS}
 	${MOC_SRCS}
 )
-TARGET_LINK_LIBRARIES( styleplugin ${QT_LIBRARIES} )
-
-
+TARGET_LINK_LIBRARIES( styleplugin ${LIBRARIES} )
 
 IF (WIN32)
 	SET_TARGET_PROPERTIES(styleplugin PROPERTIES
diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt
index 719ec69e..d008a815 100644
--- a/telldus-gui/Plugins/QML/CMakeLists.txt
+++ b/telldus-gui/Plugins/QML/CMakeLists.txt
@@ -26,6 +26,8 @@ INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE )
 
 IF (WIN32)
 	SET(QT_COMPONENTS_OUTPUT_DIR "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/Plugins/declarative")
+ELSEIF (APPLE)
+	SET(QT_COMPONENTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/declarative")
 ELSE()
 	SET(QT_COMPONENTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/declarative")
 ENDIF()

From 48daf2ca2fee9ebc88f54e65d82616c5d2d5bccc Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Tue, 17 Jan 2012 12:20:05 +0100
Subject: [PATCH 1815/2215] Bump version to 2.1.1_beta1

---
 telldus-core/CMakeLists.txt | 4 ++--
 telldus-gui/CMakeLists.txt  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt
index 4165ec69..a7836523 100644
--- a/telldus-core/CMakeLists.txt
+++ b/telldus-core/CMakeLists.txt
@@ -11,9 +11,9 @@ ENDIF(NOT FORCE_COMPILE_FROM_TRUNK)
 
 SET(PACKAGE_MAJOR_VERSION 2)
 SET(PACKAGE_MINOR_VERSION 1)
-SET(PACKAGE_PATCH_VERSION 0)
+SET(PACKAGE_PATCH_VERSION 1)
 SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}")
-SET(PACKAGE_SUBVERSION)
+SET(PACKAGE_SUBVERSION "beta1")
 SET(PACKAGE_SOVERSION 2)
 
 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt
index 6de4f891..63bafafc 100644
--- a/telldus-gui/CMakeLists.txt
+++ b/telldus-gui/CMakeLists.txt
@@ -8,10 +8,10 @@ endif(COMMAND cmake_policy)
 
 SET(PACKAGE_MAJOR_VERSION 2)
 SET(PACKAGE_MINOR_VERSION 1)
-SET(PACKAGE_PATCH_VERSION 0)
+SET(PACKAGE_PATCH_VERSION 1)
 SET(PACKAGE_SOVERSION 2)
 SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}")
-SET(DISPLAYED_VERSION ${PACKAGE_VERSION})
+SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta1")
 
 SET(BRANDING "telldus" CACHE STRING "The brand to use")
 

From a182ba2111f3fa020edcce1f5e9192dd0ce25c56 Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Tue, 17 Jan 2012 13:16:10 +0100
Subject: [PATCH 1816/2215] Delete sensors from model and storage

---
 telldus-gui/Plugins/QML/qmlarray.cpp | 8 ++++++++
 telldus-gui/Plugins/QML/qmlarray.h   | 1 +
 2 files changed, 9 insertions(+)

diff --git a/telldus-gui/Plugins/QML/qmlarray.cpp b/telldus-gui/Plugins/QML/qmlarray.cpp
index b36bfac8..8c46d294 100644
--- a/telldus-gui/Plugins/QML/qmlarray.cpp
+++ b/telldus-gui/Plugins/QML/qmlarray.cpp
@@ -35,6 +35,14 @@ void QMLArray::push(const QScriptValue &v) {
 	endInsertRows();
 }
 
+void QMLArray::remove(int index) {
+	qDebug() << "Count first: " << d->list.count();
+	beginRemoveRows( QModelIndex(), index, index );
+	d->list.takeAt(index);
+	endRemoveRows();
+	qDebug() << "Count after: " << d->list.size();
+}
+
 int QMLArray::rowCount(const QModelIndex &parent) const {
 	return d->list.size();
 }
diff --git a/telldus-gui/Plugins/QML/qmlarray.h b/telldus-gui/Plugins/QML/qmlarray.h
index 8c29b798..25eb51f8 100644
--- a/telldus-gui/Plugins/QML/qmlarray.h
+++ b/telldus-gui/Plugins/QML/qmlarray.h
@@ -19,6 +19,7 @@ signals:
 
 public slots:
 	void push(const QScriptValue &v);
+	void remove(int index);
 	QVariant get(int index) const;
 
 

From 5b3b6699970beabbd1af5f4a45002244dfa42de5 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Tue, 17 Jan 2012 13:20:19 +0100
Subject: [PATCH 1817/2215] Remove Stefans debug code

---
 telldus-gui/Plugins/QML/qmlarray.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/telldus-gui/Plugins/QML/qmlarray.cpp b/telldus-gui/Plugins/QML/qmlarray.cpp
index 8c46d294..634e7949 100644
--- a/telldus-gui/Plugins/QML/qmlarray.cpp
+++ b/telldus-gui/Plugins/QML/qmlarray.cpp
@@ -1,7 +1,5 @@
 #include "qmlarray.h"
 
-#include 
-
 class QMLArray::PrivateData {
 public:
 	QList list;
@@ -36,11 +34,9 @@ void QMLArray::push(const QScriptValue &v) {
 }
 
 void QMLArray::remove(int index) {
-	qDebug() << "Count first: " << d->list.count();
 	beginRemoveRows( QModelIndex(), index, index );
 	d->list.takeAt(index);
 	endRemoveRows();
-	qDebug() << "Count after: " << d->list.size();
 }
 
 int QMLArray::rowCount(const QModelIndex &parent) const {

From 5ce0b81e39f7ef7fca38b915ed42b6d3bef1ce91 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Tue, 17 Jan 2012 13:31:01 +0100
Subject: [PATCH 1818/2215] Add function QMLArray::removeLater()

---
 telldus-gui/Plugins/QML/qmlarray.cpp | 7 +++++++
 telldus-gui/Plugins/QML/qmlarray.h   | 1 +
 2 files changed, 8 insertions(+)

diff --git a/telldus-gui/Plugins/QML/qmlarray.cpp b/telldus-gui/Plugins/QML/qmlarray.cpp
index 634e7949..fa306fea 100644
--- a/telldus-gui/Plugins/QML/qmlarray.cpp
+++ b/telldus-gui/Plugins/QML/qmlarray.cpp
@@ -1,4 +1,5 @@
 #include "qmlarray.h"
+#include 
 
 class QMLArray::PrivateData {
 public:
@@ -39,6 +40,12 @@ void QMLArray::remove(int index) {
 	endRemoveRows();
 }
 
+void QMLArray::removeLater(int index) {
+	int methodIndex = this->metaObject()->indexOfMethod(QMetaObject::normalizedSignature("remove(int)"));
+	QMetaMethod method = this->metaObject()->method(methodIndex);
+	method.invoke(this, Qt::QueuedConnection, Q_ARG(int, index));
+}
+
 int QMLArray::rowCount(const QModelIndex &parent) const {
 	return d->list.size();
 }
diff --git a/telldus-gui/Plugins/QML/qmlarray.h b/telldus-gui/Plugins/QML/qmlarray.h
index 25eb51f8..d9da42e1 100644
--- a/telldus-gui/Plugins/QML/qmlarray.h
+++ b/telldus-gui/Plugins/QML/qmlarray.h
@@ -20,6 +20,7 @@ signals:
 public slots:
 	void push(const QScriptValue &v);
 	void remove(int index);
+	void removeLater(int index);
 	QVariant get(int index) const;
 
 

From 645ef2098e00e54a96cbcc13ecd9b504fe64768b Mon Sep 17 00:00:00 2001
From: Stefan Persson 
Date: Tue, 17 Jan 2012 15:10:46 +0100
Subject: [PATCH 1819/2215] Sensor save and load from storage, and deletion.
 Closes #96

---
 telldus-gui/Plugins/Sensors/SensorList.qml |  33 +---
 telldus-gui/Plugins/Sensors/SensorView.qml | 210 ++++++++++++---------
 telldus-gui/Plugins/Sensors/__init__.js    | 107 +++++++++--
 telldus-gui/Plugins/Sensors/sensor.cpp     |   7 +-
 telldus-gui/Plugins/Sensors/sensor.h       |   5 +-
 telldus-gui/Plugins/Settings/settings.cpp  |   4 +-
 6 files changed, 237 insertions(+), 129 deletions(-)

diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml
index bd6f03c7..8f6635bd 100644
--- a/telldus-gui/Plugins/Sensors/SensorList.qml
+++ b/telldus-gui/Plugins/Sensors/SensorList.qml
@@ -5,10 +5,6 @@ Column {
 	id: sensorList
 	spacing: 1
 
-	SensorView {
-		id: sensorView
-	}
-
 	BorderImage {
 		id: header
 		source: "header_bg.png"
@@ -22,6 +18,13 @@ Column {
 			anchors.leftMargin: 15
 		}
 		HeaderTitle {
+			text: ""
+			anchors.right: sensorid.left
+			visible: main.state == "EDIT"
+			width: 50
+		}
+		HeaderTitle {
+			id: sensorid
 			text: "ID"
 			anchors.right: modelTitle.left
 			visible: main.state == "EDIT"
@@ -58,7 +61,7 @@ Column {
 	}
 	Repeater {
 		model: sensorModel
-		delegate: sensorView
+		delegate: SensorView{ state: main.state == "EDIT" ? 'EDIT' : ''}
 	}
 	Row{
 		spacing: 20
@@ -71,27 +74,9 @@ Column {
 					main.state = "EDIT"
 				}
 				else{
-					main.state  ="VIEW"
+					main.state = "VIEW"
 				}
 			}
 		}
-		/*
-			Rectangle {
-				//TODO should this button exist at all, or always save?
-				width: 50
-				height: 20
-				visible: main.state == "EDIT"
-				Text{
-					anchors.centerIn: parent
-					text: "Cancel"
-				}
-				MouseArea{
-					anchors.fill: parent
-					onClicked: {
-						main.state  ="VIEW"
-					}
-				}
-			}
-			*/
 	}
 }
diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml
index c0492840..e383c8b3 100644
--- a/telldus-gui/Plugins/Sensors/SensorView.qml
+++ b/telldus-gui/Plugins/Sensors/SensorView.qml
@@ -1,98 +1,138 @@
 import Qt 4.7
 import QtDesktop 0.1
 
-Component {
-	id: sensorView
-	Item{
-		id: sensorViewItem
-		visible: main.state == "EDIT" || modelData.showInList
-		height: childrenRect.height
+Item{
+	id: sensorViewItem
+	visible: state == "EDIT" || modelData.showInList
+	height: childrenRect.height
+	width: parent ? parent.width : 0
+
+	states:[
+		State {
+			name: "EDIT"
+		}
+	]
+
+	BorderImage {
+		source: "row_bg.png"
+		border.left: 5; border.top: 5
+		border.right: 5; border.bottom: 5
+		height: sensorInfo.height
 		width: parent.width
 
-		property string state: main.state
-		onStateChanged: {
-			if (state != "EDIT") {
-				modelData.setName(nameEdit.text)
+		Text {
+			visible: sensorViewItem.state != "EDIT"
+			anchors.left: parent.left
+			anchors.leftMargin: 15
+			height: 40
+			verticalAlignment: Text.AlignVCenter
+			text: modelData.name == '' ? '' : modelData.name;
+			color: "#004275"
+		}
+		TextField {
+			id: nameEdit
+			visible: sensorViewItem.state == "EDIT"
+			anchors.left: parent.left
+			anchors.leftMargin: 15
+			anchors.top: parent.top
+			anchors.topMargin: (40-nameEdit.height)/2
+			text: modelData.name;
+			placeholderText: 'Enter a name'
+			onTextChanged: modelData.name = text
+		}
+
+		Text{
+			anchors.right: sensorid.left
+			visible: sensorViewItem.state == "EDIT"
+			height: 40
+			verticalAlignment: Text.AlignVCenter
+			text: "Delete"
+			font.underline: true
+			color: "#004275"
+			width: 50
+			MouseArea{
+				anchors.fill: parent
+				onClicked: {
+					confirmDeletion.visible = true;
+				}
+			}
+		}
+		Text{
+			id: sensorid
+			anchors.right: model.left
+			visible: sensorViewItem.state == "EDIT"
+			height: 40
+			verticalAlignment: Text.AlignVCenter
+			text: modelData.id
+			color: "#004275"
+			width: 50
+		}
+		Text{
+			id: model
+			anchors.right: visibleinlistcheckbox.left
+			visible: sensorViewItem.state == "EDIT"
+			height: 40
+			verticalAlignment: Text.AlignVCenter
+			text: modelData.model
+			color: "#004275"
+			width: 100
+		}
+		Item  {
+			id: visibleinlistcheckbox
+			height: 40
+			width: 100
+			anchors.right: sensorInfo.left
+			CheckBox {
+				id: checkBox
+				anchors.centerIn: parent
+				width: checkBox.height
+				visible: sensorViewItem.state == "EDIT"
+				checked: modelData.showInList
+				onClicked: modelData.setShowInList(!modelData.showInList)
 			}
 		}
 
-		BorderImage {
-			source: "row_bg.png"
-			border.left: 5; border.top: 5
-			border.right: 5; border.bottom: 5
-			height: sensorInfo.height
-			width: parent.width
-
-			Text {
-				visible: main.state == "VIEW"
-				anchors.left: parent.left
-				anchors.leftMargin: 15
-				height: 40
-				verticalAlignment: Text.AlignVCenter
-				text: modelData.name == '' ? '' : modelData.name;
-				color: "#004275"
+		Column {
+			id: sensorInfo
+			anchors.right: parent.right
+			width: 250
+			SensorValue {
+				visible: modelData.hasTemperature
+				text: visible ? modelData.sensorValue(1).value + '°C' : ''
+				icon: "icon_temp.png"
+				lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date()
 			}
-			TextField {
-				id: nameEdit
-				visible: main.state == "EDIT"
-				anchors.left: parent.left
-				anchors.leftMargin: 15
-				anchors.top: parent.top
-				anchors.topMargin: (40-nameEdit.height)/2
-				text: modelData.name;
-				placeholderText: 'Enter a name'
-			}
-			Text{
-				anchors.right: model.left
-				visible: main.state == "EDIT"
-				height: 40
-				verticalAlignment: Text.AlignVCenter
-				text: modelData.id
-				color: "#004275"
-				width: 50
-			}
-			Text{
-				id: model
-				anchors.right: visibleinlistcheckbox.left
-				visible: main.state == "EDIT"
-				height: 40
-				verticalAlignment: Text.AlignVCenter
-				text: modelData.model
-				color: "#004275"
-				width: 100
-			}
-			Item  {
-				id: visibleinlistcheckbox
-				height: 40
-				width: 100
-				anchors.right: sensorInfo.left
-				CheckBox {
-					id: checkBox
-					anchors.centerIn: parent
-					width: checkBox.height
-					visible: main.state == "EDIT"
-					checked: modelData.showInList
-					onClicked: modelData.setShowInList(!modelData.showInList)
-				}
-			}
-
-			Column {
-				id: sensorInfo
-				anchors.right: parent.right
-				width: 250
-				SensorValue {
-					visible: modelData.hasTemperature
-					text: visible ? modelData.sensorValue(1).value + '°C' : ''
-					icon: "icon_temp.png"
-					lastUpdated: visible ? modelData.sensorValue(1).lastUpdated : new Date()
-				}
-				SensorValue {
-					visible: modelData.hasHumidity
-					text: visible ? modelData.sensorValue(2).value + '%' : ''
-					icon: "icon_humidity.png"
-					lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date()
-				}
+			SensorValue {
+				visible: modelData.hasHumidity
+				text: visible ? modelData.sensorValue(2).value + '%' : ''
+				icon: "icon_humidity.png"
+				lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date()
 			}
 		}
 	}
+
+	Dialog{
+		id: confirmDeletion
+		modal: true
+		title: "Confirm deletion"
+		Text{
+			id: descriptionHeadline
+			text:"Delete this sensor?"
+			font.bold: true
+		}
+		Text{
+			id: descriptionText
+			anchors.top: descriptionHeadline.bottom
+			anchors.topMargin: 10
+			width: parent.width - 20
+			anchors.left: parent.left
+			anchors.leftMargin: 10
+			text: "Please note that a sensor that is still transmitting will reappear here again, but it will be hidden in the list by default."
+			wrapMode: Text.Wrap
+		}
+
+		onAccepted: {
+			deleteSensor.callWith(modelData.protocol, modelData.model, modelData.id);
+		}
+	}
 }
diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js
index 70283e2b..b2a36c73 100644
--- a/telldus-gui/Plugins/Sensors/__init__.js
+++ b/telldus-gui/Plugins/Sensors/__init__.js
@@ -6,10 +6,13 @@ __postInit__ = function() {
 }
 
 com.telldus.sensors = function() {
-	var sensorList = new com.telldus.qml.array();
-
+	var sensorList;
 	function init() {
 		var sensorData = 0;
+		sensorList = loadSensorModel();
+		sensorList.rowsRemoved.connect(function(){saveSensorModel();});
+		sensorList.rowsInserted.connect(function(){saveSensorModel();});
+
 		while(sensorData = com.telldus.core.sensor()) {
 			var p = sensorData["protocol"];
 			var m = sensorData["model"];
@@ -19,7 +22,7 @@ com.telldus.sensors = function() {
 			var tryFetchValue = function(p, m, id, types, type) {
 				if (types & type) {
 					sensorValue = com.telldus.core.sensorValue(p, m, id, type);
-					sensorEvent(p, m, id, type, sensorValue["value"], sensorValue["timestamp"]);
+					sensorEvent(p, m, id, type, sensorValue["value"], sensorValue["timestamp"], true);
 				}
 			}
 			tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_TEMPERATURE);
@@ -28,14 +31,94 @@ com.telldus.sensors = function() {
 		}
 
 		com.telldus.core.sensorEvent.connect(sensorEvent);
-		view = new com.telldus.qml.view({});
+		view = new com.telldus.qml.view({
+			deleteSensor: deleteSensor
+		});
 
 		view.setProperty('sensorModel', sensorList);
+		saveSensorModel();
 		view.load("main.qml");
 		application.addWidget("sensors.gui", "icon.png", view);
 	}
 
-	function sensorEvent(protocol, model, id, dataType, value, timestamp) {
+	function createSensor(protocol, model, id, name, showInList){
+		var sensor = new com.telldus.sensors.sensor();
+		sensor.protocol = protocol;
+		sensor.model = model;
+		sensor.id = id;
+		sensor.name = name;
+		sensor.nameChanged.connect(function() { saveSensorModel(); });
+		sensor.showInList = showInList;
+		sensor.showInListChanged.connect(function() { saveSensorModel(); });
+		return sensor;
+	}
+
+	function deleteSensor(protocol, model, id){
+		var i = 0;
+		var found = false;
+		for (; i < sensorList.length; ++i) {
+			if (sensorList.get(i).protocol != protocol) {
+				continue;
+			}
+			if (sensorList.get(i).model != model) {
+				continue;
+			}
+			if (sensorList.get(i).id != id) {
+				continue;
+			}
+			found = true;
+			break;
+		}
+		if(found){
+			sensorList.removeLater(i);
+		}
+	}
+
+	function loadSensorModel(){
+		var settings = new com.telldus.settings();
+		var sensors = new com.telldus.qml.array();
+
+		var sensorProperties = settings.value("sensors", "");
+		if(sensorProperties){
+			for (var i = 0; i < sensorProperties.length; i++) {
+				var sensor = createSensor(sensorProperties[i].protocol, sensorProperties[i].model, sensorProperties[i].id, sensorProperties[i].name, sensorProperties[i].showInList=="true");
+				for (var j = 0; j < sensorProperties[i].values.length; j++) {
+					sensor.setValue(sensorProperties[i].values[j].type, sensorProperties[i].values[j].value, sensorProperties[i].values[j].lastUpdated)
+				}
+				sensors.push(sensor);
+			}
+		}
+		return sensors;
+	}
+
+	function saveSensorModel(){
+		var settings = new com.telldus.settings();
+		var sensorProperties = new Array();
+
+		for (var i = 0; i < sensorList.length; ++i) {
+			var sensor = sensorList.get(i);
+
+			var allValues = new Array();
+			if(sensor.hasHumidity){
+				var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_HUMIDITY);
+				var value = {type: com.telldus.core.TELLSTICK_HUMIDITY, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value};
+				allValues.push(value);
+			}
+			if(sensor.hasTemperature){
+				var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_TEMPERATURE);
+				var value = {type: com.telldus.core.TELLSTICK_TEMPERATURE, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value};
+				allValues.push(value);
+			}
+
+			var sensorProp = {protocol:sensor.protocol, model:sensor.model, id:sensor.id, values:allValues, name:sensor.name, showInList:sensor.showInList};
+			sensorProperties.push(sensorProp);
+		}
+
+		settings.setValue("sensors", sensorProperties);
+	}
+
+	function sensorEvent(protocol, model, id, dataType, value, timestamp, avoidSave) {
+
 		var sensor = 0;
 		for (var i = 0; i < sensorList.length; ++i) {
 			if (sensorList.get(i).protocol != protocol) {
@@ -52,19 +135,15 @@ com.telldus.sensors = function() {
 		}
 
 		if (!sensor) {
-			sensor = new com.telldus.sensors.sensor();
-			sensor.protocol = protocol;
-			sensor.model = model;
-			sensor.id = id;
-			sensor.showInList = false;
+			sensor = createSensor(protocol, model, id, "", false);
 			sensorList.push(sensor);
-			print("Create new");
-		} else {
-			print("Update");
 		}
 
-		print("Sensor event", protocol, model, id, dataType, value, timestamp);
 		sensor.setValue(dataType, value, timestamp);
+
+		if(!avoidSave){
+			saveSensorModel();
+		}
 	}
 
 	return { //Public functions
diff --git a/telldus-gui/Plugins/Sensors/sensor.cpp b/telldus-gui/Plugins/Sensors/sensor.cpp
index d800032a..1ba7d76f 100644
--- a/telldus-gui/Plugins/Sensors/sensor.cpp
+++ b/telldus-gui/Plugins/Sensors/sensor.cpp
@@ -17,6 +17,7 @@ Sensor::Sensor(QObject *parent) :
 {
 	d = new PrivateData;
 	d->id = 0;
+	d->showInList = false;
 }
 
 Sensor::~Sensor() {
@@ -50,6 +51,9 @@ QString Sensor::name() const {
 }
 
 void Sensor::setName(const QString &name) {
+	if (name == d->name) {
+		return;
+	}
 	d->name = name;
 	emit nameChanged();
 }
@@ -67,7 +71,7 @@ bool Sensor::hasTemperature() const {
 	return d->values.contains(TELLSTICK_TEMPERATURE);
 }
 
-SensorValue * Sensor::sensorValue(int type) {
+QObject * Sensor::sensorValue(int type) {
 	return (d->values.contains(type) ? d->values[type] : 0);
 }
 
@@ -90,7 +94,6 @@ void Sensor::setValue(int type, const QString &value, const QDateTime ×tamp
 }
 
 bool Sensor::showInList() const{
-	//TODO showInList and name must be persistent...
 	return d->showInList;
 }
 
diff --git a/telldus-gui/Plugins/Sensors/sensor.h b/telldus-gui/Plugins/Sensors/sensor.h
index 85164246..6683e305 100644
--- a/telldus-gui/Plugins/Sensors/sensor.h
+++ b/telldus-gui/Plugins/Sensors/sensor.h
@@ -17,7 +17,7 @@ class Sensor : public QObject
 	Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged)
 	Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
 	Q_PROPERTY(QString protocol READ protocol WRITE setProtocol NOTIFY protocolChanged)
-	Q_PROPERTY(bool showInList READ showInList NOTIFY showInListChanged)
+	Q_PROPERTY(bool showInList READ showInList WRITE setShowInList NOTIFY showInListChanged)
 
 public:
 	explicit Sensor(QObject *parent = 0);
@@ -32,7 +32,6 @@ public:
 	void setModel(const QString &model);
 
 	QString name() const;
-	//void setName(const QString &name);
 
 	QString protocol() const;
 	void setProtocol(const QString &protocol);
@@ -40,7 +39,7 @@ public:
 	bool hasTemperature() const;
 	bool showInList() const;
 
-	Q_INVOKABLE SensorValue *sensorValue(int type);
+	Q_INVOKABLE QObject *sensorValue(int type);
 	Q_INVOKABLE void setValue(int type, const QString &value, const QDateTime ×tamp);
 	Q_INVOKABLE void setName(const QString &name);
 	Q_INVOKABLE void setShowInList(bool show);
diff --git a/telldus-gui/Plugins/Settings/settings.cpp b/telldus-gui/Plugins/Settings/settings.cpp
index d0f7097b..85ae12ff 100644
--- a/telldus-gui/Plugins/Settings/settings.cpp
+++ b/telldus-gui/Plugins/Settings/settings.cpp
@@ -26,10 +26,12 @@ void Settings::setValue( const QString & key, const QVariant & value ) {
 		d->s.beginGroup(key);
 		d->s.setValue("size", list.size());
 		d->s.setValue("type", "array");
+		//d->s.beginWriteArray("list"); //TODO write or read? What prefix?
 		for (int i = 0; i < list.size(); ++i) {
-			d->s.setArrayIndex(i);
+			//d->s.setArrayIndex(i);
 			this->setValue(QString::number(i), list.at(i));
 		}
+		//d->s.endArray();
 		d->s.endGroup();
 
 	} else if (value.type() == QVariant::Map) {

From 848f65803c6c460de9219c4de46b5eb80d1c2c37 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:21:42 +0100
Subject: [PATCH 1820/2215] Add getopt implementation from OpenBSD

---
 telldus-core/3rdparty/openbsd-getopt/err.h    |   9 +
 telldus-core/3rdparty/openbsd-getopt/getopt.h |  78 +++
 .../3rdparty/openbsd-getopt/getopt_long.c     | 511 ++++++++++++++++++
 .../3rdparty/openbsd-getopt/sys/_types.h      |  71 +++
 .../3rdparty/openbsd-getopt/sys/cdefs.h       | 386 +++++++++++++
 .../3rdparty/openbsd-getopt/sys/types.h       | 243 +++++++++
 .../3rdparty/openbsd-getopt/sys/unistd.h      | 159 ++++++
 telldus-core/3rdparty/openbsd-getopt/unistd.h | 274 ++++++++++
 8 files changed, 1731 insertions(+)
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/err.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/getopt.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/getopt_long.c
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/sys/_types.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/sys/types.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/sys/unistd.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/unistd.h

diff --git a/telldus-core/3rdparty/openbsd-getopt/err.h b/telldus-core/3rdparty/openbsd-getopt/err.h
new file mode 100644
index 00000000..b7d57bb2
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/err.h
@@ -0,0 +1,9 @@
+#include 
+#include 
+
+__inline void warnx(const char *fmt, ...) {
+	va_list ap;
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+}
diff --git a/telldus-core/3rdparty/openbsd-getopt/getopt.h b/telldus-core/3rdparty/openbsd-getopt/getopt.h
new file mode 100644
index 00000000..0311b078
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/getopt.h
@@ -0,0 +1,78 @@
+/*	$OpenBSD: getopt.h,v 1.2 2008/06/26 05:42:04 ray Exp $	*/
+/*	$NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $	*/
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GETOPT_H_
+#define _GETOPT_H_
+
+#include 
+
+/*
+ * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
+ */
+#define no_argument        0
+#define required_argument  1
+#define optional_argument  2
+
+struct option {
+	/* name of long option */
+	const char *name;
+	/*
+	 * one of no_argument, required_argument, and optional_argument:
+	 * whether option takes an argument
+	 */
+	int has_arg;
+	/* if not NULL, set *flag to val when option found */
+	int *flag;
+	/* if flag not NULL, value to set *flag to; else return value */
+	int val;
+};
+
+__BEGIN_DECLS
+int	 getopt_long(int, char * const *, const char *,
+	    const struct option *, int *);
+int	 getopt_long_only(int, char * const *, const char *,
+	    const struct option *, int *);
+#ifndef _GETOPT_DEFINED_
+#define _GETOPT_DEFINED_
+int	 getopt(int, char * const *, const char *);
+int	 getsubopt(char **, char * const *, char **);
+
+extern   char *optarg;                  /* getopt(3) external variables */
+extern   int opterr;
+extern   int optind;
+extern   int optopt;
+extern   int optreset;
+extern   char *suboptarg;               /* getsubopt(3) external variable */
+#endif
+__END_DECLS
+ 
+#endif /* !_GETOPT_H_ */
diff --git a/telldus-core/3rdparty/openbsd-getopt/getopt_long.c b/telldus-core/3rdparty/openbsd-getopt/getopt_long.c
new file mode 100644
index 00000000..e149fe0a
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/getopt_long.c
@@ -0,0 +1,511 @@
+/*	$OpenBSD: getopt_long.c,v 1.25 2011/03/05 22:10:11 guenther Exp $	*/
+/*	$NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $	*/
+
+/*
+ * Copyright (c) 2002 Todd C. Miller 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int	opterr = 1;		/* if error message should be printed */
+int	optind = 1;		/* index into parent argv vector */
+int	optopt = '?';		/* character checked for validity */
+int	optreset;		/* reset getopt */
+char    *optarg;		/* argument associated with option */
+
+#define PRINT_ERROR	((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE	0x01	/* permute non-options to the end of argv */
+#define FLAG_ALLARGS	0x02	/* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY	0x04	/* operate as getopt_long_only */
+
+/* return values */
+#define	BADCH		(int)'?'
+#define	BADARG		((*options == ':') ? (int)':' : (int)'?')
+#define	INORDER 	(int)1
+
+#define	EMSG		""
+
+static int getopt_internal(int, char * const *, const char *,
+			   const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+			      const struct option *, int *, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1;   /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptchar[] = "unknown option -- %c";
+static const char illoptstring[] = "unknown option -- %s";
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+	int c;
+
+	c = a % b;
+	while (c != 0) {
+		a = b;
+		b = c;
+		c = a % b;
+	}
+
+	return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+	char * const *nargv)
+{
+	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+	char *swap;
+
+	/*
+	 * compute lengths of blocks and number and size of cycles
+	 */
+	nnonopts = panonopt_end - panonopt_start;
+	nopts = opt_end - panonopt_end;
+	ncycle = gcd(nnonopts, nopts);
+	cyclelen = (opt_end - panonopt_start) / ncycle;
+
+	for (i = 0; i < ncycle; i++) {
+		cstart = panonopt_end+i;
+		pos = cstart;
+		for (j = 0; j < cyclelen; j++) {
+			if (pos >= panonopt_end)
+				pos -= nnonopts;
+			else
+				pos += nopts;
+			swap = nargv[pos];
+			/* LINTED const cast */
+			((char **) nargv)[pos] = nargv[cstart];
+			/* LINTED const cast */
+			((char **)nargv)[cstart] = swap;
+		}
+	}
+}
+
+/*
+ * parse_long_options --
+ *	Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int short_too)
+{
+	char *current_argv, *has_equal;
+	size_t current_argv_len;
+	int i, match;
+
+	current_argv = place;
+	match = -1;
+
+	optind++;
+
+	if ((has_equal = strchr(current_argv, '=')) != NULL) {
+		/* argument found (--option=arg) */
+		current_argv_len = has_equal - current_argv;
+		has_equal++;
+	} else
+		current_argv_len = strlen(current_argv);
+
+	for (i = 0; long_options[i].name; i++) {
+		/* find matching long option */
+		if (strncmp(current_argv, long_options[i].name,
+		    current_argv_len))
+			continue;
+
+		if (strlen(long_options[i].name) == current_argv_len) {
+			/* exact match */
+			match = i;
+			break;
+		}
+		/*
+		 * If this is a known short option, don't allow
+		 * a partial match of a single character.
+		 */
+		if (short_too && current_argv_len == 1)
+			continue;
+
+		if (match == -1)	/* partial match */
+			match = i;
+		else {
+			/* ambiguous abbreviation */
+			if (PRINT_ERROR)
+				warnx(ambig, (int)current_argv_len,
+				     current_argv);
+			optopt = 0;
+			return (BADCH);
+		}
+	}
+	if (match != -1) {		/* option found */
+		if (long_options[match].has_arg == no_argument
+		    && has_equal) {
+			if (PRINT_ERROR)
+				warnx(noarg, (int)current_argv_len,
+				     current_argv);
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+			return (BADARG);
+		}
+		if (long_options[match].has_arg == required_argument ||
+		    long_options[match].has_arg == optional_argument) {
+			if (has_equal)
+				optarg = has_equal;
+			else if (long_options[match].has_arg ==
+			    required_argument) {
+				/*
+				 * optional argument doesn't use next nargv
+				 */
+				optarg = nargv[optind++];
+			}
+		}
+		if ((long_options[match].has_arg == required_argument)
+		    && (optarg == NULL)) {
+			/*
+			 * Missing argument; leading ':' indicates no error
+			 * should be generated.
+			 */
+			if (PRINT_ERROR)
+				warnx(recargstring,
+				    current_argv);
+			/*
+			 * XXX: GNU sets optopt to val regardless of flag
+			 */
+			if (long_options[match].flag == NULL)
+				optopt = long_options[match].val;
+			else
+				optopt = 0;
+			--optind;
+			return (BADARG);
+		}
+	} else {			/* unknown option */
+		if (short_too) {
+			--optind;
+			return (-1);
+		}
+		if (PRINT_ERROR)
+			warnx(illoptstring, current_argv);
+		optopt = 0;
+		return (BADCH);
+	}
+	if (idx)
+		*idx = match;
+	if (long_options[match].flag) {
+		*long_options[match].flag = long_options[match].val;
+		return (0);
+	} else
+		return (long_options[match].val);
+}
+
+/*
+ * getopt_internal --
+ *	Parse argc/argv argument vector.  Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+	const struct option *long_options, int *idx, int flags)
+{
+	char *oli;				/* option letter list index */
+	int optchar, short_too;
+	static int posixly_correct = -1;
+
+	if (options == NULL)
+		return (-1);
+
+	/*
+	 * XXX Some GNU programs (like cvs) set optind to 0 instead of
+	 * XXX using optreset.  Work around this braindamage.
+	 */
+	if (optind == 0)
+		optind = optreset = 1;
+
+	/*
+	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
+	 * string begins with a '+'.
+	 */
+	if (posixly_correct == -1 || optreset)
+		posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+	if (*options == '-')
+		flags |= FLAG_ALLARGS;
+	else if (posixly_correct || *options == '+')
+		flags &= ~FLAG_PERMUTE;
+	if (*options == '+' || *options == '-')
+		options++;
+
+	optarg = NULL;
+	if (optreset)
+		nonopt_start = nonopt_end = -1;
+start:
+	if (optreset || !*place) {		/* update scanning pointer */
+		optreset = 0;
+		if (optind >= nargc) {          /* end of argument vector */
+			place = EMSG;
+			if (nonopt_end != -1) {
+				/* do permutation, if we have to */
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			else if (nonopt_start != -1) {
+				/*
+				 * If we skipped non-options, set optind
+				 * to the first of them.
+				 */
+				optind = nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+		if (*(place = nargv[optind]) != '-' ||
+		    (place[1] == '\0' && strchr(options, '-') == NULL)) {
+			place = EMSG;		/* found non-option */
+			if (flags & FLAG_ALLARGS) {
+				/*
+				 * GNU extension:
+				 * return non-option as argument to option 1
+				 */
+				optarg = nargv[optind++];
+				return (INORDER);
+			}
+			if (!(flags & FLAG_PERMUTE)) {
+				/*
+				 * If no permutation wanted, stop parsing
+				 * at first non-option.
+				 */
+				return (-1);
+			}
+			/* do permutation */
+			if (nonopt_start == -1)
+				nonopt_start = optind;
+			else if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				nonopt_start = optind -
+				    (nonopt_end - nonopt_start);
+				nonopt_end = -1;
+			}
+			optind++;
+			/* process next argument */
+			goto start;
+		}
+		if (nonopt_start != -1 && nonopt_end == -1)
+			nonopt_end = optind;
+
+		/*
+		 * If we have "-" do nothing, if "--" we are done.
+		 */
+		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+			optind++;
+			place = EMSG;
+			/*
+			 * We found an option (--), so if we skipped
+			 * non-options, we have to permute.
+			 */
+			if (nonopt_end != -1) {
+				permute_args(nonopt_start, nonopt_end,
+				    optind, nargv);
+				optind -= nonopt_end - nonopt_start;
+			}
+			nonopt_start = nonopt_end = -1;
+			return (-1);
+		}
+	}
+
+	/*
+	 * Check long options if:
+	 *  1) we were passed some
+	 *  2) the arg is not just "-"
+	 *  3) either the arg starts with -- we are getopt_long_only()
+	 */
+	if (long_options != NULL && place != nargv[optind] &&
+	    (*place == '-' || (flags & FLAG_LONGONLY))) {
+		short_too = 0;
+		if (*place == '-')
+			place++;		/* --foo long option */
+		else if (*place != ':' && strchr(options, *place) != NULL)
+			short_too = 1;		/* could be short option too */
+
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, short_too);
+		if (optchar != -1) {
+			place = EMSG;
+			return (optchar);
+		}
+	}
+
+	if ((optchar = (int)*place++) == (int)':' ||
+	    (optchar == (int)'-' && *place != '\0') ||
+	    (oli = strchr(options, optchar)) == NULL) {
+		/*
+		 * If the user specified "-" and  '-' isn't listed in
+		 * options, return -1 (non-option) as per POSIX.
+		 * Otherwise, it is an unknown option character (or ':').
+		 */
+		if (optchar == (int)'-' && *place == '\0')
+			return (-1);
+		if (!*place)
+			++optind;
+		if (PRINT_ERROR)
+			warnx(illoptchar, optchar);
+		optopt = optchar;
+		return (BADCH);
+	}
+	if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+		/* -W long-option */
+		if (*place)			/* no space */
+			/* NOTHING */;
+		else if (++optind >= nargc) {	/* no arg */
+			place = EMSG;
+			if (PRINT_ERROR)
+				warnx(recargchar, optchar);
+			optopt = optchar;
+			return (BADARG);
+		} else				/* white space */
+			place = nargv[optind];
+		optchar = parse_long_options(nargv, options, long_options,
+		    idx, 0);
+		place = EMSG;
+		return (optchar);
+	}
+	if (*++oli != ':') {			/* doesn't take argument */
+		if (!*place)
+			++optind;
+	} else {				/* takes (optional) argument */
+		optarg = NULL;
+		if (*place)			/* no white space */
+			optarg = place;
+		else if (oli[1] != ':') {	/* arg not optional */
+			if (++optind >= nargc) {	/* no arg */
+				place = EMSG;
+				if (PRINT_ERROR)
+					warnx(recargchar, optchar);
+				optopt = optchar;
+				return (BADARG);
+			} else
+				optarg = nargv[optind];
+		}
+		place = EMSG;
+		++optind;
+	}
+	/* dump back option letter */
+	return (optchar);
+}
+
+/*
+ * getopt --
+ *	Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+	/*
+	 * We don't pass FLAG_PERMUTE to getopt_internal() since
+	 * the BSD getopt(3) (unlike GNU) has never done this.
+	 *
+	 * Furthermore, since many privileged programs call getopt()
+	 * before dropping privileges it makes sense to keep things
+	 * as simple (and bug-free) as possible.
+	 */
+	return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+
+/*
+ * getopt_long --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ *	Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+    const struct option *long_options, int *idx)
+{
+
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
+	    FLAG_PERMUTE|FLAG_LONGONLY));
+}
diff --git a/telldus-core/3rdparty/openbsd-getopt/sys/_types.h b/telldus-core/3rdparty/openbsd-getopt/sys/_types.h
new file mode 100644
index 00000000..f31ae95e
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/sys/_types.h
@@ -0,0 +1,71 @@
+/*	$OpenBSD: _types.h,v 1.2 2008/03/16 19:42:57 otto Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)types.h	8.3 (Berkeley) 1/5/94
+ */
+
+#ifndef _SYS__TYPES_H_
+#define	_SYS__TYPES_H_
+
+#include 
+
+typedef	unsigned long	__cpuid_t;	/* CPU id */
+typedef	__int32_t	__dev_t;	/* device number */
+typedef	__uint32_t	__fixpt_t;	/* fixed point number */
+typedef	__uint32_t	__gid_t;	/* group id */
+typedef	__uint32_t	__id_t;		/* may contain pid, uid or gid */
+typedef __uint32_t	__in_addr_t;	/* base type for internet address */
+typedef __uint16_t	__in_port_t;	/* IP port type */
+typedef	__uint32_t	__ino_t;	/* inode number */
+typedef	long		__key_t;	/* IPC key (for Sys V IPC) */
+typedef	__uint32_t	__mode_t;	/* permissions */
+typedef	__uint32_t	__nlink_t;	/* link count */
+typedef	__int32_t	__pid_t;	/* process id */
+typedef __uint64_t	__rlim_t;	/* resource limit */
+typedef __uint8_t	__sa_family_t;	/* sockaddr address family type */
+typedef	__int32_t	__segsz_t;	/* segment size */
+typedef __uint32_t	__socklen_t;	/* length type for network syscalls */
+typedef	__int32_t	__swblk_t;	/* swap offset */
+typedef	__uint32_t	__uid_t;	/* user id */
+typedef	__uint32_t	__useconds_t;	/* microseconds */
+typedef	__int32_t	__suseconds_t;	/* microseconds (signed) */
+typedef __uint64_t	__fsblkcnt_t;	/* file system block count */
+typedef __uint64_t	__fsfilcnt_t;	/* file system file count */
+
+/*
+ * mbstate_t is an opaque object to keep conversion state, during multibyte
+ * stream conversions. The content must not be referenced by user programs.
+ */
+typedef union {
+	char __mbstate8[128];
+	__int64_t __mbstateL;			/* for alignment */
+} __mbstate_t;
+
+#endif /* !_SYS__TYPES_H_ */
diff --git a/telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h b/telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h
new file mode 100644
index 00000000..b9ad10d0
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h
@@ -0,0 +1,386 @@
+/*	$OpenBSD: cdefs.h,v 1.32 2012/01/03 16:56:58 kettenis Exp $	*/
+/*	$NetBSD: cdefs.h,v 1.16 1996/04/03 20:46:39 christos Exp $	*/
+
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)cdefs.h	8.7 (Berkeley) 1/21/94
+ */
+
+#ifndef	_SYS_CDEFS_H_
+#define	_SYS_CDEFS_H_
+
+#include 
+
+#if defined(__cplusplus)
+#define	__BEGIN_DECLS	extern "C" {
+#define	__END_DECLS	}
+#else
+#define	__BEGIN_DECLS
+#define	__END_DECLS
+#endif
+
+/*
+ * Macro to test if we're using a specific version of gcc or later.
+ */
+#ifdef __GNUC__
+#define __GNUC_PREREQ__(ma, mi) \
+	((__GNUC__ > (ma)) || (__GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)))
+#else
+#define __GNUC_PREREQ__(ma, mi) 0
+#endif
+
+/*
+ * The __CONCAT macro is used to concatenate parts of symbol names, e.g.
+ * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo.
+ * The __CONCAT macro is a bit tricky -- make sure you don't put spaces
+ * in between its arguments.  __CONCAT can also concatenate double-quoted
+ * strings produced by the __STRING macro, but this only works with ANSI C.
+ */
+#if defined(__STDC__) || defined(__cplusplus)
+#define	__P(protos)	protos		/* full-blown ANSI C */
+#define	__CONCAT(x,y)	x ## y
+#define	__STRING(x)	#x
+
+#define	__const		const		/* define reserved names to standard */
+#define	__signed	signed
+#define	__volatile	volatile
+#if defined(__cplusplus) || defined(__PCC__)
+#define	__inline	inline		/* convert to C++ keyword */
+#else
+#if !defined(__GNUC__) && !defined(lint)
+#define	__inline			/* delete GCC keyword */
+#endif /* !__GNUC__ && !lint */
+#endif /* !__cplusplus */
+
+#else	/* !(__STDC__ || __cplusplus) */
+#define	__P(protos)	()		/* traditional C preprocessor */
+#define	__CONCAT(x,y)	x/**/y
+#define	__STRING(x)	"x"
+
+#if !defined(__GNUC__) && !defined(lint)
+#define	__const				/* delete pseudo-ANSI C keywords */
+#define	__inline
+#define	__signed
+#define	__volatile
+#endif	/* !__GNUC__ && !lint */
+
+/*
+ * In non-ANSI C environments, new programs will want ANSI-only C keywords
+ * deleted from the program and old programs will want them left alone.
+ * Programs using the ANSI C keywords const, inline etc. as normal
+ * identifiers should define -DNO_ANSI_KEYWORDS.
+ */
+#ifndef	NO_ANSI_KEYWORDS
+#define	const		__const		/* convert ANSI C keywords */
+#define	inline		__inline
+#define	signed		__signed
+#define	volatile	__volatile
+#endif /* !NO_ANSI_KEYWORDS */
+#endif	/* !(__STDC__ || __cplusplus) */
+
+/*
+ * GCC1 and some versions of GCC2 declare dead (non-returning) and
+ * pure (no side effects) functions using "volatile" and "const";
+ * unfortunately, these then cause warnings under "-ansi -pedantic".
+ * GCC >= 2.5 uses the __attribute__((attrs)) style.  All of these
+ * work for GNU C++ (modulo a slight glitch in the C++ grammar in
+ * the distribution version of 2.5.5).
+ */
+
+#if !__GNUC_PREREQ__(2, 5) && !defined(__PCC__)
+#define	__attribute__(x)	/* delete __attribute__ if non-gcc or gcc1 */
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+#define	__dead		__volatile
+#define	__pure		__const
+#elif defined(lint)
+#define __dead		/* NORETURN */
+#endif
+#elif !defined(__STRICT_ANSI__)
+#define __dead		__attribute__((__noreturn__))
+#define __pure		__attribute__((__const__))
+#endif
+
+#if __GNUC_PREREQ__(2, 7)
+#define	__unused	__attribute__((__unused__))
+#else
+#define	__unused	/* delete */
+#endif
+
+#if __GNUC_PREREQ__(3, 1)
+#define	__used		__attribute__((__used__))
+#else
+#define	__used		__unused	/* suppress -Wunused warnings */
+#endif
+
+/*
+ * __returns_twice makes the compiler not assume the function
+ * only returns once.  This affects registerisation of variables:
+ * even local variables need to be in memory across such a call.
+ * Example: setjmp()
+ */
+#if __GNUC_PREREQ__(4, 1)
+#define __returns_twice	__attribute__((returns_twice))
+#else
+#define __returns_twice
+#endif
+
+/*
+ * __only_inline makes the compiler only use this function definition
+ * for inlining; references that can't be inlined will be left as
+ * external references instead of generating a local copy.  The
+ * matching library should include a simple extern definition for
+ * the function to handle those references.  c.f. ctype.h
+ */
+#ifdef __GNUC__
+#  if __GNUC_PREREQ__(4, 2)
+#define __only_inline	extern __inline __attribute__((__gnu_inline__))
+#  else
+#define __only_inline	extern __inline
+#  endif
+#else
+#define __only_inline	static __inline
+#endif
+
+/*
+ * GNU C version 2.96 adds explicit branch prediction so that
+ * the CPU back-end can hint the processor and also so that
+ * code blocks can be reordered such that the predicted path
+ * sees a more linear flow, thus improving cache behavior, etc.
+ *
+ * The following two macros provide us with a way to utilize this
+ * compiler feature.  Use __predict_true() if you expect the expression
+ * to evaluate to true, and __predict_false() if you expect the
+ * expression to evaluate to false.
+ *
+ * A few notes about usage:
+ *
+ *	* Generally, __predict_false() error condition checks (unless
+ *	  you have some _strong_ reason to do otherwise, in which case
+ *	  document it), and/or __predict_true() `no-error' condition
+ *	  checks, assuming you want to optimize for the no-error case.
+ *
+ *	* Other than that, if you don't know the likelihood of a test
+ *	  succeeding from empirical or other `hard' evidence, don't
+ *	  make predictions.
+ *
+ *	* These are meant to be used in places that are run `a lot'.
+ *	  It is wasteful to make predictions in code that is run
+ *	  seldomly (e.g. at subsystem initialization time) as the
+ *	  basic block reordering that this affects can often generate
+ *	  larger code.
+ */
+#if __GNUC_PREREQ__(2, 96)
+#define __predict_true(exp)	__builtin_expect(((exp) != 0), 1)
+#define __predict_false(exp)	__builtin_expect(((exp) != 0), 0)
+#else
+#define __predict_true(exp)	((exp) != 0)
+#define __predict_false(exp)	((exp) != 0)
+#endif
+
+/* Delete pseudo-keywords wherever they are not available or needed. */
+#ifndef __dead
+#define	__dead
+#define	__pure
+#endif
+
+#if __GNUC_PREREQ__(2, 7) || defined(__PCC__)
+#define	__packed	__attribute__((__packed__))
+#elif defined(lint)
+#define	__packed
+#endif
+
+#if !__GNUC_PREREQ__(2, 8)
+#define	__extension__
+#endif
+
+#if __GNUC_PREREQ__(2, 8) || defined(__PCC__)
+#define __statement(x)	__extension__(x)
+#elif defined(lint)
+#define __statement(x)	(0)
+#else
+#define __statement(x)	(x)
+#endif
+
+#if __GNUC_PREREQ__(3, 0)
+#define	__malloc	__attribute__((__malloc__))
+#else
+#define	__malloc
+#endif
+
+/*
+ * "The nice thing about standards is that there are so many to choose from."
+ * There are a number of "feature test macros" specified by (different)
+ * standards that determine which interfaces and types the header files
+ * should expose.
+ *
+ * Because of inconsistencies in these macros, we define our own
+ * set in the private name space that end in _VISIBLE.  These are
+ * always defined and so headers can test their values easily.
+ * Things can get tricky when multiple feature macros are defined.
+ * We try to take the union of all the features requested.
+ *
+ * The following macros are guaranteed to have a value after cdefs.h
+ * has been included:
+ *	__POSIX_VISIBLE
+ *	__XPG_VISIBLE
+ *	__ISO_C_VISIBLE
+ *	__BSD_VISIBLE
+ */
+
+/*
+ * X/Open Portability Guides and Single Unix Specifications.
+ * _XOPEN_SOURCE				XPG3
+ * _XOPEN_SOURCE && _XOPEN_VERSION = 4		XPG4
+ * _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED = 1	XPG4v2
+ * _XOPEN_SOURCE == 500				XPG5
+ * _XOPEN_SOURCE == 520				XPG5v2
+ * _XOPEN_SOURCE == 600				POSIX 1003.1-2001 with XSI
+ * _XOPEN_SOURCE == 700				POSIX 1003.1-2008 with XSI
+ *
+ * The XPG spec implies a specific value for _POSIX_C_SOURCE.
+ */
+#ifdef _XOPEN_SOURCE
+# if (_XOPEN_SOURCE - 0 >= 700)
+#  define __XPG_VISIBLE		700
+#  undef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE	200809L
+# elif (_XOPEN_SOURCE - 0 >= 600)
+#  define __XPG_VISIBLE		600
+#  undef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE	200112L
+# elif (_XOPEN_SOURCE - 0 >= 520)
+#  define __XPG_VISIBLE		520
+#  undef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE	199506L
+# elif (_XOPEN_SOURCE - 0 >= 500)
+#  define __XPG_VISIBLE		500
+#  undef _POSIX_C_SOURCE
+#  define _POSIX_C_SOURCE	199506L
+# elif (_XOPEN_SOURCE_EXTENDED - 0 == 1)
+#  define __XPG_VISIBLE		420
+# elif (_XOPEN_VERSION - 0 >= 4)
+#  define __XPG_VISIBLE		400
+# else
+#  define __XPG_VISIBLE		300
+# endif
+#endif
+
+/*
+ * POSIX macros, these checks must follow the XOPEN ones above.
+ *
+ * _POSIX_SOURCE == 1		1003.1-1988 (superseded by _POSIX_C_SOURCE)
+ * _POSIX_C_SOURCE == 1		1003.1-1990
+ * _POSIX_C_SOURCE == 2		1003.2-1992
+ * _POSIX_C_SOURCE == 199309L	1003.1b-1993
+ * _POSIX_C_SOURCE == 199506L   1003.1c-1995, 1003.1i-1995,
+ *				and the omnibus ISO/IEC 9945-1:1996
+ * _POSIX_C_SOURCE == 200112L   1003.1-2001
+ * _POSIX_C_SOURCE == 200809L   1003.1-2008
+ *
+ * The POSIX spec implies a specific value for __ISO_C_VISIBLE, though
+ * this may be overridden by the _ISOC99_SOURCE macro later.
+ */
+#ifdef _POSIX_C_SOURCE
+# if (_POSIX_C_SOURCE - 0 >= 200809)
+#  define __POSIX_VISIBLE	200809
+#  define __ISO_C_VISIBLE	1999
+# elif (_POSIX_C_SOURCE - 0 >= 200112)
+#  define __POSIX_VISIBLE	200112
+#  define __ISO_C_VISIBLE	1999
+# elif (_POSIX_C_SOURCE - 0 >= 199506)
+#  define __POSIX_VISIBLE	199506
+#  define __ISO_C_VISIBLE	1990
+# elif (_POSIX_C_SOURCE - 0 >= 199309)
+#  define __POSIX_VISIBLE	199309
+#  define __ISO_C_VISIBLE	1990
+# elif (_POSIX_C_SOURCE - 0 >= 2)
+#  define __POSIX_VISIBLE	199209
+#  define __ISO_C_VISIBLE	1990
+# else
+#  define __POSIX_VISIBLE	199009
+#  define __ISO_C_VISIBLE	1990
+# endif
+#elif defined(_POSIX_SOURCE)
+# define __POSIX_VISIBLE	198808
+#  define __ISO_C_VISIBLE	0
+#endif
+
+/*
+ * _ANSI_SOURCE means to expose ANSI C89 interfaces only.
+ * If the user defines it in addition to one of the POSIX or XOPEN
+ * macros, assume the POSIX/XOPEN macro(s) should take precedence.
+ */
+#if defined(_ANSI_SOURCE) && !defined(__POSIX_VISIBLE) && \
+    !defined(__XPG_VISIBLE)
+# define __POSIX_VISIBLE	0
+# define __XPG_VISIBLE		0
+# define __ISO_C_VISIBLE	1990
+#endif
+
+/*
+ * _ISOC99_SOURCE and __STDC_VERSION__ override any of the other macros since
+ * they are non-exclusive.
+ */
+#if defined(_ISOC99_SOURCE) || \
+    (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901) || \
+    (defined(__cplusplus) && __cplusplus >= 201103)
+# undef __ISO_C_VISIBLE
+# define __ISO_C_VISIBLE	1999
+#endif
+
+/*
+ * Finally deal with BSD-specific interfaces that are not covered
+ * by any standards.  We expose these when none of the POSIX or XPG
+ * macros is defined or if the user explicitly asks for them.
+ */
+#if !defined(_BSD_SOURCE) && \
+   (defined(_ANSI_SOURCE) || defined(__XPG_VISIBLE) || defined(__POSIX_VISIBLE))
+# define __BSD_VISIBLE		0
+#endif
+
+/*
+ * Default values.
+ */
+#ifndef __XPG_VISIBLE
+# define __XPG_VISIBLE		700
+#endif
+#ifndef __POSIX_VISIBLE
+# define __POSIX_VISIBLE	200809
+#endif
+#ifndef __ISO_C_VISIBLE
+# define __ISO_C_VISIBLE	1999
+#endif
+#ifndef __BSD_VISIBLE
+# define __BSD_VISIBLE		1
+#endif
+
+#endif /* !_SYS_CDEFS_H_ */
diff --git a/telldus-core/3rdparty/openbsd-getopt/sys/types.h b/telldus-core/3rdparty/openbsd-getopt/sys/types.h
new file mode 100644
index 00000000..c2ebbb10
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/sys/types.h
@@ -0,0 +1,243 @@
+/*	$OpenBSD: types.h,v 1.32 2011/03/19 18:26:06 deraadt Exp $	*/
+/*	$NetBSD: types.h,v 1.29 1996/11/15 22:48:25 jtc Exp $	*/
+
+/*-
+ * Copyright (c) 1982, 1986, 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)types.h	8.4 (Berkeley) 1/21/94
+ */
+
+#ifndef _SYS_TYPES_H_
+#define	_SYS_TYPES_H_
+
+#include 
+#include 
+#include 
+
+#if __BSD_VISIBLE
+typedef	unsigned char	u_char;
+typedef	unsigned short	u_short;
+typedef	unsigned int	u_int;
+typedef	unsigned long	u_long;
+
+typedef unsigned char	unchar;		/* Sys V compatibility */
+typedef	unsigned short	ushort;		/* Sys V compatibility */
+typedef	unsigned int	uint;		/* Sys V compatibility */
+typedef unsigned long	ulong;		/* Sys V compatibility */
+
+typedef	__cpuid_t	cpuid_t;	/* CPU id */
+typedef	__register_t	register_t;	/* register-sized type */
+#endif /* __BSD_VISIBLE */
+
+/*
+ * XXX The exact-width bit types should only be exposed if __BSD_VISIBLE
+ *     but the rest of the includes are not ready for that yet.
+ */
+#ifndef	__BIT_TYPES_DEFINED__
+#define	__BIT_TYPES_DEFINED__
+#endif
+
+#ifndef	_INT8_T_DEFINED_
+#define	_INT8_T_DEFINED_
+typedef	__int8_t		int8_t;
+#endif
+
+#ifndef	_UINT8_T_DEFINED_
+#define	_UINT8_T_DEFINED_
+typedef	__uint8_t		uint8_t;
+#endif
+
+#ifndef	_INT16_T_DEFINED_
+#define	_INT16_T_DEFINED_
+typedef	__int16_t		int16_t;
+#endif
+
+#ifndef	_UINT16_T_DEFINED_
+#define	_UINT16_T_DEFINED_
+typedef	__uint16_t		uint16_t;
+#endif
+
+#ifndef	_INT32_T_DEFINED_
+#define	_INT32_T_DEFINED_
+typedef	__int32_t		int32_t;
+#endif
+
+#ifndef	_UINT32_T_DEFINED_
+#define	_UINT32_T_DEFINED_
+typedef	__uint32_t		uint32_t;
+#endif
+
+#ifndef	_INT64_T_DEFINED_
+#define	_INT64_T_DEFINED_
+typedef	__int64_t		int64_t;
+#endif
+
+#ifndef	_UINT64_T_DEFINED_
+#define	_UINT64_T_DEFINED_
+typedef	__uint64_t		uint64_t;
+#endif
+
+/* BSD-style unsigned bits types */
+typedef	__uint8_t	u_int8_t;
+typedef	__uint16_t	u_int16_t;
+typedef	__uint32_t	u_int32_t;
+typedef	__uint64_t	u_int64_t;
+
+/* quads, deprecated in favor of 64 bit int types */
+typedef	__int64_t	quad_t;
+typedef	__uint64_t	u_quad_t;
+typedef	quad_t *	qaddr_t;
+
+#if __BSD_VISIBLE
+/* VM system types */
+typedef __vaddr_t	vaddr_t;
+typedef __paddr_t	paddr_t;
+typedef __vsize_t	vsize_t;
+typedef __psize_t	psize_t;
+#endif /* __BSD_VISIBLE */
+
+/* Standard system types */
+typedef	char *		caddr_t;	/* core address */
+typedef	__int32_t	daddr32_t;	/* 32-bit disk address */
+typedef	__int64_t	daddr_t;	/* 64-bit disk address */
+typedef	__int64_t	daddr64_t;	/* 64-bit disk address */
+typedef	__dev_t		dev_t;		/* device number */
+typedef	__fixpt_t	fixpt_t;	/* fixed point number */
+typedef	__gid_t		gid_t;		/* group id */
+typedef	__id_t		id_t;		/* may contain pid, uid or gid */
+typedef	__ino_t		ino_t;		/* inode number */
+typedef	__key_t		key_t;		/* IPC key (for Sys V IPC) */
+typedef	__mode_t	mode_t;		/* permissions */
+typedef	__nlink_t	nlink_t;	/* link count */
+typedef	__pid_t		pid_t;		/* process id */
+typedef __rlim_t	rlim_t;		/* resource limit */
+typedef	__segsz_t	segsz_t;	/* segment size */
+typedef	__swblk_t	swblk_t;	/* swap offset */
+typedef	__uid_t		uid_t;		/* user id */
+typedef	__useconds_t	useconds_t;	/* microseconds */
+typedef	__suseconds_t	suseconds_t;	/* microseconds (signed) */
+typedef	__fsblkcnt_t	fsblkcnt_t;	/* file system block count */
+typedef	__fsfilcnt_t	fsfilcnt_t;	/* file system file count */
+
+/*
+ * XPG4.2 states that inclusion of  must pull these
+ * in and that inclusion of  must pull in sa_family_t.
+ * We put these here because there are other headers that require
+ * these types and  and  will indirectly
+ * include .
+ * XXX - now that we have protected versions these should move.
+ */
+typedef __in_addr_t	in_addr_t;	/* base type for internet address */
+typedef __in_port_t	in_port_t;	/* IP port type */
+typedef __sa_family_t	sa_family_t;	/* sockaddr address family type */
+typedef __socklen_t	socklen_t;	/* length type for network syscalls */
+
+/*
+ * The following types may be defined in multiple header files.
+ */
+#ifndef	_CLOCK_T_DEFINED_
+#define	_CLOCK_T_DEFINED_
+typedef	__clock_t	clock_t;
+#endif
+
+#ifndef	_CLOCKID_T_DEFINED_
+#define	_CLOCKID_T_DEFINED_
+typedef	__clockid_t	clockid_t;
+#endif
+
+#ifndef	_SIZE_T_DEFINED_
+#define	_SIZE_T_DEFINED_
+typedef	__size_t	size_t;
+#endif
+
+#ifndef	_SSIZE_T_DEFINED_
+#define	_SSIZE_T_DEFINED_
+typedef	__ssize_t	ssize_t;
+#endif
+
+#ifndef	_TIME_T_DEFINED_
+#define	_TIME_T_DEFINED_
+typedef	__time_t	time_t;
+#endif
+
+#ifndef	_TIMER_T_DEFINED_
+#define	_TIMER_T_DEFINED_
+typedef	__timer_t	timer_t;
+#endif
+
+#ifndef	_OFF_T_DEFINED_
+#define	_OFF_T_DEFINED_
+typedef	__off_t		off_t;
+#endif
+
+/*
+ * These belong in unistd.h, but are placed here too to ensure that
+ * long arguments will be promoted to off_t if the program fails to
+ * include that header or explicitly cast them to off_t.
+ */
+#if __BSD_VISIBLE && !defined(_KERNEL)
+__BEGIN_DECLS
+off_t	 lseek(int, off_t, int);
+int	 ftruncate(int, off_t);
+int	 truncate(const char *, off_t);
+__END_DECLS
+#endif /* __BSD_VISIBLE && !_KERNEL */
+
+#if __BSD_VISIBLE
+/* Major, minor numbers, dev_t's. */
+#define	major(x)	((int32_t)(((u_int32_t)(x) >> 8) & 0xff))
+#define	minor(x)	((int32_t)((x) & 0xff) | (((x) & 0xffff0000) >> 8))
+#define	makedev(x,y)	((dev_t)((((x) & 0xff) << 8) | ((y) & 0xff) | (((y) & 0xffff00) << 8)))
+#endif
+
+#if __BSD_VISIBLE
+#include 	/* must be after type declarations */
+#endif
+
+#if defined(__STDC__) && defined(_KERNEL)
+/*
+ * Forward structure declarations for function prototypes.  We include the
+ * common structures that cross subsystem boundaries here; others are mostly
+ * used in the same place that the structure is defined.
+ */
+struct	proc;
+struct	pgrp;
+struct	ucred;
+struct	rusage;
+struct	file;
+struct	buf;
+struct	tty;
+struct	uio;
+#endif
+
+#endif /* !_SYS_TYPES_H_ */
diff --git a/telldus-core/3rdparty/openbsd-getopt/sys/unistd.h b/telldus-core/3rdparty/openbsd-getopt/sys/unistd.h
new file mode 100644
index 00000000..52b8545c
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/sys/unistd.h
@@ -0,0 +1,159 @@
+/*	$OpenBSD: unistd.h,v 1.19 2011/10/15 23:35:29 guenther Exp $	*/
+/*	$NetBSD: unistd.h,v 1.10 1994/06/29 06:46:06 cgd Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)unistd.h	8.2 (Berkeley) 1/7/94
+ */
+
+#ifndef _SYS_UNISTD_H_
+#define	_SYS_UNISTD_H_
+
+#include 
+
+/* compile-time symbolic constants */
+				/* implementation supports job control */
+#define	_POSIX_JOB_CONTROL	1
+				/* saved set-user-ID and set-group-ID */
+#define	_POSIX_SAVED_IDS	1
+
+#define	_POSIX_VERSION		199009L
+#define	_POSIX2_VERSION		199212L
+
+/* execution-time symbolic constants */
+				/* chown requires appropriate privileges */
+#define	_POSIX_CHOWN_RESTRICTED	1
+				/* too-long path components generate errors */
+#define	_POSIX_NO_TRUNC		1
+				/* may disable terminal special characters */
+#define	_POSIX_VDISABLE		(0377)
+				/* file synchronization is available */
+#define	_POSIX_FSYNC		1
+
+/* access function */
+#define	F_OK		0	/* test for existence of file */
+#define	X_OK		0x01	/* test for execute or search permission */
+#define	W_OK		0x02	/* test for write permission */
+#define	R_OK		0x04	/* test for read permission */
+
+/* whence values for lseek(2) */
+#define	SEEK_SET	0	/* set file offset to offset */
+#define	SEEK_CUR	1	/* set file offset to current plus offset */
+#define	SEEK_END	2	/* set file offset to EOF plus offset */
+
+#if __BSD_VISIBLE
+/* old BSD whence values for lseek(2); renamed by POSIX 1003.1 */
+#define	L_SET		SEEK_SET
+#define	L_INCR		SEEK_CUR
+#define	L_XTND		SEEK_END
+
+/* the parameters argument passed to the __tfork() syscall */
+struct __tfork {
+	void	*tf_tcb;
+	pid_t	*tf_tid;
+	int	tf_flags;
+};
+#endif
+
+/* configurable pathname variables */
+#define	_PC_LINK_MAX		 1
+#define	_PC_MAX_CANON		 2
+#define	_PC_MAX_INPUT		 3
+#define	_PC_NAME_MAX		 4
+#define	_PC_PATH_MAX		 5
+#define	_PC_PIPE_BUF		 6
+#define	_PC_CHOWN_RESTRICTED	 7
+#define	_PC_NO_TRUNC		 8
+#define	_PC_VDISABLE		 9
+
+/* configurable system variables */
+#define	_SC_ARG_MAX		 1
+#define	_SC_CHILD_MAX		 2
+#define	_SC_CLK_TCK		 3
+#define	_SC_NGROUPS_MAX		 4
+#define	_SC_OPEN_MAX		 5
+#define	_SC_JOB_CONTROL		 6
+#define	_SC_SAVED_IDS		 7
+#define	_SC_VERSION		 8
+#define	_SC_BC_BASE_MAX		 9
+#define	_SC_BC_DIM_MAX		10
+#define	_SC_BC_SCALE_MAX	11
+#define	_SC_BC_STRING_MAX	12
+#define	_SC_COLL_WEIGHTS_MAX	13
+#define	_SC_EXPR_NEST_MAX	14
+#define	_SC_LINE_MAX		15
+#define	_SC_RE_DUP_MAX		16
+#define	_SC_2_VERSION		17
+#define	_SC_2_C_BIND		18
+#define	_SC_2_C_DEV		19
+#define	_SC_2_CHAR_TERM		20
+#define	_SC_2_FORT_DEV		21
+#define	_SC_2_FORT_RUN		22
+#define	_SC_2_LOCALEDEF		23
+#define	_SC_2_SW_DEV		24
+#define	_SC_2_UPE		25
+#define	_SC_STREAM_MAX		26
+#define	_SC_TZNAME_MAX		27
+#define	_SC_PAGESIZE		28
+#define	_SC_PAGE_SIZE		_SC_PAGESIZE	/* 1170 compatibility */
+#define	_SC_FSYNC		29
+#define	_SC_XOPEN_SHM		30
+#define	_SC_SEM_NSEMS_MAX	31
+#define	_SC_SEM_VALUE_MAX	32
+#define	_SC_HOST_NAME_MAX	33
+
+/* P1003.1c */
+#define _SC_GETGR_R_SIZE_MAX	100
+#define _SC_GETPW_R_SIZE_MAX	101
+#define _SC_LOGIN_NAME_MAX	102
+#define _SC_THREAD_SAFE_FUNCTIONS 103
+#ifdef notyet
+#define _SC_THREAD_DESTRUCTOR_ITERATIONS
+#define _SC_THREAD_KEYS_MAX
+#define _SC_THREAD_STACK_MIN
+#define _SC_THREAD_THREADS_MAX
+#define _SC_TTY_NAME_MAX
+#define _SC_THREADS
+#define _SC_THREAD_ATTR_STACKADDR
+#define _SC_THREAD_ATTR_STACKSIZE
+#define _SC_THREAD_PRIORITY_SCHEDULING
+#define _SC_THREAD_PRIO_INHERIT
+#define _SC_THREAD_PRIO_PROTECT
+#define _SC_THREAD_PROCESS_SHARED
+#endif
+
+#define	_SC_PHYS_PAGES		500
+#define	_SC_AVPHYS_PAGES	501
+#define	_SC_NPROCESSORS_CONF	502
+#define	_SC_NPROCESSORS_ONLN	503
+
+/* configurable system strings */
+#define	_CS_PATH		 1
+
+#endif /* !_SYS_UNISTD_H_ */
diff --git a/telldus-core/3rdparty/openbsd-getopt/unistd.h b/telldus-core/3rdparty/openbsd-getopt/unistd.h
new file mode 100644
index 00000000..51116fdc
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/unistd.h
@@ -0,0 +1,274 @@
+/*	$OpenBSD: unistd.h,v 1.67 2012/01/13 13:16:44 nigel Exp $ */
+/*	$NetBSD: unistd.h,v 1.26.4.1 1996/05/28 02:31:51 mrg Exp $	*/
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)unistd.h	5.13 (Berkeley) 6/17/91
+ */
+
+#ifndef _UNISTD_H_
+#define	_UNISTD_H_
+
+#include 
+#include 
+#include 
+
+#define	STDIN_FILENO	0	/* standard input file descriptor */
+#define	STDOUT_FILENO	1	/* standard output file descriptor */
+#define	STDERR_FILENO	2	/* standard error file descriptor */
+
+#if __XPG_VISIBLE || __POSIX_VISIBLE >= 200112
+#define F_ULOCK         0	/* unlock locked section */
+#define F_LOCK          1	/* lock a section for exclusive use */
+#define F_TLOCK         2	/* test and lock a section for exclusive use */
+#define F_TEST          3	/* test a section for locks by other procs */
+#endif
+
+#if __POSIX_VISIBLE
+#define _POSIX_REENTRANT_FUNCTIONS	1
+#define _POSIX_THREAD_SAFE_FUNCTIONS	200112L
+#endif
+
+#ifndef NULL
+#ifdef 	__GNUG__
+#define	NULL	__null
+#elif defined(__cplusplus)
+#define	NULL	0L
+#else
+#define	NULL	((void *)0)
+#endif
+#endif
+
+__BEGIN_DECLS
+__dead void	 _exit(int);
+int	 access(const char *, int);
+unsigned int alarm(unsigned int);
+int	 chdir(const char *);
+int	 chown(const char *, uid_t, gid_t);
+int	 close(int);
+int	 dup(int);
+int	 dup2(int, int);
+int	 execl(const char *, const char *, ...) 
+	    __attribute__((sentinel));
+int	 execle(const char *, const char *, ...);
+int	 execlp(const char *, const char *, ...) 
+	    __attribute__((sentinel));
+int	 execv(const char *, char * const *);
+int	 execve(const char *, char * const *, char * const *);
+int	 execvp(const char *, char * const *);
+pid_t	 fork(void);
+long	 fpathconf(int, int);
+char	*getcwd(char *, size_t)
+		__attribute__((__bounded__(__string__,1,2)));
+gid_t	 getegid(void);
+uid_t	 geteuid(void);
+gid_t	 getgid(void);
+int	 getgroups(int, gid_t *);
+char	*getlogin(void);
+pid_t	 getpgrp(void);
+pid_t	 getpid(void);
+pid_t	 getppid(void);
+uid_t	 getuid(void);
+int	 isatty(int);
+int	 link(const char *, const char *);
+off_t	 lseek(int, off_t, int);
+long	 pathconf(const char *, int);
+int	 pause(void);
+int	 pipe(int *);
+ssize_t	 read(int, void *, size_t)
+		__attribute__((__bounded__(__buffer__,2,3)));
+int	 rmdir(const char *);
+int	 setgid(gid_t);
+int	 setuid(uid_t);
+unsigned int sleep(unsigned int);
+long	 sysconf(int);
+pid_t	 tcgetpgrp(int);
+int	 tcsetpgrp(int, pid_t);
+char	*ttyname(int);
+int	 unlink(const char *);
+ssize_t	 write(int, const void *, size_t)
+		__attribute__((__bounded__(__buffer__,2,3)));
+
+#if __POSIX_VISIBLE || __XPG_VISIBLE >= 300
+pid_t	 setsid(void);
+int	 setpgid(pid_t, pid_t);
+#endif
+
+#if __POSIX_VISIBLE >= 199209 || __XPG_VISIBLE
+size_t	 confstr(int, char *, size_t)
+		__attribute__((__bounded__(__string__,2,3)));
+#ifndef _GETOPT_DEFINED_
+#define _GETOPT_DEFINED_
+int	 getopt(int, char * const *, const char *);
+extern	 char *optarg;			/* getopt(3) external variables */
+extern	 int opterr, optind, optopt, optreset;
+/* XXX - getsubopt does not belong here */
+int	 getsubopt(char **, char * const *, char **);
+extern	 char *suboptarg;		/* getsubopt(3) external variable */
+#endif /* _GETOPT_DEFINED_ */
+#endif
+
+#if __POSIX_VISIBLE >= 199506 || __XPG_VISIBLE
+int	 fsync(int);
+int	 ftruncate(int, off_t);
+int	 getlogin_r(char *, size_t)
+		__attribute__((__bounded__(__string__,1,2)));
+#endif
+
+#if __XPG_VISIBLE || __BSD_VISIBLE
+char	*crypt(const char *, const char *);
+int	 encrypt(char *, int);
+int	 fchdir(int);
+int	 fchown(int, uid_t, gid_t);
+long	 gethostid(void);
+char	*getwd(char *)
+		__attribute__ ((__bounded__(__minbytes__,1,1024)));
+int	 lchown(const char *, uid_t, gid_t);
+int	 mkstemp(char *);
+char	*mktemp(char *);
+int	 nice(int);
+int	 readlink(const char *, char *, size_t)
+		__attribute__ ((__bounded__(__string__,2,3)));
+int	 setkey(const char *);
+int	 setpgrp(pid_t pid, pid_t pgrp);	/* obsoleted by setpgid() */
+int	 setregid(gid_t, gid_t);
+int	 setreuid(uid_t, uid_t);
+void	 swab(const void *, void *, size_t);
+void	 sync(void);
+int	 truncate(const char *, off_t);
+unsigned int	 ualarm(unsigned int, unsigned int);
+int	 usleep(useconds_t);
+pid_t	 vfork(void);
+#endif
+
+#if __XPG_VISIBLE >= 420
+pid_t	 getpgid(pid_t);
+pid_t	 getsid(pid_t);
+#endif
+
+#if __XPG_VISIBLE >= 500
+ssize_t  pread(int, void *, size_t, off_t);
+ssize_t  pwrite(int, const void *, size_t, off_t);
+int	 ttyname_r(int, char *, size_t)
+	    __attribute__((__bounded__(__string__,2,3)));
+#endif
+
+#if __BSD_VISIBLE ||  __XPG_VISIBLE <= 500
+/* Interfaces withdrawn by X/Open Issue 5 Version 0 */
+int	 brk(void *);
+int	 chroot(const char *);
+int	 getdtablesize(void);
+int	 getpagesize(void);
+char	*getpass(const char *);
+void	*sbrk(int);
+#endif
+
+#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 420
+int     lockf(int, int, off_t);
+#endif
+
+#if __POSIX_VISIBLE >= 200112 || __XPG_VISIBLE >= 420 || __BSD_VISIBLE
+int	 symlink(const char *, const char *);
+int	 gethostname(char *, size_t)
+		__attribute__ ((__bounded__(__string__,1,2)));
+int	 setegid(gid_t);
+int	 seteuid(uid_t);
+#endif
+
+#if __POSIX_VISIBLE >= 200809
+int	faccessat(int, const char *, int, int);
+int	fchownat(int, const char *, uid_t, gid_t, int);
+int	linkat(int, const char *, int, const char *, int);
+ssize_t	readlinkat(int, const char *, char *, size_t);
+int	symlinkat(const char *, int, const char *);
+int	unlinkat(int, const char *, int);
+#endif
+
+#if __BSD_VISIBLE
+int	 acct(const char *);
+int	 closefrom(int);
+int	 des_cipher(const char *, char *, int32_t, int);
+int	 des_setkey(const char *);
+void	 endusershell(void);
+int	 exect(const char *, char * const *, char * const *);
+char	*fflagstostr(u_int32_t);
+int	 getdomainname(char *, size_t)
+		__attribute__ ((__bounded__(__string__,1,2)));
+int	 getgrouplist(const char *, gid_t, gid_t *, int *);
+mode_t	 getmode(const void *, mode_t);
+int	 getresgid(gid_t *, gid_t *, gid_t *);
+int	 getresuid(uid_t *, uid_t *, uid_t *);
+char	*getusershell(void);
+int	 initgroups(const char *, gid_t);
+int	 iruserok(u_int32_t, int, const char *, const char *);
+int	 iruserok_sa(const void *, int, int, const char *, const char *);
+int	 issetugid(void);
+char	*mkdtemp(char *);
+int	 mkstemps(char *, int);
+int	 nfssvc(int, void *);
+int	 profil(char *, size_t, unsigned long, unsigned int)
+		__attribute__ ((__bounded__(__string__,1,2)));
+int	 quotactl(const char *, int, int, char *);
+int	 rcmd(char **, int, const char *,
+	    const char *, const char *, int *);
+int	 rcmd_af(char **, int, const char *,
+	    const char *, const char *, int *, int);
+int	 rcmdsh(char **, int, const char *,
+	    const char *, const char *, char *);
+char	*re_comp(const char *);
+int	 re_exec(const char *);
+int	 reboot(int);
+int	 revoke(const char *);
+int	 rfork(int opts);
+int	 rresvport(int *);
+int	 rresvport_af(int *, int);
+int	 ruserok(const char *, int, const char *, const char *);
+#ifndef _SELECT_DEFINED_
+#define _SELECT_DEFINED_
+struct timeval;
+int	 select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+#endif
+int	 setdomainname(const char *, size_t);
+int	 setgroups(int, const gid_t *);
+int	 sethostid(long);
+int	 sethostname(const char *, size_t);
+int	 setlogin(const char *);
+void	*setmode(const char *);
+int	 setresgid(gid_t, gid_t, gid_t);
+int	 setresuid(uid_t, uid_t, uid_t);
+int	 setrgid(gid_t);
+int	 setruid(uid_t);
+void	 setusershell(void);
+int	 strtofflags(char **, u_int32_t *, u_int32_t *);
+int	 swapctl(int cmd, const void *arg, int misc);
+int	 syscall(int, ...);
+#endif /* __BSD_VISIBLE */
+__END_DECLS
+
+#endif /* !_UNISTD_H_ */

From d78d37a597e0248f4d29a9cbbc6de8b6816f762a Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:27:59 +0100
Subject: [PATCH 1821/2215] Add my support header for letting getopt build on
 Windows

---
 .../3rdparty/openbsd-getopt/machine/_types.h         | 10 ++++++++++
 telldus-core/3rdparty/openbsd-getopt/machine/cdefs.h | 12 ++++++++++++
 .../3rdparty/openbsd-getopt/machine/endian.h         |  0
 3 files changed, 22 insertions(+)
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/machine/_types.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/machine/cdefs.h
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/machine/endian.h

diff --git a/telldus-core/3rdparty/openbsd-getopt/machine/_types.h b/telldus-core/3rdparty/openbsd-getopt/machine/_types.h
new file mode 100644
index 00000000..3799f02b
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/machine/_types.h
@@ -0,0 +1,10 @@
+#include 
+
+typedef __int8 __int8_t;
+typedef unsigned __int8 __uint8_t;
+typedef __int16 __int16_t;
+typedef unsigned __int16 __uint16_t;
+typedef __int32 __int32_t;
+typedef unsigned __int32 __uint32_t;
+typedef __int64 __int64_t;
+typedef unsigned __int64 __uint64_t;
diff --git a/telldus-core/3rdparty/openbsd-getopt/machine/cdefs.h b/telldus-core/3rdparty/openbsd-getopt/machine/cdefs.h
new file mode 100644
index 00000000..72946254
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/machine/cdefs.h
@@ -0,0 +1,12 @@
+#include 
+
+#define _ANSI_SOURCE 1
+#define NO_ANSI_KEYWORDS 1
+
+#define _CLOCK_T_DEFINED_
+#define _CLOCKID_T_DEFINED_
+#define _SIZE_T_DEFINED_
+#define _SSIZE_T_DEFINED_
+#define _TIME_T_DEFINED_
+#define _TIMER_T_DEFINED_
+#define _OFF_T_DEFINED_
diff --git a/telldus-core/3rdparty/openbsd-getopt/machine/endian.h b/telldus-core/3rdparty/openbsd-getopt/machine/endian.h
new file mode 100644
index 00000000..e69de29b

From b7bc0715571aa50ce515bf30d0ccf4a8830b1a6d Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:33:02 +0100
Subject: [PATCH 1822/2215] Don't redefine pseudo-ANSI C keywords on Windows

---
 telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h b/telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h
index b9ad10d0..65c06d8e 100644
--- a/telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h
+++ b/telldus-core/3rdparty/openbsd-getopt/sys/cdefs.h
@@ -86,7 +86,9 @@
 #define	__CONCAT(x,y)	x/**/y
 #define	__STRING(x)	"x"
 
-#if !defined(__GNUC__) && !defined(lint)
+#if defined(_MSC_VER)
+#include 
+#elif !defined(__GNUC__) && !defined(lint)
 #define	__const				/* delete pseudo-ANSI C keywords */
 #define	__inline
 #define	__signed

From 0427ff6de99270baa4972803601aac8c2b6d702f Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:35:28 +0100
Subject: [PATCH 1823/2215] These functions seems to conflict with Windows of
 some reason. We don't need them anyway

---
 telldus-core/3rdparty/openbsd-getopt/unistd.h | 46 +++++++++----------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/telldus-core/3rdparty/openbsd-getopt/unistd.h b/telldus-core/3rdparty/openbsd-getopt/unistd.h
index 51116fdc..b013d3ec 100644
--- a/telldus-core/3rdparty/openbsd-getopt/unistd.h
+++ b/telldus-core/3rdparty/openbsd-getopt/unistd.h
@@ -66,22 +66,22 @@
 #endif
 
 __BEGIN_DECLS
-__dead void	 _exit(int);
-int	 access(const char *, int);
+//__dead void	 _exit(int);
+//int	 access(const char *, int);
 unsigned int alarm(unsigned int);
-int	 chdir(const char *);
-int	 chown(const char *, uid_t, gid_t);
+//int	 chdir(const char *);
+//int	 chown(const char *, uid_t, gid_t);
 int	 close(int);
 int	 dup(int);
 int	 dup2(int, int);
-int	 execl(const char *, const char *, ...) 
-	    __attribute__((sentinel));
-int	 execle(const char *, const char *, ...);
-int	 execlp(const char *, const char *, ...) 
-	    __attribute__((sentinel));
-int	 execv(const char *, char * const *);
-int	 execve(const char *, char * const *, char * const *);
-int	 execvp(const char *, char * const *);
+//int	 execl(const char *, const char *, ...)
+//	    __attribute__((sentinel));
+//int	 execle(const char *, const char *, ...);
+//int	 execlp(const char *, const char *, ...)
+//	    __attribute__((sentinel));
+//int	 execv(const char *, char * const *);
+//int	 execve(const char *, char * const *, char * const *);
+//int	 execvp(const char *, char * const *);
 pid_t	 fork(void);
 long	 fpathconf(int, int);
 char	*getcwd(char *, size_t)
@@ -96,14 +96,14 @@ pid_t	 getpid(void);
 pid_t	 getppid(void);
 uid_t	 getuid(void);
 int	 isatty(int);
-int	 link(const char *, const char *);
-off_t	 lseek(int, off_t, int);
-long	 pathconf(const char *, int);
+//int	 link(const char *, const char *);
+//off_t	 lseek(int, off_t, int);
+//long	 pathconf(const char *, int);
 int	 pause(void);
 int	 pipe(int *);
-ssize_t	 read(int, void *, size_t)
-		__attribute__((__bounded__(__buffer__,2,3)));
-int	 rmdir(const char *);
+//ssize_t	 read(int, void *, size_t)
+//		__attribute__((__bounded__(__buffer__,2,3)));
+//int	 rmdir(const char *);
 int	 setgid(gid_t);
 int	 setuid(uid_t);
 unsigned int sleep(unsigned int);
@@ -111,9 +111,9 @@ long	 sysconf(int);
 pid_t	 tcgetpgrp(int);
 int	 tcsetpgrp(int, pid_t);
 char	*ttyname(int);
-int	 unlink(const char *);
-ssize_t	 write(int, const void *, size_t)
-		__attribute__((__bounded__(__buffer__,2,3)));
+//int	 unlink(const char *);
+//ssize_t	 write(int, const void *, size_t)
+//		__attribute__((__bounded__(__buffer__,2,3)));
 
 #if __POSIX_VISIBLE || __XPG_VISIBLE >= 300
 pid_t	 setsid(void);
@@ -182,10 +182,10 @@ int	 ttyname_r(int, char *, size_t)
 #if __BSD_VISIBLE ||  __XPG_VISIBLE <= 500
 /* Interfaces withdrawn by X/Open Issue 5 Version 0 */
 int	 brk(void *);
-int	 chroot(const char *);
+//int	 chroot(const char *);
 int	 getdtablesize(void);
 int	 getpagesize(void);
-char	*getpass(const char *);
+//char	*getpass(const char *);
 void	*sbrk(int);
 #endif
 

From 49b5292415176d90e4bdb5de8c341ce105064e4b Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:36:49 +0100
Subject: [PATCH 1824/2215] Remove debug code

---
 telldus-core/client/Client.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp
index 94845688..17a038ae 100644
--- a/telldus-core/client/Client.cpp
+++ b/telldus-core/client/Client.cpp
@@ -299,26 +299,22 @@ std::wstring Client::sendToService(const Message &msg) {
 		Socket s;
 		s.connect(L"TelldusClient");
 		if (!s.isConnected()) { //Connection failed
-			printf("Connection failed\n\r");
 			msleep(500);
 			continue; //retry
 		}
 		s.write(msg.data());
 		if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later)
-			printf("Connection failed after write\n\r");
 			msleep(500);
 			continue; //retry
 		}
 		readData = s.read(8000);  //TODO changed to 10000 from 5000, how much does this do...?
 		if(readData == L""){
-			printf("Readdata nothing\n\r");
 			msleep(500);
 			continue; //TODO can we be really sure it SHOULD be anything?
 			//TODO perhaps break here instead?
 		}
 		
 		if (!s.isConnected()) { //Connection failed sometime during operation...
-			printf("Connection failed in the end\n\r");
 			msleep(500);
 			continue; //retry
 		}

From 3d7f600dd983fbf37b994db81c5b23ec40c2a223 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:37:25 +0100
Subject: [PATCH 1825/2215] Add CMakeLists.txt for building getopt

---
 .../3rdparty/openbsd-getopt/CMakeLists.txt         | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 telldus-core/3rdparty/openbsd-getopt/CMakeLists.txt

diff --git a/telldus-core/3rdparty/openbsd-getopt/CMakeLists.txt b/telldus-core/3rdparty/openbsd-getopt/CMakeLists.txt
new file mode 100644
index 00000000..89080c41
--- /dev/null
+++ b/telldus-core/3rdparty/openbsd-getopt/CMakeLists.txt
@@ -0,0 +1,14 @@
+SET( SRCS
+	getopt_long.c
+)
+
+SET( HDRS
+	getopt.h
+)
+
+INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} )
+
+ADD_LIBRARY(openbsd-getopt STATIC
+	${SRCS}
+	${HDRS}
+)

From eac97c36841b0fcf85531c8fa45bf65e487a53ee Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:43:45 +0100
Subject: [PATCH 1826/2215] Add openbsd-getopt to tdtool on Windows

---
 telldus-core/CMakeLists.txt        | 3 +++
 telldus-core/tdtool/CMakeLists.txt | 7 +++++--
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt
index a7836523..7c521f52 100644
--- a/telldus-core/CMakeLists.txt
+++ b/telldus-core/CMakeLists.txt
@@ -52,6 +52,9 @@ ADD_SUBDIRECTORY(service)
 ADD_SUBDIRECTORY(client)
 
 IF(BUILD_TDTOOL)
+	IF(WIN32)
+		ADD_SUBDIRECTORY(3rdparty/openbsd-getopt)
+	ENDIF()
 	ADD_SUBDIRECTORY(tdtool)
 ENDIF(BUILD_TDTOOL)
 IF(BUILD_TDADMIN)
diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt
index c94f703f..2bf324a4 100644
--- a/telldus-core/tdtool/CMakeLists.txt
+++ b/telldus-core/tdtool/CMakeLists.txt
@@ -22,9 +22,12 @@ INCLUDE_DIRECTORIES(
 ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" )
 
 IF (WIN32)
-	FIND_LIBRARY(TELLDUSCORE_LIBRARY TelldusCore)
 	TARGET_LINK_LIBRARIES(tdtool
-		${TELLDUSCORE_LIBRARY}
+		TelldusCore
+		openbsd-getopt
+	)
+	INCLUDE_DIRECTORIES(
+		${CMAKE_SOURCE_DIR}/3rdparty/openbsd-getopt
 	)
 ELSEIF (APPLE)
 	TARGET_LINK_LIBRARIES(tdtool

From 5807bceda82aea3cdd70692843fdbf6d5ccc5bb5 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:45:25 +0100
Subject: [PATCH 1827/2215] The function strcasecmp is named _stricmp on
 Windows

---
 telldus-core/tdtool/main.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp
index 8304d443..5f31a902 100644
--- a/telldus-core/tdtool/main.cpp
+++ b/telldus-core/tdtool/main.cpp
@@ -5,6 +5,10 @@
 #include 
 #include "../client/telldus-core.h"
 
+#ifdef _WINDOWS
+#define strcasecmp _stricmp
+#endif
+
 const int SUPPORTED_METHODS =
 	TELLSTICK_TURNON |
 	TELLSTICK_TURNOFF |

From 8d9679bf77b44c1d604ac42aae04f97edd3bb6b6 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:46:06 +0100
Subject: [PATCH 1828/2215] The size of the array must be a constant on Windows

---
 telldus-core/tdtool/main.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp
index 5f31a902..50863453 100644
--- a/telldus-core/tdtool/main.cpp
+++ b/telldus-core/tdtool/main.cpp
@@ -15,6 +15,8 @@ const int SUPPORTED_METHODS =
 	TELLSTICK_BELL |
 	TELLSTICK_DIM;
 
+const int DATA_LENGTH = 20;
+
 void print_usage( char *name ) {
 	printf("Usage: %s [ options ]\n", name);
 	printf("\n");
@@ -123,7 +125,6 @@ int list_devices() {
 		i++;
 	}
 
-	int DATA_LENGTH = 20;
 	char protocol[DATA_LENGTH], model[DATA_LENGTH];
 	int sensorId = 0, dataTypes = 0;
 

From 982c470387bebc481a60229d18578a7df6590910 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:47:46 +0100
Subject: [PATCH 1829/2215] Since tdtool now builds on Windows it can be
 included by default. This closes #89

---
 telldus-core/CMakeLists.txt | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt
index 7c521f52..e01671d5 100644
--- a/telldus-core/CMakeLists.txt
+++ b/telldus-core/CMakeLists.txt
@@ -27,13 +27,10 @@ ENDIF(PACKAGE_SUBVERSION)
 SET(BUILD_LIBTELLDUS-CORE	TRUE	CACHE BOOL "Build libtelldus-core")
 
 IF (WIN32)
-	SET(TDTOOL_DEFAULT FALSE)
 	SET(TDADMIN_DEFAULT FALSE)
 ELSEIF(APPLE)
-	SET(TDTOOL_DEFAULT TRUE)
 	SET(TDADMIN_DEFAULT FALSE)
 ELSE (WIN32)
-	SET(TDTOOL_DEFAULT TRUE)
 	SET(TDADMIN_DEFAULT TRUE)
 ENDIF (WIN32)
 
@@ -42,7 +39,7 @@ IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
 	LINK_DIRECTORIES(/usr/local/lib)
 ENDIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
 
-SET(BUILD_TDTOOL	${TDTOOL_DEFAULT}	CACHE BOOL "Build tdtool")
+SET(BUILD_TDTOOL	TRUE				CACHE BOOL "Build tdtool")
 SET(BUILD_TDADMIN	${TDADMIN_DEFAULT}	CACHE BOOL "Build tdadmin")
 
 SET(GENERATE_MAN	FALSE	CACHE	BOOL "Enable generation of man-files")

From 6a9a390eb7427cb8f78abc58de50f75945a37e2a Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 11:54:37 +0100
Subject: [PATCH 1830/2215] Remove extra empty row

---
 telldus-core/tdtool/main.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp
index 50863453..be876d55 100644
--- a/telldus-core/tdtool/main.cpp
+++ b/telldus-core/tdtool/main.cpp
@@ -154,8 +154,6 @@ int list_devices() {
 			strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp));
 		}
 		printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf);
-
-		printf("\n");
 	}
 	if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){
 		char *errorString = tdGetErrorString(sensorStatus);

From 4f181a05ce4383ed2c883266d465e9a2b6c9646d Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 12:01:36 +0100
Subject: [PATCH 1831/2215] Sign tdtool

---
 telldus-core/tdtool/CMakeLists.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt
index 2bf324a4..d9016d34 100644
--- a/telldus-core/tdtool/CMakeLists.txt
+++ b/telldus-core/tdtool/CMakeLists.txt
@@ -13,6 +13,7 @@ SET(tdtool_SRCS
 ADD_EXECUTABLE(tdtool
 	${tdtool_SRCS}
 )
+SIGN(tdtool)
 
 INCLUDE_DIRECTORIES(
 	${CMAKE_CURRENT_BINARY_DIR}

From 17de443f19090c43397ba890a4c722dcfe510ad6 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Wed, 18 Jan 2012 12:02:21 +0100
Subject: [PATCH 1832/2215] Add missing breaks in select. tdtool showed the
 list of devices on --version

---
 telldus-core/tdtool/main.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp
index be876d55..e5367cad 100644
--- a/telldus-core/tdtool/main.cpp
+++ b/telldus-core/tdtool/main.cpp
@@ -335,9 +335,11 @@ int main(int argc, char **argv)
 			case 'h' :
 				print_usage( argv[0] );
 				success = TELLSTICK_SUCCESS;
+				break;
 			case 'i' :
 				print_version( );
 				success = TELLSTICK_SUCCESS;
+				break;
 			case 'l' :
 				success = list_devices();
 				break;

From 000148a6c8615d240fc00c2b5a19c033547343d5 Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Mon, 14 Nov 2011 13:30:30 +0100
Subject: [PATCH 1833/2215] Rename files to allow easier reorder of chapters in
 doc

---
 docs/{telldus-core.dox => 01-telldus-core.dox}             | 0
 docs/{tellstick-protocol.dox => 02-tellstick-protocol.dox} | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename docs/{telldus-core.dox => 01-telldus-core.dox} (100%)
 rename docs/{tellstick-protocol.dox => 02-tellstick-protocol.dox} (100%)

diff --git a/docs/telldus-core.dox b/docs/01-telldus-core.dox
similarity index 100%
rename from docs/telldus-core.dox
rename to docs/01-telldus-core.dox
diff --git a/docs/tellstick-protocol.dox b/docs/02-tellstick-protocol.dox
similarity index 100%
rename from docs/tellstick-protocol.dox
rename to docs/02-tellstick-protocol.dox

From d2dd46049005328789da236acd642ce5847c102f Mon Sep 17 00:00:00 2001
From: Micke Prag 
Date: Mon, 14 Nov 2011 14:01:34 +0100
Subject: [PATCH 1834/2215] Documentation for TellStick Net auto discovery

---
 docs/03-tellstick-net-protocol.dox | 35 ++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 docs/03-tellstick-net-protocol.dox

diff --git a/docs/03-tellstick-net-protocol.dox b/docs/03-tellstick-net-protocol.dox
new file mode 100644
index 00000000..f4e46b61
--- /dev/null
+++ b/docs/03-tellstick-net-protocol.dox
@@ -0,0 +1,35 @@
+/**
+ * @page TellStickNet TellStick Net protocol
+ *
+ * \section Introduction
+ *
+ * TellStick Net will eventually support local access through the LAN. This is
+ * unsupported by Telldus Technologies but can be useful in some cases. For
+ * instance in mobile devices or when the internet is not available. Using
+ * TellStick Net through Telldus Live! is still the prefered and supported
+ * method.
+ *
+ * This interface is still under development and is not ready for production.
+ *
+ * \section autodiscovery Auto discovery
+ *
+ * The TellStick Net can be auto discovered on the LAN using UDP broadcast.
+ * Sending a package to the broadcast address 255.255.255.255 port 30303 will
+ * be responded by any TellStick Net on the network. The packet should only
+ * contain the single character 'D' (ascii number 68).
+ *
+ * The response from the device will be sent back to the same host and port as
+ * the originated packet. So any dynamically port can be assigned by the host
+ * implementing the auto discovery.
+ * The returning packet is cunstructed in the following way:
+ * product:mac address:activation code:firmware
+ *
+ * Example:
+ * TellStickNet:ABCDEFGHIJKL:ABDCEFGHIJ:2
+ * Product: TellStick Net (TSNET)
+ * Mac address: AB:CD:EF:GH:IJ:KL
+ * Code for activation: ABCDEFGHIJ
+ * Firmware version: 2 + * + * Use the source ip-address to determine the address to the device. + */ From a26244fa951ae39b004b1dcf69685e7c70e9e41a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 23 Jan 2012 10:54:39 +0100 Subject: [PATCH 1835/2215] Typo --- docs/03-tellstick-net-protocol.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/03-tellstick-net-protocol.dox b/docs/03-tellstick-net-protocol.dox index f4e46b61..8023d038 100644 --- a/docs/03-tellstick-net-protocol.dox +++ b/docs/03-tellstick-net-protocol.dox @@ -21,7 +21,7 @@ * The response from the device will be sent back to the same host and port as * the originated packet. So any dynamically port can be assigned by the host * implementing the auto discovery. - * The returning packet is cunstructed in the following way: + * The returning packet is constructed in the following way: * product:mac address:activation code:firmware * * Example:
From fec44a8e77c8c4485b2f8d21ee78b7f77b280884 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 23 Jan 2012 11:12:46 +0100 Subject: [PATCH 1836/2215] Tried to clarify the fallback mechanism used in tdMethods() --- docs/01-telldus-core.dox | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/01-telldus-core.dox b/docs/01-telldus-core.dox index 9185076e..d7df9100 100644 --- a/docs/01-telldus-core.dox +++ b/docs/01-telldus-core.dox @@ -94,8 +94,12 @@ * } * \endcode * - * By supplying the methods the application supports, the library can be backwards - * compatible. Let's say that the client application only supports turning on and + * By supplying the methods your application supports, the library can return + * customized methods for your application, even if your application doesn't + * support the same methods as the device accepts. One example is if your + * application only supports ON and OFF, you can control a device that needs UP + * and DOWN anyway by using just ON and OFF. + * Let's say that the client application only supports turning on and * off. The call to query a device for it's methods should be: * \code * int methods = tdMethods( id, TELLSTICK_TURNON | TELLSTICK_TURNOFF ); From e384c5b677f7dad188b94035fa6972683981783a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 23 Jan 2012 18:07:49 +0100 Subject: [PATCH 1837/2215] When reading the target executable for prerequisites we must include the DESTDIR, else we might read an already installed file --- telldus-core/service/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 4943544f..09a3fe4f 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -221,7 +221,7 @@ IF (APPLE) INSTALL(CODE " INCLUDE(GetPrerequisites) GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) - GET_PREREQUISITES(\"${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" prereqs 1 0 \"\$\" \"\$\") + GET_PREREQUISITES(\"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" prereqs 1 0 \"\$\" \"\$\") FOREACH(pr \${prereqs}) GET_FILENAME_COMPONENT(lib \${pr} NAME) FILE(INSTALL \${pr} DESTINATION ${TELLDUS_SERVICE_TARGET_PATH}) From 31a0b22da96896de48dbdba391a572b8507be307 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 24 Jan 2012 14:34:38 +0100 Subject: [PATCH 1838/2215] Workaround for building targeting Leopard using SnowLeopard SDK. Some symbols in stdlibc is missing --- telldus-core/common/CMakeLists.txt | 1 + telldus-core/common/stdlibc_workaround.cpp | 67 ++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 telldus-core/common/stdlibc_workaround.cpp diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 93f5a8ee..71262738 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -30,6 +30,7 @@ IF (APPLE) ADD_DEFINITIONS( -D_MACOSX ) LIST(APPEND telldus-common_SRCS Socket_unix.cpp + stdlibc_workaround.cpp #Remove this when we drop support for 10.5 ) LIST(APPEND telldus-common_LIBRARIES ${ICONV_LIBRARY} diff --git a/telldus-core/common/stdlibc_workaround.cpp b/telldus-core/common/stdlibc_workaround.cpp new file mode 100644 index 00000000..78aaaa65 --- /dev/null +++ b/telldus-core/common/stdlibc_workaround.cpp @@ -0,0 +1,67 @@ +#include +// Workarounds for symbols that are missing from Leopard stdlibc++.dylib. +_GLIBCXX_BEGIN_NAMESPACE(std) +// From ostream_insert.h +template ostream& __ostream_insert(ostream&, const char*, streamsize); + +#ifdef _GLIBCXX_USE_WCHAR_T + template wostream& __ostream_insert(wostream&, const wchar_t*, streamsize); +#endif + +// From ostream.tcc +template ostream& ostream::_M_insert(long); +template ostream& ostream::_M_insert(unsigned long); +template ostream& ostream::_M_insert(bool); +#ifdef _GLIBCXX_USE_LONG_LONG + template ostream& ostream::_M_insert(long long); + template ostream& ostream::_M_insert(unsigned long long); +#endif +template ostream& ostream::_M_insert(double); +template ostream& ostream::_M_insert(long double); +template ostream& ostream::_M_insert(const void*); + +#ifdef _GLIBCXX_USE_WCHAR_T + template wostream& wostream::_M_insert(long); + template wostream& wostream::_M_insert(unsigned long); + template wostream& wostream::_M_insert(bool); + #ifdef _GLIBCXX_USE_LONG_LONG + template wostream& wostream::_M_insert(long long); + template wostream& wostream::_M_insert(unsigned long long); + #endif + template wostream& wostream::_M_insert(double); + template wostream& wostream::_M_insert(long double); + template wostream& wostream::_M_insert(const void*); +#endif + +// From istream.tcc +template istream& istream::_M_extract(unsigned short&); +template istream& istream::_M_extract(unsigned int&); +template istream& istream::_M_extract(long&); +template istream& istream::_M_extract(unsigned long&); +template istream& istream::_M_extract(bool&); +#ifdef _GLIBCXX_USE_LONG_LONG + template istream& istream::_M_extract(long long&); + template istream& istream::_M_extract(unsigned long long&); +#endif +template istream& istream::_M_extract(float&); +template istream& istream::_M_extract(double&); +template istream& istream::_M_extract(long double&); +template istream& istream::_M_extract(void*&); + +#ifdef _GLIBCXX_USE_WCHAR_T + template wistream& wistream::_M_extract(unsigned short&); + template wistream& wistream::_M_extract(unsigned int&); + template wistream& wistream::_M_extract(long&); + template wistream& wistream::_M_extract(unsigned long&); + template wistream& wistream::_M_extract(bool&); + #ifdef _GLIBCXX_USE_LONG_LONG + template wistream& wistream::_M_extract(long long&); + template wistream& wistream::_M_extract(unsigned long long&); + #endif + template wistream& wistream::_M_extract(float&); + template wistream& wistream::_M_extract(double&); + template wistream& wistream::_M_extract(long double&); + template wistream& wistream::_M_extract(void*&); +#endif + +_GLIBCXX_END_NAMESPACE From 6289a1138e14301ba99e1ffbd7cce53b99dfcf0d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 24 Jan 2012 15:21:13 +0100 Subject: [PATCH 1839/2215] Fixed listing of sensors in tdtool. Closes #164 --- telldus-core/tdtool/main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index e5367cad..ba7b2a44 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -130,11 +130,9 @@ int list_devices() { int sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); if(sensorStatus == 0){ - printf("\nSENSORS:\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED"); + printf("\n\nSENSORS:\n\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED"); } while(sensorStatus == 0){ - sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); - char tempvalue[DATA_LENGTH]; tempvalue[0] = 0; char humidityvalue[DATA_LENGTH]; @@ -154,7 +152,10 @@ int list_devices() { strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); } printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf); + + sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); } + printf("\n"); if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){ char *errorString = tdGetErrorString(sensorStatus); fprintf(stderr, "Error fetching sensors: %s\n", errorString); From 430871bebfb0c08ff4026decffcd011eff4d5b40 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 24 Jan 2012 17:40:55 +0100 Subject: [PATCH 1840/2215] Temperature sign removed from tdtool in windows. Closes #166 --- telldus-core/tdtool/main.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index ba7b2a44..2caa7562 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -7,6 +7,9 @@ #ifdef _WINDOWS #define strcasecmp _stricmp +#define DEGREE " " +#else +#define DEGREE "°" #endif const int SUPPORTED_METHODS = @@ -142,7 +145,7 @@ int list_devices() { if (dataTypes & TELLSTICK_TEMPERATURE) { tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp); - strcat(tempvalue, "°"); + strcat(tempvalue, DEGREE); strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); } From e69f7abba82ffdcb5f6bc755d4eb4f009cbfe0d1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 25 Jan 2012 17:01:44 +0100 Subject: [PATCH 1841/2215] Sensor view now starts up in view mode if no sensors are set to be visible. Closes #168 --- telldus-gui/Plugins/Sensors/__init__.js | 8 ++++++++ telldus-gui/Plugins/Sensors/main.qml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js index b2a36c73..5012dba4 100644 --- a/telldus-gui/Plugins/Sensors/__init__.js +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -36,6 +36,14 @@ com.telldus.sensors = function() { }); view.setProperty('sensorModel', sensorList); + var initialViewMode = 'EDIT'; + for (var i=0; i < sensorList.length; ++i) { + if (sensorList.get(i).showInList || sensorList.get(i).name !== "") { + initialViewMode = 'VIEW'; + break; + } + } + view.setProperty('initialViewMode', initialViewMode); saveSensorModel(); view.load("main.qml"); application.addWidget("sensors.gui", "icon.png", view); diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml index 41ecb0ac..c4710d0a 100644 --- a/telldus-gui/Plugins/Sensors/main.qml +++ b/telldus-gui/Plugins/Sensors/main.qml @@ -3,7 +3,7 @@ import QtDesktop 0.1 Item { id: main - state: "VIEW" + state: initialViewMode ScrollArea { id: scrollArea From c35be687c0ce2285842ccc1521a247b06c284b88 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 25 Jan 2012 17:41:27 +0100 Subject: [PATCH 1842/2215] pid=0 and vid=0 means all. This way we can easily disconnect all controllers or initiate a rescan --- telldus-core/service/ControllerManager.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 6865e450..fc46b350 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -33,6 +33,20 @@ ControllerManager::~ControllerManager() { } void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) { + if (vid == 0x0 && pid == 0x0) { //All + if (inserted) { + loadControllers(); + } else { + //Disconnect all + TelldusCore::MutexLocker locker(&d->mutex); + while(d->controllers.size()) { + ControllerMap::iterator it = d->controllers.begin(); + delete it->second; + d->controllers.erase(it); + } + } + return; + } if (vid != 0x1781) { return; } From 5f1d6e7fe54aba7fe19fecb3800e50322165b5ea Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 25 Jan 2012 17:42:41 +0100 Subject: [PATCH 1843/2215] Listen for suspend/resume signals and disconnect all usb-devices. This closes #171 --- telldus-core/service/TelldusMain.cpp | 18 ++++++++++++++++++ telldus-core/service/TelldusMain.h | 2 ++ telldus-core/service/TelldusWinService_win.cpp | 9 +++++++++ 3 files changed, 29 insertions(+) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 32202c0b..f5f0e188 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -38,6 +38,24 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { d->controllerChangeEvent->signal(data); } +void TelldusMain::resume() { + Log::notice("Came back from suspend"); + ControllerChangeEventData *data = new ControllerChangeEventData; + data->vid = 0x0; + data->pid = 0x0; + data->inserted = true; + d->controllerChangeEvent->signal(data); +} + +void TelldusMain::suspend() { + Log::notice("Preparing for suspend"); + ControllerChangeEventData *data = new ControllerChangeEventData; + data->vid = 0x0; + data->pid = 0x0; + data->inserted = false; + d->controllerChangeEvent->signal(data); +} + void TelldusMain::start(void) { EventRef clientEvent = d->eventHandler.addEvent(); EventRef dataEvent = d->eventHandler.addEvent(); diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index 46d6dbbe..13f19486 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -12,6 +12,8 @@ public: //Thread safe! void deviceInsertedOrRemoved(int vid, int pid, bool inserted); + void resume(); + void suspend(); private: class PrivateData; diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 6a415120..3fb51221 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -40,6 +40,13 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus( serviceStatusHandle, &serviceStatus ); + return NO_ERROR; + case SERVICE_CONTROL_POWEREVENT: + if (dwEventType == PBT_APMSUSPEND) { + tm->suspend(); + } else if (dwEventType == PBT_APMRESUMEAUTOMATIC) { + tm->resume(); + } return NO_ERROR; } return ERROR_CALL_NOT_IMPLEMENTED; @@ -137,6 +144,8 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { // running instance.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + // Register for power management notification + instance.serviceStatus.dwControlsAccepted |= SERVICE_ACCEPT_POWEREVENT; instance.serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); From bf72debefba5c47023afd5993290995c613e4185 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 25 Jan 2012 17:43:16 +0100 Subject: [PATCH 1844/2215] Output when debug mode is enabled --- telldus-core/service/TelldusWinService_win.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 3fb51221..29e41b60 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -123,6 +123,7 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { for(unsigned int i = 1; i < argc; ++i) { if (wcscmp(argv[i], L"--debug") == 0) { Log::setDebug(); + Log::debug("Debug message output enabled"); } } From afa1e88e622132518caeac7195353d46208f9a32 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 26 Jan 2012 14:38:42 +0100 Subject: [PATCH 1845/2215] Changed usage of strol method, so that windows uses _strtoui64 instead. Closes #172, #175 --- telldus-core/common/Strings.cpp | 8 ++++++++ telldus-core/common/Strings.h | 9 +++++++++ telldus-core/service/ProtocolFineoffset.cpp | 15 +++++---------- telldus-core/service/ProtocolMandolyn.cpp | 10 ++-------- telldus-core/service/ProtocolOregon.cpp | 13 ++++--------- 5 files changed, 28 insertions(+), 27 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index fe0b7ca1..c563fa49 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -144,6 +144,14 @@ std::wstring TelldusCore::intToWStringSafe(int value){ } */ +uint64_t TelldusCore::hexTo64l(const std::string data){ +#ifdef _WINDOWS + return _strtoui64(data.c_str(), NULL, 16); +#else + return strtol(data.c_str(), NULL, 16); +#endif +} + int TelldusCore::wideToInteger(const std::wstring &input){ std::wstringstream inputstream; inputstream << input; diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index ad898424..7c5f85ad 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -3,6 +3,14 @@ #include #include +#ifdef _MSC_VER +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif namespace TelldusCore { std::wstring charToWstring(const char *value); @@ -13,6 +21,7 @@ namespace TelldusCore { std::wstring intToWstring(int value); //std::wstring intToWStringSafe(int value); std::string intToString(int value); + uint64_t hexTo64l(const std::string data); std::string wideToString(const std::wstring &input); int wideToInteger(const std::wstring &input); diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index 31d150a0..4ed310d0 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -1,13 +1,8 @@ #include "ProtocolFineoffset.h" +#include "Strings.h" #include #include #include -#ifdef _MSC_VER -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -#else -#include -#endif std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) { @@ -16,13 +11,13 @@ std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) return ""; } - uint8_t checksum = strtol(data.substr(data.length()-2).c_str(), NULL, 16); + uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); data = data.substr(0, data.length()-2); - uint8_t humidity = strtol(data.substr(data.length()-2).c_str(), NULL, 16); + uint8_t humidity = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); data = data.substr(0, data.length()-2); - uint16_t value = strtol(data.substr(data.length()-3).c_str(), NULL, 16); + uint16_t value = (uint16_t)TelldusCore::hexTo64l(data.substr(data.length()-3)); double temperature = (value & 0x7FF)/10.0; value >>= 11; @@ -31,7 +26,7 @@ std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) } data = data.substr(0, data.length()-3); - uint16_t id = strtol(data.c_str(), NULL, 16) & 0xFF; + uint16_t id = (uint16_t)TelldusCore::hexTo64l(data) & 0xFF; std::stringstream retString; retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:"; diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index 420d6bdb..b8f5aae5 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -1,19 +1,13 @@ #include "ProtocolMandolyn.h" +#include "Strings.h" #include #include #include -#ifdef _MSC_VER -typedef unsigned __int8 uint8_t; -typedef unsigned __int32 uint32_t; -#else -#include -#endif - std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); - uint32_t value = strtol(data.c_str(), NULL, 16); + uint32_t value = (uint32_t)TelldusCore::hexTo64l(data); bool parity = value & 0x1; value >>= 1; diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 704ebeeb..c5847952 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -1,13 +1,8 @@ #include "ProtocolOregon.h" +#include "Strings.h" #include #include #include -#ifdef _MSC_VER -typedef unsigned __int8 uint8_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) { @@ -24,8 +19,8 @@ std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) } std::string ProtocolOregon::decodeEA4C(const std::string &data) { - uint64_t value = strtol(data.c_str(), NULL, 16); - + uint64_t value = TelldusCore::hexTo64l(data); + uint8_t checksum = 0xE + 0xA + 0x4 + 0xC; checksum -= (value & 0xF) * 0x10; checksum -= 0xA; @@ -69,7 +64,7 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { } std::string ProtocolOregon::decode1A2D(const std::string &data) { - uint64_t value = strtol(data.c_str(), NULL, 16); + uint64_t value = TelldusCore::hexTo64l(data); uint8_t checksum2 = value & 0xFF; value >>= 8; uint8_t checksum1 = value & 0xFF; From ee8f3b41d0207f6a981fa9406fbed01fda1a7411 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 26 Jan 2012 11:54:51 +0100 Subject: [PATCH 1846/2215] Print debug message on all platforms activating it, not only Windows --- telldus-core/service/Log.cpp | 1 + telldus-core/service/TelldusWinService_win.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index f555378a..eef21e59 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -110,6 +110,7 @@ void Log::error(const char *fmt, ...) { void Log::setDebug() { Log *log = Log::instance(); log->d->debug = true; + Log::debug("Debug message output enabled"); } void Log::setLogOutput(LogOutput logOutput) { diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 29e41b60..3fb51221 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -123,7 +123,6 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { for(unsigned int i = 1; i < argc; ++i) { if (wcscmp(argv[i], L"--debug") == 0) { Log::setDebug(); - Log::debug("Debug message output enabled"); } } From f1e58433c1686dd570e7a3f79b52d81eb5d39250 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 26 Jan 2012 11:55:15 +0100 Subject: [PATCH 1847/2215] Add --debug option for unix as well --- telldus-core/service/main_unix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index b68d13b7..73cff6d1 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -47,6 +47,8 @@ int main(int argc, char **argv) { if (strcmp(argv[i], "--nodaemon") == 0) { deamonize = false; Log::setLogOutput(Log::StdOut); + } else if (strcmp(argv[i], "--debug") == 0) { + Log::setDebug(); } else if (strcmp(argv[i], "--help") == 0) { printf("Telldus TellStick background service\n\nStart with --nodaemon to not run as daemon\n\n"); printf("Report bugs to \n"); From 1ef4610f524951d17487f534a13072d7ca933899 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 26 Jan 2012 12:42:56 +0100 Subject: [PATCH 1848/2215] Make sure the substration is made using two doubles. Since value is unsigned negative results might overflow otherwise. This closes #177 --- telldus-core/service/ProtocolMandolyn.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index b8f5aae5..0a6ffcfb 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -12,7 +12,7 @@ std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) bool parity = value & 0x1; value >>= 1; - double temp = (value & 0x7FFF) - 6400; + double temp = (double)(value & 0x7FFF) - (double)6400; temp = temp/128.0; value >>= 15; From de745731df7c5974271faccc00ab508c1565a86c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 26 Jan 2012 15:01:23 +0100 Subject: [PATCH 1849/2215] Set the environmental variables from the udev rule makeing sure they exists in all distributions. This closes #115 --- telldus-core/tdadmin/05-tellstick.rules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules index 7a6ae615..24d1c457 100644 --- a/telldus-core/tdadmin/05-tellstick.rules +++ b/telldus-core/tdadmin/05-tellstick.rules @@ -1,3 +1,3 @@ -ATTRS{idVendor}=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" -ENV{ID_VENDOR_ID}=="1781", SUBSYSTEM=="usb", ACTION=="remove" RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ATTRS{idVendor}=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}", ENV{ID_SERIAL_SHORT}="$attr{serial}", RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ENV{ID_VENDOR_ID}=="1781", SUBSYSTEM=="usb", ACTION=="remove", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}", ENV{ID_SERIAL_SHORT}="$attr{serial}", RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" From c6ecc4a1d42d0f5f3246b174ccf59c7af5fe53fe Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 26 Jan 2012 15:13:22 +0100 Subject: [PATCH 1850/2215] Use @VAR@ syntax in the file, else cmake complaints --- telldus-core/tdadmin/05-tellstick.rules | 4 ++-- telldus-core/tdadmin/CMakeLists.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-core/tdadmin/05-tellstick.rules b/telldus-core/tdadmin/05-tellstick.rules index 24d1c457..b450b35f 100644 --- a/telldus-core/tdadmin/05-tellstick.rules +++ b/telldus-core/tdadmin/05-tellstick.rules @@ -1,3 +1,3 @@ -ATTRS{idVendor}=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}", ENV{ID_SERIAL_SHORT}="$attr{serial}", RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" -ENV{ID_VENDOR_ID}=="1781", SUBSYSTEM=="usb", ACTION=="remove", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}", ENV{ID_SERIAL_SHORT}="$attr{serial}", RUN+="${CMAKE_INSTALL_PREFIX}/share/telldus-core/helpers/udev.sh" +ATTRS{idVendor}=="1781", SUBSYSTEM=="usb", ACTION=="add", MODE="664", GROUP="plugdev", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}", ENV{ID_SERIAL_SHORT}="$attr{serial}", RUN+="@CMAKE_INSTALL_PREFIX@/share/telldus-core/helpers/udev.sh" +ENV{ID_VENDOR_ID}=="1781", SUBSYSTEM=="usb", ACTION=="remove", ENV{ID_VENDOR_ID}="$attr{idVendor}", ENV{ID_MODEL_ID}="$attr{idProduct}", ENV{ID_SERIAL_SHORT}="$attr{serial}", RUN+="@CMAKE_INSTALL_PREFIX@/share/telldus-core/helpers/udev.sh" diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt index 8bc06e9f..501baabe 100644 --- a/telldus-core/tdadmin/CMakeLists.txt +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -63,6 +63,7 @@ IF (UNIX AND NOT APPLE) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/05-tellstick.rules ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules + @ONLY ) CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/udev.sh From 4ccb9b3563133f2356f6f0bfbb328aa9d6a9db91 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 26 Jan 2012 17:01:50 +0100 Subject: [PATCH 1851/2215] Fix crash when removing sensor with name textfield selected --- telldus-gui/Plugins/Sensors/SensorView.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml index e383c8b3..2a862999 100644 --- a/telldus-gui/Plugins/Sensors/SensorView.qml +++ b/telldus-gui/Plugins/Sensors/SensorView.qml @@ -53,6 +53,7 @@ Item{ MouseArea{ anchors.fill: parent onClicked: { + main.focus = true confirmDeletion.visible = true; } } From e7a2e9dc768453f01d356d4ecb380c7ed6bf007e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 27 Jan 2012 11:31:32 +0100 Subject: [PATCH 1852/2215] Copy the framworks the plugins depends on, not only rewrite the path --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index daae9f1a..4e29fd33 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -102,6 +102,7 @@ IF(Plugin_SRCS) GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) + GET_FILENAME_COMPONENT(exedir \"\${exe}\" PATH) SET(plugin \"\${bundle}/Contents/Plugins/script/${Plugin_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}\") GET_ITEM_KEY(\"\${plugin}\" pkey) @@ -115,7 +116,10 @@ IF(Plugin_SRCS) #Check to see if this is ourself IF (NOT \${pkey} STREQUAL \${rkey}) SET(kv \"\") - SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exe}\" \"\${bundle}/Contents/Frameworks/\" 0) + SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exedir}\" \"\${bundle}/Contents/Frameworks/\" 1) + IF (NOT EXISTS \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") + COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(\"\${\${kv}_RESOLVED_ITEM}\" \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") + ENDIF () EXECUTE_PROCESS(COMMAND install_name_tool -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${plugin}\" ) From 03f00a0fffd8fbe8b762541f599dbaa323988e32 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 30 Jan 2012 12:53:07 +0100 Subject: [PATCH 1853/2215] Changed graphics on deletebutton, see #165 --- telldus-gui/Plugins/Sensors/CMakeLists.txt | 1 + telldus-gui/Plugins/Sensors/SensorView.qml | 29 +++++++++--------- .../Plugins/Sensors/btn_action_remove.png | Bin 0 -> 1123 bytes 3 files changed, 16 insertions(+), 14 deletions(-) create mode 100644 telldus-gui/Plugins/Sensors/btn_action_remove.png diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt index 45371412..92042b57 100644 --- a/telldus-gui/Plugins/Sensors/CMakeLists.txt +++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt @@ -24,6 +24,7 @@ SET( Plugin_MOC_HDRS SET( Plugin_PATH "com.telldus.sensors" ) SET( Plugin_EXTRA + btn_action_remove.png header_bg.png icon.png icon_humidity.png diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml index 2a862999..a3626bcb 100644 --- a/telldus-gui/Plugins/Sensors/SensorView.qml +++ b/telldus-gui/Plugins/Sensors/SensorView.qml @@ -40,21 +40,22 @@ Item{ placeholderText: 'Enter a name' onTextChanged: modelData.name = text } - - Text{ - anchors.right: sensorid.left - visible: sensorViewItem.state == "EDIT" + Item { height: 40 - verticalAlignment: Text.AlignVCenter - text: "Delete" - font.underline: true - color: "#004275" - width: 50 - MouseArea{ - anchors.fill: parent - onClicked: { - main.focus = true - confirmDeletion.visible = true; + width: deleteImg.width + anchors.right: sensorid.left + anchors.rightMargin: 15 + visible: sensorViewItem.state == "EDIT" + Image { + id: deleteImg + anchors.centerIn: parent + source: "btn_action_remove.png" + MouseArea{ + anchors.fill: parent + onClicked: { + main.focus = true + confirmDeletion.visible = true; + } } } } diff --git a/telldus-gui/Plugins/Sensors/btn_action_remove.png b/telldus-gui/Plugins/Sensors/btn_action_remove.png new file mode 100644 index 0000000000000000000000000000000000000000..d9e5bf753f9b7134bc75ac749fba154f00515554 GIT binary patch literal 1123 zcmV-p1f2VcP)OH3AX z5cDKIfG3ZF_z*dG6Cc2h4*I>W>yKqwKJWMY zn|4VmV1+-NpPPG3K`)BW>BE!KDd(YN3@M3U9gWA2R{H%Xo-4lX?A%^nS$SiIGcZ(B z(Xd*pOt|Mmi2&tC(?_9llWz$j>dwYBDIz@4l%uZOTfH#{H z;OABhfyJ|Bf=Y<~oDw*p#7}^gCP!ON%J&zSmTuWSbNl=IKQ(kOK}6&v{1|j;eSf0= zC6&`hQC*L^-R`PgUpP28{4LCrc@vr6*_06L)Q*K{bV19$wJY-r3yX#0$f78!Aq5~D zgU>(E<|6 z@}O{vg?z+JiIotP$P6xgk-idUk`Vw2;&|!E%%9Gi7j525+yw|A04f!M#GR>faj^(n zLgJ8zj;NSkWhf>Sp)dcF~2YF-Bkr}uHrK>O5A_>DoNL9 z{CW)dEXN>n*$Tm&)y`KnR}|+`;Ak>oOr{}Bl;WU}@!yPFcP-6!)WzA^b16_9Bk?~} zE0%o}cn4Be^Bnccwd<4+?JdPUY{850|Yl&Bh++1y>zB#i!EOt{vOtg>e-M6!zI zJ52M_(DN2eWTbd5jPvLSP9FarC-QK z-APrA((0CHHadGJb{?P>g>!-Hf>au>p=eQx%`EMrrN+vrf@cJoBUATvt7#fTR7*oPA!$6G=z*kp$eF_^pjiRapTT!RY3G!f zm_+9kx?L{SB&?RUciG&V-sTFnz+yR>{4gIQJ!A#vtdUNkF~`Z>XqJF#st*hZS1kz1 zd?oxhy4#TV#^Exc?)BnX8WpwiWU@%y>GG#Ts zVD3vB8?V=PcX!{G({Wk;8XDdkuQ%4LES8z{UAEpX*zW}% p>wo+uZq0pc?n84Q@R Date: Mon, 30 Jan 2012 12:56:59 +0100 Subject: [PATCH 1854/2215] Set a minimum width for the sensor view, closes #165 --- telldus-gui/Plugins/Sensors/SensorList.qml | 1 + telldus-gui/Plugins/Sensors/main.qml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml index 8f6635bd..ea1ed7c4 100644 --- a/telldus-gui/Plugins/Sensors/SensorList.qml +++ b/telldus-gui/Plugins/Sensors/SensorList.qml @@ -3,6 +3,7 @@ import QtDesktop 0.1 Column { id: sensorList + property int minimumWidth: main.state == "EDIT" ? 770 : 475 spacing: 1 BorderImage { diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml index c4710d0a..75b4847f 100644 --- a/telldus-gui/Plugins/Sensors/main.qml +++ b/telldus-gui/Plugins/Sensors/main.qml @@ -15,7 +15,8 @@ Item { SensorList { id: sensorList - width: main.width-scrollArea.verticalScrollBar.width + property int calculatedWidth: main.width-scrollArea.verticalScrollBar.width + width: (calculatedWidth < minimumWidth ? minimumWidth : calculatedWidth) } } } From 9a8c76513f58a452770eceaf32278722fc7390f5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 30 Jan 2012 13:21:16 +0100 Subject: [PATCH 1855/2215] Bump version from 2.1.1_beta1 to 2.1.1 --- telldus-gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index 63bafafc..5058a201 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -11,7 +11,7 @@ SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 1) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta1") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}") SET(BRANDING "telldus" CACHE STRING "The brand to use") From 4ef7de7ac5c77210567ce43bbb71f8adda0f455b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 30 Jan 2012 15:42:08 +0100 Subject: [PATCH 1856/2215] Change path to qt-components-desktop submodule to our own mirror since gitorious fails so often --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 1512eb7b..2ffccaba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "telldus-gui/3rdparty/qt-components-desktop"] path = telldus-gui/3rdparty/qt-components-desktop - url = git://gitorious.org/qt-components/desktop.git + url = http://git.telldus.com/qt-components-desktop.git From 91cf55816c082f625d54a715647067388cf818af Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 31 Jan 2012 11:34:39 +0100 Subject: [PATCH 1857/2215] Rewrite dependencies for QtComponents desktop on install --- .../3rdparty/qt-components-desktop.cmake | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/telldus-gui/3rdparty/qt-components-desktop.cmake b/telldus-gui/3rdparty/qt-components-desktop.cmake index ff7deaba..d76bec8c 100644 --- a/telldus-gui/3rdparty/qt-components-desktop.cmake +++ b/telldus-gui/3rdparty/qt-components-desktop.cmake @@ -52,6 +52,41 @@ IF (WIN32) SET_TARGET_PROPERTIES(styleplugin PROPERTIES PREFIX "Plugins/declarative/QtDesktop/plugin/" ) +ELSEIF(APPLE) + ADD_CUSTOM_COMMAND(TARGET styleplugin POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${QT_COMPONENTS_OUTPUT_DIR}/plugin/ + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/libstyleplugin.dylib + ${QT_COMPONENTS_OUTPUT_DIR}/plugin/ + COMMENT "Copy plugin to destination bundle" + ) + INSTALL(CODE " + GET_FILENAME_COMPONENT(DESTDIR \"\$ENV{DESTDIR}\" ABSOLUTE) + SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") + GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) + GET_FILENAME_COMPONENT(exedir \"\${exe}\" PATH) + SET(plugin \"\${bundle}/Contents/Plugins/declarative/QtDesktop/plugin/libstyleplugin${CMAKE_SHARED_LIBRARY_SUFFIX}\") + + GET_ITEM_KEY(\"\${plugin}\" pkey) + SET(prereqs \"\") + GET_PREREQUISITES(\${plugin} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\") + FOREACH(pr \${prereqs}) + GET_ITEM_KEY(\"\${pr}\" rkey) + + #Check to see if this is ourself + IF (NOT \${pkey} STREQUAL \${rkey}) + SET(kv \"\") + SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exedir}\" \"\${bundle}/Contents/Frameworks/\" 1) + IF (NOT EXISTS \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") + COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(\"\${\${kv}_RESOLVED_ITEM}\" \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") + ENDIF () + EXECUTE_PROCESS(COMMAND install_name_tool + -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${plugin}\" + ) + ENDIF () + + ENDFOREACH() + ") ELSE() SET_TARGET_PROPERTIES(styleplugin PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${QT_COMPONENTS_OUTPUT_DIR}/plugin From 6cbdac52b94aa004d967cf648710a356ebeaebbf Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 2 Feb 2012 12:35:08 +0100 Subject: [PATCH 1858/2215] Fixed TelldusCenter freeze when saving device changes in Linux/Mac --- telldus-core/client/CallbackDispatcher.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 2447a43e..1a0ce48d 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -21,7 +21,6 @@ TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct * TDDeviceEventDispatcher::~TDDeviceEventDispatcher() { this->wait(); - d->mutex.unlock(); } bool TDDeviceEventDispatcher::done() const { @@ -33,6 +32,7 @@ void TDDeviceEventDispatcher::run() { d->event(deviceId, method, strData.c_str(), d->id, d->context); doneRunning = true; + d->mutex.unlock(); } @@ -45,7 +45,6 @@ TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStructwait(); - d->mutex.unlock(); } bool TDDeviceChangeEventDispatcher::done() const { @@ -55,6 +54,7 @@ bool TDDeviceChangeEventDispatcher::done() const { void TDDeviceChangeEventDispatcher::run() { d->event(deviceId, changeEvent, changeType, d->id, d->context); doneRunning = true; + d->mutex.unlock(); } TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id) @@ -66,7 +66,6 @@ TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStructwait(); - d->mutex.unlock(); } bool TDRawDeviceEventDispatcher::done() const { @@ -76,6 +75,7 @@ bool TDRawDeviceEventDispatcher::done() const { void TDRawDeviceEventDispatcher::run() { d->event(strData.c_str(), controllerId, d->id, d->context); doneRunning = true; + d->mutex.unlock(); } TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, int type, const std::string &v, int t) @@ -87,7 +87,6 @@ TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct TDSensorEventDispatcher::~TDSensorEventDispatcher() { this->wait(); - d->mutex.unlock(); } bool TDSensorEventDispatcher::done() const { @@ -97,4 +96,5 @@ bool TDSensorEventDispatcher::done() const { void TDSensorEventDispatcher::run() { d->event(protocol.c_str(), model.c_str(), sensorId, dataType, value.c_str(), timestamp, d->id, d->context); doneRunning = true; + d->mutex.unlock(); } From f62881d42e171b9d38911d42e2e2239cf4b08d55 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 2 Feb 2012 12:40:34 +0100 Subject: [PATCH 1859/2215] Removed 'beta1' from version --- telldus-core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index e01671d5..e1904ff7 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -13,7 +13,7 @@ SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 1) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "beta1") +SET(PACKAGE_SUBVERSION "") SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") From f15fd887e8800351944c6339f90cb60cc3e7469b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 2 Feb 2012 15:16:23 +0100 Subject: [PATCH 1860/2215] Escape command line paths since they might containing spaces or other strange chars --- telldus-core/service/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 09a3fe4f..a02ca8fa 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -148,7 +148,7 @@ ELSEIF (WIN32) #### Windows #### ) ADD_CUSTOM_COMMAND( OUTPUT Messages.rc Messages.h - COMMAND mc.exe -u -r ${CMAKE_CURRENT_BINARY_DIR} -h ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc + COMMAND mc.exe -u -r \"${CMAKE_CURRENT_BINARY_DIR}\" -h \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc\" DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc DEPENDS Messages.rc COMMENT "Compiling Messages Resource" From 7834d935e2929edbb52df7401a4cd4be4861fb96 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 2 Feb 2012 15:58:55 +0100 Subject: [PATCH 1861/2215] Fixed wrong endpoint in our php example --- examples/php/live/authentication/common.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/php/live/authentication/common.php b/examples/php/live/authentication/common.php index 05873f77..3256b9b7 100644 --- a/examples/php/live/authentication/common.php +++ b/examples/php/live/authentication/common.php @@ -7,7 +7,7 @@ require_once 'HTTP/OAuth/Consumer.php'; define('PUBLIC_KEY', ''); define('PRIVATE_KEY', ''); -define('URL', 'http://api.telldus.net'); +define('URL', 'http://api.telldus.com'); //https should be used in production! define('REQUEST_TOKEN', constant('URL').'/oauth/requestToken'); define('AUTHORIZE_TOKEN', constant('URL').'/oauth/authorize'); define('ACCESS_TOKEN', constant('URL').'/oauth/accessToken'); @@ -16,4 +16,4 @@ define('REQUEST_URI', constant('URL').'/xml'); define('BASE_URL', 'http://'.$_SERVER["SERVER_NAME"].dirname($_SERVER['REQUEST_URI'])); define('TELLSTICK_TURNON', 1); -define('TELLSTICK_TURNOFF', 2); \ No newline at end of file +define('TELLSTICK_TURNOFF', 2); From 24f7755358d42e543b0740d35fc0fd5f661d157c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 2 Feb 2012 17:21:48 +0100 Subject: [PATCH 1862/2215] Workaround for dependencies in plugins not resolved correctly --- telldus-gui/TelldusCenter/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 8ec1b15b..8e55ce1b 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -1,7 +1,11 @@ FIND_PACKAGE( Qt4 REQUIRED ) SET(QT_USE_QTSCRIPT TRUE) SET(QT_USE_QTNETWORK TRUE) -SET(QT_USE_QTUITOOLS TRUE) +SET(QT_USE_QTUITOOLS TRUE) +IF (APPLE) + #This is a workaround for plugins that depends on libraries and will not copy these correctly + SET(QT_USE_QTDECLARATIVE TRUE) +ENDIF() INCLUDE( ${QT_USE_FILE} ) FIND_PACKAGE( SignTool REQUIRED ) From 72e480a8705ad038a2628610d8c62b4ba17f5949 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 11:07:14 +0100 Subject: [PATCH 1863/2215] Add a (hopefully) 64-bit safe conversion on OS X --- telldus-core/common/Strings.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index c563fa49..9971bcee 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -147,6 +147,8 @@ std::wstring TelldusCore::intToWStringSafe(int value){ uint64_t TelldusCore::hexTo64l(const std::string data){ #ifdef _WINDOWS return _strtoui64(data.c_str(), NULL, 16); +#elif defined(_MACOSX) + return strtoq(data.c_str(), NULL, 16); #else return strtol(data.c_str(), NULL, 16); #endif From e718228a121b4bc5dda9c461ba50ab637d8cd326 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 11:17:36 +0100 Subject: [PATCH 1864/2215] hexTo64l() should convert it to an unsigned value on Linux --- telldus-core/common/Strings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 9971bcee..3678e49d 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -150,7 +150,7 @@ uint64_t TelldusCore::hexTo64l(const std::string data){ #elif defined(_MACOSX) return strtoq(data.c_str(), NULL, 16); #else - return strtol(data.c_str(), NULL, 16); + return strtoul(data.c_str(), NULL, 16); #endif } From 189ddc9383a342debf5c6388a8605e7715480a63 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 11:41:20 +0100 Subject: [PATCH 1865/2215] Convert the number in hexTo64l() it to a long long int instead of long int to be safe for 32-bit systems --- telldus-core/common/Strings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 3678e49d..b4d02376 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -150,7 +150,7 @@ uint64_t TelldusCore::hexTo64l(const std::string data){ #elif defined(_MACOSX) return strtoq(data.c_str(), NULL, 16); #else - return strtoul(data.c_str(), NULL, 16); + return strtoull(data.c_str(), NULL, 16); #endif } From 938187b2a652cc6691f5a3b2ec9d0d73fd4e6748 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 14:51:39 +0100 Subject: [PATCH 1866/2215] Move the event system into common to be used by our threads --- telldus-core/common/CMakeLists.txt | 9 +++++++++ telldus-core/{service => common}/Event.cpp | 0 telldus-core/{service => common}/Event.h | 0 telldus-core/{service => common}/EventHandler.h | 0 telldus-core/{service => common}/EventHandler_unix.cpp | 0 telldus-core/{service => common}/EventHandler_win.cpp | 0 telldus-core/{service => common}/Event_unix.cpp | 0 telldus-core/{service => common}/Event_win.cpp | 0 telldus-core/service/CMakeLists.txt | 9 --------- 9 files changed, 9 insertions(+), 9 deletions(-) rename telldus-core/{service => common}/Event.cpp (100%) rename telldus-core/{service => common}/Event.h (100%) rename telldus-core/{service => common}/EventHandler.h (100%) rename telldus-core/{service => common}/EventHandler_unix.cpp (100%) rename telldus-core/{service => common}/EventHandler_win.cpp (100%) rename telldus-core/{service => common}/Event_unix.cpp (100%) rename telldus-core/{service => common}/Event_win.cpp (100%) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 71262738..05ed0893 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -4,6 +4,7 @@ ENDIF(COMMAND cmake_policy) ######## Non configurable options ######## SET( telldus-common_SRCS + Event.cpp Message.cpp Mutex.cpp Strings.cpp @@ -12,6 +13,8 @@ SET( telldus-common_SRCS SET( telldus-common_HDRS common.h + Event.h + EventHandler.h Message.h Mutex.h Socket.h @@ -29,6 +32,8 @@ IF (APPLE) FIND_LIBRARY(ICONV_LIBRARY iconv) ADD_DEFINITIONS( -D_MACOSX ) LIST(APPEND telldus-common_SRCS + Event_unix.cpp + EventHandler_unix.cpp Socket_unix.cpp stdlibc_workaround.cpp #Remove this when we drop support for 10.5 ) @@ -41,6 +46,8 @@ ELSEIF (WIN32) ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No ADD_DEFINITIONS( -D_WINDOWS ) LIST(APPEND telldus-common_SRCS + Event_win.cpp + EventHandler_win.cpp Socket_win.cpp ) ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") @@ -48,6 +55,8 @@ ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") FIND_LIBRARY(ICONV_LIBRARY iconv) ADD_DEFINITIONS( -D_FREEBSD ) LIST(APPEND telldus-common_SRCS + Event_unix.cpp + EventHandler_unix.cpp Socket_unix.cpp ) LIST(APPEND telldus-common_LIBRARIES diff --git a/telldus-core/service/Event.cpp b/telldus-core/common/Event.cpp similarity index 100% rename from telldus-core/service/Event.cpp rename to telldus-core/common/Event.cpp diff --git a/telldus-core/service/Event.h b/telldus-core/common/Event.h similarity index 100% rename from telldus-core/service/Event.h rename to telldus-core/common/Event.h diff --git a/telldus-core/service/EventHandler.h b/telldus-core/common/EventHandler.h similarity index 100% rename from telldus-core/service/EventHandler.h rename to telldus-core/common/EventHandler.h diff --git a/telldus-core/service/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp similarity index 100% rename from telldus-core/service/EventHandler_unix.cpp rename to telldus-core/common/EventHandler_unix.cpp diff --git a/telldus-core/service/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp similarity index 100% rename from telldus-core/service/EventHandler_win.cpp rename to telldus-core/common/EventHandler_win.cpp diff --git a/telldus-core/service/Event_unix.cpp b/telldus-core/common/Event_unix.cpp similarity index 100% rename from telldus-core/service/Event_unix.cpp rename to telldus-core/common/Event_unix.cpp diff --git a/telldus-core/service/Event_win.cpp b/telldus-core/common/Event_win.cpp similarity index 100% rename from telldus-core/service/Event_win.cpp rename to telldus-core/common/Event_win.cpp diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index a02ca8fa..b7d0fa3c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -18,7 +18,6 @@ SET( telldus-service_SRCS ControllerMessage.cpp Device.cpp DeviceManager.cpp - Event.cpp Log.cpp Sensor.cpp Settings.cpp @@ -78,8 +77,6 @@ SET( telldus-service_HDRS ControllerMessage.h Device.h DeviceManager.h - Event.h - EventHandler.h EventUpdateManager.h Log.h Sensor.h @@ -116,8 +113,6 @@ IF (APPLE) #### Mac OS X #### main_mac.cpp ConnectionListener_unix.cpp ControllerListener_mac.cpp - Event_unix.cpp - EventHandler_unix.cpp SettingsCoreFoundationPreferences.cpp ) @@ -134,8 +129,6 @@ ELSEIF (WIN32) #### Windows #### ) LIST(APPEND telldus-service_SRCS ConnectionListener_win.cpp - Event_win.cpp - EventHandler_win.cpp main_win.cpp SettingsWinRegistry.cpp TelldusWinService_win.cpp @@ -164,8 +157,6 @@ ELSE (APPLE) #### Linux #### SET( telldus-service_TARGET telldusd ) LIST(APPEND telldus-service_SRCS ConnectionListener_unix.cpp - Event_unix.cpp - EventHandler_unix.cpp main_unix.cpp SettingsConfuse.cpp ) From ceec23dfed3ad0e67cef7e12bc29ef881880a79f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 15:50:04 +0100 Subject: [PATCH 1867/2215] Add function Thread::startAndLock() --- telldus-core/common/Thread.cpp | 20 ++++++++++++++++++++ telldus-core/common/Thread.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index d823d949..6415c1b2 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -14,12 +14,15 @@ #ifdef _WINDOWS #include #endif +#include "EventHandler.h" using namespace TelldusCore; class TelldusCore::ThreadPrivate { public: bool running; + EventRef threadStarted; + Mutex *mutex; #ifdef _WINDOWS HANDLE thread; DWORD threadId; @@ -31,6 +34,7 @@ public: Thread::Thread() { d = new ThreadPrivate; d->thread = 0; + d->mutex = 0; } Thread::~Thread() { @@ -46,6 +50,15 @@ void Thread::start() { #endif } +void Thread::startAndLock(Mutex *lock) { + EventHandler handler; + d->threadStarted = handler.addEvent(); + d->mutex = lock; + this->start(); + handler.waitForAny(); + d->threadStarted.reset(); +} + bool Thread::wait() { if (!d->thread) { return true; @@ -64,7 +77,14 @@ bool Thread::wait() { void *Thread::exec( void *ptr ) { Thread *t = reinterpret_cast(ptr); if (t) { + if (t->d->threadStarted) { + t->d->mutex->lock(); + t->d->threadStarted->signal(); + } t->run(); + if (t->d->mutex) { + t->d->mutex->unlock(); + } t->d->running = false; } #ifdef _WINDOWS diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index 683efb99..e7bf144e 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -13,6 +13,7 @@ #define THREAD_H #include +#include "Mutex.h" namespace TelldusCore { class ThreadPrivate; @@ -21,6 +22,7 @@ namespace TelldusCore { Thread(); virtual ~Thread(); void start(); + void startAndLock(Mutex *); bool wait(); protected: From 868c8b322c052181e36262773192fb03fa02fdea Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 15:52:15 +0100 Subject: [PATCH 1868/2215] The mutex must be locked and unlocked by the same thread. We easily get deadlocks in Windows otherwise --- telldus-core/client/CallbackDispatcher.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 1a0ce48d..86dbc0d3 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -15,8 +15,7 @@ using namespace TelldusCore; TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct *data, int id, int m, const std::string &strD) :Thread(), d(data), deviceId(id), method(m), strData(strD), doneRunning(false) { - d->mutex.lock(); - this->start(); + this->startAndLock(&d->mutex); } TDDeviceEventDispatcher::~TDDeviceEventDispatcher() { @@ -32,15 +31,13 @@ void TDDeviceEventDispatcher::run() { d->event(deviceId, method, strData.c_str(), d->id, d->context); doneRunning = true; - d->mutex.unlock(); } TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStruct *data, int id, int event, int type) :Thread(), d(data), deviceId(id), changeEvent(event), changeType(type), doneRunning(false) { - d->mutex.lock(); - this->start(); + this->startAndLock(&d->mutex); } TDDeviceChangeEventDispatcher::~TDDeviceChangeEventDispatcher() { @@ -54,14 +51,12 @@ bool TDDeviceChangeEventDispatcher::done() const { void TDDeviceChangeEventDispatcher::run() { d->event(deviceId, changeEvent, changeType, d->id, d->context); doneRunning = true; - d->mutex.unlock(); } TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id) :Thread(), d(data), controllerId(id), strData(strD), doneRunning(false) { - d->mutex.lock(); - this->start(); + this->startAndLock(&d->mutex); } TDRawDeviceEventDispatcher::~TDRawDeviceEventDispatcher() { @@ -75,14 +70,12 @@ bool TDRawDeviceEventDispatcher::done() const { void TDRawDeviceEventDispatcher::run() { d->event(strData.c_str(), controllerId, d->id, d->context); doneRunning = true; - d->mutex.unlock(); } TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, int type, const std::string &v, int t) :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t), doneRunning(false) { - d->mutex.lock(); - this->start(); + this->startAndLock(&d->mutex); } TDSensorEventDispatcher::~TDSensorEventDispatcher() { @@ -96,5 +89,4 @@ bool TDSensorEventDispatcher::done() const { void TDSensorEventDispatcher::run() { d->event(protocol.c_str(), model.c_str(), sensorId, dataType, value.c_str(), timestamp, d->id, d->context); doneRunning = true; - d->mutex.unlock(); } From 12506815144a25f959a1c78776ad82fa8970b5a3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 16:18:15 +0100 Subject: [PATCH 1869/2215] Missed the Event files for Linux --- telldus-core/common/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index 05ed0893..c0d64759 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -66,6 +66,8 @@ ELSE (APPLE) #### Linux #### ADD_DEFINITIONS( -D_LINUX ) LIST(APPEND telldus-common_SRCS + Event_unix.cpp + EventHandler_unix.cpp Socket_unix.cpp ) ENDIF (APPLE) From e834160492fcf522ade2ab40239ba2bf66e17be3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 17:09:38 +0100 Subject: [PATCH 1870/2215] Move class Event and EventHandler into the TelldusCore namespace --- telldus-core/common/Event.cpp | 4 +- telldus-core/common/Event.h | 95 ++++++++++--------- telldus-core/common/EventHandler.h | 31 +++--- telldus-core/common/EventHandler_unix.cpp | 2 + telldus-core/common/Event_unix.cpp | 2 + .../service/ClientCommunicationHandler.cpp | 4 +- .../service/ClientCommunicationHandler.h | 2 +- telldus-core/service/ConnectionListener.h | 4 +- .../service/ConnectionListener_unix.cpp | 8 +- telldus-core/service/Controller.cpp | 8 +- telldus-core/service/Controller.h | 6 +- telldus-core/service/ControllerListener.h | 8 +- telldus-core/service/ControllerManager.cpp | 4 +- telldus-core/service/ControllerManager.h | 6 +- telldus-core/service/DeviceManager.cpp | 4 +- telldus-core/service/DeviceManager.h | 2 +- telldus-core/service/EventUpdateManager.cpp | 10 +- telldus-core/service/EventUpdateManager.h | 6 +- telldus-core/service/TellStick.h | 2 +- telldus-core/service/TellStick_libftdi.cpp | 2 +- telldus-core/service/TelldusMain.cpp | 20 ++-- telldus-core/service/Timer.cpp | 4 +- telldus-core/service/Timer.h | 2 +- 23 files changed, 125 insertions(+), 111 deletions(-) diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index b982d99a..76d060cb 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -4,6 +4,8 @@ #include +using namespace TelldusCore; + EventData::~EventData() { } @@ -22,7 +24,7 @@ public: std::list eventDataList; }; -EventBase::EventBase(EventHandler *handler) { +EventBase::EventBase(TelldusCore::EventHandler *handler) { d = new PrivateData; d->handler = handler; } diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index ad52aa02..ec92c35d 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -1,70 +1,73 @@ #ifndef EVENT_H #define EVENT_H -class EventHandler; #include "Thread.h" #ifdef _WINDOWS - #include - #include +#include +#include typedef HANDLE EVENT_T; #else - #include +#include typedef void* EVENT_T; #endif -class EventData { -public: - virtual ~EventData(); - virtual bool isValid() const; -}; +namespace TelldusCore { + class EventHandler; -class EventDataBase : public EventData { -public: - virtual bool isValid() const; -}; + class EventData { + public: + virtual ~EventData(); + virtual bool isValid() const; + }; -typedef std::tr1::shared_ptr EventDataRef; + class EventDataBase : public EventData { + public: + virtual bool isValid() const; + }; -class EventBase { -public: - virtual ~EventBase(); + typedef std::tr1::shared_ptr EventDataRef; - void popSignal(); - bool isSignaled(); - void signal(); - virtual void signal(EventData *); - EventDataRef takeSignal(); + class EventBase { + public: + virtual ~EventBase(); -protected: - EventBase(EventHandler *handler); - void clearHandler(); - virtual void clearSignal() = 0; - EventHandler *handler() const; - virtual void sendSignal() = 0; + void popSignal(); + bool isSignaled(); + void signal(); + virtual void signal(EventData *); + EventDataRef takeSignal(); -private: - class PrivateData; - PrivateData *d; -}; + protected: + EventBase(EventHandler *handler); + void clearHandler(); + virtual void clearSignal() = 0; + EventHandler *handler() const; + virtual void sendSignal() = 0; -class Event : public EventBase { -public: - virtual ~Event(); + private: + class PrivateData; + PrivateData *d; + }; -protected: - Event(EventHandler *handler); - EVENT_T retrieveNative(); - virtual void clearSignal(); - virtual void sendSignal(); + class Event : public EventBase { + public: + virtual ~Event(); -private: - class PrivateData; - PrivateData *d; + protected: + Event(EventHandler *handler); + EVENT_T retrieveNative(); + virtual void clearSignal(); + virtual void sendSignal(); -friend class EventHandler; -}; + private: + class PrivateData; + PrivateData *d; -typedef std::tr1::shared_ptr EventRef; + friend class EventHandler; + }; + + typedef std::tr1::shared_ptr EventRef; +} #endif //EVENT_H diff --git a/telldus-core/common/EventHandler.h b/telldus-core/common/EventHandler.h index 44a220a2..d6a59ef7 100644 --- a/telldus-core/common/EventHandler.h +++ b/telldus-core/common/EventHandler.h @@ -3,24 +3,27 @@ #include "Event.h" -class EventHandler { -public: - EventHandler(); - virtual ~EventHandler(void); +namespace TelldusCore { - EventRef addEvent(); + class EventHandler { + public: + EventHandler(); + virtual ~EventHandler(void); - bool waitForAny(); + EventRef addEvent(); -protected: - void signal(Event *event); + bool waitForAny(); -private: - class PrivateData; - PrivateData *d; - bool listIsSignalled(); + protected: + void signal(Event *event); - friend class Event; -}; + private: + class PrivateData; + PrivateData *d; + bool listIsSignalled(); + + friend class Event; + }; +} #endif //EVENTHANDLER_H diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 2e10f7e0..f826c004 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -6,6 +6,8 @@ #include #include +using namespace TelldusCore; + class EventHandler::PrivateData { public: pthread_cond_t event; diff --git a/telldus-core/common/Event_unix.cpp b/telldus-core/common/Event_unix.cpp index 4ade1e2f..0cf88cc2 100644 --- a/telldus-core/common/Event_unix.cpp +++ b/telldus-core/common/Event_unix.cpp @@ -2,6 +2,8 @@ #include "EventHandler.h" #include "Thread.h" +using namespace TelldusCore; + class Event::PrivateData { public: }; diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index d51144ab..96342382 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -7,7 +7,7 @@ class ClientCommunicationHandler::PrivateData { public: TelldusCore::Socket *clientSocket; - EventRef event, deviceUpdateEvent; + TelldusCore::EventRef event, deviceUpdateEvent; bool done; DeviceManager *deviceManager; }; @@ -16,7 +16,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(){ } -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, EventRef event, DeviceManager *deviceManager, EventRef deviceUpdateEvent) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent) :Thread() { d = new PrivateData; diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index e05c2000..7333775a 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -12,7 +12,7 @@ class ClientCommunicationHandler : public TelldusCore::Thread { public: ClientCommunicationHandler(); - ClientCommunicationHandler(TelldusCore::Socket *clientSocket, EventRef event, DeviceManager *deviceManager, EventRef deviceUpdateEvent); + ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent); ~ClientCommunicationHandler(void); bool isDone(); diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index e92252aa..365fd393 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -10,14 +10,14 @@ namespace TelldusCore { class Socket; }; -class ConnectionListenerEventData : public EventDataBase { +class ConnectionListenerEventData : public TelldusCore::EventDataBase { public: TelldusCore::Socket *socket; }; class ConnectionListener : public TelldusCore::Thread { public: - ConnectionListener(const std::wstring &name, EventRef waitEvent); + ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent); virtual ~ConnectionListener(void); protected: diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 4648a273..4c6c6ab6 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -14,12 +14,12 @@ class ConnectionListener::PrivateData { public: - EventRef waitEvent; + TelldusCore::EventRef waitEvent; std::string name; bool running; }; -ConnectionListener::ConnectionListener(const std::wstring &name, EventRef waitEvent) +ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) { d = new PrivateData; d->waitEvent = waitEvent; @@ -56,7 +56,7 @@ void ConnectionListener::run(){ int size = SUN_LEN(&name); bind(serverSocket, (struct sockaddr *)&name, size); listen(serverSocket, 5); - + //Change permissions to allow everyone chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); len = sizeof(struct sockaddr_un); @@ -80,7 +80,7 @@ void ConnectionListener::run(){ continue; } SOCKET_T clientSocket = accept(serverSocket, NULL, NULL); - + ConnectionListenerEventData *data = new ConnectionListenerEventData(); data->socket = new TelldusCore::Socket(clientSocket); d->waitEvent->signal(data); diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index fe663f65..02a88acc 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -4,11 +4,11 @@ class Controller::PrivateData { public: - Event *event; + TelldusCore::Event *event; int id; }; -Controller::Controller(int id, Event *event){ +Controller::Controller(int id, TelldusCore::Event *event){ d = new PrivateData; d->event = event; d->id = id; @@ -28,8 +28,8 @@ void Controller::publishData(const std::string &msg) const { void Controller::decodePublishData(const std::string &data) const { std::list msgList = Protocol::decodeData(data); - + for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt){ this->publishData(*msgIt); } -} \ No newline at end of file +} diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 42c47a04..dbf5394c 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -4,14 +4,14 @@ #include "Event.h" #include -class ControllerEventData : public EventDataBase { +class ControllerEventData : public TelldusCore::EventDataBase { public: std::string msg; int controllerId; }; class Controller { -public: +public: virtual ~Controller(); virtual int firmwareVersion() = 0; @@ -19,7 +19,7 @@ public: virtual int reset() = 0; protected: - Controller(int id, Event *event); + Controller(int id, TelldusCore::Event *event); void publishData(const std::string &data) const; void decodePublishData(const std::string &data) const; diff --git a/telldus-core/service/ControllerListener.h b/telldus-core/service/ControllerListener.h index 7fd7fbce..bae13a5e 100644 --- a/telldus-core/service/ControllerListener.h +++ b/telldus-core/service/ControllerListener.h @@ -4,7 +4,7 @@ #include "Thread.h" #include "Event.h" -class ControllerChangeEventData : public EventDataBase { +class ControllerChangeEventData : public TelldusCore::EventDataBase { public: int vid, pid; bool inserted; @@ -12,13 +12,13 @@ public: class ControllerListener : public TelldusCore::Thread { public: - ControllerListener(EventRef event); + ControllerListener(TelldusCore::EventRef event); virtual ~ControllerListener(); protected: void run(); - -private: + +private: class PrivateData; PrivateData *d; }; diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index fc46b350..27d8b283 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -14,11 +14,11 @@ class ControllerManager::PrivateData { public: int lastControllerId; ControllerMap controllers; - Event *event; + TelldusCore::Event *event; TelldusCore::Mutex mutex; }; -ControllerManager::ControllerManager(Event *event){ +ControllerManager::ControllerManager(TelldusCore::Event *event){ d = new PrivateData; d->lastControllerId = 0; d->event = event; diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index bab3525c..a3d0c6bb 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -2,13 +2,15 @@ #define CONTROLLERMANAGER_H class Controller; -class Event; +namespace TelldusCore { + class Event; +} #include class ControllerManager { public: - ControllerManager(Event *event); + ControllerManager(TelldusCore::Event *event); ~ControllerManager(void); void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 3930108a..2d074963 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -21,10 +21,10 @@ public: Settings set; TelldusCore::Mutex lock; ControllerManager *controllerManager; - EventRef deviceUpdateEvent; + TelldusCore::EventRef deviceUpdateEvent; }; -DeviceManager::DeviceManager(ControllerManager *controllerManager, EventRef deviceUpdateEvent){ +DeviceManager::DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent){ d = new PrivateData; d->controllerManager = controllerManager; d->deviceUpdateEvent = deviceUpdateEvent; diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 814efd18..b4311761 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -12,7 +12,7 @@ class Sensor; class DeviceManager { public: - DeviceManager(ControllerManager *controllerManager, EventRef deviceUpdateEvent); + DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent); ~DeviceManager(void); int getNumberOfDevices(void); int addDevice(); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 5594e12a..08a4341c 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -12,8 +12,8 @@ typedef std::list SocketList; class EventUpdateManager::PrivateData { public: - EventHandler eventHandler; - EventRef stopEvent, updateEvent, clientConnectEvent; + TelldusCore::EventHandler eventHandler; + TelldusCore::EventRef stopEvent, updateEvent, clientConnectEvent; SocketList clients; ConnectionListener *eventUpdateClientListener; }; @@ -40,7 +40,7 @@ EventUpdateManager::~EventUpdateManager(void) { delete d; } -EventRef EventUpdateManager::retrieveUpdateEvent(){ +TelldusCore::EventRef EventUpdateManager::retrieveUpdateEvent(){ return d->updateEvent; } @@ -54,7 +54,7 @@ void EventUpdateManager::run(){ if(d->clientConnectEvent->isSignaled()){ //new client added - EventDataRef eventData = d->clientConnectEvent->takeSignal(); + TelldusCore::EventDataRef eventData = d->clientConnectEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventData.get()); if(data){ d->clients.push_back(data->socket); @@ -62,7 +62,7 @@ void EventUpdateManager::run(){ } else if(d->updateEvent->isSignaled()){ //device event, signal all clients - EventDataRef eventData = d->updateEvent->takeSignal(); + TelldusCore::EventDataRef eventData = d->updateEvent->takeSignal(); EventUpdateData *data = reinterpret_cast(eventData.get()); if(data){ sendMessageToClients(data); diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 56811c4c..636b067f 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -4,7 +4,7 @@ #include "Thread.h" #include "Event.h" -class EventUpdateData : public EventDataBase { +class EventUpdateData : public TelldusCore::EventDataBase { public: std::wstring messageType; int controllerId; @@ -29,8 +29,8 @@ public: EventUpdateManager(void); ~EventUpdateManager(void); - EventRef retrieveUpdateEvent(); - EventRef retrieveClientConnectEvent(); + TelldusCore::EventRef retrieveUpdateEvent(); + TelldusCore::EventRef retrieveClientConnectEvent(); protected: void run(); diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index db73faab..ba4ccfb7 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -24,7 +24,7 @@ public: class TellStick : public Controller, public TelldusCore::Thread { public: - TellStick(int controllerId, Event *event, const TellStickDescriptor &d); + TellStick(int controllerId, TelldusCore::Event *event, const TellStickDescriptor &d); virtual ~TellStick(); virtual int firmwareVersion(); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 56b2a5a5..8c638168 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -42,7 +42,7 @@ public: TelldusCore::Mutex mutex; }; -TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &td ) +TellStick::TellStick(int controllerId, TelldusCore::Event *event, const TellStickDescriptor &td ) :Controller(controllerId, event) { d = new PrivateData; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index f5f0e188..9cac2660 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -15,8 +15,8 @@ class TelldusMain::PrivateData { public: - EventHandler eventHandler; - EventRef stopEvent, controllerChangeEvent; + TelldusCore::EventHandler eventHandler; + TelldusCore::EventRef stopEvent, controllerChangeEvent; }; TelldusMain::TelldusMain(void) @@ -57,16 +57,16 @@ void TelldusMain::suspend() { } void TelldusMain::start(void) { - EventRef clientEvent = d->eventHandler.addEvent(); - EventRef dataEvent = d->eventHandler.addEvent(); - EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups + TelldusCore::EventRef clientEvent = d->eventHandler.addEvent(); + TelldusCore::EventRef dataEvent = d->eventHandler.addEvent(); + TelldusCore::EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups Timer supervisor(janitor); //Tells the janitor to go back to work supervisor.setInterval(60); //Once every minute supervisor.start(); ControllerManager controllerManager(dataEvent.get()); EventUpdateManager eventUpdateManager; - EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); + TelldusCore::EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); eventUpdateManager.start(); DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); @@ -74,7 +74,7 @@ void TelldusMain::start(void) { std::list clientCommunicationHandlerList; - EventRef handlerEvent = d->eventHandler.addEvent(); + TelldusCore::EventRef handlerEvent = d->eventHandler.addEvent(); #ifdef _MACOSX //This is only needed on OS X @@ -88,7 +88,7 @@ void TelldusMain::start(void) { } if (clientEvent->isSignaled()) { //New client connection - EventDataRef eventDataRef = clientEvent->takeSignal(); + TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent); @@ -98,7 +98,7 @@ void TelldusMain::start(void) { } if (d->controllerChangeEvent->isSignaled()) { - EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal(); + TelldusCore::EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal(); ControllerChangeEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, "", data->inserted); @@ -106,7 +106,7 @@ void TelldusMain::start(void) { } if (dataEvent->isSignaled()) { - EventDataRef eventData = dataEvent->takeSignal(); + TelldusCore::EventDataRef eventData = dataEvent->takeSignal(); ControllerEventData *data = reinterpret_cast(eventData.get()); if (data) { deviceManager.handleControllerMessage(*data); diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index f552a414..a31d0ad2 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -9,7 +9,7 @@ class Timer::PrivateData { public: PrivateData() : interval(0), running(false) {} - EventRef event; + TelldusCore::EventRef event; int interval; bool running; #ifdef _WINDOWS @@ -21,7 +21,7 @@ public: #endif }; -Timer::Timer(EventRef event) +Timer::Timer(TelldusCore::EventRef event) :TelldusCore::Thread(), d(new PrivateData) { d->event = event; diff --git a/telldus-core/service/Timer.h b/telldus-core/service/Timer.h index 7e8c082a..fcb15356 100644 --- a/telldus-core/service/Timer.h +++ b/telldus-core/service/Timer.h @@ -6,7 +6,7 @@ class Timer : public TelldusCore::Thread { public: - Timer(EventRef event); + Timer(TelldusCore::EventRef event); virtual ~Timer(); void setInterval(int sec); From ba9c50f6251736f1ee21a6071cb6d80ed267029f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 17:32:54 +0100 Subject: [PATCH 1871/2215] Fix missing namespace in Events on Windows and Mac OS X --- telldus-core/common/EventHandler_win.cpp | 2 ++ telldus-core/common/Event_win.cpp | 2 ++ telldus-core/service/ConnectionListener_win.cpp | 4 ++-- telldus-core/service/TellStick_ftd2xx.cpp | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index f44fe8c7..9c8b4be5 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -5,6 +5,8 @@ #include #include +using namespace TelldusCore; + class EventHandler::PrivateData { public: HANDLE *eventArray; diff --git a/telldus-core/common/Event_win.cpp b/telldus-core/common/Event_win.cpp index c40a37d5..7a9e9fb5 100644 --- a/telldus-core/common/Event_win.cpp +++ b/telldus-core/common/Event_win.cpp @@ -1,6 +1,8 @@ #include "Event.h" #include "Thread.h" +using namespace TelldusCore; + class Event::PrivateData { public: EVENT_T event; diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index f88bac48..ec10d8bd 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -14,10 +14,10 @@ public: SECURITY_ATTRIBUTES sa; HANDLE hEvent; bool running; - EventRef waitEvent; + TelldusCore::EventRef waitEvent; }; -ConnectionListener::ConnectionListener(const std::wstring &name, EventRef waitEvent) +ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) { d = new PrivateData; d->hEvent = 0; diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 05ac6c10..25fdc866 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -40,7 +40,7 @@ public: #endif }; -TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &td ) +TellStick::TellStick(int controllerId, TelldusCore::Event *event, const TellStickDescriptor &td ) :Controller(controllerId, event) { d = new PrivateData; From a1079c48dae1b80ad86c86589d69f2d021668ca2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 3 Feb 2012 17:53:37 +0100 Subject: [PATCH 1872/2215] Add missing namespace for Mac OS X --- telldus-core/service/ControllerListener_mac.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp index 7ae64ffc..c042b0db 100644 --- a/telldus-core/service/ControllerListener_mac.cpp +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -12,7 +12,7 @@ public: CFStringRef serialNumber; UInt32 vid; UInt32 pid; - EventRef event; + TelldusCore::EventRef event; }; class ControllerListener::PrivateData { @@ -20,14 +20,14 @@ public: IONotificationPortRef gNotifyPort; CFRunLoopRef gRunLoop; io_iterator_t gAddedIter; - EventRef event; + TelldusCore::EventRef event; void addUsbFilter(int vid, int pid); static void DeviceAdded(void *refCon, io_iterator_t iterator); static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); }; -ControllerListener::ControllerListener(EventRef event) +ControllerListener::ControllerListener(TelldusCore::EventRef event) :Thread() { d = new PrivateData; From c235062c39630b9661f6602c16d325503e128779 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 9 Feb 2012 12:34:13 +0100 Subject: [PATCH 1873/2215] Add TellStick Net message format to the documentation --- docs/03-tellstick-net-protocol.dox | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/03-tellstick-net-protocol.dox b/docs/03-tellstick-net-protocol.dox index 8023d038..26496a3c 100644 --- a/docs/03-tellstick-net-protocol.dox +++ b/docs/03-tellstick-net-protocol.dox @@ -32,4 +32,30 @@ * Firmware version: 2 * * Use the source ip-address to determine the address to the device. + * + * \section messageformat Message format + * + * The message format used to communicate with TellStick Net is designed to be + * easily parsed but still be flexible. It can be converted to and from json + * without losing information. + * + * There exists four datatypes; string, integer, list and dictionary: + * + * - Strings are length-prefixed base sixteen followed by a colon and the + * string. For example 6:FooBar corresponds to 'FooBar'. + * + * - Integers are represented by an 'i' followed by the number in base 16 + * followed by an 's'. For example i3s corresponds to 3 and i-3s corresponds + * to -3. Integers have no size limitation. i-0s is invalid. All encodings + * with a leading zero, such as i03s, are invalid, other than i0s, which of + * course corresponds to 0. + * + * - Lists are encoded as an 'l' followed by their elements (also encoded) + * followed by an 's'. For example l3:foo3:bars corresponds to ['foo', 'bar']. + * + * - Dictionaries are encoded as a 'h' followed by a list of alternating keys and + * their corresponding values followed by an 's'. For example, + * h3:foo3:bar5:hello5:worlds corresponds to {'foo': 'bar', 'hello': 'world'} + * and h3:fool3:bar3:bazss corresponds to {'foo': ['bar', 'baz']}. Keys must + * be strings. */ From ca4c10021a9362d49b7f9caa8fe68c033f7dc359 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 9 Feb 2012 17:15:25 +0100 Subject: [PATCH 1874/2215] Emphasize that this is still under development --- docs/03-tellstick-net-protocol.dox | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/03-tellstick-net-protocol.dox b/docs/03-tellstick-net-protocol.dox index 26496a3c..34775160 100644 --- a/docs/03-tellstick-net-protocol.dox +++ b/docs/03-tellstick-net-protocol.dox @@ -9,7 +9,8 @@ * TellStick Net through Telldus Live! is still the prefered and supported * method. * - * This interface is still under development and is not ready for production. + * This interface is still under development and is not ready for + * production. * * \section autodiscovery Auto discovery * From 371a8bf24a7c75e8e9c5228d8e032ec9618f6dc8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 9 Feb 2012 17:16:25 +0100 Subject: [PATCH 1875/2215] The strings length-prefix must be in upper case --- docs/03-tellstick-net-protocol.dox | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/03-tellstick-net-protocol.dox b/docs/03-tellstick-net-protocol.dox index 34775160..b2fe32eb 100644 --- a/docs/03-tellstick-net-protocol.dox +++ b/docs/03-tellstick-net-protocol.dox @@ -42,8 +42,8 @@ * * There exists four datatypes; string, integer, list and dictionary: * - * - Strings are length-prefixed base sixteen followed by a colon and the - * string. For example 6:FooBar corresponds to 'FooBar'. + * - Strings are length-prefixed base sixteen (upper case) followed by a colon + * and the string. For example 6:FooBar corresponds to 'FooBar'. * * - Integers are represented by an 'i' followed by the number in base 16 * followed by an 's'. For example i3s corresponds to 3 and i-3s corresponds From 5fd3b2c425cd374c46898fbec4fe1ecfe33585cd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 9 Feb 2012 17:16:55 +0100 Subject: [PATCH 1876/2215] First example on how to communicate with the TellStick Net locally --- docs/03-tellstick-net-protocol.dox | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/docs/03-tellstick-net-protocol.dox b/docs/03-tellstick-net-protocol.dox index b2fe32eb..e077f063 100644 --- a/docs/03-tellstick-net-protocol.dox +++ b/docs/03-tellstick-net-protocol.dox @@ -59,4 +59,36 @@ * h3:foo3:bar5:hello5:worlds corresponds to {'foo': 'bar', 'hello': 'world'} * and h3:fool3:bar3:bazss corresponds to {'foo': ['bar', 'baz']}. Keys must * be strings. + * + * Communication with TellStick Net is done over UDP on port 42314. + * The first string sent contains the command to execute. The following python + * example sends a disconnection command to a TellStick Net. This will reboot + * the device. + * \code + * from socket import * + * UDPSock = socket(AF_INET,SOCK_DGRAM) + * UDPSock.sendto("A:disconnect", ("192.168.0.155",42314)) + * \endcode + * \section tellstick_net_command_send Send command + * + * For readability the examples will be displayed in json format in this + * documentation. They must be encoded using the TellStick Net message format + * before sending to an actual TellStick Net. + * + * Sending RF-data uses the same encoding as TellStick \ref sec_send with the + * difference that prefixes should be sent as a parameter and not in the + * RF-data. + * + * The parameters are sent encoded in a dictionary, with the RF-data in the key + * 'S'. Example sending Arctech Code switch A1 ON:
+ * {'S': '$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$kk$$kk$$kk$$k'} + * The string sent will be encoded like this:
+ * 4:sendh1:S32:$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$kk$$kk$$k$k$ks + * + * The same example as above but with a 20 ms pause between the 15 packages:
+ * {'S': '$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$kk$$kk$$kk$$k', + * 'P': 20, 'R': 15} + * + * The command \ref sec_send_extended "\"Send extended\" (T)" is not implemented + * since a TellStick Net can handle packages over 255 pulses. */ From 4014158e8f0ebb37fa40327c5d86ca8aac910fae Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 6 Jan 2012 18:17:48 +0100 Subject: [PATCH 1877/2215] Add CppUnit test with just a simple dummy failing test --- telldus-core/CMakeLists.txt | 3 ++ telldus-core/tests/CMakeLists.txt | 8 +++++ telldus-core/tests/common/CMakeLists.txt | 9 ++++++ telldus-core/tests/common/StringsTest.cpp | 31 ++++++++++++++++++ telldus-core/tests/common/StringsTest.h | 26 +++++++++++++++ telldus-core/tests/cppunit.cpp | 39 +++++++++++++++++++++++ 6 files changed, 116 insertions(+) create mode 100644 telldus-core/tests/CMakeLists.txt create mode 100644 telldus-core/tests/common/CMakeLists.txt create mode 100644 telldus-core/tests/common/StringsTest.cpp create mode 100644 telldus-core/tests/common/StringsTest.h create mode 100644 telldus-core/tests/cppunit.cpp diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index e1904ff7..af00e1c8 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -57,3 +57,6 @@ ENDIF(BUILD_TDTOOL) IF(BUILD_TDADMIN) ADD_SUBDIRECTORY(tdadmin) ENDIF(BUILD_TDADMIN) + +ENABLE_TESTING() +ADD_SUBDIRECTORY(tests) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt new file mode 100644 index 00000000..1e071489 --- /dev/null +++ b/telldus-core/tests/CMakeLists.txt @@ -0,0 +1,8 @@ +ADD_SUBDIRECTORY(common) + +ADD_EXECUTABLE(TestRunner cppunit.cpp) +TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) +ADD_DEPENDENCIES(TestRunner TelldusCommonTests) + +ADD_TEST(Tests ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) + diff --git a/telldus-core/tests/common/CMakeLists.txt b/telldus-core/tests/common/CMakeLists.txt new file mode 100644 index 00000000..0386e19f --- /dev/null +++ b/telldus-core/tests/common/CMakeLists.txt @@ -0,0 +1,9 @@ +FILE(GLOB SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*Test.cpp" ) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common) + +ADD_LIBRARY(TelldusCommonTests SHARED ${SRCS} ) + +TARGET_LINK_LIBRARIES( TelldusCommonTests TelldusCommon ) +ADD_DEPENDENCIES( TelldusCommonTests TelldusCommon ) + diff --git a/telldus-core/tests/common/StringsTest.cpp b/telldus-core/tests/common/StringsTest.cpp new file mode 100644 index 00000000..d1548ab6 --- /dev/null +++ b/telldus-core/tests/common/StringsTest.cpp @@ -0,0 +1,31 @@ +#include "StringsTest.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (StringsTest); + +void StringsTest :: setUp (void) +{ +} + +void StringsTest :: tearDown (void) +{ +} + +void StringsTest :: addTest (void) +{ + // check subtraction results + CPPUNIT_ASSERT_EQUAL (1, 1); + CPPUNIT_ASSERT_EQUAL (1, 2); +} + +void StringsTest :: subTest (void) +{ + // check addition results + CPPUNIT_ASSERT_EQUAL (1, 1); +} + + +void StringsTest :: equalTest (void) +{ + // test successful, if true is returned + CPPUNIT_ASSERT (1 == 1); +} diff --git a/telldus-core/tests/common/StringsTest.h b/telldus-core/tests/common/StringsTest.h new file mode 100644 index 00000000..b75c1f7a --- /dev/null +++ b/telldus-core/tests/common/StringsTest.h @@ -0,0 +1,26 @@ +#ifndef STRINGSTEST_H +#define STRINGSTEST_H + +#include +#include +#include "Strings.h" + +class StringsTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (StringsTest); + CPPUNIT_TEST (addTest); + CPPUNIT_TEST (subTest); + CPPUNIT_TEST (equalTest); + CPPUNIT_TEST_SUITE_END (); + + public: + void setUp (void); + void tearDown (void); + + protected: + void addTest (void); + void subTest (void); + void equalTest (void); +}; + +#endif //STRINGSTEST_H diff --git a/telldus-core/tests/cppunit.cpp b/telldus-core/tests/cppunit.cpp new file mode 100644 index 00000000..65f0739e --- /dev/null +++ b/telldus-core/tests/cppunit.cpp @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +int main (int argc, char* argv[]) +{ + // informs test-listener about testresults + CPPUNIT_NS :: TestResult testresult; + + // register listener for collecting the test-results + CPPUNIT_NS :: TestResultCollector collectedresults; + testresult.addListener (&collectedresults); + + // register listener for per-test progress output + CPPUNIT_NS :: BriefTestProgressListener progress; + testresult.addListener (&progress); + + // insert test-suite at test-runner by registry + CPPUNIT_NS :: TestRunner testrunner; + testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ()); + testrunner.run (testresult); + + // output results in compiler-format + CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr); + compileroutputter.write (); + + std::ofstream xmlFileOut("cpptestresults.xml"); + CPPUNIT_NS :: XmlOutputter xmlOut(&collectedresults, xmlFileOut); + xmlOut.write(); + + // return 0 if tests were successful + return collectedresults.wasSuccessful () ? 0 : 1; +} From 06be6ecedc692abbac0a7c92951284460de13db1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 9 Jan 2012 16:31:43 +0100 Subject: [PATCH 1878/2215] Add cppcheck to our tests --- telldus-core/tests/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index 1e071489..951f99ca 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -4,5 +4,6 @@ ADD_EXECUTABLE(TestRunner cppunit.cpp) TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) ADD_DEPENDENCIES(TestRunner TelldusCommonTests) -ADD_TEST(Tests ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) +ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) +ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR}) From d260100d38ec6ad5269e4705f316461c7dfe23c5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 17 Jan 2012 17:00:09 +0100 Subject: [PATCH 1879/2215] Add real test for TelldusCore::formatf() --- telldus-core/tests/common/StringsTest.cpp | 24 ++++++----------------- telldus-core/tests/common/StringsTest.h | 21 ++++++++------------ 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/telldus-core/tests/common/StringsTest.cpp b/telldus-core/tests/common/StringsTest.cpp index d1548ab6..c71a0e97 100644 --- a/telldus-core/tests/common/StringsTest.cpp +++ b/telldus-core/tests/common/StringsTest.cpp @@ -1,4 +1,5 @@ #include "StringsTest.h" +#include "Strings.h" CPPUNIT_TEST_SUITE_REGISTRATION (StringsTest); @@ -10,22 +11,9 @@ void StringsTest :: tearDown (void) { } -void StringsTest :: addTest (void) -{ - // check subtraction results - CPPUNIT_ASSERT_EQUAL (1, 1); - CPPUNIT_ASSERT_EQUAL (1, 2); -} - -void StringsTest :: subTest (void) -{ - // check addition results - CPPUNIT_ASSERT_EQUAL (1, 1); -} - - -void StringsTest :: equalTest (void) -{ - // test successful, if true is returned - CPPUNIT_ASSERT (1 == 1); +void StringsTest :: formatfTest (void) { + CPPUNIT_ASSERT_EQUAL(std::string("42"), TelldusCore::formatf("%u", 42)); + CPPUNIT_ASSERT_EQUAL(std::string("0"), TelldusCore::formatf("%u", 42.1)); + CPPUNIT_ASSERT_EQUAL(std::string("2A"), TelldusCore::formatf("%X", 42)); + CPPUNIT_ASSERT_EQUAL(std::string("42"), TelldusCore::formatf("%s", "42")); } diff --git a/telldus-core/tests/common/StringsTest.h b/telldus-core/tests/common/StringsTest.h index b75c1f7a..4c5642c7 100644 --- a/telldus-core/tests/common/StringsTest.h +++ b/telldus-core/tests/common/StringsTest.h @@ -3,24 +3,19 @@ #include #include -#include "Strings.h" class StringsTest : public CPPUNIT_NS :: TestFixture { - CPPUNIT_TEST_SUITE (StringsTest); - CPPUNIT_TEST (addTest); - CPPUNIT_TEST (subTest); - CPPUNIT_TEST (equalTest); - CPPUNIT_TEST_SUITE_END (); + CPPUNIT_TEST_SUITE (StringsTest); + CPPUNIT_TEST (formatfTest); + CPPUNIT_TEST_SUITE_END (); - public: - void setUp (void); - void tearDown (void); +public: + void setUp (void); + void tearDown (void); - protected: - void addTest (void); - void subTest (void); - void equalTest (void); +protected: + void formatfTest(void); }; #endif //STRINGSTEST_H From 670e5f1c7290cf59b37002542290479f9075d067 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 31 Jan 2012 16:21:06 +0100 Subject: [PATCH 1880/2215] Fixed mismatching allocation and deallocation --- telldus-core/service/ProtocolIkea.cpp | 2 +- telldus-core/service/SettingsWinRegistry.cpp | 12 ++++++------ telldus-core/service/TellStick_ftd2xx.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index aae28b38..d251a4d4 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -45,7 +45,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co intUnits = intUnits | ( 1<<(9-intUnit) ); } while ( (strToken = strtok(NULL, ",")) != NULL ); - free(tempUnits); + delete[] tempUnits; std::string strReturn = "STTTTTTª"; //Startcode, always like this; diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 5ee83b2c..d4667bce 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -76,8 +76,8 @@ int Settings::getDeviceId(int intDeviceIndex) const { if (RegEnumKeyEx(hk, intDeviceIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { intReturn = _wtoi(Buff); } - - delete Buff; + + delete[] Buff; RegCloseKey(hk); } return intReturn; @@ -171,14 +171,14 @@ std::wstring Settings::getSetting(const std::wstring &strName) const{ if(lngStatus == ERROR_MORE_DATA){ //The buffer is to small, recreate it - delete Buff; + delete[] Buff; Buff = new wchar_t[dwLength]; lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); } if (lngStatus == ERROR_SUCCESS) { strReturn = Buff; } - delete Buff; + delete[] Buff; } RegCloseKey(hk); return strReturn; @@ -199,14 +199,14 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam if(lngStatus == ERROR_MORE_DATA){ //The buffer is to small, recreate it - delete Buff; + delete[] Buff; Buff = new wchar_t[dwLength]; lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); } if (lngStatus == ERROR_SUCCESS) { strReturn = Buff; } - delete Buff; + delete[] Buff; } RegCloseKey(hk); return strReturn; diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 25fdc866..e307d336 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -68,7 +68,7 @@ TellStick::TellStick(int controllerId, TelldusCore::Event *event, const TellStic #endif Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str()); FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); - delete tempSerial; + delete[] tempSerial; if (ftStatus == FT_OK) { d->open = true; FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); From f4ece8a4f9cd185c1c1f50210841ec148dd7da8c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 31 Jan 2012 16:22:10 +0100 Subject: [PATCH 1881/2215] Ignore the build directory in cppcheck --- telldus-core/tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index 951f99ca..34f46ab8 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -5,5 +5,5 @@ TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) ADD_DEPENDENCIES(TestRunner TelldusCommonTests) ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) -ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR}) +ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR} -i ${CMAKE_BINARY_DIR}) From a7405913805e3ccb9c0efa6582bd089f187146b2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 31 Jan 2012 16:23:07 +0100 Subject: [PATCH 1882/2215] Only check using cppcheck on Linux --- telldus-core/tests/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index 34f46ab8..f95e85e7 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -5,5 +5,7 @@ TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) ADD_DEPENDENCIES(TestRunner TelldusCommonTests) ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) -ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR} -i ${CMAKE_BINARY_DIR}) +IF (UNIX AND NOT APPLE) + ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR} -i ${CMAKE_BINARY_DIR}) +ENDIF() From 9f24d01e4304f63258d398262bd60714e91ef4fa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 31 Jan 2012 16:29:48 +0100 Subject: [PATCH 1883/2215] Fixed memory leak --- telldus-core/service/SettingsCoreFoundationPreferences.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index bbac1d02..2dbaeb8d 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -102,8 +102,8 @@ int Settings::getDeviceId(int intDeviceIndex) const { CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); cp = (char *)realloc( cp, strlen(cp) + 1); id = atoi(cp); - - + free(cp); + CFRelease(key); CFRelease(split); CFRelease(cfid); From 12ecb1adb990333703b2c641888181e0c83467c1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 31 Jan 2012 16:32:19 +0100 Subject: [PATCH 1884/2215] Fixed resource leak --- telldus-core/tdtool/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 2caa7562..c43f49b1 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -285,6 +285,7 @@ int send_raw_command( char *command ) { return TELLSTICK_ERROR_UNKNOWN; } fgets(msg, MAX_LENGTH, fd); + fclose(fd); } int retval = tdSendRawCommand( msg, 0 ); From 01f70d69c00f740b34ab64e0f58f192fb5d7c3a5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 10 Feb 2012 16:39:15 +0100 Subject: [PATCH 1885/2215] We must enable unit tests explicit in our builds --- telldus-core/tests/CMakeLists.txt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index f95e85e7..cd803ed0 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -1,11 +1,15 @@ -ADD_SUBDIRECTORY(common) +SET(ENABLE_TESTING FALSE CACHE BOOL "Enable unit tests") -ADD_EXECUTABLE(TestRunner cppunit.cpp) -TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) -ADD_DEPENDENCIES(TestRunner TelldusCommonTests) +IF(ENABLE_TESTING) + ADD_SUBDIRECTORY(common) -ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) -IF (UNIX AND NOT APPLE) - ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR} -i ${CMAKE_BINARY_DIR}) + ADD_EXECUTABLE(TestRunner cppunit.cpp) + TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) + ADD_DEPENDENCIES(TestRunner TelldusCommonTests) + + ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) + IF (UNIX AND NOT APPLE) + ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR} -i ${CMAKE_BINARY_DIR}) + ENDIF() ENDIF() From a1809f410ac9b8434b174ee8910c6e8ef1bf9e27 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 10 Feb 2012 16:41:04 +0100 Subject: [PATCH 1886/2215] This test seems to return undefined results --- telldus-core/tests/common/StringsTest.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/tests/common/StringsTest.cpp b/telldus-core/tests/common/StringsTest.cpp index c71a0e97..790368a1 100644 --- a/telldus-core/tests/common/StringsTest.cpp +++ b/telldus-core/tests/common/StringsTest.cpp @@ -13,7 +13,6 @@ void StringsTest :: tearDown (void) void StringsTest :: formatfTest (void) { CPPUNIT_ASSERT_EQUAL(std::string("42"), TelldusCore::formatf("%u", 42)); - CPPUNIT_ASSERT_EQUAL(std::string("0"), TelldusCore::formatf("%u", 42.1)); CPPUNIT_ASSERT_EQUAL(std::string("2A"), TelldusCore::formatf("%X", 42)); CPPUNIT_ASSERT_EQUAL(std::string("42"), TelldusCore::formatf("%s", "42")); } From af183d28709ccf26c9a8cae2f19d8e438c52fc3b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 10 Feb 2012 16:48:09 +0100 Subject: [PATCH 1887/2215] The -i option doesn't seem to be supported in the version of cppcheck used in debian 6 --- telldus-core/tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index cd803ed0..6ef2bb75 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -9,7 +9,7 @@ IF(ENABLE_TESTING) ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) IF (UNIX AND NOT APPLE) - ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR} -i ${CMAKE_BINARY_DIR}) + ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR}) ENDIF() ENDIF() From d53543922be2047966b5fbf0e41e2ba99c9f62ee Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 10 Feb 2012 16:41:05 +0000 Subject: [PATCH 1888/2215] Fix common realloc mistake --- .../SettingsCoreFoundationPreferences.cpp | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index 2dbaeb8d..c84e5fe7 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -100,8 +100,14 @@ int Settings::getDeviceId(int intDeviceIndex) const { CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1; cp = (char *)malloc(size); CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); - cp = (char *)realloc( cp, strlen(cp) + 1); - id = atoi(cp); + char *newcp = (char *)realloc( cp, strlen(cp) + 1); + if (newcp != NULL) { + cp = newcp; + id = atoi(cp); + } else { + //Should not happen + id = 0; + } free(cp); CFRelease(key); @@ -184,15 +190,22 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &wna return L""; } + std::wstring retval; char *cp = NULL; CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( value ), kCFStringEncodingUTF8) + 1; cp = (char *)malloc(size); CFStringGetCString( value, cp, size, kCFStringEncodingUTF8 ); - cp = (char *)realloc( cp, strlen(cp) + 1); + char *newcp = (char *)realloc( cp, strlen(cp) + 1); + if (newcp != NULL) { + cp = newcp; + retval = TelldusCore::charToWstring(cp); + } else { + //Should not happen + retval = L""; + } + free(cp); CFRelease(value); - std::wstring retval = TelldusCore::charToWstring(cp); - free(cp); return retval; } From 795123285752d03cefd0b375abbef4d5a4e2e762 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 13 Feb 2012 14:46:09 +0100 Subject: [PATCH 1889/2215] Add version info to all functions exported in telldus-core --- telldus-core/client/telldus-core.cpp | 142 ++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 27 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 88fa6a8d..21a82223 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -96,30 +96,51 @@ using namespace TelldusCore; * Error code. An unkown error has occurred. */ +/** + * This function initiates the library. Call this function before any other + * call to a function in telldus-core. + * + * Added in version 2.0.0. + **/ void WINAPI tdInit(void) { Client::getInstance(); //Create the manager-object } +/** + * Added in version 2.0.0. + **/ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { Client *client = Client::getInstance(); return client->registerDeviceEvent( eventFunction, context ); } +/** + * Added in version 2.0.0. + **/ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { Client *client = Client::getInstance(); return client->registerRawDeviceEvent( eventFunction, context ); } +/** + * Added in version 2.1.0. + **/ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { Client *client = Client::getInstance(); return client->registerDeviceChangeEvent( eventFunction, context ); } +/** + * Added in version 2.1.0. + **/ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { Client *client = Client::getInstance(); return client->registerSensorEvent( eventFunction, context ); } +/** + * Added in version 2.1.0. + **/ int WINAPI tdUnregisterCallback( int callbackId ) { Client *client = Client::getInstance(); return client->unregisterCallback( callbackId ); @@ -128,6 +149,8 @@ int WINAPI tdUnregisterCallback( int callbackId ) { /** * Close the library and clean up the cache it uses. * This should be called when the library is not supposed to be used anymore + * + * Added in version 2.0.0. **/ void WINAPI tdClose(void) { Client::close(); @@ -136,6 +159,8 @@ void WINAPI tdClose(void) { /** * This method releases resources allocated by telldus-core. * It should be called on the returned value from all functions return char * + * + * Added in version 2.0.1. **/ void WINAPI tdReleaseString(char *string) { #ifdef _WINDOWS @@ -145,12 +170,13 @@ void WINAPI tdReleaseString(char *string) { #endif } - /** * Turns a device on. * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to turn on. + * + * Added in version 2.0.0. **/ int WINAPI tdTurnOn(int intDeviceId){ Message msg(L"tdTurnOn"); @@ -163,7 +189,9 @@ int WINAPI tdTurnOn(int intDeviceId){ * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to turn off. - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdTurnOff(int intDeviceId){ Message msg(L"tdTurnOff"); msg.addArgument(intDeviceId); @@ -175,7 +203,9 @@ int WINAPI tdTurnOff(int intDeviceId){ * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to send bell to - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdBell(int intDeviceId){ Message msg(L"tdBell"); msg.addArgument(intDeviceId); @@ -188,7 +218,9 @@ int WINAPI tdBell(int intDeviceId){ * call to this function. * @param intDeviceId The device id to dim * @param level The level the device should dim to. This value should be 0-255 - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdDim(int intDeviceId, unsigned char level){ Message msg(L"tdDim"); msg.addArgument(intDeviceId); @@ -201,7 +233,9 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The id to execute - */ + * + * Added in version 2.1.0. + **/ int WINAPI tdExecute(int intDeviceId){ Message msg(L"tdExecute"); msg.addArgument(intDeviceId); @@ -213,7 +247,9 @@ int WINAPI tdExecute(int intDeviceId){ * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to send the command to - */ + * + * Added in version 2.1.0. + **/ int WINAPI tdUp(int intDeviceId){ Message msg(L"tdUp"); msg.addArgument(intDeviceId); @@ -225,7 +261,9 @@ int WINAPI tdUp(int intDeviceId){ * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to send the command to - */ + * + * Added in version 2.1.0. + **/ int WINAPI tdDown(int intDeviceId){ Message msg(L"tdDown"); msg.addArgument(intDeviceId); @@ -237,6 +275,8 @@ int WINAPI tdDown(int intDeviceId){ * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to stop + * + * Added in version 2.1.0. */ int WINAPI tdStop(int intDeviceId){ Message msg(L"tdStop"); @@ -250,7 +290,9 @@ int WINAPI tdStop(int intDeviceId){ * Make sure the device supports this by calling tdMethods() before any * call to this function. * @param intDeviceId The device id to learn. - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdLearn(int intDeviceId) { Message msg(L"tdLearn"); msg.addArgument(intDeviceId); @@ -262,7 +304,9 @@ int WINAPI tdLearn(int intDeviceId) { * @param intDeviceId The device id to query * @param methodsSupported The methods supported by the client. See tdMethods() for more information. * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { Message msg(L"tdLastSentCommand"); msg.addArgument(intDeviceId); @@ -274,7 +318,9 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { * If the last sent command it TELLSTICK_DIM this returns the dimmed value. * @param intDeviceId The device id to query * @returns the the value as a human readable string, example "128" for 50% - */ + * + * Added in version 2.0.0. + **/ char * WINAPI tdLastSentValue( int intDeviceId ) { Message msg(L"tdLastSentValue"); msg.addArgument(intDeviceId); @@ -285,7 +331,9 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { /** * This function returns the number of devices configured * @returns an integer of the total number of devices configured - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdGetNumberOfDevices(void){ return Client::getIntegerFromService(Message(L"tdGetNumberOfDevices")); } @@ -302,7 +350,9 @@ int WINAPI tdGetNumberOfDevices(void){ * \endcode * @param intDeviceIndex The device index to query. The index starts from 0. * @returns the unique id for the device or -1 if the device is not found. - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdGetDeviceId(int intDeviceIndex){ Message msg(L"tdGetDeviceId"); msg.addArgument(intDeviceIndex); @@ -312,7 +362,9 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ /** * Returns which type the device is. The device could be either * TELLSTICK_TYPE_DEVICE, TELLSTICK_TYPE_GROUP or TELLSTICK_TYPE_SCENE - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdGetDeviceType(int intDeviceId) { Message msg(L"tdGetDeviceType"); msg.addArgument(intDeviceId); @@ -323,7 +375,9 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * Query a device for it's name. * @param intDeviceId The unique id of the device to query * @returns The name of the device or an empty string if the device is not found. - */ + * + * Added in version 2.0.0. + **/ char * WINAPI tdGetName(int intDeviceId){ Message msg(L"tdGetName"); msg.addArgument(intDeviceId); @@ -337,7 +391,9 @@ char * WINAPI tdGetName(int intDeviceId){ * @param intDeviceId The device id to change the name for * @param strNewName The new name for the devices * @returns \c true on success, \c false otherwise. - */ + * + * Added in version 2.0.0. + **/ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ Message msg(L"tdSetName"); msg.addArgument(intDeviceId); @@ -348,7 +404,9 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ /** * @returns the protocol used by a specific device. * @param intDeviceId The device id to query. - */ + * + * Added in version 2.0.0. + **/ char* WINAPI tdGetProtocol(int intDeviceId){ Message msg(L"tdGetProtocol"); msg.addArgument(intDeviceId); @@ -364,7 +422,9 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * @returns \c true on success, \c false otherwise. * @sa tdSetModel() * @sa tdSetDeviceParameter() - */ + * + * Added in version 2.0.0. + **/ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ Message msg(L"tdSetProtocol"); msg.addArgument(intDeviceId); @@ -375,7 +435,9 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ /** * @returns the model for a device. Not all protocols uses this. * @param intDeviceId The device to query. - */ + * + * Added in version 2.0.0. + **/ char* WINAPI tdGetModel(int intDeviceId){ Message msg(L"tdGetModel"); msg.addArgument(intDeviceId); @@ -389,7 +451,9 @@ char* WINAPI tdGetModel(int intDeviceId){ * @param intDeviceId The device to change * @param strModel The new model * @returns \c true on success, \c false otherwise. - */ + * + * Added in version 2.0.0. + **/ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ Message msg(L"tdSetModel"); msg.addArgument(intDeviceId); @@ -404,7 +468,9 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * @param strName The parameter to change. * @param strValue The new value for the parameter. * @returns \c true on success, \c false otherwise. - */ + * + * Added in version 2.0.0. + **/ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ Message msg(L"tdSetDeviceParameter"); msg.addArgument(intDeviceId); @@ -418,7 +484,9 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * @param intDeviceId The device to query. * @param strName The name of the parameter to query. * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. - */ + * + * Added in version 2.0.0. + **/ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ Message msg(L"tdGetDeviceParameter"); msg.addArgument(intDeviceId); @@ -433,7 +501,9 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c * any call to tdSetName(), tdSetProtocol() and similar functions. * @returns the new device id for the newly created device. If the creation fails it returnes a * negative value. - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdAddDevice(){ Message msg(L"tdAddDevice"); return Client::getIntegerFromService(msg); @@ -442,7 +512,9 @@ int WINAPI tdAddDevice(){ /** * Removes a device. * @returns \c true on success, \c false otherwise. - */ + * + * Added in version 2.0.0. + **/ bool WINAPI tdRemoveDevice(int intDeviceId){ Message msg(L"tdRemoveDevice"); msg.addArgument(intDeviceId); @@ -471,7 +543,9 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_UP * @sa TELLSTICK_DOWN * @sa TELLSTICK_STOP - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdMethods(int id, int methodsSupported){ Message msg(L"tdMethods"); msg.addArgument(id); @@ -496,7 +570,9 @@ int WINAPI tdMethods(int id, int methodsSupported){ * @sa TELLSTICK_ERROR_BROKEN_PIPE * @sa TELLSTICK_ERROR_COMMUNICATING_SERVICE * @sa TELLSTICK_ERROR_UNKNOWN - */ + * + * Added in version 2.0.0. + **/ char * WINAPI tdGetErrorString(int intErrorNo) { const int numResponses = 10; const char *responses[numResponses] = { @@ -527,8 +603,11 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * Send a raw command to TellStick. Please read the TellStick protocol * definition on how the command should be constructed. * @param command The command for TellStick in its native format + * @param reserved Reserved for future use * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure - */ + * + * Added in version 2.0.0. + **/ int WINAPI tdSendRawCommand(const char *command, int reserved) { std::wstring wcommand; for(int i = 0; i < strlen(command);++i) { @@ -540,7 +619,9 @@ int WINAPI tdSendRawCommand(const char *command, int reserved) { return Client::getIntegerFromService(msg); } - +/** + * Added in version 2.1.0. + **/ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { Message msg(L"tdConnectTellStickController"); msg.addArgument(vid); @@ -549,6 +630,9 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { Client::getWStringFromService(msg); } +/** + * Added in version 2.1.0. + **/ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { Message msg(L"tdDisconnectTellStickController"); msg.addArgument(vid); @@ -560,6 +644,8 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial /** * Use this function to iterate over all sensors. Iterate until * TELLSTICK_SUCCESS is not returned + * + * Added in version 2.1.0. * @param protocol A byref string where the protocol of the sensor will be placed * @param protocolLen The length of the \c protocol parameter * @param model A byref string where the model of the sensor will be placed @@ -577,6 +663,8 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, * Get one of the supported sensor values from a sensor. Make sure it support * the value type first by calling tdSensor(). The triplet \c protocol, * \c model, and \c id together identifies a sensor. + * + * Added in version 2.1.0. * @param protocol The protocol for the sensor * @param model The model for the sensor * @param id The id of the sensor From 629fbaca9985c75f9ac9886b2aca3ee3f81091e0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 13 Feb 2012 18:13:25 +0100 Subject: [PATCH 1890/2215] Escape paths --- telldus-core/client/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 5f328c63..7ec93967 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -92,7 +92,7 @@ IF (WIN32) FOREACH(_FILE ${telldus-core_PUB_HDRS}) ADD_CUSTOM_COMMAND( TARGET ${telldus-core_TARGET} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}" "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}" + COMMAND ${CMAKE_COMMAND} -E copy \"${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}\" \"${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\" COMMENT "Copy ${_FILE}" ) ENDFOREACH(_FILE) From 2896cc74ad80596dd65a65596d95d14be7a32369 Mon Sep 17 00:00:00 2001 From: Lauri Date: Mon, 20 Feb 2012 09:24:22 +0100 Subject: [PATCH 1891/2215] Add missing include stdarg.h, seems to be needed by uClibc --- telldus-core/service/Log.h | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/Log.h b/telldus-core/service/Log.h index a2f547c0..c204e75d 100644 --- a/telldus-core/service/Log.h +++ b/telldus-core/service/Log.h @@ -2,6 +2,7 @@ #define LOG_H #include +#include class Log { public: From 0fda29f7a1833d82f7343e074ab806b58c5133f4 Mon Sep 17 00:00:00 2001 From: Lauri Date: Mon, 20 Feb 2012 09:27:28 +0100 Subject: [PATCH 1892/2215] The udev script should be sh instead of bash to keep dependencies low --- telldus-core/tdadmin/udev.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/tdadmin/udev.sh b/telldus-core/tdadmin/udev.sh index 77f8364d..8993f81c 100755 --- a/telldus-core/tdadmin/udev.sh +++ b/telldus-core/tdadmin/udev.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh if [ "${ID_VENDOR_ID}" == "1781" ]; then if [ "${ACTION}" == "add" ]; then From f34e1ad53ff0a7c476b99d1bc12c4957ba96cc97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B6rn=20L=C3=B6nnemark?= Date: Fri, 17 Feb 2012 23:36:55 +0100 Subject: [PATCH 1893/2215] Fix Client::close to allow for reinitialization Make sure Client::close cleans up properly to allow for reinitialization of the Client class. Closes #188 --- telldus-core/client/Client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 17a038ae..cf278757 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -66,6 +66,7 @@ Client::~Client(void) { void Client::close() { if (Client::instance != 0) { delete Client::instance; + Client::instance = 0; } } From 799c25f98ee032ef9e67f2475b24691fcbd2e379 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 13 Feb 2012 18:05:09 +0100 Subject: [PATCH 1894/2215] Refactor ControllerManager's list of controllers to allow for metadata storage and loaded controller without an actual connected controller --- telldus-core/service/ControllerManager.cpp | 43 +++++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 27d8b283..c5421612 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -8,7 +8,14 @@ #include #include -typedef std::map ControllerMap; +class ControllerDescriptor { +public: + std::string name; + int type; + Controller *controller; +}; + +typedef std::map ControllerMap; class ControllerManager::PrivateData { public: @@ -27,7 +34,9 @@ ControllerManager::ControllerManager(TelldusCore::Event *event){ ControllerManager::~ControllerManager() { for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - delete( it->second ); + if (it->second.controller) { + delete( it->second.controller ); + } } delete d; } @@ -41,7 +50,7 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str TelldusCore::MutexLocker locker(&d->mutex); while(d->controllers.size()) { ControllerMap::iterator it = d->controllers.begin(); - delete it->second; + delete it->second.controller; d->controllers.erase(it); } } @@ -62,7 +71,10 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str while(again) { again = false; for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - TellStick *tellstick = reinterpret_cast(it->second); + if (!it->second.controller) { + continue; + } + TellStick *tellstick = reinterpret_cast(it->second.controller); if (!tellstick) { continue; } @@ -94,9 +106,9 @@ Controller *ControllerManager::getBestControllerById(int id) { } ControllerMap::const_iterator it = d->controllers.find(id); if (it != d->controllers.end()) { - return it->second; + return it->second.controller; } - return d->controllers.begin()->second; + return d->controllers.begin()->second.controller; } @@ -112,7 +124,10 @@ void ControllerManager::loadControllers() { bool found = false; ControllerMap::const_iterator cit = d->controllers.begin(); for(; cit != d->controllers.end(); ++cit) { - TellStick *tellstick = reinterpret_cast(cit->second); + if (!cit->second.controller) { + continue; + } + TellStick *tellstick = reinterpret_cast(cit->second.controller); if (!tellstick) { continue; } @@ -125,14 +140,19 @@ void ControllerManager::loadControllers() { continue; } - int controllerId = d->lastControllerId-1; + int controllerId = d->lastControllerId+1; TellStick *controller = new TellStick(controllerId, d->event, *it); if (!controller->isOpen()) { delete controller; continue; } d->lastControllerId = controllerId; - d->controllers[d->lastControllerId] = controller; + d->controllers[d->lastControllerId].controller = controller; + if (controller->pid() == 0x0c30) { + d->controllers[d->lastControllerId].type = TELLSTICK_CONTROLLER_TELLSTICK; + } else { + d->controllers[d->lastControllerId].type = TELLSTICK_CONTROLLER_TELLSTICK_DUO; + } } } @@ -143,7 +163,10 @@ void ControllerManager::queryControllerStatus(){ { TelldusCore::MutexLocker locker(&d->mutex); for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - TellStick *tellstick = reinterpret_cast(it->second); + if (!it->second.controller) { + continue; + } + TellStick *tellstick = reinterpret_cast(it->second.controller); if (tellstick) { tellStickControllers.push_back(tellstick); } From 00eeea1283b5dc8168ff7b48b95fcdd92fe5b792 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 13 Feb 2012 18:08:21 +0100 Subject: [PATCH 1895/2215] Add function to query controllers in the service --- telldus-core/client/telldus-core.h | 5 +++++ .../service/ClientCommunicationHandler.cpp | 11 +++++++---- .../service/ClientCommunicationHandler.h | 8 +++++++- telldus-core/service/ControllerManager.cpp | 17 +++++++++++++++++ telldus-core/service/ControllerManager.h | 2 ++ telldus-core/service/TelldusMain.cpp | 2 +- 6 files changed, 39 insertions(+), 6 deletions(-) diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 87eb6132..f78d6bcc 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -125,6 +125,11 @@ extern "C" { #define TELLSTICK_TYPE_GROUP 2 #define TELLSTICK_TYPE_SCENE 3 +//Controller typedef +#define TELLSTICK_CONTROLLER_TELLSTICK 1 +#define TELLSTICK_CONTROLLER_TELLSTICK_DUO 2 +#define TELLSTICK_CONTROLLER_TELLSTICK_NET 3 + //Device changes #define TELLSTICK_DEVICE_ADDED 1 #define TELLSTICK_DEVICE_CHANGED 2 diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 96342382..f0278bd6 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -10,13 +10,14 @@ public: TelldusCore::EventRef event, deviceUpdateEvent; bool done; DeviceManager *deviceManager; + ControllerManager *controllerManager; }; ClientCommunicationHandler::ClientCommunicationHandler(){ } -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent) +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent, ControllerManager *controllerManager) :Thread() { d = new PrivateData; @@ -25,7 +26,7 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie d->done = false; d->deviceManager = deviceManager; d->deviceUpdateEvent = deviceUpdateEvent; - + d->controllerManager = controllerManager; } ClientCommunicationHandler::~ClientCommunicationHandler(void) @@ -230,8 +231,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int dataType = TelldusCore::Message::takeInt(&msg); (*wstringReturn) = d->deviceManager->getSensorValue(protocol, model, id, dataType); - } - else{ + } else if (function == L"tdController") { + (*wstringReturn) = d->controllerManager->getControllers(); + + } else{ (*intReturn) = TELLSTICK_ERROR_UNKNOWN; } } diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 7333775a..08c9d421 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -12,7 +12,13 @@ class ClientCommunicationHandler : public TelldusCore::Thread { public: ClientCommunicationHandler(); - ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent); + ClientCommunicationHandler( + TelldusCore::Socket *clientSocket, + TelldusCore::EventRef event, + DeviceManager *deviceManager, + TelldusCore::EventRef deviceUpdateEvent, + ControllerManager *controllerManager + ); ~ClientCommunicationHandler(void); bool isDone(); diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index c5421612..ef5a73b7 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -3,6 +3,7 @@ #include "Mutex.h" #include "TellStick.h" #include "Log.h" +#include "Message.h" #include "../client/telldus-core.h" #include @@ -202,3 +203,19 @@ int ControllerManager::resetController(Controller *controller) { deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete return success; } + +std::wstring ControllerManager::getControllers() const { + TelldusCore::MutexLocker locker(&d->mutex); + + TelldusCore::Message msg; + + msg.addArgument((int)d->controllers.size()); + + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + msg.addArgument(it->first); + msg.addArgument(it->second.type); + msg.addArgument(it->second.name.c_str()); + msg.addArgument(it->second.controller ? 1 : 0); + } + return msg; +} diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index a3d0c6bb..2c0a16aa 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -20,6 +20,8 @@ public: void queryControllerStatus(); int resetController(Controller *controller); + std::wstring getControllers() const; + private: class PrivateData; PrivateData *d; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 9cac2660..edf4c9de 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -91,7 +91,7 @@ void TelldusMain::start(void) { TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent); + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent, &controllerManager); clientCommunication->start(); clientCommunicationHandlerList.push_back(clientCommunication); } From 2b7f02bbb405071bc97b6092901e8bc10823691c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 13 Feb 2012 18:10:20 +0100 Subject: [PATCH 1896/2215] Add public function tdController() to telldus-core. See #108 --- telldus-core/client/Client.cpp | 46 +++++++++++++++++++++++++--- telldus-core/client/Client.h | 1 + telldus-core/client/telldus-core.cpp | 19 ++++++++++++ telldus-core/client/telldus-core.h | 2 ++ 4 files changed, 64 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index cf278757..34c79968 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -32,8 +32,8 @@ public: Socket eventSocket; RawDeviceEventList rawDeviceEventList; SensorEventList sensorEventList; - bool running, sensorCached; - std::wstring sensorCache; + bool running, sensorCached, controllerCached; + std::wstring sensorCache, controllerCache; TelldusCore::Mutex mutex; std::list > deviceEventThreadList; @@ -287,7 +287,7 @@ void Client::cleanupCallbacks() { } std::wstring Client::sendToService(const Message &msg) { - + int tries = 0; std::wstring readData; while(tries < 20){ @@ -314,7 +314,7 @@ std::wstring Client::sendToService(const Message &msg) { continue; //TODO can we be really sure it SHOULD be anything? //TODO perhaps break here instead? } - + if (!s.isConnected()) { //Connection failed sometime during operation... msleep(500); continue; //retry @@ -449,3 +449,41 @@ int Client::getSensor(char *protocol, int protocolLen, char *model, int modelLen return TELLSTICK_SUCCESS; } + +int Client::getController(int *controllerId, int *controllerType, char *name, int nameLen, int *available) { + if (!d->controllerCached) { + Message msg(L"tdController"); + std::wstring response = Client::getWStringFromService(msg); + int count = Message::takeInt(&response); + d->controllerCached = true; + d->controllerCache = L""; + if (count > 0) { + d->controllerCache = response; + } + } + + if (d->controllerCache == L"") { + d->controllerCached = false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + int id = Message::takeInt(&d->controllerCache); + int type = Message::takeInt(&d->controllerCache); + std::wstring n = Message::takeString(&d->controllerCache); + int a = Message::takeInt(&d->controllerCache); + + if (controllerId) { + (*controllerId) = id; + } + if (controllerType) { + (*controllerType) = type; + } + if (name && nameLen) { + strncpy(name, TelldusCore::wideToString(n).c_str(), nameLen); + } + if (available) { + (*available) = a; + } + + return TELLSTICK_SUCCESS; +} diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 4287f83c..153acb75 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -26,6 +26,7 @@ namespace TelldusCore { bool unregisterCallback( int callbackId ); int getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); + int getController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); static bool getBoolFromService(const Message &msg); static int getIntegerFromService(const Message &msg); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 21a82223..889a1adc 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -697,5 +697,24 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da return TELLSTICK_SUCCESS; } +/** + * Use this function to iterate over all controllers. Iterate until + * TELLSTICK_SUCCESS is not returned + * + * Added in version 2.1.2. + * @param controllerId A byref int where the id of the controller will be placed + * @param controllerType A byref int where the type of the controller will be placed + * @param name A byref string where the name of the controller will be placed + * @param nameLen The length of the \c name parameter + * @param available A byref int if the controller is currently available or maybe disconnected + * @returns TELLSTICK_SUCCESS if there is more sensors to be fetched + * @sa TELLSTICK_CONTROLLER_TELLSTICK + * @sa TELLSTICK_CONTROLLER_TELLSTICK_DUO + * @sa TELLSTICK_CONTROLLER_TELLSTICK_NET + **/ +int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available) { + Client *client = Client::getInstance(); + return client->getController(controllerId, controllerType, name, nameLen, available); +} /* @} */ diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index f78d6bcc..899f2a34 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -86,6 +86,8 @@ extern "C" { TELLSTICK_API int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); + TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); + #ifdef __cplusplus } #endif From f8226be943f5d023e4c74835c7e4aa506069d022 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 14 Feb 2012 11:24:28 +0100 Subject: [PATCH 1897/2215] Add overloaded function ConfigurationDialog::addPage() to load a QWidget directly --- telldus-gui/TelldusCenter/configurationdialog.cpp | 6 ++++++ telldus-gui/TelldusCenter/configurationdialog.h | 1 + 2 files changed, 7 insertions(+) diff --git a/telldus-gui/TelldusCenter/configurationdialog.cpp b/telldus-gui/TelldusCenter/configurationdialog.cpp index 938dc77b..703e0dcf 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.cpp +++ b/telldus-gui/TelldusCenter/configurationdialog.cpp @@ -87,6 +87,12 @@ QScriptValue ConfigurationDialog::addPage( const QString &name, const QString &f QWidget *widget = loader.load(&file, this); file.close(); + return this->addPage(name, widget, icon); +} + +QScriptValue ConfigurationDialog::addPage(const QString &name, QWidget *widget, const QString &icon) { + QDir dir = this->baseDir(); + int index = d->stackedLayout->addWidget(widget); QListWidgetItem *item = new QListWidgetItem(QIcon(dir.filePath(icon)), name, d->listWidget); diff --git a/telldus-gui/TelldusCenter/configurationdialog.h b/telldus-gui/TelldusCenter/configurationdialog.h index 171500fc..c91c082a 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.h +++ b/telldus-gui/TelldusCenter/configurationdialog.h @@ -20,6 +20,7 @@ signals: public slots: QScriptValue addPage( const QString &name, const QString &file, const QString &icon ); + QScriptValue addPage( const QString &name, QWidget *widget, const QString &icon); void open(); void valueChanged(); From 979e6082c2fbd03afe7655512c318913c858246e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 10:24:04 +0100 Subject: [PATCH 1898/2215] Implement tdSetControllerValue in TelldusService --- .../service/ClientCommunicationHandler.cpp | 6 ++++++ telldus-core/service/ControllerManager.cpp | 16 ++++++++++++++++ telldus-core/service/ControllerManager.h | 1 + 3 files changed, 23 insertions(+) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index f0278bd6..b3823d21 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -234,6 +234,12 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdController") { (*wstringReturn) = d->controllerManager->getControllers(); + } else if (function == L"tdSetControllerValue") { + int id = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring value = TelldusCore::Message::takeString(&msg); + (*intReturn) = d->controllerManager->setControllerValue(id, name, value); + } else{ (*intReturn) = TELLSTICK_ERROR_UNKNOWN; } diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index ef5a73b7..8eb0ee7e 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -4,6 +4,7 @@ #include "TellStick.h" #include "Log.h" #include "Message.h" +#include "Strings.h" #include "../client/telldus-core.h" #include @@ -219,3 +220,18 @@ std::wstring ControllerManager::getControllers() const { } return msg; } + +int ControllerManager::setControllerValue(int id, const std::wstring &name, const std::wstring &value) { + TelldusCore::MutexLocker locker(&d->mutex); + + ControllerMap::iterator it = d->controllers.find(id); + if (it == d->controllers.end()) { + return TELLSTICK_ERROR_NOT_FOUND; + } + if (name == L"name") { + it->second.name = TelldusCore::wideToString(value); + } else { + return TELLSTICK_ERROR_SYNTAX; //TODO: Is this the best error? + } + return TELLSTICK_SUCCESS; +} diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 2c0a16aa..33fa774e 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -21,6 +21,7 @@ public: int resetController(Controller *controller); std::wstring getControllers() const; + int setControllerValue(int id, const std::wstring &name, const std::wstring &value); private: class PrivateData; From cd044d818d26e33ce2900e193b4280926724e979 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 10:25:07 +0100 Subject: [PATCH 1899/2215] Implement tdSetControllerValue in telldus-core --- telldus-core/client/telldus-core.cpp | 17 +++++++++++++++++ telldus-core/client/telldus-core.h | 1 + 2 files changed, 18 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 889a1adc..f473186a 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -717,4 +717,21 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int return client->getController(controllerId, controllerType, name, nameLen, available); } +/** + * This function sets a parameter on a controller. + * Valid parameters are: \c name + * + * Added in version 2.1.2. + * @param controllerId The controller to change + * @param name The parameter to change. + * @param value The new value for the parameter. + **/ +int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value) { + Message msg(L"tdSetControllerValue"); + msg.addArgument(controllerId); + msg.addArgument(name); + msg.addArgument(value); + return Client::getIntegerFromService(msg); +} + /* @} */ diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 899f2a34..2e92daef 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -87,6 +87,7 @@ extern "C" { TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); + TELLSTICK_API int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value); #ifdef __cplusplus } From 433f4db3e0f176767e7288fdaab279db6d537595 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 10:27:28 +0100 Subject: [PATCH 1900/2215] Make the mutex for Settings static to be shared between instances --- telldus-core/service/Settings.cpp | 2 ++ telldus-core/service/Settings.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index a32fffef..7c98db50 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -1,5 +1,7 @@ #include "Settings.h" +TelldusCore::Mutex Settings::mutex; + /* * Get the name of the device */ diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 730e3fdb..e5b11b47 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -40,7 +40,7 @@ private: class PrivateData; PrivateData *d; - mutable TelldusCore::Mutex mutex; + static TelldusCore::Mutex mutex; }; #endif From 541e656fe1c6ff89ba655af5c151f7472a5fdb4f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 10:28:18 +0100 Subject: [PATCH 1901/2215] Add controllers to our settings file --- telldus-core/service/SettingsConfuse.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 9c0c7084..36d140f9 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -345,6 +345,13 @@ bool readConfig(cfg_t **cfg) { //All the const_cast keywords is to remove the compiler warnings generated by the C++-compiler. cfg_opt_t controller_opts[] = { CFG_INT(const_cast("id"), -1, CFGF_NONE), + CFG_STR(const_cast("name"), const_cast("Unnamed"), CFGF_NONE), + CFG_STR(const_cast("type"), 0, CFGF_NONE), + CFG_STR(const_cast("vid"), 0, CFGF_NONE), + CFG_STR(const_cast("pid"), 0, CFGF_NONE), + CFG_STR(const_cast("serial"), const_cast(""), CFGF_NONE), + + CFG_END() }; cfg_opt_t device_parameter_opts[] = { @@ -377,6 +384,7 @@ bool readConfig(cfg_t **cfg) { CFG_STR(const_cast("deviceNode"), const_cast("/dev/tellstick"), CFGF_NONE), CFG_STR(const_cast("ignoreControllerConfirmation"), const_cast("false"), CFGF_NONE), CFG_SEC(const_cast("device"), device_opts, CFGF_MULTI), + CFG_SEC(const_cast("controller"), controller_opts, CFGF_MULTI), CFG_END() }; From 1ad79b663ed357f56f631cd470ebcda7c0a3d987 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 10:28:54 +0100 Subject: [PATCH 1902/2215] Add function Settings::getNumberOfControllers() --- telldus-core/service/Settings.h | 2 ++ telldus-core/service/SettingsConfuse.cpp | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index e5b11b47..0aff65ee 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -25,6 +25,8 @@ public: int getPreferredControllerId(int intDeviceId); int setPreferredControllerId(int intDeviceId, int value); + int getNumberOfControllers(void) const; + int addDevice(); int getDeviceId(int intDeviceIndex) const; int removeDevice(int intDeviceId); diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 36d140f9..dadba651 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -84,6 +84,14 @@ int Settings::getNumberOfDevices(void) const { return 0; } +int Settings::getNumberOfControllers() const { + TelldusCore::MutexLocker locker(&mutex); + if (d->cfg > 0) { + return cfg_size(d->cfg, "controller"); + } + return 0; +} + int Settings::getDeviceId(int intDeviceIndex) const { if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds return -1; From 39265caa01a155d7a39c3978bf167dac8e8a698f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 11:33:58 +0100 Subject: [PATCH 1903/2215] Refactor to reuse same functions in settings for both devices and controllers --- telldus-core/service/DeviceManager.cpp | 14 +-- telldus-core/service/Settings.cpp | 33 +++--- telldus-core/service/Settings.h | 27 ++--- telldus-core/service/SettingsConfuse.cpp | 132 +++++++++++++---------- 4 files changed, 116 insertions(+), 90 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 2d074963..701f681c 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -47,13 +47,13 @@ DeviceManager::~DeviceManager(void) { } void DeviceManager::fillDevices(){ - int numberOfDevices = d->set.getNumberOfDevices(); + int numberOfDevices = d->set.getNumberOfNodes(Settings::Device); TelldusCore::MutexLocker deviceListLocker(&d->lock); for (int i = 0; i < numberOfDevices; ++i) { - int id = d->set.getDeviceId(i); + int id = d->set.getNodeId(Settings::Device, i); d->devices[id] = new Device(id); - d->devices[id]->setName(d->set.getName(id)); + d->devices[id]->setName(d->set.getName(Settings::Device, id)); d->devices[id]->setModel(d->set.getModel(id)); d->devices[id]->setProtocolName(d->set.getProtocol(id)); d->devices[id]->setPreferredControllerId(d->set.getPreferredControllerId(id)); @@ -235,7 +235,7 @@ int DeviceManager::setDeviceName(int deviceId, const std::wstring &name){ DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); - int ret = d->set.setName(deviceId, name); + int ret = d->set.setName(Settings::Device, deviceId, name); if (ret != TELLSTICK_SUCCESS) { return ret; } @@ -330,7 +330,7 @@ int DeviceManager::getNumberOfDevices(){ int DeviceManager::addDevice(){ - int id = d->set.addDevice(); + int id = d->set.addNode(Settings::Device); if(id < 0){ return id; } @@ -344,7 +344,7 @@ int DeviceManager::addDevice(){ } int DeviceManager::getDeviceId(int deviceIndex) { - return d->set.getDeviceId(deviceIndex); + return d->set.getNodeId(Settings::Device, deviceIndex); } int DeviceManager::getDeviceType(int deviceId){ @@ -573,7 +573,7 @@ int DeviceManager::removeDevice(int deviceId){ Device *device = 0; { - int ret = d->set.removeDevice(deviceId); //remove from register/settings + int ret = d->set.removeNode(Settings::Device, deviceId); //remove from register/settings if (ret != TELLSTICK_SUCCESS) { return ret; } diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 7c98db50..447b9afa 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -5,17 +5,17 @@ TelldusCore::Mutex Settings::mutex; /* * Get the name of the device */ -std::wstring Settings::getName(int intDeviceId) const { +std::wstring Settings::getName(Node type, int intNodeId) const { TelldusCore::MutexLocker locker(&mutex); - return getStringSetting(intDeviceId, L"name", false); + return getStringSetting(type, intNodeId, L"name", false); } /* * Set the name of the device */ -int Settings::setName(int intDeviceId, const std::wstring &strNewName){ +int Settings::setName(Node type, int intDeviceId, const std::wstring &strNewName){ TelldusCore::MutexLocker locker(&mutex); - return setStringSetting(intDeviceId, L"name", strNewName, false); + return setStringSetting(type, intDeviceId, L"name", strNewName, false); } /* @@ -23,7 +23,7 @@ int Settings::setName(int intDeviceId, const std::wstring &strNewName){ */ std::wstring Settings::getProtocol(int intDeviceId) const { TelldusCore::MutexLocker locker(&mutex); - return getStringSetting(intDeviceId, L"protocol", false); + return getStringSetting(Device, intDeviceId, L"protocol", false); } /* @@ -31,7 +31,7 @@ std::wstring Settings::getProtocol(int intDeviceId) const { */ int Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ TelldusCore::MutexLocker locker(&mutex); - return setStringSetting(intDeviceId, L"protocol", strVendor, false); + return setStringSetting(Device, intDeviceId, L"protocol", strVendor, false); } /* @@ -39,7 +39,7 @@ int Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ */ std::wstring Settings::getModel(int intDeviceId) const { TelldusCore::MutexLocker locker(&mutex); - return getStringSetting(intDeviceId, L"model", false); + return getStringSetting(Device, intDeviceId, L"model", false); } /* @@ -47,7 +47,7 @@ std::wstring Settings::getModel(int intDeviceId) const { */ int Settings::setModel(int intDeviceId, const std::wstring &strModel){ TelldusCore::MutexLocker locker(&mutex); - return setStringSetting(intDeviceId, L"model", strModel, false); + return setStringSetting(Device, intDeviceId, L"model", strModel, false); } /* @@ -55,7 +55,7 @@ int Settings::setModel(int intDeviceId, const std::wstring &strModel){ */ int Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue){ TelldusCore::MutexLocker locker(&mutex); - return setStringSetting(intDeviceId, strName, strValue, true); + return setStringSetting(Device, intDeviceId, strName, strValue, true); } /* @@ -63,7 +63,7 @@ int Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, c */ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &strName) const { TelldusCore::MutexLocker locker(&mutex); - return getStringSetting(intDeviceId, strName, true); + return getStringSetting(Device, intDeviceId, strName, true); } /* @@ -71,7 +71,7 @@ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &s */ int Settings::setPreferredControllerId(int intDeviceId, int value){ TelldusCore::MutexLocker locker(&mutex); - return setIntSetting(intDeviceId, L"controller", value, false); + return setIntSetting(Device, intDeviceId, L"controller", value, false); } /* @@ -79,7 +79,16 @@ int Settings::setPreferredControllerId(int intDeviceId, int value){ */ int Settings::getPreferredControllerId(int intDeviceId) { TelldusCore::MutexLocker locker(&mutex); - return getIntSetting(intDeviceId, L"controller", false); + return getIntSetting(Device, intDeviceId, L"controller", false); +} + + +std::string Settings::getNodeString(Settings::Node type) const { + if (type == Device) { + return "device"; + } else if (type == Controller) { + return "controller"; + } } #ifndef _CONFUSE diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 0aff65ee..9db50628 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -6,13 +6,15 @@ class Settings { public: + enum Node { Device, Controller }; + Settings(void); virtual ~Settings(void); std::wstring getSetting(const std::wstring &strName) const; - int getNumberOfDevices(void) const; - std::wstring getName(int intDeviceId) const; - int setName(int intDeviceId, const std::wstring &strNewName); + int getNumberOfNodes(Node type) const; + std::wstring getName(Node type, int intNodeId) const; + int setName(Node type, int intDeviceId, const std::wstring &strNewName); std::wstring getProtocol(int intDeviceId) const; int setProtocol(int intDeviceId, const std::wstring &strVendor); std::wstring getModel(int intDeviceId) const; @@ -25,20 +27,19 @@ public: int getPreferredControllerId(int intDeviceId); int setPreferredControllerId(int intDeviceId, int value); - int getNumberOfControllers(void) const; - - int addDevice(); - int getDeviceId(int intDeviceIndex) const; - int removeDevice(int intDeviceId); + int addNode(Node type); + int getNodeId(Node type, int intDeviceIndex) const; + int removeNode(Node type, int intNodeId); protected: - std::wstring getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const; - int setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter); - int getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const; - int setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter); + std::wstring getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const; + int setStringSetting(Node type, int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter); + int getIntSetting(Node type, int intDeviceId, const std::wstring &name, bool parameter) const; + int setIntSetting(Node type, int intDeviceId, const std::wstring &name, int value, bool parameter); private: - int getNextDeviceId() const; + int getNextNodeId(Node type) const; + std::string getNodeString(Node type) const; class PrivateData; PrivateData *d; diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index dadba651..ebe0e8c2 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -76,94 +76,107 @@ std::wstring Settings::getSetting(const std::wstring &strName) const { /* * Return the number of stored devices */ -int Settings::getNumberOfDevices(void) const { +int Settings::getNumberOfNodes(Node node) const { TelldusCore::MutexLocker locker(&mutex); if (d->cfg > 0) { - return cfg_size(d->cfg, "device"); + if (node == Device) { + return cfg_size(d->cfg, "device"); + } else if (node == Controller) { + return cfg_size(d->cfg, "controller"); + } } return 0; } -int Settings::getNumberOfControllers() const { - TelldusCore::MutexLocker locker(&mutex); - if (d->cfg > 0) { - return cfg_size(d->cfg, "controller"); - } - return 0; -} - -int Settings::getDeviceId(int intDeviceIndex) const { - if (intDeviceIndex >= getNumberOfDevices()) { //Out of bounds +int Settings::getNodeId(Node type, int intDeviceIndex) const { + if (intDeviceIndex >= getNumberOfNodes(type)) { //Out of bounds return -1; } TelldusCore::MutexLocker locker(&mutex); - cfg_t *cfg_device = cfg_getnsec(d->cfg, "device", intDeviceIndex); - int id = cfg_getint(cfg_device, "id"); + cfg_t *cfg_node; + if (type == Device) { + cfg_node = cfg_getnsec(d->cfg, "device", intDeviceIndex); + } else if (type == Controller) { + cfg_node = cfg_getnsec(d->cfg, "controller", intDeviceIndex); + } + int id = cfg_getint(cfg_node, "id"); return id; } /* -* Add a new device +* Add a new node */ -int Settings::addDevice(){ +int Settings::addNode(Node type){ TelldusCore::MutexLocker locker(&mutex); - int intDeviceId = getNextDeviceId(); + int intNodeId = getNextNodeId(type); FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } cfg_print(d->cfg, fp); //Print the config-file - fprintf(fp, "device {\n id=%d\n}\n", intDeviceId); //Print the new device + if (type == Device) { + fprintf(fp, "device {\n id=%d\n}\n", intNodeId); //Print the new device + } else if (type == Controller) { + fprintf(fp, "controller {\n id=%d\n}\n", intNodeId); //Print the new controller + } fclose(fp); //Re-read config-file cfg_free(d->cfg); readConfig(&d->cfg); - return intDeviceId; + return intNodeId; } /* -* Get next available device id +* Get next available node id */ -int Settings::getNextDeviceId() const { +int Settings::getNextNodeId(Node type) const { //Private, no locks needed - int intDeviceId = 0; - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") >= intDeviceId) { - intDeviceId = cfg_getint(cfg_device, "id"); + int intNodeId = 0; + cfg_t *cfg_node; + std::string strType; + if (type == Device) { + strType = "device"; + } else if (type == Controller) { + strType = "controller"; + } + for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { + cfg_node = cfg_getnsec(d->cfg, strType.c_str(), i); + if (cfg_getint(cfg_node, "id") >= intNodeId) { + intNodeId = cfg_getint(cfg_node, "id"); } } - intDeviceId++; - return intDeviceId; + intNodeId++; + return intNodeId; } /* * Remove a device */ -int Settings::removeDevice(int intDeviceId){ +int Settings::removeNode(Node type, int intNodeId){ TelldusCore::MutexLocker locker(&mutex); FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } + std::string strType = getNodeString(type); + // Print all opts for(int i = 0; d->cfg->opts[i].name; i++) { // Check if it isn't a device section - if (strcmp(d->cfg->opts[i].name, "device") != 0) { + if (strcmp(d->cfg->opts[i].name, strType.c_str()) != 0) { cfg_opt_print(&d->cfg->opts[i], fp); } else { // Print all sections except the one to remove - cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") != intDeviceId) { //This isn't the one to skip - fprintf(fp, "device {\n"); - cfg_print_indent(cfg_device, fp, 1); + cfg_t *cfg_node; + for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { + cfg_node = cfg_getnsec(d->cfg, strType.c_str(), i); + if (cfg_getint(cfg_node, "id") != intNodeId) { //This isn't the one to skip + fprintf(fp, "%s {\n", strType.c_str()); + cfg_print_indent(cfg_node, fp, 1); fprintf(fp, "}\n"); } } @@ -252,15 +265,17 @@ std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { return L""; } -std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const { +std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { //already locked if (d->cfg == 0) { return L""; } + std::string strType = getNodeString(type); + cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") == intDeviceId) { + for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { + cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i); + if (cfg_getint(cfg_device, "id") == intNodeId) { if (parameter) { cfg_device = cfg_getsec(cfg_device, "parameters"); } @@ -275,14 +290,15 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam return L""; } -int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { +int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { //already locked if (d->cfg == 0) { return TELLSTICK_ERROR_PERMISSION_DENIED; } + std::string strType = getNodeString(type); cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); + for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { + cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i); if (cfg_getint(cfg_device, "id") == intDeviceId) { std::string newValue = TelldusCore::wideToString(value); if (parameter) { @@ -303,32 +319,34 @@ int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const { +int Settings::getIntSetting(Node type, int intDeviceId, const std::wstring &name, bool parameter) const { //already locked if (d->cfg == 0) { return 0; } - cfg_t *cfg_device; - for(int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); - if (cfg_getint(cfg_device, "id") == intDeviceId) { + std::string strType = getNodeString(type); + cfg_t *cfg_node; + for(int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { + cfg_node = cfg_getnsec(d->cfg, strType.c_str(), i); + if (cfg_getint(cfg_node, "id") == intDeviceId) { if (parameter) { - cfg_device = cfg_getsec(cfg_device, "parameters"); + cfg_node = cfg_getsec(cfg_node, "parameters"); } - return cfg_getint(cfg_device, TelldusCore::wideToString(name).c_str()); + return cfg_getint(cfg_node, TelldusCore::wideToString(name).c_str()); } } return 0; } -int Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { +int Settings::setIntSetting(Node type, int intDeviceId, const std::wstring &name, int value, bool parameter) { //already locked if (d->cfg == 0) { return TELLSTICK_ERROR_PERMISSION_DENIED; } + std::string strType = getNodeString(type); cfg_t *cfg_device; - for (int i = 0; i < cfg_size(d->cfg, "device"); ++i) { - cfg_device = cfg_getnsec(d->cfg, "device", i); + for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { + cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i); if (cfg_getint(cfg_device, "id") == intDeviceId) { if (parameter) { cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); @@ -353,10 +371,8 @@ bool readConfig(cfg_t **cfg) { //All the const_cast keywords is to remove the compiler warnings generated by the C++-compiler. cfg_opt_t controller_opts[] = { CFG_INT(const_cast("id"), -1, CFGF_NONE), - CFG_STR(const_cast("name"), const_cast("Unnamed"), CFGF_NONE), - CFG_STR(const_cast("type"), 0, CFGF_NONE), - CFG_STR(const_cast("vid"), 0, CFGF_NONE), - CFG_STR(const_cast("pid"), 0, CFGF_NONE), + CFG_STR(const_cast("name"), const_cast(""), CFGF_NONE), + CFG_INT(const_cast("type"), 0, CFGF_NONE), CFG_STR(const_cast("serial"), const_cast(""), CFGF_NONE), CFG_END() From 62fa35926cb8aebdde02a70f59a1bcab3eb14466 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 14:31:27 +0100 Subject: [PATCH 1904/2215] Name should be wide --- telldus-core/service/ControllerManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 8eb0ee7e..c2a431e0 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -12,7 +12,7 @@ class ControllerDescriptor { public: - std::string name; + std::wstring name; int type; Controller *controller; }; @@ -229,7 +229,7 @@ int ControllerManager::setControllerValue(int id, const std::wstring &name, cons return TELLSTICK_ERROR_NOT_FOUND; } if (name == L"name") { - it->second.name = TelldusCore::wideToString(value); + it->second.name = value; } else { return TELLSTICK_ERROR_SYNTAX; //TODO: Is this the best error? } From 210b41b262498ab68de60a0f6843d0ad5ca1bdf2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 14:33:39 +0100 Subject: [PATCH 1905/2215] Add function QMLView::sizeRootObjectToView() --- telldus-gui/Plugins/QML/qmlview.cpp | 8 ++++++++ telldus-gui/Plugins/QML/qmlview.h | 1 + 2 files changed, 9 insertions(+) diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp index 6d12cc0f..5fd8d2f7 100644 --- a/telldus-gui/Plugins/QML/qmlview.cpp +++ b/telldus-gui/Plugins/QML/qmlview.cpp @@ -69,3 +69,11 @@ void QMLView::setProperty( const QString & name, const QScriptValue &value ) { context->setContextProperty(name, value.toVariant()); } } + +void QMLView::sizeRootObjectToView(bool enable) { + if (enable) { + this->setResizeMode(QDeclarativeView::SizeRootObjectToView); + } else { + this->setResizeMode(QDeclarativeView::SizeViewToRootObject); + } +} diff --git a/telldus-gui/Plugins/QML/qmlview.h b/telldus-gui/Plugins/QML/qmlview.h index 8db88f42..adbb97bc 100644 --- a/telldus-gui/Plugins/QML/qmlview.h +++ b/telldus-gui/Plugins/QML/qmlview.h @@ -17,6 +17,7 @@ signals: public slots: void load(const QString &url); void setProperty( const QString & name, const QScriptValue &value ); + void sizeRootObjectToView(bool enable); private: class PrivateData; From 94ca412554041980a0a56c6826d8192e99167f2a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 15 Feb 2012 14:34:23 +0100 Subject: [PATCH 1906/2215] Load controllers from settings --- telldus-core/service/ControllerManager.cpp | 15 +++++++++++++++ telldus-core/service/ControllerManager.h | 1 + 2 files changed, 16 insertions(+) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index c2a431e0..3c70e5ce 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -5,6 +5,7 @@ #include "Log.h" #include "Message.h" #include "Strings.h" +#include "Settings.h" #include "../client/telldus-core.h" #include @@ -22,6 +23,7 @@ typedef std::map ControllerMap; class ControllerManager::PrivateData { public: int lastControllerId; + Settings settings; ControllerMap controllers; TelldusCore::Event *event; TelldusCore::Mutex mutex; @@ -31,6 +33,7 @@ ControllerManager::ControllerManager(TelldusCore::Event *event){ d = new PrivateData; d->lastControllerId = 0; d->event = event; + this->loadStoredControllers(); this->loadControllers(); } @@ -158,6 +161,18 @@ void ControllerManager::loadControllers() { } } +void ControllerManager::loadStoredControllers() { + int numberOfControllers = d->settings.getNumberOfNodes(Settings::Controller); + TelldusCore::MutexLocker locker(&d->mutex); + + for (int i = 0; i < numberOfControllers; ++i) { + int id = d->settings.getNodeId(Settings::Controller, i); + d->controllers[id].controller = NULL; + d->controllers[id].type = TELLSTICK_CONTROLLER_TELLSTICK; + d->controllers[id].name = d->settings.getName(Settings::Controller, id); + } +} + void ControllerManager::queryControllerStatus(){ std::list tellStickControllers; diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 33fa774e..df149e9d 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -17,6 +17,7 @@ public: Controller *getBestControllerById(int id); void loadControllers(); + void loadStoredControllers(); void queryControllerStatus(); int resetController(Controller *controller); From f1c71e64a0d89089ee1dc6439c6b9089b794954f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Feb 2012 13:04:08 +0100 Subject: [PATCH 1907/2215] Don't remove controllers, just mark them as unavailable --- telldus-core/service/ControllerManager.cpp | 52 ++++++++++------------ 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 3c70e5ce..afe111bd 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -56,7 +56,8 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str while(d->controllers.size()) { ControllerMap::iterator it = d->controllers.begin(); delete it->second.controller; - d->controllers.erase(it); + it->second.controller = 0; + //TODO: signal controller lost } } return; @@ -72,34 +73,29 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str } else { //Autodetect which has been disconnected TelldusCore::MutexLocker locker(&d->mutex); - bool again = true; - while(again) { - again = false; - for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - if (!it->second.controller) { - continue; - } - TellStick *tellstick = reinterpret_cast(it->second.controller); - if (!tellstick) { - continue; - } - if (serial.compare("") != 0) { - TellStickDescriptor tsd; - tsd.vid = vid; - tsd.pid = pid; - tsd.serial = serial; - if (!tellstick->isSameAsDescriptor(tsd)) { - continue; - } - } else if (tellstick->stillConnected()) { - continue; - } - - d->controllers.erase(it); - delete tellstick; - again=true; - break; + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (!it->second.controller) { + continue; } + TellStick *tellstick = reinterpret_cast(it->second.controller); + if (!tellstick) { + continue; + } + if (serial.compare("") != 0) { + TellStickDescriptor tsd; + tsd.vid = vid; + tsd.pid = pid; + tsd.serial = serial; + if (!tellstick->isSameAsDescriptor(tsd)) { + continue; + } + } else if (tellstick->stillConnected()) { + continue; + } + + it->second.controller = 0; + delete tellstick; + //TODO: signal controller lost } } } From bfb24c3aeb82d65b4ce187a8e7a60ae52741a744 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Feb 2012 13:04:59 +0100 Subject: [PATCH 1908/2215] Add functions to get/set controller serial and type --- telldus-core/service/Settings.cpp | 19 +++++++++++++++++++ telldus-core/service/Settings.h | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 447b9afa..dac837dd 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -82,6 +82,25 @@ int Settings::getPreferredControllerId(int intDeviceId) { return getIntSetting(Device, intDeviceId, L"controller", false); } +std::wstring Settings::getControllerSerial(int intControllerId) const { + TelldusCore::MutexLocker locker(&mutex); + return getStringSetting(Controller, intControllerId, L"serial", false); +} + +int Settings::setControllerSerial(int intControllerId, const std::wstring &serial) { + TelldusCore::MutexLocker locker(&mutex); + return setStringSetting(Controller, intControllerId, L"serial", serial, false); +} + +int Settings::getControllerType(int intControllerId) const { + TelldusCore::MutexLocker locker(&mutex); + return getIntSetting(Controller, intControllerId, L"type", false); +} + +int Settings::setControllerType(int intControllerId, int type) { + TelldusCore::MutexLocker locker(&mutex); + return setIntSetting(Controller, intControllerId, L"type", type, false); +} std::string Settings::getNodeString(Settings::Node type) const { if (type == Device) { diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 9db50628..d4a6bfc1 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -31,6 +31,11 @@ public: int getNodeId(Node type, int intDeviceIndex) const; int removeNode(Node type, int intNodeId); + std::wstring getControllerSerial(int intControllerId) const; + int setControllerSerial(int intControllerId, const std::wstring &serial); + int getControllerType(int intControllerId) const; + int setControllerType(int intControllerId, int type); + protected: std::wstring getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const; int setStringSetting(Node type, int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter); From 23f368b968bde32e045631495af8c9e74c638d42 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Feb 2012 13:06:15 +0100 Subject: [PATCH 1909/2215] If the requested controller is not avaialable, find the firt available one --- telldus-core/service/ControllerManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index afe111bd..b2d00b11 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -106,10 +106,16 @@ Controller *ControllerManager::getBestControllerById(int id) { return 0; } ControllerMap::const_iterator it = d->controllers.find(id); - if (it != d->controllers.end()) { + if (it != d->controllers.end() && it->second.controller) { return it->second.controller; } - return d->controllers.begin()->second.controller; + //Find first available controller + for(it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (it->second.controller) { + return it->second.controller; + } + } + return 0; } From 0800cfde10ddab3ac64676ac38efeeb408a2a334 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Feb 2012 13:10:23 +0100 Subject: [PATCH 1910/2215] When enumerating usb-devices, try matching them to the stored ones and add them if they are not found --- telldus-core/service/ControllerManager.cpp | 40 ++++++++++++++++------ 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index b2d00b11..2915ebb3 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -13,7 +13,7 @@ class ControllerDescriptor { public: - std::wstring name; + std::wstring name, serial; int type; Controller *controller; }; @@ -147,19 +147,38 @@ void ControllerManager::loadControllers() { continue; } - int controllerId = d->lastControllerId+1; + int type = TELLSTICK_CONTROLLER_TELLSTICK; + if ((*it).pid == 0x0c31) { + type = TELLSTICK_CONTROLLER_TELLSTICK_DUO; + } + int controllerId = 0; + //See if the controller matches one of the loaded, non available controllers + std::wstring serial = TelldusCore::charToWstring((*it).serial.c_str()); + for(cit = d->controllers.begin(); cit != d->controllers.end(); ++cit) { + if (cit->second.type == type && cit->second.serial.compare(serial) == 0) { + controllerId = cit->first; + break; + } + } + if (!controllerId) { + controllerId = d->settings.addNode(Settings::Controller); + if(controllerId < 0){ + //TODO: How to handle this? + continue; + } + d->controllers[controllerId].type = type; + d->settings.setControllerType(controllerId, type); + d->controllers[controllerId].serial = TelldusCore::charToWstring((*it).serial.c_str()); + d->settings.setControllerSerial(controllerId, d->controllers[controllerId].serial); + } + + //int controllerId = d->lastControllerId+1; TellStick *controller = new TellStick(controllerId, d->event, *it); if (!controller->isOpen()) { delete controller; continue; } - d->lastControllerId = controllerId; - d->controllers[d->lastControllerId].controller = controller; - if (controller->pid() == 0x0c30) { - d->controllers[d->lastControllerId].type = TELLSTICK_CONTROLLER_TELLSTICK; - } else { - d->controllers[d->lastControllerId].type = TELLSTICK_CONTROLLER_TELLSTICK_DUO; - } + d->controllers[controllerId].controller = controller; } } @@ -170,8 +189,9 @@ void ControllerManager::loadStoredControllers() { for (int i = 0; i < numberOfControllers; ++i) { int id = d->settings.getNodeId(Settings::Controller, i); d->controllers[id].controller = NULL; - d->controllers[id].type = TELLSTICK_CONTROLLER_TELLSTICK; d->controllers[id].name = d->settings.getName(Settings::Controller, id); + d->controllers[id].type = d->settings.getControllerType(id); + d->controllers[id].serial = d->settings.getControllerSerial(id); } } From fae493f4979a96e9c481fe141792546b11138d8b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Feb 2012 15:31:21 +0100 Subject: [PATCH 1911/2215] Store the new name in tdSetControllerValue() --- telldus-core/service/ControllerManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 2915ebb3..811acd00 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -267,6 +267,7 @@ int ControllerManager::setControllerValue(int id, const std::wstring &name, cons } if (name == L"name") { it->second.name = value; + d->settings.setName(Settings::Controller, id, value); } else { return TELLSTICK_ERROR_SYNTAX; //TODO: Is this the best error? } From 345ff62a93ce400304a3f3674f830ada770b0cd7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Feb 2012 15:32:39 +0100 Subject: [PATCH 1912/2215] Add new function tdControllerValue(), see #108 --- telldus-core/client/telldus-core.cpp | 24 +++++++++++++++++++ telldus-core/client/telldus-core.h | 1 + .../service/ClientCommunicationHandler.cpp | 5 ++++ telldus-core/service/ControllerManager.cpp | 18 ++++++++++++++ telldus-core/service/ControllerManager.h | 1 + 5 files changed, 49 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index f473186a..f6fd6508 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -717,6 +717,30 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int return client->getController(controllerId, controllerType, name, nameLen, available); } +/** + * This function gets a parameter on a controller. + * Valid parameters are: \c serial \c and firmware + * + * Added in version 2.1.2. + * @param controllerId The controller to change + * @param name The parameter to get. + * @param value A byref string where the value of the parameter will be placed + **/ +int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen) { + Message msg(L"tdControllerValue"); + msg.addArgument(controllerId); + msg.addArgument(name); + std::wstring retval = Client::getWStringFromService(msg); + if (retval.length() == 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } + + if (value && valueLen) { + strncpy(value, TelldusCore::wideToString(retval).c_str(), valueLen); + } + return TELLSTICK_SUCCESS; +} + /** * This function sets a parameter on a controller. * Valid parameters are: \c name diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 2e92daef..c7a1fd56 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -87,6 +87,7 @@ extern "C" { TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); + TELLSTICK_API int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen); TELLSTICK_API int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value); #ifdef __cplusplus diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index b3823d21..72eb6226 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -234,6 +234,11 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } else if (function == L"tdController") { (*wstringReturn) = d->controllerManager->getControllers(); + } else if (function == L"tdControllerValue") { + int id = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + (*wstringReturn) = d->controllerManager->getControllerValue(id, name); + } else if (function == L"tdSetControllerValue") { int id = TelldusCore::Message::takeInt(&msg); std::wstring name = TelldusCore::Message::takeString(&msg); diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 811acd00..210e7db0 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -258,6 +258,24 @@ std::wstring ControllerManager::getControllers() const { return msg; } +std::wstring ControllerManager::getControllerValue(int id, const std::wstring &name) { + TelldusCore::MutexLocker locker(&d->mutex); + + ControllerMap::iterator it = d->controllers.find(id); + if (it == d->controllers.end()) { + return L""; + } + if (name == L"serial") { + return it->second.serial; + } else if (name == L"firmware") { + if (!it->second.controller) { + return L"-1"; + } + return TelldusCore::intToWstring(it->second.controller->firmwareVersion()); + } + return L""; +} + int ControllerManager::setControllerValue(int id, const std::wstring &name, const std::wstring &value) { TelldusCore::MutexLocker locker(&d->mutex); diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index df149e9d..11cdcf4c 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -22,6 +22,7 @@ public: int resetController(Controller *controller); std::wstring getControllers() const; + std::wstring getControllerValue(int id, const std::wstring &name); int setControllerValue(int id, const std::wstring &name, const std::wstring &value); private: From 3de0a98f89a6481ab9ffe89bb3d0a056599b8bda Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 Feb 2012 15:36:36 +0100 Subject: [PATCH 1913/2215] Add new 'Controllers' plugin to admin controllers, see #108 --- telldus-gui/Plugins/CMakeLists.txt | 7 +- .../Plugins/Controllers/CMakeLists.txt | 41 ++++++++ .../Plugins/Controllers/ControllerView.qml | 92 ++++++++++++++++++ .../Plugins/Controllers/HeaderTitle.qml | 10 ++ telldus-gui/Plugins/Controllers/__init__.js | 25 +++++ .../Plugins/Controllers/btn_action_remove.png | Bin 0 -> 1123 bytes .../Plugins/Controllers/controller.cpp | 84 ++++++++++++++++ telldus-gui/Plugins/Controllers/controller.h | 52 ++++++++++ .../Plugins/Controllers/controllerlist.cpp | 48 +++++++++ .../Plugins/Controllers/controllerlist.h | 30 ++++++ .../Plugins/Controllers/controllersplugin.cpp | 30 ++++++ .../Plugins/Controllers/controllersplugin.h | 16 +++ telldus-gui/Plugins/Controllers/header_bg.png | Bin 0 -> 526 bytes telldus-gui/Plugins/Controllers/icon.png | Bin 0 -> 754 bytes telldus-gui/Plugins/Controllers/main.qml | 30 ++++++ telldus-gui/Plugins/Controllers/row_bg.png | Bin 0 -> 346 bytes telldus-gui/Plugins/Controllers/tellstick.png | Bin 0 -> 17555 bytes .../Plugins/Controllers/tellstick_duo.png | Bin 0 -> 26377 bytes 18 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 telldus-gui/Plugins/Controllers/CMakeLists.txt create mode 100644 telldus-gui/Plugins/Controllers/ControllerView.qml create mode 100644 telldus-gui/Plugins/Controllers/HeaderTitle.qml create mode 100644 telldus-gui/Plugins/Controllers/__init__.js create mode 100644 telldus-gui/Plugins/Controllers/btn_action_remove.png create mode 100644 telldus-gui/Plugins/Controllers/controller.cpp create mode 100644 telldus-gui/Plugins/Controllers/controller.h create mode 100644 telldus-gui/Plugins/Controllers/controllerlist.cpp create mode 100644 telldus-gui/Plugins/Controllers/controllerlist.h create mode 100644 telldus-gui/Plugins/Controllers/controllersplugin.cpp create mode 100644 telldus-gui/Plugins/Controllers/controllersplugin.h create mode 100644 telldus-gui/Plugins/Controllers/header_bg.png create mode 100644 telldus-gui/Plugins/Controllers/icon.png create mode 100644 telldus-gui/Plugins/Controllers/main.qml create mode 100644 telldus-gui/Plugins/Controllers/row_bg.png create mode 100644 telldus-gui/Plugins/Controllers/tellstick.png create mode 100644 telldus-gui/Plugins/Controllers/tellstick_duo.png diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 366d2f0d..4b29d679 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -8,11 +8,12 @@ IF (BUILD_LIBTELLDUS-GUI) SET(BUILD_PLUGIN_SYSTRAY TRUE CACHE BOOL "Build plugin 'Systray'") ENDIF (BUILD_LIBTELLDUS-GUI) +SET(BUILD_PLUGIN_CONTROLLERS FALSE CACHE BOOL "Build plugin 'Controllers admin plugin'") SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") -SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") SET(BUILD_PLUGIN_SCHEDULERGUISIMPLE FALSE CACHE BOOL "Build plugin 'Simple Scheduler GUI'") SET(BUILD_PLUGIN_SENSORS TRUE CACHE BOOL "Build plugin 'Sensors'") +SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") ADD_SUBDIRECTORY(telldus) @@ -28,6 +29,10 @@ IF(BUILD_PLUGIN_SYSTRAY) ADD_SUBDIRECTORY(Systray) ENDIF(BUILD_PLUGIN_SYSTRAY) +IF(BUILD_PLUGIN_CONTROLLERS) + ADD_SUBDIRECTORY(Controllers) +ENDIF() + IF(BUILD_PLUGIN_DBUS) ADD_SUBDIRECTORY(DBus) ENDIF(BUILD_PLUGIN_DBUS) diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt new file mode 100644 index 00000000..71825541 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -0,0 +1,41 @@ +SET(REQUIRE_PLUGIN_QML TRUE PARENT_SCOPE) +#SET(REQUIRE_PLUGIN_SETTINGS TRUE PARENT_SCOPE) + +SET(QT_USE_QTDECLARATIVE TRUE) + +SET( Plugin_NAME "Controllers" ) + + +SET( Plugin_SRCS + controller.cpp + controllerlist.cpp + controllersplugin.cpp +) + +SET( Plugin_HDRS + controllersplugin.h +) + +SET( Plugin_MOC_HDRS + controller.h + controllerlist.h +) + +SET( Plugin_PATH "com.telldus.controllers" ) + +SET( Plugin_EXTRA + btn_action_remove.png + ControllerView.qml + header_bg.png + HeaderTitle.qml + icon.png + main.qml + row_bg.png + tellstick.png + tellstick_duo.png +) + +FIND_PACKAGE(TelldusCore REQUIRED) +SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Controllers/ControllerView.qml b/telldus-gui/Plugins/Controllers/ControllerView.qml new file mode 100644 index 00000000..00989020 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/ControllerView.qml @@ -0,0 +1,92 @@ +import QtQuick 1.1 +import QtDesktop 0.1 + +BorderImage { + source: "row_bg.png" + border.left: 5; border.top: 5 + border.right: 5; border.bottom: 5 + width: parent.width + height: content.height + content.anchors.margins*2 + + Item { + id: content + anchors.top: parent.top + anchors.left: parent.left + anchors.margins: 5 + height: childrenRect.height + width: childrenRect.width + + Row { + spacing: 10 + Image { + source: icon(controller.type) + width: 50 + smooth: true + fillMode: Image.PreserveAspectFit + opacity: controller.available ? 1 : 0.5 + } + + Column { + Text { + color: "#004275" + text: productName(controller.type) + font.pixelSize: 15 + } + TextField { + //id: nameEdit + text: controller.name; + placeholderText: 'Enter a name for this controller' + onTextChanged: controller.name = text + } + } + Loader { + sourceComponent: tellstick + } + Image { + source: "btn_action_remove.png" + visible: !controller.available + } + } + } + + Component { + id: tellstick + Grid { + spacing: 3 + columns: 2 + Text { + color: "#004275" + text: "Serial:" + } + Text { + color: "#004275" + text: controller.serial + } + Text { + color: "#004275" + text: "Firmware version:" + } + Text { + color: "#004275" + text: controller.firmware + } + } + } + + function icon(type) { + if (type == 1) { + return "tellstick.png"; + } else if (type == 2) { + return "tellstick_duo.png"; + } + return "tellstick.png"; + } + function productName(type) { + if (type == 1) { + return "TellStick"; + } else if (type == 2) { + return "TellStick Duo"; + } + return ""; + } +} diff --git a/telldus-gui/Plugins/Controllers/HeaderTitle.qml b/telldus-gui/Plugins/Controllers/HeaderTitle.qml new file mode 100644 index 00000000..0d7ae213 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/HeaderTitle.qml @@ -0,0 +1,10 @@ +import Qt 4.7 + +Text { + id: headerTitle + text: "Name" + color: "white" + font.weight: Font.Bold + height: parent.height + verticalAlignment: Text.AlignVCenter +} diff --git a/telldus-gui/Plugins/Controllers/__init__.js b/telldus-gui/Plugins/Controllers/__init__.js new file mode 100644 index 00000000..b06ea8c4 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/__init__.js @@ -0,0 +1,25 @@ +/** Sensors **/ +__setupPackage__( __extension__ ); + +__postInit__ = function() { + application.allDoneLoading.connect( com.telldus.controllers.init ); +} + +com.telldus.controllers = function() { + var view = null; + + function init() { + view = new com.telldus.qml.view({}); + view.setProperty('controllerModel', com.telldus.controllers.list); + view.load("main.qml"); + view.sizeRootObjectToView(true); + application.configuration.addPage('Controllers', view, 'icon.png'); + com.telldus.controllers.list.changed.connect(application.configuration.valueChanged) + application.configuration.save.connect(com.telldus.controllers.list.save) + } + + return { //Public functions + init:init + } + +}(); diff --git a/telldus-gui/Plugins/Controllers/btn_action_remove.png b/telldus-gui/Plugins/Controllers/btn_action_remove.png new file mode 100644 index 0000000000000000000000000000000000000000..d9e5bf753f9b7134bc75ac749fba154f00515554 GIT binary patch literal 1123 zcmV-p1f2VcP)OH3AX z5cDKIfG3ZF_z*dG6Cc2h4*I>W>yKqwKJWMY zn|4VmV1+-NpPPG3K`)BW>BE!KDd(YN3@M3U9gWA2R{H%Xo-4lX?A%^nS$SiIGcZ(B z(Xd*pOt|Mmi2&tC(?_9llWz$j>dwYBDIz@4l%uZOTfH#{H z;OABhfyJ|Bf=Y<~oDw*p#7}^gCP!ON%J&zSmTuWSbNl=IKQ(kOK}6&v{1|j;eSf0= zC6&`hQC*L^-R`PgUpP28{4LCrc@vr6*_06L)Q*K{bV19$wJY-r3yX#0$f78!Aq5~D zgU>(E<|6 z@}O{vg?z+JiIotP$P6xgk-idUk`Vw2;&|!E%%9Gi7j525+yw|A04f!M#GR>faj^(n zLgJ8zj;NSkWhf>Sp)dcF~2YF-Bkr}uHrK>O5A_>DoNL9 z{CW)dEXN>n*$Tm&)y`KnR}|+`;Ak>oOr{}Bl;WU}@!yPFcP-6!)WzA^b16_9Bk?~} zE0%o}cn4Be^Bnccwd<
4+?JdPUY{850|Yl&Bh++1y>zB#i!EOt{vOtg>e-M6!zI zJ52M_(DN2eWTbd5jPvLSP9FarC-QK z-APrA((0CHHadGJb{?P>g>!-Hf>au>p=eQx%`EMrrN+vrf@cJoBUATvt7#fTR7*oPA!$6G=z*kp$eF_^pjiRapTT!RY3G!f zm_+9kx?L{SB&?RUciG&V-sTFnz+yR>{4gIQJ!A#vtdUNkF~`Z>XqJF#st*hZS1kz1 zd?oxhy4#TV#^Exc?)BnX8WpwiWU@%y>GG#Ts zVD3vB8?V=PcX!{G({Wk;8XDdkuQ%4LES8z{UAEpX*zW}% p>wo+uZq0pc?n84Q@R +#include + +class Controller::PrivateData { +public: + bool available, nameChanged; + int id, type; + QString name, serial, firmware; +}; + +Controller::Controller(int id, int type, const QString &name, QObject *parent) : + QObject(parent) +{ + d = new PrivateData; + d->id = id; + d->type = type; + d->available = false; + d->nameChanged = false; + d->name = name; + + const int DATA_LENGTH = 255; + char buff[DATA_LENGTH]; + if (tdControllerValue(id, "serial", buff, DATA_LENGTH) == TELLSTICK_SUCCESS) { + d->serial = QString::fromUtf8(buff); + } + if (tdControllerValue(id, "firmware", buff, DATA_LENGTH) == TELLSTICK_SUCCESS) { + d->firmware = QString::fromUtf8(buff); + } +} + +Controller::~Controller() { + delete d; +} + +bool Controller::available() const { + return d->available; +} + +void Controller::setAvailable(bool available) { + d->available = available; + emit availableChanged(); + emit firmwareChanged(); +} + +QString Controller::firmware() const { + if (!d->available) { + return "?"; + } + return d->firmware; +} + +int Controller::id() const { + return d->id; +} + +QString Controller::name() const { + return d->name; +} + +void Controller::setName(const QString &name) { + if (name == d->name) { + return; + } + d->nameChanged = true; + d->name = name; + emit nameChanged(); +} + +void Controller::save() { + if (d->nameChanged) { + tdSetControllerValue(d->id, "name", d->name.toUtf8()); + d->nameChanged = false; + } +} + +QString Controller::serial() const { + return d->serial; +} + +int Controller::type() const { + return d->type; +} + diff --git a/telldus-gui/Plugins/Controllers/controller.h b/telldus-gui/Plugins/Controllers/controller.h new file mode 100644 index 00000000..07740c63 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/controller.h @@ -0,0 +1,52 @@ +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include +#include + +class Controller : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool available READ available NOTIFY availableChanged) + Q_PROPERTY(QString firmware READ firmware NOTIFY firmwareChanged) + Q_PROPERTY(int id READ id NOTIFY idChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString serial READ serial NOTIFY serialChanged) + Q_PROPERTY(int type READ type NOTIFY typeChanged()) + +public: + explicit Controller(int id = 0, int type = 1, const QString &name = "", QObject *parent = 0); + ~Controller(); + + bool available() const; + void setAvailable(bool available); + + QString firmware() const; + + int id() const; + + QString name() const; + void setName(const QString &name); + + void save(); + + QString serial() const; + + int type() const; + +signals: + void availableChanged(); + void firmwareChanged(); + void idChanged(); + void nameChanged(); + void serialChanged(); + void typeChanged(); + +private: + class PrivateData; + PrivateData *d; +}; + +Q_DECLARE_METATYPE(Controller*) + +#endif // CONTROLLER_H diff --git a/telldus-gui/Plugins/Controllers/controllerlist.cpp b/telldus-gui/Plugins/Controllers/controllerlist.cpp new file mode 100644 index 00000000..849999d0 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/controllerlist.cpp @@ -0,0 +1,48 @@ +#include "controllerlist.h" +#include "controller.h" +#include + +#include + +class ControllerList::PrivateData { +public: + QList list; +}; + +ControllerList::ControllerList(QObject *parent) : + QAbstractListModel(parent) +{ + d = new PrivateData; + + QHash roles; + roles[Qt::UserRole+1] = "controller"; + setRoleNames(roles); + + const int DATA_LENGTH = 255; + char name[DATA_LENGTH]; + int available, controllerId, type; + while(tdController(&controllerId, &type, name, DATA_LENGTH, &available) == TELLSTICK_SUCCESS) { + Controller *controller = new Controller(controllerId, type, QString::fromUtf8(name), this); + controller->setAvailable(available); + connect(controller, SIGNAL(nameChanged()), this, SIGNAL(changed())); + d->list.append(controller); + } +} + +ControllerList::~ControllerList() { + delete d; +} + +QVariant ControllerList::data(const QModelIndex &index, int role) const { + return QVariant::fromValue(d->list.at(index.row())); +} + +int ControllerList::rowCount(const QModelIndex &parent) const { + return d->list.size(); +} + +void ControllerList::save() { + for(int i = 0; i < d->list.size(); ++i) { + d->list.at(i)->save(); + } +} diff --git a/telldus-gui/Plugins/Controllers/controllerlist.h b/telldus-gui/Plugins/Controllers/controllerlist.h new file mode 100644 index 00000000..d5884feb --- /dev/null +++ b/telldus-gui/Plugins/Controllers/controllerlist.h @@ -0,0 +1,30 @@ +#ifndef CONTROLLERLIST_H +#define CONTROLLERLIST_H + +#include +#include + +class ControllerList : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(int length READ rowCount) +public: + explicit ControllerList(QObject *parent = 0); + ~ControllerList(); + + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +signals: + void changed(); + +public slots: + void save(); + +private: + class PrivateData; + PrivateData *d; + +}; + +#endif // CONTROLLERLIST_H diff --git a/telldus-gui/Plugins/Controllers/controllersplugin.cpp b/telldus-gui/Plugins/Controllers/controllersplugin.cpp new file mode 100644 index 00000000..681ccca2 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/controllersplugin.cpp @@ -0,0 +1,30 @@ +#include "controllersplugin.h" +#include "controllerlist.h" +#include "controller.h" +#include +#include + + +ControllersPlugin::ControllersPlugin ( QObject * parent ) + :QScriptExtensionPlugin( parent ) +{ +} + +ControllersPlugin::~ControllersPlugin() { +} + +void ControllersPlugin::initialize ( const QString & key, QScriptEngine * engine ) { + if (key == "com.telldus.controllers") { + qmlRegisterType("Telldus", 1, 0, "Controller"); + + QScriptValue qml = engine->globalObject().property("com").property("telldus").property("controllers"); + QScriptValue list = engine->newQObject(new ControllerList(), QScriptEngine::ScriptOwnership); + qml.setProperty("list", list); + } +} + +QStringList ControllersPlugin::keys () const { + return QStringList() << "com.telldus.controllers"; +} + +Q_EXPORT_PLUGIN2(ControllersInterface, ControllersPlugin) diff --git a/telldus-gui/Plugins/Controllers/controllersplugin.h b/telldus-gui/Plugins/Controllers/controllersplugin.h new file mode 100644 index 00000000..57cbe1d2 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/controllersplugin.h @@ -0,0 +1,16 @@ +#ifndef CONTROLLERSPLUGIN_H +#define CONTROLLERSPLUGIN_H + +#include + +class ControllersPlugin : public QScriptExtensionPlugin { +public: + ControllersPlugin ( QObject * parent = 0 ); + ~ControllersPlugin (); + + virtual void initialize ( const QString & key, QScriptEngine * engine ); + virtual QStringList keys () const; +}; + + +#endif // CONTROLLERSPLUGIN_H diff --git a/telldus-gui/Plugins/Controllers/header_bg.png b/telldus-gui/Plugins/Controllers/header_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..564a158b5d9c69a045712278b45085512e0474f7 GIT binary patch literal 526 zcmV+p0`dKcP)J)aLLt2t;vW#y(ps?7Lexe~5Cei*7!%YKMm-bF*WIl%r;#8> zyemZKc-hqp|drJ&7&)e zm~n;=Rwjo=Ov}d3SsIsF14gleD$R9OL8v)^4sy82zU*t{(ch#i*h*X@o_cU1*32S@ z63y9}Y=GfVGV_RwyC)RORk&G+zpGk^VPtZ7@-EYxL?d%x-nwd9Kd~RMZQGFc4`dCN zpHCwbHQ3>#$HpQhKfp`7aLWuaJDh zzf(xRmWJPZmXLq=rzj-Dl(Mc&T_m{XP+&M|n2J+^UkCjr(bUGPafV~(dEL_WfIF;e zP{L7e6EWqp6U9V03enO|i|WVLH1eE4jv6EGP`I?VAyOA9OFFJ^ZSMjM08uy&f`RU1 Q`v3p{07*qoM6N<$f)*X<_5c6? literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/Controllers/icon.png b/telldus-gui/Plugins/Controllers/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4badd42f0dafbb110ec9bb0c2ebe1ed0d957c1ec GIT binary patch literal 754 zcmV!sW1<6BEam5{$I63ypy?8EAv%3 z;ALa0ivUlI5_FHew-u;_WF*UxpT&Pn#4=b1Bg%)-umqR|Q?Q_wxm6a_$bwJ=q%7E~ zT3{Azhd*IkU|C--3rfNikg}jLtv-Zqfk)5{R&d}KY=*yKT3{K!A9hHsYNUCE5KT? zFR;i_z(V*AGyMwqtu6P{QNW10Jc1< zXMP3TR+ZbU;*!azQw><6lI^b^1{B_F07@xE!#0&NAQ+h-HsP99f5rcR-lG- k03Jg-!3SKn%Rd1I0Ev{!`I2XhSO5S307*qoM6N<$f)YDg9RL6T literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/Controllers/main.qml b/telldus-gui/Plugins/Controllers/main.qml new file mode 100644 index 00000000..fb8f164b --- /dev/null +++ b/telldus-gui/Plugins/Controllers/main.qml @@ -0,0 +1,30 @@ +import QtQuick 1.1 + +//import QtDesktop 0.1 + +Item { + width: 500 //Minimum width + + Column { + spacing: 1 + anchors.fill: parent + + BorderImage { + id: header + source: "header_bg.png" + width: parent.width; height: 40 + border.left: 5; border.top: 5 + border.right: 5; border.bottom: 5 + + HeaderTitle { + text: "Controllers" + anchors.left: parent.left + anchors.leftMargin: 15 + } + } + Repeater { + model: controllerModel + delegate: ControllerView {} + } + } +} diff --git a/telldus-gui/Plugins/Controllers/row_bg.png b/telldus-gui/Plugins/Controllers/row_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..06f9d82d406405c1137c8672addb67c8054ad975 GIT binary patch literal 346 zcmV-g0j2(lP)J&&wc|Kq7zX1q*Dya3ux%UDJDitT z-3xDltk6MxnbSQ3YG5=F|1?b_UV%Gfx(jib=edUaBjCI!3Unh>*M^5>Sqfyp+vggv s$2sDxJIMz>xM99Af0^I6KlmrW0Ji3+_8HcCGynhq07*qoM6N<$f;s|{CjbBd literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/Controllers/tellstick.png b/telldus-gui/Plugins/Controllers/tellstick.png new file mode 100644 index 0000000000000000000000000000000000000000..b437a369a260f66e78e0c3dfe07a2264bfc49e92 GIT binary patch literal 17555 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 UTM<9;`v3p{07*qoM6N<$f|C-HZU6uP literal 0 HcmV?d00001 diff --git a/telldus-gui/Plugins/Controllers/tellstick_duo.png b/telldus-gui/Plugins/Controllers/tellstick_duo.png new file mode 100644 index 0000000000000000000000000000000000000000..c3a4513a08c6ad5dd0f7ce7da1d9c3d703e98023 GIT binary patch literal 26377 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 literal 0 HcmV?d00001 From a766fe32decfe51a18547b8a3bf83b313eaa23ba Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 12:34:31 +0100 Subject: [PATCH 1914/2215] Add public function tdRemoveController() to telldus-core, see #108 --- telldus-core/client/telldus-core.cpp | 18 +++++++++++++++ telldus-core/client/telldus-core.h | 1 + .../service/ClientCommunicationHandler.cpp | 4 ++++ telldus-core/service/ControllerManager.cpp | 23 +++++++++++++++++++ telldus-core/service/ControllerManager.h | 1 + 5 files changed, 47 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index f6fd6508..e3143fdc 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -758,4 +758,22 @@ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char * return Client::getIntegerFromService(msg); } +/** + * This function removes a controller from the list + * of controllers. The controller must not be + * available (disconnected) for this to work. + * + * Added in version 2.1.2. + * @param controllerId The controller to remove + * @returns TELLSTICK_SUCCESS if the controller was + * removed, TELLSTICK_ERROR_NOT_FOUND if the controller was + * not found, and TELLSTICK_ERROR_PERMISSION_DENIED if the + * controller is still connected. + **/ +int WINAPI tdRemoveController(int controllerId) { + Message msg(L"tdRemoveController"); + msg.addArgument(controllerId); + return Client::getIntegerFromService(msg); +} + /* @} */ diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index c7a1fd56..c9b3d032 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -89,6 +89,7 @@ extern "C" { TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); TELLSTICK_API int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen); TELLSTICK_API int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value); + TELLSTICK_API int WINAPI tdRemoveController(int controllerId); #ifdef __cplusplus } diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 72eb6226..21159209 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -245,6 +245,10 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, std::wstring value = TelldusCore::Message::takeString(&msg); (*intReturn) = d->controllerManager->setControllerValue(id, name, value); + } else if (function == L"tdRemoveController") { + int controllerId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->controllerManager->removeController(controllerId); + } else{ (*intReturn) = TELLSTICK_ERROR_UNKNOWN; } diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 210e7db0..8c88fba9 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -276,6 +276,29 @@ std::wstring ControllerManager::getControllerValue(int id, const std::wstring &n return L""; } +int ControllerManager::removeController(int id) { + TelldusCore::MutexLocker locker(&d->mutex); + + ControllerMap::iterator it = d->controllers.find(id); + if (it == d->controllers.end()) { + return TELLSTICK_ERROR_NOT_FOUND; + } + if (it->second.controller) { + //Still connected + return TELLSTICK_ERROR_PERMISSION_DENIED; + } + + int ret = d->settings.removeNode(Settings::Controller, id); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } + + d->controllers.erase(it); + + //TODO: signal + return TELLSTICK_SUCCESS; +} + int ControllerManager::setControllerValue(int id, const std::wstring &name, const std::wstring &value) { TelldusCore::MutexLocker locker(&d->mutex); diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 11cdcf4c..7e650323 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -23,6 +23,7 @@ public: std::wstring getControllers() const; std::wstring getControllerValue(int id, const std::wstring &name); + int removeController(int id); int setControllerValue(int id, const std::wstring &name, const std::wstring &value); private: From 5238978d3243c07c73ee031758dea8a6745bdeb5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 12:37:58 +0100 Subject: [PATCH 1915/2215] Allow for controller removal in TelldusCenter --- telldus-gui/Plugins/Controllers/ControllerView.qml | 4 ++++ telldus-gui/Plugins/Controllers/controller.cpp | 13 +++++++++++++ telldus-gui/Plugins/Controllers/controller.h | 2 ++ 3 files changed, 19 insertions(+) diff --git a/telldus-gui/Plugins/Controllers/ControllerView.qml b/telldus-gui/Plugins/Controllers/ControllerView.qml index 00989020..52c7283c 100644 --- a/telldus-gui/Plugins/Controllers/ControllerView.qml +++ b/telldus-gui/Plugins/Controllers/ControllerView.qml @@ -45,6 +45,10 @@ BorderImage { Image { source: "btn_action_remove.png" visible: !controller.available + MouseArea { + anchors.fill: parent + onClicked: controller.tryRemove(); + } } } } diff --git a/telldus-gui/Plugins/Controllers/controller.cpp b/telldus-gui/Plugins/Controllers/controller.cpp index d1966c11..9f11a766 100644 --- a/telldus-gui/Plugins/Controllers/controller.cpp +++ b/telldus-gui/Plugins/Controllers/controller.cpp @@ -1,5 +1,6 @@ #include "controller.h" #include +#include #include class Controller::PrivateData { @@ -78,6 +79,18 @@ QString Controller::serial() const { return d->serial; } +void Controller::tryRemove() { + QMessageBox msgBox; + msgBox.setText( tr("Are you sure you want to remove the selected controller?") ); + msgBox.setInformativeText( tr("If you connect it again at a later point it will be readded automatically.") ); + msgBox.setIcon( QMessageBox::Warning ); + msgBox.setStandardButtons( QMessageBox::Yes | QMessageBox::No ); + msgBox.setDefaultButton( QMessageBox::No ); + if ( msgBox.exec() == QMessageBox::Yes) { + tdRemoveController(d->id); + } +} + int Controller::type() const { return d->type; } diff --git a/telldus-gui/Plugins/Controllers/controller.h b/telldus-gui/Plugins/Controllers/controller.h index 07740c63..8d10a3f6 100644 --- a/telldus-gui/Plugins/Controllers/controller.h +++ b/telldus-gui/Plugins/Controllers/controller.h @@ -32,6 +32,8 @@ public: QString serial() const; + Q_INVOKABLE void tryRemove(); + int type() const; signals: From d5166d26f890747916885c9490ab1da6c591c1f5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 12:38:56 +0100 Subject: [PATCH 1916/2215] Add function com.telldus.core.controller() to the script engine to iterate over controllers --- .../Plugins/TelldusCore/tellduscoreobject.cpp | 20 +++++++++++++++++++ .../Plugins/TelldusCore/tellduscoreobject.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp index 5500bbf0..8ff5e333 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp @@ -136,6 +136,26 @@ QVariant TelldusCoreObject::sensorValue(const QString &protocol, const QString & return retval; } +QVariant TelldusCoreObject::controller() const { + const int DATA_LENGTH = 255; + char name[DATA_LENGTH]; + int controllerId = 0, available = 0, controllerType = 0; + + if (tdController(&controllerId, &controllerType, name, DATA_LENGTH, &available) != TELLSTICK_SUCCESS) { + qDebug() << "Return null"; + return 0; + } + + QVariantMap retval; + + retval["id"] = controllerId; + retval["type"] = controllerType; + retval["name"] = name; + retval["available"] = available; + + return retval; +} + void TelldusCoreObject::triggerError(int deviceId, int errorId) { char *errorString = tdGetErrorString( errorId ); QString message = QString::fromUtf8( errorString ); diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h index a7bac7ee..8402f15a 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h @@ -32,6 +32,8 @@ public slots: QVariant sensor() const; QVariant sensorValue(const QString &protocol, const QString &model, int id, int dataType) const; + QVariant controller() const; + int turnOn( int deviceId ); int turnOff( int deviceId ); int up( int deviceId ); From 20840d5d8b266e33a06c3b3fbf09cfbb7e242ae0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 15:20:28 +0100 Subject: [PATCH 1917/2215] Initialize private variable --- telldus-core/client/Client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 34c79968..3377fc86 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -51,6 +51,7 @@ Client::Client() d->lastCallbackId = 0; d->running = true; d->sensorCached = false; + d->controllerCached = false; start(); } From 6d478708563eb5d894bdb4df455d84e96b5c1d09 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 15:21:18 +0100 Subject: [PATCH 1918/2215] Return 'TellStick not found' when no controller is connected instead of 'No device found' --- telldus-core/client/Client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 3377fc86..d89733e6 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -465,7 +465,7 @@ int Client::getController(int *controllerId, int *controllerType, char *name, in if (d->controllerCache == L"") { d->controllerCached = false; - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + return TELLSTICK_ERROR_NOT_FOUND; } int id = Message::takeInt(&d->controllerCache); From ab8bda2247e9c32121bddab1c2219f5a9860b48c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 15:21:46 +0100 Subject: [PATCH 1919/2215] Export our controller functions on Windows --- telldus-core/client/libtelldus-core.def | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def index 36cbfecb..3bddcea8 100644 --- a/telldus-core/client/libtelldus-core.def +++ b/telldus-core/client/libtelldus-core.def @@ -52,4 +52,8 @@ EXPORTS tdRegisterSensorEvent @37 tdSensor @38 tdSensorValue @39 - \ No newline at end of file + + tdController @40 + tdControllerValue @41 + tdSetControllerValue @42 + tdRemoveController @43 From 23437505d60b3f1ee8c22d2b72ad803e442fee03 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 15:24:50 +0100 Subject: [PATCH 1920/2215] Initialize variable dwLength, we might get ERROR_MORE_DATA otherwize --- telldus-core/service/SettingsWinRegistry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index d4667bce..6db54647 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -120,7 +120,7 @@ int Settings::getNextDeviceId() const { if(lnExists == ERROR_SUCCESS){ - DWORD dwLength; + DWORD dwLength = sizeof(DWORD); DWORD nResult(0); long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); From 5bc43a21ab6e07d48ddde55b1b74b93549bad1cc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 15:26:38 +0100 Subject: [PATCH 1921/2215] Fix settings functions on Windows for our refactoring --- telldus-core/service/Settings.cpp | 8 +- telldus-core/service/SettingsWinRegistry.cpp | 84 +++++++++++--------- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index dac837dd..541ec8c7 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -114,19 +114,19 @@ std::string Settings::getNodeString(Settings::Node type) const { bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { TelldusCore::MutexLocker locker(&mutex); - bool retval = setIntSetting( intDeviceId, L"state", intDeviceState, true ); - setStringSetting( intDeviceId, L"stateValue", strDeviceStateValue, true ); + bool retval = setIntSetting( Settings::Device, intDeviceId, L"state", intDeviceState, true ); + setStringSetting( Settings::Device, intDeviceId, L"stateValue", strDeviceStateValue, true ); return retval; } int Settings::getDeviceState( int intDeviceId ) const { TelldusCore::MutexLocker locker(&mutex); - return getIntSetting( intDeviceId, L"state", true ); + return getIntSetting( Settings::Device, intDeviceId, L"state", true ); } std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { TelldusCore::MutexLocker locker(&mutex); - return getStringSetting( intDeviceId, L"stateValue", true ); + return getStringSetting( Settings::Device, intDeviceId, L"stateValue", true ); } #endif diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 6db54647..639335f6 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -15,16 +15,24 @@ const int intMaxRegValueLength = 1000; class Settings::PrivateData { public: HKEY rootKey; - std::wstring strRegPathDevice; - std::wstring strRegPath; + std::wstring strRegPath; + std::wstring getNodePath(Settings::Node type); }; +std::wstring Settings::PrivateData::getNodePath(Settings::Node type) { + if (type == Settings::Device) { + return L"SOFTWARE\\Telldus\\Devices\\"; + } else if (type == Settings::Controller) { + return L"SOFTWARE\\Telldus\\Controllers\\"; + } + return L""; +} + /* * Constructor */ Settings::Settings(void) { d = new PrivateData(); - d->strRegPathDevice = L"SOFTWARE\\Telldus\\Devices\\"; d->strRegPath = L"SOFTWARE\\Telldus\\"; d->rootKey = HKEY_LOCAL_MACHINE; } @@ -39,41 +47,41 @@ Settings::~Settings(void) { /* * Return the number of stored devices */ -int Settings::getNumberOfDevices(void) const { +int Settings::getNumberOfNodes(Node type) const { TelldusCore::MutexLocker locker(&mutex); - int intNumberOfDevices = 0; + int intNumberOfNodes = 0; HKEY hk; - long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_QUERY_VALUE, &hk); - + long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); + if(lnExists == ERROR_SUCCESS){ std::wstring strNumSubKeys; DWORD dNumSubKeys; RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - intNumberOfDevices = (int)dNumSubKeys; + intNumberOfNodes = (int)dNumSubKeys; RegCloseKey(hk); } - return intNumberOfDevices; + return intNumberOfNodes; } -int Settings::getDeviceId(int intDeviceIndex) const { +int Settings::getNodeId(Node type, int intNodeIndex) const { TelldusCore::MutexLocker locker(&mutex); int intReturn = -1; HKEY hk; - long lnExists = RegOpenKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, KEY_READ, &hk); + long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); if(lnExists == ERROR_SUCCESS){ wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD size = intMaxRegValueLength; - if (RegEnumKeyEx(hk, intDeviceIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + if (RegEnumKeyEx(hk, intNodeIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { intReturn = _wtoi(Buff); } @@ -84,39 +92,39 @@ int Settings::getDeviceId(int intDeviceIndex) const { } /* -* Add a new device +* Add a new node */ -int Settings::addDevice() { +int Settings::addNode(Node type) { TelldusCore::MutexLocker locker(&mutex); - int intDeviceId = -1; + int intNodeId = -1; HKEY hk; DWORD dwDisp; - intDeviceId = getNextDeviceId(); + intNodeId = getNextNodeId(type); - std::wstring strCompleteRegPath = d->strRegPathDevice; - strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) { //fail - intDeviceId = -1; + intNodeId = -1; } RegCloseKey(hk); - return intDeviceId; + return intNodeId; } /* * Get next available device id */ -int Settings::getNextDeviceId() const { +int Settings::getNextNodeId(Node type) const { //Private, no locks needed int intReturn = -1; HKEY hk; DWORD dwDisp; - long lnExists = RegCreateKeyEx(d->rootKey, d->strRegPathDevice.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created + long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created if(lnExists == ERROR_SUCCESS){ @@ -141,11 +149,11 @@ int Settings::getNextDeviceId() const { /* * Remove a device */ -int Settings::removeDevice(int intDeviceId) { +int Settings::removeNode(Node type, int intNodeId) { TelldusCore::MutexLocker locker(&mutex); - std::wstring strCompleteRegPath = d->strRegPathDevice; - strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); @@ -184,12 +192,12 @@ std::wstring Settings::getSetting(const std::wstring &strName) const{ return strReturn; } -std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &name, bool parameter) const { +std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { std::wstring strReturn; HKEY hk; - std::wstring strCompleteRegPath = d->strRegPathDevice; - strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS){ @@ -212,14 +220,14 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &nam return strReturn; } -int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { +int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &name, const std::wstring &value, bool parameter) { HKEY hk; int ret = TELLSTICK_SUCCESS; - std::wstring bla = TelldusCore::intToWstring(intDeviceId); - std::wstring strCompleteRegPath = d->strRegPathDevice; - strCompleteRegPath.append(bla); + std::wstring strNodeId = TelldusCore::intToWstring(intNodeId); + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(strNodeId); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS){ @@ -234,23 +242,23 @@ int Settings::setStringSetting(int intDeviceId, const std::wstring &name, const } -int Settings::getIntSetting(int intDeviceId, const std::wstring &name, bool parameter) const { +int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { int intReturn = 0; - std::wstring strSetting = getStringSetting(intDeviceId, name, parameter); + std::wstring strSetting = getStringSetting(type, intNodeId, name, parameter); if (strSetting.length()) { - intReturn = (int)strSetting[0]; + intReturn = (int)strSetting[0]; //TODO: do real conversion instead } return intReturn; } -int Settings::setIntSetting(int intDeviceId, const std::wstring &name, int value, bool parameter) { +int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &name, int value, bool parameter) { int intReturn = TELLSTICK_ERROR_UNKNOWN; HKEY hk; - std::wstring strCompleteRegPath = d->strRegPathDevice; - strCompleteRegPath.append(TelldusCore::intToWstring(intDeviceId)); + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS) { DWORD dwVal = value; From a0e9fd963bd728ae3b436e7b774fa7dcb811daa9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 23 Feb 2012 15:27:20 +0100 Subject: [PATCH 1922/2215] Add qmldir for plugin Controllers --- telldus-gui/Plugins/Controllers/CMakeLists.txt | 1 + telldus-gui/Plugins/Controllers/qmldir | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 telldus-gui/Plugins/Controllers/qmldir diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt index 71825541..6ffd2263 100644 --- a/telldus-gui/Plugins/Controllers/CMakeLists.txt +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -30,6 +30,7 @@ SET( Plugin_EXTRA HeaderTitle.qml icon.png main.qml + qmldir row_bg.png tellstick.png tellstick_duo.png diff --git a/telldus-gui/Plugins/Controllers/qmldir b/telldus-gui/Plugins/Controllers/qmldir new file mode 100644 index 00000000..737b55f1 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/qmldir @@ -0,0 +1,2 @@ +HeaderTitle 1.0 HeaderTitle.qml +ControllerView 1.0 ControllerView.qml From c049b97a6454904cf4c23215c092c99cabcee15c Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 23 Feb 2012 15:44:36 +0100 Subject: [PATCH 1923/2215] Dispatching of events in own thread, to somewhat counter problems with long running events. --- telldus-core/client/CMakeLists.txt | 2 + telldus-core/client/CallbackDispatcher.cpp | 23 +-- telldus-core/client/CallbackDispatcher.h | 17 +- .../client/CallbackMainDispatcher.cpp | 159 ++++++++++++++++++ telldus-core/client/CallbackMainDispatcher.h | 69 ++++++++ telldus-core/client/Client.cpp | 120 ++++--------- telldus-core/client/Client.h | 3 +- telldus-core/common/Socket_win.cpp | 4 +- 8 files changed, 293 insertions(+), 104 deletions(-) create mode 100644 telldus-core/client/CallbackMainDispatcher.cpp create mode 100644 telldus-core/client/CallbackMainDispatcher.h diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 7ec93967..03dbd6da 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -7,12 +7,14 @@ FIND_PACKAGE( SignTool REQUIRED ) ######## Non configurable options ######## SET( telldus-core_SRCS CallbackDispatcher.cpp + CallbackMainDispatcher.cpp Client.cpp telldus-core.cpp ) SET( telldus-core_HDRS CallbackDispatcher.h + CallbackMainDispatcher.cpp Client.h ) SET( telldus-core_PUB_HDRS diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 86dbc0d3..c8dbc873 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -8,12 +8,11 @@ */ #include "CallbackDispatcher.h" -#include "common.h" using namespace TelldusCore; -TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct *data, int id, int m, const std::string &strD) -:Thread(), d(data), deviceId(id), method(m), strData(strD), doneRunning(false) +TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct *data, int id, int m, const std::string &strD, TelldusCore::EventRef cbDone) +:Thread(), d(data), deviceId(id), method(m), strData(strD), doneRunning(false), callbackExecuted(cbDone) { this->startAndLock(&d->mutex); } @@ -29,13 +28,12 @@ bool TDDeviceEventDispatcher::done() const { void TDDeviceEventDispatcher::run() { char *str = wrapStdString(strData); d->event(deviceId, method, strData.c_str(), d->id, d->context); - doneRunning = true; + callbackExecuted->signal(); } - -TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStruct *data, int id, int event, int type) -:Thread(), d(data), deviceId(id), changeEvent(event), changeType(type), doneRunning(false) +TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStruct *data, int id, int event, int type, TelldusCore::EventRef cbDone) +:Thread(), d(data), deviceId(id), changeEvent(event), changeType(type), doneRunning(false), callbackExecuted(cbDone) { this->startAndLock(&d->mutex); } @@ -51,10 +49,11 @@ bool TDDeviceChangeEventDispatcher::done() const { void TDDeviceChangeEventDispatcher::run() { d->event(deviceId, changeEvent, changeType, d->id, d->context); doneRunning = true; + callbackExecuted->signal(); } -TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id) -:Thread(), d(data), controllerId(id), strData(strD), doneRunning(false) +TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id, TelldusCore::EventRef cbDone) +:Thread(), d(data), controllerId(id), strData(strD), doneRunning(false), callbackExecuted(cbDone) { this->startAndLock(&d->mutex); } @@ -70,10 +69,11 @@ bool TDRawDeviceEventDispatcher::done() const { void TDRawDeviceEventDispatcher::run() { d->event(strData.c_str(), controllerId, d->id, d->context); doneRunning = true; + callbackExecuted->signal(); } -TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, int type, const std::string &v, int t) - :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t), doneRunning(false) +TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, int type, const std::string &v, int t, TelldusCore::EventRef cbDone) + :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t), doneRunning(false), callbackExecuted(cbDone) { this->startAndLock(&d->mutex); } @@ -89,4 +89,5 @@ bool TDSensorEventDispatcher::done() const { void TDSensorEventDispatcher::run() { d->event(protocol.c_str(), model.c_str(), sensorId, dataType, value.c_str(), timestamp, d->id, d->context); doneRunning = true; + callbackExecuted->signal(); } diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 8cc24add..cf86101d 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -7,10 +7,11 @@ * */ - #ifndef CALLBACKDISPATCHER_H #define CALLBACKDISPATCHER_H +#include "common.h" +#include "Event.h" #include "Thread.h" #include "Mutex.h" #include "telldus-core.h" @@ -25,7 +26,7 @@ namespace TelldusCore { class TDDeviceEventDispatcher : public Thread { public: - TDDeviceEventDispatcher(CallbackStruct *data, int deviceId, int method, const std::string &strData); + TDDeviceEventDispatcher(CallbackStruct *data, int deviceId, int method, const std::string &strData, TelldusCore::EventRef cbDone); virtual ~TDDeviceEventDispatcher(); bool done() const; protected: @@ -35,22 +36,24 @@ namespace TelldusCore { CallbackStruct *d; int deviceId, method; std::string strData; + TelldusCore::EventRef callbackExecuted; }; class TDDeviceChangeEventDispatcher : public Thread { public: - TDDeviceChangeEventDispatcher(CallbackStruct *data, int deviceId, int changeEvent, int changeType); + TDDeviceChangeEventDispatcher(CallbackStruct *data, int deviceId, int changeEvent, int changeType, TelldusCore::EventRef cbDone); virtual ~TDDeviceChangeEventDispatcher(); bool done() const; protected: virtual void run(); bool doneRunning; - public: + private: CallbackStruct *d; int deviceId, changeEvent, changeType; + TelldusCore::EventRef callbackExecuted; }; class TDRawDeviceEventDispatcher : public Thread { public: - TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strData, int controllerId); + TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strData, int controllerId, TelldusCore::EventRef cbDone); virtual ~TDRawDeviceEventDispatcher(); bool done() const; protected: @@ -60,10 +63,11 @@ namespace TelldusCore { CallbackStruct *d; int controllerId; std::string strData; + TelldusCore::EventRef callbackExecuted; }; class TDSensorEventDispatcher : public Thread { public: - TDSensorEventDispatcher( CallbackStruct *data, const std::string &protocol, const std::string &model, int id, int dataType, const std::string &value, int timestamp); + TDSensorEventDispatcher( CallbackStruct *data, const std::string &protocol, const std::string &model, int id, int dataType, const std::string &value, int timestamp, TelldusCore::EventRef cbDone); virtual ~TDSensorEventDispatcher(); bool done() const; protected: @@ -77,6 +81,7 @@ namespace TelldusCore { int dataType; std::string value; int timestamp; + TelldusCore::EventRef callbackExecuted; }; } diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp new file mode 100644 index 00000000..fd02b1f0 --- /dev/null +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -0,0 +1,159 @@ +/* + * CallbackMainDispatcher.cpp + * telldus-core + * + * Created by Stefan Persson on 2012-02-23. + * Copyright 2012 Telldus Technologies AB. All rights reserved. + * + */ + +#include "CallbackMainDispatcher.h" + +#include + +class CallbackMainDispatcher::PrivateData { +public: + TelldusCore::EventHandler eventHandler; + TelldusCore::EventRef stopEvent, generalCallbackEvent, janitor; + + std::list > deviceEventThreadList; + std::list > deviceChangeEventThreadList; + std::list > rawDeviceEventThreadList; + std::list > sensorEventThreadList; + + TelldusCore::Mutex mutex; +}; + +CallbackMainDispatcher::CallbackMainDispatcher() +:Thread() +{ + d = new PrivateData; + d->stopEvent = d->eventHandler.addEvent(); + d->generalCallbackEvent = d->eventHandler.addEvent(); + d->janitor = d->eventHandler.addEvent(); //Used for cleanups +} + +CallbackMainDispatcher::~CallbackMainDispatcher(void){ + d->stopEvent->signal(); + wait(); + { + TelldusCore::MutexLocker locker(&d->mutex); + } + delete d; +} + +TelldusCore::EventRef CallbackMainDispatcher::retrieveCallbackEvent(){ + return d->generalCallbackEvent; +} + +void CallbackMainDispatcher::run(){ + + while(!d->stopEvent->isSignaled()){ + if (!d->eventHandler.waitForAny()) { + continue; + } + + if(d->generalCallbackEvent->isSignaled()){ + TelldusCore::EventDataRef eventData = d->generalCallbackEvent->takeSignal(); + + DeviceEventCallbackData *decd = dynamic_cast(eventData.get()); + if(decd){ + std::tr1::shared_ptr ptr(new TelldusCore::TDDeviceEventDispatcher(decd->data, decd->deviceId, decd->deviceState, decd->deviceStateValue, d->janitor)); + TelldusCore::MutexLocker locker(&d->mutex); + d->deviceEventThreadList.push_back(ptr); + continue; + } + + DeviceChangeEventCallbackData *dcecd = dynamic_cast(eventData.get()); + if(dcecd){ + std::tr1::shared_ptr ptr(new TelldusCore::TDDeviceChangeEventDispatcher(dcecd->data, dcecd->deviceId, dcecd->eventDeviceChanges, dcecd->eventChangeType, d->janitor)); + TelldusCore::MutexLocker locker(&d->mutex); + d->deviceChangeEventThreadList.push_back(ptr); + continue; + } + + RawDeviceEventCallbackData *rdecd = dynamic_cast(eventData.get()); + if(rdecd){ + std::tr1::shared_ptr ptr(new TelldusCore::TDRawDeviceEventDispatcher(rdecd->data, rdecd->command, rdecd->controllerId, d->janitor)); + TelldusCore::MutexLocker locker(&d->mutex); + d->rawDeviceEventThreadList.push_back(ptr); + continue; + } + + SensorEventCallbackData *secd = dynamic_cast(eventData.get()); + if(secd){ + std::tr1::shared_ptr ptr(new TelldusCore::TDSensorEventDispatcher(secd->data, secd->protocol, secd->model, secd->id, secd->dataType, secd->value, secd->timestamp, d->janitor)); + TelldusCore::MutexLocker locker(&d->mutex); + d->sensorEventThreadList.push_back(ptr); + continue; + } + } + if (d->janitor->isSignaled()) { + //Clear all of them if there is more than one + while(d->janitor->isSignaled()) { + d->janitor->popSignal(); + } + this->cleanupCallbacks(); + } + } +} + +void CallbackMainDispatcher::cleanupCallbacks() { + bool again = false; + + //Device Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->deviceEventThreadList.begin(); + for (;it != d->deviceEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->deviceEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); + + //Device Change Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->deviceChangeEventThreadList.begin(); + for (;it != d->deviceChangeEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->deviceChangeEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); + + //Raw Device Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->rawDeviceEventThreadList.begin(); + for (;it != d->rawDeviceEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->rawDeviceEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); + + //Sensor Event + do { + again = false; + TelldusCore::MutexLocker locker(&d->mutex); + std::list >::iterator it = d->sensorEventThreadList.begin(); + for (;it != d->sensorEventThreadList.end(); ++it) { + if ((*it)->done()) { + d->sensorEventThreadList.erase(it); + again = true; + break; + } + } + } while (again); +} \ No newline at end of file diff --git a/telldus-core/client/CallbackMainDispatcher.h b/telldus-core/client/CallbackMainDispatcher.h new file mode 100644 index 00000000..39403233 --- /dev/null +++ b/telldus-core/client/CallbackMainDispatcher.h @@ -0,0 +1,69 @@ +/* + * CallbackMainDispatcher.h + * telldus-core + * + * Created by Stefan Persson on 2012-02-23. + * Copyright 2012 Telldus Technologies AB. All rights reserved. + * + */ + +#ifndef CALLBACKMAINDISPATCHER_H +#define CALLBACKMAINDISPATCHER_H + +#include "CallbackDispatcher.h" +#include "Thread.h" +#include "Event.h" +#include "EventHandler.h" + +class DeviceChangeEventCallbackData : public TelldusCore::EventDataBase { +public: + TelldusCore::CallbackStruct *data; + int deviceId; + int eventDeviceChanges; + int eventChangeType; +}; + +class DeviceEventCallbackData : public TelldusCore::EventDataBase { +public: + TelldusCore::CallbackStruct *data; + int deviceId; + int deviceState; + std::string deviceStateValue; +}; + +class RawDeviceEventCallbackData : public TelldusCore::EventDataBase { +public: + TelldusCore::CallbackStruct *data; + int controllerId; + std::string command; +}; + +class SensorEventCallbackData : public TelldusCore::EventDataBase { +public: + TelldusCore::CallbackStruct *data; + std::string protocol; + std::string model; + int id; + int dataType; + std::string value; + int timestamp; +}; + +class CallbackMainDispatcher : public TelldusCore::Thread +{ +public: + CallbackMainDispatcher(void); + ~CallbackMainDispatcher(void); + + TelldusCore::EventRef retrieveCallbackEvent(); + +protected: + void run(); + +private: + class PrivateData; + PrivateData *d; + void cleanupCallbacks(void); +}; + +#endif //CALLBACKMAINDISPATCHER_H diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index cf278757..65067e9e 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,17 +1,11 @@ #include "Client.h" #include "CallbackDispatcher.h" +#include "CallbackMainDispatcher.h" #include "Socket.h" #include "Strings.h" #include "Mutex.h" -#include "common.h" #include -#ifdef _WINDOWS -#include -#else -#include -#endif - using namespace TelldusCore; @@ -35,11 +29,8 @@ public: bool running, sensorCached; std::wstring sensorCache; TelldusCore::Mutex mutex; + CallbackMainDispatcher callbackMainDispatcher; - std::list > deviceEventThreadList; - std::list > deviceChangeEventThreadList; - std::list > rawDeviceEventThreadList; - std::list > sensorEventThreadList; }; Client *Client::instance = 0; @@ -51,6 +42,7 @@ Client::Client() d->lastCallbackId = 0; d->running = true; d->sensorCached = false; + d->callbackMainDispatcher.start(); start(); } @@ -80,32 +72,57 @@ Client *Client::getInstance() { void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue){ TelldusCore::MutexLocker locker(&d->mutex); for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDDeviceEventDispatcher(*callback_it, deviceId, deviceState, TelldusCore::wideToString(deviceStateValue))); - d->deviceEventThreadList.push_back(ptr); + DeviceEventCallbackData *deviceEventCallbackData = new DeviceEventCallbackData(); + deviceEventCallbackData->data = *callback_it; + deviceEventCallbackData->deviceId = deviceId; + deviceEventCallbackData->deviceState = deviceState; + deviceEventCallbackData->deviceStateValue = TelldusCore::wideToString(deviceStateValue); + + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(deviceEventCallbackData); } } void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType){ + TelldusCore::MutexLocker locker(&d->mutex); for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDDeviceChangeEventDispatcher(*callback_it, deviceId, eventDeviceChanges, eventChangeType)); - d->deviceChangeEventThreadList.push_back(ptr); + DeviceChangeEventCallbackData *deviceChangeEventCallbackData = new DeviceChangeEventCallbackData(); + deviceChangeEventCallbackData->data = *callback_it; + deviceChangeEventCallbackData->deviceId = deviceId; + deviceChangeEventCallbackData->eventDeviceChanges = eventDeviceChanges; + deviceChangeEventCallbackData->eventChangeType = eventChangeType; + + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(deviceChangeEventCallbackData); } } void Client::callbackRawEvent(std::wstring command, int controllerId) { + TelldusCore::MutexLocker locker(&d->mutex); for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDRawDeviceEventDispatcher(*callback_it, TelldusCore::wideToString(command), controllerId)); - d->rawDeviceEventThreadList.push_back(ptr); + RawDeviceEventCallbackData *rawDeviceEventCallbackData = new RawDeviceEventCallbackData(); + rawDeviceEventCallbackData->data = *callback_it; + rawDeviceEventCallbackData->controllerId = controllerId; + rawDeviceEventCallbackData->command = TelldusCore::wideToString(command); + + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(rawDeviceEventCallbackData); } } void Client::callbackSensorEvent(const std::wstring &protocol, const std::wstring &model, int id, int dataType, const std::wstring &value, int timestamp) { + TelldusCore::MutexLocker locker(&d->mutex); for(SensorEventList::iterator callback_it = d->sensorEventList.begin(); callback_it != d->sensorEventList.end(); ++callback_it) { - std::tr1::shared_ptr ptr(new TDSensorEventDispatcher(*callback_it, TelldusCore::wideToString(protocol), TelldusCore::wideToString(model), id, dataType, TelldusCore::wideToString(value), timestamp)); - d->sensorEventThreadList.push_back(ptr); + SensorEventCallbackData *sensorEventCallbackData = new SensorEventCallbackData(); + sensorEventCallbackData->data = *callback_it; + sensorEventCallbackData->protocol = TelldusCore::wideToString(protocol); + sensorEventCallbackData->model = TelldusCore::wideToString(model); + sensorEventCallbackData->id = id; + sensorEventCallbackData->dataType = dataType; + sensorEventCallbackData->value = TelldusCore::wideToString(value); + sensorEventCallbackData->timestamp = timestamp; + + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(sensorEventCallbackData); } } @@ -186,7 +203,7 @@ void Client::run(){ } std::wstring clientMessage = d->eventSocket.read(1000); //testing 5 second timeout - + while(clientMessage != L""){ //a message arrived std::wstring type = Message::takeString(&clientMessage); @@ -220,72 +237,9 @@ void Client::run(){ clientMessage = L""; //cleanup, if message contained garbage/unhandled data } } - - //Clean up finished callbacks - this->cleanupCallbacks(); } } -void Client::cleanupCallbacks() { - bool again = false; - - //Device Event - do { - again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->deviceEventThreadList.begin(); - for (;it != d->deviceEventThreadList.end(); ++it) { - if ((*it)->done()) { - d->deviceEventThreadList.erase(it); - again = true; - break; - } - } - } while (again); - - //Device Change Event - do { - again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->deviceChangeEventThreadList.begin(); - for (;it != d->deviceChangeEventThreadList.end(); ++it) { - if ((*it)->done()) { - d->deviceChangeEventThreadList.erase(it); - again = true; - break; - } - } - } while (again); - - //Raw Device Event - do { - again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->rawDeviceEventThreadList.begin(); - for (;it != d->rawDeviceEventThreadList.end(); ++it) { - if ((*it)->done()) { - d->rawDeviceEventThreadList.erase(it); - again = true; - break; - } - } - } while (again); - - //Sensor Event - do { - again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->sensorEventThreadList.begin(); - for (;it != d->sensorEventThreadList.end(); ++it) { - if ((*it)->done()) { - d->sensorEventThreadList.erase(it); - again = true; - break; - } - } - } while (again); -} - std::wstring Client::sendToService(const Message &msg) { int tries = 0; diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 4287f83c..8e7a128b 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -37,8 +37,7 @@ namespace TelldusCore { private: Client(); static std::wstring sendToService(const Message &msg); - void cleanupCallbacks(); - + class PrivateData; PrivateData *d; static Client *instance; diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 5fe760e4..f71c84f7 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -95,7 +95,7 @@ std::wstring Socket::read(int timeout){ BOOL fSuccess = false; std::wstring returnString; bool moreData = true; - + while(moreData){ moreData = false; memset(&buf, 0, sizeof(buf)); @@ -117,7 +117,7 @@ std::wstring Socket::read(int timeout){ // Cancel, we still need to cleanup } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, true); - + if (!fSuccess) { DWORD err = GetLastError(); From f0a07fd42451d9fba37b80a16062204ead991943 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 24 Feb 2012 09:29:49 +0100 Subject: [PATCH 1924/2215] Added CallbackMainDispatcher to TelldusCore namespace --- .../client/CallbackMainDispatcher.cpp | 54 +++++------ telldus-core/client/CallbackMainDispatcher.h | 90 ++++++++++--------- 2 files changed, 74 insertions(+), 70 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index fd02b1f0..82a39012 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -11,17 +11,19 @@ #include +using namespace TelldusCore; + class CallbackMainDispatcher::PrivateData { public: - TelldusCore::EventHandler eventHandler; - TelldusCore::EventRef stopEvent, generalCallbackEvent, janitor; + EventHandler eventHandler; + EventRef stopEvent, generalCallbackEvent, janitor; - std::list > deviceEventThreadList; - std::list > deviceChangeEventThreadList; - std::list > rawDeviceEventThreadList; - std::list > sensorEventThreadList; + std::list > deviceEventThreadList; + std::list > deviceChangeEventThreadList; + std::list > rawDeviceEventThreadList; + std::list > sensorEventThreadList; - TelldusCore::Mutex mutex; + Mutex mutex; }; CallbackMainDispatcher::CallbackMainDispatcher() @@ -37,12 +39,12 @@ CallbackMainDispatcher::~CallbackMainDispatcher(void){ d->stopEvent->signal(); wait(); { - TelldusCore::MutexLocker locker(&d->mutex); + MutexLocker locker(&d->mutex); } delete d; } -TelldusCore::EventRef CallbackMainDispatcher::retrieveCallbackEvent(){ +EventRef CallbackMainDispatcher::retrieveCallbackEvent(){ return d->generalCallbackEvent; } @@ -54,36 +56,36 @@ void CallbackMainDispatcher::run(){ } if(d->generalCallbackEvent->isSignaled()){ - TelldusCore::EventDataRef eventData = d->generalCallbackEvent->takeSignal(); + EventDataRef eventData = d->generalCallbackEvent->takeSignal(); DeviceEventCallbackData *decd = dynamic_cast(eventData.get()); if(decd){ - std::tr1::shared_ptr ptr(new TelldusCore::TDDeviceEventDispatcher(decd->data, decd->deviceId, decd->deviceState, decd->deviceStateValue, d->janitor)); - TelldusCore::MutexLocker locker(&d->mutex); + std::tr1::shared_ptr ptr(new TDDeviceEventDispatcher(decd->data, decd->deviceId, decd->deviceState, decd->deviceStateValue, d->janitor)); + MutexLocker locker(&d->mutex); d->deviceEventThreadList.push_back(ptr); continue; } DeviceChangeEventCallbackData *dcecd = dynamic_cast(eventData.get()); if(dcecd){ - std::tr1::shared_ptr ptr(new TelldusCore::TDDeviceChangeEventDispatcher(dcecd->data, dcecd->deviceId, dcecd->eventDeviceChanges, dcecd->eventChangeType, d->janitor)); - TelldusCore::MutexLocker locker(&d->mutex); + std::tr1::shared_ptr ptr(new TDDeviceChangeEventDispatcher(dcecd->data, dcecd->deviceId, dcecd->eventDeviceChanges, dcecd->eventChangeType, d->janitor)); + MutexLocker locker(&d->mutex); d->deviceChangeEventThreadList.push_back(ptr); continue; } RawDeviceEventCallbackData *rdecd = dynamic_cast(eventData.get()); if(rdecd){ - std::tr1::shared_ptr ptr(new TelldusCore::TDRawDeviceEventDispatcher(rdecd->data, rdecd->command, rdecd->controllerId, d->janitor)); - TelldusCore::MutexLocker locker(&d->mutex); + std::tr1::shared_ptr ptr(new TDRawDeviceEventDispatcher(rdecd->data, rdecd->command, rdecd->controllerId, d->janitor)); + MutexLocker locker(&d->mutex); d->rawDeviceEventThreadList.push_back(ptr); continue; } SensorEventCallbackData *secd = dynamic_cast(eventData.get()); if(secd){ - std::tr1::shared_ptr ptr(new TelldusCore::TDSensorEventDispatcher(secd->data, secd->protocol, secd->model, secd->id, secd->dataType, secd->value, secd->timestamp, d->janitor)); - TelldusCore::MutexLocker locker(&d->mutex); + std::tr1::shared_ptr ptr(new TDSensorEventDispatcher(secd->data, secd->protocol, secd->model, secd->id, secd->dataType, secd->value, secd->timestamp, d->janitor)); + MutexLocker locker(&d->mutex); d->sensorEventThreadList.push_back(ptr); continue; } @@ -104,8 +106,8 @@ void CallbackMainDispatcher::cleanupCallbacks() { //Device Event do { again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->deviceEventThreadList.begin(); + MutexLocker locker(&d->mutex); + std::list >::iterator it = d->deviceEventThreadList.begin(); for (;it != d->deviceEventThreadList.end(); ++it) { if ((*it)->done()) { d->deviceEventThreadList.erase(it); @@ -118,8 +120,8 @@ void CallbackMainDispatcher::cleanupCallbacks() { //Device Change Event do { again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->deviceChangeEventThreadList.begin(); + MutexLocker locker(&d->mutex); + std::list >::iterator it = d->deviceChangeEventThreadList.begin(); for (;it != d->deviceChangeEventThreadList.end(); ++it) { if ((*it)->done()) { d->deviceChangeEventThreadList.erase(it); @@ -132,8 +134,8 @@ void CallbackMainDispatcher::cleanupCallbacks() { //Raw Device Event do { again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->rawDeviceEventThreadList.begin(); + MutexLocker locker(&d->mutex); + std::list >::iterator it = d->rawDeviceEventThreadList.begin(); for (;it != d->rawDeviceEventThreadList.end(); ++it) { if ((*it)->done()) { d->rawDeviceEventThreadList.erase(it); @@ -146,8 +148,8 @@ void CallbackMainDispatcher::cleanupCallbacks() { //Sensor Event do { again = false; - TelldusCore::MutexLocker locker(&d->mutex); - std::list >::iterator it = d->sensorEventThreadList.begin(); + MutexLocker locker(&d->mutex); + std::list >::iterator it = d->sensorEventThreadList.begin(); for (;it != d->sensorEventThreadList.end(); ++it) { if ((*it)->done()) { d->sensorEventThreadList.erase(it); diff --git a/telldus-core/client/CallbackMainDispatcher.h b/telldus-core/client/CallbackMainDispatcher.h index 39403233..61bc9697 100644 --- a/telldus-core/client/CallbackMainDispatcher.h +++ b/telldus-core/client/CallbackMainDispatcher.h @@ -15,55 +15,57 @@ #include "Event.h" #include "EventHandler.h" -class DeviceChangeEventCallbackData : public TelldusCore::EventDataBase { -public: - TelldusCore::CallbackStruct *data; - int deviceId; - int eventDeviceChanges; - int eventChangeType; -}; +namespace TelldusCore { + class DeviceChangeEventCallbackData : public EventDataBase { + public: + CallbackStruct *data; + int deviceId; + int eventDeviceChanges; + int eventChangeType; + }; -class DeviceEventCallbackData : public TelldusCore::EventDataBase { -public: - TelldusCore::CallbackStruct *data; - int deviceId; - int deviceState; - std::string deviceStateValue; -}; + class DeviceEventCallbackData : public EventDataBase { + public: + CallbackStruct *data; + int deviceId; + int deviceState; + std::string deviceStateValue; + }; -class RawDeviceEventCallbackData : public TelldusCore::EventDataBase { -public: - TelldusCore::CallbackStruct *data; - int controllerId; - std::string command; -}; + class RawDeviceEventCallbackData : public EventDataBase { + public: + CallbackStruct *data; + int controllerId; + std::string command; + }; -class SensorEventCallbackData : public TelldusCore::EventDataBase { -public: - TelldusCore::CallbackStruct *data; - std::string protocol; - std::string model; - int id; - int dataType; - std::string value; - int timestamp; -}; + class SensorEventCallbackData : public EventDataBase { + public: + CallbackStruct *data; + std::string protocol; + std::string model; + int id; + int dataType; + std::string value; + int timestamp; + }; -class CallbackMainDispatcher : public TelldusCore::Thread -{ -public: - CallbackMainDispatcher(void); - ~CallbackMainDispatcher(void); + class CallbackMainDispatcher : public Thread + { + public: + CallbackMainDispatcher(void); + ~CallbackMainDispatcher(void); - TelldusCore::EventRef retrieveCallbackEvent(); - -protected: - void run(); + EventRef retrieveCallbackEvent(); + + protected: + void run(); -private: - class PrivateData; - PrivateData *d; - void cleanupCallbacks(void); -}; + private: + class PrivateData; + PrivateData *d; + void cleanupCallbacks(void); + }; +} #endif //CALLBACKMAINDISPATCHER_H From 5d4ee9a4be6abe8d6d5c91d85af17fb1bdd1c07a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 24 Feb 2012 16:45:47 +0100 Subject: [PATCH 1925/2215] Protect against including common.h twice --- telldus-core/common/common.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index e078688a..a223a114 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -5,6 +5,9 @@ // // +#ifndef COMMON_H +#define COMMON_H + #ifdef _WINDOWS #include #include @@ -75,3 +78,5 @@ inline char *wrapStdString( const std::string &string) { inline char *wrapStdWstring( const std::wstring &wstring) { return wrapStdString(TelldusCore::wideToString(wstring)); } + +#endif //COMMON_H From 148fd52c7644f1ca275706ce4b5be0b169a96466 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 24 Feb 2012 16:47:30 +0100 Subject: [PATCH 1926/2215] Create one generic callback dispatcher that can handle all our callbacks. This minimize code duplication and allows us much easier to add and maintain callbacks. --- telldus-core/client/CallbackDispatcher.cpp | 95 +++---- telldus-core/client/CallbackDispatcher.h | 98 +++---- .../client/CallbackMainDispatcher.cpp | 136 ++++------ telldus-core/client/CallbackMainDispatcher.h | 38 +-- telldus-core/client/Client.cpp | 252 +++--------------- telldus-core/client/Client.h | 12 +- telldus-core/client/telldus-core.cpp | 10 +- 7 files changed, 187 insertions(+), 454 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index c8dbc873..6acb2302 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -11,83 +11,54 @@ using namespace TelldusCore; -TDDeviceEventDispatcher::TDDeviceEventDispatcher(CallbackStruct *data, int id, int m, const std::string &strD, TelldusCore::EventRef cbDone) -:Thread(), d(data), deviceId(id), method(m), strData(strD), doneRunning(false), callbackExecuted(cbDone) +TDEventDispatcher::TDEventDispatcher(EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) + :Thread(), doneRunning(false), callbackData(cbd), callback(cb), callbackExecuted(cbDone) { - this->startAndLock(&d->mutex); + this->startAndLock(&callback->mutex); } -TDDeviceEventDispatcher::~TDDeviceEventDispatcher() { +TDEventDispatcher::~TDEventDispatcher() { this->wait(); } -bool TDDeviceEventDispatcher::done() const { +bool TDEventDispatcher::done() const { return doneRunning; } -void TDDeviceEventDispatcher::run() { - char *str = wrapStdString(strData); - d->event(deviceId, method, strData.c_str(), d->id, d->context); +void TDEventDispatcher::run() { + this->fireEvent(); doneRunning = true; callbackExecuted->signal(); } -TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(CallbackStruct *data, int id, int event, int type, TelldusCore::EventRef cbDone) -:Thread(), d(data), deviceId(id), changeEvent(event), changeType(type), doneRunning(false), callbackExecuted(cbDone) -{ - this->startAndLock(&d->mutex); -} +void TDEventDispatcher::fireEvent() { + if (callback->type == CallbackStruct::DeviceEvent) { + DeviceEventCallbackData *data = dynamic_cast(callbackData.get()); + if (!data) { + return; + } + ((TDDeviceEvent)callback->event)(data->deviceId, data->deviceState, data->deviceStateValue.c_str(), callback->id, callback->context); -TDDeviceChangeEventDispatcher::~TDDeviceChangeEventDispatcher() { - this->wait(); -} + } else if (callback->type == CallbackStruct::DeviceChangeEvent) { + DeviceChangeEventCallbackData *data = dynamic_cast(callbackData.get()); + if (!data) { + return; + } + ((TDDeviceChangeEvent)callback->event)(data->deviceId, data->changeEvent, data->changeType, callback->id, callback->context); -bool TDDeviceChangeEventDispatcher::done() const { - return doneRunning; -} + } else if (callback->type == CallbackStruct::RawDeviceEvent) { + RawDeviceEventCallbackData *data = dynamic_cast(callbackData.get()); + if (!data) { + return; + } + ((TDRawDeviceEvent)callback->event)(data->data.c_str(), data->controllerId, callback->id, callback->context); -void TDDeviceChangeEventDispatcher::run() { - d->event(deviceId, changeEvent, changeType, d->id, d->context); - doneRunning = true; - callbackExecuted->signal(); -} + } else if (callback->type == CallbackStruct::SensorEvent) { + SensorEventCallbackData *data = dynamic_cast(callbackData.get()); + if (!data) { + return; + } + ((TDSensorEvent)callback->event)(data->protocol.c_str(), data->model.c_str(), data->id, data->dataType, data->value.c_str(), data->timestamp, callback->id, callback->context); -TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strD, int id, TelldusCore::EventRef cbDone) -:Thread(), d(data), controllerId(id), strData(strD), doneRunning(false), callbackExecuted(cbDone) -{ - this->startAndLock(&d->mutex); -} - -TDRawDeviceEventDispatcher::~TDRawDeviceEventDispatcher() { - this->wait(); -} - -bool TDRawDeviceEventDispatcher::done() const { - return doneRunning; -} - -void TDRawDeviceEventDispatcher::run() { - d->event(strData.c_str(), controllerId, d->id, d->context); - doneRunning = true; - callbackExecuted->signal(); -} - -TDSensorEventDispatcher::TDSensorEventDispatcher( CallbackStruct *data, const std::string &p, const std::string &m, int id, int type, const std::string &v, int t, TelldusCore::EventRef cbDone) - :Thread(), d(data), protocol(p), model(m), sensorId(id), dataType(type), value(v), timestamp(t), doneRunning(false), callbackExecuted(cbDone) -{ - this->startAndLock(&d->mutex); -} - -TDSensorEventDispatcher::~TDSensorEventDispatcher() { - this->wait(); -} - -bool TDSensorEventDispatcher::done() const { - return doneRunning; -} - -void TDSensorEventDispatcher::run() { - d->event(protocol.c_str(), model.c_str(), sensorId, dataType, value.c_str(), timestamp, d->id, d->context); - doneRunning = true; - callbackExecuted->signal(); + } } diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index cf86101d..397343a8 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -17,71 +17,77 @@ #include "telldus-core.h" namespace TelldusCore { - template struct CallbackStruct { + + /*template struct CallbackStruct { T event; int id; void *context; TelldusCore::Mutex mutex; + };*/ + struct CallbackStruct { + enum CallbackType { DeviceEvent, DeviceChangeEvent, RawDeviceEvent, SensorEvent }; + CallbackType type; + void *event; + int id; + void *context; + TelldusCore::Mutex mutex; + }; + /*typedef CallbackStruct DeviceChangeEvent; + typedef CallbackStruct RawDeviceEvent; + typedef CallbackStruct SensorEvent;*/ + + class CallbackData: public EventDataBase { + public: + explicit CallbackData(CallbackStruct::CallbackType t) : EventDataBase(), type(t) {} + CallbackStruct::CallbackType type; }; - class TDDeviceEventDispatcher : public Thread { + class DeviceEventCallbackData : public CallbackData { public: - TDDeviceEventDispatcher(CallbackStruct *data, int deviceId, int method, const std::string &strData, TelldusCore::EventRef cbDone); - virtual ~TDDeviceEventDispatcher(); - bool done() const; - protected: - virtual void run(); - bool doneRunning; - private: - CallbackStruct *d; - int deviceId, method; - std::string strData; - TelldusCore::EventRef callbackExecuted; + DeviceEventCallbackData() : CallbackData(CallbackStruct::DeviceEvent) {} + int deviceId; + int deviceState; + std::string deviceStateValue; }; - class TDDeviceChangeEventDispatcher : public Thread { + class DeviceChangeEventCallbackData : public CallbackData { public: - TDDeviceChangeEventDispatcher(CallbackStruct *data, int deviceId, int changeEvent, int changeType, TelldusCore::EventRef cbDone); - virtual ~TDDeviceChangeEventDispatcher(); - bool done() const; - protected: - virtual void run(); - bool doneRunning; - private: - CallbackStruct *d; - int deviceId, changeEvent, changeType; - TelldusCore::EventRef callbackExecuted; + DeviceChangeEventCallbackData() : CallbackData(CallbackStruct::DeviceChangeEvent) {} + int deviceId; + int changeEvent; + int changeType; }; - class TDRawDeviceEventDispatcher : public Thread { + + class RawDeviceEventCallbackData : public CallbackData { public: - TDRawDeviceEventDispatcher( CallbackStruct *data, const std::string &strData, int controllerId, TelldusCore::EventRef cbDone); - virtual ~TDRawDeviceEventDispatcher(); - bool done() const; - protected: - virtual void run(); - bool doneRunning; - private: - CallbackStruct *d; + RawDeviceEventCallbackData() : CallbackData(CallbackStruct::RawDeviceEvent) {} + std::string data; int controllerId; - std::string strData; - TelldusCore::EventRef callbackExecuted; }; - class TDSensorEventDispatcher : public Thread { + + class SensorEventCallbackData : public CallbackData { public: - TDSensorEventDispatcher( CallbackStruct *data, const std::string &protocol, const std::string &model, int id, int dataType, const std::string &value, int timestamp, TelldusCore::EventRef cbDone); - virtual ~TDSensorEventDispatcher(); - bool done() const; - protected: - virtual void run(); - bool doneRunning; - private: - CallbackStruct *d; + SensorEventCallbackData() : CallbackData(CallbackStruct::SensorEvent) {} std::string protocol; std::string model; - int sensorId; + int id; int dataType; std::string value; int timestamp; - TelldusCore::EventRef callbackExecuted; + }; + + class TDEventDispatcher : public Thread { + public: + TDEventDispatcher(EventDataRef callbackData, CallbackStruct *callback, TelldusCore::EventRef cbDone); + virtual ~TDEventDispatcher(); + bool done() const; + protected: + virtual void run(); + bool doneRunning; + private: + void fireEvent(); + EventDataRef callbackData; + CallbackStruct *callback; + EventRef callbackExecuted; }; } diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 82a39012..fb9a20f3 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -13,17 +13,19 @@ using namespace TelldusCore; +typedef std::list CallbackList; + class CallbackMainDispatcher::PrivateData { public: EventHandler eventHandler; EventRef stopEvent, generalCallbackEvent, janitor; - std::list > deviceEventThreadList; - std::list > deviceChangeEventThreadList; - std::list > rawDeviceEventThreadList; - std::list > sensorEventThreadList; - Mutex mutex; + std::list > eventThreadList; + + CallbackList callbackList; + + int lastCallbackId; }; CallbackMainDispatcher::CallbackMainDispatcher() @@ -33,6 +35,8 @@ CallbackMainDispatcher::CallbackMainDispatcher() d->stopEvent = d->eventHandler.addEvent(); d->generalCallbackEvent = d->eventHandler.addEvent(); d->janitor = d->eventHandler.addEvent(); //Used for cleanups + + d->lastCallbackId = 0; } CallbackMainDispatcher::~CallbackMainDispatcher(void){ @@ -48,6 +52,42 @@ EventRef CallbackMainDispatcher::retrieveCallbackEvent(){ return d->generalCallbackEvent; } +int CallbackMainDispatcher::registerCallback(CallbackStruct::CallbackType type, void *eventFunction, void *context) { + TelldusCore::MutexLocker locker(&d->mutex); + int id = ++d->lastCallbackId; + CallbackStruct *callback = new CallbackStruct; + callback->type = type; + callback->event = eventFunction; + callback->id = id; + callback->context = context; + d->callbackList.push_back(callback); + return id; +} + +bool CallbackMainDispatcher::unregisterCallback(int callbackId) { + CallbackList newEventList; + { + TelldusCore::MutexLocker locker(&d->mutex); + for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { + if ( (*callback_it)->id != callbackId ) { + continue; + } + newEventList.splice(newEventList.begin(), d->callbackList, callback_it); + break; + } + } + if (newEventList.size()) { + CallbackList::iterator it = newEventList.begin(); + { //Lock and unlock to make sure no one else uses the object + TelldusCore::MutexLocker locker( &(*it)->mutex ); + } + delete (*it); + newEventList.erase(it); + return true; + } + return false; +} + void CallbackMainDispatcher::run(){ while(!d->stopEvent->isSignaled()){ @@ -57,37 +97,17 @@ void CallbackMainDispatcher::run(){ if(d->generalCallbackEvent->isSignaled()){ EventDataRef eventData = d->generalCallbackEvent->takeSignal(); - - DeviceEventCallbackData *decd = dynamic_cast(eventData.get()); - if(decd){ - std::tr1::shared_ptr ptr(new TDDeviceEventDispatcher(decd->data, decd->deviceId, decd->deviceState, decd->deviceStateValue, d->janitor)); - MutexLocker locker(&d->mutex); - d->deviceEventThreadList.push_back(ptr); - continue; - } - DeviceChangeEventCallbackData *dcecd = dynamic_cast(eventData.get()); - if(dcecd){ - std::tr1::shared_ptr ptr(new TDDeviceChangeEventDispatcher(dcecd->data, dcecd->deviceId, dcecd->eventDeviceChanges, dcecd->eventChangeType, d->janitor)); - MutexLocker locker(&d->mutex); - d->deviceChangeEventThreadList.push_back(ptr); + CallbackData *cbd = dynamic_cast(eventData.get()); + if (!cbd) { continue; } - - RawDeviceEventCallbackData *rdecd = dynamic_cast(eventData.get()); - if(rdecd){ - std::tr1::shared_ptr ptr(new TDRawDeviceEventDispatcher(rdecd->data, rdecd->command, rdecd->controllerId, d->janitor)); - MutexLocker locker(&d->mutex); - d->rawDeviceEventThreadList.push_back(ptr); - continue; - } - - SensorEventCallbackData *secd = dynamic_cast(eventData.get()); - if(secd){ - std::tr1::shared_ptr ptr(new TDSensorEventDispatcher(secd->data, secd->protocol, secd->model, secd->id, secd->dataType, secd->value, secd->timestamp, d->janitor)); - MutexLocker locker(&d->mutex); - d->sensorEventThreadList.push_back(ptr); - continue; + TelldusCore::MutexLocker locker(&d->mutex); + for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { + if ( (*callback_it)->type == cbd->type ) { + std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); + d->eventThreadList.push_back(ptr); + } } } if (d->janitor->isSignaled()) { @@ -107,55 +127,13 @@ void CallbackMainDispatcher::cleanupCallbacks() { do { again = false; MutexLocker locker(&d->mutex); - std::list >::iterator it = d->deviceEventThreadList.begin(); - for (;it != d->deviceEventThreadList.end(); ++it) { + std::list >::iterator it = d->eventThreadList.begin(); + for (;it != d->eventThreadList.end(); ++it) { if ((*it)->done()) { - d->deviceEventThreadList.erase(it); + d->eventThreadList.erase(it); again = true; break; } } } while (again); - - //Device Change Event - do { - again = false; - MutexLocker locker(&d->mutex); - std::list >::iterator it = d->deviceChangeEventThreadList.begin(); - for (;it != d->deviceChangeEventThreadList.end(); ++it) { - if ((*it)->done()) { - d->deviceChangeEventThreadList.erase(it); - again = true; - break; - } - } - } while (again); - - //Raw Device Event - do { - again = false; - MutexLocker locker(&d->mutex); - std::list >::iterator it = d->rawDeviceEventThreadList.begin(); - for (;it != d->rawDeviceEventThreadList.end(); ++it) { - if ((*it)->done()) { - d->rawDeviceEventThreadList.erase(it); - again = true; - break; - } - } - } while (again); - - //Sensor Event - do { - again = false; - MutexLocker locker(&d->mutex); - std::list >::iterator it = d->sensorEventThreadList.begin(); - for (;it != d->sensorEventThreadList.end(); ++it) { - if ((*it)->done()) { - d->sensorEventThreadList.erase(it); - again = true; - break; - } - } - } while (again); -} \ No newline at end of file +} diff --git a/telldus-core/client/CallbackMainDispatcher.h b/telldus-core/client/CallbackMainDispatcher.h index 61bc9697..c8856895 100644 --- a/telldus-core/client/CallbackMainDispatcher.h +++ b/telldus-core/client/CallbackMainDispatcher.h @@ -16,39 +16,6 @@ #include "EventHandler.h" namespace TelldusCore { - class DeviceChangeEventCallbackData : public EventDataBase { - public: - CallbackStruct *data; - int deviceId; - int eventDeviceChanges; - int eventChangeType; - }; - - class DeviceEventCallbackData : public EventDataBase { - public: - CallbackStruct *data; - int deviceId; - int deviceState; - std::string deviceStateValue; - }; - - class RawDeviceEventCallbackData : public EventDataBase { - public: - CallbackStruct *data; - int controllerId; - std::string command; - }; - - class SensorEventCallbackData : public EventDataBase { - public: - CallbackStruct *data; - std::string protocol; - std::string model; - int id; - int dataType; - std::string value; - int timestamp; - }; class CallbackMainDispatcher : public Thread { @@ -57,7 +24,10 @@ namespace TelldusCore { ~CallbackMainDispatcher(void); EventRef retrieveCallbackEvent(); - + + int registerCallback( TelldusCore::CallbackStruct::CallbackType type, void *eventFunction, void *context ); + bool unregisterCallback( int callbackId ); + protected: void run(); diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index fb9365fc..6a3a87d9 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -9,23 +9,9 @@ using namespace TelldusCore; -typedef CallbackStruct DeviceEvent; -typedef CallbackStruct DeviceChangeEvent; -typedef CallbackStruct RawDeviceEvent; -typedef CallbackStruct SensorEvent; -typedef std::list DeviceEventList; -typedef std::list DeviceChangeList; -typedef std::list RawDeviceEventList; -typedef std::list SensorEventList; - class Client::PrivateData { public: - int lastCallbackId; - DeviceEventList deviceEventList; - DeviceChangeList deviceChangeEventList; Socket eventSocket; - RawDeviceEventList rawDeviceEventList; - SensorEventList sensorEventList; bool running, sensorCached, controllerCached; std::wstring sensorCache, controllerCache; TelldusCore::Mutex mutex; @@ -39,7 +25,6 @@ Client::Client() : Thread() { d = new PrivateData; - d->lastCallbackId = 0; d->running = true; d->sensorCached = false; d->controllerCached = false; @@ -70,63 +55,6 @@ Client *Client::getInstance() { return Client::instance; } -void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue){ - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - DeviceEventCallbackData *deviceEventCallbackData = new DeviceEventCallbackData(); - deviceEventCallbackData->data = *callback_it; - deviceEventCallbackData->deviceId = deviceId; - deviceEventCallbackData->deviceState = deviceState; - deviceEventCallbackData->deviceStateValue = TelldusCore::wideToString(deviceStateValue); - - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(deviceEventCallbackData); - } -} - -void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType){ - - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { - DeviceChangeEventCallbackData *deviceChangeEventCallbackData = new DeviceChangeEventCallbackData(); - deviceChangeEventCallbackData->data = *callback_it; - deviceChangeEventCallbackData->deviceId = deviceId; - deviceChangeEventCallbackData->eventDeviceChanges = eventDeviceChanges; - deviceChangeEventCallbackData->eventChangeType = eventChangeType; - - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(deviceChangeEventCallbackData); - } -} - -void Client::callbackRawEvent(std::wstring command, int controllerId) { - - TelldusCore::MutexLocker locker(&d->mutex); - for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - RawDeviceEventCallbackData *rawDeviceEventCallbackData = new RawDeviceEventCallbackData(); - rawDeviceEventCallbackData->data = *callback_it; - rawDeviceEventCallbackData->controllerId = controllerId; - rawDeviceEventCallbackData->command = TelldusCore::wideToString(command); - - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(rawDeviceEventCallbackData); - } -} - -void Client::callbackSensorEvent(const std::wstring &protocol, const std::wstring &model, int id, int dataType, const std::wstring &value, int timestamp) { - - TelldusCore::MutexLocker locker(&d->mutex); - for(SensorEventList::iterator callback_it = d->sensorEventList.begin(); callback_it != d->sensorEventList.end(); ++callback_it) { - SensorEventCallbackData *sensorEventCallbackData = new SensorEventCallbackData(); - sensorEventCallbackData->data = *callback_it; - sensorEventCallbackData->protocol = TelldusCore::wideToString(protocol); - sensorEventCallbackData->model = TelldusCore::wideToString(model); - sensorEventCallbackData->id = id; - sensorEventCallbackData->dataType = dataType; - sensorEventCallbackData->value = TelldusCore::wideToString(value); - sensorEventCallbackData->timestamp = timestamp; - - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(sensorEventCallbackData); - } -} - bool Client::getBoolFromService(const Message &msg) { return getIntegerFromService(msg) == TELLSTICK_SUCCESS; } @@ -144,48 +72,8 @@ std::wstring Client::getWStringFromService(const Message &msg) { return Message::takeString(&response); } -int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - TelldusCore::MutexLocker locker(&d->mutex); - int id = ++d->lastCallbackId; - DeviceEvent *callback = new DeviceEvent; - callback->event = eventFunction; - callback->id = id; - callback->context = context; - d->deviceEventList.push_back(callback); - return id; -} - -int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { - TelldusCore::MutexLocker locker(&d->mutex); - int id = ++d->lastCallbackId; - DeviceChangeEvent *callback = new DeviceChangeEvent; - callback->event = eventFunction; - callback->id = id; - callback->context = context; - d->deviceChangeEventList.push_back(callback); - return id; -} - -int Client::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { - TelldusCore::MutexLocker locker(&d->mutex); - int id = ++d->lastCallbackId; - RawDeviceEvent *callback = new RawDeviceEvent; - callback->event = eventFunction; - callback->id = id; - callback->context = context; - d->rawDeviceEventList.push_back(callback); - return id; -} - -int Client::registerSensorEvent( TDSensorEvent eventFunction, void *context ) { - TelldusCore::MutexLocker locker(&d->mutex); - int id = ++d->lastCallbackId; - SensorEvent *callback = new SensorEvent; - callback->event = eventFunction; - callback->id = id; - callback->context = context; - d->sensorEventList.push_back(callback); - return id; +int Client::registerEvent( CallbackStruct::CallbackType type, void *eventFunction, void *context ) { + return d->callbackMainDispatcher.registerCallback(type, eventFunction, context ); } void Client::run(){ @@ -209,32 +97,36 @@ void Client::run(){ //a message arrived std::wstring type = Message::takeString(&clientMessage); if(type == L"TDDeviceChangeEvent"){ - int deviceId = Message::takeInt(&clientMessage); - int eventDeviceChanges = Message::takeInt(&clientMessage); - int eventChangeType = Message::takeInt(&clientMessage); - callbackDeviceChangeEvent(deviceId, eventDeviceChanges, eventChangeType); - } - else if(type == L"TDDeviceEvent"){ - int deviceId = Message::takeInt(&clientMessage); - int eventState = Message::takeInt(&clientMessage); - std::wstring eventValue = Message::takeString(&clientMessage); - callbackDeviceEvent(deviceId, eventState, eventValue); - } - else if(type == L"TDRawDeviceEvent"){ - std::wstring command = Message::takeString(&clientMessage); - int controllerId = Message::takeInt(&clientMessage); - callbackRawEvent(command, controllerId); - } - else if(type == L"TDSensorEvent"){ - std::wstring protocol = Message::takeString(&clientMessage); - std::wstring model = Message::takeString(&clientMessage); - int sensorId = Message::takeInt(&clientMessage); - int dataType = Message::takeInt(&clientMessage); - std::wstring value = Message::takeString(&clientMessage); - int timestamp = Message::takeInt(&clientMessage); - callbackSensorEvent(protocol, model, sensorId, dataType, value, timestamp); - } - else{ + DeviceChangeEventCallbackData *data = new DeviceChangeEventCallbackData(); + data->deviceId = Message::takeInt(&clientMessage); + data->changeEvent = Message::takeInt(&clientMessage); + data->changeType = Message::takeInt(&clientMessage); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else if(type == L"TDDeviceEvent"){ + DeviceEventCallbackData *data = new DeviceEventCallbackData(); + data->deviceId = Message::takeInt(&clientMessage); + data->deviceState = Message::takeInt(&clientMessage); + data->deviceStateValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else if(type == L"TDRawDeviceEvent"){ + RawDeviceEventCallbackData *data = new RawDeviceEventCallbackData(); + data->data = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->controllerId = Message::takeInt(&clientMessage); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else if(type == L"TDSensorEvent"){ + SensorEventCallbackData *data = new SensorEventCallbackData(); + data->protocol = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->model = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->id = Message::takeInt(&clientMessage); + data->dataType = Message::takeInt(&clientMessage); + data->value = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->timestamp = Message::takeInt(&clientMessage); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else { clientMessage = L""; //cleanup, if message contained garbage/unhandled data } } @@ -286,85 +178,7 @@ void Client::stopThread(){ } bool Client::unregisterCallback( int callbackId ) { - DeviceEventList newDEList; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { - if ( (*callback_it)->id != callbackId ) { - continue; - } - newDEList.splice(newDEList.begin(), d->deviceEventList, callback_it); - break; - } - } - if (newDEList.size()) { - DeviceEventList::iterator it = newDEList.begin(); - { //Lock and unlock to make sure no one else uses the object - TelldusCore::MutexLocker locker( &(*it)->mutex ); - } - delete (*it); - newDEList.erase(it); - return true; - } - - DeviceChangeList newDCList; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(DeviceChangeList::iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { - if ( (*callback_it)->id != callbackId ) { - continue; - } - newDCList.splice(newDCList.begin(), d->deviceChangeEventList, callback_it); - break; - } - } - if (newDCList.size()) { - DeviceChangeList::iterator it = newDCList.begin(); - {TelldusCore::MutexLocker locker( &(*it)->mutex );} - delete (*it); - newDCList.erase(it); - return true; - } - - RawDeviceEventList newRDEList; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(RawDeviceEventList::iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { - if ( (*callback_it)->id != callbackId ) { - continue; - } - newRDEList.splice(newRDEList.begin(), d->rawDeviceEventList, callback_it ); - break; - } - } - if (newRDEList.size()) { - RawDeviceEventList::iterator it = newRDEList.begin(); - {TelldusCore::MutexLocker locker( &(*it)->mutex );} - delete (*it); - newRDEList.erase(it); - return true; - } - - SensorEventList newSEList; - { - TelldusCore::MutexLocker locker(&d->mutex); - for(SensorEventList::iterator callback_it = d->sensorEventList.begin(); callback_it != d->sensorEventList.end(); ++callback_it) { - if ( (*callback_it)->id != callbackId ) { - continue; - } - newSEList.splice(newSEList.begin(), d->sensorEventList, callback_it ); - break; - } - } - if (newSEList.size()) { - SensorEventList::iterator it = newSEList.begin(); - {TelldusCore::MutexLocker locker( &(*it)->mutex );} - delete (*it); - newSEList.erase(it); - return true; - } - - return false; + return d->callbackMainDispatcher.unregisterCallback(callbackId); } int Client::getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *sensorId, int *dataTypes) { diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 398758dc..ccaf00db 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -4,6 +4,7 @@ #include "Message.h" #include "telldus-core.h" #include "Thread.h" +#include "CallbackDispatcher.h" namespace TelldusCore { class Client : public Thread @@ -14,14 +15,7 @@ namespace TelldusCore { static Client *getInstance(); static void close(); - void callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue); - void callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType); - void callbackRawEvent(std::wstring command, int controllerId); - void callbackSensorEvent(const std::wstring &protocol, const std::wstring &model, int id, int dataType, const std::wstring &value, int timestamp); - int registerDeviceEvent( TDDeviceEvent eventFunction, void *context ); - int registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ); - int registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); - int registerSensorEvent( TDSensorEvent eventFunction, void *context ); + int registerEvent(CallbackStruct::CallbackType type, void *eventFunction, void *context ); void stopThread(void); bool unregisterCallback( int callbackId ); @@ -38,7 +32,7 @@ namespace TelldusCore { private: Client(); static std::wstring sendToService(const Message &msg); - + class PrivateData; PrivateData *d; static Client *instance; diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index e3143fdc..b76f0bfb 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -110,8 +110,8 @@ void WINAPI tdInit(void) { * Added in version 2.0.0. **/ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - Client *client = Client::getInstance(); - return client->registerDeviceEvent( eventFunction, context ); + eventFunction; Client *client = Client::getInstance(); + return client->registerEvent( CallbackStruct::DeviceEvent, (void *)eventFunction, context ); } /** @@ -119,7 +119,7 @@ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { **/ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { Client *client = Client::getInstance(); - return client->registerRawDeviceEvent( eventFunction, context ); + return client->registerEvent( CallbackStruct::RawDeviceEvent, (void *)eventFunction, context ); } /** @@ -127,7 +127,7 @@ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *conte **/ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { Client *client = Client::getInstance(); - return client->registerDeviceChangeEvent( eventFunction, context ); + return client->registerEvent( CallbackStruct::DeviceChangeEvent, (void *)eventFunction, context ); } /** @@ -135,7 +135,7 @@ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void **/ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { Client *client = Client::getInstance(); - return client->registerSensorEvent( eventFunction, context ); + return client->registerEvent( CallbackStruct::SensorEvent, (void *)eventFunction, context ); } /** From 42beb57169769ac2cee81bdfb24b71a0004400cc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 24 Feb 2012 17:39:52 +0100 Subject: [PATCH 1927/2215] Pass around an EventRef instead of a raw Event pointer. This is safer --- telldus-core/service/Controller.cpp | 4 ++-- telldus-core/service/Controller.h | 2 +- telldus-core/service/ControllerManager.cpp | 4 ++-- telldus-core/service/ControllerManager.h | 6 ++---- telldus-core/service/TellStick.h | 2 +- telldus-core/service/TellStick_ftd2xx.cpp | 2 +- telldus-core/service/TelldusMain.cpp | 2 +- 7 files changed, 10 insertions(+), 12 deletions(-) diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 02a88acc..e7b9794f 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -4,11 +4,11 @@ class Controller::PrivateData { public: - TelldusCore::Event *event; + TelldusCore::EventRef event; int id; }; -Controller::Controller(int id, TelldusCore::Event *event){ +Controller::Controller(int id, TelldusCore::EventRef event){ d = new PrivateData; d->event = event; d->id = id; diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index dbf5394c..6c9236af 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -19,7 +19,7 @@ public: virtual int reset() = 0; protected: - Controller(int id, TelldusCore::Event *event); + Controller(int id, TelldusCore::EventRef event); void publishData(const std::string &data) const; void decodePublishData(const std::string &data) const; diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 8c88fba9..de46927c 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -25,11 +25,11 @@ public: int lastControllerId; Settings settings; ControllerMap controllers; - TelldusCore::Event *event; + TelldusCore::EventRef event; TelldusCore::Mutex mutex; }; -ControllerManager::ControllerManager(TelldusCore::Event *event){ +ControllerManager::ControllerManager(TelldusCore::EventRef event){ d = new PrivateData; d->lastControllerId = 0; d->event = event; diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 7e650323..bf754693 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -1,16 +1,14 @@ #ifndef CONTROLLERMANAGER_H #define CONTROLLERMANAGER_H +#include "Event.h" class Controller; -namespace TelldusCore { - class Event; -} #include class ControllerManager { public: - ControllerManager(TelldusCore::Event *event); + ControllerManager(TelldusCore::EventRef event); ~ControllerManager(void); void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted); diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index ba4ccfb7..1a5c1b45 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -24,7 +24,7 @@ public: class TellStick : public Controller, public TelldusCore::Thread { public: - TellStick(int controllerId, TelldusCore::Event *event, const TellStickDescriptor &d); + TellStick(int controllerId, TelldusCore::EventRef event, const TellStickDescriptor &d); virtual ~TellStick(); virtual int firmwareVersion(); diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index e307d336..01f95038 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -40,7 +40,7 @@ public: #endif }; -TellStick::TellStick(int controllerId, TelldusCore::Event *event, const TellStickDescriptor &td ) +TellStick::TellStick(int controllerId, TelldusCore::EventRef event, const TellStickDescriptor &td ) :Controller(controllerId, event) { d = new PrivateData; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index edf4c9de..474b427a 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -64,7 +64,7 @@ void TelldusMain::start(void) { supervisor.setInterval(60); //Once every minute supervisor.start(); - ControllerManager controllerManager(dataEvent.get()); + ControllerManager controllerManager(dataEvent); EventUpdateManager eventUpdateManager; TelldusCore::EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); eventUpdateManager.start(); From 11950d6c2d08cdd164115c8942539a03629aebe1 Mon Sep 17 00:00:00 2001 From: Lauri Aarnio Date: Sat, 25 Feb 2012 12:59:20 +0200 Subject: [PATCH 1928/2215] Fixed a nonportable bash'ism: Use "=" for comparing strings - the "==" operator is specific to bash, use "=" instead; it is compatible with the "test" utility and other shells (and posix, too) --- telldus-core/tdadmin/udev.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/tdadmin/udev.sh b/telldus-core/tdadmin/udev.sh index 8993f81c..3b935d78 100755 --- a/telldus-core/tdadmin/udev.sh +++ b/telldus-core/tdadmin/udev.sh @@ -1,9 +1,9 @@ #!/bin/sh -if [ "${ID_VENDOR_ID}" == "1781" ]; then - if [ "${ACTION}" == "add" ]; then +if [ "${ID_VENDOR_ID}" = "1781" ]; then + if [ "${ACTION}" = "add" ]; then @CMAKE_INSTALL_PREFIX@/sbin/tdadmin controller connect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} - elif [ "${ACTION}" == "remove" ]; then + elif [ "${ACTION}" = "remove" ]; then @CMAKE_INSTALL_PREFIX@/sbin/tdadmin controller disconnect --pid=${ID_MODEL_ID} --vid=${ID_VENDOR_ID} --serial=${ID_SERIAL_SHORT} fi fi From d51e301f6b2d0befeb95948044b5dc4538c18d2f Mon Sep 17 00:00:00 2001 From: Lauri Aarnio Date: Sat, 25 Feb 2012 13:18:49 +0200 Subject: [PATCH 1929/2215] tdtool: minor bugfix: clear timeBuf, so that it won't be used uninitialized --- telldus-core/tdtool/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index c43f49b1..adf2faf7 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -141,6 +141,7 @@ int list_devices() { char humidityvalue[DATA_LENGTH]; humidityvalue[0] = 0; char timeBuf[80]; + timeBuf[0] = 0; time_t timestamp = 0; if (dataTypes & TELLSTICK_TEMPERATURE) { From 842a042cdbf502f00883b8655f442d261fc5ecf3 Mon Sep 17 00:00:00 2001 From: Lauri Aarnio Date: Sat, 25 Feb 2012 23:35:41 +0200 Subject: [PATCH 1930/2215] tdtool: Added an alternative listing format (new options --list-sensors and --list-devices) - These options list devices and sensors in a more machine-readable-friendly format: tab-separated key=value fields, one line/device, and no header lines, percent- or degree signs. Additionally, for sensors, age (in seconds) of the collected data is also printed. --- telldus-core/tdtool/main.cpp | 112 +++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index adf2faf7..f9ff478d 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -25,6 +25,7 @@ void print_usage( char *name ) { printf("\n"); printf("Options:\n"); printf(" -[bdefhlnrv] [ --list ] [ --help ]\n"); + printf(" [ --list-sensors ] [ --list-devices ]\n"); printf(" [ --on device ] [ --off device ] [ --bell device ]\n"); printf(" [ --learn device ]\n"); printf(" [ --dimlevel level --dim device ]\n"); @@ -33,6 +34,12 @@ void print_usage( char *name ) { printf(" --list (-l short option)\n"); printf(" List currently configured devices and all discovered sensors.\n"); printf("\n"); + printf(" --list-sensors\n"); + printf(" --list-devices\n"); + printf(" Alternative devices/sensors listing:\n"); + printf(" Shows devices and/or sensors using key=value format (with tabs as\n"); + printf(" separators, one device/sensor per line, no header lines.)\n"); + printf("\n"); printf(" --help (-h short option)\n"); printf(" Shows this screen.\n"); printf("\n"); @@ -169,6 +176,100 @@ int list_devices() { return TELLSTICK_SUCCESS; } +/* list sensors using key=value format, one sensor/line, no header lines + * and no degree or percent signs attached to the numbers - just + * plain values. */ +int list_kv_sensors() { + char protocol[DATA_LENGTH], model[DATA_LENGTH]; + + tdInit(); + int sensorId = 0, dataTypes = 0; + time_t now = 0; + int sensorStatus; + + time(&now); + while(1) { + sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + if (sensorStatus != 0) break; + + printf("type=sensor\tprotocol=%s\tmodel=%s\tid=%d", + protocol, model, sensorId); + + time_t timestamp = 0; + + if (dataTypes & TELLSTICK_TEMPERATURE) { + char tempvalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp); + printf("\ttemperature=%s", tempvalue); + } + + if (dataTypes & TELLSTICK_HUMIDITY) { + char humidityvalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp); + printf("\thumidity=%s", humidityvalue); + } + + if (dataTypes & (TELLSTICK_TEMPERATURE | TELLSTICK_HUMIDITY)) { + /* timestamp has been set, print time & age */ + /* (age is more useful on e.g. embedded systems + * which may not have real-time clock chips => + * time is useful only as a relative value) */ + char timeBuf[80]; + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + printf("\ttime=%s\tage=%d", timeBuf, (int)(now - timestamp)); + } + printf("\n"); + + } + if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){ + char *errorString = tdGetErrorString(sensorStatus); + fprintf(stderr, "Error fetching sensors: %s\n", errorString); + tdReleaseString(errorString); + return sensorStatus; + } + return TELLSTICK_SUCCESS; +} + +/* list devices using key=value format, one device/line, no header lines */ +int list_kv_devices() { + tdInit(); + int intNum = tdGetNumberOfDevices(); + if (intNum < 0) { + char *errorString = tdGetErrorString(intNum); + fprintf(stderr, "Error fetching devices: %s\n", errorString); + tdReleaseString(errorString); + return intNum; + } + int index = 0; + while (index < intNum) { + tdInit(); + int intId = tdGetDeviceId(index); + char *name = tdGetName(intId); + printf("type=device\tid=%i\tname=%s", intId, name); + tdReleaseString(name); + + int lastSentCommand = tdLastSentCommand(intId, SUPPORTED_METHODS); + char *level = 0; + switch(lastSentCommand) { + case TELLSTICK_TURNON: + printf("\tlastsentcommand=ON"); + break; + case TELLSTICK_TURNOFF: + printf("\tlastsentcommand=OFF"); + break; + case TELLSTICK_DIM: + level = tdLastSentValue(intId); + printf("\tlastsentcommand=DIMMED\tdimlevel=%s", level); + tdReleaseString(level); + break; + /* default: state is unknown, print nothing. */ + } + printf("\n"); + index++; + } +} + + int find_device( char *device ) { tdInit(); int deviceId = atoi(device); @@ -296,12 +397,17 @@ int send_raw_command( char *command ) { return retval; } +#define LIST_KV_SENSORS 1 +#define LIST_KV_DEVICES 2 + int main(int argc, char **argv) { int optch, longindex; static char optstring[] = "ln:f:d:b:v:e:r:hi"; static struct option long_opts[] = { { "list", 0, 0, 'l' }, + { "list-sensors", 0, 0, LIST_KV_SENSORS }, + { "list-devices", 0, 0, LIST_KV_DEVICES }, { "on", 1, 0, 'n' }, { "off", 1, 0, 'f' }, { "dim", 1, 0, 'd' }, @@ -349,6 +455,12 @@ int main(int argc, char **argv) case 'l' : success = list_devices(); break; + case LIST_KV_SENSORS: + success = list_kv_sensors(); + break; + case LIST_KV_DEVICES: + success = list_kv_devices(); + break; case 'n' : success = switch_device(true, &optarg[0]); break; From 246b4273cedacc90ee5a533e9915097ad82cf62d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 15:19:04 +0100 Subject: [PATCH 1931/2215] Add callback TDControllerEvent --- telldus-core/client/CallbackDispatcher.cpp | 7 +++++++ telldus-core/client/CallbackDispatcher.h | 10 +++++++++- telldus-core/client/Client.cpp | 8 ++++++++ telldus-core/client/libtelldus-core.def | 1 + telldus-core/client/telldus-core.cpp | 8 ++++++++ telldus-core/client/telldus-core.h | 2 ++ 6 files changed, 35 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 6acb2302..664c303a 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -60,5 +60,12 @@ void TDEventDispatcher::fireEvent() { } ((TDSensorEvent)callback->event)(data->protocol.c_str(), data->model.c_str(), data->id, data->dataType, data->value.c_str(), data->timestamp, callback->id, callback->context); + } else if (callback->type == CallbackStruct::ControllerEvent) { + ControllerEventCallbackData *data = dynamic_cast(callbackData.get()); + if (!data) { + return; + } + ((TDControllerEvent)callback->event)(data->controllerId, data->changeEvent, data->changeType, data->newValue.c_str(), callback->id, callback->context); + } } diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 397343a8..377b9f7a 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -25,7 +25,7 @@ namespace TelldusCore { TelldusCore::Mutex mutex; };*/ struct CallbackStruct { - enum CallbackType { DeviceEvent, DeviceChangeEvent, RawDeviceEvent, SensorEvent }; + enum CallbackType { DeviceEvent, DeviceChangeEvent, RawDeviceEvent, SensorEvent, ControllerEvent }; CallbackType type; void *event; int id; @@ -74,6 +74,14 @@ namespace TelldusCore { std::string value; int timestamp; }; + class ControllerEventCallbackData : public CallbackData { + public: + ControllerEventCallbackData() : CallbackData(CallbackStruct::ControllerEvent) {} + int controllerId; + int changeEvent; + int changeType; + std::string newValue; + }; class TDEventDispatcher : public Thread { public: diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 6a3a87d9..3b65b079 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -126,6 +126,14 @@ void Client::run(){ data->timestamp = Message::takeInt(&clientMessage); d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + } else if(type == L"TDControllerEvent") { + ControllerEventCallbackData *data = new ControllerEventCallbackData(); + data->controllerId = Message::takeInt(&clientMessage); + data->changeEvent = Message::takeInt(&clientMessage); + data->changeType = Message::takeInt(&clientMessage); + data->newValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + } else { clientMessage = L""; //cleanup, if message contained garbage/unhandled data } diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def index 3bddcea8..be32e8cb 100644 --- a/telldus-core/client/libtelldus-core.def +++ b/telldus-core/client/libtelldus-core.def @@ -57,3 +57,4 @@ EXPORTS tdControllerValue @41 tdSetControllerValue @42 tdRemoveController @43 + tdRegisterControllerEvent @44 diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index b76f0bfb..8108f761 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -138,6 +138,14 @@ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { return client->registerEvent( CallbackStruct::SensorEvent, (void *)eventFunction, context ); } +/** + * Added in version 2.1.2. + **/ +int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context) { + Client *client = Client::getInstance(); + return client->registerEvent( CallbackStruct::ControllerEvent, (void *)eventFunction, context ); +} + /** * Added in version 2.1.0. **/ diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index c9b3d032..edbb5eaa 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -29,6 +29,7 @@ typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); typedef void (WINAPI *TDSensorEvent)(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context); +typedef void (WINAPI *TDControllerEvent)(int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context); #ifndef __cplusplus #define bool char @@ -42,6 +43,7 @@ extern "C" { TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); TELLSTICK_API int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context); TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); TELLSTICK_API void WINAPI tdClose(void); TELLSTICK_API void WINAPI tdReleaseString(char *string); From 237cf4e8e7a05f12e175bfb91e1954f1a515b6e5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 15:26:56 +0100 Subject: [PATCH 1932/2215] Implement controller callback in telldus-service --- telldus-core/client/telldus-core.h | 1 + telldus-core/service/ControllerManager.cpp | 31 +++++++++++++++++---- telldus-core/service/ControllerManager.h | 3 +- telldus-core/service/EventUpdateManager.cpp | 7 +++++ telldus-core/service/TelldusMain.cpp | 2 +- 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index edbb5eaa..e84cf0b4 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -148,5 +148,6 @@ extern "C" { #define TELLSTICK_CHANGE_PROTOCOL 2 #define TELLSTICK_CHANGE_MODEL 3 #define TELLSTICK_CHANGE_METHOD 4 +#define TELLSTICK_CHANGE_AVAILABLE 5 #endif diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index de46927c..e43246dc 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -6,6 +6,7 @@ #include "Message.h" #include "Strings.h" #include "Settings.h" +#include "EventUpdateManager.h" #include "../client/telldus-core.h" #include @@ -25,14 +26,15 @@ public: int lastControllerId; Settings settings; ControllerMap controllers; - TelldusCore::EventRef event; + TelldusCore::EventRef event, updateEvent; TelldusCore::Mutex mutex; }; -ControllerManager::ControllerManager(TelldusCore::EventRef event){ +ControllerManager::ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ d = new PrivateData; d->lastControllerId = 0; d->event = event; + d->updateEvent = updateEvent; this->loadStoredControllers(); this->loadControllers(); } @@ -57,7 +59,7 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str ControllerMap::iterator it = d->controllers.begin(); delete it->second.controller; it->second.controller = 0; - //TODO: signal controller lost + signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0"); } } return; @@ -95,7 +97,7 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str it->second.controller = 0; delete tellstick; - //TODO: signal controller lost + signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0"); } } } @@ -160,12 +162,14 @@ void ControllerManager::loadControllers() { break; } } + bool isNew = false; if (!controllerId) { controllerId = d->settings.addNode(Settings::Controller); if(controllerId < 0){ //TODO: How to handle this? continue; } + isNew = true; d->controllers[controllerId].type = type; d->settings.setControllerType(controllerId, type); d->controllers[controllerId].serial = TelldusCore::charToWstring((*it).serial.c_str()); @@ -179,6 +183,11 @@ void ControllerManager::loadControllers() { continue; } d->controllers[controllerId].controller = controller; + if (isNew) { + signalControllerEvent(controllerId, TELLSTICK_DEVICE_ADDED, type, L""); + } else { + signalControllerEvent(controllerId, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"1"); + } } } @@ -192,6 +201,7 @@ void ControllerManager::loadStoredControllers() { d->controllers[id].name = d->settings.getName(Settings::Controller, id); d->controllers[id].type = d->settings.getControllerType(id); d->controllers[id].serial = d->settings.getControllerSerial(id); + signalControllerEvent(id, TELLSTICK_DEVICE_ADDED, 0, L""); } } @@ -295,7 +305,7 @@ int ControllerManager::removeController(int id) { d->controllers.erase(it); - //TODO: signal + signalControllerEvent(id, TELLSTICK_DEVICE_REMOVED, 0, L""); return TELLSTICK_SUCCESS; } @@ -309,8 +319,19 @@ int ControllerManager::setControllerValue(int id, const std::wstring &name, cons if (name == L"name") { it->second.name = value; d->settings.setName(Settings::Controller, id, value); + signalControllerEvent(id, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME, value); } else { return TELLSTICK_ERROR_SYNTAX; //TODO: Is this the best error? } return TELLSTICK_SUCCESS; } + +void ControllerManager::signalControllerEvent(int controllerId, int changeEvent, int changeType, const std::wstring &newValue) { + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDControllerEvent"; + eventData->controllerId = controllerId; + eventData->eventState = changeEvent; + eventData->eventChangeType = changeType; + eventData->eventValue = newValue; + d->updateEvent->signal(eventData); +} diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index bf754693..ccc6dd1e 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -8,7 +8,7 @@ class Controller; class ControllerManager { public: - ControllerManager(TelldusCore::EventRef event); + ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent); ~ControllerManager(void); void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted); @@ -25,6 +25,7 @@ public: int setControllerValue(int id, const std::wstring &name, const std::wstring &value); private: + void signalControllerEvent(int controllerId, int changeEvent, int changeType, const std::wstring &newValue); class PrivateData; PrivateData *d; }; diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 08a4341c..82263bbc 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -105,6 +105,13 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ msg.addArgument(data->value); msg.addArgument(data->timestamp); } + else if(data->messageType == L"TDControllerEvent") { + msg.addArgument("TDControllerEvent"); + msg.addArgument(data->controllerId); + msg.addArgument(data->eventState); + msg.addArgument(data->eventChangeType); + msg.addArgument(data->eventValue); + } (*it)->write(msg); diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 474b427a..cb852ca5 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -64,10 +64,10 @@ void TelldusMain::start(void) { supervisor.setInterval(60); //Once every minute supervisor.start(); - ControllerManager controllerManager(dataEvent); EventUpdateManager eventUpdateManager; TelldusCore::EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); eventUpdateManager.start(); + ControllerManager controllerManager(dataEvent, deviceUpdateEvent); DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); ConnectionListener clientListener(L"TelldusClient", clientEvent); From d728664785064a747ce7e8d6fa4961c20f3d9eb1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 15:32:21 +0100 Subject: [PATCH 1933/2215] Signal the firmware version as a modified signal. This since we don't know the firmware when a new controller is found. We need to communicate with the device first and the version will be detected later --- telldus-core/client/telldus-core.h | 1 + telldus-core/service/Controller.cpp | 26 ++++++++++++++++++---- telldus-core/service/Controller.h | 5 +++-- telldus-core/service/ControllerManager.cpp | 2 +- telldus-core/service/TellStick.h | 3 +-- telldus-core/service/TellStick_ftd2xx.cpp | 13 ++++------- 6 files changed, 32 insertions(+), 18 deletions(-) diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index e84cf0b4..3067ab7c 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -149,5 +149,6 @@ extern "C" { #define TELLSTICK_CHANGE_MODEL 3 #define TELLSTICK_CHANGE_METHOD 4 #define TELLSTICK_CHANGE_AVAILABLE 5 +#define TELLSTICK_CHANGE_FIRMWARE 6 #endif diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index e7b9794f..02a6b279 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -1,17 +1,20 @@ #include "Controller.h" #include "Protocol.h" -#include //TODO DEBUG +#include "EventUpdateManager.h" +#include "Strings.h" class Controller::PrivateData { public: - TelldusCore::EventRef event; - int id; + TelldusCore::EventRef event, updateEvent; + int id, firmwareVersion; }; -Controller::Controller(int id, TelldusCore::EventRef event){ +Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ d = new PrivateData; d->event = event; + d->updateEvent = updateEvent; d->id = id; + d->firmwareVersion = 0; } Controller::~Controller(){ @@ -33,3 +36,18 @@ void Controller::decodePublishData(const std::string &data) const { this->publishData(*msgIt); } } + +int Controller::firmwareVersion() const { + return d->firmwareVersion; +} + +void Controller::setFirmwareVersion(int version) { + d->firmwareVersion = version; + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDControllerEvent"; + eventData->controllerId = d->id; + eventData->eventState = TELLSTICK_DEVICE_CHANGED; + eventData->eventChangeType = TELLSTICK_CHANGE_FIRMWARE; + eventData->eventValue = TelldusCore::intToWstring(version); + d->updateEvent->signal(eventData); +} diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 6c9236af..eff903f7 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -14,14 +14,15 @@ class Controller { public: virtual ~Controller(); - virtual int firmwareVersion() = 0; + virtual int firmwareVersion() const; virtual int send( const std::string &message ) = 0; virtual int reset() = 0; protected: - Controller(int id, TelldusCore::EventRef event); + Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent); void publishData(const std::string &data) const; void decodePublishData(const std::string &data) const; + void setFirmwareVersion(int version); private: class PrivateData; diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index e43246dc..ba6bcff3 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -177,7 +177,7 @@ void ControllerManager::loadControllers() { } //int controllerId = d->lastControllerId+1; - TellStick *controller = new TellStick(controllerId, d->event, *it); + TellStick *controller = new TellStick(controllerId, d->event, d->updateEvent, *it); if (!controller->isOpen()) { delete controller; continue; diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 1a5c1b45..05e76b04 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -24,10 +24,9 @@ public: class TellStick : public Controller, public TelldusCore::Thread { public: - TellStick(int controllerId, TelldusCore::EventRef event, const TellStickDescriptor &d); + TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &d); virtual ~TellStick(); - virtual int firmwareVersion(); virtual int pid() const; virtual int vid() const; virtual std::string serial() const; diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 01f95038..a10e71f3 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -24,7 +24,7 @@ class TellStick::PrivateData { public: bool open, running, ignoreControllerConfirmation; - int vid, pid, fwVersion; + int vid, pid; std::string serial, message; FT_HANDLE ftHandle; TelldusCore::Mutex mutex; @@ -40,8 +40,8 @@ public: #endif }; -TellStick::TellStick(int controllerId, TelldusCore::EventRef event, const TellStickDescriptor &td ) - :Controller(controllerId, event) +TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &td ) + :Controller(controllerId, event, updateEvent) { d = new PrivateData; #ifdef _WINDOWS @@ -54,7 +54,6 @@ TellStick::TellStick(int controllerId, TelldusCore::EventRef event, const TellSt d->running = false; d->vid = td.vid; d->pid = td.pid; - d->fwVersion = 0; d->serial = td.serial; Settings set; d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true"; @@ -109,10 +108,6 @@ void TellStick::setBaud( int baud ) { FT_SetBaudRate(d->ftHandle, baud); } -int TellStick::firmwareVersion() { - return d->fwVersion; -} - int TellStick::pid() const { return d->pid; } @@ -148,7 +143,7 @@ void TellStick::processData( const std::string &data ) { continue; } else if (data[i] == 10) { // \n found if (d->message.substr(0,2).compare("+V") == 0) { - d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); + setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str())); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); } else if(d->message.substr(0,2).compare("+W") == 0) { From 6196793ff65dbe77af081c8c448a64942e94d626 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 15:34:32 +0100 Subject: [PATCH 1934/2215] Make the firmware setable from C++ --- telldus-gui/Plugins/Controllers/controller.cpp | 5 +++++ telldus-gui/Plugins/Controllers/controller.h | 1 + 2 files changed, 6 insertions(+) diff --git a/telldus-gui/Plugins/Controllers/controller.cpp b/telldus-gui/Plugins/Controllers/controller.cpp index 9f11a766..09a1e770 100644 --- a/telldus-gui/Plugins/Controllers/controller.cpp +++ b/telldus-gui/Plugins/Controllers/controller.cpp @@ -51,6 +51,11 @@ QString Controller::firmware() const { return d->firmware; } +void Controller::setFirmware(const QString &version) { + d->firmware = version; + emit firmwareChanged(); +} + int Controller::id() const { return d->id; } diff --git a/telldus-gui/Plugins/Controllers/controller.h b/telldus-gui/Plugins/Controllers/controller.h index 8d10a3f6..5cc8ee5e 100644 --- a/telldus-gui/Plugins/Controllers/controller.h +++ b/telldus-gui/Plugins/Controllers/controller.h @@ -22,6 +22,7 @@ public: void setAvailable(bool available); QString firmware() const; + void setFirmware(const QString &version); int id() const; From c0fe38e0eb944aa6fcf56fe53bf2c865b3263397 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 15:35:59 +0100 Subject: [PATCH 1935/2215] Implement the controller callback --- .../Plugins/Controllers/controllerlist.cpp | 56 ++++++++++++++++++- .../Plugins/Controllers/controllerlist.h | 6 ++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Controllers/controllerlist.cpp b/telldus-gui/Plugins/Controllers/controllerlist.cpp index 849999d0..76f0f347 100644 --- a/telldus-gui/Plugins/Controllers/controllerlist.cpp +++ b/telldus-gui/Plugins/Controllers/controllerlist.cpp @@ -1,12 +1,12 @@ #include "controllerlist.h" #include "controller.h" -#include #include class ControllerList::PrivateData { public: QList list; + int callbackId; }; ControllerList::ControllerList(QObject *parent) : @@ -18,6 +18,9 @@ ControllerList::ControllerList(QObject *parent) : roles[Qt::UserRole+1] = "controller"; setRoleNames(roles); + connect(this, SIGNAL(controllerEventSignal(int,int,int,QString)), this, SLOT(controllerEventSlot(int,int,int,QString)), Qt::QueuedConnection); + d->callbackId = tdRegisterControllerEvent(&ControllerList::controllerEvent, this); + const int DATA_LENGTH = 255; char name[DATA_LENGTH]; int available, controllerId, type; @@ -30,6 +33,7 @@ ControllerList::ControllerList(QObject *parent) : } ControllerList::~ControllerList() { + tdUnregisterCallback(d->callbackId); delete d; } @@ -46,3 +50,53 @@ void ControllerList::save() { d->list.at(i)->save(); } } + +void ControllerList::controllerEventSlot(int controllerId, int changeEvent, int changeType, const QString &newValue) { + if (changeEvent == TELLSTICK_DEVICE_STATE_CHANGED) { + for(int i = 0; i < d->list.size(); ++i) { + if (d->list.at(i)->id() != controllerId) { + continue; + } + if (changeType == TELLSTICK_CHANGE_AVAILABLE) { + if (newValue == "1") { + d->list.at(i)->setAvailable(true); + } else if (newValue == "0") { + d->list.at(i)->setAvailable(false); + } + } else if (changeType == TELLSTICK_CHANGE_FIRMWARE) { + d->list.at(i)->setFirmware(newValue); + } + } + return; + } + + if (changeEvent == TELLSTICK_DEVICE_ADDED) { + beginInsertRows( QModelIndex(), d->list.size(), d->list.size() ); + Controller *controller = new Controller(controllerId, changeType, "", this); + controller->setAvailable(true); + connect(controller, SIGNAL(nameChanged()), this, SIGNAL(changed())); + d->list.append(controller); + endInsertRows(); + return; + } + + if (changeEvent == TELLSTICK_DEVICE_REMOVED) { + for(int i = 0; i < d->list.size(); ++i) { + if (d->list.at(i)->id() != controllerId) { + continue; + } + beginRemoveRows( QModelIndex(), i, i ); + d->list.takeAt(i); + endRemoveRows(); + } + return; + } +} + +void WINAPI ControllerList::controllerEvent( int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context) { + ControllerList *controllerList = reinterpret_cast(context); + if (!controllerList) { + return; + } + emit controllerList->controllerEventSignal(controllerId, changeEvent, changeType, QString::fromUtf8(newValue)); +} diff --git a/telldus-gui/Plugins/Controllers/controllerlist.h b/telldus-gui/Plugins/Controllers/controllerlist.h index d5884feb..c325868c 100644 --- a/telldus-gui/Plugins/Controllers/controllerlist.h +++ b/telldus-gui/Plugins/Controllers/controllerlist.h @@ -3,6 +3,7 @@ #include #include +#include class ControllerList : public QAbstractListModel { @@ -17,11 +18,16 @@ public: signals: void changed(); + void controllerEventSignal(int controllerId, int changeEvent, int changeType, const QString &newValue); public slots: void save(); +private slots: + void controllerEventSlot(int controllerId, int changeEvent, int changeType, const QString &newValue); + private: + static void WINAPI controllerEvent( int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context); class PrivateData; PrivateData *d; From 5dd66bfb033d8586ec35cc4aa6d1a4c1f37291e9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 15:56:02 +0100 Subject: [PATCH 1936/2215] Compability fixes on unix since the interface changed in a previous commit --- telldus-core/service/TellStick_libftdi.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 8c638168..9f8a919c 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -34,7 +34,7 @@ typedef int DWORD; class TellStick::PrivateData { public: bool open, ignoreControllerConfirmation; - int vid, pid, fwVersion; + int vid, pid; std::string serial, message; ftdi_context ftHandle; EVENT_HANDLE eh; @@ -42,14 +42,13 @@ public: TelldusCore::Mutex mutex; }; -TellStick::TellStick(int controllerId, TelldusCore::Event *event, const TellStickDescriptor &td ) - :Controller(controllerId, event) +TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &td ) + :Controller(controllerId, event, updateEvent) { d = new PrivateData; d->open = false; d->vid = td.vid; d->pid = td.pid; - d->fwVersion = 0; d->serial = td.serial; d->running = false; @@ -96,10 +95,6 @@ TellStick::~TellStick() { delete d; } -int TellStick::firmwareVersion() { - return d->fwVersion; -} - int TellStick::pid() const { return d->pid; } @@ -135,7 +130,7 @@ void TellStick::processData( const std::string &data ) { continue; } else if (data[i] == 10) { // \n found if (d->message.substr(0,2).compare("+V") == 0) { - d->fwVersion = TelldusCore::charToInteger(d->message.substr(2).c_str()); + setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str())); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); } else if(d->message.substr(0,2).compare("+W") == 0) { From 5fcc391c9565dc5d4ae3edcf84132b6a3fcc024c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 16:46:16 +0100 Subject: [PATCH 1937/2215] Update CoreFoundationPreerences settings engine to handle both controllers and devices --- .../SettingsCoreFoundationPreferences.cpp | 176 ++++++++++-------- 1 file changed, 95 insertions(+), 81 deletions(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index c84e5fe7..46b6031b 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: telldussettingsconfuse // -// Description: +// Description: // // // Author: Micke Prag , (C) 2008 @@ -30,7 +30,7 @@ public: CFStringRef userName; CFStringRef hostName; }; - + /* * Constructor */ @@ -60,22 +60,26 @@ std::wstring Settings::getSetting(const std::wstring &strName) const { /* * Return the number of stored devices */ -int Settings::getNumberOfDevices(void) const { +int Settings::getNumberOfNodes(Node type) const { CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); if (!cfarray) return 0; CFIndex size = CFArrayGetCount( cfarray ); - int devices = 0; + int nodes = 0; for (CFIndex k = 0; k < size; ++k) { CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); - if (CFStringHasPrefix( key, CFSTR("devices.") ) && - CFStringHasSuffix( key, CFSTR(".name") ) ) { - devices++; + if (!CFStringHasSuffix( key, CFSTR(".name") )) { + continue; } - } - return devices; + if (type == Device && CFStringHasPrefix( key, CFSTR("devices.") )) { + ++nodes; + } else if (type == Controller && CFStringHasPrefix( key, CFSTR("controllers.") )) { + ++nodes; + } + } + return nodes; } -int Settings::getDeviceId(int intDeviceIndex) const { +int Settings::getNodeId(Node type, int intNodeIndex) const { CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); if (!cfarray) return 0; CFIndex size = CFArrayGetCount( cfarray ); @@ -83,63 +87,73 @@ int Settings::getDeviceId(int intDeviceIndex) const { int id = 0; for (CFIndex k = 0; k < size; ++k) { CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); - if (CFStringHasPrefix( key, CFSTR("devices.") ) && - CFStringHasSuffix( key, CFSTR(".name") ) ) { - - if (index == intDeviceIndex) { - CFArrayRef split = CFStringCreateArrayBySeparatingStrings( 0, key, CFSTR(".") ); - if ( !split || CFArrayGetCount( split ) != 3 ) continue; - - // This code crashes! - //CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); - //if (cfid) - // CFNumberGetValue( cfid, kCFNumberIntType, &id); - - CFStringRef cfid = (CFStringRef) CFArrayGetValueAtIndex( split, 1 ); - char *cp = NULL; - CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1; - cp = (char *)malloc(size); - CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); - char *newcp = (char *)realloc( cp, strlen(cp) + 1); - if (newcp != NULL) { - cp = newcp; - id = atoi(cp); - } else { - //Should not happen - id = 0; - } - free(cp); - - CFRelease(key); - CFRelease(split); - CFRelease(cfid); - break; - } - index++; + if (!CFStringHasSuffix( key, CFSTR(".name") )) { + CFRelease( key ); + continue; } - CFRelease( key ); + if ( type == Device && !CFStringHasPrefix(key, CFSTR("devices.")) ) { + CFRelease( key ); + continue; + } + if ( type == Controller && !CFStringHasPrefix(key, CFSTR("controllers.")) ) { + CFRelease( key ); + continue; + } + if (index == intNodeIndex) { + CFArrayRef split = CFStringCreateArrayBySeparatingStrings( 0, key, CFSTR(".") ); + if ( !split || CFArrayGetCount( split ) != 3 ) continue; + + // This code crashes! + //CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); + //if (cfid) + // CFNumberGetValue( cfid, kCFNumberIntType, &id); + + CFStringRef cfid = (CFStringRef) CFArrayGetValueAtIndex( split, 1 ); + char *cp = NULL; + CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1; + cp = (char *)malloc(size); + CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); + char *newcp = (char *)realloc( cp, strlen(cp) + 1); + if (newcp != NULL) { + cp = newcp; + id = atoi(cp); + } else { + //Should not happen + id = 0; + } + free(cp); + + CFRelease(key); + CFRelease(split); + CFRelease(cfid); + break; + } + index++; } return id; } /* -* Add a new device +* Add a new node */ -int Settings::addDevice() { - int id = getNextDeviceId(); - setStringSetting( id, L"name", L"", false ); //Create a empty name so the device has an entry - setStringSetting( id, L"model", L"", false ); +int Settings::addNode(Node type) { + int id = getNextNodeId(type); + setStringSetting( type, id, L"name", L"", false ); //Create a empty name so the node has an entry + if (type == Device) { + //Is there a reason we do this? + setStringSetting( type, id, L"model", L"", false ); + } return id; } /* -* Get next available device id +* Get next available node id */ -int Settings::getNextDeviceId() const { +int Settings::getNextNodeId(Node type) const { int id = 0, max = 0; - int numberOfDevices = getNumberOfDevices(); - for( int i = 0; i < numberOfDevices; i++) { - id = getDeviceId( i ); + int numberOfNodes = getNumberOfNodes(type); + for( int i = 0; i < numberOfNodes; i++) { + id = getNodeId( type, i ); if (id > max) { max = id; } @@ -151,9 +165,9 @@ int Settings::getNextDeviceId() const { /* * Remove a device */ -int Settings::removeDevice(int intDeviceId){ +int Settings::removeNode(Node type, int intNodeId){ int ret = TELLSTICK_ERROR_DEVICE_NOT_FOUND; - CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d."), intDeviceId); // The key to search for + CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d."), getNodeString(type).c_str(), intNodeId); // The key to search for CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); if (!cfarray) { @@ -167,29 +181,29 @@ int Settings::removeDevice(int intDeviceId){ ret = TELLSTICK_SUCCESS; } } - + CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); return ret; } -std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &wname, bool parameter) const { +std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &wname, bool parameter) const { std::string name(TelldusCore::wideToString(wname)); CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); - + CFStringRef key; if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname); } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname); } - + CFStringRef value; - + value = (CFStringRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName); if (!value) { return L""; } - + std::wstring retval; char *cp = NULL; CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( value ), kCFStringEncodingUTF8) + 1; @@ -204,22 +218,22 @@ std::wstring Settings::getStringSetting(int intDeviceId, const std::wstring &wna retval = L""; } free(cp); - + CFRelease(value); return retval; } -int Settings::setStringSetting(int intDeviceId, const std::wstring &wname, const std::wstring &wvalue, bool parameter) { +int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &wname, const std::wstring &wvalue, bool parameter) { std::string name(TelldusCore::wideToString(wname)); std::string value(TelldusCore::wideToString(wvalue)); CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); CFStringRef cfvalue = CFStringCreateWithCString( 0, value.c_str(), kCFStringEncodingUTF8 ); - + CFStringRef key; if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname); } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname); } CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); @@ -227,19 +241,19 @@ int Settings::setStringSetting(int intDeviceId, const std::wstring &wname, const return TELLSTICK_SUCCESS; } -int Settings::getIntSetting(int intDeviceId, const std::wstring &wname, bool parameter) const { +int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &wname, bool parameter) const { int retval = 0; std::string name(TelldusCore::wideToString(wname)); CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); CFNumberRef cfvalue; - + CFStringRef key; if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname); } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname); } - + cfvalue = (CFNumberRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName); // If the preference exists, use it. @@ -254,23 +268,23 @@ int Settings::getIntSetting(int intDeviceId, const std::wstring &wname, bool par retval = 0; } } - + return retval; } -int Settings::setIntSetting(int intDeviceId, const std::wstring &wname, int value, bool parameter) { +int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &wname, int value, bool parameter) { std::string name(TelldusCore::wideToString(wname)); CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 ); CFNumberRef cfvalue = CFNumberCreate(NULL, kCFNumberIntType, &value); - + CFStringRef key; if (parameter) { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.parameters.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname); } else { - key = CFStringCreateWithFormat(0, NULL, CFSTR("devices.%d.%@"), intDeviceId, cfname); + key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname); } - + CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); - return TELLSTICK_SUCCESS; + return TELLSTICK_SUCCESS; } From 9500c4c898404ccef239eb50336d2ad3d4046c94 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 17:37:52 +0100 Subject: [PATCH 1938/2215] Convert dos endings to unix in telldus-core, see #160 --- telldus-core/CMakeLists.txt | 124 +- telldus-core/client/CMakeLists.txt | 264 +-- telldus-core/client/Client.cpp | 532 ++--- telldus-core/client/Client.h | 84 +- telldus-core/client/libtelldus-core.def | 120 +- telldus-core/cmake/FindSignTool.cmake | 36 +- telldus-core/common/CMakeLists.txt | 152 +- telldus-core/common/Event.cpp | 154 +- telldus-core/common/EventHandler.h | 58 +- telldus-core/common/EventHandler_unix.cpp | 144 +- telldus-core/common/EventHandler_win.cpp | 138 +- telldus-core/common/Event_unix.cpp | 56 +- telldus-core/common/Event_win.cpp | 70 +- telldus-core/common/Message.cpp | 256 +-- telldus-core/common/Message.h | 62 +- telldus-core/common/Socket.h | 66 +- telldus-core/common/Socket_unix.cpp | 254 +-- telldus-core/common/Socket_win.cpp | 358 +-- telldus-core/common/Strings.cpp | 514 ++--- telldus-core/common/Strings.h | 66 +- telldus-core/service/CMakeLists.txt | 504 ++--- .../service/ClientCommunicationHandler.cpp | 530 ++--- telldus-core/service/ConnectionListener.h | 62 +- .../service/ConnectionListener_unix.cpp | 182 +- .../service/ConnectionListener_win.cpp | 298 +-- telldus-core/service/Controller.cpp | 106 +- telldus-core/service/Controller.h | 64 +- telldus-core/service/ControllerManager.cpp | 674 +++--- telldus-core/service/ControllerMessage.cpp | 178 +- telldus-core/service/Device.cpp | 506 ++--- telldus-core/service/Device.h | 86 +- telldus-core/service/DeviceManager.cpp | 1566 +++++++------- telldus-core/service/EventUpdateManager.cpp | 252 +-- telldus-core/service/Log.cpp | 362 ++-- telldus-core/service/Protocol.cpp | 526 ++--- telldus-core/service/Protocol.h | 82 +- telldus-core/service/ProtocolBrateck.cpp | 92 +- telldus-core/service/ProtocolComen.cpp | 24 +- telldus-core/service/ProtocolEverflourish.cpp | 260 +-- telldus-core/service/ProtocolFineoffset.cpp | 90 +- telldus-core/service/ProtocolFuhaote.cpp | 108 +- telldus-core/service/ProtocolGroup.cpp | 16 +- telldus-core/service/ProtocolGroup.h | 8 +- telldus-core/service/ProtocolHasta.cpp | 130 +- telldus-core/service/ProtocolIkea.cpp | 254 +-- telldus-core/service/ProtocolMandolyn.cpp | 76 +- telldus-core/service/ProtocolNexa.cpp | 564 ++--- telldus-core/service/ProtocolOregon.cpp | 230 +- telldus-core/service/ProtocolRisingSun.cpp | 222 +- telldus-core/service/ProtocolSartano.cpp | 208 +- telldus-core/service/ProtocolScene.cpp | 16 +- telldus-core/service/ProtocolScene.h | 8 +- telldus-core/service/ProtocolSilvanChip.cpp | 280 +-- telldus-core/service/ProtocolUpm.cpp | 142 +- telldus-core/service/ProtocolWaveman.cpp | 138 +- telldus-core/service/ProtocolX10.cpp | 348 +-- telldus-core/service/ProtocolYidong.cpp | 48 +- telldus-core/service/SettingsWinRegistry.cpp | 536 ++--- telldus-core/service/TellStick_ftd2xx.cpp | 70 +- telldus-core/service/TelldusMain.cpp | 284 +-- telldus-core/service/TelldusMain.h | 46 +- .../service/TelldusWinService_win.cpp | 354 +-- telldus-core/service/TelldusWinService_win.h | 70 +- telldus-core/service/Timer.cpp | 228 +- telldus-core/service/ftd2xx.h | 30 +- telldus-core/service/main_win.cpp | 40 +- telldus-core/service/win/ftd2xx.h | 1926 ++++++++--------- telldus-core/tdadmin/CMakeLists.txt | 158 +- telldus-core/tdadmin/main.cpp | 170 +- telldus-core/tdtool/CMakeLists.txt | 112 +- telldus-core/tdtool/main.cpp | 972 ++++----- telldus-core/tests/common/CMakeLists.txt | 18 +- 72 files changed, 8881 insertions(+), 8881 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index af00e1c8..47ca4881 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -1,62 +1,62 @@ -PROJECT( telldus-core ) - -CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) - -CMAKE_POLICY(SET CMP0003 NEW) - -OPTION(FORCE_COMPILE_FROM_TRUNK FALSE "Accept compiling source from trunk. This is unsupported and highly unrecommended") -IF(NOT FORCE_COMPILE_FROM_TRUNK) - MESSAGE(FATAL_ERROR "You are compiling sources from trunk. Don't do that!") -ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) - -SET(PACKAGE_MAJOR_VERSION 2) -SET(PACKAGE_MINOR_VERSION 1) -SET(PACKAGE_PATCH_VERSION 1) -SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "") -SET(PACKAGE_SOVERSION 2) - -SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") - -IF (PACKAGE_SUBVERSION) - SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_${PACKAGE_SUBVERSION}") -ELSE (PACKAGE_SUBVERSION) - SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) -ENDIF(PACKAGE_SUBVERSION) - -SET(BUILD_LIBTELLDUS-CORE TRUE CACHE BOOL "Build libtelldus-core") - -IF (WIN32) - SET(TDADMIN_DEFAULT FALSE) -ELSEIF(APPLE) - SET(TDADMIN_DEFAULT FALSE) -ELSE (WIN32) - SET(TDADMIN_DEFAULT TRUE) -ENDIF (WIN32) - -IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - INCLUDE_DIRECTORIES(/usr/local/include) - LINK_DIRECTORIES(/usr/local/lib) -ENDIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - -SET(BUILD_TDTOOL TRUE CACHE BOOL "Build tdtool") -SET(BUILD_TDADMIN ${TDADMIN_DEFAULT} CACHE BOOL "Build tdadmin") - -SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") - -ADD_SUBDIRECTORY(common) -ADD_SUBDIRECTORY(service) -ADD_SUBDIRECTORY(client) - -IF(BUILD_TDTOOL) - IF(WIN32) - ADD_SUBDIRECTORY(3rdparty/openbsd-getopt) - ENDIF() - ADD_SUBDIRECTORY(tdtool) -ENDIF(BUILD_TDTOOL) -IF(BUILD_TDADMIN) - ADD_SUBDIRECTORY(tdadmin) -ENDIF(BUILD_TDADMIN) - -ENABLE_TESTING() -ADD_SUBDIRECTORY(tests) +PROJECT( telldus-core ) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) + +CMAKE_POLICY(SET CMP0003 NEW) + +OPTION(FORCE_COMPILE_FROM_TRUNK FALSE "Accept compiling source from trunk. This is unsupported and highly unrecommended") +IF(NOT FORCE_COMPILE_FROM_TRUNK) + MESSAGE(FATAL_ERROR "You are compiling sources from trunk. Don't do that!") +ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) + +SET(PACKAGE_MAJOR_VERSION 2) +SET(PACKAGE_MINOR_VERSION 1) +SET(PACKAGE_PATCH_VERSION 1) +SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") +SET(PACKAGE_SUBVERSION "") +SET(PACKAGE_SOVERSION 2) + +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") + +IF (PACKAGE_SUBVERSION) + SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_${PACKAGE_SUBVERSION}") +ELSE (PACKAGE_SUBVERSION) + SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) +ENDIF(PACKAGE_SUBVERSION) + +SET(BUILD_LIBTELLDUS-CORE TRUE CACHE BOOL "Build libtelldus-core") + +IF (WIN32) + SET(TDADMIN_DEFAULT FALSE) +ELSEIF(APPLE) + SET(TDADMIN_DEFAULT FALSE) +ELSE (WIN32) + SET(TDADMIN_DEFAULT TRUE) +ENDIF (WIN32) + +IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + INCLUDE_DIRECTORIES(/usr/local/include) + LINK_DIRECTORIES(/usr/local/lib) +ENDIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + +SET(BUILD_TDTOOL TRUE CACHE BOOL "Build tdtool") +SET(BUILD_TDADMIN ${TDADMIN_DEFAULT} CACHE BOOL "Build tdadmin") + +SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") + +ADD_SUBDIRECTORY(common) +ADD_SUBDIRECTORY(service) +ADD_SUBDIRECTORY(client) + +IF(BUILD_TDTOOL) + IF(WIN32) + ADD_SUBDIRECTORY(3rdparty/openbsd-getopt) + ENDIF() + ADD_SUBDIRECTORY(tdtool) +ENDIF(BUILD_TDTOOL) +IF(BUILD_TDADMIN) + ADD_SUBDIRECTORY(tdadmin) +ENDIF(BUILD_TDADMIN) + +ENABLE_TESTING() +ADD_SUBDIRECTORY(tests) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index 03dbd6da..d764c3a7 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -1,132 +1,132 @@ -IF(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - -FIND_PACKAGE( SignTool REQUIRED ) - -######## Non configurable options ######## -SET( telldus-core_SRCS - CallbackDispatcher.cpp - CallbackMainDispatcher.cpp - Client.cpp - telldus-core.cpp -) - -SET( telldus-core_HDRS - CallbackDispatcher.h - CallbackMainDispatcher.cpp - Client.h -) -SET( telldus-core_PUB_HDRS - telldus-core.h -) - -FIND_PACKAGE(Threads) -LIST(APPEND telldus-core_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR}/../common -) - -######## Configurable options for the platform ######## - - - -######## Platforms-specific, non configurable ######## - -IF (APPLE) - #### Mac OS X #### - SET( telldus-core_TARGET TelldusCore ) - ADD_DEFINITIONS( - -D_MACOSX - ) - LIST(APPEND telldus-core_LIBRARIES - TelldusCommon - ) -ELSEIF (WIN32) - #### Windows #### - ADD_DEFINITIONS( -DUNICODE ) - ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No - SET( telldus-core_TARGET TelldusCore ) - LIST(APPEND telldus-core_LIBRARIES - TelldusCommon - ) - CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in - ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc - ) - LIST(APPEND telldus-core_SRCS - libtelldus-core.def - ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in - ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc - ) - ADD_DEFINITIONS( - -D_WINDOWS - -DTELLDUSCORE_EXPORTS - ) - IF (CMAKE_CL_64) - ADD_DEFINITIONS(-D_CL64) - ENDIF(CMAKE_CL_64) -ELSE (APPLE) - #### Linux #### - SET( telldus-core_TARGET telldus-core ) - LIST(APPEND telldus-core_LIBRARIES - TelldusCommon - ) - - ADD_DEFINITIONS( - -D_LINUX - ) -ENDIF (APPLE) - - - -######## Configuring ######## - -ADD_LIBRARY(${telldus-core_TARGET} SHARED - ${telldus-core_SRCS} - ${telldus-core_HDRS} - ${telldus-core_PUB_HDRS} -) - -#Copy public headers files on windows -IF (WIN32) - FOREACH(_FILE ${telldus-core_PUB_HDRS}) - ADD_CUSTOM_COMMAND( TARGET ${telldus-core_TARGET} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy \"${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}\" \"${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\" - COMMENT "Copy ${_FILE}" - ) - ENDFOREACH(_FILE) -ENDIF () - -ADD_DEPENDENCIES(${telldus-core_TARGET} TelldusCommon) - -IF (UNIX) - SET_TARGET_PROPERTIES( ${telldus-core_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") -ENDIF (UNIX) - -TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) - -SET_TARGET_PROPERTIES(${telldus-core_TARGET} PROPERTIES - FRAMEWORK TRUE - INSTALL_NAME_DIR "/Library/Frameworks" - PUBLIC_HEADER ${telldus-core_PUB_HDRS} - VERSION ${PACKAGE_VERSION} - SOVERSION ${PACKAGE_SOVERSION} -) -SIGN(${telldus-core_TARGET}) - -IF (NOT LIB_INSTALL_DIR) - SET(LIB_INSTALL_DIR "lib") -ENDIF (NOT LIB_INSTALL_DIR) - -IF (UNIX) - INSTALL(TARGETS ${telldus-core_TARGET} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${LIB_INSTALL_DIR} - FRAMEWORK DESTINATION "/Library/Frameworks" - PUBLIC_HEADER DESTINATION include - ) -ENDIF (UNIX) - +IF(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +FIND_PACKAGE( SignTool REQUIRED ) + +######## Non configurable options ######## +SET( telldus-core_SRCS + CallbackDispatcher.cpp + CallbackMainDispatcher.cpp + Client.cpp + telldus-core.cpp +) + +SET( telldus-core_HDRS + CallbackDispatcher.h + CallbackMainDispatcher.cpp + Client.h +) +SET( telldus-core_PUB_HDRS + telldus-core.h +) + +FIND_PACKAGE(Threads) +LIST(APPEND telldus-core_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/../common +) + +######## Configurable options for the platform ######## + + + +######## Platforms-specific, non configurable ######## + +IF (APPLE) + #### Mac OS X #### + SET( telldus-core_TARGET TelldusCore ) + ADD_DEFINITIONS( + -D_MACOSX + ) + LIST(APPEND telldus-core_LIBRARIES + TelldusCommon + ) +ELSEIF (WIN32) + #### Windows #### + ADD_DEFINITIONS( -DUNICODE ) + ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No + SET( telldus-core_TARGET TelldusCore ) + LIST(APPEND telldus-core_LIBRARIES + TelldusCommon + ) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc + ) + LIST(APPEND telldus-core_SRCS + libtelldus-core.def + ${CMAKE_CURRENT_SOURCE_DIR}/telldus-core.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/telldus-core.rc + ) + ADD_DEFINITIONS( + -D_WINDOWS + -DTELLDUSCORE_EXPORTS + ) + IF (CMAKE_CL_64) + ADD_DEFINITIONS(-D_CL64) + ENDIF(CMAKE_CL_64) +ELSE (APPLE) + #### Linux #### + SET( telldus-core_TARGET telldus-core ) + LIST(APPEND telldus-core_LIBRARIES + TelldusCommon + ) + + ADD_DEFINITIONS( + -D_LINUX + ) +ENDIF (APPLE) + + + +######## Configuring ######## + +ADD_LIBRARY(${telldus-core_TARGET} SHARED + ${telldus-core_SRCS} + ${telldus-core_HDRS} + ${telldus-core_PUB_HDRS} +) + +#Copy public headers files on windows +IF (WIN32) + FOREACH(_FILE ${telldus-core_PUB_HDRS}) + ADD_CUSTOM_COMMAND( TARGET ${telldus-core_TARGET} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy \"${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}\" \"${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\" + COMMENT "Copy ${_FILE}" + ) + ENDFOREACH(_FILE) +ENDIF () + +ADD_DEPENDENCIES(${telldus-core_TARGET} TelldusCommon) + +IF (UNIX) + SET_TARGET_PROPERTIES( ${telldus-core_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") +ENDIF (UNIX) + +TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) + +SET_TARGET_PROPERTIES(${telldus-core_TARGET} PROPERTIES + FRAMEWORK TRUE + INSTALL_NAME_DIR "/Library/Frameworks" + PUBLIC_HEADER ${telldus-core_PUB_HDRS} + VERSION ${PACKAGE_VERSION} + SOVERSION ${PACKAGE_SOVERSION} +) +SIGN(${telldus-core_TARGET}) + +IF (NOT LIB_INSTALL_DIR) + SET(LIB_INSTALL_DIR "lib") +ENDIF (NOT LIB_INSTALL_DIR) + +IF (UNIX) + INSTALL(TARGETS ${telldus-core_TARGET} + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + ARCHIVE DESTINATION ${LIB_INSTALL_DIR} + FRAMEWORK DESTINATION "/Library/Frameworks" + PUBLIC_HEADER DESTINATION include + ) +ENDIF (UNIX) + diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 3b65b079..20e7e89f 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,266 +1,266 @@ -#include "Client.h" -#include "CallbackDispatcher.h" -#include "CallbackMainDispatcher.h" -#include "Socket.h" -#include "Strings.h" -#include "Mutex.h" - -#include - -using namespace TelldusCore; - -class Client::PrivateData { -public: - Socket eventSocket; - bool running, sensorCached, controllerCached; - std::wstring sensorCache, controllerCache; - TelldusCore::Mutex mutex; - CallbackMainDispatcher callbackMainDispatcher; - -}; - -Client *Client::instance = 0; - -Client::Client() - : Thread() -{ - d = new PrivateData; - d->running = true; - d->sensorCached = false; - d->controllerCached = false; - d->callbackMainDispatcher.start(); - start(); -} - -Client::~Client(void) { - stopThread(); - wait(); - { - TelldusCore::MutexLocker locker(&d->mutex); - } - delete d; -} - -void Client::close() { - if (Client::instance != 0) { - delete Client::instance; - Client::instance = 0; - } -} - -Client *Client::getInstance() { - if (Client::instance == 0) { - Client::instance = new Client(); - } - return Client::instance; -} - -bool Client::getBoolFromService(const Message &msg) { - return getIntegerFromService(msg) == TELLSTICK_SUCCESS; -} - -int Client::getIntegerFromService(const Message &msg) { - std::wstring response = sendToService(msg); - if (response.compare(L"") == 0) { - return TELLSTICK_ERROR_COMMUNICATING_SERVICE; - } - return Message::takeInt(&response); -} - -std::wstring Client::getWStringFromService(const Message &msg) { - std::wstring response = sendToService(msg); - return Message::takeString(&response); -} - -int Client::registerEvent( CallbackStruct::CallbackType type, void *eventFunction, void *context ) { - return d->callbackMainDispatcher.registerCallback(type, eventFunction, context ); -} - -void Client::run(){ - //listen here - d->eventSocket.connect(L"TelldusEvents"); - - while(d->running){ - - if(!d->eventSocket.isConnected()){ - d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service - if(!d->eventSocket.isConnected()){ - //reconnect didn't succeed, wait a while and try again - msleep(2000); - continue; - } - } - - std::wstring clientMessage = d->eventSocket.read(1000); //testing 5 second timeout - - while(clientMessage != L""){ - //a message arrived - std::wstring type = Message::takeString(&clientMessage); - if(type == L"TDDeviceChangeEvent"){ - DeviceChangeEventCallbackData *data = new DeviceChangeEventCallbackData(); - data->deviceId = Message::takeInt(&clientMessage); - data->changeEvent = Message::takeInt(&clientMessage); - data->changeType = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - - } else if(type == L"TDDeviceEvent"){ - DeviceEventCallbackData *data = new DeviceEventCallbackData(); - data->deviceId = Message::takeInt(&clientMessage); - data->deviceState = Message::takeInt(&clientMessage); - data->deviceStateValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - - } else if(type == L"TDRawDeviceEvent"){ - RawDeviceEventCallbackData *data = new RawDeviceEventCallbackData(); - data->data = TelldusCore::wideToString(Message::takeString(&clientMessage)); - data->controllerId = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - - } else if(type == L"TDSensorEvent"){ - SensorEventCallbackData *data = new SensorEventCallbackData(); - data->protocol = TelldusCore::wideToString(Message::takeString(&clientMessage)); - data->model = TelldusCore::wideToString(Message::takeString(&clientMessage)); - data->id = Message::takeInt(&clientMessage); - data->dataType = Message::takeInt(&clientMessage); - data->value = TelldusCore::wideToString(Message::takeString(&clientMessage)); - data->timestamp = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - - } else if(type == L"TDControllerEvent") { - ControllerEventCallbackData *data = new ControllerEventCallbackData(); - data->controllerId = Message::takeInt(&clientMessage); - data->changeEvent = Message::takeInt(&clientMessage); - data->changeType = Message::takeInt(&clientMessage); - data->newValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - - } else { - clientMessage = L""; //cleanup, if message contained garbage/unhandled data - } - } - } -} - -std::wstring Client::sendToService(const Message &msg) { - - int tries = 0; - std::wstring readData; - while(tries < 20){ - tries++; - if(tries == 20){ - TelldusCore::Message msg; - msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); - return msg; - } - Socket s; - s.connect(L"TelldusClient"); - if (!s.isConnected()) { //Connection failed - msleep(500); - continue; //retry - } - s.write(msg.data()); - if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) - msleep(500); - continue; //retry - } - readData = s.read(8000); //TODO changed to 10000 from 5000, how much does this do...? - if(readData == L""){ - msleep(500); - continue; //TODO can we be really sure it SHOULD be anything? - //TODO perhaps break here instead? - } - - if (!s.isConnected()) { //Connection failed sometime during operation... - msleep(500); - continue; //retry - } - break; - } - - return readData; -} - -void Client::stopThread(){ - d->running = false; - d->eventSocket.stopReadWait(); -} - -bool Client::unregisterCallback( int callbackId ) { - return d->callbackMainDispatcher.unregisterCallback(callbackId); -} - -int Client::getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *sensorId, int *dataTypes) { - if (!d->sensorCached) { - Message msg(L"tdSensor"); - std::wstring response = Client::getWStringFromService(msg); - int count = Message::takeInt(&response); - d->sensorCached = true; - d->sensorCache = L""; - if (count > 0) { - d->sensorCache = response; - } - } - - if (d->sensorCache == L"") { - d->sensorCached = false; - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - std::wstring p = Message::takeString(&d->sensorCache); - std::wstring m = Message::takeString(&d->sensorCache); - int id = Message::takeInt(&d->sensorCache); - int dt = Message::takeInt(&d->sensorCache); - - if (protocol && protocolLen) { - strncpy(protocol, TelldusCore::wideToString(p).c_str(), protocolLen); - } - if (model && modelLen) { - strncpy(model, TelldusCore::wideToString(m).c_str(), modelLen); - } - if (sensorId) { - (*sensorId) = id; - } - if (dataTypes) { - (*dataTypes) = dt; - } - - return TELLSTICK_SUCCESS; -} - -int Client::getController(int *controllerId, int *controllerType, char *name, int nameLen, int *available) { - if (!d->controllerCached) { - Message msg(L"tdController"); - std::wstring response = Client::getWStringFromService(msg); - int count = Message::takeInt(&response); - d->controllerCached = true; - d->controllerCache = L""; - if (count > 0) { - d->controllerCache = response; - } - } - - if (d->controllerCache == L"") { - d->controllerCached = false; - return TELLSTICK_ERROR_NOT_FOUND; - } - - int id = Message::takeInt(&d->controllerCache); - int type = Message::takeInt(&d->controllerCache); - std::wstring n = Message::takeString(&d->controllerCache); - int a = Message::takeInt(&d->controllerCache); - - if (controllerId) { - (*controllerId) = id; - } - if (controllerType) { - (*controllerType) = type; - } - if (name && nameLen) { - strncpy(name, TelldusCore::wideToString(n).c_str(), nameLen); - } - if (available) { - (*available) = a; - } - - return TELLSTICK_SUCCESS; -} +#include "Client.h" +#include "CallbackDispatcher.h" +#include "CallbackMainDispatcher.h" +#include "Socket.h" +#include "Strings.h" +#include "Mutex.h" + +#include + +using namespace TelldusCore; + +class Client::PrivateData { +public: + Socket eventSocket; + bool running, sensorCached, controllerCached; + std::wstring sensorCache, controllerCache; + TelldusCore::Mutex mutex; + CallbackMainDispatcher callbackMainDispatcher; + +}; + +Client *Client::instance = 0; + +Client::Client() + : Thread() +{ + d = new PrivateData; + d->running = true; + d->sensorCached = false; + d->controllerCached = false; + d->callbackMainDispatcher.start(); + start(); +} + +Client::~Client(void) { + stopThread(); + wait(); + { + TelldusCore::MutexLocker locker(&d->mutex); + } + delete d; +} + +void Client::close() { + if (Client::instance != 0) { + delete Client::instance; + Client::instance = 0; + } +} + +Client *Client::getInstance() { + if (Client::instance == 0) { + Client::instance = new Client(); + } + return Client::instance; +} + +bool Client::getBoolFromService(const Message &msg) { + return getIntegerFromService(msg) == TELLSTICK_SUCCESS; +} + +int Client::getIntegerFromService(const Message &msg) { + std::wstring response = sendToService(msg); + if (response.compare(L"") == 0) { + return TELLSTICK_ERROR_COMMUNICATING_SERVICE; + } + return Message::takeInt(&response); +} + +std::wstring Client::getWStringFromService(const Message &msg) { + std::wstring response = sendToService(msg); + return Message::takeString(&response); +} + +int Client::registerEvent( CallbackStruct::CallbackType type, void *eventFunction, void *context ) { + return d->callbackMainDispatcher.registerCallback(type, eventFunction, context ); +} + +void Client::run(){ + //listen here + d->eventSocket.connect(L"TelldusEvents"); + + while(d->running){ + + if(!d->eventSocket.isConnected()){ + d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service + if(!d->eventSocket.isConnected()){ + //reconnect didn't succeed, wait a while and try again + msleep(2000); + continue; + } + } + + std::wstring clientMessage = d->eventSocket.read(1000); //testing 5 second timeout + + while(clientMessage != L""){ + //a message arrived + std::wstring type = Message::takeString(&clientMessage); + if(type == L"TDDeviceChangeEvent"){ + DeviceChangeEventCallbackData *data = new DeviceChangeEventCallbackData(); + data->deviceId = Message::takeInt(&clientMessage); + data->changeEvent = Message::takeInt(&clientMessage); + data->changeType = Message::takeInt(&clientMessage); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else if(type == L"TDDeviceEvent"){ + DeviceEventCallbackData *data = new DeviceEventCallbackData(); + data->deviceId = Message::takeInt(&clientMessage); + data->deviceState = Message::takeInt(&clientMessage); + data->deviceStateValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else if(type == L"TDRawDeviceEvent"){ + RawDeviceEventCallbackData *data = new RawDeviceEventCallbackData(); + data->data = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->controllerId = Message::takeInt(&clientMessage); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else if(type == L"TDSensorEvent"){ + SensorEventCallbackData *data = new SensorEventCallbackData(); + data->protocol = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->model = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->id = Message::takeInt(&clientMessage); + data->dataType = Message::takeInt(&clientMessage); + data->value = TelldusCore::wideToString(Message::takeString(&clientMessage)); + data->timestamp = Message::takeInt(&clientMessage); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else if(type == L"TDControllerEvent") { + ControllerEventCallbackData *data = new ControllerEventCallbackData(); + data->controllerId = Message::takeInt(&clientMessage); + data->changeEvent = Message::takeInt(&clientMessage); + data->changeType = Message::takeInt(&clientMessage); + data->newValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); + d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + + } else { + clientMessage = L""; //cleanup, if message contained garbage/unhandled data + } + } + } +} + +std::wstring Client::sendToService(const Message &msg) { + + int tries = 0; + std::wstring readData; + while(tries < 20){ + tries++; + if(tries == 20){ + TelldusCore::Message msg; + msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); + return msg; + } + Socket s; + s.connect(L"TelldusClient"); + if (!s.isConnected()) { //Connection failed + msleep(500); + continue; //retry + } + s.write(msg.data()); + if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) + msleep(500); + continue; //retry + } + readData = s.read(8000); //TODO changed to 10000 from 5000, how much does this do...? + if(readData == L""){ + msleep(500); + continue; //TODO can we be really sure it SHOULD be anything? + //TODO perhaps break here instead? + } + + if (!s.isConnected()) { //Connection failed sometime during operation... + msleep(500); + continue; //retry + } + break; + } + + return readData; +} + +void Client::stopThread(){ + d->running = false; + d->eventSocket.stopReadWait(); +} + +bool Client::unregisterCallback( int callbackId ) { + return d->callbackMainDispatcher.unregisterCallback(callbackId); +} + +int Client::getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *sensorId, int *dataTypes) { + if (!d->sensorCached) { + Message msg(L"tdSensor"); + std::wstring response = Client::getWStringFromService(msg); + int count = Message::takeInt(&response); + d->sensorCached = true; + d->sensorCache = L""; + if (count > 0) { + d->sensorCache = response; + } + } + + if (d->sensorCache == L"") { + d->sensorCached = false; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + std::wstring p = Message::takeString(&d->sensorCache); + std::wstring m = Message::takeString(&d->sensorCache); + int id = Message::takeInt(&d->sensorCache); + int dt = Message::takeInt(&d->sensorCache); + + if (protocol && protocolLen) { + strncpy(protocol, TelldusCore::wideToString(p).c_str(), protocolLen); + } + if (model && modelLen) { + strncpy(model, TelldusCore::wideToString(m).c_str(), modelLen); + } + if (sensorId) { + (*sensorId) = id; + } + if (dataTypes) { + (*dataTypes) = dt; + } + + return TELLSTICK_SUCCESS; +} + +int Client::getController(int *controllerId, int *controllerType, char *name, int nameLen, int *available) { + if (!d->controllerCached) { + Message msg(L"tdController"); + std::wstring response = Client::getWStringFromService(msg); + int count = Message::takeInt(&response); + d->controllerCached = true; + d->controllerCache = L""; + if (count > 0) { + d->controllerCache = response; + } + } + + if (d->controllerCache == L"") { + d->controllerCached = false; + return TELLSTICK_ERROR_NOT_FOUND; + } + + int id = Message::takeInt(&d->controllerCache); + int type = Message::takeInt(&d->controllerCache); + std::wstring n = Message::takeString(&d->controllerCache); + int a = Message::takeInt(&d->controllerCache); + + if (controllerId) { + (*controllerId) = id; + } + if (controllerType) { + (*controllerType) = type; + } + if (name && nameLen) { + strncpy(name, TelldusCore::wideToString(n).c_str(), nameLen); + } + if (available) { + (*available) = a; + } + + return TELLSTICK_SUCCESS; +} diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index ccaf00db..2bd0c5ce 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -1,42 +1,42 @@ -#ifndef CLIENT_H -#define CLIENT_H - -#include "Message.h" -#include "telldus-core.h" -#include "Thread.h" -#include "CallbackDispatcher.h" - -namespace TelldusCore { - class Client : public Thread - { - public: - ~Client(void); - - static Client *getInstance(); - static void close(); - - int registerEvent(CallbackStruct::CallbackType type, void *eventFunction, void *context ); - void stopThread(void); - bool unregisterCallback( int callbackId ); - - int getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); - int getController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); - - static bool getBoolFromService(const Message &msg); - static int getIntegerFromService(const Message &msg); - static std::wstring getWStringFromService(const Message &msg); - - protected: - void run(void); - - private: - Client(); - static std::wstring sendToService(const Message &msg); - - class PrivateData; - PrivateData *d; - static Client *instance; - }; -} - -#endif //CLIENT_H +#ifndef CLIENT_H +#define CLIENT_H + +#include "Message.h" +#include "telldus-core.h" +#include "Thread.h" +#include "CallbackDispatcher.h" + +namespace TelldusCore { + class Client : public Thread + { + public: + ~Client(void); + + static Client *getInstance(); + static void close(); + + int registerEvent(CallbackStruct::CallbackType type, void *eventFunction, void *context ); + void stopThread(void); + bool unregisterCallback( int callbackId ); + + int getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); + int getController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); + + static bool getBoolFromService(const Message &msg); + static int getIntegerFromService(const Message &msg); + static std::wstring getWStringFromService(const Message &msg); + + protected: + void run(void); + + private: + Client(); + static std::wstring sendToService(const Message &msg); + + class PrivateData; + PrivateData *d; + static Client *instance; + }; +} + +#endif //CLIENT_H diff --git a/telldus-core/client/libtelldus-core.def b/telldus-core/client/libtelldus-core.def index be32e8cb..57c3976e 100644 --- a/telldus-core/client/libtelldus-core.def +++ b/telldus-core/client/libtelldus-core.def @@ -1,60 +1,60 @@ -LIBRARY tellduscore -EXPORTS - tdGetNumberOfDevices @1 - tdGetDeviceId @2 - - tdGetName @3 - tdGetProtocol @4 - tdGetModel @5 - tdGetDeviceParameter @6 - - tdSetName @7 - tdSetProtocol @8 - tdSetModel @9 - tdSetDeviceParameter @10 - - tdAddDevice @11 - tdRemoveDevice @12 - - tdMethods @13 - tdTurnOn @14 - tdTurnOff @15 - tdBell @16 - tdDim @17 - - tdGetErrorString @18 - - tdClose @19 - - tdInit @20 - tdRegisterDeviceEvent @21 - tdLastSentCommand @22 - tdGetDeviceType @23 - - tdSendRawCommand @24 - tdRegisterRawDeviceEvent @25 - - tdLearn @26 - tdLastSentValue @27 - - tdReleaseString @28 - tdUnregisterCallback @29 - - tdConnectTellStickController @30 - tdDisconnectTellStickController @31 - - tdRegisterDeviceChangeEvent @32 - tdExecute @33 - tdUp @34 - tdDown @35 - tdStop @36 - - tdRegisterSensorEvent @37 - tdSensor @38 - tdSensorValue @39 - - tdController @40 - tdControllerValue @41 - tdSetControllerValue @42 - tdRemoveController @43 - tdRegisterControllerEvent @44 +LIBRARY tellduscore +EXPORTS + tdGetNumberOfDevices @1 + tdGetDeviceId @2 + + tdGetName @3 + tdGetProtocol @4 + tdGetModel @5 + tdGetDeviceParameter @6 + + tdSetName @7 + tdSetProtocol @8 + tdSetModel @9 + tdSetDeviceParameter @10 + + tdAddDevice @11 + tdRemoveDevice @12 + + tdMethods @13 + tdTurnOn @14 + tdTurnOff @15 + tdBell @16 + tdDim @17 + + tdGetErrorString @18 + + tdClose @19 + + tdInit @20 + tdRegisterDeviceEvent @21 + tdLastSentCommand @22 + tdGetDeviceType @23 + + tdSendRawCommand @24 + tdRegisterRawDeviceEvent @25 + + tdLearn @26 + tdLastSentValue @27 + + tdReleaseString @28 + tdUnregisterCallback @29 + + tdConnectTellStickController @30 + tdDisconnectTellStickController @31 + + tdRegisterDeviceChangeEvent @32 + tdExecute @33 + tdUp @34 + tdDown @35 + tdStop @36 + + tdRegisterSensorEvent @37 + tdSensor @38 + tdSensorValue @39 + + tdController @40 + tdControllerValue @41 + tdSetControllerValue @42 + tdRemoveController @43 + tdRegisterControllerEvent @44 diff --git a/telldus-core/cmake/FindSignTool.cmake b/telldus-core/cmake/FindSignTool.cmake index 5ea02930..ff7dfc08 100644 --- a/telldus-core/cmake/FindSignTool.cmake +++ b/telldus-core/cmake/FindSignTool.cmake @@ -1,19 +1,19 @@ -IF(WIN32) - SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") -ENDIF() - -FUNCTION(SIGN TARGET) - IF (NOT WIN32) - RETURN() - ENDIF() - IF (NOT SIGN_FILES) - RETURN() - ENDIF() - GET_TARGET_PROPERTY(file ${TARGET} LOCATION) - GET_FILENAME_COMPONENT(filename ${file} NAME) - ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD - COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} - COMMENT "Signing file ${filename}" - ) -ENDFUNCTION() +IF(WIN32) + SET(SIGN_FILES FALSE CACHE BOOL "Sign the generated files. This requires a certificate to be installed on the computer!") +ENDIF() + +FUNCTION(SIGN TARGET) + IF (NOT WIN32) + RETURN() + ENDIF() + IF (NOT SIGN_FILES) + RETURN() + ENDIF() + GET_TARGET_PROPERTY(file ${TARGET} LOCATION) + GET_FILENAME_COMPONENT(filename ${file} NAME) + ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD + COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} + COMMENT "Signing file ${filename}" + ) +ENDFUNCTION() diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index c0d64759..b55277e4 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -1,87 +1,87 @@ -IF(COMMAND cmake_policy) - CMAKE_POLICY(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - -######## Non configurable options ######## -SET( telldus-common_SRCS - Event.cpp - Message.cpp - Mutex.cpp - Strings.cpp - Thread.cpp -) - -SET( telldus-common_HDRS - common.h - Event.h - EventHandler.h - Message.h - Mutex.h - Socket.h - Strings.h - Thread.h -) - -######## Configurable options for the platform ######## - - -######## Platforms-specific, non configurable ######## - -IF (APPLE) - #### Mac OS X #### - FIND_LIBRARY(ICONV_LIBRARY iconv) - ADD_DEFINITIONS( -D_MACOSX ) - LIST(APPEND telldus-common_SRCS - Event_unix.cpp - EventHandler_unix.cpp - Socket_unix.cpp +IF(COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +######## Non configurable options ######## +SET( telldus-common_SRCS + Event.cpp + Message.cpp + Mutex.cpp + Strings.cpp + Thread.cpp +) + +SET( telldus-common_HDRS + common.h + Event.h + EventHandler.h + Message.h + Mutex.h + Socket.h + Strings.h + Thread.h +) + +######## Configurable options for the platform ######## + + +######## Platforms-specific, non configurable ######## + +IF (APPLE) + #### Mac OS X #### + FIND_LIBRARY(ICONV_LIBRARY iconv) + ADD_DEFINITIONS( -D_MACOSX ) + LIST(APPEND telldus-common_SRCS + Event_unix.cpp + EventHandler_unix.cpp + Socket_unix.cpp stdlibc_workaround.cpp #Remove this when we drop support for 10.5 - ) - LIST(APPEND telldus-common_LIBRARIES - ${ICONV_LIBRARY} - ) -ELSEIF (WIN32) - #### Windows #### - ADD_DEFINITIONS( -DUNICODE ) - ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No - ADD_DEFINITIONS( -D_WINDOWS ) - LIST(APPEND telldus-common_SRCS - Event_win.cpp - EventHandler_win.cpp - Socket_win.cpp - ) + ) + LIST(APPEND telldus-common_LIBRARIES + ${ICONV_LIBRARY} + ) +ELSEIF (WIN32) + #### Windows #### + ADD_DEFINITIONS( -DUNICODE ) + ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No + ADD_DEFINITIONS( -D_WINDOWS ) + LIST(APPEND telldus-common_SRCS + Event_win.cpp + EventHandler_win.cpp + Socket_win.cpp + ) ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") #### FreeBSD #### FIND_LIBRARY(ICONV_LIBRARY iconv) ADD_DEFINITIONS( -D_FREEBSD ) LIST(APPEND telldus-common_SRCS - Event_unix.cpp - EventHandler_unix.cpp + Event_unix.cpp + EventHandler_unix.cpp Socket_unix.cpp ) LIST(APPEND telldus-common_LIBRARIES ${ICONV_LIBRARY} ) -ELSE (APPLE) - #### Linux #### - ADD_DEFINITIONS( -D_LINUX ) - LIST(APPEND telldus-common_SRCS - Event_unix.cpp - EventHandler_unix.cpp - Socket_unix.cpp - ) -ENDIF (APPLE) - - -######## Configuring ######## - -ADD_LIBRARY(TelldusCommon STATIC - ${telldus-common_SRCS} - ${telldus-common_HDRS} -) - -IF (UNIX) - SET_TARGET_PROPERTIES( TelldusCommon PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") -ENDIF (UNIX) - -TARGET_LINK_LIBRARIES( TelldusCommon ${telldus-common_LIBRARIES} ) +ELSE (APPLE) + #### Linux #### + ADD_DEFINITIONS( -D_LINUX ) + LIST(APPEND telldus-common_SRCS + Event_unix.cpp + EventHandler_unix.cpp + Socket_unix.cpp + ) +ENDIF (APPLE) + + +######## Configuring ######## + +ADD_LIBRARY(TelldusCommon STATIC + ${telldus-common_SRCS} + ${telldus-common_HDRS} +) + +IF (UNIX) + SET_TARGET_PROPERTIES( TelldusCommon PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") +ENDIF (UNIX) + +TARGET_LINK_LIBRARIES( TelldusCommon ${telldus-common_LIBRARIES} ) diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index 76d060cb..02ed6b8c 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -1,77 +1,77 @@ -#include "Event.h" -#include "EventHandler.h" -#include "Mutex.h" - -#include - -using namespace TelldusCore; - -EventData::~EventData() { -} - -bool EventData::isValid() const { - return false; -}; - -bool EventDataBase::isValid() const { - return true; -}; - -class EventBase::PrivateData { -public: - TelldusCore::Mutex mutex; - EventHandler *handler; - std::list eventDataList; -}; - -EventBase::EventBase(TelldusCore::EventHandler *handler) { - d = new PrivateData; - d->handler = handler; -} - -EventBase::~EventBase(void) { - delete d; -} - -void EventBase::clearHandler() { - TelldusCore::MutexLocker locker(&d->mutex); - d->handler = 0; -} - -void EventBase::popSignal() { - this->takeSignal(); -} - -EventHandler *EventBase::handler() const { - return d->handler; -} - -bool EventBase::isSignaled() { - TelldusCore::MutexLocker locker(&d->mutex); - return (d->eventDataList.size() > 0); -} - -void EventBase::signal() { - signal(new EventData()); -} - -void EventBase::signal(EventData *eventData) { - { - TelldusCore::MutexLocker locker(&d->mutex); - d->eventDataList.push_back(EventDataRef(eventData)); - } - sendSignal(); -} - -EventDataRef EventBase::takeSignal() { - TelldusCore::MutexLocker locker(&d->mutex); - if (d->eventDataList.size() == 0) { - return EventDataRef(new EventData()); - } - EventDataRef data = d->eventDataList.front(); - d->eventDataList.pop_front(); - if (d->eventDataList.size() == 0) { - this->clearSignal(); - } - return data; -} +#include "Event.h" +#include "EventHandler.h" +#include "Mutex.h" + +#include + +using namespace TelldusCore; + +EventData::~EventData() { +} + +bool EventData::isValid() const { + return false; +}; + +bool EventDataBase::isValid() const { + return true; +}; + +class EventBase::PrivateData { +public: + TelldusCore::Mutex mutex; + EventHandler *handler; + std::list eventDataList; +}; + +EventBase::EventBase(TelldusCore::EventHandler *handler) { + d = new PrivateData; + d->handler = handler; +} + +EventBase::~EventBase(void) { + delete d; +} + +void EventBase::clearHandler() { + TelldusCore::MutexLocker locker(&d->mutex); + d->handler = 0; +} + +void EventBase::popSignal() { + this->takeSignal(); +} + +EventHandler *EventBase::handler() const { + return d->handler; +} + +bool EventBase::isSignaled() { + TelldusCore::MutexLocker locker(&d->mutex); + return (d->eventDataList.size() > 0); +} + +void EventBase::signal() { + signal(new EventData()); +} + +void EventBase::signal(EventData *eventData) { + { + TelldusCore::MutexLocker locker(&d->mutex); + d->eventDataList.push_back(EventDataRef(eventData)); + } + sendSignal(); +} + +EventDataRef EventBase::takeSignal() { + TelldusCore::MutexLocker locker(&d->mutex); + if (d->eventDataList.size() == 0) { + return EventDataRef(new EventData()); + } + EventDataRef data = d->eventDataList.front(); + d->eventDataList.pop_front(); + if (d->eventDataList.size() == 0) { + this->clearSignal(); + } + return data; +} diff --git a/telldus-core/common/EventHandler.h b/telldus-core/common/EventHandler.h index d6a59ef7..7123bf90 100644 --- a/telldus-core/common/EventHandler.h +++ b/telldus-core/common/EventHandler.h @@ -1,29 +1,29 @@ -#ifndef EVENTHANDLER_H -#define EVENTHANDLER_H - -#include "Event.h" - -namespace TelldusCore { - - class EventHandler { - public: - EventHandler(); - virtual ~EventHandler(void); - - EventRef addEvent(); - - bool waitForAny(); - - protected: - void signal(Event *event); - - private: - class PrivateData; - PrivateData *d; - bool listIsSignalled(); - - friend class Event; - }; -} - -#endif //EVENTHANDLER_H +#ifndef EVENTHANDLER_H +#define EVENTHANDLER_H + +#include "Event.h" + +namespace TelldusCore { + + class EventHandler { + public: + EventHandler(); + virtual ~EventHandler(void); + + EventRef addEvent(); + + bool waitForAny(); + + protected: + void signal(Event *event); + + private: + class PrivateData; + PrivateData *d; + bool listIsSignalled(); + + friend class Event; + }; +} + +#endif //EVENTHANDLER_H diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index f826c004..df36338e 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -1,72 +1,72 @@ -#include "EventHandler.h" -#include "Event.h" -#include "Mutex.h" -#include "Thread.h" -#include -#include -#include - -using namespace TelldusCore; - -class EventHandler::PrivateData { -public: - pthread_cond_t event; - pthread_mutex_t mutex; - std::list eventList; - TelldusCore::Mutex listMutex; -}; - -EventHandler::EventHandler() { - d = new PrivateData; - pthread_cond_init(&d->event, NULL); - pthread_mutex_init(&d->mutex, NULL); -} - -EventHandler::~EventHandler(void) { - pthread_mutex_destroy(&d->mutex); - pthread_cond_destroy(&d->event); - - std::list::const_iterator it = d->eventList.begin(); - for(; it != d->eventList.end(); ++it) { - //We clear the handler if someone else still has a reference to the event - (*it)->clearHandler(); - } - - delete d; -} - -EventRef EventHandler::addEvent() { - EventRef event(new Event(this)); - TelldusCore::MutexLocker locker(&d->listMutex); - d->eventList.push_back(event); - return event; -} - -bool EventHandler::listIsSignalled(){ - TelldusCore::MutexLocker locker(&d->listMutex); - - std::list::const_iterator it = d->eventList.begin(); - for(; it != d->eventList.end(); ++it) { - if((*it)->isSignaled()){ - return true; - } - } - return false; -} - -void EventHandler::signal(Event *event) { - pthread_mutex_lock(&d->mutex); - //event->setSignaled(); - pthread_cond_signal(&d->event); - pthread_mutex_unlock(&d->mutex); -} - -bool EventHandler::waitForAny() { - pthread_mutex_lock(&d->mutex); - while(!listIsSignalled()) { - pthread_cond_wait(&d->event, &d->mutex); - } - pthread_mutex_unlock(&d->mutex); - - return true; -} +#include "EventHandler.h" +#include "Event.h" +#include "Mutex.h" +#include "Thread.h" +#include +#include +#include + +using namespace TelldusCore; + +class EventHandler::PrivateData { +public: + pthread_cond_t event; + pthread_mutex_t mutex; + std::list eventList; + TelldusCore::Mutex listMutex; +}; + +EventHandler::EventHandler() { + d = new PrivateData; + pthread_cond_init(&d->event, NULL); + pthread_mutex_init(&d->mutex, NULL); +} + +EventHandler::~EventHandler(void) { + pthread_mutex_destroy(&d->mutex); + pthread_cond_destroy(&d->event); + + std::list::const_iterator it = d->eventList.begin(); + for(; it != d->eventList.end(); ++it) { + //We clear the handler if someone else still has a reference to the event + (*it)->clearHandler(); + } + + delete d; +} + +EventRef EventHandler::addEvent() { + EventRef event(new Event(this)); + TelldusCore::MutexLocker locker(&d->listMutex); + d->eventList.push_back(event); + return event; +} + +bool EventHandler::listIsSignalled(){ + TelldusCore::MutexLocker locker(&d->listMutex); + + std::list::const_iterator it = d->eventList.begin(); + for(; it != d->eventList.end(); ++it) { + if((*it)->isSignaled()){ + return true; + } + } + return false; +} + +void EventHandler::signal(Event *event) { + pthread_mutex_lock(&d->mutex); + //event->setSignaled(); + pthread_cond_signal(&d->event); + pthread_mutex_unlock(&d->mutex); +} + +bool EventHandler::waitForAny() { + pthread_mutex_lock(&d->mutex); + while(!listIsSignalled()) { + pthread_cond_wait(&d->event, &d->mutex); + } + pthread_mutex_unlock(&d->mutex); + + return true; +} diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index 9c8b4be5..35158a41 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -1,69 +1,69 @@ -#include "EventHandler.h" -#include "Event.h" -#include "Mutex.h" - -#include -#include - -using namespace TelldusCore; - -class EventHandler::PrivateData { -public: - HANDLE *eventArray; - EventRef *eventObjectArray; - TelldusCore::Mutex mutex; - int eventCount; -}; - -EventHandler::EventHandler() { - d = new PrivateData; - d->eventCount = 0; - d->eventArray = new HANDLE[0]; - d->eventObjectArray = new EventRef[0]; -} - -EventHandler::~EventHandler(void) { - delete[] d->eventObjectArray; - delete[] d->eventArray; - delete d; -} - -EventRef EventHandler::addEvent() { - EventRef event(new Event(this)); - - TelldusCore::MutexLocker locker(&d->mutex); - - HANDLE *newArray = new HANDLE[d->eventCount+1]; - EventRef *newObjectArray = new EventRef[d->eventCount+1]; - for (int i = 0; i < d->eventCount; ++i) { - newArray[i] = d->eventArray[i]; - newObjectArray[i] = d->eventObjectArray[i]; - } - delete[] d->eventArray; - delete[] d->eventObjectArray; - d->eventArray = newArray; - d->eventObjectArray = newObjectArray; - d->eventArray[d->eventCount] = event->retrieveNative(); - d->eventObjectArray[d->eventCount] = event; - ++d->eventCount; - return event; -} - -void EventHandler::signal(Event *) { -} - -bool EventHandler::waitForAny() { - - while(1){ - int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000); - if (result == WAIT_TIMEOUT) { - continue; - } - TelldusCore::MutexLocker locker(&d->mutex); - int eventIndex = result - WAIT_OBJECT_0; - if (eventIndex >= d->eventCount) { - return false; - } - return true; - } -} +#include "EventHandler.h" +#include "Event.h" +#include "Mutex.h" + +#include +#include + +using namespace TelldusCore; + +class EventHandler::PrivateData { +public: + HANDLE *eventArray; + EventRef *eventObjectArray; + TelldusCore::Mutex mutex; + int eventCount; +}; + +EventHandler::EventHandler() { + d = new PrivateData; + d->eventCount = 0; + d->eventArray = new HANDLE[0]; + d->eventObjectArray = new EventRef[0]; +} + +EventHandler::~EventHandler(void) { + delete[] d->eventObjectArray; + delete[] d->eventArray; + delete d; +} + +EventRef EventHandler::addEvent() { + EventRef event(new Event(this)); + + TelldusCore::MutexLocker locker(&d->mutex); + + HANDLE *newArray = new HANDLE[d->eventCount+1]; + EventRef *newObjectArray = new EventRef[d->eventCount+1]; + for (int i = 0; i < d->eventCount; ++i) { + newArray[i] = d->eventArray[i]; + newObjectArray[i] = d->eventObjectArray[i]; + } + delete[] d->eventArray; + delete[] d->eventObjectArray; + d->eventArray = newArray; + d->eventObjectArray = newObjectArray; + d->eventArray[d->eventCount] = event->retrieveNative(); + d->eventObjectArray[d->eventCount] = event; + ++d->eventCount; + return event; +} + +void EventHandler::signal(Event *) { +} + +bool EventHandler::waitForAny() { + + while(1){ + int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000); + if (result == WAIT_TIMEOUT) { + continue; + } + TelldusCore::MutexLocker locker(&d->mutex); + int eventIndex = result - WAIT_OBJECT_0; + if (eventIndex >= d->eventCount) { + return false; + } + return true; + } +} diff --git a/telldus-core/common/Event_unix.cpp b/telldus-core/common/Event_unix.cpp index 0cf88cc2..e6a375d7 100644 --- a/telldus-core/common/Event_unix.cpp +++ b/telldus-core/common/Event_unix.cpp @@ -1,28 +1,28 @@ -#include "Event.h" -#include "EventHandler.h" -#include "Thread.h" - -using namespace TelldusCore; - -class Event::PrivateData { -public: -}; - -Event::Event(EventHandler *handler) - :EventBase(handler){ - d = new PrivateData; -} - -Event::~Event(void) { - delete d; -} - -void Event::clearSignal() { -} - -void Event::sendSignal() { - EventHandler *handler = this->handler(); - if (handler) { - handler->signal(this); - } -} +#include "Event.h" +#include "EventHandler.h" +#include "Thread.h" + +using namespace TelldusCore; + +class Event::PrivateData { +public: +}; + +Event::Event(EventHandler *handler) + :EventBase(handler){ + d = new PrivateData; +} + +Event::~Event(void) { + delete d; +} + +void Event::clearSignal() { +} + +void Event::sendSignal() { + EventHandler *handler = this->handler(); + if (handler) { + handler->signal(this); + } +} diff --git a/telldus-core/common/Event_win.cpp b/telldus-core/common/Event_win.cpp index 7a9e9fb5..681d5e91 100644 --- a/telldus-core/common/Event_win.cpp +++ b/telldus-core/common/Event_win.cpp @@ -1,35 +1,35 @@ -#include "Event.h" -#include "Thread.h" - -using namespace TelldusCore; - -class Event::PrivateData { -public: - EVENT_T event; -}; - -Event::Event(EventHandler *handler) - :EventBase(handler) -{ - d = new PrivateData; - d->event = CreateEvent(NULL, true, false, NULL); -} - -Event::~Event(void) { - CloseHandle(d->event); - delete d; -} - -EVENT_T Event::retrieveNative() { - return d->event; -} - -void Event::clearSignal() { - ResetEvent(d->event); -} - -void Event::sendSignal() { - SetEvent(d->event); -} - - +#include "Event.h" +#include "Thread.h" + +using namespace TelldusCore; + +class Event::PrivateData { +public: + EVENT_T event; +}; + +Event::Event(EventHandler *handler) + :EventBase(handler) +{ + d = new PrivateData; + d->event = CreateEvent(NULL, true, false, NULL); +} + +Event::~Event(void) { + CloseHandle(d->event); + delete d; +} + +EVENT_T Event::retrieveNative() { + return d->event; +} + +void Event::clearSignal() { + ResetEvent(d->event); +} + +void Event::sendSignal() { + SetEvent(d->event); +} + + diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index f2820021..efc847ea 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -1,128 +1,128 @@ -#include "Message.h" -#include "Socket.h" -#include "Strings.h" -#include -#include -#include - -using namespace TelldusCore; - - -Message::Message() - : std::wstring() -{ -} - -Message::Message(const std::wstring &functionName) - :std::wstring() -{ - this->addArgument(functionName); -} - -Message::~Message(void) { -} - -void Message::addArgument(const std::wstring &value) { - //std::wstringstream st; - //st << (int)value.size(); - this->append(TelldusCore::intToWstring(value.size())); //st.str()); - this->append(L":"); - this->append(value); -} - -void Message::addArgument(int value) { - //std::wstringstream st; - //st << (int)value; - this->append(L"i"); - this->append(TelldusCore::intToWstring(value)); // st.str()); - this->append(L"s"); -} - -/* -void Message::addSpecialArgument(const std::wstring &value){ - int i = 0; - while(i<1000000){ - i++; - - char numstr[21]; // enough to hold all numbers up to 64-bits - //sprintf(numstr, "%d", value.size()); - //this->append(TelldusCore::charToWstring(numstr)); //.str()); - - itoa(value.size(), numstr, 10); - std::string test(numstr); - std::wstring temp(test.length(), L' '); - std::copy(test.begin(), test.end(), temp.begin()); - - this->append(temp); - this->append(L":"); - this->append(value); - - /* - std::wstringstream st; - st << (int)value.size(); - this->append(st.str()); - this->append(L":"); - this->append(value); - - } -} - -void Message::addSpecialArgument(int value){ - int i = 0; - while(i<1000000){ - i++; - /* - //std::wstringstream st; - //st << (int)value; - this->append(L"i"); - //this->append(st.str()); - this->append(L"s"); - - } -} -*/ -/* -void Message::addSpecialArgument(const char *value){ - this->addSpecialArgument(TelldusCore::charToWstring(value)); -} -*/ - -void Message::addArgument(const char *value) { - this->addArgument(TelldusCore::charToWstring(value)); -} - -bool Message::nextIsInt(const std::wstring &message) { - if (message.length() == 0) { - return false; - } - return (message.at(0) == 'i'); -} - -bool Message::nextIsString(const std::wstring &message) { - if (message.length() == 0) { - return false; - } - return (iswdigit(message.at(0)) != 0); -} - -std::wstring Message::takeString(std::wstring *message) { - - if (!Message::nextIsString(*message)) { - return L""; - } - size_t index = message->find(':'); - int length = wideToInteger(message->substr(0, index)); - std::wstring retval(message->substr(index+1, length)); - message->erase(0, index+length+1); - return retval; -} - -int Message::takeInt(std::wstring *message) { - if (!Message::nextIsInt(*message)) { - return 0; - } - size_t index = message->find('s'); - int value = wideToInteger(message->substr(1, index - 1)); - message->erase(0, index+1); - return value; -} +#include "Message.h" +#include "Socket.h" +#include "Strings.h" +#include +#include +#include + +using namespace TelldusCore; + + +Message::Message() + : std::wstring() +{ +} + +Message::Message(const std::wstring &functionName) + :std::wstring() +{ + this->addArgument(functionName); +} + +Message::~Message(void) { +} + +void Message::addArgument(const std::wstring &value) { + //std::wstringstream st; + //st << (int)value.size(); + this->append(TelldusCore::intToWstring(value.size())); //st.str()); + this->append(L":"); + this->append(value); +} + +void Message::addArgument(int value) { + //std::wstringstream st; + //st << (int)value; + this->append(L"i"); + this->append(TelldusCore::intToWstring(value)); // st.str()); + this->append(L"s"); +} + +/* +void Message::addSpecialArgument(const std::wstring &value){ + int i = 0; + while(i<1000000){ + i++; + + char numstr[21]; // enough to hold all numbers up to 64-bits + //sprintf(numstr, "%d", value.size()); + //this->append(TelldusCore::charToWstring(numstr)); //.str()); + + itoa(value.size(), numstr, 10); + std::string test(numstr); + std::wstring temp(test.length(), L' '); + std::copy(test.begin(), test.end(), temp.begin()); + + this->append(temp); + this->append(L":"); + this->append(value); + + /* + std::wstringstream st; + st << (int)value.size(); + this->append(st.str()); + this->append(L":"); + this->append(value); + + } +} + +void Message::addSpecialArgument(int value){ + int i = 0; + while(i<1000000){ + i++; + /* + //std::wstringstream st; + //st << (int)value; + this->append(L"i"); + //this->append(st.str()); + this->append(L"s"); + + } +} +*/ +/* +void Message::addSpecialArgument(const char *value){ + this->addSpecialArgument(TelldusCore::charToWstring(value)); +} +*/ + +void Message::addArgument(const char *value) { + this->addArgument(TelldusCore::charToWstring(value)); +} + +bool Message::nextIsInt(const std::wstring &message) { + if (message.length() == 0) { + return false; + } + return (message.at(0) == 'i'); +} + +bool Message::nextIsString(const std::wstring &message) { + if (message.length() == 0) { + return false; + } + return (iswdigit(message.at(0)) != 0); +} + +std::wstring Message::takeString(std::wstring *message) { + + if (!Message::nextIsString(*message)) { + return L""; + } + size_t index = message->find(':'); + int length = wideToInteger(message->substr(0, index)); + std::wstring retval(message->substr(index+1, length)); + message->erase(0, index+length+1); + return retval; +} + +int Message::takeInt(std::wstring *message) { + if (!Message::nextIsInt(*message)) { + return 0; + } + size_t index = message->find('s'); + int value = wideToInteger(message->substr(1, index - 1)); + message->erase(0, index+1); + return value; +} diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 4b13123b..50c06702 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -1,31 +1,31 @@ -#ifndef MESSAGE_H -#define MESSAGE_H - -#include - -namespace TelldusCore { - class Message : public std::wstring { - public: - Message(); - Message(const std::wstring &); - ~Message(void); - - void addArgument(const std::wstring &); - //void addSpecialArgument(const std::wstring &); - //void addSpecialArgument(int); - //void addSpecialArgument(const char *); - void addArgument(int); - void addArgument(const char *); - - static bool nextIsInt(const std::wstring &); - static bool nextIsString(const std::wstring &); - - static std::wstring takeString(std::wstring *); - static int takeInt(std::wstring *); - - private: - - }; -} - -#endif //MESSAGE_H +#ifndef MESSAGE_H +#define MESSAGE_H + +#include + +namespace TelldusCore { + class Message : public std::wstring { + public: + Message(); + Message(const std::wstring &); + ~Message(void); + + void addArgument(const std::wstring &); + //void addSpecialArgument(const std::wstring &); + //void addSpecialArgument(int); + //void addSpecialArgument(const char *); + void addArgument(int); + void addArgument(const char *); + + static bool nextIsInt(const std::wstring &); + static bool nextIsString(const std::wstring &); + + static std::wstring takeString(std::wstring *); + static int takeInt(std::wstring *); + + private: + + }; +} + +#endif //MESSAGE_H diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 194a2d6c..a7ef6435 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -1,33 +1,33 @@ -#ifndef SOCKET_H -#define SOCKET_H - -#include - -#ifdef _WINDOWS - #include - typedef HANDLE SOCKET_T; -#else - typedef int SOCKET_T; -#endif - -namespace TelldusCore { - class Socket - { - public: - Socket(); - Socket(SOCKET_T hPipe); - virtual ~Socket(void); - - void connect(const std::wstring &server); - bool isConnected(); - std::wstring read(); - std::wstring read(int timeout); - void stopReadWait(); - void write(const std::wstring &msg); - - private: - class PrivateData; - PrivateData *d; - }; -} -#endif //SOCKET_H +#ifndef SOCKET_H +#define SOCKET_H + +#include + +#ifdef _WINDOWS + #include + typedef HANDLE SOCKET_T; +#else + typedef int SOCKET_T; +#endif + +namespace TelldusCore { + class Socket + { + public: + Socket(); + Socket(SOCKET_T hPipe); + virtual ~Socket(void); + + void connect(const std::wstring &server); + bool isConnected(); + std::wstring read(); + std::wstring read(int timeout); + void stopReadWait(); + void write(const std::wstring &msg); + + private: + class PrivateData; + PrivateData *d; + }; +} +#endif //SOCKET_H diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 0a2a2639..23512a60 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -1,127 +1,127 @@ -#include "Socket.h" - -#include "Mutex.h" -#include "Strings.h" - -#include -#include -#include -#include - -#define BUFSIZE 512 - -using namespace TelldusCore; - -int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - return connect(sockfd, addr, addrlen); -} - -class Socket::PrivateData { -public: - SOCKET_T socket; - bool connected; - fd_set infds; - Mutex mutex; -}; - -Socket::Socket() { - d = new PrivateData; - d->socket = 0; - d->connected = false; - FD_ZERO(&d->infds); -} - -Socket::Socket(SOCKET_T socket) -{ - d = new PrivateData; - d->socket = socket; - FD_ZERO(&d->infds); - d->connected = true; -} - -Socket::~Socket(void) { - if(d->socket){ - close(d->socket); - } - delete d; -} - -void Socket::connect(const std::wstring &server) { - struct sockaddr_un remote; - socklen_t len; - - if ((d->socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - return; - } - std::string name = "/tmp/" + std::string(server.begin(), server.end()); - remote.sun_family = AF_UNIX; - strcpy(remote.sun_path, name.c_str()); - - len = SUN_LEN(&remote); - if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { - return; - } - - TelldusCore::MutexLocker locker(&d->mutex); - d->connected = true; -} - -bool Socket::isConnected(){ - TelldusCore::MutexLocker locker(&d->mutex); - return d->connected; -} - -std::wstring Socket::read() { - return this->read(0); -} - -std::wstring Socket::read(int timeout) { - struct timeval tv; - char inbuf[BUFSIZE]; - - FD_SET(d->socket, &d->infds); - std::string msg; - while(isConnected()) { - tv.tv_sec = floor(timeout / 1000.0); - tv.tv_usec = timeout % 1000; - - int response = select(d->socket+1, &d->infds, NULL, NULL, &tv); - if (response == 0 && timeout > 0) { - return L""; - } else if (response <= 0) { - FD_SET(d->socket, &d->infds); - continue; - } - - int received = BUFSIZE; - while(received >= (BUFSIZE - 1)){ - memset(inbuf, '\0', sizeof(inbuf)); - received = recv(d->socket, inbuf, BUFSIZE - 1, 0); - if(received > 0){ - msg.append(std::string(inbuf)); - } - } - if (received < 0) { - TelldusCore::MutexLocker locker(&d->mutex); - d->connected = false; - } - break; - } - - return TelldusCore::charToWstring(msg.c_str()); -} - -void Socket::stopReadWait(){ - TelldusCore::MutexLocker locker(&d->mutex); - d->connected = false; - //TODO somehow signal the socket here? -} - -void Socket::write(const std::wstring &msg) { - std::string newMsg(TelldusCore::wideToString(msg)); - int sent = send(d->socket, newMsg.c_str(), newMsg.length(), 0); - if (sent < 0) { - TelldusCore::MutexLocker locker(&d->mutex); - d->connected = false; - } -} +#include "Socket.h" + +#include "Mutex.h" +#include "Strings.h" + +#include +#include +#include +#include + +#define BUFSIZE 512 + +using namespace TelldusCore; + +int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { + return connect(sockfd, addr, addrlen); +} + +class Socket::PrivateData { +public: + SOCKET_T socket; + bool connected; + fd_set infds; + Mutex mutex; +}; + +Socket::Socket() { + d = new PrivateData; + d->socket = 0; + d->connected = false; + FD_ZERO(&d->infds); +} + +Socket::Socket(SOCKET_T socket) +{ + d = new PrivateData; + d->socket = socket; + FD_ZERO(&d->infds); + d->connected = true; +} + +Socket::~Socket(void) { + if(d->socket){ + close(d->socket); + } + delete d; +} + +void Socket::connect(const std::wstring &server) { + struct sockaddr_un remote; + socklen_t len; + + if ((d->socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + return; + } + std::string name = "/tmp/" + std::string(server.begin(), server.end()); + remote.sun_family = AF_UNIX; + strcpy(remote.sun_path, name.c_str()); + + len = SUN_LEN(&remote); + if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { + return; + } + + TelldusCore::MutexLocker locker(&d->mutex); + d->connected = true; +} + +bool Socket::isConnected(){ + TelldusCore::MutexLocker locker(&d->mutex); + return d->connected; +} + +std::wstring Socket::read() { + return this->read(0); +} + +std::wstring Socket::read(int timeout) { + struct timeval tv; + char inbuf[BUFSIZE]; + + FD_SET(d->socket, &d->infds); + std::string msg; + while(isConnected()) { + tv.tv_sec = floor(timeout / 1000.0); + tv.tv_usec = timeout % 1000; + + int response = select(d->socket+1, &d->infds, NULL, NULL, &tv); + if (response == 0 && timeout > 0) { + return L""; + } else if (response <= 0) { + FD_SET(d->socket, &d->infds); + continue; + } + + int received = BUFSIZE; + while(received >= (BUFSIZE - 1)){ + memset(inbuf, '\0', sizeof(inbuf)); + received = recv(d->socket, inbuf, BUFSIZE - 1, 0); + if(received > 0){ + msg.append(std::string(inbuf)); + } + } + if (received < 0) { + TelldusCore::MutexLocker locker(&d->mutex); + d->connected = false; + } + break; + } + + return TelldusCore::charToWstring(msg.c_str()); +} + +void Socket::stopReadWait(){ + TelldusCore::MutexLocker locker(&d->mutex); + d->connected = false; + //TODO somehow signal the socket here? +} + +void Socket::write(const std::wstring &msg) { + std::string newMsg(TelldusCore::wideToString(msg)); + int sent = send(d->socket, newMsg.c_str(), newMsg.length(), 0); + if (sent < 0) { + TelldusCore::MutexLocker locker(&d->mutex); + d->connected = false; + } +} diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index f71c84f7..87b6b37a 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -1,180 +1,180 @@ -#include "Socket.h" - -#include -#include -#include - -#define BUFSIZE 512 - -using namespace TelldusCore; - -class Socket::PrivateData { -public: - HANDLE hPipe; - HANDLE readEvent; - bool connected; - bool running; -}; - -Socket::Socket() { - d = new PrivateData; - d->hPipe = INVALID_HANDLE_VALUE; - d->connected = false; - d->running = true; -} - -Socket::Socket(SOCKET_T hPipe) -{ - d = new PrivateData; - d->hPipe = hPipe; - d->connected = true; - d->running = true; -} - - -Socket::~Socket(void){ - d->running = false; - SetEvent(d->readEvent); //signal for break - if (d->hPipe != INVALID_HANDLE_VALUE) { - CloseHandle(d->hPipe); - d->hPipe = 0; - } - delete d; -} - -void Socket::connect(const std::wstring &server){ - BOOL fSuccess = false; - - std::wstring name(L"\\\\.\\pipe\\" + server); - d->hPipe = CreateFile( - (const wchar_t *)name.c_str(), // pipe name - GENERIC_READ | // read and write access - GENERIC_WRITE, - 0, // no sharing - NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - FILE_FLAG_OVERLAPPED, // default attributes - NULL); // no template file - - if (d->hPipe == INVALID_HANDLE_VALUE) { - return; - } - - DWORD dwMode = PIPE_READMODE_MESSAGE; - fSuccess = SetNamedPipeHandleState( - d->hPipe, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time - - if (!fSuccess) { - return; - } - d->connected = true; -} - -void Socket::stopReadWait(){ - d->running = false; - SetEvent(d->readEvent); -} - -std::wstring Socket::read() { - return read(INFINITE); -} - -std::wstring Socket::read(int timeout){ - wchar_t buf[BUFSIZE]; - int result; - DWORD cbBytesRead = 0; - OVERLAPPED oOverlap; - - memset(&oOverlap, 0, sizeof(OVERLAPPED)); - - d->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - oOverlap.hEvent = d->readEvent; - BOOL fSuccess = false; - std::wstring returnString; - bool moreData = true; - - while(moreData){ - moreData = false; - memset(&buf, 0, sizeof(buf)); - - ReadFile( d->hPipe, &buf, sizeof(buf)-sizeof(wchar_t), &cbBytesRead, &oOverlap); - - result = WaitForSingleObject(oOverlap.hEvent, timeout); - - if(!d->running){ - CancelIo(d->hPipe); - WaitForSingleObject(oOverlap.hEvent, INFINITE); - d->readEvent = 0; - CloseHandle(oOverlap.hEvent); - return L""; - } - - if (result == WAIT_TIMEOUT) { - CancelIo(d->hPipe); - // Cancel, we still need to cleanup - } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, true); - - if (!fSuccess) { - DWORD err = GetLastError(); - - if(err == ERROR_MORE_DATA){ - moreData = true; - } - else{ - buf[0] = 0; - } - if (err == ERROR_BROKEN_PIPE) { - d->connected = false; - } - } - returnString.append(buf); - } - d->readEvent = 0; - CloseHandle(oOverlap.hEvent); - return returnString; -} - -void Socket::write(const std::wstring &msg){ - - OVERLAPPED oOverlap; - DWORD bytesWritten = 0; - int result; - BOOL fSuccess = false; - - memset(&oOverlap, 0, sizeof(OVERLAPPED)); - - HANDLE writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - oOverlap.hEvent = writeEvent; - - BOOL writeSuccess = WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); - result = GetLastError(); - if (writeSuccess || result == ERROR_IO_PENDING) { - result = WaitForSingleObject(writeEvent, 500); - if (result == WAIT_TIMEOUT) { - CancelIo(d->hPipe); - WaitForSingleObject(oOverlap.hEvent, INFINITE); - CloseHandle(writeEvent); - CloseHandle(d->hPipe); - d->hPipe = 0; - d->connected = false; - return; - } - fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); - } - - CloseHandle(writeEvent); - if (!fSuccess) { - CloseHandle(d->hPipe); - d->hPipe = 0; - d->connected = false; - return; - } -} - -bool Socket::isConnected(){ - return d->connected; +#include "Socket.h" + +#include +#include +#include + +#define BUFSIZE 512 + +using namespace TelldusCore; + +class Socket::PrivateData { +public: + HANDLE hPipe; + HANDLE readEvent; + bool connected; + bool running; +}; + +Socket::Socket() { + d = new PrivateData; + d->hPipe = INVALID_HANDLE_VALUE; + d->connected = false; + d->running = true; +} + +Socket::Socket(SOCKET_T hPipe) +{ + d = new PrivateData; + d->hPipe = hPipe; + d->connected = true; + d->running = true; +} + + +Socket::~Socket(void){ + d->running = false; + SetEvent(d->readEvent); //signal for break + if (d->hPipe != INVALID_HANDLE_VALUE) { + CloseHandle(d->hPipe); + d->hPipe = 0; + } + delete d; +} + +void Socket::connect(const std::wstring &server){ + BOOL fSuccess = false; + + std::wstring name(L"\\\\.\\pipe\\" + server); + d->hPipe = CreateFile( + (const wchar_t *)name.c_str(), // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, // default attributes + NULL); // no template file + + if (d->hPipe == INVALID_HANDLE_VALUE) { + return; + } + + DWORD dwMode = PIPE_READMODE_MESSAGE; + fSuccess = SetNamedPipeHandleState( + d->hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time + + if (!fSuccess) { + return; + } + d->connected = true; +} + +void Socket::stopReadWait(){ + d->running = false; + SetEvent(d->readEvent); +} + +std::wstring Socket::read() { + return read(INFINITE); +} + +std::wstring Socket::read(int timeout){ + wchar_t buf[BUFSIZE]; + int result; + DWORD cbBytesRead = 0; + OVERLAPPED oOverlap; + + memset(&oOverlap, 0, sizeof(OVERLAPPED)); + + d->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + oOverlap.hEvent = d->readEvent; + BOOL fSuccess = false; + std::wstring returnString; + bool moreData = true; + + while(moreData){ + moreData = false; + memset(&buf, 0, sizeof(buf)); + + ReadFile( d->hPipe, &buf, sizeof(buf)-sizeof(wchar_t), &cbBytesRead, &oOverlap); + + result = WaitForSingleObject(oOverlap.hEvent, timeout); + + if(!d->running){ + CancelIo(d->hPipe); + WaitForSingleObject(oOverlap.hEvent, INFINITE); + d->readEvent = 0; + CloseHandle(oOverlap.hEvent); + return L""; + } + + if (result == WAIT_TIMEOUT) { + CancelIo(d->hPipe); + // Cancel, we still need to cleanup + } + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, true); + + if (!fSuccess) { + DWORD err = GetLastError(); + + if(err == ERROR_MORE_DATA){ + moreData = true; + } + else{ + buf[0] = 0; + } + if (err == ERROR_BROKEN_PIPE) { + d->connected = false; + } + } + returnString.append(buf); + } + d->readEvent = 0; + CloseHandle(oOverlap.hEvent); + return returnString; +} + +void Socket::write(const std::wstring &msg){ + + OVERLAPPED oOverlap; + DWORD bytesWritten = 0; + int result; + BOOL fSuccess = false; + + memset(&oOverlap, 0, sizeof(OVERLAPPED)); + + HANDLE writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + oOverlap.hEvent = writeEvent; + + BOOL writeSuccess = WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); + result = GetLastError(); + if (writeSuccess || result == ERROR_IO_PENDING) { + result = WaitForSingleObject(writeEvent, 500); + if (result == WAIT_TIMEOUT) { + CancelIo(d->hPipe); + WaitForSingleObject(oOverlap.hEvent, INFINITE); + CloseHandle(writeEvent); + CloseHandle(d->hPipe); + d->hPipe = 0; + d->connected = false; + return; + } + fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); + } + + CloseHandle(writeEvent); + if (!fSuccess) { + CloseHandle(d->hPipe); + d->hPipe = 0; + d->connected = false; + return; + } +} + +bool Socket::isConnected(){ + return d->connected; } \ No newline at end of file diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index b4d02376..5bee53a9 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -1,257 +1,257 @@ -#include "Strings.h" - -#include -#include -#include -#include -#include - -#ifdef _WINDOWS -#include -#else -#include -#endif - -#ifdef _MACOSX -#define WCHAR_T_ENCODING "UCS-4-INTERNAL" -#else -#define WCHAR_T_ENCODING "WCHAR_T" -#endif - -std::wstring TelldusCore::charToWstring(const char *value) { -#ifdef _WINDOWS - //Determine size - int size = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0); - if (size == 0) { - return L""; - } - wchar_t *buffer; - buffer = new wchar_t[size]; - memset(buffer, 0, sizeof(wchar_t)*(size)); - - int bytes = MultiByteToWideChar(CP_UTF8, 0, value, -1, buffer, size); - std::wstring retval(buffer); - delete[] buffer; - return retval; - -#else - size_t utf8Length = strlen(value); - size_t outbytesLeft = utf8Length*sizeof(wchar_t); - - //Copy the instring - char *inString = new char[strlen(value)+1]; - strcpy(inString, value); - - //Create buffer for output - char *outString = (char*)new wchar_t[utf8Length+1]; - memset(outString, 0, sizeof(wchar_t)*(utf8Length+1)); - -#ifdef _FREEBSD - const char *inPointer = inString; -#else - char *inPointer = inString; -#endif - char *outPointer = outString; - - iconv_t convDesc = iconv_open(WCHAR_T_ENCODING, "UTF-8"); - iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft); - iconv_close(convDesc); - - std::wstring retval( (wchar_t *)outString ); - - //Cleanup - delete[] inString; - delete[] outString; - - return retval; -#endif -} - -int TelldusCore::charToInteger(const char *input){ - std::stringstream inputstream; - inputstream << input; - int retval; - inputstream >> retval; - return retval; -} - -std::wstring TelldusCore::charUnsignedToWstring(const unsigned char value) { - std::wstringstream st; - st << value; - return st.str(); -} - -/** -* This method doesn't support all locales -*/ -bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { - transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); - transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); - - return stringA == stringB; -} - -std::wstring TelldusCore::intToWstring(int value) { -#ifdef _WINDOWS - //no stream used -//TODO! Make effective and safe... - wchar_t numstr[21]; // enough to hold all numbers up to 64-bits - _itow_s(value, numstr, sizeof(numstr), 10); - std::wstring newstring(numstr); - return newstring; - //return TelldusCore::charToWstring(stdstring.c_str()); - //std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); - //std::wstring temp(stdstring.length(), L' '); - //std::copy(stdstring.begin(), stdstring.end(), temp.begin()); - //return temp; -#else - std::wstringstream st; - st << value; - return st.str(); -#endif -} - -std::string TelldusCore::intToString(int value) { -//Not sure if this is neecssary (for ordinary stringstream that is) -#ifdef _WINDOWS - char numstr[21]; // enough to hold all numbers up to 64-bits - _itoa_s(value, numstr, sizeof(numstr), 10); - std::string stdstring(numstr); - return stdstring; -#else - std::stringstream st; - st << value; - return st.str(); -#endif -} - -/* -std::wstring TelldusCore::intToWStringSafe(int value){ - #ifdef _WINDOWS - //no stream used - //TODO! Make effective and safe... - char numstr[21]; // enough to hold all numbers up to 64-bits - itoa(value, numstr, 10); - std::string stdstring(numstr); - return TelldusCore::charToWstring(stdstring.c_str()); - //std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); - //std::wstring temp(stdstring.length(), L' '); - //std::copy(stdstring.begin(), stdstring.end(), temp.begin()); - //return temp; - #else - return TelldusCore::intToWString(value); - #endif -} -*/ - -uint64_t TelldusCore::hexTo64l(const std::string data){ -#ifdef _WINDOWS - return _strtoui64(data.c_str(), NULL, 16); -#elif defined(_MACOSX) - return strtoq(data.c_str(), NULL, 16); -#else - return strtoull(data.c_str(), NULL, 16); -#endif -} - -int TelldusCore::wideToInteger(const std::wstring &input){ - std::wstringstream inputstream; - inputstream << input; - int retval; - inputstream >> retval; - return retval; -} - -std::string TelldusCore::wideToString(const std::wstring &input) { -#ifdef _WINDOWS - //Determine size - int size = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, NULL, 0, NULL, NULL); - if (size == 0) { - return ""; - } - char *buffer; - buffer = new char[size]; - memset(buffer, 0, sizeof(char)*size); - - int bytes = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, buffer, size, NULL, NULL); - std::string retval(buffer); - delete[] buffer; - return retval; - -#else - size_t wideSize = sizeof(wchar_t)*input.length(); - size_t outbytesLeft = wideSize+sizeof(char); //We cannot know how many wide character there is yet - - //Copy the instring - char *inString = (char*)new wchar_t[input.length()+1]; - memcpy(inString, input.c_str(), wideSize+sizeof(wchar_t)); - - //Create buffer for output - char *outString = new char[outbytesLeft]; - memset(outString, 0, sizeof(char)*(outbytesLeft)); - -#ifdef _FREEBSD - const char *inPointer = inString; -#else - char *inPointer = inString; -#endif - char *outPointer = outString; - - iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING); - iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft); - iconv_close(convDesc); - - std::string retval(outString); - - //Cleanup - delete[] inString; - delete[] outString; - - return retval; -#endif -} - -std::string TelldusCore::formatf(const char *format, ...) { - va_list ap; - va_start(ap, format); - std::string retval = sformatf(format, ap); - va_end(ap); - return retval; -} - -std::string TelldusCore::sformatf(const char *format, va_list ap) { - //This code is based on code from the Linux man-pages project (man vsprintf) - int n; - int size = 100; /* Guess we need no more than 100 bytes. */ - char *p, *np; - - if ((p = (char*)malloc(size)) == NULL) { - return ""; - } - - while (1) { - /* Try to print in the allocated space. */ - n = vsnprintf(p, size, format, ap); - - /* If that worked, return the string. */ - if (n > -1 && n < size) { - std::string retval(p); - free(p); - return retval; - } - - /* Else try again with more space. */ - - if (n > -1) { /* glibc 2.1 */ - size = n+1; /* precisely what is needed */ - } else { /* glibc 2.0 */ - size *= 2; /* twice the old size */ - } - if ((np = (char *)realloc (p, size)) == NULL) { - free(p); - return ""; - } else { - p = np; - } - } -} +#include "Strings.h" + +#include +#include +#include +#include +#include + +#ifdef _WINDOWS +#include +#else +#include +#endif + +#ifdef _MACOSX +#define WCHAR_T_ENCODING "UCS-4-INTERNAL" +#else +#define WCHAR_T_ENCODING "WCHAR_T" +#endif + +std::wstring TelldusCore::charToWstring(const char *value) { +#ifdef _WINDOWS + //Determine size + int size = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0); + if (size == 0) { + return L""; + } + wchar_t *buffer; + buffer = new wchar_t[size]; + memset(buffer, 0, sizeof(wchar_t)*(size)); + + int bytes = MultiByteToWideChar(CP_UTF8, 0, value, -1, buffer, size); + std::wstring retval(buffer); + delete[] buffer; + return retval; + +#else + size_t utf8Length = strlen(value); + size_t outbytesLeft = utf8Length*sizeof(wchar_t); + + //Copy the instring + char *inString = new char[strlen(value)+1]; + strcpy(inString, value); + + //Create buffer for output + char *outString = (char*)new wchar_t[utf8Length+1]; + memset(outString, 0, sizeof(wchar_t)*(utf8Length+1)); + +#ifdef _FREEBSD + const char *inPointer = inString; +#else + char *inPointer = inString; +#endif + char *outPointer = outString; + + iconv_t convDesc = iconv_open(WCHAR_T_ENCODING, "UTF-8"); + iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft); + iconv_close(convDesc); + + std::wstring retval( (wchar_t *)outString ); + + //Cleanup + delete[] inString; + delete[] outString; + + return retval; +#endif +} + +int TelldusCore::charToInteger(const char *input){ + std::stringstream inputstream; + inputstream << input; + int retval; + inputstream >> retval; + return retval; +} + +std::wstring TelldusCore::charUnsignedToWstring(const unsigned char value) { + std::wstringstream st; + st << value; + return st.str(); +} + +/** +* This method doesn't support all locales +*/ +bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { + transform(stringA.begin(), stringA.end(), stringA.begin(), toupper); + transform(stringB.begin(), stringB.end(), stringB.begin(), toupper); + + return stringA == stringB; +} + +std::wstring TelldusCore::intToWstring(int value) { +#ifdef _WINDOWS + //no stream used +//TODO! Make effective and safe... + wchar_t numstr[21]; // enough to hold all numbers up to 64-bits + _itow_s(value, numstr, sizeof(numstr), 10); + std::wstring newstring(numstr); + return newstring; + //return TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp(stdstring.length(), L' '); + //std::copy(stdstring.begin(), stdstring.end(), temp.begin()); + //return temp; +#else + std::wstringstream st; + st << value; + return st.str(); +#endif +} + +std::string TelldusCore::intToString(int value) { +//Not sure if this is neecssary (for ordinary stringstream that is) +#ifdef _WINDOWS + char numstr[21]; // enough to hold all numbers up to 64-bits + _itoa_s(value, numstr, sizeof(numstr), 10); + std::string stdstring(numstr); + return stdstring; +#else + std::stringstream st; + st << value; + return st.str(); +#endif +} + +/* +std::wstring TelldusCore::intToWStringSafe(int value){ + #ifdef _WINDOWS + //no stream used + //TODO! Make effective and safe... + char numstr[21]; // enough to hold all numbers up to 64-bits + itoa(value, numstr, 10); + std::string stdstring(numstr); + return TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); + //std::wstring temp(stdstring.length(), L' '); + //std::copy(stdstring.begin(), stdstring.end(), temp.begin()); + //return temp; + #else + return TelldusCore::intToWString(value); + #endif +} +*/ + +uint64_t TelldusCore::hexTo64l(const std::string data){ +#ifdef _WINDOWS + return _strtoui64(data.c_str(), NULL, 16); +#elif defined(_MACOSX) + return strtoq(data.c_str(), NULL, 16); +#else + return strtoull(data.c_str(), NULL, 16); +#endif +} + +int TelldusCore::wideToInteger(const std::wstring &input){ + std::wstringstream inputstream; + inputstream << input; + int retval; + inputstream >> retval; + return retval; +} + +std::string TelldusCore::wideToString(const std::wstring &input) { +#ifdef _WINDOWS + //Determine size + int size = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, NULL, 0, NULL, NULL); + if (size == 0) { + return ""; + } + char *buffer; + buffer = new char[size]; + memset(buffer, 0, sizeof(char)*size); + + int bytes = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, buffer, size, NULL, NULL); + std::string retval(buffer); + delete[] buffer; + return retval; + +#else + size_t wideSize = sizeof(wchar_t)*input.length(); + size_t outbytesLeft = wideSize+sizeof(char); //We cannot know how many wide character there is yet + + //Copy the instring + char *inString = (char*)new wchar_t[input.length()+1]; + memcpy(inString, input.c_str(), wideSize+sizeof(wchar_t)); + + //Create buffer for output + char *outString = new char[outbytesLeft]; + memset(outString, 0, sizeof(char)*(outbytesLeft)); + +#ifdef _FREEBSD + const char *inPointer = inString; +#else + char *inPointer = inString; +#endif + char *outPointer = outString; + + iconv_t convDesc = iconv_open("UTF-8", WCHAR_T_ENCODING); + iconv(convDesc, &inPointer, &wideSize, &outPointer, &outbytesLeft); + iconv_close(convDesc); + + std::string retval(outString); + + //Cleanup + delete[] inString; + delete[] outString; + + return retval; +#endif +} + +std::string TelldusCore::formatf(const char *format, ...) { + va_list ap; + va_start(ap, format); + std::string retval = sformatf(format, ap); + va_end(ap); + return retval; +} + +std::string TelldusCore::sformatf(const char *format, va_list ap) { + //This code is based on code from the Linux man-pages project (man vsprintf) + int n; + int size = 100; /* Guess we need no more than 100 bytes. */ + char *p, *np; + + if ((p = (char*)malloc(size)) == NULL) { + return ""; + } + + while (1) { + /* Try to print in the allocated space. */ + n = vsnprintf(p, size, format, ap); + + /* If that worked, return the string. */ + if (n > -1 && n < size) { + std::string retval(p); + free(p); + return retval; + } + + /* Else try again with more space. */ + + if (n > -1) { /* glibc 2.1 */ + size = n+1; /* precisely what is needed */ + } else { /* glibc 2.0 */ + size *= 2; /* twice the old size */ + } + if ((np = (char *)realloc (p, size)) == NULL) { + free(p); + return ""; + } else { + p = np; + } + } +} diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index 7c5f85ad..28e671c2 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -1,33 +1,33 @@ -#ifndef STRING_H -#define STRING_H - -#include -#include -#ifdef _MSC_VER -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#else -#include -#endif - -namespace TelldusCore { - std::wstring charToWstring(const char *value); - int charToInteger(const char *value); - std::wstring charUnsignedToWstring(const unsigned char value); - - bool comparei(std::wstring stringA, std::wstring stringB); - std::wstring intToWstring(int value); - //std::wstring intToWStringSafe(int value); - std::string intToString(int value); - uint64_t hexTo64l(const std::string data); - std::string wideToString(const std::wstring &input); - - int wideToInteger(const std::wstring &input); - - std::string formatf(const char *format, ...); - std::string sformatf(const char *format, va_list ap); -} - -#endif //STRING_H +#ifndef STRING_H +#define STRING_H + +#include +#include +#ifdef _MSC_VER +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif + +namespace TelldusCore { + std::wstring charToWstring(const char *value); + int charToInteger(const char *value); + std::wstring charUnsignedToWstring(const unsigned char value); + + bool comparei(std::wstring stringA, std::wstring stringB); + std::wstring intToWstring(int value); + //std::wstring intToWStringSafe(int value); + std::string intToString(int value); + uint64_t hexTo64l(const std::string data); + std::string wideToString(const std::wstring &input); + + int wideToInteger(const std::wstring &input); + + std::string formatf(const char *format, ...); + std::string sformatf(const char *format, va_list ap); +} + +#endif //STRING_H diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index b7d0fa3c..0545af4a 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -1,252 +1,252 @@ -IF(COMMAND cmake_policy) - CMAKE_POLICY(SET CMP0003 NEW) -ENDIF(COMMAND cmake_policy) - -FIND_PACKAGE( SignTool REQUIRED ) - -SET (telldusd_DESCRIPTION - "background service for Telldus TellStick, must be running to control TellStick" -) - -ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) - -######## Non configurable options ######## -SET( telldus-service_SRCS - ClientCommunicationHandler.cpp - Controller.cpp - ControllerManager.cpp - ControllerMessage.cpp - Device.cpp - DeviceManager.cpp - Log.cpp - Sensor.cpp - Settings.cpp - TelldusMain.cpp - TellStick.cpp - Timer.cpp - EventUpdateManager.cpp -) -SET( telldus-service_protocol_SRCS - Protocol.h - Protocol.cpp - ProtocolBrateck.h - ProtocolBrateck.cpp - ProtocolComen.h - ProtocolComen.cpp - ProtocolEverflourish.h - ProtocolEverflourish.cpp - ProtocolFineoffset.h - ProtocolFineoffset.cpp - ProtocolFuhaote.h - ProtocolFuhaote.cpp - ProtocolGroup.h - ProtocolGroup.cpp - ProtocolHasta.h - ProtocolHasta.cpp - ProtocolIkea.h - ProtocolIkea.cpp - ProtocolMandolyn.h - ProtocolMandolyn.cpp - ProtocolNexa.h - ProtocolNexa.cpp - ProtocolOregon.h - ProtocolOregon.cpp - ProtocolRisingSun.h - ProtocolRisingSun.cpp - ProtocolSartano.h - ProtocolSartano.cpp - ProtocolScene.h - ProtocolScene.cpp - ProtocolSilvanChip.h - ProtocolSilvanChip.cpp - ProtocolUpm.h - ProtocolUpm.cpp - ProtocolWaveman.h - ProtocolWaveman.cpp - ProtocolX10.h - ProtocolX10.cpp - ProtocolYidong.h - ProtocolYidong.cpp -) -SET( telldus-service_HDRS - ClientCommunicationHandler.h - ConnectionListener.h - Controller.h - ControllerListener.h - ControllerManager.h - ControllerMessage.h - Device.h - DeviceManager.h - EventUpdateManager.h - Log.h - Sensor.h - Settings.h - TelldusMain.h - TellStick.h - Timer.h -) -FIND_PACKAGE(Threads REQUIRED) -LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR}/../common -) - -######## Configurable options for the platform ######## - -######## Platforms-specific, non configurable ######## - -IF (APPLE) #### Mac OS X #### - SET(DEFAULT_FTDI_ENGINE "ftd2xx") - SET( telldus-service_TARGET TelldusService ) - ADD_DEFINITIONS( -D_MACOSX ) - FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) - FIND_LIBRARY(IOKIT_LIBRARY IOKit) - - SET( telldus-service_LIBRARIES - ${telldus-service_LIBRARIES} - ${COREFOUNDATION_LIBRARY} - ${IOKIT_LIBRARY} - TelldusCommon - ) - LIST(APPEND telldus-service_SRCS - main_mac.cpp - ConnectionListener_unix.cpp - ControllerListener_mac.cpp - SettingsCoreFoundationPreferences.cpp - ) - -ELSEIF (WIN32) #### Windows #### - SET(DEFAULT_FTDI_ENGINE "ftd2xx") - SET( telldus-service_TARGET TelldusService ) - ADD_DEFINITIONS( -DUNICODE ) - ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No - SET(CMAKE_EXE_LINKER_FLAGS - "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" - ) - LIST(APPEND telldus-service_LIBRARIES - TelldusCommon - ) - LIST(APPEND telldus-service_SRCS - ConnectionListener_win.cpp - main_win.cpp - SettingsWinRegistry.cpp - TelldusWinService_win.cpp - Messages.mc - ${CMAKE_CURRENT_BINARY_DIR}/Messages.rc - ${CMAKE_CURRENT_BINARY_DIR}/Messages.h - ) - LIST(APPEND telldus-service_HDRS - TelldusWinService_win.h - ) - ADD_CUSTOM_COMMAND( - OUTPUT Messages.rc Messages.h - COMMAND mc.exe -u -r \"${CMAKE_CURRENT_BINARY_DIR}\" -h \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc\" - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc - DEPENDS Messages.rc - COMMENT "Compiling Messages Resource" - ) - INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ) - -ELSE (APPLE) #### Linux #### - SET(DEFAULT_FTDI_ENGINE "libftdi") - FIND_LIBRARY(CONFUSE_LIBRARY confuse) - ADD_DEFINITIONS( -D_CONFUSE ) - ADD_DEFINITIONS( -D_LINUX ) - - SET( telldus-service_TARGET telldusd ) - LIST(APPEND telldus-service_SRCS - ConnectionListener_unix.cpp - main_unix.cpp - SettingsConfuse.cpp - ) - LIST(APPEND telldus-service_LIBRARIES - ${CONFUSE_LIBRARY} - TelldusCommon - ) -ENDIF (APPLE) - -SET(FTDI_ENGINE ${DEFAULT_FTDI_ENGINE} CACHE STRING "Which FTDI engine to use. This could be either 'libftdi' or 'ftd2xx'") -IF (FTDI_ENGINE STREQUAL "ftd2xx") - FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) - ADD_DEFINITIONS( -DLIBFTD2XX ) - LIST(APPEND telldus-service_SRCS TellStick_ftd2xx.cpp ) - LIST(APPEND telldus-service_LIBRARIES ${FTD2XX_LIBRARY}) -ELSE (FTDI_ENGINE STREQUAL "ftd2xx") - FIND_LIBRARY(FTDI_LIBRARY ftdi) - INCLUDE(FindPkgConfig) - PKG_SEARCH_MODULE(FTDI libftdi) - INCLUDE_DIRECTORIES( ${FTDI_INCLUDEDIR} ) - ADD_DEFINITIONS( -DLIBFTDI ) - LIST(APPEND telldus-service_SRCS TellStick_libftdi.cpp ) - LIST(APPEND telldus-service_LIBRARIES ${FTDI_LIBRARY}) -ENDIF (FTDI_ENGINE STREQUAL "ftd2xx") - -######## Configuring ######## - -SOURCE_GROUP("Protocol Files" FILES ${telldus-service_protocol_SRCS}) - -ADD_EXECUTABLE(${telldus-service_TARGET} - ${telldus-service_SRCS} - ${telldus-service_protocol_SRCS} - ${telldus-service_HDRS} -) -ADD_DEPENDENCIES(${telldus-service_TARGET} TelldusCommon) -SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - -TARGET_LINK_LIBRARIES( ${telldus-service_TARGET} ${telldus-service_LIBRARIES} ) - -SIGN(${telldus-service_TARGET}) - -SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist -) -IF (APPLE) - SET(TELLDUS_SERVICE_TARGET_PATH "/Library/Telldus" CACHE STRING "Path to install TelldusService") - SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} - ) - INSTALL(TARGETS ${telldus-service_TARGET} - RUNTIME DESTINATION ${TELLDUS_SERVICE_TARGET_PATH} - ) - INSTALL(CODE " - INCLUDE(GetPrerequisites) - GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) - GET_PREREQUISITES(\"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" prereqs 1 0 \"\$\" \"\$\") - FOREACH(pr \${prereqs}) - GET_FILENAME_COMPONENT(lib \${pr} NAME) - FILE(INSTALL \${pr} DESTINATION ${TELLDUS_SERVICE_TARGET_PATH}) - EXECUTE_PROCESS(COMMAND install_name_tool - -change \"\${pr}\" \"${TELLDUS_SERVICE_TARGET_PATH}/\${lib}\" \"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" - ) - ENDFOREACH () - ") - INSTALL(FILES com.telldus.service.plist DESTINATION /Library/LaunchDaemons) -ENDIF (APPLE) - -IF (UNIX) - IF (GENERATE_MAN) - ADD_CUSTOM_COMMAND( - TARGET ${telldus-service_TARGET} - POST_BUILD - COMMAND help2man -n ${telldusd_DESCRIPTION} ./telldusd > telldusd.1 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating man file telldusd.1" - ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/telldusd.1 DESTINATION share/man/man1) - ENDIF (GENERATE_MAN) -ENDIF (UNIX) - -IF (UNIX AND NOT APPLE) - INSTALL(TARGETS ${telldus-service_TARGET} RUNTIME DESTINATION sbin) - SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) - SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) - - INSTALL(FILES tellstick.conf - DESTINATION ${SYSCONF_INSTALL_DIR} - ) - INSTALL(FILES telldus-core.conf - DESTINATION ${STATE_INSTALL_DIR} - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE - ) -ENDIF (UNIX AND NOT APPLE) +IF(COMMAND cmake_policy) + CMAKE_POLICY(SET CMP0003 NEW) +ENDIF(COMMAND cmake_policy) + +FIND_PACKAGE( SignTool REQUIRED ) + +SET (telldusd_DESCRIPTION + "background service for Telldus TellStick, must be running to control TellStick" +) + +ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) + +######## Non configurable options ######## +SET( telldus-service_SRCS + ClientCommunicationHandler.cpp + Controller.cpp + ControllerManager.cpp + ControllerMessage.cpp + Device.cpp + DeviceManager.cpp + Log.cpp + Sensor.cpp + Settings.cpp + TelldusMain.cpp + TellStick.cpp + Timer.cpp + EventUpdateManager.cpp +) +SET( telldus-service_protocol_SRCS + Protocol.h + Protocol.cpp + ProtocolBrateck.h + ProtocolBrateck.cpp + ProtocolComen.h + ProtocolComen.cpp + ProtocolEverflourish.h + ProtocolEverflourish.cpp + ProtocolFineoffset.h + ProtocolFineoffset.cpp + ProtocolFuhaote.h + ProtocolFuhaote.cpp + ProtocolGroup.h + ProtocolGroup.cpp + ProtocolHasta.h + ProtocolHasta.cpp + ProtocolIkea.h + ProtocolIkea.cpp + ProtocolMandolyn.h + ProtocolMandolyn.cpp + ProtocolNexa.h + ProtocolNexa.cpp + ProtocolOregon.h + ProtocolOregon.cpp + ProtocolRisingSun.h + ProtocolRisingSun.cpp + ProtocolSartano.h + ProtocolSartano.cpp + ProtocolScene.h + ProtocolScene.cpp + ProtocolSilvanChip.h + ProtocolSilvanChip.cpp + ProtocolUpm.h + ProtocolUpm.cpp + ProtocolWaveman.h + ProtocolWaveman.cpp + ProtocolX10.h + ProtocolX10.cpp + ProtocolYidong.h + ProtocolYidong.cpp +) +SET( telldus-service_HDRS + ClientCommunicationHandler.h + ConnectionListener.h + Controller.h + ControllerListener.h + ControllerManager.h + ControllerMessage.h + Device.h + DeviceManager.h + EventUpdateManager.h + Log.h + Sensor.h + Settings.h + TelldusMain.h + TellStick.h + Timer.h +) +FIND_PACKAGE(Threads REQUIRED) +LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_SOURCE_DIR}/../common +) + +######## Configurable options for the platform ######## + +######## Platforms-specific, non configurable ######## + +IF (APPLE) #### Mac OS X #### + SET(DEFAULT_FTDI_ENGINE "ftd2xx") + SET( telldus-service_TARGET TelldusService ) + ADD_DEFINITIONS( -D_MACOSX ) + FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation) + FIND_LIBRARY(IOKIT_LIBRARY IOKit) + + SET( telldus-service_LIBRARIES + ${telldus-service_LIBRARIES} + ${COREFOUNDATION_LIBRARY} + ${IOKIT_LIBRARY} + TelldusCommon + ) + LIST(APPEND telldus-service_SRCS + main_mac.cpp + ConnectionListener_unix.cpp + ControllerListener_mac.cpp + SettingsCoreFoundationPreferences.cpp + ) + +ELSEIF (WIN32) #### Windows #### + SET(DEFAULT_FTDI_ENGINE "ftd2xx") + SET( telldus-service_TARGET TelldusService ) + ADD_DEFINITIONS( -DUNICODE ) + ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No + SET(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE" + ) + LIST(APPEND telldus-service_LIBRARIES + TelldusCommon + ) + LIST(APPEND telldus-service_SRCS + ConnectionListener_win.cpp + main_win.cpp + SettingsWinRegistry.cpp + TelldusWinService_win.cpp + Messages.mc + ${CMAKE_CURRENT_BINARY_DIR}/Messages.rc + ${CMAKE_CURRENT_BINARY_DIR}/Messages.h + ) + LIST(APPEND telldus-service_HDRS + TelldusWinService_win.h + ) + ADD_CUSTOM_COMMAND( + OUTPUT Messages.rc Messages.h + COMMAND mc.exe -u -r \"${CMAKE_CURRENT_BINARY_DIR}\" -h \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc\" + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc + DEPENDS Messages.rc + COMMENT "Compiling Messages Resource" + ) + INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ) + +ELSE (APPLE) #### Linux #### + SET(DEFAULT_FTDI_ENGINE "libftdi") + FIND_LIBRARY(CONFUSE_LIBRARY confuse) + ADD_DEFINITIONS( -D_CONFUSE ) + ADD_DEFINITIONS( -D_LINUX ) + + SET( telldus-service_TARGET telldusd ) + LIST(APPEND telldus-service_SRCS + ConnectionListener_unix.cpp + main_unix.cpp + SettingsConfuse.cpp + ) + LIST(APPEND telldus-service_LIBRARIES + ${CONFUSE_LIBRARY} + TelldusCommon + ) +ENDIF (APPLE) + +SET(FTDI_ENGINE ${DEFAULT_FTDI_ENGINE} CACHE STRING "Which FTDI engine to use. This could be either 'libftdi' or 'ftd2xx'") +IF (FTDI_ENGINE STREQUAL "ftd2xx") + FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) + ADD_DEFINITIONS( -DLIBFTD2XX ) + LIST(APPEND telldus-service_SRCS TellStick_ftd2xx.cpp ) + LIST(APPEND telldus-service_LIBRARIES ${FTD2XX_LIBRARY}) +ELSE (FTDI_ENGINE STREQUAL "ftd2xx") + FIND_LIBRARY(FTDI_LIBRARY ftdi) + INCLUDE(FindPkgConfig) + PKG_SEARCH_MODULE(FTDI libftdi) + INCLUDE_DIRECTORIES( ${FTDI_INCLUDEDIR} ) + ADD_DEFINITIONS( -DLIBFTDI ) + LIST(APPEND telldus-service_SRCS TellStick_libftdi.cpp ) + LIST(APPEND telldus-service_LIBRARIES ${FTDI_LIBRARY}) +ENDIF (FTDI_ENGINE STREQUAL "ftd2xx") + +######## Configuring ######## + +SOURCE_GROUP("Protocol Files" FILES ${telldus-service_protocol_SRCS}) + +ADD_EXECUTABLE(${telldus-service_TARGET} + ${telldus-service_SRCS} + ${telldus-service_protocol_SRCS} + ${telldus-service_HDRS} +) +ADD_DEPENDENCIES(${telldus-service_TARGET} TelldusCommon) +SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + +TARGET_LINK_LIBRARIES( ${telldus-service_TARGET} ${telldus-service_LIBRARIES} ) + +SIGN(${telldus-service_TARGET}) + +SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist +) +IF (APPLE) + SET(TELLDUS_SERVICE_TARGET_PATH "/Library/Telldus" CACHE STRING "Path to install TelldusService") + SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} + ) + INSTALL(TARGETS ${telldus-service_TARGET} + RUNTIME DESTINATION ${TELLDUS_SERVICE_TARGET_PATH} + ) + INSTALL(CODE " + INCLUDE(GetPrerequisites) + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + GET_PREREQUISITES(\"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" prereqs 1 0 \"\$\" \"\$\") + FOREACH(pr \${prereqs}) + GET_FILENAME_COMPONENT(lib \${pr} NAME) + FILE(INSTALL \${pr} DESTINATION ${TELLDUS_SERVICE_TARGET_PATH}) + EXECUTE_PROCESS(COMMAND install_name_tool + -change \"\${pr}\" \"${TELLDUS_SERVICE_TARGET_PATH}/\${lib}\" \"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" + ) + ENDFOREACH () + ") + INSTALL(FILES com.telldus.service.plist DESTINATION /Library/LaunchDaemons) +ENDIF (APPLE) + +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET ${telldus-service_TARGET} + POST_BUILD + COMMAND help2man -n ${telldusd_DESCRIPTION} ./telldusd > telldusd.1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file telldusd.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/telldusd.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + +IF (UNIX AND NOT APPLE) + INSTALL(TARGETS ${telldus-service_TARGET} RUNTIME DESTINATION sbin) + SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) + SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) + + INSTALL(FILES tellstick.conf + DESTINATION ${SYSCONF_INSTALL_DIR} + ) + INSTALL(FILES telldus-core.conf + DESTINATION ${STATE_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE + ) +ENDIF (UNIX AND NOT APPLE) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 21159209..c6de79d0 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -1,265 +1,265 @@ -#include "ClientCommunicationHandler.h" -#include "Message.h" -#include "Strings.h" - -#include - -class ClientCommunicationHandler::PrivateData { -public: - TelldusCore::Socket *clientSocket; - TelldusCore::EventRef event, deviceUpdateEvent; - bool done; - DeviceManager *deviceManager; - ControllerManager *controllerManager; -}; - -ClientCommunicationHandler::ClientCommunicationHandler(){ - -} - -ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent, ControllerManager *controllerManager) - :Thread() -{ - d = new PrivateData; - d->clientSocket = clientSocket; - d->event = event; - d->done = false; - d->deviceManager = deviceManager; - d->deviceUpdateEvent = deviceUpdateEvent; - d->controllerManager = controllerManager; -} - -ClientCommunicationHandler::~ClientCommunicationHandler(void) -{ - wait(); - delete(d->clientSocket); - delete d; -} - -void ClientCommunicationHandler::run(){ - //run thread - - std::wstring clientMessage = d->clientSocket->read(2000); - - int intReturn; - std::wstring strReturn; - strReturn = L""; - parseMessage(clientMessage, &intReturn, &strReturn); - - TelldusCore::Message msg; - - if(strReturn == L""){ - msg.addArgument(intReturn); - } - else{ - msg.addArgument(strReturn); - } - msg.append(L"\n"); - d->clientSocket->write(msg); - - //We are done, signal for removal - d->done = true; - d->event->signal(); -} - -bool ClientCommunicationHandler::isDone(){ - return d->done; -} - - -void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn){ - - (*intReturn) = 0; - (*wstringReturn) = L""; - std::wstring msg(clientMessage); //Copy - std::wstring function(TelldusCore::Message::takeString(&msg)); - - if (function == L"tdTurnOn") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); - - } else if (function == L"tdTurnOff") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0); - - } else if (function == L"tdBell") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0); - - } else if (function == L"tdDim") { - int deviceId = TelldusCore::Message::takeInt(&msg); - int level = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, level); - - } else if (function == L"tdExecute") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_EXECUTE, 0); - - } else if (function == L"tdUp") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_UP, 0); - - } else if (function == L"tdDown") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DOWN, 0); - - } else if (function == L"tdStop") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_STOP, 0); - - } else if (function == L"tdLearn") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); - - } else if (function == L"tdLastSentCommand") { - int deviceId = TelldusCore::Message::takeInt(&msg); - int methodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceLastSentCommand(deviceId, methodsSupported); - - } else if (function == L"tdLastSentValue") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceStateValue(deviceId); - - } else if(function == L"tdGetNumberOfDevices"){ - - (*intReturn) = d->deviceManager->getNumberOfDevices(); - - } else if (function == L"tdGetDeviceId") { - int deviceIndex = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceId(deviceIndex); - - } else if (function == L"tdGetDeviceType") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceType(deviceId); - - } else if (function == L"tdGetName") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceName(deviceId); - - } else if (function == L"tdSetName") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - (*intReturn) = d->deviceManager->setDeviceName(deviceId, name); - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME); - - } else if (function == L"tdGetProtocol") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceProtocol(deviceId); - - } else if (function == L"tdSetProtocol") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring protocol = TelldusCore::Message::takeString(&msg); - int oldMethods = d->deviceManager->getDeviceMethods(deviceId); - (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); - if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); - } - - } else if (function == L"tdGetModel") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getDeviceModel(deviceId); - - } else if (function == L"tdSetModel") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring model = TelldusCore::Message::takeString(&msg); - int oldMethods = d->deviceManager->getDeviceMethods(deviceId); - (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); - if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); - } - - } else if (function == L"tdGetDeviceParameter") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - std::wstring defaultValue = TelldusCore::Message::takeString(&msg); - (*wstringReturn) = d->deviceManager->getDeviceParameter(deviceId, name, defaultValue); - - } else if (function == L"tdSetDeviceParameter") { - int deviceId = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - std::wstring value = TelldusCore::Message::takeString(&msg); - int oldMethods = d->deviceManager->getDeviceMethods(deviceId); - (*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value); - if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); - } - - } else if (function == L"tdAddDevice") { - (*intReturn) = d->deviceManager->addDevice(); - if((*intReturn) >= 0){ - sendDeviceSignal((*intReturn), TELLSTICK_DEVICE_ADDED, 0); - } - - } else if (function == L"tdRemoveDevice") { - int deviceId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->removeDevice(deviceId); - if((*intReturn) == TELLSTICK_SUCCESS){ - sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0); - } - - } else if (function == L"tdMethods") { - int deviceId = TelldusCore::Message::takeInt(&msg); - int intMethodsSupported = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); - - } else if (function == L"tdSendRawCommand") { - std::wstring command = TelldusCore::Message::takeString(&msg); - int reserved = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->deviceManager->sendRawCommand(command, reserved); - - } else if (function == L"tdConnectTellStickController") { - int vid = TelldusCore::Message::takeInt(&msg); - int pid = TelldusCore::Message::takeInt(&msg); - std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); - d->deviceManager->connectTellStickController(vid, pid, serial); - - } else if (function == L"tdDisconnectTellStickController") { - int vid = TelldusCore::Message::takeInt(&msg); - int pid = TelldusCore::Message::takeInt(&msg); - std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); - d->deviceManager->disconnectTellStickController(vid, pid, serial); - - } else if (function == L"tdSensor") { - (*wstringReturn) = d->deviceManager->getSensors(); - - } else if (function == L"tdSensorValue") { - std::wstring protocol = TelldusCore::Message::takeString(&msg); - std::wstring model = TelldusCore::Message::takeString(&msg); - int id = TelldusCore::Message::takeInt(&msg); - int dataType = TelldusCore::Message::takeInt(&msg); - (*wstringReturn) = d->deviceManager->getSensorValue(protocol, model, id, dataType); - - } else if (function == L"tdController") { - (*wstringReturn) = d->controllerManager->getControllers(); - - } else if (function == L"tdControllerValue") { - int id = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - (*wstringReturn) = d->controllerManager->getControllerValue(id, name); - - } else if (function == L"tdSetControllerValue") { - int id = TelldusCore::Message::takeInt(&msg); - std::wstring name = TelldusCore::Message::takeString(&msg); - std::wstring value = TelldusCore::Message::takeString(&msg); - (*intReturn) = d->controllerManager->setControllerValue(id, name, value); - - } else if (function == L"tdRemoveController") { - int controllerId = TelldusCore::Message::takeInt(&msg); - (*intReturn) = d->controllerManager->removeController(controllerId); - - } else{ - (*intReturn) = TELLSTICK_ERROR_UNKNOWN; - } -} - -void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType){ - - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDDeviceChangeEvent"; - eventData->deviceId = deviceId; - eventData->eventDeviceChanges = eventDeviceChanges; - eventData->eventChangeType = eventChangeType; - d->deviceUpdateEvent->signal(eventData); -} +#include "ClientCommunicationHandler.h" +#include "Message.h" +#include "Strings.h" + +#include + +class ClientCommunicationHandler::PrivateData { +public: + TelldusCore::Socket *clientSocket; + TelldusCore::EventRef event, deviceUpdateEvent; + bool done; + DeviceManager *deviceManager; + ControllerManager *controllerManager; +}; + +ClientCommunicationHandler::ClientCommunicationHandler(){ + +} + +ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent, ControllerManager *controllerManager) + :Thread() +{ + d = new PrivateData; + d->clientSocket = clientSocket; + d->event = event; + d->done = false; + d->deviceManager = deviceManager; + d->deviceUpdateEvent = deviceUpdateEvent; + d->controllerManager = controllerManager; +} + +ClientCommunicationHandler::~ClientCommunicationHandler(void) +{ + wait(); + delete(d->clientSocket); + delete d; +} + +void ClientCommunicationHandler::run(){ + //run thread + + std::wstring clientMessage = d->clientSocket->read(2000); + + int intReturn; + std::wstring strReturn; + strReturn = L""; + parseMessage(clientMessage, &intReturn, &strReturn); + + TelldusCore::Message msg; + + if(strReturn == L""){ + msg.addArgument(intReturn); + } + else{ + msg.addArgument(strReturn); + } + msg.append(L"\n"); + d->clientSocket->write(msg); + + //We are done, signal for removal + d->done = true; + d->event->signal(); +} + +bool ClientCommunicationHandler::isDone(){ + return d->done; +} + + +void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn){ + + (*intReturn) = 0; + (*wstringReturn) = L""; + std::wstring msg(clientMessage); //Copy + std::wstring function(TelldusCore::Message::takeString(&msg)); + + if (function == L"tdTurnOn") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0); + + } else if (function == L"tdTurnOff") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0); + + } else if (function == L"tdBell") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0); + + } else if (function == L"tdDim") { + int deviceId = TelldusCore::Message::takeInt(&msg); + int level = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, level); + + } else if (function == L"tdExecute") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_EXECUTE, 0); + + } else if (function == L"tdUp") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_UP, 0); + + } else if (function == L"tdDown") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DOWN, 0); + + } else if (function == L"tdStop") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_STOP, 0); + + } else if (function == L"tdLearn") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); + + } else if (function == L"tdLastSentCommand") { + int deviceId = TelldusCore::Message::takeInt(&msg); + int methodsSupported = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceLastSentCommand(deviceId, methodsSupported); + + } else if (function == L"tdLastSentValue") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceStateValue(deviceId); + + } else if(function == L"tdGetNumberOfDevices"){ + + (*intReturn) = d->deviceManager->getNumberOfDevices(); + + } else if (function == L"tdGetDeviceId") { + int deviceIndex = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceId(deviceIndex); + + } else if (function == L"tdGetDeviceType") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceType(deviceId); + + } else if (function == L"tdGetName") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceName(deviceId); + + } else if (function == L"tdSetName") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + (*intReturn) = d->deviceManager->setDeviceName(deviceId, name); + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME); + + } else if (function == L"tdGetProtocol") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceProtocol(deviceId); + + } else if (function == L"tdSetProtocol") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring protocol = TelldusCore::Message::takeString(&msg); + int oldMethods = d->deviceManager->getDeviceMethods(deviceId); + (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); + } + + } else if (function == L"tdGetModel") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getDeviceModel(deviceId); + + } else if (function == L"tdSetModel") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring model = TelldusCore::Message::takeString(&msg); + int oldMethods = d->deviceManager->getDeviceMethods(deviceId); + (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); + } + + } else if (function == L"tdGetDeviceParameter") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring defaultValue = TelldusCore::Message::takeString(&msg); + (*wstringReturn) = d->deviceManager->getDeviceParameter(deviceId, name, defaultValue); + + } else if (function == L"tdSetDeviceParameter") { + int deviceId = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring value = TelldusCore::Message::takeString(&msg); + int oldMethods = d->deviceManager->getDeviceMethods(deviceId); + (*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value); + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); + } + + } else if (function == L"tdAddDevice") { + (*intReturn) = d->deviceManager->addDevice(); + if((*intReturn) >= 0){ + sendDeviceSignal((*intReturn), TELLSTICK_DEVICE_ADDED, 0); + } + + } else if (function == L"tdRemoveDevice") { + int deviceId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->removeDevice(deviceId); + if((*intReturn) == TELLSTICK_SUCCESS){ + sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0); + } + + } else if (function == L"tdMethods") { + int deviceId = TelldusCore::Message::takeInt(&msg); + int intMethodsSupported = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported); + + } else if (function == L"tdSendRawCommand") { + std::wstring command = TelldusCore::Message::takeString(&msg); + int reserved = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->deviceManager->sendRawCommand(command, reserved); + + } else if (function == L"tdConnectTellStickController") { + int vid = TelldusCore::Message::takeInt(&msg); + int pid = TelldusCore::Message::takeInt(&msg); + std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); + d->deviceManager->connectTellStickController(vid, pid, serial); + + } else if (function == L"tdDisconnectTellStickController") { + int vid = TelldusCore::Message::takeInt(&msg); + int pid = TelldusCore::Message::takeInt(&msg); + std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg)); + d->deviceManager->disconnectTellStickController(vid, pid, serial); + + } else if (function == L"tdSensor") { + (*wstringReturn) = d->deviceManager->getSensors(); + + } else if (function == L"tdSensorValue") { + std::wstring protocol = TelldusCore::Message::takeString(&msg); + std::wstring model = TelldusCore::Message::takeString(&msg); + int id = TelldusCore::Message::takeInt(&msg); + int dataType = TelldusCore::Message::takeInt(&msg); + (*wstringReturn) = d->deviceManager->getSensorValue(protocol, model, id, dataType); + + } else if (function == L"tdController") { + (*wstringReturn) = d->controllerManager->getControllers(); + + } else if (function == L"tdControllerValue") { + int id = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + (*wstringReturn) = d->controllerManager->getControllerValue(id, name); + + } else if (function == L"tdSetControllerValue") { + int id = TelldusCore::Message::takeInt(&msg); + std::wstring name = TelldusCore::Message::takeString(&msg); + std::wstring value = TelldusCore::Message::takeString(&msg); + (*intReturn) = d->controllerManager->setControllerValue(id, name, value); + + } else if (function == L"tdRemoveController") { + int controllerId = TelldusCore::Message::takeInt(&msg); + (*intReturn) = d->controllerManager->removeController(controllerId); + + } else{ + (*intReturn) = TELLSTICK_ERROR_UNKNOWN; + } +} + +void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType){ + + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDDeviceChangeEvent"; + eventData->deviceId = deviceId; + eventData->eventDeviceChanges = eventDeviceChanges; + eventData->eventChangeType = eventChangeType; + d->deviceUpdateEvent->signal(eventData); +} diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index 365fd393..fe84f093 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -1,31 +1,31 @@ -#ifndef CONNECTIONLISTENER_H -#define CONNECTIONLISTENER_H - -#include -#include "Thread.h" -#include "Event.h" - -class Event; -namespace TelldusCore { - class Socket; -}; - -class ConnectionListenerEventData : public TelldusCore::EventDataBase { -public: - TelldusCore::Socket *socket; -}; - -class ConnectionListener : public TelldusCore::Thread { -public: - ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent); - virtual ~ConnectionListener(void); - -protected: - void run(); - -private: - class PrivateData; - PrivateData *d; -}; - -#endif //CONNECTIONLISTENER_H +#ifndef CONNECTIONLISTENER_H +#define CONNECTIONLISTENER_H + +#include +#include "Thread.h" +#include "Event.h" + +class Event; +namespace TelldusCore { + class Socket; +}; + +class ConnectionListenerEventData : public TelldusCore::EventDataBase { +public: + TelldusCore::Socket *socket; +}; + +class ConnectionListener : public TelldusCore::Thread { +public: + ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent); + virtual ~ConnectionListener(void); + +protected: + void run(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CONNECTIONLISTENER_H diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 4c6c6ab6..b1fbe2a4 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -1,91 +1,91 @@ -#include "ConnectionListener.h" -#include "Socket.h" - -#include -#include -#include -#include -#include - - -#include -#include -#include - -class ConnectionListener::PrivateData { -public: - TelldusCore::EventRef waitEvent; - std::string name; - bool running; -}; - -ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) -{ - d = new PrivateData; - d->waitEvent = waitEvent; - - d->name = "/tmp/" + std::string(name.begin(), name.end()); - d->running = true; - - this->start(); -} - -ConnectionListener::~ConnectionListener(void) { - d->running = false; - this->wait(); - unlink(d->name.c_str()); - delete d; -} - -void ConnectionListener::run(){ - struct timeval tv = { 0, 0 }; - - //Timeout for select - - SOCKET_T serverSocket; - struct sockaddr_un name; - socklen_t len; - serverSocket = socket(PF_LOCAL, SOCK_STREAM, 0); - if (serverSocket < 0) { - return; - } - name.sun_family = AF_LOCAL; - memset(name.sun_path, '\0', sizeof(name.sun_path)); - strncpy(name.sun_path, d->name.c_str(), sizeof(name.sun_path)); - unlink(name.sun_path); - int size = SUN_LEN(&name); - bind(serverSocket, (struct sockaddr *)&name, size); - listen(serverSocket, 5); - - //Change permissions to allow everyone - chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); - len = sizeof(struct sockaddr_un); - - fd_set infds; - FD_ZERO(&infds); - FD_SET(serverSocket, &infds); - - while(d->running) { - tv.tv_sec = 5; - - int response = select(serverSocket+1, &infds, NULL, NULL, &tv); - if (response == 0) { - FD_SET(serverSocket, &infds); - continue; - } else if (response < 0 ) { - continue; - } - //Make sure it is a new connection - if (!FD_ISSET(serverSocket, &infds)) { - continue; - } - SOCKET_T clientSocket = accept(serverSocket, NULL, NULL); - - ConnectionListenerEventData *data = new ConnectionListenerEventData(); - data->socket = new TelldusCore::Socket(clientSocket); - d->waitEvent->signal(data); - - } - close(serverSocket); -} - +#include "ConnectionListener.h" +#include "Socket.h" + +#include +#include +#include +#include +#include + + +#include +#include +#include + +class ConnectionListener::PrivateData { +public: + TelldusCore::EventRef waitEvent; + std::string name; + bool running; +}; + +ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) +{ + d = new PrivateData; + d->waitEvent = waitEvent; + + d->name = "/tmp/" + std::string(name.begin(), name.end()); + d->running = true; + + this->start(); +} + +ConnectionListener::~ConnectionListener(void) { + d->running = false; + this->wait(); + unlink(d->name.c_str()); + delete d; +} + +void ConnectionListener::run(){ + struct timeval tv = { 0, 0 }; + + //Timeout for select + + SOCKET_T serverSocket; + struct sockaddr_un name; + socklen_t len; + serverSocket = socket(PF_LOCAL, SOCK_STREAM, 0); + if (serverSocket < 0) { + return; + } + name.sun_family = AF_LOCAL; + memset(name.sun_path, '\0', sizeof(name.sun_path)); + strncpy(name.sun_path, d->name.c_str(), sizeof(name.sun_path)); + unlink(name.sun_path); + int size = SUN_LEN(&name); + bind(serverSocket, (struct sockaddr *)&name, size); + listen(serverSocket, 5); + + //Change permissions to allow everyone + chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); + len = sizeof(struct sockaddr_un); + + fd_set infds; + FD_ZERO(&infds); + FD_SET(serverSocket, &infds); + + while(d->running) { + tv.tv_sec = 5; + + int response = select(serverSocket+1, &infds, NULL, NULL, &tv); + if (response == 0) { + FD_SET(serverSocket, &infds); + continue; + } else if (response < 0 ) { + continue; + } + //Make sure it is a new connection + if (!FD_ISSET(serverSocket, &infds)) { + continue; + } + SOCKET_T clientSocket = accept(serverSocket, NULL, NULL); + + ConnectionListenerEventData *data = new ConnectionListenerEventData(); + data->socket = new TelldusCore::Socket(clientSocket); + d->waitEvent->signal(data); + + } + close(serverSocket); +} + diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index ec10d8bd..6e1c35a8 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -1,149 +1,149 @@ -#include "ConnectionListener.h" -#include "Event.h" -#include "Socket.h" - -#include -#include -#include - -#define BUFSIZE 512 - -class ConnectionListener::PrivateData { -public: - std::wstring pipename; - SECURITY_ATTRIBUTES sa; - HANDLE hEvent; - bool running; - TelldusCore::EventRef waitEvent; -}; - -ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) -{ - d = new PrivateData; - d->hEvent = 0; - - d->running = true; - d->waitEvent = waitEvent; - d->pipename = L"\\\\.\\pipe\\" + name; - - PSECURITY_DESCRIPTOR pSD = NULL; - PACL pACL = NULL; - EXPLICIT_ACCESS ea; - PSID pEveryoneSID = NULL; - SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; - - pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); - if (pSD == NULL) { - return; - } - - if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { - LocalFree(pSD); - return; - } - - if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) { - LocalFree(pSD); - } - - ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); - ea.grfAccessPermissions = STANDARD_RIGHTS_ALL; - ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance= NO_INHERITANCE; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; - ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; - - - // Add the ACL to the security descriptor. - if (!SetSecurityDescriptorDacl(pSD, - TRUE, // bDaclPresent flag - pACL, - FALSE)) // not a default DACL - { - LocalFree(pSD); - FreeSid(pEveryoneSID); - } - - - d->sa.nLength = sizeof(SECURITY_ATTRIBUTES); - d->sa.lpSecurityDescriptor = pSD; - d->sa.bInheritHandle = false; - - start(); -} - -ConnectionListener::~ConnectionListener(void) { - d->running = false; - if (d->hEvent) { - SetEvent(d->hEvent); - } - wait(); - delete d; -} - -void ConnectionListener::run() { - HANDLE hPipe; - OVERLAPPED oOverlap; - DWORD cbBytesRead; - - memset(&oOverlap, 0, sizeof(OVERLAPPED)); - - d->hEvent = CreateEvent(NULL, true, false, NULL); - oOverlap.hEvent = d->hEvent; - bool recreate = true; - - while (1) { - BOOL alreadyConnected = false; - if (recreate) { - hPipe = CreateNamedPipe( - (const wchar_t *)d->pipename.c_str(), // pipe name - PIPE_ACCESS_DUPLEX | // read/write access - FILE_FLAG_OVERLAPPED, //Overlapped mode - PIPE_TYPE_MESSAGE | // message type pipe - PIPE_READMODE_MESSAGE | // message-read mode - PIPE_WAIT, // blocking mode - PIPE_UNLIMITED_INSTANCES, // max. instances - BUFSIZE, // output buffer size - BUFSIZE, // input buffer size - 0, // client time-out - &d->sa); // default security attribute - - if (hPipe == INVALID_HANDLE_VALUE) { - return; - } - - ConnectNamedPipe(hPipe, &oOverlap); - alreadyConnected = GetLastError() == ERROR_PIPE_CONNECTED; - recreate = false; - } - if(!alreadyConnected){ - DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000); - if (!d->running) { - CancelIo(hPipe); - WaitForSingleObject(oOverlap.hEvent, INFINITE); - break; - } - - if(result == WAIT_TIMEOUT){ - //CloseHandle(hPipe); - continue; - } - BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); - - if (!connected) { - CloseHandle(hPipe); - return; - } - } - ConnectionListenerEventData *data = new ConnectionListenerEventData(); - ResetEvent(oOverlap.hEvent); - data->socket = new TelldusCore::Socket(hPipe); - d->waitEvent->signal(data); - - recreate = true; - } - - CloseHandle(d->hEvent); - CloseHandle(hPipe); -} +#include "ConnectionListener.h" +#include "Event.h" +#include "Socket.h" + +#include +#include +#include + +#define BUFSIZE 512 + +class ConnectionListener::PrivateData { +public: + std::wstring pipename; + SECURITY_ATTRIBUTES sa; + HANDLE hEvent; + bool running; + TelldusCore::EventRef waitEvent; +}; + +ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) +{ + d = new PrivateData; + d->hEvent = 0; + + d->running = true; + d->waitEvent = waitEvent; + d->pipename = L"\\\\.\\pipe\\" + name; + + PSECURITY_DESCRIPTOR pSD = NULL; + PACL pACL = NULL; + EXPLICIT_ACCESS ea; + PSID pEveryoneSID = NULL; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + + pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD == NULL) { + return; + } + + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { + LocalFree(pSD); + return; + } + + if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) { + LocalFree(pSD); + } + + ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); + ea.grfAccessPermissions = STANDARD_RIGHTS_ALL; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance= NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; + + + // Add the ACL to the security descriptor. + if (!SetSecurityDescriptorDacl(pSD, + TRUE, // bDaclPresent flag + pACL, + FALSE)) // not a default DACL + { + LocalFree(pSD); + FreeSid(pEveryoneSID); + } + + + d->sa.nLength = sizeof(SECURITY_ATTRIBUTES); + d->sa.lpSecurityDescriptor = pSD; + d->sa.bInheritHandle = false; + + start(); +} + +ConnectionListener::~ConnectionListener(void) { + d->running = false; + if (d->hEvent) { + SetEvent(d->hEvent); + } + wait(); + delete d; +} + +void ConnectionListener::run() { + HANDLE hPipe; + OVERLAPPED oOverlap; + DWORD cbBytesRead; + + memset(&oOverlap, 0, sizeof(OVERLAPPED)); + + d->hEvent = CreateEvent(NULL, true, false, NULL); + oOverlap.hEvent = d->hEvent; + bool recreate = true; + + while (1) { + BOOL alreadyConnected = false; + if (recreate) { + hPipe = CreateNamedPipe( + (const wchar_t *)d->pipename.c_str(), // pipe name + PIPE_ACCESS_DUPLEX | // read/write access + FILE_FLAG_OVERLAPPED, //Overlapped mode + PIPE_TYPE_MESSAGE | // message type pipe + PIPE_READMODE_MESSAGE | // message-read mode + PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max. instances + BUFSIZE, // output buffer size + BUFSIZE, // input buffer size + 0, // client time-out + &d->sa); // default security attribute + + if (hPipe == INVALID_HANDLE_VALUE) { + return; + } + + ConnectNamedPipe(hPipe, &oOverlap); + alreadyConnected = GetLastError() == ERROR_PIPE_CONNECTED; + recreate = false; + } + if(!alreadyConnected){ + DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000); + if (!d->running) { + CancelIo(hPipe); + WaitForSingleObject(oOverlap.hEvent, INFINITE); + break; + } + + if(result == WAIT_TIMEOUT){ + //CloseHandle(hPipe); + continue; + } + BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); + + if (!connected) { + CloseHandle(hPipe); + return; + } + } + ConnectionListenerEventData *data = new ConnectionListenerEventData(); + ResetEvent(oOverlap.hEvent); + data->socket = new TelldusCore::Socket(hPipe); + d->waitEvent->signal(data); + + recreate = true; + } + + CloseHandle(d->hEvent); + CloseHandle(hPipe); +} diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 02a6b279..a9f22fc1 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -1,53 +1,53 @@ -#include "Controller.h" -#include "Protocol.h" -#include "EventUpdateManager.h" -#include "Strings.h" - -class Controller::PrivateData { -public: - TelldusCore::EventRef event, updateEvent; - int id, firmwareVersion; -}; - -Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ - d = new PrivateData; - d->event = event; - d->updateEvent = updateEvent; - d->id = id; - d->firmwareVersion = 0; -} - -Controller::~Controller(){ - delete d; -} - -void Controller::publishData(const std::string &msg) const { - ControllerEventData *data = new ControllerEventData; - data->msg = msg; - data->controllerId = d->id; - d->event->signal(data); -} - -void Controller::decodePublishData(const std::string &data) const { - - std::list msgList = Protocol::decodeData(data); - - for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt){ - this->publishData(*msgIt); - } -} - -int Controller::firmwareVersion() const { - return d->firmwareVersion; -} - -void Controller::setFirmwareVersion(int version) { - d->firmwareVersion = version; - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDControllerEvent"; - eventData->controllerId = d->id; - eventData->eventState = TELLSTICK_DEVICE_CHANGED; - eventData->eventChangeType = TELLSTICK_CHANGE_FIRMWARE; - eventData->eventValue = TelldusCore::intToWstring(version); - d->updateEvent->signal(eventData); -} +#include "Controller.h" +#include "Protocol.h" +#include "EventUpdateManager.h" +#include "Strings.h" + +class Controller::PrivateData { +public: + TelldusCore::EventRef event, updateEvent; + int id, firmwareVersion; +}; + +Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ + d = new PrivateData; + d->event = event; + d->updateEvent = updateEvent; + d->id = id; + d->firmwareVersion = 0; +} + +Controller::~Controller(){ + delete d; +} + +void Controller::publishData(const std::string &msg) const { + ControllerEventData *data = new ControllerEventData; + data->msg = msg; + data->controllerId = d->id; + d->event->signal(data); +} + +void Controller::decodePublishData(const std::string &data) const { + + std::list msgList = Protocol::decodeData(data); + + for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt){ + this->publishData(*msgIt); + } +} + +int Controller::firmwareVersion() const { + return d->firmwareVersion; +} + +void Controller::setFirmwareVersion(int version) { + d->firmwareVersion = version; + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDControllerEvent"; + eventData->controllerId = d->id; + eventData->eventState = TELLSTICK_DEVICE_CHANGED; + eventData->eventChangeType = TELLSTICK_CHANGE_FIRMWARE; + eventData->eventValue = TelldusCore::intToWstring(version); + d->updateEvent->signal(eventData); +} diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index eff903f7..410abf53 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -1,32 +1,32 @@ -#ifndef CONTROLLER_H -#define CONTROLLER_H - -#include "Event.h" -#include - -class ControllerEventData : public TelldusCore::EventDataBase { -public: - std::string msg; - int controllerId; -}; - -class Controller { -public: - virtual ~Controller(); - - virtual int firmwareVersion() const; - virtual int send( const std::string &message ) = 0; - virtual int reset() = 0; - -protected: - Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent); - void publishData(const std::string &data) const; - void decodePublishData(const std::string &data) const; - void setFirmwareVersion(int version); - -private: - class PrivateData; - PrivateData *d; -}; - -#endif //CONTROLLER_H +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include "Event.h" +#include + +class ControllerEventData : public TelldusCore::EventDataBase { +public: + std::string msg; + int controllerId; +}; + +class Controller { +public: + virtual ~Controller(); + + virtual int firmwareVersion() const; + virtual int send( const std::string &message ) = 0; + virtual int reset() = 0; + +protected: + Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent); + void publishData(const std::string &data) const; + void decodePublishData(const std::string &data) const; + void setFirmwareVersion(int version); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //CONTROLLER_H diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index ba6bcff3..2ccfa9a6 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -1,337 +1,337 @@ -#include "ControllerManager.h" -#include "Controller.h" -#include "Mutex.h" -#include "TellStick.h" -#include "Log.h" -#include "Message.h" -#include "Strings.h" -#include "Settings.h" -#include "EventUpdateManager.h" -#include "../client/telldus-core.h" - -#include -#include - -class ControllerDescriptor { -public: - std::wstring name, serial; - int type; - Controller *controller; -}; - -typedef std::map ControllerMap; - -class ControllerManager::PrivateData { -public: - int lastControllerId; - Settings settings; - ControllerMap controllers; - TelldusCore::EventRef event, updateEvent; - TelldusCore::Mutex mutex; -}; - -ControllerManager::ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ - d = new PrivateData; - d->lastControllerId = 0; - d->event = event; - d->updateEvent = updateEvent; - this->loadStoredControllers(); - this->loadControllers(); -} - -ControllerManager::~ControllerManager() { - for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - if (it->second.controller) { - delete( it->second.controller ); - } - } - delete d; -} - -void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) { - if (vid == 0x0 && pid == 0x0) { //All - if (inserted) { - loadControllers(); - } else { - //Disconnect all - TelldusCore::MutexLocker locker(&d->mutex); - while(d->controllers.size()) { - ControllerMap::iterator it = d->controllers.begin(); - delete it->second.controller; - it->second.controller = 0; - signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0"); - } - } - return; - } - if (vid != 0x1781) { - return; - } - if (pid != 0x0C30 && pid != 0x0C31) { - return; - } - if (inserted) { - loadControllers(); - } else { - //Autodetect which has been disconnected - TelldusCore::MutexLocker locker(&d->mutex); - for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - if (!it->second.controller) { - continue; - } - TellStick *tellstick = reinterpret_cast(it->second.controller); - if (!tellstick) { - continue; - } - if (serial.compare("") != 0) { - TellStickDescriptor tsd; - tsd.vid = vid; - tsd.pid = pid; - tsd.serial = serial; - if (!tellstick->isSameAsDescriptor(tsd)) { - continue; - } - } else if (tellstick->stillConnected()) { - continue; - } - - it->second.controller = 0; - delete tellstick; - signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0"); - } - } -} - -Controller *ControllerManager::getBestControllerById(int id) { - TelldusCore::MutexLocker locker(&d->mutex); - if (!d->controllers.size()) { - return 0; - } - ControllerMap::const_iterator it = d->controllers.find(id); - if (it != d->controllers.end() && it->second.controller) { - return it->second.controller; - } - //Find first available controller - for(it = d->controllers.begin(); it != d->controllers.end(); ++it) { - if (it->second.controller) { - return it->second.controller; - } - } - return 0; - -} - -void ControllerManager::loadControllers() { - TelldusCore::MutexLocker locker(&d->mutex); - - std::list list = TellStick::findAll(); - - std::list::iterator it = list.begin(); - for(; it != list.end(); ++it) { - //Most backend only report non-opened devices. - //If they don't make sure we don't open them twice - bool found = false; - ControllerMap::const_iterator cit = d->controllers.begin(); - for(; cit != d->controllers.end(); ++cit) { - if (!cit->second.controller) { - continue; - } - TellStick *tellstick = reinterpret_cast(cit->second.controller); - if (!tellstick) { - continue; - } - if (tellstick->isSameAsDescriptor(*it)) { - found = true; - break; - } - } - if (found) { - continue; - } - - int type = TELLSTICK_CONTROLLER_TELLSTICK; - if ((*it).pid == 0x0c31) { - type = TELLSTICK_CONTROLLER_TELLSTICK_DUO; - } - int controllerId = 0; - //See if the controller matches one of the loaded, non available controllers - std::wstring serial = TelldusCore::charToWstring((*it).serial.c_str()); - for(cit = d->controllers.begin(); cit != d->controllers.end(); ++cit) { - if (cit->second.type == type && cit->second.serial.compare(serial) == 0) { - controllerId = cit->first; - break; - } - } - bool isNew = false; - if (!controllerId) { - controllerId = d->settings.addNode(Settings::Controller); - if(controllerId < 0){ - //TODO: How to handle this? - continue; - } - isNew = true; - d->controllers[controllerId].type = type; - d->settings.setControllerType(controllerId, type); - d->controllers[controllerId].serial = TelldusCore::charToWstring((*it).serial.c_str()); - d->settings.setControllerSerial(controllerId, d->controllers[controllerId].serial); - } - - //int controllerId = d->lastControllerId+1; - TellStick *controller = new TellStick(controllerId, d->event, d->updateEvent, *it); - if (!controller->isOpen()) { - delete controller; - continue; - } - d->controllers[controllerId].controller = controller; - if (isNew) { - signalControllerEvent(controllerId, TELLSTICK_DEVICE_ADDED, type, L""); - } else { - signalControllerEvent(controllerId, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"1"); - } - } -} - -void ControllerManager::loadStoredControllers() { - int numberOfControllers = d->settings.getNumberOfNodes(Settings::Controller); - TelldusCore::MutexLocker locker(&d->mutex); - - for (int i = 0; i < numberOfControllers; ++i) { - int id = d->settings.getNodeId(Settings::Controller, i); - d->controllers[id].controller = NULL; - d->controllers[id].name = d->settings.getName(Settings::Controller, id); - d->controllers[id].type = d->settings.getControllerType(id); - d->controllers[id].serial = d->settings.getControllerSerial(id); - signalControllerEvent(id, TELLSTICK_DEVICE_ADDED, 0, L""); - } -} - -void ControllerManager::queryControllerStatus(){ - - std::list tellStickControllers; - - { - TelldusCore::MutexLocker locker(&d->mutex); - for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - if (!it->second.controller) { - continue; - } - TellStick *tellstick = reinterpret_cast(it->second.controller); - if (tellstick) { - tellStickControllers.push_back(tellstick); - } - } - } - - bool reloadControllers = false; - std::string noop = "N+"; - for(std::list::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) { - int success = (*it)->send(noop); - if(success == TELLSTICK_ERROR_BROKEN_PIPE){ - Log::warning("TellStick query: Error in communication with TellStick, resetting USB"); - resetController(*it); - } - if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND){ - reloadControllers = true; - } - } - - if(!tellStickControllers.size() || reloadControllers){ - //no tellstick at all found, or controller was reset - Log::debug("TellStick query: Rescanning USB ports"); //only log as debug, since this will happen all the time if no TellStick is connected - loadControllers(); - } -} - -int ControllerManager::resetController(Controller *controller) { - TellStick *tellstick = reinterpret_cast(controller); - if (!tellstick) { - return true; //not tellstick, nothing to reset at the moment, just return true - } - int success = tellstick->reset(); - deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete - return success; -} - -std::wstring ControllerManager::getControllers() const { - TelldusCore::MutexLocker locker(&d->mutex); - - TelldusCore::Message msg; - - msg.addArgument((int)d->controllers.size()); - - for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { - msg.addArgument(it->first); - msg.addArgument(it->second.type); - msg.addArgument(it->second.name.c_str()); - msg.addArgument(it->second.controller ? 1 : 0); - } - return msg; -} - -std::wstring ControllerManager::getControllerValue(int id, const std::wstring &name) { - TelldusCore::MutexLocker locker(&d->mutex); - - ControllerMap::iterator it = d->controllers.find(id); - if (it == d->controllers.end()) { - return L""; - } - if (name == L"serial") { - return it->second.serial; - } else if (name == L"firmware") { - if (!it->second.controller) { - return L"-1"; - } - return TelldusCore::intToWstring(it->second.controller->firmwareVersion()); - } - return L""; -} - -int ControllerManager::removeController(int id) { - TelldusCore::MutexLocker locker(&d->mutex); - - ControllerMap::iterator it = d->controllers.find(id); - if (it == d->controllers.end()) { - return TELLSTICK_ERROR_NOT_FOUND; - } - if (it->second.controller) { - //Still connected - return TELLSTICK_ERROR_PERMISSION_DENIED; - } - - int ret = d->settings.removeNode(Settings::Controller, id); - if (ret != TELLSTICK_SUCCESS) { - return ret; - } - - d->controllers.erase(it); - - signalControllerEvent(id, TELLSTICK_DEVICE_REMOVED, 0, L""); - return TELLSTICK_SUCCESS; -} - -int ControllerManager::setControllerValue(int id, const std::wstring &name, const std::wstring &value) { - TelldusCore::MutexLocker locker(&d->mutex); - - ControllerMap::iterator it = d->controllers.find(id); - if (it == d->controllers.end()) { - return TELLSTICK_ERROR_NOT_FOUND; - } - if (name == L"name") { - it->second.name = value; - d->settings.setName(Settings::Controller, id, value); - signalControllerEvent(id, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME, value); - } else { - return TELLSTICK_ERROR_SYNTAX; //TODO: Is this the best error? - } - return TELLSTICK_SUCCESS; -} - -void ControllerManager::signalControllerEvent(int controllerId, int changeEvent, int changeType, const std::wstring &newValue) { - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDControllerEvent"; - eventData->controllerId = controllerId; - eventData->eventState = changeEvent; - eventData->eventChangeType = changeType; - eventData->eventValue = newValue; - d->updateEvent->signal(eventData); -} +#include "ControllerManager.h" +#include "Controller.h" +#include "Mutex.h" +#include "TellStick.h" +#include "Log.h" +#include "Message.h" +#include "Strings.h" +#include "Settings.h" +#include "EventUpdateManager.h" +#include "../client/telldus-core.h" + +#include +#include + +class ControllerDescriptor { +public: + std::wstring name, serial; + int type; + Controller *controller; +}; + +typedef std::map ControllerMap; + +class ControllerManager::PrivateData { +public: + int lastControllerId; + Settings settings; + ControllerMap controllers; + TelldusCore::EventRef event, updateEvent; + TelldusCore::Mutex mutex; +}; + +ControllerManager::ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ + d = new PrivateData; + d->lastControllerId = 0; + d->event = event; + d->updateEvent = updateEvent; + this->loadStoredControllers(); + this->loadControllers(); +} + +ControllerManager::~ControllerManager() { + for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (it->second.controller) { + delete( it->second.controller ); + } + } + delete d; +} + +void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) { + if (vid == 0x0 && pid == 0x0) { //All + if (inserted) { + loadControllers(); + } else { + //Disconnect all + TelldusCore::MutexLocker locker(&d->mutex); + while(d->controllers.size()) { + ControllerMap::iterator it = d->controllers.begin(); + delete it->second.controller; + it->second.controller = 0; + signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0"); + } + } + return; + } + if (vid != 0x1781) { + return; + } + if (pid != 0x0C30 && pid != 0x0C31) { + return; + } + if (inserted) { + loadControllers(); + } else { + //Autodetect which has been disconnected + TelldusCore::MutexLocker locker(&d->mutex); + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (!it->second.controller) { + continue; + } + TellStick *tellstick = reinterpret_cast(it->second.controller); + if (!tellstick) { + continue; + } + if (serial.compare("") != 0) { + TellStickDescriptor tsd; + tsd.vid = vid; + tsd.pid = pid; + tsd.serial = serial; + if (!tellstick->isSameAsDescriptor(tsd)) { + continue; + } + } else if (tellstick->stillConnected()) { + continue; + } + + it->second.controller = 0; + delete tellstick; + signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0"); + } + } +} + +Controller *ControllerManager::getBestControllerById(int id) { + TelldusCore::MutexLocker locker(&d->mutex); + if (!d->controllers.size()) { + return 0; + } + ControllerMap::const_iterator it = d->controllers.find(id); + if (it != d->controllers.end() && it->second.controller) { + return it->second.controller; + } + //Find first available controller + for(it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (it->second.controller) { + return it->second.controller; + } + } + return 0; + +} + +void ControllerManager::loadControllers() { + TelldusCore::MutexLocker locker(&d->mutex); + + std::list list = TellStick::findAll(); + + std::list::iterator it = list.begin(); + for(; it != list.end(); ++it) { + //Most backend only report non-opened devices. + //If they don't make sure we don't open them twice + bool found = false; + ControllerMap::const_iterator cit = d->controllers.begin(); + for(; cit != d->controllers.end(); ++cit) { + if (!cit->second.controller) { + continue; + } + TellStick *tellstick = reinterpret_cast(cit->second.controller); + if (!tellstick) { + continue; + } + if (tellstick->isSameAsDescriptor(*it)) { + found = true; + break; + } + } + if (found) { + continue; + } + + int type = TELLSTICK_CONTROLLER_TELLSTICK; + if ((*it).pid == 0x0c31) { + type = TELLSTICK_CONTROLLER_TELLSTICK_DUO; + } + int controllerId = 0; + //See if the controller matches one of the loaded, non available controllers + std::wstring serial = TelldusCore::charToWstring((*it).serial.c_str()); + for(cit = d->controllers.begin(); cit != d->controllers.end(); ++cit) { + if (cit->second.type == type && cit->second.serial.compare(serial) == 0) { + controllerId = cit->first; + break; + } + } + bool isNew = false; + if (!controllerId) { + controllerId = d->settings.addNode(Settings::Controller); + if(controllerId < 0){ + //TODO: How to handle this? + continue; + } + isNew = true; + d->controllers[controllerId].type = type; + d->settings.setControllerType(controllerId, type); + d->controllers[controllerId].serial = TelldusCore::charToWstring((*it).serial.c_str()); + d->settings.setControllerSerial(controllerId, d->controllers[controllerId].serial); + } + + //int controllerId = d->lastControllerId+1; + TellStick *controller = new TellStick(controllerId, d->event, d->updateEvent, *it); + if (!controller->isOpen()) { + delete controller; + continue; + } + d->controllers[controllerId].controller = controller; + if (isNew) { + signalControllerEvent(controllerId, TELLSTICK_DEVICE_ADDED, type, L""); + } else { + signalControllerEvent(controllerId, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"1"); + } + } +} + +void ControllerManager::loadStoredControllers() { + int numberOfControllers = d->settings.getNumberOfNodes(Settings::Controller); + TelldusCore::MutexLocker locker(&d->mutex); + + for (int i = 0; i < numberOfControllers; ++i) { + int id = d->settings.getNodeId(Settings::Controller, i); + d->controllers[id].controller = NULL; + d->controllers[id].name = d->settings.getName(Settings::Controller, id); + d->controllers[id].type = d->settings.getControllerType(id); + d->controllers[id].serial = d->settings.getControllerSerial(id); + signalControllerEvent(id, TELLSTICK_DEVICE_ADDED, 0, L""); + } +} + +void ControllerManager::queryControllerStatus(){ + + std::list tellStickControllers; + + { + TelldusCore::MutexLocker locker(&d->mutex); + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (!it->second.controller) { + continue; + } + TellStick *tellstick = reinterpret_cast(it->second.controller); + if (tellstick) { + tellStickControllers.push_back(tellstick); + } + } + } + + bool reloadControllers = false; + std::string noop = "N+"; + for(std::list::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) { + int success = (*it)->send(noop); + if(success == TELLSTICK_ERROR_BROKEN_PIPE){ + Log::warning("TellStick query: Error in communication with TellStick, resetting USB"); + resetController(*it); + } + if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND){ + reloadControllers = true; + } + } + + if(!tellStickControllers.size() || reloadControllers){ + //no tellstick at all found, or controller was reset + Log::debug("TellStick query: Rescanning USB ports"); //only log as debug, since this will happen all the time if no TellStick is connected + loadControllers(); + } +} + +int ControllerManager::resetController(Controller *controller) { + TellStick *tellstick = reinterpret_cast(controller); + if (!tellstick) { + return true; //not tellstick, nothing to reset at the moment, just return true + } + int success = tellstick->reset(); + deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete + return success; +} + +std::wstring ControllerManager::getControllers() const { + TelldusCore::MutexLocker locker(&d->mutex); + + TelldusCore::Message msg; + + msg.addArgument((int)d->controllers.size()); + + for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + msg.addArgument(it->first); + msg.addArgument(it->second.type); + msg.addArgument(it->second.name.c_str()); + msg.addArgument(it->second.controller ? 1 : 0); + } + return msg; +} + +std::wstring ControllerManager::getControllerValue(int id, const std::wstring &name) { + TelldusCore::MutexLocker locker(&d->mutex); + + ControllerMap::iterator it = d->controllers.find(id); + if (it == d->controllers.end()) { + return L""; + } + if (name == L"serial") { + return it->second.serial; + } else if (name == L"firmware") { + if (!it->second.controller) { + return L"-1"; + } + return TelldusCore::intToWstring(it->second.controller->firmwareVersion()); + } + return L""; +} + +int ControllerManager::removeController(int id) { + TelldusCore::MutexLocker locker(&d->mutex); + + ControllerMap::iterator it = d->controllers.find(id); + if (it == d->controllers.end()) { + return TELLSTICK_ERROR_NOT_FOUND; + } + if (it->second.controller) { + //Still connected + return TELLSTICK_ERROR_PERMISSION_DENIED; + } + + int ret = d->settings.removeNode(Settings::Controller, id); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } + + d->controllers.erase(it); + + signalControllerEvent(id, TELLSTICK_DEVICE_REMOVED, 0, L""); + return TELLSTICK_SUCCESS; +} + +int ControllerManager::setControllerValue(int id, const std::wstring &name, const std::wstring &value) { + TelldusCore::MutexLocker locker(&d->mutex); + + ControllerMap::iterator it = d->controllers.find(id); + if (it == d->controllers.end()) { + return TELLSTICK_ERROR_NOT_FOUND; + } + if (name == L"name") { + it->second.name = value; + d->settings.setName(Settings::Controller, id, value); + signalControllerEvent(id, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME, value); + } else { + return TELLSTICK_ERROR_SYNTAX; //TODO: Is this the best error? + } + return TELLSTICK_SUCCESS; +} + +void ControllerManager::signalControllerEvent(int controllerId, int changeEvent, int changeType, const std::wstring &newValue) { + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDControllerEvent"; + eventData->controllerId = controllerId; + eventData->eventState = changeEvent; + eventData->eventChangeType = changeType; + eventData->eventValue = newValue; + d->updateEvent->signal(eventData); +} diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index 72c83f24..aa0135c9 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -1,89 +1,89 @@ -#include "ControllerMessage.h" -#include "Device.h" -#include "Strings.h" - -#include "common.h" - -#include - -class ControllerMessage::PrivateData { -public: - std::map parameters; - std::string protocol, model, msgClass; - int method; -}; - -ControllerMessage::ControllerMessage(const std::string &message) { - d = new PrivateData; - - //Process our message into bits - size_t prevPos = 0; - size_t pos = message.find(";"); - while(pos != std::string::npos) { - std::string param = message.substr(prevPos, pos-prevPos); - prevPos = pos+1; - size_t delim = param.find(":"); - if (delim == std::string::npos) { - break; - } - if (param.substr(0, delim).compare("class") == 0) { - d->msgClass = param.substr(delim+1, param.length()-delim); - } else if (param.substr(0, delim).compare("protocol") == 0) { - d->protocol = param.substr(delim+1, param.length()-delim); - } else if (param.substr(0, delim).compare("model") == 0) { - d->model = param.substr(delim+1, param.length()-delim); - } else if (param.substr(0, delim).compare("method") == 0) { - d->method = Device::methodId(param.substr(delim+1, param.length()-delim)); - } else { - d->parameters[param.substr(0, delim)] = param.substr(delim+1, param.length()-delim); - } - pos = message.find(";", pos+1); - } -} - -ControllerMessage::~ControllerMessage(){ - delete d; -} - -std::string ControllerMessage::msgClass() const { - return d->msgClass; -} - -int ControllerMessage::method() const { - return d->method; -} - -std::wstring ControllerMessage::protocol() const { - return TelldusCore::charToWstring(d->protocol.c_str()); -} - -std::wstring ControllerMessage::model() const { - return TelldusCore::charToWstring(d->model.c_str()); -} - -int ControllerMessage::getIntParameter(const std::string &key) const { - std::string strValue = getParameter(key); - if (strValue.compare("") == 0) { - return -1; - } - if (strValue.substr(0,2).compare("0x") == 0) { - return strtol(strValue.c_str(), NULL, 16); - } - return strtol(strValue.c_str(), NULL, 10); -} - -std::string ControllerMessage::getParameter(const std::string &key) const { - std::map::iterator it = d->parameters.find(key); - if (it == d->parameters.end()) { - return ""; - } - return d->parameters[key]; -} - -bool ControllerMessage::hasParameter(const std::string &key) const { - std::map::iterator it = d->parameters.find(key); - if (it == d->parameters.end()) { - return false; - } - return true; -} +#include "ControllerMessage.h" +#include "Device.h" +#include "Strings.h" + +#include "common.h" + +#include + +class ControllerMessage::PrivateData { +public: + std::map parameters; + std::string protocol, model, msgClass; + int method; +}; + +ControllerMessage::ControllerMessage(const std::string &message) { + d = new PrivateData; + + //Process our message into bits + size_t prevPos = 0; + size_t pos = message.find(";"); + while(pos != std::string::npos) { + std::string param = message.substr(prevPos, pos-prevPos); + prevPos = pos+1; + size_t delim = param.find(":"); + if (delim == std::string::npos) { + break; + } + if (param.substr(0, delim).compare("class") == 0) { + d->msgClass = param.substr(delim+1, param.length()-delim); + } else if (param.substr(0, delim).compare("protocol") == 0) { + d->protocol = param.substr(delim+1, param.length()-delim); + } else if (param.substr(0, delim).compare("model") == 0) { + d->model = param.substr(delim+1, param.length()-delim); + } else if (param.substr(0, delim).compare("method") == 0) { + d->method = Device::methodId(param.substr(delim+1, param.length()-delim)); + } else { + d->parameters[param.substr(0, delim)] = param.substr(delim+1, param.length()-delim); + } + pos = message.find(";", pos+1); + } +} + +ControllerMessage::~ControllerMessage(){ + delete d; +} + +std::string ControllerMessage::msgClass() const { + return d->msgClass; +} + +int ControllerMessage::method() const { + return d->method; +} + +std::wstring ControllerMessage::protocol() const { + return TelldusCore::charToWstring(d->protocol.c_str()); +} + +std::wstring ControllerMessage::model() const { + return TelldusCore::charToWstring(d->model.c_str()); +} + +int ControllerMessage::getIntParameter(const std::string &key) const { + std::string strValue = getParameter(key); + if (strValue.compare("") == 0) { + return -1; + } + if (strValue.substr(0,2).compare("0x") == 0) { + return strtol(strValue.c_str(), NULL, 16); + } + return strtol(strValue.c_str(), NULL, 10); +} + +std::string ControllerMessage::getParameter(const std::string &key) const { + std::map::iterator it = d->parameters.find(key); + if (it == d->parameters.end()) { + return ""; + } + return d->parameters[key]; +} + +bool ControllerMessage::hasParameter(const std::string &key) const { + std::map::iterator it = d->parameters.find(key); + if (it == d->parameters.end()) { + return false; + } + return true; +} diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index b660c671..b0777542 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -1,253 +1,253 @@ -#include "Device.h" -#include "Settings.h" -#include "TellStick.h" - -class Device::PrivateData { -public: - std::wstring model; - std::wstring name; - ParameterMap parameterList; - Protocol *protocol; - std::wstring protocolName; - int preferredControllerId; - int state; - std::wstring stateValue; -}; - -Device::Device(int id) - :Mutex() -{ - d = new PrivateData; - d->protocol = 0; - d->preferredControllerId = 0; - d->state = 0; -} - -Device::~Device(void) { - delete d->protocol; - delete d; -} - -/** -* Get-/Set-methods -*/ - -int Device::getLastSentCommand(int methodsSupported){ - - int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported); - - if (lastSentCommand == TELLSTICK_BELL) { - //Bell is not a state - lastSentCommand = TELLSTICK_TURNOFF; - } - if (lastSentCommand == 0) { - lastSentCommand = TELLSTICK_TURNOFF; - } - return lastSentCommand; - -} - -int Device::getMethods() const { - Protocol *p = this->retrieveProtocol(); - if (p) { - return p->methods(); - } - return 0; -} - -void Device::setLastSentCommand(int command, std::wstring value){ - d->state = command; - d->stateValue = value; -} - -std::wstring Device::getModel(){ - return d->model; -} - -void Device::setModel(const std::wstring &model){ - if(d->protocol){ - delete(d->protocol); - d->protocol = 0; - } - d->model = model; -} - -std::wstring Device::getName(){ - return d->name; -} - -void Device::setName(const std::wstring &name){ - d->name = name; -} - -std::wstring Device::getParameter(const std::wstring &key){ - ParameterMap::iterator it = d->parameterList.find(key); - if (it == d->parameterList.end()) { - return L""; - } - return d->parameterList[key]; -} - -std::list Device::getParametersForProtocol() const { - return Protocol::getParametersForProtocol(getProtocolName()); -} - -void Device::setParameter(const std::wstring &key, const std::wstring &value){ - d->parameterList[key] = value; - if(d->protocol){ - d->protocol->setParameters(d->parameterList); - } -} - -int Device::getPreferredControllerId(){ - return d->preferredControllerId; -} - -void Device::setPreferredControllerId(int controllerId){ - d->preferredControllerId = controllerId; -} - -std::wstring Device::getProtocolName() const { - return d->protocolName; -} - -void Device::setProtocolName(const std::wstring &protocolName){ - if(d->protocol){ - delete(d->protocol); - d->protocol = 0; - } - d->protocolName = protocolName; -} - -std::wstring Device::getStateValue(){ - return d->stateValue; -} - -int Device::getType(){ - if(d->protocolName == L"group"){ - return TELLSTICK_TYPE_GROUP; - } - else if(d->protocolName == L"scene"){ - return TELLSTICK_TYPE_SCENE; - } - return TELLSTICK_TYPE_DEVICE; -} - -/** -* End Get-/Set -*/ - -int Device::doAction(int action, unsigned char data, Controller *controller) { - Protocol *p = this->retrieveProtocol(); - if(p){ - //Try to determine if we need to call another method due to masking - int methods = p->methods(); - if ((action & methods) == 0) { - //Loop all methods an see if any method masks to this one - for(int i = 1; i <= methods; i<<=1) { - if ((i & methods) == 0) { - continue; - } - if (this->maskUnsupportedMethods(i, action)) { - action = i; - break; - } - } - } - if ((action & methods) == 0) { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } - std::string code = p->getStringForMethod(action, data, controller); - if (code == "") { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } - if (code[0] != 'S' && code[0] != 'T' && code[0] != 'P' && code[0] != 'R') { - //Try autodetect sendtype - TellStick *tellstick = reinterpret_cast(controller); - if (!tellstick) { - return TELLSTICK_ERROR_UNKNOWN; - } - unsigned int maxlength = 80; - if (tellstick->pid() == 0x0c31) { - maxlength = 512; - } - if (code.length() <= maxlength) { - //S is enough - code.insert(0, 1, 'S'); - code.append(1, '+'); - } else { - code = TellStick::createTPacket(code); - } - } - return controller->send(code); - } - return TELLSTICK_ERROR_UNKNOWN; -} - -Protocol* Device::retrieveProtocol() const { - if (d->protocol) { - return d->protocol; - } - - d->protocol = Protocol::getProtocolInstance(d->protocolName); - if(d->protocol){ - d->protocol->setModel(d->model); - d->protocol->setParameters(d->parameterList); - return d->protocol; - } - - return 0; -} - -int Device::maskUnsupportedMethods(int methods, int supportedMethods) { - // Bell -> On - if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) { - methods |= TELLSTICK_TURNON; - } - - // Execute -> On - if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) { - methods |= TELLSTICK_TURNON; - } - - // Up -> Off - if ((methods & TELLSTICK_UP) && !(supportedMethods & TELLSTICK_UP)) { - methods |= TELLSTICK_TURNOFF; - } - - // Down -> On - if ((methods & TELLSTICK_DOWN) && !(supportedMethods & TELLSTICK_DOWN)) { - methods |= TELLSTICK_TURNON; - } - - //Cut of the rest of the unsupported methods we don't have a fallback for - return methods & supportedMethods; -} - -int Device::methodId( const std::string &methodName ) { - if (methodName.compare("turnon") == 0) { - return TELLSTICK_TURNON; - } - if (methodName.compare("turnoff") == 0) { - return TELLSTICK_TURNOFF; - } - if (methodName.compare("bell") == 0) { - return TELLSTICK_BELL; - } - if (methodName.compare("dim") == 0) { - return TELLSTICK_DIM; - } - if (methodName.compare("execute") == 0) { - return TELLSTICK_EXECUTE; - } - if (methodName.compare("up") == 0) { - return TELLSTICK_UP; - } - if (methodName.compare("down") == 0) { - return TELLSTICK_DOWN; - } - if (methodName.compare("stop") == 0) { - return TELLSTICK_STOP; - } - return 0; -} +#include "Device.h" +#include "Settings.h" +#include "TellStick.h" + +class Device::PrivateData { +public: + std::wstring model; + std::wstring name; + ParameterMap parameterList; + Protocol *protocol; + std::wstring protocolName; + int preferredControllerId; + int state; + std::wstring stateValue; +}; + +Device::Device(int id) + :Mutex() +{ + d = new PrivateData; + d->protocol = 0; + d->preferredControllerId = 0; + d->state = 0; +} + +Device::~Device(void) { + delete d->protocol; + delete d; +} + +/** +* Get-/Set-methods +*/ + +int Device::getLastSentCommand(int methodsSupported){ + + int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported); + + if (lastSentCommand == TELLSTICK_BELL) { + //Bell is not a state + lastSentCommand = TELLSTICK_TURNOFF; + } + if (lastSentCommand == 0) { + lastSentCommand = TELLSTICK_TURNOFF; + } + return lastSentCommand; + +} + +int Device::getMethods() const { + Protocol *p = this->retrieveProtocol(); + if (p) { + return p->methods(); + } + return 0; +} + +void Device::setLastSentCommand(int command, std::wstring value){ + d->state = command; + d->stateValue = value; +} + +std::wstring Device::getModel(){ + return d->model; +} + +void Device::setModel(const std::wstring &model){ + if(d->protocol){ + delete(d->protocol); + d->protocol = 0; + } + d->model = model; +} + +std::wstring Device::getName(){ + return d->name; +} + +void Device::setName(const std::wstring &name){ + d->name = name; +} + +std::wstring Device::getParameter(const std::wstring &key){ + ParameterMap::iterator it = d->parameterList.find(key); + if (it == d->parameterList.end()) { + return L""; + } + return d->parameterList[key]; +} + +std::list Device::getParametersForProtocol() const { + return Protocol::getParametersForProtocol(getProtocolName()); +} + +void Device::setParameter(const std::wstring &key, const std::wstring &value){ + d->parameterList[key] = value; + if(d->protocol){ + d->protocol->setParameters(d->parameterList); + } +} + +int Device::getPreferredControllerId(){ + return d->preferredControllerId; +} + +void Device::setPreferredControllerId(int controllerId){ + d->preferredControllerId = controllerId; +} + +std::wstring Device::getProtocolName() const { + return d->protocolName; +} + +void Device::setProtocolName(const std::wstring &protocolName){ + if(d->protocol){ + delete(d->protocol); + d->protocol = 0; + } + d->protocolName = protocolName; +} + +std::wstring Device::getStateValue(){ + return d->stateValue; +} + +int Device::getType(){ + if(d->protocolName == L"group"){ + return TELLSTICK_TYPE_GROUP; + } + else if(d->protocolName == L"scene"){ + return TELLSTICK_TYPE_SCENE; + } + return TELLSTICK_TYPE_DEVICE; +} + +/** +* End Get-/Set +*/ + +int Device::doAction(int action, unsigned char data, Controller *controller) { + Protocol *p = this->retrieveProtocol(); + if(p){ + //Try to determine if we need to call another method due to masking + int methods = p->methods(); + if ((action & methods) == 0) { + //Loop all methods an see if any method masks to this one + for(int i = 1; i <= methods; i<<=1) { + if ((i & methods) == 0) { + continue; + } + if (this->maskUnsupportedMethods(i, action)) { + action = i; + break; + } + } + } + if ((action & methods) == 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } + std::string code = p->getStringForMethod(action, data, controller); + if (code == "") { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } + if (code[0] != 'S' && code[0] != 'T' && code[0] != 'P' && code[0] != 'R') { + //Try autodetect sendtype + TellStick *tellstick = reinterpret_cast(controller); + if (!tellstick) { + return TELLSTICK_ERROR_UNKNOWN; + } + unsigned int maxlength = 80; + if (tellstick->pid() == 0x0c31) { + maxlength = 512; + } + if (code.length() <= maxlength) { + //S is enough + code.insert(0, 1, 'S'); + code.append(1, '+'); + } else { + code = TellStick::createTPacket(code); + } + } + return controller->send(code); + } + return TELLSTICK_ERROR_UNKNOWN; +} + +Protocol* Device::retrieveProtocol() const { + if (d->protocol) { + return d->protocol; + } + + d->protocol = Protocol::getProtocolInstance(d->protocolName); + if(d->protocol){ + d->protocol->setModel(d->model); + d->protocol->setParameters(d->parameterList); + return d->protocol; + } + + return 0; +} + +int Device::maskUnsupportedMethods(int methods, int supportedMethods) { + // Bell -> On + if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) { + methods |= TELLSTICK_TURNON; + } + + // Execute -> On + if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) { + methods |= TELLSTICK_TURNON; + } + + // Up -> Off + if ((methods & TELLSTICK_UP) && !(supportedMethods & TELLSTICK_UP)) { + methods |= TELLSTICK_TURNOFF; + } + + // Down -> On + if ((methods & TELLSTICK_DOWN) && !(supportedMethods & TELLSTICK_DOWN)) { + methods |= TELLSTICK_TURNON; + } + + //Cut of the rest of the unsupported methods we don't have a fallback for + return methods & supportedMethods; +} + +int Device::methodId( const std::string &methodName ) { + if (methodName.compare("turnon") == 0) { + return TELLSTICK_TURNON; + } + if (methodName.compare("turnoff") == 0) { + return TELLSTICK_TURNOFF; + } + if (methodName.compare("bell") == 0) { + return TELLSTICK_BELL; + } + if (methodName.compare("dim") == 0) { + return TELLSTICK_DIM; + } + if (methodName.compare("execute") == 0) { + return TELLSTICK_EXECUTE; + } + if (methodName.compare("up") == 0) { + return TELLSTICK_UP; + } + if (methodName.compare("down") == 0) { + return TELLSTICK_DOWN; + } + if (methodName.compare("stop") == 0) { + return TELLSTICK_STOP; + } + return 0; +} diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 75037d1a..5efb8e06 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -1,45 +1,45 @@ #ifndef DEVICE_H -#define DEVICE_H - -#include "Controller.h" -#include "Mutex.h" -#include "Protocol.h" -#include -#include - -class Device : public TelldusCore::Mutex -{ -public: - Device(int id); - ~Device(void); - - int doAction(int action, unsigned char data, Controller *controller); - std::wstring getStateValue(); - int getLastSentCommand(int methodsSupported); - int getMethods() const; - std::wstring getModel(); - void setModel(const std::wstring &model); - std::wstring getName(); - void setName(const std::wstring &name); - std::wstring getParameter(const std::wstring &key); - std::list getParametersForProtocol() const; - void setParameter(const std::wstring &key, const std::wstring &value); - int getPreferredControllerId(); - void setPreferredControllerId(int controllerId); - std::wstring getProtocolName() const; - void setProtocolName(const std::wstring &name); - void setStateValue(int stateValue); - void setLastSentCommand(int command, std::wstring value); - int getType(); - - static int maskUnsupportedMethods(int methods, int supportedMethods); - static int methodId( const std::string &methodName ); - -private: - Protocol *retrieveProtocol() const; - - class PrivateData; - PrivateData *d; -}; - +#define DEVICE_H + +#include "Controller.h" +#include "Mutex.h" +#include "Protocol.h" +#include +#include + +class Device : public TelldusCore::Mutex +{ +public: + Device(int id); + ~Device(void); + + int doAction(int action, unsigned char data, Controller *controller); + std::wstring getStateValue(); + int getLastSentCommand(int methodsSupported); + int getMethods() const; + std::wstring getModel(); + void setModel(const std::wstring &model); + std::wstring getName(); + void setName(const std::wstring &name); + std::wstring getParameter(const std::wstring &key); + std::list getParametersForProtocol() const; + void setParameter(const std::wstring &key, const std::wstring &value); + int getPreferredControllerId(); + void setPreferredControllerId(int controllerId); + std::wstring getProtocolName() const; + void setProtocolName(const std::wstring &name); + void setStateValue(int stateValue); + void setLastSentCommand(int command, std::wstring value); + int getType(); + + static int maskUnsupportedMethods(int methods, int supportedMethods); + static int methodId( const std::string &methodName ); + +private: + Protocol *retrieveProtocol() const; + + class PrivateData; + PrivateData *d; +}; + #endif //DEVICE_H diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 701f681c..3c8753e9 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,783 +1,783 @@ -#include "DeviceManager.h" -#include "ControllerMessage.h" -#include "Mutex.h" -#include "Sensor.h" -#include "Settings.h" -#include "Strings.h" -#include "Message.h" -#include "Log.h" - -#include -#include -#include -#include - -typedef std::map DeviceMap; - -class DeviceManager::PrivateData { -public: - DeviceMap devices; - std::list sensorList; - Settings set; - TelldusCore::Mutex lock; - ControllerManager *controllerManager; - TelldusCore::EventRef deviceUpdateEvent; -}; - -DeviceManager::DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent){ - d = new PrivateData; - d->controllerManager = controllerManager; - d->deviceUpdateEvent = deviceUpdateEvent; - fillDevices(); -} - -DeviceManager::~DeviceManager(void) { - { - TelldusCore::MutexLocker deviceListLocker(&d->lock); - for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { - {TelldusCore::MutexLocker deviceLocker(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere - delete(it->second); - } - for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { - {TelldusCore::MutexLocker sensorLocker(*it);} //aquire lock, and release it, just to see that the device it's not in use anywhere - delete(*it); - } - } - delete d; -} - -void DeviceManager::fillDevices(){ - int numberOfDevices = d->set.getNumberOfNodes(Settings::Device); - TelldusCore::MutexLocker deviceListLocker(&d->lock); - - for (int i = 0; i < numberOfDevices; ++i) { - int id = d->set.getNodeId(Settings::Device, i); - d->devices[id] = new Device(id); - d->devices[id]->setName(d->set.getName(Settings::Device, id)); - d->devices[id]->setModel(d->set.getModel(id)); - d->devices[id]->setProtocolName(d->set.getProtocol(id)); - d->devices[id]->setPreferredControllerId(d->set.getPreferredControllerId(id)); - d->devices[id]->setLastSentCommand(d->set.getDeviceState(id), d->set.getDeviceStateValue(id)); - d->devices[id]->setParameter(L"house", d->set.getDeviceParameter(id, L"house")); - d->devices[id]->setParameter(L"unit", d->set.getDeviceParameter(id, L"unit")); - d->devices[id]->setParameter(L"code", d->set.getDeviceParameter(id, L"code")); - d->devices[id]->setParameter(L"units", d->set.getDeviceParameter(id, L"units")); - d->devices[id]->setParameter(L"fade", d->set.getDeviceParameter(id, L"fade")); - d->devices[id]->setParameter(L"system", d->set.getDeviceParameter(id, L"system")); - d->devices[id]->setParameter(L"devices", d->set.getDeviceParameter(id, L"devices")); - } -} - -int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - return it->second->getLastSentCommand(methodsSupported); - } - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; -} - -int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value) -{ - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - d->set.setDeviceState(deviceId, command,value); - it->second->setLastSentCommand(command, value); - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - return TELLSTICK_SUCCESS; -} - -std::wstring DeviceManager::getDeviceStateValue(int deviceId){ - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return L"UNKNOWN"; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - return it->second->getStateValue(); - } - return L"UNKNOWN"; -} - -int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported) { - return Device::maskUnsupportedMethods(DeviceManager::getDeviceMethods(deviceId), methodsSupported); -} - -int DeviceManager::getDeviceMethods(int deviceId) { - std::set duplicateDeviceIds; - return DeviceManager::getDeviceMethods(deviceId, duplicateDeviceIds); -} - -int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDeviceIds){ - int type = 0; - int methods = 0; - std::wstring deviceIds; - std::wstring protocol; - - { - //devices locked - TelldusCore::MutexLocker deviceListLocker(&d->lock); - - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - - { - TelldusCore::MutexLocker deviceLocker(it->second); - type = it->second->getType(); - methods = it->second->getMethods(); - deviceIds = it->second->getParameter(L"devices"); - protocol = it->second->getProtocolName(); - } - } - } - if(type == 0){ - return 0; - } - if(type == TELLSTICK_TYPE_GROUP){ - - //get all methods that some device in the groups supports - std::wstring deviceIdBuffer; - std::wstringstream devicesstream(deviceIds); - methods = 0; - - duplicateDeviceIds.insert(deviceId); - - while(std::getline(devicesstream, deviceIdBuffer, L',')){ - int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); - if(duplicateDeviceIds.count(deviceIdInGroup) == 1){ - //action for device already executed, or will execute, do nothing to avoid infinite loop - continue; - } - - duplicateDeviceIds.insert(deviceIdInGroup); - - int deviceMethods = getDeviceMethods(deviceIdInGroup, duplicateDeviceIds); - if(deviceMethods > 0){ - methods |= deviceMethods; - } - } - } - return methods; -} - -std::wstring DeviceManager::getDeviceModel(int deviceId){ - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return L"UNKNOWN"; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - return it->second->getModel(); - } - return L"UNKNOWN"; -} - -int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) -{ - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - int ret = d->set.setModel(deviceId, model); - if (ret != TELLSTICK_SUCCESS) { - return ret; - } - it->second->setModel(model); - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - return TELLSTICK_SUCCESS; -} - -std::wstring DeviceManager::getDeviceName(int deviceId){ - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return L"UNKNOWN"; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - return it->second->getName(); - } - return L"UNKNOWN"; -} - -int DeviceManager::setDeviceName(int deviceId, const std::wstring &name){ - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - int ret = d->set.setName(Settings::Device, deviceId, name); - if (ret != TELLSTICK_SUCCESS) { - return ret; - } - it->second->setName(name); - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - return TELLSTICK_SUCCESS; -} - -std::wstring DeviceManager::getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defaultValue){ - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return defaultValue; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()){ - TelldusCore::MutexLocker deviceLocker(it->second); - std::wstring returnString = it->second->getParameter(name); - if(returnString != L""){ - return returnString; - } - } - return defaultValue; -} - -int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value) -{ - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - int ret = d->set.setDeviceParameter(deviceId, name, value); - if (ret != TELLSTICK_SUCCESS) { - return ret; - } - it->second->setParameter(name, value); - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - return TELLSTICK_SUCCESS; -} - -std::wstring DeviceManager::getDeviceProtocol(int deviceId){ - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return L"UNKNOWN"; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - return it->second->getProtocolName(); - } - return L"UNKNOWN"; -} - -int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) -{ - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - int ret = d->set.setProtocol(deviceId, protocol); - if (ret != TELLSTICK_SUCCESS) { - return ret; - } - it->second->setProtocolName(protocol); - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - return TELLSTICK_SUCCESS; -} - -int DeviceManager::getNumberOfDevices(){ - TelldusCore::MutexLocker deviceListLocker(&d->lock); - return (int)d->devices.size(); -} - -int DeviceManager::addDevice(){ - - int id = d->set.addNode(Settings::Device); - if(id < 0){ - return id; - } - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - d->devices[id] = new Device(id); - if(!d->devices[id]){ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - return id; -} - -int DeviceManager::getDeviceId(int deviceIndex) { - return d->set.getNodeId(Settings::Device, deviceIndex); -} - -int DeviceManager::getDeviceType(int deviceId){ - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - return it->second->getType(); - } - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; -} - -int DeviceManager::getPreferredControllerId(int deviceId){ - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - TelldusCore::MutexLocker deviceLocker(it->second); - return it->second->getPreferredControllerId(); - } - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; -} - -void DeviceManager::connectTellStickController(int vid, int pid, const std::string &serial){ - d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, true); -} - -void DeviceManager::disconnectTellStickController(int vid, int pid, const std::string &serial){ - d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, false); -} - -int DeviceManager::doAction(int deviceId, int action, unsigned char data){ - Device *device = 0; - //On the stack and will be released if we have a device lock. - std::auto_ptr deviceLocker(0); - { - //devicelist locked - TelldusCore::MutexLocker deviceListLocker(&d->lock); - - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it == d->devices.end()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found - } - //device locked - deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); - device = it->second; - } //devicelist unlocked - - int retval = TELLSTICK_ERROR_UNKNOWN; - - if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE){ - std::wstring devices = device->getParameter(L"devices"); - deviceLocker = std::auto_ptr(0); - std::set *duplicateDeviceIds = new std::set; - retval = doGroupAction(devices, action, data, device->getType(), deviceId, duplicateDeviceIds); - delete duplicateDeviceIds; - - { - //reaquire device lock, make sure it still exists - //devicelist locked - TelldusCore::MutexLocker deviceListLocker(&d->lock); - - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it == d->devices.end()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found - } - //device locked - deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); - device = it->second; - } //devicelist unlocked - } - else{ - Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - if(!controller){ - Log::warning("Trying to execute action, but no controller found. Rescanning USB ports"); - //no controller found, scan for one, and retry once - d->controllerManager->loadControllers(); - controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - } - - if(controller){ - retval = device->doAction(action, data, controller); - if(retval == TELLSTICK_ERROR_BROKEN_PIPE){ - Log::warning("Error in communication with TellStick when executing action. Resetting USB"); - d->controllerManager->resetController(controller); - } - if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){ - Log::warning("Rescanning USB ports"); - d->controllerManager->loadControllers(); - controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - if(!controller){ - Log::error("No contoller (TellStick) found, even after reset. Giving up."); - return TELLSTICK_ERROR_NOT_FOUND; - } - retval = device->doAction(action, data, controller); //retry one more time - } - } else { - Log::error("No contoller (TellStick) found after one retry. Giving up."); - return TELLSTICK_ERROR_NOT_FOUND; - } - } - if(retval == TELLSTICK_SUCCESS && device->getType() != TELLSTICK_TYPE_SCENE && device->getMethods() & action) { - //if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state - std::wstring datastring = TelldusCore::charUnsignedToWstring(data); - if (this->triggerDeviceStateChange(deviceId, action, datastring)) { - device->setLastSentCommand(action, datastring); - d->set.setDeviceState(deviceId, action, datastring); - } - } - return retval; -} - -int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId, std::set *duplicateDeviceIds){ - int retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - std::wstring singledevice; - std::wstringstream devicesstream(devices); - - duplicateDeviceIds->insert(groupDeviceId); - - while(std::getline(devicesstream, singledevice, L',')){ - - int deviceId = TelldusCore::wideToInteger(singledevice); - - if(duplicateDeviceIds->count(deviceId) == 1){ - //action for device already executed, or will execute, do nothing to avoid infinite loop - continue; - } - - duplicateDeviceIds->insert(deviceId); - - int deviceReturnValue = TELLSTICK_SUCCESS; - - if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ - deviceReturnValue = executeScene(singledevice, groupDeviceId); - } - else if(type == TELLSTICK_TYPE_GROUP){ - if(deviceId != 0){ - int childType = DeviceManager::getDeviceType(deviceId); - if(childType == TELLSTICK_TYPE_DEVICE){ - deviceReturnValue = doAction(deviceId, action, data); - } - else if(childType == TELLSTICK_TYPE_SCENE){ - deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes infinite loops-safe - } - else{ - //group (in group) - deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); - - if(deviceReturnValue == TELLSTICK_SUCCESS) { - std::wstring datastring = TelldusCore::charUnsignedToWstring(data); - if (this->triggerDeviceStateChange(deviceId, action, datastring)) { - DeviceManager::setDeviceLastSentCommand(deviceId, action, datastring); - d->set.setDeviceState(deviceId, action, datastring); - } - } - } - } - else{ - deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; //Probably incorrectly formatted parameter - } - } - - if(deviceReturnValue != TELLSTICK_ERROR_METHOD_NOT_SUPPORTED){ - //if error(s), return the last error, but still try to continue the action with the other devices - //if the error is a method not supported we igore is since there might be others supporting it - //If no devices support the method the default value will be returned (method not supported) - retval = deviceReturnValue; - } - - } - return retval; -} - -int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId){ - - std::wstringstream devicestream(singledevice); - - const int deviceParameterLength = 3; - std::wstring deviceParts[deviceParameterLength] = {L"", L"", L""}; - std::wstring devicePart = L""; - int i = 0; - while(std::getline(devicestream, devicePart, L':') && i < deviceParameterLength){ - deviceParts[i] = devicePart; - i++; - } - - if(deviceParts[0] == L"" || deviceParts[1] == L""){ - return TELLSTICK_ERROR_UNKNOWN; //malformed or missing parameter - } - - int deviceId = TelldusCore::wideToInteger(deviceParts[0]); - if(deviceId == groupDeviceId){ - return TELLSTICK_ERROR_UNKNOWN; //the scene itself has been added to its devices, avoid infinite loop - } - int method = Device::methodId(TelldusCore::wideToString(deviceParts[1])); //support methodparts both in the form of integers (e.g. TELLSTICK_TURNON) or text (e.g. "turnon") - if(method == 0){ - method = TelldusCore::wideToInteger(deviceParts[1]); - } - unsigned char devicedata = 0; - if(deviceParts[2] != L""){ - devicedata = TelldusCore::wideToInteger(deviceParts[2]); - } - - if(deviceId > 0 && method > 0){ //check for format error in parameter "devices" - return doAction(deviceId, method, devicedata); - } - - return TELLSTICK_ERROR_UNKNOWN; -} - -int DeviceManager::removeDevice(int deviceId){ - - Device *device = 0; - { - int ret = d->set.removeNode(Settings::Device, deviceId); //remove from register/settings - if (ret != TELLSTICK_SUCCESS) { - return ret; - } - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()) { - device = it->second; - d->devices.erase(it); //remove from list, keep reference - } - else{ - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - } - {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else - delete device; - - return TELLSTICK_SUCCESS; -} - -std::wstring DeviceManager::getSensors() const { - TelldusCore::MutexLocker sensorListLocker(&d->lock); - - TelldusCore::Message msg; - - msg.addArgument((int)d->sensorList.size()); - - for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { - TelldusCore::MutexLocker sensorLocker(*it); - msg.addArgument((*it)->protocol()); - msg.addArgument((*it)->model()); - msg.addArgument((*it)->id()); - msg.addArgument((*it)->dataTypes()); - } - - return msg; -} - -std::wstring DeviceManager::getSensorValue(const std::wstring &protocol, const std::wstring &model, int id, int dataType) const { - TelldusCore::MutexLocker sensorListLocker(&d->lock); - Sensor *sensor = 0; - for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { - TelldusCore::MutexLocker sensorLocker(*it); - if (!TelldusCore::comparei((*it)->protocol(), protocol)) { - continue; - } - if (!TelldusCore::comparei((*it)->model(), model)) { - continue; - } - if ((*it)->id() != id) { - continue; - } - sensor = *it; - break; - } - - if (!sensor) { - return L""; - } - TelldusCore::MutexLocker sensorLocker(sensor); - TelldusCore::Message msg; - std::string value = sensor->value(dataType); - if (value.length() > 0) { - msg.addArgument(TelldusCore::charToWstring(value.c_str())); - msg.addArgument((int)sensor->timestamp()); - } - return msg; -} - - -void DeviceManager::handleControllerMessage(const ControllerEventData &eventData) { - //Trigger raw-event - EventUpdateData *eventUpdateData = new EventUpdateData(); - eventUpdateData->messageType = L"TDRawDeviceEvent"; - eventUpdateData->controllerId = eventData.controllerId; - eventUpdateData->eventValue = TelldusCore::charToWstring(eventData.msg.c_str()); - d->deviceUpdateEvent->signal(eventUpdateData); - - ControllerMessage msg(eventData.msg); - if (msg.msgClass().compare("sensor") == 0) { - handleSensorMessage(msg); - return; - } - - TelldusCore::MutexLocker deviceListLocker(&d->lock); - for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { - TelldusCore::MutexLocker deviceLocker(it->second); - if (!TelldusCore::comparei(it->second->getProtocolName(), msg.protocol())) { - continue; - } - if (! (it->second->getMethods() & msg.method())) { - continue; - } - - std::list parameters = it->second->getParametersForProtocol(); - bool thisDevice = true; - for (std::list::iterator paramIt = parameters.begin(); paramIt != parameters.end(); ++paramIt){ - if(!TelldusCore::comparei(it->second->getParameter(TelldusCore::charToWstring((*paramIt).c_str())), TelldusCore::charToWstring(msg.getParameter(*paramIt).c_str()))){ - thisDevice = false; - break; - } - } - - if(!thisDevice){ - continue; - } - - if (this->triggerDeviceStateChange(it->first, msg.method(), L"")) { - d->set.setDeviceState(it->first, msg.method(), L""); - it->second->setLastSentCommand(msg.method(), L""); - } - } -} - -void DeviceManager::handleSensorMessage(const ControllerMessage &msg) { - TelldusCore::MutexLocker sensorListLocker(&d->lock); - Sensor *sensor = 0; - for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { - TelldusCore::MutexLocker sensorLocker(*it); - if (!TelldusCore::comparei((*it)->protocol(), msg.protocol())) { - continue; - } - if (!TelldusCore::comparei((*it)->model(), msg.model())) { - continue; - } - if ((*it)->id() != msg.getIntParameter("id")) { - continue; - } - sensor = *it; - break; - } - - if (!sensor) { - sensor = new Sensor(msg.protocol(), msg.model(), msg.getIntParameter("id")); - d->sensorList.push_back(sensor); - } - TelldusCore::MutexLocker sensorLocker(sensor); - - time_t t = time(NULL); - - setSensorValueAndSignal("temp", TELLSTICK_TEMPERATURE, sensor, msg, t); - setSensorValueAndSignal("humidity", TELLSTICK_HUMIDITY, sensor, msg, t); -} - -void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const { - if (!msg.hasParameter(dataType)) { - return; - } - sensor->setValue(dataTypeId, msg.getParameter(dataType), timestamp); - - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDSensorEvent"; - eventData->protocol = sensor->protocol(); - eventData->model = sensor->model(); - eventData->sensorId = sensor->id(); - eventData->dataType = dataTypeId; - eventData->value = TelldusCore::charToWstring(sensor->value(dataTypeId).c_str()); - eventData->timestamp = (int)timestamp; - d->deviceUpdateEvent->signal(eventData); -} - -int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){ - - Controller *controller = d->controllerManager->getBestControllerById(-1); - - if(!controller){ - //no controller found, scan for one, and retry once - d->controllerManager->loadControllers(); - controller = d->controllerManager->getBestControllerById(-1); - } - - int retval = TELLSTICK_ERROR_UNKNOWN; - if(controller){ - retval = controller->send(TelldusCore::wideToString(command)); - if(retval == TELLSTICK_ERROR_BROKEN_PIPE){ - d->controllerManager->resetController(controller); - } - if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){ - d->controllerManager->loadControllers(); - controller = d->controllerManager->getBestControllerById(-1); - if(!controller){ - return TELLSTICK_ERROR_NOT_FOUND; - } - retval = controller->send(TelldusCore::wideToString(command)); //retry one more time - } - return retval; - } else { - return TELLSTICK_ERROR_NOT_FOUND; - } -} - -bool DeviceManager::triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { - if ( intDeviceState == TELLSTICK_BELL || intDeviceState == TELLSTICK_LEARN || intDeviceState == TELLSTICK_EXECUTE) { - return false; - } - - EventUpdateData *eventData = new EventUpdateData(); - eventData->messageType = L"TDDeviceEvent"; - eventData->eventState = intDeviceState; - eventData->deviceId = deviceId; - eventData->eventValue = strDeviceStateValue; - d->deviceUpdateEvent->signal(eventData); - return true; -} +#include "DeviceManager.h" +#include "ControllerMessage.h" +#include "Mutex.h" +#include "Sensor.h" +#include "Settings.h" +#include "Strings.h" +#include "Message.h" +#include "Log.h" + +#include +#include +#include +#include + +typedef std::map DeviceMap; + +class DeviceManager::PrivateData { +public: + DeviceMap devices; + std::list sensorList; + Settings set; + TelldusCore::Mutex lock; + ControllerManager *controllerManager; + TelldusCore::EventRef deviceUpdateEvent; +}; + +DeviceManager::DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent){ + d = new PrivateData; + d->controllerManager = controllerManager; + d->deviceUpdateEvent = deviceUpdateEvent; + fillDevices(); +} + +DeviceManager::~DeviceManager(void) { + { + TelldusCore::MutexLocker deviceListLocker(&d->lock); + for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { + {TelldusCore::MutexLocker deviceLocker(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere + delete(it->second); + } + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + {TelldusCore::MutexLocker sensorLocker(*it);} //aquire lock, and release it, just to see that the device it's not in use anywhere + delete(*it); + } + } + delete d; +} + +void DeviceManager::fillDevices(){ + int numberOfDevices = d->set.getNumberOfNodes(Settings::Device); + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + for (int i = 0; i < numberOfDevices; ++i) { + int id = d->set.getNodeId(Settings::Device, i); + d->devices[id] = new Device(id); + d->devices[id]->setName(d->set.getName(Settings::Device, id)); + d->devices[id]->setModel(d->set.getModel(id)); + d->devices[id]->setProtocolName(d->set.getProtocol(id)); + d->devices[id]->setPreferredControllerId(d->set.getPreferredControllerId(id)); + d->devices[id]->setLastSentCommand(d->set.getDeviceState(id), d->set.getDeviceStateValue(id)); + d->devices[id]->setParameter(L"house", d->set.getDeviceParameter(id, L"house")); + d->devices[id]->setParameter(L"unit", d->set.getDeviceParameter(id, L"unit")); + d->devices[id]->setParameter(L"code", d->set.getDeviceParameter(id, L"code")); + d->devices[id]->setParameter(L"units", d->set.getDeviceParameter(id, L"units")); + d->devices[id]->setParameter(L"fade", d->set.getDeviceParameter(id, L"fade")); + d->devices[id]->setParameter(L"system", d->set.getDeviceParameter(id, L"system")); + d->devices[id]->setParameter(L"devices", d->set.getDeviceParameter(id, L"devices")); + } +} + +int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getLastSentCommand(methodsSupported); + } + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; +} + +int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value) +{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + d->set.setDeviceState(deviceId, command,value); + it->second->setLastSentCommand(command, value); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + return TELLSTICK_SUCCESS; +} + +std::wstring DeviceManager::getDeviceStateValue(int deviceId){ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getStateValue(); + } + return L"UNKNOWN"; +} + +int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported) { + return Device::maskUnsupportedMethods(DeviceManager::getDeviceMethods(deviceId), methodsSupported); +} + +int DeviceManager::getDeviceMethods(int deviceId) { + std::set duplicateDeviceIds; + return DeviceManager::getDeviceMethods(deviceId, duplicateDeviceIds); +} + +int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDeviceIds){ + int type = 0; + int methods = 0; + std::wstring deviceIds; + std::wstring protocol; + + { + //devices locked + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + + { + TelldusCore::MutexLocker deviceLocker(it->second); + type = it->second->getType(); + methods = it->second->getMethods(); + deviceIds = it->second->getParameter(L"devices"); + protocol = it->second->getProtocolName(); + } + } + } + if(type == 0){ + return 0; + } + if(type == TELLSTICK_TYPE_GROUP){ + + //get all methods that some device in the groups supports + std::wstring deviceIdBuffer; + std::wstringstream devicesstream(deviceIds); + methods = 0; + + duplicateDeviceIds.insert(deviceId); + + while(std::getline(devicesstream, deviceIdBuffer, L',')){ + int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); + if(duplicateDeviceIds.count(deviceIdInGroup) == 1){ + //action for device already executed, or will execute, do nothing to avoid infinite loop + continue; + } + + duplicateDeviceIds.insert(deviceIdInGroup); + + int deviceMethods = getDeviceMethods(deviceIdInGroup, duplicateDeviceIds); + if(deviceMethods > 0){ + methods |= deviceMethods; + } + } + } + return methods; +} + +std::wstring DeviceManager::getDeviceModel(int deviceId){ + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getModel(); + } + return L"UNKNOWN"; +} + +int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) +{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + int ret = d->set.setModel(deviceId, model); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } + it->second->setModel(model); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + return TELLSTICK_SUCCESS; +} + +std::wstring DeviceManager::getDeviceName(int deviceId){ + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getName(); + } + return L"UNKNOWN"; +} + +int DeviceManager::setDeviceName(int deviceId, const std::wstring &name){ + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + int ret = d->set.setName(Settings::Device, deviceId, name); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } + it->second->setName(name); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + return TELLSTICK_SUCCESS; +} + +std::wstring DeviceManager::getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defaultValue){ + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return defaultValue; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()){ + TelldusCore::MutexLocker deviceLocker(it->second); + std::wstring returnString = it->second->getParameter(name); + if(returnString != L""){ + return returnString; + } + } + return defaultValue; +} + +int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value) +{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + int ret = d->set.setDeviceParameter(deviceId, name, value); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } + it->second->setParameter(name, value); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + return TELLSTICK_SUCCESS; +} + +std::wstring DeviceManager::getDeviceProtocol(int deviceId){ + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return L"UNKNOWN"; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getProtocolName(); + } + return L"UNKNOWN"; +} + +int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) +{ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + int ret = d->set.setProtocol(deviceId, protocol); + if (ret != TELLSTICK_SUCCESS) { + return ret; + } + it->second->setProtocolName(protocol); + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + return TELLSTICK_SUCCESS; +} + +int DeviceManager::getNumberOfDevices(){ + TelldusCore::MutexLocker deviceListLocker(&d->lock); + return (int)d->devices.size(); +} + +int DeviceManager::addDevice(){ + + int id = d->set.addNode(Settings::Device); + if(id < 0){ + return id; + } + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + d->devices[id] = new Device(id); + if(!d->devices[id]){ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + return id; +} + +int DeviceManager::getDeviceId(int deviceIndex) { + return d->set.getNodeId(Settings::Device, deviceIndex); +} + +int DeviceManager::getDeviceType(int deviceId){ + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getType(); + } + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; +} + +int DeviceManager::getPreferredControllerId(int deviceId){ + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + TelldusCore::MutexLocker deviceLocker(it->second); + return it->second->getPreferredControllerId(); + } + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; +} + +void DeviceManager::connectTellStickController(int vid, int pid, const std::string &serial){ + d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, true); +} + +void DeviceManager::disconnectTellStickController(int vid, int pid, const std::string &serial){ + d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, false); +} + +int DeviceManager::doAction(int deviceId, int action, unsigned char data){ + Device *device = 0; + //On the stack and will be released if we have a device lock. + std::auto_ptr deviceLocker(0); + { + //devicelist locked + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it == d->devices.end()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found + } + //device locked + deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); + device = it->second; + } //devicelist unlocked + + int retval = TELLSTICK_ERROR_UNKNOWN; + + if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE){ + std::wstring devices = device->getParameter(L"devices"); + deviceLocker = std::auto_ptr(0); + std::set *duplicateDeviceIds = new std::set; + retval = doGroupAction(devices, action, data, device->getType(), deviceId, duplicateDeviceIds); + delete duplicateDeviceIds; + + { + //reaquire device lock, make sure it still exists + //devicelist locked + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it == d->devices.end()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found + } + //device locked + deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); + device = it->second; + } //devicelist unlocked + } + else{ + Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); + if(!controller){ + Log::warning("Trying to execute action, but no controller found. Rescanning USB ports"); + //no controller found, scan for one, and retry once + d->controllerManager->loadControllers(); + controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); + } + + if(controller){ + retval = device->doAction(action, data, controller); + if(retval == TELLSTICK_ERROR_BROKEN_PIPE){ + Log::warning("Error in communication with TellStick when executing action. Resetting USB"); + d->controllerManager->resetController(controller); + } + if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){ + Log::warning("Rescanning USB ports"); + d->controllerManager->loadControllers(); + controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); + if(!controller){ + Log::error("No contoller (TellStick) found, even after reset. Giving up."); + return TELLSTICK_ERROR_NOT_FOUND; + } + retval = device->doAction(action, data, controller); //retry one more time + } + } else { + Log::error("No contoller (TellStick) found after one retry. Giving up."); + return TELLSTICK_ERROR_NOT_FOUND; + } + } + if(retval == TELLSTICK_SUCCESS && device->getType() != TELLSTICK_TYPE_SCENE && device->getMethods() & action) { + //if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state + std::wstring datastring = TelldusCore::charUnsignedToWstring(data); + if (this->triggerDeviceStateChange(deviceId, action, datastring)) { + device->setLastSentCommand(action, datastring); + d->set.setDeviceState(deviceId, action, datastring); + } + } + return retval; +} + +int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId, std::set *duplicateDeviceIds){ + int retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + std::wstring singledevice; + std::wstringstream devicesstream(devices); + + duplicateDeviceIds->insert(groupDeviceId); + + while(std::getline(devicesstream, singledevice, L',')){ + + int deviceId = TelldusCore::wideToInteger(singledevice); + + if(duplicateDeviceIds->count(deviceId) == 1){ + //action for device already executed, or will execute, do nothing to avoid infinite loop + continue; + } + + duplicateDeviceIds->insert(deviceId); + + int deviceReturnValue = TELLSTICK_SUCCESS; + + if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ + deviceReturnValue = executeScene(singledevice, groupDeviceId); + } + else if(type == TELLSTICK_TYPE_GROUP){ + if(deviceId != 0){ + int childType = DeviceManager::getDeviceType(deviceId); + if(childType == TELLSTICK_TYPE_DEVICE){ + deviceReturnValue = doAction(deviceId, action, data); + } + else if(childType == TELLSTICK_TYPE_SCENE){ + deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes infinite loops-safe + } + else{ + //group (in group) + deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); + + if(deviceReturnValue == TELLSTICK_SUCCESS) { + std::wstring datastring = TelldusCore::charUnsignedToWstring(data); + if (this->triggerDeviceStateChange(deviceId, action, datastring)) { + DeviceManager::setDeviceLastSentCommand(deviceId, action, datastring); + d->set.setDeviceState(deviceId, action, datastring); + } + } + } + } + else{ + deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; //Probably incorrectly formatted parameter + } + } + + if(deviceReturnValue != TELLSTICK_ERROR_METHOD_NOT_SUPPORTED){ + //if error(s), return the last error, but still try to continue the action with the other devices + //if the error is a method not supported we igore is since there might be others supporting it + //If no devices support the method the default value will be returned (method not supported) + retval = deviceReturnValue; + } + + } + return retval; +} + +int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId){ + + std::wstringstream devicestream(singledevice); + + const int deviceParameterLength = 3; + std::wstring deviceParts[deviceParameterLength] = {L"", L"", L""}; + std::wstring devicePart = L""; + int i = 0; + while(std::getline(devicestream, devicePart, L':') && i < deviceParameterLength){ + deviceParts[i] = devicePart; + i++; + } + + if(deviceParts[0] == L"" || deviceParts[1] == L""){ + return TELLSTICK_ERROR_UNKNOWN; //malformed or missing parameter + } + + int deviceId = TelldusCore::wideToInteger(deviceParts[0]); + if(deviceId == groupDeviceId){ + return TELLSTICK_ERROR_UNKNOWN; //the scene itself has been added to its devices, avoid infinite loop + } + int method = Device::methodId(TelldusCore::wideToString(deviceParts[1])); //support methodparts both in the form of integers (e.g. TELLSTICK_TURNON) or text (e.g. "turnon") + if(method == 0){ + method = TelldusCore::wideToInteger(deviceParts[1]); + } + unsigned char devicedata = 0; + if(deviceParts[2] != L""){ + devicedata = TelldusCore::wideToInteger(deviceParts[2]); + } + + if(deviceId > 0 && method > 0){ //check for format error in parameter "devices" + return doAction(deviceId, method, devicedata); + } + + return TELLSTICK_ERROR_UNKNOWN; +} + +int DeviceManager::removeDevice(int deviceId){ + + Device *device = 0; + { + int ret = d->set.removeNode(Settings::Device, deviceId); //remove from register/settings + if (ret != TELLSTICK_SUCCESS) { + return ret; + } + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + if (!d->devices.size()) { + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + DeviceMap::iterator it = d->devices.find(deviceId); + if (it != d->devices.end()) { + device = it->second; + d->devices.erase(it); //remove from list, keep reference + } + else{ + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + } + {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else + delete device; + + return TELLSTICK_SUCCESS; +} + +std::wstring DeviceManager::getSensors() const { + TelldusCore::MutexLocker sensorListLocker(&d->lock); + + TelldusCore::Message msg; + + msg.addArgument((int)d->sensorList.size()); + + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + TelldusCore::MutexLocker sensorLocker(*it); + msg.addArgument((*it)->protocol()); + msg.addArgument((*it)->model()); + msg.addArgument((*it)->id()); + msg.addArgument((*it)->dataTypes()); + } + + return msg; +} + +std::wstring DeviceManager::getSensorValue(const std::wstring &protocol, const std::wstring &model, int id, int dataType) const { + TelldusCore::MutexLocker sensorListLocker(&d->lock); + Sensor *sensor = 0; + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + TelldusCore::MutexLocker sensorLocker(*it); + if (!TelldusCore::comparei((*it)->protocol(), protocol)) { + continue; + } + if (!TelldusCore::comparei((*it)->model(), model)) { + continue; + } + if ((*it)->id() != id) { + continue; + } + sensor = *it; + break; + } + + if (!sensor) { + return L""; + } + TelldusCore::MutexLocker sensorLocker(sensor); + TelldusCore::Message msg; + std::string value = sensor->value(dataType); + if (value.length() > 0) { + msg.addArgument(TelldusCore::charToWstring(value.c_str())); + msg.addArgument((int)sensor->timestamp()); + } + return msg; +} + + +void DeviceManager::handleControllerMessage(const ControllerEventData &eventData) { + //Trigger raw-event + EventUpdateData *eventUpdateData = new EventUpdateData(); + eventUpdateData->messageType = L"TDRawDeviceEvent"; + eventUpdateData->controllerId = eventData.controllerId; + eventUpdateData->eventValue = TelldusCore::charToWstring(eventData.msg.c_str()); + d->deviceUpdateEvent->signal(eventUpdateData); + + ControllerMessage msg(eventData.msg); + if (msg.msgClass().compare("sensor") == 0) { + handleSensorMessage(msg); + return; + } + + TelldusCore::MutexLocker deviceListLocker(&d->lock); + for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { + TelldusCore::MutexLocker deviceLocker(it->second); + if (!TelldusCore::comparei(it->second->getProtocolName(), msg.protocol())) { + continue; + } + if (! (it->second->getMethods() & msg.method())) { + continue; + } + + std::list parameters = it->second->getParametersForProtocol(); + bool thisDevice = true; + for (std::list::iterator paramIt = parameters.begin(); paramIt != parameters.end(); ++paramIt){ + if(!TelldusCore::comparei(it->second->getParameter(TelldusCore::charToWstring((*paramIt).c_str())), TelldusCore::charToWstring(msg.getParameter(*paramIt).c_str()))){ + thisDevice = false; + break; + } + } + + if(!thisDevice){ + continue; + } + + if (this->triggerDeviceStateChange(it->first, msg.method(), L"")) { + d->set.setDeviceState(it->first, msg.method(), L""); + it->second->setLastSentCommand(msg.method(), L""); + } + } +} + +void DeviceManager::handleSensorMessage(const ControllerMessage &msg) { + TelldusCore::MutexLocker sensorListLocker(&d->lock); + Sensor *sensor = 0; + for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { + TelldusCore::MutexLocker sensorLocker(*it); + if (!TelldusCore::comparei((*it)->protocol(), msg.protocol())) { + continue; + } + if (!TelldusCore::comparei((*it)->model(), msg.model())) { + continue; + } + if ((*it)->id() != msg.getIntParameter("id")) { + continue; + } + sensor = *it; + break; + } + + if (!sensor) { + sensor = new Sensor(msg.protocol(), msg.model(), msg.getIntParameter("id")); + d->sensorList.push_back(sensor); + } + TelldusCore::MutexLocker sensorLocker(sensor); + + time_t t = time(NULL); + + setSensorValueAndSignal("temp", TELLSTICK_TEMPERATURE, sensor, msg, t); + setSensorValueAndSignal("humidity", TELLSTICK_HUMIDITY, sensor, msg, t); +} + +void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const { + if (!msg.hasParameter(dataType)) { + return; + } + sensor->setValue(dataTypeId, msg.getParameter(dataType), timestamp); + + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDSensorEvent"; + eventData->protocol = sensor->protocol(); + eventData->model = sensor->model(); + eventData->sensorId = sensor->id(); + eventData->dataType = dataTypeId; + eventData->value = TelldusCore::charToWstring(sensor->value(dataTypeId).c_str()); + eventData->timestamp = (int)timestamp; + d->deviceUpdateEvent->signal(eventData); +} + +int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){ + + Controller *controller = d->controllerManager->getBestControllerById(-1); + + if(!controller){ + //no controller found, scan for one, and retry once + d->controllerManager->loadControllers(); + controller = d->controllerManager->getBestControllerById(-1); + } + + int retval = TELLSTICK_ERROR_UNKNOWN; + if(controller){ + retval = controller->send(TelldusCore::wideToString(command)); + if(retval == TELLSTICK_ERROR_BROKEN_PIPE){ + d->controllerManager->resetController(controller); + } + if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){ + d->controllerManager->loadControllers(); + controller = d->controllerManager->getBestControllerById(-1); + if(!controller){ + return TELLSTICK_ERROR_NOT_FOUND; + } + retval = controller->send(TelldusCore::wideToString(command)); //retry one more time + } + return retval; + } else { + return TELLSTICK_ERROR_NOT_FOUND; + } +} + +bool DeviceManager::triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) { + if ( intDeviceState == TELLSTICK_BELL || intDeviceState == TELLSTICK_LEARN || intDeviceState == TELLSTICK_EXECUTE) { + return false; + } + + EventUpdateData *eventData = new EventUpdateData(); + eventData->messageType = L"TDDeviceEvent"; + eventData->eventState = intDeviceState; + eventData->deviceId = deviceId; + eventData->eventValue = strDeviceStateValue; + d->deviceUpdateEvent->signal(eventData); + return true; +} diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 82263bbc..52fef5be 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -1,126 +1,126 @@ -#include "EventUpdateManager.h" - -#include "ConnectionListener.h" -#include "EventHandler.h" -#include "Message.h" -#include "Socket.h" - -#include -#include - -typedef std::list SocketList; - -class EventUpdateManager::PrivateData { -public: - TelldusCore::EventHandler eventHandler; - TelldusCore::EventRef stopEvent, updateEvent, clientConnectEvent; - SocketList clients; - ConnectionListener *eventUpdateClientListener; -}; - -EventUpdateManager::EventUpdateManager() - :Thread() -{ - d = new PrivateData; - d->stopEvent = d->eventHandler.addEvent(); - d->updateEvent = d->eventHandler.addEvent(); - d->clientConnectEvent = d->eventHandler.addEvent(); - d->eventUpdateClientListener = new ConnectionListener(L"TelldusEvents", d->clientConnectEvent); -} - -EventUpdateManager::~EventUpdateManager(void) { - d->stopEvent->signal(); - wait(); - delete d->eventUpdateClientListener; - - for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) { - delete(*it); - } - - delete d; -} - -TelldusCore::EventRef EventUpdateManager::retrieveUpdateEvent(){ - - return d->updateEvent; -} - -void EventUpdateManager::run(){ - - while(!d->stopEvent->isSignaled()){ - if (!d->eventHandler.waitForAny()) { - continue; - } - - if(d->clientConnectEvent->isSignaled()){ - //new client added - TelldusCore::EventDataRef eventData = d->clientConnectEvent->takeSignal(); - ConnectionListenerEventData *data = reinterpret_cast(eventData.get()); - if(data){ - d->clients.push_back(data->socket); - } - } - else if(d->updateEvent->isSignaled()){ - //device event, signal all clients - TelldusCore::EventDataRef eventData = d->updateEvent->takeSignal(); - EventUpdateData *data = reinterpret_cast(eventData.get()); - if(data){ - sendMessageToClients(data); - } - } - } -} - -void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ - - int connected = 0; - for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();){ - if((*it)->isConnected()){ - connected++; - TelldusCore::Message msg; - - if(data->messageType == L"TDDeviceEvent"){ - msg.addArgument("TDDeviceEvent"); - msg.addArgument(data->deviceId); - msg.addArgument(data->eventState); - msg.addArgument(data->eventValue); //string - } - else if(data->messageType == L"TDDeviceChangeEvent"){ - msg.addArgument("TDDeviceChangeEvent"); - msg.addArgument(data->deviceId); - msg.addArgument(data->eventDeviceChanges); - msg.addArgument(data->eventChangeType); - } - else if(data->messageType == L"TDRawDeviceEvent"){ - msg.addArgument("TDRawDeviceEvent"); - msg.addArgument(data->eventValue); //string - msg.addArgument(data->controllerId); - } - else if(data->messageType == L"TDSensorEvent"){ - msg.addArgument("TDSensorEvent"); - msg.addArgument(data->protocol); - msg.addArgument(data->model); - msg.addArgument(data->sensorId); - msg.addArgument(data->dataType); - msg.addArgument(data->value); - msg.addArgument(data->timestamp); - } - else if(data->messageType == L"TDControllerEvent") { - msg.addArgument("TDControllerEvent"); - msg.addArgument(data->controllerId); - msg.addArgument(data->eventState); - msg.addArgument(data->eventChangeType); - msg.addArgument(data->eventValue); - } - - (*it)->write(msg); - - it++; - } - else{ - //connection is dead, remove it - delete *it; - it = d->clients.erase(it); - } - } -} +#include "EventUpdateManager.h" + +#include "ConnectionListener.h" +#include "EventHandler.h" +#include "Message.h" +#include "Socket.h" + +#include +#include + +typedef std::list SocketList; + +class EventUpdateManager::PrivateData { +public: + TelldusCore::EventHandler eventHandler; + TelldusCore::EventRef stopEvent, updateEvent, clientConnectEvent; + SocketList clients; + ConnectionListener *eventUpdateClientListener; +}; + +EventUpdateManager::EventUpdateManager() + :Thread() +{ + d = new PrivateData; + d->stopEvent = d->eventHandler.addEvent(); + d->updateEvent = d->eventHandler.addEvent(); + d->clientConnectEvent = d->eventHandler.addEvent(); + d->eventUpdateClientListener = new ConnectionListener(L"TelldusEvents", d->clientConnectEvent); +} + +EventUpdateManager::~EventUpdateManager(void) { + d->stopEvent->signal(); + wait(); + delete d->eventUpdateClientListener; + + for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) { + delete(*it); + } + + delete d; +} + +TelldusCore::EventRef EventUpdateManager::retrieveUpdateEvent(){ + + return d->updateEvent; +} + +void EventUpdateManager::run(){ + + while(!d->stopEvent->isSignaled()){ + if (!d->eventHandler.waitForAny()) { + continue; + } + + if(d->clientConnectEvent->isSignaled()){ + //new client added + TelldusCore::EventDataRef eventData = d->clientConnectEvent->takeSignal(); + ConnectionListenerEventData *data = reinterpret_cast(eventData.get()); + if(data){ + d->clients.push_back(data->socket); + } + } + else if(d->updateEvent->isSignaled()){ + //device event, signal all clients + TelldusCore::EventDataRef eventData = d->updateEvent->takeSignal(); + EventUpdateData *data = reinterpret_cast(eventData.get()); + if(data){ + sendMessageToClients(data); + } + } + } +} + +void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ + + int connected = 0; + for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();){ + if((*it)->isConnected()){ + connected++; + TelldusCore::Message msg; + + if(data->messageType == L"TDDeviceEvent"){ + msg.addArgument("TDDeviceEvent"); + msg.addArgument(data->deviceId); + msg.addArgument(data->eventState); + msg.addArgument(data->eventValue); //string + } + else if(data->messageType == L"TDDeviceChangeEvent"){ + msg.addArgument("TDDeviceChangeEvent"); + msg.addArgument(data->deviceId); + msg.addArgument(data->eventDeviceChanges); + msg.addArgument(data->eventChangeType); + } + else if(data->messageType == L"TDRawDeviceEvent"){ + msg.addArgument("TDRawDeviceEvent"); + msg.addArgument(data->eventValue); //string + msg.addArgument(data->controllerId); + } + else if(data->messageType == L"TDSensorEvent"){ + msg.addArgument("TDSensorEvent"); + msg.addArgument(data->protocol); + msg.addArgument(data->model); + msg.addArgument(data->sensorId); + msg.addArgument(data->dataType); + msg.addArgument(data->value); + msg.addArgument(data->timestamp); + } + else if(data->messageType == L"TDControllerEvent") { + msg.addArgument("TDControllerEvent"); + msg.addArgument(data->controllerId); + msg.addArgument(data->eventState); + msg.addArgument(data->eventChangeType); + msg.addArgument(data->eventValue); + } + + (*it)->write(msg); + + it++; + } + else{ + //connection is dead, remove it + delete *it; + it = d->clients.erase(it); + } + } +} diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index eef21e59..a4e5cf2f 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -1,181 +1,181 @@ -#include "Log.h" -#include - -#if defined(_LINUX) -#include -#elif defined(_WINDOWS) -#include -#include "Strings.h" -#include "Messages.h" -#endif - -class Log::PrivateData { -public: - PrivateData() : logOutput(Log::System), debug(false) {} - - Log::LogOutput logOutput; - bool debug; - - static Log *instance; -#ifdef _WINDOWS - HANDLE eventSource; -#endif -}; - -Log *Log::PrivateData::instance = 0; - -Log::Log() - :d(new PrivateData) -{ -#if defined(_LINUX) - setlogmask(LOG_UPTO(LOG_INFO)); - openlog("telldusd", LOG_CONS, LOG_USER); -#elif defined(_MACOSX) - d->logOutput = Log::StdOut; -#elif defined(_WINDOWS) - //Add ourselves to the registy - HKEY hRegKey = NULL; - DWORD dwError = 0; - TCHAR filePath[MAX_PATH]; - - std::wstring path(L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\TelldusService"); - dwError = RegCreateKey( HKEY_LOCAL_MACHINE, path.c_str(), &hRegKey ); - - GetModuleFileName( NULL, filePath, MAX_PATH ); - dwError = RegSetValueEx( hRegKey, L"EventMessageFile", 0, - REG_EXPAND_SZ, (PBYTE) filePath, - (DWORD)(wcslen(filePath) + 1) * sizeof TCHAR ); - - DWORD dwTypes = LOG_DEBUG | LOG_NOTICE | LOG_WARNING | LOG_ERR; - dwError = RegSetValueEx( hRegKey, L"TypesSupported", - 0, REG_DWORD, (LPBYTE) &dwTypes, sizeof dwTypes ); - - RegCloseKey(hRegKey); - - d->eventSource = RegisterEventSource(NULL, L"TelldusService"); -#endif -} - -Log::~Log() { -#if defined(_LINUX) - closelog(); -#elif defined(_WINDOWS) - if (d->eventSource != NULL) { - DeregisterEventSource(d->eventSource); - } -#endif - delete d; -} - -void Log::destroy() { - if (PrivateData::instance == 0) { - return; - } - delete PrivateData::instance; - PrivateData::instance = 0; -} - -void Log::debug(const char *fmt, ...) { - Log *log = Log::instance(); - va_list ap; - va_start(ap, fmt); - log->message(Debug, fmt, ap); - va_end(ap); -} - -void Log::notice(const char *fmt, ...) { - Log *log = Log::instance(); - va_list ap; - va_start(ap, fmt); - log->message(Notice, fmt, ap); - va_end(ap); -} - -void Log::warning(const char *fmt, ...) { - Log *log = Log::instance(); - va_list ap; - va_start(ap, fmt); - log->message(Warning, fmt, ap); - va_end(ap); -} - -void Log::error(const char *fmt, ...) { - Log *log = Log::instance(); - va_list ap; - va_start(ap, fmt); - log->message(Error, fmt, ap); - va_end(ap); -} - -void Log::setDebug() { - Log *log = Log::instance(); - log->d->debug = true; - Log::debug("Debug message output enabled"); -} - -void Log::setLogOutput(LogOutput logOutput) { -#ifdef _MACOSX - //Always stdout - return; -#endif - Log *log = Log::instance(); - log->d->logOutput = logOutput; -} - -void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const { - if (logLevel == Debug && d->debug == false) { - return; - } - if (d->logOutput == StdOut) { - FILE *stream = stdout; - if (logLevel == Warning || logLevel == Error) { - stream = stderr; - } - vfprintf(stream, format, ap); - fprintf(stream, "\n"); - fflush(stream); - } else { -#if defined(_LINUX) - switch (logLevel) { - case Debug: - vsyslog(LOG_DEBUG, format, ap); - break; - case Notice: - vsyslog(LOG_NOTICE, format, ap); - break; - case Warning: - vsyslog(LOG_WARNING, format, ap); - break; - case Error: - vsyslog(LOG_ERR, format, ap); - break; - } -#elif defined(_WINDOWS) - LPWSTR pInsertStrings[2] = {NULL, NULL}; - std::wstring str = TelldusCore::charToWstring(TelldusCore::sformatf(format, ap).c_str()); - pInsertStrings[0] = (LPWSTR)str.c_str(); - - switch (logLevel) { - case Debug: - ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); - break; - case Notice: - ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); - break; - case Warning: - ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); - break; - case Error: - ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); - break; - } -#endif - } -} - -Log *Log::instance() { - if (PrivateData::instance == 0) { - PrivateData::instance = new Log(); - } - return PrivateData::instance; -} +#include "Log.h" +#include + +#if defined(_LINUX) +#include +#elif defined(_WINDOWS) +#include +#include "Strings.h" +#include "Messages.h" +#endif + +class Log::PrivateData { +public: + PrivateData() : logOutput(Log::System), debug(false) {} + + Log::LogOutput logOutput; + bool debug; + + static Log *instance; +#ifdef _WINDOWS + HANDLE eventSource; +#endif +}; + +Log *Log::PrivateData::instance = 0; + +Log::Log() + :d(new PrivateData) +{ +#if defined(_LINUX) + setlogmask(LOG_UPTO(LOG_INFO)); + openlog("telldusd", LOG_CONS, LOG_USER); +#elif defined(_MACOSX) + d->logOutput = Log::StdOut; +#elif defined(_WINDOWS) + //Add ourselves to the registy + HKEY hRegKey = NULL; + DWORD dwError = 0; + TCHAR filePath[MAX_PATH]; + + std::wstring path(L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\TelldusService"); + dwError = RegCreateKey( HKEY_LOCAL_MACHINE, path.c_str(), &hRegKey ); + + GetModuleFileName( NULL, filePath, MAX_PATH ); + dwError = RegSetValueEx( hRegKey, L"EventMessageFile", 0, + REG_EXPAND_SZ, (PBYTE) filePath, + (DWORD)(wcslen(filePath) + 1) * sizeof TCHAR ); + + DWORD dwTypes = LOG_DEBUG | LOG_NOTICE | LOG_WARNING | LOG_ERR; + dwError = RegSetValueEx( hRegKey, L"TypesSupported", + 0, REG_DWORD, (LPBYTE) &dwTypes, sizeof dwTypes ); + + RegCloseKey(hRegKey); + + d->eventSource = RegisterEventSource(NULL, L"TelldusService"); +#endif +} + +Log::~Log() { +#if defined(_LINUX) + closelog(); +#elif defined(_WINDOWS) + if (d->eventSource != NULL) { + DeregisterEventSource(d->eventSource); + } +#endif + delete d; +} + +void Log::destroy() { + if (PrivateData::instance == 0) { + return; + } + delete PrivateData::instance; + PrivateData::instance = 0; +} + +void Log::debug(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Debug, fmt, ap); + va_end(ap); +} + +void Log::notice(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Notice, fmt, ap); + va_end(ap); +} + +void Log::warning(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Warning, fmt, ap); + va_end(ap); +} + +void Log::error(const char *fmt, ...) { + Log *log = Log::instance(); + va_list ap; + va_start(ap, fmt); + log->message(Error, fmt, ap); + va_end(ap); +} + +void Log::setDebug() { + Log *log = Log::instance(); + log->d->debug = true; + Log::debug("Debug message output enabled"); +} + +void Log::setLogOutput(LogOutput logOutput) { +#ifdef _MACOSX + //Always stdout + return; +#endif + Log *log = Log::instance(); + log->d->logOutput = logOutput; +} + +void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const { + if (logLevel == Debug && d->debug == false) { + return; + } + if (d->logOutput == StdOut) { + FILE *stream = stdout; + if (logLevel == Warning || logLevel == Error) { + stream = stderr; + } + vfprintf(stream, format, ap); + fprintf(stream, "\n"); + fflush(stream); + } else { +#if defined(_LINUX) + switch (logLevel) { + case Debug: + vsyslog(LOG_DEBUG, format, ap); + break; + case Notice: + vsyslog(LOG_NOTICE, format, ap); + break; + case Warning: + vsyslog(LOG_WARNING, format, ap); + break; + case Error: + vsyslog(LOG_ERR, format, ap); + break; + } +#elif defined(_WINDOWS) + LPWSTR pInsertStrings[2] = {NULL, NULL}; + std::wstring str = TelldusCore::charToWstring(TelldusCore::sformatf(format, ap).c_str()); + pInsertStrings[0] = (LPWSTR)str.c_str(); + + switch (logLevel) { + case Debug: + ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + case Notice: + ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + case Warning: + ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + case Error: + ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + break; + } +#endif + } +} + +Log *Log::instance() { + if (PrivateData::instance == 0) { + PrivateData::instance = new Log(); + } + return PrivateData::instance; +} diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 0a2be23c..67a66e2f 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,263 +1,263 @@ -#include "Protocol.h" -#include "../client/telldus-core.h" - -#include "ControllerMessage.h" -#include "ProtocolBrateck.h" -#include "ProtocolComen.h" -#include "ProtocolEverflourish.h" -#include "ProtocolFineoffset.h" -#include "ProtocolFuhaote.h" -#include "ProtocolGroup.h" -#include "ProtocolHasta.h" -#include "ProtocolIkea.h" -#include "ProtocolMandolyn.h" -#include "ProtocolNexa.h" -#include "ProtocolOregon.h" -#include "ProtocolRisingSun.h" -#include "ProtocolSartano.h" -#include "ProtocolScene.h" -#include "ProtocolSilvanChip.h" -#include "ProtocolUpm.h" -#include "ProtocolWaveman.h" -#include "ProtocolX10.h" -#include "ProtocolYidong.h" - -#include "Strings.h" -#include - -class Protocol::PrivateData { -public: - ParameterMap parameterList; - std::wstring model; -}; - -Protocol::Protocol(){ - - d = new PrivateData; -} - -Protocol::~Protocol(void) { - delete d; -} - -std::wstring Protocol::model() const { - std::wstring strModel = d->model; - //Strip anything after : if it is found - size_t pos = strModel.find(L":"); - if (pos != std::wstring::npos) { - strModel = strModel.substr(0, pos); - } - - return strModel; -} - -void Protocol::setModel(const std::wstring &model){ - d->model = model; -} - -void Protocol::setParameters(ParameterMap ¶meterList){ - d->parameterList = parameterList; -} - -std::wstring Protocol::getStringParameter(const std::wstring &name, const std::wstring &defaultValue) const { - ParameterMap::const_iterator it = d->parameterList.find(name); - if (it == d->parameterList.end()) { - return defaultValue; - } - return it->second; -} - -int Protocol::getIntParameter(const std::wstring &name, int min, int max) const { - std::wstring value = getStringParameter(name, L""); - if (value == L"") { - return min; - } - std::wstringstream st; - st << value; - int intValue = 0; - st >> intValue; - if (intValue < min) { - return min; - } - if (intValue > max) { - return max; - } - return intValue; -} - -bool Protocol::checkBit(int data, int bitno) { - return ((data>>bitno)&0x01); -} - - -Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ - - if(TelldusCore::comparei(protocolname, L"arctech")){ - return new ProtocolNexa(); - - } else if (TelldusCore::comparei(protocolname, L"brateck")) { - return new ProtocolBrateck(); - - } else if (TelldusCore::comparei(protocolname, L"comen")) { - return new ProtocolComen(); - - } else if (TelldusCore::comparei(protocolname, L"everflourish")) { - return new ProtocolEverflourish(); - - } else if (TelldusCore::comparei(protocolname, L"fuhaote")) { - return new ProtocolFuhaote(); - - } else if (TelldusCore::comparei(protocolname, L"hasta")) { - return new ProtocolHasta(); - - } else if (TelldusCore::comparei(protocolname, L"ikea")) { - return new ProtocolIkea(); - - } else if (TelldusCore::comparei(protocolname, L"risingsun")) { - return new ProtocolRisingSun(); - - } else if (TelldusCore::comparei(protocolname, L"sartano")) { - return new ProtocolSartano(); - - } else if (TelldusCore::comparei(protocolname, L"silvanchip")) { - return new ProtocolSilvanChip(); - - } else if (TelldusCore::comparei(protocolname, L"upm")) { - return new ProtocolUpm(); - - } else if (TelldusCore::comparei(protocolname, L"waveman")) { - return new ProtocolWaveman(); - - } else if (TelldusCore::comparei(protocolname, L"x10")) { - return new ProtocolX10(); - - } else if (TelldusCore::comparei(protocolname, L"yidong")) { - return new ProtocolYidong(); - - } else if (TelldusCore::comparei(protocolname, L"group")) { - return new ProtocolGroup(); - } - - else if (TelldusCore::comparei(protocolname, L"scene")) { - return new ProtocolScene(); - } - - return 0; -} - -std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { - std::list parameters; - if(TelldusCore::comparei(protocolName, L"arctech")){ - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"brateck")) { - parameters.push_back("house"); - - } else if (TelldusCore::comparei(protocolName, L"comen")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"everflourish")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { - parameters.push_back("code"); - - } else if (TelldusCore::comparei(protocolName, L"hasta")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"ikea")) { - parameters.push_back("system"); - parameters.push_back("units"); - //parameters.push_back("fade"); - - } else if (TelldusCore::comparei(protocolName, L"risingsun")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"sartano")) { - parameters.push_back("code"); - - } else if (TelldusCore::comparei(protocolName, L"silvanchip")) { - parameters.push_back("house"); - - } else if (TelldusCore::comparei(protocolName, L"upm")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"waveman")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"x10")) { - parameters.push_back("house"); - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"yidong")) { - parameters.push_back("unit"); - - } else if (TelldusCore::comparei(protocolName, L"group")) { - parameters.push_back("devices"); - - } else if (TelldusCore::comparei(protocolName, L"scene")) { - parameters.push_back("devices"); - } - - return parameters; -} - -std::list Protocol::decodeData(const std::string &fullData) { - std::list retval; - std::string decoded = ""; - - ControllerMessage dataMsg(fullData); - if( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) { - decoded = ProtocolNexa::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - decoded = ProtocolWaveman::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - decoded = ProtocolSartano::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) { - decoded = ProtocolEverflourish::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) { - decoded = ProtocolFineoffset::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) { - decoded = ProtocolMandolyn::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) { - decoded = ProtocolOregon::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { - decoded = ProtocolX10::decodeData(dataMsg); - if (decoded != "") { - retval.push_back(decoded); - } - } - - return retval; -} +#include "Protocol.h" +#include "../client/telldus-core.h" + +#include "ControllerMessage.h" +#include "ProtocolBrateck.h" +#include "ProtocolComen.h" +#include "ProtocolEverflourish.h" +#include "ProtocolFineoffset.h" +#include "ProtocolFuhaote.h" +#include "ProtocolGroup.h" +#include "ProtocolHasta.h" +#include "ProtocolIkea.h" +#include "ProtocolMandolyn.h" +#include "ProtocolNexa.h" +#include "ProtocolOregon.h" +#include "ProtocolRisingSun.h" +#include "ProtocolSartano.h" +#include "ProtocolScene.h" +#include "ProtocolSilvanChip.h" +#include "ProtocolUpm.h" +#include "ProtocolWaveman.h" +#include "ProtocolX10.h" +#include "ProtocolYidong.h" + +#include "Strings.h" +#include + +class Protocol::PrivateData { +public: + ParameterMap parameterList; + std::wstring model; +}; + +Protocol::Protocol(){ + + d = new PrivateData; +} + +Protocol::~Protocol(void) { + delete d; +} + +std::wstring Protocol::model() const { + std::wstring strModel = d->model; + //Strip anything after : if it is found + size_t pos = strModel.find(L":"); + if (pos != std::wstring::npos) { + strModel = strModel.substr(0, pos); + } + + return strModel; +} + +void Protocol::setModel(const std::wstring &model){ + d->model = model; +} + +void Protocol::setParameters(ParameterMap ¶meterList){ + d->parameterList = parameterList; +} + +std::wstring Protocol::getStringParameter(const std::wstring &name, const std::wstring &defaultValue) const { + ParameterMap::const_iterator it = d->parameterList.find(name); + if (it == d->parameterList.end()) { + return defaultValue; + } + return it->second; +} + +int Protocol::getIntParameter(const std::wstring &name, int min, int max) const { + std::wstring value = getStringParameter(name, L""); + if (value == L"") { + return min; + } + std::wstringstream st; + st << value; + int intValue = 0; + st >> intValue; + if (intValue < min) { + return min; + } + if (intValue > max) { + return max; + } + return intValue; +} + +bool Protocol::checkBit(int data, int bitno) { + return ((data>>bitno)&0x01); +} + + +Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ + + if(TelldusCore::comparei(protocolname, L"arctech")){ + return new ProtocolNexa(); + + } else if (TelldusCore::comparei(protocolname, L"brateck")) { + return new ProtocolBrateck(); + + } else if (TelldusCore::comparei(protocolname, L"comen")) { + return new ProtocolComen(); + + } else if (TelldusCore::comparei(protocolname, L"everflourish")) { + return new ProtocolEverflourish(); + + } else if (TelldusCore::comparei(protocolname, L"fuhaote")) { + return new ProtocolFuhaote(); + + } else if (TelldusCore::comparei(protocolname, L"hasta")) { + return new ProtocolHasta(); + + } else if (TelldusCore::comparei(protocolname, L"ikea")) { + return new ProtocolIkea(); + + } else if (TelldusCore::comparei(protocolname, L"risingsun")) { + return new ProtocolRisingSun(); + + } else if (TelldusCore::comparei(protocolname, L"sartano")) { + return new ProtocolSartano(); + + } else if (TelldusCore::comparei(protocolname, L"silvanchip")) { + return new ProtocolSilvanChip(); + + } else if (TelldusCore::comparei(protocolname, L"upm")) { + return new ProtocolUpm(); + + } else if (TelldusCore::comparei(protocolname, L"waveman")) { + return new ProtocolWaveman(); + + } else if (TelldusCore::comparei(protocolname, L"x10")) { + return new ProtocolX10(); + + } else if (TelldusCore::comparei(protocolname, L"yidong")) { + return new ProtocolYidong(); + + } else if (TelldusCore::comparei(protocolname, L"group")) { + return new ProtocolGroup(); + } + + else if (TelldusCore::comparei(protocolname, L"scene")) { + return new ProtocolScene(); + } + + return 0; +} + +std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { + std::list parameters; + if(TelldusCore::comparei(protocolName, L"arctech")){ + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"brateck")) { + parameters.push_back("house"); + + } else if (TelldusCore::comparei(protocolName, L"comen")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"everflourish")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"fuhaote")) { + parameters.push_back("code"); + + } else if (TelldusCore::comparei(protocolName, L"hasta")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"ikea")) { + parameters.push_back("system"); + parameters.push_back("units"); + //parameters.push_back("fade"); + + } else if (TelldusCore::comparei(protocolName, L"risingsun")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"sartano")) { + parameters.push_back("code"); + + } else if (TelldusCore::comparei(protocolName, L"silvanchip")) { + parameters.push_back("house"); + + } else if (TelldusCore::comparei(protocolName, L"upm")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"waveman")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"x10")) { + parameters.push_back("house"); + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"yidong")) { + parameters.push_back("unit"); + + } else if (TelldusCore::comparei(protocolName, L"group")) { + parameters.push_back("devices"); + + } else if (TelldusCore::comparei(protocolName, L"scene")) { + parameters.push_back("devices"); + } + + return parameters; +} + +std::list Protocol::decodeData(const std::string &fullData) { + std::list retval; + std::string decoded = ""; + + ControllerMessage dataMsg(fullData); + if( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) { + decoded = ProtocolNexa::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + decoded = ProtocolWaveman::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + decoded = ProtocolSartano::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } + else if(TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) { + decoded = ProtocolEverflourish::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } + else if(TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) { + decoded = ProtocolFineoffset::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } + else if(TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) { + decoded = ProtocolMandolyn::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } + else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) { + decoded = ProtocolOregon::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } + else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { + decoded = ProtocolX10::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } + } + + return retval; +} diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 6168f8d6..bfcce857 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -1,41 +1,41 @@ -#ifndef PROTOCOL_H -#define PROTOCOL_H - -#include -#include -#include -#include "../client/telldus-core.h" - -typedef std::map ParameterMap; - -class Controller; - -class Protocol -{ -public: - Protocol(); - virtual ~Protocol(void); - - static Protocol *getProtocolInstance(const std::wstring &protocolname); - static std::list getParametersForProtocol(const std::wstring &protocolName); - static std::list decodeData(const std::string &fullData); - - virtual int methods() const = 0; - std::wstring model() const; - void setModel(const std::wstring &model); - void setParameters(ParameterMap ¶meterList); - - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0; - -protected: - std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; - int getIntParameter(const std::wstring &name, int min, int max) const; - - static bool checkBit(int data, int bit); - -private: - class PrivateData; - PrivateData *d; -}; - -#endif //PROTOCOL_H +#ifndef PROTOCOL_H +#define PROTOCOL_H + +#include +#include +#include +#include "../client/telldus-core.h" + +typedef std::map ParameterMap; + +class Controller; + +class Protocol +{ +public: + Protocol(); + virtual ~Protocol(void); + + static Protocol *getProtocolInstance(const std::wstring &protocolname); + static std::list getParametersForProtocol(const std::wstring &protocolName); + static std::list decodeData(const std::string &fullData); + + virtual int methods() const = 0; + std::wstring model() const; + void setModel(const std::wstring &model); + void setParameters(ParameterMap ¶meterList); + + virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0; + +protected: + std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; + int getIntParameter(const std::wstring &name, int min, int max) const; + + static bool checkBit(int data, int bit); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //PROTOCOL_H diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 2f01531e..da9e222e 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -1,46 +1,46 @@ -#include "ProtocolBrateck.h" - -int ProtocolBrateck::methods() const { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; -} - -std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) { - const char S = '!'; - const char L = 'V'; - const char B1[] = {L,S,L,S,0}; - const char BX[] = {S,L,L,S,0}; - const char B0[] = {S,L,S,L,0}; - const char BUP[] = {L,S,L,S,S,L,S,L,S,L,S,L,S,L,S,L,S,0}; - const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; - const char BDOWN[] = {S,L,S,L,S,L,S,L,S,L,S,L,L,S,L,S,S,0}; - - std::string strReturn; - std::wstring strHouse = this->getStringParameter(L"house", L""); - if (strHouse == L"") { - return ""; - } - - for( size_t i = 0; i < strHouse.length(); ++i ) { - if (strHouse[i] == '1') { - strReturn.insert(0, B1); - } else if (strHouse[i] == '-') { - strReturn.insert(0, BX); - } else if (strHouse[i] == '0') { - strReturn.insert(0, B0); - } - } - - strReturn.insert(0, "S"); - if (method == TELLSTICK_UP) { - strReturn.append(BUP); - } else if (method == TELLSTICK_DOWN) { - strReturn.append(BDOWN); - } else if (method == TELLSTICK_STOP) { - strReturn.append(BSTOP); - } else { - return ""; - } - strReturn.append("+"); - - return strReturn; -} +#include "ProtocolBrateck.h" + +int ProtocolBrateck::methods() const { + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; +} + +std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) { + const char S = '!'; + const char L = 'V'; + const char B1[] = {L,S,L,S,0}; + const char BX[] = {S,L,L,S,0}; + const char B0[] = {S,L,S,L,0}; + const char BUP[] = {L,S,L,S,S,L,S,L,S,L,S,L,S,L,S,L,S,0}; + const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; + const char BDOWN[] = {S,L,S,L,S,L,S,L,S,L,S,L,L,S,L,S,S,0}; + + std::string strReturn; + std::wstring strHouse = this->getStringParameter(L"house", L""); + if (strHouse == L"") { + return ""; + } + + for( size_t i = 0; i < strHouse.length(); ++i ) { + if (strHouse[i] == '1') { + strReturn.insert(0, B1); + } else if (strHouse[i] == '-') { + strReturn.insert(0, BX); + } else if (strHouse[i] == '0') { + strReturn.insert(0, B0); + } + } + + strReturn.insert(0, "S"); + if (method == TELLSTICK_UP) { + strReturn.append(BUP); + } else if (method == TELLSTICK_DOWN) { + strReturn.append(BDOWN); + } else if (method == TELLSTICK_STOP) { + strReturn.append(BSTOP); + } else { + return ""; + } + strReturn.append("+"); + + return strReturn; +} diff --git a/telldus-core/service/ProtocolComen.cpp b/telldus-core/service/ProtocolComen.cpp index cfaf99df..9fa36c64 100644 --- a/telldus-core/service/ProtocolComen.cpp +++ b/telldus-core/service/ProtocolComen.cpp @@ -1,12 +1,12 @@ -#include "ProtocolComen.h" - -int ProtocolComen::methods() const { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); -} - -std::string ProtocolComen::getStringForMethod(int method, unsigned char level, Controller *) { - int intHouse = getIntParameter(L"house", 1, 33554431); - intHouse <<= 1; //They seem to only accept even codes? - int intCode = getIntParameter(L"unit", 1, 16)-1; - return getStringSelflearningForCode(intHouse, intCode, method, level); -} +#include "ProtocolComen.h" + +int ProtocolComen::methods() const { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); +} + +std::string ProtocolComen::getStringForMethod(int method, unsigned char level, Controller *) { + int intHouse = getIntParameter(L"house", 1, 33554431); + intHouse <<= 1; //They seem to only accept even codes? + int intCode = getIntParameter(L"unit", 1, 16)-1; + return getStringSelflearningForCode(intHouse, intCode, method, level); +} diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index c74326fa..4738bb96 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -1,131 +1,131 @@ -#include "ProtocolEverflourish.h" -#include -#include -#include "ControllerMessage.h" - -int ProtocolEverflourish::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; -} - -std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, Controller *) { - unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383); - unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1; - unsigned char action; - - if (method == TELLSTICK_TURNON) { - action = 15; - } else if (method == TELLSTICK_TURNOFF) { - action = 0; - } else if (method == TELLSTICK_LEARN) { - action = 10; - } else { - return ""; - } - - const char ssss = 85; - const char sssl = 84; // 0 - const char slss = 69; // 1 - - const char bits[2] = {sssl,slss}; - int i, check; - - std::string strCode; - - deviceCode = (deviceCode << 2) | intCode; - - check = calculateChecksum(deviceCode); - - char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss,0}; - strCode.append(preamble); - - for(i=15;i>=0;i--) { - strCode.append(1, bits[(deviceCode>>i)&0x01]); - } - for(i=3;i>=0;i--) { - strCode.append(1, bits[(check>>i)&0x01]); - } - for(i=3;i>=0;i--) { - strCode.append(1, bits[(action>>i)&0x01]); - } - - strCode.append(1, ssss); - strCode.append(1, '+'); - - return strCode; -} - -// The calculation used in this function is provided by Frank Stevenson -unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { - unsigned int bits[16] = { - 0xf ,0xa ,0x7 ,0xe, - 0xf ,0xd ,0x9 ,0x1, - 0x1 ,0x2 ,0x4 ,0x8, - 0x3 ,0x6 ,0xc ,0xb - }; - unsigned int bit = 1; - unsigned int res = 0x5; - int i; - unsigned int lo,hi; - - if ((x&0x3)==3) { - lo = x & 0x00ff; - hi = x & 0xff00; - lo += 4; - if (lo>0x100) { - lo = 0x12; - } - x = lo | hi; - } - - for(i=0;i<16;i++) { - if (x&bit) { - res = res ^ bits[i]; - } - bit = bit << 1; - } - - return res; -} - -std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) -{ - std::string data = dataMsg.getParameter("data"); - unsigned int allData; - unsigned int house = 0; - unsigned int unit = 0; - unsigned int method = 0; - - sscanf(data.c_str(), "%X", &allData); - - house = allData & 0xFFFC00; - house >>= 10; - - unit = allData & 0x300; - unit >>= 8; - unit++; //unit from 1 to 4 - - method = allData & 0xF; - - if(house < 0 || house > 16383 || unit < 1 || unit > 4){ - //not everflourish - return ""; - } - - std::stringstream retString; - retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:"; - if(method == 0){ - retString << "turnoff;"; - } - else if(method == 15){ - retString << "turnon;"; - } - else if(method == 10){ - retString << "learn;"; - } - else { - //not everflourish - return ""; - } - - return retString.str(); +#include "ProtocolEverflourish.h" +#include +#include +#include "ControllerMessage.h" + +int ProtocolEverflourish::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; +} + +std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, Controller *) { + unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383); + unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1; + unsigned char action; + + if (method == TELLSTICK_TURNON) { + action = 15; + } else if (method == TELLSTICK_TURNOFF) { + action = 0; + } else if (method == TELLSTICK_LEARN) { + action = 10; + } else { + return ""; + } + + const char ssss = 85; + const char sssl = 84; // 0 + const char slss = 69; // 1 + + const char bits[2] = {sssl,slss}; + int i, check; + + std::string strCode; + + deviceCode = (deviceCode << 2) | intCode; + + check = calculateChecksum(deviceCode); + + char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss,0}; + strCode.append(preamble); + + for(i=15;i>=0;i--) { + strCode.append(1, bits[(deviceCode>>i)&0x01]); + } + for(i=3;i>=0;i--) { + strCode.append(1, bits[(check>>i)&0x01]); + } + for(i=3;i>=0;i--) { + strCode.append(1, bits[(action>>i)&0x01]); + } + + strCode.append(1, ssss); + strCode.append(1, '+'); + + return strCode; +} + +// The calculation used in this function is provided by Frank Stevenson +unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { + unsigned int bits[16] = { + 0xf ,0xa ,0x7 ,0xe, + 0xf ,0xd ,0x9 ,0x1, + 0x1 ,0x2 ,0x4 ,0x8, + 0x3 ,0x6 ,0xc ,0xb + }; + unsigned int bit = 1; + unsigned int res = 0x5; + int i; + unsigned int lo,hi; + + if ((x&0x3)==3) { + lo = x & 0x00ff; + hi = x & 0xff00; + lo += 4; + if (lo>0x100) { + lo = 0x12; + } + x = lo | hi; + } + + for(i=0;i<16;i++) { + if (x&bit) { + res = res ^ bits[i]; + } + bit = bit << 1; + } + + return res; +} + +std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + unsigned int allData; + unsigned int house = 0; + unsigned int unit = 0; + unsigned int method = 0; + + sscanf(data.c_str(), "%X", &allData); + + house = allData & 0xFFFC00; + house >>= 10; + + unit = allData & 0x300; + unit >>= 8; + unit++; //unit from 1 to 4 + + method = allData & 0xF; + + if(house < 0 || house > 16383 || unit < 1 || unit > 4){ + //not everflourish + return ""; + } + + std::stringstream retString; + retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:"; + if(method == 0){ + retString << "turnoff;"; + } + else if(method == 15){ + retString << "turnon;"; + } + else if(method == 10){ + retString << "learn;"; + } + else { + //not everflourish + return ""; + } + + return retString.str(); } \ No newline at end of file diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index 4ed310d0..3e4b444b 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -1,45 +1,45 @@ -#include "ProtocolFineoffset.h" -#include "Strings.h" -#include -#include -#include - -std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) -{ - std::string data = dataMsg.getParameter("data"); - if (data.length() < 8) { - return ""; - } - - uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); - data = data.substr(0, data.length()-2); - - uint8_t humidity = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); - data = data.substr(0, data.length()-2); - - uint16_t value = (uint16_t)TelldusCore::hexTo64l(data.substr(data.length()-3)); - double temperature = (value & 0x7FF)/10.0; - - value >>= 11; - if (value & 1) { - temperature = -temperature; - } - data = data.substr(0, data.length()-3); - - uint16_t id = (uint16_t)TelldusCore::hexTo64l(data) & 0xFF; - - std::stringstream retString; - retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:"; - - if (humidity <= 100) { - retString << "temperaturehumidity;humidity:" << (int)humidity << ";"; - } else if (humidity == 0xFF) { - retString << "temperature;"; - } else { - return ""; - } - - retString << "temp:" << std::fixed << std::setprecision(1) << temperature << ";"; - - return retString.str(); -} +#include "ProtocolFineoffset.h" +#include "Strings.h" +#include +#include +#include + +std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + if (data.length() < 8) { + return ""; + } + + uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); + data = data.substr(0, data.length()-2); + + uint8_t humidity = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); + data = data.substr(0, data.length()-2); + + uint16_t value = (uint16_t)TelldusCore::hexTo64l(data.substr(data.length()-3)); + double temperature = (value & 0x7FF)/10.0; + + value >>= 11; + if (value & 1) { + temperature = -temperature; + } + data = data.substr(0, data.length()-3); + + uint16_t id = (uint16_t)TelldusCore::hexTo64l(data) & 0xFF; + + std::stringstream retString; + retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:"; + + if (humidity <= 100) { + retString << "temperaturehumidity;humidity:" << (int)humidity << ";"; + } else if (humidity == 0xFF) { + retString << "temperature;"; + } else { + return ""; + } + + retString << "temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index 33fd9177..7baa2a30 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -1,54 +1,54 @@ -#include "ProtocolFuhaote.h" - -int ProtocolFuhaote::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) { - const char S = 19; - const char L = 58; - const char B0[] = {S,L,L,S,0}; - const char B1[] = {L,S,L,S,0}; - const char OFF[] = {S,L,S,L,S,L,L,S,0}; - const char ON[] = {S,L,L,S,S,L,S,L,0}; - - std::string strReturn = "S"; - std::wstring strCode = this->getStringParameter(L"code", L""); - if (strCode == L"") { - return ""; - } - - //House code - for(size_t i = 0; i < 5; ++i) { - if (strCode[i] == '0') { - strReturn.append(B0); - } else if (strCode[i] == '1') { - strReturn.append(B1); - } - } - //Unit code - for(size_t i = 5; i < 10; ++i) { - if (strCode[i] == '0') { - strReturn.append(B0); - } else if (strCode[i] == '1') { - strReturn.append(1, S); - strReturn.append(1, L); - strReturn.append(1, S); - strReturn.append(1, L); - } - } - - if (method == TELLSTICK_TURNON) { - strReturn.append(ON); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(OFF); - } else { - return ""; - } - - strReturn.append(1, S); - strReturn.append("+"); - return strReturn; - -} - +#include "ProtocolFuhaote.h" + +int ProtocolFuhaote::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + +std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) { + const char S = 19; + const char L = 58; + const char B0[] = {S,L,L,S,0}; + const char B1[] = {L,S,L,S,0}; + const char OFF[] = {S,L,S,L,S,L,L,S,0}; + const char ON[] = {S,L,L,S,S,L,S,L,0}; + + std::string strReturn = "S"; + std::wstring strCode = this->getStringParameter(L"code", L""); + if (strCode == L"") { + return ""; + } + + //House code + for(size_t i = 0; i < 5; ++i) { + if (strCode[i] == '0') { + strReturn.append(B0); + } else if (strCode[i] == '1') { + strReturn.append(B1); + } + } + //Unit code + for(size_t i = 5; i < 10; ++i) { + if (strCode[i] == '0') { + strReturn.append(B0); + } else if (strCode[i] == '1') { + strReturn.append(1, S); + strReturn.append(1, L); + strReturn.append(1, S); + strReturn.append(1, L); + } + } + + if (method == TELLSTICK_TURNON) { + strReturn.append(ON); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(OFF); + } else { + return ""; + } + + strReturn.append(1, S); + strReturn.append("+"); + return strReturn; + +} + diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index 6fdb0222..3d553022 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -1,9 +1,9 @@ -#include "ProtocolGroup.h" - -int ProtocolGroup::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; -} - -std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { - return ""; +#include "ProtocolGroup.h" + +int ProtocolGroup::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; +} + +std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) { + return ""; } diff --git a/telldus-core/service/ProtocolGroup.h b/telldus-core/service/ProtocolGroup.h index b75e36e3..c98a14c3 100644 --- a/telldus-core/service/ProtocolGroup.h +++ b/telldus-core/service/ProtocolGroup.h @@ -10,7 +10,7 @@ public: }; -#endif //PROTOCOLGROUP_H - - - +#endif //PROTOCOLGROUP_H + + + diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index d9b41db1..5aaa35e4 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -1,66 +1,66 @@ -#include "ProtocolHasta.h" -#include -#include - -int ProtocolHasta::methods() const { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; -} - -std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Controller *) { - int house = this->getIntParameter(L"house", 1, 65536); - int unit = this->getIntParameter(L"unit", 1, 15); - std::string strReturn; - - std::string preamble; - strReturn.append(1, 190); - strReturn.append(1, 1); - strReturn.append(1, 190); - strReturn.append(1, 1); - strReturn.append(1, 190); - strReturn.append(1, 190); - - strReturn.append(convertByte( (house&0xFF) )); - strReturn.append(convertByte( (house>>8)&0xFF )); - - int byte = unit&0x0F; - - if (method == TELLSTICK_UP) { - byte |= 0x00; - - } else if (method == TELLSTICK_DOWN) { - byte |= 0x10; - - } else if (method == TELLSTICK_STOP) { - byte |= 0x50; - - } else if (method == TELLSTICK_LEARN) { - byte |= 0x40; - - } else { - return ""; - } - strReturn.append(convertByte(byte)); - - strReturn.append(convertByte(0x0)); - strReturn.append(convertByte(0x0)); - - //Remove the last pulse - strReturn.erase(strReturn.end()-1,strReturn.end()); - - return strReturn; -} - -std::string ProtocolHasta::convertByte(unsigned char byte) { - std::string retval; - for(int i = 0; i < 8; ++i) { - if (byte & 1) { - retval.append(1, 33); - retval.append(1, 17); - } else { - retval.append(1, 17); - retval.append(1, 33); - } - byte >>= 1; - } - return retval; +#include "ProtocolHasta.h" +#include +#include + +int ProtocolHasta::methods() const { + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; +} + +std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Controller *) { + int house = this->getIntParameter(L"house", 1, 65536); + int unit = this->getIntParameter(L"unit", 1, 15); + std::string strReturn; + + std::string preamble; + strReturn.append(1, 190); + strReturn.append(1, 1); + strReturn.append(1, 190); + strReturn.append(1, 1); + strReturn.append(1, 190); + strReturn.append(1, 190); + + strReturn.append(convertByte( (house&0xFF) )); + strReturn.append(convertByte( (house>>8)&0xFF )); + + int byte = unit&0x0F; + + if (method == TELLSTICK_UP) { + byte |= 0x00; + + } else if (method == TELLSTICK_DOWN) { + byte |= 0x10; + + } else if (method == TELLSTICK_STOP) { + byte |= 0x50; + + } else if (method == TELLSTICK_LEARN) { + byte |= 0x40; + + } else { + return ""; + } + strReturn.append(convertByte(byte)); + + strReturn.append(convertByte(0x0)); + strReturn.append(convertByte(0x0)); + + //Remove the last pulse + strReturn.erase(strReturn.end()-1,strReturn.end()); + + return strReturn; +} + +std::string ProtocolHasta::convertByte(unsigned char byte) { + std::string retval; + for(int i = 0; i < 8; ++i) { + if (byte & 1) { + retval.append(1, 33); + retval.append(1, 17); + } else { + retval.append(1, 17); + retval.append(1, 33); + } + byte >>= 1; + } + return retval; } \ No newline at end of file diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index d251a4d4..bed01926 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -1,127 +1,127 @@ -#include "ProtocolIkea.h" -#include "Strings.h" - -#include -#include - -int ProtocolIkea::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM; -} - -std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { - int intSystem = this->getIntParameter(L"system", 1, 16)-1; - int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true"); - std::wstring wstrUnits = this->getStringParameter(L"units", L""); - - if (method == TELLSTICK_TURNON) { - level = 255; - } else if (method == TELLSTICK_TURNOFF) { - level = 0; - } else if (method == TELLSTICK_DIM) { - } else { - return ""; - } - - if (wstrUnits == L"") { - return ""; - } - - std::string strUnits(TelldusCore::wideToString(wstrUnits)); - int intUnits = 0; //Start without any units - - char *tempUnits = new char[strUnits.size()+1]; -#ifdef _WINDOWS - strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); -#else - strcpy(tempUnits, strUnits.c_str()); -#endif - - char *strToken = strtok(tempUnits, ","); - do { - int intUnit = atoi(strToken); - if (intUnit == 10) { - intUnit = 0; - } - intUnits = intUnits | ( 1<<(9-intUnit) ); - } while ( (strToken = strtok(NULL, ",")) != NULL ); - - delete[] tempUnits; - - std::string strReturn = "STTTTTTª"; //Startcode, always like this; - - std::string strChannels = ""; - int intCode = (intSystem << 10) | intUnits; - int checksum1 = 0; - int checksum2 = 0; - for (int i = 13; i >= 0; --i) { - if ((intCode>>i) & 1) { - strChannels.append("TT"); - if (i % 2 == 0) - checksum2++; - else - checksum1++; - } else { - strChannels.append("ª"); - } - } - strReturn.append(strChannels); //System + Units - - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum - - int intLevel = 0; - if (level <= 12) { - intLevel = 10; // Level 10 is actually off - } else if (level <= 37) { - intLevel = 1; - } else if (level <= 62) { - intLevel = 2; - } else if (level <= 87) { - intLevel = 3; - } else if (level <= 112) { - intLevel = 4; - } else if (level <= 137) { - intLevel = 5; - } else if (level <= 162) { - intLevel = 6; - } else if (level <= 187) { - intLevel = 7; - } else if (level <= 212) { - intLevel = 8; - } else if (level <= 237) { - intLevel = 9; - } else { - intLevel = 0; // Level 0 is actually full on - } - - int intFade = 0; - if (intFadeStyle == 1) { - intFade = 11 << 4; //Smooth - } else { - intFade = 1 << 4; //Instant - } - - intCode = intLevel | intFade; //Concat level and fade - - checksum1 = 0; - checksum2 = 0; - for (int i = 0; i < 6; ++i) { - if ((intCode>>i) & 1) { - strReturn.append("TT"); - if (i % 2 == 0) - checksum1++; - else - checksum2++; - } else { - strReturn.append("ª"); - } - } - - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum - - strReturn.append("+"); - - return strReturn; - -} +#include "ProtocolIkea.h" +#include "Strings.h" + +#include +#include + +int ProtocolIkea::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM; +} + +std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { + int intSystem = this->getIntParameter(L"system", 1, 16)-1; + int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true"); + std::wstring wstrUnits = this->getStringParameter(L"units", L""); + + if (method == TELLSTICK_TURNON) { + level = 255; + } else if (method == TELLSTICK_TURNOFF) { + level = 0; + } else if (method == TELLSTICK_DIM) { + } else { + return ""; + } + + if (wstrUnits == L"") { + return ""; + } + + std::string strUnits(TelldusCore::wideToString(wstrUnits)); + int intUnits = 0; //Start without any units + + char *tempUnits = new char[strUnits.size()+1]; +#ifdef _WINDOWS + strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); +#else + strcpy(tempUnits, strUnits.c_str()); +#endif + + char *strToken = strtok(tempUnits, ","); + do { + int intUnit = atoi(strToken); + if (intUnit == 10) { + intUnit = 0; + } + intUnits = intUnits | ( 1<<(9-intUnit) ); + } while ( (strToken = strtok(NULL, ",")) != NULL ); + + delete[] tempUnits; + + std::string strReturn = "STTTTTTª"; //Startcode, always like this; + + std::string strChannels = ""; + int intCode = (intSystem << 10) | intUnits; + int checksum1 = 0; + int checksum2 = 0; + for (int i = 13; i >= 0; --i) { + if ((intCode>>i) & 1) { + strChannels.append("TT"); + if (i % 2 == 0) + checksum2++; + else + checksum1++; + } else { + strChannels.append("ª"); + } + } + strReturn.append(strChannels); //System + Units + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + int intLevel = 0; + if (level <= 12) { + intLevel = 10; // Level 10 is actually off + } else if (level <= 37) { + intLevel = 1; + } else if (level <= 62) { + intLevel = 2; + } else if (level <= 87) { + intLevel = 3; + } else if (level <= 112) { + intLevel = 4; + } else if (level <= 137) { + intLevel = 5; + } else if (level <= 162) { + intLevel = 6; + } else if (level <= 187) { + intLevel = 7; + } else if (level <= 212) { + intLevel = 8; + } else if (level <= 237) { + intLevel = 9; + } else { + intLevel = 0; // Level 0 is actually full on + } + + int intFade = 0; + if (intFadeStyle == 1) { + intFade = 11 << 4; //Smooth + } else { + intFade = 1 << 4; //Instant + } + + intCode = intLevel | intFade; //Concat level and fade + + checksum1 = 0; + checksum2 = 0; + for (int i = 0; i < 6; ++i) { + if ((intCode>>i) & 1) { + strReturn.append("TT"); + if (i % 2 == 0) + checksum1++; + else + checksum2++; + } else { + strReturn.append("ª"); + } + } + + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + + strReturn.append("+"); + + return strReturn; + +} diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index 0a6ffcfb..8468adf6 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -1,38 +1,38 @@ -#include "ProtocolMandolyn.h" -#include "Strings.h" -#include -#include -#include - -std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) -{ - std::string data = dataMsg.getParameter("data"); - uint32_t value = (uint32_t)TelldusCore::hexTo64l(data); - - bool parity = value & 0x1; - value >>= 1; - - double temp = (double)(value & 0x7FFF) - (double)6400; - temp = temp/128.0; - value >>= 15; - - uint8_t humidity = (value & 0x7F); - value >>= 7; - - bool battOk = value & 0x1; - value >>= 3; - - uint8_t channel = (value & 0x3)+1; - value >>= 2; - - uint8_t house = value & 0xF; - - std::stringstream retString; - retString << "class:sensor;protocol:mandolyn;id:" - << house*10+channel - << ";model:temperaturehumidity;" - << "temp:" << std::fixed << std::setprecision(1) << temp - << ";humidity:" << (int)humidity << ";"; - - return retString.str(); -} +#include "ProtocolMandolyn.h" +#include "Strings.h" +#include +#include +#include + +std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + uint32_t value = (uint32_t)TelldusCore::hexTo64l(data); + + bool parity = value & 0x1; + value >>= 1; + + double temp = (double)(value & 0x7FFF) - (double)6400; + temp = temp/128.0; + value >>= 15; + + uint8_t humidity = (value & 0x7F); + value >>= 7; + + bool battOk = value & 0x1; + value >>= 3; + + uint8_t channel = (value & 0x3)+1; + value >>= 2; + + uint8_t house = value & 0xF; + + std::stringstream retString; + retString << "class:sensor;protocol:mandolyn;id:" + << house*10+channel + << ";model:temperaturehumidity;" + << "temp:" << std::fixed << std::setprecision(1) << temp + << ";humidity:" << (int)humidity << ";"; + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 993f3ff2..7faea29e 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,282 +1,282 @@ -#include "ProtocolNexa.h" -#include -#include -#include "TellStick.h" -#include "Strings.h" - -int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; //TODO, always removing first turnon now, make more flexible (waveman too) - -int ProtocolNexa::methods() const { - if (TelldusCore::comparei(model(), L"codeswitch")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); - - } else if (TelldusCore::comparei(model(), L"selflearning-switch")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); - - } else if (TelldusCore::comparei(model(), L"selflearning-dimmer")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); - - } else if (TelldusCore::comparei(model(), L"bell")) { - return TELLSTICK_BELL; - } - return 0; -} - -std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *controller) { - if (TelldusCore::comparei(model(), L"codeswitch")) { - return getStringCodeSwitch(method); - } else if (TelldusCore::comparei(model(), L"bell")) { - return getStringBell(); - } - if ((method == TELLSTICK_TURNON) && TelldusCore::comparei(model(), L"selflearning-dimmer")) { - //Workaround for not letting a dimmer do into "dimming mode" - return getStringSelflearning(TELLSTICK_DIM, 255); - } - if (method == TELLSTICK_LEARN) { - std::string str = getStringSelflearning(TELLSTICK_TURNON, data); - - //Check to see if we are an old TellStick (fw <= 2, batch <= 8) - TellStick *ts = reinterpret_cast(controller); - if (!ts) { - return str; - } - if (ts->pid() == 0x0c30 && ts->firmwareVersion() <= 2) { - //Workaround for the bug in early firmwares - //The TellStick have a fixed pause (max) between two packets. - //It is only correct between the first and second packet. - //It seems faster to send two packes at a time and some - //receivers seems picky about this when learning. - //We also return the last packet so Device::doAction() doesn't - //report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - - str.insert(0, 1, 2); //Repeat two times - str.insert(0, 1, 'R'); - for (int i = 0; i < 5; ++i) { - controller->send(str); - } - } - return str; - } - return getStringSelflearning(method, data); -} - -std::string ProtocolNexa::getStringCodeSwitch(int method) { - std::string strReturn = "S"; - - std::wstring house = getStringParameter(L"house", L"A"); - int intHouse = house[0] - L'A'; - strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1)); - - if (method == TELLSTICK_TURNON) { - strReturn.append("$k$k$kk$$kk$$kk$$k+"); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(this->getOffCode()); - } else { - return ""; - } - return strReturn; -} - -std::string ProtocolNexa::getStringBell() { - std::string strReturn = "S"; - - std::wstring house = getStringParameter(L"house", L"A"); - int intHouse = house[0] - L'A'; - strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append("$kk$$kk$$kk$$k$k"); //Unit 7 - strReturn.append("$kk$$kk$$kk$$kk$$k+"); //Bell - return strReturn; -} - -std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { - int intHouse = getIntParameter(L"house", 1, 67108863); - int intCode = getIntParameter(L"unit", 1, 16)-1; - return getStringSelflearningForCode(intHouse, intCode, method, level); -} - -std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode, int method, unsigned char level) { - const unsigned char START[] = {'T',127,255,24,1,0}; -// const char START[] = {'T',130,255,26,24,0}; - - std::string strMessage(reinterpret_cast(START)); - strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses - - std::string m; - for (int i = 25; i >= 0; --i) { - m.append( intHouse & 1 << i ? "10" : "01" ); - } - m.append("01"); //Group - - //On/off - if (method == TELLSTICK_DIM) { - m.append("00"); - } else if (method == TELLSTICK_TURNOFF) { - m.append("01"); - } else if (method == TELLSTICK_TURNON) { - m.append("10"); - } else { - return ""; - } - - for (int i = 3; i >= 0; --i) { - m.append( intCode & 1 << i ? "10" : "01" ); - } - - if (method == TELLSTICK_DIM) { - unsigned char newLevel = level/16; - for (int i = 3; i >= 0; --i) { - m.append(newLevel & 1 << i ? "10" : "01"); - } - } - - //The number of data is odd. - //Add this to make it even, otherwise the following loop will not work - m.append("0"); - - unsigned char code = 9; //b1001, startcode - for (unsigned int i = 0; i < m.length(); ++i) { - code <<= 4; - if (m[i] == '1') { - code |= 8; //b1000 - } else { - code |= 10; //b1010 -// code |= 11; //b1011 - } - if (i % 2 == 0) { - strMessage.append(1,code); - code = 0; - } - } - strMessage.append("+"); - -// for( int i = 0; i < strMessage.length(); ++i ) { -// printf("%i,", (unsigned char)strMessage[i]); -// } -// printf("\n"); - return strMessage; -} - -std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) -{ - unsigned long allData = 0; - - sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); - - if(TelldusCore::comparei(dataMsg.model(), L"selflearning")){ - //selflearning - return decodeDataSelfLearning(allData); - } - else{ - //codeswitch - return decodeDataCodeSwitch(allData); - } -} - -std::string ProtocolNexa::decodeDataSelfLearning(long allData){ - unsigned int house = 0; - unsigned int unit = 0; - unsigned int group = 0; - unsigned int method = 0; - - house = allData & 0xFFFFFFC0; - house >>= 6; - - group = allData & 0x20; - group >>= 5; - - method = allData & 0x10; - method >>= 4; - - unit = allData & 0xF; - unit++; - - if(house < 1 || house > 67108863 || unit < 1 || unit > 16){ - //not arctech selflearning - return ""; - } - - std::stringstream retString; - retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:"; - if(method == 1){ - retString << "turnon;"; - } - else if(method == 0){ - retString << "turnoff;"; - } - else { - //not arctech selflearning - return ""; - } - - return retString.str(); -} - -std::string ProtocolNexa::decodeDataCodeSwitch(long allData){ - - unsigned int house = 0; - unsigned int unit = 0; - unsigned int method = 0; - - method = allData & 0xF00; - method >>= 8; - - unit = allData & 0xF0; - unit >>= 4; - unit++; - - house = allData & 0xF; - - if(house < 0 || house > 16 || unit < 1 || unit > 16){ - //not arctech codeswitch - return ""; - } - - house = house + 'A'; //house from A to P - - if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ - lastArctecCodeSwitchWasTurnOff = 0; - return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - //one turnon/bell, but it's better than the alternative... - } - - if(method == 6){ - lastArctecCodeSwitchWasTurnOff = 1; - } - - std::stringstream retString; - retString << "class:command;protocol:arctech;model:codeswitch;house:" << char(house); - - if(method == 6){ - retString << ";unit:" << unit << ";method:turnoff;"; - } - else if(method == 14){ - retString << ";unit:" << unit << ";method:turnon;"; - } - else if(method == 15){ - retString << ";method:bell;"; - } - else { - //not arctech codeswitch - return ""; - } - - return retString.str(); -} - -std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { - std::string strReturn = ""; - for( int i = 0; i < 4; ++i ) { - if (intCode & 1) { //Convert 1 - strReturn.append("$kk$"); - } else { //Convert 0 - strReturn.append("$k$k"); - } - intCode >>= 1; - } - return strReturn; -} - -std::string ProtocolNexa::getOffCode() const { - return "$k$k$kk$$kk$$k$k$k+"; -} +#include "ProtocolNexa.h" +#include +#include +#include "TellStick.h" +#include "Strings.h" + +int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; //TODO, always removing first turnon now, make more flexible (waveman too) + +int ProtocolNexa::methods() const { + if (TelldusCore::comparei(model(), L"codeswitch")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); + + } else if (TelldusCore::comparei(model(), L"selflearning-switch")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); + + } else if (TelldusCore::comparei(model(), L"selflearning-dimmer")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN); + + } else if (TelldusCore::comparei(model(), L"bell")) { + return TELLSTICK_BELL; + } + return 0; +} + +std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *controller) { + if (TelldusCore::comparei(model(), L"codeswitch")) { + return getStringCodeSwitch(method); + } else if (TelldusCore::comparei(model(), L"bell")) { + return getStringBell(); + } + if ((method == TELLSTICK_TURNON) && TelldusCore::comparei(model(), L"selflearning-dimmer")) { + //Workaround for not letting a dimmer do into "dimming mode" + return getStringSelflearning(TELLSTICK_DIM, 255); + } + if (method == TELLSTICK_LEARN) { + std::string str = getStringSelflearning(TELLSTICK_TURNON, data); + + //Check to see if we are an old TellStick (fw <= 2, batch <= 8) + TellStick *ts = reinterpret_cast(controller); + if (!ts) { + return str; + } + if (ts->pid() == 0x0c30 && ts->firmwareVersion() <= 2) { + //Workaround for the bug in early firmwares + //The TellStick have a fixed pause (max) between two packets. + //It is only correct between the first and second packet. + //It seems faster to send two packes at a time and some + //receivers seems picky about this when learning. + //We also return the last packet so Device::doAction() doesn't + //report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + + str.insert(0, 1, 2); //Repeat two times + str.insert(0, 1, 'R'); + for (int i = 0; i < 5; ++i) { + controller->send(str); + } + } + return str; + } + return getStringSelflearning(method, data); +} + +std::string ProtocolNexa::getStringCodeSwitch(int method) { + std::string strReturn = "S"; + + std::wstring house = getStringParameter(L"house", L"A"); + int intHouse = house[0] - L'A'; + strReturn.append(getCodeSwitchTuple(intHouse)); + strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1)); + + if (method == TELLSTICK_TURNON) { + strReturn.append("$k$k$kk$$kk$$kk$$k+"); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(this->getOffCode()); + } else { + return ""; + } + return strReturn; +} + +std::string ProtocolNexa::getStringBell() { + std::string strReturn = "S"; + + std::wstring house = getStringParameter(L"house", L"A"); + int intHouse = house[0] - L'A'; + strReturn.append(getCodeSwitchTuple(intHouse)); + strReturn.append("$kk$$kk$$kk$$k$k"); //Unit 7 + strReturn.append("$kk$$kk$$kk$$kk$$k+"); //Bell + return strReturn; +} + +std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) { + int intHouse = getIntParameter(L"house", 1, 67108863); + int intCode = getIntParameter(L"unit", 1, 16)-1; + return getStringSelflearningForCode(intHouse, intCode, method, level); +} + +std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode, int method, unsigned char level) { + const unsigned char START[] = {'T',127,255,24,1,0}; +// const char START[] = {'T',130,255,26,24,0}; + + std::string strMessage(reinterpret_cast(START)); + strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses + + std::string m; + for (int i = 25; i >= 0; --i) { + m.append( intHouse & 1 << i ? "10" : "01" ); + } + m.append("01"); //Group + + //On/off + if (method == TELLSTICK_DIM) { + m.append("00"); + } else if (method == TELLSTICK_TURNOFF) { + m.append("01"); + } else if (method == TELLSTICK_TURNON) { + m.append("10"); + } else { + return ""; + } + + for (int i = 3; i >= 0; --i) { + m.append( intCode & 1 << i ? "10" : "01" ); + } + + if (method == TELLSTICK_DIM) { + unsigned char newLevel = level/16; + for (int i = 3; i >= 0; --i) { + m.append(newLevel & 1 << i ? "10" : "01"); + } + } + + //The number of data is odd. + //Add this to make it even, otherwise the following loop will not work + m.append("0"); + + unsigned char code = 9; //b1001, startcode + for (unsigned int i = 0; i < m.length(); ++i) { + code <<= 4; + if (m[i] == '1') { + code |= 8; //b1000 + } else { + code |= 10; //b1010 +// code |= 11; //b1011 + } + if (i % 2 == 0) { + strMessage.append(1,code); + code = 0; + } + } + strMessage.append("+"); + +// for( int i = 0; i < strMessage.length(); ++i ) { +// printf("%i,", (unsigned char)strMessage[i]); +// } +// printf("\n"); + return strMessage; +} + +std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) +{ + unsigned long allData = 0; + + sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); + + if(TelldusCore::comparei(dataMsg.model(), L"selflearning")){ + //selflearning + return decodeDataSelfLearning(allData); + } + else{ + //codeswitch + return decodeDataCodeSwitch(allData); + } +} + +std::string ProtocolNexa::decodeDataSelfLearning(long allData){ + unsigned int house = 0; + unsigned int unit = 0; + unsigned int group = 0; + unsigned int method = 0; + + house = allData & 0xFFFFFFC0; + house >>= 6; + + group = allData & 0x20; + group >>= 5; + + method = allData & 0x10; + method >>= 4; + + unit = allData & 0xF; + unit++; + + if(house < 1 || house > 67108863 || unit < 1 || unit > 16){ + //not arctech selflearning + return ""; + } + + std::stringstream retString; + retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:"; + if(method == 1){ + retString << "turnon;"; + } + else if(method == 0){ + retString << "turnoff;"; + } + else { + //not arctech selflearning + return ""; + } + + return retString.str(); +} + +std::string ProtocolNexa::decodeDataCodeSwitch(long allData){ + + unsigned int house = 0; + unsigned int unit = 0; + unsigned int method = 0; + + method = allData & 0xF00; + method >>= 8; + + unit = allData & 0xF0; + unit >>= 4; + unit++; + + house = allData & 0xF; + + if(house < 0 || house > 16 || unit < 1 || unit > 16){ + //not arctech codeswitch + return ""; + } + + house = house + 'A'; //house from A to P + + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ + lastArctecCodeSwitchWasTurnOff = 0; + return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose + //one turnon/bell, but it's better than the alternative... + } + + if(method == 6){ + lastArctecCodeSwitchWasTurnOff = 1; + } + + std::stringstream retString; + retString << "class:command;protocol:arctech;model:codeswitch;house:" << char(house); + + if(method == 6){ + retString << ";unit:" << unit << ";method:turnoff;"; + } + else if(method == 14){ + retString << ";unit:" << unit << ";method:turnon;"; + } + else if(method == 15){ + retString << ";method:bell;"; + } + else { + //not arctech codeswitch + return ""; + } + + return retString.str(); +} + +std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { + std::string strReturn = ""; + for( int i = 0; i < 4; ++i ) { + if (intCode & 1) { //Convert 1 + strReturn.append("$kk$"); + } else { //Convert 0 + strReturn.append("$k$k"); + } + intCode >>= 1; + } + return strReturn; +} + +std::string ProtocolNexa::getOffCode() const { + return "$k$k$kk$$kk$$k$k$k+"; +} diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index c5847952..a22d2942 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -1,115 +1,115 @@ -#include "ProtocolOregon.h" -#include "Strings.h" -#include -#include -#include - -std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) -{ - std::string data = dataMsg.getParameter("data"); - - std::wstring model = dataMsg.model(); - if (model.compare(L"0xEA4C") == 0) { - return decodeEA4C(data); - } else if (model.compare(L"0x1A2D") == 0) { - return decode1A2D(data); - } - - return ""; -} - -std::string ProtocolOregon::decodeEA4C(const std::string &data) { - uint64_t value = TelldusCore::hexTo64l(data); - - uint8_t checksum = 0xE + 0xA + 0x4 + 0xC; - checksum -= (value & 0xF) * 0x10; - checksum -= 0xA; - value >>= 8; - - uint8_t checksumw = (value >> 4) & 0xF; - bool neg = value & (1 << 3); - checksum += (value & 0xF); - value >>= 8; - - uint8_t temp2 = value & 0xF; - uint8_t temp1 = (value >> 4) & 0xF; - checksum += temp2 + temp1; - value >>= 8; - - uint8_t temp3 = (value >> 4) & 0xF; - checksum += (value & 0xF) + temp3; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t address = value & 0xFF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t channel = (value >> 4) & 0x7; - - if (checksum != checksumw) { - return ""; - } - - double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; - if (neg) { - temperature = -temperature; - } - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:EA4C;id:" << (int)address - << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; - - return retString.str(); -} - -std::string ProtocolOregon::decode1A2D(const std::string &data) { - uint64_t value = TelldusCore::hexTo64l(data); - uint8_t checksum2 = value & 0xFF; - value >>= 8; - uint8_t checksum1 = value & 0xFF; - value >>= 8; - - uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); - uint8_t hum1 = value & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t neg = value & (1 << 3); - uint8_t hum2 = (value >> 4) & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t temp2 = value & 0xF; - uint8_t temp1 = (value >> 4) & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t temp3 = (value >> 4) & 0xF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t address = value & 0xFF; - value >>= 8; - - checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t channel = (value >> 4) & 0x7; - - checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA; - - //TODO: Find out how checksum2 works - if (checksum != checksum1) { - return ""; - } - - double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; - if (neg) { - temperature = -temperature; - } - - std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:1A2D;id:" << (int)address - << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; - - return retString.str(); -} +#include "ProtocolOregon.h" +#include "Strings.h" +#include +#include +#include + +std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + + std::wstring model = dataMsg.model(); + if (model.compare(L"0xEA4C") == 0) { + return decodeEA4C(data); + } else if (model.compare(L"0x1A2D") == 0) { + return decode1A2D(data); + } + + return ""; +} + +std::string ProtocolOregon::decodeEA4C(const std::string &data) { + uint64_t value = TelldusCore::hexTo64l(data); + + uint8_t checksum = 0xE + 0xA + 0x4 + 0xC; + checksum -= (value & 0xF) * 0x10; + checksum -= 0xA; + value >>= 8; + + uint8_t checksumw = (value >> 4) & 0xF; + bool neg = value & (1 << 3); + checksum += (value & 0xF); + value >>= 8; + + uint8_t temp2 = value & 0xF; + uint8_t temp1 = (value >> 4) & 0xF; + checksum += temp2 + temp1; + value >>= 8; + + uint8_t temp3 = (value >> 4) & 0xF; + checksum += (value & 0xF) + temp3; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t address = value & 0xFF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t channel = (value >> 4) & 0x7; + + if (checksum != checksumw) { + return ""; + } + + double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; + if (neg) { + temperature = -temperature; + } + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:EA4C;id:" << (int)address + << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + + return retString.str(); +} + +std::string ProtocolOregon::decode1A2D(const std::string &data) { + uint64_t value = TelldusCore::hexTo64l(data); + uint8_t checksum2 = value & 0xFF; + value >>= 8; + uint8_t checksum1 = value & 0xFF; + value >>= 8; + + uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); + uint8_t hum1 = value & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t neg = value & (1 << 3); + uint8_t hum2 = (value >> 4) & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t temp2 = value & 0xF; + uint8_t temp1 = (value >> 4) & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t temp3 = (value >> 4) & 0xF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t address = value & 0xFF; + value >>= 8; + + checksum += ((value >> 4) & 0xF) + (value & 0xF); + uint8_t channel = (value >> 4) & 0x7; + + checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA; + + //TODO: Find out how checksum2 works + if (checksum != checksum1) { + return ""; + } + + double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; + if (neg) { + temperature = -temperature; + } + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:1A2D;id:" << (int)address + << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index 4068ba40..192c900d 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -1,111 +1,111 @@ -#include "ProtocolRisingSun.h" -#include "Strings.h" - -int ProtocolRisingSun::methods() const { - if (TelldusCore::comparei(model(), L"selflearning")) { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); - } - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) { - if (TelldusCore::comparei(model(), L"selflearning")) { - return getStringSelflearning(method); - } - return getStringCodeSwitch(method); -} - -std::string ProtocolRisingSun::getStringSelflearning(int method) { - int intHouse = this->getIntParameter(L"house", 1, 33554432)-1; - int intCode = this->getIntParameter(L"code", 1, 16)-1; - - const char code_on[][7] = { - "110110", "001110", "100110", "010110", - "111001", "000101", "101001", "011001", - "110000", "001000", "100000", "010000", - "111100", "000010", "101100", "011100" - }; - const char code_off[][7] = { - "111110", "000001", "101110", "011110", - "110101", "001101", "100101", "010101", - "111000", "000100", "101000", "011000", - "110010", "001010", "100010", "010010" - }; - const char l = 120; - const char s = 51; - - std::string strCode = "10"; - int code = intCode; - code = (code < 0 ? 0 : code); - code = (code > 15 ? 15 : code); - if (method == TELLSTICK_TURNON) { - strCode.append(code_on[code]); - } else if (method == TELLSTICK_TURNOFF) { - strCode.append(code_off[code]); - } else if (method == TELLSTICK_LEARN) { - strCode.append(code_on[code]); - } else { - return ""; - } - - int house = intHouse; - for(int i = 0; i < 25; ++i) { - if (house & 1) { - strCode.append(1, '1'); - } else { - strCode.append(1, '0'); - } - house >>= 1; - } - - std::string strReturn; - for(unsigned int i = 0; i < strCode.length(); ++i) { - if (strCode[i] == '1') { - strReturn.append(1, l); - strReturn.append(1, s); - } else { - strReturn.append(1, s); - strReturn.append(1, l); - } - } - - std::string prefix = "P"; - prefix.append(1, 5); - if (method == TELLSTICK_LEARN) { - prefix.append("R"); - prefix.append( 1, 50 ); - } - prefix.append("S"); - strReturn.insert(0, prefix); - strReturn.append(1, '+'); - return strReturn; -} - -std::string ProtocolRisingSun::getStringCodeSwitch(int method) { - std::string strReturn = "S.e"; - strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4)-1)); - strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4)-1)); - if (method == TELLSTICK_TURNON) { - strReturn.append("e..ee..ee..ee..e+"); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append("e..ee..ee..e.e.e+"); - } else { - return ""; - } - return strReturn; - -} - -std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) { - - std::string strReturn = ""; - for(int i = 0; i < 4; ++i) { - if (i == intToConvert) { - strReturn.append( ".e.e" ); - } else { - strReturn.append( "e..e" ); - } - } - return strReturn; - -} +#include "ProtocolRisingSun.h" +#include "Strings.h" + +int ProtocolRisingSun::methods() const { + if (TelldusCore::comparei(model(), L"selflearning")) { + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); + } + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + +std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) { + if (TelldusCore::comparei(model(), L"selflearning")) { + return getStringSelflearning(method); + } + return getStringCodeSwitch(method); +} + +std::string ProtocolRisingSun::getStringSelflearning(int method) { + int intHouse = this->getIntParameter(L"house", 1, 33554432)-1; + int intCode = this->getIntParameter(L"code", 1, 16)-1; + + const char code_on[][7] = { + "110110", "001110", "100110", "010110", + "111001", "000101", "101001", "011001", + "110000", "001000", "100000", "010000", + "111100", "000010", "101100", "011100" + }; + const char code_off[][7] = { + "111110", "000001", "101110", "011110", + "110101", "001101", "100101", "010101", + "111000", "000100", "101000", "011000", + "110010", "001010", "100010", "010010" + }; + const char l = 120; + const char s = 51; + + std::string strCode = "10"; + int code = intCode; + code = (code < 0 ? 0 : code); + code = (code > 15 ? 15 : code); + if (method == TELLSTICK_TURNON) { + strCode.append(code_on[code]); + } else if (method == TELLSTICK_TURNOFF) { + strCode.append(code_off[code]); + } else if (method == TELLSTICK_LEARN) { + strCode.append(code_on[code]); + } else { + return ""; + } + + int house = intHouse; + for(int i = 0; i < 25; ++i) { + if (house & 1) { + strCode.append(1, '1'); + } else { + strCode.append(1, '0'); + } + house >>= 1; + } + + std::string strReturn; + for(unsigned int i = 0; i < strCode.length(); ++i) { + if (strCode[i] == '1') { + strReturn.append(1, l); + strReturn.append(1, s); + } else { + strReturn.append(1, s); + strReturn.append(1, l); + } + } + + std::string prefix = "P"; + prefix.append(1, 5); + if (method == TELLSTICK_LEARN) { + prefix.append("R"); + prefix.append( 1, 50 ); + } + prefix.append("S"); + strReturn.insert(0, prefix); + strReturn.append(1, '+'); + return strReturn; +} + +std::string ProtocolRisingSun::getStringCodeSwitch(int method) { + std::string strReturn = "S.e"; + strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4)-1)); + strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4)-1)); + if (method == TELLSTICK_TURNON) { + strReturn.append("e..ee..ee..ee..e+"); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append("e..ee..ee..e.e.e+"); + } else { + return ""; + } + return strReturn; + +} + +std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) { + + std::string strReturn = ""; + for(int i = 0; i < 4; ++i) { + if (i == intToConvert) { + strReturn.append( ".e.e" ); + } else { + strReturn.append( "e..e" ); + } + } + return strReturn; + +} diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 6c214cb6..b0456825 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -1,104 +1,104 @@ -#include "ProtocolSartano.h" -#include -#include - -int ProtocolSartano::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) { - std::wstring strCode = this->getStringParameter(L"code", L""); - return getStringForCode(strCode, method); -} - -std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int method) { - - std::string strReturn("S"); - - for (size_t i = 0; i < strCode.length(); ++i) { - if (strCode[i] == L'1') { - strReturn.append("$k$k"); - } else { - strReturn.append("$kk$"); - } - } - - if (method == TELLSTICK_TURNON) { - strReturn.append("$k$k$kk$$k+"); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append("$kk$$k$k$k+"); - } else { - return ""; - } - - return strReturn; - -} - -std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) -{ - std::string data = dataMsg.getParameter("data"); - signed int allDataIn; - signed int allData = 0; - unsigned int code = 0; - unsigned int method1 = 0; - unsigned int method2 = 0; - unsigned int method = 0; - - sscanf(data.c_str(), "%X", &allDataIn); - - unsigned long mask = (1<<11); - for(int i=0;i<12;++i){ - allData >>= 1; - if((allDataIn & mask) == 0){ - allData |= (1<<11); - } - mask >>= 1; - } - - code = allData & 0xFFC; - code >>= 2; - - method1 = allData & 0x2; - method1 >>= 1; - - method2 = allData & 0x1; - - if(method1 == 0 && method2 == 1){ - method = 0; //off - } - else if(method1 == 1 && method2 == 0){ - method = 1; //on - } - else{ - return ""; - } - - if(code < 0 || code > 1023){ - //not sartano - return ""; - } - - std::stringstream retString; - retString << "class:command;protocol:sartano;model:codeswitch;code:"; - mask = (1<<9); - for(int i=0;i<10;i++){ - if((code & mask) != 0){ - retString << 1; - } - else{ - retString << 0; - } - mask >>= 1; - } - retString << ";method:"; - - if(method == 0){ - retString << "turnoff;"; - } - else{ - retString << "turnon;"; - } - - return retString.str(); -} +#include "ProtocolSartano.h" +#include +#include + +int ProtocolSartano::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + +std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) { + std::wstring strCode = this->getStringParameter(L"code", L""); + return getStringForCode(strCode, method); +} + +std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int method) { + + std::string strReturn("S"); + + for (size_t i = 0; i < strCode.length(); ++i) { + if (strCode[i] == L'1') { + strReturn.append("$k$k"); + } else { + strReturn.append("$kk$"); + } + } + + if (method == TELLSTICK_TURNON) { + strReturn.append("$k$k$kk$$k+"); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append("$kk$$k$k$k+"); + } else { + return ""; + } + + return strReturn; + +} + +std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) +{ + std::string data = dataMsg.getParameter("data"); + signed int allDataIn; + signed int allData = 0; + unsigned int code = 0; + unsigned int method1 = 0; + unsigned int method2 = 0; + unsigned int method = 0; + + sscanf(data.c_str(), "%X", &allDataIn); + + unsigned long mask = (1<<11); + for(int i=0;i<12;++i){ + allData >>= 1; + if((allDataIn & mask) == 0){ + allData |= (1<<11); + } + mask >>= 1; + } + + code = allData & 0xFFC; + code >>= 2; + + method1 = allData & 0x2; + method1 >>= 1; + + method2 = allData & 0x1; + + if(method1 == 0 && method2 == 1){ + method = 0; //off + } + else if(method1 == 1 && method2 == 0){ + method = 1; //on + } + else{ + return ""; + } + + if(code < 0 || code > 1023){ + //not sartano + return ""; + } + + std::stringstream retString; + retString << "class:command;protocol:sartano;model:codeswitch;code:"; + mask = (1<<9); + for(int i=0;i<10;i++){ + if((code & mask) != 0){ + retString << 1; + } + else{ + retString << 0; + } + mask >>= 1; + } + retString << ";method:"; + + if(method == 0){ + retString << "turnoff;"; + } + else{ + retString << "turnon;"; + } + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolScene.cpp b/telldus-core/service/ProtocolScene.cpp index 811aa7f0..e18e362a 100644 --- a/telldus-core/service/ProtocolScene.cpp +++ b/telldus-core/service/ProtocolScene.cpp @@ -1,9 +1,9 @@ -#include "ProtocolScene.h" - -int ProtocolScene::methods() const { - return TELLSTICK_EXECUTE; -} - -std::string ProtocolScene::getStringForMethod(int method, unsigned char data, Controller *) { - return ""; +#include "ProtocolScene.h" + +int ProtocolScene::methods() const { + return TELLSTICK_EXECUTE; +} + +std::string ProtocolScene::getStringForMethod(int method, unsigned char data, Controller *) { + return ""; } diff --git a/telldus-core/service/ProtocolScene.h b/telldus-core/service/ProtocolScene.h index 4b1b6903..aaa22ebb 100644 --- a/telldus-core/service/ProtocolScene.h +++ b/telldus-core/service/ProtocolScene.h @@ -10,7 +10,7 @@ public: }; -#endif //PROTOCOLSCENE_H - - - +#endif //PROTOCOLSCENE_H + + + diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index dbde18bf..23226e69 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -1,140 +1,140 @@ -#include "ProtocolSilvanChip.h" -#include "Strings.h" - -int ProtocolSilvanChip::methods() const { - if (TelldusCore::comparei(model(), L"kp100")) { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; - } else if (TelldusCore::comparei(model(), L"ecosavers")) { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; - } else if (TelldusCore::comparei(model(), L"displaymatic")) { - return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; - } - return 0; -} - -std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { - if (TelldusCore::comparei(model(), L"kp100")) { - std::string preamble; - preamble.append(1, 100); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 100); - - const std::string one = "\xFF\x1\x2E\x2E"; - const std::string zero = "\x2E\xFF\x1\x2E"; - int button = 0; - if (method == TELLSTICK_UP) { - button = 2; - } else if (method == TELLSTICK_DOWN) { - button = 8; - } else if (method == TELLSTICK_STOP) { - button = 4; - } else if (method == TELLSTICK_LEARN) { - button = 1; - } else { - return ""; - } - return this->getString(preamble, one, zero, button); - } else if (TelldusCore::comparei(model(), L"displaymatic")) { - std::string preamble; - preamble.append(1, 0x25); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 0x25); - const std::string one = "\x69\25"; - const std::string zero = "\x25\x69"; - int button = 0; - if (method == TELLSTICK_UP) { - button = 1; - } else if (method == TELLSTICK_DOWN) { - button = 4; - } else if (method == TELLSTICK_STOP) { - button = 2; - } - return this->getString(preamble, one, zero, button); - } else if (TelldusCore::comparei(model(), L"ecosavers")) { - std::string preamble; - preamble.append(1, 0x25); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 255); - preamble.append(1, 1); - preamble.append(1, 0x25); - const std::string one = "\x69\25"; - const std::string zero = "\x25\x69"; - int intUnit = this->getIntParameter(L"unit", 1, 4); - int button = 0; - if (intUnit == 1) { - button = 7; - } else if (intUnit == 2) { - button = 3; - } else if (intUnit == 3) { - button = 5; - } else if (intUnit == 4) { - button = 6; - } - - if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { - button |= 8; - } - return this->getString(preamble, one, zero, button); - } - return ""; -} - -std::string ProtocolSilvanChip::getString(const std::string &preamble, const std::string &one, const std::string &zero, int button) { - - int intHouse = this->getIntParameter(L"house", 1, 1048575); - std::string strReturn = preamble; - - for( int i = 19; i >= 0; --i ) { - if (intHouse & (1 << i)) { - strReturn.append(one); - } else { - strReturn.append(zero); - } - } - - for( int i = 3; i >= 0; --i) { - if (button & (1 << i)) { - strReturn.append(one); - } else { - strReturn.append(zero); - } - } - - strReturn.append(zero); - return strReturn; -} +#include "ProtocolSilvanChip.h" +#include "Strings.h" + +int ProtocolSilvanChip::methods() const { + if (TelldusCore::comparei(model(), L"kp100")) { + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; + } else if (TelldusCore::comparei(model(), L"ecosavers")) { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; + } else if (TelldusCore::comparei(model(), L"displaymatic")) { + return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; + } + return 0; +} + +std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) { + if (TelldusCore::comparei(model(), L"kp100")) { + std::string preamble; + preamble.append(1, 100); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 100); + + const std::string one = "\xFF\x1\x2E\x2E"; + const std::string zero = "\x2E\xFF\x1\x2E"; + int button = 0; + if (method == TELLSTICK_UP) { + button = 2; + } else if (method == TELLSTICK_DOWN) { + button = 8; + } else if (method == TELLSTICK_STOP) { + button = 4; + } else if (method == TELLSTICK_LEARN) { + button = 1; + } else { + return ""; + } + return this->getString(preamble, one, zero, button); + } else if (TelldusCore::comparei(model(), L"displaymatic")) { + std::string preamble; + preamble.append(1, 0x25); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 0x25); + const std::string one = "\x69\25"; + const std::string zero = "\x25\x69"; + int button = 0; + if (method == TELLSTICK_UP) { + button = 1; + } else if (method == TELLSTICK_DOWN) { + button = 4; + } else if (method == TELLSTICK_STOP) { + button = 2; + } + return this->getString(preamble, one, zero, button); + } else if (TelldusCore::comparei(model(), L"ecosavers")) { + std::string preamble; + preamble.append(1, 0x25); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 255); + preamble.append(1, 1); + preamble.append(1, 0x25); + const std::string one = "\x69\25"; + const std::string zero = "\x25\x69"; + int intUnit = this->getIntParameter(L"unit", 1, 4); + int button = 0; + if (intUnit == 1) { + button = 7; + } else if (intUnit == 2) { + button = 3; + } else if (intUnit == 3) { + button = 5; + } else if (intUnit == 4) { + button = 6; + } + + if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { + button |= 8; + } + return this->getString(preamble, one, zero, button); + } + return ""; +} + +std::string ProtocolSilvanChip::getString(const std::string &preamble, const std::string &one, const std::string &zero, int button) { + + int intHouse = this->getIntParameter(L"house", 1, 1048575); + std::string strReturn = preamble; + + for( int i = 19; i >= 0; --i ) { + if (intHouse & (1 << i)) { + strReturn.append(one); + } else { + strReturn.append(zero); + } + } + + for( int i = 3; i >= 0; --i) { + if (button & (1 << i)) { + strReturn.append(one); + } else { + strReturn.append(zero); + } + } + + strReturn.append(zero); + return strReturn; +} diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 5150009d..65bf7b28 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -1,71 +1,71 @@ -#include "ProtocolUpm.h" - -int ProtocolUpm::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; -} - -std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) { - const char S = ';'; - const char L = '~'; - const char START[] = {S,0}; - const char B1[] = {L,S,0}; - const char B0[] = {S,L,0}; - //const char BON[] = {S,L,L,S,0}; - //const char BOFF[] = {S,L,S,L,0}; - - int intUnit = this->getIntParameter(L"unit", 1, 4)-1; - std::string strReturn; - - int code = this->getIntParameter(L"house", 0, 4095); - for( size_t i = 0; i < 12; ++i ) { - if (code & 1) { - strReturn.insert(0, B1); - } else { - strReturn.insert(0, B0); - } - code >>= 1; - } - strReturn.insert(0, START); //Startcode, first - - code = 0; - if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { - code += 2; - } else if (method != TELLSTICK_TURNOFF) { - return ""; - } - code <<= 2; - code += intUnit; - - int check1 = 0, check2 = 0; - for( size_t i = 0; i < 6; ++i ) { - if (code & 1) { - if (i % 2 == 0) { - check1++; - } else { - check2++; - } - } - if (code & 1) { - strReturn.append(B1); - } else { - strReturn.append(B0); - } - code >>= 1; - } - - if (check1 % 2 == 0) { - strReturn.append(B0); - } else { - strReturn.append(B1); - } - if (check2 % 2 == 0) { - strReturn.append(B0); - } else { - strReturn.append(B1); - } - - strReturn.insert(0, "S"); - strReturn.append("+"); - return strReturn; -} - +#include "ProtocolUpm.h" + +int ProtocolUpm::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; +} + +std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) { + const char S = ';'; + const char L = '~'; + const char START[] = {S,0}; + const char B1[] = {L,S,0}; + const char B0[] = {S,L,0}; + //const char BON[] = {S,L,L,S,0}; + //const char BOFF[] = {S,L,S,L,0}; + + int intUnit = this->getIntParameter(L"unit", 1, 4)-1; + std::string strReturn; + + int code = this->getIntParameter(L"house", 0, 4095); + for( size_t i = 0; i < 12; ++i ) { + if (code & 1) { + strReturn.insert(0, B1); + } else { + strReturn.insert(0, B0); + } + code >>= 1; + } + strReturn.insert(0, START); //Startcode, first + + code = 0; + if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { + code += 2; + } else if (method != TELLSTICK_TURNOFF) { + return ""; + } + code <<= 2; + code += intUnit; + + int check1 = 0, check2 = 0; + for( size_t i = 0; i < 6; ++i ) { + if (code & 1) { + if (i % 2 == 0) { + check1++; + } else { + check2++; + } + } + if (code & 1) { + strReturn.append(B1); + } else { + strReturn.append(B0); + } + code >>= 1; + } + + if (check1 % 2 == 0) { + strReturn.append(B0); + } else { + strReturn.append(B1); + } + if (check2 % 2 == 0) { + strReturn.append(B0); + } else { + strReturn.append(B1); + } + + strReturn.insert(0, "S"); + strReturn.append("+"); + return strReturn; +} + diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index c5f68d2e..14ddb65b 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -1,69 +1,69 @@ -#include "ProtocolWaveman.h" -#include -#include - -int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff=0; - -int ProtocolWaveman::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) { - return getStringCodeSwitch(method); -} - -std::string ProtocolWaveman::getOffCode() const { - return "$k$k$k$k$k$k$k$k$k+"; -} - -std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) -{ - unsigned long allData = 0; - unsigned int house = 0; - unsigned int unit = 0; - unsigned int method = 0; - - sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); - - method = allData & 0xF00; - method >>= 8; - - unit = allData & 0xF0; - unit >>= 4; - unit++; - - house = allData & 0xF; - - if(house < 0 || house > 16 || unit < 1 || unit > 16){ - //not waveman - return ""; - } - - house = house + 'A'; //house from A to P - - if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ - lastArctecCodeSwitchWasTurnOff = 0; - return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - //one turnon/bell, but it's better than the alternative... - } - - if(method == 6){ - lastArctecCodeSwitchWasTurnOff = 1; - } - - std::stringstream retString; - retString << "class:command;protocol:waveman;model:codeswitch;house:" << char(house); - - if(method == 0){ - retString << ";unit:" << unit << ";method:turnoff;"; - } - else if(method == 14){ - retString << ";unit:" << unit << ";method:turnon;"; - } - else { - //not waveman - return ""; - } - - return retString.str(); -} +#include "ProtocolWaveman.h" +#include +#include + +int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff=0; + +int ProtocolWaveman::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + +std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) { + return getStringCodeSwitch(method); +} + +std::string ProtocolWaveman::getOffCode() const { + return "$k$k$k$k$k$k$k$k$k+"; +} + +std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) +{ + unsigned long allData = 0; + unsigned int house = 0; + unsigned int unit = 0; + unsigned int method = 0; + + sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); + + method = allData & 0xF00; + method >>= 8; + + unit = allData & 0xF0; + unit >>= 4; + unit++; + + house = allData & 0xF; + + if(house < 0 || house > 16 || unit < 1 || unit > 16){ + //not waveman + return ""; + } + + house = house + 'A'; //house from A to P + + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ + lastArctecCodeSwitchWasTurnOff = 0; + return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose + //one turnon/bell, but it's better than the alternative... + } + + if(method == 6){ + lastArctecCodeSwitchWasTurnOff = 1; + } + + std::stringstream retString; + retString << "class:command;protocol:waveman;model:codeswitch;house:" << char(house); + + if(method == 0){ + retString << ";unit:" << unit << ";method:turnoff;"; + } + else if(method == 14){ + retString << ";unit:" << unit << ";method:turnon;"; + } + else { + //not waveman + return ""; + } + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index e6d3fef8..ad9bcb55 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -1,174 +1,174 @@ -#include "ProtocolX10.h" -#include -#include - -const unsigned char HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; - -int ProtocolX10::methods() const { - return TELLSTICK_TURNON | TELLSTICK_TURNOFF; -} - -std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) { - const unsigned char S = 59, L = 169; - const char B0[] = {S,S,0}; - const char B1[] = {S,L,0}; - const unsigned char START_CODE[] = {'S',255,1,255,1,255,1,100,255,1,180,0}; - const unsigned char STOP_CODE[] = {S,0}; - - std::string strReturn = reinterpret_cast(START_CODE); - std::string strComplement = ""; - - std::wstring strHouse = getStringParameter(L"house", L"A"); - int intHouse = strHouse[0] - L'A'; - if (intHouse < 0) { - intHouse = 0; - } else if (intHouse > 15) { - intHouse = 15; - } - //Translate it - intHouse = HOUSES[intHouse]; - int intCode = getIntParameter(L"unit", 1, 16)-1; - - for( int i = 0; i < 4; ++i ) { - if (intHouse & 1) { - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - intHouse >>= 1; - } - strReturn.append( B0 ); - strComplement.append( B1 ); - - if (intCode >= 8) { - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - strReturn.append( B0 ); - strComplement.append( B1 ); - strReturn.append( B0 ); - strComplement.append( B1 ); - - strReturn.append( strComplement ); - strComplement = ""; - - strReturn.append( B0 ); - strComplement.append( B1 ); - - if (intCode >> 2 & 1) { //Bit 2 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - if (method == TELLSTICK_TURNON) { - strReturn.append(B0); - strComplement.append(B1); - } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(B1); - strComplement.append(B0); - } else { - return ""; - } - - if (intCode & 1) { //Bit 0 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - if (intCode >> 1 & 1) { //Bit 1 of intCode - strReturn.append(B1); - strComplement.append(B0); - } else { - strReturn.append(B0); - strComplement.append(B1); - } - - for( int i = 0; i < 3; ++i ) { - strReturn.append( B0 ); - strComplement.append( B1 ); - } - - strReturn.append( strComplement ); - strReturn.append( reinterpret_cast(STOP_CODE) ); - strReturn.append("+"); - return strReturn; - -} - -std::string ProtocolX10::decodeData(ControllerMessage& dataMsg) { - int intData = 0, currentBit = 31; - bool method=0; - sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); - - int unit = 0; - int rawHouse = 0; - for(int i = 0; i < 4; ++i) { - rawHouse >>= 1; - if (checkBit(intData, currentBit--)) { - rawHouse |= 0x8; - } - } - - if (checkBit(intData, currentBit--) != 0) { - return ""; - } - - if (checkBit(intData, currentBit--)) { - unit |= (1<<3); - } - - if (checkBit(intData, currentBit--)) { - return ""; - } - if (checkBit(intData, currentBit--)) { - return ""; - } - - currentBit = 14; - - if (checkBit(intData, currentBit--)) { - unit |= (1<<2); - } - if (checkBit(intData, currentBit--)) { - method = 1; - } - if (checkBit(intData, currentBit--)) { - unit |= (1<<0); - } - if (checkBit(intData, currentBit--)) { - unit |= (1<<1); - } - - int intHouse = 0; - for(int i = 0; i < 16; ++i) { - if (HOUSES[i] == rawHouse) { - intHouse = i; - break; - } - } - - std::stringstream retString; - retString << "class:command;protocol:x10;model:codeswitch;"; - retString << "house:" << (char)('A' + intHouse); - retString << ";unit:" << unit+1; - retString << ";method:"; - if(method == 0){ - retString << "turnon;"; - } else { - retString << "turnoff;"; - } - - return retString.str(); -} +#include "ProtocolX10.h" +#include +#include + +const unsigned char HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; + +int ProtocolX10::methods() const { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; +} + +std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) { + const unsigned char S = 59, L = 169; + const char B0[] = {S,S,0}; + const char B1[] = {S,L,0}; + const unsigned char START_CODE[] = {'S',255,1,255,1,255,1,100,255,1,180,0}; + const unsigned char STOP_CODE[] = {S,0}; + + std::string strReturn = reinterpret_cast(START_CODE); + std::string strComplement = ""; + + std::wstring strHouse = getStringParameter(L"house", L"A"); + int intHouse = strHouse[0] - L'A'; + if (intHouse < 0) { + intHouse = 0; + } else if (intHouse > 15) { + intHouse = 15; + } + //Translate it + intHouse = HOUSES[intHouse]; + int intCode = getIntParameter(L"unit", 1, 16)-1; + + for( int i = 0; i < 4; ++i ) { + if (intHouse & 1) { + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + intHouse >>= 1; + } + strReturn.append( B0 ); + strComplement.append( B1 ); + + if (intCode >= 8) { + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + strReturn.append( B0 ); + strComplement.append( B1 ); + strReturn.append( B0 ); + strComplement.append( B1 ); + + strReturn.append( strComplement ); + strComplement = ""; + + strReturn.append( B0 ); + strComplement.append( B1 ); + + if (intCode >> 2 & 1) { //Bit 2 of intCode + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + if (method == TELLSTICK_TURNON) { + strReturn.append(B0); + strComplement.append(B1); + } else if (method == TELLSTICK_TURNOFF) { + strReturn.append(B1); + strComplement.append(B0); + } else { + return ""; + } + + if (intCode & 1) { //Bit 0 of intCode + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + if (intCode >> 1 & 1) { //Bit 1 of intCode + strReturn.append(B1); + strComplement.append(B0); + } else { + strReturn.append(B0); + strComplement.append(B1); + } + + for( int i = 0; i < 3; ++i ) { + strReturn.append( B0 ); + strComplement.append( B1 ); + } + + strReturn.append( strComplement ); + strReturn.append( reinterpret_cast(STOP_CODE) ); + strReturn.append("+"); + return strReturn; + +} + +std::string ProtocolX10::decodeData(ControllerMessage& dataMsg) { + int intData = 0, currentBit = 31; + bool method=0; + sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); + + int unit = 0; + int rawHouse = 0; + for(int i = 0; i < 4; ++i) { + rawHouse >>= 1; + if (checkBit(intData, currentBit--)) { + rawHouse |= 0x8; + } + } + + if (checkBit(intData, currentBit--) != 0) { + return ""; + } + + if (checkBit(intData, currentBit--)) { + unit |= (1<<3); + } + + if (checkBit(intData, currentBit--)) { + return ""; + } + if (checkBit(intData, currentBit--)) { + return ""; + } + + currentBit = 14; + + if (checkBit(intData, currentBit--)) { + unit |= (1<<2); + } + if (checkBit(intData, currentBit--)) { + method = 1; + } + if (checkBit(intData, currentBit--)) { + unit |= (1<<0); + } + if (checkBit(intData, currentBit--)) { + unit |= (1<<1); + } + + int intHouse = 0; + for(int i = 0; i < 16; ++i) { + if (HOUSES[i] == rawHouse) { + intHouse = i; + break; + } + } + + std::stringstream retString; + retString << "class:command;protocol:x10;model:codeswitch;"; + retString << "house:" << (char)('A' + intHouse); + retString << ";unit:" << unit+1; + retString << ";method:"; + if(method == 0){ + retString << "turnon;"; + } else { + retString << "turnoff;"; + } + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolYidong.cpp b/telldus-core/service/ProtocolYidong.cpp index 3961a29c..e0310d08 100644 --- a/telldus-core/service/ProtocolYidong.cpp +++ b/telldus-core/service/ProtocolYidong.cpp @@ -1,24 +1,24 @@ -#include "ProtocolYidong.h" - -std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { - int intCode = this->getIntParameter(L"unit", 1, 4); - std::wstring strCode = L"111"; - - switch(intCode) { - case 1: - strCode.append(L"0010"); - break; - case 2: - strCode.append(L"0001"); - break; - case 3: - strCode.append(L"0100"); - break; - case 4: - strCode.append(L"1000"); - break; - } - - strCode.append(L"110"); - return getStringForCode(strCode, method); -} +#include "ProtocolYidong.h" + +std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { + int intCode = this->getIntParameter(L"unit", 1, 4); + std::wstring strCode = L"111"; + + switch(intCode) { + case 1: + strCode.append(L"0010"); + break; + case 2: + strCode.append(L"0001"); + break; + case 3: + strCode.append(L"0100"); + break; + case 4: + strCode.append(L"1000"); + break; + } + + strCode.append(L"110"); + return getStringForCode(strCode, method); +} diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 639335f6..86f43132 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -1,272 +1,272 @@ -#include "Settings.h" -#include "Strings.h" -#include -#include -#include -#include -#include -#include -#include "common.h" - -#include "../client/telldus-core.h" - -const int intMaxRegValueLength = 1000; - -class Settings::PrivateData { -public: - HKEY rootKey; - std::wstring strRegPath; - std::wstring getNodePath(Settings::Node type); -}; - -std::wstring Settings::PrivateData::getNodePath(Settings::Node type) { - if (type == Settings::Device) { - return L"SOFTWARE\\Telldus\\Devices\\"; - } else if (type == Settings::Controller) { - return L"SOFTWARE\\Telldus\\Controllers\\"; - } - return L""; -} - -/* -* Constructor -*/ -Settings::Settings(void) { - d = new PrivateData(); - d->strRegPath = L"SOFTWARE\\Telldus\\"; - d->rootKey = HKEY_LOCAL_MACHINE; -} - -/* -* Destructor -*/ -Settings::~Settings(void) { - delete d; -} - -/* -* Return the number of stored devices -*/ -int Settings::getNumberOfNodes(Node type) const { +#include "Settings.h" +#include "Strings.h" +#include +#include +#include +#include +#include +#include +#include "common.h" + +#include "../client/telldus-core.h" + +const int intMaxRegValueLength = 1000; + +class Settings::PrivateData { +public: + HKEY rootKey; + std::wstring strRegPath; + std::wstring getNodePath(Settings::Node type); +}; + +std::wstring Settings::PrivateData::getNodePath(Settings::Node type) { + if (type == Settings::Device) { + return L"SOFTWARE\\Telldus\\Devices\\"; + } else if (type == Settings::Controller) { + return L"SOFTWARE\\Telldus\\Controllers\\"; + } + return L""; +} + +/* +* Constructor +*/ +Settings::Settings(void) { + d = new PrivateData(); + d->strRegPath = L"SOFTWARE\\Telldus\\"; + d->rootKey = HKEY_LOCAL_MACHINE; +} + +/* +* Destructor +*/ +Settings::~Settings(void) { + delete d; +} + +/* +* Return the number of stored devices +*/ +int Settings::getNumberOfNodes(Node type) const { TelldusCore::MutexLocker locker(&mutex); - - int intNumberOfNodes = 0; - HKEY hk; - - long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); - - if(lnExists == ERROR_SUCCESS){ - - std::wstring strNumSubKeys; - DWORD dNumSubKeys; - RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - intNumberOfNodes = (int)dNumSubKeys; - - RegCloseKey(hk); - } - return intNumberOfNodes; -} - - -int Settings::getNodeId(Node type, int intNodeIndex) const { + + int intNumberOfNodes = 0; + HKEY hk; + + long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + + std::wstring strNumSubKeys; + DWORD dNumSubKeys; + RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + intNumberOfNodes = (int)dNumSubKeys; + + RegCloseKey(hk); + } + return intNumberOfNodes; +} + + +int Settings::getNodeId(Node type, int intNodeIndex) const { TelldusCore::MutexLocker locker(&mutex); - - int intReturn = -1; - HKEY hk; - - long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); - - if(lnExists == ERROR_SUCCESS){ - - wchar_t* Buff = new wchar_t[intMaxRegValueLength]; - DWORD size = intMaxRegValueLength; - if (RegEnumKeyEx(hk, intNodeIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { - intReturn = _wtoi(Buff); - } - - delete[] Buff; - RegCloseKey(hk); - } - return intReturn; -} - -/* -* Add a new node -*/ -int Settings::addNode(Node type) { + + int intReturn = -1; + HKEY hk; + + long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); + + if(lnExists == ERROR_SUCCESS){ + + wchar_t* Buff = new wchar_t[intMaxRegValueLength]; + DWORD size = intMaxRegValueLength; + if (RegEnumKeyEx(hk, intNodeIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + intReturn = _wtoi(Buff); + } + + delete[] Buff; + RegCloseKey(hk); + } + return intReturn; +} + +/* +* Add a new node +*/ +int Settings::addNode(Node type) { TelldusCore::MutexLocker locker(&mutex); - - int intNodeId = -1; - HKEY hk; - - DWORD dwDisp; - intNodeId = getNextNodeId(type); - - std::wstring strCompleteRegPath = d->getNodePath(type); - strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - - if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) { - //fail - intNodeId = -1; - } - - RegCloseKey(hk); - return intNodeId; -} - -/* -* Get next available device id -*/ -int Settings::getNextNodeId(Node type) const { - //Private, no locks needed - int intReturn = -1; - HKEY hk; - DWORD dwDisp; - - long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created - - if(lnExists == ERROR_SUCCESS){ - - DWORD dwLength = sizeof(DWORD); - DWORD nResult(0); - - long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); - - if(lngStatus == ERROR_SUCCESS){ - intReturn = nResult + 1; - } else { - intReturn = 1; - } - DWORD dwVal = intReturn; - RegSetValueEx (hk, L"LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); - - } - RegCloseKey(hk); - return intReturn; -} - -/* -* Remove a device -*/ -int Settings::removeNode(Node type, int intNodeId) { + + int intNodeId = -1; + HKEY hk; + + DWORD dwDisp; + intNodeId = getNextNodeId(type); + + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); + + if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) { + //fail + intNodeId = -1; + } + + RegCloseKey(hk); + return intNodeId; +} + +/* +* Get next available device id +*/ +int Settings::getNextNodeId(Node type) const { + //Private, no locks needed + int intReturn = -1; + HKEY hk; + DWORD dwDisp; + + long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created + + if(lnExists == ERROR_SUCCESS){ + + DWORD dwLength = sizeof(DWORD); + DWORD nResult(0); + + long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); + + if(lngStatus == ERROR_SUCCESS){ + intReturn = nResult + 1; + } else { + intReturn = 1; + } + DWORD dwVal = intReturn; + RegSetValueEx (hk, L"LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + + } + RegCloseKey(hk); + return intReturn; +} + +/* +* Remove a device +*/ +int Settings::removeNode(Node type, int intNodeId) { TelldusCore::MutexLocker locker(&mutex); - - std::wstring strCompleteRegPath = d->getNodePath(type); - strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - - long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); - - if(lngSuccess == ERROR_SUCCESS){ - //one of the deletions succeeded - return TELLSTICK_SUCCESS; - } - - return TELLSTICK_ERROR_UNKNOWN; -} - -std::wstring Settings::getSetting(const std::wstring &strName) const{ - std::wstring strReturn; - HKEY hk; - - std::wstring strCompleteRegPath = d->strRegPath; - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); - - if(lnExists == ERROR_SUCCESS){ - wchar_t* Buff = new wchar_t[intMaxRegValueLength]; - DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; - long lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - - if(lngStatus == ERROR_MORE_DATA){ - //The buffer is to small, recreate it - delete[] Buff; - Buff = new wchar_t[dwLength]; - lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - } - if (lngStatus == ERROR_SUCCESS) { - strReturn = Buff; - } - delete[] Buff; - } - RegCloseKey(hk); - return strReturn; -} - -std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { - std::wstring strReturn; - HKEY hk; - - std::wstring strCompleteRegPath = d->getNodePath(type); - strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); - - if(lnExists == ERROR_SUCCESS){ - wchar_t* Buff = new wchar_t[intMaxRegValueLength]; - DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; - long lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - - if(lngStatus == ERROR_MORE_DATA){ - //The buffer is to small, recreate it - delete[] Buff; - Buff = new wchar_t[dwLength]; - lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - } - if (lngStatus == ERROR_SUCCESS) { - strReturn = Buff; - } - delete[] Buff; - } - RegCloseKey(hk); - return strReturn; -} - -int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &name, const std::wstring &value, bool parameter) { - - HKEY hk; - int ret = TELLSTICK_SUCCESS; - - std::wstring strNodeId = TelldusCore::intToWstring(intNodeId); - std::wstring strCompleteRegPath = d->getNodePath(type); - strCompleteRegPath.append(strNodeId); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); - - if (lnExists == ERROR_SUCCESS){ - int length = (int)value.length() * sizeof(wchar_t); - RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); - } else { - ret = TELLSTICK_ERROR_UNKNOWN; - } - RegCloseKey(hk); - - return ret; - -} - -int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { - int intReturn = 0; - - std::wstring strSetting = getStringSetting(type, intNodeId, name, parameter); - if (strSetting.length()) { - intReturn = (int)strSetting[0]; //TODO: do real conversion instead - } - - return intReturn; -} - -int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &name, int value, bool parameter) { - int intReturn = TELLSTICK_ERROR_UNKNOWN; - HKEY hk; - - std::wstring strCompleteRegPath = d->getNodePath(type); - strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); - if (lnExists == ERROR_SUCCESS) { - DWORD dwVal = value; - lnExists = RegSetValueEx (hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); - if (lnExists == ERROR_SUCCESS) { - intReturn = TELLSTICK_SUCCESS; - } - } - RegCloseKey(hk); - return intReturn; -} + + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); + + long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); + + if(lngSuccess == ERROR_SUCCESS){ + //one of the deletions succeeded + return TELLSTICK_SUCCESS; + } + + return TELLSTICK_ERROR_UNKNOWN; +} + +std::wstring Settings::getSetting(const std::wstring &strName) const{ + std::wstring strReturn; + HKEY hk; + + std::wstring strCompleteRegPath = d->strRegPath; + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + wchar_t* Buff = new wchar_t[intMaxRegValueLength]; + DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; + long lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + //The buffer is to small, recreate it + delete[] Buff; + Buff = new wchar_t[dwLength]; + lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + } + if (lngStatus == ERROR_SUCCESS) { + strReturn = Buff; + } + delete[] Buff; + } + RegCloseKey(hk); + return strReturn; +} + +std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { + std::wstring strReturn; + HKEY hk; + + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + + if(lnExists == ERROR_SUCCESS){ + wchar_t* Buff = new wchar_t[intMaxRegValueLength]; + DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; + long lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + + if(lngStatus == ERROR_MORE_DATA){ + //The buffer is to small, recreate it + delete[] Buff; + Buff = new wchar_t[dwLength]; + lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + } + if (lngStatus == ERROR_SUCCESS) { + strReturn = Buff; + } + delete[] Buff; + } + RegCloseKey(hk); + return strReturn; +} + +int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &name, const std::wstring &value, bool parameter) { + + HKEY hk; + int ret = TELLSTICK_SUCCESS; + + std::wstring strNodeId = TelldusCore::intToWstring(intNodeId); + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(strNodeId); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + + if (lnExists == ERROR_SUCCESS){ + int length = (int)value.length() * sizeof(wchar_t); + RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); + } else { + ret = TELLSTICK_ERROR_UNKNOWN; + } + RegCloseKey(hk); + + return ret; + +} + +int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { + int intReturn = 0; + + std::wstring strSetting = getStringSetting(type, intNodeId, name, parameter); + if (strSetting.length()) { + intReturn = (int)strSetting[0]; //TODO: do real conversion instead + } + + return intReturn; +} + +int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &name, int value, bool parameter) { + int intReturn = TELLSTICK_ERROR_UNKNOWN; + HKEY hk; + + std::wstring strCompleteRegPath = d->getNodePath(type); + strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); + long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + if (lnExists == ERROR_SUCCESS) { + DWORD dwVal = value; + lnExists = RegSetValueEx (hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); + if (lnExists == ERROR_SUCCESS) { + intReturn = TELLSTICK_SUCCESS; + } + } + RegCloseKey(hk); + return intReturn; +} diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index a10e71f3..d4d8efc4 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -55,8 +55,8 @@ TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore: d->vid = td.vid; d->pid = td.pid; d->serial = td.serial; - Settings set; - d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true"; + Settings set; + d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true"; char *tempSerial = new char[td.serial.size()+1]; #ifdef _WINDOWS @@ -112,13 +112,13 @@ int TellStick::pid() const { return d->pid; } -int TellStick::vid() const { - return d->vid; -} - -std::string TellStick::serial() const { - return d->serial; -} +int TellStick::vid() const { + return d->vid; +} + +std::string TellStick::serial() const { + return d->serial; +} bool TellStick::isOpen() const { return d->open; @@ -146,8 +146,8 @@ void TellStick::processData( const std::string &data ) { setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str())); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); - } else if(d->message.substr(0,2).compare("+W") == 0) { - this->decodePublishData(d->message.substr(2)); + } else if(d->message.substr(0,2).compare("+W") == 0) { + this->decodePublishData(d->message.substr(2)); } d->message.clear(); } else { // Append the character @@ -156,16 +156,16 @@ void TellStick::processData( const std::string &data ) { } } -int TellStick::reset(){ -#ifndef _WINDOWS - return TELLSTICK_SUCCESS; //nothing to be done on other platforms -#else - int success = FT_CyclePort( d->ftHandle ); - if(success == FT_OK){ - return TELLSTICK_SUCCESS; - } - return TELLSTICK_ERROR_UNKNOWN; -#endif +int TellStick::reset(){ +#ifndef _WINDOWS + return TELLSTICK_SUCCESS; //nothing to be done on other platforms +#else + int success = FT_CyclePort( d->ftHandle ); + if(success == FT_OK){ + return TELLSTICK_SUCCESS; + } + return TELLSTICK_ERROR_UNKNOWN; +#endif } void TellStick::run() { @@ -228,20 +228,20 @@ int TellStick::send( const std::string &strMessage ) { FT_STATUS ftStatus; ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten); free(tempMessage); - - if(ftStatus != FT_OK){ - Log::debug("Broken pipe on send"); - return TELLSTICK_ERROR_BROKEN_PIPE; - } - - if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){ - //these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly - return TELLSTICK_SUCCESS; + + if(ftStatus != FT_OK){ + Log::debug("Broken pipe on send"); + return TELLSTICK_ERROR_BROKEN_PIPE; } - if(d->ignoreControllerConfirmation){ - //wait for TellStick to finish its air-sending - msleep(1000); - return TELLSTICK_SUCCESS; + + if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){ + //these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly + return TELLSTICK_SUCCESS; + } + if(d->ignoreControllerConfirmation){ + //wait for TellStick to finish its air-sending + msleep(1000); + return TELLSTICK_SUCCESS; } while(1) { @@ -257,7 +257,7 @@ int TellStick::send( const std::string &strMessage ) { return TELLSTICK_ERROR_COMMUNICATION; } } else { //Error - Log::debug("Broken pipe on read"); + Log::debug("Broken pipe on read"); return TELLSTICK_ERROR_BROKEN_PIPE; } } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index cb852ca5..a45f9899 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -1,142 +1,142 @@ -#include "TelldusMain.h" -#include "ConnectionListener.h" -#include "EventHandler.h" -#include "ClientCommunicationHandler.h" -#include "DeviceManager.h" -#include "ControllerManager.h" -#include "ControllerListener.h" -#include "EventUpdateManager.h" -#include "Timer.h" -#include "Log.h" - -#include -#include -#include - -class TelldusMain::PrivateData { -public: - TelldusCore::EventHandler eventHandler; - TelldusCore::EventRef stopEvent, controllerChangeEvent; -}; - -TelldusMain::TelldusMain(void) -{ - d = new PrivateData; - d->stopEvent = d->eventHandler.addEvent(); - d->controllerChangeEvent = d->eventHandler.addEvent(); -} - -TelldusMain::~TelldusMain(void) { - delete d; -} - -void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { - ControllerChangeEventData *data = new ControllerChangeEventData; - data->vid = vid; - data->pid = pid; - data->inserted = inserted; - d->controllerChangeEvent->signal(data); -} - -void TelldusMain::resume() { - Log::notice("Came back from suspend"); - ControllerChangeEventData *data = new ControllerChangeEventData; - data->vid = 0x0; - data->pid = 0x0; - data->inserted = true; - d->controllerChangeEvent->signal(data); -} - -void TelldusMain::suspend() { - Log::notice("Preparing for suspend"); - ControllerChangeEventData *data = new ControllerChangeEventData; - data->vid = 0x0; - data->pid = 0x0; - data->inserted = false; - d->controllerChangeEvent->signal(data); -} - -void TelldusMain::start(void) { - TelldusCore::EventRef clientEvent = d->eventHandler.addEvent(); - TelldusCore::EventRef dataEvent = d->eventHandler.addEvent(); - TelldusCore::EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups - Timer supervisor(janitor); //Tells the janitor to go back to work - supervisor.setInterval(60); //Once every minute - supervisor.start(); - - EventUpdateManager eventUpdateManager; - TelldusCore::EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); - eventUpdateManager.start(); - ControllerManager controllerManager(dataEvent, deviceUpdateEvent); - DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); - - ConnectionListener clientListener(L"TelldusClient", clientEvent); - - std::list clientCommunicationHandlerList; - - TelldusCore::EventRef handlerEvent = d->eventHandler.addEvent(); - -#ifdef _MACOSX - //This is only needed on OS X - ControllerListener controllerListener(d->controllerChangeEvent); -#endif - - - while(!d->stopEvent->isSignaled()) { - if (!d->eventHandler.waitForAny()) { - continue; - } - if (clientEvent->isSignaled()) { - //New client connection - TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal(); - ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); - if (data) { - ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent, &controllerManager); - clientCommunication->start(); - clientCommunicationHandlerList.push_back(clientCommunication); - } - } - - if (d->controllerChangeEvent->isSignaled()) { - TelldusCore::EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal(); - ControllerChangeEventData *data = reinterpret_cast(eventDataRef.get()); - if (data) { - controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, "", data->inserted); - } - } - - if (dataEvent->isSignaled()) { - TelldusCore::EventDataRef eventData = dataEvent->takeSignal(); - ControllerEventData *data = reinterpret_cast(eventData.get()); - if (data) { - deviceManager.handleControllerMessage(*data); - } - } - - if (handlerEvent->isSignaled()) { - handlerEvent->popSignal(); - for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ - if ((*it)->isDone()){ - delete *it; - it = clientCommunicationHandlerList.erase(it); - - } else { - ++it; - } - } - } - if (janitor->isSignaled()) { - //Clear all of them if there is more than one - while(janitor->isSignaled()) { - janitor->popSignal(); - } - controllerManager.queryControllerStatus(); - } - } - - supervisor.stop(); -} - -void TelldusMain::stop(void){ - d->stopEvent->signal(); -} +#include "TelldusMain.h" +#include "ConnectionListener.h" +#include "EventHandler.h" +#include "ClientCommunicationHandler.h" +#include "DeviceManager.h" +#include "ControllerManager.h" +#include "ControllerListener.h" +#include "EventUpdateManager.h" +#include "Timer.h" +#include "Log.h" + +#include +#include +#include + +class TelldusMain::PrivateData { +public: + TelldusCore::EventHandler eventHandler; + TelldusCore::EventRef stopEvent, controllerChangeEvent; +}; + +TelldusMain::TelldusMain(void) +{ + d = new PrivateData; + d->stopEvent = d->eventHandler.addEvent(); + d->controllerChangeEvent = d->eventHandler.addEvent(); +} + +TelldusMain::~TelldusMain(void) { + delete d; +} + +void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { + ControllerChangeEventData *data = new ControllerChangeEventData; + data->vid = vid; + data->pid = pid; + data->inserted = inserted; + d->controllerChangeEvent->signal(data); +} + +void TelldusMain::resume() { + Log::notice("Came back from suspend"); + ControllerChangeEventData *data = new ControllerChangeEventData; + data->vid = 0x0; + data->pid = 0x0; + data->inserted = true; + d->controllerChangeEvent->signal(data); +} + +void TelldusMain::suspend() { + Log::notice("Preparing for suspend"); + ControllerChangeEventData *data = new ControllerChangeEventData; + data->vid = 0x0; + data->pid = 0x0; + data->inserted = false; + d->controllerChangeEvent->signal(data); +} + +void TelldusMain::start(void) { + TelldusCore::EventRef clientEvent = d->eventHandler.addEvent(); + TelldusCore::EventRef dataEvent = d->eventHandler.addEvent(); + TelldusCore::EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups + Timer supervisor(janitor); //Tells the janitor to go back to work + supervisor.setInterval(60); //Once every minute + supervisor.start(); + + EventUpdateManager eventUpdateManager; + TelldusCore::EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent(); + eventUpdateManager.start(); + ControllerManager controllerManager(dataEvent, deviceUpdateEvent); + DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); + + ConnectionListener clientListener(L"TelldusClient", clientEvent); + + std::list clientCommunicationHandlerList; + + TelldusCore::EventRef handlerEvent = d->eventHandler.addEvent(); + +#ifdef _MACOSX + //This is only needed on OS X + ControllerListener controllerListener(d->controllerChangeEvent); +#endif + + + while(!d->stopEvent->isSignaled()) { + if (!d->eventHandler.waitForAny()) { + continue; + } + if (clientEvent->isSignaled()) { + //New client connection + TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal(); + ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); + if (data) { + ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent, &controllerManager); + clientCommunication->start(); + clientCommunicationHandlerList.push_back(clientCommunication); + } + } + + if (d->controllerChangeEvent->isSignaled()) { + TelldusCore::EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal(); + ControllerChangeEventData *data = reinterpret_cast(eventDataRef.get()); + if (data) { + controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, "", data->inserted); + } + } + + if (dataEvent->isSignaled()) { + TelldusCore::EventDataRef eventData = dataEvent->takeSignal(); + ControllerEventData *data = reinterpret_cast(eventData.get()); + if (data) { + deviceManager.handleControllerMessage(*data); + } + } + + if (handlerEvent->isSignaled()) { + handlerEvent->popSignal(); + for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ + if ((*it)->isDone()){ + delete *it; + it = clientCommunicationHandlerList.erase(it); + + } else { + ++it; + } + } + } + if (janitor->isSignaled()) { + //Clear all of them if there is more than one + while(janitor->isSignaled()) { + janitor->popSignal(); + } + controllerManager.queryControllerStatus(); + } + } + + supervisor.stop(); +} + +void TelldusMain::stop(void){ + d->stopEvent->signal(); +} diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index 13f19486..19f08a4a 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -1,23 +1,23 @@ -#ifndef TELLDUSMAIN_H -#define TELLDUSMAIN_H - -class TelldusMain -{ -public: - TelldusMain(void); - ~TelldusMain(void); - - void start(); - void stop(); - - //Thread safe! - void deviceInsertedOrRemoved(int vid, int pid, bool inserted); - void resume(); - void suspend(); - -private: - class PrivateData; - PrivateData *d; -}; - -#endif //TELLDUSMAIN_H +#ifndef TELLDUSMAIN_H +#define TELLDUSMAIN_H + +class TelldusMain +{ +public: + TelldusMain(void); + ~TelldusMain(void); + + void start(); + void stop(); + + //Thread safe! + void deviceInsertedOrRemoved(int vid, int pid, bool inserted); + void resume(); + void suspend(); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //TELLDUSMAIN_H diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 3fb51221..b122a5c1 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -1,177 +1,177 @@ -#include "TelldusWinService_win.h" -#include "TelldusMain.h" -#include "Log.h" - -#include -#include -#include - -int g_argc; -char **g_argv; - - -static const GUID GUID_DEVINTERFACE_USBRAW = -{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; - -TelldusWinService::TelldusWinService() - :tm(0) -{ - tm = new TelldusMain(); -} - -TelldusWinService::~TelldusWinService() { - delete tm; -} - - -void TelldusWinService::stop() { - tm->stop(); -} - -DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { - switch ( controlCode ) { - case SERVICE_CONTROL_INTERROGATE: - SetServiceStatus( serviceStatusHandle, &serviceStatus ); - return NO_ERROR; - - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - stop(); - serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus( serviceStatusHandle, &serviceStatus ); - - return NO_ERROR; - case SERVICE_CONTROL_POWEREVENT: - if (dwEventType == PBT_APMSUSPEND) { - tm->suspend(); - } else if (dwEventType == PBT_APMRESUMEAUTOMATIC) { - tm->resume(); - } - return NO_ERROR; - } - return ERROR_CALL_NOT_IMPLEMENTED; -} - -DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { - if (controlCode != SERVICE_CONTROL_DEVICEEVENT) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - - if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - - PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast(lpEventData); - if (!pDevInf) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - - std::wstring name(pDevInf->dbcc_name); - transform(name.begin(), name.end(), name.begin(), toupper); - - //Parse VID - size_t posStart = name.find(L"VID_"); - if (posStart == std::wstring::npos) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - posStart += 4; - size_t posEnd = name.find(L'&', posStart); - if (posEnd == std::wstring::npos) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - std::wstring strVID = name.substr(posStart, posEnd-posStart); - - //Parse PID - posStart = name.find(L"PID_"); - if (posStart == std::wstring::npos) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - posStart += 4; - posEnd = name.find(L'#', posStart); - if (posEnd == std::wstring::npos) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - std::wstring strPID = name.substr(posStart, posEnd-posStart); - - long int vid = strtol(std::string(strVID.begin(), strVID.end()).c_str(), NULL, 16); - long int pid = strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16); - - if (dwEventType == DBT_DEVICEARRIVAL) { - tm->deviceInsertedOrRemoved(vid, pid, true); - } else { - tm->deviceInsertedOrRemoved(vid, pid, false); - } - - return NO_ERROR; -} - -DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { - TelldusWinService *instance = reinterpret_cast(lpContext); - if (!instance) { - return ERROR_CALL_NOT_IMPLEMENTED; - } - if (controlCode == SERVICE_CONTROL_DEVICEEVENT) { - return instance->deviceNotificationHandler(controlCode, dwEventType, lpEventData); - } - return instance->serviceControlHandler(controlCode, dwEventType, lpEventData); -} - -void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { - TelldusWinService instance; - - //Enable debug if we hade this supplied - for(unsigned int i = 1; i < argc; ++i) { - if (wcscmp(argv[i], L"--debug") == 0) { - Log::setDebug(); - } - } - - // initialise service status - instance.serviceStatus.dwServiceType = SERVICE_WIN32; - instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; - instance.serviceStatus.dwControlsAccepted = 0; - instance.serviceStatus.dwWin32ExitCode = NO_ERROR; - instance.serviceStatus.dwServiceSpecificExitCode = NO_ERROR; - instance.serviceStatus.dwCheckPoint = 0; - instance.serviceStatus.dwWaitHint = 0; - - instance.serviceStatusHandle = RegisterServiceCtrlHandlerEx( serviceName, TelldusWinService::serviceControlHandler, &instance ); - - if ( instance.serviceStatusHandle ) { - // service is starting - instance.serviceStatus.dwCurrentState = SERVICE_START_PENDING; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - - // running - instance.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - // Register for power management notification - instance.serviceStatus.dwControlsAccepted |= SERVICE_ACCEPT_POWEREVENT; - instance.serviceStatus.dwCurrentState = SERVICE_RUNNING; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - - // Register for device notification - DEV_BROADCAST_DEVICEINTERFACE devInterface; - ZeroMemory( &devInterface, sizeof(devInterface) ); - devInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); - devInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; - devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW; - HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE); - - Log::notice("TelldusService started"); - - //Start our main-loop - instance.tm->start(); - - Log::notice("TelldusService stopping"); - Log::destroy(); - - // service was stopped - instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - - // service is now stopped - instance.serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); - instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; - SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); - } -} +#include "TelldusWinService_win.h" +#include "TelldusMain.h" +#include "Log.h" + +#include +#include +#include + +int g_argc; +char **g_argv; + + +static const GUID GUID_DEVINTERFACE_USBRAW = +{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; + +TelldusWinService::TelldusWinService() + :tm(0) +{ + tm = new TelldusMain(); +} + +TelldusWinService::~TelldusWinService() { + delete tm; +} + + +void TelldusWinService::stop() { + tm->stop(); +} + +DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { + switch ( controlCode ) { + case SERVICE_CONTROL_INTERROGATE: + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + return NO_ERROR; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + stop(); + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + + return NO_ERROR; + case SERVICE_CONTROL_POWEREVENT: + if (dwEventType == PBT_APMSUSPEND) { + tm->suspend(); + } else if (dwEventType == PBT_APMRESUMEAUTOMATIC) { + tm->resume(); + } + return NO_ERROR; + } + return ERROR_CALL_NOT_IMPLEMENTED; +} + +DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) { + if (controlCode != SERVICE_CONTROL_DEVICEEVENT) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + + if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast(lpEventData); + if (!pDevInf) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + + std::wstring name(pDevInf->dbcc_name); + transform(name.begin(), name.end(), name.begin(), toupper); + + //Parse VID + size_t posStart = name.find(L"VID_"); + if (posStart == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + posStart += 4; + size_t posEnd = name.find(L'&', posStart); + if (posEnd == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + std::wstring strVID = name.substr(posStart, posEnd-posStart); + + //Parse PID + posStart = name.find(L"PID_"); + if (posStart == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + posStart += 4; + posEnd = name.find(L'#', posStart); + if (posEnd == std::wstring::npos) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + std::wstring strPID = name.substr(posStart, posEnd-posStart); + + long int vid = strtol(std::string(strVID.begin(), strVID.end()).c_str(), NULL, 16); + long int pid = strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16); + + if (dwEventType == DBT_DEVICEARRIVAL) { + tm->deviceInsertedOrRemoved(vid, pid, true); + } else { + tm->deviceInsertedOrRemoved(vid, pid, false); + } + + return NO_ERROR; +} + +DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) { + TelldusWinService *instance = reinterpret_cast(lpContext); + if (!instance) { + return ERROR_CALL_NOT_IMPLEMENTED; + } + if (controlCode == SERVICE_CONTROL_DEVICEEVENT) { + return instance->deviceNotificationHandler(controlCode, dwEventType, lpEventData); + } + return instance->serviceControlHandler(controlCode, dwEventType, lpEventData); +} + +void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { + TelldusWinService instance; + + //Enable debug if we hade this supplied + for(unsigned int i = 1; i < argc; ++i) { + if (wcscmp(argv[i], L"--debug") == 0) { + Log::setDebug(); + } + } + + // initialise service status + instance.serviceStatus.dwServiceType = SERVICE_WIN32; + instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; + instance.serviceStatus.dwControlsAccepted = 0; + instance.serviceStatus.dwWin32ExitCode = NO_ERROR; + instance.serviceStatus.dwServiceSpecificExitCode = NO_ERROR; + instance.serviceStatus.dwCheckPoint = 0; + instance.serviceStatus.dwWaitHint = 0; + + instance.serviceStatusHandle = RegisterServiceCtrlHandlerEx( serviceName, TelldusWinService::serviceControlHandler, &instance ); + + if ( instance.serviceStatusHandle ) { + // service is starting + instance.serviceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + + // running + instance.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + // Register for power management notification + instance.serviceStatus.dwControlsAccepted |= SERVICE_ACCEPT_POWEREVENT; + instance.serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + + // Register for device notification + DEV_BROADCAST_DEVICEINTERFACE devInterface; + ZeroMemory( &devInterface, sizeof(devInterface) ); + devInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE); + devInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW; + HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE); + + Log::notice("TelldusService started"); + + //Start our main-loop + instance.tm->start(); + + Log::notice("TelldusService stopping"); + Log::destroy(); + + // service was stopped + instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + + // service is now stopped + instance.serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + instance.serviceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); + } +} diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index 04a5df0c..5cd78104 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -1,35 +1,35 @@ -#ifndef TELLDUSSERVICE_WIN_H -#define TELLDUSSERVICE_WIN_H - -#include - -extern int g_argc; -extern char **g_argv; - -class TelldusMain; - -#define serviceName TEXT("TelldusCore") - -class TelldusWinService { -public: - TelldusWinService(); - ~TelldusWinService(); - - static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); - -protected: - - void stop(); - - DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); - DWORD WINAPI deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); - -private: - TelldusMain *tm; - SERVICE_STATUS serviceStatus; - SERVICE_STATUS_HANDLE serviceStatusHandle; - - static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); - -}; -#endif TELLDUSSERVICE_WIN_H +#ifndef TELLDUSSERVICE_WIN_H +#define TELLDUSSERVICE_WIN_H + +#include + +extern int g_argc; +extern char **g_argv; + +class TelldusMain; + +#define serviceName TEXT("TelldusCore") + +class TelldusWinService { +public: + TelldusWinService(); + ~TelldusWinService(); + + static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); + +protected: + + void stop(); + + DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); + DWORD WINAPI deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); + +private: + TelldusMain *tm; + SERVICE_STATUS serviceStatus; + SERVICE_STATUS_HANDLE serviceStatusHandle; + + static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); + +}; +#endif TELLDUSSERVICE_WIN_H diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index a31d0ad2..567befb0 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -1,114 +1,114 @@ -#include "Timer.h" -#include "Mutex.h" -#ifdef _WINDOWS -#else -#include -#include -#endif - -class Timer::PrivateData { -public: - PrivateData() : interval(0), running(false) {} - TelldusCore::EventRef event; - int interval; - bool running; -#ifdef _WINDOWS - HANDLE cond; - TelldusCore::Mutex mutex; -#else - pthread_mutex_t waitMutex; - pthread_cond_t cond; -#endif -}; - -Timer::Timer(TelldusCore::EventRef event) - :TelldusCore::Thread(), d(new PrivateData) -{ - d->event = event; -#ifdef _WINDOWS - d->cond = CreateEventW(NULL, false, false, NULL); -#else - pthread_cond_init(&d->cond, NULL); - pthread_mutex_init(&d->waitMutex, NULL); -#endif -} - -Timer::~Timer() { - this->stop(); - this->wait(); - -#ifdef _WINDOWS -#else - pthread_mutex_destroy(&d->waitMutex); - pthread_cond_destroy(&d->cond); - delete d; -#endif -} - -void Timer::setInterval(int sec) { - d->interval = sec; -} - -void Timer::stop() { -#ifdef _WINDOWS - TelldusCore::MutexLocker(&d->mutex); - d->running = false; - SetEvent(d->cond); -#else - //Signal event - pthread_mutex_lock(&d->waitMutex); - if (d->running) { - d->running = false; - pthread_cond_signal(&d->cond); - } - pthread_mutex_unlock(&d->waitMutex); -#endif -} - -void Timer::run() { -#ifdef _WINDOWS - int interval = 0; - { - TelldusCore::MutexLocker(&d->mutex); - d->running = true; - interval = d->interval*1000; - } - while(1) { - DWORD retval = WaitForSingleObject(d->cond, interval); - if (retval == WAIT_TIMEOUT) { - d->event->signal(); - } - TelldusCore::MutexLocker(&d->mutex); - if (!d->running) { - break; - } - } -#else - struct timespec ts; - struct timeval tp; - - pthread_mutex_lock(&d->waitMutex); - d->running = true; - pthread_mutex_unlock(&d->waitMutex); - - while(1) { - int rc = gettimeofday(&tp, NULL); - - ts.tv_sec = tp.tv_sec; - ts.tv_nsec = tp.tv_usec * 1000; - ts.tv_sec += d->interval; - - pthread_mutex_lock( &d->waitMutex ); - if (d->running) { - rc = pthread_cond_timedwait(&d->cond, &d->waitMutex, &ts); - } else { - pthread_mutex_unlock( &d->waitMutex ); - break; - } - pthread_mutex_unlock( &d->waitMutex ); - if (rc == ETIMEDOUT) { - d->event->signal(); - } - } -#endif -} +#include "Timer.h" +#include "Mutex.h" +#ifdef _WINDOWS +#else +#include +#include +#endif + +class Timer::PrivateData { +public: + PrivateData() : interval(0), running(false) {} + TelldusCore::EventRef event; + int interval; + bool running; +#ifdef _WINDOWS + HANDLE cond; + TelldusCore::Mutex mutex; +#else + pthread_mutex_t waitMutex; + pthread_cond_t cond; +#endif +}; + +Timer::Timer(TelldusCore::EventRef event) + :TelldusCore::Thread(), d(new PrivateData) +{ + d->event = event; +#ifdef _WINDOWS + d->cond = CreateEventW(NULL, false, false, NULL); +#else + pthread_cond_init(&d->cond, NULL); + pthread_mutex_init(&d->waitMutex, NULL); +#endif +} + +Timer::~Timer() { + this->stop(); + this->wait(); + +#ifdef _WINDOWS +#else + pthread_mutex_destroy(&d->waitMutex); + pthread_cond_destroy(&d->cond); + delete d; +#endif +} + +void Timer::setInterval(int sec) { + d->interval = sec; +} + +void Timer::stop() { +#ifdef _WINDOWS + TelldusCore::MutexLocker(&d->mutex); + d->running = false; + SetEvent(d->cond); +#else + //Signal event + pthread_mutex_lock(&d->waitMutex); + if (d->running) { + d->running = false; + pthread_cond_signal(&d->cond); + } + pthread_mutex_unlock(&d->waitMutex); +#endif +} + +void Timer::run() { +#ifdef _WINDOWS + int interval = 0; + { + TelldusCore::MutexLocker(&d->mutex); + d->running = true; + interval = d->interval*1000; + } + while(1) { + DWORD retval = WaitForSingleObject(d->cond, interval); + if (retval == WAIT_TIMEOUT) { + d->event->signal(); + } + TelldusCore::MutexLocker(&d->mutex); + if (!d->running) { + break; + } + } +#else + struct timespec ts; + struct timeval tp; + + pthread_mutex_lock(&d->waitMutex); + d->running = true; + pthread_mutex_unlock(&d->waitMutex); + + while(1) { + int rc = gettimeofday(&tp, NULL); + + ts.tv_sec = tp.tv_sec; + ts.tv_nsec = tp.tv_usec * 1000; + ts.tv_sec += d->interval; + + pthread_mutex_lock( &d->waitMutex ); + if (d->running) { + rc = pthread_cond_timedwait(&d->cond, &d->waitMutex, &ts); + } else { + pthread_mutex_unlock( &d->waitMutex ); + break; + } + pthread_mutex_unlock( &d->waitMutex ); + if (rc == ETIMEDOUT) { + d->event->signal(); + } + } +#endif +} diff --git a/telldus-core/service/ftd2xx.h b/telldus-core/service/ftd2xx.h index f9d7b817..020aff93 100644 --- a/telldus-core/service/ftd2xx.h +++ b/telldus-core/service/ftd2xx.h @@ -1,15 +1,15 @@ - - -#ifdef LIBFTD2XX - #ifdef _WINDOWS - #include - #include "win\ftd2xx.h" - #else - #include "osx/WinTypes.h" - #include "osx/ftd2xx.h" - #endif -#endif - -#ifdef LIBFTDI - #include -#endif + + +#ifdef LIBFTD2XX + #ifdef _WINDOWS + #include + #include "win\ftd2xx.h" + #else + #include "osx/WinTypes.h" + #include "osx/ftd2xx.h" + #endif +#endif + +#ifdef LIBFTDI + #include +#endif diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp index 95257b1e..018e61ee 100644 --- a/telldus-core/service/main_win.cpp +++ b/telldus-core/service/main_win.cpp @@ -1,20 +1,20 @@ -#include "TelldusWinService_win.h" -//#include - -#include -#include - - -int main(int argc, char **argv) { - g_argc = argc; - g_argv = argv; - - SERVICE_TABLE_ENTRY serviceTable[] = { - {serviceName, TelldusWinService::serviceMain }, - { 0, 0 } - }; - - StartServiceCtrlDispatcher( serviceTable ); - - return 0; -} +#include "TelldusWinService_win.h" +//#include + +#include +#include + + +int main(int argc, char **argv) { + g_argc = argc; + g_argv = argv; + + SERVICE_TABLE_ENTRY serviceTable[] = { + {serviceName, TelldusWinService::serviceMain }, + { 0, 0 } + }; + + StartServiceCtrlDispatcher( serviceTable ); + + return 0; +} diff --git a/telldus-core/service/win/ftd2xx.h b/telldus-core/service/win/ftd2xx.h index 96a4d318..d5bc3bff 100644 --- a/telldus-core/service/win/ftd2xx.h +++ b/telldus-core/service/win/ftd2xx.h @@ -1,963 +1,963 @@ -/*++ - -Copyright (c) 2001-2007 Future Technology Devices International Ltd. - -Module Name: - - ftd2xx.h - -Abstract: - - Native USB device driver for FTDI FT8U232/245 - FTD2XX library definitions - -Environment: - - kernel & user mode - -Revision History: - - 13/03/01 awm Created. - 13/01/03 awm Added device information support. - 19/03/03 awm Added FT_W32_CancelIo. - 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. - 18/09/03 awm Added FT_SetResetPipeRetryCount. - 10/10/03 awm Added FT_ResetPort. - 23/01/04 awm Added support for open-by-location. - 16/03/04 awm Added support for FT2232C. - 23/09/04 awm Added support for FT232R. - 20/10/04 awm Added FT_CyclePort. - 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. - 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. - 25/08/05 awm Added FT_SetDeadmanTimeout. - 02/12/05 awm Removed obsolete references. - 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. - 08/09/06 awm Added FT_W32_GetCommMask. - 11/09/06 awm Added FT_Rescan. - 11/07/07 awm Added support for FT2232H and FT4232H. - 10/08/07 awm Added flags definitions. - 21/11/07 mja Added FT_GetComPortNumber. - 05/06/08 mja Added EEPROM extensions for FT2232H. - - ---*/ - - -#ifndef FTD2XX_H -#define FTD2XX_H - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// FTD2XX_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef FTD2XX_EXPORTS -#define FTD2XX_API __declspec(dllexport) -#else -#define FTD2XX_API __declspec(dllimport) -#endif - - -typedef PVOID FT_HANDLE; -typedef ULONG FT_STATUS; - -// -// Device status -// -enum { - FT_OK, - FT_INVALID_HANDLE, - FT_DEVICE_NOT_FOUND, - FT_DEVICE_NOT_OPENED, - FT_IO_ERROR, - FT_INSUFFICIENT_RESOURCES, - FT_INVALID_PARAMETER, - FT_INVALID_BAUD_RATE, - - FT_DEVICE_NOT_OPENED_FOR_ERASE, - FT_DEVICE_NOT_OPENED_FOR_WRITE, - FT_FAILED_TO_WRITE_DEVICE, - FT_EEPROM_READ_FAILED, - FT_EEPROM_WRITE_FAILED, - FT_EEPROM_ERASE_FAILED, - FT_EEPROM_NOT_PRESENT, - FT_EEPROM_NOT_PROGRAMMED, - FT_INVALID_ARGS, - FT_NOT_SUPPORTED, - FT_OTHER_ERROR, - FT_DEVICE_LIST_NOT_READY, -}; - - -#define FT_SUCCESS(status) ((status) == FT_OK) - -// -// FT_OpenEx Flags -// - -#define FT_OPEN_BY_SERIAL_NUMBER 1 -#define FT_OPEN_BY_DESCRIPTION 2 -#define FT_OPEN_BY_LOCATION 4 - -// -// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags -// - -#define FT_LIST_NUMBER_ONLY 0x80000000 -#define FT_LIST_BY_INDEX 0x40000000 -#define FT_LIST_ALL 0x20000000 - -#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) - -// -// Baud Rates -// - -#define FT_BAUD_300 300 -#define FT_BAUD_600 600 -#define FT_BAUD_1200 1200 -#define FT_BAUD_2400 2400 -#define FT_BAUD_4800 4800 -#define FT_BAUD_9600 9600 -#define FT_BAUD_14400 14400 -#define FT_BAUD_19200 19200 -#define FT_BAUD_38400 38400 -#define FT_BAUD_57600 57600 -#define FT_BAUD_115200 115200 -#define FT_BAUD_230400 230400 -#define FT_BAUD_460800 460800 -#define FT_BAUD_921600 921600 - -// -// Word Lengths -// - -#define FT_BITS_8 (UCHAR) 8 -#define FT_BITS_7 (UCHAR) 7 -#define FT_BITS_6 (UCHAR) 6 -#define FT_BITS_5 (UCHAR) 5 - -// -// Stop Bits -// - -#define FT_STOP_BITS_1 (UCHAR) 0 -#define FT_STOP_BITS_1_5 (UCHAR) 1 -#define FT_STOP_BITS_2 (UCHAR) 2 - -// -// Parity -// - -#define FT_PARITY_NONE (UCHAR) 0 -#define FT_PARITY_ODD (UCHAR) 1 -#define FT_PARITY_EVEN (UCHAR) 2 -#define FT_PARITY_MARK (UCHAR) 3 -#define FT_PARITY_SPACE (UCHAR) 4 - -// -// Flow Control -// - -#define FT_FLOW_NONE 0x0000 -#define FT_FLOW_RTS_CTS 0x0100 -#define FT_FLOW_DTR_DSR 0x0200 -#define FT_FLOW_XON_XOFF 0x0400 - -// -// Purge rx and tx buffers -// -#define FT_PURGE_RX 1 -#define FT_PURGE_TX 2 - -// -// Events -// - -typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); - -#define FT_EVENT_RXCHAR 1 -#define FT_EVENT_MODEM_STATUS 2 -#define FT_EVENT_LINE_STATUS 4 - -// -// Timeouts -// - -#define FT_DEFAULT_RX_TIMEOUT 300 -#define FT_DEFAULT_TX_TIMEOUT 300 - -// -// Device types -// - -typedef ULONG FT_DEVICE; - -enum { - FT_DEVICE_BM, - FT_DEVICE_AM, - FT_DEVICE_100AX, - FT_DEVICE_UNKNOWN, - FT_DEVICE_2232C, - FT_DEVICE_232R, - FT_DEVICE_2232H, - FT_DEVICE_4232H -}; - - -#ifdef __cplusplus -extern "C" { -#endif - - -FTD2XX_API -FT_STATUS WINAPI FT_Open( - int deviceNumber, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_OpenEx( - PVOID pArg1, - DWORD Flags, - FT_HANDLE *pHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ListDevices( - PVOID pArg1, - PVOID pArg2, - DWORD Flags - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Close( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Read( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToRead, - LPDWORD lpBytesReturned - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Write( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD dwBytesToWrite, - LPDWORD lpBytesWritten - ); - -FTD2XX_API -FT_STATUS WINAPI FT_IoCtl( - FT_HANDLE ftHandle, - DWORD dwIoControlCode, - LPVOID lpInBuf, - DWORD nInBufSize, - LPVOID lpOutBuf, - DWORD nOutBufSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBaudRate( - FT_HANDLE ftHandle, - ULONG BaudRate - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDivisor( - FT_HANDLE ftHandle, - USHORT Divisor - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDataCharacteristics( - FT_HANDLE ftHandle, - UCHAR WordLength, - UCHAR StopBits, - UCHAR Parity - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetFlowControl( - FT_HANDLE ftHandle, - USHORT FlowControl, - UCHAR XonChar, - UCHAR XoffChar - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetDevice( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrDtr( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ClrRts( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetModemStatus( - FT_HANDLE ftHandle, - ULONG *pModemStatus - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetChars( - FT_HANDLE ftHandle, - UCHAR EventChar, - UCHAR EventCharEnabled, - UCHAR ErrorChar, - UCHAR ErrorCharEnabled - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Purge( - FT_HANDLE ftHandle, - ULONG Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetTimeouts( - FT_HANDLE ftHandle, - ULONG ReadTimeout, - ULONG WriteTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetQueueStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetEventNotification( - FT_HANDLE ftHandle, - DWORD Mask, - PVOID Param - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetStatus( - FT_HANDLE ftHandle, - DWORD *dwRxBytes, - DWORD *dwTxBytes, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOn( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBreakOff( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetWaitMask( - FT_HANDLE ftHandle, - DWORD Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WaitOnMask( - FT_HANDLE ftHandle, - DWORD *Mask - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetEventStatus( - FT_HANDLE ftHandle, - DWORD *dwEventDWord - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ReadEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - LPWORD lpwValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_WriteEE( - FT_HANDLE ftHandle, - DWORD dwWordOffset, - WORD wValue - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EraseEE( - FT_HANDLE ftHandle - ); - -// -// structure to hold program data for FT_Program function -// -typedef struct ft_program_data { - - DWORD Signature1; // Header - must be 0x00000000 - DWORD Signature2; // Header - must be 0xffffffff - DWORD Version; // Header - FT_PROGRAM_DATA version - // 0 = original - // 1 = FT2232C extensions - // 2 = FT232R extensions - // 3 = FT2232H extensions - // 4 = FT4232H extensions - - WORD VendorId; // 0x0403 - WORD ProductId; // 0x6001 - char *Manufacturer; // "FTDI" - char *ManufacturerId; // "FT" - char *Description; // "USB HS Serial Converter" - char *SerialNumber; // "FT000001" if fixed, or NULL - WORD MaxPower; // 0 < MaxPower <= 500 - WORD PnP; // 0 = disabled, 1 = enabled - WORD SelfPowered; // 0 = bus powered, 1 = self powered - WORD RemoteWakeup; // 0 = not capable, 1 = capable - // - // Rev4 (FT232B) extensions - // - UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise - UCHAR IsoIn; // non-zero if in endpoint is isochronous - UCHAR IsoOut; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable; // non-zero if pull down enabled - UCHAR SerNumEnable; // non-zero if serial number to be used - UCHAR USBVersionEnable; // non-zero if chip uses USBVersion - WORD USBVersion; // BCD (0x0200 => USB2) - // - // Rev 5 (FT2232) extensions - // - UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise - UCHAR IsoInA; // non-zero if in endpoint is isochronous - UCHAR IsoInB; // non-zero if in endpoint is isochronous - UCHAR IsoOutA; // non-zero if out endpoint is isochronous - UCHAR IsoOutB; // non-zero if out endpoint is isochronous - UCHAR PullDownEnable5; // non-zero if pull down enabled - UCHAR SerNumEnable5; // non-zero if serial number to be used - UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion - WORD USBVersion5; // BCD (0x0200 => USB2) - UCHAR AIsHighCurrent; // non-zero if interface is high current - UCHAR BIsHighCurrent; // non-zero if interface is high current - UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer; // non-zero if interface is Fast serial - UCHAR AIsVCP; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer; // non-zero if interface is Fast serial - UCHAR BIsVCP; // non-zero if interface is to use VCP drivers - // - // Rev 6 (FT232R) extensions - // - UCHAR UseExtOsc; // Use External Oscillator - UCHAR HighDriveIOs; // High Drive I/Os - UCHAR EndpointSize; // Endpoint size - UCHAR PullDownEnableR; // non-zero if pull down enabled - UCHAR SerNumEnableR; // non-zero if serial number to be used - UCHAR InvertTXD; // non-zero if invert TXD - UCHAR InvertRXD; // non-zero if invert RXD - UCHAR InvertRTS; // non-zero if invert RTS - UCHAR InvertCTS; // non-zero if invert CTS - UCHAR InvertDTR; // non-zero if invert DTR - UCHAR InvertDSR; // non-zero if invert DSR - UCHAR InvertDCD; // non-zero if invert DCD - UCHAR InvertRI; // non-zero if invert RI - UCHAR Cbus0; // Cbus Mux control - UCHAR Cbus1; // Cbus Mux control - UCHAR Cbus2; // Cbus Mux control - UCHAR Cbus3; // Cbus Mux control - UCHAR Cbus4; // Cbus Mux control - UCHAR RIsD2XX; // non-zero if using D2XX driver - // - // Rev 7 (FT2232H) Extensions - // - UCHAR PullDownEnable7; // non-zero if pull down enabled - UCHAR SerNumEnable7; // non-zero if serial number to be used - UCHAR ALSlowSlew; // non-zero if AL pins have slow slew - UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR AHSlowSlew; // non-zero if AH pins have slow slew - UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BLSlowSlew; // non-zero if BL pins have slow slew - UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BHSlowSlew; // non-zero if BH pins have slow slew - UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial - UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO - UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target - UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial - UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers - UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs - // - // Rev 8 (FT4232H) Extensions - // - UCHAR PullDownEnable8; // non-zero if pull down enabled - UCHAR SerNumEnable8; // non-zero if serial number to be used - UCHAR ASlowSlew; // non-zero if AL pins have slow slew - UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input - UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR BSlowSlew; // non-zero if AH pins have slow slew - UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input - UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR CSlowSlew; // non-zero if BL pins have slow slew - UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input - UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR DSlowSlew; // non-zero if BH pins have slow slew - UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input - UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA - UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN - UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN - UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN - UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN - UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers - UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers - -} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Program( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ProgramEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_Read( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_ReadEx( - FT_HANDLE ftHandle, - PFT_PROGRAM_DATA pData, - char *Manufacturer, - char *ManufacturerId, - char *Description, - char *SerialNumber - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UASize( - FT_HANDLE ftHandle, - LPDWORD lpdwSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UAWrite( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen - ); - -FTD2XX_API -FT_STATUS WINAPI FT_EE_UARead( - FT_HANDLE ftHandle, - PUCHAR pucData, - DWORD dwDataLen, - LPDWORD lpdwBytesRead - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetLatencyTimer( - FT_HANDLE ftHandle, - UCHAR ucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLatencyTimer( - FT_HANDLE ftHandle, - PUCHAR pucLatency - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetBitMode( - FT_HANDLE ftHandle, - UCHAR ucMask, - UCHAR ucEnable - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetBitMode( - FT_HANDLE ftHandle, - PUCHAR pucMode - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetUSBParameters( - FT_HANDLE ftHandle, - ULONG ulInTransferSize, - ULONG ulOutTransferSize - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetDeadmanTimeout( - FT_HANDLE ftHandle, - ULONG ulDeadmanTimeout - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfo( - FT_HANDLE ftHandle, - FT_DEVICE *lpftDevice, - LPDWORD lpdwID, - PCHAR SerialNumber, - PCHAR Description, - LPVOID Dummy - ); - -FTD2XX_API -FT_STATUS WINAPI FT_StopInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_RestartInTask( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_SetResetPipeRetryCount( - FT_HANDLE ftHandle, - DWORD dwCount - ); - -FTD2XX_API -FT_STATUS WINAPI FT_ResetPort( - FT_HANDLE ftHandle - ); - -FTD2XX_API -FT_STATUS WINAPI FT_CyclePort( - FT_HANDLE ftHandle - ); - - -// -// Win32-type functions -// - -FTD2XX_API -FT_HANDLE WINAPI FT_W32_CreateFile( - LPCTSTR lpszName, - DWORD dwAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreate, - DWORD dwAttrsAndFlags, - HANDLE hTemplate - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CloseHandle( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ReadFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesReturned, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WriteFile( - FT_HANDLE ftHandle, - LPVOID lpBuffer, - DWORD nBufferSize, - LPDWORD lpBytesWritten, - LPOVERLAPPED lpOverlapped - ); - -FTD2XX_API -DWORD WINAPI FT_W32_GetLastError( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetOverlappedResult( - FT_HANDLE ftHandle, - LPOVERLAPPED lpOverlapped, - LPDWORD lpdwBytesTransferred, - BOOL bWait - ); - -FTD2XX_API -BOOL WINAPI FT_W32_CancelIo( - FT_HANDLE ftHandle - ); - - -// -// Win32 COMM API type functions -// -typedef struct _FTCOMSTAT { - DWORD fCtsHold : 1; - DWORD fDsrHold : 1; - DWORD fRlsdHold : 1; - DWORD fXoffHold : 1; - DWORD fXoffSent : 1; - DWORD fEof : 1; - DWORD fTxim : 1; - DWORD fReserved : 25; - DWORD cbInQue; - DWORD cbOutQue; -} FTCOMSTAT, *LPFTCOMSTAT; - -typedef struct _FTDCB { - DWORD DCBlength; /* sizeof(FTDCB) */ - DWORD BaudRate; /* Baudrate at which running */ - DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ - DWORD fParity: 1; /* Enable parity checking */ - DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ - DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ - DWORD fDtrControl:2; /* DTR Flow control */ - DWORD fDsrSensitivity:1; /* DSR Sensitivity */ - DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ - DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ - DWORD fInX: 1; /* Enable input X-ON/X-OFF */ - DWORD fErrorChar: 1; /* Enable Err Replacement */ - DWORD fNull: 1; /* Enable Null stripping */ - DWORD fRtsControl:2; /* Rts Flow control */ - DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ - DWORD fDummy2:17; /* Reserved */ - WORD wReserved; /* Not currently used */ - WORD XonLim; /* Transmit X-ON threshold */ - WORD XoffLim; /* Transmit X-OFF threshold */ - BYTE ByteSize; /* Number of bits/byte, 4-8 */ - BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ - BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ - char XonChar; /* Tx and Rx X-ON character */ - char XoffChar; /* Tx and Rx X-OFF character */ - char ErrorChar; /* Error replacement char */ - char EofChar; /* End of Input character */ - char EvtChar; /* Received Event character */ - WORD wReserved1; /* Fill for now. */ -} FTDCB, *LPFTDCB; - -typedef struct _FTTIMEOUTS { - DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ - DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ - DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ - DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ -} FTTIMEOUTS,*LPFTTIMEOUTS; - - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_ClearCommError( - FT_HANDLE ftHandle, - LPDWORD lpdwErrors, - LPFTCOMSTAT lpftComstat - ); - -FTD2XX_API -BOOL WINAPI FT_W32_EscapeCommFunction( - FT_HANDLE ftHandle, - DWORD dwFunc - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommModemStatus( - FT_HANDLE ftHandle, - LPDWORD lpdwModemStatus - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_PurgeComm( - FT_HANDLE ftHandle, - DWORD dwMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommBreak( - FT_HANDLE ftHandle - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommMask( - FT_HANDLE ftHandle, - ULONG ulEventMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_GetCommMask( - FT_HANDLE ftHandle, - LPDWORD lpdwEventMask - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommState( - FT_HANDLE ftHandle, - LPFTDCB lpftDcb - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetCommTimeouts( - FT_HANDLE ftHandle, - FTTIMEOUTS *pTimeouts - ); - -FTD2XX_API -BOOL WINAPI FT_W32_SetupComm( - FT_HANDLE ftHandle, - DWORD dwReadBufferSize, - DWORD dwWriteBufferSize - ); - -FTD2XX_API -BOOL WINAPI FT_W32_WaitCommEvent( - FT_HANDLE ftHandle, - PULONG pulEvent, - LPOVERLAPPED lpOverlapped - ); - - -// -// Device information -// - -typedef struct _ft_device_list_info_node { - ULONG Flags; - ULONG Type; - ULONG ID; - DWORD LocId; - char SerialNumber[16]; - char Description[64]; - FT_HANDLE ftHandle; -} FT_DEVICE_LIST_INFO_NODE; - -// Device information flags -enum { - FT_FLAGS_OPENED = 1, - FT_FLAGS_HISPEED = 2 -}; - - -FTD2XX_API -FT_STATUS WINAPI FT_CreateDeviceInfoList( - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoList( - FT_DEVICE_LIST_INFO_NODE *pDest, - LPDWORD lpdwNumDevs - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetDeviceInfoDetail( - DWORD dwIndex, - LPDWORD lpdwFlags, - LPDWORD lpdwType, - LPDWORD lpdwID, - LPDWORD lpdwLocId, - LPVOID lpSerialNumber, - LPVOID lpDescription, - FT_HANDLE *pftHandle - ); - - -// -// Version information -// - -FTD2XX_API -FT_STATUS WINAPI FT_GetDriverVersion( - FT_HANDLE ftHandle, - LPDWORD lpdwVersion - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetLibraryVersion( - LPDWORD lpdwVersion - ); - - -FTD2XX_API -FT_STATUS WINAPI FT_Rescan( - void - ); - -FTD2XX_API -FT_STATUS WINAPI FT_Reload( - WORD wVid, - WORD wPid - ); - -FTD2XX_API -FT_STATUS WINAPI FT_GetComPortNumber( - FT_HANDLE ftHandle, - LPLONG lpdwComPortNumber - ); - - - -#ifdef __cplusplus -} -#endif - - -#endif /* FTD2XX_H */ - +/*++ + +Copyright (c) 2001-2007 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB device driver for FTDI FT8U232/245 + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + 23/01/04 awm Added support for open-by-location. + 16/03/04 awm Added support for FT2232C. + 23/09/04 awm Added support for FT232R. + 20/10/04 awm Added FT_CyclePort. + 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. + 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. + 25/08/05 awm Added FT_SetDeadmanTimeout. + 02/12/05 awm Removed obsolete references. + 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. + 08/09/06 awm Added FT_W32_GetCommMask. + 11/09/06 awm Added FT_Rescan. + 11/07/07 awm Added support for FT2232H and FT4232H. + 10/08/07 awm Added flags definitions. + 21/11/07 mja Added FT_GetComPortNumber. + 05/06/08 mja Added EEPROM extensions for FT2232H. + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR, + FT_DEVICE_LIST_NOT_READY, +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_LINE_STATUS 4 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R, + FT_DEVICE_2232H, + FT_DEVICE_4232H +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToRead, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToWrite, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + // 3 = FT2232H extensions + // 4 = FT4232H extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 (FT232B) extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // Rev 5 (FT2232) extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // Rev 6 (FT232R) extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR RIsD2XX; // non-zero if using D2XX driver + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // + // Rev 8 (FT4232H) Extensions + // + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if AL pins have slow slew + UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if AH pins have slow slew + UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if BL pins have slow slew + UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if BH pins have slow slew + UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCTSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommMask( + FT_HANDLE ftHandle, + LPDWORD lpdwEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +// Device information flags +enum { + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 +}; + + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + +FTD2XX_API +FT_STATUS WINAPI FT_Rescan( + void + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Reload( + WORD wVid, + WORD wPid + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetComPortNumber( + FT_HANDLE ftHandle, + LPLONG lpdwComPortNumber + ); + + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + diff --git a/telldus-core/tdadmin/CMakeLists.txt b/telldus-core/tdadmin/CMakeLists.txt index 501baabe..7c72b26b 100644 --- a/telldus-core/tdadmin/CMakeLists.txt +++ b/telldus-core/tdadmin/CMakeLists.txt @@ -1,79 +1,79 @@ -PROJECT(tdadmin) - -cmake_policy(SET CMP0005 NEW) - -SET (tdadmin_DESCRIPTION - "a command line utility to edit devices and controllers for Telldus TellStick" -) - -SET(tdadmin_SRCS - main.cpp -) - -ADD_EXECUTABLE(tdadmin - ${tdadmin_SRCS} -) - -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/driver -) - -ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) - -IF (WIN32) - FIND_LIBRARY(TELLDUSCORE_LIBRARY TelldusCore) - TARGET_LINK_LIBRARIES(tdadmin - ${TELLDUSCORE_LIBRARY} - ) -ELSEIF (APPLE) - TARGET_LINK_LIBRARIES(tdadmin - TelldusCore - ) -ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - # FreeBSD does not have argp in base libc; port devel/argp-standalone is required. - FIND_LIBRARY(ARGP_LIBRARY argp) - TARGET_LINK_LIBRARIES(tdadmin - ${CMAKE_BINARY_DIR}/client/libtelldus-core.so - ${ARGP_LIBRARY} - ) -ELSE (WIN32) - TARGET_LINK_LIBRARIES(tdadmin - ${CMAKE_BINARY_DIR}/client/libtelldus-core.so - ) -ENDIF (WIN32) - -IF (UNIX) - IF (GENERATE_MAN) - ADD_CUSTOM_COMMAND( - TARGET tdadmin - POST_BUILD - COMMAND help2man -n ${tdadmin_DESCRIPTION} ./tdadmin > tdadmin.1 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating man file tdadmin.1" - ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tdadmin.1 DESTINATION share/man/man1) - ENDIF (GENERATE_MAN) -ENDIF (UNIX) - -INSTALL(TARGETS tdadmin RUNTIME DESTINATION sbin) - -IF (UNIX AND NOT APPLE) - SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) - CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/05-tellstick.rules - ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules - @ONLY - ) - CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/udev.sh - ${CMAKE_BINARY_DIR}/parsed/udev.sh - @ONLY - ) - INSTALL(FILES ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules - DESTINATION ${UDEV_RULES_DIR} - ) - INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/parsed/udev.sh - DESTINATION share/telldus-core/helpers/ - ) -ENDIF (UNIX AND NOT APPLE) +PROJECT(tdadmin) + +cmake_policy(SET CMP0005 NEW) + +SET (tdadmin_DESCRIPTION + "a command line utility to edit devices and controllers for Telldus TellStick" +) + +SET(tdadmin_SRCS + main.cpp +) + +ADD_EXECUTABLE(tdadmin + ${tdadmin_SRCS} +) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/driver +) + +ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) + +IF (WIN32) + FIND_LIBRARY(TELLDUSCORE_LIBRARY TelldusCore) + TARGET_LINK_LIBRARIES(tdadmin + ${TELLDUSCORE_LIBRARY} + ) +ELSEIF (APPLE) + TARGET_LINK_LIBRARIES(tdadmin + TelldusCore + ) +ELSEIF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + # FreeBSD does not have argp in base libc; port devel/argp-standalone is required. + FIND_LIBRARY(ARGP_LIBRARY argp) + TARGET_LINK_LIBRARIES(tdadmin + ${CMAKE_BINARY_DIR}/client/libtelldus-core.so + ${ARGP_LIBRARY} + ) +ELSE (WIN32) + TARGET_LINK_LIBRARIES(tdadmin + ${CMAKE_BINARY_DIR}/client/libtelldus-core.so + ) +ENDIF (WIN32) + +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET tdadmin + POST_BUILD + COMMAND help2man -n ${tdadmin_DESCRIPTION} ./tdadmin > tdadmin.1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file tdadmin.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tdadmin.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + +INSTALL(TARGETS tdadmin RUNTIME DESTINATION sbin) + +IF (UNIX AND NOT APPLE) + SET(UDEV_RULES_DIR "/etc/udev/rules.d" CACHE PATH "The directory where udev store its rules" ) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/05-tellstick.rules + ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules + @ONLY + ) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/udev.sh + ${CMAKE_BINARY_DIR}/parsed/udev.sh + @ONLY + ) + INSTALL(FILES ${CMAKE_BINARY_DIR}/parsed/05-tellstick.rules + DESTINATION ${UDEV_RULES_DIR} + ) + INSTALL(PROGRAMS ${CMAKE_BINARY_DIR}/parsed/udev.sh + DESTINATION share/telldus-core/helpers/ + ) +ENDIF (UNIX AND NOT APPLE) diff --git a/telldus-core/tdadmin/main.cpp b/telldus-core/tdadmin/main.cpp index 698f13b0..cb4b3b59 100644 --- a/telldus-core/tdadmin/main.cpp +++ b/telldus-core/tdadmin/main.cpp @@ -1,85 +1,85 @@ -#include "../client/telldus-core.h" -#include -#include -#include -#include - -const char *argp_program_version = "tdadmin " VERSION ; -const char *argp_program_bug_address = ""; - -static char args_doc[] = "COMMAND ACTION"; - -static char doc[] = "TellStick admin tool -- a command line utility to edit devices and controllers for Telldus TellStick"; - -const int VID = 1; -const int PID = 2; -const int SERIAL = 3; - -static struct argp_option options[] = { - {0,0,0,0, - "COMMAND: controller, ACTION: connect/disconnect\n" - "Tells the daemon to add or remove a TellStick (duo)" - }, - {"vid",VID,"VID",0, "The vendor id (1781)" }, - {"pid",PID,"PID",0,"The product id (0c30 or 0c31)" }, - {"serial",SERIAL,"SERIAL",0,"The usb serial number" }, - { 0 } -}; - -static std::string command, action; - -int vid, pid; -static std::string serial; - -static error_t parse_opt (int key, char *arg, struct argp_state *state) { - switch (key) { - case PID: - pid = strtol(arg, NULL, 16); - break; - case SERIAL: - serial = arg; - break; - case VID: - vid = strtol(arg, NULL, 16); - break; - - case ARGP_KEY_NO_ARGS: - argp_usage (state); - - case ARGP_KEY_ARG: - command = arg; - action = state->argv[state->next]; - state->next = state->argc; - - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static struct argp argp = { options, parse_opt, args_doc, doc }; - -void handle_controller(void) { - if (vid == 0 || pid == 0) { - fprintf(stderr, "Missing parameter vid or pid\n"); - } - if (action.compare("connect") == 0) { - tdConnectTellStickController(vid,pid,serial.c_str()); - - } else if (action.compare("disconnect") == 0) { - tdDisconnectTellStickController(vid,pid,serial.c_str()); - } -} - -int main(int argc, char **argv) { - - argp_parse (&argp, argc, argv, 0, 0, 0); - - if (command.compare("controller") == 0) { - handle_controller(); - } - - return 0; -} +#include "../client/telldus-core.h" +#include +#include +#include +#include + +const char *argp_program_version = "tdadmin " VERSION ; +const char *argp_program_bug_address = ""; + +static char args_doc[] = "COMMAND ACTION"; + +static char doc[] = "TellStick admin tool -- a command line utility to edit devices and controllers for Telldus TellStick"; + +const int VID = 1; +const int PID = 2; +const int SERIAL = 3; + +static struct argp_option options[] = { + {0,0,0,0, + "COMMAND: controller, ACTION: connect/disconnect\n" + "Tells the daemon to add or remove a TellStick (duo)" + }, + {"vid",VID,"VID",0, "The vendor id (1781)" }, + {"pid",PID,"PID",0,"The product id (0c30 or 0c31)" }, + {"serial",SERIAL,"SERIAL",0,"The usb serial number" }, + { 0 } +}; + +static std::string command, action; + +int vid, pid; +static std::string serial; + +static error_t parse_opt (int key, char *arg, struct argp_state *state) { + switch (key) { + case PID: + pid = strtol(arg, NULL, 16); + break; + case SERIAL: + serial = arg; + break; + case VID: + vid = strtol(arg, NULL, 16); + break; + + case ARGP_KEY_NO_ARGS: + argp_usage (state); + + case ARGP_KEY_ARG: + command = arg; + action = state->argv[state->next]; + state->next = state->argc; + + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; + +void handle_controller(void) { + if (vid == 0 || pid == 0) { + fprintf(stderr, "Missing parameter vid or pid\n"); + } + if (action.compare("connect") == 0) { + tdConnectTellStickController(vid,pid,serial.c_str()); + + } else if (action.compare("disconnect") == 0) { + tdDisconnectTellStickController(vid,pid,serial.c_str()); + } +} + +int main(int argc, char **argv) { + + argp_parse (&argp, argc, argv, 0, 0, 0); + + if (command.compare("controller") == 0) { + handle_controller(); + } + + return 0; +} diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt index d9016d34..c9aeb07b 100644 --- a/telldus-core/tdtool/CMakeLists.txt +++ b/telldus-core/tdtool/CMakeLists.txt @@ -1,56 +1,56 @@ -PROJECT(tdtool) - -cmake_policy(SET CMP0005 NEW) - -SET (tdtool_DESCRIPTION - "a command line utility to send commands to a Telldus TellStick" -) - -SET(tdtool_SRCS - main.cpp -) - -ADD_EXECUTABLE(tdtool - ${tdtool_SRCS} -) -SIGN(tdtool) - -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/driver -) - -ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) - -IF (WIN32) - TARGET_LINK_LIBRARIES(tdtool - TelldusCore - openbsd-getopt - ) - INCLUDE_DIRECTORIES( - ${CMAKE_SOURCE_DIR}/3rdparty/openbsd-getopt - ) -ELSEIF (APPLE) - TARGET_LINK_LIBRARIES(tdtool - TelldusCore - ) -ELSE (WIN32) - TARGET_LINK_LIBRARIES(tdtool - ${CMAKE_BINARY_DIR}/client/libtelldus-core.so - ) -ENDIF (WIN32) - -IF (UNIX) - IF (GENERATE_MAN) - ADD_CUSTOM_COMMAND( - TARGET tdtool - POST_BUILD - COMMAND help2man -n ${tdtool_DESCRIPTION} ./tdtool > tdtool.1 - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating man file tdtool.1" - ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tdtool.1 DESTINATION share/man/man1) - ENDIF (GENERATE_MAN) -ENDIF (UNIX) - -INSTALL(TARGETS tdtool RUNTIME DESTINATION bin) +PROJECT(tdtool) + +cmake_policy(SET CMP0005 NEW) + +SET (tdtool_DESCRIPTION + "a command line utility to send commands to a Telldus TellStick" +) + +SET(tdtool_SRCS + main.cpp +) + +ADD_EXECUTABLE(tdtool + ${tdtool_SRCS} +) +SIGN(tdtool) + +INCLUDE_DIRECTORIES( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/driver +) + +ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" ) + +IF (WIN32) + TARGET_LINK_LIBRARIES(tdtool + TelldusCore + openbsd-getopt + ) + INCLUDE_DIRECTORIES( + ${CMAKE_SOURCE_DIR}/3rdparty/openbsd-getopt + ) +ELSEIF (APPLE) + TARGET_LINK_LIBRARIES(tdtool + TelldusCore + ) +ELSE (WIN32) + TARGET_LINK_LIBRARIES(tdtool + ${CMAKE_BINARY_DIR}/client/libtelldus-core.so + ) +ENDIF (WIN32) + +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET tdtool + POST_BUILD + COMMAND help2man -n ${tdtool_DESCRIPTION} ./tdtool > tdtool.1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file tdtool.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/tdtool.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + +INSTALL(TARGETS tdtool RUNTIME DESTINATION bin) diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index f9ff478d..0b75771b 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -1,486 +1,486 @@ -#include -#include -#include -#include -#include -#include "../client/telldus-core.h" - -#ifdef _WINDOWS -#define strcasecmp _stricmp -#define DEGREE " " -#else -#define DEGREE "°" -#endif - -const int SUPPORTED_METHODS = - TELLSTICK_TURNON | - TELLSTICK_TURNOFF | - TELLSTICK_BELL | - TELLSTICK_DIM; - -const int DATA_LENGTH = 20; - -void print_usage( char *name ) { - printf("Usage: %s [ options ]\n", name); - printf("\n"); - printf("Options:\n"); - printf(" -[bdefhlnrv] [ --list ] [ --help ]\n"); - printf(" [ --list-sensors ] [ --list-devices ]\n"); - printf(" [ --on device ] [ --off device ] [ --bell device ]\n"); - printf(" [ --learn device ]\n"); - printf(" [ --dimlevel level --dim device ]\n"); - printf(" [ --raw input ]\n"); - printf("\n"); - printf(" --list (-l short option)\n"); - printf(" List currently configured devices and all discovered sensors.\n"); - printf("\n"); - printf(" --list-sensors\n"); - printf(" --list-devices\n"); - printf(" Alternative devices/sensors listing:\n"); - printf(" Shows devices and/or sensors using key=value format (with tabs as\n"); - printf(" separators, one device/sensor per line, no header lines.)\n"); - printf("\n"); - printf(" --help (-h short option)\n"); - printf(" Shows this screen.\n"); - printf("\n"); - printf(" --on device (-n short option)\n"); - printf(" Turns on device. 'device' could either be an integer of the\n"); - printf(" device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --off device (-f short option)\n"); - printf(" Turns off device. 'device' could either be an integer of the\n"); - printf(" device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --dim device (-d short option)\n"); - printf(" Dims device. 'device' could either be an integer of the device-id,\n"); - printf(" or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf(" Note: The dimlevel parameter must be set before using this option.\n"); - printf("\n"); - printf(" --dimlevel level (-v short option)\n"); - printf(" Set dim level. 'level' should an integer, 0-255.\n"); - printf(" Note: This parameter must be set before using dim.\n"); - printf("\n"); - printf(" --bell device (-b short option)\n"); - printf(" Sends bell command to devices supporting this. 'device' could\n"); - printf(" either be an integer of the device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --learn device (-e short option)\n"); - printf(" Sends a special learn command to devices supporting this. This is normaly\n"); - printf(" devices of 'selflearning' type. 'device' could either be an integer\n"); - printf(" of the device-id, or the name of the device.\n"); - printf(" Both device-id and name is outputed with the --list option\n"); - printf("\n"); - printf(" --raw input (-r short option)\n"); - printf(" This command sends a raw command to TellStick.\n"); - printf(" input can be either - or a filename. If input is - the data is\n"); - printf(" taken from stdin, otherwise the data is taken from the supplied filename.\n"); - printf("\n"); - printf(" Example to turn on an ArcTech codeswitch A1:\n"); - printf(" echo 'S$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$kk$$kk$$kk$$}+' | tdtool --raw -\n"); - printf("\n"); - printf("Report bugs to \n"); -} - -void print_version() { - printf("tdtool " VERSION "\n"); - printf("\n"); - printf("Copyright (C) 2011 Telldus Technologies AB\n"); - printf("\n"); - printf("Written by Micke Prag \n"); -} - -void print_device( int index ) { - tdInit(); - int intId = tdGetDeviceId(index); - char *name = tdGetName(intId); - printf("%i\t%s\t", intId, name); - tdReleaseString(name); - int lastSentCommand = tdLastSentCommand(intId, SUPPORTED_METHODS); - char *level = 0; - switch(lastSentCommand) { - case TELLSTICK_TURNON: - printf("ON"); - break; - case TELLSTICK_TURNOFF: - printf("OFF"); - break; - case TELLSTICK_DIM: - level = tdLastSentValue(intId); - printf("DIMMED:%s", level); - tdReleaseString(level); - break; - default: - printf("Unknown state"); - } - printf("\n"); -} - -int list_devices() { - tdInit(); - int intNum = tdGetNumberOfDevices(); - if (intNum < 0) { - char *errorString = tdGetErrorString(intNum); - fprintf(stderr, "Error fetching devices: %s\n", errorString); - tdReleaseString(errorString); - return intNum; - } - printf("Number of devices: %i\n", intNum); - int i = 0; - while (i < intNum) { - print_device( i ); - i++; - } - - char protocol[DATA_LENGTH], model[DATA_LENGTH]; - int sensorId = 0, dataTypes = 0; - - int sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); - if(sensorStatus == 0){ - printf("\n\nSENSORS:\n\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED"); - } - while(sensorStatus == 0){ - char tempvalue[DATA_LENGTH]; - tempvalue[0] = 0; - char humidityvalue[DATA_LENGTH]; - humidityvalue[0] = 0; - char timeBuf[80]; - timeBuf[0] = 0; - time_t timestamp = 0; - - if (dataTypes & TELLSTICK_TEMPERATURE) { - tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp); - strcat(tempvalue, DEGREE); - strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); - } - - if (dataTypes & TELLSTICK_HUMIDITY) { - tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp); - strcat(humidityvalue, "%"); - strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); - } - printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf); - - sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); - } - printf("\n"); - if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){ - char *errorString = tdGetErrorString(sensorStatus); - fprintf(stderr, "Error fetching sensors: %s\n", errorString); - tdReleaseString(errorString); - return sensorStatus; - } - return TELLSTICK_SUCCESS; -} - -/* list sensors using key=value format, one sensor/line, no header lines - * and no degree or percent signs attached to the numbers - just - * plain values. */ -int list_kv_sensors() { - char protocol[DATA_LENGTH], model[DATA_LENGTH]; - - tdInit(); - int sensorId = 0, dataTypes = 0; - time_t now = 0; - int sensorStatus; - - time(&now); - while(1) { - sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); - if (sensorStatus != 0) break; - - printf("type=sensor\tprotocol=%s\tmodel=%s\tid=%d", - protocol, model, sensorId); - - time_t timestamp = 0; - - if (dataTypes & TELLSTICK_TEMPERATURE) { - char tempvalue[DATA_LENGTH]; - tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp); - printf("\ttemperature=%s", tempvalue); - } - - if (dataTypes & TELLSTICK_HUMIDITY) { - char humidityvalue[DATA_LENGTH]; - tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp); - printf("\thumidity=%s", humidityvalue); - } - - if (dataTypes & (TELLSTICK_TEMPERATURE | TELLSTICK_HUMIDITY)) { - /* timestamp has been set, print time & age */ - /* (age is more useful on e.g. embedded systems - * which may not have real-time clock chips => - * time is useful only as a relative value) */ - char timeBuf[80]; - strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); - printf("\ttime=%s\tage=%d", timeBuf, (int)(now - timestamp)); - } - printf("\n"); - - } - if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){ - char *errorString = tdGetErrorString(sensorStatus); - fprintf(stderr, "Error fetching sensors: %s\n", errorString); - tdReleaseString(errorString); - return sensorStatus; - } - return TELLSTICK_SUCCESS; -} - -/* list devices using key=value format, one device/line, no header lines */ -int list_kv_devices() { - tdInit(); - int intNum = tdGetNumberOfDevices(); - if (intNum < 0) { - char *errorString = tdGetErrorString(intNum); - fprintf(stderr, "Error fetching devices: %s\n", errorString); - tdReleaseString(errorString); - return intNum; - } - int index = 0; - while (index < intNum) { - tdInit(); - int intId = tdGetDeviceId(index); - char *name = tdGetName(intId); - printf("type=device\tid=%i\tname=%s", intId, name); - tdReleaseString(name); - - int lastSentCommand = tdLastSentCommand(intId, SUPPORTED_METHODS); - char *level = 0; - switch(lastSentCommand) { - case TELLSTICK_TURNON: - printf("\tlastsentcommand=ON"); - break; - case TELLSTICK_TURNOFF: - printf("\tlastsentcommand=OFF"); - break; - case TELLSTICK_DIM: - level = tdLastSentValue(intId); - printf("\tlastsentcommand=DIMMED\tdimlevel=%s", level); - tdReleaseString(level); - break; - /* default: state is unknown, print nothing. */ - } - printf("\n"); - index++; - } -} - - -int find_device( char *device ) { - tdInit(); - int deviceId = atoi(device); - if (deviceId == 0) { //Try to find the id from the name - int intNum = tdGetNumberOfDevices(); - int index = 0; - while (index < intNum) { - int id = tdGetDeviceId(index); - char *name = tdGetName( id ); - if (strcasecmp(name, device) == 0) { - deviceId = id; - tdReleaseString(name); - break; - } - tdReleaseString(name); - index++; - } - } - return deviceId; -} - -int switch_device( bool turnOn, char *device ) { - tdInit(); - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - char *name = tdGetName( deviceId ); - int deviceType = tdGetDeviceType( deviceId ); - printf("Turning %s %s %i, %s", - (turnOn ? "on" : "off"), - (deviceType == TELLSTICK_TYPE_DEVICE ? "device" : "group"), - deviceId, - name); - tdReleaseString(name); - - int retval = (turnOn ? tdTurnOn( deviceId ) : tdTurnOff( deviceId )); - char *errorString = tdGetErrorString(retval); - - printf(" - %s\n", errorString); - tdReleaseString(errorString); - return retval; -} - -int dim_device( char *device, int level ) { - tdInit(); - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - if (level < 0 || level > 255) { - printf("Level %i out of range!\n", level); - return TELLSTICK_ERROR_SYNTAX; - } - - char *name = tdGetName( deviceId ); - int retval = tdDim( deviceId, (unsigned char)level ); - char *errorString = tdGetErrorString(retval); - printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); - tdReleaseString(name); - tdReleaseString(errorString); - return retval; -} - -int bell_device( char *device ) { - tdInit(); - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - char *name = tdGetName( deviceId ); - int retval = tdBell( deviceId ); - char *errorString = tdGetErrorString(retval); - printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); - tdReleaseString(name); - tdReleaseString(errorString); - return retval; -} - -int learn_device( char *device ) { - tdInit(); - int deviceId = find_device( device ); - if (deviceId == 0) { - printf("Device '%s', not found!\n", device); - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - - char *name = tdGetName( deviceId ); - int retval = tdLearn( deviceId ); - char *errorString = tdGetErrorString(retval); - printf("Learning device: %i %s - %s\n", deviceId, name, errorString); - tdReleaseString(name); - tdReleaseString(errorString); - return retval; -} - -int send_raw_command( char *command ) { - tdInit(); - const int MAX_LENGTH = 100; - char msg[MAX_LENGTH]; - - if (strcmp(command, "-") == 0) { - fgets(msg, MAX_LENGTH, stdin); - } else { - FILE *fd; - - fd = fopen(command, "r"); - if (fd == NULL) { - printf("Error opening file %s\n", command); - return TELLSTICK_ERROR_UNKNOWN; - } - fgets(msg, MAX_LENGTH, fd); - fclose(fd); - } - - int retval = tdSendRawCommand( msg, 0 ); - char *errorString = tdGetErrorString(retval); - printf("Sending raw command: %s\n", errorString); - tdReleaseString(errorString); - return retval; -} - -#define LIST_KV_SENSORS 1 -#define LIST_KV_DEVICES 2 - -int main(int argc, char **argv) -{ - int optch, longindex; - static char optstring[] = "ln:f:d:b:v:e:r:hi"; - static struct option long_opts[] = { - { "list", 0, 0, 'l' }, - { "list-sensors", 0, 0, LIST_KV_SENSORS }, - { "list-devices", 0, 0, LIST_KV_DEVICES }, - { "on", 1, 0, 'n' }, - { "off", 1, 0, 'f' }, - { "dim", 1, 0, 'd' }, - { "bell", 1, 0, 'b' }, - { "dimlevel", 1, 0, 'v' }, - { "learn", 1, 0, 'e' }, - { "raw", 1, 0, 'r' }, - { "help", 0, 0, 'h' }, - { "version", 0, 0, 'i'}, - { 0, 0, 0, 0} - }; - int level = -1; - - if (argc < 2) { - print_usage( argv[0] ); - return -TELLSTICK_ERROR_SYNTAX; - } - - int returnSuccess = 0; - while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ){ - int success = 0; - switch (optch) { - case 'b' : - success = bell_device( &optarg[0] ); - break; - case 'd' : - if (level >= 0) { - success = dim_device( &optarg[0], level ); - break; - } - printf("Dim level missing or incorrect value.\n"); - success = TELLSTICK_ERROR_SYNTAX; - break; - case 'f' : - success = switch_device(false, &optarg[0]); - break; - case 'h' : - print_usage( argv[0] ); - success = TELLSTICK_SUCCESS; - break; - case 'i' : - print_version( ); - success = TELLSTICK_SUCCESS; - break; - case 'l' : - success = list_devices(); - break; - case LIST_KV_SENSORS: - success = list_kv_sensors(); - break; - case LIST_KV_DEVICES: - success = list_kv_devices(); - break; - case 'n' : - success = switch_device(true, &optarg[0]); - break; - case 'e' : - success = learn_device(&optarg[0]); - break; - case 'r' : - success = send_raw_command(&optarg[0]); - break; - case 'v' : - level = atoi( &optarg[0] ); - break; - default : - print_usage( argv[0] ); - success = TELLSTICK_ERROR_SYNTAX; - } - if(success != TELLSTICK_SUCCESS){ - returnSuccess = success; //return last error message - } - } - tdClose(); //Cleaning up - return -returnSuccess; -} +#include +#include +#include +#include +#include +#include "../client/telldus-core.h" + +#ifdef _WINDOWS +#define strcasecmp _stricmp +#define DEGREE " " +#else +#define DEGREE "°" +#endif + +const int SUPPORTED_METHODS = + TELLSTICK_TURNON | + TELLSTICK_TURNOFF | + TELLSTICK_BELL | + TELLSTICK_DIM; + +const int DATA_LENGTH = 20; + +void print_usage( char *name ) { + printf("Usage: %s [ options ]\n", name); + printf("\n"); + printf("Options:\n"); + printf(" -[bdefhlnrv] [ --list ] [ --help ]\n"); + printf(" [ --list-sensors ] [ --list-devices ]\n"); + printf(" [ --on device ] [ --off device ] [ --bell device ]\n"); + printf(" [ --learn device ]\n"); + printf(" [ --dimlevel level --dim device ]\n"); + printf(" [ --raw input ]\n"); + printf("\n"); + printf(" --list (-l short option)\n"); + printf(" List currently configured devices and all discovered sensors.\n"); + printf("\n"); + printf(" --list-sensors\n"); + printf(" --list-devices\n"); + printf(" Alternative devices/sensors listing:\n"); + printf(" Shows devices and/or sensors using key=value format (with tabs as\n"); + printf(" separators, one device/sensor per line, no header lines.)\n"); + printf("\n"); + printf(" --help (-h short option)\n"); + printf(" Shows this screen.\n"); + printf("\n"); + printf(" --on device (-n short option)\n"); + printf(" Turns on device. 'device' could either be an integer of the\n"); + printf(" device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --off device (-f short option)\n"); + printf(" Turns off device. 'device' could either be an integer of the\n"); + printf(" device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --dim device (-d short option)\n"); + printf(" Dims device. 'device' could either be an integer of the device-id,\n"); + printf(" or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf(" Note: The dimlevel parameter must be set before using this option.\n"); + printf("\n"); + printf(" --dimlevel level (-v short option)\n"); + printf(" Set dim level. 'level' should an integer, 0-255.\n"); + printf(" Note: This parameter must be set before using dim.\n"); + printf("\n"); + printf(" --bell device (-b short option)\n"); + printf(" Sends bell command to devices supporting this. 'device' could\n"); + printf(" either be an integer of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --learn device (-e short option)\n"); + printf(" Sends a special learn command to devices supporting this. This is normaly\n"); + printf(" devices of 'selflearning' type. 'device' could either be an integer\n"); + printf(" of the device-id, or the name of the device.\n"); + printf(" Both device-id and name is outputed with the --list option\n"); + printf("\n"); + printf(" --raw input (-r short option)\n"); + printf(" This command sends a raw command to TellStick.\n"); + printf(" input can be either - or a filename. If input is - the data is\n"); + printf(" taken from stdin, otherwise the data is taken from the supplied filename.\n"); + printf("\n"); + printf(" Example to turn on an ArcTech codeswitch A1:\n"); + printf(" echo 'S$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$k$kk$$kk$$kk$$}+' | tdtool --raw -\n"); + printf("\n"); + printf("Report bugs to \n"); +} + +void print_version() { + printf("tdtool " VERSION "\n"); + printf("\n"); + printf("Copyright (C) 2011 Telldus Technologies AB\n"); + printf("\n"); + printf("Written by Micke Prag \n"); +} + +void print_device( int index ) { + tdInit(); + int intId = tdGetDeviceId(index); + char *name = tdGetName(intId); + printf("%i\t%s\t", intId, name); + tdReleaseString(name); + int lastSentCommand = tdLastSentCommand(intId, SUPPORTED_METHODS); + char *level = 0; + switch(lastSentCommand) { + case TELLSTICK_TURNON: + printf("ON"); + break; + case TELLSTICK_TURNOFF: + printf("OFF"); + break; + case TELLSTICK_DIM: + level = tdLastSentValue(intId); + printf("DIMMED:%s", level); + tdReleaseString(level); + break; + default: + printf("Unknown state"); + } + printf("\n"); +} + +int list_devices() { + tdInit(); + int intNum = tdGetNumberOfDevices(); + if (intNum < 0) { + char *errorString = tdGetErrorString(intNum); + fprintf(stderr, "Error fetching devices: %s\n", errorString); + tdReleaseString(errorString); + return intNum; + } + printf("Number of devices: %i\n", intNum); + int i = 0; + while (i < intNum) { + print_device( i ); + i++; + } + + char protocol[DATA_LENGTH], model[DATA_LENGTH]; + int sensorId = 0, dataTypes = 0; + + int sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + if(sensorStatus == 0){ + printf("\n\nSENSORS:\n\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED"); + } + while(sensorStatus == 0){ + char tempvalue[DATA_LENGTH]; + tempvalue[0] = 0; + char humidityvalue[DATA_LENGTH]; + humidityvalue[0] = 0; + char timeBuf[80]; + timeBuf[0] = 0; + time_t timestamp = 0; + + if (dataTypes & TELLSTICK_TEMPERATURE) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp); + strcat(tempvalue, DEGREE); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + + if (dataTypes & TELLSTICK_HUMIDITY) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp); + strcat(humidityvalue, "%"); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf); + + sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + } + printf("\n"); + if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){ + char *errorString = tdGetErrorString(sensorStatus); + fprintf(stderr, "Error fetching sensors: %s\n", errorString); + tdReleaseString(errorString); + return sensorStatus; + } + return TELLSTICK_SUCCESS; +} + +/* list sensors using key=value format, one sensor/line, no header lines + * and no degree or percent signs attached to the numbers - just + * plain values. */ +int list_kv_sensors() { + char protocol[DATA_LENGTH], model[DATA_LENGTH]; + + tdInit(); + int sensorId = 0, dataTypes = 0; + time_t now = 0; + int sensorStatus; + + time(&now); + while(1) { + sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + if (sensorStatus != 0) break; + + printf("type=sensor\tprotocol=%s\tmodel=%s\tid=%d", + protocol, model, sensorId); + + time_t timestamp = 0; + + if (dataTypes & TELLSTICK_TEMPERATURE) { + char tempvalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_TEMPERATURE, tempvalue, DATA_LENGTH, (int *)×tamp); + printf("\ttemperature=%s", tempvalue); + } + + if (dataTypes & TELLSTICK_HUMIDITY) { + char humidityvalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_HUMIDITY, humidityvalue, DATA_LENGTH, (int *)×tamp); + printf("\thumidity=%s", humidityvalue); + } + + if (dataTypes & (TELLSTICK_TEMPERATURE | TELLSTICK_HUMIDITY)) { + /* timestamp has been set, print time & age */ + /* (age is more useful on e.g. embedded systems + * which may not have real-time clock chips => + * time is useful only as a relative value) */ + char timeBuf[80]; + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + printf("\ttime=%s\tage=%d", timeBuf, (int)(now - timestamp)); + } + printf("\n"); + + } + if(sensorStatus != TELLSTICK_ERROR_DEVICE_NOT_FOUND){ + char *errorString = tdGetErrorString(sensorStatus); + fprintf(stderr, "Error fetching sensors: %s\n", errorString); + tdReleaseString(errorString); + return sensorStatus; + } + return TELLSTICK_SUCCESS; +} + +/* list devices using key=value format, one device/line, no header lines */ +int list_kv_devices() { + tdInit(); + int intNum = tdGetNumberOfDevices(); + if (intNum < 0) { + char *errorString = tdGetErrorString(intNum); + fprintf(stderr, "Error fetching devices: %s\n", errorString); + tdReleaseString(errorString); + return intNum; + } + int index = 0; + while (index < intNum) { + tdInit(); + int intId = tdGetDeviceId(index); + char *name = tdGetName(intId); + printf("type=device\tid=%i\tname=%s", intId, name); + tdReleaseString(name); + + int lastSentCommand = tdLastSentCommand(intId, SUPPORTED_METHODS); + char *level = 0; + switch(lastSentCommand) { + case TELLSTICK_TURNON: + printf("\tlastsentcommand=ON"); + break; + case TELLSTICK_TURNOFF: + printf("\tlastsentcommand=OFF"); + break; + case TELLSTICK_DIM: + level = tdLastSentValue(intId); + printf("\tlastsentcommand=DIMMED\tdimlevel=%s", level); + tdReleaseString(level); + break; + /* default: state is unknown, print nothing. */ + } + printf("\n"); + index++; + } +} + + +int find_device( char *device ) { + tdInit(); + int deviceId = atoi(device); + if (deviceId == 0) { //Try to find the id from the name + int intNum = tdGetNumberOfDevices(); + int index = 0; + while (index < intNum) { + int id = tdGetDeviceId(index); + char *name = tdGetName( id ); + if (strcasecmp(name, device) == 0) { + deviceId = id; + tdReleaseString(name); + break; + } + tdReleaseString(name); + index++; + } + } + return deviceId; +} + +int switch_device( bool turnOn, char *device ) { + tdInit(); + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + char *name = tdGetName( deviceId ); + int deviceType = tdGetDeviceType( deviceId ); + printf("Turning %s %s %i, %s", + (turnOn ? "on" : "off"), + (deviceType == TELLSTICK_TYPE_DEVICE ? "device" : "group"), + deviceId, + name); + tdReleaseString(name); + + int retval = (turnOn ? tdTurnOn( deviceId ) : tdTurnOff( deviceId )); + char *errorString = tdGetErrorString(retval); + + printf(" - %s\n", errorString); + tdReleaseString(errorString); + return retval; +} + +int dim_device( char *device, int level ) { + tdInit(); + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + if (level < 0 || level > 255) { + printf("Level %i out of range!\n", level); + return TELLSTICK_ERROR_SYNTAX; + } + + char *name = tdGetName( deviceId ); + int retval = tdDim( deviceId, (unsigned char)level ); + char *errorString = tdGetErrorString(retval); + printf("Dimming device: %i %s to %i - %s\n", deviceId, name, level, errorString); + tdReleaseString(name); + tdReleaseString(errorString); + return retval; +} + +int bell_device( char *device ) { + tdInit(); + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + char *name = tdGetName( deviceId ); + int retval = tdBell( deviceId ); + char *errorString = tdGetErrorString(retval); + printf("Sending bell to: %i %s - %s\n", deviceId, name, errorString); + tdReleaseString(name); + tdReleaseString(errorString); + return retval; +} + +int learn_device( char *device ) { + tdInit(); + int deviceId = find_device( device ); + if (deviceId == 0) { + printf("Device '%s', not found!\n", device); + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + } + + char *name = tdGetName( deviceId ); + int retval = tdLearn( deviceId ); + char *errorString = tdGetErrorString(retval); + printf("Learning device: %i %s - %s\n", deviceId, name, errorString); + tdReleaseString(name); + tdReleaseString(errorString); + return retval; +} + +int send_raw_command( char *command ) { + tdInit(); + const int MAX_LENGTH = 100; + char msg[MAX_LENGTH]; + + if (strcmp(command, "-") == 0) { + fgets(msg, MAX_LENGTH, stdin); + } else { + FILE *fd; + + fd = fopen(command, "r"); + if (fd == NULL) { + printf("Error opening file %s\n", command); + return TELLSTICK_ERROR_UNKNOWN; + } + fgets(msg, MAX_LENGTH, fd); + fclose(fd); + } + + int retval = tdSendRawCommand( msg, 0 ); + char *errorString = tdGetErrorString(retval); + printf("Sending raw command: %s\n", errorString); + tdReleaseString(errorString); + return retval; +} + +#define LIST_KV_SENSORS 1 +#define LIST_KV_DEVICES 2 + +int main(int argc, char **argv) +{ + int optch, longindex; + static char optstring[] = "ln:f:d:b:v:e:r:hi"; + static struct option long_opts[] = { + { "list", 0, 0, 'l' }, + { "list-sensors", 0, 0, LIST_KV_SENSORS }, + { "list-devices", 0, 0, LIST_KV_DEVICES }, + { "on", 1, 0, 'n' }, + { "off", 1, 0, 'f' }, + { "dim", 1, 0, 'd' }, + { "bell", 1, 0, 'b' }, + { "dimlevel", 1, 0, 'v' }, + { "learn", 1, 0, 'e' }, + { "raw", 1, 0, 'r' }, + { "help", 0, 0, 'h' }, + { "version", 0, 0, 'i'}, + { 0, 0, 0, 0} + }; + int level = -1; + + if (argc < 2) { + print_usage( argv[0] ); + return -TELLSTICK_ERROR_SYNTAX; + } + + int returnSuccess = 0; + while ( (optch = getopt_long(argc,argv,optstring,long_opts,&longindex)) != -1 ){ + int success = 0; + switch (optch) { + case 'b' : + success = bell_device( &optarg[0] ); + break; + case 'd' : + if (level >= 0) { + success = dim_device( &optarg[0], level ); + break; + } + printf("Dim level missing or incorrect value.\n"); + success = TELLSTICK_ERROR_SYNTAX; + break; + case 'f' : + success = switch_device(false, &optarg[0]); + break; + case 'h' : + print_usage( argv[0] ); + success = TELLSTICK_SUCCESS; + break; + case 'i' : + print_version( ); + success = TELLSTICK_SUCCESS; + break; + case 'l' : + success = list_devices(); + break; + case LIST_KV_SENSORS: + success = list_kv_sensors(); + break; + case LIST_KV_DEVICES: + success = list_kv_devices(); + break; + case 'n' : + success = switch_device(true, &optarg[0]); + break; + case 'e' : + success = learn_device(&optarg[0]); + break; + case 'r' : + success = send_raw_command(&optarg[0]); + break; + case 'v' : + level = atoi( &optarg[0] ); + break; + default : + print_usage( argv[0] ); + success = TELLSTICK_ERROR_SYNTAX; + } + if(success != TELLSTICK_SUCCESS){ + returnSuccess = success; //return last error message + } + } + tdClose(); //Cleaning up + return -returnSuccess; +} diff --git a/telldus-core/tests/common/CMakeLists.txt b/telldus-core/tests/common/CMakeLists.txt index 0386e19f..4c7fca41 100644 --- a/telldus-core/tests/common/CMakeLists.txt +++ b/telldus-core/tests/common/CMakeLists.txt @@ -1,9 +1,9 @@ -FILE(GLOB SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*Test.cpp" ) - -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common) - -ADD_LIBRARY(TelldusCommonTests SHARED ${SRCS} ) - -TARGET_LINK_LIBRARIES( TelldusCommonTests TelldusCommon ) -ADD_DEPENDENCIES( TelldusCommonTests TelldusCommon ) - +FILE(GLOB SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*Test.cpp" ) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common) + +ADD_LIBRARY(TelldusCommonTests SHARED ${SRCS} ) + +TARGET_LINK_LIBRARIES( TelldusCommonTests TelldusCommon ) +ADD_DEPENDENCIES( TelldusCommonTests TelldusCommon ) + From aff9b973a86d0b2e38f470014dd72053e1a4bfc6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 27 Feb 2012 17:43:29 +0100 Subject: [PATCH 1939/2215] Convert dos endings to unix in telldus-gui, closes #160 --- telldus-gui/CMakeLists.txt | 80 ++-- telldus-gui/Plugins/CMakeLists.txt | 140 +++--- telldus-gui/Plugins/Devices/CMakeLists.txt | 82 ++-- telldus-gui/Plugins/Live/CMakeLists.txt | 90 ++-- .../Plugins/Live/Equifax_Secure_CA.pem | 38 +- telldus-gui/Plugins/Live/config.h.in | 8 +- telldus-gui/Plugins/SchedulerGUISimple/qmldir | 6 +- telldus-gui/Plugins/Systray/CMakeLists.txt | 36 +- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 296 ++++++------- .../Plugins/TelldusCore/CMakeLists.txt | 50 +-- telldus-gui/Plugins/telldus/CMakeLists.txt | 22 +- telldus-gui/Plugins/xPL/CMakeLists.txt | 54 +-- telldus-gui/TelldusCenter/CMakeLists.txt | 416 +++++++++--------- telldus-gui/TelldusGui/CMakeLists.txt | 394 ++++++++--------- telldus-gui/TelldusGui/data/byron/devices.xml | 18 +- .../TelldusGui/data/byron/resources.qrc | 24 +- .../TelldusGui/data/chacon/devices.xml | 14 +- .../TelldusGui/data/chacon/resources.qrc | 16 +- .../TelldusGui/data/telldus/devices.xml | 262 +++++------ .../TelldusGui/data/telldus/resources.qrc | 114 ++--- telldus-gui/TelldusGui/deviceview.cpp | 20 +- telldus-gui/TelldusGui/telldusgui.qrc | 36 +- telldus-gui/cmake/FindQCA.cmake | 30 +- telldus-gui/cmake/FindSignTool.cmake | 36 +- telldus-gui/cmake/FindTelldusCore.cmake | 42 +- 25 files changed, 1162 insertions(+), 1162 deletions(-) diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index 5058a201..5354d13a 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -1,40 +1,40 @@ -PROJECT( telldus-gui ) - -CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -SET(PACKAGE_MAJOR_VERSION 2) -SET(PACKAGE_MINOR_VERSION 1) -SET(PACKAGE_PATCH_VERSION 1) -SET(PACKAGE_SOVERSION 2) -SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}") - -SET(BRANDING "telldus" CACHE STRING "The brand to use") - -SET(UPDATE_TRANSLATIONS FALSE CACHE BOOL "Update source translation files (WARNING: make clean will delete the source .ts files! Danger!)") -SET(LANGUAGES sv) - -SET(BUILD_LIBTELLDUS-GUI TRUE CACHE BOOL "Build libtelldus-gui") -SET(BUILD_TELLDUS-CENTER TRUE CACHE BOOL "Build TelldusCenter") - -SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") - -IF(UNIX) - SET(PLUGIN_LIB_PATH "lib" CACHE STRING "Relative path to the directory to install TelldusCenter plugin libraries into") - SET(PLUGIN_LIB_FULL_PATH "${PLUGIN_LIB_PATH}/telldus/tellduscenter/plugins") -ENDIF () - -if(BUILD_LIBTELLDUS-GUI) - ADD_SUBDIRECTORY(TelldusGui) -endif(BUILD_LIBTELLDUS-GUI) - -IF (BUILD_TELLDUS-CENTER) - ADD_SUBDIRECTORY(TelldusCenter) - ADD_SUBDIRECTORY(Plugins) -ENDIF (BUILD_TELLDUS-CENTER) - +PROJECT( telldus-gui ) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) + +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +SET(PACKAGE_MAJOR_VERSION 2) +SET(PACKAGE_MINOR_VERSION 1) +SET(PACKAGE_PATCH_VERSION 1) +SET(PACKAGE_SOVERSION 2) +SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}") + +SET(BRANDING "telldus" CACHE STRING "The brand to use") + +SET(UPDATE_TRANSLATIONS FALSE CACHE BOOL "Update source translation files (WARNING: make clean will delete the source .ts files! Danger!)") +SET(LANGUAGES sv) + +SET(BUILD_LIBTELLDUS-GUI TRUE CACHE BOOL "Build libtelldus-gui") +SET(BUILD_TELLDUS-CENTER TRUE CACHE BOOL "Build TelldusCenter") + +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") + +IF(UNIX) + SET(PLUGIN_LIB_PATH "lib" CACHE STRING "Relative path to the directory to install TelldusCenter plugin libraries into") + SET(PLUGIN_LIB_FULL_PATH "${PLUGIN_LIB_PATH}/telldus/tellduscenter/plugins") +ENDIF () + +if(BUILD_LIBTELLDUS-GUI) + ADD_SUBDIRECTORY(TelldusGui) +endif(BUILD_LIBTELLDUS-GUI) + +IF (BUILD_TELLDUS-CENTER) + ADD_SUBDIRECTORY(TelldusCenter) + ADD_SUBDIRECTORY(Plugins) +ENDIF (BUILD_TELLDUS-CENTER) + diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 4b29d679..3ba4155d 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -1,70 +1,70 @@ - -CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) - -SET(BUILD_PLUGIN_TELLDUS-CORE TRUE CACHE BOOL "Build plugin 'TelldusCore'") - -IF (BUILD_LIBTELLDUS-GUI) - SET(BUILD_PLUGIN_DEVICES TRUE CACHE BOOL "Build plugin 'Devices'") - SET(BUILD_PLUGIN_SYSTRAY TRUE CACHE BOOL "Build plugin 'Systray'") -ENDIF (BUILD_LIBTELLDUS-GUI) - -SET(BUILD_PLUGIN_CONTROLLERS FALSE CACHE BOOL "Build plugin 'Controllers admin plugin'") -SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") -SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") -SET(BUILD_PLUGIN_SCHEDULERGUISIMPLE FALSE CACHE BOOL "Build plugin 'Simple Scheduler GUI'") -SET(BUILD_PLUGIN_SENSORS TRUE CACHE BOOL "Build plugin 'Sensors'") -SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") - -ADD_SUBDIRECTORY(telldus) - -IF(BUILD_PLUGIN_TELLDUS-CORE) - ADD_SUBDIRECTORY(TelldusCore) -ENDIF(BUILD_PLUGIN_TELLDUS-CORE) - -IF(BUILD_PLUGIN_DEVICES) - ADD_SUBDIRECTORY(Devices) -ENDIF(BUILD_PLUGIN_DEVICES) - -IF(BUILD_PLUGIN_SYSTRAY) - ADD_SUBDIRECTORY(Systray) -ENDIF(BUILD_PLUGIN_SYSTRAY) - -IF(BUILD_PLUGIN_CONTROLLERS) - ADD_SUBDIRECTORY(Controllers) -ENDIF() - -IF(BUILD_PLUGIN_DBUS) - ADD_SUBDIRECTORY(DBus) -ENDIF(BUILD_PLUGIN_DBUS) - -IF(BUILD_PLUGIN_LIVE) - ADD_SUBDIRECTORY(Live) -ENDIF(BUILD_PLUGIN_LIVE) - -IF(BUILD_PLUGIN_SENSORS) - ADD_SUBDIRECTORY(Sensors) -ENDIF() - -IF(BUILD_PLUGIN_XPL) - ADD_SUBDIRECTORY(xPL) -ENDIF(BUILD_PLUGIN_XPL) - -IF(BUILD_PLUGIN_SCHEDULERGUISIMPLE) - ADD_SUBDIRECTORY(SchedulerGUISimple) -ENDIF(BUILD_PLUGIN_SCHEDULERGUISIMPLE) - -IF(REQUIRE_PLUGIN_SCHEDULER) - ADD_SUBDIRECTORY(Scheduler) -ENDIF(REQUIRE_PLUGIN_SCHEDULER) - -IF(REQUIRE_PLUGIN_SUNCALCULATOR) - ADD_SUBDIRECTORY(SunCalculator) -ENDIF(REQUIRE_PLUGIN_SUNCALCULATOR) - -IF(REQUIRE_PLUGIN_QML) - ADD_SUBDIRECTORY(QML) -ENDIF(REQUIRE_PLUGIN_QML) - -IF(REQUIRE_PLUGIN_SETTINGS) - ADD_SUBDIRECTORY(Settings) -ENDIF(REQUIRE_PLUGIN_SETTINGS) + +CMAKE_MINIMUM_REQUIRED( VERSION 2.4.0 ) + +SET(BUILD_PLUGIN_TELLDUS-CORE TRUE CACHE BOOL "Build plugin 'TelldusCore'") + +IF (BUILD_LIBTELLDUS-GUI) + SET(BUILD_PLUGIN_DEVICES TRUE CACHE BOOL "Build plugin 'Devices'") + SET(BUILD_PLUGIN_SYSTRAY TRUE CACHE BOOL "Build plugin 'Systray'") +ENDIF (BUILD_LIBTELLDUS-GUI) + +SET(BUILD_PLUGIN_CONTROLLERS FALSE CACHE BOOL "Build plugin 'Controllers admin plugin'") +SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") +SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") +SET(BUILD_PLUGIN_SCHEDULERGUISIMPLE FALSE CACHE BOOL "Build plugin 'Simple Scheduler GUI'") +SET(BUILD_PLUGIN_SENSORS TRUE CACHE BOOL "Build plugin 'Sensors'") +SET(BUILD_PLUGIN_XPL FALSE CACHE BOOL "Build plugin 'xPL'") + +ADD_SUBDIRECTORY(telldus) + +IF(BUILD_PLUGIN_TELLDUS-CORE) + ADD_SUBDIRECTORY(TelldusCore) +ENDIF(BUILD_PLUGIN_TELLDUS-CORE) + +IF(BUILD_PLUGIN_DEVICES) + ADD_SUBDIRECTORY(Devices) +ENDIF(BUILD_PLUGIN_DEVICES) + +IF(BUILD_PLUGIN_SYSTRAY) + ADD_SUBDIRECTORY(Systray) +ENDIF(BUILD_PLUGIN_SYSTRAY) + +IF(BUILD_PLUGIN_CONTROLLERS) + ADD_SUBDIRECTORY(Controllers) +ENDIF() + +IF(BUILD_PLUGIN_DBUS) + ADD_SUBDIRECTORY(DBus) +ENDIF(BUILD_PLUGIN_DBUS) + +IF(BUILD_PLUGIN_LIVE) + ADD_SUBDIRECTORY(Live) +ENDIF(BUILD_PLUGIN_LIVE) + +IF(BUILD_PLUGIN_SENSORS) + ADD_SUBDIRECTORY(Sensors) +ENDIF() + +IF(BUILD_PLUGIN_XPL) + ADD_SUBDIRECTORY(xPL) +ENDIF(BUILD_PLUGIN_XPL) + +IF(BUILD_PLUGIN_SCHEDULERGUISIMPLE) + ADD_SUBDIRECTORY(SchedulerGUISimple) +ENDIF(BUILD_PLUGIN_SCHEDULERGUISIMPLE) + +IF(REQUIRE_PLUGIN_SCHEDULER) + ADD_SUBDIRECTORY(Scheduler) +ENDIF(REQUIRE_PLUGIN_SCHEDULER) + +IF(REQUIRE_PLUGIN_SUNCALCULATOR) + ADD_SUBDIRECTORY(SunCalculator) +ENDIF(REQUIRE_PLUGIN_SUNCALCULATOR) + +IF(REQUIRE_PLUGIN_QML) + ADD_SUBDIRECTORY(QML) +ENDIF(REQUIRE_PLUGIN_QML) + +IF(REQUIRE_PLUGIN_SETTINGS) + ADD_SUBDIRECTORY(Settings) +ENDIF(REQUIRE_PLUGIN_SETTINGS) diff --git a/telldus-gui/Plugins/Devices/CMakeLists.txt b/telldus-gui/Plugins/Devices/CMakeLists.txt index 455ecb21..aad4306d 100644 --- a/telldus-gui/Plugins/Devices/CMakeLists.txt +++ b/telldus-gui/Plugins/Devices/CMakeLists.txt @@ -1,41 +1,41 @@ -SET( Plugin_NAME "Devices" ) - -SET( Plugin_SRCS - devicesplugin.cpp -) - -SET( Plugin_HDRS - devicesplugin.h -) - -SET( Plugin_MOC_HDRS -) - -SET( Plugin_PATH "com.telldus.gui" ) - -IF (WIN32) - SET( Plugin_LIBRARIES - ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusGui.lib - ) -ELSEIF (APPLE) - FIND_PACKAGE(TelldusCore REQUIRED) - SET( Plugin_LIBRARIES - ${TELLDUSCORE_LIBRARY} - TelldusGui - ) - -ELSE (WIN32) - FIND_PACKAGE(TelldusCore REQUIRED) - - SET( Plugin_LIBRARIES - ${TELLDUSGUI_LIBRARY} - ${CMAKE_BINARY_DIR}/TelldusGui/libtelldus-gui.so - ) -ENDIF (WIN32) - -INCLUDE_DIRECTORIES( - ${TELLDUSCORE_INCLUDE_DIR} -) - - -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) +SET( Plugin_NAME "Devices" ) + +SET( Plugin_SRCS + devicesplugin.cpp +) + +SET( Plugin_HDRS + devicesplugin.h +) + +SET( Plugin_MOC_HDRS +) + +SET( Plugin_PATH "com.telldus.gui" ) + +IF (WIN32) + SET( Plugin_LIBRARIES + ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusGui.lib + ) +ELSEIF (APPLE) + FIND_PACKAGE(TelldusCore REQUIRED) + SET( Plugin_LIBRARIES + ${TELLDUSCORE_LIBRARY} + TelldusGui + ) + +ELSE (WIN32) + FIND_PACKAGE(TelldusCore REQUIRED) + + SET( Plugin_LIBRARIES + ${TELLDUSGUI_LIBRARY} + ${CMAKE_BINARY_DIR}/TelldusGui/libtelldus-gui.so + ) +ENDIF (WIN32) + +INCLUDE_DIRECTORIES( + ${TELLDUSCORE_INCLUDE_DIR} +) + + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Live/CMakeLists.txt b/telldus-gui/Plugins/Live/CMakeLists.txt index 38146414..e0b8c2c2 100644 --- a/telldus-gui/Plugins/Live/CMakeLists.txt +++ b/telldus-gui/Plugins/Live/CMakeLists.txt @@ -1,45 +1,45 @@ -SET(QT_USE_QTNETWORK TRUE) - -SET( Plugin_NAME "TelldusLive" ) -SET( Plugin_PATH "com.telldus.live" ) - -SET( Plugin_SRCS - LiveMessage.cpp - LiveMessageToken.cpp - LiveObject.cpp - LivePlugin.cpp -) - -SET( Plugin_HDRS - LivePlugin.h - ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/parsed/config.h -) - -SET( Plugin_MOC_HDRS - LiveMessageToken.h - LiveMessage.h - LiveObject.h -) - -SET( Plugin_RESOURCES - Live.qrc -) - -SET( Plugin_EXTRA - configuration.ui - icon.png -) - -SET(TELLDUS_LIVE_PUBLIC_KEY "" CACHE STRING "Telldus Live! public key") -SET(TELLDUS_LIVE_PRIVATE_KEY "" CACHE STRING "Telldus Live! private key") -SET(TELLDUS_LIVE_URI "https://api.telldus.com/server/assign" CACHE STRING "Telldus Live! Connection URI") - -CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in - ${CMAKE_CURRENT_BINARY_DIR}/parsed/config.h -) - -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/parsed/) - -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) +SET(QT_USE_QTNETWORK TRUE) + +SET( Plugin_NAME "TelldusLive" ) +SET( Plugin_PATH "com.telldus.live" ) + +SET( Plugin_SRCS + LiveMessage.cpp + LiveMessageToken.cpp + LiveObject.cpp + LivePlugin.cpp +) + +SET( Plugin_HDRS + LivePlugin.h + ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/parsed/config.h +) + +SET( Plugin_MOC_HDRS + LiveMessageToken.h + LiveMessage.h + LiveObject.h +) + +SET( Plugin_RESOURCES + Live.qrc +) + +SET( Plugin_EXTRA + configuration.ui + icon.png +) + +SET(TELLDUS_LIVE_PUBLIC_KEY "" CACHE STRING "Telldus Live! public key") +SET(TELLDUS_LIVE_PRIVATE_KEY "" CACHE STRING "Telldus Live! private key") +SET(TELLDUS_LIVE_URI "https://api.telldus.com/server/assign" CACHE STRING "Telldus Live! Connection URI") + +CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/parsed/config.h +) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/parsed/) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/Live/Equifax_Secure_CA.pem b/telldus-gui/Plugins/Live/Equifax_Secure_CA.pem index ed0bd764..676db975 100644 --- a/telldus-gui/Plugins/Live/Equifax_Secure_CA.pem +++ b/telldus-gui/Plugins/Live/Equifax_Secure_CA.pem @@ -1,19 +1,19 @@ ------BEGIN CERTIFICATE----- -MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV -UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy -dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 -MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx -dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f -BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A -cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC -AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ -MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm -aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw -ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj -IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF -MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA -A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y -7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh -1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 ------END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- diff --git a/telldus-gui/Plugins/Live/config.h.in b/telldus-gui/Plugins/Live/config.h.in index 686cd084..8e6ef770 100644 --- a/telldus-gui/Plugins/Live/config.h.in +++ b/telldus-gui/Plugins/Live/config.h.in @@ -1,5 +1,5 @@ - -const char *TELLDUS_LIVE_PUBLIC_KEY = "${TELLDUS_LIVE_PUBLIC_KEY}"; -const char *TELLDUS_LIVE_PRIVATE_KEY = "${TELLDUS_LIVE_PRIVATE_KEY}"; -const char *TELLDUS_LIVE_URI = "${TELLDUS_LIVE_URI}"; + +const char *TELLDUS_LIVE_PUBLIC_KEY = "${TELLDUS_LIVE_PUBLIC_KEY}"; +const char *TELLDUS_LIVE_PRIVATE_KEY = "${TELLDUS_LIVE_PRIVATE_KEY}"; +const char *TELLDUS_LIVE_URI = "${TELLDUS_LIVE_URI}"; const char *TELLDUS_CENTER_VERSION = "${DISPLAYED_VERSION}"; \ No newline at end of file diff --git a/telldus-gui/Plugins/SchedulerGUISimple/qmldir b/telldus-gui/Plugins/SchedulerGUISimple/qmldir index bcfa10af..318a05d7 100644 --- a/telldus-gui/Plugins/SchedulerGUISimple/qmldir +++ b/telldus-gui/Plugins/SchedulerGUISimple/qmldir @@ -1,4 +1,4 @@ -ActionBar 1.0 ActionBar.qml -ActionPoint 1.0 ActionPoint.qml -Button 1.0 Button.qml +ActionBar 1.0 ActionBar.qml +ActionPoint 1.0 ActionPoint.qml +Button 1.0 Button.qml Dialog 1.0 Dialog.qml \ No newline at end of file diff --git a/telldus-gui/Plugins/Systray/CMakeLists.txt b/telldus-gui/Plugins/Systray/CMakeLists.txt index d854ec93..53a60036 100644 --- a/telldus-gui/Plugins/Systray/CMakeLists.txt +++ b/telldus-gui/Plugins/Systray/CMakeLists.txt @@ -1,18 +1,18 @@ -SET( Plugin_NAME "SystrayIcon" ) - -SET( Plugin_SRCS - systrayplugin.cpp - systrayobject.cpp -) - -SET( Plugin_HDRS - systrayplugin.h -) - -SET( Plugin_MOC_HDRS - systrayobject.h -) - -SET( Plugin_PATH "com.telldus.systray" ) - -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) +SET( Plugin_NAME "SystrayIcon" ) + +SET( Plugin_SRCS + systrayplugin.cpp + systrayobject.cpp +) + +SET( Plugin_HDRS + systrayplugin.h +) + +SET( Plugin_MOC_HDRS + systrayobject.h +) + +SET( Plugin_PATH "com.telldus.systray" ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 4e29fd33..33ab90e9 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -1,148 +1,148 @@ -FIND_PACKAGE( Qt4 REQUIRED ) -SET(QT_USE_QTSCRIPT TRUE) -INCLUDE( ${QT_USE_FILE} ) -FIND_PACKAGE( SignTool REQUIRED ) - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - - -QT4_WRAP_CPP( Plugin_MOC_SRCS ${Plugin_MOC_HDRS} ) -QT4_AUTOMOC ( ${Plugin_SRCS} ) - -IF(Plugin_RESOURCES) - QT4_ADD_RESOURCES(Plugin_RSRCS ${Plugin_RESOURCES}) -ENDIF(Plugin_RESOURCES) - -SET( Plugin_LIBRARIES - ${Plugin_LIBRARIES} - ${QT_LIBRARIES} -) - -ADD_DEFINITIONS(${QT_DEFINITIONS}) -ADD_DEFINITIONS(-DQT_PLUGIN) -ADD_DEFINITIONS(-DQT_NO_DEBUG) -ADD_DEFINITIONS(-DQT_SHARED) - -#SET( LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH/Plugins} ) - -FOREACH(lang ${LANGUAGES}) - IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/translation_${lang}.ts" OR UPDATE_TRANSLATIONS) - LIST(APPEND Plugin_TS "translation_${lang}.ts") - ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/translation_${lang}.ts" OR UPDATE_TRANSLATIONS) -ENDFOREACH(lang) -SET(translation_sources ${Plugin_SRCS}) - -IF(Plugin_PATH) - STRING(REPLACE "." "/" - Plugin_PATH_relative ${Plugin_PATH} - ) - IF (APPLE) - SET(Plugin_PATH "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script/${Plugin_PATH_relative}") - ELSEIF (WIN32) - SET(Plugin_PATH "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/Plugins/script/${Plugin_PATH_relative}") - ELSE (APPLE) - SET(Plugin_PATH "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script/${Plugin_PATH_relative}") - ENDIF (APPLE) - - LIST(APPEND translation_sources - "${CMAKE_CURRENT_SOURCE_DIR}/__init__.js" - ) - LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/__init__.js") - #Add all extra files - FOREACH(_FILE ${Plugin_EXTRA}) - LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}") - ENDFOREACH(_FILE) -ENDIF(Plugin_PATH) - -IF (UPDATE_TRANSLATIONS) - QT4_CREATE_TRANSLATION( QM_FILES ${Plugin_SRCS} ${translation_sources} ${Plugin_TS} ) -ELSE (UPDATE_TRANSLATIONS) - QT4_ADD_TRANSLATION(Plugin_QM ${Plugin_TS}) - LIST(APPEND Plugin_FILES ${Plugin_QM}) -ENDIF (UPDATE_TRANSLATIONS) - -IF(Plugin_PATH) - FOREACH(_FILE ${Plugin_FILES}) - GET_FILENAME_COMPONENT(_FILENAME ${_FILE} NAME) - ADD_CUSTOM_COMMAND( OUTPUT ${Plugin_PATH}/${_FILENAME} - COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${Plugin_PATH}/${_FILENAME} - DEPENDS ${_FILE} - COMMENT "Copy ${_FILENAME} for plugin ${Plugin_NAME}" - ) - LIST(APPEND Plugin_TARGET_FILES "${Plugin_PATH}/${_FILENAME}") - IF (NOT APPLE) - INSTALL(FILES ${_FILE} DESTINATION "${PLUGIN_LIB_FULL_PATH}/script/${Plugin_PATH_relative}") - ENDIF () - ENDFOREACH(_FILE) -ENDIF(Plugin_PATH) - -IF(Plugin_SRCS) - ADD_LIBRARY(${Plugin_NAME} SHARED - ${Plugin_SRCS} - ${Plugin_HDRS} - ${Plugin_RSRCS} - ${Plugin_MOC_HDRS} - ${Plugin_MOC_SRCS} - ${Plugin_MOC_HDRS} - ${Plugin_FILES} - ${Plugin_TS} - ${Plugin_QM} - ${Plugin_TARGET_FILES} - ) - TARGET_LINK_LIBRARIES( ${Plugin_NAME} ${Plugin_LIBRARIES} ) - - IF (APPLE) - SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script - PREFIX "../" - ) - INSTALL(CODE " - GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) - SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") - GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) - GET_FILENAME_COMPONENT(exedir \"\${exe}\" PATH) - SET(plugin \"\${bundle}/Contents/Plugins/script/${Plugin_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}\") - - GET_ITEM_KEY(\"\${plugin}\" pkey) - SET(prereqs \"\") - GET_PREREQUISITES(\${plugin} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\") - FOREACH(pr \${prereqs}) - GET_ITEM_KEY(\"\${pr}\" rkey) - - #Don't change the path to TelldusCore - IF (NOT \"\${rkey}\" STREQUAL \"TelldusCore\") - #Check to see if this is ourself - IF (NOT \${pkey} STREQUAL \${rkey}) - SET(kv \"\") - SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exedir}\" \"\${bundle}/Contents/Frameworks/\" 1) - IF (NOT EXISTS \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") - COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(\"\${\${kv}_RESOLVED_ITEM}\" \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") - ENDIF () - EXECUTE_PROCESS(COMMAND install_name_tool - -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${plugin}\" - ) - ENDIF () - ENDIF () - - ENDFOREACH() - ") - ELSEIF (WIN32) - SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES - PREFIX "Plugins/script/" - ) - ELSE (APPLE) - SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script - ) - INSTALL(TARGETS ${Plugin_NAME} - LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script" - ) - ENDIF (APPLE) - SIGN(${Plugin_NAME}) -ELSE(Plugin_SRCS) - ADD_CUSTOM_TARGET(${Plugin_NAME} ALL - SOURCES ${Plugin_FILES} ${Plugin_TARGET_FILES} - ) -ENDIF(Plugin_SRCS) +FIND_PACKAGE( Qt4 REQUIRED ) +SET(QT_USE_QTSCRIPT TRUE) +INCLUDE( ${QT_USE_FILE} ) +FIND_PACKAGE( SignTool REQUIRED ) + +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + + +QT4_WRAP_CPP( Plugin_MOC_SRCS ${Plugin_MOC_HDRS} ) +QT4_AUTOMOC ( ${Plugin_SRCS} ) + +IF(Plugin_RESOURCES) + QT4_ADD_RESOURCES(Plugin_RSRCS ${Plugin_RESOURCES}) +ENDIF(Plugin_RESOURCES) + +SET( Plugin_LIBRARIES + ${Plugin_LIBRARIES} + ${QT_LIBRARIES} +) + +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) + +#SET( LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH/Plugins} ) + +FOREACH(lang ${LANGUAGES}) + IF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/translation_${lang}.ts" OR UPDATE_TRANSLATIONS) + LIST(APPEND Plugin_TS "translation_${lang}.ts") + ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/translation_${lang}.ts" OR UPDATE_TRANSLATIONS) +ENDFOREACH(lang) +SET(translation_sources ${Plugin_SRCS}) + +IF(Plugin_PATH) + STRING(REPLACE "." "/" + Plugin_PATH_relative ${Plugin_PATH} + ) + IF (APPLE) + SET(Plugin_PATH "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script/${Plugin_PATH_relative}") + ELSEIF (WIN32) + SET(Plugin_PATH "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/Plugins/script/${Plugin_PATH_relative}") + ELSE (APPLE) + SET(Plugin_PATH "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script/${Plugin_PATH_relative}") + ENDIF (APPLE) + + LIST(APPEND translation_sources + "${CMAKE_CURRENT_SOURCE_DIR}/__init__.js" + ) + LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/__init__.js") + #Add all extra files + FOREACH(_FILE ${Plugin_EXTRA}) + LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}") + ENDFOREACH(_FILE) +ENDIF(Plugin_PATH) + +IF (UPDATE_TRANSLATIONS) + QT4_CREATE_TRANSLATION( QM_FILES ${Plugin_SRCS} ${translation_sources} ${Plugin_TS} ) +ELSE (UPDATE_TRANSLATIONS) + QT4_ADD_TRANSLATION(Plugin_QM ${Plugin_TS}) + LIST(APPEND Plugin_FILES ${Plugin_QM}) +ENDIF (UPDATE_TRANSLATIONS) + +IF(Plugin_PATH) + FOREACH(_FILE ${Plugin_FILES}) + GET_FILENAME_COMPONENT(_FILENAME ${_FILE} NAME) + ADD_CUSTOM_COMMAND( OUTPUT ${Plugin_PATH}/${_FILENAME} + COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${Plugin_PATH}/${_FILENAME} + DEPENDS ${_FILE} + COMMENT "Copy ${_FILENAME} for plugin ${Plugin_NAME}" + ) + LIST(APPEND Plugin_TARGET_FILES "${Plugin_PATH}/${_FILENAME}") + IF (NOT APPLE) + INSTALL(FILES ${_FILE} DESTINATION "${PLUGIN_LIB_FULL_PATH}/script/${Plugin_PATH_relative}") + ENDIF () + ENDFOREACH(_FILE) +ENDIF(Plugin_PATH) + +IF(Plugin_SRCS) + ADD_LIBRARY(${Plugin_NAME} SHARED + ${Plugin_SRCS} + ${Plugin_HDRS} + ${Plugin_RSRCS} + ${Plugin_MOC_HDRS} + ${Plugin_MOC_SRCS} + ${Plugin_MOC_HDRS} + ${Plugin_FILES} + ${Plugin_TS} + ${Plugin_QM} + ${Plugin_TARGET_FILES} + ) + TARGET_LINK_LIBRARIES( ${Plugin_NAME} ${Plugin_LIBRARIES} ) + + IF (APPLE) + SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script + PREFIX "../" + ) + INSTALL(CODE " + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") + GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) + GET_FILENAME_COMPONENT(exedir \"\${exe}\" PATH) + SET(plugin \"\${bundle}/Contents/Plugins/script/${Plugin_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}\") + + GET_ITEM_KEY(\"\${plugin}\" pkey) + SET(prereqs \"\") + GET_PREREQUISITES(\${plugin} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\") + FOREACH(pr \${prereqs}) + GET_ITEM_KEY(\"\${pr}\" rkey) + + #Don't change the path to TelldusCore + IF (NOT \"\${rkey}\" STREQUAL \"TelldusCore\") + #Check to see if this is ourself + IF (NOT \${pkey} STREQUAL \${rkey}) + SET(kv \"\") + SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exedir}\" \"\${bundle}/Contents/Frameworks/\" 1) + IF (NOT EXISTS \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") + COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(\"\${\${kv}_RESOLVED_ITEM}\" \"\${\${kv}_RESOLVED_EMBEDDED_ITEM}\") + ENDIF () + EXECUTE_PROCESS(COMMAND install_name_tool + -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${plugin}\" + ) + ENDIF () + ENDIF () + + ENDFOREACH() + ") + ELSEIF (WIN32) + SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES + PREFIX "Plugins/script/" + ) + ELSE (APPLE) + SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script + ) + INSTALL(TARGETS ${Plugin_NAME} + LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script" + ) + ENDIF (APPLE) + SIGN(${Plugin_NAME}) +ELSE(Plugin_SRCS) + ADD_CUSTOM_TARGET(${Plugin_NAME} ALL + SOURCES ${Plugin_FILES} ${Plugin_TARGET_FILES} + ) +ENDIF(Plugin_SRCS) diff --git a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt index c5375aed..9df579c2 100644 --- a/telldus-gui/Plugins/TelldusCore/CMakeLists.txt +++ b/telldus-gui/Plugins/TelldusCore/CMakeLists.txt @@ -1,25 +1,25 @@ -SET( Plugin_NAME "TelldusCorePlugin" ) -SET( Plugin_PATH "com.telldus.core" ) - -SET( Plugin_SRCS - tellduscoreplugin.cpp - tellduscoreobject.cpp -) - -SET( Plugin_HDRS - tellduscoreplugin.h -) - -SET( Plugin_MOC_HDRS - tellduscoreobject.h -) - -SET( Plugin_EXTRA - Device.js - DeviceCommands.js -) - -FIND_PACKAGE(TelldusCore REQUIRED) -SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ) - -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) +SET( Plugin_NAME "TelldusCorePlugin" ) +SET( Plugin_PATH "com.telldus.core" ) + +SET( Plugin_SRCS + tellduscoreplugin.cpp + tellduscoreobject.cpp +) + +SET( Plugin_HDRS + tellduscoreplugin.h +) + +SET( Plugin_MOC_HDRS + tellduscoreobject.h +) + +SET( Plugin_EXTRA + Device.js + DeviceCommands.js +) + +FIND_PACKAGE(TelldusCore REQUIRED) +SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/telldus/CMakeLists.txt b/telldus-gui/Plugins/telldus/CMakeLists.txt index 07f744a0..f66b36df 100644 --- a/telldus-gui/Plugins/telldus/CMakeLists.txt +++ b/telldus-gui/Plugins/telldus/CMakeLists.txt @@ -1,11 +1,11 @@ -SET( Plugin_NAME "common" ) - -SET( Plugin_PATH "com" ) - -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) - -SET( Plugin_NAME "telldus" ) - -SET( Plugin_PATH "com.telldus" ) - -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) +SET( Plugin_NAME "common" ) + +SET( Plugin_PATH "com" ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) + +SET( Plugin_NAME "telldus" ) + +SET( Plugin_PATH "com.telldus" ) + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/xPL/CMakeLists.txt b/telldus-gui/Plugins/xPL/CMakeLists.txt index 92bb94fa..7c8695c0 100644 --- a/telldus-gui/Plugins/xPL/CMakeLists.txt +++ b/telldus-gui/Plugins/xPL/CMakeLists.txt @@ -1,27 +1,27 @@ -SET(QT_USE_QTNETWORK TRUE) - -SET( Plugin_NAME "xPLPlugin" ) -SET( Plugin_PATH "com.telldus.xpl" ) - -SET( Plugin_SRCS - xplplugin.cpp -) - -SET( Plugin_HDRS - xplplugin.h -) - -FIND_LIBRARY( QTXPL_LIBRARY qtxpl ) - -SET(QTXPL_INCLUDE_DIR "" CACHE PATH "Path to the directory which contains header files for qtxpl") - -INCLUDE_DIRECTORIES( - ${QTXPL_INCLUDE_DIR} -) - -SET( Plugin_LIBRARIES - ${QTXPL_LIBRARY} -) - - -INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) +SET(QT_USE_QTNETWORK TRUE) + +SET( Plugin_NAME "xPLPlugin" ) +SET( Plugin_PATH "com.telldus.xpl" ) + +SET( Plugin_SRCS + xplplugin.cpp +) + +SET( Plugin_HDRS + xplplugin.h +) + +FIND_LIBRARY( QTXPL_LIBRARY qtxpl ) + +SET(QTXPL_INCLUDE_DIR "" CACHE PATH "Path to the directory which contains header files for qtxpl") + +INCLUDE_DIRECTORIES( + ${QTXPL_INCLUDE_DIR} +) + +SET( Plugin_LIBRARIES + ${QTXPL_LIBRARY} +) + + +INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 8e55ce1b..b8b64def 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -1,213 +1,213 @@ -FIND_PACKAGE( Qt4 REQUIRED ) -SET(QT_USE_QTSCRIPT TRUE) -SET(QT_USE_QTNETWORK TRUE) +FIND_PACKAGE( Qt4 REQUIRED ) +SET(QT_USE_QTSCRIPT TRUE) +SET(QT_USE_QTNETWORK TRUE) SET(QT_USE_QTUITOOLS TRUE) IF (APPLE) #This is a workaround for plugins that depends on libraries and will not copy these correctly SET(QT_USE_QTDECLARATIVE TRUE) -ENDIF() -INCLUDE( ${QT_USE_FILE} ) - -FIND_PACKAGE( SignTool REQUIRED ) - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) - cmake_policy(SET CMP0005 NEW) -endif(COMMAND cmake_policy) - -######## Non configurable options ######## -SET( telldus-center_SRCS - configurationdialog.cpp - main.cpp - mainwindow.cpp - scriptenvironment.cpp - tellduscenterapplication.cpp - AutoUpdater.cpp - message.cpp - plugintree.cpp -) - -SET( telldus-center_HDRS - AutoUpdater.h - CocoaInitializer.h - tellduscenterplugin.h - plugintree.h -) - -SET( telldus-center_MOC_HDRS - configurationdialog.h - mainwindow.h - scriptenvironment.h - tellduscenterapplication.h - message.h -) - -SET( telldus-center_RESOURCES - TelldusCenter.icns -) - -SET( telldus-center_LANGS - sv -) - -QT4_WRAP_CPP( telldus-center_MOC_SRCS ${telldus-center_MOC_HDRS} ) -QT4_AUTOMOC ( ${telldus-center_SRCS} ) -QT4_ADD_RESOURCES (telldus-center_RSRCS resource.qrc ) - -SET( telldus-center_LIBRARIES - ${QT_LIBRARIES} -) - -ADD_DEFINITIONS( -DVERSION=${DISPLAYED_VERSION} ) - -######## Configurable options for the platform ######## - - - -######## Platforms-specific, non configurable ######## - -SET( telldus-center_TARGET TelldusCenter ) - +ENDIF() +INCLUDE( ${QT_USE_FILE} ) + +FIND_PACKAGE( SignTool REQUIRED ) + +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) + cmake_policy(SET CMP0005 NEW) +endif(COMMAND cmake_policy) + +######## Non configurable options ######## +SET( telldus-center_SRCS + configurationdialog.cpp + main.cpp + mainwindow.cpp + scriptenvironment.cpp + tellduscenterapplication.cpp + AutoUpdater.cpp + message.cpp + plugintree.cpp +) + +SET( telldus-center_HDRS + AutoUpdater.h + CocoaInitializer.h + tellduscenterplugin.h + plugintree.h +) + +SET( telldus-center_MOC_HDRS + configurationdialog.h + mainwindow.h + scriptenvironment.h + tellduscenterapplication.h + message.h +) + +SET( telldus-center_RESOURCES + TelldusCenter.icns +) + +SET( telldus-center_LANGS + sv +) + +QT4_WRAP_CPP( telldus-center_MOC_SRCS ${telldus-center_MOC_HDRS} ) +QT4_AUTOMOC ( ${telldus-center_SRCS} ) +QT4_ADD_RESOURCES (telldus-center_RSRCS resource.qrc ) + +SET( telldus-center_LIBRARIES + ${QT_LIBRARIES} +) + +ADD_DEFINITIONS( -DVERSION=${DISPLAYED_VERSION} ) + +######## Configurable options for the platform ######## + + + +######## Platforms-specific, non configurable ######## + +SET( telldus-center_TARGET TelldusCenter ) + IF (APPLE) #### Mac OS X #### - INCLUDE_DIRECTORIES( - /usr/include/QtUiTools - ) - CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in - ${CMAKE_CURRENT_BINARY_DIR}/Info.plist - ) - LIST(APPEND telldus-center_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in - ) - -ELSEIF (WIN32) #### Windows #### - ADD_DEFINITIONS( -DUNICODE ) - - CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/TelldusCenter.rc.in - ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.rc - ) - - INCLUDE_DIRECTORIES( - ${TELLDUSCORE_INCLUDE_DIR} - ) - SET(CMAKE_EXE_LINKER_FLAGS - "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS" - ) - SET( telldus-center_LIBRARIES - ${telldus-center_LIBRARIES} - "${QT_LIBRARY_DIR}/qtmain.lib" - ) - SET(telldus-center_SRCS - ${telldus-center_SRCS} - ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.rc - ) -ELSE (APPLE) #### Linux #### - ADD_DEFINITIONS( -DPLUGIN_LIB_PATH=${CMAKE_INSTALL_PREFIX}/${PLUGIN_LIB_FULL_PATH} ) -ENDIF (APPLE) - -######## QtSingleApplication ######## - -INCLUDE( ../3rdparty/qtsingleapplication.cmake NO_POLICY_SCOPE ) -SET( telldus-center_SRCS - ${telldus-center_SRCS} - ${qtsingleapplication_SRCS} -) - -######## Configuring ######## - -####### i18n ######## -FOREACH(lang ${LANGUAGES}) - LIST(APPEND telldus-center_TS "${telldus-center_TARGET}_${lang}.ts") -ENDFOREACH(lang) -IF (UPDATE_TRANSLATIONS) - QT4_CREATE_TRANSLATION( QM_FILES ${telldus-center_SRCS} ${telldus-center_TS} ) -ELSE (UPDATE_TRANSLATIONS) - IF (UNIX) - SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter - ) - ENDIF () - QT4_ADD_TRANSLATION(telldus-center_QM ${telldus-center_TS}) - IF (APPLE) - INSTALL(FILES ${telldus-center_QM} DESTINATION /Applications/TelldusCenter.app/Contents/Resources) - ENDIF () -ENDIF (UPDATE_TRANSLATIONS) - - - -ADD_EXECUTABLE(${telldus-center_TARGET} MACOSX_BUNDLE - ${telldus-center_SRCS} - ${telldus-center_MOC_SRCS} - ${telldus-center_RSRCS} - ${telldus-center_RESOURCES} - ${telldus-center_TS} - ${telldus-center_QM} -) -SET_SOURCE_FILES_PROPERTIES(${telldus-center_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - -TARGET_LINK_LIBRARIES( ${telldus-center_TARGET} ${telldus-center_LIBRARIES} ) - -SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist -) -SIGN(${telldus-center_TARGET}) -IF (APPLE) - SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} - ) - ADD_CUSTOM_COMMAND( TARGET ${telldus-center_TARGET} - POST_BUILD - COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script/" - ) -ENDIF (APPLE) - -IF (UNIX) - IF (GENERATE_MAN) - ADD_CUSTOM_COMMAND( - TARGET ${telldus-center_TARGET} - POST_BUILD - - COMMAND xsltproc --nonet --param man.charmap.use.subset "0" /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.man.xml - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "Generating man file TelldusCenter.1" - ) - INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.1 DESTINATION share/man/man1) - ENDIF (GENERATE_MAN) - IF (NOT APPLE) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/images/tellduscenter.xpm DESTINATION share/pixmaps) - INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.desktop DESTINATION share/applications) - ENDIF () -ENDIF (UNIX) - -IF (WIN32) - ADD_CUSTOM_COMMAND( TARGET ${telldus-center_TARGET} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${telldus-center_QM} ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR} VERBATIM - COMMENT "Copying translation for TelldusCenter" - ) -ENDIF() - -INSTALL(TARGETS ${telldus-center_TARGET} - RUNTIME DESTINATION bin - BUNDLE DESTINATION "/Applications" -) - -IF (APPLE) - INSTALL( - DIRECTORY ${QT_QTGUI_LIBRARY}/Resources/qt_menu.nib - DESTINATION /Applications/TelldusCenter.app/Contents/Resources - ) - INSTALL( - FILES qt.conf - DESTINATION /Applications/TelldusCenter.app/Contents/Resources - ) - INSTALL(CODE " - INCLUDE(BundleUtilities) - GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) - SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") - GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) - FIXUP_BUNDLE(\"\${bundle}\" \"\" \"\") - ") -ENDIF () - + INCLUDE_DIRECTORIES( + /usr/include/QtUiTools + ) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + ${CMAKE_CURRENT_BINARY_DIR}/Info.plist + ) + LIST(APPEND telldus-center_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + ) + +ELSEIF (WIN32) #### Windows #### + ADD_DEFINITIONS( -DUNICODE ) + + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/TelldusCenter.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.rc + ) + + INCLUDE_DIRECTORIES( + ${TELLDUSCORE_INCLUDE_DIR} + ) + SET(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS" + ) + SET( telldus-center_LIBRARIES + ${telldus-center_LIBRARIES} + "${QT_LIBRARY_DIR}/qtmain.lib" + ) + SET(telldus-center_SRCS + ${telldus-center_SRCS} + ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.rc + ) +ELSE (APPLE) #### Linux #### + ADD_DEFINITIONS( -DPLUGIN_LIB_PATH=${CMAKE_INSTALL_PREFIX}/${PLUGIN_LIB_FULL_PATH} ) +ENDIF (APPLE) + +######## QtSingleApplication ######## + +INCLUDE( ../3rdparty/qtsingleapplication.cmake NO_POLICY_SCOPE ) +SET( telldus-center_SRCS + ${telldus-center_SRCS} + ${qtsingleapplication_SRCS} +) + +######## Configuring ######## + +####### i18n ######## +FOREACH(lang ${LANGUAGES}) + LIST(APPEND telldus-center_TS "${telldus-center_TARGET}_${lang}.ts") +ENDFOREACH(lang) +IF (UPDATE_TRANSLATIONS) + QT4_CREATE_TRANSLATION( QM_FILES ${telldus-center_SRCS} ${telldus-center_TS} ) +ELSE (UPDATE_TRANSLATIONS) + IF (UNIX) + SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES + OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter + ) + ENDIF () + QT4_ADD_TRANSLATION(telldus-center_QM ${telldus-center_TS}) + IF (APPLE) + INSTALL(FILES ${telldus-center_QM} DESTINATION /Applications/TelldusCenter.app/Contents/Resources) + ENDIF () +ENDIF (UPDATE_TRANSLATIONS) + + + +ADD_EXECUTABLE(${telldus-center_TARGET} MACOSX_BUNDLE + ${telldus-center_SRCS} + ${telldus-center_MOC_SRCS} + ${telldus-center_RSRCS} + ${telldus-center_RESOURCES} + ${telldus-center_TS} + ${telldus-center_QM} +) +SET_SOURCE_FILES_PROPERTIES(${telldus-center_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + +TARGET_LINK_LIBRARIES( ${telldus-center_TARGET} ${telldus-center_LIBRARIES} ) + +SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist +) +SIGN(${telldus-center_TARGET}) +IF (APPLE) + SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} + ) + ADD_CUSTOM_COMMAND( TARGET ${telldus-center_TARGET} + POST_BUILD + COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script/" + ) +ENDIF (APPLE) + +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET ${telldus-center_TARGET} + POST_BUILD + + COMMAND xsltproc --nonet --param man.charmap.use.subset "0" /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.man.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file TelldusCenter.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) + IF (NOT APPLE) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/images/tellduscenter.xpm DESTINATION share/pixmaps) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.desktop DESTINATION share/applications) + ENDIF () +ENDIF (UNIX) + +IF (WIN32) + ADD_CUSTOM_COMMAND( TARGET ${telldus-center_TARGET} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${telldus-center_QM} ${EXECUTABLE_OUTPUT_PATH}/${CMAKE_CFG_INTDIR} VERBATIM + COMMENT "Copying translation for TelldusCenter" + ) +ENDIF() + +INSTALL(TARGETS ${telldus-center_TARGET} + RUNTIME DESTINATION bin + BUNDLE DESTINATION "/Applications" +) + +IF (APPLE) + INSTALL( + DIRECTORY ${QT_QTGUI_LIBRARY}/Resources/qt_menu.nib + DESTINATION /Applications/TelldusCenter.app/Contents/Resources + ) + INSTALL( + FILES qt.conf + DESTINATION /Applications/TelldusCenter.app/Contents/Resources + ) + INSTALL(CODE " + INCLUDE(BundleUtilities) + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") + GET_BUNDLE_AND_EXECUTABLE(\"\${app}\" bundle exe valid) + FIXUP_BUNDLE(\"\${bundle}\" \"\" \"\") + ") +ENDIF () + diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index fe7f5a5e..845ea9c1 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -1,197 +1,197 @@ -FIND_PACKAGE( Qt4 REQUIRED ) -INCLUDE( ${QT_USE_FILE} ) - -FIND_PACKAGE( SignTool REQUIRED ) - -if(COMMAND cmake_policy) - cmake_policy(SET CMP0003 NEW) -endif(COMMAND cmake_policy) - -######## Non configurable options ######## -SET( telldus-gui_SRCS - telldusgui.cpp - devicewidget.cpp - devicemodel.cpp - device.cpp - editdevicedialog.cpp - editgroupdialog.cpp - filtereddeviceproxymodel.cpp - vendordevicemodel.cpp - vendordevicetreeitem.cpp - devicesettingarctechselflearning.cpp - devicesettingbrateck.cpp - devicesettinggao.cpp - devicesettingikea.cpp - devicesettingnexa.cpp - devicesettingnexabell.cpp - devicesettingrisingsun.cpp - devicesettingsartano.cpp - devicesettingselflearning.cpp - devicesettingunitcode.cpp - devicesettingupm.cpp - devicesetting.cpp - methodwidget.cpp - deviceview.cpp -) - -SET( telldus-gui_HDRS - telldusgui.h -) - -SET( telldus-gui_MOC_HDRS - devicewidget.h - devicemodel.h - device.h - editdevicedialog.h - editgroupdialog.h - filtereddeviceproxymodel.h - vendordevicemodel.h - devicesettingarctechselflearning.h - devicesettingbrateck.h - devicesettinggao.h - devicesettingikea.h - devicesettingnexa.h - devicesettingnexabell.h - devicesettingrisingsun.h - devicesettingsartano.h - devicesettingselflearning.h - devicesettingunitcode.h - devicesettingupm.h - devicesetting.h - methodwidget.h - deviceview.h -) - -QT4_WRAP_CPP( telldus-gui_MOC_SRCS ${telldus-gui_MOC_HDRS} ) -QT4_AUTOMOC ( ${telldus-gui_SRCS} ) -QT4_ADD_RESOURCES (telldus-gui_RSRCS telldusgui.qrc data/${BRANDING}/resources.qrc ) - -LIST(APPEND telldus-gui_RSRCS data/${BRANDING}/devices.xml) - -SET( telldus-gui_LIBRARIES - ${QT_LIBRARIES} -) - -FIND_PACKAGE(TelldusCore REQUIRED) -LIST(APPEND telldus-gui_LIBRARIES ${TELLDUSCORE_LIBRARY} ) - -######## Configurable options for the platform ######## - - - -######## Platforms-specific, non configurable ######## - -IF (APPLE) - #### Mac OS X #### - SET( telldus-gui_TARGET TelldusGui ) - ADD_DEFINITIONS( - -D_MACOSX - ) - INCLUDE_DIRECTORIES( - /usr/local/include - ) - -ELSEIF (WIN32) - #### Windows #### - SET( telldus-gui_TARGET TelldusGui ) - ADD_DEFINITIONS( - -D_WINDOWS - -DTELLDUSGUI_EXPORTS - ) -ELSE (APPLE) - #### Linux #### - SET( telldus-gui_TARGET telldus-gui ) - ADD_DEFINITIONS( - -D_LINUX - ) -ENDIF (APPLE) - -######## Configuring ######## - -####### i18n ######## -FOREACH(lang ${LANGUAGES}) - LIST(APPEND telldus-gui_TS "TelldusGui_${lang}.ts") -ENDFOREACH(lang) -IF (UPDATE_TRANSLATIONS) - QT4_CREATE_TRANSLATION( QM_FILES ${telldus-gui_SRCS} ${telldus-gui_TS} ) -ELSE (UPDATE_TRANSLATIONS) - IF (APPLE) - SET_SOURCE_FILES_PROPERTIES(${telldus-gui_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Resources - ) - ELSEIF (UNIX) - SET_SOURCE_FILES_PROPERTIES(${telldus-gui_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter - ) - ENDIF (APPLE) - QT4_ADD_TRANSLATION(telldus-gui_QM ${telldus-gui_TS}) -ENDIF (UPDATE_TRANSLATIONS) - -ADD_LIBRARY(${telldus-gui_TARGET} SHARED - ${telldus-gui_SRCS} - ${telldus-gui_HDRS} - ${telldus-gui_MOC_SRCS} - ${telldus-gui_RSRCS} - ${telldus-gui_TS} - ${telldus-gui_QM} -) -ADD_DEPENDENCIES(${telldus-gui_TARGET} TelldusCenter) - -IF (UNIX) - SET_TARGET_PROPERTIES( ${telldus-gui_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") -ENDIF (UNIX) - -TARGET_LINK_LIBRARIES( ${telldus-gui_TARGET} ${telldus-gui_LIBRARIES} ) - -SIGN(${telldus-gui_TARGET}) - -SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES - FRAMEWORK TRUE -# PUBLIC_HEADER ${telldus-gui_HDRS} - VERSION ${PACKAGE_VERSION} - SOVERSION ${PACKAGE_SOVERSION} - INSTALL_NAME_DIR "/Library/Frameworks" -) - -IF (WIN32) - ADD_CUSTOM_COMMAND( TARGET ${telldus-gui_TARGET} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${telldus-gui_QM} ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR} VERBATIM - COMMENT "Copying translation for TelldusGUI" - ) -ENDIF() - -IF (UNIX) - INSTALL(TARGETS ${telldus-gui_TARGET} - LIBRARY DESTINATION lib - FRAMEWORK DESTINATION /Applications/TelldusCenter.app/Contents/Frameworks - # PUBLIC_HEADER DESTINATION ${HEADER_DIR} - ) - IF (APPLE) - INSTALL(CODE " - INCLUDE(BundleUtilities) - GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) - SET(lib \"\${DESTDIR}/Applications/TelldusCenter.app/Contents/Frameworks/${telldus-gui_TARGET}.framework/${telldus-gui_TARGET}\") - - GET_ITEM_KEY(\"\${lib}\" pkey) - SET(prereqs \"\") - GET_PREREQUISITES(\${lib} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\") - FOREACH(pr \${prereqs}) - GET_ITEM_KEY(\"\${pr}\" rkey) - - #Don't change the path to TelldusCore - IF (NOT \"\${rkey}\" STREQUAL \"TelldusCore\") - #Check to see if this is ourself - IF (NOT \${pkey} STREQUAL \${rkey}) - SET(kv \"\") - SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exe}\" \"\${bundle}/Contents/Frameworks/\" 0) - EXECUTE_PROCESS(COMMAND install_name_tool - -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${lib}\" - ) - ENDIF () - ENDIF () - - ENDFOREACH() - ") - ENDIF () -ENDIF () +FIND_PACKAGE( Qt4 REQUIRED ) +INCLUDE( ${QT_USE_FILE} ) + +FIND_PACKAGE( SignTool REQUIRED ) + +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +######## Non configurable options ######## +SET( telldus-gui_SRCS + telldusgui.cpp + devicewidget.cpp + devicemodel.cpp + device.cpp + editdevicedialog.cpp + editgroupdialog.cpp + filtereddeviceproxymodel.cpp + vendordevicemodel.cpp + vendordevicetreeitem.cpp + devicesettingarctechselflearning.cpp + devicesettingbrateck.cpp + devicesettinggao.cpp + devicesettingikea.cpp + devicesettingnexa.cpp + devicesettingnexabell.cpp + devicesettingrisingsun.cpp + devicesettingsartano.cpp + devicesettingselflearning.cpp + devicesettingunitcode.cpp + devicesettingupm.cpp + devicesetting.cpp + methodwidget.cpp + deviceview.cpp +) + +SET( telldus-gui_HDRS + telldusgui.h +) + +SET( telldus-gui_MOC_HDRS + devicewidget.h + devicemodel.h + device.h + editdevicedialog.h + editgroupdialog.h + filtereddeviceproxymodel.h + vendordevicemodel.h + devicesettingarctechselflearning.h + devicesettingbrateck.h + devicesettinggao.h + devicesettingikea.h + devicesettingnexa.h + devicesettingnexabell.h + devicesettingrisingsun.h + devicesettingsartano.h + devicesettingselflearning.h + devicesettingunitcode.h + devicesettingupm.h + devicesetting.h + methodwidget.h + deviceview.h +) + +QT4_WRAP_CPP( telldus-gui_MOC_SRCS ${telldus-gui_MOC_HDRS} ) +QT4_AUTOMOC ( ${telldus-gui_SRCS} ) +QT4_ADD_RESOURCES (telldus-gui_RSRCS telldusgui.qrc data/${BRANDING}/resources.qrc ) + +LIST(APPEND telldus-gui_RSRCS data/${BRANDING}/devices.xml) + +SET( telldus-gui_LIBRARIES + ${QT_LIBRARIES} +) + +FIND_PACKAGE(TelldusCore REQUIRED) +LIST(APPEND telldus-gui_LIBRARIES ${TELLDUSCORE_LIBRARY} ) + +######## Configurable options for the platform ######## + + + +######## Platforms-specific, non configurable ######## + +IF (APPLE) + #### Mac OS X #### + SET( telldus-gui_TARGET TelldusGui ) + ADD_DEFINITIONS( + -D_MACOSX + ) + INCLUDE_DIRECTORIES( + /usr/local/include + ) + +ELSEIF (WIN32) + #### Windows #### + SET( telldus-gui_TARGET TelldusGui ) + ADD_DEFINITIONS( + -D_WINDOWS + -DTELLDUSGUI_EXPORTS + ) +ELSE (APPLE) + #### Linux #### + SET( telldus-gui_TARGET telldus-gui ) + ADD_DEFINITIONS( + -D_LINUX + ) +ENDIF (APPLE) + +######## Configuring ######## + +####### i18n ######## +FOREACH(lang ${LANGUAGES}) + LIST(APPEND telldus-gui_TS "TelldusGui_${lang}.ts") +ENDFOREACH(lang) +IF (UPDATE_TRANSLATIONS) + QT4_CREATE_TRANSLATION( QM_FILES ${telldus-gui_SRCS} ${telldus-gui_TS} ) +ELSE (UPDATE_TRANSLATIONS) + IF (APPLE) + SET_SOURCE_FILES_PROPERTIES(${telldus-gui_TS} PROPERTIES + OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Resources + ) + ELSEIF (UNIX) + SET_SOURCE_FILES_PROPERTIES(${telldus-gui_TS} PROPERTIES + OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter + ) + ENDIF (APPLE) + QT4_ADD_TRANSLATION(telldus-gui_QM ${telldus-gui_TS}) +ENDIF (UPDATE_TRANSLATIONS) + +ADD_LIBRARY(${telldus-gui_TARGET} SHARED + ${telldus-gui_SRCS} + ${telldus-gui_HDRS} + ${telldus-gui_MOC_SRCS} + ${telldus-gui_RSRCS} + ${telldus-gui_TS} + ${telldus-gui_QM} +) +ADD_DEPENDENCIES(${telldus-gui_TARGET} TelldusCenter) + +IF (UNIX) + SET_TARGET_PROPERTIES( ${telldus-gui_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") +ENDIF (UNIX) + +TARGET_LINK_LIBRARIES( ${telldus-gui_TARGET} ${telldus-gui_LIBRARIES} ) + +SIGN(${telldus-gui_TARGET}) + +SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES + FRAMEWORK TRUE +# PUBLIC_HEADER ${telldus-gui_HDRS} + VERSION ${PACKAGE_VERSION} + SOVERSION ${PACKAGE_SOVERSION} + INSTALL_NAME_DIR "/Library/Frameworks" +) + +IF (WIN32) + ADD_CUSTOM_COMMAND( TARGET ${telldus-gui_TARGET} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${telldus-gui_QM} ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR} VERBATIM + COMMENT "Copying translation for TelldusGUI" + ) +ENDIF() + +IF (UNIX) + INSTALL(TARGETS ${telldus-gui_TARGET} + LIBRARY DESTINATION lib + FRAMEWORK DESTINATION /Applications/TelldusCenter.app/Contents/Frameworks + # PUBLIC_HEADER DESTINATION ${HEADER_DIR} + ) + IF (APPLE) + INSTALL(CODE " + INCLUDE(BundleUtilities) + GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) + SET(lib \"\${DESTDIR}/Applications/TelldusCenter.app/Contents/Frameworks/${telldus-gui_TARGET}.framework/${telldus-gui_TARGET}\") + + GET_ITEM_KEY(\"\${lib}\" pkey) + SET(prereqs \"\") + GET_PREREQUISITES(\${lib} prereqs 1 0 \"\${exe}\" \"\${bundle}/Contents/Frameworks/\") + FOREACH(pr \${prereqs}) + GET_ITEM_KEY(\"\${pr}\" rkey) + + #Don't change the path to TelldusCore + IF (NOT \"\${rkey}\" STREQUAL \"TelldusCore\") + #Check to see if this is ourself + IF (NOT \${pkey} STREQUAL \${rkey}) + SET(kv \"\") + SET_BUNDLE_KEY_VALUES(kv \"\${pr}\" \"\${pr}\" \"\${exe}\" \"\${bundle}/Contents/Frameworks/\" 0) + EXECUTE_PROCESS(COMMAND install_name_tool + -change \"\${pr}\" \"\${\${rkey}_EMBEDDED_ITEM}\" \"\${lib}\" + ) + ENDIF () + ENDIF () + + ENDFOREACH() + ") + ENDIF () +ENDIF () diff --git a/telldus-gui/TelldusGui/data/byron/devices.xml b/telldus-gui/TelldusGui/data/byron/devices.xml index f74a8c7a..d91622cf 100644 --- a/telldus-gui/TelldusGui/data/byron/devices.xml +++ b/telldus-gui/TelldusGui/data/byron/devices.xml @@ -1,9 +1,9 @@ - - - - - - - Self Learning on/off - - + + + + + + + Self Learning on/off + + diff --git a/telldus-gui/TelldusGui/data/byron/resources.qrc b/telldus-gui/TelldusGui/data/byron/resources.qrc index 2ea65497..8a90e21b 100644 --- a/telldus-gui/TelldusGui/data/byron/resources.qrc +++ b/telldus-gui/TelldusGui/data/byron/resources.qrc @@ -1,12 +1,12 @@ - - - devices.xml - ../../images/devices/arctech_cs.png - ../../images/devices/arctech_sl.png - ../../images/devices/bell.png - ../../images/devices/elro.png - ../../images/devices/elro-ab600.png - ../../images/vendors/elro.png - ../../images/vendors/homeeasy.png - - + + + devices.xml + ../../images/devices/arctech_cs.png + ../../images/devices/arctech_sl.png + ../../images/devices/bell.png + ../../images/devices/elro.png + ../../images/devices/elro-ab600.png + ../../images/vendors/elro.png + ../../images/vendors/homeeasy.png + + diff --git a/telldus-gui/TelldusGui/data/chacon/devices.xml b/telldus-gui/TelldusGui/data/chacon/devices.xml index 3859e8d6..a2351f94 100644 --- a/telldus-gui/TelldusGui/data/chacon/devices.xml +++ b/telldus-gui/TelldusGui/data/chacon/devices.xml @@ -1,7 +1,7 @@ - - - - - Self Learning on/off - - + + + + + Self Learning on/off + + diff --git a/telldus-gui/TelldusGui/data/chacon/resources.qrc b/telldus-gui/TelldusGui/data/chacon/resources.qrc index 3f9316c6..1b5be0f7 100644 --- a/telldus-gui/TelldusGui/data/chacon/resources.qrc +++ b/telldus-gui/TelldusGui/data/chacon/resources.qrc @@ -1,8 +1,8 @@ - - - devices.xml - ../../images/devices/arctech_cs.png - ../../images/devices/arctech_sl.png - ../../images/vendors/chacon.png - - + + + devices.xml + ../../images/devices/arctech_cs.png + ../../images/devices/arctech_sl.png + ../../images/vendors/chacon.png + + diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index 4b5eed67..69846a28 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -1,131 +1,131 @@ - - - - - - Code Switch - - - - Code Switch - - - - Code Switch - Self Learning on/off - Self Learning dimmer - Bell - - - - Code Switch - Self Learning on/off - Self Learning dimmer - Bell - - - Self Learning - - - Self Learning - - - - Code Switch - Code Switch - System AB600 - - - - Code Switch - Self Learning on/off - - - Code Switch - - - - Code Switch - Self Learning on/off - Self Learning dimmer - - - Code Switch - - - Koppla - - - - Code Switch - Self Learning on/off - Self Learning dimmer - Bell - - - - Code Switch - Self Learning on/off - Self Learning dimmer - Bell - - - - Code Switch - - - - Code Switch - Self Learning on/off - Self Learning dimmer - Bell - - - - Code Switch - Self Learning on/off - Self Learning dimmer - Bell - - - Self Learning - - - - Code Switch - Self Learning on/off - Self Learning dimmer - Bell - - - - Code Switch - Self Learning dimmer - - - - Code Switch - - - Self Learning - - - - Code Switch - - - - Code Switch - - - - - Blinds - - - Projector screen - - - KP100 - - - + + + + + + Code Switch + + + + Code Switch + + + + Code Switch + Self Learning on/off + Self Learning dimmer + Bell + + + + Code Switch + Self Learning on/off + Self Learning dimmer + Bell + + + Self Learning + + + Self Learning + + + + Code Switch + Code Switch - System AB600 + + + + Code Switch + Self Learning on/off + + + Code Switch + + + + Code Switch + Self Learning on/off + Self Learning dimmer + + + Code Switch + + + Koppla + + + + Code Switch + Self Learning on/off + Self Learning dimmer + Bell + + + + Code Switch + Self Learning on/off + Self Learning dimmer + Bell + + + + Code Switch + + + + Code Switch + Self Learning on/off + Self Learning dimmer + Bell + + + + Code Switch + Self Learning on/off + Self Learning dimmer + Bell + + + Self Learning + + + + Code Switch + Self Learning on/off + Self Learning dimmer + Bell + + + + Code Switch + Self Learning dimmer + + + + Code Switch + + + Self Learning + + + + Code Switch + + + + Code Switch + + + + + Blinds + + + Projector screen + + + KP100 + + + diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index 1cd8b8bf..637bdf4a 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -1,57 +1,57 @@ - - - devices.xml - ../../images/devices/arctech_cs.png - ../../images/devices/arctech_sl.png - ../../images/devices/bell.png - ../../images/devices/byebye.png - ../../images/devices/brennenstuhl_cs.png - ../../images/devices/conrad-rsl888.png - ../../images/devices/ecosavers.png - ../../images/devices/elro.png - ../../images/devices/elro-ab600.png - ../../images/devices/fr004r.png - ../../images/devices/goobay.png - ../../images/devices/gao_cs.png - ../../images/devices/gao_sl.png - ../../images/devices/hasta.png - ../../images/devices/hq_cs.png - ../../images/devices/koppla.png - ../../images/devices/kp100.png - ../../images/devices/otio.png - ../../images/devices/projectorscreen.png - ../../images/devices/risingsun_cs.png - ../../images/devices/sartano.png - ../../images/devices/upm_sl.png - ../../images/devices/waveman_cs.png - ../../images/devices/x10.png - ../../images/devices/zke-2603.png - ../../images/vendors/byebyelogo.png - ../../images/vendors/chacon.png - ../../images/vendors/coco.png - ../../images/vendors/conrad.png - ../../images/vendors/brennenstuhl.png - ../../images/vendors/ecosavers.png - ../../images/vendors/elro.png - ../../images/vendors/goobay.png - ../../images/vendors/gao.png - ../../images/vendors/hasta.png - ../../images/vendors/homeeasy.png - ../../images/vendors/hq.png - ../../images/vendors/ikea.png - ../../images/vendors/intertechno.png - ../../images/vendors/kappa.png - ../../images/vendors/kingpin.png - ../../images/vendors/kjelloco.png - ../../images/vendors/klikaanklikuit.png - ../../images/vendors/nexa.png - ../../images/vendors/otio.png - ../../images/vendors/proove.png - ../../images/vendors/roxcore.png - ../../images/vendors/rusta.png - ../../images/vendors/sartano.png - ../../images/vendors/upm.png - ../../images/vendors/waveman.png - ../../images/vendors/x10.png - - + + + devices.xml + ../../images/devices/arctech_cs.png + ../../images/devices/arctech_sl.png + ../../images/devices/bell.png + ../../images/devices/byebye.png + ../../images/devices/brennenstuhl_cs.png + ../../images/devices/conrad-rsl888.png + ../../images/devices/ecosavers.png + ../../images/devices/elro.png + ../../images/devices/elro-ab600.png + ../../images/devices/fr004r.png + ../../images/devices/goobay.png + ../../images/devices/gao_cs.png + ../../images/devices/gao_sl.png + ../../images/devices/hasta.png + ../../images/devices/hq_cs.png + ../../images/devices/koppla.png + ../../images/devices/kp100.png + ../../images/devices/otio.png + ../../images/devices/projectorscreen.png + ../../images/devices/risingsun_cs.png + ../../images/devices/sartano.png + ../../images/devices/upm_sl.png + ../../images/devices/waveman_cs.png + ../../images/devices/x10.png + ../../images/devices/zke-2603.png + ../../images/vendors/byebyelogo.png + ../../images/vendors/chacon.png + ../../images/vendors/coco.png + ../../images/vendors/conrad.png + ../../images/vendors/brennenstuhl.png + ../../images/vendors/ecosavers.png + ../../images/vendors/elro.png + ../../images/vendors/goobay.png + ../../images/vendors/gao.png + ../../images/vendors/hasta.png + ../../images/vendors/homeeasy.png + ../../images/vendors/hq.png + ../../images/vendors/ikea.png + ../../images/vendors/intertechno.png + ../../images/vendors/kappa.png + ../../images/vendors/kingpin.png + ../../images/vendors/kjelloco.png + ../../images/vendors/klikaanklikuit.png + ../../images/vendors/nexa.png + ../../images/vendors/otio.png + ../../images/vendors/proove.png + ../../images/vendors/roxcore.png + ../../images/vendors/rusta.png + ../../images/vendors/sartano.png + ../../images/vendors/upm.png + ../../images/vendors/waveman.png + ../../images/vendors/x10.png + + diff --git a/telldus-gui/TelldusGui/deviceview.cpp b/telldus-gui/TelldusGui/deviceview.cpp index edd45454..6d98db53 100644 --- a/telldus-gui/TelldusGui/deviceview.cpp +++ b/telldus-gui/TelldusGui/deviceview.cpp @@ -9,7 +9,7 @@ class MethodDelegate : public QStyledItemDelegate { public: MethodDelegate( QWidget *parent = 0 ); - QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; DeviceView::DeviceView(QWidget *parent) @@ -51,15 +51,15 @@ MethodDelegate::MethodDelegate( QWidget *parent ) :QStyledItemDelegate(parent) {} -QWidget *MethodDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /* option */, const QModelIndex &index) const { - DeviceView *p = qobject_cast(this->parent()); - if (!p) { - return 0; - } +QWidget *MethodDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /* option */, const QModelIndex &index) const { + DeviceView *p = qobject_cast(this->parent()); + if (!p) { + return 0; + } DeviceModel *model = qobject_cast( p->model() ); if (!model) { return 0; - } - MethodWidget *widget = new MethodWidget(model->device(index), parent); - return widget; - } + } + MethodWidget *widget = new MethodWidget(model->device(index), parent); + return widget; + } diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index e8662ab4..550dc727 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -1,18 +1,18 @@ - - - images/bell.png - images/list-add.png - images/list-edit.png - images/list-remove.png - images/state_1.png - images/state_2.png - images/state_16.png - images/state_dimmed_25.png - images/state_dimmed_50.png - images/state_dimmed_75.png - images/execute.png - images/up.png - images/down.png - images/stop.png - - + + + images/bell.png + images/list-add.png + images/list-edit.png + images/list-remove.png + images/state_1.png + images/state_2.png + images/state_16.png + images/state_dimmed_25.png + images/state_dimmed_50.png + images/state_dimmed_75.png + images/execute.png + images/up.png + images/down.png + images/stop.png + + diff --git a/telldus-gui/cmake/FindQCA.cmake b/telldus-gui/cmake/FindQCA.cmake index 9a66f6c5..6fb6c656 100644 --- a/telldus-gui/cmake/FindQCA.cmake +++ b/telldus-gui/cmake/FindQCA.cmake @@ -1,15 +1,15 @@ - -FIND_LIBRARY( QCA_LIBRARY qca ) - -IF (WIN32) - GET_FILENAME_COMPONENT(QCA_PATH ${QCA_LIBRARY} PATH) - MESSAGE(${QCA_PATH}) - INCLUDE_DIRECTORIES( - ${QCA_PATH}/../include/QtCrypto/ - ) - -ELSE(WIN32) - #Maybe not so pretty, should be done better - INCLUDE_DIRECTORIES( /usr/include/qca2/QtCrypto/ /usr/include/QtCrypto/ ) - -ENDIF (WIN32) + +FIND_LIBRARY( QCA_LIBRARY qca ) + +IF (WIN32) + GET_FILENAME_COMPONENT(QCA_PATH ${QCA_LIBRARY} PATH) + MESSAGE(${QCA_PATH}) + INCLUDE_DIRECTORIES( + ${QCA_PATH}/../include/QtCrypto/ + ) + +ELSE(WIN32) + #Maybe not so pretty, should be done better + INCLUDE_DIRECTORIES( /usr/include/qca2/QtCrypto/ /usr/include/QtCrypto/ ) + +ENDIF (WIN32) diff --git a/telldus-gui/cmake/FindSignTool.cmake b/telldus-gui/cmake/FindSignTool.cmake index 002bca60..db63e164 100644 --- a/telldus-gui/cmake/FindSignTool.cmake +++ b/telldus-gui/cmake/FindSignTool.cmake @@ -1,19 +1,19 @@ -IF(WIN32) - SET(SIGN_FILES FALSE CACHE BOOL "Sign files ofter build") -ENDIF() - -FUNCTION(SIGN TARGET) - IF (NOT WIN32) - RETURN() - ENDIF() - IF (NOT SIGN_FILES) - RETURN() - ENDIF() - GET_TARGET_PROPERTY(file ${TARGET} LOCATION) - GET_FILENAME_COMPONENT(filename ${file} NAME) - ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD - COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} - COMMENT "Signing file ${filename}" - ) -ENDFUNCTION() +IF(WIN32) + SET(SIGN_FILES FALSE CACHE BOOL "Sign files ofter build") +ENDIF() + +FUNCTION(SIGN TARGET) + IF (NOT WIN32) + RETURN() + ENDIF() + IF (NOT SIGN_FILES) + RETURN() + ENDIF() + GET_TARGET_PROPERTY(file ${TARGET} LOCATION) + GET_FILENAME_COMPONENT(filename ${file} NAME) + ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD + COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} + COMMENT "Signing file ${filename}" + ) +ENDFUNCTION() diff --git a/telldus-gui/cmake/FindTelldusCore.cmake b/telldus-gui/cmake/FindTelldusCore.cmake index 3bedd638..0c46cc49 100644 --- a/telldus-gui/cmake/FindTelldusCore.cmake +++ b/telldus-gui/cmake/FindTelldusCore.cmake @@ -1,21 +1,21 @@ - -IF (APPLE) - FIND_LIBRARY( TELLDUSCORE_LIBRARY TelldusCore ) - - INCLUDE_DIRECTORIES( - ${TELLDUSCORE_LIBRARY}/Headers - ) - -ELSEIF (WIN32) - SET(TELLDUSCORE_LIBRARY ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCore.lib) - SET(TELLDUSCORE_INCLUDE_PATH ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/) - -ELSE (APPLE) - FIND_LIBRARY( TELLDUSCORE_LIBRARY telldus-core ) - -ENDIF(APPLE) - -IF(TELLDUSCORE_INCLUDE_PATH) - INCLUDE_DIRECTORIES(${TELLDUSCORE_INCLUDE_PATH}) -ENDIF() - + +IF (APPLE) + FIND_LIBRARY( TELLDUSCORE_LIBRARY TelldusCore ) + + INCLUDE_DIRECTORIES( + ${TELLDUSCORE_LIBRARY}/Headers + ) + +ELSEIF (WIN32) + SET(TELLDUSCORE_LIBRARY ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/TelldusCore.lib) + SET(TELLDUSCORE_INCLUDE_PATH ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/) + +ELSE (APPLE) + FIND_LIBRARY( TELLDUSCORE_LIBRARY telldus-core ) + +ENDIF(APPLE) + +IF(TELLDUSCORE_INCLUDE_PATH) + INCLUDE_DIRECTORIES(${TELLDUSCORE_INCLUDE_PATH}) +ENDIF() + From c2be82e5d6b846de0da61525d288df9dfeca1be9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 28 Feb 2012 14:28:55 +0100 Subject: [PATCH 1940/2215] Copy the plugin to the destination folder after build instead of the combination using LIBRARY_OUTPUT_DIRECTORY and PREFIX. This allows us to build the plugins as universal binaries. Closes #121 --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 33ab90e9..4516856b 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -94,9 +94,14 @@ IF(Plugin_SRCS) TARGET_LINK_LIBRARIES( ${Plugin_NAME} ${Plugin_LIBRARIES} ) IF (APPLE) + ADD_CUSTOM_COMMAND(TARGET ${Plugin_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${Plugin_NAME}.dylib + ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script + COMMENT "Copy plugin ${Plugin_NAME} to destination bundle" + ) SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script - PREFIX "../" + PREFIX "" ) INSTALL(CODE " GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) From a35ad875d20fd8935be7c87426ab33cc231528f7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 28 Feb 2012 18:39:35 +0100 Subject: [PATCH 1941/2215] Add Telldus Live! python example. A tdtool implementation --- examples/python/live/tdtool/tdtool.py | 239 ++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100755 examples/python/live/tdtool/tdtool.py diff --git a/examples/python/live/tdtool/tdtool.py b/examples/python/live/tdtool/tdtool.py new file mode 100755 index 00000000..4c52d8ee --- /dev/null +++ b/examples/python/live/tdtool/tdtool.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import sys, getopt, httplib, urllib, json, os +import oauth.oauth as oauth +from configobj import ConfigObj + +PUBLIC_KEY = '' +PRIVATE_KEY = '' + +TELLSTICK_TURNON = 1 +TELLSTICK_TURNOFF = 2 +TELLSTICK_BELL = 4 +TELLSTICK_DIM = 16 +TELLSTICK_UP = 128 +TELLSTICK_DOWN = 256 + +SUPPORTED_METHODS = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM | TELLSTICK_UP | TELLSTICK_DOWN; + +def printUsage(): + print("Usage: %s [ options ]" % sys.argv[0]) + print("") + print("Options:") + print(" -[lnfdbvh] [ --list ] [ --help ]") + print(" [ --on device ] [ --off device ] [ --bell device ]") + print(" [ --dimlevel level --dim device ]") + print(" [ --up device --down device ]") + print("") + print(" --list (-l short option)") + print(" List currently configured devices.") + print("") + print(" --help (-h short option)") + print(" Shows this screen.") + print("") + print(" --on device (-n short option)") + print(" Turns on device. 'device' must be an integer of the device-id") + print(" Device-id and name is outputed with the --list option") + print("") + print(" --off device (-f short option)") + print(" Turns off device. 'device' must be an integer of the device-id") + print(" Device-id and name is outputed with the --list option") + print("") + print(" --dim device (-d short option)") + print(" Dims device. 'device' must be an integer of the device-id") + print(" Device-id and name is outputed with the --list option") + print(" Note: The dimlevel parameter must be set before using this option.") + print("") + print(" --dimlevel level (-v short option)") + print(" Set dim level. 'level' should an integer, 0-255.") + print(" Note: This parameter must be set before using dim.") + print("") + print(" --bell device (-b short option)") + print(" Sends bell command to devices supporting this. 'device' must") + print(" be an integer of the device-id") + print(" Device-id and name is outputed with the --list option") + print("") + print(" --up device") + print(" Sends up command to devices supporting this. 'device' must") + print(" be an integer of the device-id") + print(" Device-id and name is outputed with the --list option") + print("") + print(" --down device") + print(" Sends down command to devices supporting this. 'device' must") + print(" be an integer of the device-id") + print(" Device-id and name is outputed with the --list option") + print("") + print("Report bugs to ") + +def listDevices(): + response = doRequest('devices/list', {'supportedMethods': SUPPORTED_METHODS}) + print("Number of devices: %i" % len(response['device'])); + for device in response['device']: + if (device['state'] == TELLSTICK_TURNON): + state = 'ON' + elif (device['state'] == TELLSTICK_TURNOFF): + state = 'OFF' + elif (device['state'] == TELLSTICK_DIM): + state = "DIMMED" + elif (device['state'] == TELLSTICK_UP): + state = "UP" + elif (device['state'] == TELLSTICK_DOWN): + state = "DOWN" + else: + state = 'Unknown state' + + print("%s\t%s\t%s" % (device['id'], device['name'], state)); + +def doMethod(deviceId, methodId, methodValue = 0): + response = doRequest('device/info', {'id': deviceId}) + + if (methodId == TELLSTICK_TURNON): + method = 'on' + elif (methodId == TELLSTICK_TURNOFF): + method = 'off' + elif (methodId == TELLSTICK_BELL): + method = 'bell' + elif (methodId == TELLSTICK_UP): + method = 'up' + elif (methodId == TELLSTICK_DOWN): + method = 'down' + + if ('error' in response): + name = '' + retString = response['error'] + else: + name = response['name'] + response = doRequest('device/command', {'id': deviceId, 'method': methodId, 'value': methodValue}) + if ('error' in response): + retString = response['error'] + else: + retString = response['status'] + + if (methodId in (TELLSTICK_TURNON, TELLSTICK_TURNOFF)): + print("Turning %s device %s, %s - %s" % ( method, deviceId, name, retString)); + elif (methodId in (TELLSTICK_BELL, TELLSTICK_UP, TELLSTICK_DOWN)): + print("Sending %s to: %s %s - %s" % (method, deviceId, name, retString)) + elif (methodId == TELLSTICK_DIM): + print("Dimming device: %s %s to %s - %s" % (deviceId, name, methodValue, retString)) + + +def doRequest(method, params): + global config + consumer = oauth.OAuthConsumer(PUBLIC_KEY, PRIVATE_KEY) + token = oauth.OAuthToken(config['token'], config['tokenSecret']) + + oauth_request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='GET', http_url="http://api.telldus.com/json/" + method, parameters=params) + oauth_request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, token) + headers = oauth_request.to_header() + headers['Content-Type'] = 'application/x-www-form-urlencoded' + + conn = httplib.HTTPConnection("api.telldus.com:80") + conn.request('GET', "/json/" + method + "?" + urllib.urlencode(params, True).replace('+', '%20'), headers=headers) + + response = conn.getresponse() + return json.load(response) + +def requestToken(): + global config + consumer = oauth.OAuthConsumer(PUBLIC_KEY, PRIVATE_KEY) + request = oauth.OAuthRequest.from_consumer_and_token(consumer, http_url='http://api.telldus.com/oauth/requestToken') + request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, None) + conn = httplib.HTTPConnection('api.telldus.com:80') + conn.request(request.http_method, '/oauth/requestToken', headers=request.to_header()) + + resp = conn.getresponse().read() + token = oauth.OAuthToken.from_string(resp) + print 'Open the following url in your webbrowser:\nhttp://api.telldus.com/oauth/authorize?oauth_token=%s\n' % token.key + print 'After logging in and accepting to use this application run:\n%s --authenticate' % (sys.argv[0]) + config['requestToken'] = str(token.key) + config['requestTokenSecret'] = str(token.secret) + saveConfig() + +def getAccessToken(): + global config + consumer = oauth.OAuthConsumer(PUBLIC_KEY, PRIVATE_KEY) + token = oauth.OAuthToken(config['requestToken'], config['requestTokenSecret']) + request = oauth.OAuthRequest.from_consumer_and_token(consumer, token=token, http_method='GET', http_url='http://api.telldus.com/oauth/accessToken') + request.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(), consumer, token) + conn = httplib.HTTPConnection('api.telldus.com:80') + conn.request(request.http_method, request.to_url(), headers=request.to_header()) + + resp = conn.getresponse() + if resp.status != 200: + print 'Error retreiving access token, the server replied:\n%s' % resp.read() + return + token = oauth.OAuthToken.from_string(resp.read()) + config['requestToken'] = None + config['requestTokenSecret'] = None + config['token'] = str(token.key) + config['tokenSecret'] = str(token.secret) + print 'Authentication successful, you can now use tdtool' + saveConfig() + +def authenticate(): + try: + opts, args = getopt.getopt(sys.argv[1:], '', ['authenticate']) + for opt, arg in opts: + if opt in ('--authenticate'): + getAccessToken() + return + except getopt.GetoptError: + pass + requestToken() + +def saveConfig(): + global config + try: + os.makedirs(os.environ['HOME'] + '/.config/Telldus') + except: + pass + config.write() + +def main(argv): + global config + if ('token' not in config or config['token'] == ''): + authenticate() + return + try: + opts, args = getopt.getopt(argv, "ln:f:d:b:v:h", ["list", "on=", "off=", "dim=", "bell=", "dimlevel=", "up=", "down=", "help"]) + except getopt.GetoptError: + printUsage() + sys.exit(2) + + dimlevel = -1 + + for opt, arg in opts: + if opt in ("-h", "--help"): + printUsage() + + elif opt in ("-l", "--list"): + listDevices() + + elif opt in ("-n", "--on"): + doMethod(arg, TELLSTICK_TURNON) + + elif opt in ("-f", "--off"): + doMethod(arg, TELLSTICK_TURNOFF) + + elif opt in ("-b", "--bell"): + doMethod(arg, TELLSTICK_BELL) + + elif opt in ("-d", "--dim"): + if (dimlevel < 0): + print("Dimlevel must be set with --dimlevel before --dim") + else: + doMethod(arg, TELLSTICK_DIM, dimlevel) + + elif opt in ("-v", "--dimlevel"): + dimlevel = arg + + elif opt in ("--up"): + doMethod(arg, TELLSTICK_UP) + + elif opt in ("--down"): + doMethod(arg, TELLSTICK_DOWN) + +if __name__ == "__main__": + config = ConfigObj(os.environ['HOME'] + '/.config/Telldus/tdtool.conf') + main(sys.argv[1:]) From 5e8a3c965aee05cb54a714e44fc55eb93f7f9f85 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 1 Mar 2012 15:30:40 +0100 Subject: [PATCH 1942/2215] Add the version number if we cannot detect the platform on Windows --- telldus-gui/Plugins/Live/LiveObject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 27b73280..dcd61448 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -312,7 +312,7 @@ LiveMessageToken LiveObject::generateVersionToken() { token.dictVal["os-version"] = LiveMessageToken("win7"); break; default: - token.dictVal["os-version"] = LiveMessageToken("unknown"); + token.dictVal["os-version"] = LiveMessageToken(QString("unknown %1").arg(QSysInfo::WindowsVersion)); } #elif defined(Q_OS_MAC) token.dictVal["os"] = LiveMessageToken("macosx"); From 4760aa8a3272c695320214ca23b9bc78ee947f0d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 1 Mar 2012 15:32:07 +0100 Subject: [PATCH 1943/2215] Add possible constant for detecting mountain lion --- telldus-gui/Plugins/Live/LiveObject.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index dcd61448..c5e29f0a 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -326,6 +326,9 @@ LiveMessageToken LiveObject::generateVersionToken() { case QSysInfo::MV_SNOWLEOPARD+1: //TODO: MV_LION when we build against Qt-4.8 token.dictVal["os-version"] = LiveMessageToken("lion"); break; + case QSysInfo::MV_SNOWLEOPARD+2: //TODO: MV_MOUNTAINLION? when Qt has it + token.dictVal["os-version"] = LiveMessageToken("mountainlion"); + break; default: token.dictVal["os-version"] = LiveMessageToken("unknown"); } From bda20c75f0eb821d64296ee21455637a7489723b Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 6 Mar 2012 13:51:06 +0100 Subject: [PATCH 1944/2215] Remove stray statement --- telldus-core/client/telldus-core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 8108f761..b75ff14f 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -110,7 +110,7 @@ void WINAPI tdInit(void) { * Added in version 2.0.0. **/ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - eventFunction; Client *client = Client::getInstance(); + Client *client = Client::getInstance(); return client->registerEvent( CallbackStruct::DeviceEvent, (void *)eventFunction, context ); } From e921be65b427d1473693ad89d469c4e15449b773 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 6 Mar 2012 13:53:39 +0100 Subject: [PATCH 1945/2215] Fix variable name in code example --- docs/01-telldus-core.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/01-telldus-core.dox b/docs/01-telldus-core.dox index d7df9100..b5987450 100644 --- a/docs/01-telldus-core.dox +++ b/docs/01-telldus-core.dox @@ -44,7 +44,7 @@ * \code * int intNumberOfDevices = tdGetNumberOfDevices(); * for (int i = 0; i < intNumberOfDevices; i++) { - * int id = tdGetDeviceId( index ); + * int id = tdGetDeviceId( i ); * char *name = tdGetName( id ); * printf("%d\t%s\n", id, name); * tdReleaseString(name); From 1108f3fad26f744c2418d22a547a17669522ce2e Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 6 Mar 2012 13:58:31 +0100 Subject: [PATCH 1946/2215] Return type for callbacks is void, not void* --- examples/python/callbacks.py | 10 +++++----- examples/python/sensors/sensorscallback.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/python/callbacks.py b/examples/python/callbacks.py index 2108fd28..a5a02a27 100644 --- a/examples/python/callbacks.py +++ b/examples/python/callbacks.py @@ -58,11 +58,11 @@ def rawcallbackfunction(data, controllerId, callbackId, context): print string_at(data) if (platform.system() == 'Windows'): - CMPFUNC = WINFUNCTYPE(c_void_p, c_int, c_int, POINTER(c_ubyte), c_int, c_void_p) #first is return type - CMPFUNCRAW = WINFUNCTYPE(c_void_p, POINTER(c_ubyte), c_int, c_int, c_void_p) + CMPFUNC = WINFUNCTYPE(None, c_int, c_int, POINTER(c_ubyte), c_int, c_void_p) #first is return type + CMPFUNCRAW = WINFUNCTYPE(None, POINTER(c_ubyte), c_int, c_int, c_void_p) else: - CMPFUNC = CFUNCTYPE(c_void_p, c_int, c_int, POINTER(c_ubyte), c_int, c_void_p) - CMPFUNCRAW = CFUNCTYPE(c_void_p, POINTER(c_ubyte), c_int, c_int, c_void_p) + CMPFUNC = CFUNCTYPE(None, c_int, c_int, POINTER(c_ubyte), c_int, c_void_p) + CMPFUNCRAW = CFUNCTYPE(None, POINTER(c_ubyte), c_int, c_int, c_void_p) cmp_func = CMPFUNC(callbackfunction) cmp_funcraw = CMPFUNCRAW(rawcallbackfunction) @@ -73,4 +73,4 @@ lib.tdRegisterDeviceEvent(cmp_func, 0) print "Waiting for events..." while(1): - time.sleep(0.5) #don't exit \ No newline at end of file + time.sleep(0.5) #don't exit diff --git a/examples/python/sensors/sensorscallback.py b/examples/python/sensors/sensorscallback.py index 7a592b89..8dc5ffd8 100644 --- a/examples/python/sensors/sensorscallback.py +++ b/examples/python/sensors/sensorscallback.py @@ -29,9 +29,9 @@ def callbackfunction(protocol, model, id, dataType, value, timestamp, callbackId if (platform.system() == 'Windows'): - CMPFUNC = WINFUNCTYPE(c_void_p, POINTER(c_ubyte), POINTER(c_ubyte), c_int, c_int, POINTER(c_ubyte), c_int, c_int, c_void_p) #first is return type + CMPFUNC = WINFUNCTYPE(None, POINTER(c_ubyte), POINTER(c_ubyte), c_int, c_int, POINTER(c_ubyte), c_int, c_int, c_void_p) #first is return type else: - CMPFUNC = CFUNCTYPE(c_void_p, POINTER(c_ubyte), POINTER(c_ubyte), c_int, c_int, POINTER(c_ubyte), c_int, c_int, c_void_p) + CMPFUNC = CFUNCTYPE(None, POINTER(c_ubyte), POINTER(c_ubyte), c_int, c_int, POINTER(c_ubyte), c_int, c_int, c_void_p) cmp_func = CMPFUNC(callbackfunction) From e5c2a9c84768b16189b5697678f3193587b20b93 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 13 Mar 2012 14:59:44 +0100 Subject: [PATCH 1947/2215] Store configured settings paths in header file --- telldus-core/service/CMakeLists.txt | 11 ++++++++++- telldus-core/service/SettingsConfusePaths.h.in | 7 +++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 telldus-core/service/SettingsConfusePaths.h.in diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 0545af4a..23eea99f 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -240,8 +240,17 @@ ENDIF (UNIX) IF (UNIX AND NOT APPLE) INSTALL(TARGETS ${telldus-service_TARGET} RUNTIME DESTINATION sbin) SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) - SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices" ) + IF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + SET(STATE_INSTALL_DIR "/var/spool" CACHE PATH "The directory to store state information of the devices") + ELSE (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices") + ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/SettingsConfusePaths.h.in + ${CMAKE_CURRENT_BINARY_DIR}/SettingsConfusePaths.h) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + INSTALL(FILES tellstick.conf DESTINATION ${SYSCONF_INSTALL_DIR} ) diff --git a/telldus-core/service/SettingsConfusePaths.h.in b/telldus-core/service/SettingsConfusePaths.h.in new file mode 100644 index 00000000..ea16e6b0 --- /dev/null +++ b/telldus-core/service/SettingsConfusePaths.h.in @@ -0,0 +1,7 @@ +#ifndef SETTINGSCONFUSEPATHS_H +#define SETTINGSCONFUSEPATHS_H + +#define CONFIG_PATH "@SYSCONF_INSTALL_DIR@" +#define VAR_CONFIG_PATH "@STATE_INSTALL_DIR@" + +#endif From 104ce0fb237cdf752e06b6cebeb50e660bd0564c Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 13 Mar 2012 15:00:07 +0100 Subject: [PATCH 1948/2215] Use configured paths when accessing settings files --- telldus-core/service/SettingsConfuse.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index ebe0e8c2..5d926ac1 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -10,6 +10,7 @@ // // #include "Settings.h" +#include "SettingsConfusePaths.h" #include "../client/telldus-core.h" #include "Strings.h" #include @@ -28,12 +29,8 @@ public: bool readConfig(cfg_t **cfg); bool readVarConfig(cfg_t **cfg); -const char* CONFIG_FILE = "/etc/tellstick.conf"; -#ifdef __FreeBSD__ -const char* VAR_CONFIG_FILE = "/var/spool/telldus-core.conf"; -#else -const char* VAR_CONFIG_FILE = "/var/state/telldus-core.conf"; -#endif +const char* CONFIG_FILE = CONFIG_PATH "/tellstick.conf"; +const char* VAR_CONFIG_FILE = VAR_CONFIG_PATH "/telldus-core.conf"; /* * Constructor From cc6420920e79814ee7bde54c1b009492942efa4a Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 13 Mar 2012 20:20:02 +0100 Subject: [PATCH 1949/2215] Use doxygen command @since instead of "Added in..." --- telldus-core/client/telldus-core.cpp | 94 +++++++++++++++------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 8108f761..59462d18 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -100,14 +100,14 @@ using namespace TelldusCore; * This function initiates the library. Call this function before any other * call to a function in telldus-core. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ void WINAPI tdInit(void) { Client::getInstance(); //Create the manager-object } /** - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { eventFunction; Client *client = Client::getInstance(); @@ -115,7 +115,7 @@ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { } /** - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { Client *client = Client::getInstance(); @@ -123,7 +123,7 @@ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *conte } /** - * Added in version 2.1.0. + * @since Version 2.1.0 **/ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { Client *client = Client::getInstance(); @@ -131,7 +131,7 @@ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void } /** - * Added in version 2.1.0. + * @since Version 2.1.0 **/ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { Client *client = Client::getInstance(); @@ -139,7 +139,7 @@ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { } /** - * Added in version 2.1.2. + * @since Version 2.1.2 **/ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context) { Client *client = Client::getInstance(); @@ -147,7 +147,7 @@ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *con } /** - * Added in version 2.1.0. + * @since Version 2.1.0 **/ int WINAPI tdUnregisterCallback( int callbackId ) { Client *client = Client::getInstance(); @@ -158,7 +158,7 @@ int WINAPI tdUnregisterCallback( int callbackId ) { * Close the library and clean up the cache it uses. * This should be called when the library is not supposed to be used anymore * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ void WINAPI tdClose(void) { Client::close(); @@ -168,7 +168,7 @@ void WINAPI tdClose(void) { * This method releases resources allocated by telldus-core. * It should be called on the returned value from all functions return char * * - * Added in version 2.0.1. + * @since Version 2.0.1 **/ void WINAPI tdReleaseString(char *string) { #ifdef _WINDOWS @@ -184,7 +184,7 @@ void WINAPI tdReleaseString(char *string) { * call to this function. * @param intDeviceId The device id to turn on. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdTurnOn(int intDeviceId){ Message msg(L"tdTurnOn"); @@ -198,7 +198,7 @@ int WINAPI tdTurnOn(int intDeviceId){ * call to this function. * @param intDeviceId The device id to turn off. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdTurnOff(int intDeviceId){ Message msg(L"tdTurnOff"); @@ -212,7 +212,7 @@ int WINAPI tdTurnOff(int intDeviceId){ * call to this function. * @param intDeviceId The device id to send bell to * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdBell(int intDeviceId){ Message msg(L"tdBell"); @@ -227,7 +227,7 @@ int WINAPI tdBell(int intDeviceId){ * @param intDeviceId The device id to dim * @param level The level the device should dim to. This value should be 0-255 * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdDim(int intDeviceId, unsigned char level){ Message msg(L"tdDim"); @@ -242,7 +242,7 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ * call to this function. * @param intDeviceId The id to execute * - * Added in version 2.1.0. + * @since Version 2.1.0 **/ int WINAPI tdExecute(int intDeviceId){ Message msg(L"tdExecute"); @@ -256,7 +256,7 @@ int WINAPI tdExecute(int intDeviceId){ * call to this function. * @param intDeviceId The device id to send the command to * - * Added in version 2.1.0. + * @since Version 2.1.0 **/ int WINAPI tdUp(int intDeviceId){ Message msg(L"tdUp"); @@ -270,7 +270,7 @@ int WINAPI tdUp(int intDeviceId){ * call to this function. * @param intDeviceId The device id to send the command to * - * Added in version 2.1.0. + * @since Version 2.1.0 **/ int WINAPI tdDown(int intDeviceId){ Message msg(L"tdDown"); @@ -284,7 +284,7 @@ int WINAPI tdDown(int intDeviceId){ * call to this function. * @param intDeviceId The device id to stop * - * Added in version 2.1.0. + * @since Version 2.1.0 */ int WINAPI tdStop(int intDeviceId){ Message msg(L"tdStop"); @@ -299,7 +299,7 @@ int WINAPI tdStop(int intDeviceId){ * call to this function. * @param intDeviceId The device id to learn. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdLearn(int intDeviceId) { Message msg(L"tdLearn"); @@ -313,7 +313,7 @@ int WINAPI tdLearn(int intDeviceId) { * @param methodsSupported The methods supported by the client. See tdMethods() for more information. * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { Message msg(L"tdLastSentCommand"); @@ -327,7 +327,7 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { * @param intDeviceId The device id to query * @returns the the value as a human readable string, example "128" for 50% * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ char * WINAPI tdLastSentValue( int intDeviceId ) { Message msg(L"tdLastSentValue"); @@ -340,7 +340,7 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * This function returns the number of devices configured * @returns an integer of the total number of devices configured * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdGetNumberOfDevices(void){ return Client::getIntegerFromService(Message(L"tdGetNumberOfDevices")); @@ -359,7 +359,7 @@ int WINAPI tdGetNumberOfDevices(void){ * @param intDeviceIndex The device index to query. The index starts from 0. * @returns the unique id for the device or -1 if the device is not found. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdGetDeviceId(int intDeviceIndex){ Message msg(L"tdGetDeviceId"); @@ -371,7 +371,7 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ * Returns which type the device is. The device could be either * TELLSTICK_TYPE_DEVICE, TELLSTICK_TYPE_GROUP or TELLSTICK_TYPE_SCENE * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdGetDeviceType(int intDeviceId) { Message msg(L"tdGetDeviceType"); @@ -384,7 +384,7 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * @param intDeviceId The unique id of the device to query * @returns The name of the device or an empty string if the device is not found. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ char * WINAPI tdGetName(int intDeviceId){ Message msg(L"tdGetName"); @@ -400,7 +400,7 @@ char * WINAPI tdGetName(int intDeviceId){ * @param strNewName The new name for the devices * @returns \c true on success, \c false otherwise. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ Message msg(L"tdSetName"); @@ -413,7 +413,7 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ * @returns the protocol used by a specific device. * @param intDeviceId The device id to query. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ char* WINAPI tdGetProtocol(int intDeviceId){ Message msg(L"tdGetProtocol"); @@ -431,7 +431,7 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * @sa tdSetModel() * @sa tdSetDeviceParameter() * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ Message msg(L"tdSetProtocol"); @@ -444,7 +444,7 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ * @returns the model for a device. Not all protocols uses this. * @param intDeviceId The device to query. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ char* WINAPI tdGetModel(int intDeviceId){ Message msg(L"tdGetModel"); @@ -460,7 +460,7 @@ char* WINAPI tdGetModel(int intDeviceId){ * @param strModel The new model * @returns \c true on success, \c false otherwise. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ Message msg(L"tdSetModel"); @@ -477,7 +477,7 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * @param strValue The new value for the parameter. * @returns \c true on success, \c false otherwise. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ Message msg(L"tdSetDeviceParameter"); @@ -493,7 +493,7 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * @param strName The name of the parameter to query. * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ Message msg(L"tdGetDeviceParameter"); @@ -510,7 +510,7 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c * @returns the new device id for the newly created device. If the creation fails it returnes a * negative value. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdAddDevice(){ Message msg(L"tdAddDevice"); @@ -521,7 +521,7 @@ int WINAPI tdAddDevice(){ * Removes a device. * @returns \c true on success, \c false otherwise. * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ bool WINAPI tdRemoveDevice(int intDeviceId){ Message msg(L"tdRemoveDevice"); @@ -552,7 +552,7 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * @sa TELLSTICK_DOWN * @sa TELLSTICK_STOP * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdMethods(int id, int methodsSupported){ Message msg(L"tdMethods"); @@ -579,7 +579,7 @@ int WINAPI tdMethods(int id, int methodsSupported){ * @sa TELLSTICK_ERROR_COMMUNICATING_SERVICE * @sa TELLSTICK_ERROR_UNKNOWN * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ char * WINAPI tdGetErrorString(int intErrorNo) { const int numResponses = 10; @@ -614,7 +614,7 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * @param reserved Reserved for future use * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure * - * Added in version 2.0.0. + * @since Version 2.0.0 **/ int WINAPI tdSendRawCommand(const char *command, int reserved) { std::wstring wcommand; @@ -628,7 +628,7 @@ int WINAPI tdSendRawCommand(const char *command, int reserved) { } /** - * Added in version 2.1.0. + * @since Version 2.1.0 **/ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { Message msg(L"tdConnectTellStickController"); @@ -639,7 +639,7 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { } /** - * Added in version 2.1.0. + * @since Version 2.1.0 **/ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { Message msg(L"tdDisconnectTellStickController"); @@ -653,7 +653,6 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial * Use this function to iterate over all sensors. Iterate until * TELLSTICK_SUCCESS is not returned * - * Added in version 2.1.0. * @param protocol A byref string where the protocol of the sensor will be placed * @param protocolLen The length of the \c protocol parameter * @param model A byref string where the model of the sensor will be placed @@ -661,6 +660,8 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial * @param id A byref int where the id of the sensor will be placed * @param dataTypes A byref int with flags for the supported sensor values * @returns TELLSTICK_SUCCESS if there is more sensors to be fetched + * + * @since Version 2.1.0 */ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes) { Client *client = Client::getInstance(); @@ -672,7 +673,6 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, * the value type first by calling tdSensor(). The triplet \c protocol, * \c model, and \c id together identifies a sensor. * - * Added in version 2.1.0. * @param protocol The protocol for the sensor * @param model The model for the sensor * @param id The id of the sensor @@ -682,6 +682,8 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, * @param timestamp A byref int where the timestamp of the value will be placed * @returns TELLSTICK_SUCCESS if the value could be fetched or one of the * errorcodes on failure + * + * @since Version 2.1.0 */ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp) { Message msg(L"tdSensorValue"); @@ -709,7 +711,6 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da * Use this function to iterate over all controllers. Iterate until * TELLSTICK_SUCCESS is not returned * - * Added in version 2.1.2. * @param controllerId A byref int where the id of the controller will be placed * @param controllerType A byref int where the type of the controller will be placed * @param name A byref string where the name of the controller will be placed @@ -719,6 +720,8 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da * @sa TELLSTICK_CONTROLLER_TELLSTICK * @sa TELLSTICK_CONTROLLER_TELLSTICK_DUO * @sa TELLSTICK_CONTROLLER_TELLSTICK_NET + * + * @since Version 2.1.2 **/ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available) { Client *client = Client::getInstance(); @@ -729,10 +732,11 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int * This function gets a parameter on a controller. * Valid parameters are: \c serial \c and firmware * - * Added in version 2.1.2. * @param controllerId The controller to change * @param name The parameter to get. * @param value A byref string where the value of the parameter will be placed + * + * @since Version 2.1.2 **/ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen) { Message msg(L"tdControllerValue"); @@ -753,10 +757,11 @@ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, in * This function sets a parameter on a controller. * Valid parameters are: \c name * - * Added in version 2.1.2. * @param controllerId The controller to change * @param name The parameter to change. * @param value The new value for the parameter. + * + * @since Version 2.1.2 **/ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value) { Message msg(L"tdSetControllerValue"); @@ -771,12 +776,13 @@ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char * * of controllers. The controller must not be * available (disconnected) for this to work. * - * Added in version 2.1.2. * @param controllerId The controller to remove * @returns TELLSTICK_SUCCESS if the controller was * removed, TELLSTICK_ERROR_NOT_FOUND if the controller was * not found, and TELLSTICK_ERROR_PERMISSION_DENIED if the * controller is still connected. + * + * @since Version 2.1.2 **/ int WINAPI tdRemoveController(int controllerId) { Message msg(L"tdRemoveController"); From 7434351cf595afb6e1458258e8a116f3b900f23c Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 13 Mar 2012 20:37:32 +0100 Subject: [PATCH 1950/2215] Group defines in documentation --- telldus-core/client/telldus-core.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 59462d18..315e1b7b 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -15,6 +15,9 @@ using namespace TelldusCore; /** + * @name Device method flags + * @{ + * * @def TELLSTICK_TURNON * Device-flag for devices supporting the tdTurnOn() call. * @@ -44,6 +47,12 @@ using namespace TelldusCore; * * @def TELLSTICK_LEARN * Device-flag for devices supporting the tdLearn() call. + */ +/** @} */ + +/** + * @name Device types + * @{ * * @def TELLSTICK_TYPE_DEVICE * Device type of a single device. @@ -52,14 +61,18 @@ using namespace TelldusCore; * Device type of a device which contains other devices. * * @def TELLSTICK_TYPE_SCENE - * Device type of a device which contains other devices that are sent different commands when executed (i.e. one device turns on, another turns off). + * Device type of a device which contains other devices that are sent different + * commands when executed (i.e. one device turns on, another turns off). + */ +/** @} */ + +/** + * @name Error codes + * @{ * * @def TELLSTICK_SUCCESS * Error code. Returned when the command succeeded. * - * @def TELLSTICK_ERROR_BROKEN_PIPE - * Error code. Pipe broken during communication. - * * @def TELLSTICK_ERROR_NOT_FOUND * Error code. Returned if a TellStick was not found on the system. * @@ -89,12 +102,16 @@ using namespace TelldusCore; * Error code. Input/command could not be parsed or didn't follow * input rules. * + * @def TELLSTICK_ERROR_BROKEN_PIPE + * Error code. Pipe broken during communication. + * * @def TELLSTICK_ERROR_COMMUNICATING_SERVICE * Error code. Timeout waiting for response from the Telldus Service. * * @def TELLSTICK_ERROR_UNKNOWN * Error code. An unkown error has occurred. */ +/** @} */ /** * This function initiates the library. Call this function before any other From 75000993dcdf314021848c3e019c02c8458846d7 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 13 Mar 2012 21:01:15 +0100 Subject: [PATCH 1951/2215] Add documentation for missing defines --- telldus-core/client/telldus-core.cpp | 87 +++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 7 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 315e1b7b..246b4ec6 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -15,7 +15,8 @@ using namespace TelldusCore; /** - * @name Device method flags + * @name Device flags + * Flags returned from tdMethods() indicating which methods a device supports. * @{ * * @def TELLSTICK_TURNON @@ -47,11 +48,12 @@ using namespace TelldusCore; * * @def TELLSTICK_LEARN * Device-flag for devices supporting the tdLearn() call. - */ -/** @} */ + * + **//** @} */ /** * @name Device types + * The device type as returned from tdGetDeviceType(). * @{ * * @def TELLSTICK_TYPE_DEVICE @@ -63,8 +65,80 @@ using namespace TelldusCore; * @def TELLSTICK_TYPE_SCENE * Device type of a device which contains other devices that are sent different * commands when executed (i.e. one device turns on, another turns off). - */ -/** @} */ + * + **//** @} */ + +/** + * @name Sensor value types + * The supported sensor value types are returned from tdSensor() and used when + * querying a sensor for a specific value in tdSensorValue(). + * @{ + * + * @def TELLSTICK_TEMPERATURE + * The sensor can report the temperature. + * + * @def TELLSTICK_HUMIDITY + * The sensor can report the humidity. + * + **//** @} */ + +/** + * @name Controller type + * The controller type as returned from tdController(). + * @{ + * + * @def TELLSTICK_CONTROLLER_TELLSTICK + * The controller is a TellStick. + * + * @def TELLSTICK_CONTROLLER_TELLSTICK_DUO + * The controller is a TellStick Duo. + * + * @def TELLSTICK_CONTROLLER_TELLSTICK_NET + * The controller is a TellStick Net. + * + **//** @} */ + +/** + * @name Device changes + * @{ + * + * @def TELLSTICK_DEVICE_ADDED + * A new device was added. + * + * @def TELLSTICK_DEVICE_CHANGED + * A device was changed. + * + * @def TELLSTICK_DEVICE_REMOVED + * A device was removed. + * + * @def TELLSTICK_DEVICE_STATE_CHANGED + * The state changed for a device. + * + **//** @} */ + +/** + * @name Change types + * @{ + * + * @def TELLSTICK_CHANGE_NAME + * The name has changed. + * + * @def TELLSTICK_CHANGE_PROTOCOL + * The protocol has changed. + * + * @def TELLSTICK_CHANGE_MODEL + * The model has changed. + * + * @def TELLSTICK_CHANGE_METHOD + * The method has changed. + * + * @def TELLSTICK_CHANGE_AVAILABLE + * The controller is now available or unavailable. + * + * @def TELLSTICK_CHANGE_FIRMWARE + * The firmware has changed. + * + **//** @} */ /** * @name Error codes @@ -110,8 +184,7 @@ using namespace TelldusCore; * * @def TELLSTICK_ERROR_UNKNOWN * Error code. An unkown error has occurred. - */ -/** @} */ + **//** @} */ /** * This function initiates the library. Call this function before any other From e6f777b5fa299ad1f45a3b83711c36d46956f7b7 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 13 Mar 2012 21:06:30 +0100 Subject: [PATCH 1952/2215] Add callback typedefs to documentation --- telldus-core/client/telldus-core.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 246b4ec6..c68b5683 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -186,6 +186,21 @@ using namespace TelldusCore; * Error code. An unkown error has occurred. **//** @} */ +/** + * @name Callback typedefs + * + * @typedef TDDeviceEvent + * + * @typedef TDDeviceChangeEvent + * + * @typedef TDRawDeviceEvent + * + * @typedef TDSensorEvent + * + * @typedef TDControllerEvent + * + **//** @} */ + /** * This function initiates the library. Call this function before any other * call to a function in telldus-core. From 7b65980b565eadc2208601fbf6da60b182a9d244 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Wed, 14 Mar 2012 07:24:44 +0100 Subject: [PATCH 1953/2215] Document final parameter to tdControllerValue --- telldus-core/client/telldus-core.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index c68b5683..13551672 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -840,6 +840,7 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int * @param controllerId The controller to change * @param name The parameter to get. * @param value A byref string where the value of the parameter will be placed + * @param valueLen The length of the \c value parameter * * @since Version 2.1.2 **/ From 8dc64032a8d651ab30dbcc20950dfb8d5c674bd1 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Wed, 14 Mar 2012 08:34:12 +0100 Subject: [PATCH 1954/2215] Add Doxygen config file and docs target to build documentation --- telldus-core/CMakeLists.txt | 16 + telldus-core/Doxyfile.in | 1712 +++++++++++++++++++++++++++++++++++ 2 files changed, 1728 insertions(+) create mode 100644 telldus-core/Doxyfile.in diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 47ca4881..9aa1cbd8 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -60,3 +60,19 @@ ENDIF(BUILD_TDADMIN) ENABLE_TESTING() ADD_SUBDIRECTORY(tests) + +FIND_PACKAGE(Doxygen) + +IF (DOXYGEN_FOUND) + SET(DOXY_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + + MESSAGE(STATUS "Generating ${DOXY_CONFIG}") + CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in" + ${DOXY_CONFIG} @ONLY) + + ADD_CUSTOM_TARGET(docs + ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} + DEPENDS ${DOXY_CONFIG} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating doxygen documentation" VERBATIM) +ENDIF (DOXYGEN_FOUND) diff --git a/telldus-core/Doxyfile.in b/telldus-core/Doxyfile.in new file mode 100644 index 00000000..9351c31e --- /dev/null +++ b/telldus-core/Doxyfile.in @@ -0,0 +1,1712 @@ +# Doxyfile 1.7.4 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "Telldus Core API" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @DISPLAYED_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = @PROJECT_BINARY_DIR@/docs + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = client/telldus-core.h \ + client/telldus-core.cpp \ + ../docs/01-telldus-core.dox \ + ../docs/02-tellstick-protocol.dox \ + ../docs/03-tellstick-net-protocol.dox + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is adviced to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the +# mathjax.org site, so you can quickly see the result without installing +# MathJax, but it is strongly recommended to install a local copy of MathJax +# before deployment. + +MATHJAX_RELPATH = http://www.mathjax.org/mathjax + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = YES + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = "WINAPI=\"\"" + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called Helvetica to the output +# directory and reference it in all dot files that doxygen generates. +# When you want a differently looking font you can specify the font name +# using DOT_FONTNAME. You need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES From 435778d2bab8240ff58cddabe25337924bd44ad7 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Wed, 14 Mar 2012 11:00:08 +0100 Subject: [PATCH 1955/2215] Document the callback functions --- telldus-core/client/telldus-core.cpp | 77 +++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 8 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 13551672..41e8beb1 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -49,7 +49,7 @@ using namespace TelldusCore; * @def TELLSTICK_LEARN * Device-flag for devices supporting the tdLearn() call. * - **//** @} */ + **//* @} */ /** * @name Device types @@ -66,7 +66,7 @@ using namespace TelldusCore; * Device type of a device which contains other devices that are sent different * commands when executed (i.e. one device turns on, another turns off). * - **//** @} */ + **//* @} */ /** * @name Sensor value types @@ -80,7 +80,7 @@ using namespace TelldusCore; * @def TELLSTICK_HUMIDITY * The sensor can report the humidity. * - **//** @} */ + **//* @} */ /** * @name Controller type @@ -96,7 +96,7 @@ using namespace TelldusCore; * @def TELLSTICK_CONTROLLER_TELLSTICK_NET * The controller is a TellStick Net. * - **//** @} */ + **//* @} */ /** * @name Device changes @@ -114,7 +114,7 @@ using namespace TelldusCore; * @def TELLSTICK_DEVICE_STATE_CHANGED * The state changed for a device. * - **//** @} */ + **//* @} */ /** * @name Change types @@ -138,7 +138,7 @@ using namespace TelldusCore; * @def TELLSTICK_CHANGE_FIRMWARE * The firmware has changed. * - **//** @} */ + **//* @} */ /** * @name Error codes @@ -184,22 +184,33 @@ using namespace TelldusCore; * * @def TELLSTICK_ERROR_UNKNOWN * Error code. An unkown error has occurred. - **//** @} */ + **//* @} */ /** * @name Callback typedefs + * @{ * * @typedef TDDeviceEvent + * The callback type for device events. + * @sa tdRegisterDeviceEvent * * @typedef TDDeviceChangeEvent + * The callback type for device change events. + * @sa tdRegisterDeviceChangeEvent * * @typedef TDRawDeviceEvent + * The callback type for raw events. + * @sa tdRegisterRawDeviceEvent * * @typedef TDSensorEvent + * The callback type for sensor events. + * @sa tdRegisterSensorEvent * * @typedef TDControllerEvent + * The callback type for controller events. + * @sa tdRegisterControllerEvent * - **//** @} */ + **//* @} */ /** * This function initiates the library. Call this function before any other @@ -212,6 +223,15 @@ void WINAPI tdInit(void) { } /** + * Register a callback that will receive device events. + * + * @param eventFunction Callback function + * @param context Pointer that will be passed back in the callback. + * + * @returns An id identifying the callback. Pass this id to + * tdUnregisterCallback() to stop receiving callbacks. + * + * @sa @ref sec_events_registering * @since Version 2.0.0 **/ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { @@ -220,6 +240,15 @@ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { } /** + * Register a callback that will receive raw (i.e. all) events. + * + * @param eventFunction Callback function + * @param context Pointer that will be passed back in the callback. + * + * @returns An id identifying the callback. Pass this id to + * tdUnregisterCallback() to stop receiving callbacks. + * + * @sa @ref sec_events_registering * @since Version 2.0.0 **/ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { @@ -228,6 +257,15 @@ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *conte } /** + * Register a callback that will receive device change events. + * + * @param eventFunction Callback function + * @param context Pointer that will be passed back in the callback. + * + * @returns An id identifying the callback. Pass this id to + * tdUnregisterCallback() to stop receiving callbacks. + * + * @sa @ref sec_events_registering * @since Version 2.1.0 **/ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { @@ -236,6 +274,15 @@ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void } /** + * Register a callback that will receive sensor events. + * + * @param eventFunction Callback function + * @param context Pointer that will be passed back in the callback. + * + * @returns An id identifying the callback. Pass this id to + * tdUnregisterCallback() to stop receiving callbacks. + * + * @sa @ref sec_events_registering * @since Version 2.1.0 **/ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { @@ -244,6 +291,15 @@ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { } /** + * Register a callback that will receive controller events. + * + * @param eventFunction Callback function + * @param context Pointer that will be passed back in the callback. + * + * @returns An id identifying the callback. Pass this id to + * tdUnregisterCallback() to stop receiving callbacks. + * + * @sa @ref sec_events_registering * @since Version 2.1.2 **/ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context) { @@ -252,6 +308,11 @@ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *con } /** + * Unregister a callback. + * + * @param callbackId The returned id from one of the tdRegister* functions. + * + * @sa @ref sec_events_registering * @since Version 2.1.0 **/ int WINAPI tdUnregisterCallback( int callbackId ) { From 2ce2984d672f4fac90c7e7e65c49ab6b8eca7044 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Wed, 14 Mar 2012 11:00:28 +0100 Subject: [PATCH 1956/2215] More doxygen warnings and fix WINAPI define --- telldus-core/Doxyfile.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/Doxyfile.in b/telldus-core/Doxyfile.in index 9351c31e..199a4cbc 100644 --- a/telldus-core/Doxyfile.in +++ b/telldus-core/Doxyfile.in @@ -583,7 +583,7 @@ WARN_IF_DOC_ERROR = YES # wrong or incomplete parameter documentation, but not about the absence of # documentation. -WARN_NO_PARAMDOC = NO +WARN_NO_PARAMDOC = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text @@ -1445,7 +1445,7 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = "WINAPI=\"\"" +PREDEFINED = WINAPI= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. From 690b730607111456b5eaf8f1a86bc2a0f47de551 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Wed, 14 Mar 2012 11:25:37 +0100 Subject: [PATCH 1957/2215] Add missing documentation for parameters and return value --- telldus-core/client/telldus-core.cpp | 212 +++++++++++++++++++++------ 1 file changed, 164 insertions(+), 48 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 41e8beb1..e4c1aea3 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -312,6 +312,8 @@ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *con * * @param callbackId The returned id from one of the tdRegister* functions. * + * @returns 1 on success, or 0 on failure. + * * @sa @ref sec_events_registering * @since Version 2.1.0 **/ @@ -332,7 +334,10 @@ void WINAPI tdClose(void) { /** * This method releases resources allocated by telldus-core. - * It should be called on the returned value from all functions return char * + * It should be called on the returned value from all functions returning + * char *. + * + * @param string A string returned from a td* function. * * @since Version 2.0.1 **/ @@ -348,8 +353,12 @@ void WINAPI tdReleaseString(char *string) { * Turns a device on. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to turn on. * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.0.0 **/ int WINAPI tdTurnOn(int intDeviceId){ @@ -362,8 +371,12 @@ int WINAPI tdTurnOn(int intDeviceId){ * Turns a device off. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to turn off. * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.0.0 **/ int WINAPI tdTurnOff(int intDeviceId){ @@ -376,8 +389,12 @@ int WINAPI tdTurnOff(int intDeviceId){ * Sends bell command to devices supporting this. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to send bell to * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.0.0 **/ int WINAPI tdBell(int intDeviceId){ @@ -390,9 +407,13 @@ int WINAPI tdBell(int intDeviceId){ * Dims a device. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to dim * @param level The level the device should dim to. This value should be 0-255 * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.0.0 **/ int WINAPI tdDim(int intDeviceId, unsigned char level){ @@ -406,8 +427,12 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ * Execute a scene action. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The id to execute * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.1.0 **/ int WINAPI tdExecute(int intDeviceId){ @@ -420,8 +445,12 @@ int WINAPI tdExecute(int intDeviceId){ * Send "up" command to device. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to send the command to * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.1.0 **/ int WINAPI tdUp(int intDeviceId){ @@ -434,8 +463,12 @@ int WINAPI tdUp(int intDeviceId){ * Send "down" command to device. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to send the command to * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.1.0 **/ int WINAPI tdDown(int intDeviceId){ @@ -448,8 +481,12 @@ int WINAPI tdDown(int intDeviceId){ * Send "stop" command to device. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to stop * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.1.0 */ int WINAPI tdStop(int intDeviceId){ @@ -459,12 +496,16 @@ int WINAPI tdStop(int intDeviceId){ } /** - * Sends a special learn command to some devices that need a special learn-command - * to be used from TellStick + * Sends a special learn command to some devices that need a special + * learn-command to be used from TellStick. * Make sure the device supports this by calling tdMethods() before any * call to this function. + * * @param intDeviceId The device id to learn. * + * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on + * failure. + * * @since Version 2.0.0 **/ int WINAPI tdLearn(int intDeviceId) { @@ -475,9 +516,13 @@ int WINAPI tdLearn(int intDeviceId) { /** * Returns the last sent command to a specific device + * * @param intDeviceId The device id to query - * @param methodsSupported The methods supported by the client. See tdMethods() for more information. - * @returns the last sent command as integer, example TELLSTICK_TURNON or TELLSTICK_TURNOFF + * @param methodsSupported The methods supported by the client. See tdMethods() + * for more information. + * + * @returns The last sent command as integer, example @ref TELLSTICK_TURNON or + * @ref TELLSTICK_TURNOFF * * @since Version 2.0.0 **/ @@ -489,9 +534,13 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { } /** - * If the last sent command it TELLSTICK_DIM this returns the dimmed value. + * If the last sent command it @ref TELLSTICK_DIM this returns the dimmed + * value. + * * @param intDeviceId The device id to query - * @returns the the value as a human readable string, example "128" for 50% + * + * @returns The the value as a human readable string, example "128" for + * 50%. The returned string must be freed by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -503,8 +552,9 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { } /** - * This function returns the number of devices configured - * @returns an integer of the total number of devices configured + * This function returns the number of devices configured. + * + * @returns An integer of the total number of devices configured * * @since Version 2.0.0 **/ @@ -522,8 +572,10 @@ int WINAPI tdGetNumberOfDevices(void){ * // id now contains the id number of the device with index of i * } * \endcode + * * @param intDeviceIndex The device index to query. The index starts from 0. - * @returns the unique id for the device or -1 if the device is not found. + * + * @returns The unique id for the device or -1 if the device is not found. * * @since Version 2.0.0 **/ @@ -534,8 +586,13 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ } /** - * Returns which type the device is. The device could be either - * TELLSTICK_TYPE_DEVICE, TELLSTICK_TYPE_GROUP or TELLSTICK_TYPE_SCENE + * Get the device type. + * + * @param intDeviceId The unique id of the device to query + * + * @returns Which type the device is. The device could be either @ref + * TELLSTICK_TYPE_DEVICE, @ref TELLSTICK_TYPE_GROUP or @ref + * TELLSTICK_TYPE_SCENE * * @since Version 2.0.0 **/ @@ -547,8 +604,11 @@ int WINAPI tdGetDeviceType(int intDeviceId) { /** * Query a device for it's name. + * * @param intDeviceId The unique id of the device to query - * @returns The name of the device or an empty string if the device is not found. + * + * @returns The name of the device or an empty string if the device is not + * found. The returned string must be freed by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -560,10 +620,12 @@ char * WINAPI tdGetName(int intDeviceId){ } /** - * Sets a new name for a device. The devices are global for all application, changing - * this will change the name for other applications aswell. + * Sets a new name for a device. The devices are global for all application, + * changing this will change the name for other applications aswell. + * * @param intDeviceId The device id to change the name for * @param strNewName The new name for the devices + * * @returns \c true on success, \c false otherwise. * * @since Version 2.0.0 @@ -576,9 +638,12 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ } /** - * @returns the protocol used by a specific device. + * Get the device protocol. * @param intDeviceId The device id to query. * + * @returns The protocol used by a specific device. The returned string must be + * freed by calling tdReleaseString(). + * * @since Version 2.0.0 **/ char* WINAPI tdGetProtocol(int intDeviceId){ @@ -589,11 +654,14 @@ char* WINAPI tdGetProtocol(int intDeviceId){ } /** - * This changes the current protocol used by a device. After changing the protocol, - * setting new parameters is required. + * This changes the current protocol used by a device. After changing the + * protocol, setting new parameters is required. + * * @param intDeviceId The device to change. * @param strProtocol The new protocol to use. + * * @returns \c true on success, \c false otherwise. + * * @sa tdSetModel() * @sa tdSetDeviceParameter() * @@ -607,9 +675,13 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ } /** - * @returns the model for a device. Not all protocols uses this. + * Get the device model. + * * @param intDeviceId The device to query. * + * @returns The model for a device. Not all protocols uses this. The returned + * string must be freed by calling tdReleaseString(). + * * @since Version 2.0.0 **/ char* WINAPI tdGetModel(int intDeviceId){ @@ -622,8 +694,10 @@ char* WINAPI tdGetModel(int intDeviceId){ /** * Sets a new model for a device. Which model to set depends on the * current protocol. + * * @param intDeviceId The device to change * @param strModel The new model + * * @returns \c true on success, \c false otherwise. * * @since Version 2.0.0 @@ -636,11 +710,13 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ } /** - * Sets a new protocol specific parameter. Please see the documentation of the protocols - * before setting any parameter. + * Sets a new protocol specific parameter. Please see the documentation of the + * protocols before setting any parameter. + * * @param intDeviceId The device to change. * @param strName The parameter to change. * @param strValue The new value for the parameter. + * * @returns \c true on success, \c false otherwise. * * @since Version 2.0.0 @@ -654,10 +730,15 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha } /** - * @returns any protocol specific parameter specified by \c strName + * Get a protocol specific parameter for a device. + * * @param intDeviceId The device to query. * @param strName The name of the parameter to query. - * @param defaultValue A defaultValue to return if the current parameter hasn't previously been set. + * @param defaultValue A default value to return if the current parameter + * hasn't previously been set. + * + * @returns The protocol specific parameter specified by \c strName. The + * returned string must be freed by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -671,10 +752,12 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c } /** - * Add a new device to the global database of devices. This function must be called first before - * any call to tdSetName(), tdSetProtocol() and similar functions. - * @returns the new device id for the newly created device. If the creation fails it returnes a - * negative value. + * Add a new device to the global database of devices. This function must be + * called first before any call to tdSetName(), tdSetProtocol() and similar + * functions. + * + * @returns The new device id for the newly created device. If the creation + * fails it returnes an error (i.e. negative) value. * * @since Version 2.0.0 **/ @@ -685,6 +768,9 @@ int WINAPI tdAddDevice(){ /** * Removes a device. + * + * @param intDeviceId The device to query. + * * @returns \c true on success, \c false otherwise. * * @since Version 2.0.0 @@ -696,8 +782,10 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ } /** - * Query a device for which methods it supports. By supplying the methods you support - * the library could remap the methods a device support for better fit the application. + * Query a device for which methods it supports. By supplying the methods you + * support the library could remap the methods a device support for better fit + * the application. + * * Example of querying a device supporting TELLSTICK_BELL: * \code * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); @@ -705,9 +793,12 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); * //methods is now TELLSTICK_TURNON because the client application doesn't support TELLSTICK_BELL * \endcode + * * @param id The device id to query * @param methodsSupported The methods the client application supports + * * @returns The method-flags OR'ed into an integer. + * * @sa TELLSTICK_TURNON * @sa TELLSTICK_TURNOFF * @sa TELLSTICK_BELL @@ -728,10 +819,14 @@ int WINAPI tdMethods(int id, int methodsSupported){ } /** - * Get a human readable string from an error code returned - * from a function in telldus-core. + * Get a human readable string from an error code returned from a function in + * telldus-core. + * * @param intErrorNo The error code to translate. - * @returns a string ready to show to the user. + * + * @returns A string ready to show to the user. The returned string must be + * freed by calling tdReleaseString(). + * * @sa TELLSTICK_SUCCESS * @sa TELLSTICK_ERROR_NOT_FOUND * @sa TELLSTICK_ERROR_PERMISSION_DENIED @@ -776,9 +871,12 @@ char * WINAPI tdGetErrorString(int intErrorNo) { /** * Send a raw command to TellStick. Please read the TellStick protocol * definition on how the command should be constructed. + * * @param command The command for TellStick in its native format * @param reserved Reserved for future use - * @returns TELLSTICK_SUCCESS on success or one of the errorcodes on failure + * + * @returns @ref TELLSTICK_SUCCESS on success or one of the errorc odes on + * failure * * @since Version 2.0.0 **/ @@ -794,6 +892,12 @@ int WINAPI tdSendRawCommand(const char *command, int reserved) { } /** + * Connect a TellStick controller. + * + * @param vid The vendor id + * @param pid The product id + * @param serial The serial + * * @since Version 2.1.0 **/ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { @@ -805,6 +909,12 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { } /** + * Disconnect a TellStick controller. + * + * @param vid The vendor id + * @param pid The product id + * @param serial The serial + * * @since Version 2.1.0 **/ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { @@ -816,16 +926,18 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial } /** - * Use this function to iterate over all sensors. Iterate until + * Use this function to iterate over all sensors. Iterate until @ref * TELLSTICK_SUCCESS is not returned * - * @param protocol A byref string where the protocol of the sensor will be placed + * @param protocol A byref string where the protocol of the sensor will be + * placed * @param protocolLen The length of the \c protocol parameter * @param model A byref string where the model of the sensor will be placed * @param modelLen The length of the \c model parameter * @param id A byref int where the id of the sensor will be placed * @param dataTypes A byref int with flags for the supported sensor values - * @returns TELLSTICK_SUCCESS if there is more sensors to be fetched + * + * @returns @ref TELLSTICK_SUCCESS if there is more sensors to be fetched * * @since Version 2.1.0 */ @@ -837,7 +949,7 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, /** * Get one of the supported sensor values from a sensor. Make sure it support * the value type first by calling tdSensor(). The triplet \c protocol, - * \c model, and \c id together identifies a sensor. + * \c model and \c id together identifies a sensor. * * @param protocol The protocol for the sensor * @param model The model for the sensor @@ -846,8 +958,9 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, * @param value A byref string where the value will be places * @param len The length of the \c value parameter * @param timestamp A byref int where the timestamp of the value will be placed - * @returns TELLSTICK_SUCCESS if the value could be fetched or one of the - * errorcodes on failure + * + * @returns @ref TELLSTICK_SUCCESS if the value could be fetched or one of the + * error codes on failure * * @since Version 2.1.0 */ @@ -875,7 +988,7 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da /** * Use this function to iterate over all controllers. Iterate until - * TELLSTICK_SUCCESS is not returned + * @ref TELLSTICK_SUCCESS is not returned * * @param controllerId A byref int where the id of the controller will be placed * @param controllerType A byref int where the type of the controller will be placed @@ -896,13 +1009,15 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int /** * This function gets a parameter on a controller. - * Valid parameters are: \c serial \c and firmware + * Valid parameters are: \c serial and \c firmware * * @param controllerId The controller to change * @param name The parameter to get. * @param value A byref string where the value of the parameter will be placed * @param valueLen The length of the \c value parameter * + * @returns @ref TELLSTICK_SUCCESS on success, or an error code on failure. + * * @since Version 2.1.2 **/ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen) { @@ -928,6 +1043,8 @@ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, in * @param name The parameter to change. * @param value The new value for the parameter. * + * @returns @ref TELLSTICK_SUCCESS on success, or an error code on failure. + * * @since Version 2.1.2 **/ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value) { @@ -939,15 +1056,14 @@ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char * } /** - * This function removes a controller from the list - * of controllers. The controller must not be - * available (disconnected) for this to work. + * This function removes a controller from the list of controllers. The + * controller must not be available (disconnected) for this to work. * * @param controllerId The controller to remove - * @returns TELLSTICK_SUCCESS if the controller was - * removed, TELLSTICK_ERROR_NOT_FOUND if the controller was - * not found, and TELLSTICK_ERROR_PERMISSION_DENIED if the - * controller is still connected. + * + * @returns @ref TELLSTICK_SUCCESS if the controller was removed, @ref + * TELLSTICK_ERROR_NOT_FOUND if the controller was not found, and @ref + * TELLSTICK_ERROR_PERMISSION_DENIED if the controller is still connected. * * @since Version 2.1.2 **/ From 5e49cfffe460075782d20d682fa93a76a8eb0538 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 13 Mar 2012 15:24:30 +0100 Subject: [PATCH 1958/2215] Make it possible to get controller name with tdControllerValue The name can be changed with tdSetControllerValue but unless you listen to the change event you had to fetch all controllers again to get the new name. --- telldus-core/client/telldus-core.cpp | 2 +- telldus-core/service/ControllerManager.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 8108f761..756d1976 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -727,7 +727,7 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int /** * This function gets a parameter on a controller. - * Valid parameters are: \c serial \c and firmware + * Valid parameters are: \c serial, \c name and \c firmware * * Added in version 2.1.2. * @param controllerId The controller to change diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 2ccfa9a6..4d832faf 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -277,6 +277,8 @@ std::wstring ControllerManager::getControllerValue(int id, const std::wstring &n } if (name == L"serial") { return it->second.serial; + } else if (name == L"name") { + return it->second.name; } else if (name == L"firmware") { if (!it->second.controller) { return L"-1"; From 8170629f482e638b96970c21755c65541dd6ca13 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Fri, 16 Mar 2012 14:36:24 +0100 Subject: [PATCH 1959/2215] Make "available" a valid parameter to query with tdControllerValue --- telldus-core/client/telldus-core.cpp | 2 +- telldus-core/service/ControllerManager.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 756d1976..95ec3e3e 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -727,7 +727,7 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int /** * This function gets a parameter on a controller. - * Valid parameters are: \c serial, \c name and \c firmware + * Valid parameters are: \c serial, \c name, \c available and \c firmware * * Added in version 2.1.2. * @param controllerId The controller to change diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 4d832faf..2c1e6146 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -279,6 +279,8 @@ std::wstring ControllerManager::getControllerValue(int id, const std::wstring &n return it->second.serial; } else if (name == L"name") { return it->second.name; + } else if (name == L"available") { + return it->second.controller ? L"1" : L"0"; } else if (name == L"firmware") { if (!it->second.controller) { return L"-1"; From d715e4ad411a863b81b7857dd3dfceebcdd22e1d Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Sat, 17 Mar 2012 08:51:19 +0100 Subject: [PATCH 1960/2215] Extend the documentation for device change events --- telldus-core/client/telldus-core.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index e4c1aea3..42adbc97 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -196,8 +196,24 @@ using namespace TelldusCore; * * @typedef TDDeviceChangeEvent * The callback type for device change events. + * + * @attention The callback will be called by another thread than the thread + * used by the application and some measures must be taken to synchronize it + * with the main thread. + * + * @param deviceId The id for the device that was added, changed or removed. + * @param changeEvent One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref + * TELLSTICK_DEVICE_CHANGED or @ref TELLSTICK_DEVICE_REMOVED. + * @param changeType If @a changeEvent was @ref TELLSTICK_DEVICE_CHANGED, this + * parameter indicates what has changed. It is one of the constants @ref + * TELLSTICK_CHANGE_NAME, @ref TELLSTICK_CHANGE_PROTOCOL, @ref + * TELLSTICK_CHANGE_MODEL or @ref TELLSTICK_CHANGE_METHOD. + * @param callbackId The id of the callback. + * @param context The pointer passed when registering for the event. + * * @sa tdRegisterDeviceChangeEvent * + * * @typedef TDRawDeviceEvent * The callback type for raw events. * @sa tdRegisterRawDeviceEvent @@ -257,7 +273,9 @@ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *conte } /** - * Register a callback that will receive device change events. + * Register a callback that will receive device change events. This includes + * addition of new devices, changes of device properties (e.g. name) and + * removal of existing devices. * * @param eventFunction Callback function * @param context Pointer that will be passed back in the callback. From 296be6a0680f95b24ed66ae250d30be3b41b5a47 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Sat, 17 Mar 2012 18:46:25 +0100 Subject: [PATCH 1961/2215] Document TDDeviceEvent --- telldus-core/client/telldus-core.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 42adbc97..f665d618 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -192,8 +192,22 @@ using namespace TelldusCore; * * @typedef TDDeviceEvent * The callback type for device events. + * + * @attention The callback will be called by another thread than the thread + * used by the application and some measures must be taken to synchronize it + * with the main thread. + * + * @param deviceId The id of the device that changed. + * @param method The new device state. Can be @ref TELLSTICK_TURNON, @ref + * TELLSTICK_TURNOFF, etc. + * @param data If @a method is @ref TELLSTICK_DIM this holds the current value + * as a human readable string, example "128" for 50%. + * @param callbackId The id of the callback. + * @param context The pointer passed when registering for the event. + * * @sa tdRegisterDeviceEvent * + * * @typedef TDDeviceChangeEvent * The callback type for device change events. * @@ -201,7 +215,7 @@ using namespace TelldusCore; * used by the application and some measures must be taken to synchronize it * with the main thread. * - * @param deviceId The id for the device that was added, changed or removed. + * @param deviceId The id of the device that was added, changed or removed. * @param changeEvent One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref * TELLSTICK_DEVICE_CHANGED or @ref TELLSTICK_DEVICE_REMOVED. * @param changeType If @a changeEvent was @ref TELLSTICK_DEVICE_CHANGED, this From 034b5a03e6ac38d3ed8023614bd2ce2985901b27 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Sat, 17 Mar 2012 18:55:44 +0100 Subject: [PATCH 1962/2215] Document TDRawDeviceEvent --- telldus-core/client/telldus-core.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index f665d618..e4bb8e07 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -230,8 +230,19 @@ using namespace TelldusCore; * * @typedef TDRawDeviceEvent * The callback type for raw events. + * + * @attention The callback will be called by another thread than the thread + * used by the application and some measures must be taken to synchronize it + * with the main thread. + * + * @param data Raw device data. + * @param controllerId Id of receiving controller. + * @param callbackId The id of the callback. + * @param context The pointer passed when registering for the event. + * * @sa tdRegisterRawDeviceEvent * + * * @typedef TDSensorEvent * The callback type for sensor events. * @sa tdRegisterSensorEvent From ee4d821a7a727db5eda4b254618714e407afcd3d Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Sat, 17 Mar 2012 19:02:17 +0100 Subject: [PATCH 1963/2215] Document TDSensorEvent --- telldus-core/client/telldus-core.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index e4bb8e07..349fba97 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -245,8 +245,25 @@ using namespace TelldusCore; * * @typedef TDSensorEvent * The callback type for sensor events. + * + * @attention The callback will be called by another thread than the thread + * used by the application and some measures must be taken to synchronize it + * with the main thread. + * + * @param protocol The sensor's protocol. + * @param model The model of the sensor. + * @param id The unique id for the sensor. + * @param dataType The type that @a value is. Can be one of @ref + * TELLSTICK_TEMPERATURE or @ref TELLSTICK_HUMIDITY. + * @param value A human readable string of the data. + * @param timestamp The time (as returned by the time() system call) when the + * value was received. + * @param callbackId The id of the callback. + * @param context The pointer passed when registering for the event. + * * @sa tdRegisterSensorEvent * + * * @typedef TDControllerEvent * The callback type for controller events. * @sa tdRegisterControllerEvent From 902c12d88d93b6cd0438380e4cce3a7ad409bbb1 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Sat, 17 Mar 2012 19:16:27 +0100 Subject: [PATCH 1964/2215] The controller added callback should pass the controller type This unifies the behavior between loadControllers() and loadStoredControllers(). --- telldus-core/service/ControllerManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 2ccfa9a6..449bf0eb 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -199,9 +199,10 @@ void ControllerManager::loadStoredControllers() { int id = d->settings.getNodeId(Settings::Controller, i); d->controllers[id].controller = NULL; d->controllers[id].name = d->settings.getName(Settings::Controller, id); - d->controllers[id].type = d->settings.getControllerType(id); + const int type = d->settings.getControllerType(id); + d->controllers[id].type = type; d->controllers[id].serial = d->settings.getControllerSerial(id); - signalControllerEvent(id, TELLSTICK_DEVICE_ADDED, 0, L""); + signalControllerEvent(id, TELLSTICK_DEVICE_ADDED, type, L""); } } From 0d84d52ebe7fe49b0cb47ac551da842621b2f8a7 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Sat, 17 Mar 2012 19:12:30 +0100 Subject: [PATCH 1965/2215] Document TDControllerEvent --- telldus-core/client/telldus-core.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 349fba97..2b16a94e 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -266,6 +266,27 @@ using namespace TelldusCore; * * @typedef TDControllerEvent * The callback type for controller events. + * + * @attention The callback will be called by another thread than the thread + * used by the application and some measures must be taken to synchronize it + * with the main thread. + * + * @param controllerId The id of the controller that was added, changed or + * removed. + * @param changeEvent One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref + * TELLSTICK_DEVICE_STATE_CHANGED or @ref TELLSTICK_DEVICE_REMOVED. + * @param changeType If @a changeEvent is @ref TELLSTICK_DEVICE_ADDED this is + * the controller's type (e.g. @ref TELLSTICK_CONTROLLER_TELLSTICK or @ref + * TELLSTICK_CONTROLLER_TELLSTICK_DUO); if @a changeEvent is @ref + * TELLSTICK_DEVICE_CHANGED this indicates what has changed (e.g. @ref + * TELLSTICK_CHANGE_AVAILABLE, @ref TELLSTICK_CHANGE_NAME or @ref + * TELLSTICK_CHANGE_FIRMWARE). + * @param newValue If @a changeEvent is @ref TELLSTICK_DEVICE_CHANGED this is + * the property's new value. For @ref TELLSTICK_CHANGE_AVAILABLE this is either + * 0 or 1. + * @param callbackId The id of the callback. + * @param context The pointer passed when registering for the event. + * * @sa tdRegisterControllerEvent * **//* @} */ From 5061c759f3ac7966696921c86e2020a6fcb37b0d Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Mon, 19 Mar 2012 10:00:05 +0100 Subject: [PATCH 1966/2215] Minor doc cleanups --- telldus-core/client/telldus-core.cpp | 93 ++++++++++++++++------------ 1 file changed, 52 insertions(+), 41 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 2b16a94e..ec1c2467 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -15,8 +15,9 @@ using namespace TelldusCore; /** - * @name Device flags - * Flags returned from tdMethods() indicating which methods a device supports. + * @name Device method flags + * Flags for the different methods/commands a device can support. Can be used + * as bitflags in e.g. tdMethods(). * @{ * * @def TELLSTICK_TURNON @@ -34,6 +35,9 @@ using namespace TelldusCore; * @def TELLSTICK_DIM * Device-flag for devices supporting the tdDim() call. * + * @def TELLSTICK_LEARN + * Device-flag for devices supporting the tdLearn() call. + * * @def TELLSTICK_EXECUTE * Device-flag for devices (scenes) supporting the tdExecute() call. * @@ -46,9 +50,6 @@ using namespace TelldusCore; * @def TELLSTICK_STOP * Device-flag for devices supporting the tdStop() call. * - * @def TELLSTICK_LEARN - * Device-flag for devices supporting the tdLearn() call. - * **//* @} */ /** @@ -100,6 +101,7 @@ using namespace TelldusCore; /** * @name Device changes + * Flags used in event callbacks. * @{ * * @def TELLSTICK_DEVICE_ADDED @@ -118,6 +120,7 @@ using namespace TelldusCore; /** * @name Change types + * Flags used in event callbacks. * @{ * * @def TELLSTICK_CHANGE_NAME @@ -142,6 +145,7 @@ using namespace TelldusCore; /** * @name Error codes + * The error codes returned from all API functions returning int. * @{ * * @def TELLSTICK_SUCCESS @@ -218,10 +222,10 @@ using namespace TelldusCore; * @param deviceId The id of the device that was added, changed or removed. * @param changeEvent One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref * TELLSTICK_DEVICE_CHANGED or @ref TELLSTICK_DEVICE_REMOVED. - * @param changeType If @a changeEvent was @ref TELLSTICK_DEVICE_CHANGED, this - * parameter indicates what has changed. It is one of the constants @ref - * TELLSTICK_CHANGE_NAME, @ref TELLSTICK_CHANGE_PROTOCOL, @ref - * TELLSTICK_CHANGE_MODEL or @ref TELLSTICK_CHANGE_METHOD. + * @param changeType If @a changeEvent is @ref TELLSTICK_DEVICE_CHANGED, this + * parameter indicates what has changed (e.g @ref TELLSTICK_CHANGE_NAME, @ref + * TELLSTICK_CHANGE_PROTOCOL, @ref TELLSTICK_CHANGE_MODEL or @ref + * TELLSTICK_CHANGE_METHOD). * @param callbackId The id of the callback. * @param context The pointer passed when registering for the event. * @@ -274,16 +278,21 @@ using namespace TelldusCore; * @param controllerId The id of the controller that was added, changed or * removed. * @param changeEvent One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref - * TELLSTICK_DEVICE_STATE_CHANGED or @ref TELLSTICK_DEVICE_REMOVED. - * @param changeType If @a changeEvent is @ref TELLSTICK_DEVICE_ADDED this is - * the controller's type (e.g. @ref TELLSTICK_CONTROLLER_TELLSTICK or @ref - * TELLSTICK_CONTROLLER_TELLSTICK_DUO); if @a changeEvent is @ref - * TELLSTICK_DEVICE_CHANGED this indicates what has changed (e.g. @ref - * TELLSTICK_CHANGE_AVAILABLE, @ref TELLSTICK_CHANGE_NAME or @ref - * TELLSTICK_CHANGE_FIRMWARE). - * @param newValue If @a changeEvent is @ref TELLSTICK_DEVICE_CHANGED this is - * the property's new value. For @ref TELLSTICK_CHANGE_AVAILABLE this is either - * 0 or 1. + * TELLSTICK_DEVICE_CHANGED, @ref TELLSTICK_DEVICE_STATE_CHANGED or @ref + * TELLSTICK_DEVICE_REMOVED. + + * @param changeType If @a changeEvent is: + * @arg @ref TELLSTICK_DEVICE_ADDED this is the controller's type (e.g. @ref + * TELLSTICK_CONTROLLER_TELLSTICK or @ref TELLSTICK_CONTROLLER_TELLSTICK_DUO), + * @arg @ref TELLSTICK_DEVICE_CHANGED this indicates what has changed + * (e.g. @ref TELLSTICK_CHANGE_NAME or @ref TELLSTICK_CHANGE_FIRMWARE), + * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this indicates which state that + * has changed (e.g. @ref TELLSTICK_CHANGE_AVAILABLE), + * @arg @ref TELLSTICK_DEVICE_REMOVED this is unused. + * @param newValue If @a changeEvent is: + * @arg @ref TELLSTICK_DEVICE_CHANGED this is the property's new value. + * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this is the new state. For @ref + * TELLSTICK_CHANGE_AVAILABLE this is either 0 or 1. * @param callbackId The id of the callback. * @param context The pointer passed when registering for the event. * @@ -646,13 +655,13 @@ int WINAPI tdGetNumberOfDevices(void){ /** * This function returns the unique id of a device with a specific index. * To get all the id numbers you should loop over all the devices: - * \code + * @code * int intNumberOfDevices = tdGetNumberOfDevices(); * for (int i = 0; i < intNumberOfDevices; i++) { * int id = tdGetDeviceId( i ); * // id now contains the id number of the device with index of i * } - * \endcode + * @endcode * * @param intDeviceIndex The device index to query. The index starts from 0. * @@ -707,7 +716,7 @@ char * WINAPI tdGetName(int intDeviceId){ * @param intDeviceId The device id to change the name for * @param strNewName The new name for the devices * - * @returns \c true on success, \c false otherwise. + * @returns @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -741,7 +750,7 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * @param intDeviceId The device to change. * @param strProtocol The new protocol to use. * - * @returns \c true on success, \c false otherwise. + * @returns @c true on success, @c false otherwise. * * @sa tdSetModel() * @sa tdSetDeviceParameter() @@ -779,7 +788,7 @@ char* WINAPI tdGetModel(int intDeviceId){ * @param intDeviceId The device to change * @param strModel The new model * - * @returns \c true on success, \c false otherwise. + * @returns @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -798,7 +807,7 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * @param strName The parameter to change. * @param strValue The new value for the parameter. * - * @returns \c true on success, \c false otherwise. + * @returns @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -818,7 +827,7 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * @param defaultValue A default value to return if the current parameter * hasn't previously been set. * - * @returns The protocol specific parameter specified by \c strName. The + * @returns The protocol specific parameter specified by @a strName. The * returned string must be freed by calling tdReleaseString(). * * @since Version 2.0.0 @@ -852,7 +861,7 @@ int WINAPI tdAddDevice(){ * * @param intDeviceId The device to query. * - * @returns \c true on success, \c false otherwise. + * @returns @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -868,12 +877,14 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * the application. * * Example of querying a device supporting TELLSTICK_BELL: - * \code - * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); - * //methods is now TELLSTICK_BELL + * @code + * int methods = tdMethods( + * id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); + * // methods is now TELLSTICK_BELL * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); - * //methods is now TELLSTICK_TURNON because the client application doesn't support TELLSTICK_BELL - * \endcode + * // methods is now TELLSTICK_TURNON because the client application doesn't + * // support TELLSTICK_BELL + * @endcode * * @param id The device id to query * @param methodsSupported The methods the client application supports @@ -1012,9 +1023,9 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial * * @param protocol A byref string where the protocol of the sensor will be * placed - * @param protocolLen The length of the \c protocol parameter + * @param protocolLen The length of the @a protocol parameter * @param model A byref string where the model of the sensor will be placed - * @param modelLen The length of the \c model parameter + * @param modelLen The length of the @a model parameter * @param id A byref int where the id of the sensor will be placed * @param dataTypes A byref int with flags for the supported sensor values * @@ -1029,15 +1040,15 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, /** * Get one of the supported sensor values from a sensor. Make sure it support - * the value type first by calling tdSensor(). The triplet \c protocol, - * \c model and \c id together identifies a sensor. + * the value type first by calling tdSensor(). The triplet @a protocol, + * @a model and @a id together identifies a sensor. * * @param protocol The protocol for the sensor * @param model The model for the sensor * @param id The id of the sensor * @param dataType One of the datatype to retrieve * @param value A byref string where the value will be places - * @param len The length of the \c value parameter + * @param len The length of the @a value parameter * @param timestamp A byref int where the timestamp of the value will be placed * * @returns @ref TELLSTICK_SUCCESS if the value could be fetched or one of the @@ -1074,7 +1085,7 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da * @param controllerId A byref int where the id of the controller will be placed * @param controllerType A byref int where the type of the controller will be placed * @param name A byref string where the name of the controller will be placed - * @param nameLen The length of the \c name parameter + * @param nameLen The length of the @a name parameter * @param available A byref int if the controller is currently available or maybe disconnected * @returns TELLSTICK_SUCCESS if there is more sensors to be fetched * @sa TELLSTICK_CONTROLLER_TELLSTICK @@ -1090,12 +1101,12 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int /** * This function gets a parameter on a controller. - * Valid parameters are: \c serial and \c firmware + * Valid parameters are: @c serial and @c firmware * * @param controllerId The controller to change * @param name The parameter to get. * @param value A byref string where the value of the parameter will be placed - * @param valueLen The length of the \c value parameter + * @param valueLen The length of the @a value parameter * * @returns @ref TELLSTICK_SUCCESS on success, or an error code on failure. * @@ -1118,7 +1129,7 @@ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, in /** * This function sets a parameter on a controller. - * Valid parameters are: \c name + * Valid parameters are: @c name * * @param controllerId The controller to change * @param name The parameter to change. From 8ace17c8f0fe57d97616f71375cafe3f657b2a79 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Mon, 19 Mar 2012 10:50:11 +0100 Subject: [PATCH 1967/2215] Reformat the doxygen comment --- telldus-core/client/telldus-core.cpp | 805 +++++++++++++++------------ 1 file changed, 457 insertions(+), 348 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index ec1c2467..81b35465 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -16,178 +16,147 @@ using namespace TelldusCore; /** * @name Device method flags - * Flags for the different methods/commands a device can support. Can be used - * as bitflags in e.g. tdMethods(). + * Flags for the different methods/commands a device can support. Can be used + * as bit flags in e.g. tdMethods(). * @{ * * @def TELLSTICK_TURNON - * Device-flag for devices supporting the tdTurnOn() call. - * + * Device-flag for devices supporting the tdTurnOn() call. * @def TELLSTICK_TURNOFF - * Device-flag for devices supporting the tdTurnOff() call. - * + * Device-flag for devices supporting the tdTurnOff() call. * @def TELLSTICK_BELL - * Device-flag for devices supporting the tdBell() call. - * + * Device-flag for devices supporting the tdBell() call. * @def TELLSTICK_TOGGLE - * This method is currently unimplemented. - * + * This method is currently unimplemented. * @def TELLSTICK_DIM - * Device-flag for devices supporting the tdDim() call. - * + * Device-flag for devices supporting the tdDim() call. * @def TELLSTICK_LEARN - * Device-flag for devices supporting the tdLearn() call. - * + * Device-flag for devices supporting the tdLearn() call. * @def TELLSTICK_EXECUTE - * Device-flag for devices (scenes) supporting the tdExecute() call. - * + * Device-flag for devices (scenes) supporting the tdExecute() call. * @def TELLSTICK_UP - * Device-flag for devices supporting the tdUp() call. - * + * Device-flag for devices supporting the tdUp() call. * @def TELLSTICK_DOWN - * Device-flag for devices supporting the tdDown() call. - * + * Device-flag for devices supporting the tdDown() call. * @def TELLSTICK_STOP - * Device-flag for devices supporting the tdStop() call. + * Device-flag for devices supporting the tdStop() call. * **//* @} */ /** * @name Device types - * The device type as returned from tdGetDeviceType(). + * The device type as returned from tdGetDeviceType(). * @{ * * @def TELLSTICK_TYPE_DEVICE - * Device type of a single device. - * + * Device type of a single device. * @def TELLSTICK_TYPE_GROUP - * Device type of a device which contains other devices. - * + * Device type of a device which contains other devices. * @def TELLSTICK_TYPE_SCENE - * Device type of a device which contains other devices that are sent different - * commands when executed (i.e. one device turns on, another turns off). + * Device type of a device which contains other devices that are sent + * different commands when executed (i.e. one device turns on, another turns + * off). * **//* @} */ /** * @name Sensor value types - * The supported sensor value types are returned from tdSensor() and used when - * querying a sensor for a specific value in tdSensorValue(). + * The supported sensor value types are returned from tdSensor() and used + * when querying a sensor for a specific value in tdSensorValue(). * @{ * * @def TELLSTICK_TEMPERATURE - * The sensor can report the temperature. - * + * The sensor can report the temperature. * @def TELLSTICK_HUMIDITY - * The sensor can report the humidity. + * The sensor can report the humidity. * **//* @} */ /** * @name Controller type - * The controller type as returned from tdController(). + * The controller type as returned from tdController(). * @{ * * @def TELLSTICK_CONTROLLER_TELLSTICK - * The controller is a TellStick. - * + * The controller is a TellStick. * @def TELLSTICK_CONTROLLER_TELLSTICK_DUO - * The controller is a TellStick Duo. - * + * The controller is a TellStick Duo. * @def TELLSTICK_CONTROLLER_TELLSTICK_NET - * The controller is a TellStick Net. + * The controller is a TellStick Net. * **//* @} */ /** * @name Device changes - * Flags used in event callbacks. + * Flags used in event callbacks. * @{ * * @def TELLSTICK_DEVICE_ADDED - * A new device was added. - * + * A new device was added. * @def TELLSTICK_DEVICE_CHANGED - * A device was changed. - * + * A device was changed. * @def TELLSTICK_DEVICE_REMOVED - * A device was removed. - * + * A device was removed. * @def TELLSTICK_DEVICE_STATE_CHANGED - * The state changed for a device. + * The state changed for a device. * **//* @} */ /** * @name Change types - * Flags used in event callbacks. + * Flags used in event callbacks. * @{ * * @def TELLSTICK_CHANGE_NAME - * The name has changed. - * + * The name has changed. * @def TELLSTICK_CHANGE_PROTOCOL - * The protocol has changed. - * + * The protocol has changed. * @def TELLSTICK_CHANGE_MODEL - * The model has changed. - * + * The model has changed. * @def TELLSTICK_CHANGE_METHOD - * The method has changed. - * + * The method has changed. * @def TELLSTICK_CHANGE_AVAILABLE - * The controller is now available or unavailable. - * + * The controller is now available or unavailable. * @def TELLSTICK_CHANGE_FIRMWARE - * The firmware has changed. + * The firmware has changed. * **//* @} */ /** * @name Error codes - * The error codes returned from all API functions returning int. + * The error codes returned from some API functions. * @{ * * @def TELLSTICK_SUCCESS - * Error code. Returned when the command succeeded. - * + * Error code. Returned when the command succeeded. * @def TELLSTICK_ERROR_NOT_FOUND - * Error code. Returned if a TellStick was not found on the system. - * + * Error code. Returned if a TellStick was not found on the system. * @def TELLSTICK_ERROR_PERMISSION_DENIED - * Error code. Returned if the user doesn't have privileges to open - * the TellStick device. - * + * Error code. Returned if the user doesn't have privileges to open the + * TellStick device. * @def TELLSTICK_ERROR_DEVICE_NOT_FOUND - * Error code. The supplied device id was not found. - * + * Error code. The supplied device id was not found. * @def TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - * Error code. The requested method is not supported by the device. - * This should be avoided by a call to tdMethods(). - * + * Error code. The requested method is not supported by the device. This + * should be avoided by a call to tdMethods(). * @def TELLSTICK_ERROR_COMMUNICATION - * Error code. An error occurred when communicating with TellStick. - * + * Error code. An error occurred when communicating with TellStick. * @def TELLSTICK_ERROR_CONNECTING_SERVICE - * Error code. The client library could not connect to the service. - * Maybe it is not running? - * + * Error code. The client library could not connect to the service. Maybe it + * is not running? * @def TELLSTICK_ERROR_UNKNOWN_RESPONSE - * Error code. The client library received a response from the service - * it did not understand. - * + * Error code. The client library received a response from the service it did + * not understand. * @def TELLSTICK_ERROR_SYNTAX - * Error code. Input/command could not be parsed or didn't follow - * input rules. - * + * Error code. Input/command could not be parsed or didn't follow input + * rules. * @def TELLSTICK_ERROR_BROKEN_PIPE - * Error code. Pipe broken during communication. - * + * Error code. Pipe broken during communication. * @def TELLSTICK_ERROR_COMMUNICATING_SERVICE - * Error code. Timeout waiting for response from the Telldus Service. - * + * Error code. Timeout waiting for response from the Telldus Service. * @def TELLSTICK_ERROR_UNKNOWN - * Error code. An unkown error has occurred. + * Error code. An unknown error has occurred. + * **//* @} */ /** @@ -195,106 +164,143 @@ using namespace TelldusCore; * @{ * * @typedef TDDeviceEvent - * The callback type for device events. + * The callback type for device events. * - * @attention The callback will be called by another thread than the thread - * used by the application and some measures must be taken to synchronize it - * with the main thread. + * @attention + * The callback will be called by another thread than the thread used by the + * application and some measures must be taken to synchronize it with the + * main thread. * - * @param deviceId The id of the device that changed. - * @param method The new device state. Can be @ref TELLSTICK_TURNON, @ref - * TELLSTICK_TURNOFF, etc. - * @param data If @a method is @ref TELLSTICK_DIM this holds the current value - * as a human readable string, example "128" for 50%. - * @param callbackId The id of the callback. - * @param context The pointer passed when registering for the event. + * @param deviceId + * The id of the device that changed. + * @param method + * The new device state. Can be @ref TELLSTICK_TURNON, @ref + * TELLSTICK_TURNOFF, etc. + * @param data + * If @a method is @ref TELLSTICK_DIM this holds the current value as a human + * readable string, example "128" for 50%. + * @param callbackId + * The id of the callback. + * @param context + * The pointer passed when registering for the event. * * @sa tdRegisterDeviceEvent * + ****************************************************************************** * * @typedef TDDeviceChangeEvent - * The callback type for device change events. + * The callback type for device change events. * - * @attention The callback will be called by another thread than the thread - * used by the application and some measures must be taken to synchronize it - * with the main thread. + * @attention + * The callback will be called by another thread than the thread used by the + * application and some measures must be taken to synchronize it with the + * main thread. * - * @param deviceId The id of the device that was added, changed or removed. - * @param changeEvent One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref - * TELLSTICK_DEVICE_CHANGED or @ref TELLSTICK_DEVICE_REMOVED. - * @param changeType If @a changeEvent is @ref TELLSTICK_DEVICE_CHANGED, this - * parameter indicates what has changed (e.g @ref TELLSTICK_CHANGE_NAME, @ref - * TELLSTICK_CHANGE_PROTOCOL, @ref TELLSTICK_CHANGE_MODEL or @ref - * TELLSTICK_CHANGE_METHOD). - * @param callbackId The id of the callback. - * @param context The pointer passed when registering for the event. + * @param deviceId + * The id of the device that was added, changed or removed. + * @param changeEvent + * One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref + * TELLSTICK_DEVICE_CHANGED or @ref TELLSTICK_DEVICE_REMOVED. + * @param changeType + * If @a changeEvent is @ref TELLSTICK_DEVICE_CHANGED, this parameter + * indicates what has changed (e.g @ref TELLSTICK_CHANGE_NAME, @ref + * TELLSTICK_CHANGE_PROTOCOL, @ref TELLSTICK_CHANGE_MODEL or @ref + * TELLSTICK_CHANGE_METHOD). + * @param callbackId + * The id of the callback. + * @param context + * The pointer passed when registering for the event. * * @sa tdRegisterDeviceChangeEvent * + ****************************************************************************** * * @typedef TDRawDeviceEvent - * The callback type for raw events. + * The callback type for raw events. * - * @attention The callback will be called by another thread than the thread - * used by the application and some measures must be taken to synchronize it - * with the main thread. + * @attention + * The callback will be called by another thread than the thread used by the + * application and some measures must be taken to synchronize it with the + * main thread. * - * @param data Raw device data. - * @param controllerId Id of receiving controller. - * @param callbackId The id of the callback. - * @param context The pointer passed when registering for the event. + * @param data + * Raw device data. + * @param controllerId + * Id of receiving controller. + * @param callbackId + * The id of the callback. + * @param context + * The pointer passed when registering for the event. * * @sa tdRegisterRawDeviceEvent * + ****************************************************************************** * * @typedef TDSensorEvent - * The callback type for sensor events. + * The callback type for sensor events. * - * @attention The callback will be called by another thread than the thread - * used by the application and some measures must be taken to synchronize it - * with the main thread. + * @attention + * The callback will be called by another thread than the thread used by the + * application and some measures must be taken to synchronize it with the + * main thread. * - * @param protocol The sensor's protocol. - * @param model The model of the sensor. - * @param id The unique id for the sensor. - * @param dataType The type that @a value is. Can be one of @ref - * TELLSTICK_TEMPERATURE or @ref TELLSTICK_HUMIDITY. - * @param value A human readable string of the data. - * @param timestamp The time (as returned by the time() system call) when the - * value was received. - * @param callbackId The id of the callback. - * @param context The pointer passed when registering for the event. + * @param protocol + * The sensor's protocol. + * @param model + * The model of the sensor. + * @param id + * The unique id for the sensor. + * @param dataType + * The type that @a value is. Can be one of @ref TELLSTICK_TEMPERATURE or + * @ref TELLSTICK_HUMIDITY. + * @param value + * A human readable string of the data. + * @param timestamp + * The time (as returned by the time() system call) when the value was + * received. + * @param callbackId + * The id of the callback. + * @param context + * The pointer passed when registering for the event. * * @sa tdRegisterSensorEvent * + ****************************************************************************** * * @typedef TDControllerEvent - * The callback type for controller events. + * The callback type for controller events. * - * @attention The callback will be called by another thread than the thread - * used by the application and some measures must be taken to synchronize it - * with the main thread. + * @attention + * The callback will be called by another thread than the thread used by the + * application and some measures must be taken to synchronize it with the + * main thread. * - * @param controllerId The id of the controller that was added, changed or - * removed. - * @param changeEvent One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref - * TELLSTICK_DEVICE_CHANGED, @ref TELLSTICK_DEVICE_STATE_CHANGED or @ref - * TELLSTICK_DEVICE_REMOVED. + * @param controllerId + * The id of the controller that was added, changed or removed. + * @param changeEvent + * One of the constants @ref TELLSTICK_DEVICE_ADDED, @ref + * TELLSTICK_DEVICE_CHANGED, @ref TELLSTICK_DEVICE_STATE_CHANGED or @ref + * TELLSTICK_DEVICE_REMOVED. - * @param changeType If @a changeEvent is: - * @arg @ref TELLSTICK_DEVICE_ADDED this is the controller's type (e.g. @ref - * TELLSTICK_CONTROLLER_TELLSTICK or @ref TELLSTICK_CONTROLLER_TELLSTICK_DUO), - * @arg @ref TELLSTICK_DEVICE_CHANGED this indicates what has changed - * (e.g. @ref TELLSTICK_CHANGE_NAME or @ref TELLSTICK_CHANGE_FIRMWARE), - * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this indicates which state that - * has changed (e.g. @ref TELLSTICK_CHANGE_AVAILABLE), - * @arg @ref TELLSTICK_DEVICE_REMOVED this is unused. - * @param newValue If @a changeEvent is: - * @arg @ref TELLSTICK_DEVICE_CHANGED this is the property's new value. - * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this is the new state. For @ref - * TELLSTICK_CHANGE_AVAILABLE this is either 0 or 1. - * @param callbackId The id of the callback. - * @param context The pointer passed when registering for the event. + * @param changeType + * If @a changeEvent is: + * @arg @ref TELLSTICK_DEVICE_ADDED this is the controller's type + * (e.g. @ref TELLSTICK_CONTROLLER_TELLSTICK or @ref + * TELLSTICK_CONTROLLER_TELLSTICK_DUO), + * @arg @ref TELLSTICK_DEVICE_CHANGED this indicates what has changed + * (e.g. @ref TELLSTICK_CHANGE_NAME or @ref TELLSTICK_CHANGE_FIRMWARE), + * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this indicates which state that + * has changed (e.g. @ref TELLSTICK_CHANGE_AVAILABLE), + * @arg @ref TELLSTICK_DEVICE_REMOVED this is unused. + * @param newValue + * If @a changeEvent is: + * @arg @ref TELLSTICK_DEVICE_CHANGED this is the property's new value. + * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this is the new state. For @ref + * TELLSTICK_CHANGE_AVAILABLE this is either 0 or 1. + * @param callbackId + * The id of the callback. + * @param context + * The pointer passed when registering for the event. * * @sa tdRegisterControllerEvent * @@ -313,11 +319,14 @@ void WINAPI tdInit(void) { /** * Register a callback that will receive device events. * - * @param eventFunction Callback function - * @param context Pointer that will be passed back in the callback. + * @param eventFunction + * Callback function. + * @param context + * Pointer that will be passed back in the callback. * - * @returns An id identifying the callback. Pass this id to - * tdUnregisterCallback() to stop receiving callbacks. + * @returns + * An id identifying the callback. Pass this id to tdUnregisterCallback() to + * stop receiving callbacks. * * @sa @ref sec_events_registering * @since Version 2.0.0 @@ -330,11 +339,14 @@ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { /** * Register a callback that will receive raw (i.e. all) events. * - * @param eventFunction Callback function - * @param context Pointer that will be passed back in the callback. + * @param eventFunction + * Callback function. + * @param context + * Pointer that will be passed back in the callback. * - * @returns An id identifying the callback. Pass this id to - * tdUnregisterCallback() to stop receiving callbacks. + * @returns + * An id identifying the callback. Pass this id to tdUnregisterCallback() to + * stop receiving callbacks. * * @sa @ref sec_events_registering * @since Version 2.0.0 @@ -349,11 +361,14 @@ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *conte * addition of new devices, changes of device properties (e.g. name) and * removal of existing devices. * - * @param eventFunction Callback function - * @param context Pointer that will be passed back in the callback. + * @param eventFunction + * Callback function. + * @param context + * Pointer that will be passed back in the callback. * - * @returns An id identifying the callback. Pass this id to - * tdUnregisterCallback() to stop receiving callbacks. + * @returns + * An id identifying the callback. Pass this id to tdUnregisterCallback() to + * stop receiving callbacks. * * @sa @ref sec_events_registering * @since Version 2.1.0 @@ -366,11 +381,14 @@ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void /** * Register a callback that will receive sensor events. * - * @param eventFunction Callback function - * @param context Pointer that will be passed back in the callback. + * @param eventFunction + * Callback function. + * @param context + * Pointer that will be passed back in the callback. * - * @returns An id identifying the callback. Pass this id to - * tdUnregisterCallback() to stop receiving callbacks. + * @returns + * An id identifying the callback. Pass this id to tdUnregisterCallback() to + * stop receiving callbacks. * * @sa @ref sec_events_registering * @since Version 2.1.0 @@ -383,11 +401,14 @@ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { /** * Register a callback that will receive controller events. * - * @param eventFunction Callback function - * @param context Pointer that will be passed back in the callback. + * @param eventFunction + * Callback function. + * @param context + * Pointer that will be passed back in the callback. * - * @returns An id identifying the callback. Pass this id to - * tdUnregisterCallback() to stop receiving callbacks. + * @returns + * An id identifying the callback. Pass this id to tdUnregisterCallback() to + * stop receiving callbacks. * * @sa @ref sec_events_registering * @since Version 2.1.2 @@ -400,9 +421,11 @@ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *con /** * Unregister a callback. * - * @param callbackId The returned id from one of the tdRegister* functions. + * @param callbackId + * The returned id from one of the tdRegister* functions. * - * @returns 1 on success, or 0 on failure. + * @returns + * 1 on success, or 0 on failure. * * @sa @ref sec_events_registering * @since Version 2.1.0 @@ -413,8 +436,8 @@ int WINAPI tdUnregisterCallback( int callbackId ) { } /** - * Close the library and clean up the cache it uses. - * This should be called when the library is not supposed to be used anymore + * Close the library and clean up the cache it uses. This should be called + * when the library is not supposed to be used anymore. * * @since Version 2.0.0 **/ @@ -423,11 +446,11 @@ void WINAPI tdClose(void) { } /** - * This method releases resources allocated by telldus-core. - * It should be called on the returned value from all functions returning - * char *. + * This method releases resources allocated by telldus-core. It should be + * called on the returned value from all functions returning char *. * - * @param string A string returned from a td* function. + * @param string + * A string returned from a td* function. * * @since Version 2.0.1 **/ @@ -440,14 +463,14 @@ void WINAPI tdReleaseString(char *string) { } /** - * Turns a device on. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Turns a device on. Make sure the device supports this by calling + * tdMethods() before any call to this function. * - * @param intDeviceId The device id to turn on. + * @param intDeviceId + * The device id to turn on. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.0.0 **/ @@ -458,14 +481,14 @@ int WINAPI tdTurnOn(int intDeviceId){ } /** - * Turns a device off. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Turns a device off. Make sure the device supports this by calling + * tdMethods() before any call to this function. * - * @param intDeviceId The device id to turn off. + * @param intDeviceId + * The device id to turn off. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.0.0 **/ @@ -476,14 +499,14 @@ int WINAPI tdTurnOff(int intDeviceId){ } /** - * Sends bell command to devices supporting this. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Sends bell command to devices supporting this. Make sure the device + * supports this by calling tdMethods() before any call to this function. * - * @param intDeviceId The device id to send bell to + * @param intDeviceId + * The device id to send bell to. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.0.0 **/ @@ -494,15 +517,16 @@ int WINAPI tdBell(int intDeviceId){ } /** - * Dims a device. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Dims a device. Make sure the device supports this by calling tdMethods() + * before any call to this function. * - * @param intDeviceId The device id to dim - * @param level The level the device should dim to. This value should be 0-255 + * @param intDeviceId + * The device id to dim. + * @param level + * The level the device should dim to. This value should be 0 - 255. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.0.0 **/ @@ -514,14 +538,14 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ } /** - * Execute a scene action. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Execute a scene action. Make sure the device supports this by calling + * tdMethods() before any call to this function. * - * @param intDeviceId The id to execute + * @param intDeviceId + * The id to execute. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.1.0 **/ @@ -532,14 +556,14 @@ int WINAPI tdExecute(int intDeviceId){ } /** - * Send "up" command to device. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Send "up" command to device. Make sure the device supports this by calling + * tdMethods() before any call to this function. * - * @param intDeviceId The device id to send the command to + * @param intDeviceId + * The device id to send the command to. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.1.0 **/ @@ -550,14 +574,14 @@ int WINAPI tdUp(int intDeviceId){ } /** - * Send "down" command to device. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Send "down" command to device. Make sure the device supports this by + * calling tdMethods() before any call to this function. * - * @param intDeviceId The device id to send the command to + * @param intDeviceId + * The device id to send the command to. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.1.0 **/ @@ -568,14 +592,14 @@ int WINAPI tdDown(int intDeviceId){ } /** - * Send "stop" command to device. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * Send "stop" command to device. Make sure the device supports this by + * calling tdMethods() before any call to this function. * - * @param intDeviceId The device id to stop + * @param intDeviceId + * The device id to stop. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.1.0 */ @@ -587,14 +611,14 @@ int WINAPI tdStop(int intDeviceId){ /** * Sends a special learn command to some devices that need a special - * learn-command to be used from TellStick. - * Make sure the device supports this by calling tdMethods() before any - * call to this function. + * learn-command to be used from TellStick. Make sure the device supports this + * by calling tdMethods() before any call to this function. * - * @param intDeviceId The device id to learn. + * @param intDeviceId + * The device id to learn. * - * @returns @ref TELLSTICK_SUCCESS on success or appropriate error code on - * failure. + * @returns + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @since Version 2.0.0 **/ @@ -607,12 +631,14 @@ int WINAPI tdLearn(int intDeviceId) { /** * Returns the last sent command to a specific device * - * @param intDeviceId The device id to query - * @param methodsSupported The methods supported by the client. See tdMethods() - * for more information. + * @param intDeviceId + * The device id to query. + * @param methodsSupported + * The methods supported by the client. See tdMethods() for more information. * - * @returns The last sent command as integer, example @ref TELLSTICK_TURNON or - * @ref TELLSTICK_TURNOFF + * @returns + * The last sent command as integer, example @ref TELLSTICK_TURNON or @ref + * TELLSTICK_TURNOFF * * @since Version 2.0.0 **/ @@ -627,10 +653,12 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { * If the last sent command it @ref TELLSTICK_DIM this returns the dimmed * value. * - * @param intDeviceId The device id to query + * @param intDeviceId + * The device id to query. * - * @returns The the value as a human readable string, example "128" for - * 50%. The returned string must be freed by calling tdReleaseString(). + * @returns + * The the value as a human readable string, example "128" for 50%. The + * returned string must be freed by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -644,7 +672,8 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { /** * This function returns the number of devices configured. * - * @returns An integer of the total number of devices configured + * @returns + * An integer of the total number of devices configured. * * @since Version 2.0.0 **/ @@ -654,6 +683,7 @@ int WINAPI tdGetNumberOfDevices(void){ /** * This function returns the unique id of a device with a specific index. + * * To get all the id numbers you should loop over all the devices: * @code * int intNumberOfDevices = tdGetNumberOfDevices(); @@ -663,9 +693,11 @@ int WINAPI tdGetNumberOfDevices(void){ * } * @endcode * - * @param intDeviceIndex The device index to query. The index starts from 0. + * @param intDeviceIndex + * The device index to query. The index starts from 0. * - * @returns The unique id for the device or -1 if the device is not found. + * @returns + * The unique id for the device or -1 if the device is not found. * * @since Version 2.0.0 **/ @@ -678,11 +710,13 @@ int WINAPI tdGetDeviceId(int intDeviceIndex){ /** * Get the device type. * - * @param intDeviceId The unique id of the device to query + * @param intDeviceId + * The unique id of the device to query. * - * @returns Which type the device is. The device could be either @ref - * TELLSTICK_TYPE_DEVICE, @ref TELLSTICK_TYPE_GROUP or @ref - * TELLSTICK_TYPE_SCENE + * @returns + * Which type the device is. The device could be either @ref + * TELLSTICK_TYPE_DEVICE, @ref TELLSTICK_TYPE_GROUP or @ref + * TELLSTICK_TYPE_SCENE * * @since Version 2.0.0 **/ @@ -695,10 +729,12 @@ int WINAPI tdGetDeviceType(int intDeviceId) { /** * Query a device for it's name. * - * @param intDeviceId The unique id of the device to query + * @param intDeviceId + * The unique id of the device to query. * - * @returns The name of the device or an empty string if the device is not - * found. The returned string must be freed by calling tdReleaseString(). + * @returns + * The name of the device or an empty string if the device is not found. The + * returned string must be freed by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -711,12 +747,15 @@ char * WINAPI tdGetName(int intDeviceId){ /** * Sets a new name for a device. The devices are global for all application, - * changing this will change the name for other applications aswell. + * changing this will change the name for other applications as well. * - * @param intDeviceId The device id to change the name for - * @param strNewName The new name for the devices + * @param intDeviceId + * The device id to change the name for. + * @param strNewName + * The new name for the devices. * - * @returns @c true on success, @c false otherwise. + * @returns + * @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -729,10 +768,13 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ /** * Get the device protocol. - * @param intDeviceId The device id to query. * - * @returns The protocol used by a specific device. The returned string must be - * freed by calling tdReleaseString(). + * @param intDeviceId + * The device id to query. + * + * @returns + * The protocol used by a specific device. The returned string must be freed + * by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -747,10 +789,13 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * This changes the current protocol used by a device. After changing the * protocol, setting new parameters is required. * - * @param intDeviceId The device to change. - * @param strProtocol The new protocol to use. + * @param intDeviceId + * The device to change. + * @param strProtocol + * The new protocol to use. * - * @returns @c true on success, @c false otherwise. + * @returns + * @c true on success, @c false otherwise. * * @sa tdSetModel() * @sa tdSetDeviceParameter() @@ -767,10 +812,12 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ /** * Get the device model. * - * @param intDeviceId The device to query. + * @param intDeviceId + * The device to query. * - * @returns The model for a device. Not all protocols uses this. The returned - * string must be freed by calling tdReleaseString(). + * @returns + * The model for a device. Not all protocols uses this. The returned string + * must be freed by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -785,10 +832,13 @@ char* WINAPI tdGetModel(int intDeviceId){ * Sets a new model for a device. Which model to set depends on the * current protocol. * - * @param intDeviceId The device to change - * @param strModel The new model + * @param intDeviceId + * The device to change. + * @param strModel + * The new model. * - * @returns @c true on success, @c false otherwise. + * @returns + * @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -803,11 +853,15 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * Sets a new protocol specific parameter. Please see the documentation of the * protocols before setting any parameter. * - * @param intDeviceId The device to change. - * @param strName The parameter to change. - * @param strValue The new value for the parameter. + * @param intDeviceId + * The device to change. + * @param strName + * The parameter to change. + * @param strValue + * The new value for the parameter. * - * @returns @c true on success, @c false otherwise. + * @returns + * @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -822,13 +876,17 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha /** * Get a protocol specific parameter for a device. * - * @param intDeviceId The device to query. - * @param strName The name of the parameter to query. - * @param defaultValue A default value to return if the current parameter - * hasn't previously been set. + * @param intDeviceId + * The device to query. + * @param strName + * The name of the parameter to query. + * @param defaultValue + * A default value to return if the current parameter hasn't previously been + * set. * - * @returns The protocol specific parameter specified by @a strName. The - * returned string must be freed by calling tdReleaseString(). + * @returns + * The protocol specific parameter specified by @a strName. The returned + * string must be freed by calling tdReleaseString(). * * @since Version 2.0.0 **/ @@ -846,8 +904,9 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c * called first before any call to tdSetName(), tdSetProtocol() and similar * functions. * - * @returns The new device id for the newly created device. If the creation - * fails it returnes an error (i.e. negative) value. + * @returns + * The new device id for the newly created device. If the creation fails it + * returns an error (i.e. negative) value. * * @since Version 2.0.0 **/ @@ -859,9 +918,11 @@ int WINAPI tdAddDevice(){ /** * Removes a device. * - * @param intDeviceId The device to query. + * @param intDeviceId + * The device to query. * - * @returns @c true on success, @c false otherwise. + * @returns + * @c true on success, @c false otherwise. * * @since Version 2.0.0 **/ @@ -881,15 +942,18 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * int methods = tdMethods( * id, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL); * // methods is now TELLSTICK_BELL - * int methods = tdMethods(idm TELLSTICK_TURNON | TELLSTICK_TURNOFF); + * int methods = tdMethods(id, TELLSTICK_TURNON | TELLSTICK_TURNOFF); * // methods is now TELLSTICK_TURNON because the client application doesn't * // support TELLSTICK_BELL * @endcode * - * @param id The device id to query - * @param methodsSupported The methods the client application supports + * @param id + * The device id to query. + * @param methodsSupported + * The methods the client application supports. * - * @returns The method-flags OR'ed into an integer. + * @returns + * The method-flags OR'ed into an integer. * * @sa TELLSTICK_TURNON * @sa TELLSTICK_TURNOFF @@ -914,10 +978,12 @@ int WINAPI tdMethods(int id, int methodsSupported){ * Get a human readable string from an error code returned from a function in * telldus-core. * - * @param intErrorNo The error code to translate. + * @param intErrorNo + * The error code to translate. * - * @returns A string ready to show to the user. The returned string must be - * freed by calling tdReleaseString(). + * @returns + * A string ready to show to the user. The returned string must be freed by + * calling tdReleaseString(). * * @sa TELLSTICK_SUCCESS * @sa TELLSTICK_ERROR_NOT_FOUND @@ -964,11 +1030,13 @@ char * WINAPI tdGetErrorString(int intErrorNo) { * Send a raw command to TellStick. Please read the TellStick protocol * definition on how the command should be constructed. * - * @param command The command for TellStick in its native format - * @param reserved Reserved for future use + * @param command + * The command for TellStick in its native format. + * @param reserved + * Reserved for future use. * - * @returns @ref TELLSTICK_SUCCESS on success or one of the errorc odes on - * failure + * @returns + * @ref TELLSTICK_SUCCESS on success or one of the error codes on failure * * @since Version 2.0.0 **/ @@ -986,9 +1054,12 @@ int WINAPI tdSendRawCommand(const char *command, int reserved) { /** * Connect a TellStick controller. * - * @param vid The vendor id - * @param pid The product id - * @param serial The serial + * @param vid + * The vendor id. + * @param pid + * The product id. + * @param serial + * The serial. * * @since Version 2.1.0 **/ @@ -1003,9 +1074,12 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { /** * Disconnect a TellStick controller. * - * @param vid The vendor id - * @param pid The product id - * @param serial The serial + * @param vid + * The vendor id. + * @param pid + * The product id. + * @param serial + * The serial. * * @since Version 2.1.0 **/ @@ -1019,17 +1093,23 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial /** * Use this function to iterate over all sensors. Iterate until @ref - * TELLSTICK_SUCCESS is not returned + * TELLSTICK_SUCCESS is not returned. * - * @param protocol A byref string where the protocol of the sensor will be - * placed - * @param protocolLen The length of the @a protocol parameter - * @param model A byref string where the model of the sensor will be placed - * @param modelLen The length of the @a model parameter - * @param id A byref int where the id of the sensor will be placed - * @param dataTypes A byref int with flags for the supported sensor values + * @param[out] protocol + * A by ref string where the protocol of the sensor will be placed. + * @param[in] protocolLen + * The length of the @a protocol parameter. + * @param[out] model + * A by ref string where the model of the sensor will be placed. + * @param[in] modelLen + * The length of the @a model parameter. + * @param[out] id + * A by ref int where the id of the sensor will be placed. + * @param[out] dataTypes + * A by ref int with flags for the supported sensor values. * - * @returns @ref TELLSTICK_SUCCESS if there is more sensors to be fetched + * @returns + * @ref TELLSTICK_SUCCESS if there is more sensors to be fetched. * * @since Version 2.1.0 */ @@ -1040,19 +1120,28 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, /** * Get one of the supported sensor values from a sensor. Make sure it support - * the value type first by calling tdSensor(). The triplet @a protocol, - * @a model and @a id together identifies a sensor. + * the value type first by calling tdSensor(). The triplet @a protocol, @a + * model and @a id together identifies a sensor. * - * @param protocol The protocol for the sensor - * @param model The model for the sensor - * @param id The id of the sensor - * @param dataType One of the datatype to retrieve - * @param value A byref string where the value will be places - * @param len The length of the @a value parameter - * @param timestamp A byref int where the timestamp of the value will be placed + * @param[in] protocol + * The protocol for the sensor. + * @param[in] model + * The model for the sensor. + * @param[in] id + * The id of the sensor. + * @param[in] dataType + * Which sensor value to retrive (one of @ref TELLSTICK_TEMPERATURE or @ref + * TELLSTICK_HUMIDITY). + * @param[out] value + * A by ref string where the value will be placed. + * @param[in] len + * The length of the @a value parameter. + * @param[out] timestamp + * A by ref int where the timestamp of the value will be placed. * - * @returns @ref TELLSTICK_SUCCESS if the value could be fetched or one of the - * error codes on failure + * @returns + * @ref TELLSTICK_SUCCESS if the value could be fetched or one of the error + * codes on failure. * * @since Version 2.1.0 */ @@ -1082,12 +1171,21 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da * Use this function to iterate over all controllers. Iterate until * @ref TELLSTICK_SUCCESS is not returned * - * @param controllerId A byref int where the id of the controller will be placed - * @param controllerType A byref int where the type of the controller will be placed - * @param name A byref string where the name of the controller will be placed - * @param nameLen The length of the @a name parameter - * @param available A byref int if the controller is currently available or maybe disconnected - * @returns TELLSTICK_SUCCESS if there is more sensors to be fetched + * @param[out] controllerId + * A by ref int where the id of the controller will be placed. + * @param[out] controllerType + * A by ref int where the type of the controller will be placed. + * @param[out] name + * A by ref string where the name of the controller will be placed. + * @param[in] nameLen + * The length of the @a name parameter. + * @param[out] available + * A by ref int if the controller is currently available or maybe + * disconnected. + * + * @returns + * @ref TELLSTICK_SUCCESS if there is more sensors to be fetched. + * * @sa TELLSTICK_CONTROLLER_TELLSTICK * @sa TELLSTICK_CONTROLLER_TELLSTICK_DUO * @sa TELLSTICK_CONTROLLER_TELLSTICK_NET @@ -1100,15 +1198,20 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int } /** - * This function gets a parameter on a controller. - * Valid parameters are: @c serial and @c firmware + * This function gets a parameter on a controller. Valid parameters are: @c + * serial and @c firmware * - * @param controllerId The controller to change - * @param name The parameter to get. - * @param value A byref string where the value of the parameter will be placed - * @param valueLen The length of the @a value parameter + * @param[in] controllerId + * The controller to change. + * @param[in] name + * The parameter to get. + * @param[out] value + * A by ref string where the value of the parameter will be placed. + * @param[in] valueLen + * The length of the @a value parameter. * - * @returns @ref TELLSTICK_SUCCESS on success, or an error code on failure. + * @returns + * @ref TELLSTICK_SUCCESS on success, or an error code on failure. * * @since Version 2.1.2 **/ @@ -1128,14 +1231,18 @@ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, in } /** - * This function sets a parameter on a controller. - * Valid parameters are: @c name + * This function sets a parameter on a controller. Valid parameters are: @c + * name. * - * @param controllerId The controller to change - * @param name The parameter to change. - * @param value The new value for the parameter. + * @param controllerId + * The controller to change. + * @param name + * The parameter to change. + * @param value + * The new value for the parameter. * - * @returns @ref TELLSTICK_SUCCESS on success, or an error code on failure. + * @returns + * @ref TELLSTICK_SUCCESS on success, or an error code on failure. * * @since Version 2.1.2 **/ @@ -1151,11 +1258,13 @@ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char * * This function removes a controller from the list of controllers. The * controller must not be available (disconnected) for this to work. * - * @param controllerId The controller to remove + * @param controllerId + * The controller to remove. * - * @returns @ref TELLSTICK_SUCCESS if the controller was removed, @ref - * TELLSTICK_ERROR_NOT_FOUND if the controller was not found, and @ref - * TELLSTICK_ERROR_PERMISSION_DENIED if the controller is still connected. + * @returns + * @ref TELLSTICK_SUCCESS if the controller was removed, @ref + * TELLSTICK_ERROR_NOT_FOUND if the controller was not found, and @ref + * TELLSTICK_ERROR_PERMISSION_DENIED if the controller is still connected. * * @since Version 2.1.2 **/ From bd0e01bfad11eb25ae31c148bd8352cb8f904939 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Mon, 19 Mar 2012 10:50:43 +0100 Subject: [PATCH 1968/2215] Correct spelling in error message --- telldus-core/client/telldus-core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index b75ff14f..211966cb 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -594,7 +594,7 @@ char * WINAPI tdGetErrorString(int intErrorNo) { "Received an unknown response", "Syntax error", "Broken pipe" - "An error occured while communicating with the Telldus Service" + "An error occurred while communicating with the Telldus Service" }; std::string strReturn; intErrorNo = abs(intErrorNo); //We don't use negative values here. From da0371d8035e83dfa6812c48092dd9ede6ba94d8 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Mon, 19 Mar 2012 10:55:35 +0100 Subject: [PATCH 1969/2215] Minor doc fixes --- telldus-core/client/telldus-core.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 81b35465..cb4b1c85 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -1,6 +1,6 @@ /** * @defgroup core telldus-core - * Telldus Core is the base module used to interface a Telldus TellStick. + * Telldus Core is the base module used to interface a Telldus TellStick. * @{ */ @@ -294,7 +294,7 @@ using namespace TelldusCore; * @arg @ref TELLSTICK_DEVICE_REMOVED this is unused. * @param newValue * If @a changeEvent is: - * @arg @ref TELLSTICK_DEVICE_CHANGED this is the property's new value. + * @arg @ref TELLSTICK_DEVICE_CHANGED this is the property's new value, * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this is the new state. For @ref * TELLSTICK_CHANGE_AVAILABLE this is either 0 or 1. * @param callbackId @@ -697,7 +697,7 @@ int WINAPI tdGetNumberOfDevices(void){ * The device index to query. The index starts from 0. * * @returns - * The unique id for the device or -1 if the device is not found. + * The unique id for the device or @c -1 if the device is not found. * * @since Version 2.0.0 **/ From 2eb0453f4d9021077f52c347cb770de40f95e713 Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Mon, 19 Mar 2012 10:57:56 +0100 Subject: [PATCH 1970/2215] Clarify that controller availability is a string --- telldus-core/client/telldus-core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index cb4b1c85..9af1e040 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -296,7 +296,7 @@ using namespace TelldusCore; * If @a changeEvent is: * @arg @ref TELLSTICK_DEVICE_CHANGED this is the property's new value, * @arg @ref TELLSTICK_DEVICE_STATE_CHANGED this is the new state. For @ref - * TELLSTICK_CHANGE_AVAILABLE this is either 0 or 1. + * TELLSTICK_CHANGE_AVAILABLE this is either @c "0" or @c "1". * @param callbackId * The id of the callback. * @param context From 5492623ecd4ceae1c3128c43a2a3f6ba3e9f2e3f Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Tue, 20 Mar 2012 16:37:56 +0100 Subject: [PATCH 1971/2215] Avoid one extra strlen --- telldus-core/common/Strings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 5bee53a9..c1f53411 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -39,7 +39,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { size_t outbytesLeft = utf8Length*sizeof(wchar_t); //Copy the instring - char *inString = new char[strlen(value)+1]; + char *inString = new char[utf8Length+1]; strcpy(inString, value); //Create buffer for output From 3bedad336a51ad14afdfd3c50223dea77ade23fb Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Wed, 21 Mar 2012 16:20:23 +0100 Subject: [PATCH 1972/2215] Make tdadmin handle only one parameter w/o crashing Fixes SIGSEGV when running tdadmin - (ticket #194). --- telldus-core/tdadmin/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-core/tdadmin/main.cpp b/telldus-core/tdadmin/main.cpp index cb4b3b59..66f7fcb0 100644 --- a/telldus-core/tdadmin/main.cpp +++ b/telldus-core/tdadmin/main.cpp @@ -47,6 +47,9 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) { argp_usage (state); case ARGP_KEY_ARG: + if (state->next == state->argc) { + argp_usage (state); + } command = arg; action = state->argv[state->next]; state->next = state->argc; From 0aab73dcbe2630eb53955e81ad22185b083fedaf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 30 Mar 2012 14:03:34 +0200 Subject: [PATCH 1973/2215] Cleanup the STATE_INSTALL_DIR variable in CMake. Only define it one time --- telldus-core/service/CMakeLists.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 23eea99f..06ee41ca 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -242,15 +242,16 @@ IF (UNIX AND NOT APPLE) SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) IF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - SET(STATE_INSTALL_DIR "/var/spool" CACHE PATH "The directory to store state information of the devices") - ELSE (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - SET(STATE_INSTALL_DIR "/var/state" CACHE PATH "The directory to store state information of the devices") - ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + SET(DEFAULT_STATE_INSTALL_DIR "/var/spool") + ELSE () + SET(DEFAULT_STATE_INSTALL_DIR "/var/state") + ENDIF () + SET(STATE_INSTALL_DIR "${DEFAULT_STATE_INSTALL_DIR}" CACHE PATH "The directory to store state information of the devices") CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/SettingsConfusePaths.h.in ${CMAKE_CURRENT_BINARY_DIR}/SettingsConfusePaths.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) - + INSTALL(FILES tellstick.conf DESTINATION ${SYSCONF_INSTALL_DIR} ) From db1d6c4d474ae3e212c7b6148635f8d33e49b9a0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 30 Mar 2012 14:55:34 +0200 Subject: [PATCH 1974/2215] Fix coding style in CMakeLists.txt --- telldus-core/CMakeLists.txt | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 9aa1cbd8..a21f3d25 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -19,9 +19,9 @@ SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") IF (PACKAGE_SUBVERSION) - SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_${PACKAGE_SUBVERSION}") + SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_${PACKAGE_SUBVERSION}") ELSE (PACKAGE_SUBVERSION) - SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) + SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) ENDIF(PACKAGE_SUBVERSION) SET(BUILD_LIBTELLDUS-CORE TRUE CACHE BOOL "Build libtelldus-core") @@ -63,16 +63,18 @@ ADD_SUBDIRECTORY(tests) FIND_PACKAGE(Doxygen) -IF (DOXYGEN_FOUND) - SET(DOXY_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) +IF(DOXYGEN_FOUND) + SET(DOXY_CONFIG ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) - MESSAGE(STATUS "Generating ${DOXY_CONFIG}") - CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in" - ${DOXY_CONFIG} @ONLY) + CONFIGURE_FILE( + "${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in" + ${DOXY_CONFIG} @ONLY + ) - ADD_CUSTOM_TARGET(docs - ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} - DEPENDS ${DOXY_CONFIG} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMENT "Generating doxygen documentation" VERBATIM) -ENDIF (DOXYGEN_FOUND) + ADD_CUSTOM_TARGET(docs + ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} + DEPENDS ${DOXY_CONFIG} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating doxygen documentation" VERBATIM + ) +ENDIF() From 6670f627a0237961e4cca42a29db2c9b8dd8b2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Str=C3=B6m?= Date: Mon, 9 Apr 2012 21:28:39 +0200 Subject: [PATCH 1975/2215] Race-fix for OSX ControllerListener. If the destructor was called very close (in time) after the constructor was called, we'd get a race where gRunLoop was not inited properly, and when trying to release it we crashed with EXC_BAD_ACCESS. An example when this would happen is if the user SIGINTs while starting up. The ControllerManager can be quite slow (seconds) to init sometimes, and if we'd SIGINT while waiting for it, the ControllerListener ctor would be called after, the mainloop would be skipped, and then the dtor would be called -> triggering crash. --- telldus-core/service/ControllerListener_mac.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp index c042b0db..bf2af63a 100644 --- a/telldus-core/service/ControllerListener_mac.cpp +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -21,6 +21,7 @@ public: CFRunLoopRef gRunLoop; io_iterator_t gAddedIter; TelldusCore::EventRef event; + bool running; void addUsbFilter(int vid, int pid); static void DeviceAdded(void *refCon, io_iterator_t iterator); @@ -32,11 +33,16 @@ ControllerListener::ControllerListener(TelldusCore::EventRef event) { d = new PrivateData; d->event = event; + d->running = true; + d->gRunLoop = NULL; this->start(); } ControllerListener::~ControllerListener() { - CFRunLoopStop(d->gRunLoop); + d->running = false; + if(d->gRunLoop != NULL) + CFRunLoopStop(d->gRunLoop); + this->wait(); delete d; } @@ -53,7 +59,10 @@ void ControllerListener::run() { d->addUsbFilter(0x1781, 0x0c30); d->addUsbFilter(0x1781, 0x0c31); - CFRunLoopRun(); + // Race check, if destructor was called really close to thread init, + // running might have gone false. Make sure we don't get stuck + if(d->running) + CFRunLoopRun(); } void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) { From c137bca9fe07954c5d00dd5db567d4721bb93b79 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 Apr 2012 10:24:11 +0200 Subject: [PATCH 1976/2215] Only log SIGPIPE as debug messages. Closes #194 --- telldus-core/service/main_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 73cff6d1..dd0c3659 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -30,7 +30,7 @@ void signalHandler(int sig) { tm.stop(); break; case SIGPIPE: - Log::warning("Received SIGPIPE signal."); + Log::debug("Received SIGPIPE signal."); break; default: Log::warning("Unhandled signal (%d) %s", sig, strsignal(sig)); From eb95ffe8a55d27399e3afaa03fadc3b8ff262c7e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 Apr 2012 10:55:24 +0200 Subject: [PATCH 1977/2215] Fix missing separator. --- telldus-core/client/telldus-core.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index b66a434f..8767ed6e 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -1001,7 +1001,7 @@ int WINAPI tdMethods(int id, int methodsSupported){ * @since Version 2.0.0 **/ char * WINAPI tdGetErrorString(int intErrorNo) { - const int numResponses = 10; + const int numResponses = 11; const char *responses[numResponses] = { "Success", "TellStick not found", @@ -1012,7 +1012,7 @@ char * WINAPI tdGetErrorString(int intErrorNo) { "Could not connect to the Telldus Service", "Received an unknown response", "Syntax error", - "Broken pipe" + "Broken pipe", "An error occurred while communicating with the Telldus Service" }; std::string strReturn; From 12eb097ce4997bc435b78daca8bfd93c9ee61681 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 Apr 2012 10:56:36 +0200 Subject: [PATCH 1978/2215] Add error message for syntax error in the configuration file, see #119 --- telldus-core/client/telldus-core.cpp | 5 +++-- telldus-core/client/telldus-core.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 8767ed6e..7e689f3e 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -1001,7 +1001,7 @@ int WINAPI tdMethods(int id, int methodsSupported){ * @since Version 2.0.0 **/ char * WINAPI tdGetErrorString(int intErrorNo) { - const int numResponses = 11; + const int numResponses = 12; const char *responses[numResponses] = { "Success", "TellStick not found", @@ -1013,7 +1013,8 @@ char * WINAPI tdGetErrorString(int intErrorNo) { "Received an unknown response", "Syntax error", "Broken pipe", - "An error occurred while communicating with the Telldus Service" + "An error occurred while communicating with the Telldus Service", + "Syntax error in the configuration file" }; std::string strReturn; intErrorNo = abs(intErrorNo); //We don't use negative values here. diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 3067ab7c..275373da 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -125,6 +125,7 @@ extern "C" { #define TELLSTICK_ERROR_SYNTAX -8 #define TELLSTICK_ERROR_BROKEN_PIPE -9 #define TELLSTICK_ERROR_COMMUNICATING_SERVICE -10 +#define TELLSTICK_ERROR_CONFIG_SYNTAX -11 #define TELLSTICK_ERROR_UNKNOWN -99 //Device typedef From 8babf9913dc69937f8dc021174a451af633ab55c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 Apr 2012 11:10:27 +0200 Subject: [PATCH 1979/2215] If the protocol is not valid, return TELLSTICK_ERROR_CONFIG_SYNTAX instead of TELLSTICK_ERROR_UNKNOWN. Closes #119 --- telldus-core/service/Device.cpp | 85 +++++++++++++++++---------------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index b0777542..f9757a1c 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -139,49 +139,50 @@ int Device::getType(){ int Device::doAction(int action, unsigned char data, Controller *controller) { Protocol *p = this->retrieveProtocol(); - if(p){ - //Try to determine if we need to call another method due to masking - int methods = p->methods(); - if ((action & methods) == 0) { - //Loop all methods an see if any method masks to this one - for(int i = 1; i <= methods; i<<=1) { - if ((i & methods) == 0) { - continue; - } - if (this->maskUnsupportedMethods(i, action)) { - action = i; - break; - } - } - } - if ((action & methods) == 0) { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } - std::string code = p->getStringForMethod(action, data, controller); - if (code == "") { - return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - } - if (code[0] != 'S' && code[0] != 'T' && code[0] != 'P' && code[0] != 'R') { - //Try autodetect sendtype - TellStick *tellstick = reinterpret_cast(controller); - if (!tellstick) { - return TELLSTICK_ERROR_UNKNOWN; - } - unsigned int maxlength = 80; - if (tellstick->pid() == 0x0c31) { - maxlength = 512; - } - if (code.length() <= maxlength) { - //S is enough - code.insert(0, 1, 'S'); - code.append(1, '+'); - } else { - code = TellStick::createTPacket(code); - } - } - return controller->send(code); + if (!p) { + //Syntax error in configuration, no such protocol + return TELLSTICK_ERROR_CONFIG_SYNTAX; } - return TELLSTICK_ERROR_UNKNOWN; + //Try to determine if we need to call another method due to masking + int methods = p->methods(); + if ((action & methods) == 0) { + //Loop all methods an see if any method masks to this one + for(int i = 1; i <= methods; i<<=1) { + if ((i & methods) == 0) { + continue; + } + if (this->maskUnsupportedMethods(i, action)) { + action = i; + break; + } + } + } + if ((action & methods) == 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } + std::string code = p->getStringForMethod(action, data, controller); + if (code == "") { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } + if (code[0] != 'S' && code[0] != 'T' && code[0] != 'P' && code[0] != 'R') { + //Try autodetect sendtype + TellStick *tellstick = reinterpret_cast(controller); + if (!tellstick) { + return TELLSTICK_ERROR_UNKNOWN; + } + unsigned int maxlength = 80; + if (tellstick->pid() == 0x0c31) { + maxlength = 512; + } + if (code.length() <= maxlength) { + //S is enough + code.insert(0, 1, 'S'); + code.append(1, '+'); + } else { + code = TellStick::createTPacket(code); + } + } + return controller->send(code); } Protocol* Device::retrieveProtocol() const { From 1e6767fa652b55a818df9afb815c3d959d1e6727 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 13 Apr 2012 11:22:47 +0200 Subject: [PATCH 1980/2215] Return an appropriate error code instead of true/false in tdUnregisterCallback(), closes #200 --- telldus-core/client/CallbackMainDispatcher.cpp | 6 +++--- telldus-core/client/CallbackMainDispatcher.h | 2 +- telldus-core/client/Client.cpp | 2 +- telldus-core/client/Client.h | 2 +- telldus-core/client/telldus-core.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index fb9a20f3..fbc09cbd 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -64,7 +64,7 @@ int CallbackMainDispatcher::registerCallback(CallbackStruct::CallbackType type, return id; } -bool CallbackMainDispatcher::unregisterCallback(int callbackId) { +int CallbackMainDispatcher::unregisterCallback(int callbackId) { CallbackList newEventList; { TelldusCore::MutexLocker locker(&d->mutex); @@ -83,9 +83,9 @@ bool CallbackMainDispatcher::unregisterCallback(int callbackId) { } delete (*it); newEventList.erase(it); - return true; + return TELLSTICK_SUCCESS; } - return false; + return TELLSTICK_ERROR_NOT_FOUND; } void CallbackMainDispatcher::run(){ diff --git a/telldus-core/client/CallbackMainDispatcher.h b/telldus-core/client/CallbackMainDispatcher.h index c8856895..a2d2f1c9 100644 --- a/telldus-core/client/CallbackMainDispatcher.h +++ b/telldus-core/client/CallbackMainDispatcher.h @@ -26,7 +26,7 @@ namespace TelldusCore { EventRef retrieveCallbackEvent(); int registerCallback( TelldusCore::CallbackStruct::CallbackType type, void *eventFunction, void *context ); - bool unregisterCallback( int callbackId ); + int unregisterCallback( int callbackId ); protected: void run(); diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 20e7e89f..b805bb14 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -185,7 +185,7 @@ void Client::stopThread(){ d->eventSocket.stopReadWait(); } -bool Client::unregisterCallback( int callbackId ) { +int Client::unregisterCallback( int callbackId ) { return d->callbackMainDispatcher.unregisterCallback(callbackId); } diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 2bd0c5ce..88b2b41d 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -17,7 +17,7 @@ namespace TelldusCore { int registerEvent(CallbackStruct::CallbackType type, void *eventFunction, void *context ); void stopThread(void); - bool unregisterCallback( int callbackId ); + int unregisterCallback( int callbackId ); int getSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); int getController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 7e689f3e..6ec8ddfb 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -425,7 +425,7 @@ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *con * The returned id from one of the tdRegister* functions. * * @returns - * 1 on success, or 0 on failure. + * @ref TELLSTICK_SUCCESS on success or appropriate error code on failure. * * @sa @ref sec_events_registering * @since Version 2.1.0 From deebf2045e7119c339412580f37a1e653f7d5715 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 16 Apr 2012 12:03:47 +0200 Subject: [PATCH 1981/2215] Add quit key shortcut (ctrl+q) --- telldus-gui/TelldusCenter/mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 879215a4..b0af55b4 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -89,6 +89,7 @@ void MainWindow::setupMenu() { config->setMenuRole(QAction::PreferencesRole); fileMenu->addSeparator(); QAction *quit = fileMenu->addAction(tr("&Quit"), qApp, SLOT(quit())); + quit->setShortcut(QKeySequence::Quit); quit->setMenuRole( QAction::QuitRole ); // Help From be9d0ecca556335de5bb66ea4203ffbc17cee192 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 15:56:47 +0200 Subject: [PATCH 1982/2215] Add class TellStick --- .../Plugins/Controllers/CMakeLists.txt | 2 + telldus-gui/Plugins/Controllers/tellstick.cpp | 305 ++++++++++++++++++ telldus-gui/Plugins/Controllers/tellstick.h | 56 ++++ 3 files changed, 363 insertions(+) create mode 100644 telldus-gui/Plugins/Controllers/tellstick.cpp create mode 100644 telldus-gui/Plugins/Controllers/tellstick.h diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt index 6ffd2263..440dd6c4 100644 --- a/telldus-gui/Plugins/Controllers/CMakeLists.txt +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -10,6 +10,7 @@ SET( Plugin_SRCS controller.cpp controllerlist.cpp controllersplugin.cpp + tellstick.cpp ) SET( Plugin_HDRS @@ -19,6 +20,7 @@ SET( Plugin_HDRS SET( Plugin_MOC_HDRS controller.h controllerlist.h + tellstick.h ) SET( Plugin_PATH "com.telldus.controllers" ) diff --git a/telldus-gui/Plugins/Controllers/tellstick.cpp b/telldus-gui/Plugins/Controllers/tellstick.cpp new file mode 100644 index 00000000..093ac3e1 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/tellstick.cpp @@ -0,0 +1,305 @@ +#include "tellstick.h" +#include +#include +#include +#include +#include + +#ifdef _WINDOWS +#include +#endif +#include "ftd2xx.h" + +inline void msleep( const int msec) { +#ifdef _WINDOWS + Sleep(msec); +#else + usleep(msec*1000); +#endif +} + +class TellStick::PrivateData { +public: + FT_HANDLE ftHandle; +}; + +TellStick::TellStick(int id, int type, const QString &name, QObject *parent) : + Controller(id, type, name, parent) +{ + d = new PrivateData; +} + +TellStick::~TellStick() { + delete d; +} + +void TellStick::setAvailable(bool available) { + Controller::setAvailable(available); + if (!available && upgradeStep() == 0) { + //Doing firmware upgrade + setUpgradeStep(1); + QTimer::singleShot(1000, this, SLOT(aquireTellStick())); //Allow for widget updates + } +} + +bool TellStick::isUpgradable() const { + return true; //TODO: check version +} + +void TellStick::aquireTellStick() { + char *tempSerial = new char[serial().size()+1]; +#ifdef _WINDOWS + strcpy_s(tempSerial, serial().size()+1, serial().toLocal8Bit()); +#else + strcpy(tempSerial, serial().toLocal8Bit()); + FT_SetVIDPID(0x1781, 0x0c30); //TODO: Make dynamic for TellStick Duo +#endif + FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); + delete tempSerial; + if (ftStatus != FT_OK) { + return; + } + //open = true; + + //if (this->field("pid").toInt() == 0x0C31) { + // FT_SetBaudRate(ftHandle, 115200); + //} else { + FT_SetBaudRate(d->ftHandle, 9600); + //} + FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); + FT_SetTimeouts(d->ftHandle,1000,0); + + setUpgradeStep(2); + QTimer::singleShot(0, this, SLOT(enterBootloader())); +} + +void TellStick::enterBootloader() { + FT_Purge(d->ftHandle, FT_PURGE_RX | FT_PURGE_TX); + + FT_STATUS ftStatus = FT_SetBitMode(d->ftHandle, 0xff, 0x20); + for (int i = 0; i < 100; ++i) { + msleep(1); + QApplication::processEvents(); + } + ftStatus = FT_SetBitMode(d->ftHandle, 0xf0, 0x20); + + char buf = 0; + while(1) { //TODO: Make it possible to bail! + QApplication::processEvents(); + buf = getCh(); + if (buf == 'g') { + break; + } + } + send('r'); + setUpgradeStep(3); + QTimer::singleShot(1000, this, SLOT(downloadFirmware())); +} + +void TellStick::downloadFirmware() { + QString filename = "TellStick"; + int bootloaderStart = 0x3A00; + /*if (this->field("pid").toInt() == 0x0C31) { + filename = "TellStickDuo"; + bootloaderStart = 0x7A00; + }*/ + QString path; + //if (QApplication::arguments().count() > 1) { + // path = QApplication::arguments().at(1); + //} else { + path = QString(":/firmware/%1.hex").arg(filename); + //} + + QByteArray data = readHex(path, bootloaderStart); + int bytesLeft = 0, i = 0; + char byte; + + while (i < data.length()) { + QApplication::processEvents(); + byte = getCh(); + QApplication::processEvents(); + if (byte == 'b') { + bytesLeft = data.length() - i; + if (bytesLeft > 0xFF) { + bytesLeft = 0xFF; + } + send(bytesLeft); + } else if (byte == 'd') { + send(data[i]); + --bytesLeft; + ++i; + this->setUpgradeProgress( (qreal)i/(qreal)data.length()*100.0 ); + } + } + setUpgradeStep(4); + QTimer::singleShot(0, this, SLOT(rebootTellStick())); +} + +void TellStick::rebootTellStick() { + FT_STATUS ftStatus = FT_SetBitMode(d->ftHandle, 0xff, 0x20); + for (int i = 0; i < 100; ++i) { + msleep(1); + QApplication::processEvents(); + } + ftStatus = FT_SetBitMode(d->ftHandle, 0xf0, 0x20); + FT_Close(d->ftHandle); + QApplication::processEvents(); + setUpgradeStep(5); + QTimer::singleShot(0, this, SLOT(connectTellStick())); +} + +void TellStick::connectTellStick() { + tdConnectTellStickController(0x1781, 0x0C30, this->serial().toUtf8()); + setUpgradeStep(-1); + emit upgradableChanged(); + emit upgradeDone(); +} + +char TellStick::getCh() { + char buf = 0; + DWORD dwBytesRead = 0; + FT_Read(d->ftHandle, &buf, sizeof(buf), &dwBytesRead); + return buf; +} + +void TellStick::send(uchar ch) { + DWORD bytesWritten; + FT_Write(d->ftHandle, &ch, sizeof(ch), &bytesWritten); +} + +QByteArray TellStick::readHex(const QString &filename, int maxAddress) { + QByteArray data; + + QFile file(filename); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + return ""; + } + while( !file.atEnd() ) { + QByteArray fileLine = file.readLine(); + + if (fileLine[0] != ':' || fileLine.length() < 11) { + // skip line if not hex line entry,or not minimum length ":BBAAAATTCC" + continue; + } + + int byteCount = parseHex(fileLine, 1, 2); + int startAddress = parseHex(fileLine, 3, 4); + int recordType = parseHex(fileLine, 7, 2); + + if (recordType == 1) { + //End of file, break + break; + } + if (recordType == 2) { + //Not implemented yet + } else if (recordType == 4) { + //Extended Linear Address Record not supported + break; + } else if (recordType == 0) { //Data record + if (fileLine.length() < (11+ (2*byteCount))) { + // skip if line isn't long enough for bytecount. + continue; + } + //Protect us from overwriting the bootloader + if (startAddress >= maxAddress) { + continue; + } + //Pad with empty data when needed + if ((startAddress > data.size())) { + while (startAddress > data.size()) { + data.append((char)0xFF); + } + } + + for (int lineByte = 0; lineByte < byteCount; lineByte++) { + unsigned char hex = (unsigned char)parseHex(fileLine, 9 + (2 * lineByte), 2); + data.append(hex); + } + } + } + for (int i = 0; i < 64; ++i) { //At least 64-bytes extra so the last block will be written to the memory + data.append((char)0xff); + } + return data; +} + +int TellStick::parseHex(const QByteArray &characters, int start, int length) { + int integer = 0; + + for (int i = 0; i < length; i++) { + integer *= 16; + switch(characters[start + i]) { + case '1': + integer += 1; + break; + + case '2': + integer += 2; + break; + + case '3': + integer += 3; + break; + + case '4': + integer += 4; + break; + + case '5': + integer += 5; + break; + + case '6': + integer += 6; + break; + + case '7': + integer += 7; + break; + + case '8': + integer += 8; + break; + + case '9': + integer += 9; + break; + + case 'A': + case 'a': + integer += 10; + break; + + case 'B': + case 'b': + integer += 11; + break; + + case 'C': + case 'c': + integer += 12; + break; + + case 'D': + case 'd': + integer += 13; + break; + + case 'E': + case 'e': + integer += 14; + break; + + case 'F': + case 'f': + integer += 15; + break; + } + } + return integer; +} + +void TellStick::upgrade() { + setUpgradeStep(0); + tdDisconnectTellStickController(0x1781, 0x0C30, serial().toUtf8()); //TODO: Make dynamic for TellStick Duo +} diff --git a/telldus-gui/Plugins/Controllers/tellstick.h b/telldus-gui/Plugins/Controllers/tellstick.h new file mode 100644 index 00000000..ee0af52e --- /dev/null +++ b/telldus-gui/Plugins/Controllers/tellstick.h @@ -0,0 +1,56 @@ +#ifndef TELLSTICK_H +#define TELLSTICK_H + +#include "controller.h" + +class TellStick : public Controller +{ + Q_OBJECT + +public: + explicit TellStick(int id = 0, int type = 1, const QString &name = "", QObject *parent = 0); + virtual ~TellStick(); + + //bool available() const; + virtual void setAvailable(bool available); + + /*QString firmware() const; + void setFirmware(const QString &version); + + int id() const; + + QString name() const; + void setName(const QString &name); + + void save(); + + QString serial() const; + + Q_INVOKABLE void tryRemove(); + + int type() const;*/ + + Q_INVOKABLE virtual void upgrade(); + +protected: + virtual bool isUpgradable() const; + +private slots: + void aquireTellStick(); + void enterBootloader(); + void downloadFirmware(); + void rebootTellStick(); + void connectTellStick(); + +private: + char getCh(); + void send(uchar ch); + + static QByteArray readHex(const QString &filename, int maxAddress); + static int parseHex( const QByteArray &characters, int start, int length ); + + class PrivateData; + PrivateData *d; +}; + +#endif // TELLSTICK_H From 6bc548af2bfaa14d527b10de7b778fd7e7a818fe Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 15:58:40 +0200 Subject: [PATCH 1983/2215] Add firmware to the products as resource --- .../Plugins/Controllers/CMakeLists.txt | 4 + .../Plugins/Controllers/controllers.qrc | 7 + .../Controllers/firmware/TellStick.hex | 114 + .../Controllers/firmware/TellStickDuo.hex | 789 +++ .../Controllers/firmware/TellStickNet.hex | 4476 +++++++++++++++++ 5 files changed, 5390 insertions(+) create mode 100644 telldus-gui/Plugins/Controllers/controllers.qrc create mode 100644 telldus-gui/Plugins/Controllers/firmware/TellStick.hex create mode 100644 telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex create mode 100644 telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt index 440dd6c4..77929dd0 100644 --- a/telldus-gui/Plugins/Controllers/CMakeLists.txt +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -23,6 +23,10 @@ SET( Plugin_MOC_HDRS tellstick.h ) +SET( Plugin_RESOURCES + controllers.qrc +) + SET( Plugin_PATH "com.telldus.controllers" ) SET( Plugin_EXTRA diff --git a/telldus-gui/Plugins/Controllers/controllers.qrc b/telldus-gui/Plugins/Controllers/controllers.qrc new file mode 100644 index 00000000..15095557 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/controllers.qrc @@ -0,0 +1,7 @@ + + + firmware/TellStick.hex + firmware/TellStickDuo.hex + firmware/TellStickNet.hex + + diff --git a/telldus-gui/Plugins/Controllers/firmware/TellStick.hex b/telldus-gui/Plugins/Controllers/firmware/TellStick.hex new file mode 100644 index 00000000..f0802c55 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/firmware/TellStick.hex @@ -0,0 +1,114 @@ +:100000001728FF3FFF3FFF3FFF00030E83018316CA +:10001000AA000408A9000A08AB008A012B088A007C +:10002000290884002A0E8300FF0E7F0E09000D3080 +:1000300003138316AC000A30AD002B30AE005630EF +:10004000AF00B0010D30B1000A30B200B30154303E +:10005000B4005330B5003030B6003030B700313026 +:10006000B800B9010B30BC000A30BD00BE017223DC +:100070008501860187018312850186018701871426 +:1000800035237823AC308316C0001C233630C800DB +:100090006A23B1308316C0001C2303138316031395 +:1000A00083166123700803194D2845237008A800A2 +:1000B00067289028BE144D289028BC30C800A6227E +:1000C0004D28BD30C800A6224D2890284D2828086C +:1000D000423A031959282808443A03195A2828088B +:1000E000483A03195C2828084D3A03195C28280867 +:1000F0004E3A03195C282808503A03195D2828084D +:10010000523A031961282808533A03196528280828 +:10011000543A031965282808563A031965286628B1 +:10012000F822700803194D282B30C8006A23831663 +:100130002808C8006A2383162808533A031DCC28D0 +:10014000BA01BB0180303B06F00080307002031D15 +:10015000AB283D083A020318CB28831287102D22C2 +:1001600087148316BF013C083F020318C7280330D9 +:10017000FB00FF30FA00FB0BBE28C128FA0BBE289B +:10018000BB289630FA00FA0BC328BF0AB328BA0A74 +:100190000319BB0AA22815292808543A031DFC2874 +:1001A000BA01BB0180303B06F00080307002031DB5 +:1001B000DB283D083A020318FB28831287102C2104 +:1001C00087148316BF013C083F020318F728033049 +:1001D000FB00FF30FA00FB0BEE28F128FA0BEE28AB +:1001E000EB289630FA00FA0BF328BF0AE328BA0A84 +:1001F0000319BB0AD22815292808563A031D0429D9 +:100200003630C8006A23152983162808483A031D8A +:100210000D293330C8006A231529831628084D3A62 +:10022000031D1529B430C0001C23031383160313C8 +:100230008316BE1C1E292030C0001C23BE100B30AC +:10024000BC000A30BD000D30C8006A230A30831696 +:10025000C8006A234D282B2903138316C4012030BC +:10026000C000C101043041020318B42940088400D1 +:100270000008F2007208013A031D53290130F4000E +:100280004108F000740803194929F00D7010FF3F70 +:100290004329A030F00770088400FF308000FF3051 +:1002A000840A8000B1290130F4004108F00074088C +:1002B00003195E29F00D7010FF3F58297008A03F08 +:1002C000F200400884000008F00072088400700802 +:1002D0008000840A80010130F4004108F0007408B5 +:1002E00003197629F00D7010FF3F70297008A03FA8 +:1002F000C700470884000008F000840A0008F100E5 +:100300000A30F4000030F500CD228316470884003F +:10031000700880007108840A80000130F4004108F0 +:10032000F000740803199829F00D7010FF3F92290E +:100330007008A03FF200720884000008F000840AF0 +:100340000008F1007008FF3CF0007108031C013F39 +:10035000FF3CF10072088400700880007108840A74 +:100360008000C00AC10A3229400884000008C20087 +:10037000C00A831210100C1483164208003C0318A4 +:10038000282A400884000008C300C101043041024B +:100390000318262AC0304305F4000630F200740822 +:1003A000F00072080319D829F00CF013FF3FD2298E +:1003B0000130F40074080319E129F00D7010FF3FBB +:1003C000DB297008A03F84000008F200840A0008BE +:1003D000F3007208C5007308C600C30D4310C30DB7 +:1003E00043107308FF3A031DF729FF307206031DFF +:1003F000FB29C4091E2A83120C1CFB2910100C10A7 +:10040000003083164505F4004608FF39F5007508ED +:10041000F000F101700883128F00831645088312E3 +:100420008E0083164409F0007008C4000030701874 +:100430002030831206062039860610148316C20364 +:1004400001304202031C262AC10AC629C00ABC295F +:1004500083120C1C282A8612080003138316C3017A +:10046000831210100C1420308316C200420884003E +:100470000008F2007208003A0319A12A4208840019 +:100480000008F2007208013A031D482AC3099E2A97 +:10049000420884000008C000C1010030C1004008CB +:1004A000F2004108F300F20DF30D7210F20DF30D9E +:1004B0007210F20DF30D72107208C0007308C100C3 +:1004C000420884000008F0007008F007F1010318EA +:1004D000F10A7208F00773080318013FF10770086A +:1004E000C0007108C1007008FF3CC0007108031C07 +:1004F000013FFF3CC10083120C1C7B2A10100C1022 +:10050000003083164005F4004108FF39F5007508F6 +:10051000F000F101700883128F00831640088312E7 +:100520008E0083164309F0007008C3000030701875 +:100530002030831206062039860610148316C20A5C +:10054000362A83120C1CA12A861208000313831674 +:10055000C901831210100C108F018E0110140313A7 +:1005600083128C1AC32A0C1CBB2A8316C90A831255 +:100570008F018E010C10053083164902031CC22A1C +:10058000F0010800AF2A03138316532348088400A0 +:10059000700880000130F000080003138312FB0193 +:1005A000FA01F9018030F800F10CF00C031CE12A8B +:1005B0007408F90775080318750FFA070318FB0A82 +:1005C0000310F01FE92A7408FA0775080318750F5D +:1005D000FB07FB0CFA0CF90CF80C031CD42A7B0863 +:1005E000F3007A08F2007908F1007808F0000800BA +:1005F00003138316C0012030C1005030400203189D +:100600001A2B4108C800A6227008031D092BF0010F +:100610000800410884000008F10071082B3A031D0E +:10062000172B4108840080010130F0000800C10A46 +:10063000C00AFD2AF001080003138316C101C2019C +:100640004108400784000008F1007108003A0319CE +:10065000342B4108400784000008C8006A23831631 +:10066000C10A0319C20A202B08006730031383163E +:100670009900181398161812181583129817181342 +:1006800018168316861406110800031383121A081D +:100690008316C0008312981C4F2B1812181683164D +:1006A0004008F0000800031383121A088316CA00DA +:1006B0008312981C5D2B1812181683164A08F00036 +:1006C00008000030031383128C1A0130F100710806 +:1006D000F000080003138316981C6A2B4808831245 +:1006E00099000800031383160F178F160F160800C2 +:1006F00003138312901210160800FF3FFF3FFF3FC5 +:04400E00F42FFFFF8D +:00000001FF diff --git a/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex b/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex new file mode 100644 index 00000000..185fc536 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex @@ -0,0 +1,789 @@ +:0400000014EF00F009 +:10000800FACF8CF4FBCF8DF4E9CF8EF483ED14F0A6 +:10001800D8CF7AF4E8CF7BF4E0CF7CF454EF13F038 +:1000280004EE24F07C0EF66E000EF76E10EE0DF066 +:1000380035EC00F000EE00F014EE24F02EEC00F0A9 +:1000480005EE00F011EE00F02EEC00F0000EF86E58 +:10005800D6EF16F0EE6AE550E150FCE1E250FAE125 +:1000680012000900F5CFEEFFE550E150FAE1E25049 +:10007800F8E11200000100000100FFFFF3FF80FF1C +:10008800FF00000E040104013C6F000E04013D6FE7 +:10009800000E04013E6F000E04013F6F0401370E8D +:1000A800040104015D6F0401040E04015E6F040184 +:1000B800350E040104015B6F0401040E04015C6F3A +:1000C8002FEC16F00401370E04010401566F0401E9 +:1000D800040E0401576F0401350E04010401546F26 +:1000E8000401040E0401556FE1EC10F0010E040147 +:1000F8000401386F000E0401396F000E04013A6FD5 +:10010800000E04013B6F000E04010401406F000E55 +:100118000401416F040104014151800A800F200E3F +:10012800D8B4405DD8A001D001D001D06FD004016F +:10013800370E04010401566F0401040E0401576FC1 +:100148000401350E04010401546F0401040E040176 +:10015800556FE1EC10F004010401426F0401370E01 +:1001680004010401566F0401040E0401576F0401D1 +:10017800350E04010401546F0401040E0401556F87 +:10018800E1EC10F004010401436F1BD025D00401F9 +:1001980004013851040104013C13040104013951DC +:1001A800040104013D13040104013A51040104014E +:1001B8003E13040104013B51040104013F130CD018 +:1001C80029D143C455F442C454F4B3EC16F0000AE0 +:1001D800DDE0010ADCE0F4D70401D89004013837E7 +:1001E8000401393704013A3704013B37040104019B +:1001F800404B412B040104014151800A800F200E1D +:10020800D8B4405DD8A001D001D091D704013CC436 +:1002180044F404013DC445F404013EC446F4040119 +:100228003FC447F40401441F451F461F471F110ED2 +:1002380006D0D89004014733463345334433E82E7B +:10024800F8D7FF0E040144150401486F000E04019D +:1002580045150401496F000E0401461504014A6F53 +:10026800000E0401471504014B6F04013CC44CF413 +:1002780004013DC44DF404013EC44EF404013FC4DE +:100288004FF4190E06D0D89004014F334E334D3336 +:100298004C33E82EF8D7FF0E04014C150401506FBB +:1002A800000E04014D150401516F000E04014E1596 +:1002B8000401526F000E04014F150401536F04012D +:1002C8004B51040153190EE104014A51040152191A +:1002D80009E1040149510401511904E1040148519B +:1002E80004015019D8B401D001D001D093D0FF0E29 +:1002F80004013CC444F404013DC445F404013EC473 +:1003080046F404013FC447F40401441F451F461F37 +:10031800471F040144150401486F000E04014515E8 +:100328000401496F000E0401461504014A6F000ECE +:100338000401471504014B6FFF0E04013CC44CF443 +:1003480004013DC44DF404013EC44EF404013FC40D +:100358004FF44DC44CF44EC44DF44FC44EF4040154 +:100368004F6B04014C150401506F000E04014D152C +:100378000401516F000E04014E150401526F000E66 +:1003880004014F150401536F04014B510401531923 +:100398000EE104014A510401521909E104014951CD +:1003A8000401511904E10401485104015019D8B459 +:1003B80001D001D001D02ED0C9EC17F0F10E040104 +:1003C8000401566F790E0401576F8C0E0401040165 +:1003D800546F790E0401556F9AEC17F03CC456F42B +:1003E8003DC457F43EC458F43FC459F4E30E040125 +:1003F8000401546F790E0401556F02EC0EF00401EC +:10040800446F020E04010401546F04014451BBEC13 +:1004180017F000D012000401630E040104016A6F92 +:100428000401040E04016B6F81D1040104016951B8 +:10043800250AD8B401D001D005D069C472F438ECCB +:1004480017F074D10401706F000E04010401686F85 +:10045800040170514BD07DD104010401688F61D033 +:1004680004016AC4E9FF04016BC4EAFF0401020E37 +:1004780004016A27000E04016B230401EECF6CF41B +:100488000401EDCF6DF4040104016D516C11D8A481 +:1004980001D001D007D0A60E040104016C6F790EBB +:1004A80004016D6F10D004016CC4F6FF04016DC423 +:1004B800F7FF08000401F5CF72F438EC17F00401D7 +:1004C80004016C4B6D2B04016CC4F6FF04016DC470 +:1004D800F7FF0800F5500009D8A401D001D0E3D7F0 +:1004E80025D1C00E0401040168131BD0040161C4A6 +:1004F800F6FF040162C4F7FF04010401614B622B9B +:1005080008000401F5CF69F404016951000AA3E069 +:10051800580AA2E02B0AA4E0060AE3E00D0A9CE0D0 +:10052800DFD704016AC4E9FF04016BC4EAFF0401D0 +:10053800020E04016A27000E04016B230401EECFAA +:100548006CF40401EDCF6DF478D00401706F010EE6 +:1005580004010401696F0401705104010401695127 +:10056800050AD8A401D001D001D02AD00401040181 +:100578006951020DFC0EF324F66EF76A780EF72225 +:100588000900F5CF70F40900F5CF71F4040170513A +:10059800040104016C5D04017151040104016D59E9 +:1005A800D8B001D001D001D00BD004010401692BCF +:1005B800040104016951050AD8A401D001D0D6D795 +:1005C80045D00401706F010E04010401696F040134 +:1005D8007051040104016951040AD8A401D001D062 +:1005E80001D0EED7040104016951020D060EF3246F +:1005F800F66EF76A790EF7220900F5CF70F4090054 +:10060800F5CF71F404017051040104016C5D04011B +:100618007151040104016D59D8B001D001D001D045 +:10062800CFD704010401692B040104016951040AAC +:10063800D8A401D001D0D6D709D00401040168514B +:10064800C00B800ABEE0400A80E000D069C467F4AD +:1006580064D056D0040104016751020DFC0EF32446 +:10066800F66EF76A780EF72209000401F5CF74F4E4 +:100678000A000401F5CF75F46CC472F46DC473F408 +:1006880043EC11F072C472F473C473F40A0E0401DB +:100698000401746F000E0401756FA2EC13F00401DD +:1006A80004017251300F04010401696F32D0040152 +:1006B80004016751020D060EF324F66EF76A790EEF +:1006C800F72209000401F5CF74F40A000401F5CFFC +:1006D80075F46CC472F46DC473F443EC11F00F0E2E +:1006E800040104017217390E040104017225F66E23 +:1006F800F76A790EF72208000401F5CF69F409D0EA +:10070800040104016851C00B800AD1E0400AA2E04C +:1007180000D069C472F438EC17F0040104016707CB +:1007280004016729D8A401D001D093D7040161C47A +:10073800F6FF040162C4F7FF04010401614B622B58 +:1007480008000401F5CF69F40401696701D001D0FC +:100758006CD600D0120004014B6F000E0401040196 +:10076800386F04014B51000E040104013D6F000E67 +:1007780004013E6F000E04013F6F000E0401406F3C +:10078800010E04010401416F000E0401426F000EC6 +:100798000401436F000E0401446F0401370E040185 +:1007A80004015D6F0401040E04015E6F0401350E3F +:1007B800040104015B6F0401040E04015C6F2FEC5B +:1007C80016F00401370E04010401566F0401040EEB +:1007D8000401576F0401350E04010401546F04012C +:1007E800040E0401556FE1EC10F035C43BF436C437 +:1007F8003CF40401040137C439F4040104013A6BE0 +:10080800000E04010401456F000E0401466F040147 +:1008180004014651800A800F200ED8B4455DD8A047 +:1008280001D001D001D059D00401370E04010401D0 +:100838004F6F0401040E0401506F0401350E0401CA +:1008480004014D6F0401040E04014E6FEEEC13F029 +:1008580004010401496F040104014951020AD8A4A2 +:1008680001D001D001D0EDD0040104014951D8B420 +:1008780001D001D018D00401040141510401040140 +:100888003D13040104014251040104013E13040113 +:1008980004014351040104013F13040104014451BC +:1008A8000401040140130401D890040141370401F4 +:1008B8004237040143370401443704010401454B1E +:1008C800462B040104014651800A800F200ED8B43B +:1008D800455DD8A001D001D0A7D7000E04010401BE +:1008E800476F000E0401486F040104014851800A53 +:1008F800800F040ED8B4475DD8A001D001D001D034 +:100908004AD00401370E040104014F6F0401040E9C +:100918000401506F0401350E040104014D6F0401F8 +:10092800040E04014E6FEEEC13F0040104014A6F4B +:10093800040104014A51020AD8A401D001D001D00F +:1009480080D0040104014A51D8B401D001D013D099 +:1009580047C44BF4010E04014C6F04014B2B03D028 +:10096800D89004014C3704014B2FFAD704014C519D +:1009780004010401381304010401474B482B040106 +:1009880004014851800A800F040ED8B4475DD8A0EE +:1009980001D001D0B6D70401040138510C0AD8B4EB +:1009A80001D001D001D04DD0C9EC17F0B40E04012C +:1009B8000401566F790E0401576FCE0E040104012D +:1009C800546F790E0401556F9AEC17F07A0E0401F2 +:1009D8000401566F790E0401576F8C0E040104014F +:1009E800546F790E0401556F9AEC17F0250E040127 +:1009F8000401566F790E0401576FC80E04010401F3 +:100A0800546F790E0401556F9AEC17F03DC456F4F3 +:100A18003EC457F43FC458F440C459F4E30E0401EB +:100A28000401546F790E0401556F02EC0EF00401B5 +:100A38004B6F010E04010401546F04014B51BBECD0 +:100A480017F01200040104013551D8B401D001D0C7 +:100A580005D0030E04010401362704D0030E040157 +:100A68000401365F2AD10B0E04010401366501D05A +:100A780001D009D0170E04010401366101D001D05C +:100A880002D0012A25D1030E04010401366501D0E4 +:100A980001D01CD00D0E04010401366101D001D033 +:100AA80015D0190E016401D001D00AD00401376FA6 +:100AB800010E086E04013751000E196E000E1A6EF1 +:100AC8000401376F000E016E0401375101D136C49D +:100AD8003AF435C439F439EC14F039C41BF43AC487 +:100AE8001CF4040104011C29FE0ED8B41B19D8A457 +:100AF80001D001D003D087EC17F0EAD0040104013B +:100B08001B29D8B41C29D8A401D001D001D0E0D029 +:100B18001A501910D8A401D001D006D0040104013C +:100B28001B511A6E196A43D0040104011B51191292 +:100B3800040104011C511A1211D00401376F060E6A +:100B4800026E0401375127D00401376F080E026E78 +:100B58000401375120D087EC17F0BAD019C037F408 +:100B68001AC038F40FD0040137514D0AEDE0F3D71D +:100B7800040137512D0AE8E0EED7040137514C0A39 +:100B8800DCE0E9D7040138510A0AEDE0100AF0E088 +:100B9800F00AF3E0E0D70401376F020E086E040193 +:100BA80037510401376F000E016E0401375190D0A0 +:100BB80036C43AF435C439F439EC14F039C41BF4AA +:100BC8003AC41CF4040104011C29FE0ED8B41B19F4 +:100BD800D8A401D001D003D087EC17F079D0040154 +:100BE80004011B29D8B41C29D8A401D001D001D0F4 +:100BF8006FD00F0E0124E96EEA6A000EEA220401A2 +:100C08001BC4EFFF012A0206026601D001D05ED79D +:100C180087EC17F0C9EC17F0B40E04010401566F05 +:100C2800790E0401576FCE0E04010401546F790E3A +:100C38000401556F9AEC17F0BB0E04010401566FBE +:100C4800790E0401576F8C0E04010401546F790E5C +:100C58000401556F9AEC17F0040119C056F4040109 +:100C68001AC057F404010401586B0401596BC80EEB +:100C780004010401546F790E0401556F02EC0EF063 +:100C880001C049F40F0E04010401476F000E04016E +:100C9800486FE30E04010401456F790E0401466FA5 +:100CA80033EC0FF00401376F010E04010401546F97 +:100CB80004013751BBEC17F00BD00850000A01E1D2 +:100CC800D2D6010A01E103D7030A01E171D700D0A6 +:100CD8001200000E04010401386F000E0401396F80 +:100CE800000E04013A6F000E04013B6F010E04016F +:100CF80004013C6F000E04013D6F000E04013E6FBD +:100D0800000E04013F6F0401370E040104015D6FFA +:100D18000401040E04015E6F0401350E0401040190 +:100D28005B6F0401040E04015C6F2FEC16F00401E4 +:100D3800370E04010401566F0401040E0401576FB5 +:100D48000401350E04010401546F0401040E04016A +:100D5800556FE1EC10F0000E04010401406F000E25 +:100D68000401416F040104014151800A800F200EE3 +:100D7800D8B4405DD8A001D001D001D0A1D00401E1 +:100D8800370E04010401566F0401040E0401576F65 +:100D98000401350E04010401546F0401040E04011A +:100DA800556FE1EC10F004010401426F0401370EA5 +:100DB80004010401566F0401040E0401576F040175 +:100DC800350E04010401546F0401040E0401556F2B +:100DD800E1EC10F004010401436F0401370E040133 +:100DE8000401566F0401040E0401576F0401350E07 +:100DF80004010401546F0401040E0401556FE1EC71 +:100E080010F004010401446F0401370E04010401C9 +:100E1800566F0401040E0401576F0401350E0401D6 +:100E28000401546F0401040E0401556FE1EC10F045 +:100E380004010401456F1BD029D0040104013C5171 +:100E4800040104013813040104013D5104010401A3 +:100E58003913040104013E51040104013A13040149 +:100E680004013F51040104013B1310D067D045C46D +:100E78004AF444C449F443C448F442C447F40BEC6C +:100E880015F0000AD9E0010AD8E0F0D70401D8909B +:100E980004013C3704013D3704013E3704013F3764 +:100EA80004010401404B412B040104014151800A13 +:100EB800800F200ED8B4405DD8A001D001D05FD7F4 +:100EC800C9EC17F09E0E04010401566F790E040157 +:100ED800576F8C0E04010401546F790E0401556F8D +:100EE8009AEC17F0570E04010401566F790E0401AD +:100EF800576FC80E04010401546F790E0401556F31 +:100F08009AEC17F038C456F439C457F43AC458F474 +:100F18003BC459F4E30E04010401546F790E040133 +:100F2800556F02EC0EF00401466F020E0401040135 +:100F3800546F04014651BBEC17F000D012000401B5 +:100F4800346F000E04010401316F04013451A0D044 +:100F58002EC45DF417C05BF418C05CF48BEC16F07B +:100F6800D8A001D001D02AD0960E0E6401D001D0AD +:100F780006D017C02CF418C02DF42EC42FF40E5030 +:100F8800D8B401D001D00CD00EC036F40401346FAF +:100F9800000E04010401356F0401345126EC05F0FC +:100FA800042A0401346F000E0E6E0401345104014A +:100FB800346F000E056E0401345122D00E6601D044 +:100FC80001D006D017C02AF418C02BF42EC41FF481 +:100FD8000450D8B401D001D00CD004C036F40401B8 +:100FE800346F010E04010401356F0401345126ECFD +:100FF80005F00E2A0401346F000E046E040134510A +:101008000401D8902E33040104012E6701D001D0C9 +:1010180015D00401346F800E040104012E6F040101 +:101028003451174A182A1850020A1710D8A401D0A8 +:1010380001D004D0000E176E000E186E185004016F +:1010480004012D1904E11750040104012C19D8A436 +:1010580001D001D00ED0040104012E510401040175 +:101068002F6301D001D005D0040104012C690401CB +:101078002D690E50960AD8A401D001D009D00401D8 +:10108800346F010E04010401316F040134510DD095 +:10109800040104012151181804E10401040120513C +:1010A8001718D8A401D001D053D70401040131671F +:1010B80001D001D001D078D00550D8B401D001D0EA +:1010C80001D072D02AC437F42BC438F42CC435F4B8 +:1010D8002DC436F4A9EC12F035C432F436C433F416 +:1010E8000401040133BF01D001D00DD00401040173 +:1010F8003351800A800F320ED8B4325DD8B001D097 +:1011080001D001D051D0040104013351800A800F6D +:101118009E0ED8B4325DD8A001D001D00CD0040105 +:1011280004013351800A800FA30ED8B4325DD8A0D1 +:1011380001D001D000D01FC437F42AC435F42BC421 +:1011480036F46DEC06F01FC437F42AC435F42BC40A +:1011580036F409EC0AF01FC437F42AC435F42BC45A +:1011680036F43EEC0CF01FC437F42AC435F42BC413 +:1011780036F42CEC0BF01FC437F42AC435F42BC416 +:1011880036F4AFEC03F01FC437F42AC435F42BC48B +:1011980036F445EC00F087EC17F00401346F010ECB +:1011A800056E0401345100D012000401356F0B0E96 +:1011B80004010401326F040135510401356F0A0E30 +:1011C80004010401336F04013551010E04010401C7 +:1011D8003B6F000E04013C6FFD0E04010401396FE2 +:1011E800790E04013A6F1B0E04010401376F000EDB +:1011F8000401386FFFEC12F0040138513711D8A4FC +:1012080001D001D011D0050E04010401636F000E56 +:101218000401646F850E04010401616F790E0401F5 +:10122800626F0FEC02F0F0D0010E040104013B6F75 +:10123800000E04013C6FFB0E04010401396F790EA6 +:1012480004013A6F1B0E04010401376F000E0401FC +:10125800386FFFEC12F0040138513711D8A401D0CF +:1012680001D00AD0D40E04010401616F790E040183 +:10127800626F0FEC02F0C8D00401356F000E040154 +:101288000401346F040135510401356F000E040167 +:101298000401316F04013551B0D098D0040134C431 +:1012A80035F40401366B010E04013527000E362390 +:1012B8001B0E04013525E96E000E04013621EA6E85 +:1012C800EF5004010401326F04010401342B92D061 +:1012D800040134C435F40401366B010E04013527CA +:1012E800000E36231B0E04013525E96E000E04019D +:1012F8003621EA6EEF5004010401336F0401040142 +:10130800342B78D033C43AF432C439F4010E0401D2 +:101318000401342504010401376F0401386B000E01 +:101328000401382351EC12F00401356F010E040159 +:101338000401316F04013551D90E04010401616FB4 +:10134800790E0401626F0FEC02F054D033C43AF402 +:1013580032C439F4010E04010401342504010401E6 +:10136800376F0401386B000E04013823F9EC11F0D3 +:101378000401356F010E04010401316F0401355178 +:10138800DE0E04010401616F790E0401626F0FEC37 +:1013980002F030D01B0E040104013425E96EEA6A1C +:1013A800000EEA22EF500401356F040135510401A3 +:1013B8000401636F0401646B0E0E04010401616F84 +:1013C800790E0401626F0FEC02F01ED01B0E0401AF +:1013D80004013425E96EEA6A000EEA22EF50500A49 +:1013E80001E15CD7020A01E173D7010A8BE0070A21 +:1013F800ADE0D0D704010401342B040104013151BC +:10140800D8B401D001D049D71200000E040104015C +:101418003C6F000E04013D6F000E04013E6F000E8C +:1014280004013F6F010E04010401386F000E04012E +:10143800396F000E04013A6F000E04013B6F04017E +:10144800370E040104015D6F0401040E04015E6F90 +:101458000401350E040104015B6F0401040E04014C +:101468005C6F2FEC16F00401370E04010401566F6F +:101478000401040E0401576F0401350E0401040130 +:10148800546F0401040E0401556FE1EC10F0000ED6 +:1014980004010401406F000E0401416F04010401BE +:1014A8004151800A800F0C0ED8B4405DD8A001D0FD +:1014B80001D001D08ED00401370E04010401566F0B +:1014C8000401040E0401576F0401350E04010401E0 +:1014D800546F0401040E0401556FE1EC10F004018F +:1014E8000401426F0401370E04010401566F040120 +:1014F800040E0401576F0401350E04010401546FF2 +:101508000401040E0401556FE1EC10F0040104011C +:10151800436F0401370E04010401566F0401040EE1 +:101528000401576F0401350E04010401546F0401CE +:10153800040E0401556FE1EC10F004010401446F3E +:101548000401370E04010401566F0401040E04015E +:10155800576F0401350E04010401546F0401040E91 +:101568000401556FE1EC10F004010401456F04011A +:10157800D89004013C3704013D3704013E3704018B +:101588003F3706D016D0040104013C8112D05FD049 +:1015980045C44AF444C449F443C448F442C447F433 +:1015A800CCEC14F0000AEEE0010AEDE0030AEFE0EB +:1015B80000D004010401404B412B040104014151B6 +:1015C800800A800F0C0ED8B4405DD8A001D001D09D +:1015D80072D7C9EC17F09E0E04010401566F790EFC +:1015E8000401576F8C0E04010401546F790E040135 +:1015F800556F9AEC17F0640E04010401566F790ECA +:101608000401576FC80E04010401546F790E0401D8 +:10161800556F9AEC17F03CC456F43DC457F43EC4D9 +:1016280058F43FC459F4E30E04010401546F790ED1 +:101638000401556F02EC0EF00401466F020E04011E +:101648000401546F04014651BBEC17F000D012009E +:10165800000E04010401386F000E0401396F000EFA +:1016680004013A6F000E04013B6F010E04010401EE +:101678003C6F000E04013D6F000E04013E6F000E2A +:1016880004013F6F0401370E040104015D6F04017A +:10169800040E04015E6F0401350E040104015B6F42 +:1016A8000401040E04015C6F2FEC16F0000E040117 +:1016B8000401406F000E0401416F0401040141510F +:1016C800800A800F180ED8B4405DD8A001D001D090 +:1016D80001D0A1D00401370E04010401566F0401A2 +:1016E800040E0401576F0401350E04010401546F00 +:1016F8000401040E0401556FE1EC10F0040104012B +:10170800426F0401370E04010401566F0401040EF0 +:101718000401576F0401350E04010401546F0401DC +:10172800040E0401556FE1EC10F004010401436F4D +:101738000401370E04010401566F0401040E04016C +:10174800576F0401350E04010401546F0401040E9F +:101758000401556FE1EC10F004010401446F040129 +:10176800370E04010401566F0401040E0401576F7B +:101778000401350E04010401546F0401040E040130 +:10178800556FE1EC10F004010401456F1BD029D01E +:10179800040104013C51040104013813040104014B +:1017A8003D51040104013913040104013E510401AF +:1017B80004013A13040104013F51040104013B13DD +:1017C80010D057D045C44AF444C449F443C448F43B +:1017D80042C447F44AEC15F0000AD9E0010AD8E0FF +:1017E800F0D70401D89004013C3704013D370401C7 +:1017F8003E3704013F3704010401404B412B0401EB +:1018080004014151800A800F180ED8B4405DD8A059 +:1018180001D001D05FD7C9EC17F04A0E04010401CA +:10182800566F790E0401576F8C0E04010401546F32 +:10183800790E0401556F9AEC17F038C456F439C480 +:1018480057F43AC458F43BC459F4E30E04010401B4 +:10185800546F790E0401556F02EC0EF00401466FC7 +:10186800020E04010401546F04014651BBEC17F049 +:1018780000D012000401370E040104015D6F040159 +:10188800040E04015E6F0401350E040104015B6F50 +:101898000401040E04015C6F2FEC16F0040E040121 +:1018A80004013D6F000E04013E6F040104013EAFC8 +:1018B80001D001D001D07ED00401436F000E040195 +:1018C80004013F6F04014351000E04010401406FFD +:1018D800000E0401416F040104014151800A800F88 +:1018E800080ED8B4405DD8A001D001D001D04AD0AC +:1018F8000401370E04010401476F0401040E0401BA +:10190800486F0401350E04010401456F0401040EFB +:101918000401466F89EC15F004010401426F0401CB +:1019280004014251020AD8A401D001D001D088D0C4 +:10193800040104014251D8B401D001D013D040C4ED +:1019480043F4010E0401446F0401432B03D0D890E3 +:10195800040144370401432FFAD704014451040118 +:1019680004013F1304010401404B412B040104010D +:101978004151800A800F080ED8B4405DD8A001D02C +:1019880001D0B6D70401380E040104013D25E96EE3 +:10199800EA6A0401040EEA2204013FC4EFFF0401CD +:1019A80004013D07D8A03E07040104013EAF01D061 +:1019B80001D082D7C9EC17F0B40E04010401566FA8 +:1019C800790E0401576FCE0E04010401546F790E8D +:1019D8000401556F9AEC17F06F0E04010401566F5D +:1019E800790E0401576F8C0E04010401546F790EAF +:1019F8000401556F9AEC17F00401436F050E0401BA +:101A08000401496F040143510401380E0401040123 +:101A1800476F0401040E0401486FE30E040104013A +:101A2800456F790E0401466F33EC0FF00401436FE4 +:101A3800010E04010401546F04014351BBEC17F07B +:101A4800120004014C6F000E04010401496F0401E7 +:101A58004C51030E04010401496501D001D001D0A5 +:101A680023D0040104014951040104013F25E96E12 +:101A78000401000E040104014021EA6E0401450E30 +:101A8800040104014925E16EE26A0401040EE22220 +:101A9800EFCFE7FF04010401492B030E0401040101 +:101AA800496501D001D0DDD7050E040104013F25A9 +:101AB80004014C6F000E04010401402104014D6F24 +:101AC8004CC443F44DC444F40096000E0C6E0094CC +:101AD800040100EE04F004013F51E92604014051DD +:101AE800EA22EF5004010401426F04010401426735 +:101AF80001D001D001D081D004010401426701D096 +:101B080001D001D072D043C4E9FF44C4EAFFEF50CA +:101B180004010401416F04014C6F000E040104012B +:101B28004A6F04014C51030E040104014A6501D0B7 +:101B380001D001D050D041C44CF4C00E04014C1760 +:101B4800060E04014D6FD89004014C3304014D2F4B +:101B5800FAD704014C51040104014B6F0401450EEE +:101B6800040104014B25E96EEA6A0401040EEA2225 +:101B7800010EEF6201D001D002D0008613D004011B +:101B8800450E040104014B25E96EEA6A0401040EBE +:101B9800EA22EF500D6EB18000D000A401D001D030 +:101BA800FCD700940401D8904137D89041370401FC +:101BB8000401420704010401426701D001D001D0A9 +:101BC8000AD0040104014A2B030E040104014A65EA +:101BD80001D001D0B0D704010401434B442B0401C8 +:101BE8000401426701D001D08ED7009400D000A430 +:101BF80001D001D0FCD7B1908998120054C463F485 +:101C080055C464F4C20E04010401616F790E040125 +:101C1800626F0FEC02F00401595156115711581117 +:101C2800D8A401D001D00AD0F30E04010401616FD9 +:101C3800790E0401626F0FEC02F071D004015D6F40 +:101C4800010E040104015A6F04015D5104015D6F26 +:101C5800000E040104015B6F04015D51070E0401CD +:101C680004015B6501D001D001D059D0040156C4EC +:101C78005DF4040157C45EF4040158C45FF4040120 +:101C880059C460F41D0E06D0D890040160335F3348 +:101C98005E335D33E82EF8D704015D510F0B040164 +:101CA80004015C6F040104015C6701D001D008D015 +:101CB800040104015A05D8A401D001D001D018D0DC +:101CC800040104015CC463F404010401646BEA0EBA +:101CD80004010401616F790E0401626F0FEC02F0D8 +:101CE80004015D6F000E040104015A6F04015D5187 +:101CF8000401040ED8900401563704015737040133 +:101D0800583704015937E82EF5D7040104015B2B35 +:101D1800070E040104015B6501D001D0A7D79C0E12 +:101D280004010401616F790E0401626F0FEC02F087 +:101D38001200036601D001D017D0030E040104017C +:101D48003E6501D001D007D00C0E040104013E65A8 +:101D580001D001D002D0FE0E81D004013F6F010EE8 +:101D6800036E04013F5178D00304D8A401D001D0F8 +:101D780026D00B0E040104013E6501D001D007D026 +:101D8800160E040104013E6501D001D008D00401FB +:101D98003F6F000E036E04013F51FE0E5FD00090AE +:101DA800040104013DA101D0008004013F6F020E2F +:101DB800036E04013F51000E00B0010E4FD00350D6 +:101DC800020AD8A401D001D047D0040104013D5132 +:101DD800D8B401D001D015D0030E040104013E652A +:101DE80001D001D00ED00D0E040104013E6101D0D6 +:101DF80001D007D004013F6F000E036E04013F516C +:101E080029D00B0E040104013E6501D001D00ED08B +:101E1800170E040104013E6101D001D007D004016E +:101E28003F6F010E036E04013F5114D0030E0401ED +:101E380004013E6501D001D00DD00D0E040104014E +:101E48003E6101D001D006D004013F6F000E036E41 +:101E580004013F51FF0E02D0FF0E00D0120045C40E +:101E680063F446C464F4ED0E04010401616F790E55 +:101E78000401626F0FEC02F004014B6F000E0401C5 +:101E880004014A6F04014B51040104014951040142 +:101E980004014A5DD8A001D001D001D04BD0040183 +:101EA80004014A51040104014725E96E0401000EAA +:101EB800040104014821EA6EEF5004014B6F0F0E34 +:101EC80004014B1704014B5104010401656F04011F +:101ED800666B040104014A51040104014725E96EB7 +:101EE8000401000E040104014821EA6EEF500401C8 +:101EF8004C6F04014C3B0F0E4C1704014C5104016C +:101F08000401636F0401646BE80E04010401616F4E +:101F1800790E0401626F0FEC02F0040104014A2BF0 +:101F2800040104014951040104014A5DD8A001D00B +:101F380001D0B5D79C0E04010401616F790E04012C +:101F4800626F0FEC02F012000401D8901D370401F3 +:101F580004019951D8B401D001D01BD00401040167 +:101F68001E2B040104011E51030AD8A401D001D07C +:101F780005D0070E040104011D130AD0030E040145 +:101F880004011E6501D001D003D0040104011D81A4 +:101F980008D004019A6F000E040104011E6F0401A9 +:101FA8009A510401D890223704010401232B04011B +:101FB80004011DAF01D001D004D004010401228125 +:101FC80000D0040104012351080AD8A401D001D08B +:101FD80029D004019A6F000E04010401236F040143 +:101FE8009A511B0E040104012025E96E020E04011A +:101FF80004012121EA6E040122C4EFFF0401040157 +:10200800204B212B040104012151020A2011D8A4DC +:1020180001D001D007D0000E04010401206F000E8A +:102028000401216F1200040104012651D8B401D023 +:1020380001D024D0040104012551040104012427FE +:102048007E0E04010401246501D001D004D00401EE +:102058000401256911D004010401246701D001D0CD +:102068000BD004018A6F010E04010401256F0401DD +:102078008A5104010401260724C4BEFF0401040197 +:102088002951D8B401D001D024D004010401285129 +:102098000401040127277E0E04010401276501D0ED +:1020A80001D004D004010401286911D004010401FD +:1020B800276701D001D00BD004018A6F010E0401FB +:1020C8000401286F04018A5104010401290727C467 +:1020D800BBFF04010401266701D001D002D0000E25 +:1020E800BE6E04010401296701D001D002D0000EA0 +:1020F800BB6E12000096000E0C6E00943FC4E9FF00 +:1021080040C4EAFFEF500D6EB18000D000A401D0AA +:1021180001D0FCD7010E04010401416F000E040137 +:10212800426F2FD0040104014151040104013F25ED +:10213800E96E040104014251040104014021EA6EE0 +:10214800010EEF6201D001D002D0008616D00094B3 +:10215800040104014151040104013F25E96E040111 +:1021680004014251040104014021EA6EEF500D6E52 +:1021780000D000A401D001D0FCD704010401414BD8 +:10218800422B040104014151040104013F25E96E79 +:10219800040104014251040104014021EA6EEF5098 +:1021A800D8A401D001D0BED7009400D000A401D09B +:1021B80001D0FCD7B1908998120004015A6F000E23 +:1021C80004010401596F04015A5156C4E9FF57C468 +:1021D800EAFFEF50040104015D6F54C4E9FF55C4E0 +:1021E800EAFF0401EECF5BF40401EDCF5CF48BEC65 +:1021F80016F0D8B001D002D0010E01D0000E0401B3 +:102208000401586F04010401592B56C45DF457C4E6 +:102218005EF454C45BF455C45CF42FEC16F056C459 +:10222800E9FF57C4EAFFEF50040104015D6F54C48D +:10223800E9FF55C4EAFF0401EECF5BF40401EDCFDA +:102248005CF48BEC16F0D8B001D002D0010E01D0AE +:10225800000E040104015819D8B401D001D004D0EB +:102268000401040159510AD0040104015929D8A4D0 +:1022780001D001D002D0000E01D0C4D71200000E48 +:1022880004010401776F000E0401786F0401040152 +:1022980075517411D8B401D001D047D00401796FB9 +:1022A800010E04010401766F0401795109D004017B +:1022B800D890040174370401753704010401762BA2 +:1022C8000401040175AF01D001D0F1D70401D89001 +:1022D80004017737040178370401040174510401BB +:1022E8000401725D0401040175510401040173596C +:1022F800D8A001D001D00FD0040104017451040109 +:102308000401725F04010401755104010401735B47 +:102318000401040177810401D89004017533040194 +:10232800743304010401762FD1D777C472F478C4CA +:1023380073F400D01200000EAB6EAB8EAB88AC907D +:10234800AC8AAC94B896948E949C06D00401AECF17 +:1023580031F404010401326B9EBA01D001D0F6D7E2 +:102368000401336F400EAF6E040133519F9A9F985A +:10237800F28C9D8A9D98CD909E90000ECF6E000E97 +:10238800CE6ECD9ACD98CD92000E04010401386F1F +:10239800020E0401396F000E04010401366F000EAD +:1023A8000401376F1B0E04010401346F000E040191 +:1023B800356F19EC17F0000E04010401386F010E97 +:1023C8000401396F2D0E04010401366F000E04015B +:1023D800376F0501000E04010401346F0501050E75 +:1023E8000401356F19EC17F01200E6EC17F0040140 +:1023F8003D6F000E040104013B6F04013D5140D0C4 +:1024080004013D6F020E040104013F6F04013D51B8 +:10241800EAEC17F01B0E04013D6F000E3E6F04013D +:102428000401375104013D27040104013851040116 +:102438003E233DC43FF43EC440F425EC0DF00401B6 +:102448003D6F000E040104013C6F04013D510BD0A7 +:102458000D0E04013D6FF90EE82EFED73D2FFCD777 +:10246800040104013C2B0401040139510401040155 +:102478003C5DD8A001D001D0EBD7040104013B2B6F +:10248800040104013A51040104013B5DD8A001D0C4 +:1024980001D0B6D7DCEC17F01200E6EC17F0040117 +:1024A8003D6F000E040104013B6F04013D5140D013 +:1024B80004013D6F020E040104013F6F04013D5108 +:1024C800EAEC17F01B0E04013D6F000E3E6F04018D +:1024D8000401375104013D27040104013851040166 +:1024E8003E233DC43FF43EC440F47EEC10F00401AA +:1024F8003D6F000E040104013C6F04013D510BD0F7 +:102508000D0E04013D6FF90EE82EFED73D2FFCD7C6 +:10251800040104013C2B04010401395104010401A4 +:102528003C5DD8A001D001D0EBD7040104013B2BBE +:10253800040104013A51040104013B5DD8A001D013 +:1025480001D0B6D7DCEC17F01200040104013529DC +:10255800D8B43629D8A401D001D006D0040104018A +:1025680035690401366946D0040104013851800AEE +:102578000401396F0401355104010401375D040178 +:1025880004013651800A04013959D8A001D001D07C +:1025980012D004010401355104010401375D04011E +:1025A8000401356F0401040136510401040138594E +:1025B8000401366F1FD0000E0401396F020E3A6F06 +:1025C8000401040135510401395F04010401365145 +:1025D80004013A5B0401040137510401392504015F +:1025E8000401356F04010401385104013A21040142 +:1025F800366F00D012003ED037C4E9FF38C4EAFF76 +:10260800EF50D8B401D001D014D0040139C4F6FF7A +:1026180004013AC4F7FF0800F5CF3DF437C4E9FFD9 +:1026280038C4EAFFEF5004013D19D8B401D001D0F5 +:1026380019D037C4E9FF38C4EAFFEF5004013D6FF1 +:10264800040139C4F6FF04013AC4F7FF0800F55045 +:1026580004013D5D04010401376F0401386BD8A003 +:1026680038071DD004010401374B382B040104013D +:10267800394B3A2B040104013B07D8A03C0704015D +:102688003B29D8B43C29D8A401D001D0B5D7000E35 +:1026980004010401376F000E0401386F00D01200E6 +:1026A800FACF7DF4FBCF7EF4E9CF7FF4EACF80F454 +:1026B800E1CF81F4E2CF82F4D9CF83F4DACF84F486 +:1026C800F3CF85F4F4CF86F4F6CF87F4F7CF88F408 +:1026D800F8CF89F49EAA01D001D002D0C6EC15F03B +:1026E8009EA801D001D002D05EEC16F09EA201D0C7 +:1026F80001D003D017EC10F09E9289C4F8FF88C46B +:10270800F7FF87C4F6FF86C4F4FF85C4F3FF84C4CB +:10271800DAFF83C4D9FF82C4E2FF81C4E1FF80C429 +:10272800EAFF7FC4E9FF7EC4FBFF7DC4FAFF7CC4D7 +:10273800E0FF7BC4E8FF7AC4D8FF1000040104015D +:1027480075517411D8B401D001D03ED00401776F0F +:10275800010E04010401766F0401775109D00401C8 +:10276800D890040174370401753704010401762BED +:102778000401040175AF01D001D0F1D704010401AF +:10278800745104010401725D0401040175510401CE +:1027980004017359D8A001D001D00CD00401040160 +:1027A800745104010401725F0401040175510401AC +:1027B8000401735B0401D890040175330401743378 +:1027C80004010401762FDAD772C472F473C473F467 +:1027D80000D012004FC456F450C457F44DC454F4FA +:1027E8004EC455F4E1EC10F004010401526F130ECD +:1027F80004010401526501D001D009D0290E040159 +:102808000401526101D001D002D0000E2DD04FC476 +:1028180056F450C457F44DC454F44EC455F4E1EC86 +:1028280010F004010401516F010E04010401526506 +:1028380001D001D017D0150E04010401526101D056 +:1028480001D010D0010E04010401516501D001D05E +:1028580009D0150E04010401516101D001D002D044 +:10286800010E02D0020E00D012003AC43EF439C460 +:102878003DF49DEC0EF0040104013B6F04010401DA +:102888003B51FE0AD8A401D001D008D0FE0E0401A5 +:102898000401396FFF0E04013A6F30D004010401BE +:1028A8003B29D8A401D001D006D00401040139691C +:1028B80004013A6923D0D8900632040104013B513F +:1028C800D8B401D001D001D0068E0B2A080E0B60B7 +:1028D80001D001D006D004010401396904013A6924 +:1028E8000DD004013C6F000E0B6E04013C51040135 +:1028F80006C039F4040104013A6B00D01200060046 +:10290800EACF8FF4E1CF90F4E2CF91F4D9CF92F4EB +:10291800DACF93F4F3CF94F4F4CF95F4F6CF96F49A +:10292800F7CF97F4F8CF98F4F2A401D001D00BD0E8 +:10293800000E81B8010E04010401996FA8EC0FF094 +:10294800000ED66EF294A1A201D001D006D0B368D1 +:10295800C90EB26E72EC17F0A19298C4F8FF97C432 +:10296800F7FF96C4F6FF95C4F4FF94C4F3FF93C42D +:10297800DAFF92C4D9FF91C4E2FF90C4E1FF8FC48B +:10298800EAFF8EC4E9FF8DC4FBFF8CC4FAFF110077 +:102998000F0E04010401476501D001D017D00A0EBB +:1029A80004010401486101D001D010D00F0E0401C8 +:1029B8000401496501D001D009D00A0E04010401BF +:1029C8004A6101D001D002D0000E20D00A0E0401C5 +:1029D8000401476101D001D017D00F0E0401040192 +:1029E800486501D001D010D00F0E040104014965DB +:1029F80001D001D009D00A0E040104014A6101D0B6 +:102A080001D002D0010E02D0020E00D012000F0E2B +:102A180004010401476501D001D017D00A0E040152 +:102A28000401486101D001D010D00A0E040104014C +:102A3800496101D001D009D00A0E040104014A619C +:102A480001D001D002D0000E20D00A0E04010401EA +:102A5800476101D001D017D00A0E04010401486172 +:102A680001D001D010D00F0E04010401496501D036 +:102A780001D009D00A0E040104014A6101D001D035 +:102A880002D0010E02D0020E00D012000D0E040179 +:102A98000401476101D001D017D00D0E04010401D3 +:102AA800486101D001D010D00D0E04010401496124 +:102AB80001D001D009D0100E040104014A6501D0EB +:102AC80001D002D0010E20D00D0E0401040147618F +:102AD80001D001D017D0100E04010401486501D0BF +:102AE80001D010D00D0E04010401496101D001D0BC +:102AF80009D00D0E040104014A6101D001D002D0B1 +:102B0800000E02D0020E00D0120047C456F448C48A +:102B180057F445C454F446C455F4E1EC10F00401EC +:102B28000401496F47C456F448C457F445C454F4E3 +:102B380046C455F4E1EC10F0040104014A6F0D0E8F +:102B480004010401496501D001D009D00D0E04012A +:102B580004014A6501D001D002D0000E12D00A0E3D +:102B680004010401496101D001D009D00D0E04010E +:102B780004014A6501D001D002D0010E02D0020E34 +:102B880000D01200AECF8AF4ABA201D001D002D09F +:102B9800AB98AB8800A201D001D001D029D00401A4 +:102BA80004018A512B0AD8A401D001D00BD0CD90B2 +:102BB80000821B0E0724E96EEA6A000EEA22000E64 +:102BC800EF6E16D01B0E0724E96EEA6A000EEA22A1 +:102BD80004018AC4EFFF072A000ECF6E000ECE6EE6 +:102BE800CD809E9004018B6F000E0A6E04018B51FC +:102BF80012009EA001D001D00CD01E0E0A6401D094 +:102C080001D005D0CD90000E076E009201D00A2A9F +:102C18009E9000B201D001D001D01CD0D9EC08F0B0 +:102C2800000E04010401386F020E0401396F000E12 +:102C380004010401366F000E0401376F1B0E0401F6 +:102C48000401346F000E0401356F19EC17F0000E03 +:102C5800076E009212005DC4E9FF5EC4EAFFD890D7 +:102C6800EF365DC4E9FF5EC4EAFFEF50D8A401D097 +:102C780001D01FD05DC4E9FF5EC4EAFF010EEF6E0C +:102C88005BC4E9FF5CC4EAFFEE50ED10D8A401D0A4 +:102C980001D008D05BC4E9FF5CC4EAFF000EEE6E09 +:102CA800020EED6E5BC4E9FF5CC4EAFFEE06000E9F +:102CB800ED5A120030C48AF4040104018A29D8A408 +:102CC80001D001D009D004018B6F000E040104016A +:102CD8008A6F04018B5103D0040104018A2B095027 +:102CE800040104018A6301D001D002D09D980ED05E +:102CF8000501000E040104018A25E96EEA6A05014E +:102D0800050EEA22EF50AD6E8AC430F412001B0E95 +:102D1800040104015B25E96E020E040104015C2133 +:102D2800EA6EEF50040104015E6F040104015E5174 +:102D380004015DC45FF40401606B5FBF60070401B8 +:102D48005F17000E6017040160515F11D8B401D0FD +:102D580001D002D0D88002D0D89000D012000D0E39 +:102D680004010401546101D001D009D00D0E040101 +:102D78000401556101D001D002D0000E12D0180E06 +:102D880004010401546501D001D009D00D0E0401DD +:102D98000401556101D001D002D0010E02D0020E0B +:102DA80000D01200F9EC16F0E1EC17F09FEC11F0EE +:102DB800ACEC17F0D3EC17F057EC17F0050E040144 +:102DC8000401636F000E0401646F830E04010401A3 +:102DD800616F790E0401626F0FEC02F0A3EC07F04B +:102DE800FDEC15F0FBD714EF00F0000EC26E0401E5 +:102DF800316F0F0EC16E04013151070EB46E000E13 +:102E0800806E000E926E000E946E000E956E000E8F +:102E1800826E000E836E000E936E000E816E89988E +:102E28009298949294949296120034C43AF435C4C9 +:102E38003BF40BD03AC4E9FF3BC4EAFF040136C4B3 +:102E4800EFFF040104013A4B3B2B0401040138074E +:102E5800D8A0390704013829D8B43929D8A401D011 +:102E680001D0E8D700D0120000D0095004010401B5 +:102E78003019D8B401D001D0F8D70501000E0924C3 +:102E8800E96EEA6A0501050EEA22040172C4EFFF41 +:102E98000928D8A401D001D003D0000E096E01D0B2 +:102EA800092A9D881200CA82CA9CCA8ACA98CA96E8 +:102EB800000EBD6E000EBA6EBA86BA84BD86BD8499 +:102EC800BD9ABD98BA9ABA98000EBE6E000EBB6E37 +:102ED8009E92CB689F929D82CA8412000C6601D094 +:102EE80001D00AD00DC00CF0008400B601D001D08A +:102EF80002D0897801D000960C50D8B401D001D006 +:102F080001D00C0612000401396F000E0B6E04018B +:102F180039510401396F000E036E0401395104015F +:102F2800396F000E086E04013951120056C465F459 +:102F380057C466F454C463F455C464F4AD0E040174 +:102F48000401616F790E0401626F0FEC02F0120048 +:102F5800D594D592D590D596D59AD58CF294F28AF7 +:102F680092969388F184D58EEDEC17F01200220E1C +:102F780004010401616F790E0401626F0FEC02F025 +:102F880054C455F4F3EC17F01200F50E04010401D3 +:102F9800616F790E0401626F0FEC02F012009294D7 +:102FA80092988998B19AB198A082A282B1901200A1 +:102FB800EDEC17F0D58EB1901200D08EF28EF28C17 +:102FC800F28E1200D59EF0EC17F012003FC429F4DF +:102FD800120089948986120089848996120055C442 +:042FE80026F41200B9 +:1078FC0001000A006400E8031027010010000001D9 +:10790C000010556E6B6E6F776E20636F6D6D616ED0 +:10791C006420282575290D0A0074656D70657261E7 +:10792C007475726568756D6964697479003031328B +:10793C003334353637383941424344454600657651 +:10794C006572666C6F75726973680073656C666CD2 +:10795C006561726E696E6700636F646573776974D5 +:10796C0063680066696E656F6666736574006D6149 +:10797C006E646F6C796E000D0A2B5625750D0A001E +:10798C0070726F746F636F6C0025733A3078255882 +:10799C003B006172637465636800286E756C6C29BA +:1079AC000025733A25733B0073656E736F72006F1D +:1079BC007265676F6E0025733A3078006D6F646581 +:1079CC006C00636C617373002B4E0D0A002B530D0E +:1079DC000A002B540D0A0064617461002558255867 +:1079EC000025733A00783130002B57002B52004E93 +:0479FC000056000031 +:020000040030CA +:04000000FF36FFFECA +:02000600BFFF3A +:00000001FF diff --git a/telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex b/telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex new file mode 100644 index 00000000..81fc3c2e --- /dev/null +++ b/telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex @@ -0,0 +1,4476 @@ +:0400000014EF00F009 +:10000800FACFE3F7FBCFE4F7E9CFE5F7D7EF16F040 +:10001800D8CFCBF7E8CFCCF7E0CFCDF78FEF16F0FE +:1000280006EEB5F0000EF66E000EF76E010EF86ED5 +:1000380010EE31F042EC00F0F86A00EE00F010EE3D +:10004800FFF03BEC00F001EE00F012EEFFF03BECAD +:1000580000F004EE00F010EEFFF03BEC00F005EECF +:1000680000F011EEB5F03BEC00F0F8EF04F0EE6AAA +:10007800E550E150FCE1E250FAE112000900F5CF49 +:10008800EEFFE550E150FAE1E250F8E11200070115 +:10009800BB6F140E326E0701BB510701BB6F450ED3 +:1000A80007010701A76F0701BB510701BB6F000ECE +:1000B80007010701A86F0701BB51140E07010701CB +:1000C800A52507010701A96F000E07010701A62151 +:1000D8000701AA6F154A162A15C0ABF716C0ACF768 +:1000E800000E07010701AD6F000E0701AE6F070193 +:1000F800BB6F640E07010701AF6F0701BB51A4C7AF +:10010800B0F7000E07010701B16F000E0701B26FCB +:100118003CC6B3F73DC6B4F73EC6B5F73FC6B6F71B +:10012800A2C7E9FFA3C7EAFF0701EECFB7F70701A8 +:10013800EECFB8F70701EECFB9F70701EECFBAF760 +:100148000701A70E07010701BC6F0701070E07018A +:10015800BD6F52EC0FF0140E07010701BE6F000EC1 +:100168000701BF6F0701A70E07010701BC6F070151 +:10017800070E0701BD6F38EC06F0BCC7B1F7BDC765 +:10018800B2F7140E07010701A52507010701BF6F84 +:10019800000E07010701A6210701C06F0701BB6F09 +:1001A800000E07010701BE6F0701BB51040E0701CE +:1001B8000701A22507010701BC6F000E070107010F +:1001C800A3210701BD6FA9EC12F0140E0701070166 +:1001D800C46F000E0701C56F0701A70E07010701CD +:1001E800C26F0701070E0701C36FB8EC1FF000D0FC +:1001F8001200040E07010701C66F000E0701C76F42 +:100208000701210E07010701C46F0701070E070147 +:10021800C56FA4EC19F0070107012151080A221142 +:10022800D8A401D001D090D01FC73FF720C740F70E +:10023800140E070107013D6F000E07013E6F46ECE3 +:1002480016F007013E513D11D8B401D001D001D0BC +:100258007BD00701256F000E07010701216F0701F9 +:100268002551080E070107012327080E070107017A +:10027800236101D001D00CD007010701242B07010D +:100288000701246701D001D003D007010701232B00 +:1002980000D01CEC1EF00009D8B401D001D0F9D769 +:1002A800DD0E07010701AE6F0A0E0701AF6F86EC7E +:1002B80022F01FC7A5F720C7A6F70701256F010E73 +:1002C80007010701A46F070125511DC7A2F71EC723 +:1002D800A3F74BEC00F0040E07010701C46F000EF2 +:1002E8000701C56F0701210E07010701C26F07014A +:1002F800070E0701C36FB8EC1FF0FC0E07010701DA +:100308001F2507010701B26FFF0E07010701202112 +:100318000701B36FFF0E07010701B06FFF0E07015A +:10032800B16FFF0E07010701AE6FFF0E0701AF6F38 +:10033800F8ECD1F000D07CEC22F00009D8B401D060 +:1003480001D0F9D780EC1FF0120007010F6F000EE3 +:10035800070107010E6F07010F5197D00701070129 +:100368000D513A0AD8A401D001D016D000010001DD +:10037800F051EF11D8A401D001D007D007010F6FB9 +:10038800020E266E07010F5106D007010F6F010EEE +:10039800266E07010F5184D000010001EF3B0001D8 +:1003A800F03BF00E0001F0170001EF510F0B0001B8 +:1003B800F013F00E0001EF170DC73FF7FDEC12F038 +:1003C80007010F6F07010F5100010001EF1368D0FB +:1003D80003D0070107010E2B06016F0E0701070165 +:1003E8000E25E96EEA6A0601060EEA22EF50D8A445 +:1003F80001D001D0EED706016F0E070107010E25C7 +:10040800E96EEA6A0601060EEA2207010DC7EFFF48 +:1004180000010001EF07D8A0F00700010001F0512A +:10042800EF11D8A401D001D0B6D7262A39D00701B8 +:1004380007010D51690AD8B401D001D002D026684D +:10044800AAD7262A2DD0070107010D51730AD8A46F +:1004580001D001D007D007010F6F000E266E0701EB +:100468000F511ED00D3A0E3AF00E0E160D500F0B0E +:100478000E12F00E0D160DC73FF7FDEC12F0070136 +:100488000F6F07010F510D120BD02650000A01E122 +:1004980065D7010A9DE0030ACAE0010AD4E000D04A +:1004A800120000D01CEC1EF00009D8B401D001D015 +:1004B800F9D7CF0E07010701AE6F0A0E0701AF6F1C +:1004C80086EC22F078C7E9FF79C7EAFF010EEE6EE5 +:1004D800000EED6E020E070107017825E96E000E89 +:1004E800070107017921EA6E000EEE6E080EED6E27 +:1004F800040E070107017825E96E000E07010701C0 +:100508007921EA6E060EEF6E050E070107017825C0 +:10051800E96E000E070107017921EA6E040EEF6EFD +:10052800060E07010701B26F000E0701B36F690ECF +:1005380007017A6F060E7B6F7AC7B0F77BC7B1F7F2 +:10054800080E07010701782507010701AE6F000EA5 +:100558000701070179210701AF6F18EC1AF00E0E99 +:10056800070107017825E96E000E070107017921C7 +:10057800EA6E06013CC6EEFF06013DC6EEFF060127 +:100588003EC6EEFF06013FC6EEFF78C77CF779C787 +:100598007DF79FEC11F01C0E07010701BF6F000EDD +:1005A8000701C06F07017A6F060E07010701BE6FCA +:1005B80007017A51120E0701070178250701070183 +:1005C800BC6F000E0701070179210701BD6FA9EC77 +:1005D80012F01C0E07010701C46F000E0701C56F5A +:1005E80078C7C2F779C7C3F7B8EC1FF080EC1FF0E3 +:1005F800010E00D0120021C733F722C734F7F1ECFF +:1006080013F00701276F690E07010701486F0701FB +:100618002751D0EC1DF00701070124512311D8A45C +:1006280001D001D00BD00701276F300E0701070159 +:10063800486F07012751D0EC1DF07CD00701276FC8 +:10064800000E07010701266F07012751070107015F +:10065800255107010701265DD8A001D001D001D09E +:1006680021D0070107012651070107012325E96E5B +:100678000701000E070107012421EA6EEF50300A36 +:10068800D8B401D001D001D00DD007010701262B25 +:1006980007010701255107010701265DD8A001D0F0 +:1006A80001D0DFD707010701255107010701265DA2 +:1006B800D8A001D001D001D03DD0070107012651B3 +:1006C800070107012325E96E0701000E070107014D +:1006D8002421EA6EEF50070107013C6F59EC1DF029 +:1006E80007010701486FD0EC1DF0070107012651EB +:1006F800070107012325E96E0701000E070107011D +:100708002421EA6EEF5007010701486F31EC1DF014 +:1007180007010701486FD0EC1DF007010701262BE0 +:1007280007010701255107010701265DD8A001D05F +:1007380001D0C3D70701276F730E07010701486F60 +:1007480007012751D0EC1DF012000E010E01D967E8 +:1007580001D001D002D0000EA1D0346601D001D062 +:1007680004D026EC1BF0000E99D0FBC0FDF3FCC0B2 +:10077800FEF3FDC3E0FEFEC3E1FE140E0701070110 +:10078800C66F000E0701C76F0701210E0701070199 +:10079800C46F0701070E0701C56FA4EC19F033C732 +:1007A800BEF734C7BFF7B8EC21F0BEC733F7BFC7F1 +:1007B80034F7CE0E07010701215D0A0E0701225901 +:1007C800D8B001D001D023D00701070121B101D051 +:1007D80001D01DD00701070126BF01D001D017D0D5 +:1007E8000701070125B901D001D011D0EF0E07018B +:1007F8000701235D050E07012459D8B001D001D0A7 +:1008080006D00701070125BF01D001D001D0FF00A4 +:1008180021C7FBF022C7FCF0060E07010701B26FE3 +:10082800000E0701B36F2D0E0701356F070E366FE7 +:1008380035C7B0F736C7B1F71DC7AEF71EC7AFF754 +:1008480018EC1AF01FC7E9FF20C7EAFFFF0EEF6E8A +:10085800070107013451080AD8A401D001D016D0E5 +:10086800070107013351D8B401D001D008D00701DE +:1008780007013351060AD8A401D001D007D01FC7F9 +:10088800E9FF20C7EAFF070133C7EFFF0701356F0C +:10089800000E346E07013551010E00D012004CC70E +:1008A800E9FF4DC7EAFFEECF50F7EECF51F7EECF95 +:1008B80052F7EECF53F700010001E8510701531931 +:1008C80011E100010001E751070152190BE1000194 +:1008D8000001E6510701511905E100010001E55148 +:1008E80007015019D8B401D001D06CD00001000123 +:1008F800E85106010601471914E100010001E7511A +:100908000601060146190DE100010001E651060144 +:100918000601451906E100010001E551060106013D +:100928004419D8A401D001D05CD04CC7E9FF4DC709 +:10093800EAFFEECF50F7EECF51F7EECF52F7EECFFA +:1009480053F7060106013C51070150190701546F7E +:10095800060106013D51070151190701556F0601AE +:1009680006013E51070152190701566F060106019B +:100978003F51070153190701576F060106014051FE +:10098800070154150701586F060106014151070177 +:1009980055150701596F0601060142510701561501 +:1009A80007015A6F06010601435107015715070150 +:1009B8005B6F07015B51581159115A11D8B401D016 +:1009C80001D00FD000EEE9F007014EC7E1FF0701A3 +:1009D8004FC7E2FF060EEECFE6FFE82EFCD7010E6A +:1009E80002D0000E00D01200000E07010701006FB0 +:1009F800000E0701016F000E0701026F000E0701CC +:100A0800036F000E0E010E01B66F000E0E010E01EF +:100A1800B76F000E926E000E936E000E946E000E6D +:100A2800956E000E966E000E976E000E986E000E74 +:100A3800806E000E816E000E826E000E836E000EB8 +:100A4800846E000E856E0701046F400E9B6E0701D1 +:100A580004510701046F0F0EC16E07010451AEEC7B +:100A680022F0E5EC21F040EC1EF0D6EC22F0A5ECEB +:100A7800E4F0F0EC22F0D7EC21F08DEC1BF0420E04 +:100A8800070107010B6F370E07010C6F0701046F91 +:100A9800140E070107010A6F0701045127EC1FF024 +:100AA8005CECBCF0DEEC22F019EC22F00701070147 +:100AB800005107010701A35D0701046F0701070142 +:100AC800015107010701A4590701056F0701070133 +:100AD800025107010701A5590701066F0701070120 +:100AE800035107010701A6590701076FF20E045DBC +:100AF8009E0E0559000E0659000E07010759D8A089 +:100B080001D001D00AD019EC22F0A3C700F7A4C77E +:100B180001F7A5C702F7A6C703F7CFECCAF0B7ECF1 +:100B280022F00400BDD714EF00F00701386F000E63 +:100B380007010701366F070138510701386F000EAA +:100B480007010701376F0701385121D00401000E52 +:100B58002524E96EEA6A0401040EEA22EF5007012F +:100B68000701356F252A0701070135513A0AD8A42C +:100B780001D001D001D010D00701373BF00E371754 +:100B880035C73FF7FDEC12F0070107013713C70E11 +:100B9800256401D001D0DAD7070137C738F7070134 +:100BA800396BFF0E07010701342507013A6F07016A +:100BB8003B6BFF0E07013B2307013B51800A0701EE +:100BC8003C6F0701385107013A5D07013951800A26 +:100BD80007013C59D8B001D001D006D00701070160 +:100BE80037512526000E3FD00701386F000E070148 +:100BF8000701366F070138511BD00401000E252468 +:100C0800E96EEA6A0401040EEA2207010701365177 +:100C1800070107013225E16E0701000E07010701F0 +:100C28003321E26EEFCFE7FF252A07010701362BB4 +:100C380007010701375107010701365DD8A001D028 +:100C480001D0DBD70701070137510701070132251A +:100C5800E96E0701000E070107013321EA6E000E55 +:100C6800EF6E010E00D01200D89007010701BF31C6 +:100C780007010701C16F07010701BE310701C06FF6 +:100C8800BCC7C2F7BDC7C3F7000E07010701C46F91 +:100C9800000E0701C56F000E0701C66F000E0701A1 +:100CA800C76F23D00701C2C7E9FF0701C3C7EAFF1F +:100CB8000701020E0701C227000E0701C323EECF6A +:100CC800C8F7EDCFC9F70701C85107010701C427C5 +:100CD8000701C95107010701C523000E07010701D4 +:100CE800C623000E07010701C72307010701C00734 +:100CF800D8A0C1070701C029D8B4C129D8A401D0F8 +:100D080001D0D0D707010701BEA101D001D013D06F +:100D1800C2C7E9FFC3C7EAFFEF500701C86F070161 +:100D2800C85107010701C427000E0701C5230701A1 +:100D3800C6230701C723070107EEC6F0EECFC8F7A1 +:100D4800EDCFC9F707010701C4510701C8270701FB +:100D58000701C5510701C9230701C8C7C4F707011F +:100D6800C9C7C5F707010701C66B0701C76B0701AC +:100D780007EEC6F0EE5007010701C427ED50070142 +:100D88000701C52307010701C41D07010701BC6F3F +:100D980007010701C51D0701BD6F00D012004CC730 +:100DA80050F74DC751F7070150C7F6FF070151C764 +:100DB800F7FF000EF86E08000701F5CF4FF707019F +:100DC8000701504B512B070107014F51D8B401D0EF +:100DD80001D020D0070107014F512E0AD8B401D005 +:100DE80001D018D0070107014F512F0AD8B401D0FC +:100DF80001D010D0070107014F512C0AD8B401D0F7 +:100E080001D008D0070107014F513E0AD8A401D0EC +:100E180001D0C9D7070107014C5107010701505DEF +:100E28000701526F07015205070107014E6F4EC7B0 +:100E380053F763EC1FF0070107014EC755F7070189 +:100E48000701566B4CC753F74DC754F7A8EC17F07A +:100E5800010E070107015327000E0701542307015C +:100E680007015351070107014C2707010701545196 +:100E7800070107014D23070107014F51D8B401D0DD +:100E880001D018D0070107014F512F0AD8B401D05B +:100E980001D010D0070107014F512C0AD8B401D056 +:100EA80001D008D0070107014F513E0AD8A401D04C +:100EB80001D001D001D077D70701526F000E07018A +:100EC8000701536F0701525163EC1FF0120007012D +:100ED8001B6F000E07010701186F07011B5107015F +:100EE800070116AF01D001D00FD007010701156D1A +:100EF8000701161FD8B0162B07011B6F010E07013B +:100F08000701186F07011B510701070114AF01D032 +:100F180001D00BD007010701136D0701141FD8B0CA +:100F2800142B010E07010701181B000E070107010A +:100F3800196F000E07011A6F0701070116511511E5 +:100F4800D8B401D001D047D007011B6F010E0701AB +:100F58000701176F07011B5109D00701D890070136 +:100F680015370701163707010701172B0701070176 +:100F780016AF01D001D0F1D70701D8900701193772 +:100F880007011A3707010701155107010701135D0A +:100F9800070107011651070107011459D8A001D00C +:100FA80001D00FD007010701155107010701135F91 +:100FB80007010701165107010701145B0701070123 +:100FC80019810701D8900701163307011533070166 +:100FD8000701172FD1D7070107011851D8B401D03D +:100FE80001D007D007010701196D07011A1FD8B0F2 +:100FF8001A2B19C713F71AC714F700D01200246662 +:1010080001D001D017D0030E07010701156501D0E3 +:1010180001D007D00C0E07010701156501D001D0DA +:1010280002D0FE0E81D00701166F010E246E070153 +:10103800165178D02404D8A401D001D026D00B0EA4 +:1010480007010701156501D001D007D0160E070169 +:101058000701156501D001D008D00701166F000EF1 +:10106800246E07011651FE0E5FD00090070107019C +:1010780014A101D000800701166F020E246E07012B +:101088001651000E00B0010E4FD02450020AD8A409 +:1010980001D001D047D0070107011451D8B401D0BD +:1010A80001D015D0030E07010701156501D001D045 +:1010B8000ED00D0E07010701156101D001D007D030 +:1010C8000701166F000E246E0701165129D00B0E6A +:1010D80007010701156501D001D00ED0170E0701D1 +:1010E8000701156101D001D007D00701166F010E65 +:1010F800246E0701165114D0030E07010701156568 +:1011080001D001D00DD00D0E07010701156101D0E6 +:1011180001D006D00701166F000E246E0701165184 +:10112800FF0E02D0FF0E00D012004CC750F74DC77B +:1011380051F750C7E9FF51C7EAFFEF500701070110 +:101148004F6F07010701504B512B070107014F5102 +:10115800D8B401D001D020D0070107014F512E0A81 +:10116800D8B401D001D018D0070107014F512F0A78 +:10117800D8B401D001D010D0070107014F512C0A73 +:10118800D8B401D001D008D0070107014F513E0A59 +:10119800D8A401D001D0CDD7070107014C510701D0 +:1011A8000701505D0701526F07015205070107014A +:1011B8004E6F4EC753F763EC1FF0070107014EC788 +:1011C80055F707010701566B4CC753F74DC754F73E +:1011D800EBEC17F0010E070107015327000E07017A +:1011E8005423070107015351070107014C27070141 +:1011F80007015451070107014D23070107014F510A +:10120800D8B401D001D018D0070107014F512F0AD7 +:10121800D8B401D001D010D0070107014F512C0AD2 +:10122800D8B401D001D008D0070107014F513E0AB8 +:10123800D8A401D001D001D001D07BD70701526FCB +:10124800000E07010701536F0701525163EC1FF0AD +:101258001200010E07010701566F000E0701576FB4 +:1012680007010701626907010701636907010701AF +:1012780064690701070165690701070166690701D4 +:10128800070167694CC74EF74DC74FF74CC7E9FFD1 +:101298004DC7EAFFEECF6CF7EECF6DF7EECF6EF7E6 +:1012A800EECF6FF7060106013C5107016C190701E3 +:1012B800706F060106013D5107016D190701716F35 +:1012C800060106013E5107016E190701726F0601FA +:1012D80006013F5107016F190701736F06010601E7 +:1012E8004051070170150701746F0601060141514D +:1012F800070171150701756F0601060142510701C3 +:1013080072150701766F060106014351070173152F +:101318000701776F07017751741175117611D8B4E9 +:1013280001D001D009D00601440E070107014E6F14 +:101338000601060E07014F6F4EC7E9FF4FC7EAFFC8 +:101348000701EECF68F70701EECF69F70701EECF87 +:101358006AF70701EECF6BF70701500E0701070187 +:10136800786F0701070E0701796F55EC02F012003C +:1013780023500E0D0101590EF324070107014E6F8A +:1013880007014F6B0101010E07014F23080E1324BB +:10139800070107014C6F000E142007014D6F0C0E5A +:1013A800070107014E25E96E000E070107014F21CD +:1013B800EA6E0701EECFBEF70701EDCFBFF7B8EC35 +:1013C80021F0BEC750F7BFC751F70A0E0701070142 +:1013D8004E25E96E000E070107014F21EA6E07014D +:1013E800EECFBEF70701EDCFBFF7B8EC21F0BEC7CF +:1013F80052F7BFC753F74CC7BEF74DC7BFF7B8EC96 +:1014080021F0BEC754F7BFC755F7000E0701070103 +:10141800566F000E0701576FDD0E07010701AE6F0B +:101428000A0E0701AF6F86EC22F04CC7A5F74DC72F +:10143800A6F70701586F110E07010701A46F0701EE +:1014480058514EC7A2F74FC7A3F74BEC00F0080E50 +:1014580007010701C46F000E0701C56F0701500E91 +:1014680007010701C26F0701070E0701C36FB8EC38 +:101478001FF080EC1FF0000E136E000E146E0601B4 +:101488000601E069120041C760F784EC0EF0F5C36D +:1014980043F7070107014351070AD8B401D001D027 +:1014A80010D00701070143510B0AD8B401D001D06D +:1014B80008D0000E07010701416F000E0701426FB7 +:1014C80068D0030103EEE7F0030113EEE5F0E652FE +:1014D800EE52ED50E55C02E1EF50E75CD8A001D098 +:1014E80001D03AD0030103EEE5F0EECF44F7EDCF9B +:1014F80045F703010301E7510701445F03010301B5 +:10150800E8510701455B030103EEE1F0EECF46F732 +:10151800EDCF47F703010301DF510701465F0301E0 +:101528000301E0510701475BFF0E0701462507014C +:10153800486FFF0E070147210701496F0701445112 +:101548000701485D07010701416F07014551070180 +:1015580049590701426F1DD0030103EEE7F0EECFB2 +:1015680044F7EDCF45F703010301E5510701445F57 +:1015780003010301E6510701455BFF0E07014425FE +:1015880007010701416FFF0E070145210701426F5F +:1015980000D012007BD046C7B2F747C7B3F744C79D +:1015A800B0F745C7B1F741C7AEF742C7AFF718EC78 +:1015B8001AF075D0070107014129D8B44229D8B4D7 +:1015C80001D001D006D041C7AEF742C7AFF786ECCD +:1015D80022F0100E07010701486F000E0701496F3E +:1015E8004CD007010701485107010701465D070173 +:1015F80007014951070107014759D8B001D001D067 +:1016080004D046C748F747C749F748C7B2F749C79C +:10161800B3F744C7B0F745C7B1F707014A0E07014A +:101628000701AE6F0701070E0701AF6F18EC1AF03C +:1016380048C7C4F749C7C5F707014A0E070107019C +:10164800C26F0701070E0701C36FB8EC1FF007014F +:1016580007014851070107014427000E0701070148 +:10166800452307010701485107010701465F0701A4 +:101678000701495107010701475B07010701475166 +:101688004611D8A401D001D0ACD709D00701070171 +:101698004351000A8FE0010A01E17DD700D0120012 +:1016A8002FC7E9FF30C7EAFF010EEE6E230EEE6E7C +:1016B800450EEE6E670EED6EED52ED52040E07010B +:1016C80007012F25E96E000E070107013021EA6E98 +:1016D800890EEE6EAB0EEE6ECD0EEE6EEF0EED6E6B +:1016E800ED52ED52080E070107012F25E96E000E95 +:1016F800070107013021EA6EFE0EEE6EDC0EEE6E7B +:10170800BA0EEE6E980EED6EED52ED520C0E07010C +:1017180007012F25E96E000E070107013021EA6E47 +:10172800760EEE6E540EEE6E320EEE6E100EED6EFE +:10173800ED52ED52100E070107012F25E96E000E3C +:10174800070107013021EA6EF00EEE6EE10EEE6E33 +:10175800D20EEE6EC30EED6EED52ED52140E070171 +:1017680007012F25E96E000E070107013021EA6EF7 +:10177800000EEE6E000EEE6E000EEE6E000EED6EBA +:10178800ED52ED52580E070107012F25E96E000EA4 +:10179800070107013021EA6E010EEF6E1200D9CE63 +:1017A800A6F7EECEA4F7EFCEA5F707010701A651DD +:1017B8000E010E01D96301D001D0F1D7ECCEA6F706 +:1017C800EDCEA7F707010701A45107010701A65DA0 +:1017D80007010701A55107010701A759D8B001D092 +:1017E80001D01ED00701A4C7A8F70701A5C7A9F70C +:1017F80007010701A6510701A85F07010701A751C3 +:101808000701A95B0701A851CD0807010701A26FCD +:101818000701A951D8A0E82A0A080701A36F35D003 +:1018280007010701A75107010701A51906E10701EB +:101838000701A65107010701A419D8A401D001D0B6 +:1018480008D0CD0E07010701A26F0A0E0701A36F8A +:101858001CD00701A6C7A8F70701A7C7A9F7070162 +:101868000701A4510701A85F07010701A551070156 +:10187800A95BFF0E0701A82507010701A26FFF0E4C +:101888000701A9210701A36F00D012006DD029D04C +:10189800ACC7B2F7ADC7B3F7A9C7B0F7AAC7B1F7D6 +:1018A800A6C7AEF7A7C7AFF718EC1AF022D0070102 +:1018B8000701A629D8B4A729D8B401D001D006D0E9 +:1018C800A6C7AEF7A7C7AFF786EC22F0ACC7C4F738 +:1018D800ADC7C5F7A9C7C2F7AAC7C3F7B8EC1FF0C9 +:1018E80008D007010701A851000AE1E0010AD0E089 +:1018F80000D042D031D007010701A929D8B4AA29BC +:10190800D8B401D001D006D0A9C7AEF7AAC7AFF79F +:1019180090EC22F0ACC7C6F7ADC7C7F7A6C7C4F7A7 +:10192800A7C7C5F7A4EC19F0E4D7ACC7B2F7ADC7A1 +:10193800B3F7A9C7B0F7AAC7B1F7A6C7AEF7A7C745 +:10194800AFF7F8ECD1F000D07CEC22F00009D8B465 +:1019580001D001D0F9D7CDD707010701A851000A56 +:10196800E4E0010AC8E0C5D707010701AB51000A46 +:10197800C1E0010A8CE000D012000DC713F77FEC1C +:1019880010F013C710F714C711F707010701115119 +:101998001011D8A401D001D002D0000E63D00DC719 +:1019A80060F784EC0EF0070107010F510E11D8B44F +:1019B80001D001D01BD0010E07010701AC6F000E4A +:1019C8000701AD6FFAC3ABF7EBC3A9F7ECC3AAF7EE +:1019D8000701126F010E07010701A86F07011251D5 +:1019E8000EC7A6F70FC7A7F74AEC0CF0030103EEE2 +:1019F800EBF0EE2A000EED22030113EEE3F0E652BF +:101A0800EE52ED50E55C02E1EF50E75CD8B001D052 +:101A180001D004D0E1C3EBF3E2C3ECF30701070103 +:101A280010051111D8A401D001D003D00301F78506 +:101A380017D003010301F6BB01D001D011D0030177 +:101A4800F68B55EC20F01F0E0701070170250301E6 +:101A58000301F16F000E0701070171210301F26F05 +:101A6800010E00D0120001D000D007010701345147 +:101A78000701376F0701070135510701386F070163 +:101A8800344B352B37C7F6FF38C7F7FF000EF86E13 +:101A98000E0EF76403D00800F55005D0F6CFE9FF25 +:101AA800F7CFEAFFEF500701396F070132C7F6FF9A +:101AB800070133C7F7FF000EF86E0E0EF76403D068 +:101AC8000800F55005D0F6CFE9FFF7CFEAFFEF5051 +:101AD80007013A6F0701395107013A5D070107010C +:101AE800366F0701366701D001D023D007010701FF +:101AF80032510701376F0701070133510701386F6A +:101B08000701324B332B37C7F6FF38C7F7FF000EF4 +:101B1800F86E0E0EF76403D00800F55005D0F6CF26 +:101B2800E9FFF7CFEAFFEF500009D8A401D001D0B0 +:101B38009BD707010701365107010701326F0701DB +:101B4800336B070132BF330700D01200000E0701C4 +:101B580007013A6F000E07013B6F000E07013C6F4B +:101B6800000E07013D6F3FEC21F00009D8A401D019 +:101B780001D00ED0000E07010701326F000E0701D9 +:101B8800336F000E0701346F000E0701356F4AD01E +:101B9800252A3AD00401000E2524E96EEA6A0401D8 +:101BA800040EEA22EF5007013E6F07013E5107017C +:101BB8000701366F0701376B0701386B0701396B6F +:101BC800252A07013651730A371138113911D8A45B +:101BD80001D001D001D01DD00701040ED890070113 +:101BE8003A3707013B3707013C3707013D37E82EF5 +:101BF800F5D736C73FF7FDEC12F007013E6F070136 +:101C08003E51070107013A13C70E256401D001D0E0 +:101C1800C1D73AC732F73BC733F73CC734F73DC79C +:101C280035F700D0120077ECE7F0D8C4F8F3D9C440 +:101C3800F9F3DFC3E5F3E0C3E6F3DFC3E7F3E0C39B +:101C4800E8F3E1C3E9F3E2C3EAF3E1C3EBF3E2C388 +:101C5800ECF30701716F0D0E07010701706F0701A3 +:101C6800715103010301F6A701D001D008D0070183 +:101C7800716F040E07010701706F0701715170C77A +:101C8800F5F30301F6910301F6930301F6950B00B2 +:101C98000E000301F6990301F69B0301F69D03016B +:101CA800F69F0301F7910301F7930301F7950301E9 +:101CB800F7970301F7890401EA910401EA93040103 +:101CC800EA970401EA99DFC3D4F4E0C3D5F41FEC22 +:101CD80015F072C7CCF473C7CDF41FEC15F072C7BA +:101CE800CEF473C7CFF404010401E8690401E9697B +:101CF800010E04010401DA6F000E0401DB6F12000B +:101D080007010701605106010601E46301D001D013 +:101D180001D05CD006010601E451FE0AD8B401D016 +:101D280001D022D01C0E07010701B26F000E070177 +:101D3800B36F0301DF0E07010701B06F0301030E44 +:101D48000701B16F06010601E4511C0D00016F0E79 +:101D5800F32407010701AE6F0701AF6B0001000E06 +:101D68000701AF2318EC1AF060C7E4F60701070172 +:101D78006051FE0AD8A401D001D001D027D01C0E92 +:101D880007010701B26F000E0701B36F07010701D2 +:101D980060511C0D6F0E0701616F000E626FF350EA +:101DA80007016127E86AF3BEE8680701622361C793 +:101DB800B0F762C7B1F70301DF0E07010701AE6F85 +:101DC8000301030E0701AF6F18EC1AF0120021C0CF +:101DD80025F05CD00701316F040E07010701346F4D +:101DE8000701315107012D0E07010701326F070165 +:101DF800070E0701336F99EC05F00009D8A401D04C +:101E080001D002D0000E49D007012D0E07010701AD +:101E1800346F0701070E0701356F2BC732F72CC740 +:101E280033F737EC0DF0070133513211D8A401D044 +:101E380001D002D0010E31D03FEC21F00009D8B416 +:101E480001D001D003D0AAEC0DF011D00701316FF9 +:101E5800000E07010701346F07013151000E070119 +:101E68000701326F000E0701336F99EC05F004018A +:101E7800000E2524E96EEA6A0401040EEA22730EB4 +:101E8800EF6201D001D002D0000E07D0C70E256442 +:101E980001D001D09FD7000E00D01200020E07011A +:101EA8000701BC25E96E000E07010701BD21EA6E96 +:101EB8000701EECFBEF70701EDCFBFF7B8EC21F071 +:101EC800020E07010701BC25E96E000E0701070194 +:101ED800BD21EA6E0701BEC7EEFF0701BFC7EDFFD0 +:101EE800040E07010701BC25E96E000E0701070172 +:101EF800BD21EA6E0701EECFBEF70701EDCFBFF7B0 +:101F0800B8EC21F0040E07010701BC25E96E000EAC +:101F180007010701BD21EA6E0701BEC7EEFF0701F1 +:101F2800BFC7EDFF0A0E07010701BC25E96E000EC9 +:101F380007010701BD21EA6E0701EECFBEF70701D1 +:101F4800EDCFBFF7B8EC21F00A0E07010701BC2559 +:101F5800E96E000E07010701BD21EA6E0701BEC741 +:101F6800EEFF0701BFC7EDFF12000094000E2A6EB6 +:101F780000922BC7E9FF2CC7EAFFEF502B6EB18008 +:101F880000D000A201D001D0FCD7010E0701070143 +:101F98002D6F000E07012E6F2FD0070107012D515D +:101FA800070107012B25E96E070107012E510701DB +:101FB80007012C21EA6E010EEF6201D001D002D098 +:101FC800008416D00092070107012D51070107016F +:101FD8002B25E96E070107012E51070107012C2166 +:101FE800EA6EEF502B6E00D000A201D001D0FCD7D2 +:101FF800070107012D4B2E2B070107012D51070162 +:1020080007012B25E96E070107012E51070107017A +:102018002C21EA6EEF50D8A401D001D0BED700928F +:1020280000D000A201D001D0FCD7B190899812004D +:1020380000EE8BF017EE0DF0140EEECFE6FFE82E53 +:10204800FCD719EC22F0A3C7B1F6A4C7B2F6A5C70E +:10205800B3F6A6C7B4F60701216F140E07010701EE +:10206800346F0701215107010D0E07010701326F77 +:102078000701070E0701336F99EC05F00009D8A492 +:1020880001D001D001D036D0DA0E07010701346F34 +:10209800FF0E0701356F07010D0E07010701326FAB +:1020A8000701070E0701336F37EC0DF007013351B5 +:1020B8003211D8A401D001D003D03FECD7F01AD008 +:1020C800570E07010701346FFF0E0701356F07012F +:1020D8000D0E07010701326F0701070E0701336F65 +:1020E80037EC0DF0070133513211D8A401D001D0DB +:1020F80001D0FF00120013C760F784EC0EF0030153 +:1021080003EEEBF0030113EEE9F0E652EE52ED5068 +:10211800E55C02E1EF50E75CD8A001D001D012D015 +:1021280003010301EB5103010301E95D0701070105 +:10213800136F03010301EC5103010301EA5907017D +:10214800146F3AD0030103EEE9F0EECF15F7EDCFA7 +:1021580016F703010301E1510701155F03010301AC +:10216800E2510701165B030103EEE3F0EECF17F728 +:10217800EDCF18F703010301EB510701175F0301C6 +:102188000301EC510701185B0701155107011725D9 +:102198000701196F070116510701182107011A6F66 +:1021A800010E0701192507010701136F000E07012A +:1021B8001A210701146F00D012000701316F000EB9 +:1021C80007010701306F070131512DC7E9FF2EC7FD +:1021D800EAFFEF5007010701346F2BC7E9FF2CC74F +:1021E800EAFF0701EECF32F70701EDCF33F709EC2D +:1021F8001DF0D8B001D002D0010E01D0000E0701A9 +:1022080007012F6F07010701302B2DC734F72EC7A1 +:1022180035F72BC732F72CC733F753EC1CF02DC713 +:10222800E9FF2EC7EAFFEF5007010701346F2BC7FC +:10223800E9FF2CC7EAFF0701EECF32F70701EDCF20 +:1022480033F709EC1DF0D8B001D002D0010E01D04F +:10225800000E070107012F19D8B401D001D004D00E +:102268000701070130510AD0070107013029D8A416 +:1022780001D001D002D0000E01D0C4D71200010154 +:10228800000E070107012F6F0101010E0701306FD2 +:1022980054EC0BF00401000E070107013C6F040128 +:1022A800040E07013D6F1FEC17F03CC733F73DC71D +:1022B80034F70401000E07010701316F0401040E11 +:1022C8000701326F0101000E070107012F6F01019D +:1022D800010E0701306F3AECDFF0200E070107010D +:1022E800336F000E0701346F8E0E07010701316F3F +:1022F800FE0E0701326F0101000E070107012F6F63 +:102308000101010E0701306F68ECDEF000019F0E3D +:1023180007010701316F0001000E0701326F01014B +:10232800000E070107012F6F0101010E0701306F31 +:1023380008ECB2F012007CC7E9FF7DC7EAFF07018D +:10234800EECFBEF70701EDCFBFF7B8EC21F07CC7A1 +:10235800E9FF7DC7EAFF0701BEC7EEFF0701BFC758 +:10236800EDFF020E070107017C25E96E000E07014B +:1023780007017D21EA6E0701EECFBEF70701EDCF19 +:10238800BFF7B8EC21F0020E070107017C25E96EC2 +:10239800000E070107017D21EA6E0701BEC7EEFFA7 +:1023A8000701BFC7EDFF060E070107017C25E96E8F +:1023B800000E070107017D21EA6E0701EECFBEF787 +:1023C8000701EDCFBFF7B8EC21F0060E07010701B2 +:1023D8007C25E96E000E070107017D21EA6E0701E1 +:1023E800BEC7EEFF0701BFC7EDFF120042D013C7FB +:1023F800E9FF14C7EAFFEF50D8B401D001D016D0D6 +:10240800070115C7F6FF070116C7F7FF000EF86E9C +:102418000800F5CF19F713C7E9FF14C7EAFFEF5013 +:1024280007011919D8B401D001D01BD013C7E9FF8F +:1024380014C7EAFFEF500701196F070115C7F6FF28 +:10244800070116C7F7FF000EF86E0800F5500701E0 +:10245800195D07010701136F0701146BD8A0140752 +:102468001DD007010701134B142B07010701154B5A +:10247800162B070107011707D8A018070701172906 +:10248800D8B41829D8A401D001D0B1D7000E0701BB +:102498000701136F000E0701146F00D01200070127 +:1024A80007010C29D8B40D29D8A401D001D006D031 +:1024B800070107010C6907010D6946D007010701EB +:1024C8000F51800A0701106F07010C51070107011E +:1024D8000E5D070107010D51800A07011059D8A0A8 +:1024E80001D001D012D0070107010C5107010701E3 +:1024F8000E5D070107010C6F070107010D51070168 +:1025080007010F5907010D6F1FD0000E0701106F4B +:10251800020E116F070107010C510701105F070137 +:1025280007010D510701115B070107010E51070152 +:102538001025070107010C6F070107010F5107015B +:10254800112107010D6F00D01200CF0E0E010E01F0 +:10255800E26F0A0E0E01E36F0701DC0E0701BF27C9 +:102568000A0E0701C023BFC7E6FEC0C7E7FE060E76 +:1025780007010701C46F000E0701C56FBCC7C2F78A +:10258800BDC7C3F7B8EC1FF0060E07010701C46FFB +:10259800000E0701C56F0601690E07010701C26F2A +:1025A8000601060E0701C36FB8EC1FF00701C16FE3 +:1025B800080E07010701C26F0701C151BEEC22F0E6 +:1025C8000701C16F060E07010701C26F0701C1515C +:1025D80007010701BE6701D001D008D00701C16F0C +:1025E800000E07010701C26F0701C151BEEC22F0BE +:1025F800120020D0000E50D0010E4ED0020E4CD04A +:10260800030E4AD0040E48D0050E46D0060E44D01C +:10261800070E42D0080E40D0090E3ED00A0E3CD01C +:102628000B0E3AD00C0E38D00D0E36D00E0E34D01C +:102638000F0E32D0070107013F51300ADBE0010AD3 +:10264800DBE0030ADBE0010ADBE0070ADBE0010A62 +:10265800DBE0030ADBE0010ADBE00F0ADBE0010A4A +:10266800DBE0780ADBE0030ADBE0010ADBE0070ACB +:10267800DBE0010ADBE0030ADBE0270ACFE0030A1C +:10268800CFE0010ACFE0070ACFE0010ACFE0030A52 +:10269800CFE000D0000E00D01200000E07010701A5 +:1026A8007C6F000E07017D6F000E07017E6F000E24 +:1026B80007017F6F0701070174A101D001D018D06D +:1026C800070107017851070107017C270701070166 +:1026D8007951070107017D23070107017A51070195 +:1026E80007017E23070107017B51070107017F23AB +:1026F8000701D890070178370701793707017A373A +:1027080007017B370701D890070177330701763334 +:102718000701753307017433070177517411751177 +:102728007611D8A401D001D0C5D77CC774F77DC76E +:1027380075F77EC776F77FC777F700D012000301D9 +:102748000301FB510F5C03010301FC511058D8B081 +:1027580001D001D008D006010601E3512318D8B4EE +:1027680001D001D001D038D00F5003010301FB5D27 +:1027780007010701516F105003010301FC590701BC +:10278800526F070107014F5107010701515D07010A +:1027980007015051070107015259D8B001D001D0A3 +:1027A80004D051C74FF752C750F74FC7C6F750C7A5 +:1027B800C7F74DC7C4F74EC7C5F7A4EC19F0C4C78F +:1027C8004FF7C5C750F7070107014F510F260701FB +:1027D80007015051102200D0120033C73CF734C70C +:1027E8003DF71FEC17F0070107013C5107010701EE +:1027F8003C6F59EC1DF007010701366F33C73CF7F2 +:1028080034C73DF71FEC17F0070107013C510701DA +:102818000701486F31EC1DF007010701356F07010B +:1028280007013651300AD8B401D001D004D036C7D8 +:1028380048F7D0EC1DF035C748F7D0EC1DF007017C +:10284800376F3A0E07010701486F07013751D0EC7F +:102858001DF033C73EF734C73FF70401000E0701E8 +:1028680007013C6F0401040E07013D6F65EC17F08A +:10287800120037C73CF738C73DF71FEC17F00701C0 +:1028880007013C51070107013C6F59EC1DF0070196 +:1028980007013A6F37C73CF738C73DF71FEC17F009 +:1028A800070107013C5107010701486F31EC1DF092 +:1028B80007010701396F070107013A51300AD8B4F7 +:1028C80001D001D004D03AC748F7D0EC1DF039C781 +:1028D80048F7D0EC1DF007013B6F3A0E07010701DE +:1028E800486F07013B51D0EC1DF037C73EF738C79A +:1028F8003FF70401000E070107013C6F0401040EB5 +:1029080007013D6F65EC17F0120026C72DF727C7A2 +:102918002EF724C72BF725C72CF7E1EC10F0070199 +:102928000701296F130E07010701296501D001D09E +:1029380009D0290E07010701296101D001D002D071 +:10294800000E2DD026C72DF727C72EF724C72BF743 +:1029580025C72CF7E1EC10F007010701286F010EDD +:1029680007010701296501D001D017D0150E07010D +:102978000701296101D001D010D0010E070107011C +:10298800286501D001D009D0150E0701070128617B +:1029980001D001D002D0010E02D0020E00D01200E8 +:1029A800D8901A3607010701F051D8B401D001D0E8 +:1029B80011D01B2A1B50030AD8A401D001D003D080 +:1029C800070E1A1206D0030E1B6401D001D001D0E5 +:1029D8001A8006D00701F16F000E1B6E0701F15136 +:1029E800D8901F36192A1AAE01D001D002D01F8004 +:1029F80000D01950080AD8A401D001D01BD0070173 +:102A0800F16F000E196E0701F151DF0E1724E96E00 +:102A1800010E1820EA6E1FC0EFFF174A182A185037 +:102A2800020A1710D8A401D001D004D0000E176EE6 +:102A3800000E186E1200296601D001D009D0010ECF +:102A480007010701746F000E0701756F7DEC20F018 +:102A58006D0E07010701786F4E0E0701796FC60EDC +:102A680007017A6F410E07017B6FA1C674F7A2C6F2 +:102A780075F7A3C676F7A4C677F751EC13F0390EAD +:102A880007010701742506010601A16F300E070131 +:102A9800070175210601A26F000E070107017621C3 +:102AA8000601A36F000E0701070177210601A46F35 +:102AB800FF0E0601A31507010701726F7F0E0601BD +:102AC800A4150701736F00D01200366601D001D03B +:102AD80023D007011F6F010E366E07011F51070132 +:102AE8001F6F000E070107011E6F07011F51000E1F +:102AF800070107011E6501D001D001D00DD00501E5 +:102B08000501C869070107011E2B000E070107010F +:102B18001E6501D001D0F3D705010501C829D8B435 +:102B280001D001D007D0C8C54CF787EC1AF00501D1 +:102B38000501C86907011F6F010E05010501C96F6D +:102B480007011F5107011F6F000E05010501CA6F1C +:102B580007011F510501CA890501CA83120011C75F +:102B680015F710C714F703EC08F007010701126FF7 +:102B7800070107011251FE0AD8A401D001D008D0DC +:102B8800FE0E07010701106FFF0E0701116F30D00D +:102B9800070107011229D8A401D001D006D00701E6 +:102BA800070110690701116923D0D8900232070183 +:102BB80007011251D8B401D001D001D0028E202AC9 +:102BC800080E206001D001D006D007010701106966 +:102BD800070111690DD00701136F000E206E070160 +:102BE8001351070102C010F707010701116B00D04C +:102BF800120099C7A5F69AC7A6F69BC7A7F69CC761 +:102C0800A8F69DC79FF7080E070107019F6101D02D +:102C180001D001D015D0A8C69EF7A7C6A8F6A6C6AB +:102C2800A7F6A5C6A6F69EC7A5F6080E07010701D2 +:102C38009F5F080E070107019F6101D001D0EBD704 +:102C4800070107019F6701D001D001D011D006010B +:102C5800D890A8BFD880A537A637A737A8370701C7 +:102C680007019F07070107019F6701D001D0EFD730 +:102C7800A5C699F7A6C69AF7A7C69BF7A8C69CF754 +:102C880000D012000301FDC345F70301FEC346F758 +:102C9800070107013D5107014527070107013E517B +:102CA80007014623140E0701452507010701436F55 +:102CB800000E070146210701446FCE0E07010701E8 +:102CC800435D0A0E07014459D8A001D001D007D0AE +:102CD8000701CE0E0701435F0A0E0701445BE0CEF1 +:102CE80041F7E1CE42F743C7E0FE44C7E1FE3FC7E4 +:102CF800A2F740C7A3F7D3ECE0F0A2C743F7A3C7F6 +:102D080044F741C7E0FE42C7E1FE43C73DF744C769 +:102D18003EF700D01200FACFCEF7FBCFCFF7E9CFBE +:102D2800D0F7EACFD1F7E1CFD2F7E2CFD3F7D9CFB7 +:102D3800D4F7DACFD5F7F3CFD6F7F4CFD7F7F6CF66 +:102D4800D8F7F7CFD9F7F8CFDAF7F2A401D001D046 +:102D580002D007EC21F09EA201D001D003D0E8EC0C +:102D6800E3F09E92DAC7F8FFD9C7F7FFD8C7F6FF96 +:102D7800D7C7F4FFD6C7F3FFD5C7DAFFD4C7D9FF43 +:102D8800D3C7E2FFD2C7E1FFD1C7EAFFD0C7E9FF47 +:102D9800CFC7FBFFCEC7FAFFCDC7E0FFCCC7E8FF20 +:102DA800CBC7D8FF1000EACFE6F7E1CFE7F7E2CFCD +:102DB800E8F7D9CFE9F7DACFEAF7F3CFEBF7F4CFB3 +:102DC800ECF7F6CFEDF7F7CFEEF7F8CFEFF7A4A6CD +:102DD80001D001D00BD0E20E786E000E81B8010E42 +:102DE80007010701F06FD4EC14F0A496A1A201D05A +:102DF80001D006D0B368C40EB26E01EC20F0A192E7 +:102E0800EFC7F8FFEEC7F7FFEDC7F6FFECC7F4FF13 +:102E1800EBC7F3FFEAC7DAFFE9C7D9FFE8C7E2FF64 +:102E2800E7C7E1FFE6C7EAFFE5C7E9FFE4C7FBFF3D +:102E3800E3C7FAFF11003CC73EF73DC73FF701D093 +:102E480000D0070107013E510701406F0701070144 +:102E58003F510701416F07013E4B3F2B40C7F6FF2B +:102E680041C7F7FF000EF86E0E0EF76403D0080096 +:102E7800F55005D0F6CFE9FFF7CFEAFFEF5000098C +:102E8800D8A401D001D0DCD707013EC740F707011D +:102E98003FC741F7070107013C510701405F0701A0 +:102EA80007013D510701415BFF0E0701402507015E +:102EB80007013C6FFF0E0701412107013D6F00D05C +:102EC80012003CC740F73DC741F704D0070107018E +:102ED800404B412B40C7E9FF41C7EAFFEF50D8A458 +:102EE80001D001D0F3D700D0070107013E510701F7 +:102EF800426F070107013F510701436F07013E4B2E +:102F08003F2B42C7F6FF43C7F7FF000EF86E0701D5 +:102F180040C7E1FF070141C7E2FF07010701404B36 +:102F2800412B0E0EF76403D00800F55005D0F6CFFC +:102F3800E9FFF7CFEAFFEF50E76EE750D8A401D0DA +:102F480001D0D1D700D012001150C00807010701E5 +:102F5800576F1250D8A0E82A05080701586F0701D3 +:102F68000701555107010701575D07010701565130 +:102F7800070107015859D8B001D001D004D057C76C +:102F880055F758C756F7070107015551112607018C +:102F98000701565112221150135C12501458D8B020 +:102FA80001D001D004D011C013F012C014F055C7DD +:102FB8005BF756C75CF753C759F754C75AF7C8ECBD +:102FC8001EF055C753F756C754F700D012001150DA +:102FD800C00807010701576F1250D8A0E82A050852 +:102FE8000701586F07010701555107010701575D90 +:102FF800070107015651070107015859D8B001D0F8 +:1030080001D004D057C755F758C756F7070107012D +:103018005551112607010701565112221150135C10 +:1030280012501458D8B001D001D004D011C013F0F8 +:1030380012C014F055C7C4F756C7C5F753C7C2F72F +:1030480054C7C3F7B8EC1FF055C753F756C754F722 +:1030580000D0120007014C0E070107014D6F070150 +:10306800070E07014E6F86EC1EF00009D8A401D0A8 +:1030780001D001D02DD0070107014C51C00BC00A67 +:10308800D8A401D001D00CD007014C0E07010701CC +:103098004D6F0701070E07014E6F86EC1EF018D022 +:1030A800070107014C6701D001D001D011D00701F9 +:1030B80007014CC74FF707010701506B000E0701C6 +:1030C80007014D6F000E07014E6FA3EC13F0C2D736 +:1030D80012000F0E070107011E6501D001D017D09D +:1030E8000A0E070107011F6101D001D010D00F0E91 +:1030F80007010701206501D001D009D00A0E070198 +:103108000701216101D001D002D0000E20D00A0EA3 +:10311800070107011E6101D001D017D00F0E07016A +:1031280007011F6501D001D010D00F0E070107015C +:10313800206501D001D009D00A0E070107012161DD +:1031480001D001D002D0010E02D0020E00D0120030 +:103158000F0E070107011E6501D001D017D00A0E16 +:10316800070107011F6101D001D010D00A0E070125 +:103178000701206101D001D009D00A0E070107011B +:10318800216101D001D002D0000E20D00A0E070123 +:1031980007011E6101D001D017D00A0E07010701EF +:1031A8001F6101D001D010D00F0E07010701206563 +:1031B80001D001D009D00A0E07010701216101D011 +:1031C80001D002D0010E02D0020E00D012000D0E66 +:1031D800070107011E6101D001D017D00D0E0701AC +:1031E80007011F6101D001D010D00D0E07010701A2 +:1031F800206101D001D009D0100E07010701216517 +:1032080001D001D002D0010E20D00D0E0701070118 +:103218001E6101D001D017D0100E070107011F65EC +:1032280001D001D010D00D0E07010701206101D097 +:1032380001D009D00D0E07010701216101D001D08D +:1032480002D0000E02D0020E00D012001EC72DF7C9 +:103258001FC72EF71CC72BF71DC72CF7E1EC10F082 +:1032680007010701206F1EC72DF71FC72EF71CC7C0 +:103278002BF71DC72CF7E1EC10F007010701216FB0 +:103288000D0E07010701206501D001D009D00D0EF0 +:1032980007010701216501D001D002D0000E12D02C +:1032A8000A0E07010701206101D001D009D00D0ED7 +:1032B80007010701216501D001D002D0010E02D01B +:1032C800020E00D0120043EC11F00701146F000E3B +:1032D80007010701136F07011451130E07010701B6 +:1032E800136501D001D001D028D0380E070107019D +:1032F8001325E96EEA6A000EEA22EF500701146FFF +:1033080000019F0E070107011325E96EEA6A000113 +:10331800000EEA22EF5007011419D8B401D001D0E9 +:1033280002D0000E0CD007010701132B130E070162 +:103338000701136501D001D0D8D7010E00D01200C3 +:10334800C6C7C9F7C7C7CAF707010701C551C411DE +:10335800D8B401D001D01AD00BD0C4C7E9FFC5C773 +:10336800EAFF0E01FACEEFFF07010701C44BC52B98 +:1033780007010701C907D8A0CA070701C929D8B496 +:10338800CA29D8A401D001D0E8D710D002D0FACEEB +:10339800C8F707010701C907D8A0CA070701C92943 +:1033A800D8B4CA29D8A401D001D0F1D7C6C7C4F768 +:1033B800C7C7C5F700D0120007010E6F000E07013E +:1033C80007010D6F07010E511BD00DC711F707013B +:1033D8000E6FA00E07010701106F07010E5168EC70 +:1033E800E2F007010701105109C7E9FF0AC7EAFF20 +:1033F800EF6E07010701094B0A2B070107010D2B87 +:1034080007010DC70EF707010F6B070107010B51E5 +:1034180007010E5D070107010C5107010F59D8A0DC +:1034280001D001D0D2D71200B0C7B6F7B1C7B7F7ED +:10343800AEC7B4F7AFC7B5F720D00701B6C7F6FFD8 +:103448000701B7C7F7FF000EF86EB4C7E1FFB5C7AD +:10345800E2FF0E0EF76403D00800F55005D0F6CF52 +:10346800E9FFF7CFEAFFEF50E76E07010701B64B18 +:10347800B72B07010701B44BB52B07010701B207AA +:10348800D8A0B3070701B229D8B4B329D8A401D06A +:1034980001D0D3D700D012001CEC1EF00009D8A42C +:1034A80001D001D008D0000E070107014C6F000EB3 +:1034B80007014D6F27D006010601E05107010701FA +:1034C8004C19D8B401D001D00FD04CC7E0F6000E8B +:1034D800136E000E146E000E070107014E6F000EEA +:1034E80007014F6F91EC20F04CC723F01350C00830 +:1034F800070107014C6F1450D8A0E82A05080701F6 +:103508004D6F00D01200040E070107014C6501D071 +:1035180001D001D02CD0070107014C510E0DF3CF7B +:103528004DF70C0E07014D270101590E07014D25D6 +:10353800E96EEA6A0101010EEA22000EEE6E000E43 +:10354800ED6E070107014C510E0D0101590EF324D0 +:10355800E96EEA6A0101010EEA22000EEE6E000E23 +:10356800EE6E000EEE6E000EED6EED52ED52120094 +:103578000001B30E07010701336F0001000E0701B8 +:10358800346F2DC731F72EC732F706ECC1F00009AA +:10359800D8B401D001D00AD037820701306F070EA6 +:1035A80006010601E56F0701305116D0000E04012F +:1035B8000401EF6F000E0401F06F2DC7F1F42EC760 +:1035C800F2F40701306F000E06010601E56F0701EE +:1035D80030512FC733F0379212000001B30E0701A4 +:1035E8000701336F0001000E0701346F2DC731F753 +:1035F8002EC732F789ECC2F00009D8B401D001D047 +:103608000AD037820701306F070E06010601E56F01 +:103618000701305116D02DC7EFF42EC7F0F4000E75 +:1036280004010401F16F000E0401F26F0701306F0D +:10363800000E06010601E56F070130512FC733F070 +:10364800379212003450D8B401D001D001D02DD017 +:1036580007014E6F010E346E07014E51FF0E000137 +:103668000001FB25070107014C6FFF0E0001000157 +:10367800FC2107014D6FCE0E070107014C5D0A0EB4 +:1036880007014D59D8A001D001D007D0CD0E0701B0 +:1036980007014C6F0A0E07014D6F0E01FE8D4CC7D6 +:1036A800ECFE4DC7EDFE0E01FC9D1200000E070159 +:1036B8000701646F000E0701656F0701070160A12C +:1036C80001D001D00CD007010701625107010701A1 +:1036D80064270701070163510701070165230701F3 +:1036E800D89007016237070163370701D8900701AF +:1036F8006133070160330701070161516011D8A4E4 +:1037080001D001D0DAD764C760F765C761F700D088 +:1037180012000701086F000E276E07010851060105 +:10372800688F7AECC5F016C774F717C775F77DEC84 +:1037380020F0BCECDCF0A8EC1EF0E8EC1EF045EC48 +:10374800C8F00701086F000E070107011D6F070188 +:10375800085169EC15F00601060168BD01D001D0D9 +:103768000AD00701086F000E07010701096F07015A +:103778000851EAEC1FF012000301FDC37DF70301B5 +:10378800FEC37EF707010701795107017D2707016D +:1037980007017A5107017E23140E07017D250701D1 +:1037A80007017B6F000E07017E2107017C6FCE0E9B +:1037B800070107017B5D0A0E07017C59D8A001D0DB +:1037C80001D007D00701CE0E07017B5F0A0E070163 +:1037D8007C5B7BC7E0FE7CC7E1FE12004CC723F090 +:1037E80006010601E351070107014C19D8B401D0BD +:1037F80001D008D0000E070107014C6F000E070129 +:103808004D6F1CD01EA001D001D00AD01E90000E12 +:10381800070107014E6F000E07014F6F69EC20F09A +:103828000F5003010301FB5D070107014C6F1050A6 +:1038380003010301FC5907014D6F00D01200320E3D +:10384800070107015A6F000E07015B6F000E0701A1 +:103858000701586F000E0701596F06016F0E070127 +:103868000701566F0601060E0701576F08EC1FF097 +:10387800000E0D6E000E0E6E07010D6F000E226E0B +:1038880007010D5107010D6F000E076E07010D515D +:1038980007010D6F000E266E07010D51120034C787 +:1038A800E9FF35C7EAFFD890EF3634C7E9FF35C7D7 +:1038B800EAFFEF50D8A401D001D01FD034C7E9FFE8 +:1038C80035C7EAFF010EEF6E32C7E9FF33C7EAFFDB +:1038D800EE50ED10D8A401D001D008D032C7E9FFCE +:1038E80033C7EAFF000EEE6E020EED6E32C7E9FF37 +:1038F80033C7EAFFEE06000EED5A120015C7C9FFDE +:10390800C6AE01D001D002D0FF0E25D000D0C7B07E +:1039180001D001D0FCD700D0C5CF16F71F0E070184 +:10392800161716C717F70701186B000EC7B4010E54 +:1039380007011713000E1813070118511711D8A4FF +:1039480001D001D0E9D7C5AC01D001D002D0FE0E1C +:1039580002D0000E00D0120007010701A75107018D +:103968000701A41B07010701A45107010701A71BB1 +:1039780007010701A75107010701A41B0701070158 +:10398800A65107010701A51B07010701A55107015A +:103998000701A61B07010701A65107010701A51B7F +:1039A800A4C7A4F7A5C7A5F7A6C7A6F7A7C7A7F7EB +:1039B80000D0120041C760F784EC0EF077ECE7F016 +:1039C800040104EED4F0030113EEE5F0E652EE52E2 +:1039D800ED50E518EFCFE8FFD8B4E718D8B401D018 +:1039E80001D012D00701426F010E07010701716F64 +:1039F800070142510701436F100E07010701706F5D +:103A080007014351B4EC9BF01200DF0E07010701D8 +:103A18003225E96E010E070107013321EA6EEF50E6 +:103A280007010701356F070107013551070134C741 +:103A380036F70701376B36BF370707013617000E11 +:103A48003717070137513611D8B401D001D002D049 +:103A5800D88002D0D89000D012000F0E07010701BD +:103A68004817300E07010701482507010701496F6C +:103A780007014A6B000E07014A23090E07010701D7 +:103A8800486501D001D00CD0370E07010701482541 +:103A980007010701496F07014A6B000E07014A2316 +:103AA80007010701495100D0120007013C3B0F0EE6 +:103AB8003C17300E070107013C25070107013D6F40 +:103AC80007013E6B000E07013E23090E070107019F +:103AD8003C6501D001D00CD0370E070107013C2509 +:103AE800070107013D6F07013E6B000E07013E23EA +:103AF800070107013D5100D01200070107014D5190 +:103B08004BC7E9FF4CC7EAFFEF6201D001D005D0EF +:103B18004BC74BF74CC74CF717D007014BC7E9FF0A +:103B280007014CC7EAFF070107014B4B4C2BEF502D +:103B3800D8A401D001D0E1D7000E070107014B6FCF +:103B4800000E07014C6F00D0120023C7B4FE00F02E +:103B58000701276F010E0E010E01B26F07012751F1 +:103B680000F000D00E010E018AB101D001D0FAD7C1 +:103B78000701276F000E0E010E01B26F07012751D2 +:103B880000F0B8CE25F700F0B9CE26F725C723F701 +:103B980026C724F700D01200000E070107014D6F59 +:103BA800000E07014E6F0401000E070107014B6F5D +:103BB8000401040E07014C6F81EC1DF04BC749F757 +:103BC8004CC74AF7070107014A514911D8B401D037 +:103BD80001D007D049C7E9FF4AC7EAFF070148C72C +:103BE800EFFF1200C80E070107015A6F000E070108 +:103BF8005B6F000E07010701586F000E0701596F30 +:103C08000401000E07010701566F0401040E0701A5 +:103C1800576F08EC1FF007012F6F000E256E070184 +:103C28002F5107012F6F000E0C6E07012F51120044 +:103C38000E010E01DFB701D001D002D0010E1BD05A +:103C480019EC22F01C5007010701A35F1D50070162 +:103C58000701A45B7A0E07010701A35D000E0701A7 +:103C6800A459D8A001D001D004D00E01DF9780EC70 +:103C78001FF0000E00D012009E92CB68CA82CA9C28 +:103C8800CA8ACA88CA869F929D82CA84000EBD6E5F +:103C9800000EBA6EBA86BA84BA9EBA9CBD86BD8436 +:103CA800BD9EBD9CBD86BD84BA86BA84BD9ABD98AA +:103CB800BA9ABA98000EBE6E000EBB6E12000D0EB8 +:103CC800070107012B6101D001D009D00D0E0701B2 +:103CD80007012C6101D001D002D0000E12D0180EBD +:103CE800070107012B6501D001D009D00D0E07018E +:103CF80007012C6101D001D002D0010E02D0020EC2 +:103D080000D0120003010301FB510F5C0301030102 +:103D1800FC511058D8B001D001D008D006010601D6 +:103D2800E3512318D8B401D001D002D0000E0BD033 +:103D3800C3EC22F04DC7E9FF4EC7EAFFEF6E0F4A0A +:103D4800102A010E00D0120000010001E9690001EB +:103D58000001EA6900010001EB6900010001EC695A +:103D680000010001ED6900010001EE69000E00018B +:103D78000001E56F000E0001E66F000E0001E76F1D +:103D8800000E0001E86F120011D0070159C7F6FFB5 +:103D980007015AC7F7FF000EF86E0800F5CFF3FFCA +:103DA80007010701594B5A2BF3CFFAFE0701070108 +:103DB8005B07D8A05C0707015B29D8B45C29D8A4A5 +:103DC80001D001D0E2D7120007010A6F000E0701E7 +:103DD8000701096F07010A51040E07010701096568 +:103DE80001D001D001D00ED009C74CF787EC1AF0EA +:103DF80007010701092B040E07010701096501D016 +:103E080001D0F2D71E82120056C75CF757C75DF77C +:103E18000BD05CC7E9FF5DC7EAFF070158C7EFFF92 +:103E2800070107015C4B5D2B070107015A07D8A062 +:103E38005B0707015A29D8B45B29D8A401D001D05F +:103E4800E8D700D012000AC7B4FE0BC7F3FF0CC7AF +:103E5800F4FFF250C00B070107010D6F3F0EF21679 +:103E6800F3CFB6FE00F0F4CFB7FE070107010D51FE +:103E7800F21200D00E010E018AB101D001D0FAD79A +:103E88001200E1C641F747EC0AF07D0E0701070171 +:103E9800415D000E07014259D8B001D001D001D0D0 +:103EA8000DD0F6EC1DF0C10E07010701376FFF0EAC +:103EB8000701386F3DEC14F092ECDDF01200C00EF3 +:103EC800115C050E1258D8A001D001D001D013D032 +:103ED80053C7C2F7BEEC22F0114A122A1150135CE4 +:103EE80012501458D8B001D001D004D011C013F02A +:103EF80012C014F000D012000E01DF8F0E01DF9FF8 +:103F0800080E07010701A26F00D007010701A207E9 +:103F18000701A229D8A401D001D0F7D70E01FC933C +:103F28000E01DF8719EC22F0A3C71CF0A4C71DF00F +:103F3800120006010601E229D8B401D001D007D049 +:103F4800E2C64CF787EC1AF006010601E2690701A0 +:103F5800306F070E06010601E56F070130513790F3 +:103F68003730010B00D012000CD0C2C7E9FFC3C71D +:103F7800EAFFEF50F36E07010701C24BC32BF3CFE3 +:103F8800FAFE07010701C407D8A0C5070701C4291D +:103F9800D8B4C529D8A401D001D0E7D712000701A9 +:103FA8000D6F010E06010601C96F07010D510601CB +:103FB8000601C669BB6819EC22F0A3C7CAF6A4C7F4 +:103FC800CBF6A5C7CCF6A6C7CDF6120005010501AC +:103FD800C829D8B401D001D007D0C8C54CF787ECA0 +:103FE8001AF005010501C86907010A6F000E0501ED +:103FF8000501C96F07010A5112002A6601D001D0D4 +:104008000AD02BC02AF0008200B401D001D002D01F +:10401800897801D000942A50D8B401D001D001D0B9 +:104028002A0612000401000E2524E96EEA6A04013A +:10403800040EEA22EF50680AD8B401D001D002D0A9 +:10404800000E04D02528216E010E00D01200F28A3D +:1040580000F0F29AD6CFF4F5D7CFF5F5A9C6F6F564 +:10406800AAC6F7F5ABC6F8F5ACC6F9F5F2B401D0B7 +:1040780001D0EDD7F28A1200F28A00F0F29AD6CF78 +:10408800F4F5D7CFF5F5A9C6F6F5AAC6F7F5ABC688 +:10409800F8F5ACC6F9F5F2B401D001D0EDD7F28A43 +:1040A800120040EC20F0F5C574F7F6C575F7F7C5B2 +:1040B80076F7F8C577F774C770F775C771F776C7DD +:1040C80072F777C773F700D01200080E07010701CF +:1040D8004E2507010701776F000E070107014F21E1 +:1040E8000701786FA8EC21F04EC70FF04FC710F00A +:1040F80012000701060174C7A1F60701060175C77A +:10410800A2F606010601A36B0601A46B0701766FF0 +:10411800010E296E070176511200F90E07010701F9 +:104128004E2507010701AE6F0A0E070107014F214F +:104138000701AF6F86EC22F04EC711F04FC712F09F +:10414800120030C73CF731C73DF71FEC17F03CC7EA +:1041580035F73DC736F730C733F731C734F72FC7C0 +:1041680032F7ADECCFF000D01200948694883F0E61 +:10417800C716000EC66E000EC56EC686C78E82862E +:104188008288C68A0701096F430EC86E0701095164 +:10419800120030C73CF731C73DF71FEC17F03CC79A +:1041A80035F73DC736F730C733F731C734F72FC770 +:1041B80032F710ECCCF000D012002BC72CF7EDEC46 +:1041C80022F09AEC22F00009D8A401D001D003D043 +:1041D800F6EC1DF004D046EC22F092ECDDF0120073 +:1041E8000701106F000E206E070110510701106FB4 +:1041F800000E246E070110510701106F000E086EA3 +:10420800070110511200F2A401D001D00ED0010E06 +:1042180006010601A927000E0601AA23000E0601C1 +:10422800AB23000E0601AC23F29412000701226FA3 +:10423800010E07010701236F07012251A9EC1DF0A8 +:10424800230EE96E070EEA6EEF30E832010B00D05C +:1042580012000AC73CF70BC73DF71FEC17F03CC725 +:1042680055F73DC756F70AC753F70BC754F7EBEC9A +:1042780017F000D012000401000E2524E96EEA6A46 +:104288000401040EEA22EF50690AD8B401D002D022 +:10429800010E01D0000E00D012001EB201D001D0D4 +:1042A8000DD026EC1BF0000E03010301FB6F000E7E +:1042B8000301FC6F06010601E3691E8212000AC7AA +:1042C8003CF70BC73DF71FEC17F03CC755F73DC748 +:1042D80056F70AC753F70BC754F7A8EC17F000D0E6 +:1042E8001200E1C641F747EC0AF0F6EC1DF0880E23 +:1042F80007010701376FFF0E0701386F3DEC14F017 +:1043080067EC22F0120031C737F732C738F73DECB7 +:1043180014F033C737F734C738F735C739F736C716 +:104328003AF7C4ECE6F012000DC760F784EC0EF023 +:1043380003010301F551070AD8B401D002D0010ED8 +:1043480001D0000E00D01200325007010701772576 +:1043580007010701796F000E07010701782107019E +:104368007A6FC0EC1BF01200BEC7C1F7BFC7C2F717 +:10437800C2C7C0F7C1C7C2F7C0C7C1F7C1C7BEF738 +:10438800C2C7BFF700D012002DC733F72EC734F7C6 +:104398002FC735F730C736F72BC731F72CC732F799 +:1043A80087EC21F01200000ED76E000ED66EF19445 +:1043B800F294F28A0701086F870ED56E070108513B +:1043C800120076927690769C769A7688769676849F +:1043D800A4967768A38697949388A58612002FC71A +:1043E80033F730C734F7F1EC13F031C737F732C77A +:1043F80038F73DEC14F0120020C725F71EC723F745 +:104408001FC724F71CC721F71DC722F7FFEC02F0CE +:1044180012002BEC20F0F4C5DFF7F5C5E0F7F6C580 +:10442800E1F7F7C5E2F700D0120040EC20F0F4C540 +:10443800A3F7F5C5A4F7F6C5A5F7F7C5A6F700D005 +:1044480012000DC760F784EC0EF00301F6970DC754 +:104458002DF729ECE3F0120007010E6F020E06019A +:104468000601D26F07010E510DC7CFF612000701E2 +:104478000E6F020E06010601C96F07010E510DC726 +:10448800C6F6120007012C6F730E07010701486F6B +:1044980007012C51D0EC1DF012002DC731F72EC7A3 +:1044A80032F72BC72FF72CC730F7F3EC21F01200A7 +:1044B80019EC22F0A3C7ADF6A4C7AEF6A5C7AFF6B0 +:1044C800A6C7B0F6120007012B6F680E0701070197 +:1044D800486F07012B51D0EC1DF0120037A001D016 +:1044E80001D002D0000E03D03780010E00D0120098 +:1044F8000E010E01DFAB01D002D0010E01D0000E7B +:1045080000D01200E2CEB0F7E3CEB1F7AEC7E2FEBC +:10451800AFC7E3FE00D01200E0CEB0F7E1CEB1F7AE +:10452800AEC7E0FEAFC7E1FE00D012002850030A74 +:10453800D8B401D002D0010E01D0000E00D0120074 +:104548000C50040AD8B401D002D0010E01D0000EDC +:1045580000D01200979292988998B19AB198A08247 +:10456800A282B19012003BECD5F0F0ECBDF02EEC3D +:10457800B5F01200C2C7F3FFF3CFFAFE12000E0126 +:104588000E01FA5100D012000501CA51010B00D0EA +:104598001200EAEC22F0B190768412007694E4ECF2 +:1045A80022F01200D08EF28EF28C12000601060163 +:1045B800E0691200E4ECDBF01200225000D0120097 +:1045C8008E828E9412002BC7D1F612008E928E84A2 +:0C45D80012002CC7C8F61200D18012009F +:10FE62002F7365727665722F61737369676E3F6572 +:10FE72006D6265646465643D312670726F746F6390 +:10FE82006F6C56657273696F6E3D32004841505215 +:10FE920041445539505553544557553355334136DE +:10FEA2004845504151454652455045500000005E7C +:10FEB20001E80367005357415138544845433245DE +:10FEC200424139484546454A3552555354454845BD +:10FED2005939323754000D0A436F6E6E6563746987 +:10FEE2006F6E3A20636C6F73650D0A0D0A007465BC +:10FEF2006D706572617475726568756D6964697437 +:10FF0200790020485454502F312E300D0A486F7317 +:10FF1200743A200054656C6C537469636B4E65745B +:10FF22003A0054656C6C537469636B204E657400BF +:10FF320065766572666C6F75726973680073656C5D +:10FF4200666C6561726E696E6700636F6465737774 +:10FF52006974636800646973636F6E6E65637400CD +:10FF620066696E656F66667365740070726F746F32 +:10FF7200636F6C005265676973746572006D616EC0 +:10FF8200646F6C796E0052617744617461006172D2 +:10FF920063746563680076657273696F6E0073657A +:10FFA2006E736F7200736563726574006F7265675A +:10FFB2006F6E006D6F64656C00636C6173730050EB +:10FFC200696E670047455420006861736800736872 +:10FFD200613100646174610073656E640078313070 +:10FFE2000032383A006D6163006B65790041434B22 +:0EFFF200006F730052005300330050000000F7 +:020000040001F9 +:100000006170692E74656C6C6475732E636F6D001E +:1000100000000100000000000000000100000000DE +:100020000000FFFFF3FF80FFFFFEFEFFFEFFFFFE6D +:1000300007000D0E070107014A25E96E000E0701B2 +:1000400007014B21EA6EEF50070107014F6F080EC1 +:10005000070107014A25E96E000E070107014B2140 +:10006000EA6E0701EECF64F70701EECF65F70701EF +:10007000EECF66F70701EECF67F7040E0701070121 +:100080004A25E96E000E070107014B21EA6E0701C0 +:10009000EECF58F70701EECF59F70701EECF5AF729 +:1000A0000701EECF5BF70301F6910301F69303011D +:1000B000F6950B000E0003010301F6B901D001D043 +:1000C0001BD019EC22F0740E07010701A3250301D0 +:1000D0000301ED6F350E07010701A4210301EE6F47 +:1000E000060E07010701A5210301EF6F000E0701AE +:1000F0000701A6210301F06F5BD1070107014FA59E +:1001000001D001D004D017EC0EF086EF8EF007017D +:1001100007014FA901D001D01ED064C7CCF465C738 +:10012000CDF466C7CEF467C7CFF40701686F000E41 +:1001300007010701716F070168510701696F040E1C +:1001400007010701706F07016951B4EC9BF017ECD0 +:100150000EF086EF8EF0070107014FA301D001D00A +:100160003AD0010E07010701582504010401D06FA0 +:10017000000E0701070159210401D16F000E07018C +:1001800007015A210401D26F000E070107015B210C +:100190000401D36F03ECDBF070C7EBF471C7ECF430 +:1001A0000701686F010E07010701716F07016851B0 +:1001B0000701696F120E07010701706F070169518E +:1001C000B4EC9BF00701686F060E03010301F56FA5 +:1001D0000701685102D017EC0EF086EF8EF0070190 +:1001E00007014FA501D001D002D086EF8EF00701A4 +:1001F00007014FA901D001D04BD00701070167517A +:1002000004010401CF1914E107010701665104013B +:100210000401CE190DE10701070165510401040134 +:10022000CD1906E107010701645104010401CC194D +:10023000D8B401D001D02CD0CCC458F7CDC459F7D4 +:10024000CEC45AF7CFC45BF764C7CCF465C7CDF40E +:1002500066C7CEF467C7CFF40701686F010E0701C8 +:100260000701716F070168510701696F040E0701EB +:100270000701706F07016951B4EC9BF058C7CCF4CB +:1002800059C7CDF45AC7CEF45BC7CFF486EF8EF0D2 +:10029000070107014FA301D001D087D0010E07014C +:1002A0000701582504010401D06F000E0701070162 +:1002B00059210401D16F000E070107015A210401E1 +:1002C000D26F000E070107015B210401D36F0E0EF0 +:1002D000070107014A25E96E000E070107014B21BE +:1002E000EA6E0401EECFDAF40401EDCFDBF403ECA7 +:1002F000DBF070C7EBF471C7ECF4070107014FA9FD +:1003000001D001D038D00701686F010E0701070145 +:10031000716F070168510701696F100E070107012E +:10032000706F07016951B4EC9BF00701686F070E0D +:1003300003010301F56F0701685119EC22F0740EF7 +:1003400007010701A32503010301ED6F350E070126 +:100350000701A4210301EE6F060E07010701A52185 +:100360000301EF6F000E07010701A6210301F06FE3 +:100370000301F6991AD00701686F010E0701070102 +:10038000716F070168510701696F120E07010701BC +:10039000706F07016951B4EC9BF00701686F060E9E +:1003A00003010301F56F0701685186EF8EF00AD053 +:1003B00003010301F551040A01E19FD6010A01E19D +:1003C0000ED7F5D74CC752F74DC753F707010701B2 +:1003D0004FA101D001D004D007010701524B532B8C +:1003E000070107014FA301D001D004D00701070185 +:1003F000524B532B030103EEEBF0030113EEE9F034 +:10040000E652EE52ED50E55C02E1EF50E75CD8A019 +:1004100001D001D030D0030103EEE9F0EECF68F750 +:10042000EDCF69F703010301EB510701685F030199 +:100430000301EC510701695B030103EEE3F0EECF2A +:100440006AF7EDCF6BF703010301E15107016A5F22 +:1004500003010301E25107016B5B070168510701CA +:100460006A5D07010701506F0701695107016B5968 +:100470000701516F1CD0030103EEEBF0EECF68F7DC +:10048000EDCF69F703010301E9510701685F03013B +:100490000301EA510701695BFF0E070168250701A7 +:1004A0000701506FFF0E070169210701516F040119 +:1004B0000401D05107010701585D07010701606F72 +:1004C00004010401D1510701070159590701616F66 +:1004D00004010401D251070107015A590701626F53 +:1004E00004010401D351070107015B590701636F40 +:1004F00060C754F761C755F70701686F000E070121 +:1005000007014E6F0701685107010701535152114E +:10051000D8B401D001D0F9D00701070151515011D1 +:10052000D8B401D001D0F0D00701070163BF01D0DA +:1005300001D02FD00701070150510701686F070153 +:10054000070151510701696F07016A6B07016B6B66 +:100550000701685107010701605D07016951070143 +:100560000701615907016A51070107016259070133 +:100570006B51070107016359D8B001D001D009D0F0 +:100580000701686F010E070107014E6F07016851EF +:100590006CD00701070152510701070160250701CF +:1005A000686F070107015351070107016121070126 +:1005B000696F000E07010701622107016A6F000ED3 +:1005C00007010701632107016B6F07016B51800A67 +:1005D000800F08E1000E6A5D05E1000E695D02E131 +:1005E000010E685DD8A001D001D03FD007010701FE +:1005F000525107010701505D0701686F07010701AC +:1006000053510701070151590701696F07016A6BCF +:10061000070169BF6A0707016A5107016B6F07018C +:100620006B51800A07016C6F0701070160510701D8 +:10063000685D070107016151070169590701070159 +:10064000625107016A59070107016351800A0701D6 +:100650006C59D8A001D001D008D00701686F010EF5 +:10066000070107014E6F070168510701070150514B +:100670000701686F0701070151510701696F070101 +:100680006A6B07016B6B070107016351800A070161 +:100690006C6F0701685107010701605D070169512F +:1006A00007010701615907016A51070107016259F2 +:1006B00007016B51800A07016C59D8B001D001D0F5 +:1006C00023D0070154C768F7070155C769F7070129 +:1006D000070152510701682707010701535107011C +:1006E000692307016951800A800F010ED8B4685D43 +:1006F000D8A001D001D008D00701686F010E070112 +:1007000007014E6F0701685146D007016351601120 +:1007100061116211D8A401D001D009D00701686F1E +:10072000010E070107014E6F0701685134D0070120 +:10073000070163BF01D001D02ED00701070150513E +:100740000701686F0701070151510701696F070130 +:100750006A6B07016B6B0701685107010701605D58 +:100760000701695107010701615907016A51070132 +:100770000701625907016B51070107016359D8B09E +:1007800001D001D008D00701686F010E07010701F1 +:100790004E6F07016851070107014E6701D001D074 +:1007A0001AD0070107014FB501D001D012D00701BF +:1007B000686F010E07010701716F0701685107019A +:1007C000696F100E07010701706F07016951B4ECE2 +:1007D0009BF086EF8EF0070107014F51060BD8B44E +:1007E00001D001D004D017EC0EF086EF8EF0070197 +:1007F00007014FB901D001D002D086EF8EF09DEFF6 +:1008000088F007010701675104010401CF1914E1C1 +:1008100007010701665104010401CE190DE107012A +:100820000701655104010401CD1906E10701070123 +:10083000645104010401CC19D8B401D001D02CD0EA +:10084000CCC458F7CDC459F7CEC45AF7CFC45BF720 +:1008500064C7CCF465C7CDF466C7CEF467C7CFF4E0 +:100860000701686F010E07010701716F07016851E9 +:100870000701696F040E07010701706F07016951D5 +:10088000B4EC9BF058C7CCF459C7CDF45AC7CEF49A +:100890005BC7CFF486EF8EF00701686F070E030188 +:1008A0000301F56F0701685104010401D4510301EC +:1008B0000301E55D07010701566F04010401D551ED +:1008C00003010301E6590701576F0701070157AFFD +:1008D00001D001D01BD0030103EEE1F0EECF68F7A9 +:1008E000EDCF69F703010301DF510701685F0301E1 +:1008F0000301E0510701695B070168510701070126 +:10090000562707016951070107015723070107010E +:10091000565104010401CC25070107015C6F070152 +:100920000701575104010401CD2107015D6F000E3D +:1009300004010401CE2107015E6F000E04010401D1 +:10094000CF2107015F6F070107016451070107010C +:100950005C5D0701686F0701070165510701070129 +:100960005D590701696F070107016651070107011A +:100970005E5907016A6F0701070167510701070107 +:100980005F5907016B6F07016BAF01D001D014D025 +:100990000701686F000E07010701716F07016851B9 +:1009A0000701696F100E07010701706F0701695198 +:1009B000B4EC9BF086EF8EF003010301E7510401D4 +:1009C0000401D45D0701686F03010301E8510401CC +:1009D0000401D5590701696F07016A6B070169BFF7 +:1009E0006A0707016A5107016B6F0701685104012B +:1009F0000401CC5D070107015C6F07016951040127 +:100A00000401CD5907015D6F07016A51040104011A +:100A1000CE5907015E6F07016B5104010401CF59E4 +:100A200007015F6F030103EEE7F0040114EED4F059 +:100A3000E652EE52ED50E55C02E1EF50E75CD8B0D3 +:100A400001D001D028D003010301DF5103010301CC +:100A5000E15D0701686F03010301E0510301030138 +:100A6000E2590701696F07016A6B07016B6B0701A8 +:100A70006851070107015C5F070169510701070120 +:100A80005D5B07016A51070107015E5B07016B515E +:100A9000070107015F5B070107015C5107010701BF +:100AA000645D070107015C6F070107015D510701E4 +:100AB0000701655907015D6F070107015E510701D5 +:100AC0000701665907015E6F070107015F510701C2 +:100AD0000701675907015F6F070107015F51800A2E +:100AE000800F0BE1000E07015E5D07E1000E0701BC +:100AF0005D5D03E1010E07015C5DD8A001D001D06E +:100B00003BD103010301DF5103010301E15D070153 +:100B1000686F03010301E05103010301E25907017A +:100B2000696F07016A6B07016B6B070107015C5175 +:100B30000701685D070107015D5107016959070158 +:100B400007015E5107016A59070107015F5107015B +:100B50006B59D8A001D001D00FD10401EA9704014C +:100B6000EA990301F791E7C356F7E8C357F707017E +:100B700007015C5103010301E727070107015D51EC +:100B800003010301E8230701070156510401040191 +:100B9000D45D07010701575104010401D559D8A0BC +:100BA00001D001D039D0030103EEE7F0040114EEC7 +:100BB000D4F0E652EE52ED50E55C02E1EF50E75C16 +:100BC000D8B001D001D027D0030103EEE7F0EECF7B +:100BD00068F7EDCF69F704010401D4510701685F9C +:100BE00004010401D5510701695B07016851040143 +:100BF0000401CC270701695104010401CD23000E33 +:100C000004010401CE23000E04010401CF23E7C335 +:100C1000D4F4E8C3D5F457D0030103EEE1F0EECFEE +:100C200068F7EDCF69F703010301DF510701685F42 +:100C300003010301E0510701695B04010401D45180 +:100C40000701682507010701566F04010401D5510A +:100C5000070169210701576F03010301E7510701EC +:100C60000701565D03010301E851070107015759C8 +:100C7000D8B001D001D027D0030103EEE7F0EECFCA +:100C800068F7EDCF69F70701070156510701685F63 +:100C90000701070157510701695B0701685104010A +:100CA0000401CC270701695104010401CD23000E82 +:100CB00004010401CE23000E04010401CF23E7C385 +:100CC000D4F4E8C3D5F4030103EEE1F0030113EE1D +:100CD000E7F0E652EE52ED50E55C02E1EF50E75CE2 +:100CE000D8A001D001D01BD0030103EEE1F0EECF7C +:100CF00068F7EDCF69F703010301DF510701685F72 +:100D000003010301E0510701695B07016851030119 +:100D10000301E75F0701695103010301E85B030178 +:100D200003EEE1F0040114EED4F0E652EE52ED5081 +:100D3000E55C02E1EF50E75CD8A001D001D01BD008 +:100D4000030103EEE1F0EECF68F7EDCF69F70301A1 +:100D50000301DF510701685F03010301E05107014F +:100D6000695B0701685104010401D45F07016951FF +:100D700004010401D55B93D0040104EED4F0030117 +:100D800013EEE7F0E652EE52ED50E518EFCFE8FF34 +:100D9000D8B4E718D8B401D001D081D0040104013F +:100DA000EAA701D001D079D004010401EAA901D059 +:100DB00001D071D003010301E75104010401D45DA6 +:100DC0000701686F03010301E85104010401D559CB +:100DD0000701696F07016A6B070169BF6A070701AD +:100DE0006A5107016B6F0701685104010401CC5F70 +:100DF0000701695104010401CD5B07016A51040137 +:100E00000401CE5B07016B5104010401CF5B0301B8 +:100E100003EEE7F0040114EED4F0E652EE52ED508A +:100E2000E55C02E1EF50E75CD8B001D001D02DD0F5 +:100E300003010301DF5103010301E15D0701686F55 +:100E400003010301E05103010301E2590701696F46 +:100E500007016A6B070169BF6A0707016A51070149 +:100E60006B6F0701685104010401CC5F07016951F0 +:100E700004010401CD5B07016A5104010401CE5B4A +:100E800007016B5104010401CF5BE7C3D4F4E8C34D +:100E9000D5F40301F7850401EA890401EA87030117 +:100EA00003EEE5F0030113EEE7F0E652EE52ED50EB +:100EB000E518EFCFE8FFD8B4E718D8A401D001D0E7 +:100EC00049D003010301F7B701D001D01ED019ECBE +:100ED00022F0740E07010701A32503010301ED6F42 +:100EE000350E07010701A4210301EE6F060E07016D +:100EF0000701A5210301EF6F000E07010701A621DD +:100F00000301F06F0301F69925D00701070167512E +:100F100004010401CF1914E107010701665104011E +:100F20000401CE190DE10701070165510401040117 +:100F3000CD1906E107010701645104010401CC1930 +:100F4000D8A401D001D006D00301F6990301F79788 +:100F50000401EA9104010401DB51DA11D8A401D0A3 +:100F600001D012D00E0E070107014A25E96E000ECE +:100F7000070107014B21EA6EEE50ED10D8B401D005 +:100F800001D002D00301F7830E0E070107014A25A5 +:100F9000E96E000E070107014B21EA6E0401EECF56 +:100FA000DAF40401EDCFDBF403010301F551080A83 +:100FB000D8A401D001D045D0070107016751040131 +:100FC0000401CF1914E1070107016651040104016E +:100FD000CE190DE107010701655104010401CD1986 +:100FE00006E107010701645104010401CC19D8A4EA +:100FF00001D001D025D019EC22F0BA0E070107016B +:10100000A32503010301ED6F1A0E07010701A421B7 +:101010000301EE6F030E07010701A5210301EF6F26 +:10102000000E07010701A6210301F06F0301F689F5 +:101030000701686F090E03010301F56F070168518D +:1010400058D003010301F551090AD8A401D001D0F9 +:1010500025D0070107014FB101D001D01ED064C7D0 +:10106000CCF465C7CDF466C7CEF467C7CFF40701EB +:10107000686F000E07010701716F070168510701D2 +:10108000696F140E07010701706F07016951B4EC15 +:101090009BF017EC0EF086EF8EF02BD003010301CE +:1010A000F5510A0AD8A401D001D023D007010701C5 +:1010B000675104010401CF1914E1070107016651CA +:1010C00004010401CE190DE1070107016551040176 +:1010D0000401CD1906E1070107016451040104016F +:1010E000CC19D8A401D001D002D017EC0EF086EFB5 +:1010F0008EF041D007010701675104010401CF19A7 +:1011000014E107010701665104010401CE190DE144 +:1011100007010701655104010401CD1906E107012A +:101120000701645104010401CC19D8A401D001D0F5 +:1011300002D017EC0EF086EF8EF003010301F5519B +:10114000060A02E101EF84F0010A02E154EF84F0A3 +:101150000F0A02E154EF84F0010A02E154EF84F037 +:10116000030A02E154EF84F0010A02E154EF84F033 +:10117000070AC0E0BED7070107014FAB01D001D07D +:1011800002D086EF8EF003010301F5510B0AD8A4BB +:1011900001D001D002D086EF8EF003010301F5519A +:1011A0000A0AD8A401D001D002D086EF8EF0030144 +:1011B0000301F5510C0AD8A401D001D002D086EF6A +:1011C0008EF0070107014D514C11D8B401D002D067 +:1011D0003BEF8DF0070107015551800A800F010E8A +:1011E000D8B4545DD8B001D001D0BBD10C0E0701EA +:1011F00007014A25E96E000E070107014B21EA6E3F +:10120000EF380F0B0701686F68C769F707016A6B52 +:10121000D890070169376A37D890070169376A376C +:101220000701070154510701695D07010701776F45 +:1012300007010701555107016A590701786FA8ECAA +:1012400021F0070107015451070107014C2707014D +:1012500007015551070107014D23070107014C51B3 +:1012600007010701505D070107014D510701070103 +:101270005159D8B001D001D004D050C74CF751C754 +:101280004DF7070107014C5104010401D027070164 +:1012900007014D5104010401D123000E0401040192 +:1012A000D223000E04010401D323030103EEE9F06D +:1012B000EECF68F7EDCF69F7070107014C51070141 +:1012C0006827070107014D5107016923070168518C +:1012D00003010301E35D0701695103010301E459BF +:1012E000D8B001D001D07FD0030103EEE3F0EECF00 +:1012F00068F7EDCF69F703010301E9510701685F62 +:1013000003010301EA510701695B010E070168252A +:1013100007010701566F000E070169210701576F8A +:1013200056C7ACF757C7ADF70701686F000E070146 +:101330000701AB6F07016851FF0E07010701A96F95 +:10134000FF0E0701AA6FFAC3A8F7E9C3A6F7EAC31D +:10135000A7F74AEC0CF007010701565107010701F6 +:101360004C5D07010701AC6F0701070157510701E9 +:1013700007014D590701AD6F0701686F000E0701A6 +:101380000701AB6F07016851FF0E07010701A96F45 +:10139000FF0E0701AA6FFAC3A8F7E1C3A6F7E2C3DD +:1013A000A7F74AEC0CF007014CC768F707014DC7D7 +:1013B00069F70701070156510701685F0701070137 +:1013C00057510701695B03010301E15107016825DA +:1013D00003010301E96F03010301E25107016921E0 +:1013E0000301EA6F27D04CC7ACF74DC7ADF7070133 +:1013F000686F000E07010701AB6F07016851FF0E10 +:1014000007010701A96FFF0E0701AA6FFAC3A8F72A +:10141000E9C3A6F7EAC3A7F74AEC0CF007010701F6 +:101420004C5103010301E927070107014D51030155 +:101430000301EA2304010401E829D8B4E929D8B456 +:1014400001D001D08DD0070107014C5104010401E6 +:10145000E85F070107014D5104010401E95B040144 +:101460000401E85104010401DC2507010701566F5E +:1014700004010401E95104010401DD210701576F52 +:101480000701070157AF01D001D006D004010401C4 +:10149000E8690401E96964D0040104EEE8F0EE5261 +:1014A000ED50800A800F010ED8B4EF5CD8B001D0A7 +:1014B00001D056D007010701565104010401D0277D +:1014C00007010701575104010401D123000E040153 +:1014D0000401D223000E04010401D32307010701F4 +:1014E000565103010301E927070107015751030181 +:1014F0000301EA23030103EEE9F0030113EEE3F035 +:10150000E652EE52ED50E55C02E1EF50E75CD8B0F8 +:1015100001D001D020D0030103EEE3F0EECF68F755 +:10152000EDCF69F703010301E1510701685F030192 +:101530000301E2510701695B010E07016827000EF4 +:1015400069230701685103010301E95F070169513C +:1015500003010301EA5B04010401E8690401E9698C +:101560008AD2070107015551800A800F010ED8B4B5 +:10157000545DD8A001D001D07ED207014CC768F7D6 +:1015800007014DC769F70701070154510701682793 +:101590000701070155510701692307016851070138 +:1015A0000701505D07016951070107015159D8B082 +:1015B00001D001D011D007010701545107010701E3 +:1015C000505D070107014C6F0701070155510701E5 +:1015D0000701515907014D6F0C0E070107014A25FC +:1015E000E96E000E070107014B21EA6EEF380F0B81 +:1015F0000701686F68C769F707016A6BD890070130 +:1016000069376A37D890070169376A3769C777F74A +:101610006AC778F7A8EC21F0030103EEE9F0EECFFA +:1016200068F7EDCF69F707010701545107016827F3 +:1016300007010701555107016923070107014C51B3 +:1016400007016827070107014D51070169230701B9 +:10165000685103010301E35D0701695103010301BF +:10166000E459D8B001D001D0CDD0030103EEE3F0AE +:10167000EECF68F7EDCF69F703010301E9510701E8 +:10168000685F03010301EA510701695B010E07016D +:101690006827000E69230701070154510701685D9F +:1016A00007010701566F07010701555107016959E5 +:1016B0000701576F0701070157BF01D001D051D073 +:1016C00056C7ACF757C7ADF70701686F000E0701A3 +:1016D0000701AB6F07016851FF0E07010701A96FF2 +:1016E000FF0E0701AA6FFAC3A8F7070107015451BB +:1016F00003010301E92507010701A66F070107019F +:10170000555103010301EA210701A76F4AEC0CF0D0 +:10171000070107015651070107014C5D0701070149 +:10172000AC6F070107015751070107014D59070128 +:10173000AD6F0701686F000E07010701AB6F07016E +:101740006851FF0E07010701A96FFF0E0701AA6F7D +:10175000FAC3A8F7E1C3A6F7E2C3A7F74AEC0CF077 +:1017600050D04CC7ACF74DC7ADF70701686F000EFE +:1017700007010701AB6F07016851FF0E0701070161 +:10178000A96FFF0E0701AA6FFAC3A8F7030103EEC2 +:10179000E3F0EECF69F7EDCF6AF703010301E15102 +:1017A0000701695F03010301E25107016A5B03015D +:1017B00003EEE9F0EECF6BF7EDCF6CF70701070111 +:1017C000545107016B2707010701555107016C238D +:1017D0000701695107016B5D07016D6F07016A51D0 +:1017E00007016C5907016E6FFF0E07016D25070198 +:1017F0000701A66FFF0E07016E210701A76F4AECD4 +:101800000CF028D04CC7ACF74DC7ADF70701686F97 +:10181000000E07010701AB6F07016851FF0E0701BA +:101820000701A96FFF0E0701AA6FFAC3A8F7070106 +:101830000701545103010301E92507010701A66FC0 +:1018400007010701555103010301EA210701A76FB1 +:101850004AEC0CF004010401E829D8B4E929D8A421 +:1018600001D001D009D054C7E8F455C7E9F44CC7FA +:10187000DCF44DC7DDF4FFD004010401E851070199 +:101880000701545D04010401E9510701070155599D +:10189000D8B001D001D075D0070154C768F707014F +:1018A00055C769F7070107014C5107016827070170 +:1018B00007014D5107016923040104EEE8F0EECF62 +:1018C0006AF7EDCF6BF704010401DC5107016A27C9 +:1018D00004010401DD5107016B2307016851070171 +:1018E0006A5D0701695107016B59D8A001D001D089 +:1018F0001ED0070154C768F7070155C769F70701EC +:1019000007014C5107016827070107014D510701E5 +:10191000692304010401E8510701685D0401040121 +:10192000E95107016959D8B001D001D005D04CC7A1 +:10193000DCF44DC7DDF420D0040104EEE8F0EECF76 +:1019400068F7EDCF69F704010401DC51070168274E +:1019500004010401DD510701692307010701545106 +:101960000701685D04010401DC6F0701070155519F +:10197000070169590401DD6F54C7E8F455C7E9F45C +:101980007AD0070154C768F7070155C769F70701FF +:1019900007014C5107016827070107014D51070155 +:1019A0006923040104EEE8F0EECF6AF7EDCF6BF7A0 +:1019B00004010401DC5107016A2704010401DD511F +:1019C00007016B230701685107016A5D070169512F +:1019D00007016B59D8B001D001D04DD0040104EEFD +:1019E000E8F0EECF68F7EDCF69F704010401DC51B0 +:1019F0000701682704010401DD510701692307017C +:101A0000070154510701685D07010701555107019E +:101A10006959D8A001D001D02ED0070154C768F76A +:101A2000070155C769F7070107014C5107016827EE +:101A3000070107014D510701692304010401E85121 +:101A40000701685F04010401E9510701695B0401B2 +:101A50000401DC510701685F04010401DD51070145 +:101A6000695B0701685104010401DC270701695122 +:101A700004010401DD230701070153515211D8B4B9 +:101A800001D001D040D003010301F551070AD8B4B9 +:101A900001D001D004D0E9C3EBF3EAC3ECF30301B6 +:101AA0000301F6AF01D001D015D00701686F010E18 +:101AB00007010701716F070168510701696F100E77 +:101AC00007010701706F07016951B4EC9BF077ECD7 +:101AD000E7F019D00301F68F03010301F6BD01D031 +:101AE00001D011D00301F68D55EC20F00F0E070147 +:101AF0000701702503010301F36F000E07010701C1 +:101B000071210301F46F070107014FA101D001D03A +:101B1000FDD00701070152510701070158250701B0 +:101B2000686F070107015351070107015921070198 +:101B3000696F000E070107015A2107016A6F000E45 +:101B4000070107015B2107016B6F010E040104010E +:101B5000D02507016C6F000E04010401D12107019B +:101B60006D6F000E04010401D22107016E6F000E9B +:101B700004010401D32107016F6F07016B510701B5 +:101B80006F190EE107016A5107016E1909E107019A +:101B9000695107016D1904E10701685107016C19CA +:101BA000D8A401D001D0B2D0010E04010401D02785 +:101BB000000E0401D123000E0401D223000E040103 +:101BC000D32385D00701686F0C0E03010301F56F65 +:101BD000070168510701686F010E07010701716F66 +:101BE000070168510701696F110E07010701706F46 +:101BF00007016951B4EC9BF089D00701686F0B0EA7 +:101C000003010301F56F0701685155EC20F01F0E29 +:101C100007010701702503010301F36F000E07019F +:101C2000070171210301F46F5FD0070107016751BC +:101C300004010401CF1914E10701070166510401F1 +:101C40000401CE190DE107010701655104010401EA +:101C5000CD1906E107010701645104010401CC1903 +:101C6000D8A401D001D015D00701686F000E07017C +:101C70000701716F070168510701696F100E0701B5 +:101C80000701706F07016951B4EC9BF017EC0EF07F +:101C90003DD00701686F0A0E03010301F56F0701CC +:101CA000685122D00701686F000E07010701716FAC +:101CB000070168510701696F100E07010701706F76 +:101CC00007016951B4EC9BF017EC0EF01FD0030133 +:101CD0000301F551060A01E175D7010A8EE00F0AEA +:101CE000A4E0010ADFE0DDD70701686F010E0701FC +:101CF0000701716F070168510701696F100E070135 +:101D00000701706F07016951B4EC9BF012000701E5 +:101D1000276F000E070107011E6F07012751000EF4 +:101D2000070107011E6501D001D002D0C0EF94F079 +:101D30001EC760F784EC0EF00701276F000E070145 +:101D40000701206F070127510701276F000E0701C8 +:101D500007011F6F070127510701276F000E0701B9 +:101D600007011D6F0701275103010301F7B301D0DC +:101D700001D006D003010301F7A501D001D018D08E +:101D80001CEC1EF00009D8B401D001D011D007011D +:101D9000276F100E07010701206F07012751070168 +:101DA00007011F6B0301F7A503D0070107011F2BD4 +:101DB00003010301F6AB01D001D025D055EC20F092 +:101DC00007010701705103010301F15D0701276F4E +:101DD00007010701715103010301F2590701286F3F +:101DE00007012851800A800F010ED8B4275DD8B0B2 +:101DF00001D001D008D00701276F100E070107019D +:101E0000206F0701275103010301F6AD01D001D076 +:101E100025D055EC20F007010701705103010301A3 +:101E2000F35D0701276F07010701715103010301EA +:101E3000F4590701286F07012851800A800F010E0D +:101E4000D8B4275DD8B001D001D008D00701276FE2 +:101E5000100E07010701206F07012751030103013D +:101E6000F5510B0AD8A401D001D02DD055EC20F0AB +:101E700007010701705103010301F35D0701276F9B +:101E800007010701715103010301F4590701286F8C +:101E900007012851800A800F010ED8B4275DD8B001 +:101EA00001D001D010D00701276F110E07010701E3 +:101EB000206F070127510701276F0C0E0301030153 +:101EC000F56F0701275103010301F551040AD8A456 +:101ED00001D001D066D1000E07010701216F000E6D +:101EE0000701226F030E07010701215D000E0701A4 +:101EF0002259D8A001D001D001D053D10701070148 +:101F00002151140DF3CF27F7100E070127270601E3 +:101F1000000E07012725E96EEA6A0601060EEA228D +:101F2000EE50ED10D8A401D001D001D03AD1030178 +:101F300003EEF8F0070107012151140DF3CF27F745 +:101F4000100E070127270601000E07012725E16E65 +:101F5000E26A0601060EE222E652EE52ED50E51864 +:101F6000EFCFE8FFD8B4E718D8A401D001D00AD148 +:101F700077ECE7F00A0E07010701B26F000E0701C8 +:101F8000B36F070107012151140D000E0701276FE0 +:101F9000060E286FF35007012727E86AF3BEE868AA +:101FA0000701282327C7B0F728C7B1F70401DE0EC1 +:101FB00007010701AE6F0401040E0701AF6F18ECB3 +:101FC0001AF0070107012151140DF3CF27F70A0E6C +:101FD000070127270601000E07012725E96EEA6A97 +:101FE0000601060EEA220401EECFD6F40401EDCF7D +:101FF000D7F4070107012151140DF3CF27F70C0E79 +:10200000070127270601000E07012725E96EEA6A66 +:102010000601060EEA22EECF28F7EECF29F7EECF23 +:102020002AF7EECF2BF7010E070128250401040142 +:10203000D06F000E070129210401D16F000E0701A6 +:102040002A210401D26F000E07012B210401D36F56 +:10205000040104EEE0F0EECF27F7EDCF28F70401FE +:102060000401DE510701272704010401DF510701A4 +:10207000282304010401D651070127270401040184 +:10208000D7510701282304010401D851070127195A +:1020900003010301F86F04010401D9510701281954 +:1020A0000301F96F0701276F120E07010701206F67 +:1020B000070127510701276F060E03010301F56F82 +:1020C00007012751140E07010701626F000E070177 +:1020D000636F070107012151020807010701606FC3 +:1020E000070107012251D8A0E82A00080701616F03 +:1020F0005AEC1BF060C7ACF761C7ADF70701276F5B +:10210000010E07010701AB6F070127510701070106 +:102110002129140D000E0701286F060E296FF350B8 +:1021200007012827E86AF3BEE8680701292328C7C2 +:10213000A9F729C7AAF707012A6F010E07010701AE +:10214000A86F07012A51070107012151140D000E44 +:1021500007012B6F060E2C6FF35007012B27E86A3F +:10216000F3BEE86807012C232BC7A6F72CC7A7F7F7 +:102170004AEC0CF0000E06010601386F000E060155 +:10218000396F0FD007010701214B222B030E0701E6 +:102190000701215D000E07012259D8A001D001D00E +:1021A000ADD6070107012051D8B401D001D010D01D +:1021B000070107011F51D8B401D002D0010E01D090 +:1021C000000E07010701716F20C770F7B4EC9BF098 +:1021D00003010301F6B901D001D088D00301030146 +:1021E000F551070AD8A401D001D04FD019EC22F044 +:1021F00003010301ED5107010701A35D0701276FEB +:1022000003010301EE5107010701A4590701286FDB +:1022100003010301EF5107010701A5590701296FC8 +:1022200003010301F05107010701A65907012A6FB5 +:1022300007012AAF01D001D001D097D30301F65195 +:10224000070B060AD8A401D001D020D0070107014E +:10225000206B0301F6A703D007010701202B1EC73F +:102260002DF729ECE3F01EC72DF729ECE3F0070169 +:102270000701206701D001D008D00701276F0E0E9B +:1022800003010301F56F070127516FD377ECE7F0E6 +:102290000701276F020E07010701716F0701275120 +:1022A0000701286F100E07010701706F0701285101 +:1022B000B4EC9BF019EC22F0740E07010701A32582 +:1022C00003010301ED6F350E07010701A42103018E +:1022D000EE6F060E07010701A5210301EF6F000E47 +:1022E00007010701A6210301F06F3FD319EC22F08B +:1022F00003010301ED5107010701A35D0701276FEA +:1023000003010301EE5107010701A4590701286FDA +:1023100003010301EF5107010701A5590701296FC7 +:1023200003010301F05107010701A65907012A6FB4 +:1023300007012AAF01D001D001D017D377ECE7F025 +:1023400043D272EC22F00009D8B401D001D02BD0D6 +:102350000701276F010E03010301F56F07012751E4 +:1023600004010401EAA501D001D00FD00701276FB5 +:10237000010E070107012F6F07012751DEC42DF75A +:10238000DFC42EF7BCEC1AF00ED00701276F010E48 +:10239000070107012F6F07012751DEC42DF7DFC4A6 +:1023A0002EF7F1EC1AF035D20701230E07010701D1 +:1023B0002D6F0701070E07012E6F8FEC95F00009B6 +:1023C000D8B401D001D0EFD79DEC1FF00009D8B4EC +:1023D00001D001D050D023C7DEF424C7DFF425C7D5 +:1023E000E0F426C7E1F40701276F020E03010301A1 +:1023F000F56F07012751040104EEE0F0EECF27F757 +:10240000EDCF28F704010401DE510701272704015D +:102410000401DF510701282304010401D6510701FB +:10242000272704010401D7510701282304010401CF +:10243000D8510701271903010301F86F04010401B2 +:10244000D951070128190301F96F0701276F000E01 +:1024500004010401ED6F07012751270E0401040157 +:10246000C86F000E0401C96F000E0401CA6F000E90 +:102470000401CB6F23D019EC22F0740E0701070181 +:10248000A32503010301ED6F350E07010701A42108 +:102490000301EE6F060E07010701A5210301EF6F8F +:1024A000000E07010701A6210301F06F0701276F46 +:1024B000000E03010301F56F07012751AAD155EC66 +:1024C00020F070C7F1F371C7F2F30401DE0E0701CB +:1024D00007014C6F0401040E07014D6F2DEC09F04C +:1024E0000701276F030E03010301F56F0701275151 +:1024F00090D10401E20E070107014E6F0401040EA2 +:1025000007014F6F0401DE0E070107014C6F040144 +:10251000040E07014D6F53EC04F00009D8A401D05C +:1025200001D03BD055EC20F003010301F15107012C +:102530000701705F03010301F25107010701715B9D +:1025400007010701705104010401C85D070107017B +:10255000715104010401C959D8B001D001D023D769 +:10256000060E04010401ED6101D001D00DD004017B +:102570000401ED2B0401D8900401C8370401C937C8 +:102580000401CA370401CB370701276F020E03018C +:102590000301F56F070127513CD10701276F020E98 +:1025A00007010701206F070127510701276F000E60 +:1025B000070107011F6F070127510701276F050E4C +:1025C00003010301F56F0701275123D10701276F8D +:1025D000020E07010701206F070127510701276F2E +:1025E000010E070107011F6F0701275112D1020ECB +:1025F00004010401ED6101D001D011D00701276F62 +:10260000120E07010701206F070127510701276FED +:10261000010E070107011F6F07012751C4D60301EF +:102620000301F6A701D001D011D00701276F140EC6 +:1026300007010701206F070127510701276F010ECE +:10264000070107011D6F0701275108D00701276FF8 +:10265000020E07010701206F07012751DAD0050E8E +:1026600004010401ED6101D001D011D00701276FF1 +:10267000100E07010701206F070127510701276F7F +:10268000010E070107011F6F070127518CD60701B3 +:10269000276F080E03010301F56F0701275107019A +:1026A000276F110E07010701206F07012751B1D0D5 +:1026B000050E04010401ED6101D001D011D0070124 +:1026C000276F110E07010701206F0701275107012E +:1026D000276F010E070107011F6F0701275163D6FE +:1026E0000701276F140E07010701206F070127510B +:1026F0000701276F010E070107011D6F0701275111 +:1027000088D00701276F140E07010701206F07010A +:1027100027510701276F010E070107011D6F0701F0 +:10272000275177D0050E04010401ED6101D001D0DD +:1027300011D00701276F100E07010701206F070155 +:1027400027510701276F010E070107011F6F0701BE +:10275000275129D60701276F140E07010701206FA3 +:10276000070127510701276F010E070107011D6FA0 +:10277000070127514ED0050E04010401ED6101D07F +:1027800001D011D00701276F110E07010701206F3B +:10279000070127510701276F010E070107011F6F6E +:1027A0000701275100D60701276F140E0701070103 +:1027B000206F070127510701276F010E070107014D +:1027C0001D6F0701275125D003010301F551000AB0 +:1027D00001E1B7D5010A01E1E7D5030A01E16FD6AE +:1027E000010A01E186D6060A01E1F0D6030A01E1F9 +:1027F000FED6010A01E133D70F0A01E159D7010AD8 +:1028000080E0030A8FE0010A01E129D7070AB3E05B +:10281000CAD5070107012051D8B401D001D09CD0FE +:10282000070107011F51D8B401D001D089D004019C +:102830000401ED2B0401D8900401C8370401C93705 +:102840000401CA370401CB3703010301E751040136 +:102850000401D45D0701276F03010301E85104015E +:102860000401D5590701286F0701296B070128BF0B +:1028700029070701295107012A6F07012751040180 +:102880000401CC5F0701285104010401CD5B07015D +:10289000295104010401CE5B07012A5104010401FE +:1028A000CF5B030103EEE7F0040114EED4F0E6522F +:1028B000EE52ED50E55C02E1EF50E75CD8B001D09C +:1028C00001D02DD003010301DF5103010301E15DBC +:1028D0000701276F03010301E05103010301E259DE +:1028E0000701286F0701296B070128BF2907070186 +:1028F000295107012A6F0701275104010401CC5F08 +:102900000701285104010401CD5B0701295104018D +:102910000401CE5B07012A5104010401CF5BE7C328 +:10292000D4F4E8C3D5F40701276F000E07010701AF +:10293000716F0701275120C770F7B4EC9BF00CD0E2 +:102940000701276F010E07010701716F070127516A +:1029500020C770F7B4EC9BF0070107011D51D8B4F4 +:1029600001D001D002D017EC0EF0070107011E2B99 +:10297000000E070107011E6501D002D098EF8EF00E +:10298000000E07010701216F000E0701226F030EE1 +:1029900007010701215D000E07012259D8A001D0CF +:1029A00001D001D0BBD0070107012151140DF3CF95 +:1029B00027F7100E070127270601000E070127251C +:1029C000E96EEA6A0601060EEA22EE50ED10D8A47E +:1029D00001D001D001D0A2D0070107012151140D6F +:1029E000F3CF27F7120E070127270601000E070174 +:1029F0002725E96EEA6A0601060EEA22EECF28F7DD +:102A0000EDCF29F755EC20F0070128510701070108 +:102A1000705D07012A6F07012951070107017159EC +:102A200007012B6FDD0E07012A5D010E2B59D8A07F +:102A300001D001D064D0140E07010701626F000EAF +:102A40000701636F07010701215102080701070110 +:102A5000606F070107012251D8A0E82A000807018A +:102A6000616F5AEC1BF060C7ACF761C7ADF70701A7 +:102A7000276F010E07010701AB6F070127510701FF +:102A800007012129140D000E0701286F060E296F7A +:102A9000F35007012827E86AF3BEE86807012923F5 +:102AA00028C7A9F729C7AAF707012A6F010E07014E +:102AB0000701A86F07012A51070107012151140DD1 +:102AC000000E07012B6F060E2C6FF35007012B270A +:102AD000E86AF3BEE86807012C232BC7A6F72CC7CA +:102AE000A7F74AEC0CF0000E06010601386F000E45 +:102AF0000601396F070107012107D8A02207070146 +:102B00000701214B222B030E07010701215D000E57 +:102B100007012259D8A001D001D045D712008FEF6C +:102B20009BF00701486F000E2C6E0701485107010A +:102B3000486F000E2D6E070148510601480E07012F +:102B400007014C6F0601060E07014D6F2DEC09F0D1 +:102B50002C2A19EC22F0A3C7F7F4A4C7F8F4A5C7F0 +:102B6000F9F4A6C7FAF40701486F020E0601060140 +:102B7000E56F07014851B1EF9BF00001B70E070167 +:102B800007014E6F0001000E07014F6F0601480E4E +:102B9000070107014C6F0601060E07014D6F53EC4C +:102BA00004F00009D8A401D001D046D019EC22F0DD +:102BB00004010401F75107010701A35D0701486FF4 +:102BC00004010401F85107010701A4590701496FE5 +:102BD00004010401F95107010701A55907014A6FD2 +:102BE00004010401FA5107010701A65907014B6FBF +:102BF000F30E485D9E0E4959000E4A59000E07011A +:102C00004B59D8A001D001D015D00701486F010E53 +:102C100006010601E56F07014851020E2C6401D040 +:102C200001D008D00701486F060E06010601E56FC6 +:102C300007014851B1EF9BF048C6B3F049C6B4F064 +:102C40004AC6B5F04BC6B6F00701486F030E060141 +:102C50000601E56F07014851350E07010701506F66 +:102C6000000E0701516F0001B30E070107014E6FFF +:102C70000001000E07014F6F000E070107014C6FA6 +:102C8000000E07014D6F9EECE1F006010601E26FB8 +:102C900006010601E229D8A401D001D002D0B1EF8B +:102CA0009BF00701486F040E06010601E56F07015E +:102CB0004851E2C64CF750EC1AF007014D514C1147 +:102CC000D8A401D001D002D0B1EF9BF000010001E7 +:102CD000F14BF22BF2C053F763EC1FF0F1C053F746 +:102CE00063EC1FF00701486F010E07010701536FE6 +:102CF0000701485163EC1FF00701486F000E070100 +:102D00000701536F0701485163EC1FF00701486F3B +:102D1000000E07010701536F0701485163EC1FF0D4 +:102D20000701486F010E07010701536F0701485162 +:102D300063EC1FF00701486F000E07010701536F96 +:102D40000701485163EC1FF00701486F000E0701AF +:102D50000701536F0701485163EC1FF00701486FEB +:102D6000000E07010701536F0701485163EC1FF084 +:102D70000701486F000E07010701536F0701485113 +:102D800063EC1FF00701486F000E07010701536F46 +:102D90000701485163EC1FF00701486F000E07015F +:102DA0000701536F0701485163EC1FF00401040150 +:102DB000F051EF11D8B401D001D007D0EFC44CF7D7 +:102DC000F0C44DF799EC08F006D0F1C44CF7F2C40A +:102DD0004DF7D3EC06F00701486F000E070107011D +:102DE000536F0701485163EC1FF033C053F763EC96 +:102DF0001FF00701486F000E07010701536F07011D +:102E0000485163EC1FF00701486F010E07010701ED +:102E1000536F0701485163EC1FF0BCEC09F019EC4B +:102E200022F0A3C7F7F4A4C7F8F4A5C7F9F4A6C71E +:102E3000FAF40701486F050E06010601E56F070168 +:102E40004851B1EF9BF0E2C64CF7F2EC1BF00701E2 +:102E50004D514C11D8A401D001D039D019EC22F039 +:102E600004010401F75107010701A35D0701486F41 +:102E700004010401F85107010701A4590701496F32 +:102E800004010401F95107010701A55907014A6F1F +:102E900004010401FA5107010701A65907014B6F0C +:102EA000F30E485D9E0E4959000E4A59000E070167 +:102EB0004B59D8A001D001D0BDD60701486F060EEE +:102EC00006010601E56F07014851B1EF9BF00701CC +:102ED0003D0E070107014D6F0701070E07014E6FF9 +:102EE00086EC1EF007013C0E070107014D6F07013C +:102EF000070E07014E6F86EC1EF000010001F25133 +:102F0000070107013D1906E100010001F151070128 +:102F100007013C19D8B401D001D004D051EC21F004 +:102F2000B1EF9BF007013F0E070107014D6F07014D +:102F3000070E07014E6F86EC1EF007013E0E0701DB +:102F400007014D6F0701070E07014E6F86EC1EF05B +:102F50000701410E070107014D6F0701070E070129 +:102F60004E6F86EC1EF00701400E070107014D6F02 +:102F70000701070E07014E6F86EC1EF00701430E96 +:102F8000070107014D6F0701070E07014E6F86EC21 +:102F90001EF00701420E070107014D6F0701070EE2 +:102FA00007014E6F86EC1EF00701450E0701070171 +:102FB0004D6F0701070E07014E6F86EC1EF00701EB +:102FC000440E070107014D6F0701070E07014E6F01 +:102FD00086EC1EF00701470E070107014D6F070140 +:102FE000070E07014E6F86EC1EF00701460E070123 +:102FF00007014D6F0701070E07014E6F86EC1EF0AB +:103000002ED02EEC18F00701310E070107014D6F8D +:103010000701070E07014E6F86EC1EF00701300E08 +:10302000070107014D6F0701070E07014E6F86EC80 +:103030001EF00701310E070107014D6F0701070E52 +:1030400007014E6F86EC1EF00701300E07010701E5 +:103050004D6F0701070E07014E6F86EC1EF007014A +:1030600007014007D8A0410707014029D8B44129EA +:10307000D8A401D001D0C5D7D0D02EEC18F00701CC +:10308000330E070107014D6F0701070E07014E6F51 +:1030900086EC1EF00701320E070107014D6F070194 +:1030A000070E07014E6F86EC1EF00701350E070173 +:1030B00007014D6F0701070E07014E6F86EC1EF0EA +:1030C0000701340E070107014D6F0701070E0701C5 +:1030D0004E6F86EC1EF00701390E070107014D6F98 +:1030E0000701070E07014E6F86EC1EF00701380E30 +:1030F000070107014D6F0701070E07014E6F86ECB0 +:103100001EF00701370E070107014D6F0701070E7B +:1031100007014E6F86EC1EF00701360E070107010E +:103120004D6F0701070E07014E6F86EC1EF0070179 +:103130003B0E070107014D6F0701070E07014E6F98 +:1031400086EC1EF007013A0E070107014D6F0701DB +:10315000070E07014E6F86EC1EF0070107013205CE +:103160003311D8A401D001D03FD0070107013405A5 +:103170003511D8A401D001D037D0070107013A5149 +:10318000040A3B11D8A401D001D02ED0378200010F +:10319000B30E070107014D6F0001000E07014E6FCE +:1031A00086EC1EF00001B40E070107014D6F00010F +:1031B000000E07014E6F86EC1EF00001B50E0701F0 +:1031C00007014D6F0001000E07014E6F86EC1EF0E7 +:1031D0000001B60E070107014D6F0001000E070147 +:1031E0004E6F86EC1EF0E2D10BD007012F0E0701C7 +:1031F00007014D6F0701070E07014E6F86EC1EF0A9 +:10320000070107013A07D8A03B0707013A29D8B4BC +:103210003B29D8A401D001D0E8D707010701420714 +:10322000D8A0430707014229D8B44329D8A401D024 +:1032300001D023D7D0D02EEC18F00701330E0701B0 +:1032400007014D6F0701070E07014E6F86EC1EF058 +:103250000701320E070107014D6F0701070E070135 +:103260004E6F86EC1EF00701350E070107014D6F0A +:103270000701070E07014E6F86EC1EF00701340EA2 +:10328000070107014D6F0701070E07014E6F86EC1E +:103290001EF00701390E070107014D6F0701070EE8 +:1032A00007014E6F86EC1EF00701380E070107017B +:1032B0004D6F0701070E07014E6F86EC1EF00701E8 +:1032C000370E070107014D6F0701070E07014E6F0B +:1032D00086EC1EF00701360E070107014D6F07014E +:1032E000070E07014E6F86EC1EF007013B0E07012B +:1032F00007014D6F0701070E07014E6F86EC1EF0A8 +:1033000007013A0E070107014D6F0701070E07017C +:103310004E6F86EC1EF00701070132053311D8A469 +:1033200001D001D03FD00701070134053511D8A4E1 +:1033300001D001D037D0070107013A51040A3B11EF +:10334000D8A401D001D02ED037820001B30E0701DE +:1033500007014D6F0001000E07014E6F86EC1EF055 +:103360000001B40E070107014D6F0001000E0701B7 +:103370004E6F86EC1EF00001B50E070107014D6F80 +:103380000001000E07014E6F86EC1EF00001B60E24 +:10339000070107014D6F0001000E07014E6F86EC1B +:1033A0001EF004D10BD007012F0E070107014D6F4E +:1033B0000701070E07014E6F86EC1EF0070107019B +:1033C0003A07D8A03B0707013A29D8B43B29D8A42B +:1033D00001D001D0E8D7070107014407D8A045076D +:1033E00007014429D8B44529D8A401D001D023D756 +:1033F000D0D02EEC18F00701330E070107014D6FF6 +:103400000701070E07014E6F86EC1EF00701320E12 +:10341000070107014D6F0701070E07014E6F86EC8C +:103420001EF00701350E070107014D6F0701070E5A +:1034300007014E6F86EC1EF00701340E07010701ED +:103440004D6F0701070E07014E6F86EC1EF0070156 +:10345000390E070107014D6F0701070E07014E6F77 +:1034600086EC1EF00701380E070107014D6F0701BA +:10347000070E07014E6F86EC1EF00701370E07019D +:1034800007014D6F0701070E07014E6F86EC1EF016 +:103490000701360E070107014D6F0701070E0701EF +:1034A0004E6F86EC1EF007013B0E070107014D6FC2 +:1034B0000701070E07014E6F86EC1EF007013A0E5A +:1034C000070107014D6F0701070E07014E6F86ECDC +:1034D0001EF00701070132053311D8A401D001D035 +:1034E0003FD00701070134053511D8A401D001D020 +:1034F00037D0070107013A51040A3B11D8A401D083 +:1035000001D02ED037820001B30E070107014D6FA5 +:103510000001000E07014E6F86EC1EF00001B40E94 +:10352000070107014D6F0001000E07014E6F86EC89 +:103530001EF00001B50E070107014D6F0001000EDE +:1035400007014E6F86EC1EF00001B60E0701070161 +:103550004D6F0001000E07014E6F86EC1EF026D065 +:103560000BD007012F0E070107014D6F0701070E52 +:1035700007014E6F86EC1EF0070107013A07D8A03D +:103580003B0707013A29D8B43B29D8A401D001D080 +:10359000E8D7070107014607D8A0470707014629D2 +:1035A000D8B44729D8A401D001D023D751EC21F0B9 +:1035B000E2C64CF787EC1AF006010601E269070142 +:1035C000486F070E06010601E56F0701485137B243 +:1035D00001D001D00DD0000E00010001B36F000E2C +:1035E0000001B46F000E0001B56F000E0001B66F50 +:1035F0002DC7E9FF2EC7EAFF0001B3C0EEFF0001AF +:10360000B4C0EEFF0001B5C0EEFF0001B6C0EEFF92 +:10361000010EA9D0010E2D6401D001D010D02DC70C +:10362000E9FF2EC7EAFF000EEE6E000EEE6E000EF2 +:10363000EE6E000EED6EED52ED52010E94D02D2A7D +:1036400006014F514C114D114E11D8B401D002D08A +:103650001AEF96F0060106014C5106010601481BBF +:10366000060106014D5106010601491B060106012E +:103670004E51060106014A1B060106014F51060183 +:1036800006014B1B060106014851060106014C1BB1 +:10369000060106014951060106014D1B06010601FE +:1036A0004A51060106014E1B060106014B51060157 +:1036B00006014F1B060106014C5106010601481B7D +:1036C000060106014D5106010601491B06010601CE +:1036D0004E51060106014A1B060106014F51060123 +:1036E00006014B1B0701486F000E2C6E0701485165 +:1036F00006010601E229D8B401D001D007D0E2C604 +:103700004CF787EC1AF006010601E2690701486FE1 +:10371000010E06010601E56F0701485122D006019E +:103720000601E551000A02E191EF95F0010A02E17C +:103730009DEF95F0030A02E1BDEF95F0010A02E169 +:103740002CEF96F0070A02E159EF96F0010A02E128 +:1037500023EF97F0030A01E15DD7010A01E137D7B2 +:1037600000D0000E00D0120077ECE7F0070107014F +:1037700070A101D001D005D00301F787070107012F +:1037800070910301F69B0301F69D0301F69F03016F +:10379000F7930301F7950301F79100D01CEC1EF09D +:1037A0000009D8B401D001D0F9D707010701705141 +:1037B000060BD8B401D001D008D0000E07010701D4 +:1037C000766F000E0701776FD2D2040104EED4F0B9 +:1037D000030113EEE5F0E652EE52ED50E518EFCF9F +:1037E000E8FFD8B4E718D8A401D001D019D0000E52 +:1037F00007010701766F000E0701776F03010301D0 +:10380000F7A701D001D00BD004010401DB51DA117C +:10381000D8B401D001D003D0070107017081A7D22D +:10382000030103EEE5F0040114EED4F0E652EE528B +:10383000ED50E55C02E1EF50E75CD8B001D001D07B +:10384000F7D004010401D45103010301E55D070130 +:103850000701766F04010401D55103010301E65904 +:103860000701776FDAC474F7DBC475F7030103EE61 +:10387000E7F0040114EED4F0E652EE52ED50E55CB0 +:1038800002E1EF50E75CD8A001D001D01CD00401C8 +:1038900004EED4F0EECF9CF7EDCF9DF703010301CA +:1038A000E75107019C5F03010301E85107019D5B9C +:1038B00007019C5107010701745F07019D51070132 +:1038C0000701755B38D0030103EEE7F0EECF9CF7FC +:1038D000EDCF9DF704010401D45107019C5F040161 +:1038E0000401D55107019D5B030103EEE1F0EECF2A +:1038F0009EF7EDCF9FF703010301DF5107019E5FA4 +:1039000003010301E05107019F5B07019C5107017F +:103910009E5D0701A06F07019D5107019F59070197 +:10392000A16F0701A05107010701745F0701A151B1 +:1039300007010701755B07010701765107010701C0 +:10394000745D070107017751070107017559D8B068 +:1039500001D001D004D074C776F775C777F7070197 +:103960000701765104010401EB5D0701070177515E +:1039700004010401EC59D8B001D001D006D0EBC449 +:1039800076F7ECC477F70301F78503010301F7A786 +:1039900001D001D025D007010701755107010701AA +:1039A000771906E10701070174510701070176192C +:1039B000D8B401D001D014D0040104EEEBF007011B +:1039C000EE5207017751ED18070176C7E8FFD8B42A +:1039D000EF18D8B401D001D003D0070107017081DE +:1039E00076C7ACF777C7ADF7FAC3ABF7D4C4A9F77E +:1039F000D5C4AAF707019C6F000E07010701A86F45 +:103A000007019C51050E07010701A66F0B0E070168 +:103A1000A76F4AEC0CF0070107017651040104017D +:103A2000D42707010701775104010401D5239FD151 +:103A300004010401D45103010301E15D0701070101 +:103A4000866F04010401D55103010301E259070106 +:103A5000876F070107EE86F0EECF9CF7EDCF9DF75D +:103A600003010301E55107019C2703010301E6510E +:103A700007019D2303010301DF5107019C5D07013D +:103A80000701766F03010301E05107019D5907010A +:103A9000776FDAC474F7DBC475F7030103EEE7F060 +:103AA000040114EED4F0E652EE52ED50E55C02E172 +:103AB000EF50E75CD8A001D001D01CD0040104EE87 +:103AC000D4F0EECF9CF7EDCF9DF703010301E75152 +:103AD00007019C5F03010301E85107019D5B07019A +:103AE0009C5107010701745F07019D510701070100 +:103AF000755B38D0030103EEE7F0EECF9CF7EDCF16 +:103B00009DF704010401D45107019C5F04010401E5 +:103B1000D55107019D5B030103EEE1F0EECF9EF767 +:103B2000EDCF9FF703010301DF5107019E5F030102 +:103B30000301E05107019F5B07019C5107019E5D56 +:103B40000701A06F07019D5107019F590701A16F50 +:103B50000701A05107010701745F0701A151070187 +:103B60000701755B07010701765107010701745DC5 +:103B7000070107017751070107017559D8B001D036 +:103B800001D004D074C776F775C777F7070107012E +:103B9000765104010401EB5D07010701775104012F +:103BA0000401EC59D8B001D001D006D0EBC476F7AF +:103BB000ECC477F70301F78503010301F7A701D0F0 +:103BC00001D025D0070107017551070107017719B9 +:103BD00006E1070107017451070107017619D8B4FE +:103BE00001D001D014D0040104EEEBF00701EE5235 +:103BF00007017751ED18070176C7E8FFD8B4EF1831 +:103C0000D8B401D001D003D00701070170810701AA +:103C10000701865107010701765D070107018751FA +:103C2000070107017759D8B001D001D004D076C779 +:103C300086F777C787F786C7ACF787C7ADF7FAC3AC +:103C4000ABF7D4C4A9F7D5C4AAF707019C6F000E3F +:103C500007010701A86F07019C51050E0701070125 +:103C6000A66F0B0E0701A76F4AEC0CF007010701C6 +:103C7000865107010701765D07010701866F07017D +:103C8000070187510701070177590701876F07016E +:103C9000070187518611D8B401D001D030D086C732 +:103CA000ACF787C7ADF7FAC3ABF7DFC3A9F7E0C33B +:103CB000AAF707019C6F000E07010701A86F070113 +:103CC0009C51030103EEE1F0EECF9DF7EDCF9EF79F +:103CD00004010401D45107019D5F04010401D55181 +:103CE00007019E5B050E07019D2507010701A66FD1 +:103CF0000B0E07019E210701A76F4AEC0CF007018C +:103D00000701765104010401D42707010701775107 +:103D100004010401D523030103EEE1F0040114EED4 +:103D2000D4F0E652EE52ED50E55C02E1EF50E75C74 +:103D3000D8A001D001D01BD0030103EEE1F0EECFFB +:103D40009CF7EDCF9DF703010301DF5107019C5F55 +:103D500003010301E05107019D5B07019C51040130 +:103D60000401D45F07019D5104010401D55B0701E3 +:103D7000070177517611D8A401D001D008D00701EE +:103D800007017051030BD8B401D001D04CD007010A +:103D9000070177517611D8B401D001D003D00701C3 +:103DA000070170870701070171A101D001D015D06B +:103DB00007019C6F000E04010401ED6F07019C5187 +:103DC000F20E04010401C86F9E0E0401C96F000EBB +:103DD0000401CA6F000E0401CB6F19EC22F004013C +:103DE0000401C85107010701A32503010301ED6F79 +:103DF00004010401C95107010701A4210301EE6F69 +:103E000004010401CA5107010701A5210301EF6F55 +:103E100004010401CB5107010701A6210301F06F42 +:103E20000301F68973D00701070171A301D001D006 +:103E30002AD0010E07019C6F03010301F651070B05 +:103E400007019D6F07019C5107019D270301030195 +:103E5000F65107019D19F80B07019D190301030194 +:103E6000F66F04010401CC07000E0401CD5B0401D0 +:103E7000CE5B0401CF5B010E07010701766F000ED8 +:103E80000701776F43D003010301F6A901D001D0E8 +:103E90003DD00701070171B101D001D014D0040158 +:103EA0000401ED51D8B401D001D00DD004010401BA +:103EB000ED070401D8900401CB330401CA33040197 +:103EC000C9330401C83319EC22F004010401C851BC +:103ED00007010701A32503010301ED6F040104019C +:103EE000C95107010701A4210301EE6F0401040178 +:103EF000CA5107010701A5210301EF6F0401040165 +:103F0000CB5107010701A6210301F06FD8C488F740 +:103F1000D9C489F7D6C48AF7D7C48BF7CCC48CF739 +:103F2000CDC48DF7CEC48EF7CFC48FF7D0C490F731 +:103F3000D1C491F7D2C492F7D3C493F73F0E0701CF +:103F40009517070194910701949307019495070130 +:103F500094970B000E0070C795F7000E070107013C +:103F60009A6F000E07019B6F07010701765104014C +:103F70000401CC2707010701775104010401CD2377 +:103F8000000E04010401CE23000E04010401CF231E +:103F90000701070170A301D001D033D00701070149 +:103FA00070B901D001D00DD0000E07010701906F4C +:103FB000000E0701916F000E0701926F000E0701BE +:103FC000936F04010401EAA301D001D00BD00701D3 +:103FD00007018C07000E07018D5B07018E5B07014F +:103FE0008F5B0FD0010E04010401CC27000E0401E9 +:103FF000CD23000E0401CE23000E0401CF230401C3 +:10400000EA830701070170A101D001D020D004018B +:104010000401EAA101D001D00BD0070107018C07F0 +:10402000000E07018D5B07018E5B07018F5B0FD0D0 +:10403000010E04010401CC27000E0401CD23000E63 +:104040000401CE23000E0401CF230401EA81030101 +:1040500003EEEBF0030113EEE9F0E652EE52ED5001 +:10406000E55C02E1EF50E75CD8A001D001D030D090 +:10407000030103EEE9F0EECF9CF7EDCF9DF70301CE +:104080000301EB5107019C5F03010301EC510701A0 +:104090009D5B030103EEE3F0EECF9EF7EDCF9FF7BC +:1040A00003010301E15107019E5F03010301E25196 +:1040B00007019F5B07019C5107019E5D07010701F6 +:1040C000966F07019D5107019F590701976F1CD0FB +:1040D000030103EEEBF0EECF9CF7EDCF9DF703016C +:1040E0000301E95107019C5F03010301EA51070144 +:1040F0009D5BFF0E07019C2507010701966FFF0ED0 +:1041000007019D210701976FD3EC0BF0C00E07014B +:104110000701A22507010701726FFF0E07010701C2 +:10412000A3210701736F0701070173AF01D001D00D +:1041300007D0000E07010701726F000E0701736FB1 +:1041400007010701965107010701725D0701070189 +:104150009751070107017359D8B001D001D004D09D +:1041600072C796F773C797F70701880E0701070113 +:10417000A26F0701070E0701A36F40ECD6F0140EE3 +:10418000070107017627000E0701772307019451E5 +:104190000F0B50090701946F0701070170A301D0AD +:1041A00001D038D0040E070107017627000E070161 +:1041B000772307019C6F020E07010701786F070143 +:1041C0009C5107019C6F040E07010701796F0701DD +:1041D0009C51020E070107017A6F140E07017B6FD5 +:1041E000010E07019C6F0701070194390F0B0701AE +:1041F0009D6F07019C5107019D2707019D3B07010A +:104200000701945107019D190F0B07019D19070123 +:104210000701946F3CC67CF73DC67DF73EC67EF72E +:104220003FC67FF7DEC480F7DFC481F7E0C482F7C2 +:10423000E1C483F707019C6F000E07010701846F3B +:1042400007019C5107019C6F060E07010701856F4E +:1042500007019C5176C786F777C787F786C7BEF7F1 +:1042600087C7BFF7B8EC21F0BEC786F7BFC787F78F +:104270000C0E07010701BE6F000E0701BF6F07019B +:104280007C0E07010701BC6F0701070E0701BD6F18 +:1042900038EC06F007010701BC1D07010701986F04 +:1042A00007010701BD1D0701996FDD0E0701070119 +:1042B000AE6F0A0E0701AF6F86EC22F076C7A5F746 +:1042C00077C7A6F707019C6F060E07010701A46FC9 +:1042D00007019C510401DE0E07010701A26F0401D2 +:1042E000040E0701A36F4BEC00F0140E0701070149 +:1042F000C46F000E0701C56F0701880E0701070193 +:10430000C26F0701070E0701C36FB8EC1FF007016A +:10431000070170A301D001D012D0040E07010701DC +:10432000C46F000E0701C56F0701780E0701070172 +:10433000C26F0701070E0701C36FB8EC1FF0F10E43 +:1043400007010701AE6F0A0E0701AF6F90EC22F074 +:1043500076C7A2F777C7A3F7D3ECE0F0A2C772F74E +:10436000A3C773F7010E07010701AE6F0B0E07011C +:10437000AF6F86EC22F0020E07010701C46F000E3A +:104380000701C56F0701720E07010701C26F070120 +:10439000070E0701C36FB8EC1FF080EC1FF012008E +:1043A00001019F0E07010701606F0101010E070166 +:1043B000616F52C7E9FF53C7EAFF0701EECF66F707 +:1043C0000701EECF67F70701EECF68F70701EECFE1 +:1043D00069F754C7E9FF55C7EAFF0701EECF7AF73F +:1043E0000701EECF7BF70701EECF7CF70701EECF99 +:1043F0007DF756C7E9FF57C7EAFF0701EECF72F70F +:104400000701EECF73F70701EECF74F70701EECF88 +:1044100075F758C7E9FF59C7EAFF0701EECF76F7EE +:104420000701EECF77F70701EECF78F70701EECF60 +:1044300079F75AC7E9FF5BC7EAFF0701EECF62F7DA +:104440000701EECF63F70701EECF64F70701EECF68 +:1044500065F79F0E0701866F010E876F0701070141 +:1044600051510701871905E1070107015051070163 +:104470008619D8A401D001D078D00701866F000E2C +:10448000070107015F6F070186510F0E0701070142 +:104490005F6501D001D001D067D0030E070107018D +:1044A0005025E96E000E070107015121EA6EEF5019 +:1044B000070107015E6F50C7E9FF51C7EAFF030E0E +:1044C000070107015025E16E000E07010701512188 +:1044D000E26EEFCFE7FF50C7E9FF51C7EAFF0701E0 +:1044E0005EC7EFFF010E070107015025E96E000EC0 +:1044F000070107015121EA6EEF50070107015E6FC6 +:10450000020E070107015025E96E000E07010701A1 +:104510005121EA6E010E070107015025E16E000EE0 +:10452000070107015121E26EEFCFE7FF020E0701FD +:1045300007015025E96E000E070107015121EA6EBF +:1045400007015EC7EFFF040E070107015027000EA9 +:1045500007015123070107015F2B0F0E0701070118 +:104560005F6501D001D099D7AFD00701866F000EEB +:10457000070107015F6F070186510F0E0701070151 +:104580005F6501D001D001D09FD050C7E9FF51C76E +:10459000EAFF070107015F51040DF3CF86F7030E11 +:1045A00007018627070186510701070160250701DA +:1045B000876FE86A070186BFE86807010701612184 +:1045C0000701886F87C7E1FF88C7E2FFEFCFE7FFEA +:1045D00007010701504B512B50C7E9FF51C7EAFFB4 +:1045E000070107015F51040DF3CF86F7020E0701A3 +:1045F0008627070186510701070160250701876F9C +:10460000E86A070186BFE868070107016121070121 +:10461000886F87C7E1FF88C7E2FFEFCFE7FF070199 +:104620000701504B512B50C7E9FF51C7EAFF070163 +:1046300007015F51040DF3CF86F7010E07018627AE +:10464000070186510701070160250701876FE86AA6 +:10465000070186BFE8680701070161210701886F2C +:1046600087C7E1FF88C7E2FFEFCFE7FF0701070138 +:10467000504B512B50C7E9FF51C7EAFF0701070113 +:104680005F51040DF3500701070160250701866F94 +:10469000E86AF3BEE8680701070161210701876F37 +:1046A00086C7E1FF87C7E2FFEFCFE7FF07010701FA +:1046B000504B512B070107015F2B0F0E070107011C +:1046C0005F6501D001D061D70701866F0D0E07012C +:1046D00007015E6F070186510701866F080E07010B +:1046E00007015D6F070186510701866F020E070102 +:1046F00007015C6F070186510701866F000E0701F5 +:1047000007015F6F070186514F0E070107015F65C3 +:1047100001D001D001D0D5D3140E070107015F618C +:1047200001D001D074D007017AC786F707017BC793 +:1047300087F707017CC788F707017DC789F707015D +:10474000861F871F881F891F0701070176510701F0 +:10475000861507018A6F0701070177510701871541 +:1047600007018B6F070107017851070188150701C1 +:104770008C6F0701070179510701891507018D6FBA +:10478000070107017251070107017A1507018E6FB2 +:10479000070107017351070107017B1507018F6F9F +:1047A000070107017451070107017C150701906F8C +:1047B000070107017551070107017D150701916F79 +:1047C00007018A5107018E11070107016A6F07016E +:1047D0008B5107018F1107016B6F07018C51070186 +:1047E000901107016C6F07018D51070191110701AD +:1047F0006D6F990E070107016E6F790E07016F6FDC +:10480000820E0701706F5A0E0701716F50D1130E9F +:10481000070107015F6501D001D052D0280E0701C2 +:1048200007015F6101D001D04BD007010701725130 +:10483000070107017A190701866F07010701735104 +:10484000070107017B190701876F070107017451F1 +:10485000070107017C190701886F070107017551DE +:10486000070107017D190701896F070107017651CB +:1048700007018619070107016A6F070107017751D0 +:104880000701871907016B6F0701070178510701BD +:10489000881907016C6F0701070179510701891910 +:1048A00007016D6FA10E070107016E6FEB0E070187 +:1048B0006F6FD90E0701706F6E0E0701716FF7D021 +:1048C000270E070107015F6501D001D0A6D03C0E7D +:1048D000070107015F6101D001D09FD007010701E7 +:1048E00076510701070172150701866F070107015D +:1048F00077510701070173150701876F070107014A +:1049000078510701070174150701886F0701070136 +:1049100079510701070175150701896F0701070123 +:104920007651070107017A1507018A6F0701070110 +:104930007751070107017B1507018B6F07010701FD +:104940007851070107017C1507018C6F07010701EA +:104950007951070107017D1507018D6F07010701D7 +:104960007251070107017A1507018E6F07010701D0 +:104970007351070107017B1507018F6F07010701BD +:104980007451070107017C150701906F07010701AA +:104990007551070107017D150701916F07018A51C4 +:1049A00007018E110701926F07018B5107018F11CB +:1049B0000701936F07018C51070190110701946F54 +:1049C00007018D51070191110701956F070186516C +:1049D00007019211070107016A6F0701875107015B +:1049E000931107016B6F07018851070194110701AB +:1049F0006C6F070189510701951107016D6FDC0E7E +:104A0000070107016E6FBC0E07016F6F1B0E0701D8 +:104A1000706F8F0E0701716F4AD007010701725145 +:104A2000070107017A190701866F07010701735112 +:104A3000070107017B190701876F070107017451FF +:104A4000070107017C190701886F070107017551EC +:104A5000070107017D190701896F070107017651D9 +:104A600007018619070107016A6F070107017751DE +:104A70000701871907016B6F0701070178510701CB +:104A8000881907016C6F070107017951070189191E +:104A900007016D6FD60E070107016E6FC10E07018A +:104AA0006F6F620E0701706FCA0E0701716F0F0EF4 +:104AB000070107015F6501D001D01DD10701070182 +:104AC0005E51040DF3500701070160250701866F51 +:104AD000E86AF3BEE8680701070161210701876FF3 +:104AE00086C7E9FF87C7EAFF0701EECF7EF7070118 +:104AF000EECF7FF70701EECF80F70701EECF81F70A +:104B0000070107015D51040DF350070107016025FE +:104B10000701866FE86AF3BEE868070107016121B3 +:104B20000701876F86C7E9FF87C7EAFF0701EECF56 +:104B300082F70701EECF83F70701EECF84F7070175 +:104B4000EECF85F7070107018251070107017E1BA0 +:104B5000070107018351070107017F1B07010701B7 +:104B6000845107010701801B0701070185510701D7 +:104B70000701811B070107015C51040DF350070178 +:104B8000070160250701866FE86AF3BEE868070140 +:104B9000070161210701876F86C7E9FF87C7EAFF21 +:104BA0000701EECF82F70701EECF83F70701EECFC3 +:104BB00084F70701EECF85F707010701825107014E +:104BC00007017E1B070107018351070107017F1BB6 +:104BD00007010701845107010701801B0701070135 +:104BE000855107010701811B070107015F510F0B69 +:104BF000040DF3500701070160250701866FE86A7D +:104C0000F3BEE8680701070161210701876F86C7C6 +:104C1000E9FF87C7EAFF0701EECF82F70701EECF72 +:104C200083F70701EECF84F70701EECF85F7070181 +:104C300007018251070107017E1B0701070183510C +:104C4000070107017F1B07010701845107010701C5 +:104C5000801B07010701855107010701811B07011F +:104C6000866F010E070107019D6F070186517EC700 +:104C700099F77FC79AF780C79BF781C79CF7FDEC30 +:104C800015F0070107015F510F0B040DF3500701E9 +:104C9000070160250701876FE86AF3BEE86807012E +:104CA000070161210701886F87C7E9FF88C7EAFF0D +:104CB000070199C7EEFF07019AC7EEFF07019BC7DF +:104CC000EEFF07019CC7EDFFED52ED520701070112 +:104CD0005E2B070107015D2B070107015C2B0F0EFF +:104CE000070107015E170F0E070107015D170F0E81 +:104CF000070107015C17070107015F510F0B040D46 +:104D0000F3500701070160250701866FE86AF3BECB +:104D1000E8680701070161210701876F86C7E9FF7E +:104D200087C7EAFFEECF88F7EECF89F7EECF8AF795 +:104D3000EECF8BF707018C6F050E070107019D6F02 +:104D400007018C5166C799F767C79AF768C79BF741 +:104D500069C79CF7FDEC15F00701885107010701B1 +:104D6000992507018D6F07018951070107019A21D4 +:104D700007018E6F07018A51070107019B21070177 +:104D80008F6F07018B51070107019C210701906F6D +:104D9000070107016A5107018D250701916F07017E +:104DA00007016B5107018E210701926F070107016F +:104DB0006C5107018F210701936F070107016D51A6 +:104DC000070190210701946F070107016251070154 +:104DD00091250701956F0701070163510701922192 +:104DE0000701966F0701070164510701932107012D +:104DF000976F070107016551070194210701986F1B +:104E0000070107016E5107019525070107017E6F14 +:104E1000070107016F510701962107017F6F070105 +:104E200007017051070197210701806F07010701F2 +:104E30007151070198210701816F76C762F777C723 +:104E400063F778C764F779C765F772C776F773C7F2 +:104E500077F774C778F775C779F70701866F1E0E65 +:104E6000070107019D6F070186517AC799F77BC734 +:104E70009AF77CC79BF77DC79CF7FDEC15F099C7A7 +:104E800072F79AC773F79BC774F79CC775F766C725 +:104E90007AF767C77BF768C77CF769C77DF77EC776 +:104EA00066F77FC767F780C768F781C769F70701AB +:104EB00007015F2B4F0E070107015F6501D001D08D +:104EC0002BD452C7E9FF53C7EAFF07010701665118 +:104ED000EE2607016751EE2207016851EE22070115 +:104EE0006951ED22ED52ED5254C7E9FF55C7EAFF73 +:104EF000070107017A51EE2607017B51EE220701D7 +:104F00007C51EE2207017D51ED22ED52ED5256C744 +:104F1000E9FF57C7EAFF070107017251EE260701B3 +:104F20007351EE2207017451EE2207017551ED22F3 +:104F3000ED52ED5258C7E9FF59C7EAFF07010701D3 +:104F40007651EE2607017751EE2207017851EE22C5 +:104F500007017951ED22ED52ED525AC7E9FF5BC7C7 +:104F6000EAFF070107016251EE2607016351EE22B5 +:104F700007016451EE2207016551ED22ED52ED5219 +:104F8000120007011E6F000E070107011D6F0701C8 +:104F90001E51000E070107011D6501D001D001D08F +:104FA00082D34CD376D3430E07010701506F000E16 +:104FB0000701516F000E070107014E6F000E070138 +:104FC0004F6F440E070107014C6F000E07014D6F34 +:104FD0009EECE1F005010501C86F05010501C82936 +:104FE000D8A401D001D001D054D307011E6F020E06 +:104FF00005010501C96F07011E513C0E05010501A0 +:10500000CF6F000E0501D06F000E0501D16F000EAD +:105010000501D26F07011E6F000E05010501EB6F40 +:1050200007011E510501CA910501CA951AEC21F02C +:105030000009D8A401D001D001D02BD3C8C54CF7AA +:1050400050EC1AF02C0E070107014C5D010E070110 +:105050004D59D8B001D001D001D01BD30501CA7978 +:105060000A0E070107015A6F000E07015B6FFF0E62 +:1050700007010701586F000E0701596F050105016F +:10508000C8510E0D0101590EF32407010701566F97 +:105090000701576B0101010E0701572308EC1FF0B0 +:1050A00007011E6F000E07010701236F07011E5144 +:1050B00007011F6F010E07010701226F07011F5132 +:1050C00029ECB8F019EC22F0A3C7CBF5A4C7CCF5B6 +:1050D000A5C7CDF5A6C7CEF507011E6F030E0501C6 +:1050E0000501C96F07011E51D4D2C8C54CF7F2ECB7 +:1050F0001BF0FA0E070107014C5D000E07014D5928 +:10510000D8B001D001D038D019EC22F0050105014A +:10511000CB5107010701A35D07011E6F05010501C2 +:10512000CC5107010701A45907011F6F05010501B3 +:10513000CD5107010701A5590701206F05010501A0 +:10514000CE5107010701A6590701216FE40E1E5D2C +:105150003D0E1F59010E2059000E07012159D8A0FC +:1051600001D001D01FD707011E6F020E05010501F6 +:10517000C96F07011E518DD20501CA8754ECABF0EF +:10518000020AD8B401D001D001D083D207011E6F2A +:10519000040E05010501C96F07011E51C8C54CF772 +:1051A00050EC1AF0020E070107014C5D010E0701D9 +:1051B0004D59D8B001D001D001D06BD20A0E0701F1 +:1051C00007015A6F000E07015B6FFF0E0701070111 +:1051D000586F000E0701596F05010501C8510E0DEA +:1051E0000101590EF32407010701566F0701576BA0 +:1051F0000101010E0701572308EC1FF007011E6F84 +:10520000000E07010701236F07011E5107011F6FE1 +:10521000030E07010701226F07011F5129ECB8F0A7 +:1052200019EC22F0A3C7CBF5A4C7CCF5A5C7CDF5E3 +:10523000A6C7CEF507011E6F050E05010501C96F52 +:1052400007011E5126D2C8C54CF7F2EC1BF0FA0E2E +:10525000070107014C5D000E07014D59D8B001D080 +:1052600001D038D019EC22F005010501CB5107011E +:105270000701A35D07011E6F05010501CC51070160 +:105280000701A45907011F6F05010501CD51070151 +:105290000701A5590701206F05010501CE5107013E +:1052A0000701A6590701216FE40E1E5D3D0E1F592F +:1052B000010E2059000E07012159D8A001D001D0BC +:1052C00071D607011E6F020E05010501C96F0701A6 +:1052D0001E51DFD17AD0C8C54CF787EC1AF0050112 +:1052E0000501C86919EC22F0A3C7CBF5A4C7CCF51A +:1052F000A5C7CDF5A6C7CEF507011E6F060E0501A1 +:105300000501C96F07011E510501CA830501CA8144 +:1053100005010501EBA101D001D008D0D7C53CF6AD +:10532000D8C53DF6D9C53EF6DAC53FF605010501FB +:10533000EBA501D001D008D0DFC540F6E0C541F6AD +:10534000E1C542F6E2C543F605010501EBA301D034 +:1053500001D008D0DBC544F6DCC545F6DDC546F610 +:10536000DEC547F605010501EBA701D001D008D045 +:10537000E3C548F6E4C549F6E5C54AF6E6C54BF689 +:10538000000E060106014C6F000E06014D6F000E67 +:1053900006014E6F000E06014F6F05010501EBA9D6 +:1053A00001D001D008D0E7C54CF6E8C54DF6E9C5F7 +:1053B0004EF6EAC54FF6F6D507011E6F020E05013F +:1053C0000501C96F07011E51EDD554ECABF0050A7C +:1053D00082E0030AF1E0E6D519EC22F005010501AF +:1053E000CB5107010701A35D07011E6F05010501F0 +:1053F000CC5107010701A45907011F6F05010501E1 +:10540000CD5107010701A5590701206F05010501CD +:10541000CE5107010701A6590701216FF20E1E5D4B +:105420009E0E1F59000E2059000E07012159D8B0B9 +:1054300001D001D001D02DD1020E0501CF5D000EAB +:105440000501D059000E0501D159000E05010501D5 +:10545000D259D8A001D001D018D0F20E0501050113 +:10546000CB279E0E0501CC23000E0501CD23000E97 +:105470000501CE2305010501CF07000E0501D05B14 +:105480000501D15B0501D25B04D1430E0701070181 +:10549000506F000E0701516F000E070107014E6F9C +:1054A000000E07014F6F440E070107014C6F000EFD +:1054B00007014D6F9EECE1F005010501C86F050184 +:1054C0000501C829D8A401D001D001D0E2D007013C +:1054D0001E6F070E05010501C96F07011E51C8C5E2 +:1054E0004CF750EC1AF0020E070107014C5D010E5B +:1054F00007014D59D8B001D001D001D0CAD0070161 +:105500001E6F010E07010701236F07011E510701DE +:105510001F6F030E07010701226F07011F5129ECBE +:10552000B8F00501CA9519EC22F0A3C7CBF5A4C7C2 +:10553000CCF5A5C7CDF5A6C7CEF505010501C92B4C +:10554000A8D0C8C54CF7F2EC1BF0FA0E0701070112 +:105550004C5D000E07014D59D8B001D001D041D0AB +:1055600019EC22F005010501CB5107010701A35DEC +:1055700007011E6F05010501CC5107010701A45960 +:1055800007011F6F05010501CD5107010701A5594D +:105590000701206F05010501CE5107010701A6593A +:1055A0000701216FE40E1E5D3D0E1F59010E2059AB +:1055B000000E07012159D8A001D001D0F3D4050174 +:1055C00005EEC9F0EF2A0C0EEF6401D001D008D02F +:1055D00007011E6F020E05010501C96F07011E516B +:1055E00058D025D0C8C54CF787EC1AF00501050145 +:1055F000C86919EC22F0A3C7CBF5A4C7CCF5A5C7A1 +:10560000CDF5A6C7CEF507011E6F060E05010501F3 +:10561000C96F07011E510501CA83C4D407011E6F5B +:10562000020E05010501C96F07011E51BBD454ECE0 +:10563000ABF0050AD7E0030AF1E0B4D40501050197 +:10564000C951000A01E1AED4010A01E1ACD4030A58 +:1056500001E1D3D4010A01E148D5070A01E19ED551 +:10566000010A01E1F0D5030A01E1B6D6010A01E120 +:1056700036D70F0A01E165D7010A01E130D7030AE5 +:1056800001E15FD7010A01E12AD7070A01E159D7F1 +:1056900000D0070107011D2B000E070107011D6542 +:1056A00001D001D07ED4120007012B6F000E07013C +:1056B0000701236F07012B510701250E0701070181 +:1056C0004D6F0701070E07014E6F86EC1EF00701B4 +:1056D00007012551020AD8A401D001D00FD31C0E16 +:1056E000070107014E6F000E07014F6F69EC20F0B4 +:1056F00007012B6F000E07010701266F07012B51D1 +:10570000050E07010701266501D001D001D02CD07C +:105710000701250E070107014D6F0701070E07015D +:105720004E6F86EC1EF026C72BF72D0E07012B2798 +:1057300006013C0E07012B25E96EEA6A0601060EFA +:10574000EA22EF50070107012519D8B401D001D092 +:1057500001D014D307010701262B050E070107010D +:10576000266501D001D0D4D705010501CAB501D005 +:1057700001D01DD0100E070107014E6F000E07016A +:105780004F6F69EC20F0040E070107014F6F000E08 +:105790000701506F0501D70E070107014D6F050185 +:1057A000050E07014E6FA3EC13F00501EB81F00E1F +:1057B000070107014E6F000E07014F6F69EC20F0E3 +:1057C00007012B6F000E07010701226F07012B5104 +:1057D0000701250E070107014D6F0701070E07019D +:1057E0004E6F86EC1EF00009D8A401D001D009D07C +:1057F00007012B6F010E07010701226F07012B51D3 +:105800007DD25CD20701250E070107014D6F07010C +:10581000070E07014E6F86EC1EF0070107012505F4 +:10582000D8A401D001D01BD00701230E0701070126 +:105830004D6F0701070E07014E6F86EC1EF0050144 +:105840000501CAA501D001D009D0070107012351E4 +:10585000020AD8A401D001D001D090D201D08ED2BA +:1058600046D20701250E070107014D6F0701070EFC +:1058700007014E6F86EC1EF0070107012551040A4F +:10588000D8A401D001D0EBD705010501CAA501D0EC +:1058900001D026D007012B6F000E07010701266FEC +:1058A00007012B51030E07010701266501D001D026 +:1058B00001D015D00701250E070107014D6F070123 +:1058C000070E07014E6F86EC1EF007010701262B1D +:1058D000030E07010701266501D001D0EBD714D0D4 +:1058E000040E070107014F6F000E0701506F0501FD +:1058F000DF0E070107014D6F0501050E07014E6F11 +:10590000A3EC13F00501EB85ABD70701240E0701CB +:1059100007014D6F0701070E07014E6F86EC1EF061 +:10592000030E07010701246501D001D098D70501B6 +:105930000501CAA501D001D026D007012B6F000EAA +:1059400007010701266F07012B51030E070107010D +:10595000266501D001D001D015D00701250E070121 +:1059600007014D6F0701070E07014E6F86EC1EF011 +:1059700007010701262B030E07010701266501D049 +:1059800001D0EBD714D0040E070107014F6F000EB2 +:105990000701506F0501DB0E070107014D6F05017F +:1059A000050E07014E6FA3EC13F00501EB8300D049 +:1059B000040E07010701245F0BD00701250E070124 +:1059C00007014D6F0701070E07014E6F86EC1EF0B1 +:1059D00007010701240707012429D8A401D001D019 +:1059E000ECD785D10701240E070107014D6F070190 +:1059F000070E07014E6F86EC1EF0040E070107012B +:105A0000246101D001D001D0B9D105010501CAB589 +:105A100001D001D018D0040E070107014F6F000E0E +:105A20000701506F0501E30E070107014D6F0501E6 +:105A3000050E07014E6FA3EC13F00501EB87040E72 +:105A400007010701245F030E07010701246501D048 +:105A500001D01ED005010501CAB501D001D018D072 +:105A6000040E070107014F6F000E0701506F05017B +:105A7000E70E070107014D6F0501050E07014E6F87 +:105A8000A3EC13F00501EB89040E07010701245F65 +:105A90000BD00701250E070107014D6F0701070E07 +:105AA00007014E6F86EC1EF007010701240707016E +:105AB0002429D8A401D001D0ECD719D10701250E93 +:105AC000070107014D6F0701070E07014E6F86ECB6 +:105AD0001EF0070107012551040AD8A401D001D006 +:105AE000BED607012A0E070107014D6F0701070EF9 +:105AF00007014E6F86EC1EF00701290E0701070112 +:105B00004D6F0701070E07014E6F86EC1EF007016F +:105B1000280E070107014D6F0701070E07014E6FA1 +:105B200086EC1EF00701270E070107014D6F0701E4 +:105B3000070E07014E6F86EC1EF092D607012B6F01 +:105B4000010E07010701226F07012B51D0D0070179 +:105B5000250E070107014D6F0701070E07014E6F64 +:105B600086EC1EF0070107012551040AD8A401D0D4 +:105B700001D075D605010501CAA501D001D026D0F6 +:105B800007012B6F000E07010701266F07012B513C +:105B9000030E07010701266501D001D001D015D001 +:105BA0000701250E070107014D6F0701070E0701C9 +:105BB0004E6F86EC1EF007010701262B030E07012E +:105BC0000701266501D001D0EBD756D00501D20ED2 +:105BD000070107014D6F0501050E07014E6F86ECA9 +:105BE0001EF00501D10E070107014D6F0501050EDD +:105BF00007014E6F86EC1EF00501D00E070107016C +:105C00004D6F0501050E07014E6F86EC1EF0050174 +:105C1000CF0E070107014D6F0501050E07014E6FFD +:105C200086EC1EF00501CFC52BF70501D0C52CF77A +:105C30000501D1C52DF70501D2C52EF7060E06D0F8 +:105C4000D89007012E332D332C332B33E82EF8D781 +:105C500007012B5105010501CF5F07012C510501FB +:105C60000501D05B07012D5105010501D15B07013D +:105C70002E5105010501D25BF3D50701240E070162 +:105C800007014D6F0701070E07014E6F86EC1EF0EE +:105C90000BD00701250E070107014D6F0701070E05 +:105CA00007014E6F86EC1EF007010701240707016C +:105CB0002429D8A401D001D0ECD719D007010701BD +:105CC0002551010A01E1CDD5020A01E11ED6050ADE +:105CD00001E188D6350A01E13AD7060A01E192D5F9 +:105CE000030A01E1EBD6C90A01E128D7C6D70701AB +:105CF00007012251D8B401D001D06AD507010701AC +:105D00002351020AD8A401D001D00BD027C7D3F564 +:105D100028C7D4F529C7D5F52AC7D6F50501CA8500 +:105D200027D0070107012A5105010501D61914E101 +:105D300007010701295105010501D5190DE10701E9 +:105D40000701285105010501D41906E107010701E2 +:105D5000275105010501D319D8B401D001D008D0CD +:105D600007012B6F000E07010701236F07012B515D +:105D700051EC21F007010701235104D051EC21F02F +:105D8000000E00D01200020E070107014A25E96E3D +:105D9000000E070107014B21EA6EEE50ED10D8A46A +:105DA00001D001D002D0000E32D30701546FFE0E95 +:105DB000070107014E6F07015451020E0701070149 +:105DC0004A25E96E000E070107014B21EA6EEECF6E +:105DD00054F7EDCF55F74AC7E9FF4BC7EAFFEECFBF +:105DE00056F7EDCF57F74CC7E9FF4DC7EAFFEECFA7 +:105DF00058F7EDCF59F7020E070107014C25E96E60 +:105E0000000E070107014D21EA6EEECF5AF7EDCFE4 +:105E10005BF70701585107015A2507015C6F07011D +:105E2000595107015B2107015D6F070156510701B9 +:105E30005C2507015E6F0701575107015D210701CE +:105E40005F6F0701545107015E1907010701506F89 +:105E50000701555107015F190701516F0701546F81 +:105E6000000E070107014F6F07015451000E070193 +:105E700007014F6501D001D001D0A4D04FC760F712 +:105E800084EC0EF003010301F5510D0AD8A401D0F2 +:105E900001D001D08DD003010301F551040AD8A42B +:105EA00001D001D01CD0020E070107014A25E96E7E +:105EB000000E070107014B21EA6E030113EEF8F013 +:105EC000E652EE52ED50E518EFCFE8FFD8B4E718F0 +:105ED000D8A401D001D002D04FC74EF769D003013A +:105EE00003EEF8F00701EE5207015151ED180701DA +:105EF00050C7E8FFD8B4EF18D8B401D001D001D012 +:105F000057D077ECE7F0040104EED8F0020E070159 +:105F100007014A25E16E000E070107014B21E26EE1 +:105F2000E652EE52ED50E518EFCFE8FFD8B4E7188F +:105F3000D8A401D001D03CD0040104EED6F04AC769 +:105F4000E1FF4BC7E2FFE652EE52ED50E518EFCF0E +:105F5000E8FFD8B4E718D8A401D001D029D04CC7A5 +:105F6000E9FF4DC7EAFFEECF54F7EECF55F7EECF7E +:105F700056F7EECF57F704010401E1510701571915 +:105F800011E104010401E051070156190BE104017C +:105F90000401DF510701551905E104010401DE5137 +:105FA00007015419D8A401D001D002D0010E2FD27C +:105FB000070107014F2B000E070107014F6501D0B4 +:105FC00001D05CD7070107014E51FE0AD8B401D0B9 +:105FD00001D048D04EC760F784EC0EF077ECE7F0C4 +:105FE000070107014E51FE0AD8B401D001D03AD0C2 +:105FF00050C7F8F351C7F9F30A0E07010701B26F52 +:10600000000E0701B36F4CC7B0F74DC7B1F70401DD +:10601000DE0E07010701AE6F0401040E0701AF6F2A +:1060200018EC1AF04AC7E9FF4BC7EAFF0401EECFAC +:10603000D6F40401EDCFD7F4020E070107014A257B +:10604000E96E000E070107014B21EA6E0401EECF55 +:10605000D8F40401EDCFD9F4DFC3D4F4E0C3D5F410 +:10606000010ED5D10D0E070107014A25E96E000E7C +:10607000070107014B21EA6EEF500701546F07013A +:1060800054B301D001D002D0000EC1D106010601E7 +:1060900039513811D8B401D001D002D0000EB7D197 +:1060A000000E07010701526F000E0701536F030E28 +:1060B00007010701525D000E07015359D8A001D016 +:1060C00001D001D0C8D0070107015251140DF3CF00 +:1060D00054F7100E070154270601000E070154253E +:1060E000E96EEA6A0601060EEA22EE50ED10D8A427 +:1060F00001D001D001D0AFD0020E070107014A251F +:10610000E96E000E070107014B21EA6E0701070146 +:106110005251140DF3CF54F7100E07015427060106 +:10612000000E07015425E16EE26A0601060EE22226 +:10613000E652EE52ED50E518EFCFE8FFD8B4E7187D +:10614000D8B401D001D001D077D04AC7E9FF4BC7FE +:10615000EAFF070107015251140DF3CF54F70A0E5D +:10616000070154270601000E07015425E16EE26A7B +:106170000601060EE222E652EE52ED50E518EFCF90 +:10618000E8FFD8B4E718D8B401D001D001D054D07A +:106190004CC7E9FF4DC7EAFFEECF54F7EECF55F7F6 +:1061A000EECF56F7EECF57F7070107015251140D06 +:1061B0000601000EF324E96EEA6A0601060EEA22E1 +:1061C000EECF58F7EECF59F7EECF5AF7EECF5BF799 +:1061D0000701575107015B190EE1070156510701ED +:1061E0005A1909E1070155510701591904E107013D +:1061F000545107015819D8B401D001D001D01CD096 +:1062000055EC20F0070107015251140DF3CF54F75C +:10621000120E070154270601000E07015425E96EEE +:10622000EA6A0601060EEA22070170C7EEFF0701BF +:1062300071C7EDFF000EEBD007010701524B532B46 +:10624000030E07010701525D000E07015359D8A044 +:1062500001D001D038D70701546F000E07010701A4 +:106260004F6F07015451000E070107014F6501D020 +:1062700001D001D0CAD04FC760F784EC0EF0030103 +:106280000301F6B701D001D001D0B5D077ECE7F02B +:10629000020E070107014A25E96E000E07010701FA +:1062A0004B21EA6E040114EED8F0E652EE52ED50A6 +:1062B000E518EFCFE8FFD8B4E718D8B401D001D083 +:1062C00001D099D00A0E07010701B26F000E070135 +:1062D000B36F4CC7B0F74DC7B1F707010701525173 +:1062E000140D0601000EF32407010701AE6F07012C +:1062F000AF6B0601060E0701AF2318EC1AF04AC770 +:10630000E9FF4BC7EAFF070107015251140DF3CF14 +:1063100054F70A0E070154270601000E0701542501 +:10632000E16EE26A0601060EE222EECFE6FFEDCF55 +:10633000E5FF040E070107014A25E96E000E07017B +:1063400007014B21EA6E070107015251140DF3CFEB +:1063500054F70C0E070154270601000E07015425BF +:10636000E16EE26A0601060EE222EECFE6FFEECF14 +:10637000E6FFEECFE6FFEDCFE5FFE552E552020E78 +:10638000070107014A25E96E000E070107014B21AD +:10639000EA6E070107015251140DF3CF54F7100EA6 +:1063A000070154270601000E07015425E16EE26A39 +:1063B0000601060EE222EECFE6FFEDCFE5FF55EC3B +:1063C00020F0070107015251140DF3CF54F7120EBC +:1063D000070154270601000E07015425E96EEA6AF9 +:1063E0000601060EEA22070170C7EEFF070171C71A +:1063F000EDFF000E0CD0070107014F2B000E070127 +:1064000007014F6501D001D036D7000E00D0120031 +:106410002FC7E9FF30C7EAFF0701EECF38F70701C2 +:10642000EECF39F70701EECF3AF70701EECF3BF792 +:10643000040E070107012F25E96E000E0701070171 +:106440003021EA6E0701EECF3CF70701EECF3DF7B2 +:106450000701EECF3EF70701EECF3FF7080E070129 +:1064600007012F25E96E000E070107013021EA6EB2 +:106470000701EECF40F70701EECF41F70701EECF5E +:1064800042F70701EECF43F70C0E070107012F2556 +:10649000E96E000E070107013021EA6E0701EECF19 +:1064A00044F70701EECF45F70701EECF46F70701A6 +:1064B000EECF47F7100E070107012F25E96E000EFA +:1064C000070107013021EA6E0701EECF48F7070107 +:1064D000EECF49F70701EECF4AF70701EECF4BF7B2 +:1064E000180E070107012F2507010701366F000E5F +:1064F0000701070130210701376F140E070107015B +:106500002F25E96E000E070107013021EA6EEF50DA +:1065100007014C6F3F0E07014C1707014C51070153 +:106520000701362507014D6FE86A07014CBFE8688F +:1065300007010701372107014E6F4DC734F74EC7DA +:1065400035F707014C6F000E07010701336F070194 +:106550004C5117D036C7E9FF37C7EAFF01019F0E3C +:10656000070107013325E16EE26A0101010EE22213 +:10657000EFCFE7FF07010701364B372B0701070174 +:10658000332B07010701355107010701371906E1D0 +:10659000070107013451070107013619D8A401D0BA +:1065A00001D0D8D701019F0E070107013325E96EFD +:1065B000EA6A0101010EEA22800EEF6E070107016F +:1065C000332B380E07010701336501D001D05ED0AF +:1065D0003F0E07010701336501D001D001D016D06D +:1065E00001019F0E070107013325E96EEA6A0101E7 +:1065F000010EEA22000EEF6E07010701332B3F0E5A +:1066000007010701336501D001D0EAD70701480E21 +:10661000070107015A6F0701070E07015B6F0701AA +:10662000440E07010701586F0701070E0701596F54 +:106630000701400E07010701566F0701070E07010A +:10664000576F07013C0E07010701546F0701070E42 +:106650000701556F0701380E07010701526F070147 +:10666000070E0701536F01019F0E07010701506FCD +:106670000101010E0701516FD0ECA1F007014C6F31 +:10668000000E07010701336F07014C51370E070158 +:106690000701336501D001D001D016D001019F0E52 +:1066A000070107013325E96EEA6A0101010EEA22BA +:1066B000000EEF6E07010701332B370E07010701AC +:1066C000336501D001D0EAD7140E070107012F2549 +:1066D000E96E000E070107013021EA6EEF50070155 +:1066E0004C6F0701D8904C370701D8904C37070101 +:1066F000D8904C3501010101DE6F140E070107012E +:106700002F25E96E000E070107013021EA6EEECF5A +:106710004CF7EECF4DF7EECF4EF7EECF4FF7060E1C +:1067200006D0D89007014F334E334D334C33E82E0B +:10673000F8D707014C5101010101DD6F140E07016B +:1067400007012F25E96E000E070107013021EA6ECF +:10675000EECF4CF7EECF4DF7EECF4EF7EECF4FF733 +:106760000E0E06D0D89007014F334E334D334C33C5 +:10677000E82EF8D707014C5101010101DC6F140E1E +:10678000070107012F25E96E000E070107013021DF +:10679000EA6EEECF4CF7EECF4DF7EECF4EF7EECFE1 +:1067A0004FF7160E06D0D89007014F334E334D33B6 +:1067B0004C33E82EF8D707014C5101010101DB6F82 +:1067C000140E070107012F25E96E000E07010701CE +:1067D0003021EA6EEECF4CF7EECF4DF7EECF4EF70D +:1067E000EECF4FF71E0E06D0D89007014F334E3331 +:1067F0004D334C33E82EF8D707014C51010101010C +:10680000DA6F07014C6F000E01010101D96F07011A +:106810004C5107014C6F000E01010101D86F0701B7 +:106820004C5107014C6F000E01010101D76F0701A8 +:106830004C510701480E070107015A6F0701070E67 +:1068400007015B6F0701440E07010701586F07013D +:10685000070E0701596F0701400E07010701566F28 +:106860000701070E0701576F07013C0E07010701DB +:10687000546F0701070E0701556F0701380E070116 +:106880000701526F0701070E0701536F01019F0EA9 +:1068900007010701506F0101010E0701516FD0EC94 +:1068A000A1F031C7E9FF32C7EAFF07013BC7EFFF9D +:1068B00007010701314B322B31C7E9FF32C7EAFF2D +:1068C00007013AC7EFFF07010701314B322B31C7F0 +:1068D000E9FF32C7EAFF070139C7EFFF07010701E8 +:1068E000314B322B31C7E9FF32C7EAFF070138C706 +:1068F000EFFF07010701314B322B31C7E9FF32C7E8 +:10690000EAFF07013FC7EFFF07010701314B322BB9 +:1069100031C7E9FF32C7EAFF07013EC7EFFF0701B2 +:106920000701314B322B31C7E9FF32C7EAFF0701BC +:106930003DC7EFFF07010701314B322B31C7E9FF9C +:1069400032C7EAFF07013CC7EFFF07010701314BE0 +:10695000322B31C7E9FF32C7EAFF070143C7EFFF18 +:1069600007010701314B322B31C7E9FF32C7EAFF7C +:10697000070142C7EFFF07010701314B322B31C737 +:10698000E9FF32C7EAFF070141C7EFFF070107012F +:10699000314B322B31C7E9FF32C7EAFF070140C74D +:1069A000EFFF07010701314B322B31C7E9FF32C737 +:1069B000EAFF070147C7EFFF07010701314B322B01 +:1069C00031C7E9FF32C7EAFF070146C7EFFF0701FA +:1069D0000701314B322B31C7E9FF32C7EAFF07010C +:1069E00045C7EFFF07010701314B322B31C7E9FFE4 +:1069F00032C7EAFF070144C7EFFF07010701314B28 +:106A0000322B31C7E9FF32C7EAFF07014BC7EFFF5F +:106A100007010701314B322B31C7E9FF32C7EAFFCB +:106A200007014AC7EFFF07010701314B322B31C77E +:106A3000E9FF32C7EAFF070149C7EFFF0701070176 +:106A4000314B322B31C7E9FF32C7EAFF070148C794 +:106A5000EFFF07010701314B322B12000701096FCD +:106A6000000E070107011D6F07010951C8EC22F054 +:106A70000009D8A401D001D030D00701096F000E61 +:106A8000070107010D6F070109513BEC22F00701D7 +:106A9000096FFF0E070107010D6F0701095130EC67 +:106AA00022F02850D8B401D001D016D0E1C62DF77D +:106AB00029ECE3F0E1C60DF725EC22F00701096FA0 +:106AC000FE0E06010601E16F070109510701096F7A +:106AD000000E286E07010951BBD2E1C60DF798ECF4 +:106AE00021F00009D8A401D001D010D0010E2864F3 +:106AF00001D001D00BD0060E286001D001D006D005 +:106B00000701096F060E286E0701095185D2E1ECD5 +:106B100022F00009D8A401D001D015D00701096FD7 +:106B2000FF0E070107010D6F070109513BEC22F031 +:106B30000701096FFF0E070107010D6F07010951DA +:106B400030EC22F085D20701096FFF0E0701070123 +:106B50000D6F070109513BEC22F00701096F000E90 +:106B6000070107010D6F0701095130EC22F0070101 +:106B7000096F000E07010701146F070109510DC0CD +:106B800012F70EC013F707010A6F010E0701070184 +:106B9000116F07010A516F0E07010B6F060E0C6F84 +:106BA00007010BC70DF707010CC70EF70701070117 +:106BB0000F6B0701106B7DECBFF006010601E16F62 +:106BC0000701096F010E286E0701095119EC22F027 +:106BD000A3C7FBF4A4C7FCF4A5C7FDF4A6C7FEF445 +:106BE00037D2E1C60DF798EC21F00009D8A401D006 +:106BF00001D036D019EC22F004010401FB51070149 +:106C00000701A35D0701096F04010401FC5107019D +:106C10000701A45907010A6F04010401FD5107018E +:106C20000701A55907010B6F04010401FE5107017B +:106C30000701A65907010C6F5D0E095DA00E0A59E8 +:106C4000120E0B59000E07010C59D8A001D001D02B +:106C500006D00701096F060E286E07010951F8D109 +:106C600019EC22F0A3C7B1F6A4C7B2F6A5C7B3F6D4 +:106C7000A6C7B4F60701096F020E286E0701095175 +:106C8000E7D10701096F000E070107010D6F07012A +:106C900009513BEC22F00701096F000E07010701C3 +:106CA0000D6F0701095130EC22F011ECD3F0070110 +:106CB000096F030E286E07010951CAD119EC22F0A1 +:106CC00006010601AD5107010701A35D0701096F28 +:106CD00006010601AE5107010701A45907010A6F19 +:106CE00006010601AF5107010701A55907010B6F06 +:106CF00006010601B05107010701A65907010C6FF3 +:106D0000710E095D810E0A594A0E0B59000E0701DA +:106D10000C59D8A001D001D003D045EC1FF098D178 +:106D200019EC22F006010601B15107010701A35D2C +:106D30000701096F06010601B25107010701A459B5 +:106D400007010A6F06010601B35107010701A559A2 +:106D500007010B6F06010601B45107010701A6598F +:106D600007010C6F510E095D840E0A59DF0E0B5995 +:106D7000000E07010C59D8A001D001D007D007019F +:106D8000096F080E286E0701095162D1E1C613F799 +:106D90007FEC10F0070114511311D8B401D001D0C9 +:106DA00011D019EC22F0A3C7FBF4A4C7FCF4A5C7CB +:106DB000FDF4A6C7FEF40701096F040E286E070153 +:106DC000095146D145D119EC22F004010401FB51CF +:106DD00007010701A35D0701096F04010401FC51CC +:106DE00007010701A45907010A6F04010401FD51BD +:106DF00007010701A55907010B6F04010401FE51AA +:106E000007010701A65907010C6FE50E095D3D0E4C +:106E10000A59010E0B59000E07010C59D8A001D0D8 +:106E200001D009D0F6EC1DF00701096F030E286EA2 +:106E3000070109510DD1E1C613F77FEC10F00701EE +:106E400014511311D8A401D001D001D001D1E1C651 +:106E500013F77FEC10F0070114511311D8A401D0DF +:106E600001D001D0AFD70701080E070107010E6F4F +:106E70000701070E07010F6FE1C60DF7C1EC0CF01B +:106E80000009D8A401D001D001D09CD708C70DF7C4 +:106E900080ECCEF019EC22F0A3C7FBF4A4C7FCF4FD +:106EA000A5C7FDF4A6C7FEF4A4EC22F00009D8B4EF +:106EB00001D001D007D00701096F050E286E070128 +:106EC000095180D7C4D71CEC10F0F6EC1DF0070177 +:106ED000096F030E286E07010951BAD0E1C62DF7DC +:106EE00029ECE3F0E1C60DF725EC22F00701096F6C +:106EF000080E286E07010951ABD07AECC5F07F0E61 +:106F0000070107011617000E070117170A0E0701E0 +:106F10000701162500010001F36F000E07010701AC +:106F200017210001F46F19EC22F0A3C7FBF4A4C7EA +:106F3000FCF4A5C7FDF4A6C7FEF4D3EC1FF00701CF +:106F4000096F000E070107010D6F0701095130ECB1 +:106F500022F00701096F090E286E0701095178D048 +:106F600019EC22F004010401FB5107010701A35DA4 +:106F70000701096F04010401FC5107010701A4592D +:106F800007010A6F04010401FD5107010701A5591A +:106F900007010B6F04010401FE5107010701A65907 +:106FA00007010C6FF20E07010701786F9E0E0701B3 +:106FB000796F000E07017A6F000E07017B6F0001E9 +:106FC0000701F3C074F700010701F4C075F707016A +:106FD000000E070175BFFF0E0701766F0701776F7F +:106FE00051EC13F00701095107010701745D070116 +:106FF0000A5107010701755907010B5107010701E4 +:10700000765907010C51070107017759D8B001D013 +:1070100001D0D8D6FF001CD02850000A01E177D556 +:10702000010A01E1DED5030A01E12BD6010A01E1E3 +:1070300045D6070A01E1C7D6010A01E144D7030A90 +:1070400001E14CD70E0A01E158D7010A89E000D0CE +:1070500012000701296F010E07010701536F070195 +:10706000295163EC1FF00701296F010E0701070189 +:10707000536F0701295163EC1FF00701296F060EBA +:1070800007010701536F0701295163EC1FF0070146 +:10709000296F000E07010701536F0701295163ECA7 +:1070A0001FF00701296F120E07010701536F070137 +:1070B000295163EC1FF00701296F230E0701070117 +:1070C000536F0701295163EC1FF00701296F340E3C +:1070D00007010701536F0701295163EC1FF00701F6 +:1070E000296F560E07010701536F0701295163EC01 +:1070F0001FF00701296F000E07010701536F0701F9 +:10710000295163EC1FF00701296F000E07010701E9 +:10711000536F0701295163EC1FF00701296F800E9F +:1071200007010701536F0701295105010501CAA98C +:1071300001D001D008D00701296F000E0701070117 +:10714000536F0701295163EC1FF00701296F000EEF +:1071500007010701536F0701295163EC1FF0070175 +:1071600007012251030AD8A401D001D01AD0070187 +:1071700007012351D8B401D001D013D0040E070168 +:107180000701556F000E0701566F0501D70E070165 +:107190000701536F0501050E0701546FEBEC17F063 +:1071A00028D00701296F000E07010701536F07015F +:1071B000295163EC1FF00701296F000E0701070139 +:1071C000536F0701295163EC1FF00701296F000E6F +:1071D00007010701536F0701295163EC1FF00701F5 +:1071E000296F000E07010701536F0701295163EC56 +:1071F0001FF00701296F000E07010701246F070127 +:1072000029510B0E07010701246501D001D001D0DF +:1072100014D00701296F000E07010701536F070102 +:10722000295163EC1FF007010701242B0B0E070106 +:107230000701246501D001D0ECD7060E0701070134 +:10724000556F000E0701566F0601690E0701070111 +:10725000536F0601060E0701546FEBEC17F00701A0 +:10726000296F000E07010701246F07012951C90E7C +:1072700007010701246501D001D001D014D0070116 +:10728000296F000E07010701536F0701295163ECB5 +:107290001FF007010701242BC90E07010701246510 +:1072A00001D001D0ECD70701296F630E0701070158 +:1072B000536F0701295163EC1FF00701296F820EFC +:1072C00007010701536F0701295163EC1FF0070104 +:1072D000296F530E07010701536F0701295163EC12 +:1072E0001FF00701296F630E07010701536F0701A4 +:1072F000295163EC1FF00701296F350E07010701C3 +:10730000536F0701295163EC1FF00701296F010E2C +:1073100007010701536F0701295163EC1FF022C7D2 +:1073200053F763EC1FF0070107012205D8A401D031 +:1073300001D002D00501CA95070107012251030AB5 +:10734000D8A401D001D02AD007010701236701D0BA +:1073500001D024D00701296F360E07010701536FB2 +:107360000701295163EC1FF00701296F040E070183 +:107370000701536F0701295163EC1FF0D6C553F77E +:1073800063EC1FF0D5C553F763EC1FF0D4C553F77A +:1073900063EC1FF0D3C553F763EC1FF00701296FAF +:1073A000370E07010701536F0701295163EC1FF0E6 +:1073B0000701296F040E07010701536F07012951C7 +:1073C00063EC1FF00701296F010E07010701536FDE +:1073D0000701295163EC1FF00701296F030E070114 +:1073E0000701536F0701295163EC1FF00701296F53 +:1073F000060E07010701536F0701295163EC1FF0C7 +:107400000701296F0C0E07010701536F070129516E +:1074100063EC1FF0070107012251030AD8A401D031 +:1074200001D007D0070107012351D8B401D001D002 +:1074300010D0070107012205D8A401D001D02FD018 +:107440000501DA51D711D811D911D8B401D001D022 +:1074500026D00701296F320E07010701536F07017C +:10746000295163EC1FF00701296F040E0701070182 +:10747000536F0701295163EC1FF0040E0701070148 +:10748000556F000E0701566F0501D70E0701070162 +:10749000536F0501050E0701546FEBEC17F0070160 +:1074A000296FFF0E07010701536F0701295163EC94 +:1074B0001FF00AD00701296F000E07010701536F63 +:1074C0000701295163EC1FF02C0E135C010E1458B8 +:1074D000D8A001D001D0EED73CC625F73DC626F78F +:1074E0003EC627F73FC628F707010701236701D0EB +:1074F00001D00DD0000E060106013C6F000E060102 +:107500003D6F000E06013E6F000E06013F6FBCECA2 +:1075100009F025C73CF626C73DF627C73EF628C723 +:107520003FF61200000E07010701136F000E07015E +:10753000146F000E0701156F000E0701166F07018B +:107540000E0E07010701346F0701070E0701356FA3 +:1075500007010C0E07010701326F0701070E070133 +:10756000336F53EC1CF007010E0E070107012D6F5E +:107570000701070E07012E6F07010C0E0701070117 +:107580002B6F0701070E07012C6FE1EC10F0010EC5 +:10759000070107010F6F000E0701106F000E0701B2 +:1075A000116F000E0701126F000E07010701176F20 +:1075B000000E0701186F070107011851800A800F9C +:1075C000200ED8B4175DD8A001D001D001D06FD063 +:1075D00007010E0E070107012D6F0701070E0701B6 +:1075E0002E6F07010C0E070107012B6F0701070E15 +:1075F00007012C6FE1EC10F007010701196F07017B +:107600000E0E070107012D6F0701070E07012E6FF0 +:1076100007010C0E070107012B6F0701070E070179 +:107620002C6FE1EC10F0070107011A6F1BD025D079 +:10763000070107010F510701070113130701070194 +:107640001051070107011413070107011151070128 +:10765000070115130701070112510701070116134E +:107660000CD029D11AC72CF719C72BF763EC1EF0E1 +:10767000000ADDE0010ADCE0F4D70701D890070139 +:107680000F370701103707011137070112370701BC +:107690000701174B182B070107011851800A800FAB +:1076A000200ED8B4175DD8A001D001D091D7070122 +:1076B00013C71BF7070114C71CF7070115C71DF7F0 +:1076C000070116C71EF707011B1F1C1F1D1F1E1FCA +:1076D000110E06D0D89007011E331D331C331B3307 +:1076E000E82EF8D7FF0E07011B1507011F6F000ECC +:1076F00007011C150701206F000E07011D1507016A +:10770000216F000E07011E150701226F070113C725 +:1077100023F7070114C724F7070115C725F7070149 +:1077200016C726F7190E06D0D89007012633253341 +:1077300024332333E82EF8D7FF0E07012315070162 +:10774000276F000E070124150701286F000E07019F +:1077500025150701296F000E0701261507012A6F5D +:107760000701225107012A190EE1070121510701E2 +:10777000291909E1070120510701281904E107012E +:107780001F5107012719D8B401D001D001D093D0DF +:10779000FF0E070113C71BF7070114C71CF70701EA +:1077A00015C71DF7070116C71EF707011B1F1C1F72 +:1077B0001D1F1E1F07011B1507011F6F000E07016C +:1077C0001C150701206F000E07011D150701216F11 +:1077D000000E07011E150701226FFF0E070113C7D8 +:1077E00023F7070114C724F7070115C725F7070179 +:1077F00016C726F724C723F725C724F726C725F77A +:107800000701266B070123150701276F000E0701EB +:1078100024150701286F000E070125150701296FA0 +:10782000000E0701261507012A6F070122510701E3 +:107830002A190EE1070121510701291909E1070160 +:1078400020510701281904E107011F5107012719D9 +:10785000D8B401D001D001D02ED075EC21F0DF0ECC +:10786000070107012D6FFF0E07012E6F6D0E070137 +:1078700007012B6FFF0E07012C6F51EC22F013C78D +:107880002DF714C72EF715C72FF716C730F7D50EEB +:10789000070107012B6FFF0E07012C6FC8EC21F0C9 +:1078A00007011B6F020E070107012B6F07011B5118 +:1078B000E1EC20F000D012000601060168AD01D015 +:1078C00001D044D01AEC21F007010701106F070125 +:1078D000070110512F18D8B401D001D024D010C7FF +:1078E0002FF007010701106701D001D01CD050C64E +:1078F0003CF651C63DF652C63EF653C63FF654C658 +:1079000040F655C641F656C642F657C643F606013E +:10791000688F0701116F000E070107011D6F070136 +:10792000115169EC15F0C1ECA7F00701116F000EC1 +:10793000070107011D6F07011151C8EC22F0000972 +:10794000D8B401D001D002D00601689F87EC8EF038 +:10795000DAEC22F051EC21F00701080E07010701D3 +:107960001F6F0701070E0701206F0001C10E0701FD +:1079700007011D6F0001000E07011E6FA9EC03F047 +:107980000009D8A401D001D001D029D11DD107EC24 +:10799000E0F024D107010A0E07010701236F070158 +:1079A000070E0701246F0701090E07010701216F68 +:1079B0000701070E0701226F0001BD0E0701070135 +:1079C0001F6F0001000E0701206F07010C0E070159 +:1079D00007011D6F0701070E07011E6F5DECE5F043 +:1079E0000009D8A401D001D001D0F8D007010701C7 +:1079F0000905D8A401D001D09FD0060106013F514E +:107A0000070107010F1914E1060106013E510701A4 +:107A100007010E190DE1060106013D51070107019D +:107A20000D1906E1060106013C51070107010C1979 +:107A3000D8B401D001D070D007010C29D8B40D29D9 +:107A4000D8B40E29D8B40F29D8B401D001D064D04D +:107A5000060140C611F7060141C612F7060142C6EB +:107A600013F7060143C614F70701111F121F131F56 +:107A7000141F060106013C510601060140150701CD +:107A8000156F060106013D5106010601411507016A +:107A9000166F060106013E51060106014215070157 +:107AA000176F060106013F51060106014315070144 +:107AB000186F07011151070115110701196F07010F +:107AC00012510701161107011A6F0701135107011F +:107AD000171107011B6F0701145107011811070146 +:107AE0001C6F070107010F5107011C1911E1070164 +:107AF00007010E5107011B190BE1070107010D5189 +:107B000007011A1905E1070107010C5107011919AD +:107B1000D8A401D001D00FD00AC71FF70BC720F798 +:107B20000001BD0E070107011D6F0001000E0701D6 +:107B30001E6FFDEC00F052D0070107010951060A43 +:107B4000D8A401D001D019D00AC721F70BC722F75A +:107B500007010C0E070107011F6F0701070E070140 +:107B6000206F0001BD0E070107011D6F0001000E0F +:107B700007011E6F2EECD9F031D007010701095122 +:107B8000110AD8A401D001D0D6D70AC721F70BC754 +:107B900022F707010C0E070107011F6F0701070EEF +:107BA0000701206F0001BD0E070107011D6F0001D5 +:107BB000000E07011E6F37ECD8F00009D8B401D0D1 +:107BC00001D001D00CD00AD0070107010851000AEA +:107BD00001E1E0D6060A01E1DAD600D0BBD61200F8 +:107BE0000701096F000E070107011D6F0701095109 +:107BF000C8EC22F00009D8A401D001D01ED0075053 +:107C0000D8B401D001D018D0DEC62DF729ECE3F0AE +:107C1000DEC60DF725EC22F00701096FFE0E060106 +:107C20000601DE6F0701095123EC1CF00701096F03 +:107C3000000E076E070109515FD14FD10701096F8F +:107C4000010E076E070109510701096F000E0701B8 +:107C50000701146F07010951500E07010701126F48 +:107C6000000E0701136F07010A6F010E07010701DC +:107C7000116F07010A51B50E07010B6F060E0C6F4D +:107C800007010BC70DF707010CC70EF70701070126 +:107C90000F6B0701106B7DECBFF006010601DE6F74 +:107CA00006010601DE51FE0AD8A401D001D007D09A +:107CB0000701096F000E076E070109511DD119EC6C +:107CC00022F0A3C7F3F4A4C7F4F4A5C7F5F4A6C73C +:107CD000F6F412D1DEC60DF798EC21F00009D8A415 +:107CE00001D001D036D019EC22F004010401F35187 +:107CF00007010701A35D0701096F04010401F451A5 +:107D000007010701A45907010A6F04010401F55195 +:107D100007010701A55907010B6F04010401F65182 +:107D200007010701A65907010C6F5D0E095DA00E42 +:107D30000A59120E0B59000E07010C59D8A001D098 +:107D400001D006D00701096F040E076E0701095123 +:107D5000D3D00701096F020E076E07010951CCD07D +:107D6000DEC641F747EC0AF07D0E07010701415DD1 +:107D7000000E07014259D8B001D001D001D0BCD0CB +:107D8000C60E07010701306FFF0E0701316FDEC617 +:107D90002FF7A5EC20F0620E07010701306FFE0EF1 +:107DA0000701316FDEC62FF7A5EC20F0040E0701A6 +:107DB0000701306FFF0E0701316FDEC62FF7A5EC0C +:107DC00020F00601B50E07010701306F0601060E0F +:107DD0000701316FDEC62FF7CDEC20F0D80E07017A +:107DE0000701306FFE0E0701316FDEC62FF7A5ECDD +:107DF00020F0DEC641F7DEEC1CF00701096F000E33 +:107E0000316E070109510701096F030E076E070163 +:107E1000095172D00701080E070107010E6F070113 +:107E2000070E07010F6FDEC60DF7C1EC0CF000095D +:107E3000D8A401D001D001D023D0030E316401D0E9 +:107E400001D005D008C70DF7A9EC01F018D0070143 +:107E5000070108510A0AD8B401D001D008D007019F +:107E6000070108510D0AD8A401D001D002D0312A4F +:107E700006D00701096F000E316E07010951CAD7FC +:107E8000DEC60DF798EC21F00009D8A401D001D08E +:107E900006D00701096F040E076E070109512CD0A7 +:107EA000DEC62DF729ECE3F0DEC60DF725EC22F057 +:107EB0000701096FFE0E06010601DE6F0701095179 +:107EC0000701096F010E226E070109510701096FB1 +:107ED000050E076E070109510FD00750000A01E196 +:107EE000ADD6010A01E1F6D6030A01E139D7010A4C +:107EF00091E0070AD5E000D012000701166F000ECE +:107F000007010701156F07011651000E0701070150 +:107F1000156501D001D001D076D115C760F784EC8A +:107F20000EF003010301F5510D0AD8B401D001D0C0 +:107F300001D05FD177ECE7F004010401EE510701B5 +:107F400007011419D8B401D001D001D052D1180EB4 +:107F500004010401EB6F020E0401EC6F070107013D +:107F6000116701D001D013D012C7D8F413C7D9F4C8 +:107F70000301F6870701166F040E03010301F56F75 +:107F80000701165112C7F8F313C7F9F32ED1000EEB +:107F900000010001FD5D040E0001FE59D8A001D0D2 +:107FA00001D00BD0890E00010001FD5D130E000110 +:107FB000FE59D8A001D001D007D0000E0001000169 +:107FC000FD6F040E0001FE6FFDC0D8F4FEC0D9F4B1 +:107FD00000010001FD4BFE2B12C7D6F413C7D7F4E6 +:107FE00019EC22F0A3C7EDF3A4C7EEF3A5C7EFF396 +:107FF000A6C7F0F30301F689E9D00DC7DEF40EC77A +:10800000DFF40FC7E0F410C7E1F4070107011151D5 +:10801000020AD8B401D002D0010E01D0000E07012F +:10802000166F0701164716470401EA510701161992 +:10803000FB0B16190401EA6F0701166F000E03010E +:108040000301F56F07011651D0D0070107EE0FF0BD +:10805000EECF16F7EDCF17F7070107010D51070116 +:108060001627070107010E51070117230701070112 +:1080700012510701162707010701135107011723A2 +:1080800004010401D8510701161903010301F86F17 +:1080900004010401D951070117190301F96F0DC734 +:1080A000DEF40EC7DFF40FC7E0F410C7E1F40701F8 +:1080B000166F000E04010401ED6F07011651270E23 +:1080C00004010401C86F000E0401C96F000E040111 +:1080D000CA6F000E0401CB6F0701166F020E030179 +:1080E0000301F56F0701165180D007010DC7F6FF98 +:1080F00007010EC7F7FF000EF86E0900F5CF16F75F +:108100000900F5CF17F7070100EE02F007010D5146 +:10811000E92607010E51EA22EECF18F7EDCF19F745 +:10812000070116510701182507011A6F070117519A +:108130000701192107011B6F0701070112510701F0 +:108140001A2707010701135107011B23040104012A +:10815000D85107011A1903010301F86F0401040142 +:10816000D95107011B190301F96F0A0E0701070115 +:10817000B26F000E0701B36F0DC7B0F70EC7B1F7AE +:108180000401DE0E07010701AE6F0401040E0701B2 +:10819000AF6F18EC1AF00701166F050E030103010B +:1081A000F56F070116510701166F010E0701070150 +:1081B000716F070116510701176F020E07010701C2 +:1081C000706F07011751B4EC9BF00FD00701070146 +:1081D0001151010A01E111D7030A01E10ED7010A89 +:1081E00001E133D7070A81E000D0070107011551EB +:1081F0000CD007010701152B000E070107011565BB +:1082000001D001D08AD6FE0E00D0120007013C6FCB +:10821000000E07010701356F07013C5107013C6F54 +:10822000000E07010701366F07013C51000E0701E0 +:108230000701386F000E0701396F000E07013A6F12 +:10824000000E07013B6FE7D0030E070107013665FB +:1082500001D001D001D0FBD0300E07010701375FFC +:1082600007010701356701D001D00AD0090E0701C7 +:108270000701376501D001D002D0000E49D1B7D037 +:10828000070107013551030AD8A401D001D054D009 +:10829000070107013751FE0AD8B401D001D002D03E +:1082A000000E36D1060E0701385D050E070139595B +:1082B000020E07013A59000E070107013B59D8A0E9 +:1082C00001D001D002D0000E23D1070107013651A1 +:1082D000070107013325E96E0701000E07010701B9 +:1082E0003421EA6E0701070139510A0DF3CF3CF73B +:1082F000070107013A51640DF35007013C250701BE +:1083000007013825EF6E07010701362B07013C6F87 +:10831000000E07010701356F07013C51000E0701F0 +:108320000701386F000E0701396F000E07013A6F21 +:10833000000E07013B6F6FD0070107013751FE0A9E +:10834000D8A401D001D04AD0060E0701385D050E31 +:1083500007013959020E07013A59000E07010701BA +:108360003B59D8A001D001D002D0000ED1D00701D6 +:1083700007013651070107013325E96E0701000E99 +:10838000070107013421EA6E0701070139510A0D7F +:10839000F3CF3CF7070107013A51640DF350070191 +:1083A0003C25070107013825EF6E07010701362B31 +:1083B00007013C6F000E07010701356F07013C51B3 +:1083C000000E07010701386F000E0701396F000E1C +:1083D00007013A6F000E07013B6F1DD0090E070120 +:1083E0000701376501D001D002D0000E91D00701FE +:1083F0000701352B070107013AC73BF707010701C2 +:1084000039C73AF70701070138C739F707010701EC +:10841000386B37C738F707010701315107013C6F47 +:1084200007010701325107013D6F0701314B322B24 +:108430003CC7F6FF3DC7F7FF000EF86E08000701C6 +:10844000F5CF37F70701376701D001D0FDD6070117 +:1084500007013751D8B401D001D02AD00701070154 +:1084600037512F0AD8B401D001D022D0070107011B +:1084700037510D0AD8B401D001D01AD00701070135 +:1084800037510A0AD8B401D001D012D00701070130 +:108490003751200AD8B401D001D00AD00701070112 +:1084A0003751090AD8B401D001D002D0000E30D023 +:1084B000060E0701385D050E07013959020E070146 +:1084C0003A59000E070107013B59D8A001D001D04D +:1084D00002D0000E1DD0030E070107013325E96EFF +:1084E000000E070107013421EA6E07010701395127 +:1084F0000A0DF3CF3CF7070107013A51640DF35021 +:1085000007013C25070107013825EF6E010E00D059 +:10851000120007013C6F000E07010701356F0701CC +:108520003C5107013C6F000E07010701366F070140 +:108530003C51000E07010701386F000E0701396F2B +:10854000000E07013A6F000E07013B6FE7D0030EE4 +:1085500007010701366501D001D001D0F2D0300EFD +:1085600007010701375F07010701356701D001D017 +:108570000AD0090E07010701376501D001D002D0EA +:10858000000E40D1B7D0070107013551030AD8A426 +:1085900001D001D054D0070107013751FE0AD8B4E9 +:1085A00001D001D002D0000E2DD1060E0701385D9A +:1085B000050E07013959020E07013A59000E07014D +:1085C00007013B59D8A001D001D002D0000E1AD12A +:1085D000070107013651070107013325E96E07013D +:1085E000000E070107013421EA6E07010701395126 +:1085F0000A0DF3CF3CF7070107013A51640DF35020 +:1086000007013C25070107013825EF6E0701070127 +:10861000362B07013C6F000E07010701356F07017C +:108620003C51000E07010701386F000E0701396F3A +:10863000000E07013A6F000E07013B6F6FD0070174 +:1086400007013751FE0AD8A401D001D04AD0060E46 +:108650000701385D050E07013959020E07013A5925 +:10866000000E070107013B59D8A001D001D002D06C +:10867000000EC8D007010701365107010701332555 +:10868000E96E0701000E070107013421EA6E0701B8 +:10869000070139510A0DF3CF3CF7070107013A51A1 +:1086A000640DF35007013C25070107013825EF6EE3 +:1086B00007010701362B07013C6F000E0701070178 +:1086C000356F07013C51000E07010701386F000E9E +:1086D0000701396F000E07013A6F000E07013B6F6B +:1086E0001DD0090E07010701376501D001D002D066 +:1086F000000E88D007010701352B070107013AC793 +:108700003BF70701070139C73AF70701070138C7E7 +:1087100039F707010701386B37C738F7070131C749 +:10872000E9FF070132C7EAFF07010701314B322B8E +:10873000EF5007010701376F0701376701D001D0FC +:1087400006D7070107013751D8B401D001D02AD08C +:108750000701070137512F0AD8B401D001D022D028 +:108760000701070137510D0AD8B401D001D01AD042 +:108770000701070137510A0AD8B401D001D012D03D +:10878000070107013751200AD8B401D001D00AD01F +:10879000070107013751090AD8B401D001D002D02E +:1087A000000E30D0060E0701385D050E070139595D +:1087B000020E07013A59000E070107013B59D8A0E4 +:1087C00001D001D002D0000E1DD0030E0701070119 +:1087D0003325E96E000E070107013421EA6E070117 +:1087E000070139510A0DF3CF3CF7070107013A5150 +:1087F000640DF35007013C25070107013825EF6E92 +:10880000010E00D012000701226F000E07010701C0 +:108810000F6F07012251000E07010701146F000EB0 +:108820000701156F000E0701166F000E0701176F85 +:10883000010E07010701186F000E0701196F000EE6 +:1088400007011A6F000E07011B6F07010E0E0701CB +:108850000701346F0701070E0701356F07010C0E82 +:1088600007010701326F0701070E0701336F53EC51 +:108870001CF007010E0E070107012D6F0701070EFF +:1088800007012E6F07010C0E070107012B6F07016F +:10889000070E07012C6FE1EC10F00CC712F70DC7A3 +:1088A00013F7070107010EC710F707010701116B46 +:1088B000000E070107011C6F000E07011D6F070165 +:1088C00007011D51800A800F200ED8B41C5DD8A06E +:1088D00001D001D001D059D007010E0E07010701C8 +:1088E000266F0701070E0701276F07010C0E07010E +:1088F0000701246F0701070E0701256F89EC14F0AB +:1089000007010701206F070107012051020AD8A4BF +:1089100001D001D001D0EDD0070107012051D8B41A +:1089200001D001D018D00701070118510701070134 +:108930001413070107011951070107011513070156 +:1089400007011A51070107011613070107011B51FF +:108950000701070117130701D8900701183707010E +:10896000193707011A3707011B37070107011C4B8D +:108970001D2B070107011D51800A800F200ED8B45E +:108980001C5DD8A001D001D0A7D7000E07010701B8 +:108990001E6F000E07011F6F070107011F51800A9C +:1089A000800F040ED8B41E5DD8A001D001D001D034 +:1089B0004AD007010E0E07010701266F0701070EB7 +:1089C0000701276F07010C0E07010701246F07013C +:1089D000070E0701256F89EC14F007010701216FCD +:1089E000070107012151020AD8A401D001D001D00A +:1089F00080D0070107012151D8B401D001D013D094 +:108A00001EC722F7010E0701236F0701222B03D097 +:108A1000D890070123370701222FFAD707012351E6 +:108A2000070107010F13070107011E4B1F2B070149 +:108A300007011F51800A800F040ED8B41E5DD8A014 +:108A400001D001D0B6D7070107010F510C0AD8B4E5 +:108A500001D001D001D04DD075EC21F0A00E07015E +:108A600007012D6FFF0E07012E6FBB0E07010701D7 +:108A70002B6FFF0E07012C6F51EC22F07F0E0701C8 +:108A800007012D6FFF0E07012E6F6D0E0701070105 +:108A90002B6FFF0E07012C6F51EC22F0F00E070137 +:108AA00007012D6FFE0E07012E6FB50E070107019E +:108AB0002B6FFF0E07012C6F51EC22F014C72DF71E +:108AC00015C72EF716C72FF717C730F7D50E0701B2 +:108AD00007012B6FFF0E07012C6FC8EC21F0070177 +:108AE000226F010E070107012B6F07012251E1ECF4 +:108AF00020F01200C2CF29F7C0CF2AF7D5CF2BF72D +:108B0000D6CF2DF7D7CF2CF7010EC26E07012E6FEF +:108B10003F0EC06E07012E5107012E6F880ED56ED5 +:108B200007012E5107012E6F000E070107011A6F72 +:108B300007012E51000E07010701216F000E0701EA +:108B4000226F000E0701236F000E0701246F000E35 +:108B5000070107011D6F000E07011E6F1FEC15F0C6 +:108B60000701070172C725F70701070173C726F739 +:108B70000701000E070126BFFF0E0701276F07013F +:108B8000286F000ED76E000ED66EC282040000D091 +:108B9000C2B201D001D0FCD7D6CF1FF7D7CF20F774 +:108BA0001FEC15F072C71BF773C71CF7070107010D +:108BB0001F51070107012127070107012051070164 +:108BC00007012223000E070107012323000E0701DE +:108BD000070124231A0E0701215DF20E0701225915 +:108BE0009E0E07012359000E070107012459D8A042 +:108BF00001D001D083D01FEC15F00701070172519D +:108C000007012E6F07010701735107012F6F07013D +:108C1000306B0701316B1E0ED89007012E372F37AE +:108C200030373137E82EF8D71FEC15F0070172C73F +:108C300032F7070173C733F7000E070133BFFF0E8A +:108C4000346F356F0F0ED890070132373337343712 +:108C50003537E82EF8D71FEC15F0070172C736F745 +:108C6000070173C737F7000E070137BFFF0E386FD4 +:108C7000396F070132510701361107013A6F0701B9 +:108C800033510701371107013B6F070134510701C9 +:108C9000381107013C6F07013551070139110701F0 +:108CA0003D6F07012E5107013A1107013E6F070181 +:108CB0002F5107013B1107013F6F07013051070199 +:108CC0003C110701406F0701315107013D110701B8 +:108CD000416F07013E5107010701251B07013F5165 +:108CE00007010701261B0701405107010701271B48 +:108CF0000701415107010701281B58D0070107014F +:108D00002051070107011E1906E1070107011F5144 +:108D1000070107011D19D8A401D001D001D045D009 +:108D200007011DC72EF707011EC72FF7070107010F +:108D30001F5107012E5F07010701205107012F5B1B +:108D4000070107011B5107012E2507010701746F59 +:108D5000070107011C5107012F210701756F7DECE9 +:108D600020F01FC71DF720C71EF70701D890070185 +:108D700025370701263707012737070128371FEC5A +:108D800015F0070107017351800A400F000ED8B497 +:108D9000725DD8A001D001D003D007010701258161 +:108DA000070107011A3F01D001D0EBD629C7C2FF46 +:108DB0002AC7C0FF2CC7D7FF2DC7D6FF2BC7D5FFAB +:108DC00025C716F726C717F727C718F728C719F7B3 +:108DD00000D01200070107010C51D8B401D001D016 +:108DE00005D0030E070107010D2704D0030E07016C +:108DF00007010D5F3ED10B0E070107010D6501D084 +:108E000001D009D0170E070107010D6101D001D073 +:108E100002D0032A39D1030E070107010D6501D0E5 +:108E200001D01FD00D0E070107010D6101D001D047 +:108E300018D0190E036401D001D00DD007010E6FB8 +:108E4000010E086E07010E51000E00010001F56FC2 +:108E5000000E0001F66F07010E6F000E036E070192 +:108E60000E5112D10DC711F70CC710F7B3EC15F066 +:108E700010C7F7F011C7F8F000010001F829FE0E45 +:108E8000D8B4F719D8A401D001D003D0F4EC20F065 +:108E9000FBD000010001F729D8B4F829D8A401D0EB +:108EA00001D001D0F1D000010001F651F511D8A494 +:108EB00001D001D009D000010001F75100010001EB +:108EC000F66F0001F56B49D000010001F751000178 +:108ED0000001F51300010001F85100010001F61333 +:108EE00011D007010E6F060E0A6E07010E5129D030 +:108EF00007010E6F080E0A6E07010E5122D0F4EC26 +:108F000020F0C2D00001F5C00EF70001F6C00FF747 +:108F10000FD007010E514D0AEBE0F1D707010E51BA +:108F20002D0AE6E0ECD707010E514C0ADAE0E7D74C +:108F300007010F510A0AEDE0100AF0E0F00AF3E031 +:108F4000DED707010E6F020E086E07010E510701F2 +:108F50000E6F000E036E07010E5196D00DC711F76C +:108F60000CC710F7B3EC15F010C7F7F011C7F8F005 +:108F700000010001F829FE0ED8B4F719D8A401D0D9 +:108F800001D003D0F4EC20F07FD000010001F729DC +:108F9000D8B4F829D8A401D001D001D075D00001EF +:108FA000C70E0324E96EEA6A0001000EEA220001FE +:108FB000F7C0EFFF032A0A060A6601D001D051D795 +:108FC000F4EC20F075EC21F0A00E070107012D6FE5 +:108FD000FF0E07012E6FBB0E070107012B6FFF0E5F +:108FE00007012C6F51EC22F0AE0E070107012D6F27 +:108FF000FF0E07012E6F6D0E070107012B6FFF0E8D +:1090000007012C6F51EC22F000010701F5C02DF78C +:1090100000010701F6C02EF7070107012F6B0701BA +:10902000306BB50E070107012B6FFF0E07012C6F88 +:10903000C8EC21F003C020F70001C70E07010701AB +:109040001E6F0001000E07011F6FD50E07010701FB +:109050001C6FFF0E07011D6F00EC22F007010E6F61 +:10906000010E070107012B6F07010E51E1EC20F003 +:109070000BD00850000A01E1BED6010A01E1F2D688 +:10908000030A01E16BD700D01200C00E07010701EF +:10909000126F100E0701136F00010001FE51FD1148 +:1090A000D8A401D001D019D07AECC5F0FF0E070189 +:1090B000070116150701146F070E070107011715A1 +:1090C0000701156F000E0701142500010001FD6F57 +:1090D000040E070115210001FE6F3C0E0701070178 +:1090E0005A6F000E07015B6F000E07010701586FF2 +:1090F000000E0701596F0601000E07010701566FA8 +:109100000601060E0701576F08EC1FF00701146FE8 +:10911000000E07010701096F070114510701146FC1 +:10912000000E070107010B6F07011451000E070124 +:1091300007010B6501D001D001D0EDD00BC760F75E +:1091400084EC0EF0070107010B51060DF3CF14F765 +:10915000010E07011427AF0E07011425F66EF76AFA +:10916000FE0EF722F86A000EF82208000701F5CF7C +:109170000AF7070107010B51060DF3CF14F7020E92 +:1091800007011427AF0E07011425F66EF76AFE0ECD +:10919000F722F86A000EF82209000701F5CF10F750 +:1091A0000A000701F5CF11F7070107010B51060D62 +:1091B000F3CF14F7040E07011427AF0E070114258F +:1091C000F66EF76AFE0EF722F86A000EF822090022 +:1091D0000701F5CF0EF70A000701F5CF0FF731D0E1 +:1091E00012C70CF713C70DF7070110C714F70701D3 +:1091F00011C715F7070107010E51070114270701D1 +:1092000007010F5107011523290E07011427000E2E +:1092100015230701145107010701122707011551F2 +:1092200007010701132300D0FD0E07010701125D9E +:109230001F0E07011359D8B001D001D0F5D707D0C0 +:10924000FFD7070107010A51000ACAE0F9D70AC788 +:10925000FAF3270E070107010C2503010301DF6F55 +:10926000000E070107010D210301E06F0301DFC3B9 +:1092700014F70301E0C315F70701070110510701B7 +:10928000142707010701115107011523010E0701DA +:10929000142503010301E16F000E070115210301ED +:1092A000E26F070107010E5103010301E1250301EC +:1092B0000301E36F070107010F5103010301E221DD +:1092C0000301E46F0701146F0D0E03010301F56F35 +:1092D000070114510301F69777ECE7F00701070146 +:1092E0000B51060DAF0EF324F66EF76AFE0EF72251 +:1092F000F86A000EF82208000401F5CFEEF417EC2E +:109300000EF0070107010B2B000E070107010B658B +:1093100001D001D013D712000701070143690101F1 +:10932000590E07010701456F0101010E0701466F44 +:109330000701476F000E07010701446F07014751FE +:10934000040E07010701446501D001D001D0E8D027 +:10935000020E070107013D25E96E000E0701070116 +:109360003E21EA6E0C0E070107014525E16E000E55 +:10937000070107014621E26EE652EE52ED50E51874 +:10938000EFCFE8FFD8B4E718D8A401D001D0B7D008 +:109390003DC7E9FF3EC7EAFF0A0E07010701452561 +:1093A000E16E000E070107014621E26EE652EE5221 +:1093B000ED50E518EFCFE8FFD8B4E718D8A401D0F6 +:1093C00001D09BD03FC7E9FF40C7EAFFEECF47F788 +:1093D000EECF48F7EECF49F7EECF4AF745C7E9FFA2 +:1093E00046C7EAFFEECF4BF7EECF4CF7EECF4DF787 +:1093F000EECF4EF707014A5107014E190EE1070162 +:10940000495107014D1909E10701485107014C195C +:1094100004E10701475107014B19D8B401D001D02D +:1094200068D041C7E9FF42C7EAFFEECF47F7EECF6A +:1094300048F7EECF49F7EECF4AF707014729D8B4EE +:109440004829D8B44929D8B44A29D8B401D001D080 +:1094500050D041C7E9FF42C7EAFFEECF47F7EECF52 +:1094600048F7EECF49F7EECF4AF7060140C64BF773 +:10947000060141C64CF7060142C64DF7060143C638 +:109480004EF707014B1F4C1F4D1F4E1F06010601D3 +:109490003C5107014B1107014F6F060106013D5179 +:1094A00007014C110701506F060106013E510701EB +:1094B0004D110701516F060106013F5107014E1181 +:1094C0000701526F07014A51070152190EE10701C6 +:1094D00049510701511909E1070148510701501984 +:1094E00004E10701475107014F19D8A401D001D069 +:1094F00004D007010701445151D044C743F70E0E71 +:10950000070107014527000E070146230701070150 +:10951000442B040E07010701446501D001D018D780 +:10952000070107014329D8B401D001D033D0070186 +:10953000070143510E0D0101590EF32407010701E4 +:10954000456F0701466B0101010E070146230A0E14 +:1095500007010701B26F000E0701B36F3FC7B0F7F5 +:1095600040C7B1F745C7AEF746C7AFF718EC1AF0DA +:109570003DC7E9FF3EC7EAFF0A0E0701070145257F +:10958000E16E000E070107014621E26EEECFE6FF15 +:10959000EDCFE5FF07010701435100D0120007019D +:1095A0000B6F000E07010701086F07010B51ABD0CD +:1095B000DBC634F7FEC532F7FFC533F709EC1DF003 +:1095C000D8A001D001D02AD0960E056401D001D0D8 +:1095D00006D0FEC5D9F6FFC5DAF6DBC6DCF60550C7 +:1095E000D8B401D001D00CD005C00DF707010B6F26 +:1095F000000E070107010C6F07010B51EAECC6F0E2 +:10960000062A07010B6F000E056E07010B510701BB +:109610000B6F000E016E07010B5122D0056601D0C1 +:1096200001D006D0FEC5D7F6FFC5D8F6DBC604F0DC +:109630000650D8B401D001D00CD006C00DF70701F8 +:109640000B6F010E070107010C6F07010B51EAECCC +:10965000C6F0052A07010B6F000E066E07010B51BD +:109660000601D890DB3306010601DB6701D001D08B +:109670001CD007010B6F800E06010601DB6F07018E +:109680000B5105010501FE4BFF2B05010501FF51A3 +:10969000020AFE11D8A401D001D007D0000E0501A6 +:1096A0000501FE6F000E0501FF6F05010501FF5169 +:1096B00006010601DA1906E105010501FE51060160 +:1096C0000601D919D8A401D001D00ED00601060197 +:1096D000DB5106010601DC6301D001D005D0060193 +:1096E0000601D9690601DA690550960AD8A401D0A5 +:1096F00001D009D007010B6F010E07010701086FA8 +:1097000007010B510DD0185005010501FF1904E1A7 +:10971000175005010501FE19D8A401D001D048D782 +:1097200007010701086701D001D001D078D00150AE +:10973000D8B401D001D001D072D0D7C60EF7D8C6A8 +:109740000FF7D9C60CF7DAC60DF753EC12F00CC7B9 +:1097500009F70DC70AF7070107010ABF01D001D0B9 +:109760000DD0070107010A51800A800F320ED8B4CC +:10977000095DD8B001D001D001D051D00701070157 +:109780000A51800A800F9E0ED8B4095DD8A001D07E +:1097900001D00CD0070107010A51800A800FA30EE7 +:1097A000D8B4095DD8A001D001D000D004C00EF714 +:1097B000D7C60CF7D8C60DF74AECCDF004C00EF7AB +:1097C000D7C60CF7D8C60DF7D5ECD0F004C00EF70D +:1097D000D7C60CF7D8C60DF71CECDAF004C00EF7AC +:1097E000D7C60CF7D8C60DF729ECD4F004C00EF795 +:1097F000D7C60CF7D8C60DF703ECC4F004C00EF7BB +:10980000D7C60CF7D8C60DF792ECBAF0F4EC20F0FE +:1098100007010B6F010E016E07010B5100D0120002 +:10982000000E07010701396F000E07013A6F32C7BA +:1098300060F784EC0EF032C741F747EC0AF041C7FD +:1098400037F742C738F70701070138513711D8A455 +:1098500001D001D00CD032C741F7DEEC1CF0000E75 +:1098600007010701326F000E0701336F12D137C7AE +:109870003BF738C73CF707010701375107010701DC +:10988000355D070107013851070107013659D8B086 +:1098900001D001D004D035C73BF736C73CF70301F0 +:1098A0000301F7B101D001D02ED0030103EEE1F0A6 +:1098B000EECF3DF7EDCF3EF703010301DF51070186 +:1098C0003D5F03010301E05107013E5BD8900701B2 +:1098D0003E310701406F07013D3107013F6F07012E +:1098E0000701375107013F5D0701070138510701A3 +:1098F0004059D8A001D001D006D032C741F7DEECE4 +:109900001CF00301F781030103EEE5F0EECF3DF714 +:10991000EDCF3EF7070107013B5107013D27070146 +:1099200007013C5107013E2303010301E1510701F7 +:109930003D5D03010301E25107013E59D8A001D06A +:1099400001D045D003010301E55103010301E15DAD +:1099500007010701396F03010301E6510301030108 +:10996000E25907013A6F39C7ACF73AC7ADF70701BB +:109970003D6F010E07010701AB6F07013D5133C772 +:10998000A9F734C7AAF7FAC3A8F7E5C3A6F7E6C351 +:10999000A7F74AEC0CF0070107013951070107014D +:1099A0003327070107013A51070107013423070153 +:1099B00007013951070107013B5F070107013A51D0 +:1099C000070107013C5BDFC3E5F3E0C3E6F33BC7F8 +:1099D000ACF73CC7ADF707013D6F010E070107016A +:1099E000AB6F07013D5133C7A9F734C7AAF7FAC3D4 +:1099F000A8F7E5C3A6F7E6C3A7F74AEC0CF0070102 +:109A000007013B5103010301E527070107013C5111 +:109A100003010301E623070107013751070107018D +:109A2000355D070107013851070107013659D8A0F4 +:109A300001D001D005D032C741F7DEEC1CF017D0C1 +:109A400003010301F6BB01D001D011D00301F68B55 +:109A500055EC20F0060E07010701702503010301F4 +:109A6000F16F000E0701070171210301F26F070179 +:109A700007013951070107013B2507010701326F33 +:109A8000070107013A51070107013C210701336F24 +:109A900000D01200000E070107010F6F000E070132 +:109AA000106F000E0701116F000E0701126F010EFB +:109AB00007010701136F000E0701146F000E070165 +:109AC000156F000E0701166F07010E0E0701070143 +:109AD000346F0701070E0701356F07010C0E0701F0 +:109AE0000701326F0701070E0701336F53EC1CF0BB +:109AF00007010E0E070107012D6F0701070E070171 +:109B00002E6F07010C0E070107012B6F0701070ECF +:109B100007012C6FE1EC10F0000E07010701176F31 +:109B2000000E0701186F070107011851800A800F06 +:109B3000200ED8B4175DD8A001D001D001D0A1D09B +:109B400007010E0E070107012D6F0701070E070120 +:109B50002E6F07010C0E070107012B6F0701070E7F +:109B600007012C6FE1EC10F007010701196F0701E5 +:109B70000E0E070107012D6F0701070E07012E6F5B +:109B800007010C0E070107012B6F0701070E0701E4 +:109B90002C6FE1EC10F0070107011A6F07010E0EA0 +:109BA000070107012D6F0701070E07012E6F07013F +:109BB0000C0E070107012B6F0701070E07012C6F21 +:109BC000E1EC10F0070107011B6F07010E0E070102 +:109BD00007012D6F0701070E07012E6F07010C0EFD +:109BE000070107012B6F0701070E07012C6FE1EC3E +:109BF00010F0070107011C6F1BD029D007010701D6 +:109C00001351070107010F13070107011451070141 +:109C1000070110130701070115510701070111136F +:109C200007010701165107010701121310D067D071 +:109C30001CC721F71BC720F71AC71FF719C71EF744 +:109C4000ACEC18F0000AD9E0010AD8E0F0D707011F +:109C5000D89007011337070114370701153707019B +:109C6000163707010701174B182B07010701185179 +:109C7000800A800F200ED8B4175DD8A001D001D083 +:109C80005FD775EC21F0900E070107012D6FFF0ED5 +:109C900007012E6F6D0E070107012B6FFF0E0701E5 +:109CA0002C6F51EC22F03F0E070107012D6FFF0EC4 +:109CB00007012E6FB50E070107012B6FFF0E07017D +:109CC0002C6F51EC22F00FC72DF710C72EF711C7DC +:109CD0002FF712C730F7D50E070107012B6FFF0EC4 +:109CE00007012C6FC8EC21F007011D6F020E070160 +:109CF00007012B6F07011D51E1EC20F000D012008D +:109D00000C6601D001D03FD00DC748F7D0EC1DF054 +:109D1000030E07010701176F000E0701186FE30E0E +:109D200007010701156FFF0E0701166F0401000EF2 +:109D300007010701136F0401040E0701146FFAEC09 +:109D400011F0070114511311D8A401D001D007D08C +:109D500007010F6F010E0C6E07010F5113D00401A4 +:109D600004010251D8B401D001D00CD001C400F4D8 +:109D700002C401F407010F6F000E04010401026F19 +:109D800007010F51E9D00C04D8A401D001D092D022 +:109D90000DC748F7D0EC1DF00401000E07010701C4 +:109DA0003C6F0401040E07013D6F1FEC17F0070123 +:109DB0003C512B0A3D11D8A401D001D07AD0070123 +:109DC0000F6F030E070107010E6F07010F512A0ED7 +:109DD000070107010E6501D001D001D05CD0020E51 +:109DE00007010701156F000E0701166FFD0E070131 +:109DF00007010E2507010701136F0701146BFF0E02 +:109E0000070114236BEC07F0380E07010701132537 +:109E1000E96EEA6A000EEA2207010EC70FF7070192 +:109E2000106B010E07010F27000E10230401000E16 +:109E300007010F25E16E0401040E07011021E26EF7 +:109E4000E750070107013F6FFDEC12F00701116FAA +:109E50000401000E070107010E25E16EE26A04010C +:109E6000040EE222E750070107013F6FFDEC12F0FC +:109E70000701126F07011239F00B07011111EF6E84 +:109E8000020E070107010E272A0E070107010E65C2 +:109E900001D001D0A4D7F6EC1DF007010F6F020E20 +:109EA0000C6E07010F5107010F6F000E2E6E070198 +:109EB0000F5152D00C50020AD8A401D001D01AD0B0 +:109EC000070107010D513A0AD8A401D001D009D0E9 +:109ED000F6EC1DF007010F6F030E0C6E07010F511A +:109EE00008D02E3AF00E2E160DC73FF7FDEC12F0FB +:109EF0002E1232D00C50030AD8A401D001D01AD0AF +:109F00000DC748F7D0EC1DF02E062E6601D001D00B +:109F100010D067EC19F00009D8B401D001D007D0F7 +:109F200007010F6F040E0C6E07010F5102D0F6EC03 +:109F30001DF012D00C50040AD8A401D001D00CD0CE +:109F4000F6EC1DF00DC748F7D0EC1DF007010F6FC0 +:109F5000010E0C6E07010F511200000E07010701E0 +:109F6000396F000E07013A6F32C760F784EC0EF0CC +:109F700032C741F747EC0AF041C737F742C738F715 +:109F80000701070138513711D8A401D001D00CD0F6 +:109F900032C741F7DEEC1CF0000E07010701326FFB +:109FA000000E0701336F00D103010301F7B101D0A7 +:109FB00001D02ED0030103EEE1F0EECF3DF7EDCF5F +:109FC0003EF703010301DF5107013D5F0301030178 +:109FD000E05107013E5BD89007013E310701406F19 +:109FE00007013D3107013F6F0701070137510701A5 +:109FF0003F5D07010701385107014059D8A001D042 +:10A0000001D006D032C741F7DEEC1CF00301F78126 +:10A0100037C73BF738C73CF707010701375107013E +:10A020000701355D0701070138510701070136595E +:10A03000D8B001D001D004D035C73BF736C73CF7C4 +:10A04000030103EEE5F0EECF3DF7EDCF3EF707015C +:10A0500007013B5107013D27070107013C5107015B +:10A060003E2303010301E15107013D5D03010301AB +:10A07000E25107013E59D8A001D001D03BD00301E5 +:10A080000301E55103010301E15D07010701396F98 +:10A0900003010301E65103010301E25907013A6F8D +:10A0A00039C746F73AC747F733C744F734C745F7C8 +:10A0B000FAC343F7E5C341F7E6C342F7CEEC0AF033 +:10A0C000070107013951070107013327000E070176 +:10A0D00007013423070107013951070107013B5FDD +:10A0E000070107013A51070107013C5BDFC3E5F3B4 +:10A0F000E0C3E6F33BC746F73CC747F733C744F72F +:10A1000034C745F7FAC343F7E5C341F7E6C342F75F +:10A11000CEEC0AF0070107013B5103010301E527DB +:10A12000070107013C5103010301E6230701070171 +:10A13000375107010701355D070107013851070154 +:10A1400007013659D8A001D001D005D032C741F758 +:10A15000DEEC1CF017D003010301F6BB01D001D0E7 +:10A1600011D00301F68B55EC20F0060E0701070114 +:10A17000702503010301F16F000E07010701712132 +:10A180000301F26F070107013951070107013B2560 +:10A1900007010701326F070107013A510701070163 +:10A1A0003C210701336F00D01200000E07010701A8 +:10A1B000136F000E0701146F000E0701156F000EDC +:10A1C0000701166F010E070107010F6F000E07014F +:10A1D000106F000E0701116F000E0701126F0701CB +:10A1E0000E0E07010701346F0701070E0701356FD7 +:10A1F00007010C0E07010701326F0701070E070167 +:10A20000336F53EC1CF007010E0E070107012D6F91 +:10A210000701070E07012E6F07010C0E070107014A +:10A220002B6F0701070E07012C6FE1EC10F0000EF9 +:10A2300007010701176F000E0701186F07010701DB +:10A240001851800A800F0C0ED8B4175DD8A001D029 +:10A2500001D001D08ED007010E0E070107012D6F2E +:10A260000701070E07012E6F07010C0E07010701FA +:10A270002B6F0701070E07012C6FE1EC10F00701AF +:10A280000701196F07010E0E070107012D6F070166 +:10A29000070E07012E6F07010C0E070107012B6F38 +:10A2A0000701070E07012C6FE1EC10F00701070111 +:10A2B0001A6F07010E0E070107012D6F0701070E28 +:10A2C00007012E6F07010C0E070107012B6F070115 +:10A2D000070E07012C6FE1EC10F0070107011B6F5F +:10A2E00007010E0E070107012D6F0701070E070179 +:10A2F0002E6F07010C0E070107012B6F0701070ED8 +:10A3000007012C6FE1EC10F0070107011C6F07013A +:10A31000D8900701133707011437070115370701D4 +:10A32000163706D016D007010701138112D05FD06F +:10A330001CC721F71BC720F71AC71FF719C71EF73D +:10A340006DEC18F0000AEEE0010AEDE0030AEFE020 +:10A3500000D007010701174B182B070107011851FF +:10A36000800A800F0C0ED8B4175DD8A001D001D0A0 +:10A3700072D775EC21F0900E070107012D6FFF0ECB +:10A3800007012E6F6D0E070107012B6FFF0E0701EE +:10A390002C6F51EC22F04C0E070107012D6FFF0EC0 +:10A3A00007012E6FB50E070107012B6FFF0E070186 +:10A3B0002C6F51EC22F013C72DF714C72EF715C7D9 +:10A3C0002FF716C730F7D50E070107012B6FFF0EC9 +:10A3D00007012C6FC8EC21F007011D6F020E070169 +:10A3E00007012B6F07011D51E1EC20F000D0120096 +:10A3F0000701BA6F000E07010701B56F0701BA51D7 +:10A400000701BA6F000E07010701B46F0701BA51C7 +:10A4100007010701AE29D8B4AF29D8A401D001D0D3 +:10A420000CD00701BA6F010E07010701B56F0701D4 +:10A43000BA51E2CEAEF7E3CEAFF707010701B0297C +:10A44000D8B4B129D8A401D001D00CD00701BA6F7B +:10A45000010E07010701B46F0701BA51E0CEB0F752 +:10A46000E1CEB1F7020E07010701B25D000E070150 +:10A47000B359D8B001D001D03AD0E0CEB6F7E1CE92 +:10A48000B7F7E2CEB8F7E3CEB9F7B0C7E0FEB1C791 +:10A49000E1FEAEC7E2FEAFC7E3FE07D0C3EC22F099 +:10A4A00007010701C26FBEEC22F007010701B207E6 +:10A4B000D8A0B3070701B229D8B4B329D8A401D0D2 +:10A4C00001D0ECD707010701B46701D001D004D057 +:10A4D000B6C7E0FEB7C7E1FE07010701B56701D0C7 +:10A4E00001D004D0B8C7E2FEB9C7E3FE99D0070196 +:10A4F0000701B551D8B401D001D015D0070107012B +:10A50000B25107010701AE2507010701B86F070126 +:10A510000701B35107010701AF210701B96FB8C7A0 +:10A52000E2FEB9C7E3FEFF0E07010701B0250701F0 +:10A53000BA6FFF0E07010701B1210701BB6F0701C9 +:10A54000BA5107010701B2270701BB5107010701F3 +:10A55000B32300D00E010E01DFBB01D001D0FAD72A +:10A56000B0C7F0FEB1C7F1FEAEC7F4FEAFC7F5FE4F +:10A57000CE0E07010701B05D0A0E0701B159D8B030 +:10A5800001D001D012D0CE0E07010701B25D0A0E34 +:10A590000701B359D8A001D001D007D00701CE0ED2 +:10A5A0000701B25F0A0E0701B35BB2C7F2FEB3C781 +:10A5B000F3FE0E01DF990E01DF8B00D00E010E01BC +:10A5C000DFBB01D001D0FAD707010701B451D8B4DD +:10A5D00001D001D025D007010701B24BB32BCE0E1D +:10A5E00007010701B05D0A0E0701B159D8B001D0CB +:10A5F00001D012D0CE0E07010701B25D0A0E07018D +:10A60000B359D8A001D001D007D00701CE0E070161 +:10A61000B25F0A0E0701B35BB2C7E0FEB3C7E1FE4B +:10A620001200000E070107010D6F000E07010E6FEB +:10A63000E1C641F747EC0AF07D0E07010701415DD5 +:10A64000000E07014259D8B001D001D001D000D18D +:10A65000120E070107015A6F000E07015B6F000E13 +:10A6600007010701586F000E0701596F4C0E0701D3 +:10A670000701566F000E0701576F08EC1FF0070126 +:10A6800007010E51800A800F060ED8B40D5DD8A0C8 +:10A6900001D001D001D04FD00701D89007010D356E +:10A6A00007010F6F4C0E07010F25E96EEA6A000ED5 +:10A6B000EA2200015E0E070107010D25E16EE26A44 +:10A6C0000001000EE222E750070107013C6F59EC40 +:10A6D0001DF0EF6E0701D89007010D3507010F6FD0 +:10A6E000010E07010F274C0E07010F25E96EEA6ADC +:10A6F000000EEA2200015E0E070107010D25E16E42 +:10A70000E26A0001000EE222E75007010701486FEC +:10A7100031EC1DF0EF6E070107010D4B0E2B070109 +:10A7200007010E51800A800F060ED8B40D5DD8A027 +:10A7300001D001D0B1D7F6EC1DF0760E070107016C +:10A74000376FFF0E0701386F3DEC14F067EC22F015 +:10A75000B70E07010701316FFE0E0701326FEB0ED6 +:10A76000070107012F6FFF0E0701306FF3EC21F097 +:10A770004C0E07010701316F000E0701326FE70E23 +:10A78000070107012F6FFF0E0701306FF3EC21F077 +:10A79000640E07010F6F000E106F0FC731F710C75F +:10A7A00032F7A70E070107012F6FFF0E0701306F69 +:10A7B000F3EC21F0D00E07010701316FFF0E070106 +:10A7C000326FCB0E070107012F6FFF0E0701306FAD +:10A7D000F3EC21F046EC22F067EC22F0020E0701C8 +:10A7E0000701336F000E0701346F000E0701356F4C +:10A7F000000E0701366F6D0E07010701316FFF0E66 +:10A800000701326F87EC21F0FA0E07010701316F63 +:10A81000FF0E0701326F980E070107012F6FFF0E21 +:10A820000701306FF3EC21F0240E07010701316FAF +:10A83000FF0E0701326FF30E070107012F6FFF0EA6 +:10A840000701306FF3EC21F046EC22F092ECDDF0E2 +:10A850001200000E070107010F6F000E0701106FB5 +:10A86000000E0701116F000E0701126F010E0701A4 +:10A870000701136F000E0701146F000E0701156F1B +:10A88000000E0701166F07010E0E07010701346F56 +:10A890000701070E0701356F07010C0E07010701BD +:10A8A000326F0701070E0701336F53EC1CF0000EE7 +:10A8B00007010701176F000E0701186F0701070155 +:10A8C0001851800A800F180ED8B4175DD8A001D097 +:10A8D00001D001D0A1D007010E0E070107012D6F95 +:10A8E0000701070E07012E6F07010C0E0701070174 +:10A8F0002B6F0701070E07012C6FE1EC10F0070129 +:10A900000701196F07010E0E070107012D6F0701DF +:10A91000070E07012E6F07010C0E070107012B6FB1 +:10A920000701070E07012C6FE1EC10F0070107018A +:10A930001A6F07010E0E070107012D6F0701070EA1 +:10A9400007012E6F07010C0E070107012B6F07018E +:10A95000070E07012C6FE1EC10F0070107011B6FD8 +:10A9600007010E0E070107012D6F0701070E0701F2 +:10A970002E6F07010C0E070107012B6F0701070E51 +:10A9800007012C6FE1EC10F0070107011C6F1BD0D1 +:10A9900029D0070107011351070107010F13070110 +:10A9A0000701145107010701101307010701155191 +:10A9B00007010701111307010701165107010701DC +:10A9C000121310D057D01CC721F71BC720F71AC786 +:10A9D0001FF719C71EF7EBEC18F0000AD9E0010ABF +:10A9E000D8E0F0D70701D8900701133707011437D3 +:10A9F000070115370701163707010701174B182BF9 +:10AA0000070107011851800A800F180ED8B4175D8E +:10AA1000D8A001D001D05FD775EC21F0320E07012C +:10AA200007012D6FFF0E07012E6F6D0E0701070145 +:10AA30002B6FFF0E07012C6F51EC22F00FC72DF783 +:10AA400010C72EF711C72FF712C730F7D50E070121 +:10AA500007012B6FFF0E07012C6FC8EC21F00701D7 +:10AA60001D6F020E070107012B6F07011D51E1EC5D +:10AA700020F000D01200F5D05F0E07010701506FE3 +:10AA8000760E0701516F000E070107014E6F000E91 +:10AA900007014F6F5F0E070107014C6F760E07012C +:10AAA0004D6F9EECE1F0306E3028D8A401D001D07B +:10AAB00001D0E5D00B2AE3D030C04CF7F2EC1BF00C +:10AAC00007014D514C11D8A401D001D001D0D7D0ED +:10AAD0000701080E070107014D6F0701070E070167 +:10AAE0004E6F86EC1EF051EC21F007010701085172 +:10AAF000440AD8B401D001D001D0C1D00B2A0A0E2B +:10AB000007010701B26F000E0701B36F0001BD0E10 +:10AB100007010701B06F0001000E0701B16F30504F +:10AB20000E0D0101590EF32407010701AE6F070155 +:10AB3000AF6B0101010E0701AF2318EC1AF030C012 +:10AB40004CF750EC1AF007014D514C11D8A401D02C +:10AB500001D001D094D0160E070107010A6FFF0E35 +:10AB600007010B6F63EC21F00701096F000E07016D +:10AB70000701086F07010951050E07010701086564 +:10AB800001D001D001D03CD008C709F72D0E070134 +:10AB9000092706013C0E07010925E96EEA6A06014C +:10ABA000060EEA22EF50070107013C6F59EC1DF039 +:10ABB00007010701536F63EC1FF008C709F72D0E5B +:10ABC0000701092706013C0E07010925E96EEA6A1B +:10ABD0000601060EEA22EF5007010701486F31EC2B +:10ABE0001DF007010701536F63EC1FF00701070118 +:10ABF000082B050E07010701086501D001D0C4D755 +:10AC00000701096F3A0E07010701536F0701095148 +:10AC100063EC1FF00001640E070107010A6F0001D9 +:10AC2000000E07010B6F2DEC21F00701096F3A0EA2 +:10AC300007010701536F0701095163EC1FF0FA0E7A +:10AC4000070107010A6FFF0E07010B6F63EC21F08C +:10AC5000BCEC09F00701096F010E0B6E07010951E9 +:10AC60000ED00B50000A01E107D7010A01E124D7F9 +:10AC7000030A01E164D7010A01E11DD700D01200E7 +:10AC8000A2C7E9FFA3C7EAFF0701EECFBEF707019E +:10AC9000EDCFBFF7B8EC21F0A2C7E9FFA3C7EAFFE9 +:10ACA0000701BEC7EEFF0701BFC7EDFF020E070198 +:10ACB0000701A225E96E000E07010701A321EA6E34 +:10ACC0000701EECFBEF70701EDCFBFF7B8EC21F0DB +:10ACD000020E07010701A225E96E000E0701070118 +:10ACE000A321EA6E0701BEC7EEFF0701BFC7EDFF54 +:10ACF000040E07010701A225E96E000E07010701F6 +:10AD0000A321EA6E0701EECFA4F70701EECFA5F766 +:10AD10000701EECFA6F70701EECFA7F7B0EC1CF0C6 +:10AD2000040E07010701A225E96E000E07010701C5 +:10AD3000A321EA6E0701A4C7EEFF0701A5C7EEFF36 +:10AD40000701A6C7EEFF0701A7C7EDFFED52ED52C1 +:10AD5000080E07010701A225E96E000E0701070191 +:10AD6000A321EA6E0701EECFA4F70701EECFA5F706 +:10AD70000701EECFA6F70701EECFA7F7B0EC1CF066 +:10AD8000080E07010701A225E96E000E0701070161 +:10AD9000A321EA6E0701A4C7EEFF0701A5C7EEFFD6 +:10ADA0000701A6C7EEFF0701A7C7EDFFED52ED5261 +:10ADB0000E0E07010701A225E96E000E070107012B +:10ADC000A321EA6E0701EECFBEF70701EDCFBFF773 +:10ADD000B8EC21F00E0E07010701A225E96E000E66 +:10ADE00007010701A321EA6E0701BEC7EEFF0701B5 +:10ADF000BFC7EDFF100E07010701A225E96E000E87 +:10AE000007010701A321EA6E0701EECFBEF7070194 +:10AE1000EDCFBFF7B8EC21F0100E07010701A22516 +:10AE2000E96E000E07010701A321EA6E0701BEC704 +:10AE3000EEFF0701BFC7EDFF120E07010701A225B4 +:10AE4000E96E000E07010701A321EA6E0701EECFAC +:10AE5000BEF70701EDCFBFF7B8EC21F0120E0701E6 +:10AE60000701A225E96E000E07010701A321EA6E82 +:10AE70000701BEC7EEFF0701BFC7EDFF12000701C4 +:10AE80002A6F0B0E07010701226F07012A510701E4 +:10AE90002A6F0A0E07010701236F07012A5116ECDA +:10AEA00020F00009D8A401D001D001D0DFD0FC0EE1 +:10AEB000070107012B6FFF0E07012C6FEBEC0EF063 +:10AEC0000009D8B401D001D008D0AAEC0DF00701D8 +:10AED0000701325107010701226FF60E0701070132 +:10AEE0002B6FFF0E07012C6FEBEC0EF00009D8B4AE +:10AEF00001D001D008D0AAEC0DF0070107013251B2 +:10AF000007010701236FF80E070107012B6FFF0EE2 +:10AF100007012C6FEBEC0EF00009D8A401D001D092 +:10AF200001D0A4D007012A6FC80E07010701346FB2 +:10AF300007012A510501000E07010701326F0501C3 +:10AF4000050E0701336F99EC05F00009D8A401D074 +:10AF500001D001D08BD0EF0E070107012B6FFF0E40 +:10AF600007012C6FEBEC0EF00009D8B401D001D032 +:10AF700030D0AAEC0DF032C724F733C725F734C719 +:10AF800026F735C727F7E1C641F747EC0AF07D0EF3 +:10AF900007010701415D000E07014259D8A001D009 +:10AFA00001D017D0F6EC1DF0EF0E07010701376F47 +:10AFB000FF0E0701386F3DEC14F024C737F725C7A3 +:10AFC00038F726C739F727C73AF7C4ECE6F092EC12 +:10AFD000DDF0D2EC22F007012A6F000E0701070115 +:10AFE000286F07012A5136D007012A6F020E070188 +:10AFF00007012B6F07012A51E7EC22F00501000E33 +:10B00000070107012B6F0501050E07012C6FB9EC35 +:10B010000FF007012A6F000E07010701296F0701D2 +:10B020002A510BD00E0E07012A6F830EE82EFED791 +:10B030002A2FFCD707010701292B070107012251FD +:10B0400007010701295DD8A001D001D0EBD7070186 +:10B050000701282B07010701235107010701285D7C +:10B06000D8A001D001D0C0D7CDEC22F01200000E44 +:10B0700003010301FB6F000E0301FC6F080E0701C3 +:10B080000701C66F000E0701C76F0701280E0701F1 +:10B090000701C46F0701070E0701C56FA4EC19F083 +:10B0A00028C7BEF729C7BFF7B8EC21F0BEC728F7FD +:10B0B000BFC729F72AC7BEF72BC7BFF7B8EC21F0E7 +:10B0C000BEC72AF7BFC72BF72CC7BEF72DC7BFF7E0 +:10B0D000B8EC21F0F80E07010701BE2507010701B2 +:10B0E0002C6FFF0E07010701BF2107012D6F07011C +:10B0F00007012F512E11D8B401D001D083D01DC724 +:10B10000E9FF1EC7EAFF0701EECF30F70701EECFD8 +:10B1100031F70701EECF32F70701EECF33F71FC744 +:10B12000E9FF20C7EAFF0701EECF34F70701EECFB2 +:10B1300035F70701EECF36F70701EECF37F70701F6 +:10B140003C6F000E07010701386F07013C510701F2 +:10B150003C6F110E07010701396F07013C5121C7F0 +:10B160003AF722C73BF73AC7BEF73BC7BFF7B8EC81 +:10B1700021F0BEC73AF7BFC73BF70C0E0701070126 +:10B18000BE6F000E0701BF6F0701300E07010701F8 +:10B19000BC6F0701070E0701BD6F38EC06F0070111 +:10B1A0000701BC1D07010701246F07010701BD1D31 +:10B1B0000701256F000E07010701776F000E0701D9 +:10B1C000786FA8EC21F021C7A2F722C7A3F7D3EC30 +:10B1D000E0F0A2C726F7A3C727F7070107EE26F07E +:10B1E0000701EE5207012551ED18070124C7E8FFBA +:10B1F000D8B4EF18D8B401D001D004D026EC1BF09D +:10B20000000E2BD01FC741F720C742F71DC73FF7DD +:10B210001EC740F70701280E070107013D6F070110 +:10B22000070E07013E6F8CECC9F007010701236F81 +:10B23000070107012329D8A401D001D004D026ECAE +:10B240001BF0000E0AD023C7E3F62CC7FBF32DC773 +:10B25000FCF31E801E92010E00D012001DC7E9FFF4 +:10B260001EC7EAFF0701EECF28F70701EECF29F747 +:10B270000701EECF2AF70701EECF2BF71FC7E9FF33 +:10B2800020C7EAFF0701EECF2CF70701EECF2DF71D +:10B290000701EECF2EF70701EECF2FF70701486F1A +:10B2A000000E07010701306F070148510701486F81 +:10B2B000060E07010701316F0701485121C732F718 +:10B2C00022C733F732C7BEF733C7BFF7B8EC21F058 +:10B2D000BEC732F7BFC733F70C0E07010701BE6FB9 +:10B2E000000E0701BF6F0701280E07010701BC6FA1 +:10B2F0000701070E0701BD6F38EC06F007010701D3 +:10B30000BC1D07010701246F07010701BD1D0701CF +:10B31000256F21C7A2F722C7A3F7D3ECE0F0A2C79D +:10B3200026F7A3C727F707010701275107010701E0 +:10B33000251906E107010701265107010701241914 +:10B34000D8B401D001D003D026EC1BF074D0000E8D +:10B3500007010701776F000E0701786FA8EC21F055 +:10B36000140E07010701C66F000E0701C76F070122 +:10B37000340E07010701C46F0701070E0701C56FEF +:10B38000A4EC19F00701340E07010701A26F0701B1 +:10B39000070E0701A36F40ECD6F0070140390F0BF1 +:10B3A0000701486F0701D89048370701D890483502 +:10B3B000EC0F07010701236F070107012351070164 +:10B3C0000701215D0701486F000E0701070122599F +:10B3D0000701496FEC0E0701482507010701216F9E +:10B3E000FF0E070149210701226F1DC74CF71EC739 +:10B3F0004DF70701340E070107014A6F0701070ED9 +:10B4000007014B6FC3ECAEF00009D8B401D001D0F6 +:10B410000FD021C74CF722C74DF70701340E0701A3 +:10B4200007014A6F0701070E07014B6F19EC80F007 +:10B4300026EC1BF000D0120007010E0E07010701D9 +:10B44000346F0701070E0701356F07010C0E070166 +:10B450000701326F0701070E0701336F53EC1CF031 +:10B46000040E07010701146F000E0701156F070195 +:10B47000070115AF01D001D001D07ED007011A6FAE +:10B48000000E07010701166F07011A51000E070190 +:10B490000701176F000E0701186F07010701185108 +:10B4A000800A800F080ED8B4175DD8A001D001D053 +:10B4B00001D04AD007010E0E070107011E6F0701D8 +:10B4C000070E07011F6F07010C0E070107011C6F14 +:10B4D0000701070E07011D6F2AEC19F0070107018C +:10B4E000196F070107011951020AD8A401D001D030 +:10B4F00001D088D0070107011951D8B401D001D07B +:10B5000013D017C71AF7010E07011B6F07011A2B7B +:10B5100003D0D89007011B3707011A2FFAD707016C +:10B520001B5107010701161307010701174B182BC1 +:10B53000070107011851800A800F080ED8B4175D63 +:10B54000D8A001D001D0B6D707010F0E070107011F +:10B550001425E96EEA6A0701070EEA22070116C7F9 +:10B56000EFFF070107011407D8A01507070107011E +:10B5700015AF01D001D082D775EC21F0A00E0701E4 +:10B5800007012D6FFF0E07012E6FBB0E070107018C +:10B590002B6FFF0E07012C6F51EC22F0620E07019A +:10B5A00007012D6FFF0E07012E6F6D0E07010701BA +:10B5B0002B6FFF0E07012C6F51EC22F007011A6F61 +:10B5C000050E07010701206F07011A5107010F0E31 +:10B5D000070107011E6F0701070E07011F6FD50E38 +:10B5E000070107011C6FFF0E07011D6F00EC22F021 +:10B5F00007011A6F010E070107012B6F07011A518E +:10B60000E1EC20F012000C0E07010701776F000E2D +:10B610000701786FA8EC21F0C3EC22F007010701C5 +:10B62000736F73C776F7F00E070176170701D8908E +:10B6300076330701D8907631EC0F07010701736F5D +:10B6400007010701736701D001D008D0180E070168 +:10B650000701706F020E0701716FB5D0070E070169 +:10B660000701C66F000E0701C76F000E0701070133 +:10B67000C46F000E0701C56FA4EC19F093D0C3ECA2 +:10B6800022F007010701726F07010701726701D0FD +:10B6900001D001D090D0070107017205D8A401D0D4 +:10B6A00001D001D07FD0070107017251020AD8A44E +:10B6B00001D001D04AD0030E07010701736101D008 +:10B6C00001D001D078D0000E07010701746F000E81 +:10B6D0000701756FC3EC22F007010701726F0701C4 +:10B6E00007017251040AD8A401D001D00AD0C3ECDA +:10B6F00022F007010701756FC3EC22F00701070173 +:10B70000746F180E07010701745D020E0701755969 +:10B71000D8B001D001D001D04ED0B50E070107013D +:10B72000745D050E07017559D8A001D001D008D06D +:10B73000B40E07010701706F050E0701716F43D04A +:10B7400074C770F775C771F73ED0020E0701070185 +:10B75000736101D001D001D02ED0C3EC22F00701DB +:10B760000701726F07010701725107010701736139 +:10B7700001D001D001D01FD00701070172C7C6F761 +:10B7800007010701C76B000E07010701C46F000E18 +:10B790000701C56FA4EC19F00701070172510701F9 +:10B7A0000701735F07010701730707017329D8A415 +:10B7B00001D001D064D7180E07010701706F020E87 +:10B7C0000701716F00D0120006010601DD29D8A41F +:10B7D00001D001D01AD0000E07010701506F000EF2 +:10B7E0000701516F000E070107014E6F000E0701A0 +:10B7F0004F6F450E070107014C6F000E07014D6F9B +:10B800009EECE1F006010601DD6F06010601DD296F +:10B81000D8A401D001D001D0AED0DDC64CF7F2ECF7 +:10B820001BF007014D514C11D8A401D001D001D01B +:10B83000A2D0060106013C51060106014015070190 +:10B84000166F060106013D5106010601411507016B +:10B85000176F060106013E51060106014215070158 +:10B86000186F060106013F51060106014315070145 +:10B87000196F00010001BD510601060140150701C5 +:10B880001A6F00010001BE510601060141150701B2 +:10B890001B6F00010001BF5106010601421507019F +:10B8A0001C6F00010001C05106010601431507018C +:10B8B0001D6F0701195107011D190EE107011851EC +:10B8C00007011C1909E10701175107011B1904E1C0 +:10B8D0000701165107011A19D8B401D001D003D0BD +:10B8E00051EC21F048D0060E07010701B26F000E9F +:10B8F0000701B36F690E0701166F060E176F16C7A3 +:10B90000B0F717C7B1F70701080E07010701AE6FBF +:10B910000701070E0701AF6F18EC1AF03CC60EF7CF +:10B920003DC60FF73EC610F73FC611F70A0E0701D6 +:10B930000701BE6F000E0701BF6F0701080E070168 +:10B940000701BC6F0701070E0701BD6F38EC06F059 +:10B95000BCC712F7BDC713F7D0920701080E070145 +:10B960000701146F0701070E0701156F15C7F4FFD4 +:10B9700014C7F3FFFF001200FC0E92160E01FE8B9F +:10B9800000D00E010E01FDA101D001D0FAD70701B0 +:10B99000096F010E346E07010951000E000100010C +:10B9A000FB6F000E0001FC6F000E0E010E01E86F30 +:10B9B000000E0E01E96FCD0E0E010E01EC6F0A0EA6 +:10B9C0000E010E01ED6FCD0E0E010E01EA6F0A0E93 +:10B9D0000E01EB6FCE0E0E010E01E46F0A0E0E018A +:10B9E000E56FCE0E0E010E01E26F0A0E0E01E36F3F +:10B9F0000701096F000E07010701C26F0701095116 +:10BA0000BEEC22F00701096F0D0E0E010E01A06FB2 +:10BA10000701095100F00701096F320E0E010E01F6 +:10BA2000A26F0701095100F00701096F120E0E0104 +:10BA30000E01A46F0701095100F00701096F400EC4 +:10BA40000E010E01A36F0701095100F00701096FF4 +:10BA5000120E0E010E01A66F0701095100F0070139 +:10BA6000096F0C0E0E010E01A76F0701095100F0BE +:10BA70000701096FEE0E0E010E01AA6F07010951B1 +:10BA800000F00701096F050E0E010E01AB6F0701F3 +:10BA9000095100F069C684FE00F06AC685FE00F018 +:10BAA0006BC682FE00F06CC683FE00F06DC680FEA1 +:10BAB00000F06EC681FE00F0100E070107010B6F4B +:10BAC000010E07010C6F0701096F100E0701070136 +:10BAD0000A6F0701095127EC1FF0720E07010701D9 +:10BAE0000B6F340E07010C6F0701096F140E07016D +:10BAF00007010A6F0701095127EC1FF0000E07012B +:10BB000007010B6F000E07010C6F0701096F000E94 +:10BB1000070107010A6F0701095127EC1FF00E0109 +:10BB2000DF851200E1C641F747EC0AF041C72DF767 +:10BB300042C72EF70401000E070107013C6F040104 +:10BB4000040E07013D6F1FEC17F01A0E07010701E5 +:10BB50003C27000E07013D23070107013C51070167 +:10BB60002D5D070107013D5107012E59D8B001D0C5 +:10BB700001D003D0F6EC1DF0AAD043EC11F0E30E97 +:10BB800007010701306FFF0E0701316FE1C62FF784 +:10BB9000A5EC20F007012D6F000E070107012C6FA7 +:10BBA00007012D51130E070107012C6501D001D0AB +:10BBB00001D038D000019F0E070107012C25E96E46 +:10BBC000EA6A0001000EEA22EF50070107013C6F0C +:10BBD00059EC1DF007010701306FE1C62FF711EC9A +:10BBE000E6F000019F0E070107012C25E96EEA6AC5 +:10BBF0000001000EEA22EF5007010701486F31EC07 +:10BC00001DF007010701306FE1C62FF711ECE6F0D8 +:10BC1000070107012C2B130E070107012C6501D02A +:10BC200001D0C8D70401000E070107013C6F0401D1 +:10BC3000040E07013D6F1FEC17F0070107013C518F +:10BC4000070107013C6F59EC1DF007010701306F38 +:10BC5000E1C62FF711ECE6F00401000E0701070121 +:10BC60003C6F0401040E07013D6F1FEC17F0070144 +:10BC700007013C5107010701486F31EC1DF0070136 +:10BC80000701306FE1C62FF711ECE6F007012D6FC9 +:10BC90003A0E07010701306F07012D51E1C62FF75A +:10BCA00011ECE6F00401000E07010701306F0401FA +:10BCB000040E0701316FE1C62FF7CDEC20F0E1C68D +:10BCC00041F7DEEC1CF0F6EC1DF05CEC22F012000B +:10BCD000140E070107012F25E96E000E0701070169 +:10BCE0003021EA6EEF500701376F3F0E070137171B +:10BCF000180E0701372707013751070107012F25C4 +:10BD00000701386FE86A070137BFE86807010701D4 +:10BD100030210701396F38C735F739C736F7140EA8 +:10BD2000070107012F25E96E000E070107013021E9 +:10BD3000EA6E070107013351EE2607013451EE2266 +:10BD4000000EEE22ED22ED52ED528BD0070131C7ED +:10BD5000F6FF070132C7F7FF000EF86E35C7E9FF9F +:10BD600036C7EAFF0800F5CFEFFF07010701314BA7 +:10BD7000322B07010701354B362B580E07010701FF +:10BD80002F250701376F000E07010701302107013A +:10BD9000386F0701385107010701361905E107011E +:10BDA0003751070107013519D8A401D001D054D06B +:10BDB000100E070107012F25070107015A6F000E1A +:10BDC00007010701302107015B6F0C0E0701070116 +:10BDD0002F2507010701586F000E070107013021C9 +:10BDE0000701596F080E070107012F2507010701F9 +:10BDF000566F000E0701070130210701576F040E2F +:10BE0000070107012F2507010701546F000E0701E5 +:10BE1000070130210701556F2FC752F730C753F77D +:10BE2000180E070107012F2507010701506F000EAB +:10BE30000701070130210701516FD0ECA1F0180E66 +:10BE4000070107012F2507010701356F000E0701C4 +:10BE5000070130210701366F070107013307D8A01A +:10BE600034070701070134513311D8A401D001D0A0 +:10BE70006DD71200140E070107012F25E96E000E81 +:10BE8000070107013021EA6EEF500701376F3F0EBF +:10BE900007013717180E0701372707013751070128 +:10BEA00007012F250701386FE86A070137BFE868E7 +:10BEB0000701070130210701396F38C735F739C746 +:10BEC00036F7140E070107012F25E96E000E070152 +:10BED00007013021EA6E070107013351EE26070101 +:10BEE0003451EE22000EEE22ED22ED52ED5286D0BC +:10BEF00031C7E9FF32C7EAFF35C7E1FF36C7E2FFC6 +:10BF0000EFCFE7FF07010701314B322B0701070194 +:10BF1000354B362B580E070107012F250701376FC8 +:10BF2000000E0701070130210701386F0701385162 +:10BF300007010701361905E107013751070107011C +:10BF40003519D8A401D001D054D0100E0701070133 +:10BF50002F25070107015A6F000E07010701302145 +:10BF600007015B6F0C0E070107012F250701070171 +:10BF7000586F000E0701070130210701596F080EA5 +:10BF8000070107012F2507010701566F000E070162 +:10BF9000070130210701576F040E070107012F2504 +:10BFA00007010701546F000E070107013021070147 +:10BFB000556F2FC752F730C753F7180E0701070107 +:10BFC0002F2507010701506F000E070107013021DF +:10BFD0000701516FD0ECA1F0180E070107012F25C2 +:10BFE00007010701356F000E070107013021070126 +:10BFF000366F070107013307D8A03407070107018F +:10C0000034513311D8A401D001D072D71200C2D05C +:10C010001C0E07010701C66F000E0701C76F07015D +:10C020001D0E07010701C46F0701070E0701C56F49 +:10C03000A4EC19F026EC1BF007011D0E0701070107 +:10C040007C6F0701070E07017D6F9FEC11F0070160 +:10C0500007011D051E11D8A401D001D010D0070181 +:10C0600007012151060AD8A401D001D008D0070148 +:10C0700007012251040AD8B401D001D001D092D0D6 +:10C08000070107012351020A2411D8A401D001D0CD +:10C0900012D007EE25F010EEE9F0060EEECFE6FF27 +:10C0A000E82EFCD72BC7E5F02CC7E6F02DC7E7F04C +:10C0B0002EC7E8F077D00701070123052411D8A483 +:10C0C00001D001D037D0060106013F510701070119 +:10C0D000381914E1060106013E510701070137191D +:10C0E0000DE1060106013D5107010701361906E180 +:10C0F000060106013C51070107013519D8B401D0EA +:10C1000001D001D04FD02BC7DBF02CC7DCF02DC7FE +:10C11000DDF02EC7DEF007EE25F010EEDFF0060EA4 +:10C12000EECFE6FFE82EFCD70701396F010E096E4E +:10C1300007013951020E07010701236F000E0701A5 +:10C14000246F00EEDFF017EE2FF0060EEECFE6FFC5 +:10C15000E82EFCD7DBC035F7DCC036F7DDC037F79B +:10C16000DEC038F707011D0E07010701786F0701D0 +:10C17000070E0701796F55EC02F00009D8A401D031 +:10C1800001D001D00FD00701396F000E096E0701F1 +:10C19000395107D00950000A01E13AD7010ACAE033 +:10C1A00000D000D01200FAC5AAF7FBC5ABF7FCC55A +:10C1B000ACF7FDC5ADF7E0CEA4F7E1CEA5F783D08F +:10C1C000A2C7A8F7A3C7A9F7150E07010701A25D2B +:10C1D000000E0701A359D8A001D001D007D0140E3A +:10C1E00007010701A86F000E0701A96FA8C7C6F7CE +:10C1F000A9C7C7F70701AE0E07010701C46F070102 +:10C20000070E0701C56FA4EC19F007010701A8513B +:10C2100007010701A25F07010701A95107010701F3 +:10C22000A35B07010701A8A101D001D010D007012D +:10C23000AE0E07010701A825E96EEA6A0701070E9D +:10C24000EA22000EEF6E07010701A84BA92B070198 +:10C25000AE0E07010701A66F0701070E0701A76FC2 +:10C260002AD00701A6C7E9FF0701A7C7EAFF070110 +:10C27000020E0701A627000E0701A723EECFC2F783 +:10C28000EDCFC3F70701C25107010701AA27070134 +:10C29000C35107010701AB23000E07010701AC23BF +:10C2A000000E07010701AD23020E07010701A85F79 +:10C2B000000E0701A95B07010701A951A811D8A425 +:10C2C00001D001D0CED707010701A351A211D8A4F4 +:10C2D00001D001D075D7A4C7E0FEA5C7E1FE0701D4 +:10C2E0000701AA5107010701AC2507010701AA6F41 +:10C2F00007010701AB5107010701AD210701AB6F32 +:10C300000701AC6BD8B0AC2B0701AD6B070107EE92 +:10C31000ACF0EE5007010701AA27ED500701070115 +:10C32000AB2307010701AA1D07010701A26F07013F +:10C330000701AB1D0701A36F00D012000101590EC8 +:10C3400007010701536F0101010E0701546F070137 +:10C35000556F000E07010701526F07015551040E7A +:10C3600007010701526501D001D001D0AED00C0EFB +:10C37000070107015325E96E000E0701070154214B +:10C38000EA6EEE50ED10D8A401D001D08DD00C0E85 +:10C39000070107015325E96E000E0701070154212B +:10C3A000EA6E07014CC7EEFF07014DC7EDFF07011D +:10C3B00007014D514C11D8A401D001D031D0010E4C +:10C3C00000010001F95D200E0001FA59D8B001D03A +:10C3D00001D00BD0000E00010001F95D100E00012C +:10C3E000FA59D8B001D001D007D0000E00010001E9 +:10C3F000F96F100E0001FA6F0C0E070107015325AB +:10C40000E96E000E070107015421EA6E0001F9C030 +:10C41000EEFF0001FAC0EDFF00010001F94BFA2B1D +:10C42000070107014F514E11D8B401D001D012D0ED +:10C430000A0E07010701B26F000E0701B36F4EC766 +:10C44000B0F74FC7B1F753C7AEF754C7AFF718EC03 +:10C450001AF014D00A0E070107015A6F000E0701E7 +:10C460005B6FFF0E07010701586F000E0701596F40 +:10C4700053C756F754C757F708EC1FF00A0E0701C9 +:10C4800007015325E96E000E070107015421EA6EEA +:10C49000070150C7EEFF070151C7EDFF52C723F058 +:10C4A00007010701525113D00E0E07010701532750 +:10C4B000000E0701542307010701522B040E070148 +:10C4C0000701526501D001D052D7FF0E00D01200F3 +:10C4D00000D0C5CF12F71F0E0701121712C713F7AE +:10C4E0000701146B000EC7B4010E07011313000EF1 +:10C4F0001413070114511311D8A401D001D0E9D7A6 +:10C50000C58000D0C5B001D001D0FCD7A1A601D014 +:10C5100001D006D00701070110690701116998D001 +:10C5200010C715F782EC1CF00009D8B401D001D077 +:10C5300009D0C584FD0E07010701106FFF0E07012A +:10C54000116F86D0C5BC01D001D072D011C715F7CC +:10C5500082EC1CF00009D8B401D001D009D0C58408 +:10C56000FD0E07010701106FFF0E0701116F70D05C +:10C57000C5BC01D001D052D0C58200D0C5B201D017 +:10C5800001D0FCD7A1A601D001D006D00701070138 +:10C590001069070111695CD0070107011029070123 +:10C5A0000701156F82EC1CF00009D8B401D001D04E +:10C5B00009D0C584FD0E07010701106FFF0E0701AA +:10C5C000116F46D0C5BC01D001D01ED0C58600D0A9 +:10C5D000C5B601D001D0FCD7C58AC58800D0C5B882 +:10C5E00001D001D0FCD7C58400D0C5B401D001D0A2 +:10C5F000FCD7A1A601D001D006D007010701106920 +:10C600000701116925D009D0C584FE0E0701070175 +:10C61000106FFF0E0701116F1BD009D0C584FE0EED +:10C6200007010701106FFF0E0701116F11D009D02C +:10C63000C584FE0E07010701106FFF0E0701116F81 +:10C6400007D00701C9CF10F707010701116B00D010 +:10C6500012002DC760F784EC0EF0E9C3EBF3EAC3D8 +:10C66000ECF392D09DEC1FF017EC0EF0B0D017EC6D +:10C670000EF0ADD007012E6F010E07010701716F9B +:10C6800007012E5107012F6F110E07010701706F6F +:10C6900007012F51B4EC9BF004010401DB51DA11C6 +:10C6A000D8A401D001D001D012D0040104EED4F0FE +:10C6B000030113EEE5F0E652EE52ED50E518EFCF30 +:10C6C000E8FFD8B4E718D8A401D001D0D3D7070128 +:10C6D0002E6F080E03010301F56F07012E5177D06D +:10C6E00007012E6F010E07010701716F07012E511F +:10C6F00007012F6F110E07010701706F07012F51FE +:10C70000B4EC9BF004010401DB51DA11D8A401D090 +:10C7100001D001D012D0040104EED4F0030113EED5 +:10C72000E5F0E652EE52ED50E518EFCFE8FFD8B451 +:10C73000E718D8A401D001D0D3D707012E6F0C0E73 +:10C7400003010301F56F07012E5141D007012E6F40 +:10C750000D0E03010301F56F07012E5138D00701BB +:10C760002E6F000E07010701716F07012E5107019F +:10C770002F6F140E07010701706F07012F51B4ECE2 +:10C780009BF017EC0EF023D003010301F551000AD2 +:10C7900001E16DD7010A01E165D7030A01E167D71D +:10C7A000010A01E164D7060A01E161D7030A01E148 +:10C7B00061D7010A01E15ED70F0AD1E0010ACFE09B +:10C7C000020A8EE0070ACBE0020AC0E0C8D71200D6 +:10C7D00006010601C851D8B401D001D025D0060108 +:10C7E0000601C75106010601C5277E0E0601060196 +:10C7F000C56501D001D004D006010601C76911D07A +:10C8000006010601C56701D001D00BD00701DB6F1F +:10C81000010E06010601C76F0701DB510601060183 +:10C82000C807C5C6BBFF57D006010601C951020A99 +:10C83000D8A401D001D003D0C6C6BBFF4CD006019E +:10C840000601C905D8A401D001D043D00DEC22F0D7 +:10C8500006010601CA5107010701DF5D0701DB6F11 +:10C8600006010601CB5107010701E0590701DC6F02 +:10C8700006010601CC5107010701E1590701DD6FEF +:10C8800006010601CD5107010701E2590701DE6FDC +:10C89000F30EDB5D9E0EDC59000EDD59000E070124 +:10C8A000DE59D8A001D001D013D006010601C6512F +:10C8B000FF0A06010601C66FC6C6BBFF0DEC22F0DB +:10C8C000DFC7CAF6E0C7CBF6E1C7CCF6E2C7CDF6C4 +:10C8D00002D0000EBB6E06010601D151D8B401D0C2 +:10C8E00001D025D006010601D05106010601CE2750 +:10C8F0007E0E06010601CE6501D001D004D00601EE +:10C900000601D06911D006010601CE6701D001D021 +:10C910000BD00701DB6F010E06010601D06F070186 +:10C92000DB5106010601D107CEC6BEFF0DD00601C0 +:10C930000601D251020AD8A401D001D003D0CFC63B +:10C94000BEFF02D0000EBE6E1200B9EC20F0110E38 +:10C95000070107010B6F000E07010C6F00015E0E4F +:10C9600007010701096F0001000E07010A6FE0ECE3 +:10C9700019F05E28D8A401D001D02ED00701086F8D +:10C98000000E00010001636F070108510701086FE5 +:10C99000000E00010001626F070108510701086FD6 +:10C9A000000E00010001616F070108510701086FC7 +:10C9B000540E00010001606F070108510701086F64 +:10C9C000CA0E000100015F6F070108510701086FDF +:10C9D000AC0E5E6E070108510601688D0601688F76 +:10C9E000060E07010701B26F000E0701B36F0001C9 +:10C9F0005E0E07010701B06F0001000E0701B16F65 +:10CA00000601690E07010701AE6F0601060E070158 +:10CA1000AF6F18EC1AF0C00E060106013C6FA80EAD +:10CA200006013D6F000E06013E6F330E06013F6F9B +:10CA30003CC650F63DC651F63EC652F63FC653F6CA +:10CA4000FF0E06010601406FFF0E0601416FFF0E4B +:10CA50000601426F000E0601436F40C654F641C600 +:10CA600055F642C656F643C657F6C00E06010601F5 +:10CA7000446FA80E0601456F000E0601466F010EB9 +:10CA80000601476FC00E06010601486FA80E060199 +:10CA9000496F000E06014A6F010E06014B6F000E32 +:10CAA000060106014C6F000E06014D6F000E0601D7 +:10CAB0004E6F000E06014F6F1200140E07010701A2 +:10CAC000C66F000E0701C76F0701270E0701070198 +:10CAD000C46F0701070E0701C56FA4EC19F0070129 +:10CAE00007012751F00B400AD8B401D001D002D081 +:10CAF000000E96D01F0E070107012D1507013B6F91 +:10CB0000FF0E070107012E1507013C6F07013C517D +:10CB10003B11D8B401D001D002D0000E81D027C77C +:10CB20003BF70F0E07013B170701D8903B37070172 +:10CB3000D8903B35326E070132C03FF7070107013D +:10CB4000406B000E070107013D6F000E07013E6FAD +:10CB500046EC16F03DC725F73EC726F7070132C061 +:10CB600079F7070107017A6BC0EC1BF00701070199 +:10CB700026512511D8B401D001D002D0000E50D0DA +:10CB80000701270E07010701BC6F0701070E070108 +:10CB9000BD6F52EC0FF0070107011E511D11D8B4F3 +:10CBA00001D001D010D01DC7E9FF1EC7EAFF070161 +:10CBB00037C7EEFF070138C7EEFF070139C7EEFFA1 +:10CBC00007013AC7EEFF1FC7E9FF20C7EAFF0701C9 +:10CBD00033C7EEFF070134C7EEFF070135C7EEFF8D +:10CBE000070136C7EEFF21C7E9FF22C7EAFF0701A9 +:10CBF00030C7EFFF325007010701295D07013B6F86 +:10CC0000000E070107012A5907013C6F23C7E9FFFE +:10CC100024C7EAFF3BC7EEFF3CC7EDFF010E00D083 +:10CC200012002FC760F784EC0EF02FC741F747ECD6 +:10CC30000AF041C731F742C732F707010701325105 +:10CC40003111D8A401D001D001D09DD00701070136 +:10CC500031053211D8A401D001D004D02FC741F73B +:10CC6000DEEC1CF003010301F7B101D001D02ED09E +:10CC7000030103EEE1F0EECF33F7EDCF34F703011C +:10CC80000301DF510701335F03010301E051070195 +:10CC9000345BD890070134310701366F0701333117 +:10CCA0000701356F0701070131510701355D0701A4 +:10CCB0000701325107013659D8A001D001D006D062 +:10CCC0002FC741F7DEEC1CF00301F781010E0701CD +:10CCD0000701AC6F000E0701AD6F0701336F010E46 +:10CCE00007010701AB6F070133510701300E070140 +:10CCF0000701A96F0701070E0701AA6FFAC3A8F77A +:10CD0000E5C3A6F7E6C3A7F74AEC0CF0030103EE70 +:10CD1000E1F0030113EEE5F0E62A000EE522E6520B +:10CD2000EE52ED50E55C02E1EF50E75CD8A001D097 +:10CD300001D004D0DFC3E5F3E0C3E6F30701070148 +:10CD400031053211D8A401D001D005D02FC741F749 +:10CD5000DEEC1CF017D003010301F6BB01D001D0BB +:10CD600011D00301F68B55EC20F0060E07010701E8 +:10CD7000702503010301F16F000E07010701712106 +:10CD80000301F26F00D012000701446F690E070122 +:10CD90000701486F07014451D0EC1DF007013A51DB +:10CDA000371138113911D8A401D001D00BD00701A7 +:10CDB000446F300E07010701486F07014451D0EC62 +:10CDC0001DF08AD00701446F000E070107013B6F79 +:10CDD00007014451070E070107013B6501D001D04F +:10CDE00001D029D007013C0E070107013B25E96E60 +:10CDF000EA6A0701070EEA2237C748F731EC1DF04F +:10CE0000EF6E040E0701446FD890070107013A3313 +:10CE10000701393307013833070137330701442F3E +:10CE2000F3D7070107013B2B070E070107013B65FD +:10CE300001D001D0D7D70701446F080E07010701C1 +:10CE40003B6F07014451070107013B6701D001D047 +:10CE500001D01ED03BC744F7FF0E0701442707014E +:10CE60003C0E07014425E96EEA6A0701070EEA2233 +:10CE7000EF50300AD8B401D001D001D009D0070159 +:10CE800007013B07070107013B6701D001D0E2D74B +:10CE9000070107013B6701D001D001D01DD03BC77E +:10CEA00044F7FF0E0701442707013C0E0701442504 +:10CEB000E96EEA6A0701070EEA22EF50070107014F +:10CEC000486FD0EC1DF0070107013B070701070180 +:10CED0003B6701D001D0E3D70701446F730E070110 +:10CEE0000701486F07014451D0EC1DF01200060104 +:10CEF0000601E45106010601DF6301D001D001D033 +:10CF00007ED006010601DF51FE0AD8B401D001D05F +:10CF10004BD0270E07010701AC6F000E0701AD6F64 +:10CF20000701A26F010E07010701AB6F0701A251B4 +:10CF30000401C80E07010701A96F0401040E0701CF +:10CF4000AA6F06010601DF511C0DF3CFA3F71B0EDC +:10CF50000701A32700016F0E0701A325E96EEA6A06 +:10CF60000001000EEA22EF5007010701A86F060139 +:10CF70000601DF511C0D00016F0EF324E96EEA6A11 +:10CF80000001000EEA22EECFA4F7EDCFA5F7D90EEF +:10CF90000701A42507010701A66FFF0E0701A521C0 +:10CFA0000701A76F4AEC0CF0E4C6DFF6270E070175 +:10CFB0000701AC6F000E0701AD6FFAC3ABF7D90ED6 +:10CFC00003010301DF2507010701A96FFF0E03011C +:10CFD0000301E0210701AA6F0701A26F010E0701FB +:10CFE0000701A86F0701A2510401C80E070107013C +:10CFF000A66F0401040E0701A76F4AEC0CF01200A3 +:04FFF8009EFFFDFF6C +:00000001FF From 4cc16757ad0745e9c2caa2290d051284b00a6a02 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 16:32:05 +0200 Subject: [PATCH 1984/2215] Link plugin against libftd2xx --- telldus-gui/Plugins/Controllers/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt index 77929dd0..7e45ea75 100644 --- a/telldus-gui/Plugins/Controllers/CMakeLists.txt +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -42,7 +42,8 @@ SET( Plugin_EXTRA tellstick_duo.png ) +FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx) FIND_PACKAGE(TelldusCore REQUIRED) -SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ) +SET( Plugin_LIBRARIES ${TELLDUSCORE_LIBRARY} ${FTD2XX_LIBRARY} ) INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) From a2f8d08511830c05233c8598cfef91473703eacf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 17:25:17 +0200 Subject: [PATCH 1985/2215] Add properties to the controller object for showing the upgrade status --- .../Plugins/Controllers/controller.cpp | 42 ++++++++++++++++++- telldus-gui/Plugins/Controllers/controller.h | 23 ++++++++-- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/Controllers/controller.cpp b/telldus-gui/Plugins/Controllers/controller.cpp index 09a1e770..a691d746 100644 --- a/telldus-gui/Plugins/Controllers/controller.cpp +++ b/telldus-gui/Plugins/Controllers/controller.cpp @@ -6,8 +6,9 @@ class Controller::PrivateData { public: bool available, nameChanged; - int id, type; + int id, type, upgradeStep; QString name, serial, firmware; + qreal upgradeProgress; }; Controller::Controller(int id, int type, const QString &name, QObject *parent) : @@ -19,6 +20,8 @@ Controller::Controller(int id, int type, const QString &name, QObject *parent) : d->available = false; d->nameChanged = false; d->name = name; + d->upgradeStep = -1; + d->upgradeProgress = 0; const int DATA_LENGTH = 255; char buff[DATA_LENGTH]; @@ -42,6 +45,7 @@ void Controller::setAvailable(bool available) { d->available = available; emit availableChanged(); emit firmwareChanged(); + emit upgradableChanged(); } QString Controller::firmware() const { @@ -100,3 +104,39 @@ int Controller::type() const { return d->type; } +bool Controller::upgradable() const { + if (!this->available()) { + return false; + } + return isUpgradable(); +} + +void Controller::upgrade() { + //Do nothing +} + +qreal Controller::upgradeProgress() { + return d->upgradeProgress; +} + +int Controller::upgradeStep() const { + return d->upgradeStep; +} + +void Controller::setUpgradeStep(int newStep) { + d->upgradeStep = newStep; + if (newStep = -1) { + setUpgradeProgress(0); + } + emit upgradeStepChanged(); +} + +void Controller::setUpgradeProgress(qreal completed) { + d->upgradeProgress = completed; + emit upgradeProgressChanged(); +} + +bool Controller::isUpgradable() const { + return false; +} + diff --git a/telldus-gui/Plugins/Controllers/controller.h b/telldus-gui/Plugins/Controllers/controller.h index 5cc8ee5e..392aa5a1 100644 --- a/telldus-gui/Plugins/Controllers/controller.h +++ b/telldus-gui/Plugins/Controllers/controller.h @@ -12,14 +12,17 @@ class Controller : public QObject Q_PROPERTY(int id READ id NOTIFY idChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString serial READ serial NOTIFY serialChanged) - Q_PROPERTY(int type READ type NOTIFY typeChanged()) + Q_PROPERTY(int type READ type NOTIFY typeChanged) + Q_PROPERTY(bool upgradable READ upgradable NOTIFY upgradableChanged) + Q_PROPERTY(qreal upgradeProgress READ upgradeProgress NOTIFY upgradeProgressChanged) + Q_PROPERTY(int upgradeStep READ upgradeStep NOTIFY upgradeStepChanged) public: explicit Controller(int id = 0, int type = 1, const QString &name = "", QObject *parent = 0); - ~Controller(); + virtual ~Controller(); bool available() const; - void setAvailable(bool available); + virtual void setAvailable(bool available); QString firmware() const; void setFirmware(const QString &version); @@ -37,6 +40,11 @@ public: int type() const; + bool upgradable() const; + Q_INVOKABLE virtual void upgrade(); + qreal upgradeProgress(); + int upgradeStep() const; + signals: void availableChanged(); void firmwareChanged(); @@ -44,6 +52,15 @@ signals: void nameChanged(); void serialChanged(); void typeChanged(); + void upgradableChanged(); + void upgradeProgressChanged(); + void upgradeStepChanged(); + void upgradeDone(); + +protected: + virtual bool isUpgradable() const; + void setUpgradeStep(int newStep); + void setUpgradeProgress(qreal completed); private: class PrivateData; From 3b137c03261ed1d4c9bbe3c54eb0de27aea5517a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 17:26:05 +0200 Subject: [PATCH 1986/2215] Load class TellStick for TellStick controllers --- telldus-gui/Plugins/Controllers/controllerlist.cpp | 12 ++++++++++-- telldus-gui/Plugins/Controllers/controllerlist.h | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/Controllers/controllerlist.cpp b/telldus-gui/Plugins/Controllers/controllerlist.cpp index 76f0f347..99c8f039 100644 --- a/telldus-gui/Plugins/Controllers/controllerlist.cpp +++ b/telldus-gui/Plugins/Controllers/controllerlist.cpp @@ -1,5 +1,6 @@ #include "controllerlist.h" #include "controller.h" +#include "tellstick.h" #include @@ -25,7 +26,7 @@ ControllerList::ControllerList(QObject *parent) : char name[DATA_LENGTH]; int available, controllerId, type; while(tdController(&controllerId, &type, name, DATA_LENGTH, &available) == TELLSTICK_SUCCESS) { - Controller *controller = new Controller(controllerId, type, QString::fromUtf8(name), this); + Controller *controller = loadController(controllerId, type, QString::fromUtf8(name), this); controller->setAvailable(available); connect(controller, SIGNAL(nameChanged()), this, SIGNAL(changed())); d->list.append(controller); @@ -72,7 +73,7 @@ void ControllerList::controllerEventSlot(int controllerId, int changeEvent, int if (changeEvent == TELLSTICK_DEVICE_ADDED) { beginInsertRows( QModelIndex(), d->list.size(), d->list.size() ); - Controller *controller = new Controller(controllerId, changeType, "", this); + Controller *controller = loadController(controllerId, changeType, "", this); controller->setAvailable(true); connect(controller, SIGNAL(nameChanged()), this, SIGNAL(changed())); d->list.append(controller); @@ -93,6 +94,13 @@ void ControllerList::controllerEventSlot(int controllerId, int changeEvent, int } } +Controller *ControllerList::loadController(int id, int type, const QString &name, QObject *parent) { + if (type == 1) { + return new TellStick(id, type, "", parent); + } + return new Controller(id, type, "", parent); +} + void WINAPI ControllerList::controllerEvent( int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context) { ControllerList *controllerList = reinterpret_cast(context); if (!controllerList) { diff --git a/telldus-gui/Plugins/Controllers/controllerlist.h b/telldus-gui/Plugins/Controllers/controllerlist.h index c325868c..be16af6f 100644 --- a/telldus-gui/Plugins/Controllers/controllerlist.h +++ b/telldus-gui/Plugins/Controllers/controllerlist.h @@ -5,6 +5,8 @@ #include #include +class Controller; + class ControllerList : public QAbstractListModel { Q_OBJECT @@ -27,6 +29,7 @@ private slots: void controllerEventSlot(int controllerId, int changeEvent, int changeType, const QString &newValue); private: + static Controller *loadController(int id, int type, const QString &name, QObject *parent); static void WINAPI controllerEvent( int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context); class PrivateData; PrivateData *d; From 13cd76e8aca1d3d4b11c5483939c9552ad06686a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 17:26:43 +0200 Subject: [PATCH 1987/2215] Add qml item StateLabel --- telldus-gui/Plugins/Controllers/CMakeLists.txt | 1 + telldus-gui/Plugins/Controllers/StateLabel.qml | 10 ++++++++++ telldus-gui/Plugins/Controllers/qmldir | 1 + 3 files changed, 12 insertions(+) create mode 100644 telldus-gui/Plugins/Controllers/StateLabel.qml diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt index 7e45ea75..ec0093a4 100644 --- a/telldus-gui/Plugins/Controllers/CMakeLists.txt +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -38,6 +38,7 @@ SET( Plugin_EXTRA main.qml qmldir row_bg.png + StateLabel.qml tellstick.png tellstick_duo.png ) diff --git a/telldus-gui/Plugins/Controllers/StateLabel.qml b/telldus-gui/Plugins/Controllers/StateLabel.qml new file mode 100644 index 00000000..3bf8f59f --- /dev/null +++ b/telldus-gui/Plugins/Controllers/StateLabel.qml @@ -0,0 +1,10 @@ +import QtQuick 1.1 +import QtDesktop 0.1 + +Text { + property int currentState: -1 + property int state: 0 + id: stateLabel; + text: "" + font.bold: state == currentState +} diff --git a/telldus-gui/Plugins/Controllers/qmldir b/telldus-gui/Plugins/Controllers/qmldir index 737b55f1..b745c6fe 100644 --- a/telldus-gui/Plugins/Controllers/qmldir +++ b/telldus-gui/Plugins/Controllers/qmldir @@ -1,2 +1,3 @@ HeaderTitle 1.0 HeaderTitle.qml ControllerView 1.0 ControllerView.qml +StateLabel 1.0 StateLabel.qml From bf4ad2a1a78d22b483ec1814337ad711ce828395 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 17:27:54 +0200 Subject: [PATCH 1988/2215] Add aml item ControllerUpgradeDialog --- .../Plugins/Controllers/CMakeLists.txt | 1 + .../Controllers/ControllerUpgradeDialog.qml | 124 ++++++++++++++++++ telldus-gui/Plugins/Controllers/qmldir | 1 + 3 files changed, 126 insertions(+) create mode 100644 telldus-gui/Plugins/Controllers/ControllerUpgradeDialog.qml diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt index ec0093a4..6e2366e8 100644 --- a/telldus-gui/Plugins/Controllers/CMakeLists.txt +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -31,6 +31,7 @@ SET( Plugin_PATH "com.telldus.controllers" ) SET( Plugin_EXTRA btn_action_remove.png + ControllerUpgradeDialog.qml ControllerView.qml header_bg.png HeaderTitle.qml diff --git a/telldus-gui/Plugins/Controllers/ControllerUpgradeDialog.qml b/telldus-gui/Plugins/Controllers/ControllerUpgradeDialog.qml new file mode 100644 index 00000000..6672fcf9 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/ControllerUpgradeDialog.qml @@ -0,0 +1,124 @@ +import QtQuick 1.1 +import QtDesktop 0.1 + +Window { + id: controllerUpgradeDialog + width: 400 + height: 200 + + modal: true + title: "Upgrade TellStick" + visible: false + deleteOnClose: false + + property int step: controller.upgradeStep + property variant controller: undefined + Connections { + target: controller + onUpgradeDone: state = 'upgradeDone' + } + + Item { + id: confirm + anchors.top: parent.top + anchors.left: parent.left + width: parent.width + height: parent.height + clip: true + Item { + anchors.fill: parent + anchors.margins: 16 + + Column { + Text { text: "This will upgrade your TellStick to the latest version.\n\n" } + Text { text: "Please do not unplug the TellStick or end the application during upgrade." } + Text { text: "Doing so might render the TellStick unusable." } + } + Row { + anchors.bottom: parent.bottom + anchors.right: parent.right + spacing: 8 + Button { + text: "Upgrade" + onClicked: controllerUpgradeDialog.state = 'upgrade' + } + Button { + text: "Close" + onClicked: controllerUpgradeDialog.visible = false + } + } + } + } + + Item { + id: content + anchors.topMargin:16 + anchors.margins: 16 + anchors.top: parent.top + anchors.left: parent.right + width: parent.width - 32 + height: parent.height - 32 + anchors.right: undefined + clip: true + Column { + StateLabel { text: "1. Disconnecting TellStick"; currentState: controllerUpgradeDialog.step; state: 0 } + StateLabel { text: "2. Aquiring TellStick"; currentState: controllerUpgradeDialog.step; state: 1 } + StateLabel { text: "3. Entering bootloader"; currentState: controllerUpgradeDialog.step; state: 2 } + StateLabel { text: "4. Uploading firmware"; currentState: controllerUpgradeDialog.step; state: 3 } + StateLabel { text: "5. Rebooting TellStick"; currentState: controllerUpgradeDialog.step; state: 4 } + StateLabel { text: "6. Connecting TellStick"; currentState: controllerUpgradeDialog.step; state: 5 } + } + ProgressBar { + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + minimumValue: 0 + maximumValue: 100 + value: controller.upgradeProgress + } + } + Item { + id: done + anchors.top: parent.top + anchors.left: parent.right + width: parent.width + height: parent.height + clip: true + Item { + anchors.fill: parent + anchors.margins: 16 + + Column { + Text { text: "Upgrade done.\n\n" } + Text { text: "Your TellStick has now been flashed with the latest firmware." } + } + Button { + anchors.bottom: parent.bottom + anchors.right: parent.right + text: "Close" + onClicked: controllerUpgradeDialog.visible = false + } + } + } + + states: [ + State { + name: 'upgrade' + AnchorChanges { target: confirm; anchors.left: undefined; anchors.right: controllerUpgradeDialog.left } + AnchorChanges { target: content; anchors.left: controllerUpgradeDialog.left; anchors.right: undefined } + StateChangeScript { script: controller.upgrade() } + }, + State { + name: 'upgradeDone' + AnchorChanges { target: confirm; anchors.left: undefined; anchors.right: controllerUpgradeDialog.left } + AnchorChanges { target: content; anchors.left: undefined; anchors.right: controllerUpgradeDialog.left } + AnchorChanges { target: done; anchors.left: controllerUpgradeDialog.left; anchors.right: undefined } + } + ] + + transitions: [ + Transition { + AnchorAnimation { duration: 500; easing.type: Easing.InOutQuad } + } + ] +} diff --git a/telldus-gui/Plugins/Controllers/qmldir b/telldus-gui/Plugins/Controllers/qmldir index b745c6fe..dee0f82e 100644 --- a/telldus-gui/Plugins/Controllers/qmldir +++ b/telldus-gui/Plugins/Controllers/qmldir @@ -1,3 +1,4 @@ HeaderTitle 1.0 HeaderTitle.qml ControllerView 1.0 ControllerView.qml +ControllerUpgradeDialog 1.0 ControllerUpgradeDialog.qml StateLabel 1.0 StateLabel.qml From 0ebdba4dbc3142a3c44c4265d865d7d9f848ba7c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 17:28:47 +0200 Subject: [PATCH 1989/2215] Add option to update firmware for TellStick --- .../Plugins/Controllers/ControllerView.qml | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/telldus-gui/Plugins/Controllers/ControllerView.qml b/telldus-gui/Plugins/Controllers/ControllerView.qml index 52c7283c..8fc17c7f 100644 --- a/telldus-gui/Plugins/Controllers/ControllerView.qml +++ b/telldus-gui/Plugins/Controllers/ControllerView.qml @@ -2,12 +2,38 @@ import QtQuick 1.1 import QtDesktop 0.1 BorderImage { + id: view source: "row_bg.png" border.left: 5; border.top: 5 border.right: 5; border.bottom: 5 width: parent.width height: content.height + content.anchors.margins*2 + property variant c: controller //Needed for upgradeDialogComponent + + Component { + id: upgradeDialogComponent + ControllerUpgradeDialog { + controller: c + } + } + Loader { + id: upgradeDialog + visible: false + onVisibleChanged: { + if (visible) { + upgradeDialog.sourceComponent = upgradeDialogComponent + upgradeDialog.item.visible = true + } else { + upgradeDialog.sourceComponent = undefined + } + } + Connections { + target: upgradeDialog.item + onVisibleChanged: upgradeDialog.visible = upgradeDialog.item.visible + } + } + Item { id: content anchors.top: parent.top @@ -50,6 +76,15 @@ BorderImage { onClicked: controller.tryRemove(); } } + Image { + source: "btn_action_remove.png" + rotation: 90 + visible: controller.upgradable + MouseArea { + anchors.fill: parent + onClicked: upgradeDialog.visible = true + } + } } } From 9095ba60906712766aa8d98ae8479df481e76db3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 Apr 2012 17:29:24 +0200 Subject: [PATCH 1990/2215] Load class TellStick for TellStick Duo also --- telldus-gui/Plugins/Controllers/controllerlist.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Controllers/controllerlist.cpp b/telldus-gui/Plugins/Controllers/controllerlist.cpp index 99c8f039..b5baa1fe 100644 --- a/telldus-gui/Plugins/Controllers/controllerlist.cpp +++ b/telldus-gui/Plugins/Controllers/controllerlist.cpp @@ -95,7 +95,7 @@ void ControllerList::controllerEventSlot(int controllerId, int changeEvent, int } Controller *ControllerList::loadController(int id, int type, const QString &name, QObject *parent) { - if (type == 1) { + if (type == 1 || type == 2) { return new TellStick(id, type, "", parent); } return new Controller(id, type, "", parent); From 7e287a607951deb87500d8c344cf7c7c03701ae1 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 20 Apr 2012 14:33:44 +0200 Subject: [PATCH 1991/2215] Check the current firmware version --- telldus-gui/Plugins/Controllers/tellstick.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Controllers/tellstick.cpp b/telldus-gui/Plugins/Controllers/tellstick.cpp index 093ac3e1..f013cb69 100644 --- a/telldus-gui/Plugins/Controllers/tellstick.cpp +++ b/telldus-gui/Plugins/Controllers/tellstick.cpp @@ -43,7 +43,21 @@ void TellStick::setAvailable(bool available) { } bool TellStick::isUpgradable() const { - return true; //TODO: check version + QString fw = firmware(); + if (fw == "?") { + return false; + } + int firmware = fw.toInt(); + if (type() == 1) { + //TellStick + if (firmware <= 3) { + return false; + } + if (firmware < 6) { + return true; + } + } + return false; } void TellStick::aquireTellStick() { From 00f95d22e12d96ef089e0902ef62ae8ce841dc6f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 20 Apr 2012 14:34:15 +0200 Subject: [PATCH 1992/2215] Add support for flashing TellStick Duo --- telldus-gui/Plugins/Controllers/tellstick.cpp | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/telldus-gui/Plugins/Controllers/tellstick.cpp b/telldus-gui/Plugins/Controllers/tellstick.cpp index f013cb69..eaa3397c 100644 --- a/telldus-gui/Plugins/Controllers/tellstick.cpp +++ b/telldus-gui/Plugins/Controllers/tellstick.cpp @@ -56,6 +56,12 @@ bool TellStick::isUpgradable() const { if (firmware < 6) { return true; } + + } else if (type() == 2) { + //TellStick Duo + if (firmware < 5) { + return true; + } } return false; } @@ -66,7 +72,11 @@ void TellStick::aquireTellStick() { strcpy_s(tempSerial, serial().size()+1, serial().toLocal8Bit()); #else strcpy(tempSerial, serial().toLocal8Bit()); - FT_SetVIDPID(0x1781, 0x0c30); //TODO: Make dynamic for TellStick Duo + int pid = 0x0C30; + if (type() == 2) { + pid = 0x0C31; + } + FT_SetVIDPID(0x1781, pid); #endif FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle); delete tempSerial; @@ -75,11 +85,11 @@ void TellStick::aquireTellStick() { } //open = true; - //if (this->field("pid").toInt() == 0x0C31) { - // FT_SetBaudRate(ftHandle, 115200); - //} else { + if (type() == 2) { + FT_SetBaudRate(d->ftHandle, 115200); + } else { FT_SetBaudRate(d->ftHandle, 9600); - //} + } FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); FT_SetTimeouts(d->ftHandle,1000,0); @@ -113,10 +123,10 @@ void TellStick::enterBootloader() { void TellStick::downloadFirmware() { QString filename = "TellStick"; int bootloaderStart = 0x3A00; - /*if (this->field("pid").toInt() == 0x0C31) { + if (type() == 2) { filename = "TellStickDuo"; bootloaderStart = 0x7A00; - }*/ + } QString path; //if (QApplication::arguments().count() > 1) { // path = QApplication::arguments().at(1); @@ -163,7 +173,11 @@ void TellStick::rebootTellStick() { } void TellStick::connectTellStick() { - tdConnectTellStickController(0x1781, 0x0C30, this->serial().toUtf8()); + int pid = 0x0C30; + if (type() == 2) { + pid = 0x0C31; + } + tdConnectTellStickController(0x1781, pid, this->serial().toUtf8()); setUpgradeStep(-1); emit upgradableChanged(); emit upgradeDone(); @@ -315,5 +329,9 @@ int TellStick::parseHex(const QByteArray &characters, int start, int length) { void TellStick::upgrade() { setUpgradeStep(0); - tdDisconnectTellStickController(0x1781, 0x0C30, serial().toUtf8()); //TODO: Make dynamic for TellStick Duo + int pid = 0x0C30; + if (type() == 2) { + pid = 0x0C31; + } + tdDisconnectTellStickController(0x1781, pid, serial().toUtf8()); //TODO: Make dynamic for TellStick Duo } From d4b46c71ece3f1c62233f1487f45181937387016 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 29 May 2012 14:18:28 +0200 Subject: [PATCH 1993/2215] Add some different xPL implementations done by Telldus --- xpl/data/uml.xmi | 371 +++++++++++++++++++++++ xpl/phpxpl/example.php | 21 ++ xpl/phpxpl/xpldevice.class.php | 66 ++++ xpl/phpxpl/xplinstance.class.php | 210 +++++++++++++ xpl/phpxpl/xpllighting.class.php | 172 +++++++++++ xpl/phpxpl/xplmessage.class.php | 144 +++++++++ xpl/pyxpl/__init__.py | 1 + xpl/pyxpl/xpldevice.py | 22 ++ xpl/pyxpl/xplinstance.py | 47 +++ xpl/pyxpl/xplmessage.py | 56 ++++ xpl/qtxpl/CMakeLists.txt | 43 +++ xpl/qtxpl/main.cpp | 12 + xpl/qtxpl/qtxpl.pro | 15 + xpl/qtxpl/xpldevice.cpp | 105 +++++++ xpl/qtxpl/xpldevice.h | 38 +++ xpl/qtxpl/xplinstance.cpp | 226 ++++++++++++++ xpl/qtxpl/xplinstance.h | 55 ++++ xpl/qtxpl/xplmessage.cpp | 188 ++++++++++++ xpl/qtxpl/xplmessage.h | 57 ++++ xpl/telldus-core-xpl/Makefile | 37 +++ xpl/telldus-core-xpl/xPL_TelldusCore.c | 399 +++++++++++++++++++++++++ 21 files changed, 2285 insertions(+) create mode 100644 xpl/data/uml.xmi create mode 100644 xpl/phpxpl/example.php create mode 100644 xpl/phpxpl/xpldevice.class.php create mode 100644 xpl/phpxpl/xplinstance.class.php create mode 100644 xpl/phpxpl/xpllighting.class.php create mode 100644 xpl/phpxpl/xplmessage.class.php create mode 100644 xpl/pyxpl/__init__.py create mode 100644 xpl/pyxpl/xpldevice.py create mode 100644 xpl/pyxpl/xplinstance.py create mode 100644 xpl/pyxpl/xplmessage.py create mode 100644 xpl/qtxpl/CMakeLists.txt create mode 100644 xpl/qtxpl/main.cpp create mode 100644 xpl/qtxpl/qtxpl.pro create mode 100644 xpl/qtxpl/xpldevice.cpp create mode 100644 xpl/qtxpl/xpldevice.h create mode 100644 xpl/qtxpl/xplinstance.cpp create mode 100644 xpl/qtxpl/xplinstance.h create mode 100644 xpl/qtxpl/xplmessage.cpp create mode 100644 xpl/qtxpl/xplmessage.h create mode 100644 xpl/telldus-core-xpl/Makefile create mode 100644 xpl/telldus-core-xpl/xPL_TelldusCore.c diff --git a/xpl/data/uml.xmi b/xpl/data/uml.xmi new file mode 100644 index 00000000..9aadbdee --- /dev/null +++ b/xpl/data/uml.xmi @@ -0,0 +1,371 @@ + + + + + umbrello uml modeller http://uml.sf.net + 1.5.8 + UnicodeUTF8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xpl/phpxpl/example.php b/xpl/phpxpl/example.php new file mode 100644 index 00000000..2b5b70d2 --- /dev/null +++ b/xpl/phpxpl/example.php @@ -0,0 +1,21 @@ +doEvents()) { + usleep(100); + } + } + $xplinstance->detach(); +} + +function signalHandler() { +global $running; + $running = false; +} diff --git a/xpl/phpxpl/xpldevice.class.php b/xpl/phpxpl/xpldevice.class.php new file mode 100644 index 00000000..dbce877d --- /dev/null +++ b/xpl/phpxpl/xpldevice.class.php @@ -0,0 +1,66 @@ +_vendor = substr($vendor, 0, $dash); + $this->_device = substr($vendor, $dash+1, $dot-$dash-1); + $this->_instance = substr($vendor, $dot+1); + } else { + $this->_vendor = $vendor; + $this->_device = $device; + + //Generate an instance + $randomNumber = mt_rand(1, 9999); //Generate ranom number between 1-9999 + $this->_instance = sprintf('default%s', $randomNumber); + } + } + + public function address() { + return $this->_address; + } + + public function heartBeatInterval() { + return $this->_heartBeatInterval; + } + + public function deviceName() { + return sprintf('%s-%s.%s', $this->_vendor, $this->_device, $this->_instance); + } + + public function lastHeartBeat() { + return $this->_lastHeartBeat; + } + + public function port() { + return $this->_port; + } + + public function setAddress( $address ) { + $this->_address = $address; + } + + public function setHeartBeatInterval( $minutes ) { + $this->_heartBeatInterval = $minutes; + } + + public function setPort( $p ) { + $this->_port = $p; + } + + public function setLastHeartBeat( $timestamp ) { + $this->_lastHeartBeat = $timestamp; + } +} diff --git a/xpl/phpxpl/xplinstance.class.php b/xpl/phpxpl/xplinstance.class.php new file mode 100644 index 00000000..0937c5be --- /dev/null +++ b/xpl/phpxpl/xplinstance.class.php @@ -0,0 +1,210 @@ +_ip = $ip; + $this->_thisDevice = new XPLDevice($vendor, $device); + + $this->init(); + } + + public function attatched() { + return $this->_isAttatched; + } + + public function detach() { + $message = new xPLMessage( xPLMessage::xplstat ); + $message->setMessageSchemeIdentifier( 'hbeat.end' ); + $message->setTarget('*'); + $message->setSource( $this->_thisDevice->deviceName() ); + $this->sendMessage( $message ); + socket_close($this->_socket); + $this->_socket = null; + } + + public function doEvents() { + $string = socket_read( $this->_socket, 1500); + if ($string != '') { + $message = XPLMessage::createMessageFromString($string); + if ($message) { + $this->processMessage( $message ); + } + return false; + } + $this->poll(); + return true; + } + + public function sendMessage( $message, $device = null ) { + //echo "Sending heartbeat\n"; + $msg = (string)$message; + socket_sendto( $this->_socket, $msg, strlen($msg), 0, '255.255.255.255', XPL_PORT ); + } + + protected function attatchedToNetwork() { + } + + protected function handleMessage( $message ) { + return false; + } + + + private function bindToPort() { + $port = 49152; + //$port = XPL_PORT; + $error = 98; + while ($error == 98 && $port < 65535) { + if (@socket_bind($this->_socket, $this->_ip, $port) === false) { + ++$port; + } else { + echo "Bind succeded as client on: " . $port . "\n"; + return $port; + } + } + return 0; + } + + private function init() { + if (($this->_socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === false) { + echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; + return; + } + + socket_set_option( $this->_socket, SOL_SOCKET, SO_BROADCAST, 1); + socket_set_nonblock( $this->_socket ); + + $this->_thisDevice->setPort( $this->bindToPort() ); + if ($this->_thisDevice->port() == 0) { + echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($this->_socket)) . "\n"; + return; + } + + printf("xPL server started (bound to port %s)\n", $this->_thisDevice->port()); + $this->sendHeartbeat(); + } + + private function poll() { + if (!$this->attatched()) { + $this->sendHeartbeat(); + return; + } + + if (time()-$this->_thisDevice->lastHeartBeat() >= $this->_thisDevice->heartBeatInterval() * 60) { + $this->sendHeartbeat(); + } + //Loop all devices to see if they have timed out + foreach( $this->_devices as $key => $device ) { + if ( time()-$device->lastHeartBeat() >= $device->heartBeatInterval() * 60 * 2) { + printf("Device removed (timeout): %s\n", $device->deviceName()); + + //This is not a prefeered way of removing the item from an array + //Since we are iterating the loop will miss to check the new item. + //Here, it will be checked next time poll is called + unset($this->_devices[$key]); + continue; + } + } + } + + private function processHeartBeat( $message ) { + if ($message->messageSchemeIdentifier() == 'hbeat.request') { + $this->sendHeartbeat(); + return true; + } + foreach( $this->_devices as $key => $device ) { + if ( $device->deviceName() == $message->source() ) { + if (substr($message->messageSchemeIdentifier(), -3) == 'end') { + echo "Device removed: " . $message->source() . "\n"; + unset($this->_devices[$key]); + return true; + } else { + $device->setLastHeartBeat( time() ); + $device->setHeartBeatInterval( $message->bodyItem( 'interval' ) ); + } + return true; + } + } + if ( (substr($message->messageSchemeIdentifier(), -3) != 'app') && (substr($message->messageSchemeIdentifier(), -5) != 'basic') ) { //Not a heartbeat + return false; + } + + printf( "New device: %s\n", $message->source() ); + $device = new xPLDevice( $message->source() ); + $device->setHeartBeatInterval( $message->bodyItem('interval') ); + $device->setLastHeartBeat( time() ); + if ($message->messageSchemeIdentifier() == 'hbeat.app') { + $device->setAddress( $message->bodyItem('remote-ip')); + $device->setPort( $message->bodyItem('port') ); + } + $this->_devices[] = $device; + return true; + } + + private function processMessage( $message ) { + if (!$this->attatched() && $message->messageSchemeIdentifier() == 'hbeat.app' && $message->source() == $this->_thisDevice->deviceName()) { + //Our own echo + $this->setAttatched( true ); + return; + } + if ($message->source() == $this->_thisDevice->deviceName()) { + //Ignore messages from ourselves + return; + } + if ( (substr($message->messageSchemeIdentifier(), 0, 5) == 'hbeat') || (substr($message->messageSchemeIdentifier(), 0, 6) == 'config') ) { + if ($this->processHeartBeat( $message )) { + return; + } + } + if ($message->target() != $this->_thisDevice->deviceName() && $message->target() != '*') { + //Message not for us + return; + } + if (!$this->handleMessage($message)) { + printf("Got message:\n%s", $message); + } + } + + + private function sendHeartbeat() { +// echo "Sending heartbeat\n"; + $message = new xPLMessage( xPLMessage::xplstat ); + $message->setMessageSchemeIdentifier( 'hbeat.app' ); + $message->setTarget('*'); + $message->setSource( $this->_thisDevice->deviceName() ); + $message->addBodyItem( 'interval', $this->_thisDevice->heartBeatInterval() ); + $message->addBodyItem( 'port', $this->_thisDevice->port() ); + $message->addBodyItem( 'remote-ip', $this->_ip ); + $this->sendMessage( $message ); + $this->_thisDevice->setLastHeartBeat( time() ); + } + + private function setAttatched( $attatched ) { + $this->_isAttatched = $attatched; + if ($this->_isAttatched) { + echo "Attatched to xPL-network\n"; +// timer->setInterval( 60000 ); //Once a minute + + $message = new xPLMessage( xPLMessage::xplcmnd ); + $message->setTarget( "*" ); + $message->setSource( $this->_thisDevice->deviceName() ); + $message->setMessageSchemeIdentifier( 'hbeat.request' ); + $message->addBodyItem('command', 'request'); + $this->sendMessage( $message ); + + $this->attatchedToNetwork(); + } + } + +} diff --git a/xpl/phpxpl/xpllighting.class.php b/xpl/phpxpl/xpllighting.class.php new file mode 100644 index 00000000..1799afa4 --- /dev/null +++ b/xpl/phpxpl/xpllighting.class.php @@ -0,0 +1,172 @@ +setMessageSchemeIdentifier( 'lighting.gateway' ); + $message->setTarget('*'); + $message->setSource( $this->_thisDevice->deviceName() ); + $message->addBodyItem( 'report', 'gateway-ready' ); + $this->sendMessage( $message ); + } + + protected function handleMessage( $message ) { + if ($message->messageSchemeIdentifier() == 'lighting.request') { + return $this->lightingRequest($message); + } + return false; + } + + private function lightingRequest( $message ) { + switch( $message->bodyItem('request') ) { + case 'gateinfo': + return $this->gateInfo( ); + case 'netlist': + return $this->netList( ); + case 'netinfo': + return $this->netInfo( $message ); + case 'devlist': + return $this->devList( $message ); + case 'devinfo': + return $this->devInfo( $message ); + } + return false; + } + + private function gateInfo( ) { + $message = new xPLMessage( xPLMessage::xplstat ); + $message->setMessageSchemeIdentifier( 'lighting.gateinfo' ); + $message->setTarget('*'); + $message->setSource( $this->_thisDevice->deviceName() ); + $message->addBodyItem( 'status', 'ok' ); + $message->addBodyItem( 'protocol', 'TELLDUS' ); + $message->addBodyItem( 'description', 'xPL to Telldus TellStick gateway' ); + $message->addBodyItem( 'version', '1.0' ); + $message->addBodyItem( 'author', 'Telldus Technologies AB' ); + $message->addBodyItem( 'info-url', 'http://www.telldus.se' ); + $message->addBodyItem( 'net-count', '1' ); + $message->addBodyItem( 'preferred-net', '1' ); + $message->addBodyItem( 'scenes-ok', 'false' ); + $message->addBodyItem( 'channels-ok', 'false' ); + $message->addBodyItem( 'fade-rate-ok', 'false' ); + $this->sendMessage( $message ); + return true; + } + + private function netList( ) { + $message = new xPLMessage( xPLMessage::xplstat ); + $message->setMessageSchemeIdentifier( 'lighting.netlist' ); + $message->setTarget('*'); + $message->setSource( $this->_thisDevice->deviceName() ); + $message->addBodyItem( 'status', 'ok' ); + $message->addBodyItem( 'network', '1' ); + $this->sendMessage( $message ); + return true; + } + + private function netInfo( $message ) { + $msg = new xPLMessage( xPLMessage::xplstat ); + $msg->setMessageSchemeIdentifier( 'lighting.netinfo' ); + $msg->setTarget('*'); + $msg->setSource( $this->_thisDevice->deviceName() ); +// print_r($message); + $msg->addBodyItem( 'network', $message->bodyItem('network') ); + if ($msg->bodyItem('network') == '1') { + $msg->addBodyItem( 'status', 'ok' ); + $msg->addBodyItem( 'name', exec('hostname') ); + $msg->addBodyItem( 'device-count', tdGetNumberOfDevices() ); + $msg->addBodyItem( 'scene-count', 0 ); + } else { + $msg->addBodyItem( 'status', 'not-found' ); + } + $this->sendMessage( $msg ); + return true; + } + + private function devList( $message ) { + $msg = new xPLMessage( xPLMessage::xplstat ); + $msg->setMessageSchemeIdentifier( 'lighting.devlist' ); + $msg->setTarget('*'); + $msg->setSource( $this->_thisDevice->deviceName() ); + $msg->addBodyItem( 'network', $message->bodyItem('network') ); + if ($msg->bodyItem('network') == '1') { + $msg->addBodyItem( 'status', 'ok' ); + $count = tdGetNumberOfDevices(); + $deviceList = array(); + for( $i = 0; $i < $count; ++$i ) { + $deviceList[] = tdGetDeviceId($i); + } + $msg->addBodyItem( 'device-count', $count ); + $msg->addBodyItem( 'device', implode(',', $deviceList) ); + } else { + $msg->addBodyItem( 'status', 'not-found' ); + } + $this->sendMessage( $msg ); + return true; + } + + private function devInfo( $message ) { + $found = false; + $count = tdGetNumberOfDevices(); + $deviceId = $message->bodyItem('device'); + for( $i = 0; $i < $count; ++$i ) { + if (tdGetDeviceId($i) == $deviceId) { + $found = true; + break; + } + } + + $msg = new xPLMessage( xPLMessage::xplstat ); + $msg->setMessageSchemeIdentifier( 'lighting.devinfo' ); + $msg->addBodyItem( 'network', $message->bodyItem('network') ); + $msg->addBodyItem( 'device', $deviceId ); + $msg->setTarget('*'); + $msg->setSource( $this->_thisDevice->deviceName() ); + + if ($msg->bodyItem('network') == '1' && $found) { + $methods = tdMethods($deviceId, TELLDUS_TURNON | TELLDUS_TURNOFF | TELLDUS_DIM ); + $msg->addBodyItem( 'status', 'ok' ); + $msg->addBodyItem( 'name', tdGetName($deviceId) ); + $msg->addBodyItem( 'report-on-manual', 'false' ); + $msg->addBodyItem( 'channel-count', '1'); + $msg->addBodyItem( 'primary-channel', '1'); + $msg->addBodyItem( 'channel', sprintf('1,%s,0,0', ($methods & TELLDUS_DIM ? 'true' : 'false')) ); + $msg->addBodyItem( 'scene-count', '0'); + } else { + $msg->addBodyItem( 'status', 'not-found' ); + } + $this->sendMessage( $msg ); + return true; + } + + private function scnList( $message ) { + $msg = new xPLMessage( xPLMessage::xplstat ); + $msg->setMessageSchemeIdentifier( 'lighting.scnlist' ); + $msg->setTarget('*'); + $msg->setSource( $this->_thisDevice->deviceName() ); + $msg->addBodyItem( 'network', $message->bodyItem('network') ); + $msg->addBodyItem( 'status', 'not-found' ); + $this->sendMessage( $msg ); + return true; + } + + private function scnInfo( $message ) { + $msg = new xPLMessage( xPLMessage::xplstat ); + $msg->setMessageSchemeIdentifier( 'lighting.scninfo' ); + $msg->addBodyItem( 'network', $message->bodyItem('network') ); + $msg->addBodyItem( 'scene', $message->bodyItem('scene') ); + $msg->setTarget('*'); + $msg->setSource( $this->_thisDevice->deviceName() ); + $msg->addBodyItem( 'status', 'not-found' ); + $this->sendMessage( $msg ); + return true; + } + +} diff --git a/xpl/phpxpl/xplmessage.class.php b/xpl/phpxpl/xplmessage.class.php new file mode 100644 index 00000000..ecfe7c83 --- /dev/null +++ b/xpl/phpxpl/xplmessage.class.php @@ -0,0 +1,144 @@ +_identifier = $identifier; + } + + public function addBodyItem( $key, $value ) { + $this->_body[$key] = $value; + } + + public function addHeadItem( $key, $value ) { + if ($key == 'hop') { + $hop = (int)$value; + } else if ($key == 'source') { + $this->setSource($value); + } else if ($key == 'target') { + $this->setTarget($value); + } + } + + public function bodyItem( $key ) { + if (array_key_exists($key, $this->_body)) { + return $this->_body[$key]; + } + return ''; + } + + public function messageSchemeIdentifier() { + return $this->_msi; + } + + public function source() { + return $this->_source; + } + + public function target() { + return $this->_target; + } + + public function setMessageSchemeIdentifier( $messageSchemeIdentifier ) { + $this->_msi = $messageSchemeIdentifier; + } + + public function setSource( $value ) { + $this->_source = $value; + } + + public function setTarget( $value ) { + $this->_target = $value; + } + + public function __tostring() { + $message = ''; + + switch( $this->_identifier ) { + case self::xplcmnd: + $message .= "xpl-cmnd\n"; + break; + case self::xplstat: + $message .= "xpl-stat\n"; + break; + case self::xpltrig: + $message .= "xpl-trig\n"; + break; + default: + return ""; + } + + $message .= "{\n"; + $message .= sprintf("hop=%s\n", $this->_hop); + $message .= sprintf("source=%s\n", $this->_source); + $message .= sprintf("target=%s\n", $this->_target); + $message .= "}\n"; + $message .= $this->_msi . "\n"; + $message .= "{\n"; + foreach( $this->_body as $key => $value ) { + $message .= sprintf("%s=%s\n", $key, $value); + } + $message .= "}\n"; + + return $message; + } + + public static function createMessageFromString( $message ) { + $lines = explode("\n", $message); + $row = 0; + + $i = 0; + + if ($lines[$row] == 'xpl-cmnd') { + $i = self::xplcmnd; + } else if ($lines[$row] == 'xpl-stat') { + $i = self::xplstat; + } else if ($lines[$row] == 'xpl-trig') { + $i = self::xpltrig; + } else { + return 0; + } + ++$row; + + if ($lines[$row] != '{') { + return 0; + } + ++$row; + + $msg = new xPLMessage($i); + for(; $row < count($lines) && $lines[$row] != '}'; ++$row) { + list($name, $value) = explode( '=', $lines[$row] ); + $msg->addHeadItem( $name, $value ); + } + if ($row >= count($lines)) { + return 0; + } + ++$row; + + $msg->setMessageSchemeIdentifier( $lines[$row] ); + ++$row; + + if ($lines[$row] != '{') { + return 0; + } + ++$row; + + for(; $row < count($lines) && $lines[$row] != '}'; ++$row) { + list($name, $value) = explode( '=', $lines[$row] ); + $msg->addBodyItem( $name, $value ); + } + + return $msg; + } +} diff --git a/xpl/pyxpl/__init__.py b/xpl/pyxpl/__init__.py new file mode 100644 index 00000000..35b42be0 --- /dev/null +++ b/xpl/pyxpl/__init__.py @@ -0,0 +1 @@ +__all__ = ["xplmessage", "xpldevice", "xplinstance"] \ No newline at end of file diff --git a/xpl/pyxpl/xpldevice.py b/xpl/pyxpl/xpldevice.py new file mode 100644 index 00000000..fe5cd016 --- /dev/null +++ b/xpl/pyxpl/xpldevice.py @@ -0,0 +1,22 @@ +########################################################################### +# Copyright (C) 2009 by Magnus Ahlberg +# +# +# Copyright: See COPYING file that comes with this distribution +# +########################################################################### + +class XPLDevice: + """A class to manage and xPL device""" + vendor = "" + device = "" + instance = "" + + def __init__(devicename): + pass + + def __init__(vendor, device): + pass + + def __init__(vendor, device, instance): + pass diff --git a/xpl/pyxpl/xplinstance.py b/xpl/pyxpl/xplinstance.py new file mode 100644 index 00000000..9c0354d9 --- /dev/null +++ b/xpl/pyxpl/xplinstance.py @@ -0,0 +1,47 @@ +########################################################################### +# Copyright (C) 2009 by Magnus Ahlberg +# +# +# Copyright: See COPYING file that comes with this distribution +# +########################################################################### + +from xpldevice import * + +from socket import * + +class XPLInstance: + """Class to handle an xPL session""" + MODE_UNDEFINED, MODE_CLIENT, MODE_DISCONNECTED, MODE_HUB = range(4) + + __thisDevice = XPLDevice() + __devices = () + __mode = MODE_UNDEFINED + + def __init__(self, device): + self.__thisDevice = device + + def __init__(self, vendor, deviceName): + device = XPLDevice(vendor, deviceName) + self.__init__(device) + + def attached(self): + pass + + def devices(self): + return devices + + def operationMode(self): + return operationMode + + def sendMessage(self, message): + pass + + def sendMessage(self, message, device): + pass + + def shutdown(self): + pass + + def bindToPort(self): + pass diff --git a/xpl/pyxpl/xplmessage.py b/xpl/pyxpl/xplmessage.py new file mode 100644 index 00000000..28f96dd5 --- /dev/null +++ b/xpl/pyxpl/xplmessage.py @@ -0,0 +1,56 @@ +########################################################################### +# Copyright (C) 2009 by Magnus Ahlberg +# +# +# Copyright: See COPYING file that comes with this distribution +# +########################################################################### + +class XPLMessage: + """A class for managing xPL messages""" + ID_UNDEFINED, ID_XPLCMND, ID_XPLSTAT, ID_XPLTRIG = range(4) + __body = {} + __hop = 0 + __source = "" + __target = "" + __identifier = ID_UNDEFINED + __identifierString = ("-", "xpl-cmnd", "xpl-stat", "xpl-trig") + __messageSchemaIdentifier = "" + + def __init__(self, identifier, messageSchemaIdentifier): + self.__identifier = identifier + self.__messageSchemaIdentifier = messageSchemaIdentifier + + def addBodyItem(self, key, value): + self.__body[key] = value + + def bodyItem(self, key): + return self.__body[key] + + def createMessageFromString(message): + pass + + def setSource(self, value): + self.__source = value + + def setTarget(self, value): + self.__target = value + + def toString(self): + if self.__identifier == self.ID_UNDEFINED: + return "" + + messageStringList = [] + messageStringList.append(self.__identifierString[self.__identifier] + "\n") + messageStringList.append("{\n") + messageStringList.append("hop=" + str(self.__hop) + "\n") + messageStringList.append("source=" + self.__source + "\n") + messageStringList.append("target=" + self.__target + "\n") + messageStringList.append("}\n") + messageStringList.append(self.__messageSchemaIdentifier + "\n") + messageStringList.append("{\n") + for key, value in self.__body.iteritems(): + messageStringList.append(key + "=" + value + "\n") + messageStringList.append("}\n") + + return "".join(messageStringList) \ No newline at end of file diff --git a/xpl/qtxpl/CMakeLists.txt b/xpl/qtxpl/CMakeLists.txt new file mode 100644 index 00000000..480e3796 --- /dev/null +++ b/xpl/qtxpl/CMakeLists.txt @@ -0,0 +1,43 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(qtxpl) + +FIND_PACKAGE( Qt4 REQUIRED ) +SET(QT_USE_QTNETWORK TRUE) +INCLUDE( ${QT_USE_FILE} ) + +SET( QTXPL_SRCS + xpldevice.cpp + xplinstance.cpp + xplmessage.cpp +) + +SET( QTXPL_HDRS + xpldevice.h +) + +SET( QTXPL_MOC_HDRS + xplinstance.h + xplmessage.h +) + + +QT4_WRAP_CPP( QTXPL_MOC_SRCS ${QTXPL_MOC_HDRS} ) +QT4_AUTOMOC ( ${QTXPL_SRCS} ) + + +SET( QTXPL_LIBRARIES + ${QT_LIBRARIES} +) + +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_NO_DEBUG) + +ADD_LIBRARY("qtxpl" SHARED + ${QTXPL_SRCS} + ${QTXPL_HDRS} + ${QTXPL_MOC_HDRS} + ${QTXPL_MOC_SRCS} +) + +TARGET_LINK_LIBRARIES( "qtxpl" ${QTXPL_LIBRARIES} ) + diff --git a/xpl/qtxpl/main.cpp b/xpl/qtxpl/main.cpp new file mode 100644 index 00000000..d50652dd --- /dev/null +++ b/xpl/qtxpl/main.cpp @@ -0,0 +1,12 @@ +#include + +#include "xplinstance.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + /*xPLInstance *instance = */new xPLInstance("telldus", "center"); + + return a.exec(); +} diff --git a/xpl/qtxpl/qtxpl.pro b/xpl/qtxpl/qtxpl.pro new file mode 100644 index 00000000..89bb1f4e --- /dev/null +++ b/xpl/qtxpl/qtxpl.pro @@ -0,0 +1,15 @@ +# ------------------------------------------------- +# Project created by QtCreator 2009-03-05T16:12:24 +# ------------------------------------------------- +QT += network +QT -= gui +TARGET = qtxpl +CONFIG += console +CONFIG -= app_bundle +TEMPLATE = lib +SOURCES += xpldevice.cpp \ + xplinstance.cpp \ + xplmessage.cpp +HEADERS += xpldevice.h \ + xplinstance.h \ + xplmessage.h diff --git a/xpl/qtxpl/xpldevice.cpp b/xpl/qtxpl/xpldevice.cpp new file mode 100644 index 00000000..04cee0da --- /dev/null +++ b/xpl/qtxpl/xpldevice.cpp @@ -0,0 +1,105 @@ +#include "xpldevice.h" + +#include +#include +#include + +const int DEFAULT_HBEAT_INTERVAL = 5; + +class xPLDevicePrivate { +public: + QString vendor, device, instance; + QDateTime lastHeartBeat; + int port, heartBeatInterval; + QHostAddress address; +}; + +xPLDevice::xPLDevice( const xPLDevice &other ) + : d( new xPLDevicePrivate( *other.d )) +{ + //do nothing +} + +xPLDevice& xPLDevice::operator=( xPLDevice other ) { + std::swap( this->d, other.d ); + return *this; +} + +xPLDevice::xPLDevice( const QString &deviceName ) + :d(new xPLDevicePrivate) +{ + d->port = 0; + d->heartBeatInterval = DEFAULT_HBEAT_INTERVAL; + QString name = deviceName.section('.', 0, 0); + d->vendor = name.section('-', 0, 0); + d->device = name.section('-', 1, 1); + d->instance = deviceName.section('.', 1); +} + +xPLDevice::xPLDevice( const QString &vendor, const QString &device ) + :d(new xPLDevicePrivate) +{ + d->vendor = vendor; + d->device = device; + d->instance = ""; + d->port = 0; + d->heartBeatInterval = DEFAULT_HBEAT_INTERVAL; + + //Seed the random number generator + srand( (unsigned int)time( NULL ) ); + + //Generate an instance + int randomNumber = rand() % 9999 + 1; //Generate ranom number between 1-9999 + d->instance = QString("default%1").arg(randomNumber); +} + +xPLDevice::xPLDevice( const QString &vendor, const QString &device, const QString &instance ) + :d(new xPLDevicePrivate) +{ + d->vendor = vendor; + d->device = device; + d->instance = instance; + d->port = 0; + d->heartBeatInterval = DEFAULT_HBEAT_INTERVAL; + +} + +xPLDevice::~xPLDevice() { + delete d; +} + +QHostAddress xPLDevice::address() const { + return d->address; +} + +int xPLDevice::heartBeatInterval() const { + return d->heartBeatInterval; +} + +QString xPLDevice::deviceName() const { + return QString("%1-%2.%3").arg(d->vendor).arg(d->device).arg(d->instance); +} + +QDateTime xPLDevice::lastHeartBeat() const { + return d->lastHeartBeat; +} + +int xPLDevice::port() const { + return d->port; +} + +void xPLDevice::setAddress( const QHostAddress &address ) { + d->address = address; +} + +void xPLDevice::setHeartBeatInterval( int minutes ) { + d->heartBeatInterval = minutes; +} + +void xPLDevice::setPort( int p ) { + d->port = p; +} + +void xPLDevice::setLastHeartBeat( const QDateTime ×tamp ) { + d->lastHeartBeat = timestamp; +} diff --git a/xpl/qtxpl/xpldevice.h b/xpl/qtxpl/xpldevice.h new file mode 100644 index 00000000..3c1d2bae --- /dev/null +++ b/xpl/qtxpl/xpldevice.h @@ -0,0 +1,38 @@ +#ifndef XPLDEVICE_H +#define XPLDEVICE_H + +#include "xplmessage.h" +#include +#include + +class xPLDevicePrivate; + +class QTXPL_EXPORT xPLDevice +{ +public: + xPLDevice( const xPLDevice & ); //Copy constructor + xPLDevice& operator=( xPLDevice ); //Copy assignment operator + + xPLDevice( const QString &deviceName ); + xPLDevice( const QString &vendor, const QString &device ); + xPLDevice( const QString &vendor, const QString &device, const QString &instance ); + + ~xPLDevice(); + + QString deviceName() const; + + QDateTime lastHeartBeat() const; + + QHostAddress address() const; + int heartBeatInterval() const; + int port() const; + void setAddress( const QHostAddress &address ); + void setHeartBeatInterval( int minutes ); + void setPort( int port ); + void setLastHeartBeat( const QDateTime ×tamp ); + +private: + xPLDevicePrivate *d; +}; + +#endif // XPLDEVICE_H diff --git a/xpl/qtxpl/xplinstance.cpp b/xpl/qtxpl/xplinstance.cpp new file mode 100644 index 00000000..5d2db3a9 --- /dev/null +++ b/xpl/qtxpl/xplinstance.cpp @@ -0,0 +1,226 @@ +#include "xplinstance.h" +#include "xplmessage.h" + +#include +#include +#include + +#include +#include + +class xPLInstancePrivate { +public: + xPLDevice *thisDevice; + QLinkedList devices; + QUdpSocket *socket; + xPLInstance::OperationMode mode; + QHostAddress address; + bool isAttatched; + QTimer *timer; +}; + +xPLInstance::xPLInstance( const xPLDevice &device, QObject *parent ) + :QObject(parent) +{ + d = new xPLInstancePrivate; + d->thisDevice = new xPLDevice(device); + d->mode = Disconnected; + d->timer = new QTimer(this); + this->init(); +} + +xPLInstance::xPLInstance( const QString &vendor, const QString &device, QObject *parent ) + :QObject(parent) +{ + d = new xPLInstancePrivate; + d->thisDevice = new xPLDevice(vendor, device); + d->mode = Disconnected; + d->timer = new QTimer(this); + this->init(); +} + +xPLInstance::~xPLInstance() { + delete d->thisDevice; + delete d; +} + +void xPLInstance::init() { + foreach(QHostAddress address, QNetworkInterface::allAddresses()) { + if (address.protocol() == QAbstractSocket::IPv4Protocol && address != QHostAddress::LocalHost) { + d->address = address; + break; + } + } + d->isAttatched = false; + d->socket = new QUdpSocket(this); + d->thisDevice->setPort(this->bindToPort()); + if (d->thisDevice->port() == 0) { + return; + } + d->timer->setInterval( 3000 ); + connect(d->socket, SIGNAL(readyRead()), this, SLOT(processPendingDatagrams())); + connect(d->timer, SIGNAL(timeout()), this, SLOT(poll())); + this->sendHeartbeat(); + d->timer->start(); +} + +bool xPLInstance::attatched() const { + return this->d->isAttatched; +} + +int xPLInstance::bindToPort() { + //Hub-mode not supported + /*if (d->socket->bind( XPL_PORT )) { + d->mode = Hub; + qDebug("Bind succeded as hub"); + return XPL_PORT; + }*/ + for (int port = 49152; port <= 65535; ++port) { + if (d->socket->bind( port, QUdpSocket::DontShareAddress )) { + d->mode = Client; + qDebug() << "Bind succeded as client on" << port; + return port; + } + } + qDebug("Bind failed"); + return 0; +} + +xPLInstance::OperationMode xPLInstance::operationMode() const { + return d->mode; +} + +void xPLInstance::processPendingDatagrams() { + while (d->socket->hasPendingDatagrams()) { + QByteArray datagram; + datagram.resize(d->socket->pendingDatagramSize()); + d->socket->readDatagram(datagram.data(), datagram.size()); + xPLMessage *message = xPLMessage::createMessageFromString( datagram.data() ); + if (message) { + processMessage( *message ); + delete message; + } + } +} + +void xPLInstance::poll() { + if (!attatched()) { + sendHeartbeat(); + return; + } + if (d->thisDevice->lastHeartBeat().secsTo( QDateTime::currentDateTime() ) >= d->thisDevice->heartBeatInterval() * 60) { + sendHeartbeat(); + } + //Loop all devices to see if they have timed out + for( QLinkedList::iterator it = d->devices.begin(); it != d->devices.end(); ) { + if ((*it).lastHeartBeat().secsTo( QDateTime::currentDateTime() ) >= (*it).heartBeatInterval() * 60 * 2) { + qDebug() << "Device removed (timeout):" << (*it).deviceName(); + it = d->devices.erase( it ); + continue; + } + ++it; + } +} + +void xPLInstance::sendMessage( const xPLMessage &msg ) const { + xPLMessage message(msg); //Copy so we don't have const + message.setSource(d->thisDevice->deviceName()); + QByteArray datagram = message.toString().toAscii(); + d->socket->writeDatagram(datagram.data(), datagram.size(), QHostAddress::Broadcast, XPL_PORT); +} + +void xPLInstance::sendMessage( xPLMessage * message ) const { + this->sendMessage(*message); +} + +void xPLInstance::sendMessage( const xPLMessage &message, const xPLDevice &device ) const { + QByteArray datagram = message.toString().toAscii(); + d->socket->writeDatagram(datagram.data(), datagram.size(), device.address(), device.port()); +} + +void xPLInstance::processHeartBeat( const xPLMessage &message ) { + if (message.messageSchemeIdentifier() == "hbeat.request") { + sendHeartbeat(); + return; + } + for( QLinkedList::iterator it = d->devices.begin(); it != d->devices.end(); ++it ) { + if ( (*it).deviceName() == message.source() ) { + if (message.messageSchemeIdentifier() == "hbeat.end") { + qDebug() << "Device removed:" << message.source(); + d->devices.erase( it ); + return; + } else { + (*it).setLastHeartBeat( QDateTime::currentDateTime() ); + (*it).setHeartBeatInterval( message.bodyItem( "interval" ).toInt() ); + } + return; + } + } + if (!message.messageSchemeIdentifier().endsWith("app") && !message.messageSchemeIdentifier().endsWith("basic")) { + return; + } + qDebug() << "New device:" << message.source(); + xPLDevice device( message.source() ); + device.setHeartBeatInterval( message.bodyItem("interval").toInt() ); + device.setLastHeartBeat( QDateTime::currentDateTime() ); + if (message.messageSchemeIdentifier() == "hbeat.app") { + device.setAddress( QHostAddress(message.bodyItem("remote-ip")) ); + device.setPort( message.bodyItem("port").toInt() ); + } + d->devices.append( device ); +} + +void xPLInstance::processMessage( const xPLMessage &message ) { + if (!attatched() && message.messageSchemeIdentifier() == "hbeat.app" && message.source() == d->thisDevice->deviceName()) { + //Our own echo + setAttatched( true ); + return; + } + if (message.source() == d->thisDevice->deviceName()) { + //Ignore messages from ourselves + return; + } + if (message.messageSchemeIdentifier().startsWith("hbeat") || message.messageSchemeIdentifier().startsWith("config")) { + processHeartBeat( message ); + } + if (d->mode == xPLInstance::Hub) { + //Reply the message to all clients + for( QLinkedList::iterator it = d->devices.begin(); it != d->devices.end(); ++it ) { + sendMessage(message, *it); + } + } + if (message.target() != d->thisDevice->deviceName() && message.target() != "*") { + //Message not for us + return; + } + xPLMessage newMsg(message); + emit messageReceived(&newMsg); +} + +void xPLInstance::sendHeartbeat() { + xPLMessage message( xPLMessage::xplstat ); + message.setMessageSchemeIdentifier( "hbeat.app" ); + message.setTarget("*"); + message.setSource( d->thisDevice->deviceName() ); + message.addBodyItem( "interval", QString::number(d->thisDevice->heartBeatInterval()) ); + message.addBodyItem( "port", QString::number(d->thisDevice->port()) ); + message.addBodyItem( "remote-ip", d->address.toString() ); + sendMessage( message ); + d->thisDevice->setLastHeartBeat( QDateTime::currentDateTime() ); +} + +void xPLInstance::setAttatched( bool attatched ) { + d->isAttatched = attatched; + if (d->isAttatched) { + qDebug() << "Attached to network!"; + d->timer->setInterval( 60000 ); //Once a minute + + xPLMessage message( xPLMessage::xplcmnd ); + message.setTarget( "*" ); + message.setSource( d->thisDevice->deviceName() ); + message.setMessageSchemeIdentifier( "hbeat.request" ); + message.addBodyItem("command", "request"); + sendMessage( message ); + emit attachedToNetwork(); + } +} diff --git a/xpl/qtxpl/xplinstance.h b/xpl/qtxpl/xplinstance.h new file mode 100644 index 00000000..61ee990a --- /dev/null +++ b/xpl/qtxpl/xplinstance.h @@ -0,0 +1,55 @@ +#ifndef XPLINSTANCE_H +#define XPLINSTANCE_H + +#include +#include "xpldevice.h" +#include "xplmessage.h" + +const int XPL_PORT = 3865; + +class QTimer; +class xPLInstancePrivate; + +class QTXPL_EXPORT xPLInstance : public QObject +{ + Q_OBJECT + + Q_ENUMS( OperationMode ); + + Q_PROPERTY( OperationMode operationMode READ operationMode ); +public: + enum OperationMode { Client, Disconnected, Hub }; + + xPLInstance( const xPLDevice &device, QObject *parent = 0 ); + xPLInstance( const QString &vendor, const QString &device, QObject *parent = 0 ); + ~xPLInstance(); + +public slots: + bool attatched() const; + + OperationMode operationMode() const; + + void sendMessage( const xPLMessage &message ) const; + void sendMessage( xPLMessage * message ) const; + void sendMessage( const xPLMessage &message, const xPLDevice &device ) const; + +signals: + void messageReceived(xPLMessage *message); + void attachedToNetwork(); + +private slots: + void processPendingDatagrams(); + void sendHeartbeat(); + void poll(); + +private: + void processHeartBeat( const xPLMessage &message ); + void processMessage( const xPLMessage &message ); + void init(); + int bindToPort(); + void setAttatched( bool attatched ); + + xPLInstancePrivate *d; +}; + +#endif // XPLINSTANCE_H diff --git a/xpl/qtxpl/xplmessage.cpp b/xpl/qtxpl/xplmessage.cpp new file mode 100644 index 00000000..ced743cf --- /dev/null +++ b/xpl/qtxpl/xplmessage.cpp @@ -0,0 +1,188 @@ +#include "xplmessage.h" + +#include +#include +#include + +class xPLMessage::xPLMessagePrivate { +public: + xPLMessage::Identifier identifier; + int hop; + QString source, target, msi; + QMap headExtra, body; +}; + +xPLMessage::xPLMessage( const xPLMessage &other ) + : QObject(), + d( new xPLMessagePrivate( *other.d )) +{ + //do nothing +} + +xPLMessage& xPLMessage::operator=( xPLMessage other ) { + std::swap( this->d, other.d ); + return *this; +} + + +xPLMessage::xPLMessage(Identifier i) + :QObject(), + d(new xPLMessagePrivate) +{ + d->hop = 1; + d->identifier = i; + d->target = "*"; +} + +xPLMessage::xPLMessage() + :QObject(), + d(new xPLMessagePrivate) +{ + + d->hop = 1; + d->identifier = xplcmnd; + d->target = "*"; +} + +xPLMessage::~xPLMessage() { + delete d; +} + + +void xPLMessage::addBodyItem( const QString &key, const QString &value ) { + d->body[key] = value; +} + +void xPLMessage::addHeadItem( const QString &key, const QString &value ) { + if (key == "hop") { + d->hop = value.toInt(); + } else if (key == "source") { + setSource(value); + } else if (key == "target") { + setTarget(value); + } else { + d->headExtra[key] = value; + } +} + +QString xPLMessage::bodyItem( const QString &key ) const { + if (d->body.contains(key)) { + return d->body[key]; + } + return ""; +} + +QString xPLMessage::headItem( const QString &key ) const { + if (d->headExtra.contains(key)) { + return d->headExtra[key]; + } + return ""; +} + +QString xPLMessage::messageSchemeIdentifier() const { + return d->msi; +} + +QString xPLMessage::source() const { + return d->source; +} + +QString xPLMessage::target() const { + return d->target; +} + +void xPLMessage::setMessageSchemeIdentifier( const QString &messageSchemeIdentifier ) { + d->msi = messageSchemeIdentifier; +} + +void xPLMessage::setSource( const QString &value ) { + d->source = value; +} + +void xPLMessage::setTarget( const QString &value ) { + d->target = value; +} + +QString xPLMessage::toString() const { + QString message; + + switch( d->identifier ) { + case xplcmnd: + message += "xpl-cmnd\n"; + break; + case xplstat: + message += "xpl-stat\n"; + break; + case xpltrig: + message += "xpl-trig\n"; + break; + default: + return ""; + } + + message += "{\n"; + message += QString("hop=%1\n").arg(d->hop); + message += QString("source=%1\n").arg(d->source); + message += QString("target=%1\n").arg(d->target); + for( QMap::const_iterator it = d->headExtra.begin(); it != d->headExtra.end(); ++it ) { + message += QString("%1=%2\n").arg(it.key()).arg(it.value()); + } + message += "}\n"; + message += d->msi + "\n"; + message += "{\n"; + for( QMap::const_iterator it = d->body.begin(); it != d->body.end(); ++it ) { + message += QString("%1=%2\n").arg(it.key()).arg(it.value()); + } + message += "}\n"; + + return message; +} + +xPLMessage *xPLMessage::createMessageFromString( const QString &message ) { + QStringList lines = message.split('\n', QString::SkipEmptyParts); + QStringList::const_iterator it = lines.begin(); + + Identifier i; + + if (*it == "xpl-cmnd") { + i = xplcmnd; + } else if (*it == "xpl-stat") { + i = xplstat; + } else if (*it == "xpl-trig") { + i = xpltrig; + } else { + return 0; + } + ++it; + + if (*it != "{") { + return 0; + } + ++it; + + xPLMessage *msg = new xPLMessage(i); + for(; it != lines.end() && *it != "}"; ++it) { + msg->addHeadItem( (*it).section('=', 0, 0), (*it).section('=', 1) ); + } + if (it == lines.end()) { + delete msg; + return 0; + } + ++it; + + msg->setMessageSchemeIdentifier( *it ); + ++it; + + if (*it != "{") { + delete msg; + return 0; + } + ++it; + + for(; it != lines.end() && *it != "}"; ++it) { + msg->addBodyItem( (*it).section('=', 0, 0), (*it).section('=', 1) ); + } + + return msg; +} + diff --git a/xpl/qtxpl/xplmessage.h b/xpl/qtxpl/xplmessage.h new file mode 100644 index 00000000..916d3b0a --- /dev/null +++ b/xpl/qtxpl/xplmessage.h @@ -0,0 +1,57 @@ +#ifndef XPLMESSAGE_H +#define XPLMESSAGE_H + +#ifdef _WINDOWS + #ifdef qtxpl_EXPORTS + #define QTXPL_EXPORT __declspec(dllexport) + #else + #define QTXPL_EXPORT __declspec(dllimport) + #endif +#else + #define QTXPL_EXPORT +#endif + +#include +#include + +class QTXPL_EXPORT xPLMessage : public QObject +{ + Q_OBJECT + + Q_ENUMS( Identifier ); +public: + enum Identifier { xplcmnd, xplstat, xpltrig }; + + xPLMessage( const xPLMessage & ); //Copy constructor + xPLMessage& operator=( xPLMessage ); //Copy assignment operator + + xPLMessage(Identifier identifier); + xPLMessage(); + virtual ~xPLMessage(); + + static xPLMessage *createMessageFromString( const QString &message ); + +public slots: + void addBodyItem( const QString &key, const QString &value ); + void addHeadItem( const QString &key, const QString &value ); + + QString bodyItem( const QString &key ) const; + QString headItem( const QString &key ) const; + QString messageSchemeIdentifier() const; + QString source() const; + QString target() const; + + void setMessageSchemeIdentifier( const QString &msi ); + void setSource( const QString &value ); + void setTarget( const QString &value ); + + QString toString() const; + +private: + class xPLMessagePrivate; + xPLMessagePrivate *d; +}; + +Q_DECLARE_METATYPE(xPLMessage*) + +#endif // XPLMESSAGE_H diff --git a/xpl/telldus-core-xpl/Makefile b/xpl/telldus-core-xpl/Makefile new file mode 100644 index 00000000..00b6c1b0 --- /dev/null +++ b/xpl/telldus-core-xpl/Makefile @@ -0,0 +1,37 @@ +# +# Makefile for xPLLib +# + +# +# For LINUX, use the following +CCOPTS = -g -DLINUX -pedantic -Wall +LIBS = -g -lm -lxPL -ltelldus-core + +LDOPTS = -O +CC = cc $(CCOPTS) +LD = cc $(LDOPTS) + +CMD_LIST = xPL_TelldusCore + +.c.o: + $(CC) -c $< + +.o: + $(LD) -o $@ $< $(LIBS) + +.c: + $(CC) -c $< + $(LD) -o $@ $< $(LIBS) + + +all: ${CMD_LIST} + +clean: + rm -f *.o *.a core ${CMD_LIST} + +rebuild: clean all + + + + + diff --git a/xpl/telldus-core-xpl/xPL_TelldusCore.c b/xpl/telldus-core-xpl/xPL_TelldusCore.c new file mode 100644 index 00000000..b4c08620 --- /dev/null +++ b/xpl/telldus-core-xpl/xPL_TelldusCore.c @@ -0,0 +1,399 @@ + + +#include +#include +#include +#include +#include +#include + +#define TELLDUS_VERSION "1.0" +#define INSTANCE_MAX 16 + +static xPL_ServicePtr telldusService = NULL; +static Bool daemonMode = TRUE; +char hostname[INSTANCE_MAX]; + +void sendDevInfo(xPL_MessagePtr msg); +void sendDevList(xPL_MessagePtr msg); +void sendGatewayInfo(); +void sendNetInfo(xPL_MessagePtr msg); +void sendNetList(); + +void lightingCommandHandler(xPL_ServicePtr theService, xPL_MessagePtr theMessage, xPL_ObjectPtr userValue) { + Bool found = FALSE; + int deviceCount = 0, deviceId = 0, i, level = 0; + + if (!xPL_doesMessageNamedValueExist(theMessage, "command")) { + return; + } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "command"), "goto") != 0) { + return; + } + + if (!xPL_doesMessageNamedValueExist(theMessage, "network")) { + return; + } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "network"), "1") != 0) { + return; + } + + if (!xPL_doesMessageNamedValueExist(theMessage, "device")) { + return; + } else { + /* Loop the devices to see it realy exists */ + deviceCount = tdGetNumberOfDevices(); + + xPL_strToInt(xPL_getMessageNamedValue(theMessage, "device"), &deviceId); + for( i = 0; i < deviceCount; ++i ) { + if (tdGetDeviceId(i) == deviceId) { + found = TRUE; + break; + } + } + if (found == FALSE) { + return; + } + } + + if (!xPL_doesMessageNamedValueExist(theMessage, "level")) { + return; + } else { + xPL_strToInt(xPL_getMessageNamedValue(theMessage, "level"), &level); + if (level < 0 || level > 100) { + return; + } + level = (float)level * 255.0 / 100.0; + } + + if (level > 0 && level < 255) { + /* See if the device supports dim */ + if (!(tdMethods(deviceId, TELLSTICK_DIM) & TELLSTICK_DIM)) { + /* Non dimmable device was dimmed */ + return; + } + tdDim(deviceId, (unsigned char)level); + } else if (level == 255) { + /* See if the device supports dim */ + if (!(tdMethods(deviceId, TELLSTICK_TURNON) & TELLSTICK_TURNON)) { + /* Non dimmable device was dimmed */ + return; + } + tdTurnOn(deviceId); + } else if (level == 0) { + /* See if the device supports dim */ + if (!(tdMethods(deviceId, TELLSTICK_TURNOFF) & TELLSTICK_TURNOFF)) { + /* Non dimmable device was dimmed */ + return; + } + tdTurnOff(deviceId); + } + +} + +void lightingRequestHandler(xPL_ServicePtr theService, xPL_MessagePtr theMessage, xPL_ObjectPtr userValue) { + + if (!xPL_doesMessageNamedValueExist(theMessage, "request")) { + return; + } + + if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "devinfo") == 0) { + sendDevInfo(theMessage); + } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "devlist") == 0) { + sendDevList(theMessage); + } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "gateinfo") == 0) { + sendGatewayInfo(); + } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "netinfo") == 0) { + sendNetInfo(theMessage); + } else if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(theMessage, "request"), "netlist") == 0) { + sendNetList(); + } else { +/* fprintf(stdout, "Request: %s\n", xPL_getMessageNamedValue(theMessage, "request")); */ + } +} + +void shutdownHandler(int onSignal) { + xPL_setServiceEnabled(telldusService, FALSE); + xPL_releaseService(telldusService); + xPL_shutdown(); + exit(0); +} + +void sendDevInfo(xPL_MessagePtr msg) { + xPL_MessagePtr message = NULL; + Bool found = FALSE, deviceCount = tdGetNumberOfDevices(); + int deviceId = 0, methods = 0, i = 0, lastSentCommand, level = 0; + char *name, buffer[12], *value; + + xPL_strToInt(xPL_getMessageNamedValue(msg, "device"), &deviceId); + for( i = 0; i < deviceCount; ++i ) { + if (tdGetDeviceId(i) == deviceId) { + found = TRUE; + break; + } + } + + message = xPL_createBroadcastMessage(telldusService, xPL_MESSAGE_STATUS); + xPL_setSchema(message, "lighting", "devinfo"); + + xPL_setMessageNamedValue(message, "network", xPL_getMessageNamedValue(msg, "network")); + xPL_setMessageNamedValue(message, "device", xPL_getMessageNamedValue(msg, "device")); + + if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(msg, "network"), "1") == 0 && found == TRUE) { + lastSentCommand = tdLastSentCommand(deviceId, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); + if (lastSentCommand == TELLSTICK_TURNON) { + level = 100; + } else if (lastSentCommand == TELLSTICK_DIM) { + value = tdLastSentValue(deviceId); + level = atoi(value); + free(value); + level = round((float)level / 255.0 * 100.0); + if (level > 100) { + level = 100; + } else if (level < 0) { + level = 0; + } + } else { + level = 0; + } + methods = tdMethods(deviceId, TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM); + name = tdGetName(deviceId); + sprintf(buffer, "1,%s,0,%i", (methods & TELLSTICK_DIM ? "true" : "false"), level); + xPL_setMessageNamedValue(message, "status", "ok"); + xPL_setMessageNamedValue(message, "name", name ); + xPL_setMessageNamedValue(message, "report-on-manual", "false" ); + xPL_setMessageNamedValue(message, "channel-count", "1" ); + xPL_setMessageNamedValue(message, "primary-channel", "1" ); + xPL_setMessageNamedValue(message, "channel", buffer ); + xPL_setMessageNamedValue(message, "scene-count", "0" ); + + free(name); + } else { + xPL_setMessageNamedValue(message, "status", "not-found"); + } + + xPL_sendMessage(message); + + xPL_releaseMessage(message); +} + +void sendDevList(xPL_MessagePtr msg) { + int deviceCount = 0, i; + char deviceList[128]; + xPL_MessagePtr message = NULL; + + message = xPL_createBroadcastMessage(telldusService, xPL_MESSAGE_STATUS); + xPL_setSchema(message, "lighting", "devlist"); + + xPL_setMessageNamedValue(message, "network", xPL_getMessageNamedValue(msg, "network")); + + if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(msg, "network"), "1") == 0) { + xPL_setMessageNamedValue(message, "status", "ok"); + deviceCount = tdGetNumberOfDevices(); + for( i = 0; i < deviceCount; ++i ) { + if (i == 0) { /* First */ + strcpy(deviceList, xPL_intToStr(tdGetDeviceId(i))); + } else { + strcat(deviceList, ","); + strcat(deviceList, xPL_intToStr(tdGetDeviceId(i))); + } + } + + xPL_setMessageNamedValue(message, "device-count", xPL_intToStr(deviceCount) ); + xPL_setMessageNamedValue(message, "device", deviceList ); + } else { + xPL_setMessageNamedValue(message, "status", "not-found"); + } + + xPL_sendMessage(message); + + xPL_releaseMessage(message); +} + +void sendGatewayInfo() { + xPL_MessagePtr message = NULL; + + message = xPL_createBroadcastMessage(telldusService, xPL_MESSAGE_STATUS); + xPL_setSchema(message, "lighting", "gateinfo"); + + xPL_setMessageNamedValue(message, "status", "ok"); + xPL_setMessageNamedValue(message, "protocol", "TELLDUS"); + xPL_setMessageNamedValue(message, "description", "xPL to Telldus TellStick gateway"); + xPL_setMessageNamedValue(message, "version", TELLDUS_VERSION); + xPL_setMessageNamedValue(message, "author", "Telldus Technologies AB"); + xPL_setMessageNamedValue(message, "info-url", "http://www.telldus.se"); + xPL_setMessageNamedValue(message, "net-count", "1"); + xPL_setMessageNamedValue(message, "preferred-net", "1"); + xPL_setMessageNamedValue(message, "scenes-ok", "false"); + xPL_setMessageNamedValue(message, "channels-ok", "false"); + xPL_setMessageNamedValue(message, "fade-rate-ok", "false"); + + /* Broadcast the message */ + xPL_sendMessage(message); + + xPL_releaseMessage(message); +} + +void sendNetInfo(xPL_MessagePtr msg) { + xPL_MessagePtr message = NULL; + + message = xPL_createBroadcastMessage(telldusService, xPL_MESSAGE_STATUS); + xPL_setSchema(message, "lighting", "netinfo"); + + xPL_setMessageNamedValue(message, "network", xPL_getMessageNamedValue(msg, "network")); + + if (xPL_strcmpIgnoreCase(xPL_getMessageNamedValue(msg, "network"), "1") == 0) { + xPL_setMessageNamedValue(message, "status", "ok"); + xPL_setMessageNamedValue(message, "name", hostname ); + xPL_setMessageNamedValue(message, "device-count", xPL_intToStr(tdGetNumberOfDevices()) ); + xPL_setMessageNamedValue(message, "scene-count", "0" ); + } else { + xPL_setMessageNamedValue(message, "status", "not-found"); + } + + xPL_sendMessage(message); + + xPL_releaseMessage(message); +} + +void sendNetList() { + xPL_MessagePtr message = NULL; + + message = xPL_createBroadcastMessage(telldusService, xPL_MESSAGE_STATUS); + xPL_setSchema(message, "lighting", "netlist"); + + xPL_setMessageNamedValue(message, "status", "ok"); + xPL_setMessageNamedValue(message, "network", "1"); + + /* Broadcast the message */ + xPL_sendMessage(message); + + xPL_releaseMessage(message); +} + +void sendGatewayReadyMessage() { + xPL_MessagePtr gatewayReadyMessage = NULL; + /* Create a message to send */ + gatewayReadyMessage = xPL_createBroadcastMessage(telldusService, xPL_MESSAGE_TRIGGER); + xPL_setSchema(gatewayReadyMessage, "lighting", "gateway"); + + /* Install the value and send the message */ + xPL_setMessageNamedValue(gatewayReadyMessage, "report", "gateway-ready"); + + /* Broadcast the message */ + xPL_sendMessage(gatewayReadyMessage); + + xPL_releaseMessage(gatewayReadyMessage); +} + +/* parseCmdLine will handles command line switches. Valid switches are: */ +/* -interface x - set interface to use */ +/* -xpldebug - set debugging and enable xPL debugging */ +/* -nodaemon - Dosn't disconnect from the console */ +static Bool parseCmdLine( int *argc, char *argv[]) { + int swptr; + int newcnt = 0; + + /* Handle each item of the command line. If it starts with a '-', then */ + /* process it as a switch. If not, then copy it to a new position in */ + /* the argv list and up the new parm counter. */ + for(swptr = 0; swptr < *argc; swptr++) { + /* If it doesn't begin with a '-', it's not a switch. */ + if (argv[swptr][0] != '-') { + if (swptr != newcnt) argv[++newcnt] = argv[swptr]; + } else { + /* Check for daemon mode */ + if (!strcmp(argv[swptr],"-nodaemon")) { + daemonMode = FALSE; + continue; + } + + /* Anything left is unknown */ + fprintf(stderr, "Unknown switch `%s'", argv[swptr] ); + return FALSE; + } + } + + /* Set in place the new argument count and exit */ + *argc = newcnt + 1; + return TRUE; +} + +/* Print command usage info out */ +void printUsage(String ourName) { + fprintf(stderr, "%s - Telldus TellStick xPL interface\n", ourName); + fprintf(stderr, "Copyright (c) 2009, Telldus Technologies AB\n\n"); + fprintf(stderr, "Usage: %s [-xpldebug] [-nodaemon] [-ip x] [-interface x]\n", ourName); + fprintf(stderr, " -xpldebug -- enable xPLLib debugging messagaes\n"); + fprintf(stderr, " -nodaemon -- don't detach -- run from the console\n"); + fprintf(stderr, " -interface x -- Use interface named x (i.e. eth0) as network interface\n"); + fprintf(stderr, " -ip x -- Bind to specified IP address for xPL\n"); +} + +void startServer() { + /* Initialze lighting service */ + + /* Create a service for us */ + if (gethostname(hostname, INSTANCE_MAX) != 0) { + fprintf(stderr, "Unable to retrieve the hostname"); + exit(1); + } + telldusService = xPL_createService("telldus", "core", hostname); + xPL_setServiceVersion(telldusService, TELLDUS_VERSION); + + /* Add a responder */ + xPL_addServiceListener(telldusService, lightingRequestHandler, xPL_MESSAGE_COMMAND, "lighting", "request", NULL); + xPL_addServiceListener(telldusService, lightingCommandHandler, xPL_MESSAGE_COMMAND, "lighting", "basic", NULL); + + /* Install signal traps for proper shutdown */ + signal(SIGTERM, shutdownHandler); + signal(SIGINT, shutdownHandler); + + /* Enable the service */ + xPL_setServiceEnabled(telldusService, TRUE); + sendGatewayReadyMessage(); + + for (;;) { + /* Let XPL run */ + xPL_processMessages(-1); + } +} + +int main(int argc, String argv[]) { + + /* Parse command line parms */ + if (!xPL_parseCommonArgs(&argc, argv, FALSE)) { + exit(1); + } + + /* Start xPL up */ + if (!xPL_initialize(xPL_getParsedConnectionType())) { + fprintf(stderr, "Unable to start xPL"); + exit(1); + } + + /* Parse Hub command arguments */ + if (!parseCmdLine(&argc, argv)) { + printUsage(argv[0]); + exit(1); + } + + if (daemonMode) { + switch (fork()) { + case 0: /* child */ + /* No io in child mode */ + close(fileno(stdin)); + close(fileno(stdout)); + close(fileno(stderr)); + setpgrp(); + + startServer(); + break; + case -1: /* error */ + fprintf(stderr, "Unable to spawn daemon, %s (%d)\n", strerror(errno), errno); + exit(1); + } + } else { + startServer(); + } + return 0; +} + From 72b31cc86eeeef18f1371a3067b6e8a5ca21abfc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 1 Jun 2012 12:33:03 +0200 Subject: [PATCH 1994/2215] Add headers for ftd2xx, needed at least in Windows --- telldus-gui/Plugins/Controllers/ftd2xx.h | 7 + .../Plugins/Controllers/osx/WinTypes.h | 87 ++ telldus-gui/Plugins/Controllers/osx/ftd2xx.h | 1008 +++++++++++++++++ telldus-gui/Plugins/Controllers/win/ftd2xx.h | 963 ++++++++++++++++ 4 files changed, 2065 insertions(+) create mode 100644 telldus-gui/Plugins/Controllers/ftd2xx.h create mode 100644 telldus-gui/Plugins/Controllers/osx/WinTypes.h create mode 100644 telldus-gui/Plugins/Controllers/osx/ftd2xx.h create mode 100644 telldus-gui/Plugins/Controllers/win/ftd2xx.h diff --git a/telldus-gui/Plugins/Controllers/ftd2xx.h b/telldus-gui/Plugins/Controllers/ftd2xx.h new file mode 100644 index 00000000..344e1605 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/ftd2xx.h @@ -0,0 +1,7 @@ +#ifdef _WINDOWS + #include + #include "win\ftd2xx.h" +#else + #include "osx/WinTypes.h" + #include "osx/ftd2xx.h" +#endif diff --git a/telldus-gui/Plugins/Controllers/osx/WinTypes.h b/telldus-gui/Plugins/Controllers/osx/WinTypes.h new file mode 100644 index 00000000..e8b5b090 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/osx/WinTypes.h @@ -0,0 +1,87 @@ +#ifndef __WINDOWS_TYPES__ +#define __WINDOWS_TYPES__ + +#define MAX_NUM_DEVICES 50 +#include + +typedef unsigned int DWORD; +typedef unsigned int ULONG; +typedef unsigned short USHORT; +typedef unsigned short SHORT; +typedef unsigned char UCHAR; +typedef unsigned short WORD; +typedef unsigned char BYTE; +typedef BYTE *LPBYTE; +typedef unsigned int BOOL; +typedef unsigned char BOOLEAN; +typedef unsigned char CHAR; +typedef BOOL *LPBOOL; +typedef UCHAR *PUCHAR; +typedef const char *LPCSTR; +typedef char *PCHAR; +typedef void *PVOID; +typedef void *HANDLE; +typedef unsigned int LONG; +typedef int INT; +typedef unsigned int UINT; +typedef char *LPSTR; +typedef char *LPTSTR; +typedef DWORD *LPDWORD; +typedef WORD *LPWORD; +typedef ULONG *PULONG; +typedef PVOID LPVOID; +typedef void VOID; +typedef unsigned long long int ULONGLONG; + +typedef struct _OVERLAPPED { + DWORD Internal; + DWORD InternalHigh; + DWORD Offset; + DWORD OffsetHigh; + HANDLE hEvent; +} OVERLAPPED, *LPOVERLAPPED; + +typedef struct _SECURITY_ATTRIBUTES { + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES; + +typedef struct timeval SYSTEMTIME; +typedef struct timeval FILETIME; +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +// +// Modem Status Flags +// +#define MS_CTS_ON ((DWORD)0x0010) +#define MS_DSR_ON ((DWORD)0x0020) +#define MS_RING_ON ((DWORD)0x0040) +#define MS_RLSD_ON ((DWORD)0x0080) + +// +// Error Flags +// + +#define CE_RXOVER 0x0001 // Receive Queue overflow +#define CE_OVERRUN 0x0002 // Receive Overrun Error +#define CE_RXPARITY 0x0004 // Receive Parity Error +#define CE_FRAME 0x0008 // Receive Framing error +#define CE_BREAK 0x0010 // Break Detected +#define CE_TXFULL 0x0100 // TX Queue is full +#define CE_PTO 0x0200 // LPTx Timeout +#define CE_IOE 0x0400 // LPTx I/O Error +#define CE_DNS 0x0800 // LPTx Device not selected +#define CE_OOP 0x1000 // LPTx Out-Of-Paper +#define CE_MODE 0x8000 // Requested mode unsupported + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE 0xFFFFFFFF +#endif + +#endif diff --git a/telldus-gui/Plugins/Controllers/osx/ftd2xx.h b/telldus-gui/Plugins/Controllers/osx/ftd2xx.h new file mode 100644 index 00000000..04b65274 --- /dev/null +++ b/telldus-gui/Plugins/Controllers/osx/ftd2xx.h @@ -0,0 +1,1008 @@ +/*++ + + Copyright (c) 2001-2011 Future Technology Devices International Limited + + THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + FTDI DRIVERS MAY BE USED ONLY IN CONJUNCTION WITH PRODUCTS BASED ON FTDI PARTS. + + FTDI DRIVERS MAY BE DISTRIBUTED IN ANY FORM AS LONG AS LICENSE INFORMATION IS NOT MODIFIED. + + IF A CUSTOM VENDOR ID AND/OR PRODUCT ID OR DESCRIPTION STRING ARE USED, IT IS THE + RESPONSIBILITY OF THE PRODUCT MANUFACTURER TO MAINTAIN ANY CHANGES AND SUBSEQUENT WHQL + RE-CERTIFICATION AS A RESULT OF MAKING THESE CHANGES. + + + Module Name: + + ftd2xx.h + + Abstract: + + Native USB device driver for FTDI FT232x, FT245x, FT2232x and FT4232x devices + FTD2XX library definitions + + Environment: + + user mode + + + --*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +#ifndef _WINDOWS +#include +#define WINAPI +#endif + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + +#ifndef _WINDOWS +#include "WinTypes.h" + +#ifdef FTD2XX_API +#undef FTD2XX_API +#define FTD2XX_API +#endif +#endif +typedef struct _EVENT_HANDLE{ + pthread_cond_t eCondVar; + pthread_mutex_t eMutex; + int iVar; +} EVENT_HANDLE; + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, //7 + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_LINE_STATUS 4 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R, + FT_DEVICE_2232H, + FT_DEVICE_4232H + }; + +// +// Bit Modes +// + +#define FT_BITMODE_RESET 0x00 +#define FT_BITMODE_ASYNC_BITBANG 0x01 +#define FT_BITMODE_MPSSE 0x02 +#define FT_BITMODE_SYNC_BITBANG 0x04 +#define FT_BITMODE_MCU_HOST 0x08 +#define FT_BITMODE_FAST_SERIAL 0x10 +#define FT_BITMODE_CBUS_BITBANG 0x20 +#define FT_BITMODE_SYNC_FIFO 0x40 + + +#ifdef __cplusplus +extern "C" { +#endif + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS FT_SetVIDPID( + DWORD dwVID, + DWORD dwPID + ); + +FTD2XX_API +FT_STATUS FT_GetVIDPID( + DWORD * pdwVID, + DWORD * pdwPID + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + // 3 = FT2232H extensions + // 4 = FT4232H extensions + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 (FT232B) extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // Rev 5 (FT2232) extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // Rev 6 (FT232R) extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR RIsD2XX; // non-zero if using D2XX drivers + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // + // Rev 8 (FT4232H) Extensions + // + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if AL pins have slow slew + UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if AH pins have slow slew + UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if BL pins have slow slew + UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if BH pins have slow slew + UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA lpData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceLocId( + FT_HANDLE ftHandle, + LPDWORD lpdwLocId + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +// Device information flags +enum { + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 +}; + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + +// +// Events +// + +#define EV_RXCHAR 0x0001 // Any Character received +#define EV_RXFLAG 0x0002 // Received certain character +#define EV_TXEMPTY 0x0004 // Transmitt Queue Empty +#define EV_CTS 0x0008 // CTS changed state +#define EV_DSR 0x0010 // DSR changed state +#define EV_RLSD 0x0020 // RLSD changed state +#define EV_BREAK 0x0040 // BREAK received +#define EV_ERR 0x0080 // Line status error occurred +#define EV_RING 0x0100 // Ring signal detected +#define EV_PERR 0x0200 // Printer error occured +#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full +#define EV_EVENT1 0x0800 // Provider specific event 1 +#define EV_EVENT2 0x1000 // Provider specific event 2 + +// +// Escape Functions +// + +#define SETXOFF 1 // Simulate XOFF received +#define SETXON 2 // Simulate XON received +#define SETRTS 3 // Set RTS high +#define CLRRTS 4 // Set RTS low +#define SETDTR 5 // Set DTR high +#define CLRDTR 6 // Set DTR low +#define RESETDEV 7 // Reset device if possible +#define SETBREAK 8 // Set the device break line. +#define CLRBREAK 9 // Clear the device break line. + +// +// PURGE function flags. +// +#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port. +#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port. +#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there. +#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there. + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + + + + + + diff --git a/telldus-gui/Plugins/Controllers/win/ftd2xx.h b/telldus-gui/Plugins/Controllers/win/ftd2xx.h new file mode 100644 index 00000000..d5bc3bff --- /dev/null +++ b/telldus-gui/Plugins/Controllers/win/ftd2xx.h @@ -0,0 +1,963 @@ +/*++ + +Copyright (c) 2001-2007 Future Technology Devices International Ltd. + +Module Name: + + ftd2xx.h + +Abstract: + + Native USB device driver for FTDI FT8U232/245 + FTD2XX library definitions + +Environment: + + kernel & user mode + +Revision History: + + 13/03/01 awm Created. + 13/01/03 awm Added device information support. + 19/03/03 awm Added FT_W32_CancelIo. + 12/06/03 awm Added FT_StopInTask and FT_RestartInTask. + 18/09/03 awm Added FT_SetResetPipeRetryCount. + 10/10/03 awm Added FT_ResetPort. + 23/01/04 awm Added support for open-by-location. + 16/03/04 awm Added support for FT2232C. + 23/09/04 awm Added support for FT232R. + 20/10/04 awm Added FT_CyclePort. + 18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type. + 11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE. + 25/08/05 awm Added FT_SetDeadmanTimeout. + 02/12/05 awm Removed obsolete references. + 05/12/05 awm Added FT_GetVersion, FT_GetVersionEx. + 08/09/06 awm Added FT_W32_GetCommMask. + 11/09/06 awm Added FT_Rescan. + 11/07/07 awm Added support for FT2232H and FT4232H. + 10/08/07 awm Added flags definitions. + 21/11/07 mja Added FT_GetComPortNumber. + 05/06/08 mja Added EEPROM extensions for FT2232H. + + +--*/ + + +#ifndef FTD2XX_H +#define FTD2XX_H + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the FTD2XX_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// FTD2XX_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef FTD2XX_EXPORTS +#define FTD2XX_API __declspec(dllexport) +#else +#define FTD2XX_API __declspec(dllimport) +#endif + + +typedef PVOID FT_HANDLE; +typedef ULONG FT_STATUS; + +// +// Device status +// +enum { + FT_OK, + FT_INVALID_HANDLE, + FT_DEVICE_NOT_FOUND, + FT_DEVICE_NOT_OPENED, + FT_IO_ERROR, + FT_INSUFFICIENT_RESOURCES, + FT_INVALID_PARAMETER, + FT_INVALID_BAUD_RATE, + + FT_DEVICE_NOT_OPENED_FOR_ERASE, + FT_DEVICE_NOT_OPENED_FOR_WRITE, + FT_FAILED_TO_WRITE_DEVICE, + FT_EEPROM_READ_FAILED, + FT_EEPROM_WRITE_FAILED, + FT_EEPROM_ERASE_FAILED, + FT_EEPROM_NOT_PRESENT, + FT_EEPROM_NOT_PROGRAMMED, + FT_INVALID_ARGS, + FT_NOT_SUPPORTED, + FT_OTHER_ERROR, + FT_DEVICE_LIST_NOT_READY, +}; + + +#define FT_SUCCESS(status) ((status) == FT_OK) + +// +// FT_OpenEx Flags +// + +#define FT_OPEN_BY_SERIAL_NUMBER 1 +#define FT_OPEN_BY_DESCRIPTION 2 +#define FT_OPEN_BY_LOCATION 4 + +// +// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags +// + +#define FT_LIST_NUMBER_ONLY 0x80000000 +#define FT_LIST_BY_INDEX 0x40000000 +#define FT_LIST_ALL 0x20000000 + +#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL) + +// +// Baud Rates +// + +#define FT_BAUD_300 300 +#define FT_BAUD_600 600 +#define FT_BAUD_1200 1200 +#define FT_BAUD_2400 2400 +#define FT_BAUD_4800 4800 +#define FT_BAUD_9600 9600 +#define FT_BAUD_14400 14400 +#define FT_BAUD_19200 19200 +#define FT_BAUD_38400 38400 +#define FT_BAUD_57600 57600 +#define FT_BAUD_115200 115200 +#define FT_BAUD_230400 230400 +#define FT_BAUD_460800 460800 +#define FT_BAUD_921600 921600 + +// +// Word Lengths +// + +#define FT_BITS_8 (UCHAR) 8 +#define FT_BITS_7 (UCHAR) 7 +#define FT_BITS_6 (UCHAR) 6 +#define FT_BITS_5 (UCHAR) 5 + +// +// Stop Bits +// + +#define FT_STOP_BITS_1 (UCHAR) 0 +#define FT_STOP_BITS_1_5 (UCHAR) 1 +#define FT_STOP_BITS_2 (UCHAR) 2 + +// +// Parity +// + +#define FT_PARITY_NONE (UCHAR) 0 +#define FT_PARITY_ODD (UCHAR) 1 +#define FT_PARITY_EVEN (UCHAR) 2 +#define FT_PARITY_MARK (UCHAR) 3 +#define FT_PARITY_SPACE (UCHAR) 4 + +// +// Flow Control +// + +#define FT_FLOW_NONE 0x0000 +#define FT_FLOW_RTS_CTS 0x0100 +#define FT_FLOW_DTR_DSR 0x0200 +#define FT_FLOW_XON_XOFF 0x0400 + +// +// Purge rx and tx buffers +// +#define FT_PURGE_RX 1 +#define FT_PURGE_TX 2 + +// +// Events +// + +typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD); + +#define FT_EVENT_RXCHAR 1 +#define FT_EVENT_MODEM_STATUS 2 +#define FT_EVENT_LINE_STATUS 4 + +// +// Timeouts +// + +#define FT_DEFAULT_RX_TIMEOUT 300 +#define FT_DEFAULT_TX_TIMEOUT 300 + +// +// Device types +// + +typedef ULONG FT_DEVICE; + +enum { + FT_DEVICE_BM, + FT_DEVICE_AM, + FT_DEVICE_100AX, + FT_DEVICE_UNKNOWN, + FT_DEVICE_2232C, + FT_DEVICE_232R, + FT_DEVICE_2232H, + FT_DEVICE_4232H +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +FTD2XX_API +FT_STATUS WINAPI FT_Open( + int deviceNumber, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_OpenEx( + PVOID pArg1, + DWORD Flags, + FT_HANDLE *pHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ListDevices( + PVOID pArg1, + PVOID pArg2, + DWORD Flags + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Close( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Read( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToRead, + LPDWORD lpBytesReturned + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Write( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD dwBytesToWrite, + LPDWORD lpBytesWritten + ); + +FTD2XX_API +FT_STATUS WINAPI FT_IoCtl( + FT_HANDLE ftHandle, + DWORD dwIoControlCode, + LPVOID lpInBuf, + DWORD nInBufSize, + LPVOID lpOutBuf, + DWORD nOutBufSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBaudRate( + FT_HANDLE ftHandle, + ULONG BaudRate + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDivisor( + FT_HANDLE ftHandle, + USHORT Divisor + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDataCharacteristics( + FT_HANDLE ftHandle, + UCHAR WordLength, + UCHAR StopBits, + UCHAR Parity + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetFlowControl( + FT_HANDLE ftHandle, + USHORT FlowControl, + UCHAR XonChar, + UCHAR XoffChar + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetDevice( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrDtr( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ClrRts( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetModemStatus( + FT_HANDLE ftHandle, + ULONG *pModemStatus + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetChars( + FT_HANDLE ftHandle, + UCHAR EventChar, + UCHAR EventCharEnabled, + UCHAR ErrorChar, + UCHAR ErrorCharEnabled + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Purge( + FT_HANDLE ftHandle, + ULONG Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetTimeouts( + FT_HANDLE ftHandle, + ULONG ReadTimeout, + ULONG WriteTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetQueueStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetEventNotification( + FT_HANDLE ftHandle, + DWORD Mask, + PVOID Param + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetStatus( + FT_HANDLE ftHandle, + DWORD *dwRxBytes, + DWORD *dwTxBytes, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOn( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBreakOff( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetWaitMask( + FT_HANDLE ftHandle, + DWORD Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WaitOnMask( + FT_HANDLE ftHandle, + DWORD *Mask + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetEventStatus( + FT_HANDLE ftHandle, + DWORD *dwEventDWord + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ReadEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + LPWORD lpwValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_WriteEE( + FT_HANDLE ftHandle, + DWORD dwWordOffset, + WORD wValue + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EraseEE( + FT_HANDLE ftHandle + ); + +// +// structure to hold program data for FT_Program function +// +typedef struct ft_program_data { + + DWORD Signature1; // Header - must be 0x00000000 + DWORD Signature2; // Header - must be 0xffffffff + DWORD Version; // Header - FT_PROGRAM_DATA version + // 0 = original + // 1 = FT2232C extensions + // 2 = FT232R extensions + // 3 = FT2232H extensions + // 4 = FT4232H extensions + + WORD VendorId; // 0x0403 + WORD ProductId; // 0x6001 + char *Manufacturer; // "FTDI" + char *ManufacturerId; // "FT" + char *Description; // "USB HS Serial Converter" + char *SerialNumber; // "FT000001" if fixed, or NULL + WORD MaxPower; // 0 < MaxPower <= 500 + WORD PnP; // 0 = disabled, 1 = enabled + WORD SelfPowered; // 0 = bus powered, 1 = self powered + WORD RemoteWakeup; // 0 = not capable, 1 = capable + // + // Rev4 (FT232B) extensions + // + UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise + UCHAR IsoIn; // non-zero if in endpoint is isochronous + UCHAR IsoOut; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable; // non-zero if pull down enabled + UCHAR SerNumEnable; // non-zero if serial number to be used + UCHAR USBVersionEnable; // non-zero if chip uses USBVersion + WORD USBVersion; // BCD (0x0200 => USB2) + // + // Rev 5 (FT2232) extensions + // + UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise + UCHAR IsoInA; // non-zero if in endpoint is isochronous + UCHAR IsoInB; // non-zero if in endpoint is isochronous + UCHAR IsoOutA; // non-zero if out endpoint is isochronous + UCHAR IsoOutB; // non-zero if out endpoint is isochronous + UCHAR PullDownEnable5; // non-zero if pull down enabled + UCHAR SerNumEnable5; // non-zero if serial number to be used + UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion + WORD USBVersion5; // BCD (0x0200 => USB2) + UCHAR AIsHighCurrent; // non-zero if interface is high current + UCHAR BIsHighCurrent; // non-zero if interface is high current + UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer; // non-zero if interface is Fast serial + UCHAR AIsVCP; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer; // non-zero if interface is Fast serial + UCHAR BIsVCP; // non-zero if interface is to use VCP drivers + // + // Rev 6 (FT232R) extensions + // + UCHAR UseExtOsc; // Use External Oscillator + UCHAR HighDriveIOs; // High Drive I/Os + UCHAR EndpointSize; // Endpoint size + UCHAR PullDownEnableR; // non-zero if pull down enabled + UCHAR SerNumEnableR; // non-zero if serial number to be used + UCHAR InvertTXD; // non-zero if invert TXD + UCHAR InvertRXD; // non-zero if invert RXD + UCHAR InvertRTS; // non-zero if invert RTS + UCHAR InvertCTS; // non-zero if invert CTS + UCHAR InvertDTR; // non-zero if invert DTR + UCHAR InvertDSR; // non-zero if invert DSR + UCHAR InvertDCD; // non-zero if invert DCD + UCHAR InvertRI; // non-zero if invert RI + UCHAR Cbus0; // Cbus Mux control + UCHAR Cbus1; // Cbus Mux control + UCHAR Cbus2; // Cbus Mux control + UCHAR Cbus3; // Cbus Mux control + UCHAR Cbus4; // Cbus Mux control + UCHAR RIsD2XX; // non-zero if using D2XX driver + // + // Rev 7 (FT2232H) Extensions + // + UCHAR PullDownEnable7; // non-zero if pull down enabled + UCHAR SerNumEnable7; // non-zero if serial number to be used + UCHAR ALSlowSlew; // non-zero if AL pins have slow slew + UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR AHSlowSlew; // non-zero if AH pins have slow slew + UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BLSlowSlew; // non-zero if BL pins have slow slew + UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BHSlowSlew; // non-zero if BH pins have slow slew + UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial + UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO + UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target + UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial + UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers + UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs + // + // Rev 8 (FT4232H) Extensions + // + UCHAR PullDownEnable8; // non-zero if pull down enabled + UCHAR SerNumEnable8; // non-zero if serial number to be used + UCHAR ASlowSlew; // non-zero if AL pins have slow slew + UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input + UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR BSlowSlew; // non-zero if AH pins have slow slew + UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input + UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR CSlowSlew; // non-zero if BL pins have slow slew + UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input + UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR DSlowSlew; // non-zero if BH pins have slow slew + UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input + UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA + UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN + UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN + UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN + UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN + UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers + UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers + +} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA; + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Program( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ProgramEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_Read( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_ReadEx( + FT_HANDLE ftHandle, + PFT_PROGRAM_DATA pData, + char *Manufacturer, + char *ManufacturerId, + char *Description, + char *SerialNumber + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UASize( + FT_HANDLE ftHandle, + LPDWORD lpdwSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UAWrite( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen + ); + +FTD2XX_API +FT_STATUS WINAPI FT_EE_UARead( + FT_HANDLE ftHandle, + PUCHAR pucData, + DWORD dwDataLen, + LPDWORD lpdwBytesRead + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetLatencyTimer( + FT_HANDLE ftHandle, + UCHAR ucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLatencyTimer( + FT_HANDLE ftHandle, + PUCHAR pucLatency + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetBitMode( + FT_HANDLE ftHandle, + UCHAR ucMask, + UCHAR ucEnable + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetBitMode( + FT_HANDLE ftHandle, + PUCHAR pucMode + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetUSBParameters( + FT_HANDLE ftHandle, + ULONG ulInTransferSize, + ULONG ulOutTransferSize + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetDeadmanTimeout( + FT_HANDLE ftHandle, + ULONG ulDeadmanTimeout + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfo( + FT_HANDLE ftHandle, + FT_DEVICE *lpftDevice, + LPDWORD lpdwID, + PCHAR SerialNumber, + PCHAR Description, + LPVOID Dummy + ); + +FTD2XX_API +FT_STATUS WINAPI FT_StopInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_RestartInTask( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_SetResetPipeRetryCount( + FT_HANDLE ftHandle, + DWORD dwCount + ); + +FTD2XX_API +FT_STATUS WINAPI FT_ResetPort( + FT_HANDLE ftHandle + ); + +FTD2XX_API +FT_STATUS WINAPI FT_CyclePort( + FT_HANDLE ftHandle + ); + + +// +// Win32-type functions +// + +FTD2XX_API +FT_HANDLE WINAPI FT_W32_CreateFile( + LPCTSTR lpszName, + DWORD dwAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreate, + DWORD dwAttrsAndFlags, + HANDLE hTemplate + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CloseHandle( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ReadFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesReturned, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WriteFile( + FT_HANDLE ftHandle, + LPVOID lpBuffer, + DWORD nBufferSize, + LPDWORD lpBytesWritten, + LPOVERLAPPED lpOverlapped + ); + +FTD2XX_API +DWORD WINAPI FT_W32_GetLastError( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetOverlappedResult( + FT_HANDLE ftHandle, + LPOVERLAPPED lpOverlapped, + LPDWORD lpdwBytesTransferred, + BOOL bWait + ); + +FTD2XX_API +BOOL WINAPI FT_W32_CancelIo( + FT_HANDLE ftHandle + ); + + +// +// Win32 COMM API type functions +// +typedef struct _FTCOMSTAT { + DWORD fCtsHold : 1; + DWORD fDsrHold : 1; + DWORD fRlsdHold : 1; + DWORD fXoffHold : 1; + DWORD fXoffSent : 1; + DWORD fEof : 1; + DWORD fTxim : 1; + DWORD fReserved : 25; + DWORD cbInQue; + DWORD cbOutQue; +} FTCOMSTAT, *LPFTCOMSTAT; + +typedef struct _FTDCB { + DWORD DCBlength; /* sizeof(FTDCB) */ + DWORD BaudRate; /* Baudrate at which running */ + DWORD fBinary: 1; /* Binary Mode (skip EOF check) */ + DWORD fParity: 1; /* Enable parity checking */ + DWORD fOutxCtsFlow:1; /* CTS handshaking on output */ + DWORD fOutxDsrFlow:1; /* DSR handshaking on output */ + DWORD fDtrControl:2; /* DTR Flow control */ + DWORD fDsrSensitivity:1; /* DSR Sensitivity */ + DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */ + DWORD fOutX: 1; /* Enable output X-ON/X-OFF */ + DWORD fInX: 1; /* Enable input X-ON/X-OFF */ + DWORD fErrorChar: 1; /* Enable Err Replacement */ + DWORD fNull: 1; /* Enable Null stripping */ + DWORD fRtsControl:2; /* Rts Flow control */ + DWORD fAbortOnError:1; /* Abort all reads and writes on Error */ + DWORD fDummy2:17; /* Reserved */ + WORD wReserved; /* Not currently used */ + WORD XonLim; /* Transmit X-ON threshold */ + WORD XoffLim; /* Transmit X-OFF threshold */ + BYTE ByteSize; /* Number of bits/byte, 4-8 */ + BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */ + BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */ + char XonChar; /* Tx and Rx X-ON character */ + char XoffChar; /* Tx and Rx X-OFF character */ + char ErrorChar; /* Error replacement char */ + char EofChar; /* End of Input character */ + char EvtChar; /* Received Event character */ + WORD wReserved1; /* Fill for now. */ +} FTDCB, *LPFTDCB; + +typedef struct _FTTIMEOUTS { + DWORD ReadIntervalTimeout; /* Maximum time between read chars. */ + DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */ + DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */ + DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */ +} FTTIMEOUTS,*LPFTTIMEOUTS; + + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_ClearCommError( + FT_HANDLE ftHandle, + LPDWORD lpdwErrors, + LPFTCOMSTAT lpftComstat + ); + +FTD2XX_API +BOOL WINAPI FT_W32_EscapeCommFunction( + FT_HANDLE ftHandle, + DWORD dwFunc + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommModemStatus( + FT_HANDLE ftHandle, + LPDWORD lpdwModemStatus + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_PurgeComm( + FT_HANDLE ftHandle, + DWORD dwMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommBreak( + FT_HANDLE ftHandle + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommMask( + FT_HANDLE ftHandle, + ULONG ulEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_GetCommMask( + FT_HANDLE ftHandle, + LPDWORD lpdwEventMask + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommState( + FT_HANDLE ftHandle, + LPFTDCB lpftDcb + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetCommTimeouts( + FT_HANDLE ftHandle, + FTTIMEOUTS *pTimeouts + ); + +FTD2XX_API +BOOL WINAPI FT_W32_SetupComm( + FT_HANDLE ftHandle, + DWORD dwReadBufferSize, + DWORD dwWriteBufferSize + ); + +FTD2XX_API +BOOL WINAPI FT_W32_WaitCommEvent( + FT_HANDLE ftHandle, + PULONG pulEvent, + LPOVERLAPPED lpOverlapped + ); + + +// +// Device information +// + +typedef struct _ft_device_list_info_node { + ULONG Flags; + ULONG Type; + ULONG ID; + DWORD LocId; + char SerialNumber[16]; + char Description[64]; + FT_HANDLE ftHandle; +} FT_DEVICE_LIST_INFO_NODE; + +// Device information flags +enum { + FT_FLAGS_OPENED = 1, + FT_FLAGS_HISPEED = 2 +}; + + +FTD2XX_API +FT_STATUS WINAPI FT_CreateDeviceInfoList( + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoList( + FT_DEVICE_LIST_INFO_NODE *pDest, + LPDWORD lpdwNumDevs + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetDeviceInfoDetail( + DWORD dwIndex, + LPDWORD lpdwFlags, + LPDWORD lpdwType, + LPDWORD lpdwID, + LPDWORD lpdwLocId, + LPVOID lpSerialNumber, + LPVOID lpDescription, + FT_HANDLE *pftHandle + ); + + +// +// Version information +// + +FTD2XX_API +FT_STATUS WINAPI FT_GetDriverVersion( + FT_HANDLE ftHandle, + LPDWORD lpdwVersion + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetLibraryVersion( + LPDWORD lpdwVersion + ); + + +FTD2XX_API +FT_STATUS WINAPI FT_Rescan( + void + ); + +FTD2XX_API +FT_STATUS WINAPI FT_Reload( + WORD wVid, + WORD wPid + ); + +FTD2XX_API +FT_STATUS WINAPI FT_GetComPortNumber( + FT_HANDLE ftHandle, + LPLONG lpdwComPortNumber + ); + + + +#ifdef __cplusplus +} +#endif + + +#endif /* FTD2XX_H */ + From 4af5c5b658e677743e6de4bd3540bc5a1b0d3faf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 1 Jun 2012 15:28:59 +0200 Subject: [PATCH 1995/2215] Check that the option we set in Settings::setStringSetting() actually exists before write when using libConfuse. Writing to a non existing option makes telldusd SIGABRT. Closes #207. --- telldus-core/service/SettingsConfuse.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 5d926ac1..0948793a 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -298,12 +298,15 @@ int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &n cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i); if (cfg_getint(cfg_device, "id") == intDeviceId) { std::string newValue = TelldusCore::wideToString(value); + cfg_t *p = cfg_device; if (parameter) { - cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters"); - cfg_setstr(cfg_parameters, TelldusCore::wideToString(name).c_str(), newValue.c_str()); - } else { - cfg_setstr(cfg_device, TelldusCore::wideToString(name).c_str(), newValue.c_str()); + cfg_t *cfg_p = cfg_getsec(cfg_device, "parameters"); } + cfg_opt_t *opt = cfg_getopt(p, TelldusCore::wideToString(name).c_str()); + if (!opt) { + return TELLSTICK_ERROR_CONFIG_SYNTAX; + } + cfg_setstr(p, TelldusCore::wideToString(name).c_str(), newValue.c_str()); FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; From 488ab8c7542600e5499c1b6ae5f193455bf1c25d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Jun 2012 12:28:13 +0200 Subject: [PATCH 1996/2215] The function close() is declared in unistd.h. We must include this since it might not be pulled in by other headers on all platforms. Closes #216 --- telldus-core/common/Socket_unix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 23512a60..947df5bb 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -4,6 +4,7 @@ #include "Strings.h" #include +#include #include #include #include From 506c740d81ef858df4fb47336c41e7315e6a9f0e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 28 Feb 2012 21:21:58 +0100 Subject: [PATCH 1997/2215] Add Google style guideline check tool: cpplint --- telldus-core/client/CMakeLists.txt | 1 + telldus-core/service/CMakeLists.txt | 1 + telldus-core/tests/CMakeLists.txt | 16 + telldus-core/tests/cpplint.py | 3361 +++++++++++++++++++++++++++ 4 files changed, 3379 insertions(+) create mode 100755 telldus-core/tests/cpplint.py diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index d764c3a7..e07e4445 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -108,6 +108,7 @@ ENDIF (UNIX) TARGET_LINK_LIBRARIES( ${telldus-core_TARGET} ${telldus-core_LIBRARIES} ) +SET(telldus-core_TARGET ${telldus-core_TARGET} PARENT_SCOPE) SET_TARGET_PROPERTIES(${telldus-core_TARGET} PROPERTIES FRAMEWORK TRUE INSTALL_NAME_DIR "/Library/Frameworks" diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 06ee41ca..97b53857 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -186,6 +186,7 @@ ENDIF (FTDI_ENGINE STREQUAL "ftd2xx") SOURCE_GROUP("Protocol Files" FILES ${telldus-service_protocol_SRCS}) +SET(telldus-service_TARGET ${telldus-service_TARGET} PARENT_SCOPE) ADD_EXECUTABLE(${telldus-service_TARGET} ${telldus-service_SRCS} ${telldus-service_protocol_SRCS} diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index 6ef2bb75..8bbdc1cf 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -1,5 +1,17 @@ SET(ENABLE_TESTING FALSE CACHE BOOL "Enable unit tests") +SET(cpplint_filters + -whitespace/tab,-whitespace/parens,-whitespace/line_length,-whitespace/labels +) + +FUNCTION(ADD_SOURCES TARGET PATH) + GET_TARGET_PROPERTY(SOURCES ${TARGET} SOURCES) + FOREACH(SOURCE ${SOURCES}) + LIST(APPEND L ${PATH}/${SOURCE}) + ENDFOREACH() + ADD_TEST(StyleGuidelines-${TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/cpplint.py --filter=${cpplint_filters} ${L}) +ENDFUNCTION() + IF(ENABLE_TESTING) ADD_SUBDIRECTORY(common) @@ -7,6 +19,10 @@ IF(ENABLE_TESTING) TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) ADD_DEPENDENCIES(TestRunner TelldusCommonTests) + ADD_SOURCES(TelldusCommon ${CMAKE_SOURCE_DIR}/common) + ADD_SOURCES(${telldus-core_TARGET} ${CMAKE_SOURCE_DIR}/client) + ADD_SOURCES(${telldus-service_TARGET} ${CMAKE_SOURCE_DIR}/service) + ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) IF (UNIX AND NOT APPLE) ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR}) diff --git a/telldus-core/tests/cpplint.py b/telldus-core/tests/cpplint.py new file mode 100755 index 00000000..526b9556 --- /dev/null +++ b/telldus-core/tests/cpplint.py @@ -0,0 +1,3361 @@ +#!/usr/bin/python +# +# Copyright (c) 2009 Google Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Here are some issues that I've had people identify in my code during reviews, +# that I think are possible to flag automatically in a lint tool. If these were +# caught by lint, it would save time both for myself and that of my reviewers. +# Most likely, some of these are beyond the scope of the current lint framework, +# but I think it is valuable to retain these wish-list items even if they cannot +# be immediately implemented. +# +# Suggestions +# ----------- +# - Check for no 'explicit' for multi-arg ctor +# - Check for boolean assign RHS in parens +# - Check for ctor initializer-list colon position and spacing +# - Check that if there's a ctor, there should be a dtor +# - Check accessors that return non-pointer member variables are +# declared const +# - Check accessors that return non-const pointer member vars are +# *not* declared const +# - Check for using public includes for testing +# - Check for spaces between brackets in one-line inline method +# - Check for no assert() +# - Check for spaces surrounding operators +# - Check for 0 in pointer context (should be NULL) +# - Check for 0 in char context (should be '\0') +# - Check for camel-case method name conventions for methods +# that are not simple inline getters and setters +# - Check that base classes have virtual destructors +# put " // namespace" after } that closes a namespace, with +# namespace's name after 'namespace' if it is named. +# - Do not indent namespace contents +# - Avoid inlining non-trivial constructors in header files +# include base/basictypes.h if DISALLOW_EVIL_CONSTRUCTORS is used +# - Check for old-school (void) cast for call-sites of functions +# ignored return value +# - Check gUnit usage of anonymous namespace +# - Check for class declaration order (typedefs, consts, enums, +# ctor(s?), dtor, friend declarations, methods, member vars) +# + +"""Does google-lint on c++ files. + +The goal of this script is to identify places in the code that *may* +be in non-compliance with google style. It does not attempt to fix +up these problems -- the point is to educate. It does also not +attempt to find all problems, or to ensure that everything it does +find is legitimately a problem. + +In particular, we can get very confused by /* and // inside strings! +We do a small hack, which is to ignore //'s with "'s after them on the +same line, but it is far from perfect (in either direction). +""" + +import codecs +import getopt +import math # for log +import os +import re +import sre_compile +import string +import sys +import unicodedata + + +_USAGE = """ +Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] + [--counting=total|toplevel|detailed] + [file] ... + + The style guidelines this tries to follow are those in + http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml + + Every problem is given a confidence score from 1-5, with 5 meaning we are + certain of the problem, and 1 meaning it could be a legitimate construct. + This will miss some errors, and is not a substitute for a code review. + + To suppress false-positive errors of a certain category, add a + 'NOLINT(category)' comment to the line. NOLINT or NOLINT(*) + suppresses errors of all categories on that line. + + The files passed in will be linted; at least one file must be provided. + Linted extensions are .cc, .cpp, and .h. Other file types will be ignored. + + Flags: + + output=vs7 + By default, the output is formatted to ease emacs parsing. Visual Studio + compatible output (vs7) may also be used. Other formats are unsupported. + + verbose=# + Specify a number 0-5 to restrict errors to certain verbosity levels. + + filter=-x,+y,... + Specify a comma-separated list of category-filters to apply: only + error messages whose category names pass the filters will be printed. + (Category names are printed with the message and look like + "[whitespace/indent]".) Filters are evaluated left to right. + "-FOO" and "FOO" means "do not print categories that start with FOO". + "+FOO" means "do print categories that start with FOO". + + Examples: --filter=-whitespace,+whitespace/braces + --filter=whitespace,runtime/printf,+runtime/printf_format + --filter=-,+build/include_what_you_use + + To see a list of all the categories used in cpplint, pass no arg: + --filter= + + counting=total|toplevel|detailed + The total number of errors found is always printed. If + 'toplevel' is provided, then the count of errors in each of + the top-level categories like 'build' and 'whitespace' will + also be printed. If 'detailed' is provided, then a count + is provided for each category like 'build/class'. +""" + +# We categorize each error message we print. Here are the categories. +# We want an explicit list so we can list them all in cpplint --filter=. +# If you add a new error message with a new category, add it to the list +# here! cpplint_unittest.py should tell you if you forget to do this. +# \ used for clearer layout -- pylint: disable-msg=C6013 +_ERROR_CATEGORIES = [ + 'build/class', + 'build/deprecated', + 'build/endif_comment', + 'build/explicit_make_pair', + 'build/forward_decl', + 'build/header_guard', + 'build/include', + 'build/include_alpha', + 'build/include_order', + 'build/include_what_you_use', + 'build/namespaces', + 'build/printf_format', + 'build/storage_class', + 'legal/copyright', + 'readability/braces', + 'readability/casting', + 'readability/check', + 'readability/constructors', + 'readability/fn_size', + 'readability/function', + 'readability/multiline_comment', + 'readability/multiline_string', + 'readability/nolint', + 'readability/streams', + 'readability/todo', + 'readability/utf8', + 'runtime/arrays', + 'runtime/casting', + 'runtime/explicit', + 'runtime/int', + 'runtime/init', + 'runtime/invalid_increment', + 'runtime/member_string_references', + 'runtime/memset', + 'runtime/operator', + 'runtime/printf', + 'runtime/printf_format', + 'runtime/references', + 'runtime/rtti', + 'runtime/sizeof', + 'runtime/string', + 'runtime/threadsafe_fn', + 'runtime/virtual', + 'whitespace/blank_line', + 'whitespace/braces', + 'whitespace/comma', + 'whitespace/comments', + 'whitespace/end_of_line', + 'whitespace/ending_newline', + 'whitespace/indent', + 'whitespace/labels', + 'whitespace/line_length', + 'whitespace/newline', + 'whitespace/operators', + 'whitespace/parens', + 'whitespace/semicolon', + 'whitespace/tab', + 'whitespace/todo' + ] + +# The default state of the category filter. This is overrided by the --filter= +# flag. By default all errors are on, so only add here categories that should be +# off by default (i.e., categories that must be enabled by the --filter= flags). +# All entries here should start with a '-' or '+', as in the --filter= flag. +_DEFAULT_FILTERS = ['-build/include_alpha'] + +# We used to check for high-bit characters, but after much discussion we +# decided those were OK, as long as they were in UTF-8 and didn't represent +# hard-coded international strings, which belong in a separate i18n file. + +# Headers that we consider STL headers. +_STL_HEADERS = frozenset([ + 'algobase.h', 'algorithm', 'alloc.h', 'bitset', 'deque', 'exception', + 'function.h', 'functional', 'hash_map', 'hash_map.h', 'hash_set', + 'hash_set.h', 'iterator', 'list', 'list.h', 'map', 'memory', 'new', + 'pair.h', 'pthread_alloc', 'queue', 'set', 'set.h', 'sstream', 'stack', + 'stl_alloc.h', 'stl_relops.h', 'type_traits.h', + 'utility', 'vector', 'vector.h', + ]) + + +# Non-STL C++ system headers. +_CPP_HEADERS = frozenset([ + 'algo.h', 'builtinbuf.h', 'bvector.h', 'cassert', 'cctype', + 'cerrno', 'cfloat', 'ciso646', 'climits', 'clocale', 'cmath', + 'complex', 'complex.h', 'csetjmp', 'csignal', 'cstdarg', 'cstddef', + 'cstdio', 'cstdlib', 'cstring', 'ctime', 'cwchar', 'cwctype', + 'defalloc.h', 'deque.h', 'editbuf.h', 'exception', 'fstream', + 'fstream.h', 'hashtable.h', 'heap.h', 'indstream.h', 'iomanip', + 'iomanip.h', 'ios', 'iosfwd', 'iostream', 'iostream.h', 'istream', + 'istream.h', 'iterator.h', 'limits', 'map.h', 'multimap.h', 'multiset.h', + 'numeric', 'ostream', 'ostream.h', 'parsestream.h', 'pfstream.h', + 'PlotFile.h', 'procbuf.h', 'pthread_alloc.h', 'rope', 'rope.h', + 'ropeimpl.h', 'SFile.h', 'slist', 'slist.h', 'stack.h', 'stdexcept', + 'stdiostream.h', 'streambuf.h', 'stream.h', 'strfile.h', 'string', + 'strstream', 'strstream.h', 'tempbuf.h', 'tree.h', 'typeinfo', 'valarray', + ]) + + +# Assertion macros. These are defined in base/logging.h and +# testing/base/gunit.h. Note that the _M versions need to come first +# for substring matching to work. +_CHECK_MACROS = [ + 'DCHECK', 'CHECK', + 'EXPECT_TRUE_M', 'EXPECT_TRUE', + 'ASSERT_TRUE_M', 'ASSERT_TRUE', + 'EXPECT_FALSE_M', 'EXPECT_FALSE', + 'ASSERT_FALSE_M', 'ASSERT_FALSE', + ] + +# Replacement macros for CHECK/DCHECK/EXPECT_TRUE/EXPECT_FALSE +_CHECK_REPLACEMENT = dict([(m, {}) for m in _CHECK_MACROS]) + +for op, replacement in [('==', 'EQ'), ('!=', 'NE'), + ('>=', 'GE'), ('>', 'GT'), + ('<=', 'LE'), ('<', 'LT')]: + _CHECK_REPLACEMENT['DCHECK'][op] = 'DCHECK_%s' % replacement + _CHECK_REPLACEMENT['CHECK'][op] = 'CHECK_%s' % replacement + _CHECK_REPLACEMENT['EXPECT_TRUE'][op] = 'EXPECT_%s' % replacement + _CHECK_REPLACEMENT['ASSERT_TRUE'][op] = 'ASSERT_%s' % replacement + _CHECK_REPLACEMENT['EXPECT_TRUE_M'][op] = 'EXPECT_%s_M' % replacement + _CHECK_REPLACEMENT['ASSERT_TRUE_M'][op] = 'ASSERT_%s_M' % replacement + +for op, inv_replacement in [('==', 'NE'), ('!=', 'EQ'), + ('>=', 'LT'), ('>', 'LE'), + ('<=', 'GT'), ('<', 'GE')]: + _CHECK_REPLACEMENT['EXPECT_FALSE'][op] = 'EXPECT_%s' % inv_replacement + _CHECK_REPLACEMENT['ASSERT_FALSE'][op] = 'ASSERT_%s' % inv_replacement + _CHECK_REPLACEMENT['EXPECT_FALSE_M'][op] = 'EXPECT_%s_M' % inv_replacement + _CHECK_REPLACEMENT['ASSERT_FALSE_M'][op] = 'ASSERT_%s_M' % inv_replacement + + +# These constants define types of headers for use with +# _IncludeState.CheckNextIncludeOrder(). +_C_SYS_HEADER = 1 +_CPP_SYS_HEADER = 2 +_LIKELY_MY_HEADER = 3 +_POSSIBLE_MY_HEADER = 4 +_OTHER_HEADER = 5 + + +_regexp_compile_cache = {} + +# Finds occurrences of NOLINT or NOLINT(...). +_RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') + +# {str, set(int)}: a map from error categories to sets of linenumbers +# on which those errors are expected and should be suppressed. +_error_suppressions = {} + +def ParseNolintSuppressions(filename, raw_line, linenum, error): + """Updates the global list of error-suppressions. + + Parses any NOLINT comments on the current line, updating the global + error_suppressions store. Reports an error if the NOLINT comment + was malformed. + + Args: + filename: str, the name of the input file. + raw_line: str, the line of input text, with comments. + linenum: int, the number of the current line. + error: function, an error handler. + """ + # FIXME(adonovan): "NOLINT(" is misparsed as NOLINT(*). + matched = _RE_SUPPRESSION.search(raw_line) + if matched: + category = matched.group(1) + if category in (None, '(*)'): # => "suppress all" + _error_suppressions.setdefault(None, set()).add(linenum) + else: + if category.startswith('(') and category.endswith(')'): + category = category[1:-1] + if category in _ERROR_CATEGORIES: + _error_suppressions.setdefault(category, set()).add(linenum) + else: + error(filename, linenum, 'readability/nolint', 5, + 'Unknown NOLINT error category: %s' % category) + + +def ResetNolintSuppressions(): + "Resets the set of NOLINT suppressions to empty." + _error_suppressions.clear() + + +def IsErrorSuppressedByNolint(category, linenum): + """Returns true if the specified error category is suppressed on this line. + + Consults the global error_suppressions map populated by + ParseNolintSuppressions/ResetNolintSuppressions. + + Args: + category: str, the category of the error. + linenum: int, the current line number. + Returns: + bool, True iff the error should be suppressed due to a NOLINT comment. + """ + return (linenum in _error_suppressions.get(category, set()) or + linenum in _error_suppressions.get(None, set())) + +def Match(pattern, s): + """Matches the string with the pattern, caching the compiled regexp.""" + # The regexp compilation caching is inlined in both Match and Search for + # performance reasons; factoring it out into a separate function turns out + # to be noticeably expensive. + if not pattern in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].match(s) + + +def Search(pattern, s): + """Searches the string for the pattern, caching the compiled regexp.""" + if not pattern in _regexp_compile_cache: + _regexp_compile_cache[pattern] = sre_compile.compile(pattern) + return _regexp_compile_cache[pattern].search(s) + + +class _IncludeState(dict): + """Tracks line numbers for includes, and the order in which includes appear. + + As a dict, an _IncludeState object serves as a mapping between include + filename and line number on which that file was included. + + Call CheckNextIncludeOrder() once for each header in the file, passing + in the type constants defined above. Calls in an illegal order will + raise an _IncludeError with an appropriate error message. + + """ + # self._section will move monotonically through this set. If it ever + # needs to move backwards, CheckNextIncludeOrder will raise an error. + _INITIAL_SECTION = 0 + _MY_H_SECTION = 1 + _C_SECTION = 2 + _CPP_SECTION = 3 + _OTHER_H_SECTION = 4 + + _TYPE_NAMES = { + _C_SYS_HEADER: 'C system header', + _CPP_SYS_HEADER: 'C++ system header', + _LIKELY_MY_HEADER: 'header this file implements', + _POSSIBLE_MY_HEADER: 'header this file may implement', + _OTHER_HEADER: 'other header', + } + _SECTION_NAMES = { + _INITIAL_SECTION: "... nothing. (This can't be an error.)", + _MY_H_SECTION: 'a header this file implements', + _C_SECTION: 'C system header', + _CPP_SECTION: 'C++ system header', + _OTHER_H_SECTION: 'other header', + } + + def __init__(self): + dict.__init__(self) + # The name of the current section. + self._section = self._INITIAL_SECTION + # The path of last found header. + self._last_header = '' + + def CanonicalizeAlphabeticalOrder(self, header_path): + """Returns a path canonicalized for alphabetical comparison. + + - replaces "-" with "_" so they both cmp the same. + - removes '-inl' since we don't require them to be after the main header. + - lowercase everything, just in case. + + Args: + header_path: Path to be canonicalized. + + Returns: + Canonicalized path. + """ + return header_path.replace('-inl.h', '.h').replace('-', '_').lower() + + def IsInAlphabeticalOrder(self, header_path): + """Check if a header is in alphabetical order with the previous header. + + Args: + header_path: Header to be checked. + + Returns: + Returns true if the header is in alphabetical order. + """ + canonical_header = self.CanonicalizeAlphabeticalOrder(header_path) + if self._last_header > canonical_header: + return False + self._last_header = canonical_header + return True + + def CheckNextIncludeOrder(self, header_type): + """Returns a non-empty error message if the next header is out of order. + + This function also updates the internal state to be ready to check + the next include. + + Args: + header_type: One of the _XXX_HEADER constants defined above. + + Returns: + The empty string if the header is in the right order, or an + error message describing what's wrong. + + """ + error_message = ('Found %s after %s' % + (self._TYPE_NAMES[header_type], + self._SECTION_NAMES[self._section])) + + last_section = self._section + + if header_type == _C_SYS_HEADER: + if self._section <= self._C_SECTION: + self._section = self._C_SECTION + else: + self._last_header = '' + return error_message + elif header_type == _CPP_SYS_HEADER: + if self._section <= self._CPP_SECTION: + self._section = self._CPP_SECTION + else: + self._last_header = '' + return error_message + elif header_type == _LIKELY_MY_HEADER: + if self._section <= self._MY_H_SECTION: + self._section = self._MY_H_SECTION + else: + self._section = self._OTHER_H_SECTION + elif header_type == _POSSIBLE_MY_HEADER: + if self._section <= self._MY_H_SECTION: + self._section = self._MY_H_SECTION + else: + # This will always be the fallback because we're not sure + # enough that the header is associated with this file. + self._section = self._OTHER_H_SECTION + else: + assert header_type == _OTHER_HEADER + self._section = self._OTHER_H_SECTION + + if last_section != self._section: + self._last_header = '' + + return '' + + +class _CppLintState(object): + """Maintains module-wide state..""" + + def __init__(self): + self.verbose_level = 1 # global setting. + self.error_count = 0 # global count of reported errors + # filters to apply when emitting error messages + self.filters = _DEFAULT_FILTERS[:] + self.counting = 'total' # In what way are we counting errors? + self.errors_by_category = {} # string to int dict storing error counts + + # output format: + # "emacs" - format that emacs can parse (default) + # "vs7" - format that Microsoft Visual Studio 7 can parse + self.output_format = 'emacs' + + def SetOutputFormat(self, output_format): + """Sets the output format for errors.""" + self.output_format = output_format + + def SetVerboseLevel(self, level): + """Sets the module's verbosity, and returns the previous setting.""" + last_verbose_level = self.verbose_level + self.verbose_level = level + return last_verbose_level + + def SetCountingStyle(self, counting_style): + """Sets the module's counting options.""" + self.counting = counting_style + + def SetFilters(self, filters): + """Sets the error-message filters. + + These filters are applied when deciding whether to emit a given + error message. + + Args: + filters: A string of comma-separated filters (eg "+whitespace/indent"). + Each filter should start with + or -; else we die. + + Raises: + ValueError: The comma-separated filters did not all start with '+' or '-'. + E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" + """ + # Default filters always have less priority than the flag ones. + self.filters = _DEFAULT_FILTERS[:] + for filt in filters.split(','): + clean_filt = filt.strip() + if clean_filt: + self.filters.append(clean_filt) + for filt in self.filters: + if not (filt.startswith('+') or filt.startswith('-')): + raise ValueError('Every filter in --filters must start with + or -' + ' (%s does not)' % filt) + + def ResetErrorCounts(self): + """Sets the module's error statistic back to zero.""" + self.error_count = 0 + self.errors_by_category = {} + + def IncrementErrorCount(self, category): + """Bumps the module's error statistic.""" + self.error_count += 1 + if self.counting in ('toplevel', 'detailed'): + if self.counting != 'detailed': + category = category.split('/')[0] + if category not in self.errors_by_category: + self.errors_by_category[category] = 0 + self.errors_by_category[category] += 1 + + def PrintErrorCounts(self): + """Print a summary of errors by category, and the total.""" + for category, count in self.errors_by_category.iteritems(): + sys.stderr.write('Category \'%s\' errors found: %d\n' % + (category, count)) + sys.stderr.write('Total errors found: %d\n' % self.error_count) + +_cpplint_state = _CppLintState() + + +def _OutputFormat(): + """Gets the module's output format.""" + return _cpplint_state.output_format + + +def _SetOutputFormat(output_format): + """Sets the module's output format.""" + _cpplint_state.SetOutputFormat(output_format) + + +def _VerboseLevel(): + """Returns the module's verbosity setting.""" + return _cpplint_state.verbose_level + + +def _SetVerboseLevel(level): + """Sets the module's verbosity, and returns the previous setting.""" + return _cpplint_state.SetVerboseLevel(level) + + +def _SetCountingStyle(level): + """Sets the module's counting options.""" + _cpplint_state.SetCountingStyle(level) + + +def _Filters(): + """Returns the module's list of output filters, as a list.""" + return _cpplint_state.filters + + +def _SetFilters(filters): + """Sets the module's error-message filters. + + These filters are applied when deciding whether to emit a given + error message. + + Args: + filters: A string of comma-separated filters (eg "whitespace/indent"). + Each filter should start with + or -; else we die. + """ + _cpplint_state.SetFilters(filters) + + +class _FunctionState(object): + """Tracks current function name and the number of lines in its body.""" + + _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. + _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. + + def __init__(self): + self.in_a_function = False + self.lines_in_function = 0 + self.current_function = '' + + def Begin(self, function_name): + """Start analyzing function body. + + Args: + function_name: The name of the function being tracked. + """ + self.in_a_function = True + self.lines_in_function = 0 + self.current_function = function_name + + def Count(self): + """Count line in current function body.""" + if self.in_a_function: + self.lines_in_function += 1 + + def Check(self, error, filename, linenum): + """Report if too many lines in function body. + + Args: + error: The function to call with any errors found. + filename: The name of the current file. + linenum: The number of the line to check. + """ + if Match(r'T(EST|est)', self.current_function): + base_trigger = self._TEST_TRIGGER + else: + base_trigger = self._NORMAL_TRIGGER + trigger = base_trigger * 2**_VerboseLevel() + + if self.lines_in_function > trigger: + error_level = int(math.log(self.lines_in_function / base_trigger, 2)) + # 50 => 0, 100 => 1, 200 => 2, 400 => 3, 800 => 4, 1600 => 5, ... + if error_level > 5: + error_level = 5 + error(filename, linenum, 'readability/fn_size', error_level, + 'Small and focused functions are preferred:' + ' %s has %d non-comment lines' + ' (error triggered by exceeding %d lines).' % ( + self.current_function, self.lines_in_function, trigger)) + + def End(self): + """Stop analyzing function body.""" + self.in_a_function = False + + +class _IncludeError(Exception): + """Indicates a problem with the include order in a file.""" + pass + + +class FileInfo: + """Provides utility functions for filenames. + + FileInfo provides easy access to the components of a file's path + relative to the project root. + """ + + def __init__(self, filename): + self._filename = filename + + def FullName(self): + """Make Windows paths like Unix.""" + return os.path.abspath(self._filename).replace('\\', '/') + + def RepositoryName(self): + """FullName after removing the local path to the repository. + + If we have a real absolute path name here we can try to do something smart: + detecting the root of the checkout and truncating /path/to/checkout from + the name so that we get header guards that don't include things like + "C:\Documents and Settings\..." or "/home/username/..." in them and thus + people on different computers who have checked the source out to different + locations won't see bogus errors. + """ + fullname = self.FullName() + + if os.path.exists(fullname): + project_dir = os.path.dirname(fullname) + + if os.path.exists(os.path.join(project_dir, ".svn")): + # If there's a .svn file in the current directory, we recursively look + # up the directory tree for the top of the SVN checkout + root_dir = project_dir + one_up_dir = os.path.dirname(root_dir) + while os.path.exists(os.path.join(one_up_dir, ".svn")): + root_dir = os.path.dirname(root_dir) + one_up_dir = os.path.dirname(one_up_dir) + + prefix = os.path.commonprefix([root_dir, project_dir]) + return fullname[len(prefix) + 1:] + + # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by + # searching up from the current path. + root_dir = os.path.dirname(fullname) + while (root_dir != os.path.dirname(root_dir) and + not os.path.exists(os.path.join(root_dir, ".git")) and + not os.path.exists(os.path.join(root_dir, ".hg")) and + not os.path.exists(os.path.join(root_dir, ".svn"))): + root_dir = os.path.dirname(root_dir) + + if (os.path.exists(os.path.join(root_dir, ".git")) or + os.path.exists(os.path.join(root_dir, ".hg")) or + os.path.exists(os.path.join(root_dir, ".svn"))): + prefix = os.path.commonprefix([root_dir, project_dir]) + return fullname[len(prefix) + 1:] + + # Don't know what to do; header guard warnings may be wrong... + return fullname + + def Split(self): + """Splits the file into the directory, basename, and extension. + + For 'chrome/browser/browser.cc', Split() would + return ('chrome/browser', 'browser', '.cc') + + Returns: + A tuple of (directory, basename, extension). + """ + + googlename = self.RepositoryName() + project, rest = os.path.split(googlename) + return (project,) + os.path.splitext(rest) + + def BaseName(self): + """File base name - text after the final slash, before the final period.""" + return self.Split()[1] + + def Extension(self): + """File extension - text following the final period.""" + return self.Split()[2] + + def NoExtension(self): + """File has no source file extension.""" + return '/'.join(self.Split()[0:2]) + + def IsSource(self): + """File has a source file extension.""" + return self.Extension()[1:] in ('c', 'cc', 'cpp', 'cxx') + + +def _ShouldPrintError(category, confidence, linenum): + """If confidence >= verbose, category passes filter and is not suppressed.""" + + # There are three ways we might decide not to print an error message: + # a "NOLINT(category)" comment appears in the source, + # the verbosity level isn't high enough, or the filters filter it out. + if IsErrorSuppressedByNolint(category, linenum): + return False + if confidence < _cpplint_state.verbose_level: + return False + + is_filtered = False + for one_filter in _Filters(): + if one_filter.startswith('-'): + if category.startswith(one_filter[1:]): + is_filtered = True + elif one_filter.startswith('+'): + if category.startswith(one_filter[1:]): + is_filtered = False + else: + assert False # should have been checked for in SetFilter. + if is_filtered: + return False + + return True + + +def Error(filename, linenum, category, confidence, message): + """Logs the fact we've found a lint error. + + We log where the error was found, and also our confidence in the error, + that is, how certain we are this is a legitimate style regression, and + not a misidentification or a use that's sometimes justified. + + False positives can be suppressed by the use of + "cpplint(category)" comments on the offending line. These are + parsed into _error_suppressions. + + Args: + filename: The name of the file containing the error. + linenum: The number of the line containing the error. + category: A string used to describe the "category" this bug + falls under: "whitespace", say, or "runtime". Categories + may have a hierarchy separated by slashes: "whitespace/indent". + confidence: A number from 1-5 representing a confidence score for + the error, with 5 meaning that we are certain of the problem, + and 1 meaning that it could be a legitimate construct. + message: The error message. + """ + if _ShouldPrintError(category, confidence, linenum): + _cpplint_state.IncrementErrorCount(category) + if _cpplint_state.output_format == 'vs7': + sys.stderr.write('%s(%s): %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + else: + sys.stderr.write('%s:%s: %s [%s] [%d]\n' % ( + filename, linenum, message, category, confidence)) + + +# Matches standard C++ escape esequences per 2.13.2.3 of the C++ standard. +_RE_PATTERN_CLEANSE_LINE_ESCAPES = re.compile( + r'\\([abfnrtv?"\\\']|\d+|x[0-9a-fA-F]+)') +# Matches strings. Escape codes should already be removed by ESCAPES. +_RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES = re.compile(r'"[^"]*"') +# Matches characters. Escape codes should already be removed by ESCAPES. +_RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES = re.compile(r"'.'") +# Matches multi-line C++ comments. +# This RE is a little bit more complicated than one might expect, because we +# have to take care of space removals tools so we can handle comments inside +# statements better. +# The current rule is: We only clear spaces from both sides when we're at the +# end of the line. Otherwise, we try to remove spaces from the right side, +# if this doesn't work we try on left side but only if there's a non-character +# on the right. +_RE_PATTERN_CLEANSE_LINE_C_COMMENTS = re.compile( + r"""(\s*/\*.*\*/\s*$| + /\*.*\*/\s+| + \s+/\*.*\*/(?=\W)| + /\*.*\*/)""", re.VERBOSE) + + +def IsCppString(line): + """Does line terminate so, that the next symbol is in string constant. + + This function does not consider single-line nor multi-line comments. + + Args: + line: is a partial line of code starting from the 0..n. + + Returns: + True, if next character appended to 'line' is inside a + string constant. + """ + + line = line.replace(r'\\', 'XX') # after this, \\" does not match to \" + return ((line.count('"') - line.count(r'\"') - line.count("'\"'")) & 1) == 1 + + +def FindNextMultiLineCommentStart(lines, lineix): + """Find the beginning marker for a multiline comment.""" + while lineix < len(lines): + if lines[lineix].strip().startswith('/*'): + # Only return this marker if the comment goes beyond this line + if lines[lineix].strip().find('*/', 2) < 0: + return lineix + lineix += 1 + return len(lines) + + +def FindNextMultiLineCommentEnd(lines, lineix): + """We are inside a comment, find the end marker.""" + while lineix < len(lines): + if lines[lineix].strip().endswith('*/'): + return lineix + lineix += 1 + return len(lines) + + +def RemoveMultiLineCommentsFromRange(lines, begin, end): + """Clears a range of lines for multi-line comments.""" + # Having // dummy comments makes the lines non-empty, so we will not get + # unnecessary blank line warnings later in the code. + for i in range(begin, end): + lines[i] = '// dummy' + + +def RemoveMultiLineComments(filename, lines, error): + """Removes multiline (c-style) comments from lines.""" + lineix = 0 + while lineix < len(lines): + lineix_begin = FindNextMultiLineCommentStart(lines, lineix) + if lineix_begin >= len(lines): + return + lineix_end = FindNextMultiLineCommentEnd(lines, lineix_begin) + if lineix_end >= len(lines): + error(filename, lineix_begin + 1, 'readability/multiline_comment', 5, + 'Could not find end of multi-line comment') + return + RemoveMultiLineCommentsFromRange(lines, lineix_begin, lineix_end + 1) + lineix = lineix_end + 1 + + +def CleanseComments(line): + """Removes //-comments and single-line C-style /* */ comments. + + Args: + line: A line of C++ source. + + Returns: + The line with single-line comments removed. + """ + commentpos = line.find('//') + if commentpos != -1 and not IsCppString(line[:commentpos]): + line = line[:commentpos].rstrip() + # get rid of /* ... */ + return _RE_PATTERN_CLEANSE_LINE_C_COMMENTS.sub('', line) + + +class CleansedLines(object): + """Holds 3 copies of all lines with different preprocessing applied to them. + + 1) elided member contains lines without strings and comments, + 2) lines member contains lines without comments, and + 3) raw member contains all the lines without processing. + All these three members are of , and of the same length. + """ + + def __init__(self, lines): + self.elided = [] + self.lines = [] + self.raw_lines = lines + self.num_lines = len(lines) + for linenum in range(len(lines)): + self.lines.append(CleanseComments(lines[linenum])) + elided = self._CollapseStrings(lines[linenum]) + self.elided.append(CleanseComments(elided)) + + def NumLines(self): + """Returns the number of lines represented.""" + return self.num_lines + + @staticmethod + def _CollapseStrings(elided): + """Collapses strings and chars on a line to simple "" or '' blocks. + + We nix strings first so we're not fooled by text like '"http://"' + + Args: + elided: The line being processed. + + Returns: + The line with collapsed strings. + """ + if not _RE_PATTERN_INCLUDE.match(elided): + # Remove escaped characters first to make quote/single quote collapsing + # basic. Things that look like escaped characters shouldn't occur + # outside of strings and chars. + elided = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', elided) + elided = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", elided) + elided = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', elided) + return elided + + +def CloseExpression(clean_lines, linenum, pos): + """If input points to ( or { or [, finds the position that closes it. + + If lines[linenum][pos] points to a '(' or '{' or '[', finds the + linenum/pos that correspond to the closing of the expression. + + Args: + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + pos: A position on the line. + + Returns: + A tuple (line, linenum, pos) pointer *past* the closing brace, or + (line, len(lines), -1) if we never find a close. Note we ignore + strings and comments when matching; and the line we return is the + 'cleansed' line at linenum. + """ + + line = clean_lines.elided[linenum] + startchar = line[pos] + if startchar not in '({[': + return (line, clean_lines.NumLines(), -1) + if startchar == '(': endchar = ')' + if startchar == '[': endchar = ']' + if startchar == '{': endchar = '}' + + num_open = line.count(startchar) - line.count(endchar) + while linenum < clean_lines.NumLines() and num_open > 0: + linenum += 1 + line = clean_lines.elided[linenum] + num_open += line.count(startchar) - line.count(endchar) + # OK, now find the endchar that actually got us back to even + endpos = len(line) + while num_open >= 0: + endpos = line.rfind(')', 0, endpos) + num_open -= 1 # chopped off another ) + return (line, linenum, endpos + 1) + + +def CheckForCopyright(filename, lines, error): + """Logs an error if no Copyright message appears at the top of the file.""" + + # We'll say it should occur by line 10. Don't forget there's a + # dummy line at the front. + for line in xrange(1, min(len(lines), 11)): + if re.search(r'Copyright', lines[line], re.I): break + else: # means no copyright line was found + error(filename, 0, 'legal/copyright', 5, + 'No copyright message found. ' + 'You should have a line: "Copyright [year] "') + + +def GetHeaderGuardCPPVariable(filename): + """Returns the CPP variable that should be used as a header guard. + + Args: + filename: The name of a C++ header file. + + Returns: + The CPP variable that should be used as a header guard in the + named file. + + """ + + # Restores original filename in case that cpplint is invoked from Emacs's + # flymake. + filename = re.sub(r'_flymake\.h$', '.h', filename) + + fileinfo = FileInfo(filename) + return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_' + + +def CheckForHeaderGuard(filename, lines, error): + """Checks that the file contains a header guard. + + Logs an error if no #ifndef header guard is present. For other + headers, checks that the full pathname is used. + + Args: + filename: The name of the C++ header file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + + cppvar = GetHeaderGuardCPPVariable(filename) + + ifndef = None + ifndef_linenum = 0 + define = None + endif = None + endif_linenum = 0 + for linenum, line in enumerate(lines): + linesplit = line.split() + if len(linesplit) >= 2: + # find the first occurrence of #ifndef and #define, save arg + if not ifndef and linesplit[0] == '#ifndef': + # set ifndef to the header guard presented on the #ifndef line. + ifndef = linesplit[1] + ifndef_linenum = linenum + if not define and linesplit[0] == '#define': + define = linesplit[1] + # find the last occurrence of #endif, save entire line + if line.startswith('#endif'): + endif = line + endif_linenum = linenum + + if not ifndef: + error(filename, 0, 'build/header_guard', 5, + 'No #ifndef header guard found, suggested CPP variable is: %s' % + cppvar) + return + + if not define: + error(filename, 0, 'build/header_guard', 5, + 'No #define header guard found, suggested CPP variable is: %s' % + cppvar) + return + + # The guard should be PATH_FILE_H_, but we also allow PATH_FILE_H__ + # for backward compatibility. + if ifndef != cppvar: + error_level = 0 + if ifndef != cppvar + '_': + error_level = 5 + + ParseNolintSuppressions(filename, lines[ifndef_linenum], ifndef_linenum, + error) + error(filename, ifndef_linenum, 'build/header_guard', error_level, + '#ifndef header guard has wrong style, please use: %s' % cppvar) + + if define != ifndef: + error(filename, 0, 'build/header_guard', 5, + '#ifndef and #define don\'t match, suggested CPP variable is: %s' % + cppvar) + return + + if endif != ('#endif // %s' % cppvar): + error_level = 0 + if endif != ('#endif // %s' % (cppvar + '_')): + error_level = 5 + + ParseNolintSuppressions(filename, lines[endif_linenum], endif_linenum, + error) + error(filename, endif_linenum, 'build/header_guard', error_level, + '#endif line should be "#endif // %s"' % cppvar) + + +def CheckForUnicodeReplacementCharacters(filename, lines, error): + """Logs an error for each line containing Unicode replacement characters. + + These indicate that either the file contained invalid UTF-8 (likely) + or Unicode replacement characters (which it shouldn't). Note that + it's possible for this to throw off line numbering if the invalid + UTF-8 occurred adjacent to a newline. + + Args: + filename: The name of the current file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + for linenum, line in enumerate(lines): + if u'\ufffd' in line: + error(filename, linenum, 'readability/utf8', 5, + 'Line contains invalid UTF-8 (or Unicode replacement character).') + + +def CheckForNewlineAtEOF(filename, lines, error): + """Logs an error if there is no newline char at the end of the file. + + Args: + filename: The name of the current file. + lines: An array of strings, each representing a line of the file. + error: The function to call with any errors found. + """ + + # The array lines() was created by adding two newlines to the + # original file (go figure), then splitting on \n. + # To verify that the file ends in \n, we just have to make sure the + # last-but-two element of lines() exists and is empty. + if len(lines) < 3 or lines[-2]: + error(filename, len(lines) - 2, 'whitespace/ending_newline', 5, + 'Could not find a newline character at the end of the file.') + + +def CheckForMultilineCommentsAndStrings(filename, clean_lines, linenum, error): + """Logs an error if we see /* ... */ or "..." that extend past one line. + + /* ... */ comments are legit inside macros, for one line. + Otherwise, we prefer // comments, so it's ok to warn about the + other. Likewise, it's ok for strings to extend across multiple + lines, as long as a line continuation character (backslash) + terminates each line. Although not currently prohibited by the C++ + style guide, it's ugly and unnecessary. We don't do well with either + in this lint program, so we warn about both. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + + # Remove all \\ (escaped backslashes) from the line. They are OK, and the + # second (escaped) slash may trigger later \" detection erroneously. + line = line.replace('\\\\', '') + + if line.count('/*') > line.count('*/'): + error(filename, linenum, 'readability/multiline_comment', 5, + 'Complex multi-line /*...*/-style comment found. ' + 'Lint may give bogus warnings. ' + 'Consider replacing these with //-style comments, ' + 'with #if 0...#endif, ' + 'or with more clearly structured multi-line comments.') + + if (line.count('"') - line.count('\\"')) % 2: + error(filename, linenum, 'readability/multiline_string', 5, + 'Multi-line string ("...") found. This lint script doesn\'t ' + 'do well with such strings, and may give bogus warnings. They\'re ' + 'ugly and unnecessary, and you should use concatenation instead".') + + +threading_list = ( + ('asctime(', 'asctime_r('), + ('ctime(', 'ctime_r('), + ('getgrgid(', 'getgrgid_r('), + ('getgrnam(', 'getgrnam_r('), + ('getlogin(', 'getlogin_r('), + ('getpwnam(', 'getpwnam_r('), + ('getpwuid(', 'getpwuid_r('), + ('gmtime(', 'gmtime_r('), + ('localtime(', 'localtime_r('), + ('rand(', 'rand_r('), + ('readdir(', 'readdir_r('), + ('strtok(', 'strtok_r('), + ('ttyname(', 'ttyname_r('), + ) + + +def CheckPosixThreading(filename, clean_lines, linenum, error): + """Checks for calls to thread-unsafe functions. + + Much code has been originally written without consideration of + multi-threading. Also, engineers are relying on their old experience; + they have learned posix before threading extensions were added. These + tests guide the engineers to use thread-safe functions (when using + posix directly). + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + for single_thread_function, multithread_safe_function in threading_list: + ix = line.find(single_thread_function) + # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 + if ix >= 0 and (ix == 0 or (not line[ix - 1].isalnum() and + line[ix - 1] not in ('_', '.', '>'))): + error(filename, linenum, 'runtime/threadsafe_fn', 2, + 'Consider using ' + multithread_safe_function + + '...) instead of ' + single_thread_function + + '...) for improved thread safety.') + + +# Matches invalid increment: *count++, which moves pointer instead of +# incrementing a value. +_RE_PATTERN_INVALID_INCREMENT = re.compile( + r'^\s*\*\w+(\+\+|--);') + + +def CheckInvalidIncrement(filename, clean_lines, linenum, error): + """Checks for invalid increment *count++. + + For example following function: + void increment_counter(int* count) { + *count++; + } + is invalid, because it effectively does count++, moving pointer, and should + be replaced with ++*count, (*count)++ or *count += 1. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + line = clean_lines.elided[linenum] + if _RE_PATTERN_INVALID_INCREMENT.match(line): + error(filename, linenum, 'runtime/invalid_increment', 5, + 'Changing pointer instead of value (or unused value of operator*).') + + +class _ClassInfo(object): + """Stores information about a class.""" + + def __init__(self, name, clean_lines, linenum): + self.name = name + self.linenum = linenum + self.seen_open_brace = False + self.is_derived = False + self.virtual_method_linenumber = None + self.has_virtual_destructor = False + self.brace_depth = 0 + + # Try to find the end of the class. This will be confused by things like: + # class A { + # } *x = { ... + # + # But it's still good enough for CheckSectionSpacing. + self.last_line = 0 + depth = 0 + for i in range(linenum, clean_lines.NumLines()): + line = clean_lines.lines[i] + depth += line.count('{') - line.count('}') + if not depth: + self.last_line = i + break + + +class _ClassState(object): + """Holds the current state of the parse relating to class declarations. + + It maintains a stack of _ClassInfos representing the parser's guess + as to the current nesting of class declarations. The innermost class + is at the top (back) of the stack. Typically, the stack will either + be empty or have exactly one entry. + """ + + def __init__(self): + self.classinfo_stack = [] + + def CheckFinished(self, filename, error): + """Checks that all classes have been completely parsed. + + Call this when all lines in a file have been processed. + Args: + filename: The name of the current file. + error: The function to call with any errors found. + """ + if self.classinfo_stack: + # Note: This test can result in false positives if #ifdef constructs + # get in the way of brace matching. See the testBuildClass test in + # cpplint_unittest.py for an example of this. + error(filename, self.classinfo_stack[0].linenum, 'build/class', 5, + 'Failed to find complete declaration of class %s' % + self.classinfo_stack[0].name) + + +def CheckForNonStandardConstructs(filename, clean_lines, linenum, + class_state, error): + """Logs an error if we see certain non-ANSI constructs ignored by gcc-2. + + Complain about several constructs which gcc-2 accepts, but which are + not standard C++. Warning about these in lint is one way to ease the + transition to new compilers. + - put storage class first (e.g. "static const" instead of "const static"). + - "%lld" instead of %qd" in printf-type functions. + - "%1$d" is non-standard in printf-type functions. + - "\%" is an undefined character escape sequence. + - text after #endif is not allowed. + - invalid inner-style forward declaration. + - >? and ?= and )\?=?\s*(\w+|[+-]?\d+)(\.\d*)?', + line): + error(filename, linenum, 'build/deprecated', 3, + '>? and ))?' + # r'\s*const\s*' + type_name + '\s*&\s*\w+\s*;' + error(filename, linenum, 'runtime/member_string_references', 2, + 'const string& members are dangerous. It is much better to use ' + 'alternatives, such as pointers or simple constants.') + + # Track class entry and exit, and attempt to find cases within the + # class declaration that don't meet the C++ style + # guidelines. Tracking is very dependent on the code matching Google + # style guidelines, but it seems to perform well enough in testing + # to be a worthwhile addition to the checks. + classinfo_stack = class_state.classinfo_stack + # Look for a class declaration. The regexp accounts for decorated classes + # such as in: + # class LOCKABLE API Object { + # }; + class_decl_match = Match( + r'\s*(template\s*<[\w\s<>,:]*>\s*)?' + '(class|struct)\s+([A-Z_]+\s+)*(\w+(::\w+)*)', line) + if class_decl_match: + classinfo_stack.append(_ClassInfo( + class_decl_match.group(4), clean_lines, linenum)) + + # Everything else in this function uses the top of the stack if it's + # not empty. + if not classinfo_stack: + return + + classinfo = classinfo_stack[-1] + + # If the opening brace hasn't been seen look for it and also + # parent class declarations. + if not classinfo.seen_open_brace: + # If the line has a ';' in it, assume it's a forward declaration or + # a single-line class declaration, which we won't process. + if line.find(';') != -1: + classinfo_stack.pop() + return + classinfo.seen_open_brace = (line.find('{') != -1) + # Look for a bare ':' + if Search('(^|[^:]):($|[^:])', line): + classinfo.is_derived = True + if not classinfo.seen_open_brace: + return # Everything else in this function is for after open brace + + # The class may have been declared with namespace or classname qualifiers. + # The constructor and destructor will not have those qualifiers. + base_classname = classinfo.name.split('::')[-1] + + # Look for single-argument constructors that aren't marked explicit. + # Technically a valid construct, but against style. + args = Match(r'\s+(?:inline\s+)?%s\s*\(([^,()]+)\)' + % re.escape(base_classname), + line) + if (args and + args.group(1) != 'void' and + not Match(r'(const\s+)?%s\s*(?:<\w+>\s*)?&' % re.escape(base_classname), + args.group(1).strip())): + error(filename, linenum, 'runtime/explicit', 5, + 'Single-argument constructors should be marked explicit.') + + # Look for methods declared virtual. + if Search(r'\bvirtual\b', line): + classinfo.virtual_method_linenumber = linenum + # Only look for a destructor declaration on the same line. It would + # be extremely unlikely for the destructor declaration to occupy + # more than one line. + if Search(r'~%s\s*\(' % base_classname, line): + classinfo.has_virtual_destructor = True + + # Look for class end. + brace_depth = classinfo.brace_depth + brace_depth = brace_depth + line.count('{') - line.count('}') + if brace_depth <= 0: + classinfo = classinfo_stack.pop() + # Try to detect missing virtual destructor declarations. + # For now, only warn if a non-derived class with virtual methods lacks + # a virtual destructor. This is to make it less likely that people will + # declare derived virtual destructors without declaring the base + # destructor virtual. + if ((classinfo.virtual_method_linenumber is not None) and + (not classinfo.has_virtual_destructor) and + (not classinfo.is_derived)): # Only warn for base classes + error(filename, classinfo.linenum, 'runtime/virtual', 4, + 'The class %s probably needs a virtual destructor due to ' + 'having virtual method(s), one declared at line %d.' + % (classinfo.name, classinfo.virtual_method_linenumber)) + else: + classinfo.brace_depth = brace_depth + + +def CheckSpacingForFunctionCall(filename, line, linenum, error): + """Checks for the correctness of various spacing around function calls. + + Args: + filename: The name of the current file. + line: The text of the line to check. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + # Since function calls often occur inside if/for/while/switch + # expressions - which have their own, more liberal conventions - we + # first see if we should be looking inside such an expression for a + # function call, to which we can apply more strict standards. + fncall = line # if there's no control flow construct, look at whole line + for pattern in (r'\bif\s*\((.*)\)\s*{', + r'\bfor\s*\((.*)\)\s*{', + r'\bwhile\s*\((.*)\)\s*[{;]', + r'\bswitch\s*\((.*)\)\s*{'): + match = Search(pattern, line) + if match: + fncall = match.group(1) # look inside the parens for function calls + break + + # Except in if/for/while/switch, there should never be space + # immediately inside parens (eg "f( 3, 4 )"). We make an exception + # for nested parens ( (a+b) + c ). Likewise, there should never be + # a space before a ( when it's a function argument. I assume it's a + # function argument when the char before the whitespace is legal in + # a function name (alnum + _) and we're not starting a macro. Also ignore + # pointers and references to arrays and functions coz they're too tricky: + # we use a very simple way to recognize these: + # " (something)(maybe-something)" or + # " (something)(maybe-something," or + # " (something)[something]" + # Note that we assume the contents of [] to be short enough that + # they'll never need to wrap. + if ( # Ignore control structures. + not Search(r'\b(if|for|while|switch|return|delete)\b', fncall) and + # Ignore pointers/references to functions. + not Search(r' \([^)]+\)\([^)]*(\)|,$)', fncall) and + # Ignore pointers/references to arrays. + not Search(r' \([^)]+\)\[[^\]]+\]', fncall)): + if Search(r'\w\s*\(\s(?!\s*\\$)', fncall): # a ( used for a fn call + error(filename, linenum, 'whitespace/parens', 4, + 'Extra space after ( in function call') + elif Search(r'\(\s+(?!(\s*\\)|\()', fncall): + error(filename, linenum, 'whitespace/parens', 2, + 'Extra space after (') + if (Search(r'\w\s+\(', fncall) and + not Search(r'#\s*define|typedef', fncall)): + error(filename, linenum, 'whitespace/parens', 4, + 'Extra space before ( in function call') + # If the ) is followed only by a newline or a { + newline, assume it's + # part of a control statement (if/while/etc), and don't complain + if Search(r'[^)]\s+\)\s*[^{\s]', fncall): + # If the closing parenthesis is preceded by only whitespaces, + # try to give a more descriptive error message. + if Search(r'^\s+\)', fncall): + error(filename, linenum, 'whitespace/parens', 2, + 'Closing ) should be moved to the previous line') + else: + error(filename, linenum, 'whitespace/parens', 2, + 'Extra space before )') + + +def IsBlankLine(line): + """Returns true if the given line is blank. + + We consider a line to be blank if the line is empty or consists of + only white spaces. + + Args: + line: A line of a string. + + Returns: + True, if the given line is blank. + """ + return not line or line.isspace() + + +def CheckForFunctionLengths(filename, clean_lines, linenum, + function_state, error): + """Reports for long function bodies. + + For an overview why this is done, see: + http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions + + Uses a simplistic algorithm assuming other style guidelines + (especially spacing) are followed. + Only checks unindented functions, so class members are unchecked. + Trivial bodies are unchecked, so constructors with huge initializer lists + may be missed. + Blank/comment lines are not counted so as to avoid encouraging the removal + of vertical space and comments just to get through a lint check. + NOLINT *on the last line of a function* disables this check. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + function_state: Current function name and lines in body so far. + error: The function to call with any errors found. + """ + lines = clean_lines.lines + line = lines[linenum] + raw = clean_lines.raw_lines + raw_line = raw[linenum] + joined_line = '' + + starting_func = False + regexp = r'(\w(\w|::|\*|\&|\s)*)\(' # decls * & space::name( ... + match_result = Match(regexp, line) + if match_result: + # If the name is all caps and underscores, figure it's a macro and + # ignore it, unless it's TEST or TEST_F. + function_name = match_result.group(1).split()[-1] + if function_name == 'TEST' or function_name == 'TEST_F' or ( + not Match(r'[A-Z_]+$', function_name)): + starting_func = True + + if starting_func: + body_found = False + for start_linenum in xrange(linenum, clean_lines.NumLines()): + start_line = lines[start_linenum] + joined_line += ' ' + start_line.lstrip() + if Search(r'(;|})', start_line): # Declarations and trivial functions + body_found = True + break # ... ignore + elif Search(r'{', start_line): + body_found = True + function = Search(r'((\w|:)*)\(', line).group(1) + if Match(r'TEST', function): # Handle TEST... macros + parameter_regexp = Search(r'(\(.*\))', joined_line) + if parameter_regexp: # Ignore bad syntax + function += parameter_regexp.group(1) + else: + function += '()' + function_state.Begin(function) + break + if not body_found: + # No body for the function (or evidence of a non-function) was found. + error(filename, linenum, 'readability/fn_size', 5, + 'Lint failed to find start of function body.') + elif Match(r'^\}\s*$', line): # function end + function_state.Check(error, filename, linenum) + function_state.End() + elif not Match(r'^\s*$', line): + function_state.Count() # Count non-blank/non-comment lines. + + +_RE_PATTERN_TODO = re.compile(r'^//(\s*)TODO(\(.+?\))?:?(\s|$)?') + + +def CheckComment(comment, filename, linenum, error): + """Checks for common mistakes in TODO comments. + + Args: + comment: The text of the comment from the line in question. + filename: The name of the current file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + match = _RE_PATTERN_TODO.match(comment) + if match: + # One whitespace is correct; zero whitespace is handled elsewhere. + leading_whitespace = match.group(1) + if len(leading_whitespace) > 1: + error(filename, linenum, 'whitespace/todo', 2, + 'Too many spaces before TODO') + + username = match.group(2) + if not username: + error(filename, linenum, 'readability/todo', 2, + 'Missing username in TODO; it should look like ' + '"// TODO(my_username): Stuff."') + + middle_whitespace = match.group(3) + # Comparisons made explicit for correctness -- pylint: disable-msg=C6403 + if middle_whitespace != ' ' and middle_whitespace != '': + error(filename, linenum, 'whitespace/todo', 2, + 'TODO(my_username) should be followed by a space') + + +def CheckSpacing(filename, clean_lines, linenum, error): + """Checks for the correctness of various spacing issues in the code. + + Things we check for: spaces around operators, spaces after + if/for/while/switch, no spaces around parens in function calls, two + spaces between code and comment, don't start a block with a blank + line, don't end a function with a blank line, don't add a blank line + after public/protected/private, don't have too many blank lines in a row. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + raw = clean_lines.raw_lines + line = raw[linenum] + + # Before nixing comments, check if the line is blank for no good + # reason. This includes the first line after a block is opened, and + # blank lines at the end of a function (ie, right before a line like '}' + if IsBlankLine(line): + elided = clean_lines.elided + prev_line = elided[linenum - 1] + prevbrace = prev_line.rfind('{') + # TODO(unknown): Don't complain if line before blank line, and line after, + # both start with alnums and are indented the same amount. + # This ignores whitespace at the start of a namespace block + # because those are not usually indented. + if (prevbrace != -1 and prev_line[prevbrace:].find('}') == -1 + and prev_line[:prevbrace].find('namespace') == -1): + # OK, we have a blank line at the start of a code block. Before we + # complain, we check if it is an exception to the rule: The previous + # non-empty line has the parameters of a function header that are indented + # 4 spaces (because they did not fit in a 80 column line when placed on + # the same line as the function name). We also check for the case where + # the previous line is indented 6 spaces, which may happen when the + # initializers of a constructor do not fit into a 80 column line. + exception = False + if Match(r' {6}\w', prev_line): # Initializer list? + # We are looking for the opening column of initializer list, which + # should be indented 4 spaces to cause 6 space indentation afterwards. + search_position = linenum-2 + while (search_position >= 0 + and Match(r' {6}\w', elided[search_position])): + search_position -= 1 + exception = (search_position >= 0 + and elided[search_position][:5] == ' :') + else: + # Search for the function arguments or an initializer list. We use a + # simple heuristic here: If the line is indented 4 spaces; and we have a + # closing paren, without the opening paren, followed by an opening brace + # or colon (for initializer lists) we assume that it is the last line of + # a function header. If we have a colon indented 4 spaces, it is an + # initializer list. + exception = (Match(r' {4}\w[^\(]*\)\s*(const\s*)?(\{\s*$|:)', + prev_line) + or Match(r' {4}:', prev_line)) + + if not exception: + error(filename, linenum, 'whitespace/blank_line', 2, + 'Blank line at the start of a code block. Is this needed?') + # This doesn't ignore whitespace at the end of a namespace block + # because that is too hard without pairing open/close braces; + # however, a special exception is made for namespace closing + # brackets which have a comment containing "namespace". + # + # Also, ignore blank lines at the end of a block in a long if-else + # chain, like this: + # if (condition1) { + # // Something followed by a blank line + # + # } else if (condition2) { + # // Something else + # } + if linenum + 1 < clean_lines.NumLines(): + next_line = raw[linenum + 1] + if (next_line + and Match(r'\s*}', next_line) + and next_line.find('namespace') == -1 + and next_line.find('} else ') == -1): + error(filename, linenum, 'whitespace/blank_line', 3, + 'Blank line at the end of a code block. Is this needed?') + + matched = Match(r'\s*(public|protected|private):', prev_line) + if matched: + error(filename, linenum, 'whitespace/blank_line', 3, + 'Do not leave a blank line after "%s:"' % matched.group(1)) + + # Next, we complain if there's a comment too near the text + commentpos = line.find('//') + if commentpos != -1: + # Check if the // may be in quotes. If so, ignore it + # Comparisons made explicit for clarity -- pylint: disable-msg=C6403 + if (line.count('"', 0, commentpos) - + line.count('\\"', 0, commentpos)) % 2 == 0: # not in quotes + # Allow one space for new scopes, two spaces otherwise: + if (not Match(r'^\s*{ //', line) and + ((commentpos >= 1 and + line[commentpos-1] not in string.whitespace) or + (commentpos >= 2 and + line[commentpos-2] not in string.whitespace))): + error(filename, linenum, 'whitespace/comments', 2, + 'At least two spaces is best between code and comments') + # There should always be a space between the // and the comment + commentend = commentpos + 2 + if commentend < len(line) and not line[commentend] == ' ': + # but some lines are exceptions -- e.g. if they're big + # comment delimiters like: + # //---------------------------------------------------------- + # or are an empty C++ style Doxygen comment, like: + # /// + # or they begin with multiple slashes followed by a space: + # //////// Header comment + match = (Search(r'[=/-]{4,}\s*$', line[commentend:]) or + Search(r'^/$', line[commentend:]) or + Search(r'^/+ ', line[commentend:])) + if not match: + error(filename, linenum, 'whitespace/comments', 4, + 'Should have a space between // and comment') + CheckComment(line[commentpos:], filename, linenum, error) + + line = clean_lines.elided[linenum] # get rid of comments and strings + + # Don't try to do spacing checks for operator methods + line = re.sub(r'operator(==|!=|<|<<|<=|>=|>>|>)\(', 'operator\(', line) + + # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )". + # Otherwise not. Note we only check for non-spaces on *both* sides; + # sometimes people put non-spaces on one side when aligning ='s among + # many lines (not that this is behavior that I approve of...) + if Search(r'[\w.]=[\w.]', line) and not Search(r'\b(if|while) ', line): + error(filename, linenum, 'whitespace/operators', 4, + 'Missing spaces around =') + + # It's ok not to have spaces around binary operators like + - * /, but if + # there's too little whitespace, we get concerned. It's hard to tell, + # though, so we punt on this one for now. TODO. + + # You should always have whitespace around binary operators. + # Alas, we can't test < or > because they're legitimately used sans spaces + # (a->b, vector a). The only time we can tell is a < with no >, and + # only if it's not template params list spilling into the next line. + match = Search(r'[^<>=!\s](==|!=|<=|>=)[^<>=!\s]', line) + if not match: + # Note that while it seems that the '<[^<]*' term in the following + # regexp could be simplified to '<.*', which would indeed match + # the same class of strings, the [^<] means that searching for the + # regexp takes linear rather than quadratic time. + if not Search(r'<[^<]*,\s*$', line): # template params spill + match = Search(r'[^<>=!\s](<)[^<>=!\s]([^>]|->)*$', line) + if match: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around %s' % match.group(1)) + # We allow no-spaces around << and >> when used like this: 10<<20, but + # not otherwise (particularly, not when used as streams) + match = Search(r'[^0-9\s](<<|>>)[^0-9\s]', line) + if match: + error(filename, linenum, 'whitespace/operators', 3, + 'Missing spaces around %s' % match.group(1)) + + # There shouldn't be space around unary operators + match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line) + if match: + error(filename, linenum, 'whitespace/operators', 4, + 'Extra space for operator %s' % match.group(1)) + + # A pet peeve of mine: no spaces after an if, while, switch, or for + match = Search(r' (if\(|for\(|while\(|switch\()', line) + if match: + error(filename, linenum, 'whitespace/parens', 5, + 'Missing space before ( in %s' % match.group(1)) + + # For if/for/while/switch, the left and right parens should be + # consistent about how many spaces are inside the parens, and + # there should either be zero or one spaces inside the parens. + # We don't want: "if ( foo)" or "if ( foo )". + # Exception: "for ( ; foo; bar)" and "for (foo; bar; )" are allowed. + match = Search(r'\b(if|for|while|switch)\s*' + r'\(([ ]*)(.).*[^ ]+([ ]*)\)\s*{\s*$', + line) + if match: + if len(match.group(2)) != len(match.group(4)): + if not (match.group(3) == ';' and + len(match.group(2)) == 1 + len(match.group(4)) or + not match.group(2) and Search(r'\bfor\s*\(.*; \)', line)): + error(filename, linenum, 'whitespace/parens', 5, + 'Mismatching spaces inside () in %s' % match.group(1)) + if not len(match.group(2)) in [0, 1]: + error(filename, linenum, 'whitespace/parens', 5, + 'Should have zero or one spaces inside ( and ) in %s' % + match.group(1)) + + # You should always have a space after a comma (either as fn arg or operator) + if Search(r',[^\s]', line): + error(filename, linenum, 'whitespace/comma', 3, + 'Missing space after ,') + + # You should always have a space after a semicolon + # except for few corner cases + # TODO(unknown): clarify if 'if (1) { return 1;}' is requires one more + # space after ; + if Search(r';[^\s};\\)/]', line): + error(filename, linenum, 'whitespace/semicolon', 3, + 'Missing space after ;') + + # Next we will look for issues with function calls. + CheckSpacingForFunctionCall(filename, line, linenum, error) + + # Except after an opening paren, or after another opening brace (in case of + # an initializer list, for instance), you should have spaces before your + # braces. And since you should never have braces at the beginning of a line, + # this is an easy test. + if Search(r'[^ ({]{', line): + error(filename, linenum, 'whitespace/braces', 5, + 'Missing space before {') + + # Make sure '} else {' has spaces. + if Search(r'}else', line): + error(filename, linenum, 'whitespace/braces', 5, + 'Missing space before else') + + # You shouldn't have spaces before your brackets, except maybe after + # 'delete []' or 'new char * []'. + if Search(r'\w\s+\[', line) and not Search(r'delete\s+\[', line): + error(filename, linenum, 'whitespace/braces', 5, + 'Extra space before [') + + # You shouldn't have a space before a semicolon at the end of the line. + # There's a special case for "for" since the style guide allows space before + # the semicolon there. + if Search(r':\s*;\s*$', line): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Semicolon defining empty statement. Use { } instead.') + elif Search(r'^\s*;\s*$', line): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Line contains only semicolon. If this should be an empty statement, ' + 'use { } instead.') + elif (Search(r'\s+;\s*$', line) and + not Search(r'\bfor\b', line)): + error(filename, linenum, 'whitespace/semicolon', 5, + 'Extra space before last semicolon. If this should be an empty ' + 'statement, use { } instead.') + + +def CheckSectionSpacing(filename, clean_lines, class_info, linenum, error): + """Checks for additional blank line issues related to sections. + + Currently the only thing checked here is blank line before protected/private. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + class_info: A _ClassInfo objects. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + # Skip checks if the class is small, where small means 25 lines or less. + # 25 lines seems like a good cutoff since that's the usual height of + # terminals, and any class that can't fit in one screen can't really + # be considered "small". + # + # Also skip checks if we are on the first line. This accounts for + # classes that look like + # class Foo { public: ... }; + # + # If we didn't find the end of the class, last_line would be zero, + # and the check will be skipped by the first condition. + if (class_info.last_line - class_info.linenum <= 24 or + linenum <= class_info.linenum): + return + + matched = Match(r'\s*(public|protected|private):', clean_lines.lines[linenum]) + if matched: + # Issue warning if the line before public/protected/private was + # not a blank line, but don't do this if the previous line contains + # "class" or "struct". This can happen two ways: + # - We are at the beginning of the class. + # - We are forward-declaring an inner class that is semantically + # private, but needed to be public for implementation reasons. + prev_line = clean_lines.lines[linenum - 1] + if (not IsBlankLine(prev_line) and + not Search(r'\b(class|struct)\b', prev_line)): + # Try a bit harder to find the beginning of the class. This is to + # account for multi-line base-specifier lists, e.g.: + # class Derived + # : public Base { + end_class_head = class_info.linenum + for i in range(class_info.linenum, linenum): + if Search(r'\{\s*$', clean_lines.lines[i]): + end_class_head = i + break + if end_class_head < linenum - 1: + error(filename, linenum, 'whitespace/blank_line', 3, + '"%s:" should be preceded by a blank line' % matched.group(1)) + + +def GetPreviousNonBlankLine(clean_lines, linenum): + """Return the most recent non-blank line and its line number. + + Args: + clean_lines: A CleansedLines instance containing the file contents. + linenum: The number of the line to check. + + Returns: + A tuple with two elements. The first element is the contents of the last + non-blank line before the current line, or the empty string if this is the + first non-blank line. The second is the line number of that line, or -1 + if this is the first non-blank line. + """ + + prevlinenum = linenum - 1 + while prevlinenum >= 0: + prevline = clean_lines.elided[prevlinenum] + if not IsBlankLine(prevline): # if not a blank line... + return (prevline, prevlinenum) + prevlinenum -= 1 + return ('', -1) + + +def CheckBraces(filename, clean_lines, linenum, error): + """Looks for misplaced braces (e.g. at the end of line). + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + line = clean_lines.elided[linenum] # get rid of comments and strings + + if Match(r'\s*{\s*$', line): + # We allow an open brace to start a line in the case where someone + # is using braces in a block to explicitly create a new scope, + # which is commonly used to control the lifetime of + # stack-allocated variables. We don't detect this perfectly: we + # just don't complain if the last non-whitespace character on the + # previous non-blank line is ';', ':', '{', or '}'. + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if not Search(r'[;:}{]\s*$', prevline): + error(filename, linenum, 'whitespace/braces', 4, + '{ should almost always be at the end of the previous line') + + # An else clause should be on the same line as the preceding closing brace. + if Match(r'\s*else\s*', line): + prevline = GetPreviousNonBlankLine(clean_lines, linenum)[0] + if Match(r'\s*}\s*$', prevline): + error(filename, linenum, 'whitespace/newline', 4, + 'An else should appear on the same line as the preceding }') + + # If braces come on one side of an else, they should be on both. + # However, we have to worry about "else if" that spans multiple lines! + if Search(r'}\s*else[^{]*$', line) or Match(r'[^}]*else\s*{', line): + if Search(r'}\s*else if([^{]*)$', line): # could be multi-line if + # find the ( after the if + pos = line.find('else if') + pos = line.find('(', pos) + if pos > 0: + (endline, _, endpos) = CloseExpression(clean_lines, linenum, pos) + if endline[endpos:].find('{') == -1: # must be brace after if + error(filename, linenum, 'readability/braces', 5, + 'If an else has a brace on one side, it should have it on both') + else: # common case: else not followed by a multi-line if + error(filename, linenum, 'readability/braces', 5, + 'If an else has a brace on one side, it should have it on both') + + # Likewise, an else should never have the else clause on the same line + if Search(r'\belse [^\s{]', line) and not Search(r'\belse if\b', line): + error(filename, linenum, 'whitespace/newline', 4, + 'Else clause should never be on same line as else (use 2 lines)') + + # In the same way, a do/while should never be on one line + if Match(r'\s*do [^\s{]', line): + error(filename, linenum, 'whitespace/newline', 4, + 'do/while clauses should not be on a single line') + + # Braces shouldn't be followed by a ; unless they're defining a struct + # or initializing an array. + # We can't tell in general, but we can for some common cases. + prevlinenum = linenum + while True: + (prevline, prevlinenum) = GetPreviousNonBlankLine(clean_lines, prevlinenum) + if Match(r'\s+{.*}\s*;', line) and not prevline.count(';'): + line = prevline + line + else: + break + if (Search(r'{.*}\s*;', line) and + line.count('{') == line.count('}') and + not Search(r'struct|class|enum|\s*=\s*{', line)): + error(filename, linenum, 'readability/braces', 4, + "You don't need a ; after a }") + + +def ReplaceableCheck(operator, macro, line): + """Determine whether a basic CHECK can be replaced with a more specific one. + + For example suggest using CHECK_EQ instead of CHECK(a == b) and + similarly for CHECK_GE, CHECK_GT, CHECK_LE, CHECK_LT, CHECK_NE. + + Args: + operator: The C++ operator used in the CHECK. + macro: The CHECK or EXPECT macro being called. + line: The current source line. + + Returns: + True if the CHECK can be replaced with a more specific one. + """ + + # This matches decimal and hex integers, strings, and chars (in that order). + match_constant = r'([-+]?(\d+|0[xX][0-9a-fA-F]+)[lLuU]{0,3}|".*"|\'.*\')' + + # Expression to match two sides of the operator with something that + # looks like a literal, since CHECK(x == iterator) won't compile. + # This means we can't catch all the cases where a more specific + # CHECK is possible, but it's less annoying than dealing with + # extraneous warnings. + match_this = (r'\s*' + macro + r'\((\s*' + + match_constant + r'\s*' + operator + r'[^<>].*|' + r'.*[^<>]' + operator + r'\s*' + match_constant + + r'\s*\))') + + # Don't complain about CHECK(x == NULL) or similar because + # CHECK_EQ(x, NULL) won't compile (requires a cast). + # Also, don't complain about more complex boolean expressions + # involving && or || such as CHECK(a == b || c == d). + return Match(match_this, line) and not Search(r'NULL|&&|\|\|', line) + + +def CheckCheck(filename, clean_lines, linenum, error): + """Checks the use of CHECK and EXPECT macros. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + + # Decide the set of replacement macros that should be suggested + raw_lines = clean_lines.raw_lines + current_macro = '' + for macro in _CHECK_MACROS: + if raw_lines[linenum].find(macro) >= 0: + current_macro = macro + break + if not current_macro: + # Don't waste time here if line doesn't contain 'CHECK' or 'EXPECT' + return + + line = clean_lines.elided[linenum] # get rid of comments and strings + + # Encourage replacing plain CHECKs with CHECK_EQ/CHECK_NE/etc. + for operator in ['==', '!=', '>=', '>', '<=', '<']: + if ReplaceableCheck(operator, current_macro, line): + error(filename, linenum, 'readability/check', 2, + 'Consider using %s instead of %s(a %s b)' % ( + _CHECK_REPLACEMENT[current_macro][operator], + current_macro, operator)) + break + + +def GetLineWidth(line): + """Determines the width of the line in column positions. + + Args: + line: A string, which may be a Unicode string. + + Returns: + The width of the line in column positions, accounting for Unicode + combining characters and wide characters. + """ + if isinstance(line, unicode): + width = 0 + for uc in unicodedata.normalize('NFC', line): + if unicodedata.east_asian_width(uc) in ('W', 'F'): + width += 2 + elif not unicodedata.combining(uc): + width += 1 + return width + else: + return len(line) + + +def CheckStyle(filename, clean_lines, linenum, file_extension, class_state, + error): + """Checks rules from the 'C++ style rules' section of cppguide.html. + + Most of these rules are hard to test (naming, comment style), but we + do what we can. In particular we check for 2-space indents, line lengths, + tab usage, spaces inside code, etc. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + file_extension: The extension (without the dot) of the filename. + error: The function to call with any errors found. + """ + + raw_lines = clean_lines.raw_lines + line = raw_lines[linenum] + + if line.find('\t') != -1: + error(filename, linenum, 'whitespace/tab', 1, + 'Tab found; better to use spaces') + + # One or three blank spaces at the beginning of the line is weird; it's + # hard to reconcile that with 2-space indents. + # NOTE: here are the conditions rob pike used for his tests. Mine aren't + # as sophisticated, but it may be worth becoming so: RLENGTH==initial_spaces + # if(RLENGTH > 20) complain = 0; + # if(match($0, " +(error|private|public|protected):")) complain = 0; + # if(match(prev, "&& *$")) complain = 0; + # if(match(prev, "\\|\\| *$")) complain = 0; + # if(match(prev, "[\",=><] *$")) complain = 0; + # if(match($0, " <<")) complain = 0; + # if(match(prev, " +for \\(")) complain = 0; + # if(prevodd && match(prevprev, " +for \\(")) complain = 0; + initial_spaces = 0 + cleansed_line = clean_lines.elided[linenum] + while initial_spaces < len(line) and line[initial_spaces] == ' ': + initial_spaces += 1 + if line and line[-1].isspace(): + error(filename, linenum, 'whitespace/end_of_line', 4, + 'Line ends in whitespace. Consider deleting these extra spaces.') + # There are certain situations we allow one space, notably for labels + elif ((initial_spaces == 1 or initial_spaces == 3) and + not Match(r'\s*\w+\s*:\s*$', cleansed_line)): + error(filename, linenum, 'whitespace/indent', 3, + 'Weird number of spaces at line-start. ' + 'Are you using a 2-space indent?') + # Labels should always be indented at least one space. + elif not initial_spaces and line[:2] != '//' and Search(r'[^:]:\s*$', + line): + error(filename, linenum, 'whitespace/labels', 4, + 'Labels should always be indented at least one space. ' + 'If this is a member-initializer list in a constructor or ' + 'the base class list in a class definition, the colon should ' + 'be on the following line.') + + + # Check if the line is a header guard. + is_header_guard = False + if file_extension == 'h': + cppvar = GetHeaderGuardCPPVariable(filename) + if (line.startswith('#ifndef %s' % cppvar) or + line.startswith('#define %s' % cppvar) or + line.startswith('#endif // %s' % cppvar)): + is_header_guard = True + # #include lines and header guards can be long, since there's no clean way to + # split them. + # + # URLs can be long too. It's possible to split these, but it makes them + # harder to cut&paste. + # + # The "$Id:...$" comment may also get very long without it being the + # developers fault. + if (not line.startswith('#include') and not is_header_guard and + not Match(r'^\s*//.*http(s?)://\S*$', line) and + not Match(r'^// \$Id:.*#[0-9]+ \$$', line)): + line_width = GetLineWidth(line) + if line_width > 100: + error(filename, linenum, 'whitespace/line_length', 4, + 'Lines should very rarely be longer than 100 characters') + elif line_width > 80: + error(filename, linenum, 'whitespace/line_length', 2, + 'Lines should be <= 80 characters long') + + if (cleansed_line.count(';') > 1 and + # for loops are allowed two ;'s (and may run over two lines). + cleansed_line.find('for') == -1 and + (GetPreviousNonBlankLine(clean_lines, linenum)[0].find('for') == -1 or + GetPreviousNonBlankLine(clean_lines, linenum)[0].find(';') != -1) and + # It's ok to have many commands in a switch case that fits in 1 line + not ((cleansed_line.find('case ') != -1 or + cleansed_line.find('default:') != -1) and + cleansed_line.find('break;') != -1)): + error(filename, linenum, 'whitespace/newline', 4, + 'More than one command on the same line') + + # Some more style checks + CheckBraces(filename, clean_lines, linenum, error) + CheckSpacing(filename, clean_lines, linenum, error) + CheckCheck(filename, clean_lines, linenum, error) + if class_state and class_state.classinfo_stack: + CheckSectionSpacing(filename, clean_lines, + class_state.classinfo_stack[-1], linenum, error) + + +_RE_PATTERN_INCLUDE_NEW_STYLE = re.compile(r'#include +"[^/]+\.h"') +_RE_PATTERN_INCLUDE = re.compile(r'^\s*#\s*include\s*([<"])([^>"]*)[>"].*$') +# Matches the first component of a filename delimited by -s and _s. That is: +# _RE_FIRST_COMPONENT.match('foo').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo.cc').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo-bar_baz.cc').group(0) == 'foo' +# _RE_FIRST_COMPONENT.match('foo_bar-baz.cc').group(0) == 'foo' +_RE_FIRST_COMPONENT = re.compile(r'^[^-_.]+') + + +def _DropCommonSuffixes(filename): + """Drops common suffixes like _test.cc or -inl.h from filename. + + For example: + >>> _DropCommonSuffixes('foo/foo-inl.h') + 'foo/foo' + >>> _DropCommonSuffixes('foo/bar/foo.cc') + 'foo/bar/foo' + >>> _DropCommonSuffixes('foo/foo_internal.h') + 'foo/foo' + >>> _DropCommonSuffixes('foo/foo_unusualinternal.h') + 'foo/foo_unusualinternal' + + Args: + filename: The input filename. + + Returns: + The filename with the common suffix removed. + """ + for suffix in ('test.cc', 'regtest.cc', 'unittest.cc', + 'inl.h', 'impl.h', 'internal.h'): + if (filename.endswith(suffix) and len(filename) > len(suffix) and + filename[-len(suffix) - 1] in ('-', '_')): + return filename[:-len(suffix) - 1] + return os.path.splitext(filename)[0] + + +def _IsTestFilename(filename): + """Determines if the given filename has a suffix that identifies it as a test. + + Args: + filename: The input filename. + + Returns: + True if 'filename' looks like a test, False otherwise. + """ + if (filename.endswith('_test.cc') or + filename.endswith('_unittest.cc') or + filename.endswith('_regtest.cc')): + return True + else: + return False + + +def _ClassifyInclude(fileinfo, include, is_system): + """Figures out what kind of header 'include' is. + + Args: + fileinfo: The current file cpplint is running over. A FileInfo instance. + include: The path to a #included file. + is_system: True if the #include used <> rather than "". + + Returns: + One of the _XXX_HEADER constants. + + For example: + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'stdio.h', True) + _C_SYS_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'string', True) + _CPP_SYS_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/foo.h', False) + _LIKELY_MY_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo_unknown_extension.cc'), + ... 'bar/foo_other_ext.h', False) + _POSSIBLE_MY_HEADER + >>> _ClassifyInclude(FileInfo('foo/foo.cc'), 'foo/bar.h', False) + _OTHER_HEADER + """ + # This is a list of all standard c++ header files, except + # those already checked for above. + is_stl_h = include in _STL_HEADERS + is_cpp_h = is_stl_h or include in _CPP_HEADERS + + if is_system: + if is_cpp_h: + return _CPP_SYS_HEADER + else: + return _C_SYS_HEADER + + # If the target file and the include we're checking share a + # basename when we drop common extensions, and the include + # lives in . , then it's likely to be owned by the target file. + target_dir, target_base = ( + os.path.split(_DropCommonSuffixes(fileinfo.RepositoryName()))) + include_dir, include_base = os.path.split(_DropCommonSuffixes(include)) + if target_base == include_base and ( + include_dir == target_dir or + include_dir == os.path.normpath(target_dir + '/../public')): + return _LIKELY_MY_HEADER + + # If the target and include share some initial basename + # component, it's possible the target is implementing the + # include, so it's allowed to be first, but we'll never + # complain if it's not there. + target_first_component = _RE_FIRST_COMPONENT.match(target_base) + include_first_component = _RE_FIRST_COMPONENT.match(include_base) + if (target_first_component and include_first_component and + target_first_component.group(0) == + include_first_component.group(0)): + return _POSSIBLE_MY_HEADER + + return _OTHER_HEADER + + + +def CheckIncludeLine(filename, clean_lines, linenum, include_state, error): + """Check rules that are applicable to #include lines. + + Strings on #include lines are NOT removed from elided line, to make + certain tasks easier. However, to prevent false positives, checks + applicable to #include lines in CheckLanguage must be put here. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + include_state: An _IncludeState instance in which the headers are inserted. + error: The function to call with any errors found. + """ + fileinfo = FileInfo(filename) + + line = clean_lines.lines[linenum] + + # "include" should use the new style "foo/bar.h" instead of just "bar.h" + if _RE_PATTERN_INCLUDE_NEW_STYLE.search(line): + error(filename, linenum, 'build/include', 4, + 'Include the directory when naming .h files') + + # we shouldn't include a file more than once. actually, there are a + # handful of instances where doing so is okay, but in general it's + # not. + match = _RE_PATTERN_INCLUDE.search(line) + if match: + include = match.group(2) + is_system = (match.group(1) == '<') + if include in include_state: + error(filename, linenum, 'build/include', 4, + '"%s" already included at %s:%s' % + (include, filename, include_state[include])) + else: + include_state[include] = linenum + + # We want to ensure that headers appear in the right order: + # 1) for foo.cc, foo.h (preferred location) + # 2) c system files + # 3) cpp system files + # 4) for foo.cc, foo.h (deprecated location) + # 5) other google headers + # + # We classify each include statement as one of those 5 types + # using a number of techniques. The include_state object keeps + # track of the highest type seen, and complains if we see a + # lower type after that. + error_message = include_state.CheckNextIncludeOrder( + _ClassifyInclude(fileinfo, include, is_system)) + if error_message: + error(filename, linenum, 'build/include_order', 4, + '%s. Should be: %s.h, c system, c++ system, other.' % + (error_message, fileinfo.BaseName())) + if not include_state.IsInAlphabeticalOrder(include): + error(filename, linenum, 'build/include_alpha', 4, + 'Include "%s" not in alphabetical order' % include) + + # Look for any of the stream classes that are part of standard C++. + match = _RE_PATTERN_INCLUDE.match(line) + if match: + include = match.group(2) + if Match(r'(f|ind|io|i|o|parse|pf|stdio|str|)?stream$', include): + # Many unit tests use cout, so we exempt them. + if not _IsTestFilename(filename): + error(filename, linenum, 'readability/streams', 3, + 'Streams are highly discouraged.') + + +def _GetTextInside(text, start_pattern): + """Retrieves all the text between matching open and close parentheses. + + Given a string of lines and a regular expression string, retrieve all the text + following the expression and between opening punctuation symbols like + (, [, or {, and the matching close-punctuation symbol. This properly nested + occurrences of the punctuations, so for the text like + printf(a(), b(c())); + a call to _GetTextInside(text, r'printf\(') will return 'a(), b(c())'. + start_pattern must match string having an open punctuation symbol at the end. + + Args: + text: The lines to extract text. Its comments and strings must be elided. + It can be single line and can span multiple lines. + start_pattern: The regexp string indicating where to start extracting + the text. + Returns: + The extracted text. + None if either the opening string or ending punctuation could not be found. + """ + # TODO(sugawarayu): Audit cpplint.py to see what places could be profitably + # rewritten to use _GetTextInside (and use inferior regexp matching today). + + # Give opening punctuations to get the matching close-punctuations. + matching_punctuation = {'(': ')', '{': '}', '[': ']'} + closing_punctuation = set(matching_punctuation.itervalues()) + + # Find the position to start extracting text. + match = re.search(start_pattern, text, re.M) + if not match: # start_pattern not found in text. + return None + start_position = match.end(0) + + assert start_position > 0, ( + 'start_pattern must ends with an opening punctuation.') + assert text[start_position - 1] in matching_punctuation, ( + 'start_pattern must ends with an opening punctuation.') + # Stack of closing punctuations we expect to have in text after position. + punctuation_stack = [matching_punctuation[text[start_position - 1]]] + position = start_position + while punctuation_stack and position < len(text): + if text[position] == punctuation_stack[-1]: + punctuation_stack.pop() + elif text[position] in closing_punctuation: + # A closing punctuation without matching opening punctuations. + return None + elif text[position] in matching_punctuation: + punctuation_stack.append(matching_punctuation[text[position]]) + position += 1 + if punctuation_stack: + # Opening punctuations left without matching close-punctuations. + return None + # punctuations match. + return text[start_position:position - 1] + + +def CheckLanguage(filename, clean_lines, linenum, file_extension, include_state, + error): + """Checks rules from the 'C++ language rules' section of cppguide.html. + + Some of these rules are hard to test (function overloading, using + uint32 inappropriately), but we do the best we can. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + file_extension: The extension (without the dot) of the filename. + include_state: An _IncludeState instance in which the headers are inserted. + error: The function to call with any errors found. + """ + # If the line is empty or consists of entirely a comment, no need to + # check it. + line = clean_lines.elided[linenum] + if not line: + return + + match = _RE_PATTERN_INCLUDE.search(line) + if match: + CheckIncludeLine(filename, clean_lines, linenum, include_state, error) + return + + # Create an extended_line, which is the concatenation of the current and + # next lines, for more effective checking of code that may span more than one + # line. + if linenum + 1 < clean_lines.NumLines(): + extended_line = line + clean_lines.elided[linenum + 1] + else: + extended_line = line + + # Make Windows paths like Unix. + fullname = os.path.abspath(filename).replace('\\', '/') + + # TODO(unknown): figure out if they're using default arguments in fn proto. + + # Check for non-const references in functions. This is tricky because & + # is also used to take the address of something. We allow <> for templates, + # (ignoring whatever is between the braces) and : for classes. + # These are complicated re's. They try to capture the following: + # paren (for fn-prototype start), typename, &, varname. For the const + # version, we're willing for const to be before typename or after + # Don't check the implementation on same line. + fnline = line.split('{', 1)[0] + if (len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) > + len(re.findall(r'\([^()]*\bconst\s+(?:typename\s+)?(?:struct\s+)?' + r'(?:[\w:]|<[^()]*>)+(\s?&|&\s?)\w+', fnline)) + + len(re.findall(r'\([^()]*\b(?:[\w:]|<[^()]*>)+\s+const(\s?&|&\s?)[\w]+', + fnline))): + + # We allow non-const references in a few standard places, like functions + # called "swap()" or iostream operators like "<<" or ">>". + if not Search( + r'(swap|Swap|operator[<>][<>])\s*\(\s*(?:[\w:]|<.*>)+\s*&', + fnline): + error(filename, linenum, 'runtime/references', 2, + 'Is this a non-const reference? ' + 'If so, make const or use a pointer.') + + # Check to see if they're using an conversion function cast. + # I just try to capture the most common basic types, though there are more. + # Parameterless conversion functions, such as bool(), are allowed as they are + # probably a member operator declaration or default constructor. + match = Search( + r'(\bnew\s+)?\b' # Grab 'new' operator, if it's there + r'(int|float|double|bool|char|int32|uint32|int64|uint64)\([^)]', line) + if match: + # gMock methods are defined using some variant of MOCK_METHODx(name, type) + # where type may be float(), int(string), etc. Without context they are + # virtually indistinguishable from int(x) casts. Likewise, gMock's + # MockCallback takes a template parameter of the form return_type(arg_type), + # which looks much like the cast we're trying to detect. + if (match.group(1) is None and # If new operator, then this isn't a cast + not (Match(r'^\s*MOCK_(CONST_)?METHOD\d+(_T)?\(', line) or + Match(r'^\s*MockCallback<.*>', line))): + error(filename, linenum, 'readability/casting', 4, + 'Using deprecated casting style. ' + 'Use static_cast<%s>(...) instead' % + match.group(2)) + + CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], + 'static_cast', + r'\((int|float|double|bool|char|u?int(16|32|64))\)', error) + + # This doesn't catch all cases. Consider (const char * const)"hello". + # + # (char *) "foo" should always be a const_cast (reinterpret_cast won't + # compile). + if CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], + 'const_cast', r'\((char\s?\*+\s?)\)\s*"', error): + pass + else: + # Check pointer casts for other than string constants + CheckCStyleCast(filename, linenum, line, clean_lines.raw_lines[linenum], + 'reinterpret_cast', r'\((\w+\s?\*+\s?)\)', error) + + # In addition, we look for people taking the address of a cast. This + # is dangerous -- casts can assign to temporaries, so the pointer doesn't + # point where you think. + if Search( + r'(&\([^)]+\)[\w(])|(&(static|dynamic|reinterpret)_cast\b)', line): + error(filename, linenum, 'runtime/casting', 4, + ('Are you taking an address of a cast? ' + 'This is dangerous: could be a temp var. ' + 'Take the address before doing the cast, rather than after')) + + # Check for people declaring static/global STL strings at the top level. + # This is dangerous because the C++ language does not guarantee that + # globals with constructors are initialized before the first access. + match = Match( + r'((?:|static +)(?:|const +))string +([a-zA-Z0-9_:]+)\b(.*)', + line) + # Make sure it's not a function. + # Function template specialization looks like: "string foo(...". + # Class template definitions look like: "string Foo::Method(...". + if match and not Match(r'\s*(<.*>)?(::[a-zA-Z0-9_]+)?\s*\(([^"]|$)', + match.group(3)): + error(filename, linenum, 'runtime/string', 4, + 'For a static/global string constant, use a C style string instead: ' + '"%schar %s[]".' % + (match.group(1), match.group(2))) + + # Check that we're not using RTTI outside of testing code. + if Search(r'\bdynamic_cast<', line) and not _IsTestFilename(filename): + error(filename, linenum, 'runtime/rtti', 5, + 'Do not use dynamic_cast<>. If you need to cast within a class ' + "hierarchy, use static_cast<> to upcast. Google doesn't support " + 'RTTI.') + + if Search(r'\b([A-Za-z0-9_]*_)\(\1\)', line): + error(filename, linenum, 'runtime/init', 4, + 'You seem to be initializing a member variable with itself.') + + if file_extension == 'h': + # TODO(unknown): check that 1-arg constructors are explicit. + # How to tell it's a constructor? + # (handled in CheckForNonStandardConstructs for now) + # TODO(unknown): check that classes have DISALLOW_EVIL_CONSTRUCTORS + # (level 1 error) + pass + + # Check if people are using the verboten C basic types. The only exception + # we regularly allow is "unsigned short port" for port. + if Search(r'\bshort port\b', line): + if not Search(r'\bunsigned short port\b', line): + error(filename, linenum, 'runtime/int', 4, + 'Use "unsigned short" for ports, not "short"') + else: + match = Search(r'\b(short|long(?! +double)|long long)\b', line) + if match: + error(filename, linenum, 'runtime/int', 4, + 'Use int16/int64/etc, rather than the C type %s' % match.group(1)) + + # When snprintf is used, the second argument shouldn't be a literal. + match = Search(r'snprintf\s*\(([^,]*),\s*([0-9]*)\s*,', line) + if match and match.group(2) != '0': + # If 2nd arg is zero, snprintf is used to calculate size. + error(filename, linenum, 'runtime/printf', 3, + 'If you can, use sizeof(%s) instead of %s as the 2nd arg ' + 'to snprintf.' % (match.group(1), match.group(2))) + + # Check if some verboten C functions are being used. + if Search(r'\bsprintf\b', line): + error(filename, linenum, 'runtime/printf', 5, + 'Never use sprintf. Use snprintf instead.') + match = Search(r'\b(strcpy|strcat)\b', line) + if match: + error(filename, linenum, 'runtime/printf', 4, + 'Almost always, snprintf is better than %s' % match.group(1)) + + if Search(r'\bsscanf\b', line): + error(filename, linenum, 'runtime/printf', 1, + 'sscanf can be ok, but is slow and can overflow buffers.') + + # Check if some verboten operator overloading is going on + # TODO(unknown): catch out-of-line unary operator&: + # class X {}; + # int operator&(const X& x) { return 42; } // unary operator& + # The trick is it's hard to tell apart from binary operator&: + # class Y { int operator&(const Y& x) { return 23; } }; // binary operator& + if Search(r'\boperator\s*&\s*\(\s*\)', line): + error(filename, linenum, 'runtime/operator', 4, + 'Unary operator& is dangerous. Do not use it.') + + # Check for suspicious usage of "if" like + # } if (a == b) { + if Search(r'\}\s*if\s*\(', line): + error(filename, linenum, 'readability/braces', 4, + 'Did you mean "else if"? If not, start a new line for "if".') + + # Check for potential format string bugs like printf(foo). + # We constrain the pattern not to pick things like DocidForPrintf(foo). + # Not perfect but it can catch printf(foo.c_str()) and printf(foo->c_str()) + # TODO(sugawarayu): Catch the following case. Need to change the calling + # convention of the whole function to process multiple line to handle it. + # printf( + # boy_this_is_a_really_long_variable_that_cannot_fit_on_the_prev_line); + printf_args = _GetTextInside(line, r'(?i)\b(string)?printf\s*\(') + if printf_args: + match = Match(r'([\w.\->()]+)$', printf_args) + if match: + function_name = re.search(r'\b((?:string)?printf)\s*\(', + line, re.I).group(1) + error(filename, linenum, 'runtime/printf', 4, + 'Potential format string bug. Do %s("%%s", %s) instead.' + % (function_name, match.group(1))) + + # Check for potential memset bugs like memset(buf, sizeof(buf), 0). + match = Search(r'memset\s*\(([^,]*),\s*([^,]*),\s*0\s*\)', line) + if match and not Match(r"^''|-?[0-9]+|0x[0-9A-Fa-f]$", match.group(2)): + error(filename, linenum, 'runtime/memset', 4, + 'Did you mean "memset(%s, 0, %s)"?' + % (match.group(1), match.group(2))) + + if Search(r'\busing namespace\b', line): + error(filename, linenum, 'build/namespaces', 5, + 'Do not use namespace using-directives. ' + 'Use using-declarations instead.') + + # Detect variable-length arrays. + match = Match(r'\s*(.+::)?(\w+) [a-z]\w*\[(.+)];', line) + if (match and match.group(2) != 'return' and match.group(2) != 'delete' and + match.group(3).find(']') == -1): + # Split the size using space and arithmetic operators as delimiters. + # If any of the resulting tokens are not compile time constants then + # report the error. + tokens = re.split(r'\s|\+|\-|\*|\/|<<|>>]', match.group(3)) + is_const = True + skip_next = False + for tok in tokens: + if skip_next: + skip_next = False + continue + + if Search(r'sizeof\(.+\)', tok): continue + if Search(r'arraysize\(\w+\)', tok): continue + + tok = tok.lstrip('(') + tok = tok.rstrip(')') + if not tok: continue + if Match(r'\d+', tok): continue + if Match(r'0[xX][0-9a-fA-F]+', tok): continue + if Match(r'k[A-Z0-9]\w*', tok): continue + if Match(r'(.+::)?k[A-Z0-9]\w*', tok): continue + if Match(r'(.+::)?[A-Z][A-Z0-9_]*', tok): continue + # A catch all for tricky sizeof cases, including 'sizeof expression', + # 'sizeof(*type)', 'sizeof(const type)', 'sizeof(struct StructName)' + # requires skipping the next token because we split on ' ' and '*'. + if tok.startswith('sizeof'): + skip_next = True + continue + is_const = False + break + if not is_const: + error(filename, linenum, 'runtime/arrays', 1, + 'Do not use variable-length arrays. Use an appropriately named ' + "('k' followed by CamelCase) compile-time constant for the size.") + + # If DISALLOW_EVIL_CONSTRUCTORS, DISALLOW_COPY_AND_ASSIGN, or + # DISALLOW_IMPLICIT_CONSTRUCTORS is present, then it should be the last thing + # in the class declaration. + match = Match( + (r'\s*' + r'(DISALLOW_(EVIL_CONSTRUCTORS|COPY_AND_ASSIGN|IMPLICIT_CONSTRUCTORS))' + r'\(.*\);$'), + line) + if match and linenum + 1 < clean_lines.NumLines(): + next_line = clean_lines.elided[linenum + 1] + # We allow some, but not all, declarations of variables to be present + # in the statement that defines the class. The [\w\*,\s]* fragment of + # the regular expression below allows users to declare instances of + # the class or pointers to instances, but not less common types such + # as function pointers or arrays. It's a tradeoff between allowing + # reasonable code and avoiding trying to parse more C++ using regexps. + if not Search(r'^\s*}[\w\*,\s]*;', next_line): + error(filename, linenum, 'readability/constructors', 3, + match.group(1) + ' should be the last thing in the class') + + # Check for use of unnamed namespaces in header files. Registration + # macros are typically OK, so we allow use of "namespace {" on lines + # that end with backslashes. + if (file_extension == 'h' + and Search(r'\bnamespace\s*{', line) + and line[-1] != '\\'): + error(filename, linenum, 'build/namespaces', 4, + 'Do not use unnamed namespaces in header files. See ' + 'http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces' + ' for more information.') + + +def CheckCStyleCast(filename, linenum, line, raw_line, cast_type, pattern, + error): + """Checks for a C-style cast by looking for the pattern. + + This also handles sizeof(type) warnings, due to similarity of content. + + Args: + filename: The name of the current file. + linenum: The number of the line to check. + line: The line of code to check. + raw_line: The raw line of code to check, with comments. + cast_type: The string for the C++ cast to recommend. This is either + reinterpret_cast, static_cast, or const_cast, depending. + pattern: The regular expression used to find C-style casts. + error: The function to call with any errors found. + + Returns: + True if an error was emitted. + False otherwise. + """ + match = Search(pattern, line) + if not match: + return False + + # e.g., sizeof(int) + sizeof_match = Match(r'.*sizeof\s*$', line[0:match.start(1) - 1]) + if sizeof_match: + error(filename, linenum, 'runtime/sizeof', 1, + 'Using sizeof(type). Use sizeof(varname) instead if possible') + return True + + remainder = line[match.end(0):] + + # The close paren is for function pointers as arguments to a function. + # eg, void foo(void (*bar)(int)); + # The semicolon check is a more basic function check; also possibly a + # function pointer typedef. + # eg, void foo(int); or void foo(int) const; + # The equals check is for function pointer assignment. + # eg, void *(*foo)(int) = ... + # The > is for MockCallback<...> ... + # + # Right now, this will only catch cases where there's a single argument, and + # it's unnamed. It should probably be expanded to check for multiple + # arguments with some unnamed. + function_match = Match(r'\s*(\)|=|(const)?\s*(;|\{|throw\(\)|>))', remainder) + if function_match: + if (not function_match.group(3) or + function_match.group(3) == ';' or + ('MockCallback<' not in raw_line and + '/*' not in raw_line)): + error(filename, linenum, 'readability/function', 3, + 'All parameters should be named in a function') + return True + + # At this point, all that should be left is actual casts. + error(filename, linenum, 'readability/casting', 4, + 'Using C-style cast. Use %s<%s>(...) instead' % + (cast_type, match.group(1))) + + return True + + +_HEADERS_CONTAINING_TEMPLATES = ( + ('', ('deque',)), + ('', ('unary_function', 'binary_function', + 'plus', 'minus', 'multiplies', 'divides', 'modulus', + 'negate', + 'equal_to', 'not_equal_to', 'greater', 'less', + 'greater_equal', 'less_equal', + 'logical_and', 'logical_or', 'logical_not', + 'unary_negate', 'not1', 'binary_negate', 'not2', + 'bind1st', 'bind2nd', + 'pointer_to_unary_function', + 'pointer_to_binary_function', + 'ptr_fun', + 'mem_fun_t', 'mem_fun', 'mem_fun1_t', 'mem_fun1_ref_t', + 'mem_fun_ref_t', + 'const_mem_fun_t', 'const_mem_fun1_t', + 'const_mem_fun_ref_t', 'const_mem_fun1_ref_t', + 'mem_fun_ref', + )), + ('', ('numeric_limits',)), + ('', ('list',)), + ('', ('map', 'multimap',)), + ('', ('allocator',)), + ('', ('queue', 'priority_queue',)), + ('', ('set', 'multiset',)), + ('', ('stack',)), + ('', ('char_traits', 'basic_string',)), + ('', ('pair',)), + ('', ('vector',)), + + # gcc extensions. + # Note: std::hash is their hash, ::hash is our hash + ('', ('hash_map', 'hash_multimap',)), + ('', ('hash_set', 'hash_multiset',)), + ('', ('slist',)), + ) + +_RE_PATTERN_STRING = re.compile(r'\bstring\b') + +_re_pattern_algorithm_header = [] +for _template in ('copy', 'max', 'min', 'min_element', 'sort', 'swap', + 'transform'): + # Match max(..., ...), max(..., ...), but not foo->max, foo.max or + # type::max(). + _re_pattern_algorithm_header.append( + (re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'), + _template, + '')) + +_re_pattern_templates = [] +for _header, _templates in _HEADERS_CONTAINING_TEMPLATES: + for _template in _templates: + _re_pattern_templates.append( + (re.compile(r'(\<|\b)' + _template + r'\s*\<'), + _template + '<>', + _header)) + + +def FilesBelongToSameModule(filename_cc, filename_h): + """Check if these two filenames belong to the same module. + + The concept of a 'module' here is a as follows: + foo.h, foo-inl.h, foo.cc, foo_test.cc and foo_unittest.cc belong to the + same 'module' if they are in the same directory. + some/path/public/xyzzy and some/path/internal/xyzzy are also considered + to belong to the same module here. + + If the filename_cc contains a longer path than the filename_h, for example, + '/absolute/path/to/base/sysinfo.cc', and this file would include + 'base/sysinfo.h', this function also produces the prefix needed to open the + header. This is used by the caller of this function to more robustly open the + header file. We don't have access to the real include paths in this context, + so we need this guesswork here. + + Known bugs: tools/base/bar.cc and base/bar.h belong to the same module + according to this implementation. Because of this, this function gives + some false positives. This should be sufficiently rare in practice. + + Args: + filename_cc: is the path for the .cc file + filename_h: is the path for the header path + + Returns: + Tuple with a bool and a string: + bool: True if filename_cc and filename_h belong to the same module. + string: the additional prefix needed to open the header file. + """ + + if not filename_cc.endswith('.cc'): + return (False, '') + filename_cc = filename_cc[:-len('.cc')] + if filename_cc.endswith('_unittest'): + filename_cc = filename_cc[:-len('_unittest')] + elif filename_cc.endswith('_test'): + filename_cc = filename_cc[:-len('_test')] + filename_cc = filename_cc.replace('/public/', '/') + filename_cc = filename_cc.replace('/internal/', '/') + + if not filename_h.endswith('.h'): + return (False, '') + filename_h = filename_h[:-len('.h')] + if filename_h.endswith('-inl'): + filename_h = filename_h[:-len('-inl')] + filename_h = filename_h.replace('/public/', '/') + filename_h = filename_h.replace('/internal/', '/') + + files_belong_to_same_module = filename_cc.endswith(filename_h) + common_path = '' + if files_belong_to_same_module: + common_path = filename_cc[:-len(filename_h)] + return files_belong_to_same_module, common_path + + +def UpdateIncludeState(filename, include_state, io=codecs): + """Fill up the include_state with new includes found from the file. + + Args: + filename: the name of the header to read. + include_state: an _IncludeState instance in which the headers are inserted. + io: The io factory to use to read the file. Provided for testability. + + Returns: + True if a header was succesfully added. False otherwise. + """ + headerfile = None + try: + headerfile = io.open(filename, 'r', 'utf8', 'replace') + except IOError: + return False + linenum = 0 + for line in headerfile: + linenum += 1 + clean_line = CleanseComments(line) + match = _RE_PATTERN_INCLUDE.search(clean_line) + if match: + include = match.group(2) + # The value formatting is cute, but not really used right now. + # What matters here is that the key is in include_state. + include_state.setdefault(include, '%s:%d' % (filename, linenum)) + return True + + +def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, + io=codecs): + """Reports for missing stl includes. + + This function will output warnings to make sure you are including the headers + necessary for the stl containers and functions that you use. We only give one + reason to include a header. For example, if you use both equal_to<> and + less<> in a .h file, only one (the latter in the file) of these will be + reported as a reason to include the . + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + include_state: An _IncludeState instance. + error: The function to call with any errors found. + io: The IO factory to use to read the header file. Provided for unittest + injection. + """ + required = {} # A map of header name to linenumber and the template entity. + # Example of required: { '': (1219, 'less<>') } + + for linenum in xrange(clean_lines.NumLines()): + line = clean_lines.elided[linenum] + if not line or line[0] == '#': + continue + + # String is special -- it is a non-templatized type in STL. + matched = _RE_PATTERN_STRING.search(line) + if matched: + # Don't warn about strings in non-STL namespaces: + # (We check only the first match per line; good enough.) + prefix = line[:matched.start()] + if prefix.endswith('std::') or not prefix.endswith('::'): + required[''] = (linenum, 'string') + + for pattern, template, header in _re_pattern_algorithm_header: + if pattern.search(line): + required[header] = (linenum, template) + + # The following function is just a speed up, no semantics are changed. + if not '<' in line: # Reduces the cpu time usage by skipping lines. + continue + + for pattern, template, header in _re_pattern_templates: + if pattern.search(line): + required[header] = (linenum, template) + + # The policy is that if you #include something in foo.h you don't need to + # include it again in foo.cc. Here, we will look at possible includes. + # Let's copy the include_state so it is only messed up within this function. + include_state = include_state.copy() + + # Did we find the header for this file (if any) and succesfully load it? + header_found = False + + # Use the absolute path so that matching works properly. + abs_filename = FileInfo(filename).FullName() + + # For Emacs's flymake. + # If cpplint is invoked from Emacs's flymake, a temporary file is generated + # by flymake and that file name might end with '_flymake.cc'. In that case, + # restore original file name here so that the corresponding header file can be + # found. + # e.g. If the file name is 'foo_flymake.cc', we should search for 'foo.h' + # instead of 'foo_flymake.h' + abs_filename = re.sub(r'_flymake\.cc$', '.cc', abs_filename) + + # include_state is modified during iteration, so we iterate over a copy of + # the keys. + header_keys = include_state.keys() + for header in header_keys: + (same_module, common_path) = FilesBelongToSameModule(abs_filename, header) + fullpath = common_path + header + if same_module and UpdateIncludeState(fullpath, include_state, io): + header_found = True + + # If we can't find the header file for a .cc, assume it's because we don't + # know where to look. In that case we'll give up as we're not sure they + # didn't include it in the .h file. + # TODO(unknown): Do a better job of finding .h files so we are confident that + # not having the .h file means there isn't one. + if filename.endswith('.cc') and not header_found: + return + + # All the lines have been processed, report the errors found. + for required_header_unstripped in required: + template = required[required_header_unstripped][1] + if required_header_unstripped.strip('<>"') not in include_state: + error(filename, required[required_header_unstripped][0], + 'build/include_what_you_use', 4, + 'Add #include ' + required_header_unstripped + ' for ' + template) + + +_RE_PATTERN_EXPLICIT_MAKEPAIR = re.compile(r'\bmake_pair\s*<') + + +def CheckMakePairUsesDeduction(filename, clean_lines, linenum, error): + """Check that make_pair's template arguments are deduced. + + G++ 4.6 in C++0x mode fails badly if make_pair's template arguments are + specified explicitly, and such use isn't intended in any case. + + Args: + filename: The name of the current file. + clean_lines: A CleansedLines instance containing the file. + linenum: The number of the line to check. + error: The function to call with any errors found. + """ + raw = clean_lines.raw_lines + line = raw[linenum] + match = _RE_PATTERN_EXPLICIT_MAKEPAIR.search(line) + if match: + error(filename, linenum, 'build/explicit_make_pair', + 4, # 4 = high confidence + 'Omit template arguments from make_pair OR use pair directly OR' + ' if appropriate, construct a pair directly') + + +def ProcessLine(filename, file_extension, + clean_lines, line, include_state, function_state, + class_state, error, extra_check_functions=[]): + """Processes a single line in the file. + + Args: + filename: Filename of the file that is being processed. + file_extension: The extension (dot not included) of the file. + clean_lines: An array of strings, each representing a line of the file, + with comments stripped. + line: Number of line being processed. + include_state: An _IncludeState instance in which the headers are inserted. + function_state: A _FunctionState instance which counts function lines, etc. + class_state: A _ClassState instance which maintains information about + the current stack of nested class declarations being parsed. + error: A callable to which errors are reported, which takes 4 arguments: + filename, line number, error level, and message + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + raw_lines = clean_lines.raw_lines + ParseNolintSuppressions(filename, raw_lines[line], line, error) + CheckForFunctionLengths(filename, clean_lines, line, function_state, error) + CheckForMultilineCommentsAndStrings(filename, clean_lines, line, error) + CheckStyle(filename, clean_lines, line, file_extension, class_state, error) + CheckLanguage(filename, clean_lines, line, file_extension, include_state, + error) + CheckForNonStandardConstructs(filename, clean_lines, line, + class_state, error) + CheckPosixThreading(filename, clean_lines, line, error) + CheckInvalidIncrement(filename, clean_lines, line, error) + CheckMakePairUsesDeduction(filename, clean_lines, line, error) + for check_fn in extra_check_functions: + check_fn(filename, clean_lines, line, error) + +def ProcessFileData(filename, file_extension, lines, error, + extra_check_functions=[]): + """Performs lint checks and reports any errors to the given error function. + + Args: + filename: Filename of the file that is being processed. + file_extension: The extension (dot not included) of the file. + lines: An array of strings, each representing a line of the file, with the + last element being empty if the file is terminated with a newline. + error: A callable to which errors are reported, which takes 4 arguments: + filename, line number, error level, and message + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + lines = (['// marker so line numbers and indices both start at 1'] + lines + + ['// marker so line numbers end in a known way']) + + include_state = _IncludeState() + function_state = _FunctionState() + class_state = _ClassState() + + ResetNolintSuppressions() + + CheckForCopyright(filename, lines, error) + + if file_extension == 'h': + CheckForHeaderGuard(filename, lines, error) + + RemoveMultiLineComments(filename, lines, error) + clean_lines = CleansedLines(lines) + for line in xrange(clean_lines.NumLines()): + ProcessLine(filename, file_extension, clean_lines, line, + include_state, function_state, class_state, error, + extra_check_functions) + class_state.CheckFinished(filename, error) + + CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) + + # We check here rather than inside ProcessLine so that we see raw + # lines rather than "cleaned" lines. + CheckForUnicodeReplacementCharacters(filename, lines, error) + + CheckForNewlineAtEOF(filename, lines, error) + +def ProcessFile(filename, vlevel, extra_check_functions=[]): + """Does google-lint on a single file. + + Args: + filename: The name of the file to parse. + + vlevel: The level of errors to report. Every error of confidence + >= verbose_level will be reported. 0 is a good default. + + extra_check_functions: An array of additional check functions that will be + run on each source line. Each function takes 4 + arguments: filename, clean_lines, line, error + """ + + _SetVerboseLevel(vlevel) + + try: + # Support the UNIX convention of using "-" for stdin. Note that + # we are not opening the file with universal newline support + # (which codecs doesn't support anyway), so the resulting lines do + # contain trailing '\r' characters if we are reading a file that + # has CRLF endings. + # If after the split a trailing '\r' is present, it is removed + # below. If it is not expected to be present (i.e. os.linesep != + # '\r\n' as in Windows), a warning is issued below if this file + # is processed. + + if filename == '-': + lines = codecs.StreamReaderWriter(sys.stdin, + codecs.getreader('utf8'), + codecs.getwriter('utf8'), + 'replace').read().split('\n') + else: + lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n') + + carriage_return_found = False + # Remove trailing '\r'. + for linenum in range(len(lines)): + if lines[linenum].endswith('\r'): + lines[linenum] = lines[linenum].rstrip('\r') + carriage_return_found = True + + except IOError: + sys.stderr.write( + "Skipping input '%s': Can't open for reading\n" % filename) + return + + # Note, if no dot is found, this will give the entire filename as the ext. + file_extension = filename[filename.rfind('.') + 1:] + + # When reading from stdin, the extension is unknown, so no cpplint tests + # should rely on the extension. + if (filename != '-' and file_extension != 'cc' and file_extension != 'h' + and file_extension != 'cpp'): + sys.stderr.write('Ignoring %s; not a .cc or .h file\n' % filename) + else: + ProcessFileData(filename, file_extension, lines, Error, + extra_check_functions) + if carriage_return_found and os.linesep != '\r\n': + # Use 0 for linenum since outputting only one error for potentially + # several lines. + Error(filename, 0, 'whitespace/newline', 1, + 'One or more unexpected \\r (^M) found;' + 'better to use only a \\n') + + sys.stderr.write('Done processing %s\n' % filename) + + +def PrintUsage(message): + """Prints a brief usage string and exits, optionally with an error message. + + Args: + message: The optional error message. + """ + sys.stderr.write(_USAGE) + if message: + sys.exit('\nFATAL ERROR: ' + message) + else: + sys.exit(1) + + +def PrintCategories(): + """Prints a list of all the error-categories used by error messages. + + These are the categories used to filter messages via --filter. + """ + sys.stderr.write(''.join(' %s\n' % cat for cat in _ERROR_CATEGORIES)) + sys.exit(0) + + +def ParseArguments(args): + """Parses the command line arguments. + + This may set the output format and verbosity level as side-effects. + + Args: + args: The command line arguments: + + Returns: + The list of filenames to lint. + """ + try: + (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', + 'counting=', + 'filter=']) + except getopt.GetoptError: + PrintUsage('Invalid arguments.') + + verbosity = _VerboseLevel() + output_format = _OutputFormat() + filters = '' + counting_style = '' + + for (opt, val) in opts: + if opt == '--help': + PrintUsage(None) + elif opt == '--output': + if not val in ('emacs', 'vs7'): + PrintUsage('The only allowed output formats are emacs and vs7.') + output_format = val + elif opt == '--verbose': + verbosity = int(val) + elif opt == '--filter': + filters = val + if not filters: + PrintCategories() + elif opt == '--counting': + if val not in ('total', 'toplevel', 'detailed'): + PrintUsage('Valid counting options are total, toplevel, and detailed') + counting_style = val + + if not filenames: + PrintUsage('No files were specified.') + + _SetOutputFormat(output_format) + _SetVerboseLevel(verbosity) + _SetFilters(filters) + _SetCountingStyle(counting_style) + + return filenames + + +def main(): + filenames = ParseArguments(sys.argv[1:]) + + # Change stderr to write with replacement characters so we don't die + # if we try to print something containing non-ASCII characters. + sys.stderr = codecs.StreamReaderWriter(sys.stderr, + codecs.getreader('utf8'), + codecs.getwriter('utf8'), + 'replace') + + _cpplint_state.ResetErrorCounts() + for filename in filenames: + ProcessFile(filename, _cpplint_state.verbose_level) + _cpplint_state.PrintErrorCounts() + + sys.exit(_cpplint_state.error_count > 0) + + +if __name__ == '__main__': + main() From d3b75fc4f6b446594d0802bd926c15a09e444ecf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Jun 2012 14:53:22 +0200 Subject: [PATCH 1998/2215] Change the test so a tab character before a braces is ok --- telldus-core/tests/cpplint.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/tests/cpplint.py b/telldus-core/tests/cpplint.py index 526b9556..19a37be5 100755 --- a/telldus-core/tests/cpplint.py +++ b/telldus-core/tests/cpplint.py @@ -1883,9 +1883,9 @@ def CheckSpacing(filename, clean_lines, linenum, error): # an initializer list, for instance), you should have spaces before your # braces. And since you should never have braces at the beginning of a line, # this is an easy test. - if Search(r'[^ ({]{', line): + if Search(r'[^ \t({]{', line): # The check for tab was added by Telldus error(filename, linenum, 'whitespace/braces', 5, - 'Missing space before {') + 'Missing whitespace before {') # Make sure '} else {' has spaces. if Search(r'}else', line): From 3101fd0969216b4b17754c9cd42b3037b8cf3b11 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 12:30:31 +0200 Subject: [PATCH 1999/2215] Add test for checking that tab is used for indentation --- telldus-core/tests/cpplint.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/telldus-core/tests/cpplint.py b/telldus-core/tests/cpplint.py index 19a37be5..5c88df49 100755 --- a/telldus-core/tests/cpplint.py +++ b/telldus-core/tests/cpplint.py @@ -204,14 +204,18 @@ _ERROR_CATEGORIES = [ 'whitespace/parens', 'whitespace/semicolon', 'whitespace/tab', - 'whitespace/todo' + 'whitespace/todo', + 'whitespace/use_tab_for_indentation' ] # The default state of the category filter. This is overrided by the --filter= # flag. By default all errors are on, so only add here categories that should be # off by default (i.e., categories that must be enabled by the --filter= flags). # All entries here should start with a '-' or '+', as in the --filter= flag. -_DEFAULT_FILTERS = ['-build/include_alpha'] +_DEFAULT_FILTERS = [ + '-build/include_alpha', + '-whitespace/use_tab_for_indentation' +] # We used to check for high-bit characters, but after much discussion we # decided those were OK, as long as they were in UTF-8 and didn't represent @@ -2177,6 +2181,10 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, class_state, error(filename, linenum, 'whitespace/tab', 1, 'Tab found; better to use spaces') + if line and line[0] == ' ': + error(filename, linenum, 'whitespace/use_tab_for_indentation', 1, + 'Space found; use tabs for indentation') + # One or three blank spaces at the beginning of the line is weird; it's # hard to reconcile that with 2-space indents. # NOTE: here are the conditions rob pike used for his tests. Mine aren't From 5b5be387cd0290e06d1111228eaf78ecb6fa9b89 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 11:15:24 +0200 Subject: [PATCH 2000/2215] Include the directory when naming .h files. According to Google style guideline "build/include". --- telldus-core/client/CMakeLists.txt | 4 +- telldus-core/client/CallbackDispatcher.cpp | 2 +- telldus-core/client/CallbackDispatcher.h | 10 ++-- .../client/CallbackMainDispatcher.cpp | 2 +- telldus-core/client/CallbackMainDispatcher.h | 8 +-- telldus-core/client/Client.cpp | 13 ++--- telldus-core/client/Client.h | 8 +-- telldus-core/client/telldus-core.cpp | 11 ++-- telldus-core/common/CMakeLists.txt | 2 + telldus-core/common/Event.cpp | 6 +-- telldus-core/common/Event.h | 1 + telldus-core/common/EventHandler.h | 2 +- telldus-core/common/EventHandler_unix.cpp | 10 ++-- telldus-core/common/Event_unix.cpp | 6 +-- telldus-core/common/Message.cpp | 14 ++--- telldus-core/common/Mutex.cpp | 5 +- telldus-core/common/Socket_unix.cpp | 8 +-- telldus-core/common/Strings.cpp | 3 +- telldus-core/common/Thread.cpp | 4 +- telldus-core/common/Thread.h | 2 +- telldus-core/common/common.h | 1 + telldus-core/service/CMakeLists.txt | 6 +-- .../service/ClientCommunicationHandler.cpp | 4 +- .../service/ClientCommunicationHandler.h | 10 ++-- telldus-core/service/ConnectionListener.h | 4 +- .../service/ConnectionListener_unix.cpp | 4 +- telldus-core/service/Controller.cpp | 8 +-- telldus-core/service/Controller.h | 2 +- telldus-core/service/ControllerListener.h | 4 +- telldus-core/service/ControllerManager.cpp | 20 +++---- telldus-core/service/ControllerManager.h | 2 +- telldus-core/service/ControllerMessage.cpp | 8 +-- telldus-core/service/Device.cpp | 6 +-- telldus-core/service/Device.h | 8 +-- telldus-core/service/DeviceManager.cpp | 16 +++--- telldus-core/service/DeviceManager.h | 8 +-- telldus-core/service/EventUpdateManager.cpp | 10 ++-- telldus-core/service/EventUpdateManager.h | 4 +- telldus-core/service/Log.cpp | 6 +-- telldus-core/service/Protocol.cpp | 46 ++++++++-------- telldus-core/service/Protocol.h | 2 +- telldus-core/service/ProtocolBrateck.cpp | 2 +- telldus-core/service/ProtocolBrateck.h | 2 +- telldus-core/service/ProtocolComen.cpp | 2 +- telldus-core/service/ProtocolComen.h | 2 +- telldus-core/service/ProtocolEverflourish.cpp | 26 +++++----- telldus-core/service/ProtocolEverflourish.h | 4 +- telldus-core/service/ProtocolFineoffset.cpp | 4 +- telldus-core/service/ProtocolFineoffset.h | 4 +- telldus-core/service/ProtocolFuhaote.cpp | 2 +- telldus-core/service/ProtocolFuhaote.h | 2 +- telldus-core/service/ProtocolGroup.cpp | 2 +- telldus-core/service/ProtocolGroup.h | 2 +- telldus-core/service/ProtocolHasta.cpp | 4 +- telldus-core/service/ProtocolHasta.h | 2 +- telldus-core/service/ProtocolIkea.cpp | 4 +- telldus-core/service/ProtocolIkea.h | 2 +- telldus-core/service/ProtocolMandolyn.cpp | 4 +- telldus-core/service/ProtocolMandolyn.h | 4 +- telldus-core/service/ProtocolNexa.cpp | 52 +++++++++---------- telldus-core/service/ProtocolNexa.h | 4 +- telldus-core/service/ProtocolOregon.cpp | 6 +-- telldus-core/service/ProtocolOregon.h | 4 +- telldus-core/service/ProtocolRisingSun.cpp | 4 +- telldus-core/service/ProtocolRisingSun.h | 2 +- telldus-core/service/ProtocolSartano.cpp | 22 ++++---- telldus-core/service/ProtocolSartano.h | 4 +- telldus-core/service/ProtocolScene.cpp | 2 +- telldus-core/service/ProtocolScene.h | 2 +- telldus-core/service/ProtocolSilvanChip.cpp | 4 +- telldus-core/service/ProtocolSilvanChip.h | 2 +- telldus-core/service/ProtocolUpm.cpp | 2 +- telldus-core/service/ProtocolUpm.h | 2 +- telldus-core/service/ProtocolWaveman.cpp | 26 +++++----- telldus-core/service/ProtocolWaveman.h | 2 +- telldus-core/service/ProtocolX10.cpp | 2 +- telldus-core/service/ProtocolX10.h | 4 +- telldus-core/service/ProtocolYidong.cpp | 2 +- telldus-core/service/ProtocolYidong.h | 2 +- telldus-core/service/Sensor.cpp | 6 +-- telldus-core/service/Sensor.h | 2 +- telldus-core/service/Settings.cpp | 2 +- telldus-core/service/Settings.h | 2 +- telldus-core/service/SettingsConfuse.cpp | 8 +-- telldus-core/service/TellStick.cpp | 2 +- telldus-core/service/TellStick.h | 4 +- telldus-core/service/TellStick_libftdi.cpp | 16 +++--- telldus-core/service/TelldusMain.cpp | 20 +++---- telldus-core/service/Timer.cpp | 4 +- telldus-core/service/Timer.h | 4 +- telldus-core/service/main_unix.cpp | 8 +-- 91 files changed, 302 insertions(+), 300 deletions(-) diff --git a/telldus-core/client/CMakeLists.txt b/telldus-core/client/CMakeLists.txt index e07e4445..3336d298 100644 --- a/telldus-core/client/CMakeLists.txt +++ b/telldus-core/client/CMakeLists.txt @@ -24,9 +24,7 @@ SET( telldus-core_PUB_HDRS FIND_PACKAGE(Threads) LIST(APPEND telldus-core_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR}/../common -) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) ######## Configurable options for the platform ######## diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 664c303a..8f4f0309 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -7,7 +7,7 @@ * */ -#include "CallbackDispatcher.h" +#include "client/CallbackDispatcher.h" using namespace TelldusCore; diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 377b9f7a..1d19d7e7 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -10,11 +10,11 @@ #ifndef CALLBACKDISPATCHER_H #define CALLBACKDISPATCHER_H -#include "common.h" -#include "Event.h" -#include "Thread.h" -#include "Mutex.h" -#include "telldus-core.h" +#include "common/common.h" +#include "common/Event.h" +#include "common/Thread.h" +#include "common/Mutex.h" +#include "client/telldus-core.h" namespace TelldusCore { diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index fbc09cbd..a4bb67fe 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -7,7 +7,7 @@ * */ -#include "CallbackMainDispatcher.h" +#include "client/CallbackMainDispatcher.h" #include diff --git a/telldus-core/client/CallbackMainDispatcher.h b/telldus-core/client/CallbackMainDispatcher.h index a2d2f1c9..764780e3 100644 --- a/telldus-core/client/CallbackMainDispatcher.h +++ b/telldus-core/client/CallbackMainDispatcher.h @@ -10,10 +10,10 @@ #ifndef CALLBACKMAINDISPATCHER_H #define CALLBACKMAINDISPATCHER_H -#include "CallbackDispatcher.h" -#include "Thread.h" -#include "Event.h" -#include "EventHandler.h" +#include "client/CallbackDispatcher.h" +#include "common/Thread.h" +#include "common/Event.h" +#include "common/EventHandler.h" namespace TelldusCore { diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index b805bb14..0ace0ba2 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,12 +1,13 @@ -#include "Client.h" -#include "CallbackDispatcher.h" -#include "CallbackMainDispatcher.h" -#include "Socket.h" -#include "Strings.h" -#include "Mutex.h" +#include "client/Client.h" #include +#include "client/CallbackDispatcher.h" +#include "client/CallbackMainDispatcher.h" +#include "common/Socket.h" +#include "common/Strings.h" +#include "common/Mutex.h" + using namespace TelldusCore; class Client::PrivateData { diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 88b2b41d..ab627f24 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -1,10 +1,10 @@ #ifndef CLIENT_H #define CLIENT_H -#include "Message.h" -#include "telldus-core.h" -#include "Thread.h" -#include "CallbackDispatcher.h" +#include "client/telldus-core.h" +#include "client/CallbackDispatcher.h" +#include "common/Message.h" +#include "common/Thread.h" namespace TelldusCore { class Client : public Thread diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 6ec8ddfb..6ebfcea3 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -4,16 +4,15 @@ * @{ */ -#include "telldus-core.h" -#include "common.h" -#include "Client.h" -#include "Message.h" -#include "Socket.h" #include +#include "client/telldus-core.h" +#include "client/Client.h" +#include "common/common.h" +#include "common/Message.h" +#include "common/Socket.h" using namespace TelldusCore; - /** * @name Device method flags * Flags for the different methods/commands a device can support. Can be used diff --git a/telldus-core/common/CMakeLists.txt b/telldus-core/common/CMakeLists.txt index b55277e4..13aafa87 100644 --- a/telldus-core/common/CMakeLists.txt +++ b/telldus-core/common/CMakeLists.txt @@ -22,6 +22,8 @@ SET( telldus-common_HDRS Thread.h ) +INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR} ) + ######## Configurable options for the platform ######## diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index 02ed6b8c..ee369c35 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -1,6 +1,6 @@ -#include "Event.h" -#include "EventHandler.h" -#include "Mutex.h" +#include "common/Event.h" +#include "common/EventHandler.h" +#include "common/Mutex.h" #include diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index ec92c35d..15423507 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -11,6 +11,7 @@ #include typedef void* EVENT_T; #endif +#include "common/Thread.h" namespace TelldusCore { class EventHandler; diff --git a/telldus-core/common/EventHandler.h b/telldus-core/common/EventHandler.h index 7123bf90..974c420b 100644 --- a/telldus-core/common/EventHandler.h +++ b/telldus-core/common/EventHandler.h @@ -1,7 +1,7 @@ #ifndef EVENTHANDLER_H #define EVENTHANDLER_H -#include "Event.h" +#include "common/Event.h" namespace TelldusCore { diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index df36338e..59bf19b2 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -1,10 +1,10 @@ -#include "EventHandler.h" -#include "Event.h" -#include "Mutex.h" -#include "Thread.h" -#include #include #include +#include +#include "common/EventHandler.h" +#include "common/Event.h" +#include "common/Mutex.h" +#include "common/Thread.h" using namespace TelldusCore; diff --git a/telldus-core/common/Event_unix.cpp b/telldus-core/common/Event_unix.cpp index e6a375d7..22d68d80 100644 --- a/telldus-core/common/Event_unix.cpp +++ b/telldus-core/common/Event_unix.cpp @@ -1,6 +1,6 @@ -#include "Event.h" -#include "EventHandler.h" -#include "Thread.h" +#include "common/Event.h" +#include "common/EventHandler.h" +#include "common/Thread.h" using namespace TelldusCore; diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index efc847ea..6e286835 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -1,9 +1,9 @@ -#include "Message.h" -#include "Socket.h" -#include "Strings.h" -#include #include #include +#include +#include "common/Message.h" +#include "common/Socket.h" +#include "common/Strings.h" using namespace TelldusCore; @@ -63,7 +63,7 @@ void Message::addSpecialArgument(const std::wstring &value){ this->append(st.str()); this->append(L":"); this->append(value); - + } } @@ -77,7 +77,7 @@ void Message::addSpecialArgument(int value){ this->append(L"i"); //this->append(st.str()); this->append(L"s"); - + } } */ @@ -106,7 +106,7 @@ bool Message::nextIsString(const std::wstring &message) { } std::wstring Message::takeString(std::wstring *message) { - + if (!Message::nextIsString(*message)) { return L""; } diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index ca90ecfc..5a7b6436 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -10,8 +10,7 @@ // // -#include "Mutex.h" -#include "common.h" +#include "common/Mutex.h" using namespace TelldusCore; @@ -23,6 +22,8 @@ using namespace TelldusCore; typedef pthread_mutex_t MUTEX_T; #endif +#include "common/common.h" + class Mutex::PrivateData { public: MUTEX_T mutex; diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 947df5bb..357d7653 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -1,7 +1,3 @@ -#include "Socket.h" - -#include "Mutex.h" -#include "Strings.h" #include #include @@ -9,6 +5,10 @@ #include #include +#include "common/Socket.h" +#include "common/Mutex.h" +#include "common/Strings.h" + #define BUFSIZE 512 using namespace TelldusCore; diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index c1f53411..7074762b 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -1,5 +1,4 @@ -#include "Strings.h" - +#include "common/Strings.h" #include #include #include diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index 6415c1b2..f4cb6d71 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -10,11 +10,11 @@ // // -#include "Thread.h" +#include "common/Thread.h" #ifdef _WINDOWS #include #endif -#include "EventHandler.h" +#include "common/EventHandler.h" using namespace TelldusCore; diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index e7bf144e..877468bf 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -13,7 +13,7 @@ #define THREAD_H #include -#include "Mutex.h" +#include "common/Mutex.h" namespace TelldusCore { class ThreadPrivate; diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index a223a114..29c391d5 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -22,6 +22,7 @@ #include #include #include +#include "common/Strings.h" inline void msleep( const int msec) { #ifdef _WINDOWS diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 97b53857..d0964188 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -88,9 +88,7 @@ SET( telldus-service_HDRS FIND_PACKAGE(Threads REQUIRED) LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) -INCLUDE_DIRECTORIES( - ${CMAKE_CURRENT_SOURCE_DIR}/../common -) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) ######## Configurable options for the platform ######## @@ -250,7 +248,7 @@ IF (UNIX AND NOT APPLE) SET(STATE_INSTALL_DIR "${DEFAULT_STATE_INSTALL_DIR}" CACHE PATH "The directory to store state information of the devices") CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/SettingsConfusePaths.h.in - ${CMAKE_CURRENT_BINARY_DIR}/SettingsConfusePaths.h) + ${CMAKE_CURRENT_BINARY_DIR}/service/SettingsConfusePaths.h) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) INSTALL(FILES tellstick.conf diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index c6de79d0..356854bd 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -1,6 +1,6 @@ #include "ClientCommunicationHandler.h" -#include "Message.h" -#include "Strings.h" +#include "common/Message.h" +#include "common/Strings.h" #include diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 08c9d421..95fc6574 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -2,11 +2,11 @@ #define CLIENTCOMMUNICATIONHANDLER_H #include -#include "Thread.h" -#include "Socket.h" -#include "Event.h" -#include "DeviceManager.h" -#include "ControllerManager.h" +#include "common/Thread.h" +#include "common/Socket.h" +#include "common/Event.h" +#include "service/DeviceManager.h" +#include "service/ControllerManager.h" class ClientCommunicationHandler : public TelldusCore::Thread { diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index fe84f093..8a79ca16 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -2,8 +2,8 @@ #define CONNECTIONLISTENER_H #include -#include "Thread.h" -#include "Event.h" +#include "common/Thread.h" +#include "common/Event.h" class Event; namespace TelldusCore { diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index b1fbe2a4..6780e52e 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -1,5 +1,5 @@ -#include "ConnectionListener.h" -#include "Socket.h" +#include "service/ConnectionListener.h" +#include "common/Socket.h" #include #include diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index a9f22fc1..4fc27088 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -1,7 +1,7 @@ -#include "Controller.h" -#include "Protocol.h" -#include "EventUpdateManager.h" -#include "Strings.h" +#include "service/Controller.h" +#include "service/Protocol.h" +#include "service/EventUpdateManager.h" +#include "common/Strings.h" class Controller::PrivateData { public: diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 410abf53..e873b0e9 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -1,7 +1,7 @@ #ifndef CONTROLLER_H #define CONTROLLER_H -#include "Event.h" +#include "common/Event.h" #include class ControllerEventData : public TelldusCore::EventDataBase { diff --git a/telldus-core/service/ControllerListener.h b/telldus-core/service/ControllerListener.h index bae13a5e..cbb6f364 100644 --- a/telldus-core/service/ControllerListener.h +++ b/telldus-core/service/ControllerListener.h @@ -1,8 +1,8 @@ #ifndef CONTROLLERLISTENER_H #define CONTROLLERLISTENER_H -#include "Thread.h" -#include "Event.h" +#include "common/Thread.h" +#include "common/Event.h" class ControllerChangeEventData : public TelldusCore::EventDataBase { public: diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 91aed596..3a992c16 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -1,13 +1,13 @@ -#include "ControllerManager.h" -#include "Controller.h" -#include "Mutex.h" -#include "TellStick.h" -#include "Log.h" -#include "Message.h" -#include "Strings.h" -#include "Settings.h" -#include "EventUpdateManager.h" -#include "../client/telldus-core.h" +#include "service/ControllerManager.h" +#include "service/Controller.h" +#include "common/Mutex.h" +#include "service/TellStick.h" +#include "service/Log.h" +#include "common/Message.h" +#include "common/Strings.h" +#include "service/Settings.h" +#include "service/EventUpdateManager.h" +#include "client/telldus-core.h" #include #include diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index ccc6dd1e..5276c15c 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -1,7 +1,7 @@ #ifndef CONTROLLERMANAGER_H #define CONTROLLERMANAGER_H -#include "Event.h" +#include "common/Event.h" class Controller; #include diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index aa0135c9..a6bbdb7b 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -1,8 +1,8 @@ -#include "ControllerMessage.h" -#include "Device.h" -#include "Strings.h" +#include "service/ControllerMessage.h" +#include "service/Device.h" +#include "common/Strings.h" -#include "common.h" +#include "common/common.h" #include diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index f9757a1c..efad7081 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -1,6 +1,6 @@ -#include "Device.h" -#include "Settings.h" -#include "TellStick.h" +#include "service/Device.h" +#include "service/Settings.h" +#include "service/TellStick.h" class Device::PrivateData { public: diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 5efb8e06..e97a6604 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -1,9 +1,9 @@ #ifndef DEVICE_H #define DEVICE_H -#include "Controller.h" -#include "Mutex.h" -#include "Protocol.h" +#include "service/Controller.h" +#include "common/Mutex.h" +#include "service/Protocol.h" #include #include @@ -34,7 +34,7 @@ public: static int maskUnsupportedMethods(int methods, int supportedMethods); static int methodId( const std::string &methodName ); - + private: Protocol *retrieveProtocol() const; diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 3c8753e9..afab2e8b 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,11 +1,11 @@ -#include "DeviceManager.h" -#include "ControllerMessage.h" -#include "Mutex.h" -#include "Sensor.h" -#include "Settings.h" -#include "Strings.h" -#include "Message.h" -#include "Log.h" +#include "service/DeviceManager.h" +#include "service/ControllerMessage.h" +#include "common/Mutex.h" +#include "service/Sensor.h" +#include "service/Settings.h" +#include "common/Strings.h" +#include "common/Message.h" +#include "service/Log.h" #include #include diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index b4311761..e3930ad6 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -1,10 +1,10 @@ #ifndef DEVICEMANAGER_H #define DEVICEMANAGER_H -#include "Device.h" -#include "ControllerManager.h" -#include "ControllerMessage.h" -#include "EventUpdateManager.h" +#include "service/Device.h" +#include "service/ControllerManager.h" +#include "service/ControllerMessage.h" +#include "service/EventUpdateManager.h" #include class Sensor; diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 52fef5be..429c1a5e 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -1,9 +1,9 @@ -#include "EventUpdateManager.h" +#include "service/EventUpdateManager.h" -#include "ConnectionListener.h" -#include "EventHandler.h" -#include "Message.h" -#include "Socket.h" +#include "service/ConnectionListener.h" +#include "common/EventHandler.h" +#include "common/Message.h" +#include "common/Socket.h" #include #include diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 636b067f..4e664ac8 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -1,8 +1,8 @@ #ifndef EVENTUPDATEMANAGER_H #define EVENTUPDATEMANAGER_H -#include "Thread.h" -#include "Event.h" +#include "common/Thread.h" +#include "common/Event.h" class EventUpdateData : public TelldusCore::EventDataBase { public: diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index a4e5cf2f..bf4b15d7 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -1,12 +1,12 @@ -#include "Log.h" +#include "service/Log.h" #include #if defined(_LINUX) #include #elif defined(_WINDOWS) #include -#include "Strings.h" -#include "Messages.h" +#include "service/Strings.h" +#include "service/Messages.h" #endif class Log::PrivateData { diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 67a66e2f..fd6d2cce 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,28 +1,28 @@ -#include "Protocol.h" -#include "../client/telldus-core.h" +#include "service/Protocol.h" +#include "client/telldus-core.h" -#include "ControllerMessage.h" -#include "ProtocolBrateck.h" -#include "ProtocolComen.h" -#include "ProtocolEverflourish.h" -#include "ProtocolFineoffset.h" -#include "ProtocolFuhaote.h" -#include "ProtocolGroup.h" -#include "ProtocolHasta.h" -#include "ProtocolIkea.h" -#include "ProtocolMandolyn.h" -#include "ProtocolNexa.h" -#include "ProtocolOregon.h" -#include "ProtocolRisingSun.h" -#include "ProtocolSartano.h" -#include "ProtocolScene.h" -#include "ProtocolSilvanChip.h" -#include "ProtocolUpm.h" -#include "ProtocolWaveman.h" -#include "ProtocolX10.h" -#include "ProtocolYidong.h" +#include "service/ControllerMessage.h" +#include "service/ProtocolBrateck.h" +#include "service/ProtocolComen.h" +#include "service/ProtocolEverflourish.h" +#include "service/ProtocolFineoffset.h" +#include "service/ProtocolFuhaote.h" +#include "service/ProtocolGroup.h" +#include "service/ProtocolHasta.h" +#include "service/ProtocolIkea.h" +#include "service/ProtocolMandolyn.h" +#include "service/ProtocolNexa.h" +#include "service/ProtocolOregon.h" +#include "service/ProtocolRisingSun.h" +#include "service/ProtocolSartano.h" +#include "service/ProtocolScene.h" +#include "service/ProtocolSilvanChip.h" +#include "service/ProtocolUpm.h" +#include "service/ProtocolWaveman.h" +#include "service/ProtocolX10.h" +#include "service/ProtocolYidong.h" -#include "Strings.h" +#include "common/Strings.h" #include class Protocol::PrivateData { diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index bfcce857..ca2948b6 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -4,7 +4,7 @@ #include #include #include -#include "../client/telldus-core.h" +#include "client/telldus-core.h" typedef std::map ParameterMap; diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index da9e222e..1c44400a 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -1,4 +1,4 @@ -#include "ProtocolBrateck.h" +#include "service/ProtocolBrateck.h" int ProtocolBrateck::methods() const { return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index 97eba44d..da8ed5c0 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLBRATECK_H #define PROTOCOLBRATECK_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolBrateck : public Protocol { diff --git a/telldus-core/service/ProtocolComen.cpp b/telldus-core/service/ProtocolComen.cpp index 9fa36c64..a372e0b8 100644 --- a/telldus-core/service/ProtocolComen.cpp +++ b/telldus-core/service/ProtocolComen.cpp @@ -1,4 +1,4 @@ -#include "ProtocolComen.h" +#include "service/ProtocolComen.h" int ProtocolComen::methods() const { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); diff --git a/telldus-core/service/ProtocolComen.h b/telldus-core/service/ProtocolComen.h index 35bdab8a..39b4631e 100644 --- a/telldus-core/service/ProtocolComen.h +++ b/telldus-core/service/ProtocolComen.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLCOMEN_H #define PROTOCOLCOMEN_H -#include "ProtocolNexa.h" +#include "service/ProtocolNexa.h" #include class ProtocolComen : public ProtocolNexa { diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 4738bb96..ae7c87e3 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -1,7 +1,7 @@ #include "ProtocolEverflourish.h" #include #include -#include "ControllerMessage.h" +#include "service/ControllerMessage.h" int ProtocolEverflourish::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; @@ -21,7 +21,7 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, } else { return ""; } - + const char ssss = 85; const char sssl = 84; // 0 const char slss = 69; // 1 @@ -32,7 +32,7 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, std::string strCode; deviceCode = (deviceCode << 2) | intCode; - + check = calculateChecksum(deviceCode); char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss,0}; @@ -47,7 +47,7 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, for(i=3;i>=0;i--) { strCode.append(1, bits[(action>>i)&0x01]); } - + strCode.append(1, ssss); strCode.append(1, '+'); @@ -84,7 +84,7 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { bit = bit << 1; } - return res; + return res; } std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) @@ -94,23 +94,23 @@ std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; - + sscanf(data.c_str(), "%X", &allData); - + house = allData & 0xFFFC00; house >>= 10; - + unit = allData & 0x300; unit >>= 8; unit++; //unit from 1 to 4 - + method = allData & 0xF; - + if(house < 0 || house > 16383 || unit < 1 || unit > 4){ //not everflourish return ""; } - + std::stringstream retString; retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:"; if(method == 0){ @@ -126,6 +126,6 @@ std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) //not everflourish return ""; } - + return retString.str(); -} \ No newline at end of file +} diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 28d783eb..6dbffdaf 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -1,8 +1,8 @@ #ifndef PROTOCOLEVERFLOURISH_H #define PROTOCOLEVERFLOURISH_H -#include "ControllerMessage.h" -#include "Protocol.h" +#include "service/Protocol.h" +#include "service/ControllerMessage.h" class ProtocolEverflourish : public Protocol { diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index 3e4b444b..1fb94a19 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -1,5 +1,5 @@ -#include "ProtocolFineoffset.h" -#include "Strings.h" +#include "service/ProtocolFineoffset.h" +#include "common/Strings.h" #include #include #include diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h index fbae92c0..dba7946a 100644 --- a/telldus-core/service/ProtocolFineoffset.h +++ b/telldus-core/service/ProtocolFineoffset.h @@ -1,8 +1,8 @@ #ifndef PROTOCOLFINEOFFSET_H #define PROTOCOLFINEOFFSET_H -#include "ControllerMessage.h" -#include "Protocol.h" +#include "service/Protocol.h" +#include "service/ControllerMessage.h" class ProtocolFineoffset : public Protocol { diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index 7baa2a30..357f1fe7 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -1,4 +1,4 @@ -#include "ProtocolFuhaote.h" +#include "service/ProtocolFuhaote.h" int ProtocolFuhaote::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index 3b89d06c..a68c7f70 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLFUHAOTE_H #define PROTOCOLFUHAOTE_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolFuhaote : public Protocol { diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index 3d553022..aaaaeb04 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -1,4 +1,4 @@ -#include "ProtocolGroup.h" +#include "service/ProtocolGroup.h" int ProtocolGroup::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; diff --git a/telldus-core/service/ProtocolGroup.h b/telldus-core/service/ProtocolGroup.h index c98a14c3..f9689c02 100644 --- a/telldus-core/service/ProtocolGroup.h +++ b/telldus-core/service/ProtocolGroup.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLGROUP_H #define PROTOCOLGROUP_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolGroup : public Protocol { public: diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index 5aaa35e4..8166c8a5 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -1,4 +1,4 @@ -#include "ProtocolHasta.h" +#include "service/ProtocolHasta.h" #include #include @@ -63,4 +63,4 @@ std::string ProtocolHasta::convertByte(unsigned char byte) { byte >>= 1; } return retval; -} \ No newline at end of file +} diff --git a/telldus-core/service/ProtocolHasta.h b/telldus-core/service/ProtocolHasta.h index 971f0762..d13555be 100644 --- a/telldus-core/service/ProtocolHasta.h +++ b/telldus-core/service/ProtocolHasta.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLHASTA_H #define PROTOCOLHASTA_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolHasta : public Protocol { diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index bed01926..3c65e63b 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -1,5 +1,5 @@ -#include "ProtocolIkea.h" -#include "Strings.h" +#include "service/ProtocolIkea.h" +#include "common/Strings.h" #include #include diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index 81327d8e..07cd294a 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLIKEA_H #define PROTOCOLIKEA_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolIkea : public Protocol { diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index 8468adf6..a93864d1 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -1,5 +1,5 @@ -#include "ProtocolMandolyn.h" -#include "Strings.h" +#include "service/ProtocolMandolyn.h" +#include "common/Strings.h" #include #include #include diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h index a3ff0700..08ead0eb 100644 --- a/telldus-core/service/ProtocolMandolyn.h +++ b/telldus-core/service/ProtocolMandolyn.h @@ -1,8 +1,8 @@ #ifndef PROTOCOLMANDOLYN_H #define PROTOCOLMANDOLYN_H -#include "ControllerMessage.h" -#include "Protocol.h" +#include "service/Protocol.h" +#include "service/ControllerMessage.h" class ProtocolMandolyn : public Protocol { diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 7faea29e..9b43a7c7 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,8 +1,8 @@ -#include "ProtocolNexa.h" -#include +#include "service/ProtocolNexa.h" #include -#include "TellStick.h" -#include "Strings.h" +#include +#include "service/TellStick.h" +#include "common/Strings.h" int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; //TODO, always removing first turnon now, make more flexible (waveman too) @@ -160,12 +160,12 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) { unsigned long allData = 0; - + sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); - + if(TelldusCore::comparei(dataMsg.model(), L"selflearning")){ //selflearning - return decodeDataSelfLearning(allData); + return decodeDataSelfLearning(allData); } else{ //codeswitch @@ -178,24 +178,24 @@ std::string ProtocolNexa::decodeDataSelfLearning(long allData){ unsigned int unit = 0; unsigned int group = 0; unsigned int method = 0; - + house = allData & 0xFFFFFFC0; house >>= 6; - + group = allData & 0x20; group >>= 5; - + method = allData & 0x10; method >>= 4; - + unit = allData & 0xF; unit++; - + if(house < 1 || house > 67108863 || unit < 1 || unit > 16){ //not arctech selflearning return ""; } - + std::stringstream retString; retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:"; if(method == 1){ @@ -208,45 +208,45 @@ std::string ProtocolNexa::decodeDataSelfLearning(long allData){ //not arctech selflearning return ""; } - + return retString.str(); } std::string ProtocolNexa::decodeDataCodeSwitch(long allData){ - + unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; - + method = allData & 0xF00; method >>= 8; - + unit = allData & 0xF0; unit >>= 4; unit++; - + house = allData & 0xF; - + if(house < 0 || house > 16 || unit < 1 || unit > 16){ //not arctech codeswitch return ""; } - + house = house + 'A'; //house from A to P - + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ lastArctecCodeSwitchWasTurnOff = 0; return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - //one turnon/bell, but it's better than the alternative... + //one turnon/bell, but it's better than the alternative... } - + if(method == 6){ lastArctecCodeSwitchWasTurnOff = 1; } - + std::stringstream retString; retString << "class:command;protocol:arctech;model:codeswitch;house:" << char(house); - + if(method == 6){ retString << ";unit:" << unit << ";method:turnoff;"; } @@ -260,7 +260,7 @@ std::string ProtocolNexa::decodeDataCodeSwitch(long allData){ //not arctech codeswitch return ""; } - + return retString.str(); } diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 90cf06db..ac6b8906 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -1,8 +1,8 @@ #ifndef PROTOCOLNEXA_H #define PROTOCOLNEXA_H -#include "ControllerMessage.h" -#include "Device.h" +#include "service/ControllerMessage.h" +#include "service/Device.h" #include class ProtocolNexa : public Protocol { diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index a22d2942..30f7ad86 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -1,5 +1,5 @@ -#include "ProtocolOregon.h" -#include "Strings.h" +#include "service/ProtocolOregon.h" +#include "common/Strings.h" #include #include #include @@ -20,7 +20,7 @@ std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) std::string ProtocolOregon::decodeEA4C(const std::string &data) { uint64_t value = TelldusCore::hexTo64l(data); - + uint8_t checksum = 0xE + 0xA + 0x4 + 0xC; checksum -= (value & 0xF) * 0x10; checksum -= 0xA; diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index 8d8c3c8f..1210430c 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -1,8 +1,8 @@ #ifndef PROTOCOLOREGON_H #define PROTOCOLOREGON_H -#include "ControllerMessage.h" -#include "Protocol.h" +#include "service/Protocol.h" +#include "service/ControllerMessage.h" class ProtocolOregon : public Protocol { diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index 192c900d..b1cde0e7 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -1,5 +1,5 @@ -#include "ProtocolRisingSun.h" -#include "Strings.h" +#include "service/ProtocolRisingSun.h" +#include "common/Strings.h" int ProtocolRisingSun::methods() const { if (TelldusCore::comparei(model(), L"selflearning")) { diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h index 1d338fc3..f2775ac2 100644 --- a/telldus-core/service/ProtocolRisingSun.h +++ b/telldus-core/service/ProtocolRisingSun.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLRISINGSUN_H #define PROTOCOLRISINGSUN_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolRisingSun : public Protocol { diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index b0456825..4fb92ea9 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -1,4 +1,4 @@ -#include "ProtocolSartano.h" +#include "service/ProtocolSartano.h" #include #include @@ -44,9 +44,9 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) unsigned int method1 = 0; unsigned int method2 = 0; unsigned int method = 0; - + sscanf(data.c_str(), "%X", &allDataIn); - + unsigned long mask = (1<<11); for(int i=0;i<12;++i){ allData >>= 1; @@ -55,15 +55,15 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) } mask >>= 1; } - + code = allData & 0xFFC; code >>= 2; - + method1 = allData & 0x2; method1 >>= 1; - + method2 = allData & 0x1; - + if(method1 == 0 && method2 == 1){ method = 0; //off } @@ -73,12 +73,12 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) else{ return ""; } - + if(code < 0 || code > 1023){ //not sartano return ""; } - + std::stringstream retString; retString << "class:command;protocol:sartano;model:codeswitch;code:"; mask = (1<<9); @@ -92,13 +92,13 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) mask >>= 1; } retString << ";method:"; - + if(method == 0){ retString << "turnoff;"; } else{ retString << "turnon;"; } - + return retString.str(); } diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index 6c38a263..0f555442 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -1,8 +1,8 @@ #ifndef PROTOCOLSARTANO_H #define PROTOCOLSARTANO_H -#include "ControllerMessage.h" -#include "Protocol.h" +#include "service/Protocol.h" +#include "service/ControllerMessage.h" class ProtocolSartano : public Protocol { diff --git a/telldus-core/service/ProtocolScene.cpp b/telldus-core/service/ProtocolScene.cpp index e18e362a..f30f702b 100644 --- a/telldus-core/service/ProtocolScene.cpp +++ b/telldus-core/service/ProtocolScene.cpp @@ -1,4 +1,4 @@ -#include "ProtocolScene.h" +#include "service/ProtocolScene.h" int ProtocolScene::methods() const { return TELLSTICK_EXECUTE; diff --git a/telldus-core/service/ProtocolScene.h b/telldus-core/service/ProtocolScene.h index aaa22ebb..2a4979c1 100644 --- a/telldus-core/service/ProtocolScene.h +++ b/telldus-core/service/ProtocolScene.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLSCENE_H #define PROTOCOLSCENE_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolScene : public Protocol { public: diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 23226e69..b08cd294 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -1,5 +1,5 @@ -#include "ProtocolSilvanChip.h" -#include "Strings.h" +#include "service/ProtocolSilvanChip.h" +#include "common/Strings.h" int ProtocolSilvanChip::methods() const { if (TelldusCore::comparei(model(), L"kp100")) { diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h index c27dcc52..ba55cb25 100644 --- a/telldus-core/service/ProtocolSilvanChip.h +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLSILVANCHIP_H #define PROTOCOLSILVANCHIP_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolSilvanChip : public Protocol { diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 65bf7b28..58406e80 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -1,4 +1,4 @@ -#include "ProtocolUpm.h" +#include "service/ProtocolUpm.h" int ProtocolUpm::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h index 1f91dafe..74724f24 100644 --- a/telldus-core/service/ProtocolUpm.h +++ b/telldus-core/service/ProtocolUpm.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLUPM_H #define PROTOCOLUPM_H -#include "Protocol.h" +#include "service/Protocol.h" class ProtocolUpm : public Protocol { diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 14ddb65b..7adfe3ef 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -1,4 +1,4 @@ -#include "ProtocolWaveman.h" +#include "service/ProtocolWaveman.h" #include #include @@ -22,38 +22,38 @@ std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; - + sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); - + method = allData & 0xF00; method >>= 8; - + unit = allData & 0xF0; unit >>= 4; unit++; - + house = allData & 0xF; - + if(house < 0 || house > 16 || unit < 1 || unit > 16){ //not waveman return ""; } - + house = house + 'A'; //house from A to P - + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ lastArctecCodeSwitchWasTurnOff = 0; return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - //one turnon/bell, but it's better than the alternative... + //one turnon/bell, but it's better than the alternative... } - + if(method == 6){ lastArctecCodeSwitchWasTurnOff = 1; } - + std::stringstream retString; retString << "class:command;protocol:waveman;model:codeswitch;house:" << char(house); - + if(method == 0){ retString << ";unit:" << unit << ";method:turnoff;"; } @@ -64,6 +64,6 @@ std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) //not waveman return ""; } - + return retString.str(); } diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h index 69b26333..76453643 100644 --- a/telldus-core/service/ProtocolWaveman.h +++ b/telldus-core/service/ProtocolWaveman.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLWAVEMAN_H #define PROTOCOLWAVEMAN_H -#include "ProtocolNexa.h" +#include "service/ProtocolNexa.h" class ProtocolWaveman : public ProtocolNexa { public: diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index ad9bcb55..c0dc108f 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -1,4 +1,4 @@ -#include "ProtocolX10.h" +#include "service/ProtocolX10.h" #include #include diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 8e53095e..0df0067d 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -1,8 +1,8 @@ #ifndef PROTOCOLX10_H #define PROTOCOLX10_H -#include "Protocol.h" -#include "ControllerMessage.h" +#include "service/Protocol.h" +#include "service/ControllerMessage.h" class ProtocolX10 : public Protocol { diff --git a/telldus-core/service/ProtocolYidong.cpp b/telldus-core/service/ProtocolYidong.cpp index e0310d08..94487028 100644 --- a/telldus-core/service/ProtocolYidong.cpp +++ b/telldus-core/service/ProtocolYidong.cpp @@ -1,4 +1,4 @@ -#include "ProtocolYidong.h" +#include "service/ProtocolYidong.h" std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { int intCode = this->getIntParameter(L"unit", 1, 4); diff --git a/telldus-core/service/ProtocolYidong.h b/telldus-core/service/ProtocolYidong.h index 580d250f..df64e6a4 100644 --- a/telldus-core/service/ProtocolYidong.h +++ b/telldus-core/service/ProtocolYidong.h @@ -1,7 +1,7 @@ #ifndef PROTOCOLYIDONG_H #define PROTOCOLYIDONG_H -#include "ProtocolSartano.h" +#include "service/ProtocolSartano.h" class ProtocolYidong : public ProtocolSartano { diff --git a/telldus-core/service/Sensor.cpp b/telldus-core/service/Sensor.cpp index 649a576a..af9bbb07 100644 --- a/telldus-core/service/Sensor.cpp +++ b/telldus-core/service/Sensor.cpp @@ -1,6 +1,6 @@ -#include "Sensor.h" -#include "common.h" -#include "../client/telldus-core.h" +#include "service/Sensor.h" +#include "common/common.h" +#include "client/telldus-core.h" #include class Sensor::PrivateData { diff --git a/telldus-core/service/Sensor.h b/telldus-core/service/Sensor.h index 83fcf57d..61eb9cee 100644 --- a/telldus-core/service/Sensor.h +++ b/telldus-core/service/Sensor.h @@ -1,7 +1,7 @@ #ifndef SENSOR_H #define SENSOR_H -#include "Mutex.h" +#include "common/Mutex.h" #include class Sensor : public TelldusCore::Mutex diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 541ec8c7..86170231 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -1,4 +1,4 @@ -#include "Settings.h" +#include "service/Settings.h" TelldusCore::Mutex Settings::mutex; diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index d4a6bfc1..7863c643 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -2,7 +2,7 @@ #define SETTINGS_H #include -#include "Mutex.h" +#include "common/Mutex.h" class Settings { public: diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 0948793a..c421be31 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -10,9 +10,11 @@ // // #include "Settings.h" -#include "SettingsConfusePaths.h" -#include "../client/telldus-core.h" -#include "Strings.h" +#include "client/telldus-core.h" +#include "service/Settings.h" +#include "service/SettingsConfusePaths.h" +#include "client/telldus-core.h" +#include "common/Strings.h" #include #include #include diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index b77f512f..d0ad01df 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -9,7 +9,7 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "TellStick.h" +#include "service/TellStick.h" #include #include diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 05e76b04..246feb1f 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -12,9 +12,9 @@ #ifndef TELLSTICK_H #define TELLSTICK_H -#include "Controller.h" -#include "Thread.h" #include +#include "service/Controller.h" +#include "common/Thread.h" class TellStickDescriptor { public: diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 9f8a919c..6e805bb6 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -9,19 +9,19 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "TellStick.h" -#include "../client/telldus-core.h" +#include "service/TellStick.h" +#include "client/telldus-core.h" #include #include #include #include -#include "Thread.h" -#include "Mutex.h" -#include "Log.h" -#include "Settings.h" -#include "Strings.h" -#include "common.h" +#include "service/Log.h" +#include "service/Settings.h" +#include "common/Thread.h" +#include "common/Mutex.h" +#include "common/Strings.h" +#include "common/common.h" #include diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index a45f9899..a1f59fa7 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -1,13 +1,13 @@ -#include "TelldusMain.h" -#include "ConnectionListener.h" -#include "EventHandler.h" -#include "ClientCommunicationHandler.h" -#include "DeviceManager.h" -#include "ControllerManager.h" -#include "ControllerListener.h" -#include "EventUpdateManager.h" -#include "Timer.h" -#include "Log.h" +#include "service/TelldusMain.h" +#include "service/ConnectionListener.h" +#include "common/EventHandler.h" +#include "service/ClientCommunicationHandler.h" +#include "service/DeviceManager.h" +#include "service/ControllerManager.h" +#include "service/ControllerListener.h" +#include "service/EventUpdateManager.h" +#include "service/Timer.h" +#include "service/Log.h" #include #include diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index 567befb0..070bcc29 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -1,5 +1,5 @@ -#include "Timer.h" -#include "Mutex.h" +#include "service/Timer.h" +#include "common/Mutex.h" #ifdef _WINDOWS #else #include diff --git a/telldus-core/service/Timer.h b/telldus-core/service/Timer.h index fcb15356..cc08381c 100644 --- a/telldus-core/service/Timer.h +++ b/telldus-core/service/Timer.h @@ -1,8 +1,8 @@ #ifndef TIMER_H #define TIMER_H -#include "Event.h" -#include "Thread.h" +#include "common/Event.h" +#include "common/Thread.h" class Timer : public TelldusCore::Thread { public: diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index dd0c3659..ef287b62 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -1,4 +1,4 @@ -#include "TelldusMain.h" +#include "service/TelldusMain.h" #include #include #include @@ -9,9 +9,9 @@ #include #include -#include "Settings.h" -#include "Strings.h" -#include "Log.h" +#include "service/Settings.h" +#include "common/Strings.h" +#include "service/Log.h" #define DAEMON_NAME "telldusd" #define PID_FILE "/var/run/" DAEMON_NAME ".pid" From 8d0228ced2622f3d5867b10c74d756ce0fffc0cf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 10:06:47 +0200 Subject: [PATCH 2001/2215] Add copyright message according to Google style guidelines "legal/copyright" --- telldus-core/client/Client.cpp | 6 ++++++ telldus-core/client/Client.h | 6 ++++++ telldus-core/client/telldus-core.cpp | 6 ++++++ telldus-core/client/telldus-core.h | 6 ++++++ telldus-core/common/Event.cpp | 6 ++++++ telldus-core/common/Event.h | 6 ++++++ telldus-core/common/EventHandler.h | 6 ++++++ telldus-core/common/EventHandler_unix.cpp | 6 ++++++ telldus-core/common/Event_unix.cpp | 6 ++++++ telldus-core/common/Message.cpp | 6 ++++++ telldus-core/common/Message.h | 6 ++++++ telldus-core/common/Socket.h | 6 ++++++ telldus-core/common/Socket_unix.cpp | 6 ++++++ telldus-core/common/Strings.cpp | 7 +++++++ telldus-core/common/Strings.h | 6 ++++++ telldus-core/service/ClientCommunicationHandler.cpp | 6 ++++++ telldus-core/service/ClientCommunicationHandler.h | 6 ++++++ telldus-core/service/ConnectionListener.h | 6 ++++++ telldus-core/service/ConnectionListener_unix.cpp | 6 ++++++ telldus-core/service/Controller.cpp | 6 ++++++ telldus-core/service/Controller.h | 6 ++++++ telldus-core/service/ControllerListener.h | 6 ++++++ telldus-core/service/ControllerManager.cpp | 6 ++++++ telldus-core/service/ControllerManager.h | 6 ++++++ telldus-core/service/ControllerMessage.cpp | 6 ++++++ telldus-core/service/ControllerMessage.h | 6 ++++++ telldus-core/service/Device.cpp | 6 ++++++ telldus-core/service/Device.h | 6 ++++++ telldus-core/service/DeviceManager.cpp | 6 ++++++ telldus-core/service/DeviceManager.h | 6 ++++++ telldus-core/service/EventUpdateManager.cpp | 6 ++++++ telldus-core/service/EventUpdateManager.h | 6 ++++++ telldus-core/service/Log.cpp | 6 ++++++ telldus-core/service/Log.h | 6 ++++++ telldus-core/service/Protocol.cpp | 6 ++++++ telldus-core/service/Protocol.h | 6 ++++++ telldus-core/service/ProtocolBrateck.cpp | 6 ++++++ telldus-core/service/ProtocolBrateck.h | 6 ++++++ telldus-core/service/ProtocolComen.cpp | 6 ++++++ telldus-core/service/ProtocolComen.h | 6 ++++++ telldus-core/service/ProtocolEverflourish.cpp | 6 ++++++ telldus-core/service/ProtocolEverflourish.h | 6 ++++++ telldus-core/service/ProtocolFineoffset.cpp | 6 ++++++ telldus-core/service/ProtocolFineoffset.h | 6 ++++++ telldus-core/service/ProtocolFuhaote.cpp | 6 ++++++ telldus-core/service/ProtocolFuhaote.h | 6 ++++++ telldus-core/service/ProtocolGroup.cpp | 6 ++++++ telldus-core/service/ProtocolGroup.h | 6 ++++++ telldus-core/service/ProtocolHasta.cpp | 6 ++++++ telldus-core/service/ProtocolHasta.h | 6 ++++++ telldus-core/service/ProtocolIkea.cpp | 6 ++++++ telldus-core/service/ProtocolIkea.h | 6 ++++++ telldus-core/service/ProtocolMandolyn.cpp | 6 ++++++ telldus-core/service/ProtocolMandolyn.h | 6 ++++++ telldus-core/service/ProtocolNexa.cpp | 6 ++++++ telldus-core/service/ProtocolNexa.h | 8 +++++++- telldus-core/service/ProtocolOregon.cpp | 6 ++++++ telldus-core/service/ProtocolOregon.h | 6 ++++++ telldus-core/service/ProtocolRisingSun.cpp | 6 ++++++ telldus-core/service/ProtocolRisingSun.h | 6 ++++++ telldus-core/service/ProtocolSartano.cpp | 6 ++++++ telldus-core/service/ProtocolSartano.h | 6 ++++++ telldus-core/service/ProtocolScene.cpp | 6 ++++++ telldus-core/service/ProtocolScene.h | 6 ++++++ telldus-core/service/ProtocolSilvanChip.cpp | 6 ++++++ telldus-core/service/ProtocolSilvanChip.h | 6 ++++++ telldus-core/service/ProtocolUpm.cpp | 6 ++++++ telldus-core/service/ProtocolUpm.h | 6 ++++++ telldus-core/service/ProtocolWaveman.cpp | 6 ++++++ telldus-core/service/ProtocolWaveman.h | 6 ++++++ telldus-core/service/ProtocolX10.cpp | 6 ++++++ telldus-core/service/ProtocolX10.h | 6 ++++++ telldus-core/service/ProtocolYidong.cpp | 6 ++++++ telldus-core/service/ProtocolYidong.h | 6 ++++++ telldus-core/service/Sensor.cpp | 6 ++++++ telldus-core/service/Sensor.h | 6 ++++++ telldus-core/service/Settings.cpp | 6 ++++++ telldus-core/service/Settings.h | 6 ++++++ telldus-core/service/SettingsConfuse.cpp | 7 +------ telldus-core/service/TellStick.cpp | 7 +------ telldus-core/service/TellStick.h | 7 +------ telldus-core/service/TellStick_libftdi.cpp | 7 +------ telldus-core/service/TelldusMain.cpp | 6 ++++++ telldus-core/service/TelldusMain.h | 6 ++++++ telldus-core/service/Timer.cpp | 6 ++++++ telldus-core/service/Timer.h | 6 ++++++ telldus-core/service/main_unix.cpp | 6 ++++++ 87 files changed, 504 insertions(+), 25 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 0ace0ba2..eb5cacee 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "client/Client.h" #include diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index ab627f24..6cce43a5 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef CLIENT_H #define CLIENT_H diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 6ebfcea3..7a084e9a 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// /** * @defgroup core telldus-core * Telldus Core is the base module used to interface a Telldus TellStick. diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 275373da..fbc77338 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef TELLDUSCORE_H #define TELLDUSCORE_H diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index ee369c35..7f89ecf9 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "common/Event.h" #include "common/EventHandler.h" #include "common/Mutex.h" diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index 15423507..881e0b69 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef EVENT_H #define EVENT_H diff --git a/telldus-core/common/EventHandler.h b/telldus-core/common/EventHandler.h index 974c420b..e7ad06c8 100644 --- a/telldus-core/common/EventHandler.h +++ b/telldus-core/common/EventHandler.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef EVENTHANDLER_H #define EVENTHANDLER_H diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 59bf19b2..4db41f73 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include #include #include diff --git a/telldus-core/common/Event_unix.cpp b/telldus-core/common/Event_unix.cpp index 22d68d80..be31ee89 100644 --- a/telldus-core/common/Event_unix.cpp +++ b/telldus-core/common/Event_unix.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "common/Event.h" #include "common/EventHandler.h" #include "common/Thread.h" diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 6e286835..030564fa 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include #include #include diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 50c06702..65b40112 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef MESSAGE_H #define MESSAGE_H diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index a7ef6435..0646aa9e 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef SOCKET_H #define SOCKET_H diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 357d7653..d6e5bc07 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include #include diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 7074762b..3b451b0e 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -1,3 +1,10 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// + #include "common/Strings.h" #include #include diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index 28e671c2..d7883bbd 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef STRING_H #define STRING_H diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 356854bd..31b5e527 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "ClientCommunicationHandler.h" #include "common/Message.h" #include "common/Strings.h" diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 95fc6574..7e560b4b 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef CLIENTCOMMUNICATIONHANDLER_H #define CLIENTCOMMUNICATIONHANDLER_H diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index 8a79ca16..b41d39fa 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef CONNECTIONLISTENER_H #define CONNECTIONLISTENER_H diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 6780e52e..02344bd9 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ConnectionListener.h" #include "common/Socket.h" diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 4fc27088..b0fc19d2 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/Controller.h" #include "service/Protocol.h" #include "service/EventUpdateManager.h" diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index e873b0e9..2ec22143 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef CONTROLLER_H #define CONTROLLER_H diff --git a/telldus-core/service/ControllerListener.h b/telldus-core/service/ControllerListener.h index cbb6f364..3f28ec99 100644 --- a/telldus-core/service/ControllerListener.h +++ b/telldus-core/service/ControllerListener.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef CONTROLLERLISTENER_H #define CONTROLLERLISTENER_H diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 3a992c16..5f58409d 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ControllerManager.h" #include "service/Controller.h" #include "common/Mutex.h" diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index 5276c15c..cecf57d5 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef CONTROLLERMANAGER_H #define CONTROLLERMANAGER_H diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index a6bbdb7b..ce42e0ab 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ControllerMessage.h" #include "service/Device.h" #include "common/Strings.h" diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index d08691ec..767903bc 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef CONTROLLERMESSAGE_H #define CONTROLLERMESSAGE_H diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index efad7081..7a68821c 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/Device.h" #include "service/Settings.h" #include "service/TellStick.h" diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index e97a6604..1d0f630f 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef DEVICE_H #define DEVICE_H diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index afab2e8b..5d8098a5 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/DeviceManager.h" #include "service/ControllerMessage.h" #include "common/Mutex.h" diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index e3930ad6..c5c12ce9 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef DEVICEMANAGER_H #define DEVICEMANAGER_H diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 429c1a5e..e966a867 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/EventUpdateManager.h" #include "service/ConnectionListener.h" diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 4e664ac8..5ae1dc98 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef EVENTUPDATEMANAGER_H #define EVENTUPDATEMANAGER_H diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index bf4b15d7..c4a8f482 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/Log.h" #include diff --git a/telldus-core/service/Log.h b/telldus-core/service/Log.h index c204e75d..0b462b82 100644 --- a/telldus-core/service/Log.h +++ b/telldus-core/service/Log.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef LOG_H #define LOG_H diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index fd6d2cce..04fbacbc 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/Protocol.h" #include "client/telldus-core.h" diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index ca2948b6..4dd8e8a4 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOL_H #define PROTOCOL_H diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 1c44400a..290a0e49 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolBrateck.h" int ProtocolBrateck::methods() const { diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index da8ed5c0..fb385e29 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLBRATECK_H #define PROTOCOLBRATECK_H diff --git a/telldus-core/service/ProtocolComen.cpp b/telldus-core/service/ProtocolComen.cpp index a372e0b8..a12f85c6 100644 --- a/telldus-core/service/ProtocolComen.cpp +++ b/telldus-core/service/ProtocolComen.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolComen.h" int ProtocolComen::methods() const { diff --git a/telldus-core/service/ProtocolComen.h b/telldus-core/service/ProtocolComen.h index 39b4631e..4a54572c 100644 --- a/telldus-core/service/ProtocolComen.h +++ b/telldus-core/service/ProtocolComen.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLCOMEN_H #define PROTOCOLCOMEN_H diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index ae7c87e3..0d59c8d0 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "ProtocolEverflourish.h" #include #include diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 6dbffdaf..f4c54029 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLEVERFLOURISH_H #define PROTOCOLEVERFLOURISH_H diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index 1fb94a19..11abe163 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolFineoffset.h" #include "common/Strings.h" #include diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h index dba7946a..501e6426 100644 --- a/telldus-core/service/ProtocolFineoffset.h +++ b/telldus-core/service/ProtocolFineoffset.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLFINEOFFSET_H #define PROTOCOLFINEOFFSET_H diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index 357f1fe7..dcc9cede 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolFuhaote.h" int ProtocolFuhaote::methods() const { diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index a68c7f70..f6f9020c 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLFUHAOTE_H #define PROTOCOLFUHAOTE_H diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index aaaaeb04..41748e45 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolGroup.h" int ProtocolGroup::methods() const { diff --git a/telldus-core/service/ProtocolGroup.h b/telldus-core/service/ProtocolGroup.h index f9689c02..97864fc4 100644 --- a/telldus-core/service/ProtocolGroup.h +++ b/telldus-core/service/ProtocolGroup.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLGROUP_H #define PROTOCOLGROUP_H diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index 8166c8a5..3f5b74ef 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolHasta.h" #include #include diff --git a/telldus-core/service/ProtocolHasta.h b/telldus-core/service/ProtocolHasta.h index d13555be..5844e30e 100644 --- a/telldus-core/service/ProtocolHasta.h +++ b/telldus-core/service/ProtocolHasta.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLHASTA_H #define PROTOCOLHASTA_H diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 3c65e63b..4bf43d50 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolIkea.h" #include "common/Strings.h" diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index 07cd294a..fcf8e034 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLIKEA_H #define PROTOCOLIKEA_H diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index a93864d1..f9b5059a 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolMandolyn.h" #include "common/Strings.h" #include diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h index 08ead0eb..d8434210 100644 --- a/telldus-core/service/ProtocolMandolyn.h +++ b/telldus-core/service/ProtocolMandolyn.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLMANDOLYN_H #define PROTOCOLMANDOLYN_H diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 9b43a7c7..2b2a19e9 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolNexa.h" #include #include diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index ac6b8906..d2432a7a 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLNEXA_H #define PROTOCOLNEXA_H @@ -18,7 +24,7 @@ protected: virtual std::string getOffCode() const; static std::string getCodeSwitchTuple(int code); static std::string getStringSelflearningForCode(int house, int unit, int method, unsigned char data); - + private: static int lastArctecCodeSwitchWasTurnOff; static std::string decodeDataCodeSwitch(long allData); diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 30f7ad86..30d0c1a6 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolOregon.h" #include "common/Strings.h" #include diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index 1210430c..eba2807a 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLOREGON_H #define PROTOCOLOREGON_H diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index b1cde0e7..5e87bc22 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolRisingSun.h" #include "common/Strings.h" diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h index f2775ac2..6d21c9f5 100644 --- a/telldus-core/service/ProtocolRisingSun.h +++ b/telldus-core/service/ProtocolRisingSun.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLRISINGSUN_H #define PROTOCOLRISINGSUN_H diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 4fb92ea9..40182d4b 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolSartano.h" #include #include diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index 0f555442..fffcdc00 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLSARTANO_H #define PROTOCOLSARTANO_H diff --git a/telldus-core/service/ProtocolScene.cpp b/telldus-core/service/ProtocolScene.cpp index f30f702b..68957d7e 100644 --- a/telldus-core/service/ProtocolScene.cpp +++ b/telldus-core/service/ProtocolScene.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolScene.h" int ProtocolScene::methods() const { diff --git a/telldus-core/service/ProtocolScene.h b/telldus-core/service/ProtocolScene.h index 2a4979c1..59c3bc9f 100644 --- a/telldus-core/service/ProtocolScene.h +++ b/telldus-core/service/ProtocolScene.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLSCENE_H #define PROTOCOLSCENE_H diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index b08cd294..35857d83 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolSilvanChip.h" #include "common/Strings.h" diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h index ba55cb25..9befbf4a 100644 --- a/telldus-core/service/ProtocolSilvanChip.h +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLSILVANCHIP_H #define PROTOCOLSILVANCHIP_H diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 58406e80..2c4eff55 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolUpm.h" int ProtocolUpm::methods() const { diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h index 74724f24..51c32b81 100644 --- a/telldus-core/service/ProtocolUpm.h +++ b/telldus-core/service/ProtocolUpm.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLUPM_H #define PROTOCOLUPM_H diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 7adfe3ef..4f507094 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolWaveman.h" #include #include diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h index 76453643..cc908abb 100644 --- a/telldus-core/service/ProtocolWaveman.h +++ b/telldus-core/service/ProtocolWaveman.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLWAVEMAN_H #define PROTOCOLWAVEMAN_H diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index c0dc108f..ee178613 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolX10.h" #include #include diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 0df0067d..4fc02d98 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLX10_H #define PROTOCOLX10_H diff --git a/telldus-core/service/ProtocolYidong.cpp b/telldus-core/service/ProtocolYidong.cpp index 94487028..6e362b45 100644 --- a/telldus-core/service/ProtocolYidong.cpp +++ b/telldus-core/service/ProtocolYidong.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/ProtocolYidong.h" std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { diff --git a/telldus-core/service/ProtocolYidong.h b/telldus-core/service/ProtocolYidong.h index df64e6a4..693dcc15 100644 --- a/telldus-core/service/ProtocolYidong.h +++ b/telldus-core/service/ProtocolYidong.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef PROTOCOLYIDONG_H #define PROTOCOLYIDONG_H diff --git a/telldus-core/service/Sensor.cpp b/telldus-core/service/Sensor.cpp index af9bbb07..17ae3ac2 100644 --- a/telldus-core/service/Sensor.cpp +++ b/telldus-core/service/Sensor.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/Sensor.h" #include "common/common.h" #include "client/telldus-core.h" diff --git a/telldus-core/service/Sensor.h b/telldus-core/service/Sensor.h index 61eb9cee..6edbb0d0 100644 --- a/telldus-core/service/Sensor.h +++ b/telldus-core/service/Sensor.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef SENSOR_H #define SENSOR_H diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 86170231..993f4533 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/Settings.h" TelldusCore::Mutex Settings::mutex; diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 7863c643..7b1b5788 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef SETTINGS_H #define SETTINGS_H diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index c421be31..01c5a66b 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -1,10 +1,5 @@ // -// C++ Implementation: telldussettingsconfuse -// -// Description: -// -// -// Author: Micke Prag , (C) 2008 +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. // // Copyright: See COPYING file that comes with this distribution // diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index d0ad01df..e3f88c0b 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -1,10 +1,5 @@ // -// C++ Implementation: TellStick -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. // // Copyright: See COPYING file that comes with this distribution // diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 246feb1f..765d8146 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -1,10 +1,5 @@ // -// C++ Interface: TellStick -// -// Description: -// -// -// Author: Micke Prag , (C) 2010 +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. // // Copyright: See COPYING file that comes with this distribution // diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 6e805bb6..f6f927c7 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -1,10 +1,5 @@ // -// C++ Implementation: TellStick -// -// Description: -// -// -// Author: Micke Prag , (C) 2009 +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. // // Copyright: See COPYING file that comes with this distribution // diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index a1f59fa7..0d11fe9f 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/TelldusMain.h" #include "service/ConnectionListener.h" #include "common/EventHandler.h" diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index 19f08a4a..18929bc2 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef TELLDUSMAIN_H #define TELLDUSMAIN_H diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index 070bcc29..838b0009 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/Timer.h" #include "common/Mutex.h" #ifdef _WINDOWS diff --git a/telldus-core/service/Timer.h b/telldus-core/service/Timer.h index cc08381c..e3b68ddb 100644 --- a/telldus-core/service/Timer.h +++ b/telldus-core/service/Timer.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef TIMER_H #define TIMER_H diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index ef287b62..c2485865 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "service/TelldusMain.h" #include #include From 0d25f0b389cdf645df683cab695552cd20f65fe6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 28 Feb 2012 22:07:56 +0100 Subject: [PATCH 2002/2215] Fix #ifndef header guard style, according to Google style guidelines "build/header_guard" --- telldus-core/client/CallbackDispatcher.h | 6 +++--- telldus-core/client/Client.h | 6 +++--- telldus-core/client/telldus-core.h | 6 +++--- telldus-core/common/Event.h | 6 +++--- telldus-core/common/EventHandler.h | 6 +++--- telldus-core/common/Message.h | 12 ++++++------ telldus-core/common/Mutex.h | 6 +++--- telldus-core/common/Socket.h | 8 ++++---- telldus-core/common/Strings.h | 6 +++--- telldus-core/common/Thread.h | 6 +++--- telldus-core/common/common.h | 6 +++--- telldus-core/service/ClientCommunicationHandler.h | 6 +++--- telldus-core/service/ConnectionListener.h | 6 +++--- telldus-core/service/Controller.h | 6 +++--- telldus-core/service/ControllerListener.h | 6 +++--- telldus-core/service/ControllerManager.h | 6 +++--- telldus-core/service/ControllerMessage.h | 6 +++--- telldus-core/service/Device.h | 6 +++--- telldus-core/service/DeviceManager.h | 6 +++--- telldus-core/service/EventUpdateManager.h | 6 +++--- telldus-core/service/Log.h | 6 +++--- telldus-core/service/Protocol.h | 6 +++--- telldus-core/service/ProtocolBrateck.h | 6 +++--- telldus-core/service/ProtocolComen.h | 6 +++--- telldus-core/service/ProtocolEverflourish.h | 6 +++--- telldus-core/service/ProtocolFineoffset.h | 6 +++--- telldus-core/service/ProtocolFuhaote.h | 6 +++--- telldus-core/service/ProtocolGroup.h | 6 +++--- telldus-core/service/ProtocolHasta.h | 6 +++--- telldus-core/service/ProtocolIkea.h | 6 +++--- telldus-core/service/ProtocolMandolyn.h | 6 +++--- telldus-core/service/ProtocolNexa.h | 6 +++--- telldus-core/service/ProtocolOregon.h | 6 +++--- telldus-core/service/ProtocolRisingSun.h | 6 +++--- telldus-core/service/ProtocolSartano.h | 6 +++--- telldus-core/service/ProtocolScene.h | 6 +++--- telldus-core/service/ProtocolSilvanChip.h | 6 +++--- telldus-core/service/ProtocolUpm.h | 6 +++--- telldus-core/service/ProtocolWaveman.h | 6 +++--- telldus-core/service/ProtocolX10.h | 6 +++--- telldus-core/service/ProtocolYidong.h | 6 +++--- telldus-core/service/Sensor.h | 6 +++--- telldus-core/service/Settings.h | 6 +++--- telldus-core/service/TellStick.h | 6 +++--- telldus-core/service/TelldusMain.h | 6 +++--- telldus-core/service/Timer.h | 6 +++--- 46 files changed, 142 insertions(+), 142 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 1d19d7e7..4d77d7e0 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -7,8 +7,8 @@ * */ -#ifndef CALLBACKDISPATCHER_H -#define CALLBACKDISPATCHER_H +#ifndef TELLDUS_CORE_CLIENT_CALLBACKDISPATCHER_H_ +#define TELLDUS_CORE_CLIENT_CALLBACKDISPATCHER_H_ #include "common/common.h" #include "common/Event.h" @@ -99,4 +99,4 @@ namespace TelldusCore { }; } -#endif //CALLBACKDISPATCHER_H +#endif // TELLDUS_CORE_CLIENT_CALLBACKDISPATCHER_H_ diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index 6cce43a5..c03c4d41 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef CLIENT_H -#define CLIENT_H +#ifndef TELLDUS_CORE_CLIENT_CLIENT_H_ +#define TELLDUS_CORE_CLIENT_CLIENT_H_ #include "client/telldus-core.h" #include "client/CallbackDispatcher.h" @@ -45,4 +45,4 @@ namespace TelldusCore { }; } -#endif //CLIENT_H +#endif // TELLDUS_CORE_CLIENT_CLIENT_H_ diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index fbc77338..107f9095 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef TELLDUSCORE_H -#define TELLDUSCORE_H +#ifndef TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ +#define TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ // The following ifdef block is the standard way of creating macros // which make exporting from a DLL simpler. All files within this DLL @@ -158,4 +158,4 @@ extern "C" { #define TELLSTICK_CHANGE_AVAILABLE 5 #define TELLSTICK_CHANGE_FIRMWARE 6 -#endif +#endif // TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index 881e0b69..42bc8f2f 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef EVENT_H -#define EVENT_H +#ifndef TELLDUS_CORE_COMMON_EVENT_H_ +#define TELLDUS_CORE_COMMON_EVENT_H_ #include "Thread.h" @@ -77,4 +77,4 @@ namespace TelldusCore { typedef std::tr1::shared_ptr EventRef; } -#endif //EVENT_H +#endif // TELLDUS_CORE_COMMON_EVENT_H_ diff --git a/telldus-core/common/EventHandler.h b/telldus-core/common/EventHandler.h index e7ad06c8..99be16c7 100644 --- a/telldus-core/common/EventHandler.h +++ b/telldus-core/common/EventHandler.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef EVENTHANDLER_H -#define EVENTHANDLER_H +#ifndef TELLDUS_CORE_COMMON_EVENTHANDLER_H_ +#define TELLDUS_CORE_COMMON_EVENTHANDLER_H_ #include "common/Event.h" @@ -32,4 +32,4 @@ namespace TelldusCore { }; } -#endif //EVENTHANDLER_H +#endif // TELLDUS_CORE_COMMON_EVENTHANDLER_H_ diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 65b40112..a03ff472 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef MESSAGE_H -#define MESSAGE_H +#ifndef TELLDUS_CORE_COMMON_MESSAGE_H_ +#define TELLDUS_CORE_COMMON_MESSAGE_H_ #include @@ -22,16 +22,16 @@ namespace TelldusCore { //void addSpecialArgument(const char *); void addArgument(int); void addArgument(const char *); - + static bool nextIsInt(const std::wstring &); static bool nextIsString(const std::wstring &); static std::wstring takeString(std::wstring *); static int takeInt(std::wstring *); - + private: - + }; } -#endif //MESSAGE_H +#endif // TELLDUS_CORE_COMMON_MESSAGE_H_ diff --git a/telldus-core/common/Mutex.h b/telldus-core/common/Mutex.h index 75a91b87..69a04847 100644 --- a/telldus-core/common/Mutex.h +++ b/telldus-core/common/Mutex.h @@ -9,8 +9,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef MUTEX_H -#define MUTEX_H +#ifndef TELLDUS_CORE_COMMON_MUTEX_H_ +#define TELLDUS_CORE_COMMON_MUTEX_H_ namespace TelldusCore { class Mutex { @@ -42,4 +42,4 @@ namespace TelldusCore { }; } -#endif //MUTEX_H +#endif // TELLDUS_CORE_COMMON_MUTEX_H_ diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 0646aa9e..656d99a6 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef SOCKET_H -#define SOCKET_H +#ifndef TELLDUS_CORE_COMMON_SOCKET_H_ +#define TELLDUS_CORE_COMMON_SOCKET_H_ #include @@ -30,10 +30,10 @@ namespace TelldusCore { std::wstring read(int timeout); void stopReadWait(); void write(const std::wstring &msg); - + private: class PrivateData; PrivateData *d; }; } -#endif //SOCKET_H +#endif // TELLDUS_CORE_COMMON_SOCKET_H_ diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index d7883bbd..c937fce9 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef STRING_H -#define STRING_H +#ifndef TELLDUS_CORE_COMMON_STRINGS_H_ +#define TELLDUS_CORE_COMMON_STRINGS_H_ #include #include @@ -36,4 +36,4 @@ namespace TelldusCore { std::string sformatf(const char *format, va_list ap); } -#endif //STRING_H +#endif // TELLDUS_CORE_COMMON_STRINGS_H_ diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index 877468bf..154d7095 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -9,8 +9,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef THREAD_H -#define THREAD_H +#ifndef TELLDUS_CORE_COMMON_THREAD_H_ +#define TELLDUS_CORE_COMMON_THREAD_H_ #include #include "common/Mutex.h" @@ -34,4 +34,4 @@ namespace TelldusCore { }; } -#endif +#endif // TELLDUS_CORE_COMMON_THREAD_H_ diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 29c391d5..f79caf96 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -5,8 +5,8 @@ // // -#ifndef COMMON_H -#define COMMON_H +#ifndef TELLDUS_CORE_COMMON_COMMON_H_ +#define TELLDUS_CORE_COMMON_COMMON_H_ #ifdef _WINDOWS #include @@ -80,4 +80,4 @@ inline char *wrapStdWstring( const std::wstring &wstring) { return wrapStdString(TelldusCore::wideToString(wstring)); } -#endif //COMMON_H +#endif // TELLDUS_CORE_COMMON_COMMON_H_ diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 7e560b4b..3a89908c 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef CLIENTCOMMUNICATIONHANDLER_H -#define CLIENTCOMMUNICATIONHANDLER_H +#ifndef TELLDUS_CORE_SERVICE_CLIENTCOMMUNICATIONHANDLER_H_ +#define TELLDUS_CORE_SERVICE_CLIENTCOMMUNICATIONHANDLER_H_ #include #include "common/Thread.h" @@ -39,4 +39,4 @@ private: void sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType); }; -#endif //CLIENTCOMMUNICATIONHANDLER_H +#endif // TELLDUS_CORE_SERVICE_CLIENTCOMMUNICATIONHANDLER_H_ diff --git a/telldus-core/service/ConnectionListener.h b/telldus-core/service/ConnectionListener.h index b41d39fa..08e838e3 100644 --- a/telldus-core/service/ConnectionListener.h +++ b/telldus-core/service/ConnectionListener.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef CONNECTIONLISTENER_H -#define CONNECTIONLISTENER_H +#ifndef TELLDUS_CORE_SERVICE_CONNECTIONLISTENER_H_ +#define TELLDUS_CORE_SERVICE_CONNECTIONLISTENER_H_ #include #include "common/Thread.h" @@ -34,4 +34,4 @@ private: PrivateData *d; }; -#endif //CONNECTIONLISTENER_H +#endif // TELLDUS_CORE_SERVICE_CONNECTIONLISTENER_H_ diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 2ec22143..3dcdd709 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef CONTROLLER_H -#define CONTROLLER_H +#ifndef TELLDUS_CORE_SERVICE_CONTROLLER_H_ +#define TELLDUS_CORE_SERVICE_CONTROLLER_H_ #include "common/Event.h" #include @@ -35,4 +35,4 @@ private: PrivateData *d; }; -#endif //CONTROLLER_H +#endif // TELLDUS_CORE_SERVICE_CONTROLLER_H_ diff --git a/telldus-core/service/ControllerListener.h b/telldus-core/service/ControllerListener.h index 3f28ec99..3a24b61a 100644 --- a/telldus-core/service/ControllerListener.h +++ b/telldus-core/service/ControllerListener.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef CONTROLLERLISTENER_H -#define CONTROLLERLISTENER_H +#ifndef TELLDUS_CORE_SERVICE_CONTROLLERLISTENER_H_ +#define TELLDUS_CORE_SERVICE_CONTROLLERLISTENER_H_ #include "common/Thread.h" #include "common/Event.h" @@ -29,4 +29,4 @@ private: PrivateData *d; }; -#endif //CONTROLLERLISTENER_H +#endif // TELLDUS_CORE_SERVICE_CONTROLLERLISTENER_H_ diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index cecf57d5..f1000c5f 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef CONTROLLERMANAGER_H -#define CONTROLLERMANAGER_H +#ifndef TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_ +#define TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_ #include "common/Event.h" class Controller; @@ -36,4 +36,4 @@ private: PrivateData *d; }; -#endif //CONTROLLERMANAGER_H +#endif // TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_ diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index 767903bc..897eb529 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef CONTROLLERMESSAGE_H -#define CONTROLLERMESSAGE_H +#ifndef TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_ +#define TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_ #include @@ -28,4 +28,4 @@ private: PrivateData *d; }; -#endif //CONTROLLERMESSAGE_H +#endif // TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_ diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 1d0f630f..0c024267 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef DEVICE_H -#define DEVICE_H +#ifndef TELLDUS_CORE_SERVICE_DEVICE_H_ +#define TELLDUS_CORE_SERVICE_DEVICE_H_ #include "service/Controller.h" #include "common/Mutex.h" @@ -48,4 +48,4 @@ private: PrivateData *d; }; -#endif //DEVICE_H +#endif // TELLDUS_CORE_SERVICE_DEVICE_H_ diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index c5c12ce9..cd704f0e 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef DEVICEMANAGER_H -#define DEVICEMANAGER_H +#ifndef TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_ +#define TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_ #include "service/Device.h" #include "service/ControllerManager.h" @@ -62,4 +62,4 @@ private: PrivateData *d; }; -#endif //DEVICEMANAGER_H +#endif // TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_ diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 5ae1dc98..7499da69 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef EVENTUPDATEMANAGER_H -#define EVENTUPDATEMANAGER_H +#ifndef TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_ +#define TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_ #include "common/Thread.h" #include "common/Event.h" @@ -47,4 +47,4 @@ private: void sendMessageToClients(EventUpdateData *data); }; -#endif //EVENTUPDATEMANAGER_H +#endif // TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_ diff --git a/telldus-core/service/Log.h b/telldus-core/service/Log.h index 0b462b82..fc2491e8 100644 --- a/telldus-core/service/Log.h +++ b/telldus-core/service/Log.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef LOG_H -#define LOG_H +#ifndef TELLDUS_CORE_SERVICE_LOG_H_ +#define TELLDUS_CORE_SERVICE_LOG_H_ #include #include @@ -37,4 +37,4 @@ private: }; -#endif //LOG_H +#endif // TELLDUS_CORE_SERVICE_LOG_H_ diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 4dd8e8a4..5c887102 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOL_H -#define PROTOCOL_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOL_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOL_H_ #include #include @@ -44,4 +44,4 @@ private: PrivateData *d; }; -#endif //PROTOCOL_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOL_H_ diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index fb385e29..33a77df9 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLBRATECK_H -#define PROTOCOLBRATECK_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ #include "service/Protocol.h" @@ -16,4 +16,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLBRATECK_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ diff --git a/telldus-core/service/ProtocolComen.h b/telldus-core/service/ProtocolComen.h index 4a54572c..d6a9e8b9 100644 --- a/telldus-core/service/ProtocolComen.h +++ b/telldus-core/service/ProtocolComen.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLCOMEN_H -#define PROTOCOLCOMEN_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ #include "service/ProtocolNexa.h" #include @@ -16,4 +16,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLCOMEN_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index f4c54029..26a54bbf 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLEVERFLOURISH_H -#define PROTOCOLEVERFLOURISH_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ #include "service/Protocol.h" #include "service/ControllerMessage.h" @@ -21,4 +21,4 @@ private: static unsigned int calculateChecksum(unsigned int x); }; -#endif //PROTOCOLEVERFLOURISH_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h index 501e6426..fcf0cdcd 100644 --- a/telldus-core/service/ProtocolFineoffset.h +++ b/telldus-core/service/ProtocolFineoffset.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLFINEOFFSET_H -#define PROTOCOLFINEOFFSET_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ #include "service/Protocol.h" #include "service/ControllerMessage.h" @@ -16,4 +16,4 @@ public: static std::string decodeData(ControllerMessage &dataMsg); }; -#endif //PROTOCOLFINEOFFSET_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index f6f9020c..7d92fd9d 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLFUHAOTE_H -#define PROTOCOLFUHAOTE_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ #include "service/Protocol.h" @@ -16,4 +16,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLFUHAOTE_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ diff --git a/telldus-core/service/ProtocolGroup.h b/telldus-core/service/ProtocolGroup.h index 97864fc4..0301ac91 100644 --- a/telldus-core/service/ProtocolGroup.h +++ b/telldus-core/service/ProtocolGroup.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLGROUP_H -#define PROTOCOLGROUP_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ #include "service/Protocol.h" @@ -16,7 +16,7 @@ public: }; -#endif //PROTOCOLGROUP_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ diff --git a/telldus-core/service/ProtocolHasta.h b/telldus-core/service/ProtocolHasta.h index 5844e30e..de05003a 100644 --- a/telldus-core/service/ProtocolHasta.h +++ b/telldus-core/service/ProtocolHasta.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLHASTA_H -#define PROTOCOLHASTA_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ #include "service/Protocol.h" @@ -19,4 +19,4 @@ protected: static std::string convertByte(unsigned char byte); }; -#endif //PROTOCOLHASTA_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index fcf8e034..0f1c6097 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLIKEA_H -#define PROTOCOLIKEA_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ #include "service/Protocol.h" @@ -16,4 +16,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLIKEA_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h index d8434210..aa99d5e0 100644 --- a/telldus-core/service/ProtocolMandolyn.h +++ b/telldus-core/service/ProtocolMandolyn.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLMANDOLYN_H -#define PROTOCOLMANDOLYN_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ #include "service/Protocol.h" #include "service/ControllerMessage.h" @@ -16,4 +16,4 @@ public: static std::string decodeData(ControllerMessage &dataMsg); }; -#endif //PROTOCOLMANDOLYN_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index d2432a7a..a4bc8b83 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLNEXA_H -#define PROTOCOLNEXA_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ #include "service/ControllerMessage.h" #include "service/Device.h" @@ -31,4 +31,4 @@ private: static std::string decodeDataSelfLearning(long allData); }; -#endif //PROTOCOLNEXA_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index eba2807a..97448afa 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLOREGON_H -#define PROTOCOLOREGON_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ #include "service/Protocol.h" #include "service/ControllerMessage.h" @@ -20,4 +20,4 @@ protected: static std::string decode1A2D(const std::string &data); }; -#endif //PROTOCOLOREGON_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h index 6d21c9f5..c67462c7 100644 --- a/telldus-core/service/ProtocolRisingSun.h +++ b/telldus-core/service/ProtocolRisingSun.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLRISINGSUN_H -#define PROTOCOLRISINGSUN_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ #include "service/Protocol.h" @@ -21,4 +21,4 @@ protected: static std::string getCodeSwitchTuple(int code); }; -#endif //PROTOCOLRISINGSUN_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index fffcdc00..427cf083 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLSARTANO_H -#define PROTOCOLSARTANO_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ #include "service/Protocol.h" #include "service/ControllerMessage.h" @@ -21,4 +21,4 @@ protected: std::string getStringForCode(const std::wstring &code, int method); }; -#endif //PROTOCOLSARTANO_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ diff --git a/telldus-core/service/ProtocolScene.h b/telldus-core/service/ProtocolScene.h index 59c3bc9f..e5b17983 100644 --- a/telldus-core/service/ProtocolScene.h +++ b/telldus-core/service/ProtocolScene.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLSCENE_H -#define PROTOCOLSCENE_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ #include "service/Protocol.h" @@ -16,7 +16,7 @@ public: }; -#endif //PROTOCOLSCENE_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h index 9befbf4a..974c83ce 100644 --- a/telldus-core/service/ProtocolSilvanChip.h +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLSILVANCHIP_H -#define PROTOCOLSILVANCHIP_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ #include "service/Protocol.h" @@ -19,4 +19,4 @@ protected: virtual std::string getString(const std::string &preamble, const std::string &one, const std::string &zero, int button); }; -#endif //PROTOCOLSILVANCHIP_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h index 51c32b81..f40869af 100644 --- a/telldus-core/service/ProtocolUpm.h +++ b/telldus-core/service/ProtocolUpm.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLUPM_H -#define PROTOCOLUPM_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ #include "service/Protocol.h" @@ -16,4 +16,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLUPM_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h index cc908abb..3ddaf0d1 100644 --- a/telldus-core/service/ProtocolWaveman.h +++ b/telldus-core/service/ProtocolWaveman.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLWAVEMAN_H -#define PROTOCOLWAVEMAN_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ #include "service/ProtocolNexa.h" @@ -22,4 +22,4 @@ private: static int lastArctecCodeSwitchWasTurnOff; }; -#endif //PROTOCOLWAVEMAN_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 4fc02d98..71c8c64e 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLX10_H -#define PROTOCOLX10_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ #include "service/Protocol.h" #include "service/ControllerMessage.h" @@ -19,4 +19,4 @@ public: static std::string decodeData(ControllerMessage& dataMsg); }; -#endif //PROTOCOLX10_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ diff --git a/telldus-core/service/ProtocolYidong.h b/telldus-core/service/ProtocolYidong.h index 693dcc15..bf096982 100644 --- a/telldus-core/service/ProtocolYidong.h +++ b/telldus-core/service/ProtocolYidong.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef PROTOCOLYIDONG_H -#define PROTOCOLYIDONG_H +#ifndef TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ +#define TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ #include "service/ProtocolSartano.h" @@ -15,4 +15,4 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; -#endif //PROTOCOLYIDONG_H +#endif // TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ diff --git a/telldus-core/service/Sensor.h b/telldus-core/service/Sensor.h index 6edbb0d0..f7eba022 100644 --- a/telldus-core/service/Sensor.h +++ b/telldus-core/service/Sensor.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef SENSOR_H -#define SENSOR_H +#ifndef TELLDUS_CORE_SERVICE_SENSOR_H_ +#define TELLDUS_CORE_SERVICE_SENSOR_H_ #include "common/Mutex.h" #include @@ -31,4 +31,4 @@ private: PrivateData *d; }; -#endif // SENSOR_H +#endif // TELLDUS_CORE_SERVICE_SENSOR_H_ diff --git a/telldus-core/service/Settings.h b/telldus-core/service/Settings.h index 7b1b5788..4b26d843 100644 --- a/telldus-core/service/Settings.h +++ b/telldus-core/service/Settings.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef SETTINGS_H -#define SETTINGS_H +#ifndef TELLDUS_CORE_SERVICE_SETTINGS_H_ +#define TELLDUS_CORE_SERVICE_SETTINGS_H_ #include #include "common/Mutex.h" @@ -57,4 +57,4 @@ private: static TelldusCore::Mutex mutex; }; -#endif +#endif // TELLDUS_CORE_SERVICE_SETTINGS_H_ diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index 765d8146..b596d4f4 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef TELLSTICK_H -#define TELLSTICK_H +#ifndef TELLDUS_CORE_SERVICE_TELLSTICK_H_ +#define TELLDUS_CORE_SERVICE_TELLSTICK_H_ #include #include "service/Controller.h" @@ -50,4 +50,4 @@ private: PrivateData *d; }; -#endif +#endif // TELLDUS_CORE_SERVICE_TELLSTICK_H_ diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index 18929bc2..fde55c33 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef TELLDUSMAIN_H -#define TELLDUSMAIN_H +#ifndef TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_ +#define TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_ class TelldusMain { @@ -26,4 +26,4 @@ private: PrivateData *d; }; -#endif //TELLDUSMAIN_H +#endif // TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_ diff --git a/telldus-core/service/Timer.h b/telldus-core/service/Timer.h index e3b68ddb..8b470e15 100644 --- a/telldus-core/service/Timer.h +++ b/telldus-core/service/Timer.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef TIMER_H -#define TIMER_H +#ifndef TELLDUS_CORE_SERVICE_TIMER_H_ +#define TELLDUS_CORE_SERVICE_TIMER_H_ #include "common/Event.h" #include "common/Thread.h" @@ -27,4 +27,4 @@ private: }; -#endif //TIMER_H +#endif // TELLDUS_CORE_SERVICE_TIMER_H_ From a4dfd27d3507a3c67aff7abc9aef3a65e14e9d88 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 28 Feb 2012 22:08:55 +0100 Subject: [PATCH 2003/2215] Single-argument constructors should be marked explicit. According to Google style guideline "runtime/explicit" --- telldus-core/common/Event.h | 4 ++-- telldus-core/common/Message.h | 2 +- telldus-core/common/Mutex.h | 2 +- telldus-core/common/Socket.h | 2 +- telldus-core/service/ControllerListener.h | 2 +- telldus-core/service/ControllerMessage.h | 2 +- telldus-core/service/Device.h | 2 +- telldus-core/service/Timer.h | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index 42bc8f2f..56274a1d 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -46,7 +46,7 @@ namespace TelldusCore { EventDataRef takeSignal(); protected: - EventBase(EventHandler *handler); + explicit EventBase(EventHandler *handler); void clearHandler(); virtual void clearSignal() = 0; EventHandler *handler() const; @@ -62,7 +62,7 @@ namespace TelldusCore { virtual ~Event(); protected: - Event(EventHandler *handler); + explicit Event(EventHandler *handler); EVENT_T retrieveNative(); virtual void clearSignal(); virtual void sendSignal(); diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index a03ff472..74ca5538 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -13,7 +13,7 @@ namespace TelldusCore { class Message : public std::wstring { public: Message(); - Message(const std::wstring &); + explicit Message(const std::wstring &); ~Message(void); void addArgument(const std::wstring &); diff --git a/telldus-core/common/Mutex.h b/telldus-core/common/Mutex.h index 69a04847..41086576 100644 --- a/telldus-core/common/Mutex.h +++ b/telldus-core/common/Mutex.h @@ -35,7 +35,7 @@ namespace TelldusCore { class MutexLocker { public: - MutexLocker(Mutex *m); + explicit MutexLocker(Mutex *m); ~MutexLocker(); private: Mutex *mutex; diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 656d99a6..712d7f97 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -21,7 +21,7 @@ namespace TelldusCore { { public: Socket(); - Socket(SOCKET_T hPipe); + explicit Socket(SOCKET_T hPipe); virtual ~Socket(void); void connect(const std::wstring &server); diff --git a/telldus-core/service/ControllerListener.h b/telldus-core/service/ControllerListener.h index 3a24b61a..3730f0fc 100644 --- a/telldus-core/service/ControllerListener.h +++ b/telldus-core/service/ControllerListener.h @@ -18,7 +18,7 @@ public: class ControllerListener : public TelldusCore::Thread { public: - ControllerListener(TelldusCore::EventRef event); + explicit ControllerListener(TelldusCore::EventRef event); virtual ~ControllerListener(); protected: diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index 897eb529..f31aeffd 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -11,7 +11,7 @@ class ControllerMessage { public: - ControllerMessage(const std::string &rawMessage); + explicit ControllerMessage(const std::string &rawMessage); virtual ~ControllerMessage(); std::string msgClass() const; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 0c024267..fef206c4 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -16,7 +16,7 @@ class Device : public TelldusCore::Mutex { public: - Device(int id); + explicit Device(int id); ~Device(void); int doAction(int action, unsigned char data, Controller *controller); diff --git a/telldus-core/service/Timer.h b/telldus-core/service/Timer.h index 8b470e15..f5f51942 100644 --- a/telldus-core/service/Timer.h +++ b/telldus-core/service/Timer.h @@ -12,7 +12,7 @@ class Timer : public TelldusCore::Thread { public: - Timer(TelldusCore::EventRef event); + explicit Timer(TelldusCore::EventRef event); virtual ~Timer(); void setInterval(int sec); From 78444e20b993737a369965afbda322cd4754c195 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 10:58:31 +0200 Subject: [PATCH 2004/2215] Add #include for string, according to Google style guidelines "build/include_what_you_use" --- telldus-core/client/CallbackDispatcher.h | 1 + telldus-core/client/telldus-core.cpp | 9 +++++---- telldus-core/client/telldus-core.h | 2 +- telldus-core/common/Socket_unix.cpp | 1 + telldus-core/service/ClientCommunicationHandler.cpp | 1 + telldus-core/service/Controller.cpp | 2 ++ telldus-core/service/Device.cpp | 2 ++ telldus-core/service/DeviceManager.h | 1 + telldus-core/service/ProtocolBrateck.cpp | 1 + telldus-core/service/ProtocolBrateck.h | 1 + telldus-core/service/ProtocolComen.cpp | 1 + telldus-core/service/ProtocolEverflourish.cpp | 1 + telldus-core/service/ProtocolEverflourish.h | 1 + telldus-core/service/ProtocolFineoffset.h | 1 + telldus-core/service/ProtocolFuhaote.cpp | 1 + telldus-core/service/ProtocolFuhaote.h | 1 + telldus-core/service/ProtocolGroup.cpp | 1 + telldus-core/service/ProtocolGroup.h | 1 + telldus-core/service/ProtocolHasta.h | 1 + telldus-core/service/ProtocolIkea.h | 1 + telldus-core/service/ProtocolMandolyn.h | 1 + telldus-core/service/ProtocolOregon.h | 1 + telldus-core/service/ProtocolRisingSun.cpp | 1 + telldus-core/service/ProtocolRisingSun.h | 1 + telldus-core/service/ProtocolSartano.h | 1 + telldus-core/service/ProtocolScene.cpp | 1 + telldus-core/service/ProtocolScene.h | 1 + telldus-core/service/ProtocolSilvanChip.cpp | 1 + telldus-core/service/ProtocolSilvanChip.h | 1 + telldus-core/service/ProtocolUpm.cpp | 1 + telldus-core/service/ProtocolUpm.h | 1 + telldus-core/service/ProtocolWaveman.h | 1 + telldus-core/service/ProtocolX10.cpp | 1 + telldus-core/service/ProtocolX10.h | 1 + telldus-core/service/ProtocolYidong.cpp | 1 + telldus-core/service/ProtocolYidong.h | 1 + telldus-core/service/Settings.cpp | 1 + telldus-core/service/TellStick.h | 1 + telldus-core/service/TellStick_libftdi.cpp | 4 +++- telldus-core/service/main_unix.cpp | 1 + 40 files changed, 48 insertions(+), 6 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index 4d77d7e0..ee2b11f0 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -10,6 +10,7 @@ #ifndef TELLDUS_CORE_CLIENT_CALLBACKDISPATCHER_H_ #define TELLDUS_CORE_CLIENT_CALLBACKDISPATCHER_H_ +#include #include "common/common.h" #include "common/Event.h" #include "common/Thread.h" diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 7a084e9a..cf15eb6d 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -11,6 +11,7 @@ */ #include +#include #include "client/telldus-core.h" #include "client/Client.h" #include "common/common.h" @@ -454,16 +455,16 @@ void WINAPI tdClose(void) { * This method releases resources allocated by telldus-core. It should be * called on the returned value from all functions returning char *. * - * @param string + * @param thestring * A string returned from a td* function. * * @since Version 2.0.1 **/ -void WINAPI tdReleaseString(char *string) { +void WINAPI tdReleaseString(char *thestring) { #ifdef _WINDOWS - SysFreeString((BSTR)string); + SysFreeString((BSTR)thestring); #else - free(string); + free(thestring); #endif } diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 107f9095..7aa9ba2b 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -52,7 +52,7 @@ extern "C" { TELLSTICK_API int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context); TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); TELLSTICK_API void WINAPI tdClose(void); - TELLSTICK_API void WINAPI tdReleaseString(char *string); + TELLSTICK_API void WINAPI tdReleaseString(char *thestring); TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index d6e5bc07..fa759e88 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "common/Socket.h" #include "common/Mutex.h" diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 31b5e527..175fb91f 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -9,6 +9,7 @@ #include "common/Strings.h" #include +#include class ClientCommunicationHandler::PrivateData { public: diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index b0fc19d2..f24b786e 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -5,6 +5,8 @@ // // #include "service/Controller.h" +#include +#include #include "service/Protocol.h" #include "service/EventUpdateManager.h" #include "common/Strings.h" diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 7a68821c..e0605a44 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -5,6 +5,8 @@ // // #include "service/Device.h" +#include +#include #include "service/Settings.h" #include "service/TellStick.h" diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index cd704f0e..ef6d0b5c 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_ #define TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_ +#include #include "service/Device.h" #include "service/ControllerManager.h" #include "service/ControllerMessage.h" diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 290a0e49..836e1a35 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolBrateck.h" +#include int ProtocolBrateck::methods() const { return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index 33a77df9..702f9ad3 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_ +#include #include "service/Protocol.h" class ProtocolBrateck : public Protocol diff --git a/telldus-core/service/ProtocolComen.cpp b/telldus-core/service/ProtocolComen.cpp index a12f85c6..f160a1cc 100644 --- a/telldus-core/service/ProtocolComen.cpp +++ b/telldus-core/service/ProtocolComen.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolComen.h" +#include int ProtocolComen::methods() const { return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 0d59c8d0..69f7e93c 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -8,6 +8,7 @@ #include #include #include "service/ControllerMessage.h" +#include int ProtocolEverflourish::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 26a54bbf..325a7c89 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_ +#include #include "service/Protocol.h" #include "service/ControllerMessage.h" diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h index fcf0cdcd..c0546e73 100644 --- a/telldus-core/service/ProtocolFineoffset.h +++ b/telldus-core/service/ProtocolFineoffset.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ +#include #include "service/Protocol.h" #include "service/ControllerMessage.h" diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index dcc9cede..bbbd573c 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolFuhaote.h" +#include int ProtocolFuhaote::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index 7d92fd9d..b3b8d004 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_ +#include #include "service/Protocol.h" class ProtocolFuhaote : public Protocol diff --git a/telldus-core/service/ProtocolGroup.cpp b/telldus-core/service/ProtocolGroup.cpp index 41748e45..4c4d0d15 100644 --- a/telldus-core/service/ProtocolGroup.cpp +++ b/telldus-core/service/ProtocolGroup.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolGroup.h" +#include int ProtocolGroup::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; diff --git a/telldus-core/service/ProtocolGroup.h b/telldus-core/service/ProtocolGroup.h index 0301ac91..aa82edc7 100644 --- a/telldus-core/service/ProtocolGroup.h +++ b/telldus-core/service/ProtocolGroup.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ +#include #include "service/Protocol.h" class ProtocolGroup : public Protocol { diff --git a/telldus-core/service/ProtocolHasta.h b/telldus-core/service/ProtocolHasta.h index de05003a..5e7c3e3c 100644 --- a/telldus-core/service/ProtocolHasta.h +++ b/telldus-core/service/ProtocolHasta.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ +#include #include "service/Protocol.h" class ProtocolHasta : public Protocol diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index 0f1c6097..c9aceeb9 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_ +#include #include "service/Protocol.h" class ProtocolIkea : public Protocol diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h index aa99d5e0..421f7daa 100644 --- a/telldus-core/service/ProtocolMandolyn.h +++ b/telldus-core/service/ProtocolMandolyn.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ +#include #include "service/Protocol.h" #include "service/ControllerMessage.h" diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index 97448afa..2dd8a8e9 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ +#include #include "service/Protocol.h" #include "service/ControllerMessage.h" diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index 5e87bc22..a48d59b3 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolRisingSun.h" +#include #include "common/Strings.h" int ProtocolRisingSun::methods() const { diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h index c67462c7..e68941a4 100644 --- a/telldus-core/service/ProtocolRisingSun.h +++ b/telldus-core/service/ProtocolRisingSun.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_ +#include #include "service/Protocol.h" class ProtocolRisingSun : public Protocol diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index 427cf083..f28b4376 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_ +#include #include "service/Protocol.h" #include "service/ControllerMessage.h" diff --git a/telldus-core/service/ProtocolScene.cpp b/telldus-core/service/ProtocolScene.cpp index 68957d7e..24ae5318 100644 --- a/telldus-core/service/ProtocolScene.cpp +++ b/telldus-core/service/ProtocolScene.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolScene.h" +#include int ProtocolScene::methods() const { return TELLSTICK_EXECUTE; diff --git a/telldus-core/service/ProtocolScene.h b/telldus-core/service/ProtocolScene.h index e5b17983..87ca70f7 100644 --- a/telldus-core/service/ProtocolScene.h +++ b/telldus-core/service/ProtocolScene.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ +#include #include "service/Protocol.h" class ProtocolScene : public Protocol { diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 35857d83..7c57f539 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolSilvanChip.h" +#include #include "common/Strings.h" int ProtocolSilvanChip::methods() const { diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h index 974c83ce..eaa1f7d7 100644 --- a/telldus-core/service/ProtocolSilvanChip.h +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_ +#include #include "service/Protocol.h" class ProtocolSilvanChip : public Protocol diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 2c4eff55..41dee66f 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolUpm.h" +#include int ProtocolUpm::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h index f40869af..3a55134d 100644 --- a/telldus-core/service/ProtocolUpm.h +++ b/telldus-core/service/ProtocolUpm.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_ +#include #include "service/Protocol.h" class ProtocolUpm : public Protocol diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h index 3ddaf0d1..200066fd 100644 --- a/telldus-core/service/ProtocolWaveman.h +++ b/telldus-core/service/ProtocolWaveman.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_ +#include #include "service/ProtocolNexa.h" class ProtocolWaveman : public ProtocolNexa { diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index ee178613..ca445e35 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -7,6 +7,7 @@ #include "service/ProtocolX10.h" #include #include +#include const unsigned char HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 71c8c64e..4c88b100 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ +#include #include "service/Protocol.h" #include "service/ControllerMessage.h" diff --git a/telldus-core/service/ProtocolYidong.cpp b/telldus-core/service/ProtocolYidong.cpp index 6e362b45..61b9f33f 100644 --- a/telldus-core/service/ProtocolYidong.cpp +++ b/telldus-core/service/ProtocolYidong.cpp @@ -4,6 +4,7 @@ // Copyright: See COPYING file that comes with this distribution // // +#include #include "service/ProtocolYidong.h" std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) { diff --git a/telldus-core/service/ProtocolYidong.h b/telldus-core/service/ProtocolYidong.h index bf096982..7bbe6b68 100644 --- a/telldus-core/service/ProtocolYidong.h +++ b/telldus-core/service/ProtocolYidong.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_ +#include #include "service/ProtocolSartano.h" class ProtocolYidong : public ProtocolSartano diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 993f4533..1daef643 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -5,6 +5,7 @@ // // #include "service/Settings.h" +#include TelldusCore::Mutex Settings::mutex; diff --git a/telldus-core/service/TellStick.h b/telldus-core/service/TellStick.h index b596d4f4..61d844bb 100644 --- a/telldus-core/service/TellStick.h +++ b/telldus-core/service/TellStick.h @@ -8,6 +8,7 @@ #define TELLDUS_CORE_SERVICE_TELLSTICK_H_ #include +#include #include "service/Controller.h" #include "common/Thread.h" diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index f6f927c7..e456b74b 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -9,8 +9,10 @@ #include #include #include - +#include #include +#include +#include #include "service/Log.h" #include "service/Settings.h" #include "common/Thread.h" diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index c2485865..544c0e91 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "service/Settings.h" #include "common/Strings.h" From e1608f94a822156d56d64ec8e829bf11d56b1443 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 28 Feb 2012 22:19:02 +0100 Subject: [PATCH 2005/2215] { should almost always be at the end of the previous line, according to Google style guidelines "whitespace/braces" --- telldus-core/client/CallbackDispatcher.cpp | 3 +- .../client/CallbackMainDispatcher.cpp | 14 +- telldus-core/client/Client.cpp | 40 ++-- telldus-core/client/Client.h | 3 +- telldus-core/client/telldus-core.cpp | 42 ++-- telldus-core/common/EventHandler_unix.cpp | 4 +- telldus-core/common/Event_unix.cpp | 2 +- telldus-core/common/Message.cpp | 6 +- telldus-core/common/Mutex.cpp | 3 +- telldus-core/common/Socket.h | 3 +- telldus-core/common/Socket_unix.cpp | 13 +- telldus-core/common/Strings.cpp | 6 +- telldus-core/common/common.h | 2 +- .../service/ClientCommunicationHandler.cpp | 38 ++-- .../service/ClientCommunicationHandler.h | 3 +- .../service/ConnectionListener_unix.cpp | 5 +- telldus-core/service/Controller.cpp | 6 +- telldus-core/service/ControllerManager.cpp | 19 +- telldus-core/service/ControllerMessage.cpp | 2 +- telldus-core/service/Device.cpp | 42 ++-- telldus-core/service/Device.h | 3 +- telldus-core/service/DeviceManager.cpp | 185 ++++++++---------- telldus-core/service/DeviceManager.h | 3 +- telldus-core/service/EventUpdateManager.cpp | 42 ++-- telldus-core/service/EventUpdateManager.h | 3 +- telldus-core/service/Log.cpp | 3 +- telldus-core/service/Protocol.cpp | 14 +- telldus-core/service/Protocol.h | 3 +- telldus-core/service/ProtocolBrateck.h | 3 +- telldus-core/service/ProtocolEverflourish.cpp | 13 +- telldus-core/service/ProtocolEverflourish.h | 3 +- telldus-core/service/ProtocolFineoffset.cpp | 3 +- telldus-core/service/ProtocolFineoffset.h | 3 +- telldus-core/service/ProtocolFuhaote.h | 3 +- telldus-core/service/ProtocolHasta.h | 3 +- telldus-core/service/ProtocolIkea.h | 3 +- telldus-core/service/ProtocolMandolyn.cpp | 3 +- telldus-core/service/ProtocolMandolyn.h | 3 +- telldus-core/service/ProtocolNexa.cpp | 38 ++-- telldus-core/service/ProtocolOregon.cpp | 3 +- telldus-core/service/ProtocolOregon.h | 3 +- telldus-core/service/ProtocolRisingSun.h | 3 +- telldus-core/service/ProtocolSartano.cpp | 31 ++- telldus-core/service/ProtocolSartano.h | 3 +- telldus-core/service/ProtocolSilvanChip.h | 3 +- telldus-core/service/ProtocolUpm.h | 3 +- telldus-core/service/ProtocolWaveman.cpp | 17 +- telldus-core/service/ProtocolX10.cpp | 2 +- telldus-core/service/ProtocolX10.h | 3 +- telldus-core/service/ProtocolYidong.h | 3 +- telldus-core/service/Sensor.cpp | 3 +- telldus-core/service/Sensor.h | 3 +- telldus-core/service/Settings.cpp | 10 +- telldus-core/service/SettingsConfuse.cpp | 12 +- telldus-core/service/TellStick_libftdi.cpp | 19 +- telldus-core/service/TelldusMain.cpp | 9 +- telldus-core/service/TelldusMain.h | 3 +- telldus-core/service/Timer.cpp | 3 +- 58 files changed, 323 insertions(+), 403 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 8f4f0309..9b427421 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -12,8 +12,7 @@ using namespace TelldusCore; TDEventDispatcher::TDEventDispatcher(EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) - :Thread(), doneRunning(false), callbackData(cbd), callback(cb), callbackExecuted(cbDone) -{ + :Thread(), doneRunning(false), callbackData(cbd), callback(cb), callbackExecuted(cbDone) { this->startAndLock(&callback->mutex); } diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index a4bb67fe..9a349b05 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -29,8 +29,7 @@ public: }; CallbackMainDispatcher::CallbackMainDispatcher() -:Thread() -{ +:Thread() { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); d->generalCallbackEvent = d->eventHandler.addEvent(); @@ -39,7 +38,7 @@ CallbackMainDispatcher::CallbackMainDispatcher() d->lastCallbackId = 0; } -CallbackMainDispatcher::~CallbackMainDispatcher(void){ +CallbackMainDispatcher::~CallbackMainDispatcher(void) { d->stopEvent->signal(); wait(); { @@ -48,7 +47,7 @@ CallbackMainDispatcher::~CallbackMainDispatcher(void){ delete d; } -EventRef CallbackMainDispatcher::retrieveCallbackEvent(){ +EventRef CallbackMainDispatcher::retrieveCallbackEvent() { return d->generalCallbackEvent; } @@ -88,14 +87,13 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { return TELLSTICK_ERROR_NOT_FOUND; } -void CallbackMainDispatcher::run(){ - - while(!d->stopEvent->isSignaled()){ +void CallbackMainDispatcher::run() { + while(!d->stopEvent->isSignaled()) { if (!d->eventHandler.waitForAny()) { continue; } - if(d->generalCallbackEvent->isSignaled()){ + if(d->generalCallbackEvent->isSignaled()) { EventDataRef eventData = d->generalCallbackEvent->takeSignal(); CallbackData *cbd = dynamic_cast(eventData.get()); diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index eb5cacee..370c3353 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -29,8 +29,7 @@ public: Client *Client::instance = 0; Client::Client() - : Thread() -{ + : Thread() { d = new PrivateData; d->running = true; d->sensorCached = false; @@ -83,16 +82,15 @@ int Client::registerEvent( CallbackStruct::CallbackType type, void *eventFunctio return d->callbackMainDispatcher.registerCallback(type, eventFunction, context ); } -void Client::run(){ - //listen here +void Client::run() { + // listen here d->eventSocket.connect(L"TelldusEvents"); - while(d->running){ - - if(!d->eventSocket.isConnected()){ - d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service - if(!d->eventSocket.isConnected()){ - //reconnect didn't succeed, wait a while and try again + while(d->running) { + if(!d->eventSocket.isConnected()) { + d->eventSocket.connect(L"TelldusEvents"); // try to reconnect to service + if(!d->eventSocket.isConnected()) { + // reconnect didn't succeed, wait a while and try again msleep(2000); continue; } @@ -100,30 +98,30 @@ void Client::run(){ std::wstring clientMessage = d->eventSocket.read(1000); //testing 5 second timeout - while(clientMessage != L""){ - //a message arrived + while(clientMessage != L"") { + // a message arrived std::wstring type = Message::takeString(&clientMessage); - if(type == L"TDDeviceChangeEvent"){ + if(type == L"TDDeviceChangeEvent") { DeviceChangeEventCallbackData *data = new DeviceChangeEventCallbackData(); data->deviceId = Message::takeInt(&clientMessage); data->changeEvent = Message::takeInt(&clientMessage); data->changeType = Message::takeInt(&clientMessage); d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - } else if(type == L"TDDeviceEvent"){ + } else if(type == L"TDDeviceEvent") { DeviceEventCallbackData *data = new DeviceEventCallbackData(); data->deviceId = Message::takeInt(&clientMessage); data->deviceState = Message::takeInt(&clientMessage); data->deviceStateValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - } else if(type == L"TDRawDeviceEvent"){ + } else if(type == L"TDRawDeviceEvent") { RawDeviceEventCallbackData *data = new RawDeviceEventCallbackData(); data->data = TelldusCore::wideToString(Message::takeString(&clientMessage)); data->controllerId = Message::takeInt(&clientMessage); d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); - } else if(type == L"TDSensorEvent"){ + } else if(type == L"TDSensorEvent") { SensorEventCallbackData *data = new SensorEventCallbackData(); data->protocol = TelldusCore::wideToString(Message::takeString(&clientMessage)); data->model = TelldusCore::wideToString(Message::takeString(&clientMessage)); @@ -152,9 +150,9 @@ std::wstring Client::sendToService(const Message &msg) { int tries = 0; std::wstring readData; - while(tries < 20){ + while(tries < 20) { tries++; - if(tries == 20){ + if(tries == 20) { TelldusCore::Message msg; msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); return msg; @@ -170,8 +168,8 @@ std::wstring Client::sendToService(const Message &msg) { msleep(500); continue; //retry } - readData = s.read(8000); //TODO changed to 10000 from 5000, how much does this do...? - if(readData == L""){ + readData = s.read(8000); // TODO changed to 10000 from 5000, how much does this do...? + if(readData == L"") { msleep(500); continue; //TODO can we be really sure it SHOULD be anything? //TODO perhaps break here instead? @@ -187,7 +185,7 @@ std::wstring Client::sendToService(const Message &msg) { return readData; } -void Client::stopThread(){ +void Client::stopThread() { d->running = false; d->eventSocket.stopReadWait(); } diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index c03c4d41..ce47a543 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -13,8 +13,7 @@ #include "common/Thread.h" namespace TelldusCore { - class Client : public Thread - { + class Client : public Thread { public: ~Client(void); diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index cf15eb6d..b2e27ccd 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -480,7 +480,7 @@ void WINAPI tdReleaseString(char *thestring) { * * @since Version 2.0.0 **/ -int WINAPI tdTurnOn(int intDeviceId){ +int WINAPI tdTurnOn(int intDeviceId) { Message msg(L"tdTurnOn"); msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); @@ -498,7 +498,7 @@ int WINAPI tdTurnOn(int intDeviceId){ * * @since Version 2.0.0 **/ -int WINAPI tdTurnOff(int intDeviceId){ +int WINAPI tdTurnOff(int intDeviceId) { Message msg(L"tdTurnOff"); msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); @@ -516,7 +516,7 @@ int WINAPI tdTurnOff(int intDeviceId){ * * @since Version 2.0.0 **/ -int WINAPI tdBell(int intDeviceId){ +int WINAPI tdBell(int intDeviceId) { Message msg(L"tdBell"); msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); @@ -536,7 +536,7 @@ int WINAPI tdBell(int intDeviceId){ * * @since Version 2.0.0 **/ -int WINAPI tdDim(int intDeviceId, unsigned char level){ +int WINAPI tdDim(int intDeviceId, unsigned char level) { Message msg(L"tdDim"); msg.addArgument(intDeviceId); msg.addArgument(level); @@ -555,7 +555,7 @@ int WINAPI tdDim(int intDeviceId, unsigned char level){ * * @since Version 2.1.0 **/ -int WINAPI tdExecute(int intDeviceId){ +int WINAPI tdExecute(int intDeviceId) { Message msg(L"tdExecute"); msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); @@ -573,7 +573,7 @@ int WINAPI tdExecute(int intDeviceId){ * * @since Version 2.1.0 **/ -int WINAPI tdUp(int intDeviceId){ +int WINAPI tdUp(int intDeviceId) { Message msg(L"tdUp"); msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); @@ -591,7 +591,7 @@ int WINAPI tdUp(int intDeviceId){ * * @since Version 2.1.0 **/ -int WINAPI tdDown(int intDeviceId){ +int WINAPI tdDown(int intDeviceId) { Message msg(L"tdDown"); msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); @@ -609,7 +609,7 @@ int WINAPI tdDown(int intDeviceId){ * * @since Version 2.1.0 */ -int WINAPI tdStop(int intDeviceId){ +int WINAPI tdStop(int intDeviceId) { Message msg(L"tdStop"); msg.addArgument(intDeviceId); return Client::getIntegerFromService(msg); @@ -683,7 +683,7 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * * @since Version 2.0.0 **/ -int WINAPI tdGetNumberOfDevices(void){ +int WINAPI tdGetNumberOfDevices(void) { return Client::getIntegerFromService(Message(L"tdGetNumberOfDevices")); } @@ -707,7 +707,7 @@ int WINAPI tdGetNumberOfDevices(void){ * * @since Version 2.0.0 **/ -int WINAPI tdGetDeviceId(int intDeviceIndex){ +int WINAPI tdGetDeviceId(int intDeviceIndex) { Message msg(L"tdGetDeviceId"); msg.addArgument(intDeviceIndex); return Client::getIntegerFromService(msg); @@ -744,7 +744,7 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * * @since Version 2.0.0 **/ -char * WINAPI tdGetName(int intDeviceId){ +char * WINAPI tdGetName(int intDeviceId) { Message msg(L"tdGetName"); msg.addArgument(intDeviceId); std::wstring strReturn = Client::getWStringFromService(msg); @@ -765,7 +765,7 @@ char * WINAPI tdGetName(int intDeviceId){ * * @since Version 2.0.0 **/ -bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ +bool WINAPI tdSetName(int intDeviceId, const char* strNewName) { Message msg(L"tdSetName"); msg.addArgument(intDeviceId); msg.addArgument(strNewName); @@ -784,7 +784,7 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName){ * * @since Version 2.0.0 **/ -char* WINAPI tdGetProtocol(int intDeviceId){ +char* WINAPI tdGetProtocol(int intDeviceId) { Message msg(L"tdGetProtocol"); msg.addArgument(intDeviceId); std::wstring strReturn = Client::getWStringFromService(msg); @@ -808,7 +808,7 @@ char* WINAPI tdGetProtocol(int intDeviceId){ * * @since Version 2.0.0 **/ -bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ +bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol) { Message msg(L"tdSetProtocol"); msg.addArgument(intDeviceId); msg.addArgument(strProtocol); @@ -827,7 +827,7 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol){ * * @since Version 2.0.0 **/ -char* WINAPI tdGetModel(int intDeviceId){ +char* WINAPI tdGetModel(int intDeviceId) { Message msg(L"tdGetModel"); msg.addArgument(intDeviceId); std::wstring strReturn = Client::getWStringFromService(msg); @@ -848,7 +848,7 @@ char* WINAPI tdGetModel(int intDeviceId){ * * @since Version 2.0.0 **/ -bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ +bool WINAPI tdSetModel(int intDeviceId, const char *strModel) { Message msg(L"tdSetModel"); msg.addArgument(intDeviceId); msg.addArgument(strModel); @@ -871,7 +871,7 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel){ * * @since Version 2.0.0 **/ -bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue){ +bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue) { Message msg(L"tdSetDeviceParameter"); msg.addArgument(intDeviceId); msg.addArgument(strName); @@ -896,7 +896,7 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * * @since Version 2.0.0 **/ -char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue){ +char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue) { Message msg(L"tdGetDeviceParameter"); msg.addArgument(intDeviceId); msg.addArgument(strName); @@ -916,7 +916,7 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c * * @since Version 2.0.0 **/ -int WINAPI tdAddDevice(){ +int WINAPI tdAddDevice() { Message msg(L"tdAddDevice"); return Client::getIntegerFromService(msg); } @@ -932,7 +932,7 @@ int WINAPI tdAddDevice(){ * * @since Version 2.0.0 **/ -bool WINAPI tdRemoveDevice(int intDeviceId){ +bool WINAPI tdRemoveDevice(int intDeviceId) { Message msg(L"tdRemoveDevice"); msg.addArgument(intDeviceId); return Client::getBoolFromService(msg); @@ -973,7 +973,7 @@ bool WINAPI tdRemoveDevice(int intDeviceId){ * * @since Version 2.0.0 **/ -int WINAPI tdMethods(int id, int methodsSupported){ +int WINAPI tdMethods(int id, int methodsSupported) { Message msg(L"tdMethods"); msg.addArgument(id); msg.addArgument(methodsSupported); diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 4db41f73..44aa3899 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -48,12 +48,12 @@ EventRef EventHandler::addEvent() { return event; } -bool EventHandler::listIsSignalled(){ +bool EventHandler::listIsSignalled() { TelldusCore::MutexLocker locker(&d->listMutex); std::list::const_iterator it = d->eventList.begin(); for(; it != d->eventList.end(); ++it) { - if((*it)->isSignaled()){ + if((*it)->isSignaled()) { return true; } } diff --git a/telldus-core/common/Event_unix.cpp b/telldus-core/common/Event_unix.cpp index be31ee89..a2630412 100644 --- a/telldus-core/common/Event_unix.cpp +++ b/telldus-core/common/Event_unix.cpp @@ -15,7 +15,7 @@ public: }; Event::Event(EventHandler *handler) - :EventBase(handler){ + :EventBase(handler) { d = new PrivateData; } diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 030564fa..efbb87ca 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -15,13 +15,11 @@ using namespace TelldusCore; Message::Message() - : std::wstring() -{ + : std::wstring() { } Message::Message(const std::wstring &functionName) - :std::wstring() -{ + :std::wstring() { this->addArgument(functionName); } diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index 5a7b6436..6b17b2e5 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -77,8 +77,7 @@ void LoggedMutex::unlock() { } MutexLocker::MutexLocker(Mutex *m) - :mutex(m) -{ + :mutex(m) { mutex->lock(); } diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 712d7f97..eed6a0b7 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -17,8 +17,7 @@ #endif namespace TelldusCore { - class Socket - { + class Socket { public: Socket(); explicit Socket(SOCKET_T hPipe); diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index fa759e88..89172a5a 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -39,8 +39,7 @@ Socket::Socket() { FD_ZERO(&d->infds); } -Socket::Socket(SOCKET_T socket) -{ +Socket::Socket(SOCKET_T socket) { d = new PrivateData; d->socket = socket; FD_ZERO(&d->infds); @@ -48,7 +47,7 @@ Socket::Socket(SOCKET_T socket) } Socket::~Socket(void) { - if(d->socket){ + if(d->socket) { close(d->socket); } delete d; @@ -74,7 +73,7 @@ void Socket::connect(const std::wstring &server) { d->connected = true; } -bool Socket::isConnected(){ +bool Socket::isConnected() { TelldusCore::MutexLocker locker(&d->mutex); return d->connected; } @@ -102,10 +101,10 @@ std::wstring Socket::read(int timeout) { } int received = BUFSIZE; - while(received >= (BUFSIZE - 1)){ + while(received >= (BUFSIZE - 1)) { memset(inbuf, '\0', sizeof(inbuf)); received = recv(d->socket, inbuf, BUFSIZE - 1, 0); - if(received > 0){ + if(received > 0) { msg.append(std::string(inbuf)); } } @@ -119,7 +118,7 @@ std::wstring Socket::read(int timeout) { return TelldusCore::charToWstring(msg.c_str()); } -void Socket::stopReadWait(){ +void Socket::stopReadWait() { TelldusCore::MutexLocker locker(&d->mutex); d->connected = false; //TODO somehow signal the socket here? diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 3b451b0e..d7cef23c 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -73,7 +73,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { #endif } -int TelldusCore::charToInteger(const char *input){ +int TelldusCore::charToInteger(const char *input) { std::stringstream inputstream; inputstream << input; int retval; @@ -150,7 +150,7 @@ std::wstring TelldusCore::intToWStringSafe(int value){ } */ -uint64_t TelldusCore::hexTo64l(const std::string data){ +uint64_t TelldusCore::hexTo64l(const std::string data) { #ifdef _WINDOWS return _strtoui64(data.c_str(), NULL, 16); #elif defined(_MACOSX) @@ -160,7 +160,7 @@ uint64_t TelldusCore::hexTo64l(const std::string data){ #endif } -int TelldusCore::wideToInteger(const std::wstring &input){ +int TelldusCore::wideToInteger(const std::wstring &input) { std::wstringstream inputstream; inputstream << input; int retval; diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index f79caf96..1a596dd3 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -41,7 +41,7 @@ inline void dlog(const char *fmt, ...) { fflush(stdout); } -inline void debuglog(const int intMessage, const std::string strMessage){ +inline void debuglog(const int intMessage, const std::string strMessage) { #ifdef _WINDOWS static bool firstRun = true; std::ofstream file; diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 175fb91f..b8355374 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -20,13 +20,11 @@ public: ControllerManager *controllerManager; }; -ClientCommunicationHandler::ClientCommunicationHandler(){ - +ClientCommunicationHandler::ClientCommunicationHandler() { } ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent, ControllerManager *controllerManager) - :Thread() -{ + :Thread() { d = new PrivateData; d->clientSocket = clientSocket; d->event = event; @@ -36,15 +34,14 @@ ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clie d->controllerManager = controllerManager; } -ClientCommunicationHandler::~ClientCommunicationHandler(void) -{ +ClientCommunicationHandler::~ClientCommunicationHandler(void) { wait(); delete(d->clientSocket); delete d; } -void ClientCommunicationHandler::run(){ - //run thread +void ClientCommunicationHandler::run() { + // run thread std::wstring clientMessage = d->clientSocket->read(2000); @@ -55,10 +52,10 @@ void ClientCommunicationHandler::run(){ TelldusCore::Message msg; - if(strReturn == L""){ + if(strReturn == L"") { msg.addArgument(intReturn); } - else{ + else { msg.addArgument(strReturn); } msg.append(L"\n"); @@ -69,13 +66,12 @@ void ClientCommunicationHandler::run(){ d->event->signal(); } -bool ClientCommunicationHandler::isDone(){ +bool ClientCommunicationHandler::isDone() { return d->done; } -void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn){ - +void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn) { (*intReturn) = 0; (*wstringReturn) = L""; std::wstring msg(clientMessage); //Copy @@ -127,8 +123,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); (*wstringReturn) = d->deviceManager->getDeviceStateValue(deviceId); - } else if(function == L"tdGetNumberOfDevices"){ - + } else if(function == L"tdGetNumberOfDevices") { (*intReturn) = d->deviceManager->getNumberOfDevices(); } else if (function == L"tdGetDeviceId") { @@ -159,7 +154,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int oldMethods = d->deviceManager->getDeviceMethods(deviceId); (*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol); sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL); - if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)) { sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); } @@ -173,7 +168,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int oldMethods = d->deviceManager->getDeviceMethods(deviceId); (*intReturn) = d->deviceManager->setDeviceModel(deviceId, model); sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL); - if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)) { sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); } @@ -189,20 +184,20 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, std::wstring value = TelldusCore::Message::takeString(&msg); int oldMethods = d->deviceManager->getDeviceMethods(deviceId); (*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value); - if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)){ + if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)) { sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD); } } else if (function == L"tdAddDevice") { (*intReturn) = d->deviceManager->addDevice(); - if((*intReturn) >= 0){ + if((*intReturn) >= 0) { sendDeviceSignal((*intReturn), TELLSTICK_DEVICE_ADDED, 0); } } else if (function == L"tdRemoveDevice") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->removeDevice(deviceId); - if((*intReturn) == TELLSTICK_SUCCESS){ + if((*intReturn) == TELLSTICK_SUCCESS) { sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0); } @@ -261,8 +256,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, } } -void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType){ - +void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType) { EventUpdateData *eventData = new EventUpdateData(); eventData->messageType = L"TDDeviceChangeEvent"; eventData->deviceId = deviceId; diff --git a/telldus-core/service/ClientCommunicationHandler.h b/telldus-core/service/ClientCommunicationHandler.h index 3a89908c..e25f1729 100644 --- a/telldus-core/service/ClientCommunicationHandler.h +++ b/telldus-core/service/ClientCommunicationHandler.h @@ -14,8 +14,7 @@ #include "service/DeviceManager.h" #include "service/ControllerManager.h" -class ClientCommunicationHandler : public TelldusCore::Thread -{ +class ClientCommunicationHandler : public TelldusCore::Thread { public: ClientCommunicationHandler(); ClientCommunicationHandler( diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 02344bd9..354d8673 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -25,8 +25,7 @@ public: bool running; }; -ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) -{ +ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) { d = new PrivateData; d->waitEvent = waitEvent; @@ -43,7 +42,7 @@ ConnectionListener::~ConnectionListener(void) { delete d; } -void ConnectionListener::run(){ +void ConnectionListener::run() { struct timeval tv = { 0, 0 }; //Timeout for select diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index f24b786e..ad23935d 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -17,7 +17,7 @@ public: int id, firmwareVersion; }; -Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ +Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent) { d = new PrivateData; d->event = event; d->updateEvent = updateEvent; @@ -25,7 +25,7 @@ Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRe d->firmwareVersion = 0; } -Controller::~Controller(){ +Controller::~Controller() { delete d; } @@ -40,7 +40,7 @@ void Controller::decodePublishData(const std::string &data) const { std::list msgList = Protocol::decodeData(data); - for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt){ + for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt) { this->publishData(*msgIt); } } diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 5f58409d..678caca4 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -36,7 +36,7 @@ public: TelldusCore::Mutex mutex; }; -ControllerManager::ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent){ +ControllerManager::ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent) { d = new PrivateData; d->lastControllerId = 0; d->event = event; @@ -171,8 +171,8 @@ void ControllerManager::loadControllers() { bool isNew = false; if (!controllerId) { controllerId = d->settings.addNode(Settings::Controller); - if(controllerId < 0){ - //TODO: How to handle this? + if(controllerId < 0) { + // TODO: How to handle this? continue; } isNew = true; @@ -212,8 +212,7 @@ void ControllerManager::loadStoredControllers() { } } -void ControllerManager::queryControllerStatus(){ - +void ControllerManager::queryControllerStatus() { std::list tellStickControllers; { @@ -233,18 +232,18 @@ void ControllerManager::queryControllerStatus(){ std::string noop = "N+"; for(std::list::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) { int success = (*it)->send(noop); - if(success == TELLSTICK_ERROR_BROKEN_PIPE){ + if(success == TELLSTICK_ERROR_BROKEN_PIPE) { Log::warning("TellStick query: Error in communication with TellStick, resetting USB"); resetController(*it); } - if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND){ + if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND) { reloadControllers = true; } } - if(!tellStickControllers.size() || reloadControllers){ - //no tellstick at all found, or controller was reset - Log::debug("TellStick query: Rescanning USB ports"); //only log as debug, since this will happen all the time if no TellStick is connected + if(!tellStickControllers.size() || reloadControllers) { + // no tellstick at all found, or controller was reset + Log::debug("TellStick query: Rescanning USB ports"); // only log as debug, since this will happen all the time if no TellStick is connected loadControllers(); } } diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index ce42e0ab..4cc39044 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -47,7 +47,7 @@ ControllerMessage::ControllerMessage(const std::string &message) { } } -ControllerMessage::~ControllerMessage(){ +ControllerMessage::~ControllerMessage() { delete d; } diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index e0605a44..4f71fe1b 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -23,8 +23,7 @@ public: }; Device::Device(int id) - :Mutex() -{ + :Mutex() { d = new PrivateData; d->protocol = 0; d->preferredControllerId = 0; @@ -40,8 +39,7 @@ Device::~Device(void) { * Get-/Set-methods */ -int Device::getLastSentCommand(int methodsSupported){ - +int Device::getLastSentCommand(int methodsSupported) { int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported); if (lastSentCommand == TELLSTICK_BELL) { @@ -63,32 +61,32 @@ int Device::getMethods() const { return 0; } -void Device::setLastSentCommand(int command, std::wstring value){ +void Device::setLastSentCommand(int command, std::wstring value) { d->state = command; d->stateValue = value; } -std::wstring Device::getModel(){ +std::wstring Device::getModel() { return d->model; } -void Device::setModel(const std::wstring &model){ - if(d->protocol){ +void Device::setModel(const std::wstring &model) { + if(d->protocol) { delete(d->protocol); d->protocol = 0; } d->model = model; } -std::wstring Device::getName(){ +std::wstring Device::getName() { return d->name; } -void Device::setName(const std::wstring &name){ +void Device::setName(const std::wstring &name) { d->name = name; } -std::wstring Device::getParameter(const std::wstring &key){ +std::wstring Device::getParameter(const std::wstring &key) { ParameterMap::iterator it = d->parameterList.find(key); if (it == d->parameterList.end()) { return L""; @@ -100,18 +98,18 @@ std::list Device::getParametersForProtocol() const { return Protocol::getParametersForProtocol(getProtocolName()); } -void Device::setParameter(const std::wstring &key, const std::wstring &value){ +void Device::setParameter(const std::wstring &key, const std::wstring &value) { d->parameterList[key] = value; - if(d->protocol){ + if(d->protocol) { d->protocol->setParameters(d->parameterList); } } -int Device::getPreferredControllerId(){ +int Device::getPreferredControllerId() { return d->preferredControllerId; } -void Device::setPreferredControllerId(int controllerId){ +void Device::setPreferredControllerId(int controllerId) { d->preferredControllerId = controllerId; } @@ -119,23 +117,23 @@ std::wstring Device::getProtocolName() const { return d->protocolName; } -void Device::setProtocolName(const std::wstring &protocolName){ - if(d->protocol){ +void Device::setProtocolName(const std::wstring &protocolName) { + if(d->protocol) { delete(d->protocol); d->protocol = 0; } d->protocolName = protocolName; } -std::wstring Device::getStateValue(){ +std::wstring Device::getStateValue() { return d->stateValue; } -int Device::getType(){ - if(d->protocolName == L"group"){ +int Device::getType() { + if(d->protocolName == L"group") { return TELLSTICK_TYPE_GROUP; } - else if(d->protocolName == L"scene"){ + else if(d->protocolName == L"scene") { return TELLSTICK_TYPE_SCENE; } return TELLSTICK_TYPE_DEVICE; @@ -199,7 +197,7 @@ Protocol* Device::retrieveProtocol() const { } d->protocol = Protocol::getProtocolInstance(d->protocolName); - if(d->protocol){ + if(d->protocol) { d->protocol->setModel(d->model); d->protocol->setParameters(d->parameterList); return d->protocol; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index fef206c4..77272987 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -13,8 +13,7 @@ #include #include -class Device : public TelldusCore::Mutex -{ +class Device : public TelldusCore::Mutex { public: explicit Device(int id); ~Device(void); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 5d8098a5..a09bd985 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -30,7 +30,7 @@ public: TelldusCore::EventRef deviceUpdateEvent; }; -DeviceManager::DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent){ +DeviceManager::DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent) { d = new PrivateData; d->controllerManager = controllerManager; d->deviceUpdateEvent = deviceUpdateEvent; @@ -52,7 +52,7 @@ DeviceManager::~DeviceManager(void) { delete d; } -void DeviceManager::fillDevices(){ +void DeviceManager::fillDevices() { int numberOfDevices = d->set.getNumberOfNodes(Settings::Device); TelldusCore::MutexLocker deviceListLocker(&d->lock); @@ -74,7 +74,7 @@ void DeviceManager::fillDevices(){ } } -int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ +int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -87,8 +87,7 @@ int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value) -{ +int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -99,13 +98,13 @@ int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std d->set.setDeviceState(deviceId, command,value); it->second->setLastSentCommand(command, value); } - else{ + else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_SUCCESS; } -std::wstring DeviceManager::getDeviceStateValue(int deviceId){ +std::wstring DeviceManager::getDeviceStateValue(int deviceId) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; @@ -127,7 +126,7 @@ int DeviceManager::getDeviceMethods(int deviceId) { return DeviceManager::getDeviceMethods(deviceId, duplicateDeviceIds); } -int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDeviceIds){ +int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDeviceIds) { int type = 0; int methods = 0; std::wstring deviceIds; @@ -152,29 +151,28 @@ int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDevice } } } - if(type == 0){ + if(type == 0) { return 0; } - if(type == TELLSTICK_TYPE_GROUP){ - - //get all methods that some device in the groups supports + if(type == TELLSTICK_TYPE_GROUP) { + // get all methods that some device in the groups supports std::wstring deviceIdBuffer; std::wstringstream devicesstream(deviceIds); methods = 0; duplicateDeviceIds.insert(deviceId); - while(std::getline(devicesstream, deviceIdBuffer, L',')){ + while(std::getline(devicesstream, deviceIdBuffer, L',')) { int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); - if(duplicateDeviceIds.count(deviceIdInGroup) == 1){ - //action for device already executed, or will execute, do nothing to avoid infinite loop + if(duplicateDeviceIds.count(deviceIdInGroup) == 1) { + // action for device already executed, or will execute, do nothing to avoid infinite loop continue; } duplicateDeviceIds.insert(deviceIdInGroup); int deviceMethods = getDeviceMethods(deviceIdInGroup, duplicateDeviceIds); - if(deviceMethods > 0){ + if(deviceMethods > 0) { methods |= deviceMethods; } } @@ -182,8 +180,7 @@ int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDevice return methods; } -std::wstring DeviceManager::getDeviceModel(int deviceId){ - +std::wstring DeviceManager::getDeviceModel(int deviceId) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; @@ -196,8 +193,7 @@ std::wstring DeviceManager::getDeviceModel(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) -{ +int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -211,15 +207,14 @@ int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) } it->second->setModel(model); } - else{ + else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_SUCCESS; } -std::wstring DeviceManager::getDeviceName(int deviceId){ - +std::wstring DeviceManager::getDeviceName(int deviceId) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; @@ -232,8 +227,7 @@ std::wstring DeviceManager::getDeviceName(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::setDeviceName(int deviceId, const std::wstring &name){ - +int DeviceManager::setDeviceName(int deviceId, const std::wstring &name) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -247,32 +241,30 @@ int DeviceManager::setDeviceName(int deviceId, const std::wstring &name){ } it->second->setName(name); } - else{ + else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_SUCCESS; } -std::wstring DeviceManager::getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defaultValue){ - +std::wstring DeviceManager::getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defaultValue) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return defaultValue; } DeviceMap::iterator it = d->devices.find(deviceId); - if (it != d->devices.end()){ + if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); std::wstring returnString = it->second->getParameter(name); - if(returnString != L""){ + if(returnString != L"") { return returnString; } } return defaultValue; } -int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value) -{ +int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -286,15 +278,14 @@ int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, co } it->second->setParameter(name, value); } - else{ + else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_SUCCESS; } -std::wstring DeviceManager::getDeviceProtocol(int deviceId){ - +std::wstring DeviceManager::getDeviceProtocol(int deviceId) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return L"UNKNOWN"; @@ -307,8 +298,7 @@ std::wstring DeviceManager::getDeviceProtocol(int deviceId){ return L"UNKNOWN"; } -int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) -{ +int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -322,28 +312,27 @@ int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) } it->second->setProtocolName(protocol); } - else{ + else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_SUCCESS; } -int DeviceManager::getNumberOfDevices(){ +int DeviceManager::getNumberOfDevices() { TelldusCore::MutexLocker deviceListLocker(&d->lock); return (int)d->devices.size(); } -int DeviceManager::addDevice(){ - +int DeviceManager::addDevice() { int id = d->set.addNode(Settings::Device); - if(id < 0){ + if(id < 0) { return id; } TelldusCore::MutexLocker deviceListLocker(&d->lock); d->devices[id] = new Device(id); - if(!d->devices[id]){ + if(!d->devices[id]) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return id; @@ -353,8 +342,7 @@ int DeviceManager::getDeviceId(int deviceIndex) { return d->set.getNodeId(Settings::Device, deviceIndex); } -int DeviceManager::getDeviceType(int deviceId){ - +int DeviceManager::getDeviceType(int deviceId) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; @@ -367,8 +355,7 @@ int DeviceManager::getDeviceType(int deviceId){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -int DeviceManager::getPreferredControllerId(int deviceId){ - +int DeviceManager::getPreferredControllerId(int deviceId) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -382,15 +369,15 @@ int DeviceManager::getPreferredControllerId(int deviceId){ return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } -void DeviceManager::connectTellStickController(int vid, int pid, const std::string &serial){ +void DeviceManager::connectTellStickController(int vid, int pid, const std::string &serial) { d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, true); } -void DeviceManager::disconnectTellStickController(int vid, int pid, const std::string &serial){ +void DeviceManager::disconnectTellStickController(int vid, int pid, const std::string &serial) { d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, false); } -int DeviceManager::doAction(int deviceId, int action, unsigned char data){ +int DeviceManager::doAction(int deviceId, int action, unsigned char data) { Device *device = 0; //On the stack and will be released if we have a device lock. std::auto_ptr deviceLocker(0); @@ -412,7 +399,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ int retval = TELLSTICK_ERROR_UNKNOWN; - if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE){ + if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE) { std::wstring devices = device->getParameter(L"devices"); deviceLocker = std::auto_ptr(0); std::set *duplicateDeviceIds = new std::set; @@ -436,26 +423,26 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ device = it->second; } //devicelist unlocked } - else{ + else { Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - if(!controller){ + if(!controller) { Log::warning("Trying to execute action, but no controller found. Rescanning USB ports"); //no controller found, scan for one, and retry once d->controllerManager->loadControllers(); controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); } - if(controller){ + if(controller) { retval = device->doAction(action, data, controller); - if(retval == TELLSTICK_ERROR_BROKEN_PIPE){ + if(retval == TELLSTICK_ERROR_BROKEN_PIPE) { Log::warning("Error in communication with TellStick when executing action. Resetting USB"); d->controllerManager->resetController(controller); } - if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){ + if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND) { Log::warning("Rescanning USB ports"); d->controllerManager->loadControllers(); controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - if(!controller){ + if(!controller) { Log::error("No contoller (TellStick) found, even after reset. Giving up."); return TELLSTICK_ERROR_NOT_FOUND; } @@ -477,19 +464,18 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ return retval; } -int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId, std::set *duplicateDeviceIds){ +int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId, std::set *duplicateDeviceIds) { int retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; std::wstring singledevice; std::wstringstream devicesstream(devices); duplicateDeviceIds->insert(groupDeviceId); - while(std::getline(devicesstream, singledevice, L',')){ - + while(std::getline(devicesstream, singledevice, L',')) { int deviceId = TelldusCore::wideToInteger(singledevice); - if(duplicateDeviceIds->count(deviceId) == 1){ - //action for device already executed, or will execute, do nothing to avoid infinite loop + if(duplicateDeviceIds->count(deviceId) == 1) { + // action for device already executed, or will execute, do nothing to avoid infinite loop continue; } @@ -497,20 +483,20 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c int deviceReturnValue = TELLSTICK_SUCCESS; - if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)){ + if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)) { deviceReturnValue = executeScene(singledevice, groupDeviceId); } - else if(type == TELLSTICK_TYPE_GROUP){ - if(deviceId != 0){ + else if(type == TELLSTICK_TYPE_GROUP) { + if(deviceId != 0) { int childType = DeviceManager::getDeviceType(deviceId); - if(childType == TELLSTICK_TYPE_DEVICE){ + if(childType == TELLSTICK_TYPE_DEVICE) { deviceReturnValue = doAction(deviceId, action, data); } - else if(childType == TELLSTICK_TYPE_SCENE){ - deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); //TODO make scenes infinite loops-safe + else if(childType == TELLSTICK_TYPE_SCENE) { + deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); // TODO make scenes infinite loops-safe } - else{ - //group (in group) + else { + // group (in group) deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); if(deviceReturnValue == TELLSTICK_SUCCESS) { @@ -522,15 +508,15 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c } } } - else{ - deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; //Probably incorrectly formatted parameter + else { + deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; // Probably incorrectly formatted parameter } } - if(deviceReturnValue != TELLSTICK_ERROR_METHOD_NOT_SUPPORTED){ - //if error(s), return the last error, but still try to continue the action with the other devices - //if the error is a method not supported we igore is since there might be others supporting it - //If no devices support the method the default value will be returned (method not supported) + if(deviceReturnValue != TELLSTICK_ERROR_METHOD_NOT_SUPPORTED) { + // if error(s), return the last error, but still try to continue the action with the other devices + // if the error is a method not supported we igore is since there might be others supporting it + // If no devices support the method the default value will be returned (method not supported) retval = deviceReturnValue; } @@ -538,45 +524,43 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c return retval; } -int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId){ - +int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId) { std::wstringstream devicestream(singledevice); const int deviceParameterLength = 3; std::wstring deviceParts[deviceParameterLength] = {L"", L"", L""}; std::wstring devicePart = L""; int i = 0; - while(std::getline(devicestream, devicePart, L':') && i < deviceParameterLength){ + while(std::getline(devicestream, devicePart, L':') && i < deviceParameterLength) { deviceParts[i] = devicePart; i++; } - if(deviceParts[0] == L"" || deviceParts[1] == L""){ - return TELLSTICK_ERROR_UNKNOWN; //malformed or missing parameter + if(deviceParts[0] == L"" || deviceParts[1] == L"") { + return TELLSTICK_ERROR_UNKNOWN; // malformed or missing parameter } int deviceId = TelldusCore::wideToInteger(deviceParts[0]); - if(deviceId == groupDeviceId){ - return TELLSTICK_ERROR_UNKNOWN; //the scene itself has been added to its devices, avoid infinite loop + if(deviceId == groupDeviceId) { + return TELLSTICK_ERROR_UNKNOWN; // the scene itself has been added to its devices, avoid infinite loop } - int method = Device::methodId(TelldusCore::wideToString(deviceParts[1])); //support methodparts both in the form of integers (e.g. TELLSTICK_TURNON) or text (e.g. "turnon") - if(method == 0){ + int method = Device::methodId(TelldusCore::wideToString(deviceParts[1])); // support methodparts both in the form of integers (e.g. TELLSTICK_TURNON) or text (e.g. "turnon") + if(method == 0) { method = TelldusCore::wideToInteger(deviceParts[1]); } unsigned char devicedata = 0; - if(deviceParts[2] != L""){ + if(deviceParts[2] != L"") { devicedata = TelldusCore::wideToInteger(deviceParts[2]); } - if(deviceId > 0 && method > 0){ //check for format error in parameter "devices" + if(deviceId > 0 && method > 0) { // check for format error in parameter "devices" return doAction(deviceId, method, devicedata); } return TELLSTICK_ERROR_UNKNOWN; } -int DeviceManager::removeDevice(int deviceId){ - +int DeviceManager::removeDevice(int deviceId) { Device *device = 0; { int ret = d->set.removeNode(Settings::Device, deviceId); //remove from register/settings @@ -593,7 +577,7 @@ int DeviceManager::removeDevice(int deviceId){ device = it->second; d->devices.erase(it); //remove from list, keep reference } - else{ + else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } @@ -679,14 +663,14 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData std::list parameters = it->second->getParametersForProtocol(); bool thisDevice = true; - for (std::list::iterator paramIt = parameters.begin(); paramIt != parameters.end(); ++paramIt){ - if(!TelldusCore::comparei(it->second->getParameter(TelldusCore::charToWstring((*paramIt).c_str())), TelldusCore::charToWstring(msg.getParameter(*paramIt).c_str()))){ + for (std::list::iterator paramIt = parameters.begin(); paramIt != parameters.end(); ++paramIt) { + if(!TelldusCore::comparei(it->second->getParameter(TelldusCore::charToWstring((*paramIt).c_str())), TelldusCore::charToWstring(msg.getParameter(*paramIt).c_str()))) { thisDevice = false; break; } } - if(!thisDevice){ + if(!thisDevice) { continue; } @@ -744,26 +728,25 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int da d->deviceUpdateEvent->signal(eventData); } -int DeviceManager::sendRawCommand(const std::wstring &command, int reserved){ - +int DeviceManager::sendRawCommand(const std::wstring &command, int reserved) { Controller *controller = d->controllerManager->getBestControllerById(-1); - if(!controller){ - //no controller found, scan for one, and retry once + if(!controller) { + // no controller found, scan for one, and retry once d->controllerManager->loadControllers(); controller = d->controllerManager->getBestControllerById(-1); } int retval = TELLSTICK_ERROR_UNKNOWN; - if(controller){ + if(controller) { retval = controller->send(TelldusCore::wideToString(command)); - if(retval == TELLSTICK_ERROR_BROKEN_PIPE){ + if(retval == TELLSTICK_ERROR_BROKEN_PIPE) { d->controllerManager->resetController(controller); } - if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND){ + if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND) { d->controllerManager->loadControllers(); controller = d->controllerManager->getBestControllerById(-1); - if(!controller){ + if(!controller) { return TELLSTICK_ERROR_NOT_FOUND; } retval = controller->send(TelldusCore::wideToString(command)); //retry one more time diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index ef6d0b5c..9ed8be2c 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -16,8 +16,7 @@ class Sensor; -class DeviceManager -{ +class DeviceManager { public: DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent); ~DeviceManager(void); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index e966a867..a5056d78 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -25,8 +25,7 @@ public: }; EventUpdateManager::EventUpdateManager() - :Thread() -{ + :Thread() { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); d->updateEvent = d->eventHandler.addEvent(); @@ -46,63 +45,60 @@ EventUpdateManager::~EventUpdateManager(void) { delete d; } -TelldusCore::EventRef EventUpdateManager::retrieveUpdateEvent(){ - +TelldusCore::EventRef EventUpdateManager::retrieveUpdateEvent() { return d->updateEvent; } -void EventUpdateManager::run(){ - - while(!d->stopEvent->isSignaled()){ +void EventUpdateManager::run() { + while(!d->stopEvent->isSignaled()) { if (!d->eventHandler.waitForAny()) { continue; } - if(d->clientConnectEvent->isSignaled()){ - //new client added + if(d->clientConnectEvent->isSignaled()) { + // new client added TelldusCore::EventDataRef eventData = d->clientConnectEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventData.get()); - if(data){ + if(data) { d->clients.push_back(data->socket); } } - else if(d->updateEvent->isSignaled()){ - //device event, signal all clients + else if(d->updateEvent->isSignaled()) { + // device event, signal all clients TelldusCore::EventDataRef eventData = d->updateEvent->takeSignal(); EventUpdateData *data = reinterpret_cast(eventData.get()); - if(data){ + if(data) { sendMessageToClients(data); } } } } -void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ - +void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { int connected = 0; - for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();){ - if((*it)->isConnected()){ + for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();) { + if((*it)->isConnected()) { connected++; TelldusCore::Message msg; - if(data->messageType == L"TDDeviceEvent"){ + if(data->messageType == L"TDDeviceEvent") { msg.addArgument("TDDeviceEvent"); msg.addArgument(data->deviceId); msg.addArgument(data->eventState); msg.addArgument(data->eventValue); //string } - else if(data->messageType == L"TDDeviceChangeEvent"){ + else if(data->messageType == L"TDDeviceChangeEvent") { msg.addArgument("TDDeviceChangeEvent"); msg.addArgument(data->deviceId); msg.addArgument(data->eventDeviceChanges); msg.addArgument(data->eventChangeType); } - else if(data->messageType == L"TDRawDeviceEvent"){ + else if(data->messageType == L"TDRawDeviceEvent") { msg.addArgument("TDRawDeviceEvent"); msg.addArgument(data->eventValue); //string msg.addArgument(data->controllerId); } - else if(data->messageType == L"TDSensorEvent"){ + else if(data->messageType == L"TDSensorEvent") { msg.addArgument("TDSensorEvent"); msg.addArgument(data->protocol); msg.addArgument(data->model); @@ -123,8 +119,8 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ it++; } - else{ - //connection is dead, remove it + else { + // connection is dead, remove it delete *it; it = d->clients.erase(it); } diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 7499da69..d45b4e02 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -29,8 +29,7 @@ public: int timestamp; }; -class EventUpdateManager : public TelldusCore::Thread -{ +class EventUpdateManager : public TelldusCore::Thread { public: EventUpdateManager(void); ~EventUpdateManager(void); diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index c4a8f482..b4474c3c 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -31,8 +31,7 @@ public: Log *Log::PrivateData::instance = 0; Log::Log() - :d(new PrivateData) -{ + :d(new PrivateData) { #if defined(_LINUX) setlogmask(LOG_UPTO(LOG_INFO)); openlog("telldusd", LOG_CONS, LOG_USER); diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 04fbacbc..5bd9ff1a 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -37,8 +37,7 @@ public: std::wstring model; }; -Protocol::Protocol(){ - +Protocol::Protocol() { d = new PrivateData; } @@ -57,11 +56,11 @@ std::wstring Protocol::model() const { return strModel; } -void Protocol::setModel(const std::wstring &model){ +void Protocol::setModel(const std::wstring &model) { d->model = model; } -void Protocol::setParameters(ParameterMap ¶meterList){ +void Protocol::setParameters(ParameterMap ¶meterList) { d->parameterList = parameterList; } @@ -96,9 +95,8 @@ bool Protocol::checkBit(int data, int bitno) { } -Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ - - if(TelldusCore::comparei(protocolname, L"arctech")){ +Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname) { + if(TelldusCore::comparei(protocolname, L"arctech")) { return new ProtocolNexa(); } else if (TelldusCore::comparei(protocolname, L"brateck")) { @@ -153,7 +151,7 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname){ std::list Protocol::getParametersForProtocol(const std::wstring &protocolName) { std::list parameters; - if(TelldusCore::comparei(protocolName, L"arctech")){ + if(TelldusCore::comparei(protocolName, L"arctech")) { parameters.push_back("house"); parameters.push_back("unit"); diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index 5c887102..ac48c7a4 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -16,8 +16,7 @@ typedef std::map ParameterMap; class Controller; -class Protocol -{ +class Protocol { public: Protocol(); virtual ~Protocol(void); diff --git a/telldus-core/service/ProtocolBrateck.h b/telldus-core/service/ProtocolBrateck.h index 702f9ad3..c533308a 100644 --- a/telldus-core/service/ProtocolBrateck.h +++ b/telldus-core/service/ProtocolBrateck.h @@ -10,8 +10,7 @@ #include #include "service/Protocol.h" -class ProtocolBrateck : public Protocol -{ +class ProtocolBrateck : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 69f7e93c..6ba569c5 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -94,8 +94,7 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { return res; } -std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) -{ +std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); unsigned int allData; unsigned int house = 0; @@ -113,20 +112,20 @@ std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) method = allData & 0xF; - if(house < 0 || house > 16383 || unit < 1 || unit > 4){ - //not everflourish + if(house < 0 || house > 16383 || unit < 1 || unit > 4) { + // not everflourish return ""; } std::stringstream retString; retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:"; - if(method == 0){ + if(method == 0) { retString << "turnoff;"; } - else if(method == 15){ + else if(method == 15) { retString << "turnon;"; } - else if(method == 10){ + else if(method == 10) { retString << "learn;"; } else { diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 325a7c89..4118407f 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -11,8 +11,7 @@ #include "service/Protocol.h" #include "service/ControllerMessage.h" -class ProtocolEverflourish : public Protocol -{ +class ProtocolEverflourish : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index 11abe163..85962422 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -10,8 +10,7 @@ #include #include -std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) -{ +std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); if (data.length() < 8) { return ""; diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h index c0546e73..94894f2e 100644 --- a/telldus-core/service/ProtocolFineoffset.h +++ b/telldus-core/service/ProtocolFineoffset.h @@ -11,8 +11,7 @@ #include "service/Protocol.h" #include "service/ControllerMessage.h" -class ProtocolFineoffset : public Protocol -{ +class ProtocolFineoffset : public Protocol { public: static std::string decodeData(ControllerMessage &dataMsg); }; diff --git a/telldus-core/service/ProtocolFuhaote.h b/telldus-core/service/ProtocolFuhaote.h index b3b8d004..2618ef86 100644 --- a/telldus-core/service/ProtocolFuhaote.h +++ b/telldus-core/service/ProtocolFuhaote.h @@ -10,8 +10,7 @@ #include #include "service/Protocol.h" -class ProtocolFuhaote : public Protocol -{ +class ProtocolFuhaote : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolHasta.h b/telldus-core/service/ProtocolHasta.h index 5e7c3e3c..0ab8a488 100644 --- a/telldus-core/service/ProtocolHasta.h +++ b/telldus-core/service/ProtocolHasta.h @@ -10,8 +10,7 @@ #include #include "service/Protocol.h" -class ProtocolHasta : public Protocol -{ +class ProtocolHasta : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolIkea.h b/telldus-core/service/ProtocolIkea.h index c9aceeb9..11a18cbf 100644 --- a/telldus-core/service/ProtocolIkea.h +++ b/telldus-core/service/ProtocolIkea.h @@ -10,8 +10,7 @@ #include #include "service/Protocol.h" -class ProtocolIkea : public Protocol -{ +class ProtocolIkea : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index f9b5059a..28ff77d5 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -10,8 +10,7 @@ #include #include -std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) -{ +std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); uint32_t value = (uint32_t)TelldusCore::hexTo64l(data); diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h index 421f7daa..ee9a69cd 100644 --- a/telldus-core/service/ProtocolMandolyn.h +++ b/telldus-core/service/ProtocolMandolyn.h @@ -11,8 +11,7 @@ #include "service/Protocol.h" #include "service/ControllerMessage.h" -class ProtocolMandolyn : public Protocol -{ +class ProtocolMandolyn : public Protocol { public: static std::string decodeData(ControllerMessage &dataMsg); }; diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 2b2a19e9..94a3e273 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -163,23 +163,22 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode return strMessage; } -std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) -{ +std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) { unsigned long allData = 0; sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); - if(TelldusCore::comparei(dataMsg.model(), L"selflearning")){ - //selflearning + if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { + // selflearning return decodeDataSelfLearning(allData); } - else{ - //codeswitch + else { + // codeswitch return decodeDataCodeSwitch(allData); } } -std::string ProtocolNexa::decodeDataSelfLearning(long allData){ +std::string ProtocolNexa::decodeDataSelfLearning(long allData) { unsigned int house = 0; unsigned int unit = 0; unsigned int group = 0; @@ -197,17 +196,17 @@ std::string ProtocolNexa::decodeDataSelfLearning(long allData){ unit = allData & 0xF; unit++; - if(house < 1 || house > 67108863 || unit < 1 || unit > 16){ - //not arctech selflearning + if(house < 1 || house > 67108863 || unit < 1 || unit > 16) { + // not arctech selflearning return ""; } std::stringstream retString; retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:"; - if(method == 1){ + if(method == 1) { retString << "turnon;"; } - else if(method == 0){ + else if(method == 0) { retString << "turnoff;"; } else { @@ -218,8 +217,7 @@ std::string ProtocolNexa::decodeDataSelfLearning(long allData){ return retString.str(); } -std::string ProtocolNexa::decodeDataCodeSwitch(long allData){ - +std::string ProtocolNexa::decodeDataCodeSwitch(long allData) { unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; @@ -233,33 +231,33 @@ std::string ProtocolNexa::decodeDataCodeSwitch(long allData){ house = allData & 0xF; - if(house < 0 || house > 16 || unit < 1 || unit > 16){ - //not arctech codeswitch + if(house < 0 || house > 16 || unit < 1 || unit > 16) { + // not arctech codeswitch return ""; } house = house + 'A'; //house from A to P - if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) { lastArctecCodeSwitchWasTurnOff = 0; return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose //one turnon/bell, but it's better than the alternative... } - if(method == 6){ + if(method == 6) { lastArctecCodeSwitchWasTurnOff = 1; } std::stringstream retString; retString << "class:command;protocol:arctech;model:codeswitch;house:" << char(house); - if(method == 6){ + if(method == 6) { retString << ";unit:" << unit << ";method:turnoff;"; } - else if(method == 14){ + else if(method == 14) { retString << ";unit:" << unit << ";method:turnon;"; } - else if(method == 15){ + else if(method == 15) { retString << ";method:bell;"; } else { diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 30d0c1a6..fe2aca11 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -10,8 +10,7 @@ #include #include -std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) -{ +std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); std::wstring model = dataMsg.model(); diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index 2dd8a8e9..bfa9662a 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -11,8 +11,7 @@ #include "service/Protocol.h" #include "service/ControllerMessage.h" -class ProtocolOregon : public Protocol -{ +class ProtocolOregon : public Protocol { public: static std::string decodeData(ControllerMessage &dataMsg); diff --git a/telldus-core/service/ProtocolRisingSun.h b/telldus-core/service/ProtocolRisingSun.h index e68941a4..ef6262e5 100644 --- a/telldus-core/service/ProtocolRisingSun.h +++ b/telldus-core/service/ProtocolRisingSun.h @@ -10,8 +10,7 @@ #include #include "service/Protocol.h" -class ProtocolRisingSun : public Protocol -{ +class ProtocolRisingSun : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 40182d4b..c0cc1185 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -41,8 +41,7 @@ std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int m } -std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) -{ +std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); signed int allDataIn; signed int allData = 0; @@ -54,9 +53,9 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) sscanf(data.c_str(), "%X", &allDataIn); unsigned long mask = (1<<11); - for(int i=0;i<12;++i){ + for(int i=0;i<12;++i) { allData >>= 1; - if((allDataIn & mask) == 0){ + if((allDataIn & mask) == 0) { allData |= (1<<11); } mask >>= 1; @@ -70,39 +69,39 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) method2 = allData & 0x1; - if(method1 == 0 && method2 == 1){ - method = 0; //off + if(method1 == 0 && method2 == 1) { + method = 0; // off } - else if(method1 == 1 && method2 == 0){ - method = 1; //on + else if(method1 == 1 && method2 == 0) { + method = 1; // on } - else{ + else { return ""; } - if(code < 0 || code > 1023){ - //not sartano + if(code < 0 || code > 1023) { + // not sartano return ""; } std::stringstream retString; retString << "class:command;protocol:sartano;model:codeswitch;code:"; mask = (1<<9); - for(int i=0;i<10;i++){ - if((code & mask) != 0){ + for(int i=0;i<10;i++) { + if((code & mask) != 0) { retString << 1; } - else{ + else { retString << 0; } mask >>= 1; } retString << ";method:"; - if(method == 0){ + if(method == 0) { retString << "turnoff;"; } - else{ + else { retString << "turnon;"; } diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index f28b4376..1480be83 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -11,8 +11,7 @@ #include "service/Protocol.h" #include "service/ControllerMessage.h" -class ProtocolSartano : public Protocol -{ +class ProtocolSartano : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolSilvanChip.h b/telldus-core/service/ProtocolSilvanChip.h index eaa1f7d7..188a2d4a 100644 --- a/telldus-core/service/ProtocolSilvanChip.h +++ b/telldus-core/service/ProtocolSilvanChip.h @@ -10,8 +10,7 @@ #include #include "service/Protocol.h" -class ProtocolSilvanChip : public Protocol -{ +class ProtocolSilvanChip : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolUpm.h b/telldus-core/service/ProtocolUpm.h index 3a55134d..9283a408 100644 --- a/telldus-core/service/ProtocolUpm.h +++ b/telldus-core/service/ProtocolUpm.h @@ -10,8 +10,7 @@ #include #include "service/Protocol.h" -class ProtocolUpm : public Protocol -{ +class ProtocolUpm : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 4f507094..abdd6565 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -22,8 +22,7 @@ std::string ProtocolWaveman::getOffCode() const { return "$k$k$k$k$k$k$k$k$k+"; } -std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) -{ +std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) { unsigned long allData = 0; unsigned int house = 0; unsigned int unit = 0; @@ -40,30 +39,30 @@ std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) house = allData & 0xF; - if(house < 0 || house > 16 || unit < 1 || unit > 16){ - //not waveman + if(house < 0 || house > 16 || unit < 1 || unit > 16) { + // not waveman return ""; } house = house + 'A'; //house from A to P - if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1){ + if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) { lastArctecCodeSwitchWasTurnOff = 0; return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose //one turnon/bell, but it's better than the alternative... } - if(method == 6){ + if(method == 6) { lastArctecCodeSwitchWasTurnOff = 1; } std::stringstream retString; retString << "class:command;protocol:waveman;model:codeswitch;house:" << char(house); - if(method == 0){ + if(method == 0) { retString << ";unit:" << unit << ";method:turnoff;"; - } - else if(method == 14){ + + } else if(method == 14) { retString << ";unit:" << unit << ";method:turnon;"; } else { diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index ca445e35..255138e7 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -171,7 +171,7 @@ std::string ProtocolX10::decodeData(ControllerMessage& dataMsg) { retString << "house:" << (char)('A' + intHouse); retString << ";unit:" << unit+1; retString << ";method:"; - if(method == 0){ + if(method == 0) { retString << "turnon;"; } else { retString << "turnoff;"; diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 4c88b100..7977399a 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -11,8 +11,7 @@ #include "service/Protocol.h" #include "service/ControllerMessage.h" -class ProtocolX10 : public Protocol -{ +class ProtocolX10 : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); diff --git a/telldus-core/service/ProtocolYidong.h b/telldus-core/service/ProtocolYidong.h index 7bbe6b68..c6b628c4 100644 --- a/telldus-core/service/ProtocolYidong.h +++ b/telldus-core/service/ProtocolYidong.h @@ -10,8 +10,7 @@ #include #include "service/ProtocolSartano.h" -class ProtocolYidong : public ProtocolSartano -{ +class ProtocolYidong : public ProtocolSartano { public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); }; diff --git a/telldus-core/service/Sensor.cpp b/telldus-core/service/Sensor.cpp index 17ae3ac2..65870b66 100644 --- a/telldus-core/service/Sensor.cpp +++ b/telldus-core/service/Sensor.cpp @@ -18,8 +18,7 @@ public: }; Sensor::Sensor(const std::wstring &protocol, const std::wstring &model, int id) - :Mutex() -{ + :Mutex() { d = new PrivateData; d->protocol = protocol; d->model = model; diff --git a/telldus-core/service/Sensor.h b/telldus-core/service/Sensor.h index f7eba022..3c6561e2 100644 --- a/telldus-core/service/Sensor.h +++ b/telldus-core/service/Sensor.h @@ -10,8 +10,7 @@ #include "common/Mutex.h" #include -class Sensor : public TelldusCore::Mutex -{ +class Sensor : public TelldusCore::Mutex { public: Sensor(const std::wstring &protocol, const std::wstring &model, int id); ~Sensor(); diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 1daef643..46090256 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -20,7 +20,7 @@ std::wstring Settings::getName(Node type, int intNodeId) const { /* * Set the name of the device */ -int Settings::setName(Node type, int intDeviceId, const std::wstring &strNewName){ +int Settings::setName(Node type, int intDeviceId, const std::wstring &strNewName) { TelldusCore::MutexLocker locker(&mutex); return setStringSetting(type, intDeviceId, L"name", strNewName, false); } @@ -36,7 +36,7 @@ std::wstring Settings::getProtocol(int intDeviceId) const { /* * Set the device vendor */ -int Settings::setProtocol(int intDeviceId, const std::wstring &strVendor){ +int Settings::setProtocol(int intDeviceId, const std::wstring &strVendor) { TelldusCore::MutexLocker locker(&mutex); return setStringSetting(Device, intDeviceId, L"protocol", strVendor, false); } @@ -52,7 +52,7 @@ std::wstring Settings::getModel(int intDeviceId) const { /* * Set the device model */ -int Settings::setModel(int intDeviceId, const std::wstring &strModel){ +int Settings::setModel(int intDeviceId, const std::wstring &strModel) { TelldusCore::MutexLocker locker(&mutex); return setStringSetting(Device, intDeviceId, L"model", strModel, false); } @@ -60,7 +60,7 @@ int Settings::setModel(int intDeviceId, const std::wstring &strModel){ /* * Set device argument */ -int Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue){ +int Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue) { TelldusCore::MutexLocker locker(&mutex); return setStringSetting(Device, intDeviceId, strName, strValue, true); } @@ -76,7 +76,7 @@ std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &s /* * Set preferred controller id */ -int Settings::setPreferredControllerId(int intDeviceId, int value){ +int Settings::setPreferredControllerId(int intDeviceId, int value) { TelldusCore::MutexLocker locker(&mutex); return setIntSetting(Device, intDeviceId, L"controller", value, false); } diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 01c5a66b..a24712d3 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -32,8 +32,7 @@ const char* VAR_CONFIG_FILE = VAR_CONFIG_PATH "/telldus-core.conf"; /* * Constructor */ -Settings::Settings(void) -{ +Settings::Settings(void) { TelldusCore::MutexLocker locker(&mutex); d = new PrivateData; readConfig(&d->cfg); @@ -43,8 +42,7 @@ Settings::Settings(void) /* * Destructor */ -Settings::~Settings(void) -{ +Settings::~Settings(void) { TelldusCore::MutexLocker locker(&mutex); if (d->cfg > 0) { cfg_free(d->cfg); @@ -100,7 +98,7 @@ int Settings::getNodeId(Node type, int intDeviceIndex) const { /* * Add a new node */ -int Settings::addNode(Node type){ +int Settings::addNode(Node type) { TelldusCore::MutexLocker locker(&mutex); int intNodeId = getNextNodeId(type); @@ -148,7 +146,7 @@ int Settings::getNextNodeId(Node type) const { /* * Remove a device */ -int Settings::removeNode(Node type, int intNodeId){ +int Settings::removeNode(Node type, int intNodeId) { TelldusCore::MutexLocker locker(&mutex); FILE *fp = fopen(CONFIG_FILE, "w"); if (!fp) { @@ -199,7 +197,7 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w cfg_setstr(cfg_device, "stateValue", TelldusCore::wideToString(strDeviceStateValue).c_str()); FILE *fp = fopen(VAR_CONFIG_FILE, "w"); - if(fp == 0){ + if(fp == 0) { return false; } cfg_print(d->var_cfg, fp); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index e456b74b..98574ea4 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -40,8 +40,7 @@ public: }; TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &td ) - :Controller(controllerId, event, updateEvent) -{ + :Controller(controllerId, event, updateEvent) { d = new PrivateData; d->open = false; d->vid = td.vid; @@ -140,10 +139,10 @@ void TellStick::processData( const std::string &data ) { } } -int TellStick::reset(){ +int TellStick::reset() { int success = ftdi_usb_reset( &d->ftHandle ); - if(success < 0){ - return TELLSTICK_ERROR_UNKNOWN; //-1 = FTDI reset failed, -2 = USB device unavailable + if(success < 0) { + return TELLSTICK_ERROR_UNKNOWN; // -1 = FTDI reset failed, -2 = USB device unavailable } return TELLSTICK_SUCCESS; } @@ -209,18 +208,18 @@ int TellStick::send( const std::string &strMessage ) { delete[] tempMessage; - if(!c){ + if(!c) { Log::debug("Broken pipe on send"); return TELLSTICK_ERROR_BROKEN_PIPE; } - if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){ - //these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly + if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))) { + // these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly return TELLSTICK_SUCCESS; } - if(d->ignoreControllerConfirmation){ - //allow TellStick to finish its air-sending + if(d->ignoreControllerConfirmation) { + // allow TellStick to finish its air-sending msleep(1000); return TELLSTICK_SUCCESS; } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 0d11fe9f..3ba28bf0 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -25,8 +25,7 @@ public: TelldusCore::EventRef stopEvent, controllerChangeEvent; }; -TelldusMain::TelldusMain(void) -{ +TelldusMain::TelldusMain(void) { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); d->controllerChangeEvent = d->eventHandler.addEvent(); @@ -121,8 +120,8 @@ void TelldusMain::start(void) { if (handlerEvent->isSignaled()) { handlerEvent->popSignal(); - for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ){ - if ((*it)->isDone()){ + for ( std::list::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ) { + if ((*it)->isDone()) { delete *it; it = clientCommunicationHandlerList.erase(it); @@ -143,6 +142,6 @@ void TelldusMain::start(void) { supervisor.stop(); } -void TelldusMain::stop(void){ +void TelldusMain::stop(void) { d->stopEvent->signal(); } diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index fde55c33..bbd18127 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -7,8 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_ #define TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_ -class TelldusMain -{ +class TelldusMain { public: TelldusMain(void); ~TelldusMain(void); diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index 838b0009..98288021 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -28,8 +28,7 @@ public: }; Timer::Timer(TelldusCore::EventRef event) - :TelldusCore::Thread(), d(new PrivateData) -{ + :TelldusCore::Thread(), d(new PrivateData) { d->event = event; #ifdef _WINDOWS d->cond = CreateEventW(NULL, false, false, NULL); From 75f21588e53683537e6a17a95749ae0f87ef4b4b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 28 Feb 2012 22:20:03 +0100 Subject: [PATCH 2006/2215] Should have a space between // and comment "whitespace/comments" --- .../client/CallbackMainDispatcher.cpp | 8 +-- telldus-core/client/Client.cpp | 20 +++--- telldus-core/client/telldus-core.cpp | 4 +- telldus-core/client/telldus-core.h | 14 ++--- telldus-core/common/EventHandler_unix.cpp | 4 +- telldus-core/common/Message.cpp | 12 ++-- telldus-core/common/Message.h | 6 +- telldus-core/common/Mutex.h | 2 +- telldus-core/common/Socket.h | 1 + telldus-core/common/Socket_unix.cpp | 2 +- telldus-core/common/Strings.cpp | 40 ++++++------ telldus-core/common/Strings.h | 2 +- .../service/ClientCommunicationHandler.cpp | 4 +- .../service/ConnectionListener_unix.cpp | 6 +- telldus-core/service/ControllerManager.cpp | 24 +++---- telldus-core/service/ControllerMessage.cpp | 2 +- telldus-core/service/Device.cpp | 14 ++--- telldus-core/service/DeviceManager.cpp | 42 ++++++------- telldus-core/service/EventUpdateManager.cpp | 4 +- telldus-core/service/EventUpdateManager.h | 2 +- telldus-core/service/Log.cpp | 4 +- telldus-core/service/Protocol.cpp | 4 +- telldus-core/service/ProtocolComen.cpp | 2 +- telldus-core/service/ProtocolEverflourish.cpp | 8 +-- telldus-core/service/ProtocolFuhaote.cpp | 4 +- telldus-core/service/ProtocolHasta.cpp | 4 +- telldus-core/service/ProtocolIkea.cpp | 24 +++---- telldus-core/service/ProtocolNexa.cpp | 62 +++++++++---------- telldus-core/service/ProtocolOregon.cpp | 2 +- telldus-core/service/ProtocolUpm.cpp | 12 ++-- telldus-core/service/ProtocolWaveman.cpp | 8 +-- telldus-core/service/ProtocolX10.cpp | 8 +-- telldus-core/service/SettingsConfuse.cpp | 36 +++++------ telldus-core/service/TellStick.cpp | 4 +- telldus-core/service/TellStick_libftdi.cpp | 30 ++++----- telldus-core/service/TelldusMain.cpp | 12 ++-- telldus-core/service/TelldusMain.h | 2 +- telldus-core/service/Timer.cpp | 2 +- telldus-core/service/main_unix.cpp | 8 +-- 39 files changed, 225 insertions(+), 224 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 9a349b05..22723674 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -33,7 +33,7 @@ CallbackMainDispatcher::CallbackMainDispatcher() d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); d->generalCallbackEvent = d->eventHandler.addEvent(); - d->janitor = d->eventHandler.addEvent(); //Used for cleanups + d->janitor = d->eventHandler.addEvent(); // Used for cleanups d->lastCallbackId = 0; } @@ -77,7 +77,7 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { } if (newEventList.size()) { CallbackList::iterator it = newEventList.begin(); - { //Lock and unlock to make sure no one else uses the object + { // Lock and unlock to make sure no one else uses the object TelldusCore::MutexLocker locker( &(*it)->mutex ); } delete (*it); @@ -109,7 +109,7 @@ void CallbackMainDispatcher::run() { } } if (d->janitor->isSignaled()) { - //Clear all of them if there is more than one + // Clear all of them if there is more than one while(d->janitor->isSignaled()) { d->janitor->popSignal(); } @@ -121,7 +121,7 @@ void CallbackMainDispatcher::run() { void CallbackMainDispatcher::cleanupCallbacks() { bool again = false; - //Device Event + // Device Event do { again = false; MutexLocker locker(&d->mutex); diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 370c3353..7237445e 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -96,7 +96,7 @@ void Client::run() { } } - std::wstring clientMessage = d->eventSocket.read(1000); //testing 5 second timeout + std::wstring clientMessage = d->eventSocket.read(1000); // testing 5 second timeout while(clientMessage != L"") { // a message arrived @@ -140,7 +140,7 @@ void Client::run() { d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); } else { - clientMessage = L""; //cleanup, if message contained garbage/unhandled data + clientMessage = L""; // cleanup, if message contained garbage/unhandled data } } } @@ -159,25 +159,25 @@ std::wstring Client::sendToService(const Message &msg) { } Socket s; s.connect(L"TelldusClient"); - if (!s.isConnected()) { //Connection failed + if (!s.isConnected()) { // Connection failed msleep(500); - continue; //retry + continue; // retry } s.write(msg.data()); - if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) + if (!s.isConnected()) { // Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) msleep(500); - continue; //retry + continue; // retry } readData = s.read(8000); // TODO changed to 10000 from 5000, how much does this do...? if(readData == L"") { msleep(500); - continue; //TODO can we be really sure it SHOULD be anything? - //TODO perhaps break here instead? + continue; // TODO can we be really sure it SHOULD be anything? + // TODO perhaps break here instead? } - if (!s.isConnected()) { //Connection failed sometime during operation... + if (!s.isConnected()) { // Connection failed sometime during operation... msleep(500); - continue; //retry + continue; // retry } break; } diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index b2e27ccd..989a8273 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -319,7 +319,7 @@ using namespace TelldusCore; * @since Version 2.0.0 **/ void WINAPI tdInit(void) { - Client::getInstance(); //Create the manager-object + Client::getInstance(); // Create the manager-object } /** @@ -1023,7 +1023,7 @@ char * WINAPI tdGetErrorString(int intErrorNo) { "Syntax error in the configuration file" }; std::string strReturn; - intErrorNo = abs(intErrorNo); //We don't use negative values here. + intErrorNo = abs(intErrorNo); // We don't use negative values here. if (intErrorNo >= numResponses) { strReturn = "Unknown error"; } else { diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index 7aa9ba2b..c50804ea 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -103,7 +103,7 @@ extern "C" { } #endif -//Device methods +// Device methods #define TELLSTICK_TURNON 1 #define TELLSTICK_TURNOFF 2 #define TELLSTICK_BELL 4 @@ -115,11 +115,11 @@ extern "C" { #define TELLSTICK_DOWN 256 #define TELLSTICK_STOP 512 -//Sensor value types +// Sensor value types #define TELLSTICK_TEMPERATURE 1 #define TELLSTICK_HUMIDITY 2 -//Error codes +// Error codes #define TELLSTICK_SUCCESS 0 #define TELLSTICK_ERROR_NOT_FOUND -1 #define TELLSTICK_ERROR_PERMISSION_DENIED -2 @@ -134,23 +134,23 @@ extern "C" { #define TELLSTICK_ERROR_CONFIG_SYNTAX -11 #define TELLSTICK_ERROR_UNKNOWN -99 -//Device typedef +// Device typedef #define TELLSTICK_TYPE_DEVICE 1 #define TELLSTICK_TYPE_GROUP 2 #define TELLSTICK_TYPE_SCENE 3 -//Controller typedef +// Controller typedef #define TELLSTICK_CONTROLLER_TELLSTICK 1 #define TELLSTICK_CONTROLLER_TELLSTICK_DUO 2 #define TELLSTICK_CONTROLLER_TELLSTICK_NET 3 -//Device changes +// Device changes #define TELLSTICK_DEVICE_ADDED 1 #define TELLSTICK_DEVICE_CHANGED 2 #define TELLSTICK_DEVICE_REMOVED 3 #define TELLSTICK_DEVICE_STATE_CHANGED 4 -//Change types +// Change types #define TELLSTICK_CHANGE_NAME 1 #define TELLSTICK_CHANGE_PROTOCOL 2 #define TELLSTICK_CHANGE_MODEL 3 diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 44aa3899..2297594d 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -34,7 +34,7 @@ EventHandler::~EventHandler(void) { std::list::const_iterator it = d->eventList.begin(); for(; it != d->eventList.end(); ++it) { - //We clear the handler if someone else still has a reference to the event + // We clear the handler if someone else still has a reference to the event (*it)->clearHandler(); } @@ -62,7 +62,7 @@ bool EventHandler::listIsSignalled() { void EventHandler::signal(Event *event) { pthread_mutex_lock(&d->mutex); - //event->setSignaled(); + // event->setSignaled(); pthread_cond_signal(&d->event); pthread_mutex_unlock(&d->mutex); } diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index efbb87ca..8099c653 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -27,18 +27,18 @@ Message::~Message(void) { } void Message::addArgument(const std::wstring &value) { - //std::wstringstream st; - //st << (int)value.size(); - this->append(TelldusCore::intToWstring(value.size())); //st.str()); + // std::wstringstream st; + // st << (int)value.size(); + this->append(TelldusCore::intToWstring(value.size())); // st.str()); this->append(L":"); this->append(value); } void Message::addArgument(int value) { - //std::wstringstream st; - //st << (int)value; + // std::wstringstream st; + // st << (int)value; this->append(L"i"); - this->append(TelldusCore::intToWstring(value)); // st.str()); + this->append(TelldusCore::intToWstring(value)); // st.str()); this->append(L"s"); } diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index 74ca5538..e1ffc656 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -17,9 +17,9 @@ namespace TelldusCore { ~Message(void); void addArgument(const std::wstring &); - //void addSpecialArgument(const std::wstring &); - //void addSpecialArgument(int); - //void addSpecialArgument(const char *); + // void addSpecialArgument(const std::wstring &); + // void addSpecialArgument(int); + // void addSpecialArgument(const char *); void addArgument(int); void addArgument(const char *); diff --git a/telldus-core/common/Mutex.h b/telldus-core/common/Mutex.h index 41086576..082ee173 100644 --- a/telldus-core/common/Mutex.h +++ b/telldus-core/common/Mutex.h @@ -22,7 +22,7 @@ namespace TelldusCore { virtual void unlock(); private: - Mutex(const Mutex&); //Disable copy + Mutex(const Mutex&); // Disable copy Mutex& operator = (const Mutex&); class PrivateData; PrivateData *d; diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index eed6a0b7..b8ee4aef 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -35,4 +35,5 @@ namespace TelldusCore { PrivateData *d; }; } + #endif // TELLDUS_CORE_COMMON_SOCKET_H_ diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 89172a5a..0573a494 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -121,7 +121,7 @@ std::wstring Socket::read(int timeout) { void Socket::stopReadWait() { TelldusCore::MutexLocker locker(&d->mutex); d->connected = false; - //TODO somehow signal the socket here? + // TODO somehow signal the socket here? } void Socket::write(const std::wstring &msg) { diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index d7cef23c..b1457849 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -26,7 +26,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { #ifdef _WINDOWS - //Determine size + // Determine size int size = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0); if (size == 0) { return L""; @@ -44,11 +44,11 @@ std::wstring TelldusCore::charToWstring(const char *value) { size_t utf8Length = strlen(value); size_t outbytesLeft = utf8Length*sizeof(wchar_t); - //Copy the instring + // Copy the instring char *inString = new char[utf8Length+1]; strcpy(inString, value); - //Create buffer for output + // Create buffer for output char *outString = (char*)new wchar_t[utf8Length+1]; memset(outString, 0, sizeof(wchar_t)*(utf8Length+1)); @@ -65,7 +65,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { std::wstring retval( (wchar_t *)outString ); - //Cleanup + // Cleanup delete[] inString; delete[] outString; @@ -99,17 +99,17 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { std::wstring TelldusCore::intToWstring(int value) { #ifdef _WINDOWS - //no stream used -//TODO! Make effective and safe... - wchar_t numstr[21]; // enough to hold all numbers up to 64-bits + // no stream used + // TODO! Make effective and safe... + wchar_t numstr[21]; // enough to hold all numbers up to 64-bits _itow_s(value, numstr, sizeof(numstr), 10); std::wstring newstring(numstr); return newstring; - //return TelldusCore::charToWstring(stdstring.c_str()); - //std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); - //std::wstring temp(stdstring.length(), L' '); - //std::copy(stdstring.begin(), stdstring.end(), temp.begin()); - //return temp; + // return TelldusCore::charToWstring(stdstring.c_str()); + // std::wstring temp = TelldusCore::charToWstring(stdstring.c_str()); + // std::wstring temp(stdstring.length(), L' '); + // std::copy(stdstring.begin(), stdstring.end(), temp.begin()); + // return temp; #else std::wstringstream st; st << value; @@ -118,9 +118,9 @@ std::wstring TelldusCore::intToWstring(int value) { } std::string TelldusCore::intToString(int value) { -//Not sure if this is neecssary (for ordinary stringstream that is) + // Not sure if this is neecssary (for ordinary stringstream that is) #ifdef _WINDOWS - char numstr[21]; // enough to hold all numbers up to 64-bits + char numstr[21]; // enough to hold all numbers up to 64-bits _itoa_s(value, numstr, sizeof(numstr), 10); std::string stdstring(numstr); return stdstring; @@ -170,7 +170,7 @@ int TelldusCore::wideToInteger(const std::wstring &input) { std::string TelldusCore::wideToString(const std::wstring &input) { #ifdef _WINDOWS - //Determine size + // Determine size int size = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, NULL, 0, NULL, NULL); if (size == 0) { return ""; @@ -186,13 +186,13 @@ std::string TelldusCore::wideToString(const std::wstring &input) { #else size_t wideSize = sizeof(wchar_t)*input.length(); - size_t outbytesLeft = wideSize+sizeof(char); //We cannot know how many wide character there is yet + size_t outbytesLeft = wideSize+sizeof(char); // We cannot know how many wide character there is yet - //Copy the instring + // Copy the instring char *inString = (char*)new wchar_t[input.length()+1]; memcpy(inString, input.c_str(), wideSize+sizeof(wchar_t)); - //Create buffer for output + // Create buffer for output char *outString = new char[outbytesLeft]; memset(outString, 0, sizeof(char)*(outbytesLeft)); @@ -209,7 +209,7 @@ std::string TelldusCore::wideToString(const std::wstring &input) { std::string retval(outString); - //Cleanup + // Cleanup delete[] inString; delete[] outString; @@ -226,7 +226,7 @@ std::string TelldusCore::formatf(const char *format, ...) { } std::string TelldusCore::sformatf(const char *format, va_list ap) { - //This code is based on code from the Linux man-pages project (man vsprintf) + // This code is based on code from the Linux man-pages project (man vsprintf) int n; int size = 100; /* Guess we need no more than 100 bytes. */ char *p, *np; diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index c937fce9..6a4c5eaa 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -25,7 +25,7 @@ namespace TelldusCore { bool comparei(std::wstring stringA, std::wstring stringB); std::wstring intToWstring(int value); - //std::wstring intToWStringSafe(int value); + // std::wstring intToWStringSafe(int value); std::string intToString(int value); uint64_t hexTo64l(const std::string data); std::string wideToString(const std::wstring &input); diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index b8355374..9d982f52 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -61,7 +61,7 @@ void ClientCommunicationHandler::run() { msg.append(L"\n"); d->clientSocket->write(msg); - //We are done, signal for removal + // We are done, signal for removal d->done = true; d->event->signal(); } @@ -74,7 +74,7 @@ bool ClientCommunicationHandler::isDone() { void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn) { (*intReturn) = 0; (*wstringReturn) = L""; - std::wstring msg(clientMessage); //Copy + std::wstring msg(clientMessage); // Copy std::wstring function(TelldusCore::Message::takeString(&msg)); if (function == L"tdTurnOn") { diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 354d8673..0c9600dd 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -45,7 +45,7 @@ ConnectionListener::~ConnectionListener(void) { void ConnectionListener::run() { struct timeval tv = { 0, 0 }; - //Timeout for select + // Timeout for select SOCKET_T serverSocket; struct sockaddr_un name; @@ -62,7 +62,7 @@ void ConnectionListener::run() { bind(serverSocket, (struct sockaddr *)&name, size); listen(serverSocket, 5); - //Change permissions to allow everyone + // Change permissions to allow everyone chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); len = sizeof(struct sockaddr_un); @@ -80,7 +80,7 @@ void ConnectionListener::run() { } else if (response < 0 ) { continue; } - //Make sure it is a new connection + // Make sure it is a new connection if (!FD_ISSET(serverSocket, &infds)) { continue; } diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 678caca4..d4e70a1d 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -55,11 +55,11 @@ ControllerManager::~ControllerManager() { } void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) { - if (vid == 0x0 && pid == 0x0) { //All + if (vid == 0x0 && pid == 0x0) { // All if (inserted) { loadControllers(); } else { - //Disconnect all + // Disconnect all TelldusCore::MutexLocker locker(&d->mutex); while(d->controllers.size()) { ControllerMap::iterator it = d->controllers.begin(); @@ -79,7 +79,7 @@ void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::str if (inserted) { loadControllers(); } else { - //Autodetect which has been disconnected + // Autodetect which has been disconnected TelldusCore::MutexLocker locker(&d->mutex); for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { if (!it->second.controller) { @@ -117,7 +117,7 @@ Controller *ControllerManager::getBestControllerById(int id) { if (it != d->controllers.end() && it->second.controller) { return it->second.controller; } - //Find first available controller + // Find first available controller for(it = d->controllers.begin(); it != d->controllers.end(); ++it) { if (it->second.controller) { return it->second.controller; @@ -134,8 +134,8 @@ void ControllerManager::loadControllers() { std::list::iterator it = list.begin(); for(; it != list.end(); ++it) { - //Most backend only report non-opened devices. - //If they don't make sure we don't open them twice + // Most backend only report non-opened devices. + // If they don't make sure we don't open them twice bool found = false; ControllerMap::const_iterator cit = d->controllers.begin(); for(; cit != d->controllers.end(); ++cit) { @@ -160,7 +160,7 @@ void ControllerManager::loadControllers() { type = TELLSTICK_CONTROLLER_TELLSTICK_DUO; } int controllerId = 0; - //See if the controller matches one of the loaded, non available controllers + // See if the controller matches one of the loaded, non available controllers std::wstring serial = TelldusCore::charToWstring((*it).serial.c_str()); for(cit = d->controllers.begin(); cit != d->controllers.end(); ++cit) { if (cit->second.type == type && cit->second.serial.compare(serial) == 0) { @@ -182,7 +182,7 @@ void ControllerManager::loadControllers() { d->settings.setControllerSerial(controllerId, d->controllers[controllerId].serial); } - //int controllerId = d->lastControllerId+1; + // int controllerId = d->lastControllerId+1; TellStick *controller = new TellStick(controllerId, d->event, d->updateEvent, *it); if (!controller->isOpen()) { delete controller; @@ -251,10 +251,10 @@ void ControllerManager::queryControllerStatus() { int ControllerManager::resetController(Controller *controller) { TellStick *tellstick = reinterpret_cast(controller); if (!tellstick) { - return true; //not tellstick, nothing to reset at the moment, just return true + return true; // not tellstick, nothing to reset at the moment, just return true } int success = tellstick->reset(); - deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); //remove from list and delete + deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); // remove from list and delete return success; } @@ -304,7 +304,7 @@ int ControllerManager::removeController(int id) { return TELLSTICK_ERROR_NOT_FOUND; } if (it->second.controller) { - //Still connected + // Still connected return TELLSTICK_ERROR_PERMISSION_DENIED; } @@ -331,7 +331,7 @@ int ControllerManager::setControllerValue(int id, const std::wstring &name, cons d->settings.setName(Settings::Controller, id, value); signalControllerEvent(id, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME, value); } else { - return TELLSTICK_ERROR_SYNTAX; //TODO: Is this the best error? + return TELLSTICK_ERROR_SYNTAX; // TODO: Is this the best error? } return TELLSTICK_SUCCESS; } diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index 4cc39044..d749d77b 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -22,7 +22,7 @@ public: ControllerMessage::ControllerMessage(const std::string &message) { d = new PrivateData; - //Process our message into bits + // Process our message into bits size_t prevPos = 0; size_t pos = message.find(";"); while(pos != std::string::npos) { diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 4f71fe1b..7bbbbc6b 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -43,7 +43,7 @@ int Device::getLastSentCommand(int methodsSupported) { int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported); if (lastSentCommand == TELLSTICK_BELL) { - //Bell is not a state + // Bell is not a state lastSentCommand = TELLSTICK_TURNOFF; } if (lastSentCommand == 0) { @@ -146,13 +146,13 @@ int Device::getType() { int Device::doAction(int action, unsigned char data, Controller *controller) { Protocol *p = this->retrieveProtocol(); if (!p) { - //Syntax error in configuration, no such protocol + // Syntax error in configuration, no such protocol return TELLSTICK_ERROR_CONFIG_SYNTAX; } - //Try to determine if we need to call another method due to masking + // Try to determine if we need to call another method due to masking int methods = p->methods(); if ((action & methods) == 0) { - //Loop all methods an see if any method masks to this one + // Loop all methods an see if any method masks to this one for(int i = 1; i <= methods; i<<=1) { if ((i & methods) == 0) { continue; @@ -171,7 +171,7 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } if (code[0] != 'S' && code[0] != 'T' && code[0] != 'P' && code[0] != 'R') { - //Try autodetect sendtype + // Try autodetect sendtype TellStick *tellstick = reinterpret_cast(controller); if (!tellstick) { return TELLSTICK_ERROR_UNKNOWN; @@ -181,7 +181,7 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { maxlength = 512; } if (code.length() <= maxlength) { - //S is enough + // S is enough code.insert(0, 1, 'S'); code.append(1, '+'); } else { @@ -227,7 +227,7 @@ int Device::maskUnsupportedMethods(int methods, int supportedMethods) { methods |= TELLSTICK_TURNON; } - //Cut of the rest of the unsupported methods we don't have a fallback for + // Cut of the rest of the unsupported methods we don't have a fallback for return methods & supportedMethods; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index a09bd985..e4b4a218 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -41,11 +41,11 @@ DeviceManager::~DeviceManager(void) { { TelldusCore::MutexLocker deviceListLocker(&d->lock); for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) { - {TelldusCore::MutexLocker deviceLocker(it->second);} //aquire lock, and release it, just to see that the device it's not in use anywhere + {TelldusCore::MutexLocker deviceLocker(it->second);} // aquire lock, and release it, just to see that the device it's not in use anywhere delete(it->second); } for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { - {TelldusCore::MutexLocker sensorLocker(*it);} //aquire lock, and release it, just to see that the device it's not in use anywhere + {TelldusCore::MutexLocker sensorLocker(*it);} // aquire lock, and release it, just to see that the device it's not in use anywhere delete(*it); } } @@ -133,7 +133,7 @@ int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDevice std::wstring protocol; { - //devices locked + // devices locked TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -379,10 +379,10 @@ void DeviceManager::disconnectTellStickController(int vid, int pid, const std::s int DeviceManager::doAction(int deviceId, int action, unsigned char data) { Device *device = 0; - //On the stack and will be released if we have a device lock. + // On the stack and will be released if we have a device lock. std::auto_ptr deviceLocker(0); { - //devicelist locked + // devicelist locked TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -390,12 +390,12 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data) { } DeviceMap::iterator it = d->devices.find(deviceId); if (it == d->devices.end()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; // not found } - //device locked + // device locked deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); device = it->second; - } //devicelist unlocked + } // devicelist unlocked int retval = TELLSTICK_ERROR_UNKNOWN; @@ -407,8 +407,8 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data) { delete duplicateDeviceIds; { - //reaquire device lock, make sure it still exists - //devicelist locked + // reaquire device lock, make sure it still exists + // devicelist locked TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { @@ -416,18 +416,18 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data) { } DeviceMap::iterator it = d->devices.find(deviceId); if (it == d->devices.end()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; //not found + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; // not found } - //device locked + // device locked deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); device = it->second; - } //devicelist unlocked + } // devicelist unlocked } else { Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); if(!controller) { Log::warning("Trying to execute action, but no controller found. Rescanning USB ports"); - //no controller found, scan for one, and retry once + // no controller found, scan for one, and retry once d->controllerManager->loadControllers(); controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); } @@ -446,7 +446,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data) { Log::error("No contoller (TellStick) found, even after reset. Giving up."); return TELLSTICK_ERROR_NOT_FOUND; } - retval = device->doAction(action, data, controller); //retry one more time + retval = device->doAction(action, data, controller); // retry one more time } } else { Log::error("No contoller (TellStick) found after one retry. Giving up."); @@ -454,7 +454,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data) { } } if(retval == TELLSTICK_SUCCESS && device->getType() != TELLSTICK_TYPE_SCENE && device->getMethods() & action) { - //if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state + // if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state std::wstring datastring = TelldusCore::charUnsignedToWstring(data); if (this->triggerDeviceStateChange(deviceId, action, datastring)) { device->setLastSentCommand(action, datastring); @@ -563,7 +563,7 @@ int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId) { int DeviceManager::removeDevice(int deviceId) { Device *device = 0; { - int ret = d->set.removeNode(Settings::Device, deviceId); //remove from register/settings + int ret = d->set.removeNode(Settings::Device, deviceId); // remove from register/settings if (ret != TELLSTICK_SUCCESS) { return ret; } @@ -575,13 +575,13 @@ int DeviceManager::removeDevice(int deviceId) { DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { device = it->second; - d->devices.erase(it); //remove from list, keep reference + d->devices.erase(it); // remove from list, keep reference } else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } - {TelldusCore::MutexLocker lock(device);} //waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else + {TelldusCore::MutexLocker lock(device);} // waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else delete device; return TELLSTICK_SUCCESS; @@ -638,7 +638,7 @@ std::wstring DeviceManager::getSensorValue(const std::wstring &protocol, const s void DeviceManager::handleControllerMessage(const ControllerEventData &eventData) { - //Trigger raw-event + // Trigger raw-event EventUpdateData *eventUpdateData = new EventUpdateData(); eventUpdateData->messageType = L"TDRawDeviceEvent"; eventUpdateData->controllerId = eventData.controllerId; @@ -749,7 +749,7 @@ int DeviceManager::sendRawCommand(const std::wstring &command, int reserved) { if(!controller) { return TELLSTICK_ERROR_NOT_FOUND; } - retval = controller->send(TelldusCore::wideToString(command)); //retry one more time + retval = controller->send(TelldusCore::wideToString(command)); // retry one more time } return retval; } else { diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index a5056d78..5ac35c06 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -85,7 +85,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { msg.addArgument("TDDeviceEvent"); msg.addArgument(data->deviceId); msg.addArgument(data->eventState); - msg.addArgument(data->eventValue); //string + msg.addArgument(data->eventValue); // string } else if(data->messageType == L"TDDeviceChangeEvent") { msg.addArgument("TDDeviceChangeEvent"); @@ -95,7 +95,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { } else if(data->messageType == L"TDRawDeviceEvent") { msg.addArgument("TDRawDeviceEvent"); - msg.addArgument(data->eventValue); //string + msg.addArgument(data->eventValue); // string msg.addArgument(data->controllerId); } else if(data->messageType == L"TDSensorEvent") { diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index d45b4e02..0757a176 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -20,7 +20,7 @@ public: int eventState; std::wstring eventValue; - //Sensor event + // Sensor event std::wstring protocol; std::wstring model; int sensorId; diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index b4474c3c..91ad5b95 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -38,7 +38,7 @@ Log::Log() #elif defined(_MACOSX) d->logOutput = Log::StdOut; #elif defined(_WINDOWS) - //Add ourselves to the registy + // Add ourselves to the registy HKEY hRegKey = NULL; DWORD dwError = 0; TCHAR filePath[MAX_PATH]; @@ -120,7 +120,7 @@ void Log::setDebug() { void Log::setLogOutput(LogOutput logOutput) { #ifdef _MACOSX - //Always stdout + // Always stdout return; #endif Log *log = Log::instance(); diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 5bd9ff1a..1b49442c 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -47,7 +47,7 @@ Protocol::~Protocol(void) { std::wstring Protocol::model() const { std::wstring strModel = d->model; - //Strip anything after : if it is found + // Strip anything after : if it is found size_t pos = strModel.find(L":"); if (pos != std::wstring::npos) { strModel = strModel.substr(0, pos); @@ -176,7 +176,7 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"ikea")) { parameters.push_back("system"); parameters.push_back("units"); - //parameters.push_back("fade"); + // parameters.push_back("fade"); } else if (TelldusCore::comparei(protocolName, L"risingsun")) { parameters.push_back("house"); diff --git a/telldus-core/service/ProtocolComen.cpp b/telldus-core/service/ProtocolComen.cpp index f160a1cc..2652fde4 100644 --- a/telldus-core/service/ProtocolComen.cpp +++ b/telldus-core/service/ProtocolComen.cpp @@ -13,7 +13,7 @@ int ProtocolComen::methods() const { std::string ProtocolComen::getStringForMethod(int method, unsigned char level, Controller *) { int intHouse = getIntParameter(L"house", 1, 33554431); - intHouse <<= 1; //They seem to only accept even codes? + intHouse <<= 1; // They seem to only accept even codes? int intCode = getIntParameter(L"unit", 1, 16)-1; return getStringSelflearningForCode(intHouse, intCode, method, level); } diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 6ba569c5..913b37a8 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -30,8 +30,8 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, } const char ssss = 85; - const char sssl = 84; // 0 - const char slss = 69; // 1 + const char sssl = 84; // 0 + const char slss = 69; // 1 const char bits[2] = {sssl,slss}; int i, check; @@ -108,7 +108,7 @@ std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) { unit = allData & 0x300; unit >>= 8; - unit++; //unit from 1 to 4 + unit++; // unit from 1 to 4 method = allData & 0xF; @@ -129,7 +129,7 @@ std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) { retString << "learn;"; } else { - //not everflourish + // not everflourish return ""; } diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index bbbd573c..37704869 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -25,7 +25,7 @@ std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Contr return ""; } - //House code + // House code for(size_t i = 0; i < 5; ++i) { if (strCode[i] == '0') { strReturn.append(B0); @@ -33,7 +33,7 @@ std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Contr strReturn.append(B1); } } - //Unit code + // Unit code for(size_t i = 5; i < 10; ++i) { if (strCode[i] == '0') { strReturn.append(B0); diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index 3f5b74ef..963e98da 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -50,8 +50,8 @@ std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Control strReturn.append(convertByte(0x0)); strReturn.append(convertByte(0x0)); - //Remove the last pulse - strReturn.erase(strReturn.end()-1,strReturn.end()); + // Remove the last pulse + strReturn.erase(strReturn.end()-1, strReturn.end()); return strReturn; } diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 4bf43d50..6985b0e7 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -33,7 +33,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co } std::string strUnits(TelldusCore::wideToString(wstrUnits)); - int intUnits = 0; //Start without any units + int intUnits = 0; // Start without any units char *tempUnits = new char[strUnits.size()+1]; #ifdef _WINDOWS @@ -53,7 +53,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co delete[] tempUnits; - std::string strReturn = "STTTTTTª"; //Startcode, always like this; + std::string strReturn = "STTTTTTª"; // Startcode, always like this; std::string strChannels = ""; int intCode = (intSystem << 10) | intUnits; @@ -70,14 +70,14 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co strChannels.append("ª"); } } - strReturn.append(strChannels); //System + Units + strReturn.append(strChannels); // System + Units - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); // 1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); // 2nd checksum int intLevel = 0; if (level <= 12) { - intLevel = 10; // Level 10 is actually off + intLevel = 10; // Level 10 is actually off } else if (level <= 37) { intLevel = 1; } else if (level <= 62) { @@ -97,17 +97,17 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co } else if (level <= 237) { intLevel = 9; } else { - intLevel = 0; // Level 0 is actually full on + intLevel = 0; // Level 0 is actually full on } int intFade = 0; if (intFadeStyle == 1) { - intFade = 11 << 4; //Smooth + intFade = 11 << 4; // Smooth } else { - intFade = 1 << 4; //Instant + intFade = 1 << 4; // Instant } - intCode = intLevel | intFade; //Concat level and fade + intCode = intLevel | intFade; // Concat level and fade checksum1 = 0; checksum2 = 0; @@ -123,8 +123,8 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co } } - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); //1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); //2nd checksum + strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); // 1st checksum + strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); // 2nd checksum strReturn.append("+"); diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 94a3e273..feac5df4 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -10,7 +10,7 @@ #include "service/TellStick.h" #include "common/Strings.h" -int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; //TODO, always removing first turnon now, make more flexible (waveman too) +int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; // TODO, always removing first turnon now, make more flexible (waveman too) int ProtocolNexa::methods() const { if (TelldusCore::comparei(model(), L"codeswitch")) { @@ -35,27 +35,27 @@ std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Con return getStringBell(); } if ((method == TELLSTICK_TURNON) && TelldusCore::comparei(model(), L"selflearning-dimmer")) { - //Workaround for not letting a dimmer do into "dimming mode" + // Workaround for not letting a dimmer do into "dimming mode" return getStringSelflearning(TELLSTICK_DIM, 255); } if (method == TELLSTICK_LEARN) { std::string str = getStringSelflearning(TELLSTICK_TURNON, data); - //Check to see if we are an old TellStick (fw <= 2, batch <= 8) + // Check to see if we are an old TellStick (fw <= 2, batch <= 8) TellStick *ts = reinterpret_cast(controller); if (!ts) { return str; } if (ts->pid() == 0x0c30 && ts->firmwareVersion() <= 2) { - //Workaround for the bug in early firmwares - //The TellStick have a fixed pause (max) between two packets. - //It is only correct between the first and second packet. - //It seems faster to send two packes at a time and some - //receivers seems picky about this when learning. - //We also return the last packet so Device::doAction() doesn't - //report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED + // Workaround for the bug in early firmwares + // The TellStick have a fixed pause (max) between two packets. + // It is only correct between the first and second packet. + // It seems faster to send two packes at a time and some + // receivers seems picky about this when learning. + // We also return the last packet so Device::doAction() doesn't + // report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED - str.insert(0, 1, 2); //Repeat two times + str.insert(0, 1, 2); // Repeat two times str.insert(0, 1, 'R'); for (int i = 0; i < 5; ++i) { controller->send(str); @@ -90,8 +90,8 @@ std::string ProtocolNexa::getStringBell() { std::wstring house = getStringParameter(L"house", L"A"); int intHouse = house[0] - L'A'; strReturn.append(getCodeSwitchTuple(intHouse)); - strReturn.append("$kk$$kk$$kk$$k$k"); //Unit 7 - strReturn.append("$kk$$kk$$kk$$kk$$k+"); //Bell + strReturn.append("$kk$$kk$$kk$$k$k"); // Unit 7 + strReturn.append("$kk$$kk$$kk$$kk$$k+"); // Bell return strReturn; } @@ -102,19 +102,19 @@ std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) } std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode, int method, unsigned char level) { - const unsigned char START[] = {'T',127,255,24,1,0}; -// const char START[] = {'T',130,255,26,24,0}; + const unsigned char START[] = {'T', 127, 255, 24, 1, 0}; + // const char START[] = {'T',130,255,26,24,0}; std::string strMessage(reinterpret_cast(START)); - strMessage.append(1,(method == TELLSTICK_DIM ? 147 : 132)); //Number of pulses + strMessage.append(1, (method == TELLSTICK_DIM ? 147 : 132)); // Number of pulses std::string m; for (int i = 25; i >= 0; --i) { m.append( intHouse & 1 << i ? "10" : "01" ); } - m.append("01"); //Group + m.append("01"); // Group - //On/off + // On/off if (method == TELLSTICK_DIM) { m.append("00"); } else if (method == TELLSTICK_TURNOFF) { @@ -136,18 +136,18 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode } } - //The number of data is odd. - //Add this to make it even, otherwise the following loop will not work + // The number of data is odd. + // Add this to make it even, otherwise the following loop will not work m.append("0"); - unsigned char code = 9; //b1001, startcode + unsigned char code = 9; // b1001, startcode for (unsigned int i = 0; i < m.length(); ++i) { code <<= 4; if (m[i] == '1') { - code |= 8; //b1000 + code |= 8; // b1000 } else { - code |= 10; //b1010 -// code |= 11; //b1011 + code |= 10; // b1010 + // code |= 11; //b1011 } if (i % 2 == 0) { strMessage.append(1,code); @@ -210,7 +210,7 @@ std::string ProtocolNexa::decodeDataSelfLearning(long allData) { retString << "turnoff;"; } else { - //not arctech selflearning + // not arctech selflearning return ""; } @@ -236,12 +236,12 @@ std::string ProtocolNexa::decodeDataCodeSwitch(long allData) { return ""; } - house = house + 'A'; //house from A to P + house = house + 'A'; // house from A to P if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) { lastArctecCodeSwitchWasTurnOff = 0; - return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - //one turnon/bell, but it's better than the alternative... + return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose + // one turnon/bell, but it's better than the alternative... } if(method == 6) { @@ -261,7 +261,7 @@ std::string ProtocolNexa::decodeDataCodeSwitch(long allData) { retString << ";method:bell;"; } else { - //not arctech codeswitch + // not arctech codeswitch return ""; } @@ -271,9 +271,9 @@ std::string ProtocolNexa::decodeDataCodeSwitch(long allData) { std::string ProtocolNexa::getCodeSwitchTuple(int intCode) { std::string strReturn = ""; for( int i = 0; i < 4; ++i ) { - if (intCode & 1) { //Convert 1 + if (intCode & 1) { // Convert 1 strReturn.append("$kk$"); - } else { //Convert 0 + } else { // Convert 0 strReturn.append("$k$k"); } intCode >>= 1; diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index fe2aca11..737ad91f 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -102,7 +102,7 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA; - //TODO: Find out how checksum2 works + // TODO: Find out how checksum2 works if (checksum != checksum1) { return ""; } diff --git a/telldus-core/service/ProtocolUpm.cpp b/telldus-core/service/ProtocolUpm.cpp index 41dee66f..4e70b797 100644 --- a/telldus-core/service/ProtocolUpm.cpp +++ b/telldus-core/service/ProtocolUpm.cpp @@ -14,11 +14,11 @@ int ProtocolUpm::methods() const { std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) { const char S = ';'; const char L = '~'; - const char START[] = {S,0}; - const char B1[] = {L,S,0}; - const char B0[] = {S,L,0}; - //const char BON[] = {S,L,L,S,0}; - //const char BOFF[] = {S,L,S,L,0}; + const char START[] = {S, 0}; + const char B1[] = {L, S, 0}; + const char B0[] = {S, L, 0}; + // const char BON[] = {S,L,L,S,0}; + // const char BOFF[] = {S,L,S,L,0}; int intUnit = this->getIntParameter(L"unit", 1, 4)-1; std::string strReturn; @@ -32,7 +32,7 @@ std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controlle } code >>= 1; } - strReturn.insert(0, START); //Startcode, first + strReturn.insert(0, START); // Startcode, first code = 0; if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) { diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index abdd6565..00ced94a 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -44,12 +44,12 @@ std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) { return ""; } - house = house + 'A'; //house from A to P + house = house + 'A'; // house from A to P if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) { lastArctecCodeSwitchWasTurnOff = 0; - return ""; //probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose - //one turnon/bell, but it's better than the alternative... + return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose + // one turnon/bell, but it's better than the alternative... } if(method == 6) { @@ -66,7 +66,7 @@ std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) { retString << ";unit:" << unit << ";method:turnon;"; } else { - //not waveman + // not waveman return ""; } diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index 255138e7..51234065 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -32,7 +32,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont } else if (intHouse > 15) { intHouse = 15; } - //Translate it + // Translate it intHouse = HOUSES[intHouse]; int intCode = getIntParameter(L"unit", 1, 16)-1; @@ -68,7 +68,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont strReturn.append( B0 ); strComplement.append( B1 ); - if (intCode >> 2 & 1) { //Bit 2 of intCode + if (intCode >> 2 & 1) { // Bit 2 of intCode strReturn.append(B1); strComplement.append(B0); } else { @@ -86,7 +86,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont return ""; } - if (intCode & 1) { //Bit 0 of intCode + if (intCode & 1) { // Bit 0 of intCode strReturn.append(B1); strComplement.append(B0); } else { @@ -94,7 +94,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont strComplement.append(B1); } - if (intCode >> 1 & 1) { //Bit 1 of intCode + if (intCode >> 1 & 1) { // Bit 1 of intCode strReturn.append(B1); strComplement.append(B0); } else { diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index a24712d3..db3f9325 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -81,7 +81,7 @@ int Settings::getNumberOfNodes(Node node) const { } int Settings::getNodeId(Node type, int intDeviceIndex) const { - if (intDeviceIndex >= getNumberOfNodes(type)) { //Out of bounds + if (intDeviceIndex >= getNumberOfNodes(type)) { // Out of bounds return -1; } TelldusCore::MutexLocker locker(&mutex); @@ -106,15 +106,15 @@ int Settings::addNode(Node type) { if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } - cfg_print(d->cfg, fp); //Print the config-file + cfg_print(d->cfg, fp); // Print the config-file if (type == Device) { - fprintf(fp, "device {\n id=%d\n}\n", intNodeId); //Print the new device + fprintf(fp, "device {\n id=%d\n}\n", intNodeId); // Print the new device } else if (type == Controller) { - fprintf(fp, "controller {\n id=%d\n}\n", intNodeId); //Print the new controller + fprintf(fp, "controller {\n id=%d\n}\n", intNodeId); // Print the new controller } fclose(fp); - //Re-read config-file + // Re-read config-file cfg_free(d->cfg); readConfig(&d->cfg); return intNodeId; @@ -124,7 +124,7 @@ int Settings::addNode(Node type) { * Get next available node id */ int Settings::getNextNodeId(Node type) const { - //Private, no locks needed + // Private, no locks needed int intNodeId = 0; cfg_t *cfg_node; std::string strType; @@ -166,7 +166,7 @@ int Settings::removeNode(Node type, int intNodeId) { cfg_t *cfg_node; for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) { cfg_node = cfg_getnsec(d->cfg, strType.c_str(), i); - if (cfg_getint(cfg_node, "id") != intNodeId) { //This isn't the one to skip + if (cfg_getint(cfg_node, "id") != intNodeId) { // This isn't the one to skip fprintf(fp, "%s {\n", strType.c_str()); cfg_print_indent(cfg_node, fp, 1); fprintf(fp, "}\n"); @@ -176,7 +176,7 @@ int Settings::removeNode(Node type, int intNodeId) { } fclose(fp); - //Re-read config-file + // Re-read config-file cfg_free(d->cfg); readConfig(&d->cfg); @@ -205,7 +205,7 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w return true; } } - // The device is not found in the file, we must create it manualy... + // The device is not found in the file, we must create it manualy... FILE *fp = fopen(VAR_CONFIG_FILE, "w"); if(!fp) { fprintf(stderr, "Failed to write state to %s: %s\n", @@ -213,11 +213,11 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w return false; } - cfg_print(d->var_cfg, fp); //Print the config-file - fprintf(fp, "device %d {\n}\n", intDeviceId); //Print the new device + cfg_print(d->var_cfg, fp); // Print the config-file + fprintf(fp, "device %d {\n}\n", intDeviceId); // Print the new device fclose(fp); - //Re-read config-file + // Re-read config-file cfg_free(d->var_cfg); readVarConfig(&d->var_cfg); @@ -258,7 +258,7 @@ std::wstring Settings::getDeviceStateValue( int intDeviceId ) const { } std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { - //already locked + // already locked if (d->cfg == 0) { return L""; } @@ -283,7 +283,7 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst } int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) { - //already locked + // already locked if (d->cfg == 0) { return TELLSTICK_ERROR_PERMISSION_DENIED; } @@ -315,7 +315,7 @@ int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &n } int Settings::getIntSetting(Node type, int intDeviceId, const std::wstring &name, bool parameter) const { - //already locked + // already locked if (d->cfg == 0) { return 0; } @@ -334,7 +334,7 @@ int Settings::getIntSetting(Node type, int intDeviceId, const std::wstring &name } int Settings::setIntSetting(Node type, int intDeviceId, const std::wstring &name, int value, bool parameter) { - //already locked + // already locked if (d->cfg == 0) { return TELLSTICK_ERROR_PERMISSION_DENIED; } @@ -363,7 +363,7 @@ int Settings::setIntSetting(Node type, int intDeviceId, const std::wstring &name bool readConfig(cfg_t **cfg) { - //All the const_cast keywords is to remove the compiler warnings generated by the C++-compiler. + // All the const_cast keywords is to remove the compiler warnings generated by the C++-compiler. cfg_opt_t controller_opts[] = { CFG_INT(const_cast("id"), -1, CFGF_NONE), CFG_STR(const_cast("name"), const_cast(""), CFGF_NONE), @@ -374,7 +374,7 @@ bool readConfig(cfg_t **cfg) { }; cfg_opt_t device_parameter_opts[] = { - //Groups + // Groups CFG_STR(const_cast("devices"), 0, CFGF_NONE), CFG_STR(const_cast("house"), 0, CFGF_NONE), diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index e3f88c0b..074a99fd 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -14,7 +14,7 @@ std::string TellStick::createTPacket( const std::string &msg ) { std::string data; int index = 0; for(size_t i = 0; i < msg.length(); ++i) { - //Search to se if it already exists and get the index + // Search to se if it already exists and get the index if (times.find(msg.at(i)) == times.end()) { times[msg.at(i)] = index++; if (times.size() > 4) { @@ -23,7 +23,7 @@ std::string TellStick::createTPacket( const std::string &msg ) { } data.append(1, times[msg.at(i)]); } - //Reorder the times + // Reorder the times unsigned char t0 = 1, t1 = 1, t2 = 1, t3 = 1; for(std::map::const_iterator it = times.begin(); it != times.end(); ++it) { if ((*it).second == 0) { diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 98574ea4..d3535df9 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -122,10 +122,10 @@ bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const { void TellStick::processData( const std::string &data ) { for (unsigned int i = 0; i < data.length(); ++i) { - if (data[i] == 13) { // Skip \r + if (data[i] == 13) { // Skip \r continue; - } else if (data[i] == 10) { // \n found - if (d->message.substr(0,2).compare("+V") == 0) { + } else if (data[i] == 10) { // \n found + if (d->message.substr(0, 2).compare("+V") == 0) { setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str())); } else if (d->message.substr(0,2).compare("+R") == 0) { this->publishData(d->message.substr(2)); @@ -133,7 +133,7 @@ void TellStick::processData( const std::string &data ) { this->decodePublishData(d->message.substr(2)); } d->message.clear(); - } else { // Append the character + } else { // Append the character d->message.append( 1, data[i] ); } } @@ -159,12 +159,12 @@ void TellStick::run() { d->running = true; } - //Send a firmware version request + // Send a firmware version request unsigned char msg[] = "V+"; ftdi_write_data( &d->ftHandle, msg, 2 ) ; while(1) { - //Is there any better way then sleeping between reads? + // Is there any better way then sleeping between reads? msleep(100); TelldusCore::MutexLocker locker(&d->mutex); if (!d->running) { @@ -173,9 +173,9 @@ void TellStick::run() { memset(buf, 0, sizeof(buf)); dwBytesRead = ftdi_read_data(&d->ftHandle, buf, sizeof(buf)); if (dwBytesRead < 0) { - //An error occured, avoid flooding by sleeping longer - //Hopefully if will start working again - msleep(1000); //1s + // An error occured, avoid flooding by sleeping longer + // Hopefully if will start working again + msleep(1000); // 1s } if (dwBytesRead < 1) { continue; @@ -193,9 +193,9 @@ int TellStick::send( const std::string &strMessage ) { unsigned char *tempMessage = new unsigned char[strMessage.size()]; memcpy(tempMessage, strMessage.c_str(), strMessage.size()); - //This lock does two things - // 1 Prevents two calls from different threads to this function - // 2 Prevents our running thread from receiving the data we are interested in here + // This lock does two things + // 1 Prevents two calls from different threads to this function + // 2 Prevents our running thread from receiving the data we are interested in here TelldusCore::MutexLocker locker(&d->mutex); int ret; @@ -232,9 +232,9 @@ int TellStick::send( const std::string &strMessage ) { if (in == '\n') { return TELLSTICK_SUCCESS; } - } else if(ret == 0) { // No data available + } else if(ret == 0) { // No data available usleep(100); - } else { //Error + } else { // Error Log::debug("Broken pipe on read"); return TELLSTICK_ERROR_BROKEN_PIPE; } @@ -322,7 +322,7 @@ void TellStick::stop() { TelldusCore::MutexLocker locker(&d->mutex); d->running = false; } - //Unlock the wait-condition + // Unlock the wait-condition pthread_cond_broadcast(&d->eh.eCondVar); } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 3ba28bf0..52ad2ffa 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -64,9 +64,9 @@ void TelldusMain::suspend() { void TelldusMain::start(void) { TelldusCore::EventRef clientEvent = d->eventHandler.addEvent(); TelldusCore::EventRef dataEvent = d->eventHandler.addEvent(); - TelldusCore::EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups - Timer supervisor(janitor); //Tells the janitor to go back to work - supervisor.setInterval(60); //Once every minute + TelldusCore::EventRef janitor = d->eventHandler.addEvent(); // Used for regular cleanups + Timer supervisor(janitor); // Tells the janitor to go back to work + supervisor.setInterval(60); // Once every minute supervisor.start(); EventUpdateManager eventUpdateManager; @@ -82,7 +82,7 @@ void TelldusMain::start(void) { TelldusCore::EventRef handlerEvent = d->eventHandler.addEvent(); #ifdef _MACOSX - //This is only needed on OS X + // This is only needed on OS X ControllerListener controllerListener(d->controllerChangeEvent); #endif @@ -92,7 +92,7 @@ void TelldusMain::start(void) { continue; } if (clientEvent->isSignaled()) { - //New client connection + // New client connection TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal(); ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); if (data) { @@ -131,7 +131,7 @@ void TelldusMain::start(void) { } } if (janitor->isSignaled()) { - //Clear all of them if there is more than one + // Clear all of them if there is more than one while(janitor->isSignaled()) { janitor->popSignal(); } diff --git a/telldus-core/service/TelldusMain.h b/telldus-core/service/TelldusMain.h index bbd18127..388f933a 100644 --- a/telldus-core/service/TelldusMain.h +++ b/telldus-core/service/TelldusMain.h @@ -15,7 +15,7 @@ public: void start(); void stop(); - //Thread safe! + // Thread safe! void deviceInsertedOrRemoved(int vid, int pid, bool inserted); void resume(); void suspend(); diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index 98288021..4f2e3dbf 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -60,7 +60,7 @@ void Timer::stop() { d->running = false; SetEvent(d->cond); #else - //Signal event + // Signal event pthread_mutex_lock(&d->waitMutex); if (d->running) { d->running = false; diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 544c0e91..4e72f3b8 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -77,9 +77,9 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } if (pid > 0) { - //We are the parent - //Let the parent store the clients pid, - //This way anyone starting the daemon can read the pidfile immediately + // We are the parent + // Let the parent store the clients pid, + // This way anyone starting the daemon can read the pidfile immediately // Record the pid fd = fopen(PID_FILE,"w"); @@ -103,7 +103,7 @@ int main(int argc, char **argv) { sid = setsid(); if (sid < 0) { - //Something went wrong + // Something went wrong printf("Could not set sid\n"); exit(EXIT_FAILURE); } From 3a0cee353a5517c6d71e14eddbaee7f6a2b4d27e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 11:57:22 +0200 Subject: [PATCH 2007/2215] Fix include header order according to Google style guidelines "build/include_order" --- telldus-core/common/Event.cpp | 2 +- telldus-core/common/Event.h | 13 ++++++------- telldus-core/common/Message.cpp | 3 +-- telldus-core/common/Socket.h | 4 ++-- telldus-core/common/Strings.cpp | 7 ++++--- telldus-core/common/Strings.h | 2 +- telldus-core/common/common.h | 5 ++--- telldus-core/service/ClientCommunicationHandler.cpp | 7 ++++--- telldus-core/service/ConnectionListener_unix.cpp | 10 ++++------ telldus-core/service/Controller.h | 2 +- telldus-core/service/ControllerManager.cpp | 9 ++++++--- telldus-core/service/ControllerManager.h | 2 +- telldus-core/service/ControllerMessage.cpp | 5 ++--- telldus-core/service/Device.h | 4 ++-- telldus-core/service/DeviceManager.cpp | 13 ++++++++----- telldus-core/service/DeviceManager.h | 2 +- telldus-core/service/EventUpdateManager.cpp | 6 +++--- telldus-core/service/Protocol.cpp | 7 ++++--- telldus-core/service/ProtocolComen.h | 2 +- telldus-core/service/ProtocolEverflourish.cpp | 6 +++--- telldus-core/service/ProtocolFineoffset.cpp | 5 +++-- telldus-core/service/ProtocolHasta.cpp | 3 ++- telldus-core/service/ProtocolIkea.cpp | 4 ++-- telldus-core/service/ProtocolMandolyn.cpp | 5 +++-- telldus-core/service/ProtocolNexa.cpp | 1 + telldus-core/service/ProtocolNexa.h | 2 +- telldus-core/service/ProtocolOregon.cpp | 5 +++-- telldus-core/service/ProtocolSartano.cpp | 3 ++- telldus-core/service/ProtocolWaveman.cpp | 3 ++- telldus-core/service/Sensor.cpp | 3 ++- telldus-core/service/Sensor.h | 2 +- telldus-core/service/SettingsConfuse.cpp | 11 +++++------ telldus-core/service/TellStick.cpp | 3 ++- telldus-core/service/TellStick_libftdi.cpp | 9 ++++----- telldus-core/service/TelldusMain.cpp | 8 +++++--- telldus-core/service/Timer.cpp | 2 +- telldus-core/service/main_unix.cpp | 2 +- 37 files changed, 97 insertions(+), 85 deletions(-) diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index 7f89ecf9..fa4176fd 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -5,10 +5,10 @@ // // #include "common/Event.h" +#include #include "common/EventHandler.h" #include "common/Mutex.h" -#include using namespace TelldusCore; diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index 56274a1d..f8451f73 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -7,15 +7,14 @@ #ifndef TELLDUS_CORE_COMMON_EVENT_H_ #define TELLDUS_CORE_COMMON_EVENT_H_ -#include "Thread.h" -#ifdef _WINDOWS -#include -#include - typedef HANDLE EVENT_T; -#else -#include +#ifndef _WINDOWS + #include typedef void* EVENT_T; +#else + #include + #include + typedef HANDLE EVENT_T; #endif #include "common/Thread.h" diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 8099c653..600cb460 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -4,16 +4,15 @@ // Copyright: See COPYING file that comes with this distribution // // +#include "common/Message.h" #include #include #include -#include "common/Message.h" #include "common/Socket.h" #include "common/Strings.h" using namespace TelldusCore; - Message::Message() : std::wstring() { } diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index b8ee4aef..98fdbc51 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -7,8 +7,6 @@ #ifndef TELLDUS_CORE_COMMON_SOCKET_H_ #define TELLDUS_CORE_COMMON_SOCKET_H_ -#include - #ifdef _WINDOWS #include typedef HANDLE SOCKET_T; @@ -16,6 +14,8 @@ typedef int SOCKET_T; #endif +#include + namespace TelldusCore { class Socket { public: diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index b1457849..6b2f1bf2 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -6,9 +6,6 @@ // #include "common/Strings.h" -#include -#include -#include #include #include @@ -17,6 +14,10 @@ #else #include #endif +#include +#include +#include + #ifdef _MACOSX #define WCHAR_T_ENCODING "UCS-4-INTERNAL" diff --git a/telldus-core/common/Strings.h b/telldus-core/common/Strings.h index 6a4c5eaa..d4b81971 100644 --- a/telldus-core/common/Strings.h +++ b/telldus-core/common/Strings.h @@ -7,7 +7,6 @@ #ifndef TELLDUS_CORE_COMMON_STRINGS_H_ #define TELLDUS_CORE_COMMON_STRINGS_H_ -#include #include #ifdef _MSC_VER typedef unsigned __int8 uint8_t; @@ -17,6 +16,7 @@ typedef unsigned __int64 uint64_t; #else #include #endif +#include namespace TelldusCore { std::wstring charToWstring(const char *value); diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 1a596dd3..13e39bda 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -16,12 +16,11 @@ #else #include #endif -#include "Strings.h" -#include +#include #include #include +#include #include -#include #include "common/Strings.h" inline void msleep( const int msec) { diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 9d982f52..5b091343 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -4,13 +4,14 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "ClientCommunicationHandler.h" -#include "common/Message.h" -#include "common/Strings.h" +#include "service/ClientCommunicationHandler.h" #include #include +#include "common/Message.h" +#include "common/Strings.h" + class ClientCommunicationHandler::PrivateData { public: TelldusCore::Socket *clientSocket; diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 0c9600dd..32b991a9 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -4,19 +4,17 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "service/ConnectionListener.h" -#include "common/Socket.h" - -#include #include #include #include #include - - #include #include #include +#include + +#include "service/ConnectionListener.h" +#include "common/Socket.h" class ConnectionListener::PrivateData { public: diff --git a/telldus-core/service/Controller.h b/telldus-core/service/Controller.h index 3dcdd709..3bbb667c 100644 --- a/telldus-core/service/Controller.h +++ b/telldus-core/service/Controller.h @@ -7,8 +7,8 @@ #ifndef TELLDUS_CORE_SERVICE_CONTROLLER_H_ #define TELLDUS_CORE_SERVICE_CONTROLLER_H_ -#include "common/Event.h" #include +#include "common/Event.h" class ControllerEventData : public TelldusCore::EventDataBase { public: diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index d4e70a1d..a8ac4ecd 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -5,6 +5,12 @@ // // #include "service/ControllerManager.h" + +#include +#include +#include +#include + #include "service/Controller.h" #include "common/Mutex.h" #include "service/TellStick.h" @@ -15,9 +21,6 @@ #include "service/EventUpdateManager.h" #include "client/telldus-core.h" -#include -#include - class ControllerDescriptor { public: std::wstring name, serial; diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index f1000c5f..f5e583b5 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -7,10 +7,10 @@ #ifndef TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_ #define TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_ +#include #include "common/Event.h" class Controller; -#include class ControllerManager { public: diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index d749d77b..32746d95 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -5,13 +5,12 @@ // // #include "service/ControllerMessage.h" +#include +#include #include "service/Device.h" #include "common/Strings.h" - #include "common/common.h" -#include - class ControllerMessage::PrivateData { public: std::map parameters; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 77272987..8ef9107d 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -7,11 +7,11 @@ #ifndef TELLDUS_CORE_SERVICE_DEVICE_H_ #define TELLDUS_CORE_SERVICE_DEVICE_H_ +#include +#include #include "service/Controller.h" #include "common/Mutex.h" #include "service/Protocol.h" -#include -#include class Device : public TelldusCore::Mutex { public: diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index e4b4a218..cc4b56cc 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -5,6 +5,14 @@ // // #include "service/DeviceManager.h" +#include +#include +#include +#include +#include +#include +#include + #include "service/ControllerMessage.h" #include "common/Mutex.h" #include "service/Sensor.h" @@ -13,11 +21,6 @@ #include "common/Message.h" #include "service/Log.h" -#include -#include -#include -#include - typedef std::map DeviceMap; class DeviceManager::PrivateData { diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 9ed8be2c..152dec12 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -7,12 +7,12 @@ #ifndef TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_ #define TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_ +#include #include #include "service/Device.h" #include "service/ControllerManager.h" #include "service/ControllerMessage.h" #include "service/EventUpdateManager.h" -#include class Sensor; diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 5ac35c06..3f5dc623 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -6,14 +6,14 @@ // #include "service/EventUpdateManager.h" +#include +#include + #include "service/ConnectionListener.h" #include "common/EventHandler.h" #include "common/Message.h" #include "common/Socket.h" -#include -#include - typedef std::list SocketList; class EventUpdateManager::PrivateData { diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 1b49442c..8c4f8ca0 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -5,8 +5,11 @@ // // #include "service/Protocol.h" -#include "client/telldus-core.h" +#include +#include +#include +#include "client/telldus-core.h" #include "service/ControllerMessage.h" #include "service/ProtocolBrateck.h" #include "service/ProtocolComen.h" @@ -27,9 +30,7 @@ #include "service/ProtocolWaveman.h" #include "service/ProtocolX10.h" #include "service/ProtocolYidong.h" - #include "common/Strings.h" -#include class Protocol::PrivateData { public: diff --git a/telldus-core/service/ProtocolComen.h b/telldus-core/service/ProtocolComen.h index d6a9e8b9..a9ef9211 100644 --- a/telldus-core/service/ProtocolComen.h +++ b/telldus-core/service/ProtocolComen.h @@ -7,8 +7,8 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ -#include "service/ProtocolNexa.h" #include +#include "service/ProtocolNexa.h" class ProtocolComen : public ProtocolNexa { public: diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 913b37a8..a9defc2a 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -4,11 +4,11 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "ProtocolEverflourish.h" -#include +#include "service/ProtocolEverflourish.h" #include -#include "service/ControllerMessage.h" +#include #include +#include "service/ControllerMessage.h" int ProtocolEverflourish::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN; diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index 85962422..d7b8119e 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -5,10 +5,11 @@ // // #include "service/ProtocolFineoffset.h" -#include "common/Strings.h" #include -#include #include +#include +#include +#include "common/Strings.h" std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index 963e98da..d89c4830 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -5,8 +5,9 @@ // // #include "service/ProtocolHasta.h" -#include #include +#include +#include int ProtocolHasta::methods() const { return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 6985b0e7..1d8d7c45 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -5,10 +5,10 @@ // // #include "service/ProtocolIkea.h" -#include "common/Strings.h" - #include #include +#include +#include "common/Strings.h" int ProtocolIkea::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM; diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index 28ff77d5..fd720893 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -5,10 +5,11 @@ // // #include "service/ProtocolMandolyn.h" -#include "common/Strings.h" #include -#include #include +#include +#include +#include "common/Strings.h" std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index feac5df4..3036ff00 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -7,6 +7,7 @@ #include "service/ProtocolNexa.h" #include #include +#include #include "service/TellStick.h" #include "common/Strings.h" diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index a4bc8b83..37e6b813 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -7,9 +7,9 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ +#include #include "service/ControllerMessage.h" #include "service/Device.h" -#include class ProtocolNexa : public Protocol { public: diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 737ad91f..6870929d 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -5,10 +5,11 @@ // // #include "service/ProtocolOregon.h" -#include "common/Strings.h" #include -#include #include +#include +#include +#include "common/Strings.h" std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index c0cc1185..6fa9c7e6 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -5,8 +5,9 @@ // // #include "service/ProtocolSartano.h" -#include #include +#include +#include int ProtocolSartano::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 00ced94a..fecd4c3c 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -5,8 +5,9 @@ // // #include "service/ProtocolWaveman.h" -#include #include +#include +#include int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff=0; diff --git a/telldus-core/service/Sensor.cpp b/telldus-core/service/Sensor.cpp index 65870b66..787bf4c9 100644 --- a/telldus-core/service/Sensor.cpp +++ b/telldus-core/service/Sensor.cpp @@ -5,9 +5,10 @@ // // #include "service/Sensor.h" +#include +#include #include "common/common.h" #include "client/telldus-core.h" -#include class Sensor::PrivateData { public: diff --git a/telldus-core/service/Sensor.h b/telldus-core/service/Sensor.h index 3c6561e2..0ebd6332 100644 --- a/telldus-core/service/Sensor.h +++ b/telldus-core/service/Sensor.h @@ -7,8 +7,8 @@ #ifndef TELLDUS_CORE_SERVICE_SENSOR_H_ #define TELLDUS_CORE_SERVICE_SENSOR_H_ -#include "common/Mutex.h" #include +#include "common/Mutex.h" class Sensor : public TelldusCore::Mutex { public: diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index db3f9325..95042105 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -4,16 +4,15 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "Settings.h" -#include "client/telldus-core.h" -#include "service/Settings.h" -#include "service/SettingsConfusePaths.h" -#include "client/telldus-core.h" -#include "common/Strings.h" #include #include #include #include +#include +#include "service/Settings.h" +#include "service/SettingsConfusePaths.h" +#include "client/telldus-core.h" +#include "common/Strings.h" using namespace std; diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index 074a99fd..4987118a 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -6,8 +6,9 @@ // #include "service/TellStick.h" -#include #include +#include +#include std::string TellStick::createTPacket( const std::string &msg ) { std::map times; diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index d3535df9..ce726b64 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -4,24 +4,23 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "service/TellStick.h" -#include "client/telldus-core.h" +#include #include #include #include #include -#include #include #include + +#include "service/TellStick.h" #include "service/Log.h" #include "service/Settings.h" +#include "client/telldus-core.h" #include "common/Thread.h" #include "common/Mutex.h" #include "common/Strings.h" #include "common/common.h" -#include - typedef struct _EVENT_HANDLE { pthread_cond_t eCondVar; pthread_mutex_t eMutex; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 52ad2ffa..3016a520 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -5,6 +5,11 @@ // // #include "service/TelldusMain.h" + +#include +#include +#include + #include "service/ConnectionListener.h" #include "common/EventHandler.h" #include "service/ClientCommunicationHandler.h" @@ -15,9 +20,6 @@ #include "service/Timer.h" #include "service/Log.h" -#include -#include -#include class TelldusMain::PrivateData { public: diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index 4f2e3dbf..758881e3 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -5,12 +5,12 @@ // // #include "service/Timer.h" -#include "common/Mutex.h" #ifdef _WINDOWS #else #include #include #endif +#include "common/Mutex.h" class Timer::PrivateData { public: diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 4e72f3b8..97d9358e 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -4,7 +4,6 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "service/TelldusMain.h" #include #include #include @@ -16,6 +15,7 @@ #include #include +#include "service/TelldusMain.h" #include "service/Settings.h" #include "common/Strings.h" #include "service/Log.h" From 110dcc2c574320d8673e61f20a4137157709913d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 Feb 2012 10:38:01 +0100 Subject: [PATCH 2008/2215] Should have spaces after comma according to Google style guidelines "whitespace/comma" --- telldus-core/service/ControllerMessage.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/ProtocolBrateck.cpp | 12 ++++++------ telldus-core/service/ProtocolEverflourish.cpp | 14 +++++++------- telldus-core/service/ProtocolFuhaote.cpp | 8 ++++---- telldus-core/service/ProtocolNexa.cpp | 2 +- telldus-core/service/ProtocolX10.cpp | 10 +++++----- telldus-core/service/Sensor.cpp | 2 +- telldus-core/service/TellStick.cpp | 2 +- telldus-core/service/TellStick_libftdi.cpp | 4 ++-- telldus-core/service/main_unix.cpp | 4 ++-- 11 files changed, 31 insertions(+), 31 deletions(-) diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index 32746d95..a701ffea 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -71,7 +71,7 @@ int ControllerMessage::getIntParameter(const std::string &key) const { if (strValue.compare("") == 0) { return -1; } - if (strValue.substr(0,2).compare("0x") == 0) { + if (strValue.substr(0, 2).compare("0x") == 0) { return strtol(strValue.c_str(), NULL, 16); } return strtol(strValue.c_str(), NULL, 10); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index cc4b56cc..e322c811 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -98,7 +98,7 @@ int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); - d->set.setDeviceState(deviceId, command,value); + d->set.setDeviceState(deviceId, command, value); it->second->setLastSentCommand(command, value); } else { diff --git a/telldus-core/service/ProtocolBrateck.cpp b/telldus-core/service/ProtocolBrateck.cpp index 836e1a35..ab03387c 100644 --- a/telldus-core/service/ProtocolBrateck.cpp +++ b/telldus-core/service/ProtocolBrateck.cpp @@ -14,12 +14,12 @@ int ProtocolBrateck::methods() const { std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) { const char S = '!'; const char L = 'V'; - const char B1[] = {L,S,L,S,0}; - const char BX[] = {S,L,L,S,0}; - const char B0[] = {S,L,S,L,0}; - const char BUP[] = {L,S,L,S,S,L,S,L,S,L,S,L,S,L,S,L,S,0}; - const char BSTOP[] = {S,L,S,L,L,S,L,S,S,L,S,L,S,L,S,L,S,0}; - const char BDOWN[] = {S,L,S,L,S,L,S,L,S,L,S,L,L,S,L,S,S,0}; + const char B1[] = {L, S, L, S, 0}; + const char BX[] = {S, L, L, S, 0}; + const char B0[] = {S, L, S, L, 0}; + const char BUP[] = {L, S, L, S, S, L, S, L, S, L, S, L, S, L, S, L, S, 0}; + const char BSTOP[] = {S, L, S, L, L, S, L, S, S, L, S, L, S, L, S, L, S, 0}; + const char BDOWN[] = {S, L, S, L, S, L, S, L, S, L, S, L, L, S, L, S, S, 0}; std::string strReturn; std::wstring strHouse = this->getStringParameter(L"house", L""); diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index a9defc2a..addf3680 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -33,7 +33,7 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, const char sssl = 84; // 0 const char slss = 69; // 1 - const char bits[2] = {sssl,slss}; + const char bits[2] = {sssl, slss}; int i, check; std::string strCode; @@ -42,7 +42,7 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, check = calculateChecksum(deviceCode); - char preamble[] = {'R', 5, 'T', 114,60,1,1,105,ssss,ssss,0}; + char preamble[] = {'R', 5, 'T', 114, 60, 1, 1, 105, ssss, ssss, 0}; strCode.append(preamble); for(i=15;i>=0;i--) { @@ -64,15 +64,15 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, // The calculation used in this function is provided by Frank Stevenson unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { unsigned int bits[16] = { - 0xf ,0xa ,0x7 ,0xe, - 0xf ,0xd ,0x9 ,0x1, - 0x1 ,0x2 ,0x4 ,0x8, - 0x3 ,0x6 ,0xc ,0xb + 0xf, 0xa, 0x7, 0xe, + 0xf, 0xd, 0x9, 0x1, + 0x1, 0x2, 0x4, 0x8, + 0x3, 0x6, 0xc, 0xb }; unsigned int bit = 1; unsigned int res = 0x5; int i; - unsigned int lo,hi; + unsigned int lo, hi; if ((x&0x3)==3) { lo = x & 0x00ff; diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index 37704869..b80b0b83 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -14,10 +14,10 @@ int ProtocolFuhaote::methods() const { std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) { const char S = 19; const char L = 58; - const char B0[] = {S,L,L,S,0}; - const char B1[] = {L,S,L,S,0}; - const char OFF[] = {S,L,S,L,S,L,L,S,0}; - const char ON[] = {S,L,L,S,S,L,S,L,0}; + const char B0[] = {S, L, L, S, 0}; + const char B1[] = {L, S, L, S, 0}; + const char OFF[] = {S, L, S, L, S, L, L, S, 0}; + const char ON[] = {S, L, L, S, S, L, S, L, 0}; std::string strReturn = "S"; std::wstring strCode = this->getStringParameter(L"code", L""); diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 3036ff00..f06de6b9 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -151,7 +151,7 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode // code |= 11; //b1011 } if (i % 2 == 0) { - strMessage.append(1,code); + strMessage.append(1, code); code = 0; } } diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index 51234065..ba9f11e1 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -9,7 +9,7 @@ #include #include -const unsigned char HOUSES[] = {6,0xE,2,0xA,1,9,5,0xD,7,0xF,3,0xB,0,8,4,0xC}; +const unsigned char HOUSES[] = {6, 0xE, 2, 0xA, 1, 9, 5, 0xD, 7, 0xF, 3, 0xB, 0, 8, 4, 0xC}; int ProtocolX10::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; @@ -17,10 +17,10 @@ int ProtocolX10::methods() const { std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) { const unsigned char S = 59, L = 169; - const char B0[] = {S,S,0}; - const char B1[] = {S,L,0}; - const unsigned char START_CODE[] = {'S',255,1,255,1,255,1,100,255,1,180,0}; - const unsigned char STOP_CODE[] = {S,0}; + const char B0[] = {S, S, 0}; + const char B1[] = {S, L, 0}; + const unsigned char START_CODE[] = {'S', 255, 1, 255, 1, 255, 1, 100, 255, 1, 180, 0}; + const unsigned char STOP_CODE[] = {S, 0}; std::string strReturn = reinterpret_cast(START_CODE); std::string strComplement = ""; diff --git a/telldus-core/service/Sensor.cpp b/telldus-core/service/Sensor.cpp index 787bf4c9..d5002651 100644 --- a/telldus-core/service/Sensor.cpp +++ b/telldus-core/service/Sensor.cpp @@ -55,7 +55,7 @@ int Sensor::dataTypes() const { } void Sensor::setValue(int type, const std::string &value, time_t timestamp) { - if (value.substr(0,2).compare("0x") == 0) { + if (value.substr(0, 2).compare("0x") == 0) { int intval = strtol(value.c_str(), NULL, 16); d->values[type] = TelldusCore::intToString(intval); } else { diff --git a/telldus-core/service/TellStick.cpp b/telldus-core/service/TellStick.cpp index 4987118a..3fa0205a 100644 --- a/telldus-core/service/TellStick.cpp +++ b/telldus-core/service/TellStick.cpp @@ -38,7 +38,7 @@ std::string TellStick::createTPacket( const std::string &msg ) { } } - return TellStick::convertSToT(t0,t1,t2,t3,data); + return TellStick::convertSToT(t0, t1, t2, t3, data); } std::string TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ) { diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index ce726b64..d31cdb0e 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -126,9 +126,9 @@ void TellStick::processData( const std::string &data ) { } else if (data[i] == 10) { // \n found if (d->message.substr(0, 2).compare("+V") == 0) { setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str())); - } else if (d->message.substr(0,2).compare("+R") == 0) { + } else if (d->message.substr(0, 2).compare("+R") == 0) { this->publishData(d->message.substr(2)); - } else if(d->message.substr(0,2).compare("+W") == 0) { + } else if(d->message.substr(0, 2).compare("+W") == 0) { this->decodePublishData(d->message.substr(2)); } d->message.clear(); diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 97d9358e..6acb2a8a 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -82,9 +82,9 @@ int main(int argc, char **argv) { // This way anyone starting the daemon can read the pidfile immediately // Record the pid - fd = fopen(PID_FILE,"w"); + fd = fopen(PID_FILE, "w"); if (fd) { - fprintf(fd,"%d\n",pid); + fprintf(fd, "%d\n", pid); fclose(fd); } else { Log::error("Could not open pid file %s: %s", PID_FILE, strerror(errno)); From dc357ddeca29f94729d65a50fe618baf7807c03a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 Feb 2012 10:47:01 +0100 Subject: [PATCH 2009/2215] Remove extra blank lines according to Google style guidelines "whitespace/blank_line" --- telldus-core/client/CallbackDispatcher.cpp | 1 - telldus-core/client/Client.cpp | 2 -- telldus-core/common/Message.cpp | 1 - telldus-core/common/Message.h | 1 - telldus-core/service/ClientCommunicationHandler.cpp | 4 ++-- telldus-core/service/ConnectionListener_unix.cpp | 1 - telldus-core/service/Controller.cpp | 1 - telldus-core/service/ControllerManager.cpp | 1 - telldus-core/service/Device.cpp | 1 - telldus-core/service/DeviceManager.cpp | 2 -- telldus-core/service/Protocol.cpp | 2 +- telldus-core/service/ProtocolFuhaote.cpp | 1 - telldus-core/service/ProtocolGroup.h | 1 - telldus-core/service/ProtocolIkea.cpp | 1 - telldus-core/service/ProtocolRisingSun.cpp | 3 --- telldus-core/service/ProtocolSartano.cpp | 2 -- telldus-core/service/ProtocolScene.h | 1 - telldus-core/service/ProtocolSilvanChip.cpp | 1 - telldus-core/service/ProtocolX10.cpp | 1 - telldus-core/service/SettingsConfuse.cpp | 2 -- telldus-core/service/TellStick_libftdi.cpp | 2 -- 21 files changed, 3 insertions(+), 29 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 9b427421..91ba088b 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -65,6 +65,5 @@ void TDEventDispatcher::fireEvent() { return; } ((TDControllerEvent)callback->event)(data->controllerId, data->changeEvent, data->changeType, data->newValue.c_str(), callback->id, callback->context); - } } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 7237445e..c0e394a1 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -23,7 +23,6 @@ public: std::wstring sensorCache, controllerCache; TelldusCore::Mutex mutex; CallbackMainDispatcher callbackMainDispatcher; - }; Client *Client::instance = 0; @@ -147,7 +146,6 @@ void Client::run() { } std::wstring Client::sendToService(const Message &msg) { - int tries = 0; std::wstring readData; while(tries < 20) { diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 600cb460..7c05895c 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -109,7 +109,6 @@ bool Message::nextIsString(const std::wstring &message) { } std::wstring Message::takeString(std::wstring *message) { - if (!Message::nextIsString(*message)) { return L""; } diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index e1ffc656..b79cacf2 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -30,7 +30,6 @@ namespace TelldusCore { static int takeInt(std::wstring *); private: - }; } diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 5b091343..7291590e 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -111,7 +111,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_STOP, 0); - } else if (function == L"tdLearn") { + } else if (function == L"tdLearn") { int deviceId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0); @@ -252,7 +252,7 @@ void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int controllerId = TelldusCore::Message::takeInt(&msg); (*intReturn) = d->controllerManager->removeController(controllerId); - } else{ + } else { (*intReturn) = TELLSTICK_ERROR_UNKNOWN; } } diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 32b991a9..78d3911a 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -87,7 +87,6 @@ void ConnectionListener::run() { ConnectionListenerEventData *data = new ConnectionListenerEventData(); data->socket = new TelldusCore::Socket(clientSocket); d->waitEvent->signal(data); - } close(serverSocket); } diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index ad23935d..2cca4c03 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -37,7 +37,6 @@ void Controller::publishData(const std::string &msg) const { } void Controller::decodePublishData(const std::string &data) const { - std::list msgList = Protocol::decodeData(data); for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt) { diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index a8ac4ecd..977ff598 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -127,7 +127,6 @@ Controller *ControllerManager::getBestControllerById(int id) { } } return 0; - } void ControllerManager::loadControllers() { diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 7bbbbc6b..41399643 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -50,7 +50,6 @@ int Device::getLastSentCommand(int methodsSupported) { lastSentCommand = TELLSTICK_TURNOFF; } return lastSentCommand; - } int Device::getMethods() const { diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index e322c811..84fe73c2 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -144,7 +144,6 @@ int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDevice } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { - { TelldusCore::MutexLocker deviceLocker(it->second); type = it->second->getType(); @@ -522,7 +521,6 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c // If no devices support the method the default value will be returned (method not supported) retval = deviceReturnValue; } - } return retval; } diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 8c4f8ca0..04420885 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -207,7 +207,7 @@ std::list Protocol::getParametersForProtocol(const std::wstring &pr } else if (TelldusCore::comparei(protocolName, L"group")) { parameters.push_back("devices"); - } else if (TelldusCore::comparei(protocolName, L"scene")) { + } else if (TelldusCore::comparei(protocolName, L"scene")) { parameters.push_back("devices"); } diff --git a/telldus-core/service/ProtocolFuhaote.cpp b/telldus-core/service/ProtocolFuhaote.cpp index b80b0b83..7254520e 100644 --- a/telldus-core/service/ProtocolFuhaote.cpp +++ b/telldus-core/service/ProtocolFuhaote.cpp @@ -56,6 +56,5 @@ std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Contr strReturn.append(1, S); strReturn.append("+"); return strReturn; - } diff --git a/telldus-core/service/ProtocolGroup.h b/telldus-core/service/ProtocolGroup.h index aa82edc7..509c2a3a 100644 --- a/telldus-core/service/ProtocolGroup.h +++ b/telldus-core/service/ProtocolGroup.h @@ -14,7 +14,6 @@ class ProtocolGroup : public Protocol { public: virtual int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_ diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 1d8d7c45..6b246562 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -129,5 +129,4 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co strReturn.append("+"); return strReturn; - } diff --git a/telldus-core/service/ProtocolRisingSun.cpp b/telldus-core/service/ProtocolRisingSun.cpp index a48d59b3..c4e9ae0c 100644 --- a/telldus-core/service/ProtocolRisingSun.cpp +++ b/telldus-core/service/ProtocolRisingSun.cpp @@ -100,11 +100,9 @@ std::string ProtocolRisingSun::getStringCodeSwitch(int method) { return ""; } return strReturn; - } std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) { - std::string strReturn = ""; for(int i = 0; i < 4; ++i) { if (i == intToConvert) { @@ -114,5 +112,4 @@ std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) { } } return strReturn; - } diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 6fa9c7e6..255aaca7 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -19,7 +19,6 @@ std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Contr } std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int method) { - std::string strReturn("S"); for (size_t i = 0; i < strCode.length(); ++i) { @@ -39,7 +38,6 @@ std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int m } return strReturn; - } std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) { diff --git a/telldus-core/service/ProtocolScene.h b/telldus-core/service/ProtocolScene.h index 87ca70f7..87f80afe 100644 --- a/telldus-core/service/ProtocolScene.h +++ b/telldus-core/service/ProtocolScene.h @@ -14,7 +14,6 @@ class ProtocolScene : public Protocol { public: virtual int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_ diff --git a/telldus-core/service/ProtocolSilvanChip.cpp b/telldus-core/service/ProtocolSilvanChip.cpp index 7c57f539..ddc20068 100644 --- a/telldus-core/service/ProtocolSilvanChip.cpp +++ b/telldus-core/service/ProtocolSilvanChip.cpp @@ -122,7 +122,6 @@ std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char dat } std::string ProtocolSilvanChip::getString(const std::string &preamble, const std::string &one, const std::string &zero, int button) { - int intHouse = this->getIntParameter(L"house", 1, 1048575); std::string strReturn = preamble; diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index ba9f11e1..88b2308c 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -111,7 +111,6 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont strReturn.append( reinterpret_cast(STOP_CODE) ); strReturn.append("+"); return strReturn; - } std::string ProtocolX10::decodeData(ControllerMessage& dataMsg) { diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 95042105..89af7d09 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -156,7 +156,6 @@ int Settings::removeNode(Node type, int intNodeId) { // Print all opts for(int i = 0; d->cfg->opts[i].name; i++) { - // Check if it isn't a device section if (strcmp(d->cfg->opts[i].name, strType.c_str()) != 0) { cfg_opt_print(&d->cfg->opts[i], fp); @@ -416,7 +415,6 @@ bool readConfig(cfg_t **cfg) { } bool readVarConfig(cfg_t **cfg) { - cfg_opt_t device_opts[] = { CFG_INT(const_cast("state"), 0, CFGF_NONE), CFG_STR(const_cast("stateValue"), const_cast(""), CFGF_NONE), diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index d31cdb0e..e22fcc83 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -65,7 +65,6 @@ TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore: ftdi_set_latency_timer(&d->ftHandle, 16); if (d->open) { - if (td.pid == 0x0C31) { this->setBaud(9600); } else { @@ -258,7 +257,6 @@ std::list TellStick::findAll() { } return tellstick; - } bool TellStick::stillConnected() const { From 1f9a069df7b4eb9a87f31e374beb68ea754982d5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 Feb 2012 18:10:47 +0100 Subject: [PATCH 2010/2215] Remove extra spaces at end of line according to Google style guidelines "whitespace/end_of_line" --- telldus-core/common/Thread.cpp | 2 +- telldus-core/common/Thread.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index f4cb6d71..c66ff604 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -1,7 +1,7 @@ // // C++ Implementation: Thread // -// Description: +// Description: // // // Author: Micke Prag , (C) 2009 diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index 154d7095..139aad38 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -1,7 +1,7 @@ // // C++ Interface: Thread // -// Description: +// Description: // // // Author: Micke Prag , (C) 2009 @@ -24,10 +24,10 @@ namespace TelldusCore { void start(); void startAndLock(Mutex *); bool wait(); - + protected: virtual void run() = 0; - + private: static void* exec( void *ptr ); ThreadPrivate *d; From a01b42b4d72214fcaa901ad5319faea8763c8e9b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 Feb 2012 17:53:52 +0100 Subject: [PATCH 2011/2215] An else should appear on the same line as the preceding } according to Google style guidelines "whitespace/newline" --- telldus-core/service/Device.cpp | 3 +-- telldus-core/service/EventUpdateManager.cpp | 3 +-- telldus-core/service/Protocol.cpp | 18 ++++++------------ telldus-core/service/ProtocolWaveman.cpp | 4 +--- 4 files changed, 9 insertions(+), 19 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 41399643..f1cdc3ad 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -131,8 +131,7 @@ std::wstring Device::getStateValue() { int Device::getType() { if(d->protocolName == L"group") { return TELLSTICK_TYPE_GROUP; - } - else if(d->protocolName == L"scene") { + } else if(d->protocolName == L"scene") { return TELLSTICK_TYPE_SCENE; } return TELLSTICK_TYPE_DEVICE; diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 3f5dc623..b81ec06a 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -62,8 +62,7 @@ void EventUpdateManager::run() { if(data) { d->clients.push_back(data->socket); } - } - else if(d->updateEvent->isSignaled()) { + } else if(d->updateEvent->isSignaled()) { // device event, signal all clients TelldusCore::EventDataRef eventData = d->updateEvent->takeSignal(); EventUpdateData *data = reinterpret_cast(eventData.get()); diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 04420885..454b3930 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -141,9 +141,8 @@ Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname) { } else if (TelldusCore::comparei(protocolname, L"group")) { return new ProtocolGroup(); - } - else if (TelldusCore::comparei(protocolname, L"scene")) { + } else if (TelldusCore::comparei(protocolname, L"scene")) { return new ProtocolScene(); } @@ -232,32 +231,27 @@ std::list Protocol::decodeData(const std::string &fullData) { if (decoded != "") { retval.push_back(decoded); } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) { + } else if(TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) { decoded = ProtocolEverflourish::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) { + } else if(TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) { decoded = ProtocolFineoffset::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) { + } else if(TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) { decoded = ProtocolMandolyn::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) { + } else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) { decoded = ProtocolOregon::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); } - } - else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { + } else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) { decoded = ProtocolX10::decodeData(dataMsg); if (decoded != "") { retval.push_back(decoded); diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index fecd4c3c..0dd2b688 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -62,11 +62,9 @@ std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) { if(method == 0) { retString << ";unit:" << unit << ";method:turnoff;"; - } else if(method == 14) { retString << ";unit:" << unit << ";method:turnon;"; - } - else { + } else { // not waveman return ""; } From e7bb22cf34f081f0f606a2877ec91707adadc4cb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 Feb 2012 10:47:18 +0100 Subject: [PATCH 2012/2215] We need spaces surrounding operators according to Google style guidelines "whitespace/operators" --- telldus-core/service/Device.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/Protocol.cpp | 2 +- telldus-core/service/ProtocolEverflourish.cpp | 16 ++++++++-------- telldus-core/service/ProtocolIkea.cpp | 4 ++-- telldus-core/service/ProtocolNexa.cpp | 2 +- telldus-core/service/ProtocolSartano.cpp | 4 ++-- telldus-core/service/ProtocolWaveman.cpp | 2 +- telldus-core/service/ProtocolX10.cpp | 2 +- telldus-core/service/TellStick_libftdi.cpp | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index f1cdc3ad..5a24bc9f 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -151,7 +151,7 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { int methods = p->methods(); if ((action & methods) == 0) { // Loop all methods an see if any method masks to this one - for(int i = 1; i <= methods; i<<=1) { + for(int i = 1; i <= methods; i <<= 1) { if ((i & methods) == 0) { continue; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 84fe73c2..8801afbe 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -658,7 +658,7 @@ void DeviceManager::handleControllerMessage(const ControllerEventData &eventData if (!TelldusCore::comparei(it->second->getProtocolName(), msg.protocol())) { continue; } - if (! (it->second->getMethods() & msg.method())) { + if ( !(it->second->getMethods() & msg.method()) ) { continue; } diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 454b3930..5a9a58eb 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -92,7 +92,7 @@ int Protocol::getIntParameter(const std::wstring &name, int min, int max) const } bool Protocol::checkBit(int data, int bitno) { - return ((data>>bitno)&0x01); + return ((data >> bitno)&0x01); } diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index addf3680..fbd7ae90 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -45,14 +45,14 @@ std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, char preamble[] = {'R', 5, 'T', 114, 60, 1, 1, 105, ssss, ssss, 0}; strCode.append(preamble); - for(i=15;i>=0;i--) { - strCode.append(1, bits[(deviceCode>>i)&0x01]); + for(i = 15; i >= 0; i--) { + strCode.append(1, bits[(deviceCode >> i)&0x01]); } - for(i=3;i>=0;i--) { - strCode.append(1, bits[(check>>i)&0x01]); + for(i = 3; i >= 0; i--) { + strCode.append(1, bits[(check >> i)&0x01]); } - for(i=3;i>=0;i--) { - strCode.append(1, bits[(action>>i)&0x01]); + for(i = 3; i >= 0; i--) { + strCode.append(1, bits[(action >> i)&0x01]); } strCode.append(1, ssss); @@ -74,7 +74,7 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { int i; unsigned int lo, hi; - if ((x&0x3)==3) { + if ((x&0x3) == 3) { lo = x & 0x00ff; hi = x & 0xff00; lo += 4; @@ -84,7 +84,7 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { x = lo | hi; } - for(i=0;i<16;i++) { + for(i = 0; i < 16; i++) { if (x&bit) { res = res ^ bits[i]; } diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 6b246562..a776e565 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -60,7 +60,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co int checksum1 = 0; int checksum2 = 0; for (int i = 13; i >= 0; --i) { - if ((intCode>>i) & 1) { + if ((intCode >> i) & 1) { strChannels.append("TT"); if (i % 2 == 0) checksum2++; @@ -112,7 +112,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co checksum1 = 0; checksum2 = 0; for (int i = 0; i < 6; ++i) { - if ((intCode>>i) & 1) { + if ((intCode >> i) & 1) { strReturn.append("TT"); if (i % 2 == 0) checksum1++; diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index f06de6b9..72ef42e7 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -11,7 +11,7 @@ #include "service/TellStick.h" #include "common/Strings.h" -int ProtocolNexa::lastArctecCodeSwitchWasTurnOff=0; // TODO, always removing first turnon now, make more flexible (waveman too) +int ProtocolNexa::lastArctecCodeSwitchWasTurnOff = 0; // TODO, always removing first turnon now, make more flexible (waveman too) int ProtocolNexa::methods() const { if (TelldusCore::comparei(model(), L"codeswitch")) { diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 255aaca7..ef7ded13 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -52,7 +52,7 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) { sscanf(data.c_str(), "%X", &allDataIn); unsigned long mask = (1<<11); - for(int i=0;i<12;++i) { + for(int i = 0; i < 12; ++i) { allData >>= 1; if((allDataIn & mask) == 0) { allData |= (1<<11); @@ -86,7 +86,7 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) { std::stringstream retString; retString << "class:command;protocol:sartano;model:codeswitch;code:"; mask = (1<<9); - for(int i=0;i<10;i++) { + for(int i = 0; i < 10; i++) { if((code & mask) != 0) { retString << 1; } diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 0dd2b688..482699ac 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -9,7 +9,7 @@ #include #include -int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff=0; +int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff = 0; int ProtocolWaveman::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF; diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index 88b2308c..9128f689 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -115,7 +115,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont std::string ProtocolX10::decodeData(ControllerMessage& dataMsg) { int intData = 0, currentBit = 31; - bool method=0; + bool method = 0; sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); int unit = 0; diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index e22fcc83..700ff40f 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -48,7 +48,7 @@ TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore: d->running = false; Settings set; - d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true"; + d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation") == L"true"; ftdi_init(&d->ftHandle); ftdi_set_interface(&d->ftHandle, INTERFACE_ANY); From 67d8bf7fb079d0e8b4669dca6ba6ba72a0039bb4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Jun 2012 16:24:12 +0200 Subject: [PATCH 2013/2215] We need spaces after semicolon in for loops according to Google style guidelines "whitespace/semicolon" --- telldus-core/client/CallbackMainDispatcher.cpp | 2 +- telldus-core/client/telldus-core.cpp | 2 +- telldus-core/service/TellStick_libftdi.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 22723674..a9643d77 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -126,7 +126,7 @@ void CallbackMainDispatcher::cleanupCallbacks() { again = false; MutexLocker locker(&d->mutex); std::list >::iterator it = d->eventThreadList.begin(); - for (;it != d->eventThreadList.end(); ++it) { + for (; it != d->eventThreadList.end(); ++it) { if ((*it)->done()) { d->eventThreadList.erase(it); again = true; diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 989a8273..48270e84 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -1049,7 +1049,7 @@ char * WINAPI tdGetErrorString(int intErrorNo) { **/ int WINAPI tdSendRawCommand(const char *command, int reserved) { std::wstring wcommand; - for(int i = 0; i < strlen(command);++i) { + for(int i = 0; i < strlen(command); ++i) { wcommand.append(1, (unsigned char)command[i]); } Message msg(L"tdSendRawCommand"); diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 700ff40f..9cc3de19 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -159,7 +159,7 @@ void TellStick::run() { // Send a firmware version request unsigned char msg[] = "V+"; - ftdi_write_data( &d->ftHandle, msg, 2 ) ; + ftdi_write_data( &d->ftHandle, msg, 2 ); while(1) { // Is there any better way then sleeping between reads? @@ -197,7 +197,7 @@ int TellStick::send( const std::string &strMessage ) { TelldusCore::MutexLocker locker(&d->mutex); int ret; - ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ) ; + ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() ); if(ret < 0) { c = false; } else if(ret != strMessage.length()) { From 6666dc02947e3a0ddb231dcd1e5eeb6827e8d5ab Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Jun 2012 18:24:06 +0200 Subject: [PATCH 2014/2215] Do not use namespace using-directives according to Google style guidelines "build/namespaces" --- telldus-core/client/CallbackDispatcher.cpp | 4 +- .../client/CallbackMainDispatcher.cpp | 4 +- telldus-core/client/Client.cpp | 4 +- telldus-core/client/telldus-core.cpp | 162 +++++++++--------- telldus-core/common/Event.cpp | 5 +- telldus-core/common/EventHandler_unix.cpp | 4 +- telldus-core/common/Event_unix.cpp | 4 +- telldus-core/common/Message.cpp | 4 +- telldus-core/common/Mutex.cpp | 6 +- telldus-core/common/Socket_unix.cpp | 4 +- telldus-core/common/Thread.cpp | 6 +- telldus-core/service/SettingsConfuse.cpp | 2 - 12 files changed, 112 insertions(+), 97 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 91ba088b..2cae6ebb 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -9,7 +9,7 @@ #include "client/CallbackDispatcher.h" -using namespace TelldusCore; +namespace TelldusCore { TDEventDispatcher::TDEventDispatcher(EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) :Thread(), doneRunning(false), callbackData(cbd), callback(cb), callbackExecuted(cbDone) { @@ -67,3 +67,5 @@ void TDEventDispatcher::fireEvent() { ((TDControllerEvent)callback->event)(data->controllerId, data->changeEvent, data->changeType, data->newValue.c_str(), callback->id, callback->context); } } + +} // namespace TelldusCore diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index a9643d77..585c65b0 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -11,7 +11,7 @@ #include -using namespace TelldusCore; +namespace TelldusCore { typedef std::list CallbackList; @@ -135,3 +135,5 @@ void CallbackMainDispatcher::cleanupCallbacks() { } } while (again); } + +} // namespace TelldusCore diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index c0e394a1..521906d6 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -14,7 +14,7 @@ #include "common/Strings.h" #include "common/Mutex.h" -using namespace TelldusCore; +namespace TelldusCore { class Client::PrivateData { public: @@ -267,3 +267,5 @@ int Client::getController(int *controllerId, int *controllerType, char *name, in return TELLSTICK_SUCCESS; } + +} // namespace TelldusCore diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index 48270e84..fdb1f3e7 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -18,8 +18,6 @@ #include "common/Message.h" #include "common/Socket.h" -using namespace TelldusCore; - /** * @name Device method flags * Flags for the different methods/commands a device can support. Can be used @@ -319,7 +317,7 @@ using namespace TelldusCore; * @since Version 2.0.0 **/ void WINAPI tdInit(void) { - Client::getInstance(); // Create the manager-object + TelldusCore::Client::getInstance(); // Create the manager-object } /** @@ -338,8 +336,8 @@ void WINAPI tdInit(void) { * @since Version 2.0.0 **/ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { - Client *client = Client::getInstance(); - return client->registerEvent( CallbackStruct::DeviceEvent, (void *)eventFunction, context ); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); + return client->registerEvent( TelldusCore::CallbackStruct::DeviceEvent, reinterpret_cast(eventFunction), context ); } /** @@ -358,8 +356,8 @@ int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ) { * @since Version 2.0.0 **/ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { - Client *client = Client::getInstance(); - return client->registerEvent( CallbackStruct::RawDeviceEvent, (void *)eventFunction, context ); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); + return client->registerEvent( TelldusCore::CallbackStruct::RawDeviceEvent, reinterpret_cast(eventFunction), context ); } /** @@ -380,8 +378,8 @@ int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *conte * @since Version 2.1.0 **/ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context) { - Client *client = Client::getInstance(); - return client->registerEvent( CallbackStruct::DeviceChangeEvent, (void *)eventFunction, context ); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); + return client->registerEvent( TelldusCore::CallbackStruct::DeviceChangeEvent, reinterpret_cast(eventFunction), context ); } /** @@ -400,8 +398,8 @@ int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void * @since Version 2.1.0 **/ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { - Client *client = Client::getInstance(); - return client->registerEvent( CallbackStruct::SensorEvent, (void *)eventFunction, context ); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); + return client->registerEvent( TelldusCore::CallbackStruct::SensorEvent, reinterpret_cast(eventFunction), context ); } /** @@ -420,8 +418,8 @@ int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context) { * @since Version 2.1.2 **/ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context) { - Client *client = Client::getInstance(); - return client->registerEvent( CallbackStruct::ControllerEvent, (void *)eventFunction, context ); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); + return client->registerEvent( TelldusCore::CallbackStruct::ControllerEvent, reinterpret_cast(eventFunction), context ); } /** @@ -437,7 +435,7 @@ int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *con * @since Version 2.1.0 **/ int WINAPI tdUnregisterCallback( int callbackId ) { - Client *client = Client::getInstance(); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); return client->unregisterCallback( callbackId ); } @@ -448,7 +446,7 @@ int WINAPI tdUnregisterCallback( int callbackId ) { * @since Version 2.0.0 **/ void WINAPI tdClose(void) { - Client::close(); + TelldusCore::Client::close(); } /** @@ -481,9 +479,9 @@ void WINAPI tdReleaseString(char *thestring) { * @since Version 2.0.0 **/ int WINAPI tdTurnOn(int intDeviceId) { - Message msg(L"tdTurnOn"); + TelldusCore::Message msg(L"tdTurnOn"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -499,9 +497,9 @@ int WINAPI tdTurnOn(int intDeviceId) { * @since Version 2.0.0 **/ int WINAPI tdTurnOff(int intDeviceId) { - Message msg(L"tdTurnOff"); + TelldusCore::Message msg(L"tdTurnOff"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -517,9 +515,9 @@ int WINAPI tdTurnOff(int intDeviceId) { * @since Version 2.0.0 **/ int WINAPI tdBell(int intDeviceId) { - Message msg(L"tdBell"); + TelldusCore::Message msg(L"tdBell"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -537,10 +535,10 @@ int WINAPI tdBell(int intDeviceId) { * @since Version 2.0.0 **/ int WINAPI tdDim(int intDeviceId, unsigned char level) { - Message msg(L"tdDim"); + TelldusCore::Message msg(L"tdDim"); msg.addArgument(intDeviceId); msg.addArgument(level); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -556,9 +554,9 @@ int WINAPI tdDim(int intDeviceId, unsigned char level) { * @since Version 2.1.0 **/ int WINAPI tdExecute(int intDeviceId) { - Message msg(L"tdExecute"); + TelldusCore::Message msg(L"tdExecute"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -574,9 +572,9 @@ int WINAPI tdExecute(int intDeviceId) { * @since Version 2.1.0 **/ int WINAPI tdUp(int intDeviceId) { - Message msg(L"tdUp"); + TelldusCore::Message msg(L"tdUp"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -592,9 +590,9 @@ int WINAPI tdUp(int intDeviceId) { * @since Version 2.1.0 **/ int WINAPI tdDown(int intDeviceId) { - Message msg(L"tdDown"); + TelldusCore::Message msg(L"tdDown"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -610,9 +608,9 @@ int WINAPI tdDown(int intDeviceId) { * @since Version 2.1.0 */ int WINAPI tdStop(int intDeviceId) { - Message msg(L"tdStop"); + TelldusCore::Message msg(L"tdStop"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -629,9 +627,9 @@ int WINAPI tdStop(int intDeviceId) { * @since Version 2.0.0 **/ int WINAPI tdLearn(int intDeviceId) { - Message msg(L"tdLearn"); + TelldusCore::Message msg(L"tdLearn"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -649,10 +647,10 @@ int WINAPI tdLearn(int intDeviceId) { * @since Version 2.0.0 **/ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { - Message msg(L"tdLastSentCommand"); + TelldusCore::Message msg(L"tdLastSentCommand"); msg.addArgument(intDeviceId); msg.addArgument(methodsSupported); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -669,9 +667,9 @@ int WINAPI tdLastSentCommand(int intDeviceId, int methodsSupported ) { * @since Version 2.0.0 **/ char * WINAPI tdLastSentValue( int intDeviceId ) { - Message msg(L"tdLastSentValue"); + TelldusCore::Message msg(L"tdLastSentValue"); msg.addArgument(intDeviceId); - std::wstring strReturn = Client::getWStringFromService(msg); + std::wstring strReturn = TelldusCore::Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -684,7 +682,7 @@ char * WINAPI tdLastSentValue( int intDeviceId ) { * @since Version 2.0.0 **/ int WINAPI tdGetNumberOfDevices(void) { - return Client::getIntegerFromService(Message(L"tdGetNumberOfDevices")); + return TelldusCore::Client::getIntegerFromService(TelldusCore::Message(L"tdGetNumberOfDevices")); } /** @@ -708,9 +706,9 @@ int WINAPI tdGetNumberOfDevices(void) { * @since Version 2.0.0 **/ int WINAPI tdGetDeviceId(int intDeviceIndex) { - Message msg(L"tdGetDeviceId"); + TelldusCore::Message msg(L"tdGetDeviceId"); msg.addArgument(intDeviceIndex); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -727,9 +725,9 @@ int WINAPI tdGetDeviceId(int intDeviceIndex) { * @since Version 2.0.0 **/ int WINAPI tdGetDeviceType(int intDeviceId) { - Message msg(L"tdGetDeviceType"); + TelldusCore::Message msg(L"tdGetDeviceType"); msg.addArgument(intDeviceId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -745,9 +743,9 @@ int WINAPI tdGetDeviceType(int intDeviceId) { * @since Version 2.0.0 **/ char * WINAPI tdGetName(int intDeviceId) { - Message msg(L"tdGetName"); + TelldusCore::Message msg(L"tdGetName"); msg.addArgument(intDeviceId); - std::wstring strReturn = Client::getWStringFromService(msg); + std::wstring strReturn = TelldusCore::Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -766,10 +764,10 @@ char * WINAPI tdGetName(int intDeviceId) { * @since Version 2.0.0 **/ bool WINAPI tdSetName(int intDeviceId, const char* strNewName) { - Message msg(L"tdSetName"); + TelldusCore::Message msg(L"tdSetName"); msg.addArgument(intDeviceId); msg.addArgument(strNewName); - return Client::getBoolFromService(msg); + return TelldusCore::Client::getBoolFromService(msg); } /** @@ -785,9 +783,9 @@ bool WINAPI tdSetName(int intDeviceId, const char* strNewName) { * @since Version 2.0.0 **/ char* WINAPI tdGetProtocol(int intDeviceId) { - Message msg(L"tdGetProtocol"); + TelldusCore::Message msg(L"tdGetProtocol"); msg.addArgument(intDeviceId); - std::wstring strReturn = Client::getWStringFromService(msg); + std::wstring strReturn = TelldusCore::Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -809,10 +807,10 @@ char* WINAPI tdGetProtocol(int intDeviceId) { * @since Version 2.0.0 **/ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol) { - Message msg(L"tdSetProtocol"); + TelldusCore::Message msg(L"tdSetProtocol"); msg.addArgument(intDeviceId); msg.addArgument(strProtocol); - return Client::getBoolFromService(msg); + return TelldusCore::Client::getBoolFromService(msg); } /** @@ -828,9 +826,9 @@ bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol) { * @since Version 2.0.0 **/ char* WINAPI tdGetModel(int intDeviceId) { - Message msg(L"tdGetModel"); + TelldusCore::Message msg(L"tdGetModel"); msg.addArgument(intDeviceId); - std::wstring strReturn = Client::getWStringFromService(msg); + std::wstring strReturn = TelldusCore::Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -849,10 +847,10 @@ char* WINAPI tdGetModel(int intDeviceId) { * @since Version 2.0.0 **/ bool WINAPI tdSetModel(int intDeviceId, const char *strModel) { - Message msg(L"tdSetModel"); + TelldusCore::Message msg(L"tdSetModel"); msg.addArgument(intDeviceId); msg.addArgument(strModel); - return Client::getBoolFromService(msg); + return TelldusCore::Client::getBoolFromService(msg); } /** @@ -872,11 +870,11 @@ bool WINAPI tdSetModel(int intDeviceId, const char *strModel) { * @since Version 2.0.0 **/ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char *strValue) { - Message msg(L"tdSetDeviceParameter"); + TelldusCore::Message msg(L"tdSetDeviceParameter"); msg.addArgument(intDeviceId); msg.addArgument(strName); msg.addArgument(strValue); - return Client::getBoolFromService(msg); + return TelldusCore::Client::getBoolFromService(msg); } /** @@ -897,11 +895,11 @@ bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const cha * @since Version 2.0.0 **/ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue) { - Message msg(L"tdGetDeviceParameter"); + TelldusCore::Message msg(L"tdGetDeviceParameter"); msg.addArgument(intDeviceId); msg.addArgument(strName); msg.addArgument(defaultValue); - std::wstring strReturn = Client::getWStringFromService(msg); + std::wstring strReturn = TelldusCore::Client::getWStringFromService(msg); return wrapStdWstring(strReturn); } @@ -917,8 +915,8 @@ char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const c * @since Version 2.0.0 **/ int WINAPI tdAddDevice() { - Message msg(L"tdAddDevice"); - return Client::getIntegerFromService(msg); + TelldusCore::Message msg(L"tdAddDevice"); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -933,9 +931,9 @@ int WINAPI tdAddDevice() { * @since Version 2.0.0 **/ bool WINAPI tdRemoveDevice(int intDeviceId) { - Message msg(L"tdRemoveDevice"); + TelldusCore::Message msg(L"tdRemoveDevice"); msg.addArgument(intDeviceId); - return Client::getBoolFromService(msg); + return TelldusCore::Client::getBoolFromService(msg); } /** @@ -974,10 +972,10 @@ bool WINAPI tdRemoveDevice(int intDeviceId) { * @since Version 2.0.0 **/ int WINAPI tdMethods(int id, int methodsSupported) { - Message msg(L"tdMethods"); + TelldusCore::Message msg(L"tdMethods"); msg.addArgument(id); msg.addArgument(methodsSupported); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -1052,10 +1050,10 @@ int WINAPI tdSendRawCommand(const char *command, int reserved) { for(int i = 0; i < strlen(command); ++i) { wcommand.append(1, (unsigned char)command[i]); } - Message msg(L"tdSendRawCommand"); + TelldusCore::Message msg(L"tdSendRawCommand"); msg.addArgument(wcommand); msg.addArgument(reserved); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -1071,11 +1069,11 @@ int WINAPI tdSendRawCommand(const char *command, int reserved) { * @since Version 2.1.0 **/ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { - Message msg(L"tdConnectTellStickController"); + TelldusCore::Message msg(L"tdConnectTellStickController"); msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); - Client::getWStringFromService(msg); + TelldusCore::Client::getWStringFromService(msg); } /** @@ -1091,11 +1089,11 @@ void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial) { * @since Version 2.1.0 **/ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial) { - Message msg(L"tdDisconnectTellStickController"); + TelldusCore::Message msg(L"tdDisconnectTellStickController"); msg.addArgument(vid); msg.addArgument(pid); msg.addArgument(serial); - Client::getWStringFromService(msg); + TelldusCore::Client::getWStringFromService(msg); } /** @@ -1121,7 +1119,7 @@ void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial * @since Version 2.1.0 */ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes) { - Client *client = Client::getInstance(); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); return client->getSensor(protocol, protocolLen, model, modelLen, id, dataTypes); } @@ -1153,18 +1151,18 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, * @since Version 2.1.0 */ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp) { - Message msg(L"tdSensorValue"); + TelldusCore::Message msg(L"tdSensorValue"); msg.addArgument(protocol); msg.addArgument(model); msg.addArgument(id); msg.addArgument(dataType); - std::wstring retval = Client::getWStringFromService(msg); + std::wstring retval = TelldusCore::Client::getWStringFromService(msg); if (retval.length() == 0) { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } - std::wstring v = Message::takeString(&retval); - int t = Message::takeInt(&retval); + std::wstring v = TelldusCore::Message::takeString(&retval); + int t = TelldusCore::Message::takeInt(&retval); if (value && len) { strncpy(value, TelldusCore::wideToString(v).c_str(), len); } @@ -1200,7 +1198,7 @@ int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int da * @since Version 2.1.2 **/ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available) { - Client *client = Client::getInstance(); + TelldusCore::Client *client = TelldusCore::Client::getInstance(); return client->getController(controllerId, controllerType, name, nameLen, available); } @@ -1223,10 +1221,10 @@ int WINAPI tdController(int *controllerId, int *controllerType, char *name, int * @since Version 2.1.2 **/ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen) { - Message msg(L"tdControllerValue"); + TelldusCore::Message msg(L"tdControllerValue"); msg.addArgument(controllerId); msg.addArgument(name); - std::wstring retval = Client::getWStringFromService(msg); + std::wstring retval = TelldusCore::Client::getWStringFromService(msg); if (retval.length() == 0) { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } @@ -1254,11 +1252,11 @@ int WINAPI tdControllerValue(int controllerId, const char *name, char *value, in * @since Version 2.1.2 **/ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value) { - Message msg(L"tdSetControllerValue"); + TelldusCore::Message msg(L"tdSetControllerValue"); msg.addArgument(controllerId); msg.addArgument(name); msg.addArgument(value); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /** @@ -1276,9 +1274,9 @@ int WINAPI tdSetControllerValue(int controllerId, const char *name, const char * * @since Version 2.1.2 **/ int WINAPI tdRemoveController(int controllerId) { - Message msg(L"tdRemoveController"); + TelldusCore::Message msg(L"tdRemoveController"); msg.addArgument(controllerId); - return Client::getIntegerFromService(msg); + return TelldusCore::Client::getIntegerFromService(msg); } /* @} */ diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index fa4176fd..40dbea8d 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -9,8 +9,7 @@ #include "common/EventHandler.h" #include "common/Mutex.h" - -using namespace TelldusCore; +namespace TelldusCore { EventData::~EventData() { } @@ -81,3 +80,5 @@ EventDataRef EventBase::takeSignal() { } return data; } + +} // namespace TelldusCore diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 2297594d..46fc949a 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -12,7 +12,7 @@ #include "common/Mutex.h" #include "common/Thread.h" -using namespace TelldusCore; +namespace TelldusCore { class EventHandler::PrivateData { public: @@ -76,3 +76,5 @@ bool EventHandler::waitForAny() { return true; } + +} // namespace TelldusCore diff --git a/telldus-core/common/Event_unix.cpp b/telldus-core/common/Event_unix.cpp index a2630412..301b6b2e 100644 --- a/telldus-core/common/Event_unix.cpp +++ b/telldus-core/common/Event_unix.cpp @@ -8,7 +8,7 @@ #include "common/EventHandler.h" #include "common/Thread.h" -using namespace TelldusCore; +namespace TelldusCore { class Event::PrivateData { public: @@ -32,3 +32,5 @@ void Event::sendSignal() { handler->signal(this); } } + +} // namespace TelldusCore diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index 7c05895c..f06c75fb 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -11,7 +11,7 @@ #include "common/Socket.h" #include "common/Strings.h" -using namespace TelldusCore; +namespace TelldusCore { Message::Message() : std::wstring() { @@ -128,3 +128,5 @@ int Message::takeInt(std::wstring *message) { message->erase(0, index+1); return value; } + +} // namespace TelldusCore diff --git a/telldus-core/common/Mutex.cpp b/telldus-core/common/Mutex.cpp index 6b17b2e5..003a0f8b 100644 --- a/telldus-core/common/Mutex.cpp +++ b/telldus-core/common/Mutex.cpp @@ -12,8 +12,6 @@ #include "common/Mutex.h" -using namespace TelldusCore; - #ifdef _WINDOWS #include typedef HANDLE MUTEX_T; @@ -24,6 +22,8 @@ using namespace TelldusCore; #include "common/common.h" +namespace TelldusCore { + class Mutex::PrivateData { public: MUTEX_T mutex; @@ -84,3 +84,5 @@ MutexLocker::MutexLocker(Mutex *m) MutexLocker::~MutexLocker() { mutex->unlock(); } + +} // namespace TelldusCore diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 0573a494..b837c507 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -18,7 +18,7 @@ #define BUFSIZE 512 -using namespace TelldusCore; +namespace TelldusCore { int connectWrapper(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { return connect(sockfd, addr, addrlen); @@ -132,3 +132,5 @@ void Socket::write(const std::wstring &msg) { d->connected = false; } } + +} // namespace TelldusCore diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index c66ff604..f428dfcd 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -16,9 +16,9 @@ #endif #include "common/EventHandler.h" -using namespace TelldusCore; +namespace TelldusCore { -class TelldusCore::ThreadPrivate { +class ThreadPrivate { public: bool running; EventRef threadStarted; @@ -92,3 +92,5 @@ void *Thread::exec( void *ptr ) { #endif return 0; } + +} // namespace TelldusCore diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 89af7d09..33574991 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -14,8 +14,6 @@ #include "client/telldus-core.h" #include "common/Strings.h" -using namespace std; - class Settings::PrivateData { public: cfg_t *cfg; From 3dcc7a04ba25896fecb04307e40c6711720ae41f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Jun 2012 16:45:39 +0200 Subject: [PATCH 2015/2215] Use int16/int64/etc, rather than the C types according to Google style guidelines "runtime/int" --- telldus-core/service/ProtocolNexa.cpp | 8 ++++---- telldus-core/service/ProtocolNexa.h | 5 +++-- telldus-core/service/ProtocolSartano.cpp | 3 ++- telldus-core/service/ProtocolWaveman.cpp | 5 +++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 72ef42e7..00e39e77 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -165,9 +165,9 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode } std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) { - unsigned long allData = 0; + uint32_t allData = 0; - sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); + sscanf(dataMsg.getParameter("data").c_str(), "%lx", (long*)&allData); // NOLINT(runtime/int) if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { // selflearning @@ -179,7 +179,7 @@ std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) { } } -std::string ProtocolNexa::decodeDataSelfLearning(long allData) { +std::string ProtocolNexa::decodeDataSelfLearning(uint32_t allData) { unsigned int house = 0; unsigned int unit = 0; unsigned int group = 0; @@ -218,7 +218,7 @@ std::string ProtocolNexa::decodeDataSelfLearning(long allData) { return retString.str(); } -std::string ProtocolNexa::decodeDataCodeSwitch(long allData) { +std::string ProtocolNexa::decodeDataCodeSwitch(uint32_t allData) { unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 37e6b813..4ed480c8 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ +#include #include #include "service/ControllerMessage.h" #include "service/Device.h" @@ -27,8 +28,8 @@ protected: private: static int lastArctecCodeSwitchWasTurnOff; - static std::string decodeDataCodeSwitch(long allData); - static std::string decodeDataSelfLearning(long allData); + static std::string decodeDataCodeSwitch(uint32_t allData); + static std::string decodeDataSelfLearning(uint32_t allData); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index ef7ded13..1476dff3 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolSartano.h" +#include #include #include #include @@ -51,7 +52,7 @@ std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) { sscanf(data.c_str(), "%X", &allDataIn); - unsigned long mask = (1<<11); + uint16_t mask = (1<<11); for(int i = 0; i < 12; ++i) { allData >>= 1; if((allDataIn & mask) == 0) { diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 482699ac..bc784720 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolWaveman.h" +#include #include #include #include @@ -24,12 +25,12 @@ std::string ProtocolWaveman::getOffCode() const { } std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) { - unsigned long allData = 0; + uint32_t allData = 0; unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; - sscanf(dataMsg.getParameter("data").c_str(), "%lx", &allData); + sscanf(dataMsg.getParameter("data").c_str(), "%lx", (long*)&allData); // NOLINT(runtime/int) method = allData & 0xF00; method >>= 8; From 1ac3fc25e0d4957925d7d72c6b14607ffe17f9d7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Jun 2012 16:27:22 +0200 Subject: [PATCH 2016/2215] Use pointers when passing references according to Google style guidelines "runtime/references" --- telldus-core/service/DeviceManager.cpp | 10 +++++----- telldus-core/service/DeviceManager.h | 2 +- telldus-core/service/Protocol.cpp | 2 +- telldus-core/service/Protocol.h | 2 +- telldus-core/service/ProtocolEverflourish.cpp | 6 +++--- telldus-core/service/ProtocolEverflourish.h | 2 +- telldus-core/service/ProtocolFineoffset.cpp | 2 +- telldus-core/service/ProtocolFineoffset.h | 2 +- telldus-core/service/ProtocolHasta.cpp | 4 ++-- telldus-core/service/ProtocolMandolyn.cpp | 2 +- telldus-core/service/ProtocolMandolyn.h | 2 +- telldus-core/service/ProtocolNexa.cpp | 2 +- telldus-core/service/ProtocolNexa.h | 2 +- telldus-core/service/ProtocolOregon.cpp | 2 +- telldus-core/service/ProtocolOregon.h | 2 +- telldus-core/service/ProtocolSartano.cpp | 2 +- telldus-core/service/ProtocolSartano.h | 2 +- telldus-core/service/ProtocolWaveman.cpp | 2 +- telldus-core/service/ProtocolWaveman.h | 2 +- telldus-core/service/ProtocolX10.cpp | 2 +- telldus-core/service/ProtocolX10.h | 2 +- 21 files changed, 28 insertions(+), 28 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 8801afbe..0c36ccc5 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -126,10 +126,10 @@ int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported) { int DeviceManager::getDeviceMethods(int deviceId) { std::set duplicateDeviceIds; - return DeviceManager::getDeviceMethods(deviceId, duplicateDeviceIds); + return DeviceManager::getDeviceMethods(deviceId, &duplicateDeviceIds); } -int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDeviceIds) { +int DeviceManager::getDeviceMethods(int deviceId, std::set *duplicateDeviceIds) { int type = 0; int methods = 0; std::wstring deviceIds; @@ -162,16 +162,16 @@ int DeviceManager::getDeviceMethods(int deviceId, std::set &duplicateDevice std::wstringstream devicesstream(deviceIds); methods = 0; - duplicateDeviceIds.insert(deviceId); + duplicateDeviceIds->insert(deviceId); while(std::getline(devicesstream, deviceIdBuffer, L',')) { int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer); - if(duplicateDeviceIds.count(deviceIdInGroup) == 1) { + if(duplicateDeviceIds->count(deviceIdInGroup) == 1) { // action for device already executed, or will execute, do nothing to avoid infinite loop continue; } - duplicateDeviceIds.insert(deviceIdInGroup); + duplicateDeviceIds->insert(deviceIdInGroup); int deviceMethods = getDeviceMethods(deviceIdInGroup, duplicateDeviceIds); if(deviceMethods > 0) { diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 152dec12..6a94b7e5 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -52,7 +52,7 @@ public: private: void handleSensorMessage(const ControllerMessage &msg); void setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const; - int getDeviceMethods(int deviceId, std::set &duplicateDeviceIds); + int getDeviceMethods(int deviceId, std::set *duplicateDeviceIds); int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId, std::set *duplicateDeviceIds); int executeScene(std::wstring singledevice, int groupDeviceId); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index 5a9a58eb..defc7775 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -61,7 +61,7 @@ void Protocol::setModel(const std::wstring &model) { d->model = model; } -void Protocol::setParameters(ParameterMap ¶meterList) { +void Protocol::setParameters(const ParameterMap ¶meterList) { d->parameterList = parameterList; } diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index ac48c7a4..c45da20c 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -28,7 +28,7 @@ public: virtual int methods() const = 0; std::wstring model() const; void setModel(const std::wstring &model); - void setParameters(ParameterMap ¶meterList); + void setParameters(const ParameterMap ¶meterList); virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0; diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index fbd7ae90..069771d6 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -74,7 +74,7 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { int i; unsigned int lo, hi; - if ((x&0x3) == 3) { + if ((x & 0x3) == 3) { lo = x & 0x00ff; hi = x & 0xff00; lo += 4; @@ -85,7 +85,7 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { } for(i = 0; i < 16; i++) { - if (x&bit) { + if (x & bit) { res = res ^ bits[i]; } bit = bit << 1; @@ -94,7 +94,7 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { return res; } -std::string ProtocolEverflourish::decodeData(ControllerMessage &dataMsg) { +std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); unsigned int allData; unsigned int house = 0; diff --git a/telldus-core/service/ProtocolEverflourish.h b/telldus-core/service/ProtocolEverflourish.h index 4118407f..ae4abf7c 100644 --- a/telldus-core/service/ProtocolEverflourish.h +++ b/telldus-core/service/ProtocolEverflourish.h @@ -15,7 +15,7 @@ class ProtocolEverflourish : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(ControllerMessage &dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); private: static unsigned int calculateChecksum(unsigned int x); diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index d7b8119e..daa3635e 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -11,7 +11,7 @@ #include #include "common/Strings.h" -std::string ProtocolFineoffset::decodeData(ControllerMessage &dataMsg) { +std::string ProtocolFineoffset::decodeData(const ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); if (data.length() < 8) { return ""; diff --git a/telldus-core/service/ProtocolFineoffset.h b/telldus-core/service/ProtocolFineoffset.h index 94894f2e..b3bc3ce1 100644 --- a/telldus-core/service/ProtocolFineoffset.h +++ b/telldus-core/service/ProtocolFineoffset.h @@ -13,7 +13,7 @@ class ProtocolFineoffset : public Protocol { public: - static std::string decodeData(ControllerMessage &dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_ diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index d89c4830..0c5899de 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -26,8 +26,8 @@ std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Control strReturn.append(1, 190); strReturn.append(1, 190); - strReturn.append(convertByte( (house&0xFF) )); - strReturn.append(convertByte( (house>>8)&0xFF )); + strReturn.append(convertByte( (house & 0xFF) )); + strReturn.append(convertByte( (house>>8) & 0xFF )); int byte = unit&0x0F; diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index fd720893..555f67d0 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -11,7 +11,7 @@ #include #include "common/Strings.h" -std::string ProtocolMandolyn::decodeData(ControllerMessage &dataMsg) { +std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); uint32_t value = (uint32_t)TelldusCore::hexTo64l(data); diff --git a/telldus-core/service/ProtocolMandolyn.h b/telldus-core/service/ProtocolMandolyn.h index ee9a69cd..8fcd90a5 100644 --- a/telldus-core/service/ProtocolMandolyn.h +++ b/telldus-core/service/ProtocolMandolyn.h @@ -13,7 +13,7 @@ class ProtocolMandolyn : public Protocol { public: - static std::string decodeData(ControllerMessage &dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_ diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 00e39e77..8c95514a 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -164,7 +164,7 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode return strMessage; } -std::string ProtocolNexa::decodeData(ControllerMessage& dataMsg) { +std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) { uint32_t allData = 0; sscanf(dataMsg.getParameter("data").c_str(), "%lx", (long*)&allData); // NOLINT(runtime/int) diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 4ed480c8..7b65ae8f 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -16,7 +16,7 @@ class ProtocolNexa : public Protocol { public: virtual int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(ControllerMessage& dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); protected: std::string getStringSelflearning(int method, unsigned char data); diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 6870929d..062c33af 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -11,7 +11,7 @@ #include #include "common/Strings.h" -std::string ProtocolOregon::decodeData(ControllerMessage &dataMsg) { +std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); std::wstring model = dataMsg.model(); diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index bfa9662a..1da70dc1 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -13,7 +13,7 @@ class ProtocolOregon : public Protocol { public: - static std::string decodeData(ControllerMessage &dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); protected: static std::string decodeEA4C(const std::string &data); diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 1476dff3..bb36d5a0 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -41,7 +41,7 @@ std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int m return strReturn; } -std::string ProtocolSartano::decodeData(ControllerMessage &dataMsg) { +std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); signed int allDataIn; signed int allData = 0; diff --git a/telldus-core/service/ProtocolSartano.h b/telldus-core/service/ProtocolSartano.h index 1480be83..d644a0e8 100644 --- a/telldus-core/service/ProtocolSartano.h +++ b/telldus-core/service/ProtocolSartano.h @@ -15,7 +15,7 @@ class ProtocolSartano : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(ControllerMessage &dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); protected: std::string getStringForCode(const std::wstring &code, int method); diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index bc784720..77a7a1bf 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -24,7 +24,7 @@ std::string ProtocolWaveman::getOffCode() const { return "$k$k$k$k$k$k$k$k$k+"; } -std::string ProtocolWaveman::decodeData(ControllerMessage& dataMsg) { +std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) { uint32_t allData = 0; unsigned int house = 0; unsigned int unit = 0; diff --git a/telldus-core/service/ProtocolWaveman.h b/telldus-core/service/ProtocolWaveman.h index 200066fd..a6feb394 100644 --- a/telldus-core/service/ProtocolWaveman.h +++ b/telldus-core/service/ProtocolWaveman.h @@ -14,7 +14,7 @@ class ProtocolWaveman : public ProtocolNexa { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(ControllerMessage& dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); protected: virtual std::string getOffCode() const; diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index 9128f689..a5883627 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -113,7 +113,7 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont return strReturn; } -std::string ProtocolX10::decodeData(ControllerMessage& dataMsg) { +std::string ProtocolX10::decodeData(const ControllerMessage& dataMsg) { int intData = 0, currentBit = 31; bool method = 0; sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); diff --git a/telldus-core/service/ProtocolX10.h b/telldus-core/service/ProtocolX10.h index 7977399a..c8cf8422 100644 --- a/telldus-core/service/ProtocolX10.h +++ b/telldus-core/service/ProtocolX10.h @@ -16,7 +16,7 @@ public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); - static std::string decodeData(ControllerMessage& dataMsg); + static std::string decodeData(const ControllerMessage &dataMsg); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLX10_H_ From 31ee1880adc079678288a773d34a118429f700da Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Jun 2012 16:07:18 +0200 Subject: [PATCH 2017/2215] Use sizeof(varname) instead of sizeof(type) according to Google style guidelines "runtime/sizeof" --- telldus-core/common/Strings.cpp | 7 ++++--- telldus-core/common/common.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 6b2f1bf2..29aca4a6 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -178,7 +178,7 @@ std::string TelldusCore::wideToString(const std::wstring &input) { } char *buffer; buffer = new char[size]; - memset(buffer, 0, sizeof(char)*size); + memset(buffer, 0, sizeof(*buffer)*size); int bytes = WideCharToMultiByte(CP_UTF8, 0, input.c_str(), -1, buffer, size, NULL, NULL); std::string retval(buffer); @@ -187,7 +187,8 @@ std::string TelldusCore::wideToString(const std::wstring &input) { #else size_t wideSize = sizeof(wchar_t)*input.length(); - size_t outbytesLeft = wideSize+sizeof(char); // We cannot know how many wide character there is yet + // We cannot know how many wide character there is yet + size_t outbytesLeft = wideSize+sizeof(char); // NOLINT(runtime/sizeof) // Copy the instring char *inString = (char*)new wchar_t[input.length()+1]; @@ -195,7 +196,7 @@ std::string TelldusCore::wideToString(const std::wstring &input) { // Create buffer for output char *outString = new char[outbytesLeft]; - memset(outString, 0, sizeof(char)*(outbytesLeft)); + memset(outString, 0, sizeof(*outString)*(outbytesLeft)); #ifdef _FREEBSD const char *inPointer = inString; diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 13e39bda..bbb0a783 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -69,7 +69,8 @@ inline char *wrapStdString( const std::string &string) { #ifdef _WINDOWS return (char *)SysAllocStringByteLen(string.c_str(), (unsigned int)string.size()); #else - char *returnVal = (char *)malloc(sizeof(char) * (string.size()+1)); + char *returnVal; + returnVal = (char *)malloc(sizeof(*returnVal) * (string.size()+1)); strcpy(returnVal, string.c_str()); return returnVal; #endif From 2fc9d470dd9280b8e3e5a021ca52b2d407c01f2c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Jun 2012 16:20:31 +0200 Subject: [PATCH 2018/2215] If an else has a brace on one side, it should have it on both according to Google style guidelines "readability/braces" --- .../service/ClientCommunicationHandler.cpp | 3 +- telldus-core/service/DeviceManager.cpp | 35 +++++++------------ telldus-core/service/EventUpdateManager.cpp | 15 +++----- telldus-core/service/ProtocolEverflourish.cpp | 9 ++--- telldus-core/service/ProtocolNexa.cpp | 18 ++++------ telldus-core/service/ProtocolSartano.cpp | 12 +++---- 6 files changed, 31 insertions(+), 61 deletions(-) diff --git a/telldus-core/service/ClientCommunicationHandler.cpp b/telldus-core/service/ClientCommunicationHandler.cpp index 7291590e..16700697 100644 --- a/telldus-core/service/ClientCommunicationHandler.cpp +++ b/telldus-core/service/ClientCommunicationHandler.cpp @@ -55,8 +55,7 @@ void ClientCommunicationHandler::run() { if(strReturn == L"") { msg.addArgument(intReturn); - } - else { + } else { msg.addArgument(strReturn); } msg.append(L"\n"); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 0c36ccc5..902145a9 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -93,15 +93,14 @@ int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported) int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value) { TelldusCore::MutexLocker deviceListLocker(&d->lock); if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; + return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } DeviceMap::iterator it = d->devices.find(deviceId); if (it != d->devices.end()) { TelldusCore::MutexLocker deviceLocker(it->second); d->set.setDeviceState(deviceId, command, value); it->second->setLastSentCommand(command, value); - } - else { + } else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } return TELLSTICK_SUCCESS; @@ -208,8 +207,7 @@ int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) { return ret; } it->second->setModel(model); - } - else { + } else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -242,8 +240,7 @@ int DeviceManager::setDeviceName(int deviceId, const std::wstring &name) { return ret; } it->second->setName(name); - } - else { + } else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -279,8 +276,7 @@ int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, co return ret; } it->second->setParameter(name, value); - } - else { + } else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -313,8 +309,7 @@ int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) return ret; } it->second->setProtocolName(protocol); - } - else { + } else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } @@ -424,8 +419,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data) { deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); device = it->second; } // devicelist unlocked - } - else { + } else { Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); if(!controller) { Log::warning("Trying to execute action, but no controller found. Rescanning USB ports"); @@ -487,17 +481,14 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)) { deviceReturnValue = executeScene(singledevice, groupDeviceId); - } - else if(type == TELLSTICK_TYPE_GROUP) { + } else if(type == TELLSTICK_TYPE_GROUP) { if(deviceId != 0) { int childType = DeviceManager::getDeviceType(deviceId); if(childType == TELLSTICK_TYPE_DEVICE) { deviceReturnValue = doAction(deviceId, action, data); - } - else if(childType == TELLSTICK_TYPE_SCENE) { + } else if(childType == TELLSTICK_TYPE_SCENE) { deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); // TODO make scenes infinite loops-safe - } - else { + } else { // group (in group) deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); @@ -509,8 +500,7 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c } } } - } - else { + } else { deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; // Probably incorrectly formatted parameter } } @@ -577,8 +567,7 @@ int DeviceManager::removeDevice(int deviceId) { if (it != d->devices.end()) { device = it->second; d->devices.erase(it); // remove from list, keep reference - } - else { + } else { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; } } diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index b81ec06a..bc8a5f12 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -85,19 +85,16 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { msg.addArgument(data->deviceId); msg.addArgument(data->eventState); msg.addArgument(data->eventValue); // string - } - else if(data->messageType == L"TDDeviceChangeEvent") { + } else if(data->messageType == L"TDDeviceChangeEvent") { msg.addArgument("TDDeviceChangeEvent"); msg.addArgument(data->deviceId); msg.addArgument(data->eventDeviceChanges); msg.addArgument(data->eventChangeType); - } - else if(data->messageType == L"TDRawDeviceEvent") { + } else if(data->messageType == L"TDRawDeviceEvent") { msg.addArgument("TDRawDeviceEvent"); msg.addArgument(data->eventValue); // string msg.addArgument(data->controllerId); - } - else if(data->messageType == L"TDSensorEvent") { + } else if(data->messageType == L"TDSensorEvent") { msg.addArgument("TDSensorEvent"); msg.addArgument(data->protocol); msg.addArgument(data->model); @@ -105,8 +102,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { msg.addArgument(data->dataType); msg.addArgument(data->value); msg.addArgument(data->timestamp); - } - else if(data->messageType == L"TDControllerEvent") { + } else if(data->messageType == L"TDControllerEvent") { msg.addArgument("TDControllerEvent"); msg.addArgument(data->controllerId); msg.addArgument(data->eventState); @@ -117,8 +113,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { (*it)->write(msg); it++; - } - else { + } else { // connection is dead, remove it delete *it; it = d->clients.erase(it); diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 069771d6..4b7866ec 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -121,14 +121,11 @@ std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) { retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:"; if(method == 0) { retString << "turnoff;"; - } - else if(method == 15) { + } else if(method == 15) { retString << "turnon;"; - } - else if(method == 10) { + } else if(method == 10) { retString << "learn;"; - } - else { + } else { // not everflourish return ""; } diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 8c95514a..daa91560 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -172,8 +172,7 @@ std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) { if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { // selflearning return decodeDataSelfLearning(allData); - } - else { + } else { // codeswitch return decodeDataCodeSwitch(allData); } @@ -206,11 +205,9 @@ std::string ProtocolNexa::decodeDataSelfLearning(uint32_t allData) { retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:"; if(method == 1) { retString << "turnon;"; - } - else if(method == 0) { + } else if(method == 0) { retString << "turnoff;"; - } - else { + } else { // not arctech selflearning return ""; } @@ -254,14 +251,11 @@ std::string ProtocolNexa::decodeDataCodeSwitch(uint32_t allData) { if(method == 6) { retString << ";unit:" << unit << ";method:turnoff;"; - } - else if(method == 14) { + } else if(method == 14) { retString << ";unit:" << unit << ";method:turnon;"; - } - else if(method == 15) { + } else if(method == 15) { retString << ";method:bell;"; - } - else { + } else { // not arctech codeswitch return ""; } diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index bb36d5a0..90c95023 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -71,11 +71,9 @@ std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { if(method1 == 0 && method2 == 1) { method = 0; // off - } - else if(method1 == 1 && method2 == 0) { + } else if(method1 == 1 && method2 == 0) { method = 1; // on - } - else { + } else { return ""; } @@ -90,8 +88,7 @@ std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { for(int i = 0; i < 10; i++) { if((code & mask) != 0) { retString << 1; - } - else { + } else { retString << 0; } mask >>= 1; @@ -100,8 +97,7 @@ std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { if(method == 0) { retString << "turnoff;"; - } - else { + } else { retString << "turnon;"; } From 5d2e3f33c87bff86f7fe5b287bf8e4bf9f153e90 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 8 Jun 2012 16:28:34 +0200 Subject: [PATCH 2019/2215] Use C++ casting instead of C casting according to Google style guidelines "readability/casting" --- telldus-core/common/Strings.cpp | 10 +++++----- telldus-core/common/common.h | 6 +++--- telldus-core/service/ControllerManager.cpp | 2 +- telldus-core/service/DeviceManager.cpp | 8 ++++---- telldus-core/service/Log.cpp | 8 ++++---- telldus-core/service/ProtocolFineoffset.cpp | 2 +- telldus-core/service/ProtocolMandolyn.cpp | 4 ++-- telldus-core/service/ProtocolNexa.cpp | 4 ++-- telldus-core/service/ProtocolOregon.cpp | 4 ++-- telldus-core/service/ProtocolWaveman.cpp | 4 ++-- telldus-core/service/ProtocolX10.cpp | 2 +- telldus-core/service/TellStick_libftdi.cpp | 2 +- 12 files changed, 28 insertions(+), 28 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 29aca4a6..d29ee203 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -50,7 +50,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { strcpy(inString, value); // Create buffer for output - char *outString = (char*)new wchar_t[utf8Length+1]; + char *outString = reinterpret_cast(new wchar_t[utf8Length+1]); memset(outString, 0, sizeof(wchar_t)*(utf8Length+1)); #ifdef _FREEBSD @@ -64,7 +64,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { iconv(convDesc, &inPointer, &utf8Length, &outPointer, &outbytesLeft); iconv_close(convDesc); - std::wstring retval( (wchar_t *)outString ); + std::wstring retval( reinterpret_cast(outString) ); // Cleanup delete[] inString; @@ -191,7 +191,7 @@ std::string TelldusCore::wideToString(const std::wstring &input) { size_t outbytesLeft = wideSize+sizeof(char); // NOLINT(runtime/sizeof) // Copy the instring - char *inString = (char*)new wchar_t[input.length()+1]; + char *inString = reinterpret_cast(new wchar_t[input.length()+1]); memcpy(inString, input.c_str(), wideSize+sizeof(wchar_t)); // Create buffer for output @@ -233,7 +233,7 @@ std::string TelldusCore::sformatf(const char *format, va_list ap) { int size = 100; /* Guess we need no more than 100 bytes. */ char *p, *np; - if ((p = (char*)malloc(size)) == NULL) { + if ((p = reinterpret_cast(malloc(size))) == NULL) { return ""; } @@ -255,7 +255,7 @@ std::string TelldusCore::sformatf(const char *format, va_list ap) { } else { /* glibc 2.0 */ size *= 2; /* twice the old size */ } - if ((np = (char *)realloc (p, size)) == NULL) { + if ((np = reinterpret_cast(realloc (p, size))) == NULL) { free(p); return ""; } else { diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index bbb0a783..6ead6c8b 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -58,7 +58,7 @@ inline void debuglog(const int intMessage, const std::string strMessage) { #elif !defined(_MACOSX) && !defined(__FreeBSD__) pthread_t thread = pthread_self(); - printf("[%i] %i - %s\n", (int)thread, intMessage, strMessage.c_str()); + printf("[%i] %i - %s\n", static_cast(thread), intMessage, strMessage.c_str()); fflush(stdout); #else printf("%i - %s\n", intMessage, strMessage.c_str()); @@ -67,10 +67,10 @@ inline void debuglog(const int intMessage, const std::string strMessage) { inline char *wrapStdString( const std::string &string) { #ifdef _WINDOWS - return (char *)SysAllocStringByteLen(string.c_str(), (unsigned int)string.size()); + return reinterpret_cast(SysAllocStringByteLen(string.c_str(), (unsigned int)string.size())); #else char *returnVal; - returnVal = (char *)malloc(sizeof(*returnVal) * (string.size()+1)); + returnVal = reinterpret_cast(malloc(sizeof(*returnVal) * (string.size()+1))); strcpy(returnVal, string.c_str()); return returnVal; #endif diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 977ff598..b1ce2ce1 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -265,7 +265,7 @@ std::wstring ControllerManager::getControllers() const { TelldusCore::Message msg; - msg.addArgument((int)d->controllers.size()); + msg.addArgument(static_cast(d->controllers.size())); for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { msg.addArgument(it->first); diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 902145a9..f17cc5a5 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -318,7 +318,7 @@ int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) int DeviceManager::getNumberOfDevices() { TelldusCore::MutexLocker deviceListLocker(&d->lock); - return (int)d->devices.size(); + return static_cast(d->devices.size()); } int DeviceManager::addDevice() { @@ -582,7 +582,7 @@ std::wstring DeviceManager::getSensors() const { TelldusCore::Message msg; - msg.addArgument((int)d->sensorList.size()); + msg.addArgument(static_cast(d->sensorList.size())); for (std::list::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) { TelldusCore::MutexLocker sensorLocker(*it); @@ -621,7 +621,7 @@ std::wstring DeviceManager::getSensorValue(const std::wstring &protocol, const s std::string value = sensor->value(dataType); if (value.length() > 0) { msg.addArgument(TelldusCore::charToWstring(value.c_str())); - msg.addArgument((int)sensor->timestamp()); + msg.addArgument(static_cast(sensor->timestamp())); } return msg; } @@ -714,7 +714,7 @@ void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int da eventData->sensorId = sensor->id(); eventData->dataType = dataTypeId; eventData->value = TelldusCore::charToWstring(sensor->value(dataTypeId).c_str()); - eventData->timestamp = (int)timestamp; + eventData->timestamp = static_cast(timestamp); d->deviceUpdateEvent->signal(eventData); } diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 91ad5b95..13281c59 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -162,16 +162,16 @@ void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const switch (logLevel) { case Debug: - ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); break; case Notice: - ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); break; case Warning: - ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); break; case Error: - ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); break; } #endif diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index daa3635e..c4daca58 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -38,7 +38,7 @@ std::string ProtocolFineoffset::decodeData(const ControllerMessage &dataMsg) { retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:"; if (humidity <= 100) { - retString << "temperaturehumidity;humidity:" << (int)humidity << ";"; + retString << "temperaturehumidity;humidity:" << static_cast(humidity) << ";"; } else if (humidity == 0xFF) { retString << "temperature;"; } else { diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index 555f67d0..1f5f3155 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -18,7 +18,7 @@ std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) { bool parity = value & 0x1; value >>= 1; - double temp = (double)(value & 0x7FFF) - (double)6400; + double temp = static_cast(value & 0x7FFF) - static_cast(6400); temp = temp/128.0; value >>= 15; @@ -38,7 +38,7 @@ std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) { << house*10+channel << ";model:temperaturehumidity;" << "temp:" << std::fixed << std::setprecision(1) << temp - << ";humidity:" << (int)humidity << ";"; + << ";humidity:" << static_cast(humidity) << ";"; return retString.str(); } diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index daa91560..3965b2b7 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -167,7 +167,7 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) { uint32_t allData = 0; - sscanf(dataMsg.getParameter("data").c_str(), "%lx", (long*)&allData); // NOLINT(runtime/int) + sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT(runtime/int) if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { // selflearning @@ -247,7 +247,7 @@ std::string ProtocolNexa::decodeDataCodeSwitch(uint32_t allData) { } std::stringstream retString; - retString << "class:command;protocol:arctech;model:codeswitch;house:" << char(house); + retString << "class:command;protocol:arctech;model:codeswitch;house:" << static_cast(house); if(method == 6) { retString << ";unit:" << unit << ";method:turnoff;"; diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 062c33af..b1eedb6b 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -63,7 +63,7 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { } std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:EA4C;id:" << (int)address + retString << "class:sensor;protocol:oregon;model:EA4C;id:" << static_cast(address) << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; return retString.str(); @@ -114,7 +114,7 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { } std::stringstream retString; - retString << "class:sensor;protocol:oregon;model:1A2D;id:" << (int)address + retString << "class:sensor;protocol:oregon;model:1A2D;id:" << static_cast(address) << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; return retString.str(); diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 77a7a1bf..50d4985d 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -30,7 +30,7 @@ std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) { unsigned int unit = 0; unsigned int method = 0; - sscanf(dataMsg.getParameter("data").c_str(), "%lx", (long*)&allData); // NOLINT(runtime/int) + sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT(runtime/int) method = allData & 0xF00; method >>= 8; @@ -59,7 +59,7 @@ std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) { } std::stringstream retString; - retString << "class:command;protocol:waveman;model:codeswitch;house:" << char(house); + retString << "class:command;protocol:waveman;model:codeswitch;house:" << static_cast(house); if(method == 0) { retString << ";unit:" << unit << ";method:turnoff;"; diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index a5883627..ea8d1b9c 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -167,7 +167,7 @@ std::string ProtocolX10::decodeData(const ControllerMessage& dataMsg) { std::stringstream retString; retString << "class:command;protocol:x10;model:codeswitch;"; - retString << "house:" << (char)('A' + intHouse); + retString << "house:" << static_cast('A' + intHouse); retString << ";unit:" << unit+1; retString << ";method:"; if(method == 0) { diff --git a/telldus-core/service/TellStick_libftdi.cpp b/telldus-core/service/TellStick_libftdi.cpp index 9cc3de19..8ce36700 100644 --- a/telldus-core/service/TellStick_libftdi.cpp +++ b/telldus-core/service/TellStick_libftdi.cpp @@ -201,7 +201,7 @@ int TellStick::send( const std::string &strMessage ) { if(ret < 0) { c = false; } else if(ret != strMessage.length()) { - Log::debug("Weird send length? retval %i instead of %d\n", ret, (int)strMessage.length()); + Log::debug("Weird send length? retval %i instead of %d\n", ret, static_cast(strMessage.length())); } delete[] tempMessage; From 9352ae08072f410adffce09816218b0caa9bea28 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Jun 2012 15:01:33 +0200 Subject: [PATCH 2020/2215] All parameters should be named in a function according to Google style guidelines "readability/function" --- telldus-core/common/Event.h | 2 +- telldus-core/common/Message.h | 16 ++++++++-------- telldus-core/common/Thread.h | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index f8451f73..6d662d89 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -41,7 +41,7 @@ namespace TelldusCore { void popSignal(); bool isSignaled(); void signal(); - virtual void signal(EventData *); + virtual void signal(EventData *eventData); EventDataRef takeSignal(); protected: diff --git a/telldus-core/common/Message.h b/telldus-core/common/Message.h index b79cacf2..f0ca593c 100644 --- a/telldus-core/common/Message.h +++ b/telldus-core/common/Message.h @@ -13,21 +13,21 @@ namespace TelldusCore { class Message : public std::wstring { public: Message(); - explicit Message(const std::wstring &); + explicit Message(const std::wstring &functionName); ~Message(void); - void addArgument(const std::wstring &); + void addArgument(const std::wstring &value); // void addSpecialArgument(const std::wstring &); // void addSpecialArgument(int); // void addSpecialArgument(const char *); - void addArgument(int); - void addArgument(const char *); + void addArgument(int value); + void addArgument(const char *value); - static bool nextIsInt(const std::wstring &); - static bool nextIsString(const std::wstring &); + static bool nextIsInt(const std::wstring &message); + static bool nextIsString(const std::wstring &message); - static std::wstring takeString(std::wstring *); - static int takeInt(std::wstring *); + static std::wstring takeString(std::wstring *message); + static int takeInt(std::wstring *message); private: }; diff --git a/telldus-core/common/Thread.h b/telldus-core/common/Thread.h index 139aad38..c5724eb8 100644 --- a/telldus-core/common/Thread.h +++ b/telldus-core/common/Thread.h @@ -22,7 +22,7 @@ namespace TelldusCore { Thread(); virtual ~Thread(); void start(); - void startAndLock(Mutex *); + void startAndLock(Mutex *lock); bool wait(); protected: From a165e414fd50524c4aa985e47d6bdc086ae382b6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 18 Jun 2012 16:10:39 +0200 Subject: [PATCH 2021/2215] Streams are highly discouraged according to Google style guidelines "readability/streams" --- telldus-core/common/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 6ead6c8b..a79a9972 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -17,9 +17,9 @@ #include #endif #include +#include #include #include -#include #include #include "common/Strings.h" From 6688f44084c7b933fe6dd960c58567944d1023fc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 15 Jun 2012 17:18:05 +0200 Subject: [PATCH 2022/2215] Missing username in TODO according to Google style guidelines "readability/todo" --- telldus-core/client/Client.cpp | 6 +++--- telldus-core/common/Socket_unix.cpp | 2 +- telldus-core/common/Strings.cpp | 2 +- telldus-core/service/ControllerManager.cpp | 4 ++-- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/ProtocolNexa.cpp | 2 +- telldus-core/service/ProtocolOregon.cpp | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 521906d6..d8c2b6d1 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -166,11 +166,11 @@ std::wstring Client::sendToService(const Message &msg) { msleep(500); continue; // retry } - readData = s.read(8000); // TODO changed to 10000 from 5000, how much does this do...? + readData = s.read(8000); // TODO(stefan) changed to 10000 from 5000, how much does this do...? if(readData == L"") { msleep(500); - continue; // TODO can we be really sure it SHOULD be anything? - // TODO perhaps break here instead? + continue; // TODO(stefan): can we be really sure it SHOULD be anything? + // TODO(stefan): perhaps break here instead? } if (!s.isConnected()) { // Connection failed sometime during operation... diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index b837c507..0e62d13e 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -121,7 +121,7 @@ std::wstring Socket::read(int timeout) { void Socket::stopReadWait() { TelldusCore::MutexLocker locker(&d->mutex); d->connected = false; - // TODO somehow signal the socket here? + // TODO(stefan): somehow signal the socket here? } void Socket::write(const std::wstring &msg) { diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index d29ee203..b1221ff4 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -101,7 +101,7 @@ bool TelldusCore::comparei(std::wstring stringA, std::wstring stringB) { std::wstring TelldusCore::intToWstring(int value) { #ifdef _WINDOWS // no stream used - // TODO! Make effective and safe... + // TODO(stefan): Make effective and safe... wchar_t numstr[21]; // enough to hold all numbers up to 64-bits _itow_s(value, numstr, sizeof(numstr), 10); std::wstring newstring(numstr); diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index b1ce2ce1..0cc90a99 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -174,7 +174,7 @@ void ControllerManager::loadControllers() { if (!controllerId) { controllerId = d->settings.addNode(Settings::Controller); if(controllerId < 0) { - // TODO: How to handle this? + // TODO(micke): How to handle this? continue; } isNew = true; @@ -333,7 +333,7 @@ int ControllerManager::setControllerValue(int id, const std::wstring &name, cons d->settings.setName(Settings::Controller, id, value); signalControllerEvent(id, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME, value); } else { - return TELLSTICK_ERROR_SYNTAX; // TODO: Is this the best error? + return TELLSTICK_ERROR_SYNTAX; // TODO(micke): Is this the best error? } return TELLSTICK_SUCCESS; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index f17cc5a5..09ff7a7b 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -487,7 +487,7 @@ int DeviceManager::doGroupAction(const std::wstring devices, const int action, c if(childType == TELLSTICK_TYPE_DEVICE) { deviceReturnValue = doAction(deviceId, action, data); } else if(childType == TELLSTICK_TYPE_SCENE) { - deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); // TODO make scenes infinite loops-safe + deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); // TODO(stefan) make scenes infinite loops-safe } else { // group (in group) deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index 3965b2b7..baad51cc 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -11,7 +11,7 @@ #include "service/TellStick.h" #include "common/Strings.h" -int ProtocolNexa::lastArctecCodeSwitchWasTurnOff = 0; // TODO, always removing first turnon now, make more flexible (waveman too) +int ProtocolNexa::lastArctecCodeSwitchWasTurnOff = 0; // TODO(stefan): always removing first turnon now, make more flexible (waveman too) int ProtocolNexa::methods() const { if (TelldusCore::comparei(model(), L"codeswitch")) { diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index b1eedb6b..3c397651 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -103,7 +103,7 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA; - // TODO: Find out how checksum2 works + // TODO(micke): Find out how checksum2 works if (checksum != checksum1) { return ""; } From 6067c776c59e0642b6a353ee7e94edd1742548b4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 12:29:52 +0200 Subject: [PATCH 2023/2215] Since we use tabs for indentation, convert to one line instead --- telldus-core/service/Log.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 13281c59..7c0ac9ec 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -47,13 +47,10 @@ Log::Log() dwError = RegCreateKey( HKEY_LOCAL_MACHINE, path.c_str(), &hRegKey ); GetModuleFileName( NULL, filePath, MAX_PATH ); - dwError = RegSetValueEx( hRegKey, L"EventMessageFile", 0, - REG_EXPAND_SZ, (PBYTE) filePath, - (DWORD)(wcslen(filePath) + 1) * sizeof TCHAR ); + dwError = RegSetValueEx( hRegKey, L"EventMessageFile", 0, REG_EXPAND_SZ, (PBYTE) filePath, (DWORD)(wcslen(filePath) + 1) * sizeof TCHAR ); DWORD dwTypes = LOG_DEBUG | LOG_NOTICE | LOG_WARNING | LOG_ERR; - dwError = RegSetValueEx( hRegKey, L"TypesSupported", - 0, REG_DWORD, (LPBYTE) &dwTypes, sizeof dwTypes ); + dwError = RegSetValueEx( hRegKey, L"TypesSupported", 0, REG_DWORD, (LPBYTE) &dwTypes, sizeof dwTypes ); RegCloseKey(hRegKey); From d2332cb6056a222de4af5b697e292eeceb18fc70 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 14:02:38 +0200 Subject: [PATCH 2024/2215] Convert non utf-8 characters in ProtocolIkea --- telldus-core/service/ProtocolIkea.cpp | 29 ++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index a776e565..7caf3f67 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -15,6 +15,9 @@ int ProtocolIkea::methods() const { } std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { + const char B1[] = {84, 84, 0}; + const char B0[] = {170, 0}; + int intSystem = this->getIntParameter(L"system", 1, 16)-1; int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true"); std::wstring wstrUnits = this->getStringParameter(L"units", L""); @@ -53,7 +56,15 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co delete[] tempUnits; - std::string strReturn = "STTTTTTª"; // Startcode, always like this; + std::string strReturn; + strReturn.append(1, 'S'); + strReturn.append(1, 84); + strReturn.append(1, 84); + strReturn.append(1, 84); + strReturn.append(1, 84); + strReturn.append(1, 84); + strReturn.append(1, 84); + strReturn.append(1, 170); std::string strChannels = ""; int intCode = (intSystem << 10) | intUnits; @@ -61,19 +72,19 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co int checksum2 = 0; for (int i = 13; i >= 0; --i) { if ((intCode >> i) & 1) { - strChannels.append("TT"); + strChannels.append(B1); if (i % 2 == 0) checksum2++; else checksum1++; } else { - strChannels.append("ª"); + strChannels.append(B0); } } strReturn.append(strChannels); // System + Units - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); // 1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); // 2nd checksum + strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum + strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum int intLevel = 0; if (level <= 12) { @@ -113,18 +124,18 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co checksum2 = 0; for (int i = 0; i < 6; ++i) { if ((intCode >> i) & 1) { - strReturn.append("TT"); + strReturn.append(B1); if (i % 2 == 0) checksum1++; else checksum2++; } else { - strReturn.append("ª"); + strReturn.append(B0); } } - strReturn.append(checksum1 %2 == 0 ? "TT" : "ª"); // 1st checksum - strReturn.append(checksum2 %2 == 0 ? "TT" : "ª"); // 2nd checksum + strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum + strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum strReturn.append("+"); From c26efc13058dd9eea3335160170b82d26d377507 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 14:13:18 +0200 Subject: [PATCH 2025/2215] Convert strtok() to strtok_r() for improved thread safety. --- telldus-core/service/ProtocolIkea.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 7caf3f67..b35d315c 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -45,14 +45,15 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co strcpy(tempUnits, strUnits.c_str()); #endif - char *strToken = strtok(tempUnits, ","); + char *saveptr; + char *strToken = strtok_r(tempUnits, ",", &saveptr); do { int intUnit = atoi(strToken); if (intUnit == 10) { intUnit = 0; } intUnits = intUnits | ( 1<<(9-intUnit) ); - } while ( (strToken = strtok(NULL, ",")) != NULL ); + } while ( (strToken = strtok_r(NULL, ",", &saveptr)) != NULL ); delete[] tempUnits; From 77b128f2fd4b724c98fecfbd792591f4404004ab Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 14:40:00 +0200 Subject: [PATCH 2026/2215] Add exception for using getgwnam() and getpwnam(). This is safe so early in the startup --- telldus-core/service/main_unix.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 6acb2a8a..5608a550 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -119,14 +119,18 @@ int main(int argc, char **argv) { std::string user = TelldusCore::wideToString(settings.getSetting(L"user")); std::string group = TelldusCore::wideToString(settings.getSetting(L"group")); - struct group *grp = getgrnam(group.c_str()); + // We use the non threadsafe function getgrnam() here. Since this is startup code + // and no other threads have been started yet. + struct group *grp = getgrnam(group.c_str()); // NOLINT(runtime/threadsafe_fn) if (grp) { setgid(grp->gr_gid); } else { Log::warning("Group %s could not be found", group.c_str()); exit(EXIT_FAILURE); } - struct passwd *pw = getpwnam(user.c_str()); + // We use the non threadsafe function getpwnam() here. Since this is startup code + // and no other threads have been started yet. + struct passwd *pw = getpwnam(user.c_str()); // NOLINT(runtime/threadsafe_fn) if (pw) { setuid( pw->pw_uid ); } else { From 58bf51a6e8f7690563bb3a317f3e34d714fe0648 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:18:44 +0200 Subject: [PATCH 2027/2215] Convert strcpy to snprintf. This is better according to Google style guidelines "runtime/printf" --- telldus-core/common/Socket_unix.cpp | 2 +- telldus-core/common/Strings.cpp | 2 +- telldus-core/common/common.h | 2 +- telldus-core/service/ProtocolIkea.cpp | 3 ++- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 0e62d13e..046cdaf3 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -62,7 +62,7 @@ void Socket::connect(const std::wstring &server) { } std::string name = "/tmp/" + std::string(server.begin(), server.end()); remote.sun_family = AF_UNIX; - strcpy(remote.sun_path, name.c_str()); + snprintf(remote.sun_path, sizeof(remote.sun_path), "%s", name.c_str()); len = SUN_LEN(&remote); if (connectWrapper(d->socket, (struct sockaddr *)&remote, len) == -1) { diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index b1221ff4..d2a0fe2f 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -47,7 +47,7 @@ std::wstring TelldusCore::charToWstring(const char *value) { // Copy the instring char *inString = new char[utf8Length+1]; - strcpy(inString, value); + snprintf(inString, utf8Length+1, "%s", value); // Create buffer for output char *outString = reinterpret_cast(new wchar_t[utf8Length+1]); diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index a79a9972..5aad280e 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -71,7 +71,7 @@ inline char *wrapStdString( const std::string &string) { #else char *returnVal; returnVal = reinterpret_cast(malloc(sizeof(*returnVal) * (string.size()+1))); - strcpy(returnVal, string.c_str()); + snprintf(returnVal, string.size()+1, "%s", string.c_str()); return returnVal; #endif } diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index b35d315c..f2c3515d 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolIkea.h" +#include #include #include #include @@ -42,7 +43,7 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co #ifdef _WINDOWS strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str()); #else - strcpy(tempUnits, strUnits.c_str()); + snprintf(tempUnits, strUnits.size()+1, "%s", strUnits.c_str()); #endif char *saveptr; From dbb11602ecddc04b644aa94eba842540f49fc152 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:23:36 +0200 Subject: [PATCH 2028/2215] Temporarily suppress cpplint errors "runtime/printf" for sscanf(). We should prpbably remove them later --- telldus-core/service/ProtocolEverflourish.cpp | 3 ++- telldus-core/service/ProtocolNexa.cpp | 3 ++- telldus-core/service/ProtocolSartano.cpp | 3 ++- telldus-core/service/ProtocolWaveman.cpp | 3 ++- telldus-core/service/ProtocolX10.cpp | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 4b7866ec..aec6598c 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -101,7 +101,8 @@ std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) { unsigned int unit = 0; unsigned int method = 0; - sscanf(data.c_str(), "%X", &allData); + // TODO(micke): Convert sscanf. This is slow and can overflow buffers! + sscanf(data.c_str(), "%X", &allData); // NOLINT(runtime/printf) house = allData & 0xFFFC00; house >>= 10; diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index baad51cc..a2cef58f 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -167,7 +167,8 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) { uint32_t allData = 0; - sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT(runtime/int) + // TODO(micke): Convert sscanf. This is slow and can overflow buffers! + sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { // selflearning diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 90c95023..37035d71 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -50,7 +50,8 @@ std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { unsigned int method2 = 0; unsigned int method = 0; - sscanf(data.c_str(), "%X", &allDataIn); + // TODO(micke): Convert sscanf. This is slow and can overflow buffers! + sscanf(data.c_str(), "%X", &allDataIn); // NOLINT(runtime/printf) uint16_t mask = (1<<11); for(int i = 0; i < 12; ++i) { diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 50d4985d..3f9c449f 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -30,7 +30,8 @@ std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) { unsigned int unit = 0; unsigned int method = 0; - sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT(runtime/int) + // TODO(micke): Convert sscanf. This is slow and can overflow buffers! + sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT method = allData & 0xF00; method >>= 8; diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index ea8d1b9c..40ddb27a 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -116,7 +116,8 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont std::string ProtocolX10::decodeData(const ControllerMessage& dataMsg) { int intData = 0, currentBit = 31; bool method = 0; - sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); + // TODO(micke): Convert sscanf. This is slow and can overflow buffers! + sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); // NOLINT(runtime/printf) int unit = 0; int rawHouse = 0; From 818ae8abed75e7504bb2a662dc61ef42d4119268 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:47:01 +0200 Subject: [PATCH 2029/2215] Rename ControllerMessage::getIntParameter() to ControllerMessage::getInt64Parameter() --- telldus-core/service/ControllerMessage.cpp | 5 +++-- telldus-core/service/ControllerMessage.h | 3 ++- telldus-core/service/DeviceManager.cpp | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/ControllerMessage.cpp b/telldus-core/service/ControllerMessage.cpp index a701ffea..90f54cd6 100644 --- a/telldus-core/service/ControllerMessage.cpp +++ b/telldus-core/service/ControllerMessage.cpp @@ -66,14 +66,15 @@ std::wstring ControllerMessage::model() const { return TelldusCore::charToWstring(d->model.c_str()); } -int ControllerMessage::getIntParameter(const std::string &key) const { +uint64_t ControllerMessage::getInt64Parameter(const std::string &key) const { std::string strValue = getParameter(key); if (strValue.compare("") == 0) { return -1; } if (strValue.substr(0, 2).compare("0x") == 0) { - return strtol(strValue.c_str(), NULL, 16); + return TelldusCore::hexTo64l(strValue); } + // TODO(micke): strtol() does not return uint64_t. Create a platform independent version similar to hexTo64l() return strtol(strValue.c_str(), NULL, 10); } diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index f31aeffd..892c0752 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_ #define TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_ +#include #include class ControllerMessage { @@ -15,7 +16,7 @@ public: virtual ~ControllerMessage(); std::string msgClass() const; - int getIntParameter(const std::string &key) const; + uint64_t getInt64Parameter(const std::string &key) const; std::string getParameter(const std::string &key) const; int method() const; std::wstring protocol() const; diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 09ff7a7b..3524e157 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -682,7 +682,7 @@ void DeviceManager::handleSensorMessage(const ControllerMessage &msg) { if (!TelldusCore::comparei((*it)->model(), msg.model())) { continue; } - if ((*it)->id() != msg.getIntParameter("id")) { + if ((*it)->id() != msg.getInt64Parameter("id")) { continue; } sensor = *it; @@ -690,7 +690,7 @@ void DeviceManager::handleSensorMessage(const ControllerMessage &msg) { } if (!sensor) { - sensor = new Sensor(msg.protocol(), msg.model(), msg.getIntParameter("id")); + sensor = new Sensor(msg.protocol(), msg.model(), msg.getInt64Parameter("id")); d->sensorList.push_back(sensor); } TelldusCore::MutexLocker sensorLocker(sensor); From 7b82e529cc147c17c7b84f8eefec8d910d959692 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:48:44 +0200 Subject: [PATCH 2030/2215] Convert sscanf in ProtocolNexa and ProtocolWaveman to a faster and platform independent implementation --- telldus-core/service/ProtocolNexa.cpp | 9 +++------ telldus-core/service/ProtocolNexa.h | 4 ++-- telldus-core/service/ProtocolWaveman.cpp | 5 ++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index a2cef58f..b6143d59 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -165,10 +165,7 @@ std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode } std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) { - uint32_t allData = 0; - - // TODO(micke): Convert sscanf. This is slow and can overflow buffers! - sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT + uint64_t allData = dataMsg.getInt64Parameter("data"); if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { // selflearning @@ -179,7 +176,7 @@ std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) { } } -std::string ProtocolNexa::decodeDataSelfLearning(uint32_t allData) { +std::string ProtocolNexa::decodeDataSelfLearning(uint64_t allData) { unsigned int house = 0; unsigned int unit = 0; unsigned int group = 0; @@ -216,7 +213,7 @@ std::string ProtocolNexa::decodeDataSelfLearning(uint32_t allData) { return retString.str(); } -std::string ProtocolNexa::decodeDataCodeSwitch(uint32_t allData) { +std::string ProtocolNexa::decodeDataCodeSwitch(uint64_t allData) { unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 7b65ae8f..8dd81b1d 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -28,8 +28,8 @@ protected: private: static int lastArctecCodeSwitchWasTurnOff; - static std::string decodeDataCodeSwitch(uint32_t allData); - static std::string decodeDataSelfLearning(uint32_t allData); + static std::string decodeDataCodeSwitch(uint64_t allData); + static std::string decodeDataSelfLearning(uint64_t allData); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 3f9c449f..61484cd5 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -25,13 +25,12 @@ std::string ProtocolWaveman::getOffCode() const { } std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) { - uint32_t allData = 0; + uint64_t allData = 0; unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; - // TODO(micke): Convert sscanf. This is slow and can overflow buffers! - sscanf(dataMsg.getParameter("data").c_str(), "%lx", reinterpret_cast(&allData)); // NOLINT + allData = dataMsg.getInt64Parameter("data"); method = allData & 0xF00; method >>= 8; From 39c6bb012edbba87db10f887c87a619f9c45a7c5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:49:26 +0200 Subject: [PATCH 2031/2215] Use dynamic_cast instead of reinterpret_cast for our events --- telldus-core/service/EventUpdateManager.cpp | 2 +- telldus-core/service/TelldusMain.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index bc8a5f12..0f50c5fe 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -58,7 +58,7 @@ void EventUpdateManager::run() { if(d->clientConnectEvent->isSignaled()) { // new client added TelldusCore::EventDataRef eventData = d->clientConnectEvent->takeSignal(); - ConnectionListenerEventData *data = reinterpret_cast(eventData.get()); + ConnectionListenerEventData *data = dynamic_cast(eventData.get()); if(data) { d->clients.push_back(data->socket); } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 3016a520..9bc40341 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -96,7 +96,7 @@ void TelldusMain::start(void) { if (clientEvent->isSignaled()) { // New client connection TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal(); - ConnectionListenerEventData *data = reinterpret_cast(eventDataRef.get()); + ConnectionListenerEventData *data = dynamic_cast(eventDataRef.get()); if (data) { ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent, &controllerManager); clientCommunication->start(); @@ -106,7 +106,7 @@ void TelldusMain::start(void) { if (d->controllerChangeEvent->isSignaled()) { TelldusCore::EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal(); - ControllerChangeEventData *data = reinterpret_cast(eventDataRef.get()); + ControllerChangeEventData *data = dynamic_cast(eventDataRef.get()); if (data) { controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, "", data->inserted); } @@ -114,7 +114,7 @@ void TelldusMain::start(void) { if (dataEvent->isSignaled()) { TelldusCore::EventDataRef eventData = dataEvent->takeSignal(); - ControllerEventData *data = reinterpret_cast(eventData.get()); + ControllerEventData *data = dynamic_cast(eventData.get()); if (data) { deviceManager.handleControllerMessage(*data); } From c97c88ba8d3a4fed4d9e8d583a82e4bf8a4724b5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:50:21 +0200 Subject: [PATCH 2032/2215] Extra check for the value in Nexa device settings. This could lead to a potential crash otherwise --- telldus-gui/TelldusGui/devicesettingnexa.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/devicesettingnexa.cpp b/telldus-gui/TelldusGui/devicesettingnexa.cpp index dc187a5f..acf24dd0 100644 --- a/telldus-gui/TelldusGui/devicesettingnexa.cpp +++ b/telldus-gui/TelldusGui/devicesettingnexa.cpp @@ -88,7 +88,10 @@ void DeviceSettingNexa::saveParameters() { void DeviceSettingNexa::setValue( const QString &name, const QString &value ) { if (name == "house") { - uint intHouse = value[0].toUpper().toAscii() - 'A'; + uint intHouse = 0; + if (value.length() > 0) { + intHouse = value[0].toUpper().toAscii() - 'A'; + } dialHouse->setValue( intHouse ); } else if (name == "unit") { dialUnit->setValue( value.toInt() ); From ffebd4ed4c7fbf3eef10fbdb86deb87b19db888f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:51:18 +0200 Subject: [PATCH 2033/2215] Enable test whitespace/use_tab_for_indentaion and disable test runtime/rtti --- telldus-core/tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index 8bbdc1cf..463b56cd 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -1,7 +1,7 @@ SET(ENABLE_TESTING FALSE CACHE BOOL "Enable unit tests") SET(cpplint_filters - -whitespace/tab,-whitespace/parens,-whitespace/line_length,-whitespace/labels + +whitespace/use_tab_for_indentation,-whitespace/tab,-whitespace/parens,-whitespace/line_length,-whitespace/labels,-runtime/rtti ) FUNCTION(ADD_SOURCES TARGET PATH) From 6e47588096c560cacd09431edbc1264566439793 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 19 Jun 2012 16:51:35 +0200 Subject: [PATCH 2034/2215] Add comment on why we disable some of the default tests --- telldus-core/tests/CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index 463b56cd..edc1e976 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -1,5 +1,22 @@ SET(ENABLE_TESTING FALSE CACHE BOOL "Enable unit tests") +#We have disabled some of the default tests in the google style guidelines +# whitespace/tab +# We are using tabs for indentation, not spaces, in our code +# +# whitespace/parens +# We believe grouping of parameters with spaces in some functions could ease the readability +# +# whitespace/line_length +# Although you should try to keep the lines short it should not be a requirement (at least for now) +# +# whitespace/labels +# Since we use tabs instead of spaces for indentation, this test makes no sense +# +# runtime/rtti +# We are using dynamic_cast for the events. We use this to be able to send arbitrary data +# trought the events. +# SET(cpplint_filters +whitespace/use_tab_for_indentation,-whitespace/tab,-whitespace/parens,-whitespace/line_length,-whitespace/labels,-runtime/rtti ) From ae7b9b8c1a6abbaacb0643cb53cd1e3435594849 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 12:18:50 +0200 Subject: [PATCH 2035/2215] If we enable testing, build TelldusService as a static library that can be used by the TestRunner --- telldus-core/service/CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index d0964188..0479af52 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -259,3 +259,16 @@ IF (UNIX AND NOT APPLE) PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE ) ENDIF (UNIX AND NOT APPLE) + +IF(ENABLE_TESTING) + # Build it once more, but as static library so it can be linked by the test-tool + ADD_LIBRARY(TelldusServiceStatic STATIC + ${telldus-service_SRCS} + ${telldus-service_protocol_SRCS} + ${telldus-service_HDRS} + ) + TARGET_LINK_LIBRARIES( TelldusServiceStatic ${telldus-service_LIBRARIES} ) + IF (UNIX) + SET_TARGET_PROPERTIES( TelldusServiceStatic PROPERTIES COMPILE_FLAGS "-fPIC") + ENDIF (UNIX) +ENDIF() From 264b92889ac950801a0d7a87632e55671ccf3451 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 12:20:23 +0200 Subject: [PATCH 2036/2215] Add unittest for ProtocolNexa::decodeData() --- telldus-core/tests/CMakeLists.txt | 5 ++- telldus-core/tests/service/CMakeLists.txt | 9 ++++ .../tests/service/ProtocolNexaTest.cpp | 42 +++++++++++++++++++ telldus-core/tests/service/ProtocolNexaTest.h | 25 +++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 telldus-core/tests/service/CMakeLists.txt create mode 100644 telldus-core/tests/service/ProtocolNexaTest.cpp create mode 100644 telldus-core/tests/service/ProtocolNexaTest.h diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index edc1e976..c1c8fa9e 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -31,10 +31,11 @@ ENDFUNCTION() IF(ENABLE_TESTING) ADD_SUBDIRECTORY(common) + ADD_SUBDIRECTORY(service) ADD_EXECUTABLE(TestRunner cppunit.cpp) - TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests) - ADD_DEPENDENCIES(TestRunner TelldusCommonTests) + TARGET_LINK_LIBRARIES(TestRunner cppunit TelldusCommonTests TelldusServiceTests) + ADD_DEPENDENCIES(TestRunner TelldusCommonTests TelldusServiceTests) ADD_SOURCES(TelldusCommon ${CMAKE_SOURCE_DIR}/common) ADD_SOURCES(${telldus-core_TARGET} ${CMAKE_SOURCE_DIR}/client) diff --git a/telldus-core/tests/service/CMakeLists.txt b/telldus-core/tests/service/CMakeLists.txt new file mode 100644 index 00000000..0e795cd8 --- /dev/null +++ b/telldus-core/tests/service/CMakeLists.txt @@ -0,0 +1,9 @@ +FILE(GLOB SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*Test.cpp" ) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) + +ADD_LIBRARY(TelldusServiceTests SHARED ${SRCS} ) + +TARGET_LINK_LIBRARIES( TelldusServiceTests TelldusServiceStatic ) +ADD_DEPENDENCIES( TelldusServiceTests ${telldus-service_TARGET} ) + diff --git a/telldus-core/tests/service/ProtocolNexaTest.cpp b/telldus-core/tests/service/ProtocolNexaTest.cpp new file mode 100644 index 00000000..f65c0381 --- /dev/null +++ b/telldus-core/tests/service/ProtocolNexaTest.cpp @@ -0,0 +1,42 @@ +#include "ProtocolNexaTest.h" +#include "service/ProtocolNexa.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolNexaTest); + +class ProtocolNexaTest::PrivateData { +public: + ProtocolNexa *protocol; +}; + +void ProtocolNexaTest :: setUp (void) { + d = new PrivateData; + d->protocol = new ProtocolNexa(); +} + +void ProtocolNexaTest :: tearDown (void) { + delete d->protocol; + delete d; +} + +void ProtocolNexaTest :: decodeDataTest (void) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Arctech Codeswitch A1 ON", + std::string("class:command;protocol:arctech;model:codeswitch;house:A;unit:1;method:turnon;"), + d->protocol->decodeData(ControllerMessage("protocol:arctech;model:codeswitch;data:0xE00;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Arctech Codeswitch A1 OFF", + std::string("class:command;protocol:arctech;model:codeswitch;house:A;unit:1;method:turnoff;"), + d->protocol->decodeData(ControllerMessage("protocol:arctech;model:codeswitch;data:0x600;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Arctech Selflearning 1329110 1 ON", + std::string("class:command;protocol:arctech;model:selflearning;house:1329110;unit:1;group:0;method:turnon;"), + d->protocol->decodeData(ControllerMessage("protocol:arctech;model:selflearning;data:0x511F590;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Arctech Selflearning 1329110 1 OFF", + std::string("class:command;protocol:arctech;model:selflearning;house:1329110;unit:1;group:0;method:turnoff;"), + d->protocol->decodeData(ControllerMessage("protocol:arctech;model:selflearning;data:0x511F580;")) + ); +} diff --git a/telldus-core/tests/service/ProtocolNexaTest.h b/telldus-core/tests/service/ProtocolNexaTest.h new file mode 100644 index 00000000..74c0377b --- /dev/null +++ b/telldus-core/tests/service/ProtocolNexaTest.h @@ -0,0 +1,25 @@ +#ifndef PROTOCOLNEXATEST_H +#define PROTOCOLNEXATEST_H + +#include +#include + +class ProtocolNexaTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (ProtocolNexaTest); + CPPUNIT_TEST (decodeDataTest); + CPPUNIT_TEST_SUITE_END (); + +public: + void setUp (void); + void tearDown (void); + +protected: + void decodeDataTest(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //PROTOCOLNEXATEST_H From 41816f36a3c00cb0a552d8932be0b39a21fad31d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 12:22:03 +0200 Subject: [PATCH 2037/2215] Configure SettingsConfusePaths.h in the correct section in CMakeLists.txt --- telldus-core/service/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 0479af52..70b1cfb1 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -158,6 +158,10 @@ ELSE (APPLE) #### Linux #### main_unix.cpp SettingsConfuse.cpp ) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/SettingsConfusePaths.h.in + ${CMAKE_CURRENT_BINARY_DIR}/service/SettingsConfusePaths.h) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + LIST(APPEND telldus-service_LIBRARIES ${CONFUSE_LIBRARY} TelldusCommon @@ -247,10 +251,6 @@ IF (UNIX AND NOT APPLE) ENDIF () SET(STATE_INSTALL_DIR "${DEFAULT_STATE_INSTALL_DIR}" CACHE PATH "The directory to store state information of the devices") - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/SettingsConfusePaths.h.in - ${CMAKE_CURRENT_BINARY_DIR}/service/SettingsConfusePaths.h) - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) - INSTALL(FILES tellstick.conf DESTINATION ${SYSCONF_INSTALL_DIR} ) From b50e9dd3d528435c20235ad85641889d1caec2c7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 14:18:29 +0200 Subject: [PATCH 2038/2215] Remove sscanf() from ProtocolX10 and add a unittest for ProtocolX10::decodeData() --- telldus-core/service/ProtocolX10.cpp | 7 ++-- .../tests/service/ProtocolX10Test.cpp | 32 +++++++++++++++++++ telldus-core/tests/service/ProtocolX10Test.h | 25 +++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 telldus-core/tests/service/ProtocolX10Test.cpp create mode 100644 telldus-core/tests/service/ProtocolX10Test.h diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index 40ddb27a..8de3a377 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -5,6 +5,7 @@ // // #include "service/ProtocolX10.h" +#include #include #include #include @@ -114,10 +115,10 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont } std::string ProtocolX10::decodeData(const ControllerMessage& dataMsg) { - int intData = 0, currentBit = 31; + uint64_t intData = 0, currentBit = 31; bool method = 0; - // TODO(micke): Convert sscanf. This is slow and can overflow buffers! - sscanf(dataMsg.getParameter("data").c_str(), "%X", &intData); // NOLINT(runtime/printf) + + intData = dataMsg.getInt64Parameter("data"); int unit = 0; int rawHouse = 0; diff --git a/telldus-core/tests/service/ProtocolX10Test.cpp b/telldus-core/tests/service/ProtocolX10Test.cpp new file mode 100644 index 00000000..4e97b425 --- /dev/null +++ b/telldus-core/tests/service/ProtocolX10Test.cpp @@ -0,0 +1,32 @@ +#include "ProtocolX10Test.h" +#include "service/ProtocolX10.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolX10Test); + +class ProtocolX10Test::PrivateData { +public: + ProtocolX10 *protocol; +}; + +void ProtocolX10Test :: setUp (void) { + d = new PrivateData; + d->protocol = new ProtocolX10(); +} + +void ProtocolX10Test :: tearDown (void) { + delete d->protocol; + delete d; +} + +void ProtocolX10Test :: decodeDataTest (void) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "X10 A1 ON", + std::string("class:command;protocol:x10;model:codeswitch;house:A;unit:1;method:turnon;"), + d->protocol->decodeData(ControllerMessage("protocol:x10;data:0x609F00FF;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "X10 E11 OFF", + std::string("class:command;protocol:x10;model:codeswitch;house:E;unit:11;method:turnoff;"), + d->protocol->decodeData(ControllerMessage("protocol:x10;data:0x847B28D7;")) + ); +} diff --git a/telldus-core/tests/service/ProtocolX10Test.h b/telldus-core/tests/service/ProtocolX10Test.h new file mode 100644 index 00000000..e490e53e --- /dev/null +++ b/telldus-core/tests/service/ProtocolX10Test.h @@ -0,0 +1,25 @@ +#ifndef PROTOCOLX10TEST_H +#define PROTOCOLX10TEST_H + +#include +#include + +class ProtocolX10Test : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (ProtocolX10Test); + CPPUNIT_TEST (decodeDataTest); + CPPUNIT_TEST_SUITE_END (); + +public: + void setUp (void); + void tearDown (void); + +protected: + void decodeDataTest(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //PROTOCOLX10TEST_H From ddfb87f45dff68ae3ed0cc78b110dce4298bac77 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 15:21:29 +0200 Subject: [PATCH 2039/2215] Remove sscanf() from ProtocolEverflourish and add a unittest for ProtocolEverflourish::decodeData() --- telldus-core/service/ProtocolEverflourish.cpp | 6 ++-- .../service/ProtocolEverflourishTest.cpp | 32 +++++++++++++++++++ .../tests/service/ProtocolEverflourishTest.h | 25 +++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 telldus-core/tests/service/ProtocolEverflourishTest.cpp create mode 100644 telldus-core/tests/service/ProtocolEverflourishTest.h diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index aec6598c..72ee8867 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -95,14 +95,12 @@ unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) { } std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) { - std::string data = dataMsg.getParameter("data"); - unsigned int allData; + uint64_t allData; unsigned int house = 0; unsigned int unit = 0; unsigned int method = 0; - // TODO(micke): Convert sscanf. This is slow and can overflow buffers! - sscanf(data.c_str(), "%X", &allData); // NOLINT(runtime/printf) + allData = dataMsg.getInt64Parameter("data"); house = allData & 0xFFFC00; house >>= 10; diff --git a/telldus-core/tests/service/ProtocolEverflourishTest.cpp b/telldus-core/tests/service/ProtocolEverflourishTest.cpp new file mode 100644 index 00000000..cb9749d6 --- /dev/null +++ b/telldus-core/tests/service/ProtocolEverflourishTest.cpp @@ -0,0 +1,32 @@ +#include "ProtocolEverflourishTest.h" +#include "service/ProtocolEverflourish.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolEverflourishTest); + +class ProtocolEverflourishTest::PrivateData { +public: + ProtocolEverflourish *protocol; +}; + +void ProtocolEverflourishTest :: setUp (void) { + d = new PrivateData; + d->protocol = new ProtocolEverflourish(); +} + +void ProtocolEverflourishTest :: tearDown (void) { + delete d->protocol; + delete d; +} + +void ProtocolEverflourishTest :: decodeDataTest (void) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Everflourish 4242:3 ON", + std::string("class:command;protocol:everflourish;model:selflearning;house:4242;unit:3;method:turnon;"), + d->protocol->decodeData(ControllerMessage("protocol:everflourish;data:0x424A6F;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Everflourish 5353:4 OFF", + std::string("class:command;protocol:everflourish;model:selflearning;house:5353;unit:4;method:turnoff;"), + d->protocol->decodeData(ControllerMessage("protocol:everflourish;data:0x53A7E0;")) + ); +} diff --git a/telldus-core/tests/service/ProtocolEverflourishTest.h b/telldus-core/tests/service/ProtocolEverflourishTest.h new file mode 100644 index 00000000..22612208 --- /dev/null +++ b/telldus-core/tests/service/ProtocolEverflourishTest.h @@ -0,0 +1,25 @@ +#ifndef PROTOCOLEVERFLOURISHTEST_H +#define PROTOCOLEVERFLOURISHTEST_H + +#include +#include + +class ProtocolEverflourishTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (ProtocolEverflourishTest); + CPPUNIT_TEST (decodeDataTest); + CPPUNIT_TEST_SUITE_END (); + +public: + void setUp (void); + void tearDown (void); + +protected: + void decodeDataTest(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif // PROTOCOLEVERFLOURISHTEST_H From 9eac84fb4a2787537f2d0af39ac762f10ea342bb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 15:22:10 +0200 Subject: [PATCH 2040/2215] Remove sscanf() from ProtocolSartano and add a unittest for ProtocolSartano::decodeData() --- telldus-core/service/ProtocolSartano.cpp | 8 +++--- .../tests/service/ProtocolSartanoTest.cpp | 27 +++++++++++++++++++ .../tests/service/ProtocolSartanoTest.h | 25 +++++++++++++++++ 3 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 telldus-core/tests/service/ProtocolSartanoTest.cpp create mode 100644 telldus-core/tests/service/ProtocolSartanoTest.h diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 37035d71..33d6eb84 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -42,16 +42,14 @@ std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int m } std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { - std::string data = dataMsg.getParameter("data"); - signed int allDataIn; - signed int allData = 0; + uint64_t allDataIn; + uint16_t allData = 0; unsigned int code = 0; unsigned int method1 = 0; unsigned int method2 = 0; unsigned int method = 0; - // TODO(micke): Convert sscanf. This is slow and can overflow buffers! - sscanf(data.c_str(), "%X", &allDataIn); // NOLINT(runtime/printf) + allDataIn = dataMsg.getInt64Parameter("data"); uint16_t mask = (1<<11); for(int i = 0; i < 12; ++i) { diff --git a/telldus-core/tests/service/ProtocolSartanoTest.cpp b/telldus-core/tests/service/ProtocolSartanoTest.cpp new file mode 100644 index 00000000..24bef0b0 --- /dev/null +++ b/telldus-core/tests/service/ProtocolSartanoTest.cpp @@ -0,0 +1,27 @@ +#include "ProtocolSartanoTest.h" +#include "service/ProtocolSartano.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolSartanoTest); + +class ProtocolSartanoTest::PrivateData { +public: + ProtocolSartano *protocol; +}; + +void ProtocolSartanoTest :: setUp (void) { + d = new PrivateData; + d->protocol = new ProtocolSartano(); +} + +void ProtocolSartanoTest :: tearDown (void) { + delete d->protocol; + delete d; +} + +void ProtocolSartanoTest :: decodeDataTest (void) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Sartano 0101010101 ON", + std::string("class:command;protocol:sartano;model:codeswitch;code:0101010101;method:turnon;"), + d->protocol->decodeData(ControllerMessage("protocol:arctech;model:codeswitch;data:0x955;")) + ); +} diff --git a/telldus-core/tests/service/ProtocolSartanoTest.h b/telldus-core/tests/service/ProtocolSartanoTest.h new file mode 100644 index 00000000..04ad2323 --- /dev/null +++ b/telldus-core/tests/service/ProtocolSartanoTest.h @@ -0,0 +1,25 @@ +#ifndef PROTOCOLSARTANOTEST_H +#define PROTOCOLSARTANOTEST_H + +#include +#include + +class ProtocolSartanoTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (ProtocolSartanoTest); + CPPUNIT_TEST (decodeDataTest); + CPPUNIT_TEST_SUITE_END (); + +public: + void setUp (void); + void tearDown (void); + +protected: + void decodeDataTest(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //PROTOCOLSARTANOTEST_H From 1ea754da3ddead6abdb2e313bc4eb2ad9af3ecaa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 17:12:30 +0200 Subject: [PATCH 2041/2215] Bugfix, all the parameters for a device tried to be saved as non parameters --- telldus-core/service/SettingsConfuse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 33574991..9ed2dd17 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -291,7 +291,7 @@ int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &n std::string newValue = TelldusCore::wideToString(value); cfg_t *p = cfg_device; if (parameter) { - cfg_t *cfg_p = cfg_getsec(cfg_device, "parameters"); + p = cfg_getsec(cfg_device, "parameters"); } cfg_opt_t *opt = cfg_getopt(p, TelldusCore::wideToString(name).c_str()); if (!opt) { From d6dcd11973f1dbfc636da8985b4752595a799f54 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 17:14:10 +0200 Subject: [PATCH 2042/2215] Protocol::getStringParameter() and Protocol::getIntParameter() should be virtual so they can be overriden by a protocol --- telldus-core/service/Protocol.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Protocol.h b/telldus-core/service/Protocol.h index c45da20c..a4e7e6cd 100644 --- a/telldus-core/service/Protocol.h +++ b/telldus-core/service/Protocol.h @@ -33,8 +33,8 @@ public: virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0; protected: - std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; - int getIntParameter(const std::wstring &name, int min, int max) const; + virtual std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const; + virtual int getIntParameter(const std::wstring &name, int min, int max) const; static bool checkBit(int data, int bit); From 61d0b2ac09a6f4e9fb2dfd9dd797796ae26266cb Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 17:15:26 +0200 Subject: [PATCH 2043/2215] Implement protocol Comen by hardcoding the last to bits in the housecode --- telldus-core/service/ProtocolComen.cpp | 16 ++++++++++------ telldus-core/service/ProtocolComen.h | 4 +++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/telldus-core/service/ProtocolComen.cpp b/telldus-core/service/ProtocolComen.cpp index 2652fde4..dfc7d38d 100644 --- a/telldus-core/service/ProtocolComen.cpp +++ b/telldus-core/service/ProtocolComen.cpp @@ -8,12 +8,16 @@ #include int ProtocolComen::methods() const { - return (TELLSTICK_TURNON | TELLSTICK_TURNOFF); + return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN); } -std::string ProtocolComen::getStringForMethod(int method, unsigned char level, Controller *) { - int intHouse = getIntParameter(L"house", 1, 33554431); - intHouse <<= 1; // They seem to only accept even codes? - int intCode = getIntParameter(L"unit", 1, 16)-1; - return getStringSelflearningForCode(intHouse, intCode, method, level); +int ProtocolComen::getIntParameter(const std::wstring &name, int min, int max) const { + if (name.compare(L"house") == 0) { + int intHouse = Protocol::getIntParameter(L"house", 1, 16777215); + // The last two bits must be hardcoded + intHouse <<= 2; + intHouse += 2; + return intHouse; + } + return Protocol::getIntParameter(name, min, max); } diff --git a/telldus-core/service/ProtocolComen.h b/telldus-core/service/ProtocolComen.h index a9ef9211..f43167a8 100644 --- a/telldus-core/service/ProtocolComen.h +++ b/telldus-core/service/ProtocolComen.h @@ -13,7 +13,9 @@ class ProtocolComen : public ProtocolNexa { public: virtual int methods() const; - virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + +protected: + virtual int getIntParameter(const std::wstring &name, int min, int max) const; }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_ From ed9d1237b4319329a7758e86b12a2583ae877d2d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Jun 2012 17:15:53 +0200 Subject: [PATCH 2044/2215] Add device Anslut selflearning on/off --- telldus-gui/TelldusGui/data/telldus/devices.xml | 3 +++ telldus-gui/TelldusGui/data/telldus/resources.qrc | 2 ++ telldus-gui/TelldusGui/editdevicedialog.cpp | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index 69846a28..392c0397 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -2,6 +2,9 @@ + + Self Learning on/off + Code Switch diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index 637bdf4a..b0214c11 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -1,6 +1,7 @@ devices.xml + ../../images/devices/anslut_sl.png ../../images/devices/arctech_cs.png ../../images/devices/arctech_sl.png ../../images/devices/bell.png @@ -26,6 +27,7 @@ ../../images/devices/waveman_cs.png ../../images/devices/x10.png ../../images/devices/zke-2603.png + ../../images/vendors/anslut.png ../../images/vendors/byebyelogo.png ../../images/vendors/chacon.png ../../images/vendors/coco.png diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 4a211e95..dfd4e903 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -171,6 +171,10 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f d->deviceSettings[16] = new DeviceSettingArctechSelflearning(device, this); ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setRemoteMinMax(1,65536); ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setUnitMinMax(1,15); + //Comen + d->deviceSettings[17] = new DeviceSettingArctechSelflearning(device, this); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setRemoteMinMax(1,16777215); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setUnitMinMax(1,16); foreach( DeviceSetting *s, d->deviceSettings ) { connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&, const QString&, const QString&)), s, SLOT(setProtocolValue(const QString&, const QString&, const QString&, const QString&))); From 246e04355173f74f2a83ecc28103f4638472c3d8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Jun 2012 11:43:39 +0200 Subject: [PATCH 2045/2215] Fix typo in deviceSettings index --- telldus-gui/TelldusGui/editdevicedialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index dfd4e903..832f51ab 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -169,12 +169,12 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f ((DeviceSettingSelflearning *)d->deviceSettings[15])->setRemoteMinMax(1,1048575); //Hasta d->deviceSettings[16] = new DeviceSettingArctechSelflearning(device, this); - ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setRemoteMinMax(1,65536); - ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setUnitMinMax(1,15); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[16])->setRemoteMinMax(1,65536); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[16])->setUnitMinMax(1,15); //Comen d->deviceSettings[17] = new DeviceSettingArctechSelflearning(device, this); - ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setRemoteMinMax(1,16777215); - ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setUnitMinMax(1,16); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[17])->setRemoteMinMax(1,16777215); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[17])->setUnitMinMax(1,16); foreach( DeviceSetting *s, d->deviceSettings ) { connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&, const QString&, const QString&)), s, SLOT(setProtocolValue(const QString&, const QString&, const QString&, const QString&))); From d22793ed12dd4b1ca2ac41fa6a8de35b812eb175 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Jun 2012 11:53:11 +0200 Subject: [PATCH 2046/2215] We cannot iterate over a QHash since the order is by design not guaranteed. Loop using a counter instead --- telldus-gui/TelldusGui/editdevicedialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 832f51ab..a6862908 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -176,7 +176,8 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f ((DeviceSettingArctechSelflearning *)d->deviceSettings[17])->setRemoteMinMax(1,16777215); ((DeviceSettingArctechSelflearning *)d->deviceSettings[17])->setUnitMinMax(1,16); - foreach( DeviceSetting *s, d->deviceSettings ) { + for (int i = 1; i <= d->deviceSettings.count(); ++i) { + DeviceSetting *s = d->deviceSettings[i]; connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&, const QString&, const QString&)), s, SLOT(setProtocolValue(const QString&, const QString&, const QString&, const QString&))); d->settingsLayout->addWidget( s ); } From 83dbd675cffc975a15fbb232df1df131be62334f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Jun 2012 17:21:16 +0200 Subject: [PATCH 2047/2215] Add python compiled files to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2c86bf2c..a8b54702 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ Doxyfile html/ latex/ CMakeLists.txt.user +*.pyc From 648b713955c1890c5b1328cae338adecae50fe9b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 21 Jun 2012 17:19:45 +0200 Subject: [PATCH 2048/2215] First version of a headless server for Telldus Live! --- examples/python/live/server/Client.py | 119 ++++++++++++++++++ examples/python/live/server/LiveMessage.py | 71 +++++++++++ .../python/live/server/LiveMessageToken.py | 114 +++++++++++++++++ examples/python/live/server/ServerList.py | 34 +++++ examples/python/live/server/TelldusCore.py | 40 ++++++ examples/python/live/server/run-client.py | 10 ++ 6 files changed, 388 insertions(+) create mode 100644 examples/python/live/server/Client.py create mode 100644 examples/python/live/server/LiveMessage.py create mode 100644 examples/python/live/server/LiveMessageToken.py create mode 100644 examples/python/live/server/ServerList.py create mode 100644 examples/python/live/server/TelldusCore.py create mode 100755 examples/python/live/server/run-client.py diff --git a/examples/python/live/server/Client.py b/examples/python/live/server/Client.py new file mode 100644 index 00000000..925e64cf --- /dev/null +++ b/examples/python/live/server/Client.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- + +import socket, ssl +import time, os + +from configobj import ConfigObj + +from ServerList import * +from TelldusCore import * +from LiveMessage import * + +class Client(): + def __init__(self): + self.publicKey = '' + self.privateKey = '' + self.hashMethod = 'sha1' + self.supportedMethods = 0 + self.tellduscore = TelldusCore() + self.serverList = ServerList() + + self.configPath = os.environ['HOME'] + '/.config/Telldus' + self.configFilename = 'TelldusLive.conf' + self.config = ConfigObj(self.configPath + '/' + self.configFilename) + self.connect(self.serverList.popServer()) + + def __del__(self): + try: + os.makedirs(self.configPath) + except: + pass + self.config.write() + + def connect(self, server): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1, ca_certs="/etc/ssl/certs/ca-certificates.crt",cert_reqs=ssl.CERT_REQUIRED) + self.socket.settimeout(5) + self.socket.connect((server['address'], int(server['port']))) + + uuid = '' + try: + uuid = self.config['uuid'] + except: + pass + + msg = LiveMessage('Register') + msg.append({ + 'key': self.publicKey, + 'uuid': uuid, + 'hash': self.hashMethod + }) + msg.append({ + 'protocol': 2, + 'version': '1', + 'os': 'linux', + 'os-version': 'unknown' + }) + + self.socket.write(self.signedMessage(msg)) + while(1): + try: + resp = self.socket.read(1024) + except ssl.SSLError: + # Timeout, try again + # TODO(micke): Check pong timer here + continue + if (resp == ''): + print("no response") + break + continue + + envelope = LiveMessage.fromByteArray(resp) + if (envelope.verifySignature(self.hashMethod, self.privateKey)): + self.handleMessage(LiveMessage.fromByteArray(envelope.argument(0).stringVal)) + else: + print "Signature failed" + + def handleCommand(self, args): + if (args['action'].stringVal == 'turnon'): + self.tellduscore.turnon(args['id'].intVal) + elif (args['action'].stringVal == 'turnoff'): + self.tellduscore.turnoff(args['id'].intVal) + else: + return + + if ('ACK' in args): + #Respond to ack + msg = LiveMessage("ACK") + msg.append(args['ACK'].intVal) + self.socket.write(self.signedMessage(msg)) + + def handleMessage(self, message): + if (message.name() == "notregistered"): + params = message.argument(0).dictVal + self.config['uuid'] = params['uuid'].stringVal + self.config['activationUrl'] = params['url'].stringVal + print "This client isn't activated, please activate it using this url:\n%s" % params['url'].stringVal + return + + if (message.name() == "registered"): + params = message.argument(0).dictVal + self.supportedMethods = params['supportedMethods'].intVal + self.tellduscore.setSupportedMethods(self.supportedMethods) + self.sendDevicesReport() + return + + if (message.name() == "command"): + self.handleCommand(message.argument(0).dictVal) + return + + print "Did not understand: %s" % message.toByteArray() + + + def sendDevicesReport(self): + msg = LiveMessage("DevicesReport") + msg.append(self.tellduscore.getList()) + self.socket.write(self.signedMessage(msg)) + + def signedMessage(self, message): + return message.toSignedMessage(self.hashMethod, self.privateKey) diff --git a/examples/python/live/server/LiveMessage.py b/examples/python/live/server/LiveMessage.py new file mode 100644 index 00000000..1741f256 --- /dev/null +++ b/examples/python/live/server/LiveMessage.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- + +import hashlib +from LiveMessageToken import * + +class LiveMessage(): + def __init__(self, name = ""): + if (name != ""): + self.args = [LiveMessageToken(name)] + else: + self.args = [] + + def append(self, argument): + self.args.append(LiveMessageToken(argument)) + + def argument(self,index): + if (len(self.args) > index+1): + return self.args[index+1] + + return LiveMessageToken() + + def count(self): + return len(self.args)-1 + + def name(self): + return self.argument(-1).stringVal.lower() + + def toByteArray(self): + retval = '' + for arg in self.args: + retval = retval + arg.toByteArray() + return retval + + def toSignedMessage(self, hashMethod, privateKey): + message = self.toByteArray() + envelope = LiveMessage(LiveMessage.signatureForMessage(message, hashMethod, privateKey)) + envelope.append(message) + return envelope.toByteArray() + + def verifySignature(self, hashMethod, privateKey): + signature = self.name() + rawMessage = self.argument(0).stringVal + return (self.signatureForMessage(rawMessage, hashMethod, privateKey) == signature) + + @staticmethod + def fromByteArray(rawString): + list = [] + start = 0 + while (start < len(rawString)): + start, token = LiveMessageToken.parseToken(rawString, start) + if (token.valueType == LiveMessageToken.TYPE_INVALID): + break + list.append(token) + + msg = LiveMessage() + msg.args = list + return msg + + @staticmethod + def signatureForMessage(msg, hashMethod, privateKey): + h = 0 + if (hashMethod == "sha512"): + h = hashlib.sha512() + elif (hashMethod == "sha256"): + h = hashlib.sha256() + else: + h = hashlib.sha1() + + h.update(msg) + h.update(privateKey) + return h.hexdigest().lower() diff --git a/examples/python/live/server/LiveMessageToken.py b/examples/python/live/server/LiveMessageToken.py new file mode 100644 index 00000000..8064cc7e --- /dev/null +++ b/examples/python/live/server/LiveMessageToken.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +import base64 + +class LiveMessageToken(): + TYPE_INVALID, TYPE_INT, TYPE_STRING, TYPE_BASE64, TYPE_LIST, TYPE_DICTIONARY = range(6) + + def __init__(self, value = None): + self.valueType = LiveMessageToken.TYPE_INVALID + self.stringVal = '' + self.intVal = 0 + self.dictVal = {} + self.listVal = [] + if (type(value) is int): + self.valueType = self.TYPE_INT + self.intVal = value + + elif (type(value) is str): + self.valueType = self.TYPE_STRING + self.stringVal = value + + elif (type(value) is list): + self.valueType = self.TYPE_LIST + for v in value: + self.listVal.append(LiveMessageToken(v)) + + elif (type(value) is dict): + self.valueType = self.TYPE_DICTIONARY + for key in value: + self.dictVal[key] = LiveMessageToken(value[key]) + + + def toByteArray(self): + if (self.valueType == LiveMessageToken.TYPE_INT): + return 'i%Xs' % self.intVal + + if (self.valueType == LiveMessageToken.TYPE_LIST): + retval = 'l' + for token in self.listVal: + retval = retval + token.toByteArray() + return retval + 's' + + if (self.valueType == LiveMessageToken.TYPE_DICTIONARY): + retval = 'h' + for key in self.dictVal: + retval = retval + LiveMessageToken(key).toByteArray() + self.dictVal[key].toByteArray() + return retval + 's' + + return '%X:%s' % (len(self.stringVal), self.stringVal,) + + @staticmethod + def parseToken(string, start): + token = LiveMessageToken() + if (start >= len(string)): + return (start, token) + + if (string[start] == 'i'): + start+=1 + index = string.find('s', start) + if (index < 0): + return (start, token) + + try: + token.intVal = int(string[start:index], 16) + token.valueType = LiveMessageToken.TYPE_INT + start = index + 1 + except: + return (start, token) + + elif (string[start] == 'l'): + start+=1 + while (start < len(string) and string[start] != 's'): + start, listToken = LiveMessageToken.parseToken(string, start) + if (listToken.valueType == LiveMessageToken.TYPE_INVALID): + break + token.valueType = LiveMessageToken.TYPE_LIST + token.listVal.append(listToken) + start+=1 + + elif (string[start] == 'h'): + start+=1 + while (start < len(string) and string[start] != 's'): + start, keyToken = LiveMessageToken.parseToken(string, start) + if (keyToken.valueType == LiveMessageToken.TYPE_INVALID): + break + start, valueToken = LiveMessageToken.parseToken(string, start) + if (valueToken.valueType == LiveMessageToken.TYPE_INVALID): + break + token.valueType = LiveMessageToken.TYPE_DICTIONARY + token.dictVal[keyToken.stringVal] = valueToken + start+=1 + + elif (string[start] == 'u'): #Base64 + start+=1 + start, token = LiveMessageToken.parseToken(string, start) + token.valueType = LiveMessageToken.TYPE_BASE64 + token.stringVal = base64.decodestring(token.stringVal) + + else: #String + index = string.find(':', start) + if (index < 0): + return (start, token) + + try: + length = int(string[start:index], 16) + except: + return (start, token) + + start = index + length + 1 + token.stringVal = string[index+1:start] + token.valueType = LiveMessageToken.TYPE_STRING + + return (start, token) + diff --git a/examples/python/live/server/ServerList.py b/examples/python/live/server/ServerList.py new file mode 100644 index 00000000..00ebcb10 --- /dev/null +++ b/examples/python/live/server/ServerList.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +import httplib +import xml.parsers.expat + +class ServerList(): + + def __init__(self): + self.list = [] + self.retrieveServerList() + + def popServer(self): + if (self.list == []): + self.retrieveServerList() + + if (self.list == []): + return False + + return self.list.pop(0) + + + def retrieveServerList(self): + conn = httplib.HTTPConnection("api.telldus.com:80") + conn.request('GET', "/server/assign?protocolVersion=2") + response = conn.getresponse() + + p = xml.parsers.expat.ParserCreate() + + p.StartElementHandler = self._startElement + p.Parse(response.read()) + + def _startElement(self, name, attrs): + if (name == 'server'): + self.list.append(attrs) diff --git a/examples/python/live/server/TelldusCore.py b/examples/python/live/server/TelldusCore.py new file mode 100644 index 00000000..692baa19 --- /dev/null +++ b/examples/python/live/server/TelldusCore.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- + +import ctypes + +class TelldusCore(): + + def __init__(self): + self.supportedMethods = 0 + self.lib = ctypes.cdll.LoadLibrary('libtelldus-core.so') + self.list = [] + for i in range(self.lib.tdGetNumberOfDevices()): + id = self.lib.tdGetDeviceId(i) + device = {'id': id} + namePtr = self.lib.tdGetName(id) + device['name'] = ctypes.c_char_p(namePtr).value + self.lib.tdReleaseString(namePtr) + stateValuePtr = self.lib.tdLastSentValue(id) + device['stateValue'] = ctypes.c_char_p(stateValuePtr).value + self.lib.tdReleaseString(stateValuePtr) + self.list.append(device) + + def getList(self): + return self.list + + def setSupportedMethods(self, supportedMethods): + if (self.supportedMethods == supportedMethods): + return + + self.supportedMethods = supportedMethods + for device in self.list: + device['methods'] = self.lib.tdMethods(device['id'], supportedMethods) + device['state'] = self.lib.tdLastSentCommand(device['id'], supportedMethods) + + def turnoff(self, id): + self.lib.tdTurnOff(id) + print "Turning off: %i" % id + + def turnon(self, id): + self.lib.tdTurnOn(id) + print "Turning on: %i" % id diff --git a/examples/python/live/server/run-client.py b/examples/python/live/server/run-client.py new file mode 100755 index 00000000..4153955e --- /dev/null +++ b/examples/python/live/server/run-client.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import signal +from Client import * + +if __name__ == "__main__": + c = Client() + #signal.signal(signal.SIGINT, c.shutdown) + #c.start() From 6feb0ee2f319c05b64148815713eefe7aee1c0e8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Jun 2012 17:19:43 +0200 Subject: [PATCH 2049/2215] Implement pong --- examples/python/live/server/Client.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/examples/python/live/server/Client.py b/examples/python/live/server/Client.py index 925e64cf..736bf0c1 100644 --- a/examples/python/live/server/Client.py +++ b/examples/python/live/server/Client.py @@ -14,6 +14,7 @@ class Client(): self.publicKey = '' self.privateKey = '' self.hashMethod = 'sha1' + self.pongTimer = 0 self.supportedMethods = 0 self.tellduscore = TelldusCore() self.serverList = ServerList() @@ -56,23 +57,28 @@ class Client(): }) self.socket.write(self.signedMessage(msg)) + self.pongTimer = time.time() while(1): try: resp = self.socket.read(1024) except ssl.SSLError: - # Timeout, try again - # TODO(micke): Check pong timer here + # Timeout, try again after some maintenance + if (time.time() - self.pongTimer >= 360): # No pong received + print("No pong received, disconnecting") + break + continue if (resp == ''): print("no response") break - continue envelope = LiveMessage.fromByteArray(resp) - if (envelope.verifySignature(self.hashMethod, self.privateKey)): - self.handleMessage(LiveMessage.fromByteArray(envelope.argument(0).stringVal)) - else: + if (not envelope.verifySignature(self.hashMethod, self.privateKey)): print "Signature failed" + continue + + self.pongTimer = time.time() + self.handleMessage(LiveMessage.fromByteArray(envelope.argument(0).stringVal)) def handleCommand(self, args): if (args['action'].stringVal == 'turnon'): @@ -107,6 +113,9 @@ class Client(): self.handleCommand(message.argument(0).dictVal) return + if (message.name() == "pong"): + return + print "Did not understand: %s" % message.toByteArray() From b9d23245526d55f526c0613d38db940e7a01c7da Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Jun 2012 17:20:15 +0200 Subject: [PATCH 2050/2215] Implement ping --- examples/python/live/server/Client.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/python/live/server/Client.py b/examples/python/live/server/Client.py index 736bf0c1..f73ced4c 100644 --- a/examples/python/live/server/Client.py +++ b/examples/python/live/server/Client.py @@ -15,6 +15,7 @@ class Client(): self.privateKey = '' self.hashMethod = 'sha1' self.pongTimer = 0 + self.pingTimer = 0 self.supportedMethods = 0 self.tellduscore = TelldusCore() self.serverList = ServerList() @@ -58,6 +59,7 @@ class Client(): self.socket.write(self.signedMessage(msg)) self.pongTimer = time.time() + self.pingTimer = time.time() while(1): try: resp = self.socket.read(1024) @@ -66,8 +68,14 @@ class Client(): if (time.time() - self.pongTimer >= 360): # No pong received print("No pong received, disconnecting") break + if (time.time() - self.pingTimer >= 120): + # Time to ping + msg = LiveMessage("Ping") + self.socket.write(self.signedMessage(msg)) + self.pingTimer = time.time() continue + if (resp == ''): print("no response") break From 84330f851891e85413548f9693c3156e46d20757 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 27 Jun 2012 17:21:21 +0200 Subject: [PATCH 2051/2215] Print the message before executing them. --- examples/python/live/server/TelldusCore.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/python/live/server/TelldusCore.py b/examples/python/live/server/TelldusCore.py index 692baa19..43667dde 100644 --- a/examples/python/live/server/TelldusCore.py +++ b/examples/python/live/server/TelldusCore.py @@ -32,9 +32,9 @@ class TelldusCore(): device['state'] = self.lib.tdLastSentCommand(device['id'], supportedMethods) def turnoff(self, id): - self.lib.tdTurnOff(id) print "Turning off: %i" % id + self.lib.tdTurnOff(id) def turnon(self, id): - self.lib.tdTurnOn(id) print "Turning on: %i" % id + self.lib.tdTurnOn(id) From 9d11cfb07f3b8d71ec36448f99c6bbd33a688d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 4 Aug 2012 18:42:00 +0200 Subject: [PATCH 2052/2215] added telldus python bindings --- bindings/python/MANIFEST.in | 3 + bindings/python/example/__init__.py | 42 +++ bindings/python/setup.py | 19 ++ bindings/python/telldus-core.h | 161 ++++++++++ bindings/python/telldus.c | 448 ++++++++++++++++++++++++++++ 5 files changed, 673 insertions(+) create mode 100644 bindings/python/MANIFEST.in create mode 100644 bindings/python/example/__init__.py create mode 100644 bindings/python/setup.py create mode 100644 bindings/python/telldus-core.h create mode 100644 bindings/python/telldus.c diff --git a/bindings/python/MANIFEST.in b/bindings/python/MANIFEST.in new file mode 100644 index 00000000..f2039627 --- /dev/null +++ b/bindings/python/MANIFEST.in @@ -0,0 +1,3 @@ +include telldus.c +include telldus-core.h +recursive-include example/* \ No newline at end of file diff --git a/bindings/python/example/__init__.py b/bindings/python/example/__init__.py new file mode 100644 index 00000000..b8fdb56f --- /dev/null +++ b/bindings/python/example/__init__.py @@ -0,0 +1,42 @@ + +import telldus +import time + +telldus.tdInit() +devices = telldus.tdGetNumberOfDevices(); +print "Devices: %d\n" % devices + +allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM + +for i in xrange(devices): + deviceid = telldus.tdGetDeviceId(i); + name = tdGetName(id) + + print "%s - %s\n" % (deviceid, name) + + methods = telldus.tdMethods(deviceid, allMethods) + + if methods & telldus.TELLDUS_TURNON: + print " * TurnOn\n" + telldus.tdTurnOn(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TURNOFF: + print " * TurnOff\n" + telldus.tdTurnOff(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_BELL: + echo " * Bell\n" + telldus.tdBell(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TOGGLE + print " * Toggle\n" + + if methods & telldus.TELLDUS_DIM: + print " * Dim\n" + telldus.tdDim(deviceid, 128) + time.sleep(1) + +telldus.tdClose() \ No newline at end of file diff --git a/bindings/python/setup.py b/bindings/python/setup.py new file mode 100644 index 00000000..62dc389e --- /dev/null +++ b/bindings/python/setup.py @@ -0,0 +1,19 @@ +from distutils.core import setup, Extension + +telldus = Extension( + 'telldus', + include_dirs = ['/usr/local/include'], + libraries = ['telldus-core'], + library_dirs = ['/usr/lib'], + sources = ['telldus.c'] +) + +setup( + name = 'telldus', + version = '1.0', + description = 'Python bindings for telldus', + author='Oyvind Saltvik', + author_email='oyvind.saltvik@gmail.com', + url='http://github.com/fivethreeo/telldus/', + ext_modules = [telldus] +) \ No newline at end of file diff --git a/bindings/python/telldus-core.h b/bindings/python/telldus-core.h new file mode 100644 index 00000000..c50804ea --- /dev/null +++ b/bindings/python/telldus-core.h @@ -0,0 +1,161 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ +#define TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLSTICK_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef _WINDOWS + #if defined(TELLDUSCORE_EXPORTS) + #if defined(_CL64) + #define TELLSTICK_API + #else + #define TELLSTICK_API __declspec(dllexport) + #endif + #else + #define TELLSTICK_API __declspec(dllimport) + #endif + #define WINAPI __stdcall +#else + #define WINAPI + #define TELLSTICK_API __attribute__ ((visibility("default"))) +#endif + +typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); +typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); +typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); +typedef void (WINAPI *TDSensorEvent)(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context); +typedef void (WINAPI *TDControllerEvent)(int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context); + +#ifndef __cplusplus + #define bool char +#endif + +#ifdef __cplusplus +extern "C" { +#endif + TELLSTICK_API void WINAPI tdInit(void); + TELLSTICK_API int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); + TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context); + TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); + TELLSTICK_API void WINAPI tdClose(void); + TELLSTICK_API void WINAPI tdReleaseString(char *thestring); + + TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); + TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); + TELLSTICK_API int WINAPI tdBell(int intDeviceId); + TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI tdExecute(int intDeviceId); + TELLSTICK_API int WINAPI tdUp(int intDeviceId); + TELLSTICK_API int WINAPI tdDown(int intDeviceId); + TELLSTICK_API int WINAPI tdStop(int intDeviceId); + TELLSTICK_API int WINAPI tdLearn(int intDeviceId); + TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); + TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); + TELLSTICK_API char *WINAPI tdLastSentValue( int intDeviceId ); + + TELLSTICK_API int WINAPI tdGetNumberOfDevices(); + TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); + TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); + + TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); + + TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); + TELLSTICK_API char * WINAPI tdGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, const char *intModel); + + TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); + + TELLSTICK_API int WINAPI tdAddDevice(); + TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); + + TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); + + TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); + TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); + + TELLSTICK_API int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); + TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); + + TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); + TELLSTICK_API int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen); + TELLSTICK_API int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value); + TELLSTICK_API int WINAPI tdRemoveController(int controllerId); + +#ifdef __cplusplus +} +#endif + +// Device methods +#define TELLSTICK_TURNON 1 +#define TELLSTICK_TURNOFF 2 +#define TELLSTICK_BELL 4 +#define TELLSTICK_TOGGLE 8 +#define TELLSTICK_DIM 16 +#define TELLSTICK_LEARN 32 +#define TELLSTICK_EXECUTE 64 +#define TELLSTICK_UP 128 +#define TELLSTICK_DOWN 256 +#define TELLSTICK_STOP 512 + +// Sensor value types +#define TELLSTICK_TEMPERATURE 1 +#define TELLSTICK_HUMIDITY 2 + +// Error codes +#define TELLSTICK_SUCCESS 0 +#define TELLSTICK_ERROR_NOT_FOUND -1 +#define TELLSTICK_ERROR_PERMISSION_DENIED -2 +#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 +#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 +#define TELLSTICK_ERROR_COMMUNICATION -5 +#define TELLSTICK_ERROR_CONNECTING_SERVICE -6 +#define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7 +#define TELLSTICK_ERROR_SYNTAX -8 +#define TELLSTICK_ERROR_BROKEN_PIPE -9 +#define TELLSTICK_ERROR_COMMUNICATING_SERVICE -10 +#define TELLSTICK_ERROR_CONFIG_SYNTAX -11 +#define TELLSTICK_ERROR_UNKNOWN -99 + +// Device typedef +#define TELLSTICK_TYPE_DEVICE 1 +#define TELLSTICK_TYPE_GROUP 2 +#define TELLSTICK_TYPE_SCENE 3 + +// Controller typedef +#define TELLSTICK_CONTROLLER_TELLSTICK 1 +#define TELLSTICK_CONTROLLER_TELLSTICK_DUO 2 +#define TELLSTICK_CONTROLLER_TELLSTICK_NET 3 + +// Device changes +#define TELLSTICK_DEVICE_ADDED 1 +#define TELLSTICK_DEVICE_CHANGED 2 +#define TELLSTICK_DEVICE_REMOVED 3 +#define TELLSTICK_DEVICE_STATE_CHANGED 4 + +// Change types +#define TELLSTICK_CHANGE_NAME 1 +#define TELLSTICK_CHANGE_PROTOCOL 2 +#define TELLSTICK_CHANGE_MODEL 3 +#define TELLSTICK_CHANGE_METHOD 4 +#define TELLSTICK_CHANGE_AVAILABLE 5 +#define TELLSTICK_CHANGE_FIRMWARE 6 + +#endif // TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ diff --git a/bindings/python/telldus.c b/bindings/python/telldus.c new file mode 100644 index 00000000..390f614a --- /dev/null +++ b/bindings/python/telldus.c @@ -0,0 +1,448 @@ +#include "Python.h" +#include +#include + +/* estrdup.c -- duplicate a string, die if error + * + * char *string; + * char *newstring; + * newstring = estrdup(string); + * + * estrdup returns a copy of its argument, located in memory + * allocated from the heap. If it is unable to allocate the + * necessary memory, estrdup executes error("no memory"). + * (Generally, the routine error is not expected to return, + * but if it does, estrdup will return NULL.) + */ + +char * +estrdup(char *s) +{ + register char *t; + + if (NULL == (t = malloc(strlen(s)+1))) { + return NULL; + } + strcpy(t, s); + return(t); +} + +static PyObject * +telldus_tdInit(PyObject *self) +{ + tdInit(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +telldus_tdClose(PyObject *self) +{ + tdClose(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +telldus_tdTurnOn(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdTurnOn(id)); +} + +static PyObject * +telldus_tdTurnOff(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdTurnOff(id)); +} + +static PyObject * +telldus_tdBell(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdBell(id)); +} + +static PyObject * +telldus_tdDim(PyObject *self, PyObject *args) +{ + long id; + long level; + + if (!PyArg_ParseTuple(args, "ll", &id, &level)) + return NULL; + + if (level < 0 || level > 255) + return NULL; + + return PyBool_FromLong((long) tdDim(id, level)); +} + +static PyObject * +telldus_tdLearn(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdLearn(id)); +} + +static PyObject * +telldus_tdMethods(PyObject *self, PyObject *args) +{ + long id; + long supportedmethods; + + if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) + return NULL; + + return PyLong_FromLong((long) tdMethods(id, supportedmethods)); +} + + +static PyObject * +telldus_tdLastSentCommand(PyObject *self, PyObject *args) +{ + long id; + long supportedmethods; + + if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) + return NULL; + + return PyLong_FromLong((long) tdLastSentCommand(id, supportedmethods)); +} + +static PyObject * +telldus_tdLastSentValue(PyObject *self, PyObject *args) +{ + long id; + char* value; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + value = tdLastSentValue(id); + retval = estrdup(value); + tdReleaseString(value); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdGetNumberOfDevices(PyObject *self) +{ + return PyLong_FromLong((long) tdGetNumberOfDevices()); +} + +static PyObject * +telldus_tdGetDeviceId(PyObject *self, PyObject *args) +{ + long index; + + if (!PyArg_ParseTuple(args, "l", &index)) + return NULL; + + return PyLong_FromLong((long) tdGetDeviceId(index)); +} + +static PyObject * +telldus_tdGetDeviceType(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdGetDeviceType(id)); +} + +static PyObject * +telldus_tdGetErrorString(PyObject *self, PyObject *args) +{ + long errorno; + char* errorString; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &errorno)) + return NULL; + + errorString = tdGetErrorString(errorno); + retval = estrdup(errorString); + tdReleaseString(errorString); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdGetName(PyObject *self, PyObject *args) +{ + long id; + char* name; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + name = tdGetName(id); + retval = estrdup(name); + tdReleaseString(name); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetName(PyObject *self, PyObject *args) +{ + long id; + char* name; + + if (!PyArg_ParseTuple(args, "ls", &id, &name)) + return NULL; + + return PyBool_FromLong((long) tdSetName(id, name)); +} + +static PyObject * +telldus_tdGetProtocol(PyObject *self, PyObject *args) +{ + long id; + char* protocol; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + protocol = tdGetProtocol(id); + retval = estrdup(protocol); + tdReleaseString(protocol); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetProtocol(PyObject *self, PyObject *args) +{ + long id; + char* protocol; + + if (!PyArg_ParseTuple(args, "ls", &id, &protocol)) + return NULL; + + return PyBool_FromLong((long) tdSetProtocol(id, protocol)); + +} + +static PyObject * +telldus_tdGetModel(PyObject *self, PyObject *args) +{ + long id; + char* model; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + model = tdGetModel(id); + retval = estrdup(model); + tdReleaseString(model); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetModel(PyObject *self, PyObject *args) +{ + long id; + char* model; + + if (!PyArg_ParseTuple(args, "ls", &id, &model)) + return NULL; + + return PyBool_FromLong((long) tdSetProtocol(id, model)); + +} + +static PyObject * +telldus_tdGetDeviceParameter(PyObject *self, PyObject *args) +{ + long id; + char* name; + char* defaultValue; + char* param; + char* retval; + + if (!PyArg_ParseTuple(args, "lss", &id, &name, &defaultValue)) + return NULL; + + param = tdGetDeviceParameter(id, name, defaultValue); + retval = estrdup(param); + tdReleaseString(param); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetDeviceParameter(PyObject *self, PyObject *args) +{ + long id; + char* name; + char* value; + + if (!PyArg_ParseTuple(args, "lss", &id, &name, &value)) + return NULL; + + return PyBool_FromLong((long) tdSetDeviceParameter(id, name, value)); +} + +static PyObject * +telldus_tdAddDevice(PyObject *self) +{ + return PyLong_FromLong((long) tdAddDevice()); +} + +static PyObject * +telldus_tdRemoveDevice(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdRemoveDevice(id)); +} + +static PyObject * +telldus_tdSendRawCommand(PyObject *self, PyObject *args) +{ + char *command; + long reserved = 0; + + if (!PyArg_ParseTuple(args, "s|l", &command, &reserved)); + return NULL; + + return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); +} + +static PyMethodDef telldus_methods[] = { + /* The cast of the function is necessary since PyCFunction values + * only take two PyObject* parameters, and keywdarg_parrot() takes + * three. + */ + {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, + {"tdClose", (PyCFunction) telldus_tdClose, METH_NOARGS, "Close telldus."}, + {"tdTurnOn", (PyCFunction) telldus_tdTurnOn, METH_VARARGS, "Turn on device."}, + {"tdTurnOff", (PyCFunction) telldus_tdTurnOff, METH_VARARGS, "Turn off device."}, + {"tdBell", (PyCFunction) telldus_tdBell, METH_VARARGS, "Bell device."}, + {"tdDim", (PyCFunction) telldus_tdDim, METH_VARARGS, "Dim device."}, + {"tdLearn", (PyCFunction) telldus_tdLearn, METH_VARARGS, "Learn device."}, + {"tdMethods", (PyCFunction) telldus_tdMethods, METH_VARARGS, "Methods comment."}, + {"tdLastSentCommand", (PyCFunction) telldus_tdLastSentCommand, METH_VARARGS, "LastSentCommand comment."}, + {"tdLastSentValue", (PyCFunction) telldus_tdLastSentValue, METH_VARARGS, "LastSentValue comment."}, + {"tdGetNumberOfDevices", (PyCFunction) telldus_tdGetNumberOfDevices, METH_VARARGS, "GetNumberOfDevices comment."}, + {"tdGetDeviceId", (PyCFunction) telldus_tdGetDeviceId, METH_VARARGS, "GetDeviceId comment."}, + {"tdGetDeviceType", (PyCFunction) telldus_tdGetDeviceType, METH_VARARGS, "GetDeviceType comment."}, + {"tdGetErrorString", (PyCFunction) telldus_tdGetErrorString, METH_VARARGS, "GetErrorString comment."}, + {"tdGetName", (PyCFunction) telldus_tdGetName, METH_VARARGS, "GetName comment."}, + {"tdSetName", (PyCFunction) telldus_tdSetName, METH_VARARGS, "SetName comment."}, + {"tdGetProtocol", (PyCFunction) telldus_tdGetProtocol, METH_VARARGS, "GetProtocol comment."}, + {"tdSetProtocol", (PyCFunction) telldus_tdSetProtocol, METH_VARARGS, "SetProtocol comment."}, + {"tdGetModel", (PyCFunction) telldus_tdGetModel, METH_VARARGS, "GetModel comment."}, + {"tdSetModel", (PyCFunction) telldus_tdSetModel, METH_VARARGS, "SetModel comment."}, + {"tdGetDeviceParameter", (PyCFunction) telldus_tdGetDeviceParameter, METH_VARARGS, "GetDeviceParameter comment."}, + {"tdSetDeviceParameter", (PyCFunction) telldus_tdSetDeviceParameter, METH_VARARGS, "SetDeviceParameter comment."}, + {"tdAddDevice", (PyCFunction) telldus_tdAddDevice, METH_NOARGS, "AddDevice comment."}, + {"tdRemoveDevice", (PyCFunction) telldus_tdRemoveDevice, METH_VARARGS, "RemoveDevice comment."}, + {"tdSendRawCommand", (PyCFunction) telldus_tdSendRawCommand, METH_VARARGS, "SendRawCommand comment."}, + {NULL, NULL, 0, NULL} /* sentinel */ +}; + +void +inittelldus(void) +{ + /* Create the module and add the functions */ + PyObject *module = Py_InitModule("telldus", telldus_methods); + + PyObject *TELLSTICK_TURNON_GLUE = PyLong_FromLong((long) TELLSTICK_TURNON); + PyObject_SetAttrString(module, "TELLSTICK_TURNON", TELLSTICK_TURNON_GLUE); + Py_DECREF(TELLSTICK_TURNON_GLUE); + + + PyObject *TELLSTICK_TURNOFF_GLUE = PyLong_FromLong((long) TELLSTICK_TURNOFF); + PyObject_SetAttrString(module, "TELLSTICK_TURNOFF", TELLSTICK_TURNOFF_GLUE); + Py_DECREF(TELLSTICK_TURNOFF_GLUE); + + + PyObject *TELLSTICK_BELL_GLUE = PyLong_FromLong((long) TELLSTICK_BELL); + PyObject_SetAttrString(module, "TELLSTICK_BELL", TELLSTICK_BELL_GLUE); + Py_DECREF(TELLSTICK_BELL_GLUE); + + + PyObject *TELLSTICK_TOGGLE_GLUE = PyLong_FromLong((long) TELLSTICK_TOGGLE); + PyObject_SetAttrString(module, "TELLSTICK_TOGGLE", TELLSTICK_TOGGLE_GLUE); + Py_DECREF(TELLSTICK_TOGGLE_GLUE); + + + PyObject *TELLSTICK_DIM_GLUE = PyLong_FromLong((long) TELLSTICK_DIM); + PyObject_SetAttrString(module, "TELLSTICK_DIM", TELLSTICK_DIM_GLUE); + Py_DECREF(TELLSTICK_DIM_GLUE); + + + PyObject *TELLSTICK_LEARN_GLUE = PyLong_FromLong((long) TELLSTICK_LEARN); + PyObject_SetAttrString(module, "TELLSTICK_LEARN", TELLSTICK_LEARN_GLUE); + Py_DECREF(TELLSTICK_LEARN_GLUE); + + + PyObject *TELLSTICK_SUCCESS_GLUE = PyLong_FromLong((long) TELLSTICK_SUCCESS); + PyObject_SetAttrString(module, "TELLSTICK_SUCCESS", TELLSTICK_SUCCESS_GLUE); + Py_DECREF(TELLSTICK_SUCCESS_GLUE); + + + PyObject *TELLSTICK_ERROR_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_NOT_FOUND); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_NOT_FOUND", TELLSTICK_ERROR_NOT_FOUND_GLUE); + Py_DECREF(TELLSTICK_ERROR_NOT_FOUND_GLUE); + + + PyObject *TELLSTICK_ERROR_PERMISSION_DENIED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_PERMISSION_DENIED); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_PERMISSION_DENIED", TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); + Py_DECREF(TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); + + + PyObject *TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_DEVICE_NOT_FOUND); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_DEVICE_NOT_FOUND", TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); + Py_DECREF(TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); + + + PyObject *TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_METHOD_NOT_SUPPORTED); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_METHOD_NOT_SUPPORTED", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); + Py_DECREF(TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); + + + PyObject *TELLSTICK_ERROR_COMMUNICATION_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_COMMUNICATION); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_COMMUNICATION", TELLSTICK_ERROR_COMMUNICATION_GLUE); + Py_DECREF(TELLSTICK_ERROR_COMMUNICATION_GLUE); + + + PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_UNKNOWN); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_UNKNOWN", TELLSTICK_ERROR_UNKNOWN_GLUE); + Py_DECREF(TELLSTICK_ERROR_UNKNOWN_GLUE); + + + PyObject *TELLSTICK_TYPE_DEVICE_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_DEVICE); + PyObject_SetAttrString(module, "TELLSTICK_TYPE_DEVICE", TELLSTICK_TYPE_DEVICE_GLUE); + Py_DECREF(TELLSTICK_TYPE_DEVICE_GLUE); + + + PyObject *TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); + PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); + Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); +} \ No newline at end of file From cce0c16801adb376a60e1f27ba3f3e1ceb899e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 4 Aug 2012 22:09:31 +0200 Subject: [PATCH 2053/2215] fix example --- bindings/python/example/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/example/__init__.py b/bindings/python/example/__init__.py index b8fdb56f..fda9926a 100644 --- a/bindings/python/example/__init__.py +++ b/bindings/python/example/__init__.py @@ -9,7 +9,7 @@ print "Devices: %d\n" % devices allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM for i in xrange(devices): - deviceid = telldus.tdGetDeviceId(i); + deviceid = telldus.tdGetDeviceId(i) name = tdGetName(id) print "%s - %s\n" % (deviceid, name) @@ -31,7 +31,7 @@ for i in xrange(devices): telldus.tdBell(deviceid) time.sleep(1) - if methods & telldus.TELLDUS_TOGGLE + if methods & telldus.TELLDUS_TOGGLE: print " * Toggle\n" if methods & telldus.TELLDUS_DIM: From 7130ad71c9db8f5c815989fbfa9dcc43352e819a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 4 Aug 2012 22:10:58 +0200 Subject: [PATCH 2054/2215] device --- bindings/python/example/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/example/__init__.py b/bindings/python/example/__init__.py index fda9926a..cb77ced0 100644 --- a/bindings/python/example/__init__.py +++ b/bindings/python/example/__init__.py @@ -10,7 +10,7 @@ allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_ for i in xrange(devices): deviceid = telldus.tdGetDeviceId(i) - name = tdGetName(id) + name = tdGetName(deviceid) print "%s - %s\n" % (deviceid, name) From ed3b37439a494fa1d5d02f998251c4f7c4b7d844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 4 Aug 2012 22:11:50 +0200 Subject: [PATCH 2055/2215] example fix --- bindings/python/example/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/example/__init__.py b/bindings/python/example/__init__.py index cb77ced0..8118f690 100644 --- a/bindings/python/example/__init__.py +++ b/bindings/python/example/__init__.py @@ -3,7 +3,7 @@ import telldus import time telldus.tdInit() -devices = telldus.tdGetNumberOfDevices(); +devices = telldus.tdGetNumberOfDevices() print "Devices: %d\n" % devices allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM From d1b620843525686382dca0d7dc2b63969214544b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 4 Aug 2012 22:16:04 +0200 Subject: [PATCH 2056/2215] four spaces --- bindings/python/example/__init__.py | 58 ++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/bindings/python/example/__init__.py b/bindings/python/example/__init__.py index 8118f690..f5b15316 100644 --- a/bindings/python/example/__init__.py +++ b/bindings/python/example/__init__.py @@ -9,34 +9,34 @@ print "Devices: %d\n" % devices allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM for i in xrange(devices): - deviceid = telldus.tdGetDeviceId(i) - name = tdGetName(deviceid) - - print "%s - %s\n" % (deviceid, name) - - methods = telldus.tdMethods(deviceid, allMethods) - - if methods & telldus.TELLDUS_TURNON: - print " * TurnOn\n" - telldus.tdTurnOn(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_TURNOFF: - print " * TurnOff\n" - telldus.tdTurnOff(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_BELL: - echo " * Bell\n" - telldus.tdBell(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_TOGGLE: - print " * Toggle\n" - - if methods & telldus.TELLDUS_DIM: - print " * Dim\n" - telldus.tdDim(deviceid, 128) - time.sleep(1) + deviceid = telldus.tdGetDeviceId(i) + name = tdGetName(deviceid) + + print "%s - %s\n" % (deviceid, name) + + methods = telldus.tdMethods(deviceid, allMethods) + + if methods & telldus.TELLDUS_TURNON: + print " * TurnOn\n" + telldus.tdTurnOn(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TURNOFF: + print " * TurnOff\n" + telldus.tdTurnOff(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_BELL: + echo " * Bell\n" + telldus.tdBell(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TOGGLE: + print " * Toggle\n" + + if methods & telldus.TELLDUS_DIM: + print " * Dim\n" + telldus.tdDim(deviceid, 128) + time.sleep(1) telldus.tdClose() \ No newline at end of file From 241538d107f249786b9b172bfc69346f0f9a0973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 4 Aug 2012 22:16:58 +0200 Subject: [PATCH 2057/2215] telldus --- bindings/python/example/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/example/__init__.py b/bindings/python/example/__init__.py index f5b15316..2f9c52f4 100644 --- a/bindings/python/example/__init__.py +++ b/bindings/python/example/__init__.py @@ -10,7 +10,7 @@ allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_ for i in xrange(devices): deviceid = telldus.tdGetDeviceId(i) - name = tdGetName(deviceid) + name = telldus.tdGetName(deviceid) print "%s - %s\n" % (deviceid, name) From 48efae5a6fadabd4732661e75215883f82e38d79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 01:16:51 +0200 Subject: [PATCH 2058/2215] builds on 64 bit with howto --- bindings/python/setup.py | 330 ++++++++++++++++++++++++++++++++- bindings/python/telldus-core.h | 322 ++++++++++++++++---------------- bindings/python/telldus.c | 95 +++++----- 3 files changed, 538 insertions(+), 209 deletions(-) diff --git a/bindings/python/setup.py b/bindings/python/setup.py index 62dc389e..ccf8d6da 100644 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -1,10 +1,334 @@ +import sys from distutils.core import setup, Extension +DEBUG = True + +PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win') + +if PLATFORM_IS_WINDOWS: + + __doc__="""This is a distutils setup-script for the telldus extension + + To build the telldus extensions, simply execute: + python setup.py -q build + or + python setup.py -q install + to build and install into your current Python installation. + + These extensions require a number of libraries to build, some of which may + require you to install special SDKs or toolkits. This script will attempt + to build as many as it can, and at the end of the build will report any + extension modules that could not be built and why. + + This has got complicated due to the various different versions of + Visual Studio used - some VS versions are not compatible with some SDK + versions. Below are the Windows SDK versions required (and the URL - although + these are subject to being changed by MS at any time:) + + Python 2.6+: + + Build using Microsoft Visual Studio 2008 Express Edition: + http://www.microsoft.com/en-us/download/details.aspx?id=6506 + http://jenshuebel.wordpress.com/2009/02/12/visual-c-2008-express-edition-and-64-bit-targets/ + http://www.cppblog.com/Files/xcpp/VCE64BIT_WIN7SDK.zip + copy + + For 32bit build: + Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 + http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b + Run C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat + + For 64bit build: + Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO) GRMSDKX_EN_DVD.iso + http://www.microsoft.com/en-us/download/details.aspx?id=18950 + Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars64.bat to + C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat + + Python 2.3->2.5: + + Microsoft Windows Software Development Kit Update for Windows Vista (version 6.0) + http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4377f86d-c913-4b5c-b87e-ef72e5b4e065 + ** If you want to build Python 2.3, be sure to install the SDK compilers + too - although we don't use them, this setup option installs some .lib + files we do need. + ** + + If you multiple SDK versions on a single machine, set the MSSDK environment + variable to point at the one you want to use. Note that using the SDK for + a particular platform (eg, Windows 7) doesn't force you to use that OS as your + build environment. If the links above don't work, use google to find them. + + Building: + --------- + + To install the telldus extension, execute: + python setup.py -q install + + This will install the built extensions into your site-packages directory, + create an appropriate .pth file, and should leave everything ready to use. + There is no need to modify the registry. + + To build or install debug (_d) versions of these extensions, ensure you have + built or installed a debug version of Python itself, then pass the "--debug" + flag to the build command - eg: + python setup.py -q build --debug + or to build and install a debug version: + python setup.py -q build --debug install + + To build 64bit versions of this: + + * py2.5 and earlier - sorry, I've given up in disgust. Using VS2003 with + the Vista SDK is just too painful to make work, and VS2005 is not used for + any released versions of Python. See revision 1.69 of this file for the + last version that attempted to support and document this process. + + * 2.6 and later: On a 64bit OS, just build as you would on a 32bit platform. + On a 32bit platform (ie, to cross-compile), you must use VS2008 to + cross-compile Python itself. Note that by default, the 64bit tools are not + installed with VS2008, so you may need to adjust your VS2008 setup (see "For 64bit build"). Then + use: + vcs + setup.py build --plat-name=win-amd64 + + see the distutils cross-compilation documentation for more details. + """ + # Originally by Thomas Heller, started in 2000 or so. + import os + import shutil + + is_py3k = sys.version_info > (3,) # get this out of the way early on... + # We have special handling for _winreg so our setup3.py script can avoid + # using the 'imports' fixer and therefore start much faster... + if is_py3k: + import winreg as _winreg + else: + import _winreg + + try: + from distutils import log + except ImportError: + class Log: + def debug(self, msg, *args): + print msg % args + def info(self, msg, *args): + print msg % args + log = Log() + + try: + this_file = __file__ + except NameError: + this_file = sys.argv[0] + + this_file = os.path.abspath(this_file) + # We get upset if the cwd is not our source dir, but it is a PITA to + # insist people manually CD there first! + if os.path.dirname(this_file): + os.chdir(os.path.dirname(this_file)) + + + # We need to know the platform SDK dir before we can list the extensions. + def find_platform_sdk_dir(): + # Finding the Platform SDK install dir is a treat. There can be some + # dead ends so we only consider the job done if we find the "windows.h" + # landmark. + landmark = "include\\windows.h" + # 1. The use might have their current environment setup for the + # SDK, in which case the "MSSdk" env var is set. + sdkdir = os.environ.get("MSSdk") + if sdkdir: + if DEBUG: + print "PSDK: try %%MSSdk%%: '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + # 2. The "Install Dir" value in the + # HKLM\Software\Microsoft\MicrosoftSDK\Directories registry key + # sometimes points to the right thing. However, after upgrading to + # the "Platform SDK for Windows Server 2003 SP1" this is dead end. + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\MicrosoftSDK\Directories") + sdkdir, ignore = _winreg.QueryValueEx(key, "Install Dir") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ + "\Directories\Install Dir': '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + # 3. Each installed SDK (not just the platform SDK) seems to have GUID + # subkey of HKLM\Software\Microsoft\MicrosoftSDK\InstalledSDKs and + # it *looks* like the latest installed Platform SDK will be the + # only one with an "Install Dir" sub-value. + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\MicrosoftSDK\InstalledSDKs") + i = 0 + while True: + guid = _winreg.EnumKey(key, i) + guidkey = _winreg.OpenKey(key, guid) + try: + sdkdir, ignore = _winreg.QueryValueEx(guidkey, "Install Dir") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ + "\InstallSDKs\%s\Install Dir': '%s'"\ + % (guid, sdkdir) + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + i += 1 + except EnvironmentError: + pass + # 4. Vista's SDK + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\Microsoft SDKs\Windows") + sdkdir, ignore = _winreg.QueryValueEx(key, "CurrentInstallFolder") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDKs"\ + "\Windows\CurrentInstallFolder': '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + + # 5. Failing this just try a few well-known default install locations. + progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") + defaultlocs = [ + os.path.join(progfiles, "Microsoft Platform SDK"), + os.path.join(progfiles, "Microsoft SDK"), + ] + for sdkdir in defaultlocs: + if DEBUG: + print "PSDK: try default location: '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + + + # Some nasty hacks to prevent most of our extensions using a manifest, as + # the manifest - even without a reference to the CRT assembly - is enough + # to prevent the extension from loading. For more details, see + # http://bugs.python.org/issue7833 - that issue has a patch, but it is + # languishing and will probably never be fixed for Python 2.6... + if sys.version_info > (2,6): + from distutils.spawn import spawn + from distutils.msvc9compiler import MSVCCompiler + MSVCCompiler._orig_spawn = MSVCCompiler.spawn + MSVCCompiler._orig_link = MSVCCompiler.link + + # We need to override this method for versions where issue7833 *has* landed + # (ie, 2.7 and 3.2+) + def manifest_get_embed_info(self, target_desc, ld_args): + _want_assembly_kept = getattr(self, '_want_assembly_kept', False) + if not _want_assembly_kept: + return None + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + orig_manifest = arg.split(":", 1)[1] + if target_desc==self.EXECUTABLE: + rid = 1 + else: + rid = 2 + return orig_manifest, rid + return None + # always monkeypatch it in even though it will only be called in 2.7 + # and 3.2+. + MSVCCompiler.manifest_get_embed_info = manifest_get_embed_info + + def monkeypatched_spawn(self, cmd): + is_link = cmd[0].endswith("link.exe") or cmd[0].endswith('"link.exe"') + is_mt = cmd[0].endswith("mt.exe") or cmd[0].endswith('"mt.exe"') + _want_assembly_kept = getattr(self, '_want_assembly_kept', False) + if not _want_assembly_kept and is_mt: + # We don't want mt.exe run... + return + if not _want_assembly_kept and is_link: + # remove /MANIFESTFILE:... and add MANIFEST:NO + # (but note that for winxpgui, which specifies a manifest via a + # .rc file, this is ignored by the linker - the manifest specified + # in the .rc file is still added) + for i in range(len(cmd)): + if cmd[i].startswith("/MANIFESTFILE:"): + cmd[i] = "/MANIFEST:NO" + break + if _want_assembly_kept and is_mt: + # We want mt.exe run with the original manifest + for i in range(len(cmd)): + if cmd[i] == "-manifest": + cmd[i+1] = cmd[i+1] + ".orig" + break + self._orig_spawn(cmd) + if _want_assembly_kept and is_link: + # We want a copy of the original manifest so we can use it later. + for i in range(len(cmd)): + if cmd[i].startswith("/MANIFESTFILE:"): + mfname = cmd[i][14:] + shutil.copyfile(mfname, mfname + ".orig") + break + + def monkeypatched_link(self, target_desc, objects, output_filename, *args, **kw): + # no manifests for 3.3+ + self._want_assembly_kept = sys.version_info < (3,3) and \ + (os.path.basename(output_filename).startswith("PyISAPI_loader.dll") or \ + os.path.basename(output_filename).startswith("perfmondata.dll") or \ + os.path.basename(output_filename).startswith("win32ui.pyd") or \ + target_desc==self.EXECUTABLE) + try: + return self._orig_link(target_desc, objects, output_filename, *args, **kw) + finally: + delattr(self, '_want_assembly_kept') + MSVCCompiler.spawn = monkeypatched_spawn + MSVCCompiler.link = monkeypatched_link + + def find_telldus_dev_dir(): + landmark = "telldus-core.h" + dev_dir = os.environ.get("TELLDUS_DEVDIR") + if dev_dir: + if DEBUG: + print "Telldus dev dir:" % dev_dir + if os.path.isfile(os.path.join(dev_dir, landmark)): + return dev_dir + + progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") + defaultlocs = [ + os.path.join(progfiles + ' (x86)', "Telldus", "Development"), + os.path.join(progfiles, "Telldus", "Development"), + ] + for dev_dir in defaultlocs: + if DEBUG: + print "Telldus dev dir: '%s'" % dev_dir + if os.path.isfile(os.path.join(dev_dir, landmark)): + return dev_dir + if DEBUG: + print "Telldus dev dir not found, make sure dev code is installed. Or set TELLDUS_DEVDIR." + + sdk_dir = find_platform_sdk_dir() + sdk_include_dir = os.path.join(sdk_dir, 'Include') + + telldus_dev_dir = find_telldus_dev_dir() + telldus_platform = os.environ.get("TELLDUS_PLATFORM", 'x86_64') + telldus_library_dir = os.path.join(telldus_dev_dir, telldus_platform) + + include_dirs = [sdk_include_dir, os.path.dirname(this_file)] + library_dirs = [telldus_library_dir] + libraries = ['python%i%i' % (sys.version_info[0], sys.version_info[1]) , 'TelldusCore'] + define_macros = [('_WINDOWS', 1)] + +else: + include_dirs = ['/usr/include', '/usr/local/include'] + library_dirs = ['/usr/lib', '/usr/local/lib'] + libraries = ['telldus-core'] + define_macros = [] + telldus = Extension( 'telldus', - include_dirs = ['/usr/local/include'], - libraries = ['telldus-core'], - library_dirs = ['/usr/lib'], + include_dirs = include_dirs, + libraries = libraries, + library_dirs = library_dirs, + define_macros = define_macros, sources = ['telldus.c'] ) diff --git a/bindings/python/telldus-core.h b/bindings/python/telldus-core.h index c50804ea..bd7fb147 100644 --- a/bindings/python/telldus-core.h +++ b/bindings/python/telldus-core.h @@ -1,161 +1,161 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ -#define TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// TELLSTICK_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef _WINDOWS - #if defined(TELLDUSCORE_EXPORTS) - #if defined(_CL64) - #define TELLSTICK_API - #else - #define TELLSTICK_API __declspec(dllexport) - #endif - #else - #define TELLSTICK_API __declspec(dllimport) - #endif - #define WINAPI __stdcall -#else - #define WINAPI - #define TELLSTICK_API __attribute__ ((visibility("default"))) -#endif - -typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); -typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); -typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); -typedef void (WINAPI *TDSensorEvent)(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context); -typedef void (WINAPI *TDControllerEvent)(int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context); - -#ifndef __cplusplus - #define bool char -#endif - -#ifdef __cplusplus -extern "C" { -#endif - TELLSTICK_API void WINAPI tdInit(void); - TELLSTICK_API int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); - TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context); - TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); - TELLSTICK_API void WINAPI tdClose(void); - TELLSTICK_API void WINAPI tdReleaseString(char *thestring); - - TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); - TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); - TELLSTICK_API int WINAPI tdBell(int intDeviceId); - TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); - TELLSTICK_API int WINAPI tdExecute(int intDeviceId); - TELLSTICK_API int WINAPI tdUp(int intDeviceId); - TELLSTICK_API int WINAPI tdDown(int intDeviceId); - TELLSTICK_API int WINAPI tdStop(int intDeviceId); - TELLSTICK_API int WINAPI tdLearn(int intDeviceId); - TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); - TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); - TELLSTICK_API char *WINAPI tdLastSentValue( int intDeviceId ); - - TELLSTICK_API int WINAPI tdGetNumberOfDevices(); - TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); - TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); - - TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); - - TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); - TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); - TELLSTICK_API char * WINAPI tdGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, const char *intModel); - - TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); - TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); - - TELLSTICK_API int WINAPI tdAddDevice(); - TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); - - TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); - - TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); - TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); - - TELLSTICK_API int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); - TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); - - TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); - TELLSTICK_API int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen); - TELLSTICK_API int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value); - TELLSTICK_API int WINAPI tdRemoveController(int controllerId); - -#ifdef __cplusplus -} -#endif - -// Device methods -#define TELLSTICK_TURNON 1 -#define TELLSTICK_TURNOFF 2 -#define TELLSTICK_BELL 4 -#define TELLSTICK_TOGGLE 8 -#define TELLSTICK_DIM 16 -#define TELLSTICK_LEARN 32 -#define TELLSTICK_EXECUTE 64 -#define TELLSTICK_UP 128 -#define TELLSTICK_DOWN 256 -#define TELLSTICK_STOP 512 - -// Sensor value types -#define TELLSTICK_TEMPERATURE 1 -#define TELLSTICK_HUMIDITY 2 - -// Error codes -#define TELLSTICK_SUCCESS 0 -#define TELLSTICK_ERROR_NOT_FOUND -1 -#define TELLSTICK_ERROR_PERMISSION_DENIED -2 -#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 -#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 -#define TELLSTICK_ERROR_COMMUNICATION -5 -#define TELLSTICK_ERROR_CONNECTING_SERVICE -6 -#define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7 -#define TELLSTICK_ERROR_SYNTAX -8 -#define TELLSTICK_ERROR_BROKEN_PIPE -9 -#define TELLSTICK_ERROR_COMMUNICATING_SERVICE -10 -#define TELLSTICK_ERROR_CONFIG_SYNTAX -11 -#define TELLSTICK_ERROR_UNKNOWN -99 - -// Device typedef -#define TELLSTICK_TYPE_DEVICE 1 -#define TELLSTICK_TYPE_GROUP 2 -#define TELLSTICK_TYPE_SCENE 3 - -// Controller typedef -#define TELLSTICK_CONTROLLER_TELLSTICK 1 -#define TELLSTICK_CONTROLLER_TELLSTICK_DUO 2 -#define TELLSTICK_CONTROLLER_TELLSTICK_NET 3 - -// Device changes -#define TELLSTICK_DEVICE_ADDED 1 -#define TELLSTICK_DEVICE_CHANGED 2 -#define TELLSTICK_DEVICE_REMOVED 3 -#define TELLSTICK_DEVICE_STATE_CHANGED 4 - -// Change types -#define TELLSTICK_CHANGE_NAME 1 -#define TELLSTICK_CHANGE_PROTOCOL 2 -#define TELLSTICK_CHANGE_MODEL 3 -#define TELLSTICK_CHANGE_METHOD 4 -#define TELLSTICK_CHANGE_AVAILABLE 5 -#define TELLSTICK_CHANGE_FIRMWARE 6 - -#endif // TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ +#define TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ + +// The following ifdef block is the standard way of creating macros +// which make exporting from a DLL simpler. All files within this DLL +// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. +// This symbol should not be defined on any project that uses this DLL. +// This way any other project whose source files include this file see +// TELLSTICK_API functions as being imported from a DLL, whereas this DLL +// sees symbols defined with this macro as being exported. + +#ifdef _WINDOWS + #if defined(TELLDUSCORE_EXPORTS) + #if defined(_CL64) + #define TELLSTICK_API + #else + #define TELLSTICK_API __declspec(dllexport) + #endif + #else + #define TELLSTICK_API __declspec(dllimport) + #endif + #define WINAPI __stdcall +#else + #define WINAPI + #define TELLSTICK_API __attribute__ ((visibility("default"))) +#endif + +typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); +typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); +typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); +typedef void (WINAPI *TDSensorEvent)(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context); +typedef void (WINAPI *TDControllerEvent)(int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context); + +#ifndef __cplusplus + #define bool char +#endif + +#ifdef __cplusplus +extern "C" { +#endif + TELLSTICK_API void WINAPI tdInit(void); + TELLSTICK_API int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); + TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context ); + TELLSTICK_API int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context); + TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); + TELLSTICK_API void WINAPI tdClose(void); + TELLSTICK_API void WINAPI tdReleaseString(char *thestring); + + TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); + TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); + TELLSTICK_API int WINAPI tdBell(int intDeviceId); + TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); + TELLSTICK_API int WINAPI tdExecute(int intDeviceId); + TELLSTICK_API int WINAPI tdUp(int intDeviceId); + TELLSTICK_API int WINAPI tdDown(int intDeviceId); + TELLSTICK_API int WINAPI tdStop(int intDeviceId); + TELLSTICK_API int WINAPI tdLearn(int intDeviceId); + TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); + TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); + TELLSTICK_API char *WINAPI tdLastSentValue( int intDeviceId ); + + TELLSTICK_API int WINAPI tdGetNumberOfDevices(); + TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); + TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); + + TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); + + TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); + TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); + TELLSTICK_API char * WINAPI tdGetModel(int intDeviceId); + TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, const char *intModel); + + TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); + TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); + + TELLSTICK_API int WINAPI tdAddDevice(); + TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); + + TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); + + TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); + TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); + + TELLSTICK_API int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); + TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); + + TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); + TELLSTICK_API int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen); + TELLSTICK_API int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value); + TELLSTICK_API int WINAPI tdRemoveController(int controllerId); + +#ifdef __cplusplus +} +#endif + +// Device methods +#define TELLSTICK_TURNON 1 +#define TELLSTICK_TURNOFF 2 +#define TELLSTICK_BELL 4 +#define TELLSTICK_TOGGLE 8 +#define TELLSTICK_DIM 16 +#define TELLSTICK_LEARN 32 +#define TELLSTICK_EXECUTE 64 +#define TELLSTICK_UP 128 +#define TELLSTICK_DOWN 256 +#define TELLSTICK_STOP 512 + +// Sensor value types +#define TELLSTICK_TEMPERATURE 1 +#define TELLSTICK_HUMIDITY 2 + +// Error codes +#define TELLSTICK_SUCCESS 0 +#define TELLSTICK_ERROR_NOT_FOUND -1 +#define TELLSTICK_ERROR_PERMISSION_DENIED -2 +#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 +#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 +#define TELLSTICK_ERROR_COMMUNICATION -5 +#define TELLSTICK_ERROR_CONNECTING_SERVICE -6 +#define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7 +#define TELLSTICK_ERROR_SYNTAX -8 +#define TELLSTICK_ERROR_BROKEN_PIPE -9 +#define TELLSTICK_ERROR_COMMUNICATING_SERVICE -10 +#define TELLSTICK_ERROR_CONFIG_SYNTAX -11 +#define TELLSTICK_ERROR_UNKNOWN -99 + +// Device typedef +#define TELLSTICK_TYPE_DEVICE 1 +#define TELLSTICK_TYPE_GROUP 2 +#define TELLSTICK_TYPE_SCENE 3 + +// Controller typedef +#define TELLSTICK_CONTROLLER_TELLSTICK 1 +#define TELLSTICK_CONTROLLER_TELLSTICK_DUO 2 +#define TELLSTICK_CONTROLLER_TELLSTICK_NET 3 + +// Device changes +#define TELLSTICK_DEVICE_ADDED 1 +#define TELLSTICK_DEVICE_CHANGED 2 +#define TELLSTICK_DEVICE_REMOVED 3 +#define TELLSTICK_DEVICE_STATE_CHANGED 4 + +// Change types +#define TELLSTICK_CHANGE_NAME 1 +#define TELLSTICK_CHANGE_PROTOCOL 2 +#define TELLSTICK_CHANGE_MODEL 3 +#define TELLSTICK_CHANGE_METHOD 4 +#define TELLSTICK_CHANGE_AVAILABLE 5 +#define TELLSTICK_CHANGE_FIRMWARE 6 + +#endif // TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ diff --git a/bindings/python/telldus.c b/bindings/python/telldus.c index 390f614a..c9ad7545 100644 --- a/bindings/python/telldus.c +++ b/bindings/python/telldus.c @@ -80,9 +80,9 @@ static PyObject * telldus_tdDim(PyObject *self, PyObject *args) { long id; - long level; + unsigned char level; - if (!PyArg_ParseTuple(args, "ll", &id, &level)) + if (!PyArg_ParseTuple(args, "lb", &id, &level)) return NULL; if (level < 0 || level > 255) @@ -369,80 +369,85 @@ static PyMethodDef telldus_methods[] = { void inittelldus(void) { - /* Create the module and add the functions */ - PyObject *module = Py_InitModule("telldus", telldus_methods); + PyObject *module; - PyObject *TELLSTICK_TURNON_GLUE = PyLong_FromLong((long) TELLSTICK_TURNON); + PyObject *TELLSTICK_TURNON_GLUE; + PyObject *TELLSTICK_TURNOFF_GLUE; + PyObject *TELLSTICK_BELL_GLUE; + PyObject *TELLSTICK_TOGGLE_GLUE; + PyObject *TELLSTICK_DIM_GLUE; + PyObject *TELLSTICK_LEARN_GLUE; + PyObject *TELLSTICK_SUCCESS_GLUE; + PyObject *TELLSTICK_ERROR_NOT_FOUND_GLUE; + PyObject *TELLSTICK_ERROR_PERMISSION_DENIED_GLUE; + PyObject *TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE; + PyObject *TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE; + PyObject *TELLSTICK_ERROR_COMMUNICATION_GLUE; + PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE; + PyObject *TELLSTICK_TYPE_DEVICE_GLUE; + PyObject *TELLSTICK_TYPE_GROUP_GLUE; + + /* Create the module and add the functions */ + + module = Py_InitModule("telldus", telldus_methods); + + TELLSTICK_TURNON_GLUE = PyLong_FromLong((long) TELLSTICK_TURNON); PyObject_SetAttrString(module, "TELLSTICK_TURNON", TELLSTICK_TURNON_GLUE); Py_DECREF(TELLSTICK_TURNON_GLUE); - - - PyObject *TELLSTICK_TURNOFF_GLUE = PyLong_FromLong((long) TELLSTICK_TURNOFF); + + TELLSTICK_TURNOFF_GLUE = PyLong_FromLong((long) TELLSTICK_TURNOFF); PyObject_SetAttrString(module, "TELLSTICK_TURNOFF", TELLSTICK_TURNOFF_GLUE); Py_DECREF(TELLSTICK_TURNOFF_GLUE); - - - PyObject *TELLSTICK_BELL_GLUE = PyLong_FromLong((long) TELLSTICK_BELL); + + TELLSTICK_BELL_GLUE = PyLong_FromLong((long) TELLSTICK_BELL); PyObject_SetAttrString(module, "TELLSTICK_BELL", TELLSTICK_BELL_GLUE); Py_DECREF(TELLSTICK_BELL_GLUE); - - - PyObject *TELLSTICK_TOGGLE_GLUE = PyLong_FromLong((long) TELLSTICK_TOGGLE); + + TELLSTICK_TOGGLE_GLUE = PyLong_FromLong((long) TELLSTICK_TOGGLE); PyObject_SetAttrString(module, "TELLSTICK_TOGGLE", TELLSTICK_TOGGLE_GLUE); Py_DECREF(TELLSTICK_TOGGLE_GLUE); - - - PyObject *TELLSTICK_DIM_GLUE = PyLong_FromLong((long) TELLSTICK_DIM); + + TELLSTICK_DIM_GLUE = PyLong_FromLong((long) TELLSTICK_DIM); PyObject_SetAttrString(module, "TELLSTICK_DIM", TELLSTICK_DIM_GLUE); Py_DECREF(TELLSTICK_DIM_GLUE); - - - PyObject *TELLSTICK_LEARN_GLUE = PyLong_FromLong((long) TELLSTICK_LEARN); + + TELLSTICK_LEARN_GLUE = PyLong_FromLong((long) TELLSTICK_LEARN); PyObject_SetAttrString(module, "TELLSTICK_LEARN", TELLSTICK_LEARN_GLUE); Py_DECREF(TELLSTICK_LEARN_GLUE); - - - PyObject *TELLSTICK_SUCCESS_GLUE = PyLong_FromLong((long) TELLSTICK_SUCCESS); + + TELLSTICK_SUCCESS_GLUE = PyLong_FromLong((long) TELLSTICK_SUCCESS); PyObject_SetAttrString(module, "TELLSTICK_SUCCESS", TELLSTICK_SUCCESS_GLUE); Py_DECREF(TELLSTICK_SUCCESS_GLUE); - - - PyObject *TELLSTICK_ERROR_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_NOT_FOUND); + + TELLSTICK_ERROR_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_NOT_FOUND); PyObject_SetAttrString(module, "TELLSTICK_ERROR_NOT_FOUND", TELLSTICK_ERROR_NOT_FOUND_GLUE); Py_DECREF(TELLSTICK_ERROR_NOT_FOUND_GLUE); - - - PyObject *TELLSTICK_ERROR_PERMISSION_DENIED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_PERMISSION_DENIED); + + TELLSTICK_ERROR_PERMISSION_DENIED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_PERMISSION_DENIED); PyObject_SetAttrString(module, "TELLSTICK_ERROR_PERMISSION_DENIED", TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); Py_DECREF(TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); - - PyObject *TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_DEVICE_NOT_FOUND); + TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_DEVICE_NOT_FOUND); PyObject_SetAttrString(module, "TELLSTICK_ERROR_DEVICE_NOT_FOUND", TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); Py_DECREF(TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); - - PyObject *TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_METHOD_NOT_SUPPORTED); + TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_METHOD_NOT_SUPPORTED); PyObject_SetAttrString(module, "TELLSTICK_ERROR_METHOD_NOT_SUPPORTED", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); - Py_DECREF(TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); + Py_DECREF(TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); - - PyObject *TELLSTICK_ERROR_COMMUNICATION_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_COMMUNICATION); + TELLSTICK_ERROR_COMMUNICATION_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_COMMUNICATION); PyObject_SetAttrString(module, "TELLSTICK_ERROR_COMMUNICATION", TELLSTICK_ERROR_COMMUNICATION_GLUE); - Py_DECREF(TELLSTICK_ERROR_COMMUNICATION_GLUE); + Py_DECREF(TELLSTICK_ERROR_COMMUNICATION_GLUE); - - PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_UNKNOWN); + TELLSTICK_ERROR_UNKNOWN_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_UNKNOWN); PyObject_SetAttrString(module, "TELLSTICK_ERROR_UNKNOWN", TELLSTICK_ERROR_UNKNOWN_GLUE); - Py_DECREF(TELLSTICK_ERROR_UNKNOWN_GLUE); - - - PyObject *TELLSTICK_TYPE_DEVICE_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_DEVICE); + Py_DECREF(TELLSTICK_ERROR_UNKNOWN_GLUE); + + TELLSTICK_TYPE_DEVICE_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_DEVICE); PyObject_SetAttrString(module, "TELLSTICK_TYPE_DEVICE", TELLSTICK_TYPE_DEVICE_GLUE); Py_DECREF(TELLSTICK_TYPE_DEVICE_GLUE); - - PyObject *TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); + TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); } \ No newline at end of file From cadcf0b48aecfc4b83bd6198df79fe0fe5a7ffdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 03:30:57 +0200 Subject: [PATCH 2059/2215] comment out code that might not be correct, add memoryerror --- bindings/python/setup.py | 12 +-- bindings/python/telldus.c | 176 +++++++++++++++++++++++++++++++++++++- 2 files changed, 181 insertions(+), 7 deletions(-) diff --git a/bindings/python/setup.py b/bindings/python/setup.py index ccf8d6da..f1a9f336 100644 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -31,13 +31,13 @@ if PLATFORM_IS_WINDOWS: http://www.microsoft.com/en-us/download/details.aspx?id=6506 http://jenshuebel.wordpress.com/2009/02/12/visual-c-2008-express-edition-and-64-bit-targets/ http://www.cppblog.com/Files/xcpp/VCE64BIT_WIN7SDK.zip - copy - + For 32bit build: - Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 - http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b - Run C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat - + Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 + http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b + Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat to + C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat + For 64bit build: Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO) GRMSDKX_EN_DVD.iso http://www.microsoft.com/en-us/download/details.aspx?id=18950 diff --git a/bindings/python/telldus.c b/bindings/python/telldus.c index c9ad7545..14934e04 100644 --- a/bindings/python/telldus.c +++ b/bindings/python/telldus.c @@ -21,7 +21,7 @@ estrdup(char *s) register char *t; if (NULL == (t = malloc(strlen(s)+1))) { - return NULL; + return PyErr_NoMemory(); } strcpy(t, s); return(t); @@ -30,6 +30,7 @@ estrdup(char *s) static PyObject * telldus_tdInit(PyObject *self) { + /* PyEval_InitThreads(); */ tdInit(); Py_INCREF(Py_None); return Py_None; @@ -333,6 +334,172 @@ telldus_tdSendRawCommand(PyObject *self, PyObject *args) return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); } +/* + Work in progress event callbacks +*/ + +/* +void +telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *pyfunc) +{ + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("llsl", deviceId, method, data, callbackId); + + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +void +telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, int callbackId, void *pyfunc) +{ + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("llll", deviceId, changeEvent, changeType, callbackId); + + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +void +telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackId, void *pyfunc) +{ + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("sll", data, controllerId, callbackId); + + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +void +telldus_sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *pyfunc) +{ + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); + + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +static PyObject * +telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) +{ + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterDeviceEvent((TDDeviceEvent) telldus_deviceEventCallback, &func)); +} + +static PyObject * +telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) +{ + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) telldus_deviceChangeEventCallback, &func)); +} + +static PyObject * +telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) +{ + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterRawDeviceEvent((TDRawDeviceEvent) telldus_rawDeviceEventCallback, &func)); +} + +static PyObject * +telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) +{ + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterSensorEvent((TDSensorEvent) telldus_sensorEventCallback, &func)); +} +*/ + static PyMethodDef telldus_methods[] = { /* The cast of the function is necessary since PyCFunction values * only take two PyObject* parameters, and keywdarg_parrot() takes @@ -363,6 +530,13 @@ static PyMethodDef telldus_methods[] = { {"tdAddDevice", (PyCFunction) telldus_tdAddDevice, METH_NOARGS, "AddDevice comment."}, {"tdRemoveDevice", (PyCFunction) telldus_tdRemoveDevice, METH_VARARGS, "RemoveDevice comment."}, {"tdSendRawCommand", (PyCFunction) telldus_tdSendRawCommand, METH_VARARGS, "SendRawCommand comment."}, +/* + {"tdRegisterDeviceEvent", (PyCFunction) telldus_tdRegisterDeviceEvent, METH_VARARGS, "RegisterDeviceEvent comment."}, + {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, + {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, + {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, + +*/ {NULL, NULL, 0, NULL} /* sentinel */ }; From 44869cbd4f243778feaaeb9169db630f955b04e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 13:22:20 +0200 Subject: [PATCH 2060/2215] tabs/ final newlines --- bindings/python/MANIFEST.in | 2 +- bindings/python/example/__init__.py | 58 +- bindings/python/setup.py | 648 +++++++++++------------ bindings/python/telldus.c | 789 ++++++++++++++-------------- 4 files changed, 749 insertions(+), 748 deletions(-) diff --git a/bindings/python/MANIFEST.in b/bindings/python/MANIFEST.in index f2039627..de92c867 100644 --- a/bindings/python/MANIFEST.in +++ b/bindings/python/MANIFEST.in @@ -1,3 +1,3 @@ include telldus.c include telldus-core.h -recursive-include example/* \ No newline at end of file +recursive-include example/* diff --git a/bindings/python/example/__init__.py b/bindings/python/example/__init__.py index 2f9c52f4..5e1f823c 100644 --- a/bindings/python/example/__init__.py +++ b/bindings/python/example/__init__.py @@ -9,34 +9,34 @@ print "Devices: %d\n" % devices allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM for i in xrange(devices): - deviceid = telldus.tdGetDeviceId(i) - name = telldus.tdGetName(deviceid) - - print "%s - %s\n" % (deviceid, name) - - methods = telldus.tdMethods(deviceid, allMethods) - - if methods & telldus.TELLDUS_TURNON: - print " * TurnOn\n" - telldus.tdTurnOn(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_TURNOFF: - print " * TurnOff\n" - telldus.tdTurnOff(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_BELL: - echo " * Bell\n" - telldus.tdBell(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_TOGGLE: - print " * Toggle\n" - - if methods & telldus.TELLDUS_DIM: - print " * Dim\n" - telldus.tdDim(deviceid, 128) - time.sleep(1) + deviceid = telldus.tdGetDeviceId(i) + name = telldus.tdGetName(deviceid) + + print "%s - %s\n" % (deviceid, name) + + methods = telldus.tdMethods(deviceid, allMethods) + + if methods & telldus.TELLDUS_TURNON: + print " * TurnOn\n" + telldus.tdTurnOn(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TURNOFF: + print " * TurnOff\n" + telldus.tdTurnOff(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_BELL: + echo " * Bell\n" + telldus.tdBell(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TOGGLE: + print " * Toggle\n" + + if methods & telldus.TELLDUS_DIM: + print " * Dim\n" + telldus.tdDim(deviceid, 128) + time.sleep(1) telldus.tdClose() \ No newline at end of file diff --git a/bindings/python/setup.py b/bindings/python/setup.py index f1a9f336..635121fa 100644 --- a/bindings/python/setup.py +++ b/bindings/python/setup.py @@ -7,337 +7,337 @@ PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win') if PLATFORM_IS_WINDOWS: - __doc__="""This is a distutils setup-script for the telldus extension - - To build the telldus extensions, simply execute: - python setup.py -q build - or - python setup.py -q install - to build and install into your current Python installation. - - These extensions require a number of libraries to build, some of which may - require you to install special SDKs or toolkits. This script will attempt - to build as many as it can, and at the end of the build will report any - extension modules that could not be built and why. - - This has got complicated due to the various different versions of - Visual Studio used - some VS versions are not compatible with some SDK - versions. Below are the Windows SDK versions required (and the URL - although - these are subject to being changed by MS at any time:) - - Python 2.6+: - - Build using Microsoft Visual Studio 2008 Express Edition: - http://www.microsoft.com/en-us/download/details.aspx?id=6506 - http://jenshuebel.wordpress.com/2009/02/12/visual-c-2008-express-edition-and-64-bit-targets/ - http://www.cppblog.com/Files/xcpp/VCE64BIT_WIN7SDK.zip + __doc__="""This is a distutils setup-script for the telldus extension + + To build the telldus extensions, simply execute: + python setup.py -q build + or + python setup.py -q install + to build and install into your current Python installation. + + These extensions require a number of libraries to build, some of which may + require you to install special SDKs or toolkits. This script will attempt + to build as many as it can, and at the end of the build will report any + extension modules that could not be built and why. + + This has got complicated due to the various different versions of + Visual Studio used - some VS versions are not compatible with some SDK + versions. Below are the Windows SDK versions required (and the URL - although + these are subject to being changed by MS at any time:) + + Python 2.6+: + + Build using Microsoft Visual Studio 2008 Express Edition: + http://www.microsoft.com/en-us/download/details.aspx?id=6506 + http://jenshuebel.wordpress.com/2009/02/12/visual-c-2008-express-edition-and-64-bit-targets/ + http://www.cppblog.com/Files/xcpp/VCE64BIT_WIN7SDK.zip - For 32bit build: - Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 - http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b - Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat to - C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat - - For 64bit build: - Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO) GRMSDKX_EN_DVD.iso - http://www.microsoft.com/en-us/download/details.aspx?id=18950 - Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars64.bat to - C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat - - Python 2.3->2.5: - - Microsoft Windows Software Development Kit Update for Windows Vista (version 6.0) - http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4377f86d-c913-4b5c-b87e-ef72e5b4e065 - ** If you want to build Python 2.3, be sure to install the SDK compilers - too - although we don't use them, this setup option installs some .lib - files we do need. - ** - - If you multiple SDK versions on a single machine, set the MSSDK environment - variable to point at the one you want to use. Note that using the SDK for - a particular platform (eg, Windows 7) doesn't force you to use that OS as your - build environment. If the links above don't work, use google to find them. - - Building: - --------- - - To install the telldus extension, execute: - python setup.py -q install - - This will install the built extensions into your site-packages directory, - create an appropriate .pth file, and should leave everything ready to use. - There is no need to modify the registry. - - To build or install debug (_d) versions of these extensions, ensure you have - built or installed a debug version of Python itself, then pass the "--debug" - flag to the build command - eg: - python setup.py -q build --debug - or to build and install a debug version: - python setup.py -q build --debug install - - To build 64bit versions of this: - - * py2.5 and earlier - sorry, I've given up in disgust. Using VS2003 with - the Vista SDK is just too painful to make work, and VS2005 is not used for - any released versions of Python. See revision 1.69 of this file for the - last version that attempted to support and document this process. - - * 2.6 and later: On a 64bit OS, just build as you would on a 32bit platform. - On a 32bit platform (ie, to cross-compile), you must use VS2008 to - cross-compile Python itself. Note that by default, the 64bit tools are not - installed with VS2008, so you may need to adjust your VS2008 setup (see "For 64bit build"). Then - use: - vcs - setup.py build --plat-name=win-amd64 - - see the distutils cross-compilation documentation for more details. - """ - # Originally by Thomas Heller, started in 2000 or so. - import os - import shutil - - is_py3k = sys.version_info > (3,) # get this out of the way early on... - # We have special handling for _winreg so our setup3.py script can avoid - # using the 'imports' fixer and therefore start much faster... - if is_py3k: - import winreg as _winreg - else: - import _winreg - - try: - from distutils import log - except ImportError: - class Log: - def debug(self, msg, *args): - print msg % args - def info(self, msg, *args): - print msg % args - log = Log() - - try: - this_file = __file__ - except NameError: - this_file = sys.argv[0] - - this_file = os.path.abspath(this_file) - # We get upset if the cwd is not our source dir, but it is a PITA to - # insist people manually CD there first! - if os.path.dirname(this_file): - os.chdir(os.path.dirname(this_file)) + For 32bit build: + Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 + http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b + Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat to + C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat + + For 64bit build: + Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO) GRMSDKX_EN_DVD.iso + http://www.microsoft.com/en-us/download/details.aspx?id=18950 + Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars64.bat to + C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat + + Python 2.3->2.5: + + Microsoft Windows Software Development Kit Update for Windows Vista (version 6.0) + http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4377f86d-c913-4b5c-b87e-ef72e5b4e065 + ** If you want to build Python 2.3, be sure to install the SDK compilers + too - although we don't use them, this setup option installs some .lib + files we do need. + ** + + If you multiple SDK versions on a single machine, set the MSSDK environment + variable to point at the one you want to use. Note that using the SDK for + a particular platform (eg, Windows 7) doesn't force you to use that OS as your + build environment. If the links above don't work, use google to find them. + + Building: + --------- + + To install the telldus extension, execute: + python setup.py -q install + + This will install the built extensions into your site-packages directory, + create an appropriate .pth file, and should leave everything ready to use. + There is no need to modify the registry. + + To build or install debug (_d) versions of these extensions, ensure you have + built or installed a debug version of Python itself, then pass the "--debug" + flag to the build command - eg: + python setup.py -q build --debug + or to build and install a debug version: + python setup.py -q build --debug install + + To build 64bit versions of this: + + * py2.5 and earlier - sorry, I've given up in disgust. Using VS2003 with + the Vista SDK is just too painful to make work, and VS2005 is not used for + any released versions of Python. See revision 1.69 of this file for the + last version that attempted to support and document this process. + + * 2.6 and later: On a 64bit OS, just build as you would on a 32bit platform. + On a 32bit platform (ie, to cross-compile), you must use VS2008 to + cross-compile Python itself. Note that by default, the 64bit tools are not + installed with VS2008, so you may need to adjust your VS2008 setup (see "For 64bit build"). Then + use: + vcs + setup.py build --plat-name=win-amd64 + + see the distutils cross-compilation documentation for more details. + """ + # Originally by Thomas Heller, started in 2000 or so. + import os + import shutil + + is_py3k = sys.version_info > (3,) # get this out of the way early on... + # We have special handling for _winreg so our setup3.py script can avoid + # using the 'imports' fixer and therefore start much faster... + if is_py3k: + import winreg as _winreg + else: + import _winreg + + try: + from distutils import log + except ImportError: + class Log: + def debug(self, msg, *args): + print msg % args + def info(self, msg, *args): + print msg % args + log = Log() + + try: + this_file = __file__ + except NameError: + this_file = sys.argv[0] + + this_file = os.path.abspath(this_file) + # We get upset if the cwd is not our source dir, but it is a PITA to + # insist people manually CD there first! + if os.path.dirname(this_file): + os.chdir(os.path.dirname(this_file)) - - # We need to know the platform SDK dir before we can list the extensions. - def find_platform_sdk_dir(): - # Finding the Platform SDK install dir is a treat. There can be some - # dead ends so we only consider the job done if we find the "windows.h" - # landmark. - landmark = "include\\windows.h" - # 1. The use might have their current environment setup for the - # SDK, in which case the "MSSdk" env var is set. - sdkdir = os.environ.get("MSSdk") - if sdkdir: - if DEBUG: - print "PSDK: try %%MSSdk%%: '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - # 2. The "Install Dir" value in the - # HKLM\Software\Microsoft\MicrosoftSDK\Directories registry key - # sometimes points to the right thing. However, after upgrading to - # the "Platform SDK for Windows Server 2003 SP1" this is dead end. - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\MicrosoftSDK\Directories") - sdkdir, ignore = _winreg.QueryValueEx(key, "Install Dir") - except EnvironmentError: - pass - else: - if DEBUG: - print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ - "\Directories\Install Dir': '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - # 3. Each installed SDK (not just the platform SDK) seems to have GUID - # subkey of HKLM\Software\Microsoft\MicrosoftSDK\InstalledSDKs and - # it *looks* like the latest installed Platform SDK will be the - # only one with an "Install Dir" sub-value. - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\MicrosoftSDK\InstalledSDKs") - i = 0 - while True: - guid = _winreg.EnumKey(key, i) - guidkey = _winreg.OpenKey(key, guid) - try: - sdkdir, ignore = _winreg.QueryValueEx(guidkey, "Install Dir") - except EnvironmentError: - pass - else: - if DEBUG: - print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ - "\InstallSDKs\%s\Install Dir': '%s'"\ - % (guid, sdkdir) - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - i += 1 - except EnvironmentError: - pass - # 4. Vista's SDK - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\Microsoft SDKs\Windows") - sdkdir, ignore = _winreg.QueryValueEx(key, "CurrentInstallFolder") - except EnvironmentError: - pass - else: - if DEBUG: - print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDKs"\ - "\Windows\CurrentInstallFolder': '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - - # 5. Failing this just try a few well-known default install locations. - progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") - defaultlocs = [ - os.path.join(progfiles, "Microsoft Platform SDK"), - os.path.join(progfiles, "Microsoft SDK"), - ] - for sdkdir in defaultlocs: - if DEBUG: - print "PSDK: try default location: '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - - - # Some nasty hacks to prevent most of our extensions using a manifest, as - # the manifest - even without a reference to the CRT assembly - is enough - # to prevent the extension from loading. For more details, see - # http://bugs.python.org/issue7833 - that issue has a patch, but it is - # languishing and will probably never be fixed for Python 2.6... - if sys.version_info > (2,6): - from distutils.spawn import spawn - from distutils.msvc9compiler import MSVCCompiler - MSVCCompiler._orig_spawn = MSVCCompiler.spawn - MSVCCompiler._orig_link = MSVCCompiler.link - - # We need to override this method for versions where issue7833 *has* landed - # (ie, 2.7 and 3.2+) - def manifest_get_embed_info(self, target_desc, ld_args): - _want_assembly_kept = getattr(self, '_want_assembly_kept', False) - if not _want_assembly_kept: - return None - for arg in ld_args: - if arg.startswith("/MANIFESTFILE:"): - orig_manifest = arg.split(":", 1)[1] - if target_desc==self.EXECUTABLE: - rid = 1 - else: - rid = 2 - return orig_manifest, rid - return None - # always monkeypatch it in even though it will only be called in 2.7 - # and 3.2+. - MSVCCompiler.manifest_get_embed_info = manifest_get_embed_info - - def monkeypatched_spawn(self, cmd): - is_link = cmd[0].endswith("link.exe") or cmd[0].endswith('"link.exe"') - is_mt = cmd[0].endswith("mt.exe") or cmd[0].endswith('"mt.exe"') - _want_assembly_kept = getattr(self, '_want_assembly_kept', False) - if not _want_assembly_kept and is_mt: - # We don't want mt.exe run... - return - if not _want_assembly_kept and is_link: - # remove /MANIFESTFILE:... and add MANIFEST:NO - # (but note that for winxpgui, which specifies a manifest via a - # .rc file, this is ignored by the linker - the manifest specified - # in the .rc file is still added) - for i in range(len(cmd)): - if cmd[i].startswith("/MANIFESTFILE:"): - cmd[i] = "/MANIFEST:NO" - break - if _want_assembly_kept and is_mt: - # We want mt.exe run with the original manifest - for i in range(len(cmd)): - if cmd[i] == "-manifest": - cmd[i+1] = cmd[i+1] + ".orig" - break - self._orig_spawn(cmd) - if _want_assembly_kept and is_link: - # We want a copy of the original manifest so we can use it later. - for i in range(len(cmd)): - if cmd[i].startswith("/MANIFESTFILE:"): - mfname = cmd[i][14:] - shutil.copyfile(mfname, mfname + ".orig") - break - - def monkeypatched_link(self, target_desc, objects, output_filename, *args, **kw): - # no manifests for 3.3+ - self._want_assembly_kept = sys.version_info < (3,3) and \ - (os.path.basename(output_filename).startswith("PyISAPI_loader.dll") or \ - os.path.basename(output_filename).startswith("perfmondata.dll") or \ - os.path.basename(output_filename).startswith("win32ui.pyd") or \ - target_desc==self.EXECUTABLE) - try: - return self._orig_link(target_desc, objects, output_filename, *args, **kw) - finally: - delattr(self, '_want_assembly_kept') - MSVCCompiler.spawn = monkeypatched_spawn - MSVCCompiler.link = monkeypatched_link - - def find_telldus_dev_dir(): - landmark = "telldus-core.h" - dev_dir = os.environ.get("TELLDUS_DEVDIR") - if dev_dir: - if DEBUG: - print "Telldus dev dir:" % dev_dir - if os.path.isfile(os.path.join(dev_dir, landmark)): - return dev_dir + + # We need to know the platform SDK dir before we can list the extensions. + def find_platform_sdk_dir(): + # Finding the Platform SDK install dir is a treat. There can be some + # dead ends so we only consider the job done if we find the "windows.h" + # landmark. + landmark = "include\\windows.h" + # 1. The use might have their current environment setup for the + # SDK, in which case the "MSSdk" env var is set. + sdkdir = os.environ.get("MSSdk") + if sdkdir: + if DEBUG: + print "PSDK: try %%MSSdk%%: '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + # 2. The "Install Dir" value in the + # HKLM\Software\Microsoft\MicrosoftSDK\Directories registry key + # sometimes points to the right thing. However, after upgrading to + # the "Platform SDK for Windows Server 2003 SP1" this is dead end. + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\MicrosoftSDK\Directories") + sdkdir, ignore = _winreg.QueryValueEx(key, "Install Dir") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ + "\Directories\Install Dir': '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + # 3. Each installed SDK (not just the platform SDK) seems to have GUID + # subkey of HKLM\Software\Microsoft\MicrosoftSDK\InstalledSDKs and + # it *looks* like the latest installed Platform SDK will be the + # only one with an "Install Dir" sub-value. + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\MicrosoftSDK\InstalledSDKs") + i = 0 + while True: + guid = _winreg.EnumKey(key, i) + guidkey = _winreg.OpenKey(key, guid) + try: + sdkdir, ignore = _winreg.QueryValueEx(guidkey, "Install Dir") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ + "\InstallSDKs\%s\Install Dir': '%s'"\ + % (guid, sdkdir) + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + i += 1 + except EnvironmentError: + pass + # 4. Vista's SDK + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\Microsoft SDKs\Windows") + sdkdir, ignore = _winreg.QueryValueEx(key, "CurrentInstallFolder") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDKs"\ + "\Windows\CurrentInstallFolder': '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + + # 5. Failing this just try a few well-known default install locations. + progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") + defaultlocs = [ + os.path.join(progfiles, "Microsoft Platform SDK"), + os.path.join(progfiles, "Microsoft SDK"), + ] + for sdkdir in defaultlocs: + if DEBUG: + print "PSDK: try default location: '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + + + # Some nasty hacks to prevent most of our extensions using a manifest, as + # the manifest - even without a reference to the CRT assembly - is enough + # to prevent the extension from loading. For more details, see + # http://bugs.python.org/issue7833 - that issue has a patch, but it is + # languishing and will probably never be fixed for Python 2.6... + if sys.version_info > (2,6): + from distutils.spawn import spawn + from distutils.msvc9compiler import MSVCCompiler + MSVCCompiler._orig_spawn = MSVCCompiler.spawn + MSVCCompiler._orig_link = MSVCCompiler.link + + # We need to override this method for versions where issue7833 *has* landed + # (ie, 2.7 and 3.2+) + def manifest_get_embed_info(self, target_desc, ld_args): + _want_assembly_kept = getattr(self, '_want_assembly_kept', False) + if not _want_assembly_kept: + return None + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + orig_manifest = arg.split(":", 1)[1] + if target_desc==self.EXECUTABLE: + rid = 1 + else: + rid = 2 + return orig_manifest, rid + return None + # always monkeypatch it in even though it will only be called in 2.7 + # and 3.2+. + MSVCCompiler.manifest_get_embed_info = manifest_get_embed_info + + def monkeypatched_spawn(self, cmd): + is_link = cmd[0].endswith("link.exe") or cmd[0].endswith('"link.exe"') + is_mt = cmd[0].endswith("mt.exe") or cmd[0].endswith('"mt.exe"') + _want_assembly_kept = getattr(self, '_want_assembly_kept', False) + if not _want_assembly_kept and is_mt: + # We don't want mt.exe run... + return + if not _want_assembly_kept and is_link: + # remove /MANIFESTFILE:... and add MANIFEST:NO + # (but note that for winxpgui, which specifies a manifest via a + # .rc file, this is ignored by the linker - the manifest specified + # in the .rc file is still added) + for i in range(len(cmd)): + if cmd[i].startswith("/MANIFESTFILE:"): + cmd[i] = "/MANIFEST:NO" + break + if _want_assembly_kept and is_mt: + # We want mt.exe run with the original manifest + for i in range(len(cmd)): + if cmd[i] == "-manifest": + cmd[i+1] = cmd[i+1] + ".orig" + break + self._orig_spawn(cmd) + if _want_assembly_kept and is_link: + # We want a copy of the original manifest so we can use it later. + for i in range(len(cmd)): + if cmd[i].startswith("/MANIFESTFILE:"): + mfname = cmd[i][14:] + shutil.copyfile(mfname, mfname + ".orig") + break + + def monkeypatched_link(self, target_desc, objects, output_filename, *args, **kw): + # no manifests for 3.3+ + self._want_assembly_kept = sys.version_info < (3,3) and \ + (os.path.basename(output_filename).startswith("PyISAPI_loader.dll") or \ + os.path.basename(output_filename).startswith("perfmondata.dll") or \ + os.path.basename(output_filename).startswith("win32ui.pyd") or \ + target_desc==self.EXECUTABLE) + try: + return self._orig_link(target_desc, objects, output_filename, *args, **kw) + finally: + delattr(self, '_want_assembly_kept') + MSVCCompiler.spawn = monkeypatched_spawn + MSVCCompiler.link = monkeypatched_link + + def find_telldus_dev_dir(): + landmark = "telldus-core.h" + dev_dir = os.environ.get("TELLDUS_DEVDIR") + if dev_dir: + if DEBUG: + print "Telldus dev dir:" % dev_dir + if os.path.isfile(os.path.join(dev_dir, landmark)): + return dev_dir - progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") - defaultlocs = [ - os.path.join(progfiles + ' (x86)', "Telldus", "Development"), - os.path.join(progfiles, "Telldus", "Development"), - ] - for dev_dir in defaultlocs: - if DEBUG: - print "Telldus dev dir: '%s'" % dev_dir - if os.path.isfile(os.path.join(dev_dir, landmark)): - return dev_dir - if DEBUG: - print "Telldus dev dir not found, make sure dev code is installed. Or set TELLDUS_DEVDIR." + progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") + defaultlocs = [ + os.path.join(progfiles + ' (x86)', "Telldus", "Development"), + os.path.join(progfiles, "Telldus", "Development"), + ] + for dev_dir in defaultlocs: + if DEBUG: + print "Telldus dev dir: '%s'" % dev_dir + if os.path.isfile(os.path.join(dev_dir, landmark)): + return dev_dir + if DEBUG: + print "Telldus dev dir not found, make sure dev code is installed. Or set TELLDUS_DEVDIR." - sdk_dir = find_platform_sdk_dir() - sdk_include_dir = os.path.join(sdk_dir, 'Include') + sdk_dir = find_platform_sdk_dir() + sdk_include_dir = os.path.join(sdk_dir, 'Include') - telldus_dev_dir = find_telldus_dev_dir() - telldus_platform = os.environ.get("TELLDUS_PLATFORM", 'x86_64') - telldus_library_dir = os.path.join(telldus_dev_dir, telldus_platform) - - include_dirs = [sdk_include_dir, os.path.dirname(this_file)] - library_dirs = [telldus_library_dir] - libraries = ['python%i%i' % (sys.version_info[0], sys.version_info[1]) , 'TelldusCore'] - define_macros = [('_WINDOWS', 1)] - + telldus_dev_dir = find_telldus_dev_dir() + telldus_platform = os.environ.get("TELLDUS_PLATFORM", 'x86_64') + telldus_library_dir = os.path.join(telldus_dev_dir, telldus_platform) + + include_dirs = [sdk_include_dir, os.path.dirname(this_file)] + library_dirs = [telldus_library_dir] + libraries = ['python%i%i' % (sys.version_info[0], sys.version_info[1]) , 'TelldusCore'] + define_macros = [('_WINDOWS', 1)] + else: - include_dirs = ['/usr/include', '/usr/local/include'] - library_dirs = ['/usr/lib', '/usr/local/lib'] - libraries = ['telldus-core'] - define_macros = [] - + include_dirs = ['/usr/include', '/usr/local/include'] + library_dirs = ['/usr/lib', '/usr/local/lib'] + libraries = ['telldus-core'] + define_macros = [] + telldus = Extension( - 'telldus', - include_dirs = include_dirs, - libraries = libraries, - library_dirs = library_dirs, - define_macros = define_macros, - sources = ['telldus.c'] + 'telldus', + include_dirs = include_dirs, + libraries = libraries, + library_dirs = library_dirs, + define_macros = define_macros, + sources = ['telldus.c'] ) setup( - name = 'telldus', - version = '1.0', - description = 'Python bindings for telldus', - author='Oyvind Saltvik', - author_email='oyvind.saltvik@gmail.com', - url='http://github.com/fivethreeo/telldus/', - ext_modules = [telldus] -) \ No newline at end of file + name = 'telldus', + version = '1.0', + description = 'Python bindings for telldus', + author='Oyvind Saltvik', + author_email='oyvind.saltvik@gmail.com', + url='http://github.com/fivethreeo/telldus/', + ext_modules = [telldus] +) diff --git a/bindings/python/telldus.c b/bindings/python/telldus.c index 14934e04..1b1673d2 100644 --- a/bindings/python/telldus.c +++ b/bindings/python/telldus.c @@ -10,7 +10,7 @@ * * estrdup returns a copy of its argument, located in memory * allocated from the heap. If it is unable to allocate the - * necessary memory, estrdup executes error("no memory"). + * necessary memory, estrdup executes PyErr_NoMemory(); * (Generally, the routine error is not expected to return, * but if it does, estrdup will return NULL.) */ @@ -18,610 +18,611 @@ char * estrdup(char *s) { - register char *t; + register char *t; - if (NULL == (t = malloc(strlen(s)+1))) { - return PyErr_NoMemory(); - } - strcpy(t, s); - return(t); + if (NULL == (t = malloc(strlen(s)+1))) { + return PyErr_NoMemory(); + } + strcpy(t, s); + return(t); } static PyObject * telldus_tdInit(PyObject *self) { - /* PyEval_InitThreads(); */ - tdInit(); - Py_INCREF(Py_None); - return Py_None; + tdInit(); + Py_INCREF(Py_None); + return Py_None; } static PyObject * telldus_tdClose(PyObject *self) { - tdClose(); - Py_INCREF(Py_None); - return Py_None; + tdClose(); + Py_INCREF(Py_None); + return Py_None; } static PyObject * telldus_tdTurnOn(PyObject *self, PyObject *args) { - long id; + long id; - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyBool_FromLong((long) tdTurnOn(id)); + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdTurnOn(id)); } static PyObject * telldus_tdTurnOff(PyObject *self, PyObject *args) { - long id; + long id; - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyBool_FromLong((long) tdTurnOff(id)); + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdTurnOff(id)); } static PyObject * telldus_tdBell(PyObject *self, PyObject *args) { - long id; + long id; - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyBool_FromLong((long) tdBell(id)); + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdBell(id)); } static PyObject * telldus_tdDim(PyObject *self, PyObject *args) { - long id; - unsigned char level; + long id; + unsigned char level; - if (!PyArg_ParseTuple(args, "lb", &id, &level)) - return NULL; - - if (level < 0 || level > 255) - return NULL; + if (!PyArg_ParseTuple(args, "lb", &id, &level)) + return NULL; + + if (level < 0 || level > 255) + return NULL; - return PyBool_FromLong((long) tdDim(id, level)); + return PyBool_FromLong((long) tdDim(id, level)); } static PyObject * telldus_tdLearn(PyObject *self, PyObject *args) { - long id; + long id; - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyBool_FromLong((long) tdLearn(id)); + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdLearn(id)); } static PyObject * telldus_tdMethods(PyObject *self, PyObject *args) { - long id; - long supportedmethods; + long id; + long supportedmethods; - if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) - return NULL; + if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) + return NULL; - return PyLong_FromLong((long) tdMethods(id, supportedmethods)); + return PyLong_FromLong((long) tdMethods(id, supportedmethods)); } - + static PyObject * telldus_tdLastSentCommand(PyObject *self, PyObject *args) { - long id; - long supportedmethods; + long id; + long supportedmethods; - if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) - return NULL; + if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) + return NULL; - return PyLong_FromLong((long) tdLastSentCommand(id, supportedmethods)); + return PyLong_FromLong((long) tdLastSentCommand(id, supportedmethods)); } static PyObject * telldus_tdLastSentValue(PyObject *self, PyObject *args) { - long id; - char* value; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - value = tdLastSentValue(id); - retval = estrdup(value); - tdReleaseString(value); - return PyString_FromString(retval); + long id; + char* value; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + value = tdLastSentValue(id); + retval = estrdup(value); + tdReleaseString(value); + return PyString_FromString(retval); } static PyObject * telldus_tdGetNumberOfDevices(PyObject *self) { - return PyLong_FromLong((long) tdGetNumberOfDevices()); + return PyLong_FromLong((long) tdGetNumberOfDevices()); } static PyObject * telldus_tdGetDeviceId(PyObject *self, PyObject *args) { - long index; + long index; - if (!PyArg_ParseTuple(args, "l", &index)) - return NULL; - - return PyLong_FromLong((long) tdGetDeviceId(index)); + if (!PyArg_ParseTuple(args, "l", &index)) + return NULL; + + return PyLong_FromLong((long) tdGetDeviceId(index)); } static PyObject * telldus_tdGetDeviceType(PyObject *self, PyObject *args) { - long id; + long id; - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyLong_FromLong((long) tdGetDeviceType(id)); + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdGetDeviceType(id)); } static PyObject * telldus_tdGetErrorString(PyObject *self, PyObject *args) { - long errorno; - char* errorString; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &errorno)) - return NULL; - - errorString = tdGetErrorString(errorno); - retval = estrdup(errorString); - tdReleaseString(errorString); - return PyString_FromString(retval); + long errorno; + char* errorString; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &errorno)) + return NULL; + + errorString = tdGetErrorString(errorno); + retval = estrdup(errorString); + tdReleaseString(errorString); + return PyString_FromString(retval); } static PyObject * telldus_tdGetName(PyObject *self, PyObject *args) { - long id; - char* name; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - name = tdGetName(id); - retval = estrdup(name); - tdReleaseString(name); - return PyString_FromString(retval); + long id; + char* name; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + name = tdGetName(id); + retval = estrdup(name); + tdReleaseString(name); + return PyString_FromString(retval); } static PyObject * telldus_tdSetName(PyObject *self, PyObject *args) { - long id; - char* name; - - if (!PyArg_ParseTuple(args, "ls", &id, &name)) - return NULL; - - return PyBool_FromLong((long) tdSetName(id, name)); + long id; + char* name; + + if (!PyArg_ParseTuple(args, "ls", &id, &name)) + return NULL; + + return PyBool_FromLong((long) tdSetName(id, name)); } static PyObject * telldus_tdGetProtocol(PyObject *self, PyObject *args) { - long id; - char* protocol; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - protocol = tdGetProtocol(id); - retval = estrdup(protocol); - tdReleaseString(protocol); - return PyString_FromString(retval); + long id; + char* protocol; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + protocol = tdGetProtocol(id); + retval = estrdup(protocol); + tdReleaseString(protocol); + return PyString_FromString(retval); } static PyObject * telldus_tdSetProtocol(PyObject *self, PyObject *args) { - long id; - char* protocol; - - if (!PyArg_ParseTuple(args, "ls", &id, &protocol)) - return NULL; - - return PyBool_FromLong((long) tdSetProtocol(id, protocol)); + long id; + char* protocol; + + if (!PyArg_ParseTuple(args, "ls", &id, &protocol)) + return NULL; + + return PyBool_FromLong((long) tdSetProtocol(id, protocol)); } static PyObject * telldus_tdGetModel(PyObject *self, PyObject *args) { - long id; - char* model; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - model = tdGetModel(id); - retval = estrdup(model); - tdReleaseString(model); - return PyString_FromString(retval); + long id; + char* model; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + model = tdGetModel(id); + retval = estrdup(model); + tdReleaseString(model); + return PyString_FromString(retval); } static PyObject * telldus_tdSetModel(PyObject *self, PyObject *args) { - long id; - char* model; - - if (!PyArg_ParseTuple(args, "ls", &id, &model)) - return NULL; - - return PyBool_FromLong((long) tdSetProtocol(id, model)); + long id; + char* model; + + if (!PyArg_ParseTuple(args, "ls", &id, &model)) + return NULL; + + return PyBool_FromLong((long) tdSetProtocol(id, model)); } static PyObject * telldus_tdGetDeviceParameter(PyObject *self, PyObject *args) { - long id; - char* name; - char* defaultValue; - char* param; - char* retval; - - if (!PyArg_ParseTuple(args, "lss", &id, &name, &defaultValue)) - return NULL; - - param = tdGetDeviceParameter(id, name, defaultValue); - retval = estrdup(param); - tdReleaseString(param); - return PyString_FromString(retval); + long id; + char* name; + char* defaultValue; + char* param; + char* retval; + + if (!PyArg_ParseTuple(args, "lss", &id, &name, &defaultValue)) + return NULL; + + param = tdGetDeviceParameter(id, name, defaultValue); + retval = estrdup(param); + tdReleaseString(param); + return PyString_FromString(retval); } static PyObject * telldus_tdSetDeviceParameter(PyObject *self, PyObject *args) { - long id; - char* name; - char* value; - - if (!PyArg_ParseTuple(args, "lss", &id, &name, &value)) - return NULL; - - return PyBool_FromLong((long) tdSetDeviceParameter(id, name, value)); + long id; + char* name; + char* value; + + if (!PyArg_ParseTuple(args, "lss", &id, &name, &value)) + return NULL; + + return PyBool_FromLong((long) tdSetDeviceParameter(id, name, value)); } static PyObject * telldus_tdAddDevice(PyObject *self) { - return PyLong_FromLong((long) tdAddDevice()); + return PyLong_FromLong((long) tdAddDevice()); } static PyObject * telldus_tdRemoveDevice(PyObject *self, PyObject *args) { - long id; + long id; - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyBool_FromLong((long) tdRemoveDevice(id)); + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyBool_FromLong((long) tdRemoveDevice(id)); } static PyObject * telldus_tdSendRawCommand(PyObject *self, PyObject *args) { - char *command; - long reserved = 0; + char *command; + long reserved = 0; - if (!PyArg_ParseTuple(args, "s|l", &command, &reserved)); - return NULL; + if (!PyArg_ParseTuple(args, "s|l", &command, &reserved)); + return NULL; - return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); + return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); } /* - Work in progress event callbacks + Work in progress event callbacks */ /* void telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("llsl", deviceId, method, data, callbackId); + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("llsl", deviceId, method, data, callbackId); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } - + void telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("llll", deviceId, changeEvent, changeType, callbackId); + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("llll", deviceId, changeEvent, changeType, callbackId); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } - + void telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("sll", data, controllerId, callbackId); + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("sll", data, controllerId, callbackId); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } void telldus_sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + + // prepare the arg list to pass into the Python callback function + arglist = Py_BuildValue("ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyEval_CallObject(pyfunc, arglist); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_DECREF(arglist); + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } static PyObject * telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) { - PyObject *func; + PyObject *func; - if (!PyArg_ParseTuple(args, "O", &func)); - return NULL; - - return PyLong_FromLong((long) tdRegisterDeviceEvent((TDDeviceEvent) telldus_deviceEventCallback, &func)); + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterDeviceEvent((TDDeviceEvent) telldus_deviceEventCallback, &func)); } static PyObject * telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) { - PyObject *func; + PyObject *func; - if (!PyArg_ParseTuple(args, "O", &func)); - return NULL; - - return PyLong_FromLong((long) tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) telldus_deviceChangeEventCallback, &func)); + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) telldus_deviceChangeEventCallback, &func)); } static PyObject * telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) { - PyObject *func; + PyObject *func; - if (!PyArg_ParseTuple(args, "O", &func)); - return NULL; - - return PyLong_FromLong((long) tdRegisterRawDeviceEvent((TDRawDeviceEvent) telldus_rawDeviceEventCallback, &func)); + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterRawDeviceEvent((TDRawDeviceEvent) telldus_rawDeviceEventCallback, &func)); } static PyObject * telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) { - PyObject *func; + PyObject *func; - if (!PyArg_ParseTuple(args, "O", &func)); - return NULL; - - return PyLong_FromLong((long) tdRegisterSensorEvent((TDSensorEvent) telldus_sensorEventCallback, &func)); + if (!PyArg_ParseTuple(args, "O", &func)); + return NULL; + + return PyLong_FromLong((long) tdRegisterSensorEvent((TDSensorEvent) telldus_sensorEventCallback, &func)); } */ static PyMethodDef telldus_methods[] = { - /* The cast of the function is necessary since PyCFunction values - * only take two PyObject* parameters, and keywdarg_parrot() takes - * three. - */ - {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, - {"tdClose", (PyCFunction) telldus_tdClose, METH_NOARGS, "Close telldus."}, - {"tdTurnOn", (PyCFunction) telldus_tdTurnOn, METH_VARARGS, "Turn on device."}, - {"tdTurnOff", (PyCFunction) telldus_tdTurnOff, METH_VARARGS, "Turn off device."}, - {"tdBell", (PyCFunction) telldus_tdBell, METH_VARARGS, "Bell device."}, - {"tdDim", (PyCFunction) telldus_tdDim, METH_VARARGS, "Dim device."}, - {"tdLearn", (PyCFunction) telldus_tdLearn, METH_VARARGS, "Learn device."}, - {"tdMethods", (PyCFunction) telldus_tdMethods, METH_VARARGS, "Methods comment."}, - {"tdLastSentCommand", (PyCFunction) telldus_tdLastSentCommand, METH_VARARGS, "LastSentCommand comment."}, - {"tdLastSentValue", (PyCFunction) telldus_tdLastSentValue, METH_VARARGS, "LastSentValue comment."}, - {"tdGetNumberOfDevices", (PyCFunction) telldus_tdGetNumberOfDevices, METH_VARARGS, "GetNumberOfDevices comment."}, - {"tdGetDeviceId", (PyCFunction) telldus_tdGetDeviceId, METH_VARARGS, "GetDeviceId comment."}, - {"tdGetDeviceType", (PyCFunction) telldus_tdGetDeviceType, METH_VARARGS, "GetDeviceType comment."}, - {"tdGetErrorString", (PyCFunction) telldus_tdGetErrorString, METH_VARARGS, "GetErrorString comment."}, - {"tdGetName", (PyCFunction) telldus_tdGetName, METH_VARARGS, "GetName comment."}, - {"tdSetName", (PyCFunction) telldus_tdSetName, METH_VARARGS, "SetName comment."}, - {"tdGetProtocol", (PyCFunction) telldus_tdGetProtocol, METH_VARARGS, "GetProtocol comment."}, - {"tdSetProtocol", (PyCFunction) telldus_tdSetProtocol, METH_VARARGS, "SetProtocol comment."}, - {"tdGetModel", (PyCFunction) telldus_tdGetModel, METH_VARARGS, "GetModel comment."}, - {"tdSetModel", (PyCFunction) telldus_tdSetModel, METH_VARARGS, "SetModel comment."}, - {"tdGetDeviceParameter", (PyCFunction) telldus_tdGetDeviceParameter, METH_VARARGS, "GetDeviceParameter comment."}, - {"tdSetDeviceParameter", (PyCFunction) telldus_tdSetDeviceParameter, METH_VARARGS, "SetDeviceParameter comment."}, - {"tdAddDevice", (PyCFunction) telldus_tdAddDevice, METH_NOARGS, "AddDevice comment."}, - {"tdRemoveDevice", (PyCFunction) telldus_tdRemoveDevice, METH_VARARGS, "RemoveDevice comment."}, - {"tdSendRawCommand", (PyCFunction) telldus_tdSendRawCommand, METH_VARARGS, "SendRawCommand comment."}, + /* The cast of the function is necessary since PyCFunction values + * only take two PyObject* parameters, and keywdarg_parrot() takes + * three. + */ + {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, + {"tdClose", (PyCFunction) telldus_tdClose, METH_NOARGS, "Close telldus."}, + {"tdTurnOn", (PyCFunction) telldus_tdTurnOn, METH_VARARGS, "Turn on device."}, + {"tdTurnOff", (PyCFunction) telldus_tdTurnOff, METH_VARARGS, "Turn off device."}, + {"tdBell", (PyCFunction) telldus_tdBell, METH_VARARGS, "Bell device."}, + {"tdDim", (PyCFunction) telldus_tdDim, METH_VARARGS, "Dim device."}, + {"tdLearn", (PyCFunction) telldus_tdLearn, METH_VARARGS, "Learn device."}, + {"tdMethods", (PyCFunction) telldus_tdMethods, METH_VARARGS, "Methods comment."}, + {"tdLastSentCommand", (PyCFunction) telldus_tdLastSentCommand, METH_VARARGS, "LastSentCommand comment."}, + {"tdLastSentValue", (PyCFunction) telldus_tdLastSentValue, METH_VARARGS, "LastSentValue comment."}, + {"tdGetNumberOfDevices", (PyCFunction) telldus_tdGetNumberOfDevices, METH_VARARGS, "GetNumberOfDevices comment."}, + {"tdGetDeviceId", (PyCFunction) telldus_tdGetDeviceId, METH_VARARGS, "GetDeviceId comment."}, + {"tdGetDeviceType", (PyCFunction) telldus_tdGetDeviceType, METH_VARARGS, "GetDeviceType comment."}, + {"tdGetErrorString", (PyCFunction) telldus_tdGetErrorString, METH_VARARGS, "GetErrorString comment."}, + {"tdGetName", (PyCFunction) telldus_tdGetName, METH_VARARGS, "GetName comment."}, + {"tdSetName", (PyCFunction) telldus_tdSetName, METH_VARARGS, "SetName comment."}, + {"tdGetProtocol", (PyCFunction) telldus_tdGetProtocol, METH_VARARGS, "GetProtocol comment."}, + {"tdSetProtocol", (PyCFunction) telldus_tdSetProtocol, METH_VARARGS, "SetProtocol comment."}, + {"tdGetModel", (PyCFunction) telldus_tdGetModel, METH_VARARGS, "GetModel comment."}, + {"tdSetModel", (PyCFunction) telldus_tdSetModel, METH_VARARGS, "SetModel comment."}, + {"tdGetDeviceParameter", (PyCFunction) telldus_tdGetDeviceParameter, METH_VARARGS, "GetDeviceParameter comment."}, + {"tdSetDeviceParameter", (PyCFunction) telldus_tdSetDeviceParameter, METH_VARARGS, "SetDeviceParameter comment."}, + {"tdAddDevice", (PyCFunction) telldus_tdAddDevice, METH_NOARGS, "AddDevice comment."}, + {"tdRemoveDevice", (PyCFunction) telldus_tdRemoveDevice, METH_VARARGS, "RemoveDevice comment."}, + {"tdSendRawCommand", (PyCFunction) telldus_tdSendRawCommand, METH_VARARGS, "SendRawCommand comment."}, /* - {"tdRegisterDeviceEvent", (PyCFunction) telldus_tdRegisterDeviceEvent, METH_VARARGS, "RegisterDeviceEvent comment."}, - {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, - {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, - {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, - + {"tdRegisterDeviceEvent", (PyCFunction) telldus_tdRegisterDeviceEvent, METH_VARARGS, "RegisterDeviceEvent comment."}, + {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, + {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, + {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, + */ - {NULL, NULL, 0, NULL} /* sentinel */ + {NULL, NULL, 0, NULL} /* sentinel */ }; void inittelldus(void) { - PyObject *module; - - PyObject *TELLSTICK_TURNON_GLUE; - PyObject *TELLSTICK_TURNOFF_GLUE; - PyObject *TELLSTICK_BELL_GLUE; - PyObject *TELLSTICK_TOGGLE_GLUE; - PyObject *TELLSTICK_DIM_GLUE; - PyObject *TELLSTICK_LEARN_GLUE; - PyObject *TELLSTICK_SUCCESS_GLUE; - PyObject *TELLSTICK_ERROR_NOT_FOUND_GLUE; - PyObject *TELLSTICK_ERROR_PERMISSION_DENIED_GLUE; - PyObject *TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE; - PyObject *TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE; - PyObject *TELLSTICK_ERROR_COMMUNICATION_GLUE; - PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE; - PyObject *TELLSTICK_TYPE_DEVICE_GLUE; - PyObject *TELLSTICK_TYPE_GROUP_GLUE; + PyObject *module; + + PyObject *TELLSTICK_TURNON_GLUE; + PyObject *TELLSTICK_TURNOFF_GLUE; + PyObject *TELLSTICK_BELL_GLUE; + PyObject *TELLSTICK_TOGGLE_GLUE; + PyObject *TELLSTICK_DIM_GLUE; + PyObject *TELLSTICK_LEARN_GLUE; + PyObject *TELLSTICK_SUCCESS_GLUE; + PyObject *TELLSTICK_ERROR_NOT_FOUND_GLUE; + PyObject *TELLSTICK_ERROR_PERMISSION_DENIED_GLUE; + PyObject *TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE; + PyObject *TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE; + PyObject *TELLSTICK_ERROR_COMMUNICATION_GLUE; + PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE; + PyObject *TELLSTICK_TYPE_DEVICE_GLUE; + PyObject *TELLSTICK_TYPE_GROUP_GLUE; - /* Create the module and add the functions */ - - module = Py_InitModule("telldus", telldus_methods); - - TELLSTICK_TURNON_GLUE = PyLong_FromLong((long) TELLSTICK_TURNON); - PyObject_SetAttrString(module, "TELLSTICK_TURNON", TELLSTICK_TURNON_GLUE); - Py_DECREF(TELLSTICK_TURNON_GLUE); - - TELLSTICK_TURNOFF_GLUE = PyLong_FromLong((long) TELLSTICK_TURNOFF); - PyObject_SetAttrString(module, "TELLSTICK_TURNOFF", TELLSTICK_TURNOFF_GLUE); - Py_DECREF(TELLSTICK_TURNOFF_GLUE); - - TELLSTICK_BELL_GLUE = PyLong_FromLong((long) TELLSTICK_BELL); - PyObject_SetAttrString(module, "TELLSTICK_BELL", TELLSTICK_BELL_GLUE); - Py_DECREF(TELLSTICK_BELL_GLUE); - - TELLSTICK_TOGGLE_GLUE = PyLong_FromLong((long) TELLSTICK_TOGGLE); - PyObject_SetAttrString(module, "TELLSTICK_TOGGLE", TELLSTICK_TOGGLE_GLUE); - Py_DECREF(TELLSTICK_TOGGLE_GLUE); - - TELLSTICK_DIM_GLUE = PyLong_FromLong((long) TELLSTICK_DIM); - PyObject_SetAttrString(module, "TELLSTICK_DIM", TELLSTICK_DIM_GLUE); - Py_DECREF(TELLSTICK_DIM_GLUE); - - TELLSTICK_LEARN_GLUE = PyLong_FromLong((long) TELLSTICK_LEARN); - PyObject_SetAttrString(module, "TELLSTICK_LEARN", TELLSTICK_LEARN_GLUE); - Py_DECREF(TELLSTICK_LEARN_GLUE); - - TELLSTICK_SUCCESS_GLUE = PyLong_FromLong((long) TELLSTICK_SUCCESS); - PyObject_SetAttrString(module, "TELLSTICK_SUCCESS", TELLSTICK_SUCCESS_GLUE); - Py_DECREF(TELLSTICK_SUCCESS_GLUE); - - TELLSTICK_ERROR_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_NOT_FOUND); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_NOT_FOUND", TELLSTICK_ERROR_NOT_FOUND_GLUE); - Py_DECREF(TELLSTICK_ERROR_NOT_FOUND_GLUE); - - TELLSTICK_ERROR_PERMISSION_DENIED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_PERMISSION_DENIED); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_PERMISSION_DENIED", TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); - Py_DECREF(TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); - - TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_DEVICE_NOT_FOUND); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_DEVICE_NOT_FOUND", TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); - Py_DECREF(TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); - - TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_METHOD_NOT_SUPPORTED); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_METHOD_NOT_SUPPORTED", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); - Py_DECREF(TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); - - TELLSTICK_ERROR_COMMUNICATION_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_COMMUNICATION); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_COMMUNICATION", TELLSTICK_ERROR_COMMUNICATION_GLUE); - Py_DECREF(TELLSTICK_ERROR_COMMUNICATION_GLUE); - - TELLSTICK_ERROR_UNKNOWN_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_UNKNOWN); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_UNKNOWN", TELLSTICK_ERROR_UNKNOWN_GLUE); - Py_DECREF(TELLSTICK_ERROR_UNKNOWN_GLUE); + /* Create the module and add the functions */ - TELLSTICK_TYPE_DEVICE_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_DEVICE); - PyObject_SetAttrString(module, "TELLSTICK_TYPE_DEVICE", TELLSTICK_TYPE_DEVICE_GLUE); - Py_DECREF(TELLSTICK_TYPE_DEVICE_GLUE); - - TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); - PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); - Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); -} \ No newline at end of file + /* PyEval_InitThreads(); */ + + module = Py_InitModule("telldus", telldus_methods); + + TELLSTICK_TURNON_GLUE = PyLong_FromLong((long) TELLSTICK_TURNON); + PyObject_SetAttrString(module, "TELLSTICK_TURNON", TELLSTICK_TURNON_GLUE); + Py_DECREF(TELLSTICK_TURNON_GLUE); + + TELLSTICK_TURNOFF_GLUE = PyLong_FromLong((long) TELLSTICK_TURNOFF); + PyObject_SetAttrString(module, "TELLSTICK_TURNOFF", TELLSTICK_TURNOFF_GLUE); + Py_DECREF(TELLSTICK_TURNOFF_GLUE); + + TELLSTICK_BELL_GLUE = PyLong_FromLong((long) TELLSTICK_BELL); + PyObject_SetAttrString(module, "TELLSTICK_BELL", TELLSTICK_BELL_GLUE); + Py_DECREF(TELLSTICK_BELL_GLUE); + + TELLSTICK_TOGGLE_GLUE = PyLong_FromLong((long) TELLSTICK_TOGGLE); + PyObject_SetAttrString(module, "TELLSTICK_TOGGLE", TELLSTICK_TOGGLE_GLUE); + Py_DECREF(TELLSTICK_TOGGLE_GLUE); + + TELLSTICK_DIM_GLUE = PyLong_FromLong((long) TELLSTICK_DIM); + PyObject_SetAttrString(module, "TELLSTICK_DIM", TELLSTICK_DIM_GLUE); + Py_DECREF(TELLSTICK_DIM_GLUE); + + TELLSTICK_LEARN_GLUE = PyLong_FromLong((long) TELLSTICK_LEARN); + PyObject_SetAttrString(module, "TELLSTICK_LEARN", TELLSTICK_LEARN_GLUE); + Py_DECREF(TELLSTICK_LEARN_GLUE); + + TELLSTICK_SUCCESS_GLUE = PyLong_FromLong((long) TELLSTICK_SUCCESS); + PyObject_SetAttrString(module, "TELLSTICK_SUCCESS", TELLSTICK_SUCCESS_GLUE); + Py_DECREF(TELLSTICK_SUCCESS_GLUE); + + TELLSTICK_ERROR_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_NOT_FOUND); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_NOT_FOUND", TELLSTICK_ERROR_NOT_FOUND_GLUE); + Py_DECREF(TELLSTICK_ERROR_NOT_FOUND_GLUE); + + TELLSTICK_ERROR_PERMISSION_DENIED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_PERMISSION_DENIED); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_PERMISSION_DENIED", TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); + Py_DECREF(TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); + + TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_DEVICE_NOT_FOUND); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_DEVICE_NOT_FOUND", TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); + Py_DECREF(TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); + + TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_METHOD_NOT_SUPPORTED); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_METHOD_NOT_SUPPORTED", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); + Py_DECREF(TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); + + TELLSTICK_ERROR_COMMUNICATION_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_COMMUNICATION); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_COMMUNICATION", TELLSTICK_ERROR_COMMUNICATION_GLUE); + Py_DECREF(TELLSTICK_ERROR_COMMUNICATION_GLUE); + + TELLSTICK_ERROR_UNKNOWN_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_UNKNOWN); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_UNKNOWN", TELLSTICK_ERROR_UNKNOWN_GLUE); + Py_DECREF(TELLSTICK_ERROR_UNKNOWN_GLUE); + + TELLSTICK_TYPE_DEVICE_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_DEVICE); + PyObject_SetAttrString(module, "TELLSTICK_TYPE_DEVICE", TELLSTICK_TYPE_DEVICE_GLUE); + Py_DECREF(TELLSTICK_TYPE_DEVICE_GLUE); + + TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); + PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); + Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); +} From a5da11945e0bd801883da8df6a68a7e090aea974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 13:23:25 +0200 Subject: [PATCH 2061/2215] native dir --- bindings/python/{ => native}/MANIFEST.in | 0 bindings/python/{ => native}/example/__init__.py | 0 bindings/python/{ => native}/setup.py | 0 bindings/python/{ => native}/telldus-core.h | 0 bindings/python/{ => native}/telldus.c | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename bindings/python/{ => native}/MANIFEST.in (100%) rename bindings/python/{ => native}/example/__init__.py (100%) rename bindings/python/{ => native}/setup.py (100%) rename bindings/python/{ => native}/telldus-core.h (100%) rename bindings/python/{ => native}/telldus.c (100%) diff --git a/bindings/python/MANIFEST.in b/bindings/python/native/MANIFEST.in similarity index 100% rename from bindings/python/MANIFEST.in rename to bindings/python/native/MANIFEST.in diff --git a/bindings/python/example/__init__.py b/bindings/python/native/example/__init__.py similarity index 100% rename from bindings/python/example/__init__.py rename to bindings/python/native/example/__init__.py diff --git a/bindings/python/setup.py b/bindings/python/native/setup.py similarity index 100% rename from bindings/python/setup.py rename to bindings/python/native/setup.py diff --git a/bindings/python/telldus-core.h b/bindings/python/native/telldus-core.h similarity index 100% rename from bindings/python/telldus-core.h rename to bindings/python/native/telldus-core.h diff --git a/bindings/python/telldus.c b/bindings/python/native/telldus.c similarity index 100% rename from bindings/python/telldus.c rename to bindings/python/native/telldus.c From bd766e62549a9ef1178f529d12a375ac0aa268c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 13:42:07 +0200 Subject: [PATCH 2062/2215] no .h file --- bindings/python/native/telldus-core.h | 161 -------------------------- 1 file changed, 161 deletions(-) delete mode 100644 bindings/python/native/telldus-core.h diff --git a/bindings/python/native/telldus-core.h b/bindings/python/native/telldus-core.h deleted file mode 100644 index bd7fb147..00000000 --- a/bindings/python/native/telldus-core.h +++ /dev/null @@ -1,161 +0,0 @@ -// -// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. -// -// Copyright: See COPYING file that comes with this distribution -// -// -#ifndef TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ -#define TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ - -// The following ifdef block is the standard way of creating macros -// which make exporting from a DLL simpler. All files within this DLL -// are compiled with the TELLDUSCORE_EXPORTS symbol defined on the command line. -// This symbol should not be defined on any project that uses this DLL. -// This way any other project whose source files include this file see -// TELLSTICK_API functions as being imported from a DLL, whereas this DLL -// sees symbols defined with this macro as being exported. - -#ifdef _WINDOWS - #if defined(TELLDUSCORE_EXPORTS) - #if defined(_CL64) - #define TELLSTICK_API - #else - #define TELLSTICK_API __declspec(dllexport) - #endif - #else - #define TELLSTICK_API __declspec(dllimport) - #endif - #define WINAPI __stdcall -#else - #define WINAPI - #define TELLSTICK_API __attribute__ ((visibility("default"))) -#endif - -typedef void (WINAPI *TDDeviceEvent)(int deviceId, int method, const char *data, int callbackId, void *context); -typedef void (WINAPI *TDDeviceChangeEvent)(int deviceId, int changeEvent, int changeType, int callbackId, void *context); -typedef void (WINAPI *TDRawDeviceEvent)(const char *data, int controllerId, int callbackId, void *context); -typedef void (WINAPI *TDSensorEvent)(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context); -typedef void (WINAPI *TDControllerEvent)(int controllerId, int changeEvent, int changeType, const char *newValue, int callbackId, void *context); - -#ifndef __cplusplus - #define bool char -#endif - -#ifdef __cplusplus -extern "C" { -#endif - TELLSTICK_API void WINAPI tdInit(void); - TELLSTICK_API int WINAPI tdRegisterDeviceEvent( TDDeviceEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context); - TELLSTICK_API int WINAPI tdRegisterRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterSensorEvent( TDSensorEvent eventFunction, void *context ); - TELLSTICK_API int WINAPI tdRegisterControllerEvent( TDControllerEvent eventFunction, void *context); - TELLSTICK_API int WINAPI tdUnregisterCallback( int callbackId ); - TELLSTICK_API void WINAPI tdClose(void); - TELLSTICK_API void WINAPI tdReleaseString(char *thestring); - - TELLSTICK_API int WINAPI tdTurnOn(int intDeviceId); - TELLSTICK_API int WINAPI tdTurnOff(int intDeviceId); - TELLSTICK_API int WINAPI tdBell(int intDeviceId); - TELLSTICK_API int WINAPI tdDim(int intDeviceId, unsigned char level); - TELLSTICK_API int WINAPI tdExecute(int intDeviceId); - TELLSTICK_API int WINAPI tdUp(int intDeviceId); - TELLSTICK_API int WINAPI tdDown(int intDeviceId); - TELLSTICK_API int WINAPI tdStop(int intDeviceId); - TELLSTICK_API int WINAPI tdLearn(int intDeviceId); - TELLSTICK_API int WINAPI tdMethods(int id, int methodsSupported); - TELLSTICK_API int WINAPI tdLastSentCommand( int intDeviceId, int methodsSupported ); - TELLSTICK_API char *WINAPI tdLastSentValue( int intDeviceId ); - - TELLSTICK_API int WINAPI tdGetNumberOfDevices(); - TELLSTICK_API int WINAPI tdGetDeviceId(int intDeviceIndex); - TELLSTICK_API int WINAPI tdGetDeviceType(int intDeviceId); - - TELLSTICK_API char * WINAPI tdGetErrorString(int intErrorNo); - - TELLSTICK_API char * WINAPI tdGetName(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetName(int intDeviceId, const char* chNewName); - TELLSTICK_API char * WINAPI tdGetProtocol(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetProtocol(int intDeviceId, const char* strProtocol); - TELLSTICK_API char * WINAPI tdGetModel(int intDeviceId); - TELLSTICK_API bool WINAPI tdSetModel(int intDeviceId, const char *intModel); - - TELLSTICK_API char * WINAPI tdGetDeviceParameter(int intDeviceId, const char *strName, const char *defaultValue); - TELLSTICK_API bool WINAPI tdSetDeviceParameter(int intDeviceId, const char *strName, const char* strValue); - - TELLSTICK_API int WINAPI tdAddDevice(); - TELLSTICK_API bool WINAPI tdRemoveDevice(int intDeviceId); - - TELLSTICK_API int WINAPI tdSendRawCommand(const char *command, int reserved); - - TELLSTICK_API void WINAPI tdConnectTellStickController(int vid, int pid, const char *serial); - TELLSTICK_API void WINAPI tdDisconnectTellStickController(int vid, int pid, const char *serial); - - TELLSTICK_API int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, int *id, int *dataTypes); - TELLSTICK_API int WINAPI tdSensorValue(const char *protocol, const char *model, int id, int dataType, char *value, int len, int *timestamp); - - TELLSTICK_API int WINAPI tdController(int *controllerId, int *controllerType, char *name, int nameLen, int *available); - TELLSTICK_API int WINAPI tdControllerValue(int controllerId, const char *name, char *value, int valueLen); - TELLSTICK_API int WINAPI tdSetControllerValue(int controllerId, const char *name, const char *value); - TELLSTICK_API int WINAPI tdRemoveController(int controllerId); - -#ifdef __cplusplus -} -#endif - -// Device methods -#define TELLSTICK_TURNON 1 -#define TELLSTICK_TURNOFF 2 -#define TELLSTICK_BELL 4 -#define TELLSTICK_TOGGLE 8 -#define TELLSTICK_DIM 16 -#define TELLSTICK_LEARN 32 -#define TELLSTICK_EXECUTE 64 -#define TELLSTICK_UP 128 -#define TELLSTICK_DOWN 256 -#define TELLSTICK_STOP 512 - -// Sensor value types -#define TELLSTICK_TEMPERATURE 1 -#define TELLSTICK_HUMIDITY 2 - -// Error codes -#define TELLSTICK_SUCCESS 0 -#define TELLSTICK_ERROR_NOT_FOUND -1 -#define TELLSTICK_ERROR_PERMISSION_DENIED -2 -#define TELLSTICK_ERROR_DEVICE_NOT_FOUND -3 -#define TELLSTICK_ERROR_METHOD_NOT_SUPPORTED -4 -#define TELLSTICK_ERROR_COMMUNICATION -5 -#define TELLSTICK_ERROR_CONNECTING_SERVICE -6 -#define TELLSTICK_ERROR_UNKNOWN_RESPONSE -7 -#define TELLSTICK_ERROR_SYNTAX -8 -#define TELLSTICK_ERROR_BROKEN_PIPE -9 -#define TELLSTICK_ERROR_COMMUNICATING_SERVICE -10 -#define TELLSTICK_ERROR_CONFIG_SYNTAX -11 -#define TELLSTICK_ERROR_UNKNOWN -99 - -// Device typedef -#define TELLSTICK_TYPE_DEVICE 1 -#define TELLSTICK_TYPE_GROUP 2 -#define TELLSTICK_TYPE_SCENE 3 - -// Controller typedef -#define TELLSTICK_CONTROLLER_TELLSTICK 1 -#define TELLSTICK_CONTROLLER_TELLSTICK_DUO 2 -#define TELLSTICK_CONTROLLER_TELLSTICK_NET 3 - -// Device changes -#define TELLSTICK_DEVICE_ADDED 1 -#define TELLSTICK_DEVICE_CHANGED 2 -#define TELLSTICK_DEVICE_REMOVED 3 -#define TELLSTICK_DEVICE_STATE_CHANGED 4 - -// Change types -#define TELLSTICK_CHANGE_NAME 1 -#define TELLSTICK_CHANGE_PROTOCOL 2 -#define TELLSTICK_CHANGE_MODEL 3 -#define TELLSTICK_CHANGE_METHOD 4 -#define TELLSTICK_CHANGE_AVAILABLE 5 -#define TELLSTICK_CHANGE_FIRMWARE 6 - -#endif // TELLDUS_CORE_CLIENT_TELLDUS_CORE_H_ From 384c81d85ac602baf53738e13b14decf24a9c64a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 13:45:04 +0200 Subject: [PATCH 2063/2215] add dev dir to find telldus-core.h file --- bindings/python/native/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/native/setup.py b/bindings/python/native/setup.py index 635121fa..8421a804 100644 --- a/bindings/python/native/setup.py +++ b/bindings/python/native/setup.py @@ -312,7 +312,7 @@ if PLATFORM_IS_WINDOWS: telldus_platform = os.environ.get("TELLDUS_PLATFORM", 'x86_64') telldus_library_dir = os.path.join(telldus_dev_dir, telldus_platform) - include_dirs = [sdk_include_dir, os.path.dirname(this_file)] + include_dirs = [sdk_include_dir, telldus_dev_dir] library_dirs = [telldus_library_dir] libraries = ['python%i%i' % (sys.version_info[0], sys.version_info[1]) , 'TelldusCore'] define_macros = [('_WINDOWS', 1)] From 6496e71026896baec50ae8d05f3959e01ee72a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 14:25:13 +0200 Subject: [PATCH 2064/2215] removed stray spaces --- bindings/python/native/telldus.c | 203 +++++++++++++++---------------- 1 file changed, 98 insertions(+), 105 deletions(-) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 1b1673d2..5103bd45 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -133,7 +133,7 @@ telldus_tdLastSentValue(PyObject *self, PyObject *args) long id; char* value; char* retval; - + if (!PyArg_ParseTuple(args, "l", &id)) return NULL; @@ -177,7 +177,7 @@ telldus_tdGetErrorString(PyObject *self, PyObject *args) long errorno; char* errorString; char* retval; - + if (!PyArg_ParseTuple(args, "l", &errorno)) return NULL; @@ -193,7 +193,7 @@ telldus_tdGetName(PyObject *self, PyObject *args) long id; char* name; char* retval; - + if (!PyArg_ParseTuple(args, "l", &id)) return NULL; @@ -208,7 +208,7 @@ telldus_tdSetName(PyObject *self, PyObject *args) { long id; char* name; - + if (!PyArg_ParseTuple(args, "ls", &id, &name)) return NULL; @@ -221,7 +221,7 @@ telldus_tdGetProtocol(PyObject *self, PyObject *args) long id; char* protocol; char* retval; - + if (!PyArg_ParseTuple(args, "l", &id)) return NULL; @@ -236,7 +236,7 @@ telldus_tdSetProtocol(PyObject *self, PyObject *args) { long id; char* protocol; - + if (!PyArg_ParseTuple(args, "ls", &id, &protocol)) return NULL; @@ -250,7 +250,7 @@ telldus_tdGetModel(PyObject *self, PyObject *args) long id; char* model; char* retval; - + if (!PyArg_ParseTuple(args, "l", &id)) return NULL; @@ -265,7 +265,7 @@ telldus_tdSetModel(PyObject *self, PyObject *args) { long id; char* model; - + if (!PyArg_ParseTuple(args, "ls", &id, &model)) return NULL; @@ -281,7 +281,7 @@ telldus_tdGetDeviceParameter(PyObject *self, PyObject *args) char* defaultValue; char* param; char* retval; - + if (!PyArg_ParseTuple(args, "lss", &id, &name, &defaultValue)) return NULL; @@ -297,7 +297,7 @@ telldus_tdSetDeviceParameter(PyObject *self, PyObject *args) long id; char* name; char* value; - + if (!PyArg_ParseTuple(args, "lss", &id, &name, &value)) return NULL; @@ -334,124 +334,105 @@ telldus_tdSendRawCommand(PyObject *self, PyObject *args) } /* - Work in progress event callbacks + Work in progress event callbacks */ /* void telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("llsl", deviceId, method, data, callbackId); + PyObject * arglist; + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyObject_CallFunction(pyfunc, "llsl", deviceId, method, data, callbackId); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } - + void telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("llll", deviceId, changeEvent, changeType, callbackId); + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyObject_CallFunction(pyfunc, "llll", deviceId, changeEvent, changeType, callbackId); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } - + void telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("sll", data, controllerId, callbackId); + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyObject_CallFunction(pyfunc, "sll", data, controllerId, callbackId); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } void telldus_sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *pyfunc) { - PyObject * arglist; - PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); - - // prepare the arg list to pass into the Python callback function - arglist = Py_BuildValue("ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); + PyObject * result; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); - // now call the Python callback function - result = PyEval_CallObject(pyfunc, arglist); + // now call the Python callback function + result = PyObject_CallFunction(pyfunc, "ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } - // take care of reference handling - Py_DECREF(arglist); - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; } static PyObject * @@ -462,7 +443,10 @@ telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "O", &func)); return NULL; - return PyLong_FromLong((long) tdRegisterDeviceEvent((TDDeviceEvent) telldus_deviceEventCallback, &func)); + // stick around till we need you + Py_INCREF(func); + + return PyLong_FromLong((long) tdRegisterDeviceEvent((TDDeviceEvent) telldus_deviceEventCallback, &func)); } static PyObject * @@ -473,7 +457,10 @@ telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "O", &func)); return NULL; - return PyLong_FromLong((long) tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) telldus_deviceChangeEventCallback, &func)); + // stick around till we need you + Py_INCREF(func); + + return PyLong_FromLong((long) tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) telldus_deviceChangeEventCallback, &func)); } static PyObject * @@ -483,8 +470,11 @@ telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "O", &func)); return NULL; + + // stick around till we need you + Py_INCREF(func); - return PyLong_FromLong((long) tdRegisterRawDeviceEvent((TDRawDeviceEvent) telldus_rawDeviceEventCallback, &func)); + return PyLong_FromLong((long) tdRegisterRawDeviceEvent((TDRawDeviceEvent) telldus_rawDeviceEventCallback, &func)); } static PyObject * @@ -495,15 +485,18 @@ telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "O", &func)); return NULL; - return PyLong_FromLong((long) tdRegisterSensorEvent((TDSensorEvent) telldus_sensorEventCallback, &func)); + // stick around till we need you + Py_INCREF(func); + + return PyLong_FromLong((long) tdRegisterSensorEvent((TDSensorEvent) telldus_sensorEventCallback, &func)); } */ static PyMethodDef telldus_methods[] = { /* The cast of the function is necessary since PyCFunction values - * only take two PyObject* parameters, and keywdarg_parrot() takes - * three. - */ + * only take two PyObject* parameters, and keywdarg_parrot() takes + * three. + */ {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, {"tdClose", (PyCFunction) telldus_tdClose, METH_NOARGS, "Close telldus."}, {"tdTurnOn", (PyCFunction) telldus_tdTurnOn, METH_VARARGS, "Turn on device."}, @@ -534,7 +527,7 @@ static PyMethodDef telldus_methods[] = { {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, - + */ {NULL, NULL, 0, NULL} /* sentinel */ }; From 71e13196f382f1ba79b84ffa4b1df067022ac447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Tue, 7 Aug 2012 16:08:13 +0200 Subject: [PATCH 2065/2215] add tdUnregisterCallback --- bindings/python/native/example/__init__.py | 42 --------------- bindings/python/native/example/basic.py | 42 +++++++++++++++ bindings/python/native/example/callback.py | 60 ++++++++++++++++++++++ bindings/python/native/telldus.c | 31 ++++++++--- 4 files changed, 127 insertions(+), 48 deletions(-) create mode 100644 bindings/python/native/example/basic.py create mode 100644 bindings/python/native/example/callback.py diff --git a/bindings/python/native/example/__init__.py b/bindings/python/native/example/__init__.py index 5e1f823c..e69de29b 100644 --- a/bindings/python/native/example/__init__.py +++ b/bindings/python/native/example/__init__.py @@ -1,42 +0,0 @@ - -import telldus -import time - -telldus.tdInit() -devices = telldus.tdGetNumberOfDevices() -print "Devices: %d\n" % devices - -allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM - -for i in xrange(devices): - deviceid = telldus.tdGetDeviceId(i) - name = telldus.tdGetName(deviceid) - - print "%s - %s\n" % (deviceid, name) - - methods = telldus.tdMethods(deviceid, allMethods) - - if methods & telldus.TELLDUS_TURNON: - print " * TurnOn\n" - telldus.tdTurnOn(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_TURNOFF: - print " * TurnOff\n" - telldus.tdTurnOff(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_BELL: - echo " * Bell\n" - telldus.tdBell(deviceid) - time.sleep(1) - - if methods & telldus.TELLDUS_TOGGLE: - print " * Toggle\n" - - if methods & telldus.TELLDUS_DIM: - print " * Dim\n" - telldus.tdDim(deviceid, 128) - time.sleep(1) - -telldus.tdClose() \ No newline at end of file diff --git a/bindings/python/native/example/basic.py b/bindings/python/native/example/basic.py new file mode 100644 index 00000000..5e1f823c --- /dev/null +++ b/bindings/python/native/example/basic.py @@ -0,0 +1,42 @@ + +import telldus +import time + +telldus.tdInit() +devices = telldus.tdGetNumberOfDevices() +print "Devices: %d\n" % devices + +allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM + +for i in xrange(devices): + deviceid = telldus.tdGetDeviceId(i) + name = telldus.tdGetName(deviceid) + + print "%s - %s\n" % (deviceid, name) + + methods = telldus.tdMethods(deviceid, allMethods) + + if methods & telldus.TELLDUS_TURNON: + print " * TurnOn\n" + telldus.tdTurnOn(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TURNOFF: + print " * TurnOff\n" + telldus.tdTurnOff(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_BELL: + echo " * Bell\n" + telldus.tdBell(deviceid) + time.sleep(1) + + if methods & telldus.TELLDUS_TOGGLE: + print " * Toggle\n" + + if methods & telldus.TELLDUS_DIM: + print " * Dim\n" + telldus.tdDim(deviceid, 128) + time.sleep(1) + +telldus.tdClose() \ No newline at end of file diff --git a/bindings/python/native/example/callback.py b/bindings/python/native/example/callback.py new file mode 100644 index 00000000..99289eb0 --- /dev/null +++ b/bindings/python/native/example/callback.py @@ -0,0 +1,60 @@ +import telldus +import time +from threading import Timer + +telldus.tdInit() + +timers = {} #timerlist + +def turnOn(): + print "turning on" + telldus.tdTurnOn(1) + +def turnOff(): + print "turning off" + telldus.tdTurnOff(1) + +def callback(deviceId, method, value, callbackId): + global timers + + print "callback!" + + if (deviceId == 1): + # is turning on deviceId 1 here, so just return if events for that device are picked up + return + + t = 0 + print "Received event for device %d" % (deviceId,) + if (deviceId in timers): + # a timer already exists for this device, it might be running so interrupt it + # Many devices (for example motion detectors) resends their messages many times to ensure that they + # are received correctly. In this example, we don't want to run the turnOn/turnOff methods every time, instead we + # start a timer, and run the method when the timer is finished. For every incoming event on this device, the timer + # is restarted. + t = timers[deviceId] + t.cancel() + if (method == 1): + #on + t = Timer(0.5, turnOn) #start timer with 0.5 second delay (adjust the delay to suit your needs), then turn on + else: + #off + t = Timer(0.5, turnOff) #start timer with 0.5 second delay (adjust the delay to suit your needs), then turn off + + t.start() + timers[deviceId] = t #put timer in list, to allow later cancellation + +#function to be called when device event occurs, even for unregistered devices +def rawcallback(data, controllerId, callbackId): + print str(data) + +callbackid = telldus.tdRegisterDeviceEvent(callback) +rawcallbackid = telldus.tdRegisterRawDeviceEvent(rawcallback) + +try: + while(1): + time.sleep(0.5) #don't exit +except KeyboardInterrupt: + print "Exiting" + telldus.tdUnregisterCallback(callbackid) + telldus.tdUnregisterCallback(rawcallbackid) + telldus.tdClose() diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 5103bd45..9b1fd947 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -490,13 +490,20 @@ telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) return PyLong_FromLong((long) tdRegisterSensorEvent((TDSensorEvent) telldus_sensorEventCallback, &func)); } + +static PyObject * +telldus_tdUnregisterCallback(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)); + return NULL; + + return PyBool_FromLong((long) tdUnregisterCallback(id)); +} */ static PyMethodDef telldus_methods[] = { - /* The cast of the function is necessary since PyCFunction values - * only take two PyObject* parameters, and keywdarg_parrot() takes - * three. - */ {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, {"tdClose", (PyCFunction) telldus_tdClose, METH_NOARGS, "Close telldus."}, {"tdTurnOn", (PyCFunction) telldus_tdTurnOn, METH_VARARGS, "Turn on device."}, @@ -527,6 +534,7 @@ static PyMethodDef telldus_methods[] = { {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, + {"tdUnregisterCallback", (PyCFunction) telldus_tdUnregisterCallback, METH_VARARGS, "UnregisterCallback comment."}, */ {NULL, NULL, 0, NULL} /* sentinel */ @@ -552,7 +560,9 @@ inittelldus(void) PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE; PyObject *TELLSTICK_TYPE_DEVICE_GLUE; PyObject *TELLSTICK_TYPE_GROUP_GLUE; - + PyObject *TELLSTICK_TEMPERATURE_GLUE; + PyObject *TELLSTICK_HUMIDITY_GLUE; + /* Create the module and add the functions */ /* PyEval_InitThreads(); */ @@ -617,5 +627,14 @@ inittelldus(void) TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); - Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); + Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); + + PyObject *TELLSTICK_TEMPERATURE_GLUE = PyLong_FromLong((long) TELLSTICK_TEMPERATURE); + PyObject_SetAttrString(module, "TELLSTICK_TEMPERATURE", TELLSTICK_TEMPERATURE_GLUE); + Py_DECREF(TELLSTICK_TEMPERATURE_GLUE); + + PyObject *TELLSTICK_HUMIDITY_GLUE = PyLong_FromLong((long) TELLSTICK_HUMIDITY); + PyObject_SetAttrString(module, "TELLSTICK_HUMIDITY", TELLSTICK_HUMIDITY_GLUE); + Py_DECREF(TELLSTICK_HUMIDITY_GLUE); + } From d6fcd4a5dcd10caf4567ba6881e19fd35369dc90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Wed, 8 Aug 2012 13:12:51 +0200 Subject: [PATCH 2066/2215] tdsensor --- bindings/python/native/example/poll.py | 28 +++++++++ bindings/python/native/setup.py | 2 + bindings/python/native/telldus.c | 86 ++++++++++++++++++++++---- 3 files changed, 104 insertions(+), 12 deletions(-) create mode 100644 bindings/python/native/example/poll.py diff --git a/bindings/python/native/example/poll.py b/bindings/python/native/example/poll.py new file mode 100644 index 00000000..e86632d2 --- /dev/null +++ b/bindings/python/native/example/poll.py @@ -0,0 +1,28 @@ +import telldus + +telldus.tdInit() + + while(1): + result = telldus.tdSensor() + if not result: + break + else: + protocol, model, sensorId = result + print "%s,\t%s,\t%i\n" % (protocol, model, sensorId) + + # Retrieve the values the sensor supports + if (dataTypes & telldus.TELLSTICK_TEMPERATURE): + result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_TEMPERATURE) + if result: + value, timestamp = result + print "Temperature:\t%sº\t(%s)\n" % (value, str(timestamp)) + + if (dataTypes & telldus.TELLSTICK_HUMIDITY): + result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_HUMIDITY) + if result: + value, timestamp = result + print "Humidity:\t%s\t(%s)\n" % (value, str(timestamp)) + + print "\n" + +tdClose(); diff --git a/bindings/python/native/setup.py b/bindings/python/native/setup.py index 8421a804..f130b2c2 100644 --- a/bindings/python/native/setup.py +++ b/bindings/python/native/setup.py @@ -322,6 +322,8 @@ else: library_dirs = ['/usr/lib', '/usr/local/lib'] libraries = ['telldus-core'] define_macros = [] + +define_macros.extend([('DATA_LENGTH', 20)]) telldus = Extension( 'telldus', diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 9b1fd947..6bd200c0 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -1,4 +1,5 @@ #include "Python.h" +#include "datetime.h" #include #include @@ -333,15 +334,11 @@ telldus_tdSendRawCommand(PyObject *self, PyObject *args) return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); } -/* - Work in progress event callbacks -*/ - -/* + void telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *pyfunc) { - PyObject * arglist; + PyObject * result; PyGILState_STATE gstate; @@ -501,7 +498,71 @@ telldus_tdUnregisterCallback(PyObject *self, PyObject *args) return PyBool_FromLong((long) tdUnregisterCallback(id)); } -*/ + +static PyObject * +telldus_tdSensor(PyObject *self, PyObject *args) +{ + char protocol[DATA_LENGTH]; + char model[DATA_LENGTH]; + long sensorId = 0; + long dataTypes = 0; + + long result; + + result = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + + if (result == TELLSTICK_SUCCESS) + { + return Py_BuildValue("ssll", protocol, model, sensorId, dataTypes); + } + else + { + return PyBool_FromLong(result); + } + +} + +static PyObject * +telldus_tdSensorValue(PyObject *self, PyObject *args) +{ + char protocol[DATA_LENGTH]; + char model[DATA_LENGTH]; + long sensorId = 0; + long dataType = 0; + char value[DATA_LENGTH]; + long timestamp = 0; + + PyObject *floatObj; + PyObject *timeTuple; + + long result; + + PyObject *py_date; + + if (!PyArg_ParseTuple(args, "ssll", &protocol, &model, &sensorId, &dataType)); + return NULL; + + result = tdSensorValue(protocol, model, sensorId, dataType, &value, DATA_LENGTH, ×tamp); + + floatObj = PyFloat_FromDouble(timestamp); + timeTuple = Py_BuildValue("(O)", floatObj); + Py_DECREF(floatObj); + + py_date = PyDateTime_FromTimestamp(timeTuple); + + Py_DECREF(timeTuple); + + Py_INCREF(py_date); + + if (result == TELLSTICK_SUCCESS) + { + return Py_BuildValue("sO", value, py_date); + } + else + { + return PyBool_FromLong(result); + } +} static PyMethodDef telldus_methods[] = { {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, @@ -529,14 +590,15 @@ static PyMethodDef telldus_methods[] = { {"tdAddDevice", (PyCFunction) telldus_tdAddDevice, METH_NOARGS, "AddDevice comment."}, {"tdRemoveDevice", (PyCFunction) telldus_tdRemoveDevice, METH_VARARGS, "RemoveDevice comment."}, {"tdSendRawCommand", (PyCFunction) telldus_tdSendRawCommand, METH_VARARGS, "SendRawCommand comment."}, -/* + {"tdRegisterDeviceEvent", (PyCFunction) telldus_tdRegisterDeviceEvent, METH_VARARGS, "RegisterDeviceEvent comment."}, {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, {"tdUnregisterCallback", (PyCFunction) telldus_tdUnregisterCallback, METH_VARARGS, "UnregisterCallback comment."}, - -*/ + {"tdSensor", (PyCFunction) telldus_tdSensor, METH_NOARGS, "Sensor comment."}, + {"tdSensorValue", (PyCFunction) telldus_tdSensorValue, METH_VARARGS, "SensorValue comment."}, + {NULL, NULL, 0, NULL} /* sentinel */ }; @@ -629,11 +691,11 @@ inittelldus(void) PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); - PyObject *TELLSTICK_TEMPERATURE_GLUE = PyLong_FromLong((long) TELLSTICK_TEMPERATURE); + TELLSTICK_TEMPERATURE_GLUE = PyLong_FromLong((long) TELLSTICK_TEMPERATURE); PyObject_SetAttrString(module, "TELLSTICK_TEMPERATURE", TELLSTICK_TEMPERATURE_GLUE); Py_DECREF(TELLSTICK_TEMPERATURE_GLUE); - PyObject *TELLSTICK_HUMIDITY_GLUE = PyLong_FromLong((long) TELLSTICK_HUMIDITY); + TELLSTICK_HUMIDITY_GLUE = PyLong_FromLong((long) TELLSTICK_HUMIDITY); PyObject_SetAttrString(module, "TELLSTICK_HUMIDITY", TELLSTICK_HUMIDITY_GLUE); Py_DECREF(TELLSTICK_HUMIDITY_GLUE); From f09ebea266ae4ef9b52ff945e3fa9af6a7798225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Wed, 8 Aug 2012 13:15:57 +0200 Subject: [PATCH 2067/2215] no semicolon --- bindings/python/native/example/poll.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/native/example/poll.py b/bindings/python/native/example/poll.py index e86632d2..7061b5a8 100644 --- a/bindings/python/native/example/poll.py +++ b/bindings/python/native/example/poll.py @@ -25,4 +25,4 @@ telldus.tdInit() print "\n" -tdClose(); +tdClose() From 517c987b6dd2766d9ec4ba1583f32692d8be1793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Wed, 8 Aug 2012 13:25:47 +0200 Subject: [PATCH 2068/2215] PyEval_InitThreads --- bindings/python/native/telldus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 6bd200c0..7aab562f 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -627,7 +627,7 @@ inittelldus(void) /* Create the module and add the functions */ - /* PyEval_InitThreads(); */ + PyEval_InitThreads(); module = Py_InitModule("telldus", telldus_methods); From 9073d60858a72860130a019cda951bcacdd10850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Fri, 10 Aug 2012 19:25:24 +0200 Subject: [PATCH 2069/2215] working with callbacks --- bindings/python/native/example/basic.py | 22 +- bindings/python/native/example/callback.py | 40 +--- bindings/python/native/telldus.c | 221 +++++++++++++-------- 3 files changed, 162 insertions(+), 121 deletions(-) diff --git a/bindings/python/native/example/basic.py b/bindings/python/native/example/basic.py index 5e1f823c..dd260231 100644 --- a/bindings/python/native/example/basic.py +++ b/bindings/python/native/example/basic.py @@ -6,7 +6,7 @@ telldus.tdInit() devices = telldus.tdGetNumberOfDevices() print "Devices: %d\n" % devices -allMethods = telldus.TELLDUS_TURNON | telldus.TELLDUS_TURNOFF | telldus.TELLDUS_BELL | telldus.TELLDUS_DIM +allMethods = telldus.TELLSTICK_TURNON | telldus.TELLSTICK_TURNOFF | telldus.TELLSTICK_BELL | telldus.TELLSTICK_DIM for i in xrange(devices): deviceid = telldus.tdGetDeviceId(i) @@ -16,27 +16,35 @@ for i in xrange(devices): methods = telldus.tdMethods(deviceid, allMethods) - if methods & telldus.TELLDUS_TURNON: + if methods & telldus.TELLSTICK_TURNON: print " * TurnOn\n" telldus.tdTurnOn(deviceid) time.sleep(1) - if methods & telldus.TELLDUS_TURNOFF: + if methods & telldus.TELLSTICK_TURNOFF: print " * TurnOff\n" telldus.tdTurnOff(deviceid) time.sleep(1) - if methods & telldus.TELLDUS_BELL: + if methods & telldus.TELLSTICK_BELL: echo " * Bell\n" telldus.tdBell(deviceid) time.sleep(1) - if methods & telldus.TELLDUS_TOGGLE: + if methods & telldus.TELLSTICK_TOGGLE: print " * Toggle\n" - if methods & telldus.TELLDUS_DIM: + if methods & telldus.TELLSTICK_DIM: print " * Dim\n" telldus.tdDim(deviceid, 128) time.sleep(1) -telldus.tdClose() \ No newline at end of file +telldus.tdClose() + +import time +time.sleep(30) +for i in xrange(20): + telldus.tdTurnOn(3) + telldus.tdTurnOff(3) + + diff --git a/bindings/python/native/example/callback.py b/bindings/python/native/example/callback.py index 99289eb0..43774674 100644 --- a/bindings/python/native/example/callback.py +++ b/bindings/python/native/example/callback.py @@ -1,10 +1,10 @@ +import threading import telldus import time -from threading import Timer + telldus.tdInit() -timers = {} #timerlist def turnOn(): print "turning on" @@ -15,39 +15,15 @@ def turnOff(): telldus.tdTurnOff(1) def callback(deviceId, method, value, callbackId): - global timers - - print "callback!" - - if (deviceId == 1): - # is turning on deviceId 1 here, so just return if events for that device are picked up - return - - t = 0 - print "Received event for device %d" % (deviceId,) - if (deviceId in timers): - # a timer already exists for this device, it might be running so interrupt it - # Many devices (for example motion detectors) resends their messages many times to ensure that they - # are received correctly. In this example, we don't want to run the turnOn/turnOff methods every time, instead we - # start a timer, and run the method when the timer is finished. For every incoming event on this device, the timer - # is restarted. - t = timers[deviceId] - t.cancel() - if (method == 1): - #on - t = Timer(0.5, turnOn) #start timer with 0.5 second delay (adjust the delay to suit your needs), then turn on - else: - #off - t = Timer(0.5, turnOff) #start timer with 0.5 second delay (adjust the delay to suit your needs), then turn off - - t.start() - timers[deviceId] = t #put timer in list, to allow later cancellation + print "callback" + return True #function to be called when device event occurs, even for unregistered devices def rawcallback(data, controllerId, callbackId): - print str(data) + print "raw callback" + return True -callbackid = telldus.tdRegisterDeviceEvent(callback) +#callbackid = telldus.tdRegisterDeviceEvent(callback) rawcallbackid = telldus.tdRegisterRawDeviceEvent(rawcallback) try: @@ -55,6 +31,6 @@ try: time.sleep(0.5) #don't exit except KeyboardInterrupt: print "Exiting" - telldus.tdUnregisterCallback(callbackid) + #telldus.tdUnregisterCallback(callbackid) telldus.tdUnregisterCallback(rawcallbackid) telldus.tdClose() diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 7aab562f..68cd74b4 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -1,7 +1,7 @@ #include "Python.h" #include "datetime.h" #include -#include +#include /* estrdup.c -- duplicate a string, die if error * @@ -31,6 +31,9 @@ estrdup(char *s) static PyObject * telldus_tdInit(PyObject *self) { + PyEval_InitThreads(); + PyEval_ReleaseLock(); + tdInit(); Py_INCREF(Py_None); return Py_None; @@ -52,7 +55,7 @@ telldus_tdTurnOn(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "l", &id)) return NULL; - return PyBool_FromLong((long) tdTurnOn(id)); + return PyLong_FromLong((long) tdTurnOn(id)); } static PyObject * @@ -63,7 +66,7 @@ telldus_tdTurnOff(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "l", &id)) return NULL; - return PyBool_FromLong((long) tdTurnOff(id)); + return PyLong_FromLong((long) tdTurnOff(id)); } static PyObject * @@ -74,7 +77,7 @@ telldus_tdBell(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "l", &id)) return NULL; - return PyBool_FromLong((long) tdBell(id)); + return PyLong_FromLong((long) tdBell(id)); } static PyObject * @@ -89,7 +92,7 @@ telldus_tdDim(PyObject *self, PyObject *args) if (level < 0 || level > 255) return NULL; - return PyBool_FromLong((long) tdDim(id, level)); + return PyLong_FromLong((long) tdDim(id, level)); } static PyObject * @@ -100,7 +103,7 @@ telldus_tdLearn(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "l", &id)) return NULL; - return PyBool_FromLong((long) tdLearn(id)); + return PyLong_FromLong((long) tdLearn(id)); } static PyObject * @@ -213,7 +216,7 @@ telldus_tdSetName(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ls", &id, &name)) return NULL; - return PyBool_FromLong((long) tdSetName(id, name)); + return PyLong_FromLong((long) tdSetName(id, name)); } static PyObject * @@ -241,7 +244,7 @@ telldus_tdSetProtocol(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ls", &id, &protocol)) return NULL; - return PyBool_FromLong((long) tdSetProtocol(id, protocol)); + return PyLong_FromLong((long) tdSetProtocol(id, protocol)); } @@ -270,7 +273,7 @@ telldus_tdSetModel(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ls", &id, &model)) return NULL; - return PyBool_FromLong((long) tdSetProtocol(id, model)); + return PyLong_FromLong((long) tdSetProtocol(id, model)); } @@ -302,7 +305,7 @@ telldus_tdSetDeviceParameter(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "lss", &id, &name, &value)) return NULL; - return PyBool_FromLong((long) tdSetDeviceParameter(id, name, value)); + return PyLong_FromLong((long) tdSetDeviceParameter(id, name, value)); } static PyObject * @@ -319,7 +322,7 @@ telldus_tdRemoveDevice(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "l", &id)) return NULL; - return PyBool_FromLong((long) tdRemoveDevice(id)); + return PyLong_FromLong((long) tdRemoveDevice(id)); } static PyObject * @@ -334,18 +337,17 @@ telldus_tdSendRawCommand(PyObject *self, PyObject *args) return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); } +static PyObject *DeviceEventCallback = NULL; void -telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *pyfunc) +telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, int context) { PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); + PyGILState_STATE gstate = PyGILState_Ensure(); // now call the Python callback function - result = PyObject_CallFunction(pyfunc, "llsl", deviceId, method, data, callbackId); + result = PyObject_CallFunction(DeviceEventCallback, "llsl", deviceId, method, data, callbackId); if (result == NULL) { // something went wrong so print to stderr @@ -360,16 +362,45 @@ telldus_deviceEventCallback(int deviceId, int method, const char *data, int call return; } +static PyObject * +telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) +{ + + int result; + PyObject *func; + + if (!PyArg_ParseTuple(args, "O:tdRegisterDeviceEvent", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); + return NULL; + } + + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(DeviceEventCallback); + // stick around till we need you + Py_XINCREF(func); + + DeviceEventCallback = func; + + tdRegisterDeviceEvent((TDDeviceEvent) &telldus_deviceEventCallback, 0); + + return PyLong_FromLong((long) result); +} + +static PyObject *DeviceChangeEventCallback = NULL; + void -telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, int callbackId, void *pyfunc) +telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, int callbackId, int context) { PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); + PyGILState_STATE gstate = PyGILState_Ensure(); // now call the Python callback function - result = PyObject_CallFunction(pyfunc, "llll", deviceId, changeEvent, changeType, callbackId); + result = PyObject_CallFunction(DeviceChangeEventCallback, "llll", deviceId, changeEvent, changeType, callbackId); if (result == NULL) { // something went wrong so print to stderr @@ -383,17 +414,45 @@ telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, return; } + +static PyObject * +telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) +{ + int result; + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); + return NULL; + } + + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(DeviceChangeEventCallback); + // stick around till we need you + Py_XINCREF(func); + + DeviceChangeEventCallback = func; + + result = tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) &telldus_deviceChangeEventCallback, 0); + + return PyLong_FromLong((long) result); +} + +static PyObject *RawDeviceEventCallback = NULL; void -telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackId, void *pyfunc) +telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackId, int context) { PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); + PyGILState_STATE gstate = PyGILState_Ensure(); // now call the Python callback function - result = PyObject_CallFunction(pyfunc, "sll", data, controllerId, callbackId); + result = PyObject_CallFunction(RawDeviceEventCallback, "sll", data, controllerId, callbackId); if (result == NULL) { // something went wrong so print to stderr @@ -408,16 +467,44 @@ telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackI return; } +static PyObject * +telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) +{ + int result; + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); + return NULL; + } + + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(RawDeviceEventCallback); + // stick around till we need you + Py_XINCREF(func); + + RawDeviceEventCallback = func; + + result = tdRegisterRawDeviceEvent((TDRawDeviceEvent) &telldus_rawDeviceEventCallback, 0); + + return PyLong_FromLong((long) result); +} + +static PyObject *SensorEventCallback = NULL; + void -telldus_sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *pyfunc) +telldus_sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, int context) { PyObject * result; - PyGILState_STATE gstate; - - gstate = PyGILState_Ensure(); + PyGILState_STATE gstate = PyGILState_Ensure(); // now call the Python callback function - result = PyObject_CallFunction(pyfunc, "ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); + result = PyObject_CallFunction(SensorEventCallback, "ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); if (result == NULL) { // something went wrong so print to stderr @@ -432,60 +519,32 @@ telldus_sensorEventCallback(const char *protocol, const char *model, int id, int return; } -static PyObject * -telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) -{ - PyObject *func; - - if (!PyArg_ParseTuple(args, "O", &func)); - return NULL; - - // stick around till we need you - Py_INCREF(func); - - return PyLong_FromLong((long) tdRegisterDeviceEvent((TDDeviceEvent) telldus_deviceEventCallback, &func)); -} - -static PyObject * -telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) -{ - PyObject *func; - - if (!PyArg_ParseTuple(args, "O", &func)); - return NULL; - - // stick around till we need you - Py_INCREF(func); - - return PyLong_FromLong((long) tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) telldus_deviceChangeEventCallback, &func)); -} - -static PyObject * -telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) -{ - PyObject *func; - - if (!PyArg_ParseTuple(args, "O", &func)); - return NULL; - - // stick around till we need you - Py_INCREF(func); - - return PyLong_FromLong((long) tdRegisterRawDeviceEvent((TDRawDeviceEvent) telldus_rawDeviceEventCallback, &func)); -} - static PyObject * telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) { + int result; PyObject *func; - if (!PyArg_ParseTuple(args, "O", &func)); + if (!PyArg_ParseTuple(args, "O", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); return NULL; + } + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(SensorEventCallback); // stick around till we need you - Py_INCREF(func); - - return PyLong_FromLong((long) tdRegisterSensorEvent((TDSensorEvent) telldus_sensorEventCallback, &func)); + Py_XINCREF(func); + + SensorEventCallback = func; + + result = tdRegisterSensorEvent((TDSensorEvent) &telldus_sensorEventCallback, 0); + + return PyLong_FromLong((long) result); } static PyObject * @@ -496,7 +555,7 @@ telldus_tdUnregisterCallback(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "l", &id)); return NULL; - return PyBool_FromLong((long) tdUnregisterCallback(id)); + return PyLong_FromLong((long) tdUnregisterCallback(id)); } static PyObject * @@ -517,7 +576,7 @@ telldus_tdSensor(PyObject *self, PyObject *args) } else { - return PyBool_FromLong(result); + return PyLong_FromLong(result); } } @@ -560,7 +619,7 @@ telldus_tdSensorValue(PyObject *self, PyObject *args) } else { - return PyBool_FromLong(result); + return PyLong_FromLong(result); } } @@ -626,8 +685,6 @@ inittelldus(void) PyObject *TELLSTICK_HUMIDITY_GLUE; /* Create the module and add the functions */ - - PyEval_InitThreads(); module = Py_InitModule("telldus", telldus_methods); From c5c64435cf2fdd6c83bf62ddd704822439b5944b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Fri, 10 Aug 2012 20:37:16 +0200 Subject: [PATCH 2070/2215] working examples feature complete --- bindings/python/native/example/basic.py | 59 ++++++++++------------ bindings/python/native/example/callback.py | 12 +++-- bindings/python/native/example/poll.py | 46 ++++++++--------- bindings/python/native/telldus.c | 41 +++++---------- 4 files changed, 70 insertions(+), 88 deletions(-) diff --git a/bindings/python/native/example/basic.py b/bindings/python/native/example/basic.py index dd260231..ad5e37a0 100644 --- a/bindings/python/native/example/basic.py +++ b/bindings/python/native/example/basic.py @@ -10,41 +10,38 @@ allMethods = telldus.TELLSTICK_TURNON | telldus.TELLSTICK_TURNOFF | telldus.TELL for i in xrange(devices): deviceid = telldus.tdGetDeviceId(i) - name = telldus.tdGetName(deviceid) - - print "%s - %s\n" % (deviceid, name) - - methods = telldus.tdMethods(deviceid, allMethods) - - if methods & telldus.TELLSTICK_TURNON: - print " * TurnOn\n" - telldus.tdTurnOn(deviceid) - time.sleep(1) + + if deviceid: + name = telldus.tdGetName(deviceid) + + print "%s - %s\n" % (deviceid, name) - if methods & telldus.TELLSTICK_TURNOFF: - print " * TurnOff\n" - telldus.tdTurnOff(deviceid) - time.sleep(1) + methods = telldus.tdMethods(deviceid, allMethods) - if methods & telldus.TELLSTICK_BELL: - echo " * Bell\n" - telldus.tdBell(deviceid) - time.sleep(1) - - if methods & telldus.TELLSTICK_TOGGLE: - print " * Toggle\n" - - if methods & telldus.TELLSTICK_DIM: - print " * Dim\n" - telldus.tdDim(deviceid, 128) - time.sleep(1) + if methods & telldus.TELLSTICK_TURNON: + print " * TurnOn\n" + telldus.tdTurnOn(deviceid) + time.sleep(1) + + if methods & telldus.TELLSTICK_TURNOFF: + print " * TurnOff\n" + telldus.tdTurnOff(deviceid) + time.sleep(1) + + if methods & telldus.TELLSTICK_BELL: + print " * Bell\n" + telldus.tdBell(deviceid) + time.sleep(1) + + if methods & telldus.TELLSTICK_TOGGLE: + print " * Toggle\n" + + if methods & telldus.TELLSTICK_DIM: + print " * Dim\n" + telldus.tdDim(deviceid, 128) + time.sleep(1) telldus.tdClose() -import time -time.sleep(30) -for i in xrange(20): - telldus.tdTurnOn(3) - telldus.tdTurnOff(3) diff --git a/bindings/python/native/example/callback.py b/bindings/python/native/example/callback.py index 43774674..a6242a6f 100644 --- a/bindings/python/native/example/callback.py +++ b/bindings/python/native/example/callback.py @@ -2,10 +2,8 @@ import threading import telldus import time - telldus.tdInit() - def turnOn(): print "turning on" telldus.tdTurnOn(1) @@ -15,22 +13,26 @@ def turnOff(): telldus.tdTurnOff(1) def callback(deviceId, method, value, callbackId): - print "callback" + print "callback" + print "DeviceId: %i Method: %i Value: %s" % (deviceId, method, value) return True #function to be called when device event occurs, even for unregistered devices def rawcallback(data, controllerId, callbackId): print "raw callback" + print "Data: %s ControllerId: %i" % (data, controllerId) return True -#callbackid = telldus.tdRegisterDeviceEvent(callback) +callbackid = telldus.tdRegisterDeviceEvent(callback) rawcallbackid = telldus.tdRegisterRawDeviceEvent(rawcallback) +print callbackid, rawcallbackid + try: while(1): time.sleep(0.5) #don't exit except KeyboardInterrupt: print "Exiting" - #telldus.tdUnregisterCallback(callbackid) + telldus.tdUnregisterCallback(callbackid) telldus.tdUnregisterCallback(rawcallbackid) telldus.tdClose() diff --git a/bindings/python/native/example/poll.py b/bindings/python/native/example/poll.py index 7061b5a8..71cba2c6 100644 --- a/bindings/python/native/example/poll.py +++ b/bindings/python/native/example/poll.py @@ -2,27 +2,27 @@ import telldus telldus.tdInit() - while(1): - result = telldus.tdSensor() - if not result: - break - else: - protocol, model, sensorId = result - print "%s,\t%s,\t%i\n" % (protocol, model, sensorId) - - # Retrieve the values the sensor supports - if (dataTypes & telldus.TELLSTICK_TEMPERATURE): - result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_TEMPERATURE) - if result: - value, timestamp = result - print "Temperature:\t%sº\t(%s)\n" % (value, str(timestamp)) - - if (dataTypes & telldus.TELLSTICK_HUMIDITY): - result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_HUMIDITY) - if result: - value, timestamp = result - print "Humidity:\t%s\t(%s)\n" % (value, str(timestamp)) - - print "\n" +while True: + result = telldus.tdSensor() + if not result: + break + else: + protocol, model, sensorId, dataTypes = result + print "Protocol: %s,\tModel: %s,\tSensorId: %i\nDataTypes: %i" % (protocol, model, sensorId, dataTypes) -tdClose() + # Retrieve the values the sensor supports + if dataTypes & telldus.TELLSTICK_TEMPERATURE: + result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_TEMPERATURE) + if result: + value, timestamp = result + print "Temperature:\t%sC\t(%s)\n" % (value, str(timestamp)) + + if dataTypes & telldus.TELLSTICK_HUMIDITY: + result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_HUMIDITY) + if result: + value, timestamp = result + print "Humidity:\t%s\t(%s)\n" % (value, str(timestamp)) + + print "\n" + +telldus.tdClose() diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 68cd74b4..4570bbd3 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -31,9 +31,6 @@ estrdup(char *s) static PyObject * telldus_tdInit(PyObject *self) { - PyEval_InitThreads(); - PyEval_ReleaseLock(); - tdInit(); Py_INCREF(Py_None); return Py_None; @@ -157,10 +154,10 @@ static PyObject * telldus_tdGetDeviceId(PyObject *self, PyObject *args) { long index; - + if (!PyArg_ParseTuple(args, "l", &index)) return NULL; - + return PyLong_FromLong((long) tdGetDeviceId(index)); } @@ -386,7 +383,7 @@ telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) DeviceEventCallback = func; - tdRegisterDeviceEvent((TDDeviceEvent) &telldus_deviceEventCallback, 0); + result = tdRegisterDeviceEvent((TDDeviceEvent) &telldus_deviceEventCallback, 0); return PyLong_FromLong((long) result); } @@ -552,7 +549,7 @@ telldus_tdUnregisterCallback(PyObject *self, PyObject *args) { long id; - if (!PyArg_ParseTuple(args, "l", &id)); + if (!PyArg_ParseTuple(args, "l", &id)) return NULL; return PyLong_FromLong((long) tdUnregisterCallback(id)); @@ -568,15 +565,16 @@ telldus_tdSensor(PyObject *self, PyObject *args) long result; - result = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); - + result = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + if (result == TELLSTICK_SUCCESS) { return Py_BuildValue("ssll", protocol, model, sensorId, dataTypes); } else { - return PyLong_FromLong(result); + Py_INCREF(Py_None); + return Py_None; } } @@ -590,36 +588,21 @@ telldus_tdSensorValue(PyObject *self, PyObject *args) long dataType = 0; char value[DATA_LENGTH]; long timestamp = 0; - - PyObject *floatObj; - PyObject *timeTuple; - long result; - PyObject *py_date; - - if (!PyArg_ParseTuple(args, "ssll", &protocol, &model, &sensorId, &dataType)); + if (!PyArg_ParseTuple(args, "ssll", &protocol, &model, &sensorId, &dataType)) return NULL; result = tdSensorValue(protocol, model, sensorId, dataType, &value, DATA_LENGTH, ×tamp); - floatObj = PyFloat_FromDouble(timestamp); - timeTuple = Py_BuildValue("(O)", floatObj); - Py_DECREF(floatObj); - - py_date = PyDateTime_FromTimestamp(timeTuple); - - Py_DECREF(timeTuple); - - Py_INCREF(py_date); - if (result == TELLSTICK_SUCCESS) { - return Py_BuildValue("sO", value, py_date); + return Py_BuildValue("sl", value, timestamp); } else { - return PyLong_FromLong(result); + Py_INCREF(Py_None); + return Py_None; } } From 5cfd91717fc4ac0f196913cb2e2af693fad8024b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Fri, 10 Aug 2012 21:00:40 +0200 Subject: [PATCH 2071/2215] return a datetime on success --- bindings/python/native/example/poll.py | 2 +- bindings/python/native/telldus.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/bindings/python/native/example/poll.py b/bindings/python/native/example/poll.py index 71cba2c6..c8dcf618 100644 --- a/bindings/python/native/example/poll.py +++ b/bindings/python/native/example/poll.py @@ -16,7 +16,7 @@ while True: if result: value, timestamp = result print "Temperature:\t%sC\t(%s)\n" % (value, str(timestamp)) - + if dataTypes & telldus.TELLSTICK_HUMIDITY: result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_HUMIDITY) if result: diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 4570bbd3..060299da 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -590,14 +590,27 @@ telldus_tdSensorValue(PyObject *self, PyObject *args) long timestamp = 0; long result; + PyObject *floatObj = NULL; + PyObject *timeTuple = NULL; + PyObject *dateTime = NULL; + + if (!PyArg_ParseTuple(args, "ssll", &protocol, &model, &sensorId, &dataType)) return NULL; result = tdSensorValue(protocol, model, sensorId, dataType, &value, DATA_LENGTH, ×tamp); - + if (result == TELLSTICK_SUCCESS) { - return Py_BuildValue("sl", value, timestamp); + + floatObj = PyFloat_FromDouble((double) timestamp); + timeTuple = Py_BuildValue("(O)", floatObj); + dateTime = PyDateTime_FromTimestamp(timeTuple); + + Py_DECREF(floatObj); + Py_DECREF(timeTuple); + + return Py_BuildValue("sO", value, dateTime); } else { From c9588af3c37f16b607283b8eae383cf5d4e26cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Fri, 10 Aug 2012 21:41:31 +0200 Subject: [PATCH 2072/2215] make sure errorcodes are returned --- bindings/python/native/example/poll.py | 6 +++--- bindings/python/native/telldus.c | 15 +++++---------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/bindings/python/native/example/poll.py b/bindings/python/native/example/poll.py index c8dcf618..088882c2 100644 --- a/bindings/python/native/example/poll.py +++ b/bindings/python/native/example/poll.py @@ -4,7 +4,7 @@ telldus.tdInit() while True: result = telldus.tdSensor() - if not result: + if not isinstance(result, tuple): break else: protocol, model, sensorId, dataTypes = result @@ -13,13 +13,13 @@ while True: # Retrieve the values the sensor supports if dataTypes & telldus.TELLSTICK_TEMPERATURE: result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_TEMPERATURE) - if result: + if isinstance(result, tuple): value, timestamp = result print "Temperature:\t%sC\t(%s)\n" % (value, str(timestamp)) if dataTypes & telldus.TELLSTICK_HUMIDITY: result = telldus.tdSensorValue(protocol, model, sensorId, telldus.TELLSTICK_HUMIDITY) - if result: + if isinstance(result, tuple): value, timestamp = result print "Humidity:\t%s\t(%s)\n" % (value, str(timestamp)) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 060299da..5ffc530b 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -31,17 +31,14 @@ estrdup(char *s) static PyObject * telldus_tdInit(PyObject *self) { - tdInit(); - Py_INCREF(Py_None); - return Py_None; + return PyLong_FromLong(tdInit()); } static PyObject * telldus_tdClose(PyObject *self) { - tdClose(); - Py_INCREF(Py_None); - return Py_None; + return PyLong_FromLong(tdClose();) + } static PyObject * @@ -573,8 +570,7 @@ telldus_tdSensor(PyObject *self, PyObject *args) } else { - Py_INCREF(Py_None); - return Py_None; + return PyLong_FromLong(result); } } @@ -614,8 +610,7 @@ telldus_tdSensorValue(PyObject *self, PyObject *args) } else { - Py_INCREF(Py_None); - return Py_None; + return PyLong_FromLong(result); } } From d808478ab10c62990b9189981ac4a2d87d330a97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Fri, 10 Aug 2012 23:46:39 +0200 Subject: [PATCH 2073/2215] keep track of python function so we can decref it --- bindings/python/native/telldus.c | 108 ++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 8 deletions(-) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 5ffc530b..017e7883 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -15,6 +15,80 @@ * (Generally, the routine error is not expected to return, * but if it does, estrdup will return NULL.) */ + +int callbackLen = 0; + +typedef struct { + PyObject *func; + int callbackId; +} callbackInfo; + +static callbackInfo callbackList[20]; + +void +addCallback(PyObject *func, int callbackId) +{ + if (callbackLen < 20) { + callbackList[callbackLen].func = func; + callbackList[callbackLen].callbackId = callbackId; + callbackLen++; + } +} + +void +removeCallback(int callbackId) +{ + int index = -1; + + int i; + int j; + + for (i = 0; i < callbackLen; i++) + { + if (callbackList[i].callbackId == callbackId) + { + index = i; + } + } + if (!(index == -1)) { + for (j = index; j < callbackLen; j++) + { + callbackList[j] = callbackList[j+1]; + } + callbackLen--; + } +} + +int +hasCallback(int callbackId) +{ + int i; + + for (i = 0; i < callbackLen; i++) + { + if (callbackList[i].callbackId == callbackId) + { + return 1; + } + } + return 0; + +} + +PyObject * +getCallback(int callbackId) +{ + int i; + + for (i = 0; i < callbackLen; i++) + { + if (callbackList[i].callbackId == callbackId) + { + return callbackList[i].func; + } + } + +} char * estrdup(char *s) @@ -31,14 +105,17 @@ estrdup(char *s) static PyObject * telldus_tdInit(PyObject *self) { - return PyLong_FromLong(tdInit()); + tdInit(); + Py_INCREF(Py_None); + return Py_None; } static PyObject * telldus_tdClose(PyObject *self) { - return PyLong_FromLong(tdClose();) - + tdClose(); + Py_INCREF(Py_None); + return Py_None; } static PyObject * @@ -151,7 +228,7 @@ static PyObject * telldus_tdGetDeviceId(PyObject *self, PyObject *args) { long index; - + if (!PyArg_ParseTuple(args, "l", &index)) return NULL; @@ -382,6 +459,8 @@ telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) result = tdRegisterDeviceEvent((TDDeviceEvent) &telldus_deviceEventCallback, 0); + addCallback(func, result); + return PyLong_FromLong((long) result); } @@ -433,7 +512,9 @@ telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) DeviceChangeEventCallback = func; result = tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) &telldus_deviceChangeEventCallback, 0); - + + addCallback(func, result); + return PyLong_FromLong((long) result); } @@ -485,7 +566,9 @@ telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) RawDeviceEventCallback = func; result = tdRegisterRawDeviceEvent((TDRawDeviceEvent) &telldus_rawDeviceEventCallback, 0); - + + addCallback(func, result); + return PyLong_FromLong((long) result); } @@ -537,6 +620,8 @@ telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) SensorEventCallback = func; result = tdRegisterSensorEvent((TDSensorEvent) &telldus_sensorEventCallback, 0); + + addCallback(func, result); return PyLong_FromLong((long) result); } @@ -545,10 +630,17 @@ static PyObject * telldus_tdUnregisterCallback(PyObject *self, PyObject *args) { long id; - + PyObject *callback; + if (!PyArg_ParseTuple(args, "l", &id)) return NULL; - + + if (hasCallback(id) == 1) { + callback = getCallback(id); + Py_DECREF(callback); + removeCallback(id); + } + return PyLong_FromLong((long) tdUnregisterCallback(id)); } From 5d2a3a3f7c4b99ef38d626f6ef023aa1aef457b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Fri, 10 Aug 2012 23:48:42 +0200 Subject: [PATCH 2074/2215] use tabs --- bindings/python/native/telldus.c | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 017e7883..e559cc7a 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -4,18 +4,18 @@ #include /* estrdup.c -- duplicate a string, die if error - * - * char *string; - * char *newstring; - * newstring = estrdup(string); - * - * estrdup returns a copy of its argument, located in memory - * allocated from the heap. If it is unable to allocate the - * necessary memory, estrdup executes PyErr_NoMemory(); - * (Generally, the routine error is not expected to return, - * but if it does, estrdup will return NULL.) - */ - + * + * char *string; + * char *newstring; + * newstring = estrdup(string); + * + * estrdup returns a copy of its argument, located in memory + * allocated from the heap. If it is unable to allocate the + * necessary memory, estrdup executes PyErr_NoMemory(); + * (Generally, the routine error is not expected to return, + * but if it does, estrdup will return NULL.) +*/ + int callbackLen = 0; typedef struct { @@ -459,7 +459,7 @@ telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) result = tdRegisterDeviceEvent((TDDeviceEvent) &telldus_deviceEventCallback, 0); - addCallback(func, result); + addCallback(func, result); return PyLong_FromLong((long) result); } @@ -513,7 +513,7 @@ telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) result = tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) &telldus_deviceChangeEventCallback, 0); - addCallback(func, result); + addCallback(func, result); return PyLong_FromLong((long) result); } @@ -567,7 +567,7 @@ telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) result = tdRegisterRawDeviceEvent((TDRawDeviceEvent) &telldus_rawDeviceEventCallback, 0); - addCallback(func, result); + addCallback(func, result); return PyLong_FromLong((long) result); } @@ -621,7 +621,7 @@ telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) result = tdRegisterSensorEvent((TDSensorEvent) &telldus_sensorEventCallback, 0); - addCallback(func, result); + addCallback(func, result); return PyLong_FromLong((long) result); } @@ -631,11 +631,11 @@ telldus_tdUnregisterCallback(PyObject *self, PyObject *args) { long id; PyObject *callback; - + if (!PyArg_ParseTuple(args, "l", &id)) return NULL; - if (hasCallback(id) == 1) { + if (hasCallback(id) == 1) { callback = getCallback(id); Py_DECREF(callback); removeCallback(id); From 420d33b09d07625663411b8d7f1f436fd7fe1ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 11 Aug 2012 16:20:23 +0200 Subject: [PATCH 2075/2215] don't go off the far end --- bindings/python/native/telldus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index e559cc7a..05be0337 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -51,7 +51,7 @@ removeCallback(int callbackId) } } if (!(index == -1)) { - for (j = index; j < callbackLen; j++) + for (j = index; j < callbackLen - 1; j++) { callbackList[j] = callbackList[j+1]; } From d9ac1d3638c438dd01895b9d14e163faded722b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 11 Aug 2012 18:11:23 +0200 Subject: [PATCH 2076/2215] two less warnings --- bindings/python/native/telldus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 05be0337..7acf9727 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -87,7 +87,7 @@ getCallback(int callbackId) return callbackList[i].func; } } - + return NULL; } char * @@ -96,7 +96,8 @@ estrdup(char *s) register char *t; if (NULL == (t = malloc(strlen(s)+1))) { - return PyErr_NoMemory(); + PyErr_NoMemory(); + return NULL; } strcpy(t, s); return(t); From 4065f7dc406c70a05b68233dc0cb06c37190291e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Saltvik?= Date: Sat, 11 Aug 2012 18:17:03 +0200 Subject: [PATCH 2077/2215] no complier warnings --- bindings/python/native/setup.py | 2 +- bindings/python/native/telldus.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/python/native/setup.py b/bindings/python/native/setup.py index f130b2c2..e0413c13 100644 --- a/bindings/python/native/setup.py +++ b/bindings/python/native/setup.py @@ -323,7 +323,7 @@ else: libraries = ['telldus-core'] define_macros = [] -define_macros.extend([('DATA_LENGTH', 20)]) +define_macros.extend([('DATA_LENGTH', 20), ('CALLBACK_LENGTH', 20)]) telldus = Extension( 'telldus', diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 7acf9727..8459be3f 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -23,12 +23,12 @@ typedef struct { int callbackId; } callbackInfo; -static callbackInfo callbackList[20]; +static callbackInfo callbackList[CALLBACK_LENGTH]; void addCallback(PyObject *func, int callbackId) { - if (callbackLen < 20) { + if (callbackLen < CALLBACK_LENGTH) { callbackList[callbackLen].func = func; callbackList[callbackLen].callbackId = callbackId; callbackLen++; @@ -687,7 +687,7 @@ telldus_tdSensorValue(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ssll", &protocol, &model, &sensorId, &dataType)) return NULL; - result = tdSensorValue(protocol, model, sensorId, dataType, &value, DATA_LENGTH, ×tamp); + result = tdSensorValue(protocol, model, sensorId, dataType, value, DATA_LENGTH, ×tamp); if (result == TELLSTICK_SUCCESS) { From 4ff3cfd56cf06930b62eeaf4ebec910b90551ac6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 13 Aug 2012 16:45:35 +0200 Subject: [PATCH 2078/2215] Convert CRLF to LF --- bindings/python/native/MANIFEST.in | 6 +- bindings/python/native/example/basic.py | 94 +- bindings/python/native/example/callback.py | 76 +- bindings/python/native/setup.py | 690 ++++---- bindings/python/native/telldus.c | 1686 ++++++++++---------- 5 files changed, 1276 insertions(+), 1276 deletions(-) diff --git a/bindings/python/native/MANIFEST.in b/bindings/python/native/MANIFEST.in index de92c867..9a264a7a 100644 --- a/bindings/python/native/MANIFEST.in +++ b/bindings/python/native/MANIFEST.in @@ -1,3 +1,3 @@ -include telldus.c -include telldus-core.h -recursive-include example/* +include telldus.c +include telldus-core.h +recursive-include example/* diff --git a/bindings/python/native/example/basic.py b/bindings/python/native/example/basic.py index ad5e37a0..f8fef675 100644 --- a/bindings/python/native/example/basic.py +++ b/bindings/python/native/example/basic.py @@ -1,47 +1,47 @@ - -import telldus -import time - -telldus.tdInit() -devices = telldus.tdGetNumberOfDevices() -print "Devices: %d\n" % devices - -allMethods = telldus.TELLSTICK_TURNON | telldus.TELLSTICK_TURNOFF | telldus.TELLSTICK_BELL | telldus.TELLSTICK_DIM - -for i in xrange(devices): - deviceid = telldus.tdGetDeviceId(i) - - if deviceid: - name = telldus.tdGetName(deviceid) - - print "%s - %s\n" % (deviceid, name) - - methods = telldus.tdMethods(deviceid, allMethods) - - if methods & telldus.TELLSTICK_TURNON: - print " * TurnOn\n" - telldus.tdTurnOn(deviceid) - time.sleep(1) - - if methods & telldus.TELLSTICK_TURNOFF: - print " * TurnOff\n" - telldus.tdTurnOff(deviceid) - time.sleep(1) - - if methods & telldus.TELLSTICK_BELL: - print " * Bell\n" - telldus.tdBell(deviceid) - time.sleep(1) - - if methods & telldus.TELLSTICK_TOGGLE: - print " * Toggle\n" - - if methods & telldus.TELLSTICK_DIM: - print " * Dim\n" - telldus.tdDim(deviceid, 128) - time.sleep(1) - -telldus.tdClose() - - - + +import telldus +import time + +telldus.tdInit() +devices = telldus.tdGetNumberOfDevices() +print "Devices: %d\n" % devices + +allMethods = telldus.TELLSTICK_TURNON | telldus.TELLSTICK_TURNOFF | telldus.TELLSTICK_BELL | telldus.TELLSTICK_DIM + +for i in xrange(devices): + deviceid = telldus.tdGetDeviceId(i) + + if deviceid: + name = telldus.tdGetName(deviceid) + + print "%s - %s\n" % (deviceid, name) + + methods = telldus.tdMethods(deviceid, allMethods) + + if methods & telldus.TELLSTICK_TURNON: + print " * TurnOn\n" + telldus.tdTurnOn(deviceid) + time.sleep(1) + + if methods & telldus.TELLSTICK_TURNOFF: + print " * TurnOff\n" + telldus.tdTurnOff(deviceid) + time.sleep(1) + + if methods & telldus.TELLSTICK_BELL: + print " * Bell\n" + telldus.tdBell(deviceid) + time.sleep(1) + + if methods & telldus.TELLSTICK_TOGGLE: + print " * Toggle\n" + + if methods & telldus.TELLSTICK_DIM: + print " * Dim\n" + telldus.tdDim(deviceid, 128) + time.sleep(1) + +telldus.tdClose() + + + diff --git a/bindings/python/native/example/callback.py b/bindings/python/native/example/callback.py index a6242a6f..ca5f6b8d 100644 --- a/bindings/python/native/example/callback.py +++ b/bindings/python/native/example/callback.py @@ -1,38 +1,38 @@ -import threading -import telldus -import time - -telldus.tdInit() - -def turnOn(): - print "turning on" - telldus.tdTurnOn(1) - -def turnOff(): - print "turning off" - telldus.tdTurnOff(1) - -def callback(deviceId, method, value, callbackId): - print "callback" - print "DeviceId: %i Method: %i Value: %s" % (deviceId, method, value) - return True - -#function to be called when device event occurs, even for unregistered devices -def rawcallback(data, controllerId, callbackId): - print "raw callback" - print "Data: %s ControllerId: %i" % (data, controllerId) - return True - -callbackid = telldus.tdRegisterDeviceEvent(callback) -rawcallbackid = telldus.tdRegisterRawDeviceEvent(rawcallback) - -print callbackid, rawcallbackid - -try: - while(1): - time.sleep(0.5) #don't exit -except KeyboardInterrupt: - print "Exiting" - telldus.tdUnregisterCallback(callbackid) - telldus.tdUnregisterCallback(rawcallbackid) - telldus.tdClose() +import threading +import telldus +import time + +telldus.tdInit() + +def turnOn(): + print "turning on" + telldus.tdTurnOn(1) + +def turnOff(): + print "turning off" + telldus.tdTurnOff(1) + +def callback(deviceId, method, value, callbackId): + print "callback" + print "DeviceId: %i Method: %i Value: %s" % (deviceId, method, value) + return True + +#function to be called when device event occurs, even for unregistered devices +def rawcallback(data, controllerId, callbackId): + print "raw callback" + print "Data: %s ControllerId: %i" % (data, controllerId) + return True + +callbackid = telldus.tdRegisterDeviceEvent(callback) +rawcallbackid = telldus.tdRegisterRawDeviceEvent(rawcallback) + +print callbackid, rawcallbackid + +try: + while(1): + time.sleep(0.5) #don't exit +except KeyboardInterrupt: + print "Exiting" + telldus.tdUnregisterCallback(callbackid) + telldus.tdUnregisterCallback(rawcallbackid) + telldus.tdClose() diff --git a/bindings/python/native/setup.py b/bindings/python/native/setup.py index e0413c13..19e0c7fa 100644 --- a/bindings/python/native/setup.py +++ b/bindings/python/native/setup.py @@ -1,345 +1,345 @@ -import sys -from distutils.core import setup, Extension - -DEBUG = True - -PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win') - -if PLATFORM_IS_WINDOWS: - - __doc__="""This is a distutils setup-script for the telldus extension - - To build the telldus extensions, simply execute: - python setup.py -q build - or - python setup.py -q install - to build and install into your current Python installation. - - These extensions require a number of libraries to build, some of which may - require you to install special SDKs or toolkits. This script will attempt - to build as many as it can, and at the end of the build will report any - extension modules that could not be built and why. - - This has got complicated due to the various different versions of - Visual Studio used - some VS versions are not compatible with some SDK - versions. Below are the Windows SDK versions required (and the URL - although - these are subject to being changed by MS at any time:) - - Python 2.6+: - - Build using Microsoft Visual Studio 2008 Express Edition: - http://www.microsoft.com/en-us/download/details.aspx?id=6506 - http://jenshuebel.wordpress.com/2009/02/12/visual-c-2008-express-edition-and-64-bit-targets/ - http://www.cppblog.com/Files/xcpp/VCE64BIT_WIN7SDK.zip - - For 32bit build: - Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 - http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b - Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat to - C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat - - For 64bit build: - Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO) GRMSDKX_EN_DVD.iso - http://www.microsoft.com/en-us/download/details.aspx?id=18950 - Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars64.bat to - C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat - - Python 2.3->2.5: - - Microsoft Windows Software Development Kit Update for Windows Vista (version 6.0) - http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4377f86d-c913-4b5c-b87e-ef72e5b4e065 - ** If you want to build Python 2.3, be sure to install the SDK compilers - too - although we don't use them, this setup option installs some .lib - files we do need. - ** - - If you multiple SDK versions on a single machine, set the MSSDK environment - variable to point at the one you want to use. Note that using the SDK for - a particular platform (eg, Windows 7) doesn't force you to use that OS as your - build environment. If the links above don't work, use google to find them. - - Building: - --------- - - To install the telldus extension, execute: - python setup.py -q install - - This will install the built extensions into your site-packages directory, - create an appropriate .pth file, and should leave everything ready to use. - There is no need to modify the registry. - - To build or install debug (_d) versions of these extensions, ensure you have - built or installed a debug version of Python itself, then pass the "--debug" - flag to the build command - eg: - python setup.py -q build --debug - or to build and install a debug version: - python setup.py -q build --debug install - - To build 64bit versions of this: - - * py2.5 and earlier - sorry, I've given up in disgust. Using VS2003 with - the Vista SDK is just too painful to make work, and VS2005 is not used for - any released versions of Python. See revision 1.69 of this file for the - last version that attempted to support and document this process. - - * 2.6 and later: On a 64bit OS, just build as you would on a 32bit platform. - On a 32bit platform (ie, to cross-compile), you must use VS2008 to - cross-compile Python itself. Note that by default, the 64bit tools are not - installed with VS2008, so you may need to adjust your VS2008 setup (see "For 64bit build"). Then - use: - vcs - setup.py build --plat-name=win-amd64 - - see the distutils cross-compilation documentation for more details. - """ - # Originally by Thomas Heller, started in 2000 or so. - import os - import shutil - - is_py3k = sys.version_info > (3,) # get this out of the way early on... - # We have special handling for _winreg so our setup3.py script can avoid - # using the 'imports' fixer and therefore start much faster... - if is_py3k: - import winreg as _winreg - else: - import _winreg - - try: - from distutils import log - except ImportError: - class Log: - def debug(self, msg, *args): - print msg % args - def info(self, msg, *args): - print msg % args - log = Log() - - try: - this_file = __file__ - except NameError: - this_file = sys.argv[0] - - this_file = os.path.abspath(this_file) - # We get upset if the cwd is not our source dir, but it is a PITA to - # insist people manually CD there first! - if os.path.dirname(this_file): - os.chdir(os.path.dirname(this_file)) - - - # We need to know the platform SDK dir before we can list the extensions. - def find_platform_sdk_dir(): - # Finding the Platform SDK install dir is a treat. There can be some - # dead ends so we only consider the job done if we find the "windows.h" - # landmark. - landmark = "include\\windows.h" - # 1. The use might have their current environment setup for the - # SDK, in which case the "MSSdk" env var is set. - sdkdir = os.environ.get("MSSdk") - if sdkdir: - if DEBUG: - print "PSDK: try %%MSSdk%%: '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - # 2. The "Install Dir" value in the - # HKLM\Software\Microsoft\MicrosoftSDK\Directories registry key - # sometimes points to the right thing. However, after upgrading to - # the "Platform SDK for Windows Server 2003 SP1" this is dead end. - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\MicrosoftSDK\Directories") - sdkdir, ignore = _winreg.QueryValueEx(key, "Install Dir") - except EnvironmentError: - pass - else: - if DEBUG: - print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ - "\Directories\Install Dir': '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - # 3. Each installed SDK (not just the platform SDK) seems to have GUID - # subkey of HKLM\Software\Microsoft\MicrosoftSDK\InstalledSDKs and - # it *looks* like the latest installed Platform SDK will be the - # only one with an "Install Dir" sub-value. - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\MicrosoftSDK\InstalledSDKs") - i = 0 - while True: - guid = _winreg.EnumKey(key, i) - guidkey = _winreg.OpenKey(key, guid) - try: - sdkdir, ignore = _winreg.QueryValueEx(guidkey, "Install Dir") - except EnvironmentError: - pass - else: - if DEBUG: - print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ - "\InstallSDKs\%s\Install Dir': '%s'"\ - % (guid, sdkdir) - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - i += 1 - except EnvironmentError: - pass - # 4. Vista's SDK - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\Microsoft SDKs\Windows") - sdkdir, ignore = _winreg.QueryValueEx(key, "CurrentInstallFolder") - except EnvironmentError: - pass - else: - if DEBUG: - print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDKs"\ - "\Windows\CurrentInstallFolder': '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - - # 5. Failing this just try a few well-known default install locations. - progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") - defaultlocs = [ - os.path.join(progfiles, "Microsoft Platform SDK"), - os.path.join(progfiles, "Microsoft SDK"), - ] - for sdkdir in defaultlocs: - if DEBUG: - print "PSDK: try default location: '%s'" % sdkdir - if os.path.isfile(os.path.join(sdkdir, landmark)): - return sdkdir - - - # Some nasty hacks to prevent most of our extensions using a manifest, as - # the manifest - even without a reference to the CRT assembly - is enough - # to prevent the extension from loading. For more details, see - # http://bugs.python.org/issue7833 - that issue has a patch, but it is - # languishing and will probably never be fixed for Python 2.6... - if sys.version_info > (2,6): - from distutils.spawn import spawn - from distutils.msvc9compiler import MSVCCompiler - MSVCCompiler._orig_spawn = MSVCCompiler.spawn - MSVCCompiler._orig_link = MSVCCompiler.link - - # We need to override this method for versions where issue7833 *has* landed - # (ie, 2.7 and 3.2+) - def manifest_get_embed_info(self, target_desc, ld_args): - _want_assembly_kept = getattr(self, '_want_assembly_kept', False) - if not _want_assembly_kept: - return None - for arg in ld_args: - if arg.startswith("/MANIFESTFILE:"): - orig_manifest = arg.split(":", 1)[1] - if target_desc==self.EXECUTABLE: - rid = 1 - else: - rid = 2 - return orig_manifest, rid - return None - # always monkeypatch it in even though it will only be called in 2.7 - # and 3.2+. - MSVCCompiler.manifest_get_embed_info = manifest_get_embed_info - - def monkeypatched_spawn(self, cmd): - is_link = cmd[0].endswith("link.exe") or cmd[0].endswith('"link.exe"') - is_mt = cmd[0].endswith("mt.exe") or cmd[0].endswith('"mt.exe"') - _want_assembly_kept = getattr(self, '_want_assembly_kept', False) - if not _want_assembly_kept and is_mt: - # We don't want mt.exe run... - return - if not _want_assembly_kept and is_link: - # remove /MANIFESTFILE:... and add MANIFEST:NO - # (but note that for winxpgui, which specifies a manifest via a - # .rc file, this is ignored by the linker - the manifest specified - # in the .rc file is still added) - for i in range(len(cmd)): - if cmd[i].startswith("/MANIFESTFILE:"): - cmd[i] = "/MANIFEST:NO" - break - if _want_assembly_kept and is_mt: - # We want mt.exe run with the original manifest - for i in range(len(cmd)): - if cmd[i] == "-manifest": - cmd[i+1] = cmd[i+1] + ".orig" - break - self._orig_spawn(cmd) - if _want_assembly_kept and is_link: - # We want a copy of the original manifest so we can use it later. - for i in range(len(cmd)): - if cmd[i].startswith("/MANIFESTFILE:"): - mfname = cmd[i][14:] - shutil.copyfile(mfname, mfname + ".orig") - break - - def monkeypatched_link(self, target_desc, objects, output_filename, *args, **kw): - # no manifests for 3.3+ - self._want_assembly_kept = sys.version_info < (3,3) and \ - (os.path.basename(output_filename).startswith("PyISAPI_loader.dll") or \ - os.path.basename(output_filename).startswith("perfmondata.dll") or \ - os.path.basename(output_filename).startswith("win32ui.pyd") or \ - target_desc==self.EXECUTABLE) - try: - return self._orig_link(target_desc, objects, output_filename, *args, **kw) - finally: - delattr(self, '_want_assembly_kept') - MSVCCompiler.spawn = monkeypatched_spawn - MSVCCompiler.link = monkeypatched_link - - def find_telldus_dev_dir(): - landmark = "telldus-core.h" - dev_dir = os.environ.get("TELLDUS_DEVDIR") - if dev_dir: - if DEBUG: - print "Telldus dev dir:" % dev_dir - if os.path.isfile(os.path.join(dev_dir, landmark)): - return dev_dir - - progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") - defaultlocs = [ - os.path.join(progfiles + ' (x86)', "Telldus", "Development"), - os.path.join(progfiles, "Telldus", "Development"), - ] - for dev_dir in defaultlocs: - if DEBUG: - print "Telldus dev dir: '%s'" % dev_dir - if os.path.isfile(os.path.join(dev_dir, landmark)): - return dev_dir - if DEBUG: - print "Telldus dev dir not found, make sure dev code is installed. Or set TELLDUS_DEVDIR." - - sdk_dir = find_platform_sdk_dir() - sdk_include_dir = os.path.join(sdk_dir, 'Include') - - telldus_dev_dir = find_telldus_dev_dir() - telldus_platform = os.environ.get("TELLDUS_PLATFORM", 'x86_64') - telldus_library_dir = os.path.join(telldus_dev_dir, telldus_platform) - - include_dirs = [sdk_include_dir, telldus_dev_dir] - library_dirs = [telldus_library_dir] - libraries = ['python%i%i' % (sys.version_info[0], sys.version_info[1]) , 'TelldusCore'] - define_macros = [('_WINDOWS', 1)] - -else: - include_dirs = ['/usr/include', '/usr/local/include'] - library_dirs = ['/usr/lib', '/usr/local/lib'] - libraries = ['telldus-core'] - define_macros = [] - -define_macros.extend([('DATA_LENGTH', 20), ('CALLBACK_LENGTH', 20)]) - -telldus = Extension( - 'telldus', - include_dirs = include_dirs, - libraries = libraries, - library_dirs = library_dirs, - define_macros = define_macros, - sources = ['telldus.c'] -) - -setup( - name = 'telldus', - version = '1.0', - description = 'Python bindings for telldus', - author='Oyvind Saltvik', - author_email='oyvind.saltvik@gmail.com', - url='http://github.com/fivethreeo/telldus/', - ext_modules = [telldus] -) +import sys +from distutils.core import setup, Extension + +DEBUG = True + +PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win') + +if PLATFORM_IS_WINDOWS: + + __doc__="""This is a distutils setup-script for the telldus extension + + To build the telldus extensions, simply execute: + python setup.py -q build + or + python setup.py -q install + to build and install into your current Python installation. + + These extensions require a number of libraries to build, some of which may + require you to install special SDKs or toolkits. This script will attempt + to build as many as it can, and at the end of the build will report any + extension modules that could not be built and why. + + This has got complicated due to the various different versions of + Visual Studio used - some VS versions are not compatible with some SDK + versions. Below are the Windows SDK versions required (and the URL - although + these are subject to being changed by MS at any time:) + + Python 2.6+: + + Build using Microsoft Visual Studio 2008 Express Edition: + http://www.microsoft.com/en-us/download/details.aspx?id=6506 + http://jenshuebel.wordpress.com/2009/02/12/visual-c-2008-express-edition-and-64-bit-targets/ + http://www.cppblog.com/Files/xcpp/VCE64BIT_WIN7SDK.zip + + For 32bit build: + Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 + http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b + Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat to + C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat + + For 64bit build: + Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO) GRMSDKX_EN_DVD.iso + http://www.microsoft.com/en-us/download/details.aspx?id=18950 + Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars64.bat to + C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat + + Python 2.3->2.5: + + Microsoft Windows Software Development Kit Update for Windows Vista (version 6.0) + http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4377f86d-c913-4b5c-b87e-ef72e5b4e065 + ** If you want to build Python 2.3, be sure to install the SDK compilers + too - although we don't use them, this setup option installs some .lib + files we do need. + ** + + If you multiple SDK versions on a single machine, set the MSSDK environment + variable to point at the one you want to use. Note that using the SDK for + a particular platform (eg, Windows 7) doesn't force you to use that OS as your + build environment. If the links above don't work, use google to find them. + + Building: + --------- + + To install the telldus extension, execute: + python setup.py -q install + + This will install the built extensions into your site-packages directory, + create an appropriate .pth file, and should leave everything ready to use. + There is no need to modify the registry. + + To build or install debug (_d) versions of these extensions, ensure you have + built or installed a debug version of Python itself, then pass the "--debug" + flag to the build command - eg: + python setup.py -q build --debug + or to build and install a debug version: + python setup.py -q build --debug install + + To build 64bit versions of this: + + * py2.5 and earlier - sorry, I've given up in disgust. Using VS2003 with + the Vista SDK is just too painful to make work, and VS2005 is not used for + any released versions of Python. See revision 1.69 of this file for the + last version that attempted to support and document this process. + + * 2.6 and later: On a 64bit OS, just build as you would on a 32bit platform. + On a 32bit platform (ie, to cross-compile), you must use VS2008 to + cross-compile Python itself. Note that by default, the 64bit tools are not + installed with VS2008, so you may need to adjust your VS2008 setup (see "For 64bit build"). Then + use: + vcs + setup.py build --plat-name=win-amd64 + + see the distutils cross-compilation documentation for more details. + """ + # Originally by Thomas Heller, started in 2000 or so. + import os + import shutil + + is_py3k = sys.version_info > (3,) # get this out of the way early on... + # We have special handling for _winreg so our setup3.py script can avoid + # using the 'imports' fixer and therefore start much faster... + if is_py3k: + import winreg as _winreg + else: + import _winreg + + try: + from distutils import log + except ImportError: + class Log: + def debug(self, msg, *args): + print msg % args + def info(self, msg, *args): + print msg % args + log = Log() + + try: + this_file = __file__ + except NameError: + this_file = sys.argv[0] + + this_file = os.path.abspath(this_file) + # We get upset if the cwd is not our source dir, but it is a PITA to + # insist people manually CD there first! + if os.path.dirname(this_file): + os.chdir(os.path.dirname(this_file)) + + + # We need to know the platform SDK dir before we can list the extensions. + def find_platform_sdk_dir(): + # Finding the Platform SDK install dir is a treat. There can be some + # dead ends so we only consider the job done if we find the "windows.h" + # landmark. + landmark = "include\\windows.h" + # 1. The use might have their current environment setup for the + # SDK, in which case the "MSSdk" env var is set. + sdkdir = os.environ.get("MSSdk") + if sdkdir: + if DEBUG: + print "PSDK: try %%MSSdk%%: '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + # 2. The "Install Dir" value in the + # HKLM\Software\Microsoft\MicrosoftSDK\Directories registry key + # sometimes points to the right thing. However, after upgrading to + # the "Platform SDK for Windows Server 2003 SP1" this is dead end. + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\MicrosoftSDK\Directories") + sdkdir, ignore = _winreg.QueryValueEx(key, "Install Dir") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ + "\Directories\Install Dir': '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + # 3. Each installed SDK (not just the platform SDK) seems to have GUID + # subkey of HKLM\Software\Microsoft\MicrosoftSDK\InstalledSDKs and + # it *looks* like the latest installed Platform SDK will be the + # only one with an "Install Dir" sub-value. + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\MicrosoftSDK\InstalledSDKs") + i = 0 + while True: + guid = _winreg.EnumKey(key, i) + guidkey = _winreg.OpenKey(key, guid) + try: + sdkdir, ignore = _winreg.QueryValueEx(guidkey, "Install Dir") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\ + "\InstallSDKs\%s\Install Dir': '%s'"\ + % (guid, sdkdir) + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + i += 1 + except EnvironmentError: + pass + # 4. Vista's SDK + try: + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r"Software\Microsoft\Microsoft SDKs\Windows") + sdkdir, ignore = _winreg.QueryValueEx(key, "CurrentInstallFolder") + except EnvironmentError: + pass + else: + if DEBUG: + print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDKs"\ + "\Windows\CurrentInstallFolder': '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + + # 5. Failing this just try a few well-known default install locations. + progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") + defaultlocs = [ + os.path.join(progfiles, "Microsoft Platform SDK"), + os.path.join(progfiles, "Microsoft SDK"), + ] + for sdkdir in defaultlocs: + if DEBUG: + print "PSDK: try default location: '%s'" % sdkdir + if os.path.isfile(os.path.join(sdkdir, landmark)): + return sdkdir + + + # Some nasty hacks to prevent most of our extensions using a manifest, as + # the manifest - even without a reference to the CRT assembly - is enough + # to prevent the extension from loading. For more details, see + # http://bugs.python.org/issue7833 - that issue has a patch, but it is + # languishing and will probably never be fixed for Python 2.6... + if sys.version_info > (2,6): + from distutils.spawn import spawn + from distutils.msvc9compiler import MSVCCompiler + MSVCCompiler._orig_spawn = MSVCCompiler.spawn + MSVCCompiler._orig_link = MSVCCompiler.link + + # We need to override this method for versions where issue7833 *has* landed + # (ie, 2.7 and 3.2+) + def manifest_get_embed_info(self, target_desc, ld_args): + _want_assembly_kept = getattr(self, '_want_assembly_kept', False) + if not _want_assembly_kept: + return None + for arg in ld_args: + if arg.startswith("/MANIFESTFILE:"): + orig_manifest = arg.split(":", 1)[1] + if target_desc==self.EXECUTABLE: + rid = 1 + else: + rid = 2 + return orig_manifest, rid + return None + # always monkeypatch it in even though it will only be called in 2.7 + # and 3.2+. + MSVCCompiler.manifest_get_embed_info = manifest_get_embed_info + + def monkeypatched_spawn(self, cmd): + is_link = cmd[0].endswith("link.exe") or cmd[0].endswith('"link.exe"') + is_mt = cmd[0].endswith("mt.exe") or cmd[0].endswith('"mt.exe"') + _want_assembly_kept = getattr(self, '_want_assembly_kept', False) + if not _want_assembly_kept and is_mt: + # We don't want mt.exe run... + return + if not _want_assembly_kept and is_link: + # remove /MANIFESTFILE:... and add MANIFEST:NO + # (but note that for winxpgui, which specifies a manifest via a + # .rc file, this is ignored by the linker - the manifest specified + # in the .rc file is still added) + for i in range(len(cmd)): + if cmd[i].startswith("/MANIFESTFILE:"): + cmd[i] = "/MANIFEST:NO" + break + if _want_assembly_kept and is_mt: + # We want mt.exe run with the original manifest + for i in range(len(cmd)): + if cmd[i] == "-manifest": + cmd[i+1] = cmd[i+1] + ".orig" + break + self._orig_spawn(cmd) + if _want_assembly_kept and is_link: + # We want a copy of the original manifest so we can use it later. + for i in range(len(cmd)): + if cmd[i].startswith("/MANIFESTFILE:"): + mfname = cmd[i][14:] + shutil.copyfile(mfname, mfname + ".orig") + break + + def monkeypatched_link(self, target_desc, objects, output_filename, *args, **kw): + # no manifests for 3.3+ + self._want_assembly_kept = sys.version_info < (3,3) and \ + (os.path.basename(output_filename).startswith("PyISAPI_loader.dll") or \ + os.path.basename(output_filename).startswith("perfmondata.dll") or \ + os.path.basename(output_filename).startswith("win32ui.pyd") or \ + target_desc==self.EXECUTABLE) + try: + return self._orig_link(target_desc, objects, output_filename, *args, **kw) + finally: + delattr(self, '_want_assembly_kept') + MSVCCompiler.spawn = monkeypatched_spawn + MSVCCompiler.link = monkeypatched_link + + def find_telldus_dev_dir(): + landmark = "telldus-core.h" + dev_dir = os.environ.get("TELLDUS_DEVDIR") + if dev_dir: + if DEBUG: + print "Telldus dev dir:" % dev_dir + if os.path.isfile(os.path.join(dev_dir, landmark)): + return dev_dir + + progfiles = os.environ.get("ProgramFiles", r"C:\Program Files") + defaultlocs = [ + os.path.join(progfiles + ' (x86)', "Telldus", "Development"), + os.path.join(progfiles, "Telldus", "Development"), + ] + for dev_dir in defaultlocs: + if DEBUG: + print "Telldus dev dir: '%s'" % dev_dir + if os.path.isfile(os.path.join(dev_dir, landmark)): + return dev_dir + if DEBUG: + print "Telldus dev dir not found, make sure dev code is installed. Or set TELLDUS_DEVDIR." + + sdk_dir = find_platform_sdk_dir() + sdk_include_dir = os.path.join(sdk_dir, 'Include') + + telldus_dev_dir = find_telldus_dev_dir() + telldus_platform = os.environ.get("TELLDUS_PLATFORM", 'x86_64') + telldus_library_dir = os.path.join(telldus_dev_dir, telldus_platform) + + include_dirs = [sdk_include_dir, telldus_dev_dir] + library_dirs = [telldus_library_dir] + libraries = ['python%i%i' % (sys.version_info[0], sys.version_info[1]) , 'TelldusCore'] + define_macros = [('_WINDOWS', 1)] + +else: + include_dirs = ['/usr/include', '/usr/local/include'] + library_dirs = ['/usr/lib', '/usr/local/lib'] + libraries = ['telldus-core'] + define_macros = [] + +define_macros.extend([('DATA_LENGTH', 20), ('CALLBACK_LENGTH', 20)]) + +telldus = Extension( + 'telldus', + include_dirs = include_dirs, + libraries = libraries, + library_dirs = library_dirs, + define_macros = define_macros, + sources = ['telldus.c'] +) + +setup( + name = 'telldus', + version = '1.0', + description = 'Python bindings for telldus', + author='Oyvind Saltvik', + author_email='oyvind.saltvik@gmail.com', + url='http://github.com/fivethreeo/telldus/', + ext_modules = [telldus] +) diff --git a/bindings/python/native/telldus.c b/bindings/python/native/telldus.c index 8459be3f..a96fe51d 100644 --- a/bindings/python/native/telldus.c +++ b/bindings/python/native/telldus.c @@ -1,843 +1,843 @@ -#include "Python.h" -#include "datetime.h" -#include -#include - -/* estrdup.c -- duplicate a string, die if error - * - * char *string; - * char *newstring; - * newstring = estrdup(string); - * - * estrdup returns a copy of its argument, located in memory - * allocated from the heap. If it is unable to allocate the - * necessary memory, estrdup executes PyErr_NoMemory(); - * (Generally, the routine error is not expected to return, - * but if it does, estrdup will return NULL.) -*/ - -int callbackLen = 0; - -typedef struct { - PyObject *func; - int callbackId; -} callbackInfo; - -static callbackInfo callbackList[CALLBACK_LENGTH]; - -void -addCallback(PyObject *func, int callbackId) -{ - if (callbackLen < CALLBACK_LENGTH) { - callbackList[callbackLen].func = func; - callbackList[callbackLen].callbackId = callbackId; - callbackLen++; - } -} - -void -removeCallback(int callbackId) -{ - int index = -1; - - int i; - int j; - - for (i = 0; i < callbackLen; i++) - { - if (callbackList[i].callbackId == callbackId) - { - index = i; - } - } - if (!(index == -1)) { - for (j = index; j < callbackLen - 1; j++) - { - callbackList[j] = callbackList[j+1]; - } - callbackLen--; - } -} - -int -hasCallback(int callbackId) -{ - int i; - - for (i = 0; i < callbackLen; i++) - { - if (callbackList[i].callbackId == callbackId) - { - return 1; - } - } - return 0; - -} - -PyObject * -getCallback(int callbackId) -{ - int i; - - for (i = 0; i < callbackLen; i++) - { - if (callbackList[i].callbackId == callbackId) - { - return callbackList[i].func; - } - } - return NULL; -} - -char * -estrdup(char *s) -{ - register char *t; - - if (NULL == (t = malloc(strlen(s)+1))) { - PyErr_NoMemory(); - return NULL; - } - strcpy(t, s); - return(t); -} - -static PyObject * -telldus_tdInit(PyObject *self) -{ - tdInit(); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -telldus_tdClose(PyObject *self) -{ - tdClose(); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -telldus_tdTurnOn(PyObject *self, PyObject *args) -{ - long id; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyLong_FromLong((long) tdTurnOn(id)); -} - -static PyObject * -telldus_tdTurnOff(PyObject *self, PyObject *args) -{ - long id; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyLong_FromLong((long) tdTurnOff(id)); -} - -static PyObject * -telldus_tdBell(PyObject *self, PyObject *args) -{ - long id; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyLong_FromLong((long) tdBell(id)); -} - -static PyObject * -telldus_tdDim(PyObject *self, PyObject *args) -{ - long id; - unsigned char level; - - if (!PyArg_ParseTuple(args, "lb", &id, &level)) - return NULL; - - if (level < 0 || level > 255) - return NULL; - - return PyLong_FromLong((long) tdDim(id, level)); -} - -static PyObject * -telldus_tdLearn(PyObject *self, PyObject *args) -{ - long id; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyLong_FromLong((long) tdLearn(id)); -} - -static PyObject * -telldus_tdMethods(PyObject *self, PyObject *args) -{ - long id; - long supportedmethods; - - if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) - return NULL; - - return PyLong_FromLong((long) tdMethods(id, supportedmethods)); -} - - -static PyObject * -telldus_tdLastSentCommand(PyObject *self, PyObject *args) -{ - long id; - long supportedmethods; - - if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) - return NULL; - - return PyLong_FromLong((long) tdLastSentCommand(id, supportedmethods)); -} - -static PyObject * -telldus_tdLastSentValue(PyObject *self, PyObject *args) -{ - long id; - char* value; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - value = tdLastSentValue(id); - retval = estrdup(value); - tdReleaseString(value); - return PyString_FromString(retval); -} - -static PyObject * -telldus_tdGetNumberOfDevices(PyObject *self) -{ - return PyLong_FromLong((long) tdGetNumberOfDevices()); -} - -static PyObject * -telldus_tdGetDeviceId(PyObject *self, PyObject *args) -{ - long index; - - if (!PyArg_ParseTuple(args, "l", &index)) - return NULL; - - return PyLong_FromLong((long) tdGetDeviceId(index)); -} - -static PyObject * -telldus_tdGetDeviceType(PyObject *self, PyObject *args) -{ - long id; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyLong_FromLong((long) tdGetDeviceType(id)); -} - -static PyObject * -telldus_tdGetErrorString(PyObject *self, PyObject *args) -{ - long errorno; - char* errorString; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &errorno)) - return NULL; - - errorString = tdGetErrorString(errorno); - retval = estrdup(errorString); - tdReleaseString(errorString); - return PyString_FromString(retval); -} - -static PyObject * -telldus_tdGetName(PyObject *self, PyObject *args) -{ - long id; - char* name; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - name = tdGetName(id); - retval = estrdup(name); - tdReleaseString(name); - return PyString_FromString(retval); -} - -static PyObject * -telldus_tdSetName(PyObject *self, PyObject *args) -{ - long id; - char* name; - - if (!PyArg_ParseTuple(args, "ls", &id, &name)) - return NULL; - - return PyLong_FromLong((long) tdSetName(id, name)); -} - -static PyObject * -telldus_tdGetProtocol(PyObject *self, PyObject *args) -{ - long id; - char* protocol; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - protocol = tdGetProtocol(id); - retval = estrdup(protocol); - tdReleaseString(protocol); - return PyString_FromString(retval); -} - -static PyObject * -telldus_tdSetProtocol(PyObject *self, PyObject *args) -{ - long id; - char* protocol; - - if (!PyArg_ParseTuple(args, "ls", &id, &protocol)) - return NULL; - - return PyLong_FromLong((long) tdSetProtocol(id, protocol)); - -} - -static PyObject * -telldus_tdGetModel(PyObject *self, PyObject *args) -{ - long id; - char* model; - char* retval; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - model = tdGetModel(id); - retval = estrdup(model); - tdReleaseString(model); - return PyString_FromString(retval); -} - -static PyObject * -telldus_tdSetModel(PyObject *self, PyObject *args) -{ - long id; - char* model; - - if (!PyArg_ParseTuple(args, "ls", &id, &model)) - return NULL; - - return PyLong_FromLong((long) tdSetProtocol(id, model)); - -} - -static PyObject * -telldus_tdGetDeviceParameter(PyObject *self, PyObject *args) -{ - long id; - char* name; - char* defaultValue; - char* param; - char* retval; - - if (!PyArg_ParseTuple(args, "lss", &id, &name, &defaultValue)) - return NULL; - - param = tdGetDeviceParameter(id, name, defaultValue); - retval = estrdup(param); - tdReleaseString(param); - return PyString_FromString(retval); -} - -static PyObject * -telldus_tdSetDeviceParameter(PyObject *self, PyObject *args) -{ - long id; - char* name; - char* value; - - if (!PyArg_ParseTuple(args, "lss", &id, &name, &value)) - return NULL; - - return PyLong_FromLong((long) tdSetDeviceParameter(id, name, value)); -} - -static PyObject * -telldus_tdAddDevice(PyObject *self) -{ - return PyLong_FromLong((long) tdAddDevice()); -} - -static PyObject * -telldus_tdRemoveDevice(PyObject *self, PyObject *args) -{ - long id; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - return PyLong_FromLong((long) tdRemoveDevice(id)); -} - -static PyObject * -telldus_tdSendRawCommand(PyObject *self, PyObject *args) -{ - char *command; - long reserved = 0; - - if (!PyArg_ParseTuple(args, "s|l", &command, &reserved)); - return NULL; - - return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); -} - -static PyObject *DeviceEventCallback = NULL; - -void -telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, int context) -{ - - PyObject * result; - PyGILState_STATE gstate = PyGILState_Ensure(); - - // now call the Python callback function - result = PyObject_CallFunction(DeviceEventCallback, "llsl", deviceId, method, data, callbackId); - - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } - - // take care of reference handling - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; -} - -static PyObject * -telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) -{ - - int result; - PyObject *func; - - if (!PyArg_ParseTuple(args, "O:tdRegisterDeviceEvent", &func)) { - PyErr_SetString(PyExc_StandardError, "Parse error!"); - return NULL; - } - - if (!PyCallable_Check(func)) { - // Error - PyErr_SetString(PyExc_StandardError, "The object should be callable!"); - return NULL; - } - - Py_XDECREF(DeviceEventCallback); - // stick around till we need you - Py_XINCREF(func); - - DeviceEventCallback = func; - - result = tdRegisterDeviceEvent((TDDeviceEvent) &telldus_deviceEventCallback, 0); - - addCallback(func, result); - - return PyLong_FromLong((long) result); -} - -static PyObject *DeviceChangeEventCallback = NULL; - -void -telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, int callbackId, int context) -{ - PyObject * result; - PyGILState_STATE gstate = PyGILState_Ensure(); - - // now call the Python callback function - result = PyObject_CallFunction(DeviceChangeEventCallback, "llll", deviceId, changeEvent, changeType, callbackId); - - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } - - // take care of reference handling - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; -} - -static PyObject * -telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) -{ - int result; - PyObject *func; - - if (!PyArg_ParseTuple(args, "O", &func)) { - PyErr_SetString(PyExc_StandardError, "Parse error!"); - return NULL; - } - - if (!PyCallable_Check(func)) { - // Error - PyErr_SetString(PyExc_StandardError, "The object should be callable!"); - return NULL; - } - - Py_XDECREF(DeviceChangeEventCallback); - // stick around till we need you - Py_XINCREF(func); - - DeviceChangeEventCallback = func; - - result = tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) &telldus_deviceChangeEventCallback, 0); - - addCallback(func, result); - - return PyLong_FromLong((long) result); -} - -static PyObject *RawDeviceEventCallback = NULL; - -void -telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackId, int context) -{ - PyObject * result; - PyGILState_STATE gstate = PyGILState_Ensure(); - - // now call the Python callback function - result = PyObject_CallFunction(RawDeviceEventCallback, "sll", data, controllerId, callbackId); - - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } - - // take care of reference handling - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; -} - -static PyObject * -telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) -{ - int result; - PyObject *func; - - if (!PyArg_ParseTuple(args, "O", &func)) { - PyErr_SetString(PyExc_StandardError, "Parse error!"); - return NULL; - } - - if (!PyCallable_Check(func)) { - // Error - PyErr_SetString(PyExc_StandardError, "The object should be callable!"); - return NULL; - } - - Py_XDECREF(RawDeviceEventCallback); - // stick around till we need you - Py_XINCREF(func); - - RawDeviceEventCallback = func; - - result = tdRegisterRawDeviceEvent((TDRawDeviceEvent) &telldus_rawDeviceEventCallback, 0); - - addCallback(func, result); - - return PyLong_FromLong((long) result); -} - -static PyObject *SensorEventCallback = NULL; - -void -telldus_sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, int context) -{ - PyObject * result; - PyGILState_STATE gstate = PyGILState_Ensure(); - - // now call the Python callback function - result = PyObject_CallFunction(SensorEventCallback, "ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); - - if (result == NULL) { - // something went wrong so print to stderr - PyErr_Print(); - } - - // take care of reference handling - Py_XDECREF(result); - - PyGILState_Release(gstate); - - return; -} - -static PyObject * -telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) -{ - int result; - PyObject *func; - - if (!PyArg_ParseTuple(args, "O", &func)) { - PyErr_SetString(PyExc_StandardError, "Parse error!"); - return NULL; - } - - if (!PyCallable_Check(func)) { - // Error - PyErr_SetString(PyExc_StandardError, "The object should be callable!"); - return NULL; - } - - Py_XDECREF(SensorEventCallback); - // stick around till we need you - Py_XINCREF(func); - - SensorEventCallback = func; - - result = tdRegisterSensorEvent((TDSensorEvent) &telldus_sensorEventCallback, 0); - - addCallback(func, result); - - return PyLong_FromLong((long) result); -} - -static PyObject * -telldus_tdUnregisterCallback(PyObject *self, PyObject *args) -{ - long id; - PyObject *callback; - - if (!PyArg_ParseTuple(args, "l", &id)) - return NULL; - - if (hasCallback(id) == 1) { - callback = getCallback(id); - Py_DECREF(callback); - removeCallback(id); - } - - return PyLong_FromLong((long) tdUnregisterCallback(id)); -} - -static PyObject * -telldus_tdSensor(PyObject *self, PyObject *args) -{ - char protocol[DATA_LENGTH]; - char model[DATA_LENGTH]; - long sensorId = 0; - long dataTypes = 0; - - long result; - - result = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); - - if (result == TELLSTICK_SUCCESS) - { - return Py_BuildValue("ssll", protocol, model, sensorId, dataTypes); - } - else - { - return PyLong_FromLong(result); - } - -} - -static PyObject * -telldus_tdSensorValue(PyObject *self, PyObject *args) -{ - char protocol[DATA_LENGTH]; - char model[DATA_LENGTH]; - long sensorId = 0; - long dataType = 0; - char value[DATA_LENGTH]; - long timestamp = 0; - long result; - - PyObject *floatObj = NULL; - PyObject *timeTuple = NULL; - PyObject *dateTime = NULL; - - - if (!PyArg_ParseTuple(args, "ssll", &protocol, &model, &sensorId, &dataType)) - return NULL; - - result = tdSensorValue(protocol, model, sensorId, dataType, value, DATA_LENGTH, ×tamp); - - if (result == TELLSTICK_SUCCESS) - { - - floatObj = PyFloat_FromDouble((double) timestamp); - timeTuple = Py_BuildValue("(O)", floatObj); - dateTime = PyDateTime_FromTimestamp(timeTuple); - - Py_DECREF(floatObj); - Py_DECREF(timeTuple); - - return Py_BuildValue("sO", value, dateTime); - } - else - { - return PyLong_FromLong(result); - } -} - -static PyMethodDef telldus_methods[] = { - {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, - {"tdClose", (PyCFunction) telldus_tdClose, METH_NOARGS, "Close telldus."}, - {"tdTurnOn", (PyCFunction) telldus_tdTurnOn, METH_VARARGS, "Turn on device."}, - {"tdTurnOff", (PyCFunction) telldus_tdTurnOff, METH_VARARGS, "Turn off device."}, - {"tdBell", (PyCFunction) telldus_tdBell, METH_VARARGS, "Bell device."}, - {"tdDim", (PyCFunction) telldus_tdDim, METH_VARARGS, "Dim device."}, - {"tdLearn", (PyCFunction) telldus_tdLearn, METH_VARARGS, "Learn device."}, - {"tdMethods", (PyCFunction) telldus_tdMethods, METH_VARARGS, "Methods comment."}, - {"tdLastSentCommand", (PyCFunction) telldus_tdLastSentCommand, METH_VARARGS, "LastSentCommand comment."}, - {"tdLastSentValue", (PyCFunction) telldus_tdLastSentValue, METH_VARARGS, "LastSentValue comment."}, - {"tdGetNumberOfDevices", (PyCFunction) telldus_tdGetNumberOfDevices, METH_VARARGS, "GetNumberOfDevices comment."}, - {"tdGetDeviceId", (PyCFunction) telldus_tdGetDeviceId, METH_VARARGS, "GetDeviceId comment."}, - {"tdGetDeviceType", (PyCFunction) telldus_tdGetDeviceType, METH_VARARGS, "GetDeviceType comment."}, - {"tdGetErrorString", (PyCFunction) telldus_tdGetErrorString, METH_VARARGS, "GetErrorString comment."}, - {"tdGetName", (PyCFunction) telldus_tdGetName, METH_VARARGS, "GetName comment."}, - {"tdSetName", (PyCFunction) telldus_tdSetName, METH_VARARGS, "SetName comment."}, - {"tdGetProtocol", (PyCFunction) telldus_tdGetProtocol, METH_VARARGS, "GetProtocol comment."}, - {"tdSetProtocol", (PyCFunction) telldus_tdSetProtocol, METH_VARARGS, "SetProtocol comment."}, - {"tdGetModel", (PyCFunction) telldus_tdGetModel, METH_VARARGS, "GetModel comment."}, - {"tdSetModel", (PyCFunction) telldus_tdSetModel, METH_VARARGS, "SetModel comment."}, - {"tdGetDeviceParameter", (PyCFunction) telldus_tdGetDeviceParameter, METH_VARARGS, "GetDeviceParameter comment."}, - {"tdSetDeviceParameter", (PyCFunction) telldus_tdSetDeviceParameter, METH_VARARGS, "SetDeviceParameter comment."}, - {"tdAddDevice", (PyCFunction) telldus_tdAddDevice, METH_NOARGS, "AddDevice comment."}, - {"tdRemoveDevice", (PyCFunction) telldus_tdRemoveDevice, METH_VARARGS, "RemoveDevice comment."}, - {"tdSendRawCommand", (PyCFunction) telldus_tdSendRawCommand, METH_VARARGS, "SendRawCommand comment."}, - - {"tdRegisterDeviceEvent", (PyCFunction) telldus_tdRegisterDeviceEvent, METH_VARARGS, "RegisterDeviceEvent comment."}, - {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, - {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, - {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, - {"tdUnregisterCallback", (PyCFunction) telldus_tdUnregisterCallback, METH_VARARGS, "UnregisterCallback comment."}, - {"tdSensor", (PyCFunction) telldus_tdSensor, METH_NOARGS, "Sensor comment."}, - {"tdSensorValue", (PyCFunction) telldus_tdSensorValue, METH_VARARGS, "SensorValue comment."}, - - {NULL, NULL, 0, NULL} /* sentinel */ -}; - -void -inittelldus(void) -{ - PyObject *module; - - PyObject *TELLSTICK_TURNON_GLUE; - PyObject *TELLSTICK_TURNOFF_GLUE; - PyObject *TELLSTICK_BELL_GLUE; - PyObject *TELLSTICK_TOGGLE_GLUE; - PyObject *TELLSTICK_DIM_GLUE; - PyObject *TELLSTICK_LEARN_GLUE; - PyObject *TELLSTICK_SUCCESS_GLUE; - PyObject *TELLSTICK_ERROR_NOT_FOUND_GLUE; - PyObject *TELLSTICK_ERROR_PERMISSION_DENIED_GLUE; - PyObject *TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE; - PyObject *TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE; - PyObject *TELLSTICK_ERROR_COMMUNICATION_GLUE; - PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE; - PyObject *TELLSTICK_TYPE_DEVICE_GLUE; - PyObject *TELLSTICK_TYPE_GROUP_GLUE; - PyObject *TELLSTICK_TEMPERATURE_GLUE; - PyObject *TELLSTICK_HUMIDITY_GLUE; - - /* Create the module and add the functions */ - - module = Py_InitModule("telldus", telldus_methods); - - TELLSTICK_TURNON_GLUE = PyLong_FromLong((long) TELLSTICK_TURNON); - PyObject_SetAttrString(module, "TELLSTICK_TURNON", TELLSTICK_TURNON_GLUE); - Py_DECREF(TELLSTICK_TURNON_GLUE); - - TELLSTICK_TURNOFF_GLUE = PyLong_FromLong((long) TELLSTICK_TURNOFF); - PyObject_SetAttrString(module, "TELLSTICK_TURNOFF", TELLSTICK_TURNOFF_GLUE); - Py_DECREF(TELLSTICK_TURNOFF_GLUE); - - TELLSTICK_BELL_GLUE = PyLong_FromLong((long) TELLSTICK_BELL); - PyObject_SetAttrString(module, "TELLSTICK_BELL", TELLSTICK_BELL_GLUE); - Py_DECREF(TELLSTICK_BELL_GLUE); - - TELLSTICK_TOGGLE_GLUE = PyLong_FromLong((long) TELLSTICK_TOGGLE); - PyObject_SetAttrString(module, "TELLSTICK_TOGGLE", TELLSTICK_TOGGLE_GLUE); - Py_DECREF(TELLSTICK_TOGGLE_GLUE); - - TELLSTICK_DIM_GLUE = PyLong_FromLong((long) TELLSTICK_DIM); - PyObject_SetAttrString(module, "TELLSTICK_DIM", TELLSTICK_DIM_GLUE); - Py_DECREF(TELLSTICK_DIM_GLUE); - - TELLSTICK_LEARN_GLUE = PyLong_FromLong((long) TELLSTICK_LEARN); - PyObject_SetAttrString(module, "TELLSTICK_LEARN", TELLSTICK_LEARN_GLUE); - Py_DECREF(TELLSTICK_LEARN_GLUE); - - TELLSTICK_SUCCESS_GLUE = PyLong_FromLong((long) TELLSTICK_SUCCESS); - PyObject_SetAttrString(module, "TELLSTICK_SUCCESS", TELLSTICK_SUCCESS_GLUE); - Py_DECREF(TELLSTICK_SUCCESS_GLUE); - - TELLSTICK_ERROR_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_NOT_FOUND); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_NOT_FOUND", TELLSTICK_ERROR_NOT_FOUND_GLUE); - Py_DECREF(TELLSTICK_ERROR_NOT_FOUND_GLUE); - - TELLSTICK_ERROR_PERMISSION_DENIED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_PERMISSION_DENIED); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_PERMISSION_DENIED", TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); - Py_DECREF(TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); - - TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_DEVICE_NOT_FOUND); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_DEVICE_NOT_FOUND", TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); - Py_DECREF(TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); - - TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_METHOD_NOT_SUPPORTED); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_METHOD_NOT_SUPPORTED", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); - Py_DECREF(TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); - - TELLSTICK_ERROR_COMMUNICATION_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_COMMUNICATION); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_COMMUNICATION", TELLSTICK_ERROR_COMMUNICATION_GLUE); - Py_DECREF(TELLSTICK_ERROR_COMMUNICATION_GLUE); - - TELLSTICK_ERROR_UNKNOWN_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_UNKNOWN); - PyObject_SetAttrString(module, "TELLSTICK_ERROR_UNKNOWN", TELLSTICK_ERROR_UNKNOWN_GLUE); - Py_DECREF(TELLSTICK_ERROR_UNKNOWN_GLUE); - - TELLSTICK_TYPE_DEVICE_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_DEVICE); - PyObject_SetAttrString(module, "TELLSTICK_TYPE_DEVICE", TELLSTICK_TYPE_DEVICE_GLUE); - Py_DECREF(TELLSTICK_TYPE_DEVICE_GLUE); - - TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); - PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); - Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); - - TELLSTICK_TEMPERATURE_GLUE = PyLong_FromLong((long) TELLSTICK_TEMPERATURE); - PyObject_SetAttrString(module, "TELLSTICK_TEMPERATURE", TELLSTICK_TEMPERATURE_GLUE); - Py_DECREF(TELLSTICK_TEMPERATURE_GLUE); - - TELLSTICK_HUMIDITY_GLUE = PyLong_FromLong((long) TELLSTICK_HUMIDITY); - PyObject_SetAttrString(module, "TELLSTICK_HUMIDITY", TELLSTICK_HUMIDITY_GLUE); - Py_DECREF(TELLSTICK_HUMIDITY_GLUE); - -} +#include "Python.h" +#include "datetime.h" +#include +#include + +/* estrdup.c -- duplicate a string, die if error + * + * char *string; + * char *newstring; + * newstring = estrdup(string); + * + * estrdup returns a copy of its argument, located in memory + * allocated from the heap. If it is unable to allocate the + * necessary memory, estrdup executes PyErr_NoMemory(); + * (Generally, the routine error is not expected to return, + * but if it does, estrdup will return NULL.) +*/ + +int callbackLen = 0; + +typedef struct { + PyObject *func; + int callbackId; +} callbackInfo; + +static callbackInfo callbackList[CALLBACK_LENGTH]; + +void +addCallback(PyObject *func, int callbackId) +{ + if (callbackLen < CALLBACK_LENGTH) { + callbackList[callbackLen].func = func; + callbackList[callbackLen].callbackId = callbackId; + callbackLen++; + } +} + +void +removeCallback(int callbackId) +{ + int index = -1; + + int i; + int j; + + for (i = 0; i < callbackLen; i++) + { + if (callbackList[i].callbackId == callbackId) + { + index = i; + } + } + if (!(index == -1)) { + for (j = index; j < callbackLen - 1; j++) + { + callbackList[j] = callbackList[j+1]; + } + callbackLen--; + } +} + +int +hasCallback(int callbackId) +{ + int i; + + for (i = 0; i < callbackLen; i++) + { + if (callbackList[i].callbackId == callbackId) + { + return 1; + } + } + return 0; + +} + +PyObject * +getCallback(int callbackId) +{ + int i; + + for (i = 0; i < callbackLen; i++) + { + if (callbackList[i].callbackId == callbackId) + { + return callbackList[i].func; + } + } + return NULL; +} + +char * +estrdup(char *s) +{ + register char *t; + + if (NULL == (t = malloc(strlen(s)+1))) { + PyErr_NoMemory(); + return NULL; + } + strcpy(t, s); + return(t); +} + +static PyObject * +telldus_tdInit(PyObject *self) +{ + tdInit(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +telldus_tdClose(PyObject *self) +{ + tdClose(); + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +telldus_tdTurnOn(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdTurnOn(id)); +} + +static PyObject * +telldus_tdTurnOff(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdTurnOff(id)); +} + +static PyObject * +telldus_tdBell(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdBell(id)); +} + +static PyObject * +telldus_tdDim(PyObject *self, PyObject *args) +{ + long id; + unsigned char level; + + if (!PyArg_ParseTuple(args, "lb", &id, &level)) + return NULL; + + if (level < 0 || level > 255) + return NULL; + + return PyLong_FromLong((long) tdDim(id, level)); +} + +static PyObject * +telldus_tdLearn(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdLearn(id)); +} + +static PyObject * +telldus_tdMethods(PyObject *self, PyObject *args) +{ + long id; + long supportedmethods; + + if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) + return NULL; + + return PyLong_FromLong((long) tdMethods(id, supportedmethods)); +} + + +static PyObject * +telldus_tdLastSentCommand(PyObject *self, PyObject *args) +{ + long id; + long supportedmethods; + + if (!PyArg_ParseTuple(args, "ll", &id, &supportedmethods)) + return NULL; + + return PyLong_FromLong((long) tdLastSentCommand(id, supportedmethods)); +} + +static PyObject * +telldus_tdLastSentValue(PyObject *self, PyObject *args) +{ + long id; + char* value; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + value = tdLastSentValue(id); + retval = estrdup(value); + tdReleaseString(value); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdGetNumberOfDevices(PyObject *self) +{ + return PyLong_FromLong((long) tdGetNumberOfDevices()); +} + +static PyObject * +telldus_tdGetDeviceId(PyObject *self, PyObject *args) +{ + long index; + + if (!PyArg_ParseTuple(args, "l", &index)) + return NULL; + + return PyLong_FromLong((long) tdGetDeviceId(index)); +} + +static PyObject * +telldus_tdGetDeviceType(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdGetDeviceType(id)); +} + +static PyObject * +telldus_tdGetErrorString(PyObject *self, PyObject *args) +{ + long errorno; + char* errorString; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &errorno)) + return NULL; + + errorString = tdGetErrorString(errorno); + retval = estrdup(errorString); + tdReleaseString(errorString); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdGetName(PyObject *self, PyObject *args) +{ + long id; + char* name; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + name = tdGetName(id); + retval = estrdup(name); + tdReleaseString(name); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetName(PyObject *self, PyObject *args) +{ + long id; + char* name; + + if (!PyArg_ParseTuple(args, "ls", &id, &name)) + return NULL; + + return PyLong_FromLong((long) tdSetName(id, name)); +} + +static PyObject * +telldus_tdGetProtocol(PyObject *self, PyObject *args) +{ + long id; + char* protocol; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + protocol = tdGetProtocol(id); + retval = estrdup(protocol); + tdReleaseString(protocol); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetProtocol(PyObject *self, PyObject *args) +{ + long id; + char* protocol; + + if (!PyArg_ParseTuple(args, "ls", &id, &protocol)) + return NULL; + + return PyLong_FromLong((long) tdSetProtocol(id, protocol)); + +} + +static PyObject * +telldus_tdGetModel(PyObject *self, PyObject *args) +{ + long id; + char* model; + char* retval; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + model = tdGetModel(id); + retval = estrdup(model); + tdReleaseString(model); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetModel(PyObject *self, PyObject *args) +{ + long id; + char* model; + + if (!PyArg_ParseTuple(args, "ls", &id, &model)) + return NULL; + + return PyLong_FromLong((long) tdSetProtocol(id, model)); + +} + +static PyObject * +telldus_tdGetDeviceParameter(PyObject *self, PyObject *args) +{ + long id; + char* name; + char* defaultValue; + char* param; + char* retval; + + if (!PyArg_ParseTuple(args, "lss", &id, &name, &defaultValue)) + return NULL; + + param = tdGetDeviceParameter(id, name, defaultValue); + retval = estrdup(param); + tdReleaseString(param); + return PyString_FromString(retval); +} + +static PyObject * +telldus_tdSetDeviceParameter(PyObject *self, PyObject *args) +{ + long id; + char* name; + char* value; + + if (!PyArg_ParseTuple(args, "lss", &id, &name, &value)) + return NULL; + + return PyLong_FromLong((long) tdSetDeviceParameter(id, name, value)); +} + +static PyObject * +telldus_tdAddDevice(PyObject *self) +{ + return PyLong_FromLong((long) tdAddDevice()); +} + +static PyObject * +telldus_tdRemoveDevice(PyObject *self, PyObject *args) +{ + long id; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + return PyLong_FromLong((long) tdRemoveDevice(id)); +} + +static PyObject * +telldus_tdSendRawCommand(PyObject *self, PyObject *args) +{ + char *command; + long reserved = 0; + + if (!PyArg_ParseTuple(args, "s|l", &command, &reserved)); + return NULL; + + return PyLong_FromLong((long) tdSendRawCommand(command, reserved)); +} + +static PyObject *DeviceEventCallback = NULL; + +void +telldus_deviceEventCallback(int deviceId, int method, const char *data, int callbackId, int context) +{ + + PyObject * result; + PyGILState_STATE gstate = PyGILState_Ensure(); + + // now call the Python callback function + result = PyObject_CallFunction(DeviceEventCallback, "llsl", deviceId, method, data, callbackId); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +static PyObject * +telldus_tdRegisterDeviceEvent(PyObject *self, PyObject *args) +{ + + int result; + PyObject *func; + + if (!PyArg_ParseTuple(args, "O:tdRegisterDeviceEvent", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); + return NULL; + } + + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(DeviceEventCallback); + // stick around till we need you + Py_XINCREF(func); + + DeviceEventCallback = func; + + result = tdRegisterDeviceEvent((TDDeviceEvent) &telldus_deviceEventCallback, 0); + + addCallback(func, result); + + return PyLong_FromLong((long) result); +} + +static PyObject *DeviceChangeEventCallback = NULL; + +void +telldus_deviceChangeEventCallback(int deviceId, int changeEvent, int changeType, int callbackId, int context) +{ + PyObject * result; + PyGILState_STATE gstate = PyGILState_Ensure(); + + // now call the Python callback function + result = PyObject_CallFunction(DeviceChangeEventCallback, "llll", deviceId, changeEvent, changeType, callbackId); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +static PyObject * +telldus_tdRegisterDeviceChangeEvent(PyObject *self, PyObject *args) +{ + int result; + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); + return NULL; + } + + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(DeviceChangeEventCallback); + // stick around till we need you + Py_XINCREF(func); + + DeviceChangeEventCallback = func; + + result = tdRegisterDeviceChangeEvent((TDDeviceChangeEvent) &telldus_deviceChangeEventCallback, 0); + + addCallback(func, result); + + return PyLong_FromLong((long) result); +} + +static PyObject *RawDeviceEventCallback = NULL; + +void +telldus_rawDeviceEventCallback(const char *data, int controllerId, int callbackId, int context) +{ + PyObject * result; + PyGILState_STATE gstate = PyGILState_Ensure(); + + // now call the Python callback function + result = PyObject_CallFunction(RawDeviceEventCallback, "sll", data, controllerId, callbackId); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +static PyObject * +telldus_tdRegisterRawDeviceEvent(PyObject *self, PyObject *args) +{ + int result; + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); + return NULL; + } + + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(RawDeviceEventCallback); + // stick around till we need you + Py_XINCREF(func); + + RawDeviceEventCallback = func; + + result = tdRegisterRawDeviceEvent((TDRawDeviceEvent) &telldus_rawDeviceEventCallback, 0); + + addCallback(func, result); + + return PyLong_FromLong((long) result); +} + +static PyObject *SensorEventCallback = NULL; + +void +telldus_sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, int context) +{ + PyObject * result; + PyGILState_STATE gstate = PyGILState_Ensure(); + + // now call the Python callback function + result = PyObject_CallFunction(SensorEventCallback, "ssllsll", protocol, model, id, dataType, value, timestamp, callbackId); + + if (result == NULL) { + // something went wrong so print to stderr + PyErr_Print(); + } + + // take care of reference handling + Py_XDECREF(result); + + PyGILState_Release(gstate); + + return; +} + +static PyObject * +telldus_tdRegisterSensorEvent(PyObject *self, PyObject *args) +{ + int result; + PyObject *func; + + if (!PyArg_ParseTuple(args, "O", &func)) { + PyErr_SetString(PyExc_StandardError, "Parse error!"); + return NULL; + } + + if (!PyCallable_Check(func)) { + // Error + PyErr_SetString(PyExc_StandardError, "The object should be callable!"); + return NULL; + } + + Py_XDECREF(SensorEventCallback); + // stick around till we need you + Py_XINCREF(func); + + SensorEventCallback = func; + + result = tdRegisterSensorEvent((TDSensorEvent) &telldus_sensorEventCallback, 0); + + addCallback(func, result); + + return PyLong_FromLong((long) result); +} + +static PyObject * +telldus_tdUnregisterCallback(PyObject *self, PyObject *args) +{ + long id; + PyObject *callback; + + if (!PyArg_ParseTuple(args, "l", &id)) + return NULL; + + if (hasCallback(id) == 1) { + callback = getCallback(id); + Py_DECREF(callback); + removeCallback(id); + } + + return PyLong_FromLong((long) tdUnregisterCallback(id)); +} + +static PyObject * +telldus_tdSensor(PyObject *self, PyObject *args) +{ + char protocol[DATA_LENGTH]; + char model[DATA_LENGTH]; + long sensorId = 0; + long dataTypes = 0; + + long result; + + result = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); + + if (result == TELLSTICK_SUCCESS) + { + return Py_BuildValue("ssll", protocol, model, sensorId, dataTypes); + } + else + { + return PyLong_FromLong(result); + } + +} + +static PyObject * +telldus_tdSensorValue(PyObject *self, PyObject *args) +{ + char protocol[DATA_LENGTH]; + char model[DATA_LENGTH]; + long sensorId = 0; + long dataType = 0; + char value[DATA_LENGTH]; + long timestamp = 0; + long result; + + PyObject *floatObj = NULL; + PyObject *timeTuple = NULL; + PyObject *dateTime = NULL; + + + if (!PyArg_ParseTuple(args, "ssll", &protocol, &model, &sensorId, &dataType)) + return NULL; + + result = tdSensorValue(protocol, model, sensorId, dataType, value, DATA_LENGTH, ×tamp); + + if (result == TELLSTICK_SUCCESS) + { + + floatObj = PyFloat_FromDouble((double) timestamp); + timeTuple = Py_BuildValue("(O)", floatObj); + dateTime = PyDateTime_FromTimestamp(timeTuple); + + Py_DECREF(floatObj); + Py_DECREF(timeTuple); + + return Py_BuildValue("sO", value, dateTime); + } + else + { + return PyLong_FromLong(result); + } +} + +static PyMethodDef telldus_methods[] = { + {"tdInit", (PyCFunction) telldus_tdInit, METH_NOARGS, "Initiate telldus."}, + {"tdClose", (PyCFunction) telldus_tdClose, METH_NOARGS, "Close telldus."}, + {"tdTurnOn", (PyCFunction) telldus_tdTurnOn, METH_VARARGS, "Turn on device."}, + {"tdTurnOff", (PyCFunction) telldus_tdTurnOff, METH_VARARGS, "Turn off device."}, + {"tdBell", (PyCFunction) telldus_tdBell, METH_VARARGS, "Bell device."}, + {"tdDim", (PyCFunction) telldus_tdDim, METH_VARARGS, "Dim device."}, + {"tdLearn", (PyCFunction) telldus_tdLearn, METH_VARARGS, "Learn device."}, + {"tdMethods", (PyCFunction) telldus_tdMethods, METH_VARARGS, "Methods comment."}, + {"tdLastSentCommand", (PyCFunction) telldus_tdLastSentCommand, METH_VARARGS, "LastSentCommand comment."}, + {"tdLastSentValue", (PyCFunction) telldus_tdLastSentValue, METH_VARARGS, "LastSentValue comment."}, + {"tdGetNumberOfDevices", (PyCFunction) telldus_tdGetNumberOfDevices, METH_VARARGS, "GetNumberOfDevices comment."}, + {"tdGetDeviceId", (PyCFunction) telldus_tdGetDeviceId, METH_VARARGS, "GetDeviceId comment."}, + {"tdGetDeviceType", (PyCFunction) telldus_tdGetDeviceType, METH_VARARGS, "GetDeviceType comment."}, + {"tdGetErrorString", (PyCFunction) telldus_tdGetErrorString, METH_VARARGS, "GetErrorString comment."}, + {"tdGetName", (PyCFunction) telldus_tdGetName, METH_VARARGS, "GetName comment."}, + {"tdSetName", (PyCFunction) telldus_tdSetName, METH_VARARGS, "SetName comment."}, + {"tdGetProtocol", (PyCFunction) telldus_tdGetProtocol, METH_VARARGS, "GetProtocol comment."}, + {"tdSetProtocol", (PyCFunction) telldus_tdSetProtocol, METH_VARARGS, "SetProtocol comment."}, + {"tdGetModel", (PyCFunction) telldus_tdGetModel, METH_VARARGS, "GetModel comment."}, + {"tdSetModel", (PyCFunction) telldus_tdSetModel, METH_VARARGS, "SetModel comment."}, + {"tdGetDeviceParameter", (PyCFunction) telldus_tdGetDeviceParameter, METH_VARARGS, "GetDeviceParameter comment."}, + {"tdSetDeviceParameter", (PyCFunction) telldus_tdSetDeviceParameter, METH_VARARGS, "SetDeviceParameter comment."}, + {"tdAddDevice", (PyCFunction) telldus_tdAddDevice, METH_NOARGS, "AddDevice comment."}, + {"tdRemoveDevice", (PyCFunction) telldus_tdRemoveDevice, METH_VARARGS, "RemoveDevice comment."}, + {"tdSendRawCommand", (PyCFunction) telldus_tdSendRawCommand, METH_VARARGS, "SendRawCommand comment."}, + + {"tdRegisterDeviceEvent", (PyCFunction) telldus_tdRegisterDeviceEvent, METH_VARARGS, "RegisterDeviceEvent comment."}, + {"tdRegisterDeviceChangeEvent", (PyCFunction) telldus_tdRegisterDeviceChangeEvent, METH_VARARGS, "RegisterDeviceChangeEvent comment."}, + {"tdRegisterRawDeviceEvent", (PyCFunction) telldus_tdRegisterRawDeviceEvent, METH_VARARGS, "RegisterRawDeviceEvent comment."}, + {"tdRegisterSensorEvent", (PyCFunction) telldus_tdRegisterSensorEvent, METH_VARARGS, "RegisterSensorEvent comment."}, + {"tdUnregisterCallback", (PyCFunction) telldus_tdUnregisterCallback, METH_VARARGS, "UnregisterCallback comment."}, + {"tdSensor", (PyCFunction) telldus_tdSensor, METH_NOARGS, "Sensor comment."}, + {"tdSensorValue", (PyCFunction) telldus_tdSensorValue, METH_VARARGS, "SensorValue comment."}, + + {NULL, NULL, 0, NULL} /* sentinel */ +}; + +void +inittelldus(void) +{ + PyObject *module; + + PyObject *TELLSTICK_TURNON_GLUE; + PyObject *TELLSTICK_TURNOFF_GLUE; + PyObject *TELLSTICK_BELL_GLUE; + PyObject *TELLSTICK_TOGGLE_GLUE; + PyObject *TELLSTICK_DIM_GLUE; + PyObject *TELLSTICK_LEARN_GLUE; + PyObject *TELLSTICK_SUCCESS_GLUE; + PyObject *TELLSTICK_ERROR_NOT_FOUND_GLUE; + PyObject *TELLSTICK_ERROR_PERMISSION_DENIED_GLUE; + PyObject *TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE; + PyObject *TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE; + PyObject *TELLSTICK_ERROR_COMMUNICATION_GLUE; + PyObject *TELLSTICK_ERROR_UNKNOWN_GLUE; + PyObject *TELLSTICK_TYPE_DEVICE_GLUE; + PyObject *TELLSTICK_TYPE_GROUP_GLUE; + PyObject *TELLSTICK_TEMPERATURE_GLUE; + PyObject *TELLSTICK_HUMIDITY_GLUE; + + /* Create the module and add the functions */ + + module = Py_InitModule("telldus", telldus_methods); + + TELLSTICK_TURNON_GLUE = PyLong_FromLong((long) TELLSTICK_TURNON); + PyObject_SetAttrString(module, "TELLSTICK_TURNON", TELLSTICK_TURNON_GLUE); + Py_DECREF(TELLSTICK_TURNON_GLUE); + + TELLSTICK_TURNOFF_GLUE = PyLong_FromLong((long) TELLSTICK_TURNOFF); + PyObject_SetAttrString(module, "TELLSTICK_TURNOFF", TELLSTICK_TURNOFF_GLUE); + Py_DECREF(TELLSTICK_TURNOFF_GLUE); + + TELLSTICK_BELL_GLUE = PyLong_FromLong((long) TELLSTICK_BELL); + PyObject_SetAttrString(module, "TELLSTICK_BELL", TELLSTICK_BELL_GLUE); + Py_DECREF(TELLSTICK_BELL_GLUE); + + TELLSTICK_TOGGLE_GLUE = PyLong_FromLong((long) TELLSTICK_TOGGLE); + PyObject_SetAttrString(module, "TELLSTICK_TOGGLE", TELLSTICK_TOGGLE_GLUE); + Py_DECREF(TELLSTICK_TOGGLE_GLUE); + + TELLSTICK_DIM_GLUE = PyLong_FromLong((long) TELLSTICK_DIM); + PyObject_SetAttrString(module, "TELLSTICK_DIM", TELLSTICK_DIM_GLUE); + Py_DECREF(TELLSTICK_DIM_GLUE); + + TELLSTICK_LEARN_GLUE = PyLong_FromLong((long) TELLSTICK_LEARN); + PyObject_SetAttrString(module, "TELLSTICK_LEARN", TELLSTICK_LEARN_GLUE); + Py_DECREF(TELLSTICK_LEARN_GLUE); + + TELLSTICK_SUCCESS_GLUE = PyLong_FromLong((long) TELLSTICK_SUCCESS); + PyObject_SetAttrString(module, "TELLSTICK_SUCCESS", TELLSTICK_SUCCESS_GLUE); + Py_DECREF(TELLSTICK_SUCCESS_GLUE); + + TELLSTICK_ERROR_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_NOT_FOUND); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_NOT_FOUND", TELLSTICK_ERROR_NOT_FOUND_GLUE); + Py_DECREF(TELLSTICK_ERROR_NOT_FOUND_GLUE); + + TELLSTICK_ERROR_PERMISSION_DENIED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_PERMISSION_DENIED); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_PERMISSION_DENIED", TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); + Py_DECREF(TELLSTICK_ERROR_PERMISSION_DENIED_GLUE); + + TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_DEVICE_NOT_FOUND); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_DEVICE_NOT_FOUND", TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); + Py_DECREF(TELLSTICK_ERROR_DEVICE_NOT_FOUND_GLUE); + + TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_METHOD_NOT_SUPPORTED); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_METHOD_NOT_SUPPORTED", TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); + Py_DECREF(TELLSTICK_ERROR_METHOD_NOT_SUPPORTED_GLUE); + + TELLSTICK_ERROR_COMMUNICATION_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_COMMUNICATION); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_COMMUNICATION", TELLSTICK_ERROR_COMMUNICATION_GLUE); + Py_DECREF(TELLSTICK_ERROR_COMMUNICATION_GLUE); + + TELLSTICK_ERROR_UNKNOWN_GLUE = PyLong_FromLong((long) TELLSTICK_ERROR_UNKNOWN); + PyObject_SetAttrString(module, "TELLSTICK_ERROR_UNKNOWN", TELLSTICK_ERROR_UNKNOWN_GLUE); + Py_DECREF(TELLSTICK_ERROR_UNKNOWN_GLUE); + + TELLSTICK_TYPE_DEVICE_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_DEVICE); + PyObject_SetAttrString(module, "TELLSTICK_TYPE_DEVICE", TELLSTICK_TYPE_DEVICE_GLUE); + Py_DECREF(TELLSTICK_TYPE_DEVICE_GLUE); + + TELLSTICK_TYPE_GROUP_GLUE = PyLong_FromLong((long) TELLSTICK_TYPE_GROUP); + PyObject_SetAttrString(module, "TELLSTICK_TYPE_GROUP", TELLSTICK_TYPE_GROUP_GLUE); + Py_DECREF(TELLSTICK_TYPE_GROUP_GLUE); + + TELLSTICK_TEMPERATURE_GLUE = PyLong_FromLong((long) TELLSTICK_TEMPERATURE); + PyObject_SetAttrString(module, "TELLSTICK_TEMPERATURE", TELLSTICK_TEMPERATURE_GLUE); + Py_DECREF(TELLSTICK_TEMPERATURE_GLUE); + + TELLSTICK_HUMIDITY_GLUE = PyLong_FromLong((long) TELLSTICK_HUMIDITY); + PyObject_SetAttrString(module, "TELLSTICK_HUMIDITY", TELLSTICK_HUMIDITY_GLUE); + Py_DECREF(TELLSTICK_HUMIDITY_GLUE); + +} From 0d8bf77a45f8772efdc1e8a4be8c35d9dec175cf Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 3 Sep 2012 16:59:09 +0200 Subject: [PATCH 2079/2215] Only a lot of debug printouts, but this version is working for SwitchKing at least --- .../client/CallbackMainDispatcher.cpp | 11 ++++++++ telldus-core/client/Client.cpp | 6 +++++ telldus-core/common/Socket_win.cpp | 8 ++++-- telldus-core/common/common.h | 25 ++++++++++++++++--- telldus-core/service/EventUpdateManager.cpp | 10 ++++++++ telldus-core/service/TelldusMain.cpp | 3 +++ 6 files changed, 58 insertions(+), 5 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index fbc09cbd..efb9ed11 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -61,6 +61,8 @@ int CallbackMainDispatcher::registerCallback(CallbackStruct::CallbackType type, callback->id = id; callback->context = context; d->callbackList.push_back(callback); + //logga callbackprenumeration lades till + debuglog(id, "Callback added"); return id; } @@ -69,9 +71,11 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { { TelldusCore::MutexLocker locker(&d->mutex); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { + //logga, avregistrering av callback if ( (*callback_it)->id != callbackId ) { continue; } + debuglog(callbackId, "Callback unregistered"); newEventList.splice(newEventList.begin(), d->callbackList, callback_it); break; } @@ -102,9 +106,16 @@ void CallbackMainDispatcher::run(){ if (!cbd) { continue; } + //logga här, att den fortfarande körs, ev till fil bara för att det kan bli så mkt... + //om för mkt, kolla att viss tid gått sedan förra ggn eller ngt... + debuglog(333, "Callbackevent, signalled"); TelldusCore::MutexLocker locker(&d->mutex); + //logga, har låst + debuglog(333, "Callbackevent, locked"); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { if ( (*callback_it)->type == cbd->type ) { + //ev logga här också, att det finns ngnstans att skicka till + debuglog((*callback_it)->id, "Callbackevent, sending"); std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); d->eventThreadList.push_back(ptr); } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index b805bb14..ffc662be 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -73,6 +73,8 @@ std::wstring Client::getWStringFromService(const Message &msg) { } int Client::registerEvent( CallbackStruct::CallbackType type, void *eventFunction, void *context ) { + //LOGGA, client is registering callback + debuglog(555, "Client, Registering callback"); return d->callbackMainDispatcher.registerCallback(type, eventFunction, context ); } @@ -83,6 +85,8 @@ void Client::run(){ while(d->running){ if(!d->eventSocket.isConnected()){ + //LOGGA trying to (re)connect to TelldusEvents + debuglog(555, "Client, Trying to (re)connect to TelldusEvents"); d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service if(!d->eventSocket.isConnected()){ //reconnect didn't succeed, wait a while and try again @@ -186,6 +190,8 @@ void Client::stopThread(){ } int Client::unregisterCallback( int callbackId ) { + //LOGGA, client correctly unregistering callback + debuglog(555, "Client, correctly unregistering callback"); return d->callbackMainDispatcher.unregisterCallback(callbackId); } diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 87b6b37a..301735c3 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -1,5 +1,5 @@ #include "Socket.h" - +#include "common.h" #include #include #include @@ -120,6 +120,9 @@ std::wstring Socket::read(int timeout){ if (!fSuccess) { DWORD err = GetLastError(); + if(err != ERROR_OPERATION_ABORTED){ //gets this "error" always when nothing was reads + debuglog((int)err, "Socket read error"); + } if(err == ERROR_MORE_DATA){ moreData = true; @@ -127,7 +130,8 @@ std::wstring Socket::read(int timeout){ else{ buf[0] = 0; } - if (err == ERROR_BROKEN_PIPE) { + if (err == ERROR_BROKEN_PIPE){ + debuglog(222, "Got an error, close this socket"); d->connected = false; } } diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index a223a114..934479a1 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -23,6 +23,8 @@ #include #include +#include + inline void msleep( const int msec) { #ifdef _WINDOWS Sleep(msec); @@ -40,11 +42,11 @@ inline void dlog(const char *fmt, ...) { fflush(stdout); } -inline void debuglog(const int intMessage, const std::string strMessage){ +inline void debuglogfilename(const int intMessage, const std::string strMessage, const std::string filename){ #ifdef _WINDOWS static bool firstRun = true; std::ofstream file; - std::string filename("C:/log_locks.txt"); + if (firstRun) { file.open(filename.c_str(), std::ios::out); firstRun = false; @@ -52,7 +54,14 @@ inline void debuglog(const int intMessage, const std::string strMessage){ file.open(filename.c_str(), std::ios::out | std::ios::app); } - file << "[" << GetCurrentThreadId() << "] " << intMessage << " - " << strMessage << "\n"; + time_t now = time(0); + + // Convert now to tm struct for local timezone + tm* localtm = localtime(&now); + char* thetime = asctime(localtm); + thetime[strlen(thetime)-1] = '\0'; + + file << thetime << " [" << GetCurrentThreadId() << "] " << intMessage << " - " << strMessage << "\n"; file.flush(); file.close(); @@ -65,6 +74,16 @@ inline void debuglog(const int intMessage, const std::string strMessage){ #endif } +inline void debuglogservice(const int intMessage, const std::string strMessage){ + std::string filename("C:/telldus_service_debug.txt"); + debuglogfilename(intMessage, strMessage, filename); +} + +inline void debuglog(const int intMessage, const std::string strMessage){ + std::string filename("C:/telldus_client_debug.txt"); + debuglogfilename(intMessage, strMessage, filename); +} + inline char *wrapStdString( const std::string &string) { #ifdef _WINDOWS return (char *)SysAllocStringByteLen(string.c_str(), (unsigned int)string.size()); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 52fef5be..12f736cc 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -5,6 +5,11 @@ #include "Message.h" #include "Socket.h" +#include "common.h" //debug +#include //debug +#include //debug + + #include #include @@ -119,8 +124,13 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ } else{ //connection is dead, remove it + debuglogservice(0, "Lost connection, removing it"); delete *it; it = d->clients.erase(it); } } + //printf("Sent message to %d connected clients", connected) + std::stringstream strMessage; + strMessage << "Sent message to " << connected << " clients" << std::endl; + debuglogservice(0, strMessage.str()); } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index a45f9899..87316a60 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -8,6 +8,7 @@ #include "EventUpdateManager.h" #include "Timer.h" #include "Log.h" +#include "common.h" //debug #include #include @@ -57,6 +58,8 @@ void TelldusMain::suspend() { } void TelldusMain::start(void) { + //Logga, starta service + debuglogservice(0, "Starting service"); TelldusCore::EventRef clientEvent = d->eventHandler.addEvent(); TelldusCore::EventRef dataEvent = d->eventHandler.addEvent(); TelldusCore::EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups From 7ee840792288a3fa4d4bf7d6bb0ced0fb7ff5647 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 3 Sep 2012 17:00:17 +0200 Subject: [PATCH 2080/2215] Leave read loop on broken pipe --- telldus-core/common/Socket_win.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 301735c3..068c82d1 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -133,6 +133,7 @@ std::wstring Socket::read(int timeout){ if (err == ERROR_BROKEN_PIPE){ debuglog(222, "Got an error, close this socket"); d->connected = false; + break; //TODO is this correct? } } returnString.append(buf); From 22e8549e7e72407e0e8521f8335369e13102bd72 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Sep 2012 15:05:03 +0200 Subject: [PATCH 2081/2215] Follow better the 'Apple Create Rule' for our variables. This fixes a memory leak. Closes #240 --- .../service/SettingsCoreFoundationPreferences.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index 46b6031b..4da84fe6 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -81,22 +81,21 @@ int Settings::getNumberOfNodes(Node type) const { int Settings::getNodeId(Node type, int intNodeIndex) const { CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); - if (!cfarray) return 0; + if (!cfarray) { + return 0; + } CFIndex size = CFArrayGetCount( cfarray ); int index = 0; int id = 0; for (CFIndex k = 0; k < size; ++k) { CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); if (!CFStringHasSuffix( key, CFSTR(".name") )) { - CFRelease( key ); continue; } if ( type == Device && !CFStringHasPrefix(key, CFSTR("devices.")) ) { - CFRelease( key ); continue; } if ( type == Controller && !CFStringHasPrefix(key, CFSTR("controllers.")) ) { - CFRelease( key ); continue; } if (index == intNodeIndex) { @@ -123,13 +122,12 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { } free(cp); - CFRelease(key); CFRelease(split); - CFRelease(cfid); break; } index++; } + CFRelease(cfarray); return id; } From f5756e3f930c972ef9627e8b679f7d1863ea32be Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Sep 2012 16:16:44 +0200 Subject: [PATCH 2082/2215] Update TellStick_ftd2xx.cpp to our style guidelines --- telldus-core/service/TellStick_ftd2xx.cpp | 90 +++++++++++------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index d4d8efc4..66e965d4 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -9,17 +9,19 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "TellStick.h" -#include "common.h" -#include "Mutex.h" -#include "Settings.h" -#include "Strings.h" -#include "Log.h" -#include "../client/telldus-core.h" #include #include +#include +#include +#include "common/common.h" +#include "common/Mutex.h" +#include "common/Strings.h" +#include "service/Log.h" +#include "service/Settings.h" +#include "service/TellStick.h" +#include "../client/telldus-core.h" -#include "ftd2xx.h" +#include "service/ftd2xx.h" class TellStick::PrivateData { public: @@ -32,7 +34,7 @@ public: #ifdef _WINDOWS HANDLE eh; #else -//#include +// #include struct { pthread_cond_t eCondVar; pthread_mutex_t eMutex; @@ -41,8 +43,7 @@ public: }; TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &td ) - :Controller(controllerId, event, updateEvent) -{ + :Controller(controllerId, event, updateEvent) { d = new PrivateData; #ifdef _WINDOWS d->eh = CreateEvent( NULL, false, false, NULL ); @@ -56,13 +57,13 @@ TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore: d->pid = td.pid; d->serial = td.serial; Settings set; - d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation")==L"true"; + d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation") == L"true"; char *tempSerial = new char[td.serial.size()+1]; #ifdef _WINDOWS strcpy_s(tempSerial, td.serial.size()+1, td.serial.c_str()); #else - strcpy(tempSerial, td.serial.c_str()); + snprintf(tempSerial, td.serial.size()+1, "%s", td.serial.c_str()); FT_SetVIDPID(td.vid, td.pid); #endif Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str()); @@ -71,7 +72,7 @@ TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore: if (ftStatus == FT_OK) { d->open = true; FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0); - FT_SetTimeouts(d->ftHandle,5000,0); + FT_SetTimeouts(d->ftHandle, 5000, 0); } if (d->open) { @@ -139,29 +140,29 @@ bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const { void TellStick::processData( const std::string &data ) { for (unsigned int i = 0; i < data.length(); ++i) { - if (data[i] == 13) { // Skip \r + if (data[i] == 13) { // Skip \r continue; - } else if (data[i] == 10) { // \n found - if (d->message.substr(0,2).compare("+V") == 0) { + } else if (data[i] == 10) { // \n found + if (d->message.substr(0, 2).compare("+V") == 0) { setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str())); - } else if (d->message.substr(0,2).compare("+R") == 0) { + } else if (d->message.substr(0, 2).compare("+R") == 0) { this->publishData(d->message.substr(2)); - } else if(d->message.substr(0,2).compare("+W") == 0) { + } else if(d->message.substr(0, 2).compare("+W") == 0) { this->decodePublishData(d->message.substr(2)); } d->message.clear(); - } else { // Append the character + } else { // Append the character d->message.append( 1, data[i] ); } } } -int TellStick::reset(){ +int TellStick::reset() { #ifndef _WINDOWS - return TELLSTICK_SUCCESS; //nothing to be done on other platforms + return TELLSTICK_SUCCESS; // nothing to be done on other platforms #else int success = FT_CyclePort( d->ftHandle ); - if(success == FT_OK){ + if(success == FT_OK) { return TELLSTICK_SUCCESS; } return TELLSTICK_ERROR_UNKNOWN; @@ -174,14 +175,14 @@ void TellStick::run() { DWORD dwBytesRead = 0; char *buf = 0; - //Send a firmware version request + // Send a firmware version request char msg[] = "V+"; FT_Write(d->ftHandle, msg, (DWORD)strlen(msg), &dwBytesRead); while(1) { #ifdef _WINDOWS FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, d->eh); - WaitForSingleObject(d->eh,INFINITE); + WaitForSingleObject(d->eh, INFINITE); #else FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, (PVOID)&d->eh); pthread_mutex_lock(&d->eh.eMutex); @@ -198,7 +199,7 @@ void TellStick::run() { d->mutex.unlock(); continue; } - buf = (char*)malloc(sizeof(buf) * (dwBytesInQueue+1)); + buf = reinterpret_cast(malloc(sizeof(buf) * (dwBytesInQueue+1))); memset(buf, 0, dwBytesInQueue+1); FT_Read(d->ftHandle, buf, dwBytesInQueue, &dwBytesRead); processData( buf ); @@ -210,17 +211,17 @@ int TellStick::send( const std::string &strMessage ) { if (!d->open) { return TELLSTICK_ERROR_NOT_FOUND; } - - //This lock does two things - // 1 Prevents two calls from different threads to this function - // 2 Prevents our running thread from receiving the data we are interested in here + + // This lock does two things + // 1 Prevents two calls from different threads to this function + // 2 Prevents our running thread from receiving the data we are interested in here TelldusCore::MutexLocker locker(&d->mutex); - char *tempMessage = (char *)malloc(sizeof(char) * (strMessage.size()+1)); + char *tempMessage = reinterpret_cast(malloc(sizeof(std::string::value_type) * (strMessage.size()+1))); #ifdef _WINDOWS strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str()); #else - strcpy(tempMessage, strMessage.c_str()); + snprintf(tempMessage, strMessage.size()+1, "%s", strMessage.c_str()); #endif ULONG bytesWritten, bytesRead; @@ -228,24 +229,24 @@ int TellStick::send( const std::string &strMessage ) { FT_STATUS ftStatus; ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten); free(tempMessage); - - if(ftStatus != FT_OK){ + + if(ftStatus != FT_OK) { Log::debug("Broken pipe on send"); return TELLSTICK_ERROR_BROKEN_PIPE; } - if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))){ - //these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly + if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))) { + // these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly return TELLSTICK_SUCCESS; } - if(d->ignoreControllerConfirmation){ - //wait for TellStick to finish its air-sending + if(d->ignoreControllerConfirmation) { + // wait for TellStick to finish its air-sending msleep(1000); return TELLSTICK_SUCCESS; } while(1) { - ftStatus = FT_Read(d->ftHandle,&in,1,&bytesRead); + ftStatus = FT_Read(d->ftHandle, &in, 1, &bytesRead); if (ftStatus == FT_OK) { if (bytesRead == 1) { if (in == '\n') { @@ -253,10 +254,10 @@ int TellStick::send( const std::string &strMessage ) { } else { continue; } - } else { //Timeout + } else { // Timeout return TELLSTICK_ERROR_COMMUNICATION; } - } else { //Error + } else { // Error Log::debug("Broken pipe on read"); return TELLSTICK_ERROR_BROKEN_PIPE; } @@ -274,7 +275,7 @@ bool TellStick::stillConnected() const { if (numDevs <= 0) { return false; } - for (int i = 0; i < (int)numDevs; i++) { + for (int i = 0; i < static_cast(numDevs); i++) { FT_HANDLE ftHandleTemp; DWORD flags; DWORD id; @@ -303,7 +304,6 @@ std::list TellStick::findAll() { } return tellstick; - } std::list TellStick::findAllByVIDPID( int vid, int pid ) { @@ -323,8 +323,8 @@ std::list TellStick::findAllByVIDPID( int vid, int pid ) { if (dwNumberOfDevices > 0) { FT_DEVICE_LIST_INFO_NODE *devInfo; // allocate storage for list based on dwNumberOfDevices - devInfo = (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*dwNumberOfDevices); // get the device information list - ftStatus = FT_GetDeviceInfoList(devInfo,&dwNumberOfDevices); + devInfo = reinterpret_cast(malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*dwNumberOfDevices)); // get the device information list + ftStatus = FT_GetDeviceInfoList(devInfo, &dwNumberOfDevices); if (ftStatus == FT_OK) { unsigned int id = (vid << 16) | pid; for (unsigned int i = 0; i < dwNumberOfDevices; i++) { From bc22754f8c5baefb16e0f1f364390bdf666b3d0e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Sep 2012 16:24:41 +0200 Subject: [PATCH 2083/2215] Update SettingsCoreFoundationPreferences.cpp to our style guidelines --- .../SettingsCoreFoundationPreferences.cpp | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index 4da84fe6..3ce3b4bc 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -9,13 +9,13 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "Settings.h" -#include "Strings.h" #include #include #include - -#include "../client/telldus-core.h" +#include +#include "common/Strings.h" +#include "service/Settings.h" +#include "client/telldus-core.h" class privateVars { public: @@ -34,8 +34,7 @@ public: /* * Constructor */ -Settings::Settings(void) -{ +Settings::Settings(void) { d = new PrivateData(); d->app_ID = CFSTR( "com.telldus.core" ); d->userName = kCFPreferencesAnyUser; @@ -45,8 +44,7 @@ Settings::Settings(void) /* * Destructor */ -Settings::~Settings(void) -{ +Settings::~Settings(void) { delete d; } @@ -103,21 +101,21 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { if ( !split || CFArrayGetCount( split ) != 3 ) continue; // This code crashes! - //CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); - //if (cfid) - // CFNumberGetValue( cfid, kCFNumberIntType, &id); + // CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); + // if (cfid) + // CFNumberGetValue( cfid, kCFNumberIntType, &id); CFStringRef cfid = (CFStringRef) CFArrayGetValueAtIndex( split, 1 ); char *cp = NULL; CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1; - cp = (char *)malloc(size); + cp = reinterpret_cast(malloc(size)); CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 ); - char *newcp = (char *)realloc( cp, strlen(cp) + 1); + char *newcp = reinterpret_cast(realloc( cp, strlen(cp) + 1)); if (newcp != NULL) { cp = newcp; id = atoi(cp); } else { - //Should not happen + // Should not happen id = 0; } free(cp); @@ -136,9 +134,9 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { */ int Settings::addNode(Node type) { int id = getNextNodeId(type); - setStringSetting( type, id, L"name", L"", false ); //Create a empty name so the node has an entry + setStringSetting( type, id, L"name", L"", false ); // Create a empty name so the node has an entry if (type == Device) { - //Is there a reason we do this? + // Is there a reason we do this? setStringSetting( type, id, L"model", L"", false ); } return id; @@ -163,9 +161,9 @@ int Settings::getNextNodeId(Node type) const { /* * Remove a device */ -int Settings::removeNode(Node type, int intNodeId){ +int Settings::removeNode(Node type, int intNodeId) { int ret = TELLSTICK_ERROR_DEVICE_NOT_FOUND; - CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d."), getNodeString(type).c_str(), intNodeId); // The key to search for + CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d."), getNodeString(type).c_str(), intNodeId); // The key to search for CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); if (!cfarray) { @@ -175,7 +173,7 @@ int Settings::removeNode(Node type, int intNodeId){ for (CFIndex k = 0; k < size; ++k) { CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k); if (CFStringHasPrefix( key, filterKey ) ) { - CFPreferencesSetValue( key, NULL, d->app_ID, d->userName, d->hostName ); //Remove the key + CFPreferencesSetValue( key, NULL, d->app_ID, d->userName, d->hostName ); // Remove the key ret = TELLSTICK_SUCCESS; } } @@ -205,14 +203,14 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst std::wstring retval; char *cp = NULL; CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( value ), kCFStringEncodingUTF8) + 1; - cp = (char *)malloc(size); + cp = reinterpret_cast(malloc(size)); CFStringGetCString( value, cp, size, kCFStringEncodingUTF8 ); - char *newcp = (char *)realloc( cp, strlen(cp) + 1); + char *newcp = reinterpret_cast(realloc( cp, strlen(cp) + 1)); if (newcp != NULL) { cp = newcp; retval = TelldusCore::charToWstring(cp); } else { - //Should not happen + // Should not happen retval = L""; } free(cp); From c52217329692e36069c6c0614e4455b617f12a1a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Sep 2012 16:31:27 +0200 Subject: [PATCH 2084/2215] Update ControllerListener_mac.cpp to our style guidelines --- .../service/ControllerListener_mac.cpp | 113 +++++++++--------- 1 file changed, 59 insertions(+), 54 deletions(-) diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp index bf2af63a..1843474c 100644 --- a/telldus-core/service/ControllerListener_mac.cpp +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -1,10 +1,17 @@ -#include "ControllerListener.h" +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "service/ControllerListener.h" #include #include #include #include #include +#include class TellStickData { public: @@ -22,15 +29,14 @@ public: io_iterator_t gAddedIter; TelldusCore::EventRef event; bool running; - + void addUsbFilter(int vid, int pid); static void DeviceAdded(void *refCon, io_iterator_t iterator); static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); }; ControllerListener::ControllerListener(TelldusCore::EventRef event) -:Thread() -{ +:Thread() { d = new PrivateData; d->event = event; d->running = true; @@ -48,135 +54,134 @@ ControllerListener::~ControllerListener() { } void ControllerListener::run() { - CFRunLoopSourceRef runLoopSource; - + CFRunLoopSourceRef runLoopSource; + d->gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault); - runLoopSource = IONotificationPortGetRunLoopSource(d->gNotifyPort); - + runLoopSource = IONotificationPortGetRunLoopSource(d->gNotifyPort); + d->gRunLoop = CFRunLoopGetCurrent(); - CFRunLoopAddSource(d->gRunLoop, runLoopSource, kCFRunLoopDefaultMode); - + CFRunLoopAddSource(d->gRunLoop, runLoopSource, kCFRunLoopDefaultMode); + d->addUsbFilter(0x1781, 0x0c30); d->addUsbFilter(0x1781, 0x0c31); - + // Race check, if destructor was called really close to thread init, // running might have gone false. Make sure we don't get stuck - if(d->running) + if (d->running) { CFRunLoopRun(); + } } void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) { - CFNumberRef numberRef; + CFNumberRef numberRef; kern_return_t kr; CFMutableDictionaryRef matchingDict; - matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class - // IOUSBDevice and its subclasses + matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class + // IOUSBDevice and its subclasses if (matchingDict == NULL) { return; } - + // Create a CFNumber for the idVendor and set the value in the dictionary numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vid); CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef); CFRelease(numberRef); - + // Create a CFNumber for the idProduct and set the value in the dictionary numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid); CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef); CFRelease(numberRef); - - // Now set up a notification to be called when a device is first matched by I/O Kit. - kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort - kIOFirstMatchNotification, // notificationType - matchingDict, // matching - PrivateData::DeviceAdded, // callback - this, // refCon - &gAddedIter // notification - ); - // Iterate once to get already-present devices and arm the notification - PrivateData::DeviceAdded(this, gAddedIter); + // Now set up a notification to be called when a device is first matched by I/O Kit. + kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort + kIOFirstMatchNotification, // notificationType + matchingDict, // matching + PrivateData::DeviceAdded, // callback + this, // refCon + &gAddedIter // notification + ); + // Iterate once to get already-present devices and arm the notification + PrivateData::DeviceAdded(this, gAddedIter); } void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { kern_return_t kr; - - if (messageType != kIOMessageServiceIsTerminated) { + + if (messageType != kIOMessageServiceIsTerminated) { return; } - + TellStickData *tsd = reinterpret_cast (refCon); if (!tsd) { return; } - + CFIndex size = CFStringGetLength(tsd->serialNumber); char *s = new char[size+1]; CFStringGetCString(tsd->serialNumber, s, size+1, kCFStringEncodingASCII); - std::string serial(s); //Copy the string to the stack + std::string serial(s); // Copy the string to the stack delete[] s; - + ControllerChangeEventData *data = new ControllerChangeEventData; data->vid = tsd->vid; data->pid = tsd->pid; data->inserted = false; tsd->event->signal(data); - + // Free the data we're no longer using now that the device is going away CFRelease(tsd->serialNumber); - + kr = IOObjectRelease(tsd->notification); - + delete tsd; } void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t iterator) { - io_service_t usbDevice; - kern_return_t kr; - + io_service_t usbDevice; + kern_return_t kr; + PrivateData *pd = reinterpret_cast (refCon); - + while ((usbDevice = IOIteratorNext(iterator))) { TellStickData *tsd = new TellStickData; tsd->event = pd->event; - + // Get the serial number CFStringRef serialRef = reinterpret_cast(IORegistryEntryCreateCFProperty( usbDevice, CFSTR("USB Serial Number" ), kCFAllocatorDefault, 0 )); if (serialRef == NULL) { - //No serial number, we cannot continue. Sorry + // No serial number, we cannot continue. Sorry continue; } - CFNumberRef vidRef = reinterpret_cast (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idVendor"), kCFAllocatorDefault, 0)); if (vidRef) { CFNumberGetValue(vidRef, kCFNumberIntType, &(tsd->vid)); CFRelease(vidRef); } - + CFNumberRef pidRef = reinterpret_cast (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idProduct"), kCFAllocatorDefault, 0)); if (pidRef) { CFNumberGetValue(pidRef, kCFNumberIntType, &(tsd->pid)); CFRelease(pidRef); } - + CFStringRef serialNumberAsCFString = CFStringCreateCopy(kCFAllocatorDefault, serialRef); tsd->serialNumber = serialNumberAsCFString; - CFRelease(serialRef); - + CFRelease(serialRef); + // Register for an interest notification of this device being removed. Use a reference to our - // private data as the refCon which will be passed to the notification callback. - kr = IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); - + // private data as the refCon which will be passed to the notification callback. + kr = IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); + CFIndex size = CFStringGetLength(serialNumberAsCFString); char *s = new char[size+1]; CFStringGetCString(serialNumberAsCFString, s, size+1, kCFStringEncodingASCII); - std::string serial(s); //Copy the string to the stack + std::string serial(s); // Copy the string to the stack delete[] s; - + kr = IOObjectRelease(usbDevice); - + ControllerChangeEventData *data = new ControllerChangeEventData; data->vid = tsd->vid; data->pid = tsd->pid; From 609f7581ea1d6d898a6b3e5faa184a1871be071a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Sep 2012 16:32:36 +0200 Subject: [PATCH 2085/2215] Update main_mac.cpp to our style guidelines --- telldus-core/service/main_mac.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/main_mac.cpp b/telldus-core/service/main_mac.cpp index f87b718a..1976891c 100644 --- a/telldus-core/service/main_mac.cpp +++ b/telldus-core/service/main_mac.cpp @@ -1,6 +1,12 @@ -#include "TelldusMain.h" -#include "Log.h" +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include +#include "service/TelldusMain.h" +#include "service/Log.h" TelldusMain tm; From ccc027b381a1dc953b689075c6df84421ebc2f13 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Sep 2012 16:39:05 +0200 Subject: [PATCH 2086/2215] Update stdlibc_workaround.cpp to our style guidelines --- telldus-core/common/stdlibc_workaround.cpp | 80 ++++++++++++---------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/telldus-core/common/stdlibc_workaround.cpp b/telldus-core/common/stdlibc_workaround.cpp index 78aaaa65..3b348c7a 100644 --- a/telldus-core/common/stdlibc_workaround.cpp +++ b/telldus-core/common/stdlibc_workaround.cpp @@ -1,47 +1,53 @@ -#include +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include // NOLINT(readability/streams) // Workarounds for symbols that are missing from Leopard stdlibc++.dylib. _GLIBCXX_BEGIN_NAMESPACE(std) // From ostream_insert.h template ostream& __ostream_insert(ostream&, const char*, streamsize); #ifdef _GLIBCXX_USE_WCHAR_T - template wostream& __ostream_insert(wostream&, const wchar_t*, streamsize); + template wostream& __ostream_insert(wostream&, const wchar_t*, streamsize); #endif // From ostream.tcc -template ostream& ostream::_M_insert(long); -template ostream& ostream::_M_insert(unsigned long); -template ostream& ostream::_M_insert(bool); +template ostream& ostream::_M_insert(long); // NOLINT(runtime/int) +template ostream& ostream::_M_insert(unsigned long); // NOLINT(runtime/int) +template ostream& ostream::_M_insert(bool); // NOLINT(readability/function) #ifdef _GLIBCXX_USE_LONG_LONG - template ostream& ostream::_M_insert(long long); - template ostream& ostream::_M_insert(unsigned long long); + template ostream& ostream::_M_insert(long long); // NOLINT(runtime/int) + template ostream& ostream::_M_insert(unsigned long long); // NOLINT(runtime/int) #endif -template ostream& ostream::_M_insert(double); +template ostream& ostream::_M_insert(double); // NOLINT(readability/function) template ostream& ostream::_M_insert(long double); template ostream& ostream::_M_insert(const void*); #ifdef _GLIBCXX_USE_WCHAR_T - template wostream& wostream::_M_insert(long); - template wostream& wostream::_M_insert(unsigned long); - template wostream& wostream::_M_insert(bool); - #ifdef _GLIBCXX_USE_LONG_LONG - template wostream& wostream::_M_insert(long long); - template wostream& wostream::_M_insert(unsigned long long); - #endif - template wostream& wostream::_M_insert(double); - template wostream& wostream::_M_insert(long double); - template wostream& wostream::_M_insert(const void*); + template wostream& wostream::_M_insert(long); // NOLINT(runtime/int) + template wostream& wostream::_M_insert(unsigned long); // NOLINT(runtime/int) + template wostream& wostream::_M_insert(bool); // NOLINT(readability/function) + #ifdef _GLIBCXX_USE_LONG_LONG + template wostream& wostream::_M_insert(long long); // NOLINT(runtime/int) + template wostream& wostream::_M_insert(unsigned long long); // NOLINT(runtime/int) + #endif + template wostream& wostream::_M_insert(double); // NOLINT(readability/function) + template wostream& wostream::_M_insert(long double); + template wostream& wostream::_M_insert(const void*); #endif // From istream.tcc -template istream& istream::_M_extract(unsigned short&); -template istream& istream::_M_extract(unsigned int&); -template istream& istream::_M_extract(long&); -template istream& istream::_M_extract(unsigned long&); +template istream& istream::_M_extract(unsigned short&); // NOLINT(runtime/int) +template istream& istream::_M_extract(unsigned int&); +template istream& istream::_M_extract(long&); // NOLINT(runtime/int) +template istream& istream::_M_extract(unsigned long&); // NOLINT(runtime/int) template istream& istream::_M_extract(bool&); #ifdef _GLIBCXX_USE_LONG_LONG - template istream& istream::_M_extract(long long&); - template istream& istream::_M_extract(unsigned long long&); + template istream& istream::_M_extract(long long&); // NOLINT(runtime/int) + template istream& istream::_M_extract(unsigned long long&); // NOLINT(runtime/int) #endif template istream& istream::_M_extract(float&); template istream& istream::_M_extract(double&); @@ -49,19 +55,19 @@ template istream& istream::_M_extract(long double&); template istream& istream::_M_extract(void*&); #ifdef _GLIBCXX_USE_WCHAR_T - template wistream& wistream::_M_extract(unsigned short&); - template wistream& wistream::_M_extract(unsigned int&); - template wistream& wistream::_M_extract(long&); - template wistream& wistream::_M_extract(unsigned long&); - template wistream& wistream::_M_extract(bool&); - #ifdef _GLIBCXX_USE_LONG_LONG - template wistream& wistream::_M_extract(long long&); - template wistream& wistream::_M_extract(unsigned long long&); - #endif - template wistream& wistream::_M_extract(float&); - template wistream& wistream::_M_extract(double&); - template wistream& wistream::_M_extract(long double&); - template wistream& wistream::_M_extract(void*&); + template wistream& wistream::_M_extract(unsigned short&); // NOLINT(runtime/int) + template wistream& wistream::_M_extract(unsigned int&); + template wistream& wistream::_M_extract(long&); // NOLINT(runtime/int) + template wistream& wistream::_M_extract(unsigned long&); // NOLINT(runtime/int) + template wistream& wistream::_M_extract(bool&); + #ifdef _GLIBCXX_USE_LONG_LONG + template wistream& wistream::_M_extract(long long&); // NOLINT(runtime/int) + template wistream& wistream::_M_extract(unsigned long long&); // NOLINT(runtime/int) + #endif + template wistream& wistream::_M_extract(float&); + template wistream& wistream::_M_extract(double&); + template wistream& wistream::_M_extract(long double&); + template wistream& wistream::_M_extract(void*&); #endif _GLIBCXX_END_NAMESPACE From bc777e04ca387170c3ebf6afaa492a26bd0357c2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 26 Sep 2012 16:43:19 +0200 Subject: [PATCH 2087/2215] Add cppunit on OS X as well --- telldus-core/tests/CMakeLists.txt | 3 ++- telldus-core/tests/common/CMakeLists.txt | 2 +- telldus-core/tests/service/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index c1c8fa9e..3d78b0c6 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -30,6 +30,7 @@ FUNCTION(ADD_SOURCES TARGET PATH) ENDFUNCTION() IF(ENABLE_TESTING) + FIND_LIBRARY(CPPUNIT cppunit) ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(service) @@ -42,7 +43,7 @@ IF(ENABLE_TESTING) ADD_SOURCES(${telldus-service_TARGET} ${CMAKE_SOURCE_DIR}/service) ADD_TEST(cppunit ${CMAKE_CURRENT_BINARY_DIR}/TestRunner) - IF (UNIX AND NOT APPLE) + IF (UNIX) ADD_TEST(cppcheck cppcheck --quiet --error-exitcode=2 ${CMAKE_SOURCE_DIR}) ENDIF() ENDIF() diff --git a/telldus-core/tests/common/CMakeLists.txt b/telldus-core/tests/common/CMakeLists.txt index 4c7fca41..ae52a231 100644 --- a/telldus-core/tests/common/CMakeLists.txt +++ b/telldus-core/tests/common/CMakeLists.txt @@ -4,6 +4,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common) ADD_LIBRARY(TelldusCommonTests SHARED ${SRCS} ) -TARGET_LINK_LIBRARIES( TelldusCommonTests TelldusCommon ) +TARGET_LINK_LIBRARIES( TelldusCommonTests TelldusCommon ${CPPUNIT} ) ADD_DEPENDENCIES( TelldusCommonTests TelldusCommon ) diff --git a/telldus-core/tests/service/CMakeLists.txt b/telldus-core/tests/service/CMakeLists.txt index 0e795cd8..d43357a0 100644 --- a/telldus-core/tests/service/CMakeLists.txt +++ b/telldus-core/tests/service/CMakeLists.txt @@ -4,6 +4,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) ADD_LIBRARY(TelldusServiceTests SHARED ${SRCS} ) -TARGET_LINK_LIBRARIES( TelldusServiceTests TelldusServiceStatic ) +TARGET_LINK_LIBRARIES( TelldusServiceTests TelldusServiceStatic ${CPPUNIT} ) ADD_DEPENDENCIES( TelldusServiceTests ${telldus-service_TARGET} ) From 4d1fdd777f5c4e992a5c3079b7acc8ccbe65adfe Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 30 Oct 2012 15:58:01 +0100 Subject: [PATCH 2088/2215] Comparison of unsigned expression < 0 is always false --- telldus-core/service/ProtocolEverflourish.cpp | 2 +- telldus-core/service/ProtocolNexa.cpp | 2 +- telldus-core/service/ProtocolOregon.cpp | 3 ++- telldus-core/service/ProtocolSartano.cpp | 2 +- telldus-core/service/ProtocolWaveman.cpp | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/telldus-core/service/ProtocolEverflourish.cpp b/telldus-core/service/ProtocolEverflourish.cpp index 72ee8867..cc193931 100644 --- a/telldus-core/service/ProtocolEverflourish.cpp +++ b/telldus-core/service/ProtocolEverflourish.cpp @@ -111,7 +111,7 @@ std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) { method = allData & 0xF; - if(house < 0 || house > 16383 || unit < 1 || unit > 4) { + if(house > 16383 || unit < 1 || unit > 4) { // not everflourish return ""; } diff --git a/telldus-core/service/ProtocolNexa.cpp b/telldus-core/service/ProtocolNexa.cpp index b6143d59..76cc1efc 100644 --- a/telldus-core/service/ProtocolNexa.cpp +++ b/telldus-core/service/ProtocolNexa.cpp @@ -227,7 +227,7 @@ std::string ProtocolNexa::decodeDataCodeSwitch(uint64_t allData) { house = allData & 0xF; - if(house < 0 || house > 16 || unit < 1 || unit > 16) { + if(house > 16 || unit < 1 || unit > 16) { // not arctech codeswitch return ""; } diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 3c397651..e879c46c 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -51,7 +51,8 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { value >>= 8; checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t channel = (value >> 4) & 0x7; + // channel not used + // uint8_t channel = (value >> 4) & 0x7; if (checksum != checksumw) { return ""; diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 33d6eb84..9c6931aa 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -76,7 +76,7 @@ std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) { return ""; } - if(code < 0 || code > 1023) { + if(code > 1023) { // not sartano return ""; } diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index 61484cd5..dec84412 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -41,7 +41,7 @@ std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) { house = allData & 0xF; - if(house < 0 || house > 16 || unit < 1 || unit > 16) { + if(house > 16 || unit < 1 || unit > 16) { // not waveman return ""; } From 9d5af14609032c0579aa60a039c588c7e7ba6d1a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 30 Oct 2012 15:58:34 +0100 Subject: [PATCH 2089/2215] Fix some compiler warnings --- telldus-core/common/Message.cpp | 3 +-- telldus-core/service/ProtocolFineoffset.cpp | 3 ++- telldus-core/service/ProtocolMandolyn.cpp | 6 ++++-- telldus-core/service/ProtocolOregon.cpp | 6 ++++-- telldus-core/service/Settings.cpp | 1 + telldus-core/tdtool/main.cpp | 1 + 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/telldus-core/common/Message.cpp b/telldus-core/common/Message.cpp index f06c75fb..6fbea009 100644 --- a/telldus-core/common/Message.cpp +++ b/telldus-core/common/Message.cpp @@ -60,7 +60,7 @@ void Message::addSpecialArgument(const std::wstring &value){ this->append(L":"); this->append(value); - /* + std::wstringstream st; st << (int)value.size(); this->append(st.str()); @@ -74,7 +74,6 @@ void Message::addSpecialArgument(int value){ int i = 0; while(i<1000000){ i++; - /* //std::wstringstream st; //st << (int)value; this->append(L"i"); diff --git a/telldus-core/service/ProtocolFineoffset.cpp b/telldus-core/service/ProtocolFineoffset.cpp index c4daca58..2fd6f5ae 100644 --- a/telldus-core/service/ProtocolFineoffset.cpp +++ b/telldus-core/service/ProtocolFineoffset.cpp @@ -17,7 +17,8 @@ std::string ProtocolFineoffset::decodeData(const ControllerMessage &dataMsg) { return ""; } - uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); + // Checksum currently not used + // uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); data = data.substr(0, data.length()-2); uint8_t humidity = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2)); diff --git a/telldus-core/service/ProtocolMandolyn.cpp b/telldus-core/service/ProtocolMandolyn.cpp index 1f5f3155..c37555c0 100644 --- a/telldus-core/service/ProtocolMandolyn.cpp +++ b/telldus-core/service/ProtocolMandolyn.cpp @@ -15,7 +15,8 @@ std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) { std::string data = dataMsg.getParameter("data"); uint32_t value = (uint32_t)TelldusCore::hexTo64l(data); - bool parity = value & 0x1; + // parity not used + // bool parity = value & 0x1; value >>= 1; double temp = static_cast(value & 0x7FFF) - static_cast(6400); @@ -25,7 +26,8 @@ std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) { uint8_t humidity = (value & 0x7F); value >>= 7; - bool battOk = value & 0x1; + // battOk not used + // bool battOk = value & 0x1; value >>= 3; uint8_t channel = (value & 0x3)+1; diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index e879c46c..231f71ec 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -72,7 +72,8 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { std::string ProtocolOregon::decode1A2D(const std::string &data) { uint64_t value = TelldusCore::hexTo64l(data); - uint8_t checksum2 = value & 0xFF; + // checksum2 not used yet + // uint8_t checksum2 = value & 0xFF; value >>= 8; uint8_t checksum1 = value & 0xFF; value >>= 8; @@ -100,7 +101,8 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { value >>= 8; checksum += ((value >> 4) & 0xF) + (value & 0xF); - uint8_t channel = (value >> 4) & 0x7; + // channel not used + // uint8_t channel = (value >> 4) & 0x7; checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA; diff --git a/telldus-core/service/Settings.cpp b/telldus-core/service/Settings.cpp index 46090256..296c49d2 100644 --- a/telldus-core/service/Settings.cpp +++ b/telldus-core/service/Settings.cpp @@ -115,6 +115,7 @@ std::string Settings::getNodeString(Settings::Node type) const { } else if (type == Controller) { return "controller"; } + return ""; } #ifndef _CONFUSE diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index 0b75771b..c21b1e98 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -267,6 +267,7 @@ int list_kv_devices() { printf("\n"); index++; } + return TELLSTICK_SUCCESS; } From d0b1dbba0e8992e28c2f9bccf2540f9d95dea95d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 2 Nov 2012 13:08:43 +0100 Subject: [PATCH 2090/2215] Do not unlock the mutex manually since we are using a MutexLocker. Unlocking a mutex twice seems to cause deadlocks on OS X if we stress the library. Windows seems unaffected. See #260. --- telldus-core/service/TellStick_ftd2xx.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/service/TellStick_ftd2xx.cpp b/telldus-core/service/TellStick_ftd2xx.cpp index 66e965d4..23c5677f 100644 --- a/telldus-core/service/TellStick_ftd2xx.cpp +++ b/telldus-core/service/TellStick_ftd2xx.cpp @@ -196,7 +196,6 @@ void TellStick::run() { } FT_GetQueueStatus(d->ftHandle, &dwBytesInQueue); if (dwBytesInQueue < 1) { - d->mutex.unlock(); continue; } buf = reinterpret_cast(malloc(sizeof(buf) * (dwBytesInQueue+1))); From aa16302e1e03730f85fba1699b9083ba9d26d00f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 2 Nov 2012 13:34:34 +0100 Subject: [PATCH 2091/2215] Add function ControllerManager::count() This function also rescans the controllers to add new ones if none is connected. --- telldus-core/service/ControllerManager.cpp | 25 ++++++++++++++++++++++ telldus-core/service/ControllerManager.h | 1 + 2 files changed, 26 insertions(+) diff --git a/telldus-core/service/ControllerManager.cpp b/telldus-core/service/ControllerManager.cpp index 0cc90a99..b02d65a5 100644 --- a/telldus-core/service/ControllerManager.cpp +++ b/telldus-core/service/ControllerManager.cpp @@ -57,6 +57,31 @@ ControllerManager::~ControllerManager() { delete d; } +int ControllerManager::count() { + unsigned int count = 0; + { + TelldusCore::MutexLocker locker(&d->mutex); + // Find all available controllers + for(ControllerMap::const_iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (it->second.controller) { + ++count; + } + } + } + if (count == 0) { + this->loadControllers(); + // Try again + TelldusCore::MutexLocker locker(&d->mutex); + // Find all available controllers + for(ControllerMap::const_iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) { + if (it->second.controller) { + ++count; + } + } + } + return count; +} + void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) { if (vid == 0x0 && pid == 0x0) { // All if (inserted) { diff --git a/telldus-core/service/ControllerManager.h b/telldus-core/service/ControllerManager.h index f5e583b5..093caf2b 100644 --- a/telldus-core/service/ControllerManager.h +++ b/telldus-core/service/ControllerManager.h @@ -19,6 +19,7 @@ public: void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted); + int count(); Controller *getBestControllerById(int id); void loadControllers(); void loadStoredControllers(); From 35dbc0a9806184f9b0d26b9bf3712c637eca0713 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 2 Nov 2012 15:03:57 +0100 Subject: [PATCH 2092/2215] Report humidity for Oregon 0x1A2D. This closes #221. --- telldus-core/service/ProtocolOregon.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 231f71ec..54b288f4 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -115,10 +115,12 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { if (neg) { temperature = -temperature; } + int humidity = (hum1 * 10.0) + hum2; std::stringstream retString; retString << "class:sensor;protocol:oregon;model:1A2D;id:" << static_cast(address) - << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + << ";temp:" << std::fixed << std::setprecision(1) << temperature + << ";humidity:" << humidity << ";"; return retString.str(); } From 2368b6e564fa49dd9e098296fcf2ea6949f1fefa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 2 Nov 2012 16:18:27 +0100 Subject: [PATCH 2093/2215] Add function Device::isMethodSupported() This function both checks if a method is supported and also "upmask" a method if it was masked previously. --- telldus-core/service/Device.cpp | 44 ++++++++++++++++++++++----------- telldus-core/service/Device.h | 1 + 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/telldus-core/service/Device.cpp b/telldus-core/service/Device.cpp index 5a24bc9f..6aa44ac8 100644 --- a/telldus-core/service/Device.cpp +++ b/telldus-core/service/Device.cpp @@ -148,23 +148,11 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { return TELLSTICK_ERROR_CONFIG_SYNTAX; } // Try to determine if we need to call another method due to masking - int methods = p->methods(); - if ((action & methods) == 0) { - // Loop all methods an see if any method masks to this one - for(int i = 1; i <= methods; i <<= 1) { - if ((i & methods) == 0) { - continue; - } - if (this->maskUnsupportedMethods(i, action)) { - action = i; - break; - } - } - } - if ((action & methods) == 0) { + int method = this->isMethodSupported(action); + if (method <= 0) { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } - std::string code = p->getStringForMethod(action, data, controller); + std::string code = p->getStringForMethod(method, data, controller); if (code == "") { return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } @@ -189,6 +177,32 @@ int Device::doAction(int action, unsigned char data, Controller *controller) { return controller->send(code); } +int Device::isMethodSupported(int method) const { + Protocol *p = this->retrieveProtocol(); + if (!p) { + // Syntax error in configuration, no such protocol + return TELLSTICK_ERROR_CONFIG_SYNTAX; + } + // Try to determine if we need to call another method due to masking + int methods = p->methods(); + if ((method & methods) == 0) { + // Loop all methods an see if any method masks to this one + for(int i = 1; i <= methods; i <<= 1) { + if ((i & methods) == 0) { + continue; + } + if (this->maskUnsupportedMethods(i, method)) { + method = i; + break; + } + } + } + if ((method & methods) == 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; + } + return method; +} + Protocol* Device::retrieveProtocol() const { if (d->protocol) { return d->protocol; diff --git a/telldus-core/service/Device.h b/telldus-core/service/Device.h index 8ef9107d..35b3668c 100644 --- a/telldus-core/service/Device.h +++ b/telldus-core/service/Device.h @@ -19,6 +19,7 @@ public: ~Device(void); int doAction(int action, unsigned char data, Controller *controller); + int isMethodSupported(int method) const; std::wstring getStateValue(); int getLastSentCommand(int methodsSupported); int getMethods() const; From c3bcd642465801d14a57adf3e44b5303e899353a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 2 Nov 2012 19:42:12 +0100 Subject: [PATCH 2094/2215] Queue all device commands and execute them from the main thread. By queueing all commands the client library will return immediately and all executed commands will not block any more. This is benificial for applications that calls the api using the same thread as the ui thread. For instance groups could before take several seconds to execute and the application would freeze in the meantime. If the time to execute was longer than the timeout between telldus-core and telldusd other nasty stuff like resending the same group up to 20 times could happen. This change fixes all that with the drawback that we do not really know if the command was succuessful when returning. We do the best to check all prerequisites to determine it the call will be successful. Errors like TELLSTICK_ERROR_COMMUNICATION and TELLSTICK_ERROR_BROKEN_PIPE will not be reported back to the client. We can still log them though. This fixes #260. Please reopen if the issue still exists. --- telldus-core/service/DeviceManager.cpp | 255 ++++++++++++++----------- telldus-core/service/DeviceManager.h | 5 +- telldus-core/service/TelldusMain.cpp | 5 + 3 files changed, 149 insertions(+), 116 deletions(-) diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 3524e157..1b1b7839 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -30,9 +31,17 @@ public: Settings set; TelldusCore::Mutex lock; ControllerManager *controllerManager; - TelldusCore::EventRef deviceUpdateEvent; + TelldusCore::EventRef deviceUpdateEvent, executeActionEvent; }; +class ExecuteActionEventData : public TelldusCore::EventDataBase { +public: + int deviceId; + int method; + unsigned char data; +}; + + DeviceManager::DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent) { d = new PrivateData; d->controllerManager = controllerManager; @@ -55,6 +64,66 @@ DeviceManager::~DeviceManager(void) { delete d; } +void DeviceManager::executeActionEvent() { + Device *device = 0; + TelldusCore::EventDataRef eventData = d->executeActionEvent->takeSignal(); + ExecuteActionEventData *data = dynamic_cast(eventData.get()); + if (!data) { + Log::error("Could not cast executeAction data"); + return; + } + Log::notice("Execute a TellStick Action for device %i", data->deviceId); + + std::auto_ptr deviceLocker(0); + { + // devicelist locked + TelldusCore::MutexLocker deviceListLocker(&d->lock); + + DeviceMap::iterator it = d->devices.find(data->deviceId); + if (it == d->devices.end()) { + return; + } + // device locked + deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); + device = it->second; + } // devicelist unlocked + + Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); + if(!controller) { + return; + } + + int retval = device->doAction(data->method, data->data, controller); + if(retval == TELLSTICK_ERROR_BROKEN_PIPE) { + Log::warning("Error in communication with TellStick when executing action. Resetting USB"); + d->controllerManager->resetController(controller); + } + if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND) { + Log::warning("Rescanning USB ports"); + d->controllerManager->loadControllers(); + controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); + if(!controller) { + Log::error("No contoller (TellStick) found, even after reset. Giving up."); + return; + } + retval = device->doAction(data->method, data->data, controller); // retry one more time + } + + if(retval == TELLSTICK_SUCCESS && device->getMethods() & data->method) { + // if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state + std::wstring datastring = TelldusCore::charUnsignedToWstring(data->data); + if (this->triggerDeviceStateChange(data->deviceId, data->method, datastring)) { + device->setLastSentCommand(data->method, datastring); + d->set.setDeviceState(data->deviceId, data->method, datastring); + } + } + +} + +void DeviceManager::setExecuteActionEvent(TelldusCore::EventRef event) { + d->executeActionEvent = event; +} + void DeviceManager::fillDevices() { int numberOfDevices = d->set.getNumberOfNodes(Settings::Device); TelldusCore::MutexLocker deviceListLocker(&d->lock); @@ -375,144 +444,100 @@ void DeviceManager::disconnectTellStickController(int vid, int pid, const std::s } int DeviceManager::doAction(int deviceId, int action, unsigned char data) { - Device *device = 0; - // On the stack and will be released if we have a device lock. - std::auto_ptr deviceLocker(0); + int deviceType = 0; { // devicelist locked TelldusCore::MutexLocker deviceListLocker(&d->lock); - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } DeviceMap::iterator it = d->devices.find(deviceId); if (it == d->devices.end()) { return TELLSTICK_ERROR_DEVICE_NOT_FOUND; // not found } // device locked - deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); - device = it->second; - } // devicelist unlocked + TelldusCore::MutexLocker deviceLocker(it->second); - int retval = TELLSTICK_ERROR_UNKNOWN; - - if(device->getType() == TELLSTICK_TYPE_GROUP || device->getType() == TELLSTICK_TYPE_SCENE) { - std::wstring devices = device->getParameter(L"devices"); - deviceLocker = std::auto_ptr(0); - std::set *duplicateDeviceIds = new std::set; - retval = doGroupAction(devices, action, data, device->getType(), deviceId, duplicateDeviceIds); - delete duplicateDeviceIds; - - { - // reaquire device lock, make sure it still exists - // devicelist locked - TelldusCore::MutexLocker deviceListLocker(&d->lock); - - if (!d->devices.size()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; - } - DeviceMap::iterator it = d->devices.find(deviceId); - if (it == d->devices.end()) { - return TELLSTICK_ERROR_DEVICE_NOT_FOUND; // not found - } - // device locked - deviceLocker = std::auto_ptr(new TelldusCore::MutexLocker(it->second)); - device = it->second; - } // devicelist unlocked - } else { - Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - if(!controller) { - Log::warning("Trying to execute action, but no controller found. Rescanning USB ports"); - // no controller found, scan for one, and retry once - d->controllerManager->loadControllers(); - controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - } - - if(controller) { - retval = device->doAction(action, data, controller); - if(retval == TELLSTICK_ERROR_BROKEN_PIPE) { - Log::warning("Error in communication with TellStick when executing action. Resetting USB"); - d->controllerManager->resetController(controller); - } - if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND) { - Log::warning("Rescanning USB ports"); - d->controllerManager->loadControllers(); - controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId()); - if(!controller) { - Log::error("No contoller (TellStick) found, even after reset. Giving up."); - return TELLSTICK_ERROR_NOT_FOUND; - } - retval = device->doAction(action, data, controller); // retry one more time - } - } else { - Log::error("No contoller (TellStick) found after one retry. Giving up."); - return TELLSTICK_ERROR_NOT_FOUND; + deviceType = it->second->getType(); + if (it->second->isMethodSupported(action) <= 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } } - if(retval == TELLSTICK_SUCCESS && device->getType() != TELLSTICK_TYPE_SCENE && device->getMethods() & action) { - // if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state - std::wstring datastring = TelldusCore::charUnsignedToWstring(data); - if (this->triggerDeviceStateChange(deviceId, action, datastring)) { - device->setLastSentCommand(action, datastring); - d->set.setDeviceState(deviceId, action, datastring); - } + + if (d->controllerManager->count() == 0) { + return TELLSTICK_ERROR_NOT_FOUND; } - return retval; + + // The device exists and there is at least one connected controller + + if(deviceType == TELLSTICK_TYPE_GROUP || deviceType == TELLSTICK_TYPE_SCENE) { + return this->doGroupSceneAction(deviceId, action, data); + } + + ExecuteActionEventData *eventData = new ExecuteActionEventData(); + eventData->deviceId = deviceId; + eventData->method = action; + eventData->data = data; + d->executeActionEvent->signal(eventData); + return TELLSTICK_SUCCESS; } -int DeviceManager::doGroupAction(const std::wstring devices, const int action, const unsigned char data, const int type, const int groupDeviceId, std::set *duplicateDeviceIds) { - int retval = TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; - std::wstring singledevice; - std::wstringstream devicesstream(devices); +int DeviceManager::doGroupSceneAction(int deviceId, int action, unsigned char data) { + std::set parsedDevices; + std::queue devicesToParse; - duplicateDeviceIds->insert(groupDeviceId); + devicesToParse.push(deviceId); + while (!devicesToParse.empty()) { + int deviceId = devicesToParse.front(); + devicesToParse.pop(); + if (parsedDevices.count(deviceId)) { + continue; + } + parsedDevices.insert(deviceId); - while(std::getline(devicesstream, singledevice, L',')) { - int deviceId = TelldusCore::wideToInteger(singledevice); - - if(duplicateDeviceIds->count(deviceId) == 1) { - // action for device already executed, or will execute, do nothing to avoid infinite loop + TelldusCore::MutexLocker deviceListLocker(&d->lock); + DeviceMap::iterator it = d->devices.find(deviceId); + if (it == d->devices.end()) { + // Not found continue; } - duplicateDeviceIds->insert(deviceId); - - int deviceReturnValue = TELLSTICK_SUCCESS; - - if(type == TELLSTICK_TYPE_SCENE && (action == TELLSTICK_TURNON || action == TELLSTICK_EXECUTE)) { - deviceReturnValue = executeScene(singledevice, groupDeviceId); - } else if(type == TELLSTICK_TYPE_GROUP) { - if(deviceId != 0) { - int childType = DeviceManager::getDeviceType(deviceId); - if(childType == TELLSTICK_TYPE_DEVICE) { - deviceReturnValue = doAction(deviceId, action, data); - } else if(childType == TELLSTICK_TYPE_SCENE) { - deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); // TODO(stefan) make scenes infinite loops-safe - } else { - // group (in group) - deviceReturnValue = doGroupAction(DeviceManager::getDeviceParameter(deviceId, L"devices", L""), action, data, childType, deviceId, duplicateDeviceIds); - - if(deviceReturnValue == TELLSTICK_SUCCESS) { - std::wstring datastring = TelldusCore::charUnsignedToWstring(data); - if (this->triggerDeviceStateChange(deviceId, action, datastring)) { - DeviceManager::setDeviceLastSentCommand(deviceId, action, datastring); - d->set.setDeviceState(deviceId, action, datastring); - } - } - } - } else { - deviceReturnValue = TELLSTICK_ERROR_DEVICE_NOT_FOUND; // Probably incorrectly formatted parameter - } + if (it->second->isMethodSupported(action) <= 0) { + return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED; } - if(deviceReturnValue != TELLSTICK_ERROR_METHOD_NOT_SUPPORTED) { - // if error(s), return the last error, but still try to continue the action with the other devices - // if the error is a method not supported we igore is since there might be others supporting it - // If no devices support the method the default value will be returned (method not supported) - retval = deviceReturnValue; + TelldusCore::MutexLocker deviceLocker(it->second); + if (it->second->getType() == TELLSTICK_TYPE_DEVICE) { + ExecuteActionEventData *eventData = new ExecuteActionEventData(); + eventData->deviceId = deviceId; + eventData->method = action; + eventData->data = data; + d->executeActionEvent->signal(eventData); + continue; + } + if (it->second->getType() == TELLSTICK_TYPE_GROUP) { + std::string devices = TelldusCore::wideToString(it->second->getParameter(L"devices")); + std::stringstream devicesstream(devices); + std::string singledevice; + while(std::getline(devicesstream, singledevice, ',')) { + devicesToParse.push(TelldusCore::charToInteger(singledevice.c_str())); + } + // Update state + if(it->second->getMethods() & action) { + // if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state + std::wstring datastring = TelldusCore::charUnsignedToWstring(data); + if (this->triggerDeviceStateChange(deviceId, action, datastring)) { + it->second->setLastSentCommand(action, datastring); + d->set.setDeviceState(deviceId, action, datastring); + } + } + + } + if (it->second->getType() == TELLSTICK_TYPE_SCENE) { + // TODO(micke): Not supported yet + Log::warning("Scenes are not supported yet!"); } } - return retval; + + return TELLSTICK_SUCCESS; } int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId) { diff --git a/telldus-core/service/DeviceManager.h b/telldus-core/service/DeviceManager.h index 6a94b7e5..6e5a6f25 100644 --- a/telldus-core/service/DeviceManager.h +++ b/telldus-core/service/DeviceManager.h @@ -24,6 +24,7 @@ public: int addDevice(); void connectTellStickController(int vid, int pid, const std::string &serial); void disconnectTellStickController(int vid, int pid, const std::string &serial); + void executeActionEvent(); int getDeviceId(int deviceIndex); int getDeviceLastSentCommand(int deviceId, int methodsSupported); int setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value); @@ -44,6 +45,8 @@ public: int removeDevice(int deviceId); int sendRawCommand(const std::wstring &command, int reserved); + void setExecuteActionEvent(TelldusCore::EventRef event); + std::wstring getSensors() const; std::wstring getSensorValue(const std::wstring &protocol, const std::wstring &model, int id, int dataType) const; @@ -53,7 +56,7 @@ private: void handleSensorMessage(const ControllerMessage &msg); void setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const; int getDeviceMethods(int deviceId, std::set *duplicateDeviceIds); - int doGroupAction(const std::wstring deviceIds, int action, unsigned char data, const int type, int groupDeviceId, std::set *duplicateDeviceIds); + int doGroupSceneAction(int deviceId, int action, unsigned char data); int executeScene(std::wstring singledevice, int groupDeviceId); bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ); void fillDevices(void); diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 9bc40341..57236169 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -66,6 +66,7 @@ void TelldusMain::suspend() { void TelldusMain::start(void) { TelldusCore::EventRef clientEvent = d->eventHandler.addEvent(); TelldusCore::EventRef dataEvent = d->eventHandler.addEvent(); + TelldusCore::EventRef executeActionEvent = d->eventHandler.addEvent(); TelldusCore::EventRef janitor = d->eventHandler.addEvent(); // Used for regular cleanups Timer supervisor(janitor); // Tells the janitor to go back to work supervisor.setInterval(60); // Once every minute @@ -76,6 +77,7 @@ void TelldusMain::start(void) { eventUpdateManager.start(); ControllerManager controllerManager(dataEvent, deviceUpdateEvent); DeviceManager deviceManager(&controllerManager, deviceUpdateEvent); + deviceManager.setExecuteActionEvent(executeActionEvent); ConnectionListener clientListener(L"TelldusClient", clientEvent); @@ -132,6 +134,9 @@ void TelldusMain::start(void) { } } } + if (executeActionEvent->isSignaled()) { + deviceManager.executeActionEvent(); + } if (janitor->isSignaled()) { // Clear all of them if there is more than one while(janitor->isSignaled()) { From fd8fdfcacd49a3b5470c53b5717caaf2cd9fd19a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 8 Nov 2012 10:13:59 +0100 Subject: [PATCH 2095/2215] Remove variables never used --- .../service/ConnectionListener_unix.cpp | 2 -- .../service/ControllerListener_mac.cpp | 23 ++++++++----------- telldus-core/service/Timer.cpp | 3 ++- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 78d3911a..3ea0a55e 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -47,7 +47,6 @@ void ConnectionListener::run() { SOCKET_T serverSocket; struct sockaddr_un name; - socklen_t len; serverSocket = socket(PF_LOCAL, SOCK_STREAM, 0); if (serverSocket < 0) { return; @@ -62,7 +61,6 @@ void ConnectionListener::run() { // Change permissions to allow everyone chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); - len = sizeof(struct sockaddr_un); fd_set infds; FD_ZERO(&infds); diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp index 1843474c..b309343d 100644 --- a/telldus-core/service/ControllerListener_mac.cpp +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -74,7 +74,6 @@ void ControllerListener::run() { void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) { CFNumberRef numberRef; - kern_return_t kr; CFMutableDictionaryRef matchingDict; matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class @@ -94,19 +93,18 @@ void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) { CFRelease(numberRef); // Now set up a notification to be called when a device is first matched by I/O Kit. - kr = IOServiceAddMatchingNotification(gNotifyPort, // notifyPort - kIOFirstMatchNotification, // notificationType - matchingDict, // matching - PrivateData::DeviceAdded, // callback - this, // refCon - &gAddedIter // notification - ); + IOServiceAddMatchingNotification(gNotifyPort, // notifyPort + kIOFirstMatchNotification, // notificationType + matchingDict, // matching + PrivateData::DeviceAdded, // callback + this, // refCon + &gAddedIter // notification + ); // Iterate once to get already-present devices and arm the notification PrivateData::DeviceAdded(this, gAddedIter); } void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { - kern_return_t kr; if (messageType != kIOMessageServiceIsTerminated) { return; @@ -132,14 +130,13 @@ void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_servic // Free the data we're no longer using now that the device is going away CFRelease(tsd->serialNumber); - kr = IOObjectRelease(tsd->notification); + IOObjectRelease(tsd->notification); delete tsd; } void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t iterator) { io_service_t usbDevice; - kern_return_t kr; PrivateData *pd = reinterpret_cast (refCon); @@ -172,7 +169,7 @@ void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t it // Register for an interest notification of this device being removed. Use a reference to our // private data as the refCon which will be passed to the notification callback. - kr = IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); + IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification)); CFIndex size = CFStringGetLength(serialNumberAsCFString); char *s = new char[size+1]; @@ -180,7 +177,7 @@ void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t it std::string serial(s); // Copy the string to the stack delete[] s; - kr = IOObjectRelease(usbDevice); + IOObjectRelease(usbDevice); ControllerChangeEventData *data = new ControllerChangeEventData; data->vid = tsd->vid; diff --git a/telldus-core/service/Timer.cpp b/telldus-core/service/Timer.cpp index 758881e3..bcce9b17 100644 --- a/telldus-core/service/Timer.cpp +++ b/telldus-core/service/Timer.cpp @@ -97,7 +97,8 @@ void Timer::run() { pthread_mutex_unlock(&d->waitMutex); while(1) { - int rc = gettimeofday(&tp, NULL); + int rc = 0; + gettimeofday(&tp, NULL); ts.tv_sec = tp.tv_sec; ts.tv_nsec = tp.tv_usec * 1000; From 992b03c5bae967a87200bf4fe74c1433479090be Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 8 Nov 2012 10:36:50 +0100 Subject: [PATCH 2096/2215] Code cleanup according to style guidelines --- telldus-core/service/SettingsCoreFoundationPreferences.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index 3ce3b4bc..5c52b364 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -60,7 +60,9 @@ std::wstring Settings::getSetting(const std::wstring &strName) const { */ int Settings::getNumberOfNodes(Node type) const { CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); - if (!cfarray) return 0; + if (!cfarray) { + return 0; + } CFIndex size = CFArrayGetCount( cfarray ); int nodes = 0; for (CFIndex k = 0; k < size; ++k) { From 4467a75abc54de4cf819d79c7831009bd2b432cf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 8 Nov 2012 10:49:04 +0100 Subject: [PATCH 2097/2215] Cleanup our CF variables so we do not leak memory. See #240 --- .../SettingsCoreFoundationPreferences.cpp | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/SettingsCoreFoundationPreferences.cpp b/telldus-core/service/SettingsCoreFoundationPreferences.cpp index 5c52b364..207ae928 100644 --- a/telldus-core/service/SettingsCoreFoundationPreferences.cpp +++ b/telldus-core/service/SettingsCoreFoundationPreferences.cpp @@ -76,6 +76,7 @@ int Settings::getNumberOfNodes(Node type) const { ++nodes; } } + CFRelease(cfarray); return nodes; } @@ -100,7 +101,13 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { } if (index == intNodeIndex) { CFArrayRef split = CFStringCreateArrayBySeparatingStrings( 0, key, CFSTR(".") ); - if ( !split || CFArrayGetCount( split ) != 3 ) continue; + if ( !split ) { + continue; + } + if (CFArrayGetCount( split ) != 3 ) { + CFRelease( split ); + continue; + } // This code crashes! // CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 ); @@ -169,6 +176,7 @@ int Settings::removeNode(Node type, int intNodeId) { CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName ); if (!cfarray) { + CFRelease(filterKey); return TELLSTICK_ERROR_UNKNOWN; } CFIndex size = CFArrayGetCount( cfarray ); @@ -181,6 +189,8 @@ int Settings::removeNode(Node type, int intNodeId) { } CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); + CFRelease(cfarray); + CFRelease(filterKey); return ret; } @@ -199,6 +209,8 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst value = (CFStringRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName); if (!value) { + CFRelease(key); + CFRelease(cfname); return L""; } @@ -218,6 +230,8 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst free(cp); CFRelease(value); + CFRelease(key); + CFRelease(cfname); return retval; } @@ -236,6 +250,9 @@ int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &wna CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); + CFRelease(key); + CFRelease(cfvalue); + CFRelease(cfname); return TELLSTICK_SUCCESS; } @@ -267,6 +284,8 @@ int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &wname, } } + CFRelease(key); + CFRelease(cfname); return retval; } @@ -284,5 +303,8 @@ int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &wname, CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName ); CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName ); + CFRelease(key); + CFRelease(cfvalue); + CFRelease(cfname); return TELLSTICK_SUCCESS; } From d88d5a509850777ad2823a22d4b29db9e499ac62 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 8 Nov 2012 15:40:31 +0100 Subject: [PATCH 2098/2215] Remove empty lines according to google style guidelines --- telldus-core/service/ControllerListener_mac.cpp | 1 - telldus-core/service/DeviceManager.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/telldus-core/service/ControllerListener_mac.cpp b/telldus-core/service/ControllerListener_mac.cpp index b309343d..f45ae100 100644 --- a/telldus-core/service/ControllerListener_mac.cpp +++ b/telldus-core/service/ControllerListener_mac.cpp @@ -105,7 +105,6 @@ void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) { } void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { - if (messageType != kIOMessageServiceIsTerminated) { return; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index 1b1b7839..e33e66d2 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -117,7 +117,6 @@ void DeviceManager::executeActionEvent() { d->set.setDeviceState(data->deviceId, data->method, datastring); } } - } void DeviceManager::setExecuteActionEvent(TelldusCore::EventRef event) { @@ -529,7 +528,6 @@ int DeviceManager::doGroupSceneAction(int deviceId, int action, unsigned char da d->set.setDeviceState(deviceId, action, datastring); } } - } if (it->second->getType() == TELLSTICK_TYPE_SCENE) { // TODO(micke): Not supported yet From 0018ad28d10d1f301be478b818e03df7bf9007c4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Nov 2012 10:13:34 +0100 Subject: [PATCH 2099/2215] Remove old telldus-gui.pro --- telldus-gui/telldus-gui.pro | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 telldus-gui/telldus-gui.pro diff --git a/telldus-gui/telldus-gui.pro b/telldus-gui/telldus-gui.pro deleted file mode 100644 index 4a0691f6..00000000 --- a/telldus-gui/telldus-gui.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE=subdirs -SUBDIRS = TelldusGui \ - TelldusCenter \ - Plugins From 32f2d9f955e76506d9df83c7464cdb7685b0502e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 19 Nov 2012 16:42:18 +0100 Subject: [PATCH 2100/2215] Check all incomming messages against duplicates. Only one unique message per second is accepted. Closes #84 --- telldus-core/service/Controller.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 2cca4c03..5b1249fa 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -5,6 +5,8 @@ // // #include "service/Controller.h" +#include +#include #include #include #include "service/Protocol.h" @@ -15,6 +17,8 @@ class Controller::PrivateData { public: TelldusCore::EventRef event, updateEvent; int id, firmwareVersion; + unsigned int randSeed; + std::map duplicates; }; Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent) { @@ -23,6 +27,7 @@ Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRe d->updateEvent = updateEvent; d->id = id; d->firmwareVersion = 0; + d->randSeed = time(NULL); } Controller::~Controller() { @@ -37,6 +42,28 @@ void Controller::publishData(const std::string &msg) const { } void Controller::decodePublishData(const std::string &data) const { + // Garbange collect? + if (rand_r(&d->randSeed) % 1000 == 1) { + time_t t = time(NULL); + // Standard associative-container erase idiom + for (std::map::iterator it = d->duplicates.begin(); it != d->duplicates.end(); /* no increment */) { + if ((*it).second != t) { + d->duplicates.erase(it++); + } else { + ++it; + } + } + } + // Duplicate check + if (d->duplicates.count(data) > 0) { + time_t t = d->duplicates[data]; + if (t == time(NULL)) { + // Duplicate message + return; + } + } + d->duplicates[data] = time(NULL); + std::list msgList = Protocol::decodeData(data); for (std::list::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt) { From d48ee1f02ba5b6b4fb34e5e8b3b16c069e38d679 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Nov 2012 09:57:59 +0100 Subject: [PATCH 2101/2215] Execute a script from /usr/local/share/telldus/scripts on all events. Closes #100 --- telldus-core/service/EventUpdateManager.cpp | 112 ++++++++++++++++++++ telldus-core/service/EventUpdateManager.h | 3 + telldus-core/service/main_unix.cpp | 9 ++ 3 files changed, 124 insertions(+) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 0f50c5fe..bd37e9ba 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -6,13 +6,28 @@ // #include "service/EventUpdateManager.h" +#ifdef _LINUX +#include +#include +#include +#include +#include +#include +#include +#endif // _LINUX #include #include +#ifdef _LINUX +#include +#include +#endif // _LINUX #include "service/ConnectionListener.h" #include "common/EventHandler.h" #include "common/Message.h" #include "common/Socket.h" +#include "service/Log.h" +#include "common/Strings.h" typedef std::list SocketList; @@ -68,6 +83,7 @@ void EventUpdateManager::run() { EventUpdateData *data = reinterpret_cast(eventData.get()); if(data) { sendMessageToClients(data); + executeScripts(data); } } } @@ -120,3 +136,99 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { } } } + +void EventUpdateManager::executeScripts(EventUpdateData *data) { +#ifdef _LINUX + std::string dir; + std::vector env; + + // Create a copy of the environment + unsigned int size = 0; + for(; ; ++size) { + if (environ[size] == 0) { + break; + } + } + env.reserve(size + 6); // 6 is the most used extra environmental variables any event uses + for(unsigned int i = 0; i < size; ++i) { + env.push_back(environ[i]); + } + + if(data->messageType == L"TDDeviceEvent") { + dir = "deviceevent"; + env.push_back(TelldusCore::formatf("DEVICEID=%i", data->deviceId)); + env.push_back(TelldusCore::formatf("METHOD=%i", data->eventState)); + env.push_back(TelldusCore::formatf("METHODDATA=%s", TelldusCore::wideToString(data->eventValue).c_str())); + } else if(data->messageType == L"TDDeviceChangeEvent") { + dir = "devicechangeevent"; + env.push_back(TelldusCore::formatf("DEVICEID=%i", data->deviceId)); + env.push_back(TelldusCore::formatf("CHANGEEVENT=%i", data->eventDeviceChanges)); + env.push_back(TelldusCore::formatf("CHANGETYPE=%i", data->eventChangeType)); + } else if(data->messageType == L"TDRawDeviceEvent") { + dir = "rawdeviceevent"; + env.push_back(TelldusCore::formatf("RAWDATA=%s", TelldusCore::wideToString(data->eventValue).c_str())); // string + env.push_back(TelldusCore::formatf("CONTROLLERID=%i", data->controllerId)); + } else if (data->messageType == L"TDSensorEvent") { + dir = "sensorevent"; + env.push_back(TelldusCore::formatf("PROTOCOL=%s", TelldusCore::wideToString(data->protocol).c_str())); + env.push_back(TelldusCore::formatf("MODEL=%s", TelldusCore::wideToString(data->model).c_str())); + env.push_back(TelldusCore::formatf("SENSORID=%i", data->sensorId)); + env.push_back(TelldusCore::formatf("DATATYPE=%i", data->dataType)); + env.push_back(TelldusCore::formatf("VALUE=%s", TelldusCore::wideToString(data->value).c_str())); + env.push_back(TelldusCore::formatf("TIMESTAMP=%i", data->timestamp)); + } else if(data->messageType == L"TDControllerEvent") { + dir = "controllerevent"; + env.push_back(TelldusCore::formatf("CONTROLLERID=%i", data->controllerId)); + env.push_back(TelldusCore::formatf("CHANGEEVENT=%i", data->eventState)); + env.push_back(TelldusCore::formatf("CHANGETYPE=%i", data->eventChangeType)); + env.push_back(TelldusCore::formatf("VALUE=%s", TelldusCore::wideToString(data->eventValue).c_str())); + } else { + // Unknown event, should not happen + return; + } + + char *newEnv[env.size()+1]; // +1 for the last stop element + for(int i = 0; i < env.size(); ++i) { + newEnv[i] = new char[env.at(i).length()+1]; + snprintf(newEnv[i], env.at(i).length()+1, "%s", env.at(i).c_str()); + } + newEnv[env.size()] = 0; // Mark end of array + + // List files to execute + std::string path = TelldusCore::formatf("/usr/local/share/telldus/scripts/%s", dir.c_str()); + struct dirent **namelist; + int count = scandir(path.c_str(), &namelist, NULL, alphasort); + if (count <= 0) { + return; + } + + for(int i = 0; i < count; ++i) { + if (strcmp(namelist[i]->d_name, ".") == 0 || strcmp(namelist[i]->d_name, "..") == 0) { + continue; + } + executeScript(TelldusCore::formatf("%s/%s", path.c_str(), namelist[i]->d_name), namelist[i]->d_name, newEnv); + } + + for(int i = 0; i < count; ++i) { + free(namelist[i]); + } + free(namelist); +#endif // _LINUX +} + +void EventUpdateManager::executeScript(std::string script, char *name, char ** env) { +#ifdef _LINUX + pid_t pid = fork(); + if (pid == -1) { + Log::error("Could not fork() to execute script %s", script.c_str()); + return; + } + + if (pid == 0) { + static char * argv[] = { name }; + execve(script.c_str(), argv, env); + Log::error("Could not execute %s (%i): %s", script.c_str(), errno, strerror(errno)); + exit(1); + } +#endif // _LINUX +} diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 0757a176..1372a96a 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -7,6 +7,7 @@ #ifndef TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_ #define TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_ +#include #include "common/Thread.h" #include "common/Event.h" @@ -44,6 +45,8 @@ private: class PrivateData; PrivateData *d; void sendMessageToClients(EventUpdateData *data); + void executeScripts(EventUpdateData *data); + static void executeScript(std::string script, char *name, char **env); }; #endif // TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_ diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 5608a550..c6e4f178 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -149,6 +149,15 @@ int main(int argc, char **argv) { signal(SIGINT, signalHandler); signal(SIGPIPE, signalHandler); + // Change so we do not need to call wait() for children processes + struct sigaction sa; + sa.sa_handler = SIG_IGN; + sa.sa_flags = SA_NOCLDWAIT; + sigemptyset(&sa.sa_mask); + if (sigaction(SIGCHLD, &sa, NULL) == -1) { + Log::error("Could not set the SA_NOCLDWAIT flag. We will be creating zombie processes!"); + } + tm.start(); Log::notice("%s daemon exited", DAEMON_NAME); From b2948cba5b9499b9707a574a11b3cf60cfdee8db Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Nov 2012 11:37:27 +0100 Subject: [PATCH 2102/2215] Preload all scripts to execute on startup to avoid scanning the directory on every event. --- telldus-core/service/EventUpdateManager.cpp | 58 ++++++++++++++------- telldus-core/service/EventUpdateManager.h | 3 +- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index bd37e9ba..a484a906 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -16,6 +16,7 @@ #include #endif // _LINUX #include +#include #include #ifdef _LINUX #include @@ -30,6 +31,7 @@ #include "common/Strings.h" typedef std::list SocketList; +typedef std::list StringList; class EventUpdateManager::PrivateData { public: @@ -37,6 +39,9 @@ public: TelldusCore::EventRef stopEvent, updateEvent, clientConnectEvent; SocketList clients; ConnectionListener *eventUpdateClientListener; +#ifdef _LINUX + std::map fileList; +#endif // _LINUX }; EventUpdateManager::EventUpdateManager() @@ -46,6 +51,13 @@ EventUpdateManager::EventUpdateManager() d->updateEvent = d->eventHandler.addEvent(); d->clientConnectEvent = d->eventHandler.addEvent(); d->eventUpdateClientListener = new ConnectionListener(L"TelldusEvents", d->clientConnectEvent); +#ifdef _LINUX + loadScripts("deviceevent"); + loadScripts("devicechangeevent"); + loadScripts("rawdeviceevent"); + loadScripts("sensorevent"); + loadScripts("controllerevent"); +#endif // _LINUX } EventUpdateManager::~EventUpdateManager(void) { @@ -89,6 +101,25 @@ void EventUpdateManager::run() { } } +void EventUpdateManager::loadScripts(const std::string &folder) { +#ifdef _LINUX + std::string path = TelldusCore::formatf("/usr/local/share/telldus/scripts/%s", folder.c_str()); + struct dirent **namelist; + int count = scandir(path.c_str(), &namelist, NULL, alphasort); + if (count < 0) { + return; + } + + for(int i = 0; i < count; ++i) { + if (strcmp(namelist[i]->d_name, ".") != 0 && strcmp(namelist[i]->d_name, "..") != 0) { + d->fileList[folder].push_back(namelist[i]->d_name); + } + free(namelist[i]); + } + free(namelist); +#endif // _LINUX +} + void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { int connected = 0; for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();) { @@ -194,29 +225,13 @@ void EventUpdateManager::executeScripts(EventUpdateData *data) { } newEnv[env.size()] = 0; // Mark end of array - // List files to execute - std::string path = TelldusCore::formatf("/usr/local/share/telldus/scripts/%s", dir.c_str()); - struct dirent **namelist; - int count = scandir(path.c_str(), &namelist, NULL, alphasort); - if (count <= 0) { - return; + for(StringList::iterator it = d->fileList[dir].begin(); it != d->fileList[dir].end(); ++it) { + executeScript(TelldusCore::formatf("/usr/local/share/telldus/scripts/%s/%s", dir.c_str(), (*it).c_str()), (*it), newEnv); } - - for(int i = 0; i < count; ++i) { - if (strcmp(namelist[i]->d_name, ".") == 0 || strcmp(namelist[i]->d_name, "..") == 0) { - continue; - } - executeScript(TelldusCore::formatf("%s/%s", path.c_str(), namelist[i]->d_name), namelist[i]->d_name, newEnv); - } - - for(int i = 0; i < count; ++i) { - free(namelist[i]); - } - free(namelist); #endif // _LINUX } -void EventUpdateManager::executeScript(std::string script, char *name, char ** env) { +void EventUpdateManager::executeScript(std::string script, const std::string &name, char ** env) { #ifdef _LINUX pid_t pid = fork(); if (pid == -1) { @@ -225,8 +240,11 @@ void EventUpdateManager::executeScript(std::string script, char *name, char ** e } if (pid == 0) { - static char * argv[] = { name }; + char *n = new char[name.length()+1]; + snprintf(n, name.length()+1, "%s", name.c_str()); + static char * argv[] = { n }; execve(script.c_str(), argv, env); + delete[] n; Log::error("Could not execute %s (%i): %s", script.c_str(), errno, strerror(errno)); exit(1); } diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 1372a96a..59560722 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -44,9 +44,10 @@ protected: private: class PrivateData; PrivateData *d; + void loadScripts(const std::string &folder); void sendMessageToClients(EventUpdateData *data); void executeScripts(EventUpdateData *data); - static void executeScript(std::string script, char *name, char **env); + static void executeScript(std::string script, const std::string &name, char **env); }; #endif // TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_ From fac773249c5e9293079a5e40c44bcdf4b73dbcdc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Nov 2012 11:52:16 +0100 Subject: [PATCH 2103/2215] Rename SettingsConfusePath.h to config.h so it can be used by other configurable options --- telldus-core/service/CMakeLists.txt | 7 ++++--- telldus-core/service/SettingsConfuse.cpp | 2 +- .../service/{SettingsConfusePaths.h.in => config.h.in} | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) rename telldus-core/service/{SettingsConfusePaths.h.in => config.h.in} (57%) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 70b1cfb1..90307ec0 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -158,9 +158,6 @@ ELSE (APPLE) #### Linux #### main_unix.cpp SettingsConfuse.cpp ) - CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/SettingsConfusePaths.h.in - ${CMAKE_CURRENT_BINARY_DIR}/service/SettingsConfusePaths.h) - INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) LIST(APPEND telldus-service_LIBRARIES ${CONFUSE_LIBRARY} @@ -188,6 +185,10 @@ ENDIF (FTDI_ENGINE STREQUAL "ftd2xx") SOURCE_GROUP("Protocol Files" FILES ${telldus-service_protocol_SRCS}) +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/service/config.h) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + SET(telldus-service_TARGET ${telldus-service_TARGET} PARENT_SCOPE) ADD_EXECUTABLE(${telldus-service_TARGET} ${telldus-service_SRCS} diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 9ed2dd17..f3049e8e 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -10,7 +10,7 @@ #include #include #include "service/Settings.h" -#include "service/SettingsConfusePaths.h" +#include "service/config.h" #include "client/telldus-core.h" #include "common/Strings.h" diff --git a/telldus-core/service/SettingsConfusePaths.h.in b/telldus-core/service/config.h.in similarity index 57% rename from telldus-core/service/SettingsConfusePaths.h.in rename to telldus-core/service/config.h.in index ea16e6b0..fa488ab2 100644 --- a/telldus-core/service/SettingsConfusePaths.h.in +++ b/telldus-core/service/config.h.in @@ -1,7 +1,7 @@ -#ifndef SETTINGSCONFUSEPATHS_H -#define SETTINGSCONFUSEPATHS_H +#ifndef CONFIG_H +#define CONFIG_H #define CONFIG_PATH "@SYSCONF_INSTALL_DIR@" #define VAR_CONFIG_PATH "@STATE_INSTALL_DIR@" -#endif +#endif // CONFIG_H From 46c24d4a6eab814613e7ac56d374c48570157f2c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Nov 2012 12:02:39 +0100 Subject: [PATCH 2104/2215] Make the path for the scripts configurable --- telldus-core/service/CMakeLists.txt | 4 ++++ telldus-core/service/EventUpdateManager.cpp | 5 +++-- telldus-core/service/config.h.in | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 90307ec0..6e39ac11 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -92,6 +92,10 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) ######## Configurable options for the platform ######## +IF (UNIX AND NOT APPLE) + SET(SCRIPT_PATH "/usr/local/share/telldus/scripts" CACHE PATH "The paths for scripts to execute on sensor events") +ENDIF() + ######## Platforms-specific, non configurable ######## IF (APPLE) #### Mac OS X #### diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index a484a906..f3ba28d8 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -24,6 +24,7 @@ #endif // _LINUX #include "service/ConnectionListener.h" +#include "service/config.h" #include "common/EventHandler.h" #include "common/Message.h" #include "common/Socket.h" @@ -103,7 +104,7 @@ void EventUpdateManager::run() { void EventUpdateManager::loadScripts(const std::string &folder) { #ifdef _LINUX - std::string path = TelldusCore::formatf("/usr/local/share/telldus/scripts/%s", folder.c_str()); + std::string path = TelldusCore::formatf("%s/%s", SCRIPT_PATH, folder.c_str()); struct dirent **namelist; int count = scandir(path.c_str(), &namelist, NULL, alphasort); if (count < 0) { @@ -226,7 +227,7 @@ void EventUpdateManager::executeScripts(EventUpdateData *data) { newEnv[env.size()] = 0; // Mark end of array for(StringList::iterator it = d->fileList[dir].begin(); it != d->fileList[dir].end(); ++it) { - executeScript(TelldusCore::formatf("/usr/local/share/telldus/scripts/%s/%s", dir.c_str(), (*it).c_str()), (*it), newEnv); + executeScript(TelldusCore::formatf("%s/%s/%s", SCRIPT_PATH, dir.c_str(), (*it).c_str()), (*it), newEnv); } #endif // _LINUX } diff --git a/telldus-core/service/config.h.in b/telldus-core/service/config.h.in index fa488ab2..211c884d 100644 --- a/telldus-core/service/config.h.in +++ b/telldus-core/service/config.h.in @@ -4,4 +4,8 @@ #define CONFIG_PATH "@SYSCONF_INSTALL_DIR@" #define VAR_CONFIG_PATH "@STATE_INSTALL_DIR@" +#ifdef _LINUX +#define SCRIPT_PATH "@SCRIPT_PATH@" +#endif // _LINUX + #endif // CONFIG_H From 15225dd5f6a771a8295b32afa96a27346dde00b9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Nov 2012 12:19:14 +0100 Subject: [PATCH 2105/2215] Cleanup the logger before exit --- telldus-core/service/main_unix.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index c6e4f178..07c119d3 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -161,5 +161,7 @@ int main(int argc, char **argv) { tm.start(); Log::notice("%s daemon exited", DAEMON_NAME); + // Cleanup + Log::destroy(); exit(EXIT_SUCCESS); } From e5f6858cf5239d5f556adae1985e657771c340df Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 22 Nov 2012 12:20:16 +0100 Subject: [PATCH 2106/2215] Cleanup our new environment after its use --- telldus-core/service/EventUpdateManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index f3ba28d8..6b83edcd 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -229,6 +229,10 @@ void EventUpdateManager::executeScripts(EventUpdateData *data) { for(StringList::iterator it = d->fileList[dir].begin(); it != d->fileList[dir].end(); ++it) { executeScript(TelldusCore::formatf("%s/%s/%s", SCRIPT_PATH, dir.c_str(), (*it).c_str()), (*it), newEnv); } + // Cleanup + for(int i = 0; newEnv[i] != 0; ++i) { + delete[] newEnv[i]; + } #endif // _LINUX } From df6bd2788365991d36d5af2a75833b8de2a5860f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Dec 2012 11:34:06 +0100 Subject: [PATCH 2107/2215] More logging for TelldusService debug, ticket #266, 266-1. --- telldus-core/client/CallbackMainDispatcher.cpp | 6 +++--- telldus-core/client/Client.cpp | 5 ++++- telldus-core/common/Socket_win.cpp | 11 +++++++++-- telldus-core/service/EventUpdateManager.cpp | 6 +++--- 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index efb9ed11..91df371e 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -108,14 +108,14 @@ void CallbackMainDispatcher::run(){ } //logga här, att den fortfarande körs, ev till fil bara för att det kan bli så mkt... //om för mkt, kolla att viss tid gått sedan förra ggn eller ngt... - debuglog(333, "Callbackevent, signalled"); + //debuglog(333, "Callbackevent, signalled"); TelldusCore::MutexLocker locker(&d->mutex); //logga, har låst - debuglog(333, "Callbackevent, locked"); + //debuglog(333, "Callbackevent, locked"); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { if ( (*callback_it)->type == cbd->type ) { //ev logga här också, att det finns ngnstans att skicka till - debuglog((*callback_it)->id, "Callbackevent, sending"); + //debuglog((*callback_it)->id, "Callbackevent, sending"); std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); d->eventThreadList.push_back(ptr); } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index ffc662be..b2821503 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -154,20 +154,23 @@ std::wstring Client::sendToService(const Message &msg) { if(tries == 20){ TelldusCore::Message msg; msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); + debuglog(555, "Connection failed, 20 retries, giving up."); return msg; } Socket s; s.connect(L"TelldusClient"); if (!s.isConnected()) { //Connection failed + debuglog(555, "Connection failed"); msleep(500); continue; //retry } s.write(msg.data()); if (!s.isConnected()) { //Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) msleep(500); + debuglog(555, "Error in write, should retry"); continue; //retry } - readData = s.read(8000); //TODO changed to 10000 from 5000, how much does this do...? + readData = s.read(1000); //TODO changed to 10000 from 5000, how much does this do...? if(readData == L""){ msleep(500); continue; //TODO can we be really sure it SHOULD be anything? diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 068c82d1..4940f087 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -120,6 +120,7 @@ std::wstring Socket::read(int timeout){ if (!fSuccess) { DWORD err = GetLastError(); + debuglog((int)err, "Something read error"); if(err != ERROR_OPERATION_ABORTED){ //gets this "error" always when nothing was reads debuglog((int)err, "Socket read error"); } @@ -131,7 +132,7 @@ std::wstring Socket::read(int timeout){ buf[0] = 0; } if (err == ERROR_BROKEN_PIPE){ - debuglog(222, "Got an error, close this socket"); + debuglog((int)err, "Got an error, close this socket"); d->connected = false; break; //TODO is this correct? } @@ -158,7 +159,7 @@ void Socket::write(const std::wstring &msg){ BOOL writeSuccess = WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); result = GetLastError(); if (writeSuccess || result == ERROR_IO_PENDING) { - result = WaitForSingleObject(writeEvent, 500); + result = WaitForSingleObject(writeEvent, 30000); if (result == WAIT_TIMEOUT) { CancelIo(d->hPipe); WaitForSingleObject(oOverlap.hEvent, INFINITE); @@ -169,12 +170,18 @@ void Socket::write(const std::wstring &msg){ return; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); + if (!fSuccess){ + debuglog(result, "Error in GetOverlappedResult"); + result = GetLastError(); + debuglog(result, "Error in GetOverlappedResult, this message"); + } } CloseHandle(writeEvent); if (!fSuccess) { CloseHandle(d->hPipe); d->hPipe = 0; + debuglog(result, "Error in write event, closing socket"); d->connected = false; return; } diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 12f736cc..992fde58 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -130,7 +130,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ } } //printf("Sent message to %d connected clients", connected) - std::stringstream strMessage; - strMessage << "Sent message to " << connected << " clients" << std::endl; - debuglogservice(0, strMessage.str()); + //std::stringstream strMessage; + //strMessage << "Sent message to " << connected << " clients" << std::endl; + //debuglogservice(0, strMessage.str()); } From 9f68c2083a9aa943338252d4a2f187299de1a0c6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Dec 2012 15:05:45 +0100 Subject: [PATCH 2108/2215] Some code/comment cleanup --- telldus-core/client/CallbackMainDispatcher.cpp | 6 ------ telldus-core/service/Controller.cpp | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 1c6a91c7..77685fa0 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -60,7 +60,6 @@ int CallbackMainDispatcher::registerCallback(CallbackStruct::CallbackType type, callback->id = id; callback->context = context; d->callbackList.push_back(callback); - //logga callbackprenumeration lades till debuglog(id, "Callback added"); return id; } @@ -70,7 +69,6 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { { TelldusCore::MutexLocker locker(&d->mutex); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { - //logga, avregistrering av callback if ( (*callback_it)->id != callbackId ) { continue; } @@ -104,15 +102,11 @@ void CallbackMainDispatcher::run() { if (!cbd) { continue; } - //logga här, att den fortfarande körs, ev till fil bara för att det kan bli så mkt... - //om för mkt, kolla att viss tid gått sedan förra ggn eller ngt... //debuglog(333, "Callbackevent, signalled"); TelldusCore::MutexLocker locker(&d->mutex); - //logga, har låst //debuglog(333, "Callbackevent, locked"); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { if ( (*callback_it)->type == cbd->type ) { - //ev logga här också, att det finns ngnstans att skicka till //debuglog((*callback_it)->id, "Callbackevent, sending"); std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); d->eventThreadList.push_back(ptr); diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 5b1249fa..0c6983ec 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -12,6 +12,7 @@ #include "service/Protocol.h" #include "service/EventUpdateManager.h" #include "common/Strings.h" +#include "common/common.h" //debug class Controller::PrivateData { public: From 05197abf6e08a08698a373a0b6d61f871e3aee5f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Dec 2012 15:14:40 +0100 Subject: [PATCH 2109/2215] Fixed regression errors for windows --- telldus-core/service/ConnectionListener_win.cpp | 2 +- telldus-core/service/Controller.cpp | 13 ++++++++++++- telldus-core/service/ControllerMessage.h | 4 ++++ telldus-core/service/Log.cpp | 12 ++++++------ telldus-core/service/ProtocolIkea.cpp | 3 +++ telldus-core/service/ProtocolNexa.h | 4 ++++ telldus-core/service/ProtocolSartano.cpp | 4 ++++ telldus-core/service/ProtocolWaveman.cpp | 3 +++ telldus-core/service/ProtocolX10.cpp | 3 +++ telldus-core/service/SettingsWinRegistry.cpp | 4 ++-- 10 files changed, 42 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 6e1c35a8..c61d1548 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -1,6 +1,6 @@ #include "ConnectionListener.h" #include "Event.h" -#include "Socket.h" +#include "common/Socket.h" #include #include diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 0c6983ec..28fcc1d1 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -4,6 +4,7 @@ // Copyright: See COPYING file that comes with this distribution // // +#define _CRT_RAND_S #include "service/Controller.h" #include #include @@ -14,6 +15,16 @@ #include "common/Strings.h" #include "common/common.h" //debug +inline int random( unsigned int* seed ){ + #ifdef _WINDOWS + unsigned int randomNumber; + rand_s( &randomNumber ); //no seed needed + return randomNumber; + #else + return rand_r( seed ); + #endif +} + class Controller::PrivateData { public: TelldusCore::EventRef event, updateEvent; @@ -44,7 +55,7 @@ void Controller::publishData(const std::string &msg) const { void Controller::decodePublishData(const std::string &data) const { // Garbange collect? - if (rand_r(&d->randSeed) % 1000 == 1) { + if (random(&d->randSeed) % 1000 == 1) { time_t t = time(NULL); // Standard associative-container erase idiom for (std::map::iterator it = d->duplicates.begin(); it != d->duplicates.end(); /* no increment */) { diff --git a/telldus-core/service/ControllerMessage.h b/telldus-core/service/ControllerMessage.h index 892c0752..9532ea8d 100644 --- a/telldus-core/service/ControllerMessage.h +++ b/telldus-core/service/ControllerMessage.h @@ -7,7 +7,11 @@ #ifndef TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_ #define TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_ +#ifdef _MSC_VER +typedef unsigned __int64 uint64_t; +#else #include +#endif #include class ControllerMessage { diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 7c0ac9ec..3a7fbb01 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -11,8 +11,8 @@ #include #elif defined(_WINDOWS) #include -#include "service/Strings.h" -#include "service/Messages.h" +#include "common/Strings.h" +#include "Messages.h" #endif class Log::PrivateData { @@ -159,16 +159,16 @@ void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const switch (logLevel) { case Debug: - ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); + ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); break; case Notice: - ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); + ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); break; case Warning: - ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); + ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); break; case Error: - ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, reinterpret_cast(pInsertStrings), NULL); + ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); break; } #endif diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index f2c3515d..37e90b7d 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -10,6 +10,9 @@ #include #include #include "common/Strings.h" +#ifdef _WINDOWS +#define strtok_r(s,d,p) strtok_s(s,d,p) +#endif int ProtocolIkea::methods() const { return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM; diff --git a/telldus-core/service/ProtocolNexa.h b/telldus-core/service/ProtocolNexa.h index 8dd81b1d..82809973 100644 --- a/telldus-core/service/ProtocolNexa.h +++ b/telldus-core/service/ProtocolNexa.h @@ -7,7 +7,11 @@ #ifndef TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ #define TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_ +#ifdef _MSC_VER +typedef unsigned __int64 uint64_t; +#else #include +#endif #include #include "service/ControllerMessage.h" #include "service/Device.h" diff --git a/telldus-core/service/ProtocolSartano.cpp b/telldus-core/service/ProtocolSartano.cpp index 9c6931aa..0b33f354 100644 --- a/telldus-core/service/ProtocolSartano.cpp +++ b/telldus-core/service/ProtocolSartano.cpp @@ -5,7 +5,11 @@ // // #include "service/ProtocolSartano.h" +#ifdef _MSC_VER +typedef unsigned __int16 uint16_t; +#else #include +#endif #include #include #include diff --git a/telldus-core/service/ProtocolWaveman.cpp b/telldus-core/service/ProtocolWaveman.cpp index dec84412..9684934b 100644 --- a/telldus-core/service/ProtocolWaveman.cpp +++ b/telldus-core/service/ProtocolWaveman.cpp @@ -5,7 +5,10 @@ // // #include "service/ProtocolWaveman.h" +#ifdef _MSC_VER +#else #include +#endif #include #include #include diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index 8de3a377..b3af1230 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -5,7 +5,10 @@ // // #include "service/ProtocolX10.h" +#ifdef _MSC_VER +#else #include +#endif #include #include #include diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 86f43132..350b58d5 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -1,12 +1,12 @@ #include "Settings.h" -#include "Strings.h" +#include "common/Strings.h" #include #include #include #include #include #include -#include "common.h" +#include "common/common.h" #include "../client/telldus-core.h" From d5e8c1f941fea67f1150a69be9ce45dadac4653d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Dec 2012 16:06:27 +0100 Subject: [PATCH 2110/2215] Adding copyright messages according to Google style guidelines "legal/copyright" --- telldus-core/common/EventHandler_win.cpp | 6 ++++++ telldus-core/common/Event_win.cpp | 6 ++++++ telldus-core/common/Socket_win.cpp | 6 ++++++ telldus-core/service/ConnectionListener_win.cpp | 6 ++++++ telldus-core/service/SettingsWinRegistry.cpp | 6 ++++++ telldus-core/service/TelldusWinService_win.cpp | 6 ++++++ telldus-core/service/TelldusWinService_win.h | 6 ++++++ telldus-core/service/main_win.cpp | 6 ++++++ 8 files changed, 48 insertions(+) diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index 35158a41..faa2da52 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "EventHandler.h" #include "Event.h" #include "Mutex.h" diff --git a/telldus-core/common/Event_win.cpp b/telldus-core/common/Event_win.cpp index 681d5e91..a9001683 100644 --- a/telldus-core/common/Event_win.cpp +++ b/telldus-core/common/Event_win.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "Event.h" #include "Thread.h" diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 4940f087..11b6ee8a 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "Socket.h" #include "common.h" #include diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index c61d1548..e1a1e534 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "ConnectionListener.h" #include "Event.h" #include "common/Socket.h" diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 350b58d5..e1271dde 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -4,6 +4,12 @@ #include #include #include +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include #include #include "common/common.h" diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index b122a5c1..fd7236cf 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "TelldusWinService_win.h" #include "TelldusMain.h" #include "Log.h" diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index 5cd78104..dcb3e33a 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #ifndef TELLDUSSERVICE_WIN_H #define TELLDUSSERVICE_WIN_H diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp index 018e61ee..2c93791a 100644 --- a/telldus-core/service/main_win.cpp +++ b/telldus-core/service/main_win.cpp @@ -1,3 +1,9 @@ +// +// Copyright (C) 2012 Telldus Technologies AB. All rights reserved. +// +// Copyright: See COPYING file that comes with this distribution +// +// #include "TelldusWinService_win.h" //#include From 7d0f3747fedfc509cece65fa135ebad32ebc522d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Dec 2012 16:39:39 +0100 Subject: [PATCH 2111/2215] Include directory when naming .h files, according to Google style guidelines "build/include" --- telldus-core/common/EventHandler_win.cpp | 6 +++--- telldus-core/common/Event_win.cpp | 4 ++-- telldus-core/common/Socket_win.cpp | 4 ++-- telldus-core/service/CMakeLists.txt | 6 +++--- telldus-core/service/ConnectionListener_win.cpp | 4 ++-- telldus-core/service/Log.cpp | 2 +- telldus-core/service/SettingsWinRegistry.cpp | 12 ++++++------ telldus-core/service/TelldusWinService_win.cpp | 6 +++--- telldus-core/service/main_win.cpp | 2 +- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index faa2da52..984019bb 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -4,9 +4,9 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "EventHandler.h" -#include "Event.h" -#include "Mutex.h" +#include "common/EventHandler.h" +#include "common/Event.h" +#include "common/Mutex.h" #include #include diff --git a/telldus-core/common/Event_win.cpp b/telldus-core/common/Event_win.cpp index a9001683..4af3a09c 100644 --- a/telldus-core/common/Event_win.cpp +++ b/telldus-core/common/Event_win.cpp @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "Event.h" -#include "Thread.h" +#include "common/Event.h" +#include "common/Thread.h" using namespace TelldusCore; diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 11b6ee8a..66740d2a 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "Socket.h" -#include "common.h" +#include "common/Socket.h" +#include "common/common.h" #include #include #include diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 6e39ac11..520bc95c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -136,14 +136,14 @@ ELSEIF (WIN32) #### Windows #### TelldusWinService_win.cpp Messages.mc ${CMAKE_CURRENT_BINARY_DIR}/Messages.rc - ${CMAKE_CURRENT_BINARY_DIR}/Messages.h + ${CMAKE_CURRENT_BINARY_DIR}/service/Messages.h ) LIST(APPEND telldus-service_HDRS TelldusWinService_win.h ) ADD_CUSTOM_COMMAND( - OUTPUT Messages.rc Messages.h - COMMAND mc.exe -u -r \"${CMAKE_CURRENT_BINARY_DIR}\" -h \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc\" + OUTPUT Messages.rc service/Messages.h + COMMAND mc.exe -u -r \"${CMAKE_CURRENT_BINARY_DIR}\" -h \"${CMAKE_CURRENT_BINARY_DIR}/service\" \"${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc\" DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc DEPENDS Messages.rc COMMENT "Compiling Messages Resource" diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index e1a1e534..c50b487b 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "ConnectionListener.h" -#include "Event.h" +#include "service/ConnectionListener.h" +#include "common/Event.h" #include "common/Socket.h" #include diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 3a7fbb01..37cd352c 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -12,7 +12,7 @@ #elif defined(_WINDOWS) #include #include "common/Strings.h" -#include "Messages.h" +#include "service/Messages.h" #endif class Log::PrivateData { diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index e1271dde..59364509 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -1,15 +1,15 @@ -#include "Settings.h" -#include "common/Strings.h" -#include -#include -#include -#include // // Copyright (C) 2012 Telldus Technologies AB. All rights reserved. // // Copyright: See COPYING file that comes with this distribution // // +#include "service/Settings.h" +#include "common/Strings.h" +#include +#include +#include +#include #include #include #include "common/common.h" diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index fd7236cf..286c2b4e 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -4,9 +4,9 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "TelldusWinService_win.h" -#include "TelldusMain.h" -#include "Log.h" +#include "service/TelldusWinService_win.h" +#include "service/TelldusMain.h" +#include "service/Log.h" #include #include diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp index 2c93791a..b436e209 100644 --- a/telldus-core/service/main_win.cpp +++ b/telldus-core/service/main_win.cpp @@ -4,7 +4,7 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "TelldusWinService_win.h" +#include "service/TelldusWinService_win.h" //#include #include From 81946e9887c93589c817bc2674d0707734b5431d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Dec 2012 16:12:54 +0100 Subject: [PATCH 2112/2215] Find Python dynamically so it works on Windows too --- telldus-core/tests/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/tests/CMakeLists.txt b/telldus-core/tests/CMakeLists.txt index 3d78b0c6..8cdc4cf7 100644 --- a/telldus-core/tests/CMakeLists.txt +++ b/telldus-core/tests/CMakeLists.txt @@ -26,10 +26,11 @@ FUNCTION(ADD_SOURCES TARGET PATH) FOREACH(SOURCE ${SOURCES}) LIST(APPEND L ${PATH}/${SOURCE}) ENDFOREACH() - ADD_TEST(StyleGuidelines-${TARGET} ${CMAKE_CURRENT_SOURCE_DIR}/cpplint.py --filter=${cpplint_filters} ${L}) + ADD_TEST(StyleGuidelines-${TARGET} ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/cpplint.py --filter=${cpplint_filters} ${L}) ENDFUNCTION() IF(ENABLE_TESTING) + INCLUDE(FindPythonInterp) FIND_LIBRARY(CPPUNIT cppunit) ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(service) From 01a65acdd6fee5c8fc4a61dde71f4d9784d3e16a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Dec 2012 16:56:44 +0100 Subject: [PATCH 2113/2215] Do not use namespace using-directives according to Google style guidelines "build/namespaces" --- telldus-core/common/EventHandler_win.cpp | 4 +++- telldus-core/common/Event_win.cpp | 4 ++-- telldus-core/common/Socket_win.cpp | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index 984019bb..1fdd6e0e 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -11,7 +11,7 @@ #include #include -using namespace TelldusCore; +namespace TelldusCore { class EventHandler::PrivateData { public: @@ -73,3 +73,5 @@ bool EventHandler::waitForAny() { return true; } } + +} // namespace TelldusCore diff --git a/telldus-core/common/Event_win.cpp b/telldus-core/common/Event_win.cpp index 4af3a09c..522e3a77 100644 --- a/telldus-core/common/Event_win.cpp +++ b/telldus-core/common/Event_win.cpp @@ -7,7 +7,7 @@ #include "common/Event.h" #include "common/Thread.h" -using namespace TelldusCore; +namespace TelldusCore { class Event::PrivateData { public: @@ -38,4 +38,4 @@ void Event::sendSignal() { SetEvent(d->event); } - +} // namespace TelldusCore diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 66740d2a..c1d2fec3 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -12,7 +12,7 @@ #define BUFSIZE 512 -using namespace TelldusCore; +namespace TelldusCore { class Socket::PrivateData { public: @@ -195,4 +195,6 @@ void Socket::write(const std::wstring &msg){ bool Socket::isConnected(){ return d->connected; -} \ No newline at end of file +} + +} // namespace TelldusCore From 2399e6c349a568afa6416861198739db4d0ae405 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Dec 2012 17:08:47 +0100 Subject: [PATCH 2114/2215] All parameters should be named in a function [readability/function] --- telldus-core/common/EventHandler_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index 1fdd6e0e..28f1d6fe 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -55,7 +55,7 @@ EventRef EventHandler::addEvent() { return event; } -void EventHandler::signal(Event *) { +void EventHandler::signal(Event *event) { } bool EventHandler::waitForAny() { From 6136c16d834e9fb1efb57951e2b007922e56e0cc Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Dec 2012 17:16:06 +0100 Subject: [PATCH 2115/2215] Use static_cast(...) instead of C-style cast [readability/casting] --- telldus-core/common/Socket_win.cpp | 6 +++--- telldus-core/service/SettingsWinRegistry.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index c1d2fec3..b112ff97 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -126,9 +126,9 @@ std::wstring Socket::read(int timeout){ if (!fSuccess) { DWORD err = GetLastError(); - debuglog((int)err, "Something read error"); + debuglog(static_cast(err), "Something read error"); if(err != ERROR_OPERATION_ABORTED){ //gets this "error" always when nothing was reads - debuglog((int)err, "Socket read error"); + debuglog(static_cast(err), "Socket read error"); } if(err == ERROR_MORE_DATA){ @@ -138,7 +138,7 @@ std::wstring Socket::read(int timeout){ buf[0] = 0; } if (err == ERROR_BROKEN_PIPE){ - debuglog((int)err, "Got an error, close this socket"); + debuglog(static_cast(err), "Got an error, close this socket"); d->connected = false; break; //TODO is this correct? } diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 59364509..7debf9eb 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -67,7 +67,7 @@ int Settings::getNumberOfNodes(Node type) const { DWORD dNumSubKeys; RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - intNumberOfNodes = (int)dNumSubKeys; + intNumberOfNodes = static_cast(dNumSubKeys); RegCloseKey(hk); } @@ -237,7 +237,7 @@ int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &nam long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS){ - int length = (int)value.length() * sizeof(wchar_t); + int length = static_cast(value.length()) * sizeof(wchar_t); RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); } else { ret = TELLSTICK_ERROR_UNKNOWN; @@ -253,7 +253,7 @@ int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &name, std::wstring strSetting = getStringSetting(type, intNodeId, name, parameter); if (strSetting.length()) { - intReturn = (int)strSetting[0]; //TODO: do real conversion instead + intReturn = static_cast(strSetting[0]); //TODO: do real conversion instead } return intReturn; From 3441b9cc451fce7baf1cc03cd4599405a192ca6b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Dec 2012 17:25:17 +0100 Subject: [PATCH 2116/2215] Missing username in TODO according to Google style guidelines "readability/todo" --- telldus-core/client/Client.cpp | 2 +- telldus-core/common/Socket_win.cpp | 2 +- telldus-core/service/SettingsWinRegistry.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index f998886e..2224a626 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -171,7 +171,7 @@ std::wstring Client::sendToService(const Message &msg) { debuglog(555, "Error in write, should retry"); continue; //retry } - readData = s.read(1000); //TODO changed to 10000 from 5000, how much does this do...? + readData = s.read(1000); // TODO(stefan): changed to 10000 from 5000, how much does this do...? if(readData == L""){ msleep(500); continue; // TODO(stefan): can we be really sure it SHOULD be anything? diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index b112ff97..5724d9ed 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -140,7 +140,7 @@ std::wstring Socket::read(int timeout){ if (err == ERROR_BROKEN_PIPE){ debuglog(static_cast(err), "Got an error, close this socket"); d->connected = false; - break; //TODO is this correct? + break; // TODO(stefan): is this correct? } } returnString.append(buf); diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 7debf9eb..f173be86 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -253,7 +253,7 @@ int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &name, std::wstring strSetting = getStringSetting(type, intNodeId, name, parameter); if (strSetting.length()) { - intReturn = static_cast(strSetting[0]); //TODO: do real conversion instead + intReturn = static_cast(strSetting[0]); // TODO(micke): do real conversion instead } return intReturn; From 2cb1a2ac97fe90d96c438ae0b6a2292b08f118b2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Dec 2012 12:20:19 +0100 Subject: [PATCH 2117/2215] Set the flag O_CLOEXEC on all file handles so they don't interferes with the execution of scripts. See #100 --- telldus-core/common/Socket_unix.cpp | 2 +- .../service/ConnectionListener_unix.cpp | 2 +- telldus-core/service/SettingsConfuse.cpp | 28 +++++++++++++------ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 046cdaf3..3f8a68b7 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -57,7 +57,7 @@ void Socket::connect(const std::wstring &server) { struct sockaddr_un remote; socklen_t len; - if ((d->socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + if ((d->socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) { return; } std::string name = "/tmp/" + std::string(server.begin(), server.end()); diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 3ea0a55e..adef9cb8 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -47,7 +47,7 @@ void ConnectionListener::run() { SOCKET_T serverSocket; struct sockaddr_un name; - serverSocket = socket(PF_LOCAL, SOCK_STREAM, 0); + serverSocket = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); if (serverSocket < 0) { return; } diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index f3049e8e..9c30fb7f 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -99,7 +99,7 @@ int Settings::addNode(Node type) { TelldusCore::MutexLocker locker(&mutex); int intNodeId = getNextNodeId(type); - FILE *fp = fopen(CONFIG_FILE, "w"); + FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } @@ -145,7 +145,7 @@ int Settings::getNextNodeId(Node type) const { */ int Settings::removeNode(Node type, int intNodeId) { TelldusCore::MutexLocker locker(&mutex); - FILE *fp = fopen(CONFIG_FILE, "w"); + FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } @@ -192,7 +192,7 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w cfg_setint(cfg_device, "state", intDeviceState); cfg_setstr(cfg_device, "stateValue", TelldusCore::wideToString(strDeviceStateValue).c_str()); - FILE *fp = fopen(VAR_CONFIG_FILE, "w"); + FILE *fp = fopen(VAR_CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle if(fp == 0) { return false; } @@ -202,7 +202,7 @@ bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::w } } // The device is not found in the file, we must create it manualy... - FILE *fp = fopen(VAR_CONFIG_FILE, "w"); + FILE *fp = fopen(VAR_CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle if(!fp) { fprintf(stderr, "Failed to write state to %s: %s\n", VAR_CONFIG_FILE, strerror(errno)); @@ -298,7 +298,7 @@ int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &n return TELLSTICK_ERROR_CONFIG_SYNTAX; } cfg_setstr(p, TelldusCore::wideToString(name).c_str(), newValue.c_str()); - FILE *fp = fopen(CONFIG_FILE, "w"); + FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } @@ -345,7 +345,7 @@ int Settings::setIntSetting(Node type, int intDeviceId, const std::wstring &name } else { cfg_setint(cfg_device, TelldusCore::wideToString(name).c_str(), value); } - FILE *fp = fopen(CONFIG_FILE, "w"); + FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle if (!fp) { return TELLSTICK_ERROR_PERMISSION_DENIED; } @@ -403,12 +403,18 @@ bool readConfig(cfg_t **cfg) { CFG_END() }; + FILE *fp = fopen(CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle + if (!fp) { + return false; + } (*cfg) = cfg_init(opts, CFGF_NOCASE); - if (cfg_parse((*cfg), CONFIG_FILE) == CFG_PARSE_ERROR) { + if (cfg_parse_fp((*cfg), fp) == CFG_PARSE_ERROR) { (*cfg) = 0; + fclose(fp); return false; } + fclose(fp); return true; } @@ -424,11 +430,17 @@ bool readVarConfig(cfg_t **cfg) { CFG_END() }; + FILE *fp = fopen(VAR_CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle + if (!fp) { + return false; + } (*cfg) = cfg_init(opts, CFGF_NOCASE); - if (cfg_parse((*cfg), VAR_CONFIG_FILE) == CFG_PARSE_ERROR) { + if (cfg_parse_fp((*cfg), fp) == CFG_PARSE_ERROR) { (*cfg) = 0; + fclose(fp); return false; } + fclose(fp); return true; } From 38e624af663a2c294533166ad90a3af421d30157 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Dec 2012 17:28:36 +0100 Subject: [PATCH 2118/2215] stdlib.h is needed for malloc --- telldus-core/common/common.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index d4f040e6..6c693b8e 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -19,7 +19,7 @@ #endif #include #include -//#include +#include #include #include #include "common/Strings.h" @@ -48,7 +48,7 @@ inline void debuglogfilename(const int intMessage, const std::string strMessage, #ifdef _WINDOWS static bool firstRun = true; std::ofstream file; - + if (firstRun) { file.open(filename.c_str(), std::ios::out); firstRun = false; From 174c31f4caa333f2d0cd9663fe3e774571a6982a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 11:18:07 +0100 Subject: [PATCH 2119/2215] Use fcntl() to set FD_CLOEXEC on OS X since the SOCK_CLOEXEC flag for socket() isn't supported. --- telldus-core/common/Socket_unix.cpp | 8 ++++++++ telldus-core/service/ConnectionListener_unix.cpp | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 3f8a68b7..b810ba8c 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,9 @@ #include "common/Strings.h" #define BUFSIZE 512 +#if defined(_MACOSX) && !defined(SOCK_CLOEXEC) + #define SOCK_CLOEXEC 0 +#endif namespace TelldusCore { @@ -60,6 +64,10 @@ void Socket::connect(const std::wstring &server) { if ((d->socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) { return; } +#if defined(_MACOSX) + int op = fcntl(d->socket, F_GETFD); + fcntl(d->socket, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet +#endif std::string name = "/tmp/" + std::string(server.begin(), server.end()); remote.sun_family = AF_UNIX; snprintf(remote.sun_path, sizeof(remote.sun_path), "%s", name.c_str()); diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index adef9cb8..a4af59a5 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -10,12 +10,17 @@ #include #include #include +#include #include #include #include "service/ConnectionListener.h" #include "common/Socket.h" +#if defined(_MACOSX) && !defined(SOCK_CLOEXEC) + #define SOCK_CLOEXEC 0 +#endif + class ConnectionListener::PrivateData { public: TelldusCore::EventRef waitEvent; @@ -51,6 +56,10 @@ void ConnectionListener::run() { if (serverSocket < 0) { return; } +#if defined(_MACOSX) + int op = fcntl(serverSocket, F_GETFD); + fcntl(serverSocket, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet +#endif name.sun_family = AF_LOCAL; memset(name.sun_path, '\0', sizeof(name.sun_path)); strncpy(name.sun_path, d->name.c_str(), sizeof(name.sun_path)); From bca00ef1482abb825fb18d43045d3211eeba7c92 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 11:21:13 +0100 Subject: [PATCH 2120/2215] F_SETFD must be supplied to fcntl() to set options --- telldus-core/common/Socket_unix.cpp | 2 +- telldus-core/service/ConnectionListener_unix.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index b810ba8c..2ee1d7c8 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -66,7 +66,7 @@ void Socket::connect(const std::wstring &server) { } #if defined(_MACOSX) int op = fcntl(d->socket, F_GETFD); - fcntl(d->socket, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet + fcntl(d->socket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet #endif std::string name = "/tmp/" + std::string(server.begin(), server.end()); remote.sun_family = AF_UNIX; diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index a4af59a5..5a53d14f 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -58,7 +58,7 @@ void ConnectionListener::run() { } #if defined(_MACOSX) int op = fcntl(serverSocket, F_GETFD); - fcntl(serverSocket, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet + fcntl(serverSocket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet #endif name.sun_family = AF_LOCAL; memset(name.sun_path, '\0', sizeof(name.sun_path)); From 69c67e3c0982c79bc88842a8b0e02133ca29b87b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Dec 2012 17:42:52 +0100 Subject: [PATCH 2121/2215] Fixed placement of curly braces according to Google style guidelines "whitespace/braces" --- telldus-core/client/Client.cpp | 6 ++-- telldus-core/common/EventHandler_win.cpp | 2 +- telldus-core/common/Event_win.cpp | 3 +- telldus-core/common/Socket_win.cpp | 29 +++++++++---------- telldus-core/common/common.h | 6 ++-- .../service/ConnectionListener_win.cpp | 10 +++---- telldus-core/service/Controller.cpp | 2 +- telldus-core/service/SettingsWinRegistry.cpp | 22 +++++++------- .../service/TelldusWinService_win.cpp | 3 +- 9 files changed, 39 insertions(+), 44 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 2224a626..df26ed34 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -87,10 +87,10 @@ void Client::run() { d->eventSocket.connect(L"TelldusEvents"); while(d->running) { - if(!d->eventSocket.isConnected()){ + if(!d->eventSocket.isConnected()) { debuglog(555, "Client, Trying to (re)connect to TelldusEvents"); d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service - if(!d->eventSocket.isConnected()){ + if(!d->eventSocket.isConnected()) { //reconnect didn't succeed, wait a while and try again msleep(2000); continue; @@ -172,7 +172,7 @@ std::wstring Client::sendToService(const Message &msg) { continue; //retry } readData = s.read(1000); // TODO(stefan): changed to 10000 from 5000, how much does this do...? - if(readData == L""){ + if(readData == L"") { msleep(500); continue; // TODO(stefan): can we be really sure it SHOULD be anything? // TODO(stefan): perhaps break here instead? diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index 28f1d6fe..9e5f3dbe 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -60,7 +60,7 @@ void EventHandler::signal(Event *event) { bool EventHandler::waitForAny() { - while(1){ + while(1) { int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000); if (result == WAIT_TIMEOUT) { continue; diff --git a/telldus-core/common/Event_win.cpp b/telldus-core/common/Event_win.cpp index 522e3a77..e116d380 100644 --- a/telldus-core/common/Event_win.cpp +++ b/telldus-core/common/Event_win.cpp @@ -15,8 +15,7 @@ public: }; Event::Event(EventHandler *handler) - :EventBase(handler) -{ + :EventBase(handler) { d = new PrivateData; d->event = CreateEvent(NULL, true, false, NULL); } diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 5724d9ed..162624c2 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -29,8 +29,7 @@ Socket::Socket() { d->running = true; } -Socket::Socket(SOCKET_T hPipe) -{ +Socket::Socket(SOCKET_T hPipe) { d = new PrivateData; d->hPipe = hPipe; d->connected = true; @@ -38,7 +37,7 @@ Socket::Socket(SOCKET_T hPipe) } -Socket::~Socket(void){ +Socket::~Socket(void) { d->running = false; SetEvent(d->readEvent); //signal for break if (d->hPipe != INVALID_HANDLE_VALUE) { @@ -48,7 +47,7 @@ Socket::~Socket(void){ delete d; } -void Socket::connect(const std::wstring &server){ +void Socket::connect(const std::wstring &server) { BOOL fSuccess = false; std::wstring name(L"\\\\.\\pipe\\" + server); @@ -79,7 +78,7 @@ void Socket::connect(const std::wstring &server){ d->connected = true; } -void Socket::stopReadWait(){ +void Socket::stopReadWait() { d->running = false; SetEvent(d->readEvent); } @@ -88,7 +87,7 @@ std::wstring Socket::read() { return read(INFINITE); } -std::wstring Socket::read(int timeout){ +std::wstring Socket::read(int timeout) { wchar_t buf[BUFSIZE]; int result; DWORD cbBytesRead = 0; @@ -102,7 +101,7 @@ std::wstring Socket::read(int timeout){ std::wstring returnString; bool moreData = true; - while(moreData){ + while(moreData) { moreData = false; memset(&buf, 0, sizeof(buf)); @@ -110,7 +109,7 @@ std::wstring Socket::read(int timeout){ result = WaitForSingleObject(oOverlap.hEvent, timeout); - if(!d->running){ + if(!d->running) { CancelIo(d->hPipe); WaitForSingleObject(oOverlap.hEvent, INFINITE); d->readEvent = 0; @@ -127,17 +126,17 @@ std::wstring Socket::read(int timeout){ if (!fSuccess) { DWORD err = GetLastError(); debuglog(static_cast(err), "Something read error"); - if(err != ERROR_OPERATION_ABORTED){ //gets this "error" always when nothing was reads + if(err != ERROR_OPERATION_ABORTED) { //gets this "error" always when nothing was reads debuglog(static_cast(err), "Socket read error"); } - if(err == ERROR_MORE_DATA){ + if(err == ERROR_MORE_DATA) { moreData = true; } - else{ + else { buf[0] = 0; } - if (err == ERROR_BROKEN_PIPE){ + if (err == ERROR_BROKEN_PIPE) { debuglog(static_cast(err), "Got an error, close this socket"); d->connected = false; break; // TODO(stefan): is this correct? @@ -150,7 +149,7 @@ std::wstring Socket::read(int timeout){ return returnString; } -void Socket::write(const std::wstring &msg){ +void Socket::write(const std::wstring &msg) { OVERLAPPED oOverlap; DWORD bytesWritten = 0; @@ -176,7 +175,7 @@ void Socket::write(const std::wstring &msg){ return; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); - if (!fSuccess){ + if (!fSuccess) { debuglog(result, "Error in GetOverlappedResult"); result = GetLastError(); debuglog(result, "Error in GetOverlappedResult, this message"); @@ -193,7 +192,7 @@ void Socket::write(const std::wstring &msg){ } } -bool Socket::isConnected(){ +bool Socket::isConnected() { return d->connected; } diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 6c693b8e..b3c6772a 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -43,7 +43,7 @@ inline void dlog(const char *fmt, ...) { fflush(stdout); } -inline void debuglogfilename(const int intMessage, const std::string strMessage, const std::string filename){ +inline void debuglogfilename(const int intMessage, const std::string strMessage, const std::string filename) { #ifdef _WINDOWS static bool firstRun = true; @@ -76,12 +76,12 @@ inline void debuglogfilename(const int intMessage, const std::string strMessage, #endif } -inline void debuglogservice(const int intMessage, const std::string strMessage){ +inline void debuglogservice(const int intMessage, const std::string strMessage) { std::string filename("C:/telldus_service_debug.txt"); debuglogfilename(intMessage, strMessage, filename); } -inline void debuglog(const int intMessage, const std::string strMessage){ +inline void debuglog(const int intMessage, const std::string strMessage) { std::string filename("C:/telldus_client_debug.txt"); debuglogfilename(intMessage, strMessage, filename); } diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index c50b487b..9ad58c85 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -23,8 +23,7 @@ public: TelldusCore::EventRef waitEvent; }; -ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) -{ +ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) { d = new PrivateData; d->hEvent = 0; @@ -65,8 +64,7 @@ ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::Ev if (!SetSecurityDescriptorDacl(pSD, TRUE, // bDaclPresent flag pACL, - FALSE)) // not a default DACL - { + FALSE)) { // not a default DACL LocalFree(pSD); FreeSid(pEveryoneSID); } @@ -123,7 +121,7 @@ void ConnectionListener::run() { alreadyConnected = GetLastError() == ERROR_PIPE_CONNECTED; recreate = false; } - if(!alreadyConnected){ + if(!alreadyConnected) { DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000); if (!d->running) { CancelIo(hPipe); @@ -131,7 +129,7 @@ void ConnectionListener::run() { break; } - if(result == WAIT_TIMEOUT){ + if(result == WAIT_TIMEOUT) { //CloseHandle(hPipe); continue; } diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 28fcc1d1..786a5261 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -15,7 +15,7 @@ #include "common/Strings.h" #include "common/common.h" //debug -inline int random( unsigned int* seed ){ +inline int random( unsigned int* seed ) { #ifdef _WINDOWS unsigned int randomNumber; rand_s( &randomNumber ); //no seed needed diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index f173be86..1816cd88 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -61,7 +61,7 @@ int Settings::getNumberOfNodes(Node type) const { long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); - if(lnExists == ERROR_SUCCESS){ + if(lnExists == ERROR_SUCCESS) { std::wstring strNumSubKeys; DWORD dNumSubKeys; @@ -83,7 +83,7 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); - if(lnExists == ERROR_SUCCESS){ + if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD size = intMaxRegValueLength; @@ -132,14 +132,14 @@ int Settings::getNextNodeId(Node type) const { long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created - if(lnExists == ERROR_SUCCESS){ + if(lnExists == ERROR_SUCCESS) { DWORD dwLength = sizeof(DWORD); DWORD nResult(0); long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); - if(lngStatus == ERROR_SUCCESS){ + if(lngStatus == ERROR_SUCCESS) { intReturn = nResult + 1; } else { intReturn = 1; @@ -163,7 +163,7 @@ int Settings::removeNode(Node type, int intNodeId) { long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); - if(lngSuccess == ERROR_SUCCESS){ + if(lngSuccess == ERROR_SUCCESS) { //one of the deletions succeeded return TELLSTICK_SUCCESS; } @@ -171,19 +171,19 @@ int Settings::removeNode(Node type, int intNodeId) { return TELLSTICK_ERROR_UNKNOWN; } -std::wstring Settings::getSetting(const std::wstring &strName) const{ +std::wstring Settings::getSetting(const std::wstring &strName) const { std::wstring strReturn; HKEY hk; std::wstring strCompleteRegPath = d->strRegPath; long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); - if(lnExists == ERROR_SUCCESS){ + if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; long lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - if(lngStatus == ERROR_MORE_DATA){ + if(lngStatus == ERROR_MORE_DATA) { //The buffer is to small, recreate it delete[] Buff; Buff = new wchar_t[dwLength]; @@ -206,12 +206,12 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); - if(lnExists == ERROR_SUCCESS){ + if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; long lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); - if(lngStatus == ERROR_MORE_DATA){ + if(lngStatus == ERROR_MORE_DATA) { //The buffer is to small, recreate it delete[] Buff; Buff = new wchar_t[dwLength]; @@ -236,7 +236,7 @@ int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &nam strCompleteRegPath.append(strNodeId); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); - if (lnExists == ERROR_SUCCESS){ + if (lnExists == ERROR_SUCCESS) { int length = static_cast(value.length()) * sizeof(wchar_t); RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); } else { diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 286c2b4e..ed5462bf 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -20,8 +20,7 @@ static const GUID GUID_DEVINTERFACE_USBRAW = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; TelldusWinService::TelldusWinService() - :tm(0) -{ + :tm(0) { tm = new TelldusMain(); } From e38eb0f72da4a58c54768152238526c4c0997aaf Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Dec 2012 10:50:56 +0100 Subject: [PATCH 2122/2215] Ordered header files correctly according to Google style guidelines "build/include_order" --- telldus-core/common/EventHandler_win.cpp | 6 +++--- telldus-core/common/Socket_win.cpp | 7 ++++--- telldus-core/common/common.h | 12 +++++++----- telldus-core/service/ConnectionListener_win.cpp | 7 ++++--- telldus-core/service/EventUpdateManager.cpp | 14 ++++---------- telldus-core/service/SettingsWinRegistry.cpp | 10 +++++----- telldus-core/service/TelldusMain.cpp | 12 +++++------- telldus-core/service/TelldusWinService_win.cpp | 7 ++++--- telldus-core/service/main_win.cpp | 5 ++--- 9 files changed, 38 insertions(+), 42 deletions(-) diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index 9e5f3dbe..60c34f9e 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -5,12 +5,12 @@ // // #include "common/EventHandler.h" -#include "common/Event.h" -#include "common/Mutex.h" - #include #include +#include "common/Event.h" +#include "common/Mutex.h" + namespace TelldusCore { class EventHandler::PrivateData { diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 162624c2..b1b6110d 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -4,11 +4,12 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "common/Socket.h" -#include "common/common.h" -#include #include #include +#include + +#include "common/common.h" +#include "common/Socket.h" #define BUFSIZE 512 diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index b3c6772a..f06fc205 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -9,11 +9,10 @@ #define TELLDUS_CORE_COMMON_COMMON_H_ #ifdef _WINDOWS -#include -#include -#include #define strcasecmp _stricmp #define strncasecmp _strnicmp +#include +#include #else #include #endif @@ -21,11 +20,14 @@ #include #include #include +#include + +#ifdef _WINDOWS +#include +#endif #include #include "common/Strings.h" -#include - inline void msleep( const int msec) { #ifdef _WINDOWS Sleep(msec); diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 9ad58c85..5b82922f 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -5,12 +5,13 @@ // // #include "service/ConnectionListener.h" -#include "common/Event.h" -#include "common/Socket.h" -#include #include #include +#include + +#include "common/Event.h" +#include "common/Socket.h" #define BUFSIZE 512 diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 653809fa..fa79c9c3 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -16,9 +16,6 @@ #include #endif // _LINUX -#include "common/common.h" //debug -#include //debug -#include //debug #include #include #include @@ -27,13 +24,14 @@ #include #endif // _LINUX -#include "service/ConnectionListener.h" -#include "service/config.h" +#include "common/common.h" //debug #include "common/EventHandler.h" #include "common/Message.h" #include "common/Socket.h" -#include "service/Log.h" #include "common/Strings.h" +#include "service/config.h" +#include "service/ConnectionListener.h" +#include "service/Log.h" typedef std::list SocketList; typedef std::list StringList; @@ -172,10 +170,6 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { it = d->clients.erase(it); } } - //printf("Sent message to %d connected clients", connected) - //std::stringstream strMessage; - //strMessage << "Sent message to " << connected << " clients" << std::endl; - //debuglogservice(0, strMessage.str()); } void EventUpdateManager::executeScripts(EventUpdateData *data) { diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 1816cd88..b6d945bf 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -4,17 +4,17 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "service/Settings.h" -#include "common/Strings.h" #include +#include +#include #include #include #include -#include -#include -#include "common/common.h" #include "../client/telldus-core.h" +#include "common/common.h" +#include "common/Strings.h" +#include "service/Settings.h" const int intMaxRegValueLength = 1000; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index fe3830cd..00a10a06 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -5,22 +5,20 @@ // // #include "service/TelldusMain.h" -#include "common/common.h" //debug - #include #include #include -#include "service/ConnectionListener.h" +#include "common/common.h" //debug #include "common/EventHandler.h" #include "service/ClientCommunicationHandler.h" -#include "service/DeviceManager.h" -#include "service/ControllerManager.h" +#include "service/ConnectionListener.h" #include "service/ControllerListener.h" +#include "service/ControllerManager.h" +#include "service/DeviceManager.h" #include "service/EventUpdateManager.h" -#include "service/Timer.h" #include "service/Log.h" - +#include "service/Timer.h" class TelldusMain::PrivateData { public: diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index ed5462bf..7a4f9d51 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -5,12 +5,13 @@ // // #include "service/TelldusWinService_win.h" -#include "service/TelldusMain.h" -#include "service/Log.h" #include -#include #include +#include + +#include "service/Log.h" +#include "service/TelldusMain.h" int g_argc; char **g_argv; diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp index b436e209..88a23ee3 100644 --- a/telldus-core/service/main_win.cpp +++ b/telldus-core/service/main_win.cpp @@ -4,12 +4,11 @@ // Copyright: See COPYING file that comes with this distribution // // -#include "service/TelldusWinService_win.h" -//#include - #include #include +#include "service/TelldusWinService_win.h" +//#include int main(int argc, char **argv) { g_argc = argc; From fb79664508c73d598d3a7cc99d58812738a095d8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Dec 2012 11:28:27 +0100 Subject: [PATCH 2123/2215] Removed whitespace after line end, accoring to Google style guidelines "whitespace/end_of_line" --- telldus-core/common/EventHandler_win.cpp | 1 - telldus-core/common/Socket_win.cpp | 46 +++++++++---------- .../service/ConnectionListener_win.cpp | 23 +++++----- telldus-core/service/SettingsWinRegistry.cpp | 32 ++++++------- .../service/TelldusWinService_win.cpp | 6 +-- telldus-core/service/TelldusWinService_win.h | 2 +- 6 files changed, 53 insertions(+), 57 deletions(-) diff --git a/telldus-core/common/EventHandler_win.cpp b/telldus-core/common/EventHandler_win.cpp index 60c34f9e..57833bde 100644 --- a/telldus-core/common/EventHandler_win.cpp +++ b/telldus-core/common/EventHandler_win.cpp @@ -59,7 +59,6 @@ void EventHandler::signal(Event *event) { } bool EventHandler::waitForAny() { - while(1) { int result = WaitForMultipleObjects(d->eventCount, d->eventArray, FALSE, 1000); if (result == WAIT_TIMEOUT) { diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index b1b6110d..68ed25d5 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -53,25 +53,25 @@ void Socket::connect(const std::wstring &server) { std::wstring name(L"\\\\.\\pipe\\" + server); d->hPipe = CreateFile( - (const wchar_t *)name.c_str(), // pipe name - GENERIC_READ | // read and write access - GENERIC_WRITE, - 0, // no sharing + (const wchar_t *)name.c_str(), // pipe name + GENERIC_READ | // read and write access + GENERIC_WRITE, + 0, // no sharing NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - FILE_FLAG_OVERLAPPED, // default attributes - NULL); // no template file + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, // default attributes + NULL); // no template file if (d->hPipe == INVALID_HANDLE_VALUE) { return; } - - DWORD dwMode = PIPE_READMODE_MESSAGE; - fSuccess = SetNamedPipeHandleState( - d->hPipe, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time + + DWORD dwMode = PIPE_READMODE_MESSAGE; + fSuccess = SetNamedPipeHandleState( + d->hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time if (!fSuccess) { return; @@ -92,8 +92,8 @@ std::wstring Socket::read(int timeout) { wchar_t buf[BUFSIZE]; int result; DWORD cbBytesRead = 0; - OVERLAPPED oOverlap; - + OVERLAPPED oOverlap; + memset(&oOverlap, 0, sizeof(OVERLAPPED)); d->readEvent = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -101,15 +101,15 @@ std::wstring Socket::read(int timeout) { BOOL fSuccess = false; std::wstring returnString; bool moreData = true; - + while(moreData) { moreData = false; memset(&buf, 0, sizeof(buf)); ReadFile( d->hPipe, &buf, sizeof(buf)-sizeof(wchar_t), &cbBytesRead, &oOverlap); - + result = WaitForSingleObject(oOverlap.hEvent, timeout); - + if(!d->running) { CancelIo(d->hPipe); WaitForSingleObject(oOverlap.hEvent, INFINITE); @@ -123,7 +123,7 @@ std::wstring Socket::read(int timeout) { // Cancel, we still need to cleanup } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, true); - + if (!fSuccess) { DWORD err = GetLastError(); debuglog(static_cast(err), "Something read error"); @@ -151,7 +151,7 @@ std::wstring Socket::read(int timeout) { } void Socket::write(const std::wstring &msg) { - + OVERLAPPED oOverlap; DWORD bytesWritten = 0; int result; @@ -161,7 +161,7 @@ void Socket::write(const std::wstring &msg) { HANDLE writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL); oOverlap.hEvent = writeEvent; - + BOOL writeSuccess = WriteFile(d->hPipe, msg.data(), (DWORD)msg.length()*sizeof(wchar_t), &bytesWritten, &oOverlap); result = GetLastError(); if (writeSuccess || result == ERROR_IO_PENDING) { @@ -189,7 +189,7 @@ void Socket::write(const std::wstring &msg) { d->hPipe = 0; debuglog(result, "Error in write event, closing socket"); d->connected = false; - return; + return; } } diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 5b82922f..570c13a6 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -38,12 +38,12 @@ ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::Ev PSID pEveryoneSID = NULL; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; - pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSD == NULL) { return; - } - - if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { + } + + if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { LocalFree(pSD); return; } @@ -60,12 +60,11 @@ ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::Ev ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; - - // Add the ACL to the security descriptor. - if (!SetSecurityDescriptorDacl(pSD, - TRUE, // bDaclPresent flag - pACL, - FALSE)) { // not a default DACL + // Add the ACL to the security descriptor. + if (!SetSecurityDescriptorDacl(pSD, + TRUE, // bDaclPresent flag + pACL, + FALSE)) { // not a default DACL LocalFree(pSD); FreeSid(pEveryoneSID); } @@ -97,7 +96,7 @@ void ConnectionListener::run() { d->hEvent = CreateEvent(NULL, true, false, NULL); oOverlap.hEvent = d->hEvent; bool recreate = true; - + while (1) { BOOL alreadyConnected = false; if (recreate) { @@ -129,7 +128,7 @@ void ConnectionListener::run() { WaitForSingleObject(oOverlap.hEvent, INFINITE); break; } - + if(result == WAIT_TIMEOUT) { //CloseHandle(hPipe); continue; diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index b6d945bf..8da9fb9e 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -58,15 +58,15 @@ int Settings::getNumberOfNodes(Node type) const { int intNumberOfNodes = 0; HKEY hk; - + long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); - + if(lnExists == ERROR_SUCCESS) { - + std::wstring strNumSubKeys; DWORD dNumSubKeys; RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - + intNumberOfNodes = static_cast(dNumSubKeys); RegCloseKey(hk); @@ -80,11 +80,11 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { int intReturn = -1; HKEY hk; - + long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); - + if(lnExists == ERROR_SUCCESS) { - + wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD size = intMaxRegValueLength; if (RegEnumKeyEx(hk, intNodeIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { @@ -111,7 +111,7 @@ int Settings::addNode(Node type) { std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - + if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) { //fail intNodeId = -1; @@ -131,9 +131,8 @@ int Settings::getNextNodeId(Node type) const { DWORD dwDisp; long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created - + if(lnExists == ERROR_SUCCESS) { - DWORD dwLength = sizeof(DWORD); DWORD nResult(0); @@ -146,7 +145,6 @@ int Settings::getNextNodeId(Node type) const { } DWORD dwVal = intReturn; RegSetValueEx (hk, L"LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); - } RegCloseKey(hk); return intReturn; @@ -157,7 +155,7 @@ int Settings::getNextNodeId(Node type) const { */ int Settings::removeNode(Node type, int intNodeId) { TelldusCore::MutexLocker locker(&mutex); - + std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); @@ -177,7 +175,7 @@ std::wstring Settings::getSetting(const std::wstring &strName) const { std::wstring strCompleteRegPath = d->strRegPath; long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); - + if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; @@ -205,7 +203,7 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); - + if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; @@ -230,12 +228,12 @@ int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &nam HKEY hk; int ret = TELLSTICK_SUCCESS; - + std::wstring strNodeId = TelldusCore::intToWstring(intNodeId); std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(strNodeId); long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); - + if (lnExists == ERROR_SUCCESS) { int length = static_cast(value.length()) * sizeof(wchar_t); RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1); diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index 7a4f9d51..e444de5e 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -66,7 +66,7 @@ DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DW if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) { return ERROR_CALL_NOT_IMPLEMENTED; } - + PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast(lpEventData); if (!pDevInf) { return ERROR_CALL_NOT_IMPLEMENTED; @@ -101,7 +101,7 @@ DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DW long int vid = strtol(std::string(strVID.begin(), strVID.end()).c_str(), NULL, 16); long int pid = strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16); - + if (dwEventType == DBT_DEVICEARRIVAL) { tm->deviceInsertedOrRemoved(vid, pid, true); } else { @@ -170,7 +170,7 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { Log::notice("TelldusService stopping"); Log::destroy(); - + // service was stopped instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus ); diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index dcb3e33a..be6155f5 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -22,7 +22,7 @@ public: ~TelldusWinService(); static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); - + protected: void stop(); From e36b2287e84944ebd67b159161e59b09f9db43c9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 12:01:12 +0100 Subject: [PATCH 2124/2215] Uncommented text after #endif is non-standard. Use a comment. [build/endif_comment] --- telldus-core/service/TelldusWinService_win.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index be6155f5..0780768b 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -38,4 +38,4 @@ private: static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); }; -#endif TELLDUSSERVICE_WIN_H +#endif // TELLDUSSERVICE_WIN_H From 7000632f6cfd8de50223d7b81ff0b41b397166a2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 12:05:11 +0100 Subject: [PATCH 2125/2215] Fix #ifndef header guard style, according to Google style guidelines "build/header_guard" --- telldus-core/service/TelldusWinService_win.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index 0780768b..13e81ab4 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -4,8 +4,8 @@ // Copyright: See COPYING file that comes with this distribution // // -#ifndef TELLDUSSERVICE_WIN_H -#define TELLDUSSERVICE_WIN_H +#ifndef TELLDUS_CORE_SERVICE_TELLDUSWINSERVICE_WIN_H_ +#define TELLDUS_CORE_SERVICE_TELLDUSWINSERVICE_WIN_H_ #include @@ -38,4 +38,4 @@ private: static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); }; -#endif // TELLDUSSERVICE_WIN_H +#endif // TELLDUS_CORE_SERVICE_TELLDUSWINSERVICE_WIN_H_ From 52faa7a36deb34de64e3bb957aaa9ad36b6c923d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 12:46:01 +0100 Subject: [PATCH 2126/2215] Use safe version of date functions according to google style guidelines (runtime/threadsafe_fn) --- telldus-core/common/common.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index f06fc205..5e9221de 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -58,16 +58,18 @@ inline void debuglogfilename(const int intMessage, const std::string strMessage, file.open(filename.c_str(), std::ios::out | std::ios::app); } - time_t now = time(0); + __time32_t now = _time32(0); // Convert now to tm struct for local timezone - tm* localtm = localtime(&now); - char* thetime = asctime(localtm); - thetime[strlen(thetime)-1] = '\0'; - - file << thetime << " [" << GetCurrentThreadId() << "] " << intMessage << " - " << strMessage << "\n"; - file.flush(); - file.close(); + struct tm localtm; + _localtime32_s(&localtm, &now); + char thetime[32]; + errno_t err = asctime_s(thetime, 32, &localtm); + if (!err) { + file << thetime << " [" << GetCurrentThreadId() << "] " << intMessage << " - " << strMessage << "\n"; + file.flush(); + file.close(); + } #elif !defined(_MACOSX) && !defined(__FreeBSD__) pthread_t thread = pthread_self(); From ce24cabff91162ac27a683444d5fc0b4ff539ec6 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 12:58:17 +0100 Subject: [PATCH 2127/2215] Streams are highly discouraged except for logging according to Google style guidelines "readability/streams" --- telldus-core/common/common.h | 2 +- telldus-core/service/SettingsWinRegistry.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 5e9221de..2d0ff2b7 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -23,7 +23,7 @@ #include #ifdef _WINDOWS -#include +#include // NOLINT(readability/streams) #endif #include #include "common/Strings.h" diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 8da9fb9e..e5f6f3a9 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -5,8 +5,6 @@ // // #include -#include -#include #include #include #include From 8d90a4e14abfe4e0fc2067c65b199acb06b6611b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Dec 2012 12:10:16 +0100 Subject: [PATCH 2128/2215] Added whitespaces to comments according to Google style guidelines "whitespace/comments" --- .../client/CallbackMainDispatcher.cpp | 6 ++--- telldus-core/client/Client.cpp | 8 +++---- telldus-core/common/Socket_win.cpp | 12 +++++----- .../service/ConnectionListener_win.cpp | 22 +++++++++---------- telldus-core/service/Controller.cpp | 4 ++-- telldus-core/service/EventUpdateManager.cpp | 4 ++-- telldus-core/service/SettingsWinRegistry.cpp | 12 +++++----- telldus-core/service/TelldusMain.cpp | 2 +- .../service/TelldusWinService_win.cpp | 8 +++---- telldus-core/service/main_win.cpp | 2 +- 10 files changed, 40 insertions(+), 40 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 77685fa0..5a7614bf 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -102,12 +102,12 @@ void CallbackMainDispatcher::run() { if (!cbd) { continue; } - //debuglog(333, "Callbackevent, signalled"); + // debuglog(333, "Callbackevent, signalled"); TelldusCore::MutexLocker locker(&d->mutex); - //debuglog(333, "Callbackevent, locked"); + // debuglog(333, "Callbackevent, locked"); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { if ( (*callback_it)->type == cbd->type ) { - //debuglog((*callback_it)->id, "Callbackevent, sending"); + // debuglog((*callback_it)->id, "Callbackevent, sending"); std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); d->eventThreadList.push_back(ptr); } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index df26ed34..1ea23ef8 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -89,9 +89,9 @@ void Client::run() { while(d->running) { if(!d->eventSocket.isConnected()) { debuglog(555, "Client, Trying to (re)connect to TelldusEvents"); - d->eventSocket.connect(L"TelldusEvents"); //try to reconnect to service + d->eventSocket.connect(L"TelldusEvents"); // try to reconnect to service if(!d->eventSocket.isConnected()) { - //reconnect didn't succeed, wait a while and try again + // reconnect didn't succeed, wait a while and try again msleep(2000); continue; } @@ -160,7 +160,7 @@ std::wstring Client::sendToService(const Message &msg) { } Socket s; s.connect(L"TelldusClient"); - if (!s.isConnected()) { //Connection failed + if (!s.isConnected()) { // sConnection failed debuglog(555, "Connection failed"); msleep(500); continue; // retry @@ -169,7 +169,7 @@ std::wstring Client::sendToService(const Message &msg) { if (!s.isConnected()) { // Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) msleep(500); debuglog(555, "Error in write, should retry"); - continue; //retry + continue; // retry } readData = s.read(1000); // TODO(stefan): changed to 10000 from 5000, how much does this do...? if(readData == L"") { diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 68ed25d5..48d7a337 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -40,7 +40,7 @@ Socket::Socket(SOCKET_T hPipe) { Socket::~Socket(void) { d->running = false; - SetEvent(d->readEvent); //signal for break + SetEvent(d->readEvent); // signal for break if (d->hPipe != INVALID_HANDLE_VALUE) { CloseHandle(d->hPipe); d->hPipe = 0; @@ -68,10 +68,10 @@ void Socket::connect(const std::wstring &server) { DWORD dwMode = PIPE_READMODE_MESSAGE; fSuccess = SetNamedPipeHandleState( - d->hPipe, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time + d->hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time if (!fSuccess) { return; @@ -127,7 +127,7 @@ std::wstring Socket::read(int timeout) { if (!fSuccess) { DWORD err = GetLastError(); debuglog(static_cast(err), "Something read error"); - if(err != ERROR_OPERATION_ABORTED) { //gets this "error" always when nothing was reads + if(err != ERROR_OPERATION_ABORTED) { // gets this "error" always when nothing was reads debuglog(static_cast(err), "Socket read error"); } diff --git a/telldus-core/service/ConnectionListener_win.cpp b/telldus-core/service/ConnectionListener_win.cpp index 570c13a6..6fced4e2 100644 --- a/telldus-core/service/ConnectionListener_win.cpp +++ b/telldus-core/service/ConnectionListener_win.cpp @@ -102,16 +102,16 @@ void ConnectionListener::run() { if (recreate) { hPipe = CreateNamedPipe( (const wchar_t *)d->pipename.c_str(), // pipe name - PIPE_ACCESS_DUPLEX | // read/write access - FILE_FLAG_OVERLAPPED, //Overlapped mode - PIPE_TYPE_MESSAGE | // message type pipe - PIPE_READMODE_MESSAGE | // message-read mode - PIPE_WAIT, // blocking mode - PIPE_UNLIMITED_INSTANCES, // max. instances - BUFSIZE, // output buffer size - BUFSIZE, // input buffer size - 0, // client time-out - &d->sa); // default security attribute + PIPE_ACCESS_DUPLEX | // read/write access + FILE_FLAG_OVERLAPPED, // Overlapped mode + PIPE_TYPE_MESSAGE | // message type pipe + PIPE_READMODE_MESSAGE | // message-read mode + PIPE_WAIT, // blocking mode + PIPE_UNLIMITED_INSTANCES, // max. instances + BUFSIZE, // output buffer size + BUFSIZE, // input buffer size + 0, // client time-out + &d->sa); // default security attribute if (hPipe == INVALID_HANDLE_VALUE) { return; @@ -130,7 +130,7 @@ void ConnectionListener::run() { } if(result == WAIT_TIMEOUT) { - //CloseHandle(hPipe); + // CloseHandle(hPipe); continue; } BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false); diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 786a5261..14d58d73 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -13,12 +13,12 @@ #include "service/Protocol.h" #include "service/EventUpdateManager.h" #include "common/Strings.h" -#include "common/common.h" //debug +#include "common/common.h" // debug inline int random( unsigned int* seed ) { #ifdef _WINDOWS unsigned int randomNumber; - rand_s( &randomNumber ); //no seed needed + rand_s( &randomNumber ); // no seed needed return randomNumber; #else return rand_r( seed ); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index fa79c9c3..a3760b46 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -24,7 +24,7 @@ #include #endif // _LINUX -#include "common/common.h" //debug +#include "common/common.h" // debug #include "common/EventHandler.h" #include "common/Message.h" #include "common/Socket.h" @@ -164,7 +164,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { it++; } else { - //connection is dead, remove it + // connection is dead, remove it debuglogservice(0, "Lost connection, removing it"); delete *it; it = d->clients.erase(it); diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index e5f6f3a9..8a1958bc 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -111,7 +111,7 @@ int Settings::addNode(Node type) { strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) { - //fail + // fail intNodeId = -1; } @@ -123,12 +123,12 @@ int Settings::addNode(Node type) { * Get next available device id */ int Settings::getNextNodeId(Node type) const { - //Private, no locks needed + // Private, no locks needed int intReturn = -1; HKEY hk; DWORD dwDisp; - long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); //create or open if already created + long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); // create or open if already created if(lnExists == ERROR_SUCCESS) { DWORD dwLength = sizeof(DWORD); @@ -160,7 +160,7 @@ int Settings::removeNode(Node type, int intNodeId) { long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); if(lngSuccess == ERROR_SUCCESS) { - //one of the deletions succeeded + // one of the deletions succeeded return TELLSTICK_SUCCESS; } @@ -180,7 +180,7 @@ std::wstring Settings::getSetting(const std::wstring &strName) const { long lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA) { - //The buffer is to small, recreate it + // The buffer is to small, recreate it delete[] Buff; Buff = new wchar_t[dwLength]; lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); @@ -208,7 +208,7 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst long lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA) { - //The buffer is to small, recreate it + // The buffer is to small, recreate it delete[] Buff; Buff = new wchar_t[dwLength]; lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 00a10a06..473e4c9c 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -9,7 +9,7 @@ #include #include -#include "common/common.h" //debug +#include "common/common.h" // debug #include "common/EventHandler.h" #include "service/ClientCommunicationHandler.h" #include "service/ConnectionListener.h" diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index e444de5e..e662b43c 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -75,7 +75,7 @@ DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DW std::wstring name(pDevInf->dbcc_name); transform(name.begin(), name.end(), name.begin(), toupper); - //Parse VID + // Parse VID size_t posStart = name.find(L"VID_"); if (posStart == std::wstring::npos) { return ERROR_CALL_NOT_IMPLEMENTED; @@ -87,7 +87,7 @@ DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DW } std::wstring strVID = name.substr(posStart, posEnd-posStart); - //Parse PID + // Parse PID posStart = name.find(L"PID_"); if (posStart == std::wstring::npos) { return ERROR_CALL_NOT_IMPLEMENTED; @@ -125,7 +125,7 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { TelldusWinService instance; - //Enable debug if we hade this supplied + // Enable debug if we hade this supplied for(unsigned int i = 1; i < argc; ++i) { if (wcscmp(argv[i], L"--debug") == 0) { Log::setDebug(); @@ -165,7 +165,7 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) { Log::notice("TelldusService started"); - //Start our main-loop + // Start our main-loop instance.tm->start(); Log::notice("TelldusService stopping"); diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp index 88a23ee3..1e028dcf 100644 --- a/telldus-core/service/main_win.cpp +++ b/telldus-core/service/main_win.cpp @@ -8,7 +8,7 @@ #include #include "service/TelldusWinService_win.h" -//#include +// #include int main(int argc, char **argv) { g_argc = argc; From 58d58a86407746427538ec9c5ebc9110b246a80e Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Dec 2012 12:29:45 +0100 Subject: [PATCH 2129/2215] Use tabs for indentation according to Google style guidelines "whitespace/usr_tab_for_indentation" --- telldus-core/common/Socket_win.cpp | 8 ++++---- telldus-core/service/main_win.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 48d7a337..6edf2a20 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -68,10 +68,10 @@ void Socket::connect(const std::wstring &server) { DWORD dwMode = PIPE_READMODE_MESSAGE; fSuccess = SetNamedPipeHandleState( - d->hPipe, // pipe handle - &dwMode, // new pipe mode - NULL, // don't set maximum bytes - NULL); // don't set maximum time + d->hPipe, // pipe handle + &dwMode, // new pipe mode + NULL, // don't set maximum bytes + NULL); // don't set maximum time if (!fSuccess) { return; diff --git a/telldus-core/service/main_win.cpp b/telldus-core/service/main_win.cpp index 1e028dcf..eac33a46 100644 --- a/telldus-core/service/main_win.cpp +++ b/telldus-core/service/main_win.cpp @@ -16,10 +16,10 @@ int main(int argc, char **argv) { SERVICE_TABLE_ENTRY serviceTable[] = { {serviceName, TelldusWinService::serviceMain }, - { 0, 0 } - }; + { 0, 0 } + }; - StartServiceCtrlDispatcher( serviceTable ); + StartServiceCtrlDispatcher( serviceTable ); return 0; } From 68a041edb4ac6e89d816a87bb85b5121aa27d785 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Dec 2012 12:30:41 +0100 Subject: [PATCH 2130/2215] An else should appear on the same line as the preceding }, according to Google style guidelines "whitespace/newline" --- telldus-core/common/Socket_win.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 6edf2a20..6ec2f46b 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -133,8 +133,7 @@ std::wstring Socket::read(int timeout) { if(err == ERROR_MORE_DATA) { moreData = true; - } - else { + } else { buf[0] = 0; } if (err == ERROR_BROKEN_PIPE) { From fcb798d4663edf58e53dda41ffae3ead621ad58a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Dec 2012 12:39:44 +0100 Subject: [PATCH 2131/2215] Removed blank lines at start/end of code blocks according to Google style guidelines "whitespace/blank_line" --- telldus-core/common/Socket_win.cpp | 1 - telldus-core/common/common.h | 1 - telldus-core/service/SettingsWinRegistry.cpp | 4 ---- telldus-core/service/TelldusWinService_win.cpp | 1 - telldus-core/service/TelldusWinService_win.h | 2 -- 5 files changed, 9 deletions(-) diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 6ec2f46b..36362e1e 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -150,7 +150,6 @@ std::wstring Socket::read(int timeout) { } void Socket::write(const std::wstring &msg) { - OVERLAPPED oOverlap; DWORD bytesWritten = 0; int result; diff --git a/telldus-core/common/common.h b/telldus-core/common/common.h index 2d0ff2b7..efcd7e9a 100644 --- a/telldus-core/common/common.h +++ b/telldus-core/common/common.h @@ -46,7 +46,6 @@ inline void dlog(const char *fmt, ...) { } inline void debuglogfilename(const int intMessage, const std::string strMessage, const std::string filename) { - #ifdef _WINDOWS static bool firstRun = true; std::ofstream file; diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 8a1958bc..904051c5 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -60,7 +60,6 @@ int Settings::getNumberOfNodes(Node type) const { long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS) { - std::wstring strNumSubKeys; DWORD dNumSubKeys; RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); @@ -82,7 +81,6 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); if(lnExists == ERROR_SUCCESS) { - wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD size = intMaxRegValueLength; if (RegEnumKeyEx(hk, intNodeIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { @@ -223,7 +221,6 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst } int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &name, const std::wstring &value, bool parameter) { - HKEY hk; int ret = TELLSTICK_SUCCESS; @@ -241,7 +238,6 @@ int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &nam RegCloseKey(hk); return ret; - } int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const { diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index e662b43c..e566d66d 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -29,7 +29,6 @@ TelldusWinService::~TelldusWinService() { delete tm; } - void TelldusWinService::stop() { tm->stop(); } diff --git a/telldus-core/service/TelldusWinService_win.h b/telldus-core/service/TelldusWinService_win.h index 13e81ab4..213cc1f0 100644 --- a/telldus-core/service/TelldusWinService_win.h +++ b/telldus-core/service/TelldusWinService_win.h @@ -24,7 +24,6 @@ public: static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] ); protected: - void stop(); DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ); @@ -36,6 +35,5 @@ private: SERVICE_STATUS_HANDLE serviceStatusHandle; static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ); - }; #endif // TELLDUS_CORE_SERVICE_TELLDUSWINSERVICE_WIN_H_ From 3d05f2d510a18816cd30aa9567346ff120b5ca69 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 5 Dec 2012 12:43:28 +0100 Subject: [PATCH 2132/2215] Added missing space after comma, according to Google style guidelines "whitespace/comma" --- telldus-core/service/ProtocolIkea.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 37e90b7d..bbb5d22b 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -11,7 +11,7 @@ #include #include "common/Strings.h" #ifdef _WINDOWS -#define strtok_r(s,d,p) strtok_s(s,d,p) +#define strtok_r(s, d, p) strtok_s(s, d, p) #endif int ProtocolIkea::methods() const { From 5933cf104e6f5721e039da3aa914079d5be27a6d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 13:58:06 +0100 Subject: [PATCH 2133/2215] Use Windows type LONG instead of long to follow the API better --- telldus-core/service/SettingsWinRegistry.cpp | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/telldus-core/service/SettingsWinRegistry.cpp b/telldus-core/service/SettingsWinRegistry.cpp index 904051c5..c27eaaff 100644 --- a/telldus-core/service/SettingsWinRegistry.cpp +++ b/telldus-core/service/SettingsWinRegistry.cpp @@ -57,7 +57,7 @@ int Settings::getNumberOfNodes(Node type) const { int intNumberOfNodes = 0; HKEY hk; - long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); + LONG lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS) { std::wstring strNumSubKeys; @@ -78,7 +78,7 @@ int Settings::getNodeId(Node type, int intNodeIndex) const { int intReturn = -1; HKEY hk; - long lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); + LONG lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk); if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; @@ -126,13 +126,13 @@ int Settings::getNextNodeId(Node type) const { HKEY hk; DWORD dwDisp; - long lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); // create or open if already created + LONG lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); // create or open if already created if(lnExists == ERROR_SUCCESS) { DWORD dwLength = sizeof(DWORD); DWORD nResult(0); - long lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); + LONG lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast(&nResult), &dwLength); if(lngStatus == ERROR_SUCCESS) { intReturn = nResult + 1; @@ -155,7 +155,7 @@ int Settings::removeNode(Node type, int intNodeId) { std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - long lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); + LONG lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str()); if(lngSuccess == ERROR_SUCCESS) { // one of the deletions succeeded @@ -170,12 +170,12 @@ std::wstring Settings::getSetting(const std::wstring &strName) const { HKEY hk; std::wstring strCompleteRegPath = d->strRegPath; - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; - long lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + LONG lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA) { // The buffer is to small, recreate it @@ -198,12 +198,12 @@ std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wst std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); + LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk); if(lnExists == ERROR_SUCCESS) { wchar_t* Buff = new wchar_t[intMaxRegValueLength]; DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength; - long lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); + LONG lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength); if(lngStatus == ERROR_MORE_DATA) { // The buffer is to small, recreate it @@ -227,7 +227,7 @@ int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &nam std::wstring strNodeId = TelldusCore::intToWstring(intNodeId); std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(strNodeId); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS) { int length = static_cast(value.length()) * sizeof(wchar_t); @@ -257,7 +257,7 @@ int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &name, std::wstring strCompleteRegPath = d->getNodePath(type); strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId)); - long lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); + LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk); if (lnExists == ERROR_SUCCESS) { DWORD dwVal = value; lnExists = RegSetValueEx (hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD)); From 630db4f4837aee13aaf9e3f3a772ff6b08b6e6fe Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 13:59:31 +0100 Subject: [PATCH 2134/2215] Cast the long to int. Since the value is never greater than 2 bytes this is safe. --- telldus-core/service/TelldusWinService_win.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index e566d66d..cea51638 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -98,8 +98,8 @@ DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DW } std::wstring strPID = name.substr(posStart, posEnd-posStart); - long int vid = strtol(std::string(strVID.begin(), strVID.end()).c_str(), NULL, 16); - long int pid = strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16); + int vid = static_cast(strtol(std::string(strVID.begin(), strVID.end()).c_str(), NULL, 16)); + int pid = static_cast(strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16)); if (dwEventType == DBT_DEVICEARRIVAL) { tm->deviceInsertedOrRemoved(vid, pid, true); From 641598a35969ae7a42f0ea8cfbbfb127f51761ca Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 14:07:18 +0100 Subject: [PATCH 2135/2215] We need this on one line so the style guidelines check will detect it is a struct --- telldus-core/service/TelldusWinService_win.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-core/service/TelldusWinService_win.cpp b/telldus-core/service/TelldusWinService_win.cpp index cea51638..dd405d9b 100644 --- a/telldus-core/service/TelldusWinService_win.cpp +++ b/telldus-core/service/TelldusWinService_win.cpp @@ -17,8 +17,7 @@ int g_argc; char **g_argv; -static const GUID GUID_DEVINTERFACE_USBRAW = -{ 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; +static const GUID GUID_DEVINTERFACE_USBRAW = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; TelldusWinService::TelldusWinService() :tm(0) { From 6796129cb54325a5d4f064644e5e4177cde92ae9 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 5 Dec 2012 14:28:29 +0100 Subject: [PATCH 2136/2215] Use C++ casting instead of C casting according to Google style guidelines "readability/casting" --- telldus-core/service/Log.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/service/Log.cpp b/telldus-core/service/Log.cpp index 37cd352c..64c11a06 100644 --- a/telldus-core/service/Log.cpp +++ b/telldus-core/service/Log.cpp @@ -159,16 +159,16 @@ void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const switch (logLevel) { case Debug: - ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, reinterpret_cast(&pInsertStrings), NULL); break; case Notice: - ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, reinterpret_cast(&pInsertStrings), NULL); break; case Warning: - ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, reinterpret_cast(&pInsertStrings), NULL); break; case Error: - ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL); + ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, reinterpret_cast(&pInsertStrings), NULL); break; } #endif From 475fdb9d597c22fb356a95df9f6267e25239d996 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 6 Dec 2012 16:12:42 +0100 Subject: [PATCH 2137/2215] Code cleanup, removed debug messages --- telldus-core/client/CallbackMainDispatcher.cpp | 5 ----- telldus-core/client/Client.cpp | 11 ++--------- telldus-core/common/Socket_win.cpp | 15 ++------------- telldus-core/service/Controller.cpp | 2 +- telldus-core/service/EventUpdateManager.cpp | 2 -- telldus-core/service/TelldusMain.cpp | 2 -- 6 files changed, 5 insertions(+), 32 deletions(-) diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 5a7614bf..585c65b0 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -60,7 +60,6 @@ int CallbackMainDispatcher::registerCallback(CallbackStruct::CallbackType type, callback->id = id; callback->context = context; d->callbackList.push_back(callback); - debuglog(id, "Callback added"); return id; } @@ -72,7 +71,6 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { if ( (*callback_it)->id != callbackId ) { continue; } - debuglog(callbackId, "Callback unregistered"); newEventList.splice(newEventList.begin(), d->callbackList, callback_it); break; } @@ -102,12 +100,9 @@ void CallbackMainDispatcher::run() { if (!cbd) { continue; } - // debuglog(333, "Callbackevent, signalled"); TelldusCore::MutexLocker locker(&d->mutex); - // debuglog(333, "Callbackevent, locked"); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { if ( (*callback_it)->type == cbd->type ) { - // debuglog((*callback_it)->id, "Callbackevent, sending"); std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); d->eventThreadList.push_back(ptr); } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 1ea23ef8..cf4e5e33 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -78,7 +78,6 @@ std::wstring Client::getWStringFromService(const Message &msg) { } int Client::registerEvent( CallbackStruct::CallbackType type, void *eventFunction, void *context ) { - debuglog(555, "Client, Registering callback"); return d->callbackMainDispatcher.registerCallback(type, eventFunction, context ); } @@ -88,7 +87,6 @@ void Client::run() { while(d->running) { if(!d->eventSocket.isConnected()) { - debuglog(555, "Client, Trying to (re)connect to TelldusEvents"); d->eventSocket.connect(L"TelldusEvents"); // try to reconnect to service if(!d->eventSocket.isConnected()) { // reconnect didn't succeed, wait a while and try again @@ -155,27 +153,23 @@ std::wstring Client::sendToService(const Message &msg) { if(tries == 20) { TelldusCore::Message msg; msg.addArgument(TELLSTICK_ERROR_CONNECTING_SERVICE); - debuglog(555, "Connection failed, 20 retries, giving up."); return msg; } Socket s; s.connect(L"TelldusClient"); if (!s.isConnected()) { // sConnection failed - debuglog(555, "Connection failed"); msleep(500); continue; // retry } s.write(msg.data()); if (!s.isConnected()) { // Connection failed sometime during operation... (better check here, instead of 5 seconds timeout later) msleep(500); - debuglog(555, "Error in write, should retry"); continue; // retry } - readData = s.read(1000); // TODO(stefan): changed to 10000 from 5000, how much does this do...? + readData = s.read(1000); if(readData == L"") { msleep(500); - continue; // TODO(stefan): can we be really sure it SHOULD be anything? - // TODO(stefan): perhaps break here instead? + continue; } if (!s.isConnected()) { // Connection failed sometime during operation... @@ -194,7 +188,6 @@ void Client::stopThread() { } int Client::unregisterCallback( int callbackId ) { - debuglog(555, "Client, correctly unregistering callback"); return d->callbackMainDispatcher.unregisterCallback(callbackId); } diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 36362e1e..23d87acc 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -126,20 +126,15 @@ std::wstring Socket::read(int timeout) { if (!fSuccess) { DWORD err = GetLastError(); - debuglog(static_cast(err), "Something read error"); - if(err != ERROR_OPERATION_ABORTED) { // gets this "error" always when nothing was reads - debuglog(static_cast(err), "Socket read error"); - } - + if(err == ERROR_MORE_DATA) { moreData = true; } else { buf[0] = 0; } if (err == ERROR_BROKEN_PIPE) { - debuglog(static_cast(err), "Got an error, close this socket"); d->connected = false; - break; // TODO(stefan): is this correct? + break; } } returnString.append(buf); @@ -174,18 +169,12 @@ void Socket::write(const std::wstring &msg) { return; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &bytesWritten, TRUE); - if (!fSuccess) { - debuglog(result, "Error in GetOverlappedResult"); - result = GetLastError(); - debuglog(result, "Error in GetOverlappedResult, this message"); - } } CloseHandle(writeEvent); if (!fSuccess) { CloseHandle(d->hPipe); d->hPipe = 0; - debuglog(result, "Error in write event, closing socket"); d->connected = false; return; } diff --git a/telldus-core/service/Controller.cpp b/telldus-core/service/Controller.cpp index 14d58d73..1a0e43f7 100644 --- a/telldus-core/service/Controller.cpp +++ b/telldus-core/service/Controller.cpp @@ -7,13 +7,13 @@ #define _CRT_RAND_S #include "service/Controller.h" #include +#include #include #include #include #include "service/Protocol.h" #include "service/EventUpdateManager.h" #include "common/Strings.h" -#include "common/common.h" // debug inline int random( unsigned int* seed ) { #ifdef _WINDOWS diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index a3760b46..d237c5ba 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -24,7 +24,6 @@ #include #endif // _LINUX -#include "common/common.h" // debug #include "common/EventHandler.h" #include "common/Message.h" #include "common/Socket.h" @@ -165,7 +164,6 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) { it++; } else { // connection is dead, remove it - debuglogservice(0, "Lost connection, removing it"); delete *it; it = d->clients.erase(it); } diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 473e4c9c..194d0b0d 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -9,7 +9,6 @@ #include #include -#include "common/common.h" // debug #include "common/EventHandler.h" #include "service/ClientCommunicationHandler.h" #include "service/ConnectionListener.h" @@ -63,7 +62,6 @@ void TelldusMain::suspend() { } void TelldusMain::start(void) { - debuglogservice(0, "Starting service"); TelldusCore::EventRef clientEvent = d->eventHandler.addEvent(); TelldusCore::EventRef dataEvent = d->eventHandler.addEvent(); TelldusCore::EventRef executeActionEvent = d->eventHandler.addEvent(); From 9a28b1444be61e7f37c388118a93b71279d476ac Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Feb 2013 11:10:07 +0100 Subject: [PATCH 2138/2215] Sort the devices in TelldusCenter by its name. If anyone thinks to breaks their preferred order, please read http://xkcd.com/1172/ This closes #112. --- telldus-gui/TelldusGui/deviceview.cpp | 14 ++++++++++---- telldus-gui/TelldusGui/devicewidget.cpp | 10 +++++++--- telldus-gui/TelldusGui/devicewidget.h | 2 ++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/telldus-gui/TelldusGui/deviceview.cpp b/telldus-gui/TelldusGui/deviceview.cpp index 6d98db53..e6efe4c1 100644 --- a/telldus-gui/TelldusGui/deviceview.cpp +++ b/telldus-gui/TelldusGui/deviceview.cpp @@ -3,6 +3,7 @@ #include "devicemodel.h" #include #include +#include #include class MethodDelegate : public QStyledItemDelegate { @@ -21,7 +22,7 @@ DeviceView::DeviceView(QWidget *parent) setSelectionMode( QAbstractItemView::SingleSelection ); horizontalHeader()->setStretchLastSection( true ); verticalHeader()->hide(); - setItemDelegate(new MethodDelegate(this)); + setItemDelegate(new MethodDelegate(this)); } void DeviceView::setModel ( QAbstractItemModel * model ) { @@ -32,7 +33,7 @@ void DeviceView::setModel ( QAbstractItemModel * model ) { } void DeviceView::rowsUpdated ( const QModelIndex & /*parent*/, int start, int end ) { - DeviceModel *model = qobject_cast( this->model() ); + QSortFilterProxyModel *model = qobject_cast( this->model() ); if (!model) { return; } @@ -56,10 +57,15 @@ QWidget *MethodDelegate::createEditor(QWidget *parent, const QStyleOptionViewIte if (!p) { return 0; } - DeviceModel *model = qobject_cast( p->model() ); + QSortFilterProxyModel *sModel = qobject_cast( p->model() ); + if (!sModel) { + return 0; + } + + DeviceModel *model = qobject_cast( sModel->sourceModel() ); if (!model) { return 0; } - MethodWidget *widget = new MethodWidget(model->device(index), parent); + MethodWidget *widget = new MethodWidget(model->device(sModel->mapToSource(index)), parent); return widget; } diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index b4bab2e4..794f7895 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -23,7 +23,11 @@ DeviceWidget::DeviceWidget(QWidget *parent) : removeToolButton(this), editToolButton(this) { - deviceView.setModel( &model ); + sortedModel.setSourceModel(&model); + sortedModel.setDynamicSortFilter(true); + sortedModel.setSortCaseSensitivity(Qt::CaseInsensitive); + sortedModel.sort(1, Qt::AscendingOrder); + deviceView.setModel( &sortedModel ); deviceView.resizeColumnsToContents(); deviceView.resizeRowsToContents(); connect( &deviceView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(listActivated(const QModelIndex &)) ); @@ -134,7 +138,7 @@ void DeviceWidget::deleteDevice() { msgBox.setStandardButtons( QMessageBox::Yes | QMessageBox::No ); msgBox.setDefaultButton( QMessageBox::No ); if ( msgBox.exec() == QMessageBox::Yes) { - QModelIndex index = deviceView.currentIndex(); + QModelIndex index = sortedModel.mapToSource(deviceView.currentIndex()); Device *device = model.device(index); if (device) { device->remove(); @@ -143,7 +147,7 @@ void DeviceWidget::deleteDevice() { } void DeviceWidget::editDevice() { - QModelIndex index = deviceView.currentIndex(); + QModelIndex index = sortedModel.mapToSource(deviceView.currentIndex()); Device device( model.deviceId(index), 0 ); QDialog *dialog; diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index 06a53dfb..63cc9ef9 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "devicemodel.h" #include "deviceview.h" @@ -32,6 +33,7 @@ private slots: private: DeviceModel model; + QSortFilterProxyModel sortedModel; DeviceView deviceView; QToolButton addToolButton, removeToolButton, editToolButton; }; From 05f5db163c20644d41c0e52d46b3f45bf668bd33 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Feb 2013 16:59:13 +0100 Subject: [PATCH 2139/2215] Add IKEA non dimmer. This closes #251 --- telldus-core/service/ProtocolIkea.cpp | 3 +++ telldus-gui/TelldusGui/data/telldus/devices.xml | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index bbb5d22b..6b96434a 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -15,6 +15,9 @@ #endif int ProtocolIkea::methods() const { + if (TelldusCore::comparei(model(), L"selflearning-switch")) { + return TELLSTICK_TURNON | TELLSTICK_TURNOFF; + } return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM; } diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index 392c0397..bd8c6b4c 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -55,7 +55,8 @@ Code Switch - Koppla + Koppla on/off + Koppla dimmer From d5d22aceb50c80308ab8698df490f1358944ac67 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Feb 2013 17:07:54 +0100 Subject: [PATCH 2140/2215] Do not log SIGPIPE. This is a normal signal when a client disconnects. Closes #280 --- telldus-core/service/main_unix.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/service/main_unix.cpp b/telldus-core/service/main_unix.cpp index 07c119d3..67d64f7d 100644 --- a/telldus-core/service/main_unix.cpp +++ b/telldus-core/service/main_unix.cpp @@ -37,7 +37,6 @@ void signalHandler(int sig) { tm.stop(); break; case SIGPIPE: - Log::debug("Received SIGPIPE signal."); break; default: Log::warning("Unhandled signal (%d) %s", sig, strsignal(sig)); From b6b78ad15778ce49ce2182cafc85e357a05092f3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 13 Feb 2013 17:54:43 +0100 Subject: [PATCH 2141/2215] Convert spaces to tabs. --- telldus-core/service/ConnectionListener_unix.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/ConnectionListener_unix.cpp b/telldus-core/service/ConnectionListener_unix.cpp index 5a53d14f..d3b238f9 100644 --- a/telldus-core/service/ConnectionListener_unix.cpp +++ b/telldus-core/service/ConnectionListener_unix.cpp @@ -18,7 +18,7 @@ #include "common/Socket.h" #if defined(_MACOSX) && !defined(SOCK_CLOEXEC) - #define SOCK_CLOEXEC 0 +#define SOCK_CLOEXEC 0 #endif class ConnectionListener::PrivateData { @@ -58,7 +58,7 @@ void ConnectionListener::run() { } #if defined(_MACOSX) int op = fcntl(serverSocket, F_GETFD); - fcntl(serverSocket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet + fcntl(serverSocket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet #endif name.sun_family = AF_LOCAL; memset(name.sun_path, '\0', sizeof(name.sun_path)); From 30920ea8166799916e869d6249a15854e0312d4f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Feb 2013 15:57:30 +0100 Subject: [PATCH 2142/2215] Allow .qml files to be translated. See #163 --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 4516856b..05afea26 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -52,6 +52,10 @@ IF(Plugin_PATH) LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/__init__.js") #Add all extra files FOREACH(_FILE ${Plugin_EXTRA}) + GET_FILENAME_COMPONENT(ext "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}" EXT) + IF (ext STREQUAL ".qml") + LIST(APPEND translation_sources "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}") + ENDIF () LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}") ENDFOREACH(_FILE) ENDIF(Plugin_PATH) From 3b193bfaadcf91e39d5191dbca5361967374e1ae Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Feb 2013 15:58:42 +0100 Subject: [PATCH 2143/2215] Make the sensors module translatable, see #163 --- telldus-gui/Plugins/Sensors/HeaderTitle.qml | 2 +- telldus-gui/Plugins/Sensors/SensorList.qml | 15 +++++++-------- telldus-gui/Plugins/Sensors/SensorView.qml | 10 +++++----- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/telldus-gui/Plugins/Sensors/HeaderTitle.qml b/telldus-gui/Plugins/Sensors/HeaderTitle.qml index 0d7ae213..41c568d3 100644 --- a/telldus-gui/Plugins/Sensors/HeaderTitle.qml +++ b/telldus-gui/Plugins/Sensors/HeaderTitle.qml @@ -2,7 +2,7 @@ import Qt 4.7 Text { id: headerTitle - text: "Name" + text: qsTr("Name") color: "white" font.weight: Font.Bold height: parent.height diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml index ea1ed7c4..b60f0fa5 100644 --- a/telldus-gui/Plugins/Sensors/SensorList.qml +++ b/telldus-gui/Plugins/Sensors/SensorList.qml @@ -14,7 +14,7 @@ Column { border.right: 5; border.bottom: 5 HeaderTitle { - text: "Name" + text: qsTr("Name") anchors.left: parent.left anchors.leftMargin: 15 } @@ -26,21 +26,21 @@ Column { } HeaderTitle { id: sensorid - text: "ID" + text: qsTr("ID") anchors.right: modelTitle.left visible: main.state == "EDIT" width: 50 } HeaderTitle { id: modelTitle - text: "Model" + text: qsTr("Model") anchors.right: visibleinlistTitle.left visible: main.state == "EDIT" width: 100 } HeaderTitle { id: visibleinlistTitle - text: "Visible in list" + text: qsTr("Visible in list") anchors.right: sensorinformationTitle.left horizontalAlignment: Text.AlignHCenter visible: main.state == "EDIT" @@ -48,13 +48,13 @@ Column { } HeaderTitle { id: sensorinformationTitle - text: "Sensor information" + text: qsTr("Sensor information") width: 150 anchors.right: timestampTitle.left } HeaderTitle { id: timestampTitle - text: "Last updated" + text: qsTr("Last updated") width: 100 anchors.right: parent.right //horizontalAlignment: Text.AlignRight @@ -67,9 +67,8 @@ Column { Row{ spacing: 20 Button { - width: 50 height: 20 - text: main.state == "VIEW" ? "Edit" : "View" + text: main.state == "VIEW" ? qsTr("Edit") : qsTr("View") onClicked: { if(main.state == "VIEW"){ main.state = "EDIT" diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml index a3626bcb..f577b9d0 100644 --- a/telldus-gui/Plugins/Sensors/SensorView.qml +++ b/telldus-gui/Plugins/Sensors/SensorView.qml @@ -26,7 +26,7 @@ Item{ anchors.leftMargin: 15 height: 40 verticalAlignment: Text.AlignVCenter - text: modelData.name == '' ? '' : modelData.name; + text: modelData.name == '' ? qsTr('') : modelData.name; color: "#004275" } TextField { @@ -37,7 +37,7 @@ Item{ anchors.top: parent.top anchors.topMargin: (40-nameEdit.height)/2 text: modelData.name; - placeholderText: 'Enter a name' + placeholderText: qsTr('Enter a name') onTextChanged: modelData.name = text } Item { @@ -116,10 +116,10 @@ Item{ Dialog{ id: confirmDeletion modal: true - title: "Confirm deletion" + title: qsTr("Confirm deletion") Text{ id: descriptionHeadline - text:"Delete this sensor?" + text: qsTr("Delete this sensor?") font.bold: true } Text{ @@ -129,7 +129,7 @@ Item{ width: parent.width - 20 anchors.left: parent.left anchors.leftMargin: 10 - text: "Please note that a sensor that is still transmitting will reappear here again, but it will be hidden in the list by default." + text: qsTr("Please note that a sensor that is still transmitting will reappear here again, but it will be hidden in the list by default.") wrapMode: Text.Wrap } From 6a944bffcfa4623326fa68ba4e2fcce2d3cde960 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Feb 2013 15:59:43 +0100 Subject: [PATCH 2144/2215] Use QtQuick 1.0 instead of Qt 4.7 for sensors module --- telldus-gui/Plugins/Sensors/HeaderTitle.qml | 2 +- telldus-gui/Plugins/Sensors/SensorList.qml | 2 +- telldus-gui/Plugins/Sensors/SensorValue.qml | 2 +- telldus-gui/Plugins/Sensors/main.qml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/Sensors/HeaderTitle.qml b/telldus-gui/Plugins/Sensors/HeaderTitle.qml index 41c568d3..20b59ef1 100644 --- a/telldus-gui/Plugins/Sensors/HeaderTitle.qml +++ b/telldus-gui/Plugins/Sensors/HeaderTitle.qml @@ -1,4 +1,4 @@ -import Qt 4.7 +import QtQuick 1.0 Text { id: headerTitle diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml index b60f0fa5..7ef0b95a 100644 --- a/telldus-gui/Plugins/Sensors/SensorList.qml +++ b/telldus-gui/Plugins/Sensors/SensorList.qml @@ -1,4 +1,4 @@ -import Qt 4.7 +import QtQuick 1.0 import QtDesktop 0.1 Column { diff --git a/telldus-gui/Plugins/Sensors/SensorValue.qml b/telldus-gui/Plugins/Sensors/SensorValue.qml index 083830a1..1e3a22d2 100644 --- a/telldus-gui/Plugins/Sensors/SensorValue.qml +++ b/telldus-gui/Plugins/Sensors/SensorValue.qml @@ -1,4 +1,4 @@ -import Qt 4.7 +import QtQuick 1.0 Item { property alias text: text.text diff --git a/telldus-gui/Plugins/Sensors/main.qml b/telldus-gui/Plugins/Sensors/main.qml index 75b4847f..78689985 100644 --- a/telldus-gui/Plugins/Sensors/main.qml +++ b/telldus-gui/Plugins/Sensors/main.qml @@ -1,4 +1,4 @@ -import Qt 4.7 +import QtQuick 1.0 import QtDesktop 0.1 Item { From 7372963c6d76646cec4eccb0f9b518b17ceaf32d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 14 Feb 2013 16:02:31 +0100 Subject: [PATCH 2145/2215] Add swedish translation for plugin Sensors, closes #163 --- telldus-gui/Plugins/Sensors/translation_sv.ts | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 telldus-gui/Plugins/Sensors/translation_sv.ts diff --git a/telldus-gui/Plugins/Sensors/translation_sv.ts b/telldus-gui/Plugins/Sensors/translation_sv.ts new file mode 100644 index 00000000..f2a21a81 --- /dev/null +++ b/telldus-gui/Plugins/Sensors/translation_sv.ts @@ -0,0 +1,69 @@ + + + + + HeaderTitle + + Name + Namn + + + + SensorList + + Name + Namn + + + ID + ID + + + Model + Modell + + + Visible in list + Visas i lista + + + Sensor information + Sensorinformation + + + Last updated + Uppdaterad + + + Edit + Redigera + + + View + Visa + + + + SensorView + + <unnamed> + <inget namn> + + + Enter a name + Skriv in ett namn + + + Confirm deletion + Bekräfta borttagning + + + Delete this sensor? + Ta bort sensorn? + + + Please note that a sensor that is still transmitting will reappear here again, but it will be hidden in the list by default. + Notera att en sensor som fortfarande sänder kommer tillbaka automatiskt, dock dold som standard. + + + From f49e83f0e7720e624d9861496363b3d923f6f0aa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Feb 2013 15:28:43 +0100 Subject: [PATCH 2146/2215] Do not query for controllers on OS X. This seems to make the trackpad freeze sometimes. We listen for usb-events anyway. Closes #245 --- telldus-core/service/TelldusMain.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 194d0b0d..67a85941 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -140,7 +140,9 @@ void TelldusMain::start(void) { while(janitor->isSignaled()) { janitor->popSignal(); } +#ifdef _MACOSX controllerManager.queryControllerStatus(); +#endif } } From 2effb362a0a856a185c22511aa8ecf5aaedd6b4b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 20 Feb 2013 15:46:11 +0100 Subject: [PATCH 2147/2215] We should of course skip it on OS X and run it on all other platforms. See #245 --- telldus-core/service/TelldusMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index 67a85941..5d9aa642 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -140,7 +140,7 @@ void TelldusMain::start(void) { while(janitor->isSignaled()) { janitor->popSignal(); } -#ifdef _MACOSX +#ifndef _MACOSX controllerManager.queryControllerStatus(); #endif } From 59e3ab8c16a549ac374481e23d54e37a5e8a4017 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Mar 2013 14:59:31 +0100 Subject: [PATCH 2148/2215] Handle Oregon EA4C temperatures over 100 degrees. This closes #261 --- telldus-core/service/ProtocolOregon.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 54b288f4..6882019a 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -34,6 +34,7 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { uint8_t checksumw = (value >> 4) & 0xF; bool neg = value & (1 << 3); + int hundred = value & 3; checksum += (value & 0xF); value >>= 8; @@ -58,7 +59,7 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { return ""; } - double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; + double temperature = ((hundred * 1000) + (temp1 * 100) + (temp2 * 10) + temp3)/10.0; if (neg) { temperature = -temperature; } From ccd7fcb2f30fbcac882518a9203014cd271a4ab2 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 7 Mar 2013 15:01:15 +0100 Subject: [PATCH 2149/2215] Add unit test for Oregon EA4C data. See #261 --- .../tests/service/ProtocolOregonTest.cpp | 69 +++++++++++++++++++ .../tests/service/ProtocolOregonTest.h | 25 +++++++ 2 files changed, 94 insertions(+) create mode 100644 telldus-core/tests/service/ProtocolOregonTest.cpp create mode 100644 telldus-core/tests/service/ProtocolOregonTest.h diff --git a/telldus-core/tests/service/ProtocolOregonTest.cpp b/telldus-core/tests/service/ProtocolOregonTest.cpp new file mode 100644 index 00000000..a18d3d52 --- /dev/null +++ b/telldus-core/tests/service/ProtocolOregonTest.cpp @@ -0,0 +1,69 @@ +#include "ProtocolOregonTest.h" +#include "service/ProtocolOregon.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolOregonTest); + +class ProtocolOregonTest::PrivateData { +public: +}; + +void ProtocolOregonTest :: setUp (void) { + d = new PrivateData; +} + +void ProtocolOregonTest :: tearDown (void) { + delete d; +} + +void ProtocolOregonTest :: decodeDataTest (void) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 77.3", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:77.3;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:2177307700E4;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 74.7", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:74.7;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:2177707410A4;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 77.7", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:77.7;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:217770774054;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 66.5", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:66.5;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:2177506600E4;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 122.5", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:122.5;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:2177502291A3;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 120.1", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:120.1;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:2177102031B3;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 120.6", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:120.6;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:217760208193;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 23, temp: 202.7", + std::string("class:sensor;protocol:oregon;model:EA4C;id:23;temp:202.7;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:2177702A2D3;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: 202.7", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:202.7;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:21777002A2D3;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Oregon, id: 119, temp: -23.1", + std::string("class:sensor;protocol:oregon;model:EA4C;id:119;temp:-23.1;"), + ProtocolOregon::decodeData(ControllerMessage("class:sensor;protocol:oregon;model:0xEA4C;data:21771023D8B3;")) + ); +} diff --git a/telldus-core/tests/service/ProtocolOregonTest.h b/telldus-core/tests/service/ProtocolOregonTest.h new file mode 100644 index 00000000..a2965990 --- /dev/null +++ b/telldus-core/tests/service/ProtocolOregonTest.h @@ -0,0 +1,25 @@ +#ifndef PROTOCOLOREGONTEST_H +#define PROTOCOLOREGONTEST_H + +#include +#include + +class ProtocolOregonTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (ProtocolOregonTest); + CPPUNIT_TEST (decodeDataTest); + CPPUNIT_TEST_SUITE_END (); + +public: + void setUp (void); + void tearDown (void); + +protected: + void decodeDataTest(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif // PROTOCOLOREGONTEST_H From c3bf46124d18d5afcd2f3295b4dfa0b99557e317 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 15 Apr 2013 11:16:50 +0200 Subject: [PATCH 2150/2215] Fixed crash in EventUpdateManager on receive on some platforms. --- telldus-core/common/Strings.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index d2a0fe2f..2500bb52 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -239,7 +239,10 @@ std::string TelldusCore::sformatf(const char *format, va_list ap) { while (1) { /* Try to print in the allocated space. */ - n = vsnprintf(p, size, format, ap); + va_list ap2; + va_copy(ap2, ap); + n = vsnprintf(p, size, format, ap2); + va_end(ap2); /* If that worked, return the string. */ if (n > -1 && n < size) { From a912ee28726c0ffd357bbcf4ec2b4cc002549750 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 17 Apr 2013 12:39:46 +0200 Subject: [PATCH 2151/2215] Added compability for EventUpdateManager-fix on Windows too --- telldus-core/common/Strings.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 2500bb52..296e3f20 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -25,6 +25,14 @@ #define WCHAR_T_ENCODING "WCHAR_T" #endif +#ifndef va_copy +#ifdef __va_copy +#define va_copy(a,b) __va_copy(a,b) +#else /* !__va_copy */ +#define va_copy(a,b) ((a)=(b)) +#endif /* __va_copy */ +#endif /* va_copy */ + std::wstring TelldusCore::charToWstring(const char *value) { #ifdef _WINDOWS // Determine size From b0d3d2af30e37f0832487bb4e4f6a84acc0a9f34 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 8 May 2013 13:44:25 +0200 Subject: [PATCH 2152/2215] Added hasta version 2 --- telldus-core/service/Protocol.cpp | 5 + telldus-core/service/ProtocolHasta.cpp | 142 +++++++++++++++++- telldus-core/service/ProtocolHasta.h | 5 + .../TelldusGui/data/telldus/devices.xml | 1 + 4 files changed, 151 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/Protocol.cpp b/telldus-core/service/Protocol.cpp index defc7775..2a8f00e6 100644 --- a/telldus-core/service/Protocol.cpp +++ b/telldus-core/service/Protocol.cpp @@ -256,6 +256,11 @@ std::list Protocol::decodeData(const std::string &fullData) { if (decoded != "") { retval.push_back(decoded); } + } else if(TelldusCore::comparei(dataMsg.protocol(), L"hasta") ) { + decoded = ProtocolHasta::decodeData(dataMsg); + if (decoded != "") { + retval.push_back(decoded); + } } return retval; diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index 0c5899de..0cb46376 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -8,12 +8,20 @@ #include #include #include +#include "common/Strings.h" int ProtocolHasta::methods() const { return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN; } std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Controller *) { + if (TelldusCore::comparei(model(), L"selflearningv2")) { + return getStringForMethodv2(method); + } + return getStringForMethodv1(method); +} + +std::string ProtocolHasta::getStringForMethodv1(int method) { int house = this->getIntParameter(L"house", 1, 65536); int unit = this->getIntParameter(L"unit", 1, 15); std::string strReturn; @@ -21,10 +29,10 @@ std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Control std::string preamble; strReturn.append(1, 190); strReturn.append(1, 1); - strReturn.append(1, 190); + strReturn.append(1, 107); strReturn.append(1, 1); strReturn.append(1, 190); - strReturn.append(1, 190); + strReturn.append(1, 165); strReturn.append(convertByte( (house & 0xFF) )); strReturn.append(convertByte( (house>>8) & 0xFF )); @@ -71,3 +79,133 @@ std::string ProtocolHasta::convertByte(unsigned char byte) { } return retval; } + +std::string ProtocolHasta::getStringForMethodv2(int method) { + int house = this->getIntParameter(L"house", 1, 65536); + int unit = this->getIntParameter(L"unit", 1, 15); + int sum = 0; + std::string strReturn; + + std::string preamble; + strReturn.append(1, 190); + strReturn.append(1, 1); + strReturn.append(1, 107); + strReturn.append(1, 1); + strReturn.append(1, 190); + strReturn.append(1, 190); + strReturn.append(1, 1); + strReturn.append(1, 60); + strReturn.append(1, 160); + strReturn.append(1, 40); + + strReturn.append(convertBytev2( (house>>8) & 0xFF )); + sum = ((house>>8)&0xFF); + strReturn.append(convertBytev2( (house & 0xFF) )); + sum += (house & 0xFF); + + int byte = unit&0x0F; + + if (method == TELLSTICK_UP) { + byte |= 0xC0; + + } else if (method == TELLSTICK_DOWN) { + byte |= 0x10; + + } else if (method == TELLSTICK_STOP) { + byte |= 0x50; + + } else if (method == TELLSTICK_LEARN) { + byte |= 0x40; + + } else { + return ""; + } + strReturn.append(convertBytev2(byte)); + sum += byte; + + strReturn.append(convertBytev2(0x01)); + sum += 0x01; + + int checksum = (((int)(sum/256)+1)*256+1) - sum; + strReturn.append(convertBytev2(checksum)); + strReturn.append(1, 68); + strReturn.append(1, 36); + + return strReturn; +} + +std::string ProtocolHasta::convertBytev2(unsigned char byte) { + std::string retval; + for(int i = 0; i < 8; ++i) { + if (byte & 1) { + retval.append(1, 68); + retval.append(1, 36); + } else { + retval.append(1, 36); + retval.append(1, 68); + } + byte >>= 1; + } + return retval; +} + +std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) { + uint64_t allData = dataMsg.getInt64Parameter("data"); + + unsigned int house = 0; + unsigned int unit = 0; + unsigned int method = 0; + std::string model; + std::string methodstring; + + allData >>= 8; + unit = allData & 0xF; + allData >>= 4; + method = allData & 0xF; + allData >>= 4; + if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { + //version1 + house = allData & 0xFFFF; + house = ((house << 8) | (house >> 8)) & 0xFFFF; + model = "selflearning"; + if(method == 0){ + methodstring = "up"; + } + else if(method == 1){ + methodstring = "down"; + } + else if(method == 5){ + methodstring = "stop"; + } + else{ + return ""; + } + } + else{ + //version2 + house = allData & 0xFFFF; + + model = "selflearningv2"; + if(method == 12){ + methodstring = "up"; + } + else if(method == 1 or method == 8){ //is method 8 correct? + methodstring = "down"; + } + else if(method == 5){ + methodstring = "stop"; + } + else{ + return ""; + } + } + + if(house < 1 || house > 65535 || unit < 1 || unit > 16) { + // not hasta + return ""; + } + + std::stringstream retString; + retString << "class:command;protocol:hasta;model:" << model << ";house:" << house << ";unit:" << unit << ";method:" << methodstring << ";"; + return retString.str(); +} diff --git a/telldus-core/service/ProtocolHasta.h b/telldus-core/service/ProtocolHasta.h index 0ab8a488..7a122bb2 100644 --- a/telldus-core/service/ProtocolHasta.h +++ b/telldus-core/service/ProtocolHasta.h @@ -8,15 +8,20 @@ #define TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ #include +#include "service/ControllerMessage.h" #include "service/Protocol.h" class ProtocolHasta : public Protocol { public: int methods() const; virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller); + static std::string decodeData(const ControllerMessage &dataMsg); protected: static std::string convertByte(unsigned char byte); + static std::string convertBytev2(unsigned char byte); + std::string getStringForMethodv1(int method); + std::string getStringForMethodv2(int method); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_ diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index bd8c6b4c..1ed81603 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -124,6 +124,7 @@ Blinds + Blinds (version 2) Projector screen From dc61911e7e16590d77ceb9a19407b8bff4aefdc9 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 8 May 2013 14:10:12 +0200 Subject: [PATCH 2153/2215] Fixed syntax error (a typical C++-is-not-python-error) --- telldus-core/service/ProtocolHasta.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index 0cb46376..c0eded94 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -189,7 +189,7 @@ std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) { if(method == 12){ methodstring = "up"; } - else if(method == 1 or method == 8){ //is method 8 correct? + else if(method == 1 || method == 8){ //is method 8 correct? methodstring = "down"; } else if(method == 5){ From 10ced92ec6a4cf33d90e2077cb9ebf1de20a8988 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 May 2013 15:32:43 +0200 Subject: [PATCH 2154/2215] Made sure Hasta send works for TellStick too --- telldus-core/service/ProtocolHasta.cpp | 37 ++++++++++++-------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index c0eded94..eb4d5017 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -26,13 +26,12 @@ std::string ProtocolHasta::getStringForMethodv1(int method) { int unit = this->getIntParameter(L"unit", 1, 15); std::string strReturn; - std::string preamble; - strReturn.append(1, 190); + strReturn.append(1, 164); strReturn.append(1, 1); - strReturn.append(1, 107); + strReturn.append(1, 164); strReturn.append(1, 1); - strReturn.append(1, 190); - strReturn.append(1, 165); + strReturn.append(1, 164); + strReturn.append(1, 164); strReturn.append(convertByte( (house & 0xFF) )); strReturn.append(convertByte( (house>>8) & 0xFF )); @@ -85,18 +84,16 @@ std::string ProtocolHasta::getStringForMethodv2(int method) { int unit = this->getIntParameter(L"unit", 1, 15); int sum = 0; std::string strReturn; - - std::string preamble; - strReturn.append(1, 190); + strReturn.append(1, 245); strReturn.append(1, 1); - strReturn.append(1, 107); + strReturn.append(1, 245); + strReturn.append(1, 245); + strReturn.append(1, 63); strReturn.append(1, 1); - strReturn.append(1, 190); - strReturn.append(1, 190); + strReturn.append(1, 63); strReturn.append(1, 1); - strReturn.append(1, 60); - strReturn.append(1, 160); - strReturn.append(1, 40); + strReturn.append(1, 35); + strReturn.append(1, 35); strReturn.append(convertBytev2( (house>>8) & 0xFF )); sum = ((house>>8)&0xFF); @@ -128,8 +125,8 @@ std::string ProtocolHasta::getStringForMethodv2(int method) { int checksum = (((int)(sum/256)+1)*256+1) - sum; strReturn.append(convertBytev2(checksum)); - strReturn.append(1, 68); - strReturn.append(1, 36); + strReturn.append(1, 63); + strReturn.append(1, 35); return strReturn; } @@ -138,11 +135,11 @@ std::string ProtocolHasta::convertBytev2(unsigned char byte) { std::string retval; for(int i = 0; i < 8; ++i) { if (byte & 1) { - retval.append(1, 68); - retval.append(1, 36); + retval.append(1, 63); + retval.append(1, 35); } else { - retval.append(1, 36); - retval.append(1, 68); + retval.append(1, 35); + retval.append(1, 63); } byte >>= 1; } From d37ff4ff0b6531e6b05934fa1e1570912b58c0f2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 May 2013 16:14:36 +0200 Subject: [PATCH 2155/2215] Added missing space after comma, according to Google style guidelines "whitespace/comma" --- telldus-core/common/Strings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/common/Strings.cpp b/telldus-core/common/Strings.cpp index 296e3f20..dc15f81f 100644 --- a/telldus-core/common/Strings.cpp +++ b/telldus-core/common/Strings.cpp @@ -27,9 +27,9 @@ #ifndef va_copy #ifdef __va_copy -#define va_copy(a,b) __va_copy(a,b) +#define va_copy(a, b) __va_copy(a, b) #else /* !__va_copy */ -#define va_copy(a,b) ((a)=(b)) +#define va_copy(a, b) ((a)=(b)) #endif /* __va_copy */ #endif /* va_copy */ From ae841861b206260476a375db36cc977f4d5a8ea0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 May 2013 16:16:53 +0200 Subject: [PATCH 2156/2215] Added missing space in comment, according to Google style guidelines "whitespace/comments" --- telldus-core/service/ProtocolHasta.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index eb4d5017..4c2e7ba2 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -161,7 +161,7 @@ std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) { method = allData & 0xF; allData >>= 4; if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) { - //version1 + // version1 house = allData & 0xFFFF; house = ((house << 8) | (house >> 8)) & 0xFFFF; model = "selflearning"; @@ -179,14 +179,14 @@ std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) { } } else{ - //version2 + // version2 house = allData & 0xFFFF; model = "selflearningv2"; if(method == 12){ methodstring = "up"; } - else if(method == 1 || method == 8){ //is method 8 correct? + else if(method == 1 || method == 8){ // is method 8 correct? methodstring = "down"; } else if(method == 5){ From 14399b2d7f4fc040ffadc83fd6c25bfb6a39d196 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 May 2013 16:21:37 +0200 Subject: [PATCH 2157/2215] Added missing space after braces, according to Google style guidelines "whitespace/braces" --- telldus-core/service/ProtocolHasta.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index 4c2e7ba2..e41fcb80 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -165,31 +165,31 @@ std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) { house = allData & 0xFFFF; house = ((house << 8) | (house >> 8)) & 0xFFFF; model = "selflearning"; - if(method == 0){ + if(method == 0) { methodstring = "up"; } - else if(method == 1){ + else if(method == 1) { methodstring = "down"; } - else if(method == 5){ + else if(method == 5) { methodstring = "stop"; } - else{ + else { return ""; } } - else{ + else { // version2 house = allData & 0xFFFF; model = "selflearningv2"; - if(method == 12){ + if(method == 12) { methodstring = "up"; } - else if(method == 1 || method == 8){ // is method 8 correct? + else if(method == 1 || method == 8) { // is method 8 correct? methodstring = "down"; } - else if(method == 5){ + else if(method == 5) { methodstring = "stop"; } else{ From 107d7669e7deb99792699a8639b163b4d3c536ff Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 May 2013 16:24:47 +0200 Subject: [PATCH 2158/2215] Moved "else" to same line as previous closing braces, according to Google style guidelines "whitespace/newline" --- telldus-core/service/ProtocolHasta.cpp | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index e41fcb80..df2788c5 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -167,32 +167,25 @@ std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) { model = "selflearning"; if(method == 0) { methodstring = "up"; - } - else if(method == 1) { + } else if(method == 1) { methodstring = "down"; - } - else if(method == 5) { + } else if(method == 5) { methodstring = "stop"; - } - else { + } else { return ""; } - } - else { + } else { // version2 house = allData & 0xFFFF; model = "selflearningv2"; if(method == 12) { methodstring = "up"; - } - else if(method == 1 || method == 8) { // is method 8 correct? + } else if(method == 1 || method == 8) { // is method 8 correct? methodstring = "down"; - } - else if(method == 5) { + } else if(method == 5) { methodstring = "stop"; - } - else{ + } else { return ""; } } From a78773a8ed4e4f7142c862ee55b23d54ba4c6e17 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 16 May 2013 16:29:57 +0200 Subject: [PATCH 2159/2215] Changed casting, according to Google style guidelines "readability/casting" --- telldus-core/service/ProtocolHasta.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/service/ProtocolHasta.cpp b/telldus-core/service/ProtocolHasta.cpp index df2788c5..786f068b 100644 --- a/telldus-core/service/ProtocolHasta.cpp +++ b/telldus-core/service/ProtocolHasta.cpp @@ -123,7 +123,7 @@ std::string ProtocolHasta::getStringForMethodv2(int method) { strReturn.append(convertBytev2(0x01)); sum += 0x01; - int checksum = (((int)(sum/256)+1)*256+1) - sum; + int checksum = ((static_cast(sum/256)+1)*256+1) - sum; strReturn.append(convertBytev2(checksum)); strReturn.append(1, 63); strReturn.append(1, 35); From b56823a6e79c2342af5dbd70f84f53ef0a2c09e7 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 17 May 2013 11:24:27 +0200 Subject: [PATCH 2160/2215] Some compilers seems to optimize away our tests. Compiling them statically and force initiating them seems to do the trick. --- telldus-core/tests/common/CMakeLists.txt | 2 +- telldus-core/tests/common/CommonTests.h | 11 +++++ telldus-core/tests/common/StringsTest.cpp | 2 - telldus-core/tests/cppunit.cpp | 47 +++++++++++-------- telldus-core/tests/service/CMakeLists.txt | 2 +- .../service/ProtocolEverflourishTest.cpp | 2 - .../tests/service/ProtocolNexaTest.cpp | 2 - .../tests/service/ProtocolOregonTest.cpp | 2 - .../tests/service/ProtocolSartanoTest.cpp | 2 - .../tests/service/ProtocolX10Test.cpp | 2 - telldus-core/tests/service/ServiceTests.h | 19 ++++++++ 11 files changed, 59 insertions(+), 34 deletions(-) create mode 100644 telldus-core/tests/common/CommonTests.h create mode 100644 telldus-core/tests/service/ServiceTests.h diff --git a/telldus-core/tests/common/CMakeLists.txt b/telldus-core/tests/common/CMakeLists.txt index ae52a231..eec397fb 100644 --- a/telldus-core/tests/common/CMakeLists.txt +++ b/telldus-core/tests/common/CMakeLists.txt @@ -2,7 +2,7 @@ FILE(GLOB SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*Test.cpp" ) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/common) -ADD_LIBRARY(TelldusCommonTests SHARED ${SRCS} ) +ADD_LIBRARY(TelldusCommonTests STATIC ${SRCS} ) TARGET_LINK_LIBRARIES( TelldusCommonTests TelldusCommon ${CPPUNIT} ) ADD_DEPENDENCIES( TelldusCommonTests TelldusCommon ) diff --git a/telldus-core/tests/common/CommonTests.h b/telldus-core/tests/common/CommonTests.h new file mode 100644 index 00000000..805b51ee --- /dev/null +++ b/telldus-core/tests/common/CommonTests.h @@ -0,0 +1,11 @@ +#ifndef COMMONTESTS_H +#define COMMONTESTS_H + +#include "StringsTest.h" + +namespace CommonTests { + inline void setup() { + CPPUNIT_TEST_SUITE_REGISTRATION (StringsTest); + } +} +#endif // COMMONTESTS_H diff --git a/telldus-core/tests/common/StringsTest.cpp b/telldus-core/tests/common/StringsTest.cpp index 790368a1..251d4a39 100644 --- a/telldus-core/tests/common/StringsTest.cpp +++ b/telldus-core/tests/common/StringsTest.cpp @@ -1,8 +1,6 @@ #include "StringsTest.h" #include "Strings.h" -CPPUNIT_TEST_SUITE_REGISTRATION (StringsTest); - void StringsTest :: setUp (void) { } diff --git a/telldus-core/tests/cppunit.cpp b/telldus-core/tests/cppunit.cpp index 65f0739e..8a05906f 100644 --- a/telldus-core/tests/cppunit.cpp +++ b/telldus-core/tests/cppunit.cpp @@ -8,32 +8,39 @@ #include +#include "common/CommonTests.h" +#include "service/ServiceTests.h" + int main (int argc, char* argv[]) { - // informs test-listener about testresults - CPPUNIT_NS :: TestResult testresult; + // Setup our tests + CommonTests::setup(); + ServiceTests::setup(); - // register listener for collecting the test-results - CPPUNIT_NS :: TestResultCollector collectedresults; - testresult.addListener (&collectedresults); + // informs test-listener about testresults + CPPUNIT_NS :: TestResult testresult; - // register listener for per-test progress output - CPPUNIT_NS :: BriefTestProgressListener progress; - testresult.addListener (&progress); + // register listener for collecting the test-results + CPPUNIT_NS :: TestResultCollector collectedresults; + testresult.addListener (&collectedresults); - // insert test-suite at test-runner by registry - CPPUNIT_NS :: TestRunner testrunner; - testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ()); - testrunner.run (testresult); + // register listener for per-test progress output + CPPUNIT_NS :: BriefTestProgressListener progress; + testresult.addListener (&progress); - // output results in compiler-format - CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr); - compileroutputter.write (); + // insert test-suite at test-runner by registry + CPPUNIT_NS :: TestRunner testrunner; + testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ()); + testrunner.run (testresult); - std::ofstream xmlFileOut("cpptestresults.xml"); - CPPUNIT_NS :: XmlOutputter xmlOut(&collectedresults, xmlFileOut); - xmlOut.write(); + // output results in compiler-format + CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr); + compileroutputter.write (); - // return 0 if tests were successful - return collectedresults.wasSuccessful () ? 0 : 1; + std::ofstream xmlFileOut("cpptestresults.xml"); + CPPUNIT_NS :: XmlOutputter xmlOut(&collectedresults, xmlFileOut); + xmlOut.write(); + + // return 0 if tests were successful + return collectedresults.wasSuccessful () ? 0 : 1; } diff --git a/telldus-core/tests/service/CMakeLists.txt b/telldus-core/tests/service/CMakeLists.txt index d43357a0..057f609c 100644 --- a/telldus-core/tests/service/CMakeLists.txt +++ b/telldus-core/tests/service/CMakeLists.txt @@ -2,7 +2,7 @@ FILE(GLOB SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*Test.cpp" ) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) -ADD_LIBRARY(TelldusServiceTests SHARED ${SRCS} ) +ADD_LIBRARY(TelldusServiceTests STATIC ${SRCS} ) TARGET_LINK_LIBRARIES( TelldusServiceTests TelldusServiceStatic ${CPPUNIT} ) ADD_DEPENDENCIES( TelldusServiceTests ${telldus-service_TARGET} ) diff --git a/telldus-core/tests/service/ProtocolEverflourishTest.cpp b/telldus-core/tests/service/ProtocolEverflourishTest.cpp index cb9749d6..2d9ec66d 100644 --- a/telldus-core/tests/service/ProtocolEverflourishTest.cpp +++ b/telldus-core/tests/service/ProtocolEverflourishTest.cpp @@ -1,8 +1,6 @@ #include "ProtocolEverflourishTest.h" #include "service/ProtocolEverflourish.h" -CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolEverflourishTest); - class ProtocolEverflourishTest::PrivateData { public: ProtocolEverflourish *protocol; diff --git a/telldus-core/tests/service/ProtocolNexaTest.cpp b/telldus-core/tests/service/ProtocolNexaTest.cpp index f65c0381..e2c9f8ec 100644 --- a/telldus-core/tests/service/ProtocolNexaTest.cpp +++ b/telldus-core/tests/service/ProtocolNexaTest.cpp @@ -1,8 +1,6 @@ #include "ProtocolNexaTest.h" #include "service/ProtocolNexa.h" -CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolNexaTest); - class ProtocolNexaTest::PrivateData { public: ProtocolNexa *protocol; diff --git a/telldus-core/tests/service/ProtocolOregonTest.cpp b/telldus-core/tests/service/ProtocolOregonTest.cpp index a18d3d52..2d5fd0fb 100644 --- a/telldus-core/tests/service/ProtocolOregonTest.cpp +++ b/telldus-core/tests/service/ProtocolOregonTest.cpp @@ -1,8 +1,6 @@ #include "ProtocolOregonTest.h" #include "service/ProtocolOregon.h" -CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolOregonTest); - class ProtocolOregonTest::PrivateData { public: }; diff --git a/telldus-core/tests/service/ProtocolSartanoTest.cpp b/telldus-core/tests/service/ProtocolSartanoTest.cpp index 24bef0b0..655dbb59 100644 --- a/telldus-core/tests/service/ProtocolSartanoTest.cpp +++ b/telldus-core/tests/service/ProtocolSartanoTest.cpp @@ -1,8 +1,6 @@ #include "ProtocolSartanoTest.h" #include "service/ProtocolSartano.h" -CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolSartanoTest); - class ProtocolSartanoTest::PrivateData { public: ProtocolSartano *protocol; diff --git a/telldus-core/tests/service/ProtocolX10Test.cpp b/telldus-core/tests/service/ProtocolX10Test.cpp index 4e97b425..572608f6 100644 --- a/telldus-core/tests/service/ProtocolX10Test.cpp +++ b/telldus-core/tests/service/ProtocolX10Test.cpp @@ -1,8 +1,6 @@ #include "ProtocolX10Test.h" #include "service/ProtocolX10.h" -CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolX10Test); - class ProtocolX10Test::PrivateData { public: ProtocolX10 *protocol; diff --git a/telldus-core/tests/service/ServiceTests.h b/telldus-core/tests/service/ServiceTests.h new file mode 100644 index 00000000..527f2d07 --- /dev/null +++ b/telldus-core/tests/service/ServiceTests.h @@ -0,0 +1,19 @@ +#ifndef SERVICETESTS_H +#define SERVICETESTS_H + +#include "ProtocolEverflourishTest.h" +#include "ProtocolNexaTest.h" +#include "ProtocolOregonTest.h" +#include "ProtocolSartanoTest.h" +#include "ProtocolX10Test.h" + +namespace ServiceTests { + inline void setup() { + CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolEverflourishTest); + CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolNexaTest); + CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolOregonTest); + CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolSartanoTest); + CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolX10Test); + } +} +#endif // SERVICETESTS_H From b00cbdb37c395b1ca34adce4ac7525b6fea46cc9 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 17 May 2013 11:41:58 +0200 Subject: [PATCH 2161/2215] Added unit test for Hasta protocol --- .../tests/service/ProtocolHastaTest.cpp | 42 +++++++++++++++++++ .../tests/service/ProtocolHastaTest.h | 25 +++++++++++ telldus-core/tests/service/ServiceTests.h | 2 + 3 files changed, 69 insertions(+) create mode 100644 telldus-core/tests/service/ProtocolHastaTest.cpp create mode 100644 telldus-core/tests/service/ProtocolHastaTest.h diff --git a/telldus-core/tests/service/ProtocolHastaTest.cpp b/telldus-core/tests/service/ProtocolHastaTest.cpp new file mode 100644 index 00000000..3ef50975 --- /dev/null +++ b/telldus-core/tests/service/ProtocolHastaTest.cpp @@ -0,0 +1,42 @@ +#include "ProtocolHastaTest.h" +#include "service/ProtocolHasta.h" + +CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolHastaTest); + +class ProtocolHastaTest::PrivateData { +public: + ProtocolHasta *protocol; +}; + +void ProtocolHastaTest :: setUp (void) { + d = new PrivateData; + d->protocol = new ProtocolHasta(); +} + +void ProtocolHastaTest :: tearDown (void) { + delete d->protocol; + delete d; +} + +void ProtocolHastaTest :: decodeDataTest (void) { + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Hasta Version 1 26380 1 DOWN", + std::string("class:command;protocol:hasta;model:selflearning;house:26380;unit:1;method:down;"), + d->protocol->decodeData(ControllerMessage("protocol:hasta;model:selflearning;data:0xC671100;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Hasta Version 1 26380 1 UP", + std::string("class:command;protocol:hasta;model:selflearning;house:26380;unit:1;method:up;"), + d->protocol->decodeData(ControllerMessage("protocol:arctech;model:selflearning;data:0xC670100;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Hasta Version 2 19337 15 DOWN", + std::string("class:command;protocol:hasta;model:selflearningv2;house:19337;unit:15;method:down;"), + d->protocol->decodeData(ControllerMessage("protocol:hasta;model:selflearningv2;data:0x4B891F01;")) + ); + CPPUNIT_ASSERT_EQUAL_MESSAGE( + "Hasta Version 2 19337 15 UP", + std::string("class:command;protocol:hasta;model:selflearningv2;house:19337;unit:15;method:up;"), + d->protocol->decodeData(ControllerMessage("protocol:hasta;model:selflearningv2;data:0x4B89CF01;")) + ); +} diff --git a/telldus-core/tests/service/ProtocolHastaTest.h b/telldus-core/tests/service/ProtocolHastaTest.h new file mode 100644 index 00000000..8c7b9edc --- /dev/null +++ b/telldus-core/tests/service/ProtocolHastaTest.h @@ -0,0 +1,25 @@ +#ifndef PROTOCOLHASTATEST_H +#define PROTOCOLHASTATEST_H + +#include +#include + +class ProtocolHastaTest : public CPPUNIT_NS :: TestFixture +{ + CPPUNIT_TEST_SUITE (ProtocolHastaTest); + CPPUNIT_TEST (decodeDataTest); + CPPUNIT_TEST_SUITE_END (); + +public: + void setUp (void); + void tearDown (void); + +protected: + void decodeDataTest(void); + +private: + class PrivateData; + PrivateData *d; +}; + +#endif //PROTOCOLHASTATEST_H diff --git a/telldus-core/tests/service/ServiceTests.h b/telldus-core/tests/service/ServiceTests.h index 527f2d07..7dde4e83 100644 --- a/telldus-core/tests/service/ServiceTests.h +++ b/telldus-core/tests/service/ServiceTests.h @@ -2,6 +2,7 @@ #define SERVICETESTS_H #include "ProtocolEverflourishTest.h" +#include "ProtocolHastaTest.h" #include "ProtocolNexaTest.h" #include "ProtocolOregonTest.h" #include "ProtocolSartanoTest.h" @@ -10,6 +11,7 @@ namespace ServiceTests { inline void setup() { CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolEverflourishTest); + CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolHastaTest); CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolNexaTest); CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolOregonTest); CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolSartanoTest); From a231b56d57a69513303d0061f5fa3e3cd51c85c1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 17 May 2013 11:49:38 +0200 Subject: [PATCH 2162/2215] Removed redundunt test suite registration command from Hasta unit test --- telldus-core/tests/service/ProtocolHastaTest.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/telldus-core/tests/service/ProtocolHastaTest.cpp b/telldus-core/tests/service/ProtocolHastaTest.cpp index 3ef50975..4b118664 100644 --- a/telldus-core/tests/service/ProtocolHastaTest.cpp +++ b/telldus-core/tests/service/ProtocolHastaTest.cpp @@ -1,8 +1,6 @@ #include "ProtocolHastaTest.h" #include "service/ProtocolHasta.h" -CPPUNIT_TEST_SUITE_REGISTRATION (ProtocolHastaTest); - class ProtocolHastaTest::PrivateData { public: ProtocolHasta *protocol; From 940d93556b44b8566c90929f3a0b27b2768504a3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 23 May 2013 11:39:27 +0200 Subject: [PATCH 2163/2215] Updated translations --- telldus-gui/Plugins/Live/LiveObject.cpp | 24 ++--- telldus-gui/Plugins/Live/translation_sv.ts | 87 ++++++++++++++++++- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 2 +- telldus-gui/TelldusCenter/TelldusCenter_sv.ts | 14 +-- telldus-gui/TelldusCenter/mainwindow.cpp | 2 +- telldus-gui/TelldusGui/TelldusGui_sv.ts | 26 +++--- 6 files changed, 117 insertions(+), 38 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index c5e29f0a..213a3747 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -85,7 +85,7 @@ void LiveObject::connectToServer() { d->socket->abort(); PrivateData::Server server = d->serverList.takeFirst(); emit errorChanged(""); - emit statusChanged("Connecting to server " + server.address); + emit statusChanged(tr("Connecting to server %1").arg(server.address)); d->socket->connectToHostEncrypted(server.address, server.port); } } @@ -115,7 +115,7 @@ void LiveObject::readyRead() { } else if (msg->name() == "registered") { d->registered = true; emit registered(msg->argument(0)); - emit errorChanged("Registered"); + emit errorChanged(tr("Registered")); } else if (msg->name() == "notregistered") { LiveMessageToken token = msg->arg(0); if (token.valueType != LiveMessageToken::Dictionary) { @@ -126,7 +126,7 @@ void LiveObject::readyRead() { QSettings s; s.setValue("Live/UUID", d->uuid); emit notRegistered(); - emit errorChanged("Not registered"); + emit errorChanged(tr("Not registered")); } else if (msg->name() == "command") { if (msg->arg(0).valueType == LiveMessageToken::Dictionary && msg->arg(0).dictVal.contains("ACK")) { int ack = msg->arg(0).dictVal["ACK"].intVal; @@ -142,7 +142,7 @@ void LiveObject::readyRead() { void LiveObject::refreshServerList() { emit errorChanged(""); - emit statusChanged("Discover servers"); + emit statusChanged(tr("Discover servers")); d->serverList.clear(); QUrl url(TELLDUS_LIVE_URI); QPair version("protocolVersion", "2"); @@ -199,7 +199,7 @@ void LiveObject::p_connected() { this->sendMessage(msg); emit errorChanged(""); - emit statusChanged("Connected"); + emit statusChanged(tr("Connected")); emit connected(); } @@ -208,7 +208,7 @@ void LiveObject::p_disconnected() { d->pongTimer.stop(); if (d->registered) { //Clear the registered status - emit errorChanged("Disconnected from server"); + emit errorChanged(tr("Disconnected from server")); } d->registered = false; } @@ -221,9 +221,9 @@ void LiveObject::stateChanged( QAbstractSocket::SocketState socketState ) { if (socketState == QAbstractSocket::UnconnectedState) { int timeout = rand() % 40 + 10; //Random timeout from 10-50s to avoid flooding the servers QTimer::singleShot(timeout*1000, this, SLOT(connectToServer())); - emit statusChanged("Reconnecting in " + QString::number(timeout) + " seconds..."); + emit statusChanged(tr("Reconnecting in %1 seconds...").arg(QString::number(timeout))); } else if (socketState == QAbstractSocket::ConnectingState) { - emit statusChanged("Connecting..."); + emit statusChanged(tr("Connecting...")); emit errorChanged(""); } } @@ -237,7 +237,7 @@ void LiveObject::sslErrors( const QList & errors ) { default: //qDebug() << "SSL" << error.errorString(); everythingOK = false; - emit statusChanged("SSL Error"); + emit statusChanged(tr("SSL Error")); emit errorChanged(error.errorString()); break; } @@ -252,7 +252,7 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { if (r->error() != QNetworkReply::NoError) { int timeout = rand() % 300 + 60; //Random timeout from 60s-6min to avoid flooding the servers emit errorChanged(r->errorString()); - emit statusChanged("Retrying in " + QString::number(timeout) + " seconds..."); + emit statusChanged(tr("Retrying in %1 seconds...").arg(QString::number(timeout))); QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer())); return; } @@ -278,8 +278,8 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { QTimer::singleShot(0, this, SLOT(connectToServer())); } else { int timeout = rand() % 300 + 60; //Random timeout from 60-6min to avoid flooding the servers - emit errorChanged("No servers found"); - emit statusChanged("Retrying in " + QString::number(timeout) + " seconds..."); + emit errorChanged(tr("No servers found")); + emit statusChanged(tr("Retrying in %1 seconds...").arg(QString::number(timeout))); QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer())); } } diff --git a/telldus-gui/Plugins/Live/translation_sv.ts b/telldus-gui/Plugins/Live/translation_sv.ts index 6cdfaf84..24cc7595 100644 --- a/telldus-gui/Plugins/Live/translation_sv.ts +++ b/telldus-gui/Plugins/Live/translation_sv.ts @@ -1,28 +1,107 @@ + + Form + + + Form + + + + + Status: + Status: + + + + unknown + + + + + Activate Telldus Live! + Aktivera Telldus Live! + + LiveObject - + Default browser could not be opened Standardwebbläsaren kunde inte öppnas - + We could not open your default internet browser Vi kunde inte öppna din standardwebbläsare - + Please copy the following url and enter it in your browser:<br><a href='%1'>%1</a> Kopiera följande URL och klistra in i din webbläsare:<br><a href='%1'>%1</a> + + + Connecting to server %1 + Ansluter till servern %1 + + + + Registered + Registrerad + + + + Not registered + Inte registrerad + + + + Discover servers + Söker servrar + + + + Connected + Ansluten + + + + Disconnected from server + Bortkopplad frÃ¥n server + + + + Reconnecting in %1 seconds... + Ã…teransluter om %1 sekunder... + + + + Connecting... + Ansluter... + + + + SSL Error + SSL-fel + + + + + Retrying in %1 seconds... + Försöker igen om %1 sekunder... + + + + No servers found + Inga servrar kunde hittas + __init__ - + Activate Telldus Live! Aktivera Telldus Live! diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 05afea26..4ee6386b 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -53,7 +53,7 @@ IF(Plugin_PATH) #Add all extra files FOREACH(_FILE ${Plugin_EXTRA}) GET_FILENAME_COMPONENT(ext "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}" EXT) - IF (ext STREQUAL ".qml") + IF (ext STREQUAL ".qml" OR ext STREQUAL ".ui") LIST(APPEND translation_sources "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}") ENDIF () LIST(APPEND Plugin_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${_FILE}") diff --git a/telldus-gui/TelldusCenter/TelldusCenter_sv.ts b/telldus-gui/TelldusCenter/TelldusCenter_sv.ts index 260c425e..3a8d571a 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter_sv.ts +++ b/telldus-gui/TelldusCenter/TelldusCenter_sv.ts @@ -24,33 +24,33 @@ &Avsluta - + &Help &Hjälp - + About &Qt Om &Qt - + About &TelldusCenter Om &TelldusCenter - + Pages Sidor - + About TelldusCenter Om TelldusCenter - - <center><img src=':/images/TelldusCenter_128.png' width=128 height=128 /><h2>TelldusCenter %1</h2><p>Copyright &copy; 2011 Telldus Technologies AB<p></center> + + <center><img src=':/images/TelldusCenter_128.png' width=128 height=128 /><h2>TelldusCenter %1</h2><p>Copyright &copy; 2013 Telldus Technologies AB<p></center> diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index b0af55b4..a69729cc 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -135,7 +135,7 @@ void MainWindow::addWidget( const QString &page, const QIcon &icon, QWidget *wid void MainWindow::slotAboutApplication() { QMessageBox::about(this, tr("About TelldusCenter"), tr("

TelldusCenter %1

" - "

Copyright © 2011 Telldus Technologies AB

").arg(VERSION_STRING(VERSION))); + "

Copyright © 2013 Telldus Technologies AB

").arg(VERSION_STRING(VERSION))); } void MainWindow::slotConfigure() { diff --git a/telldus-gui/TelldusGui/TelldusGui_sv.ts b/telldus-gui/TelldusGui/TelldusGui_sv.ts index f66810ab..4fc813cc 100644 --- a/telldus-gui/TelldusGui/TelldusGui_sv.ts +++ b/telldus-gui/TelldusGui/TelldusGui_sv.ts @@ -171,37 +171,37 @@ DeviceWidget - + New device... Ny enhet... - + New group... Ny grupp... - + New Ny - + Edit Redigera - + Remove Ta bort - + Are you sure you want to remove the selected device? Är du säker pÃ¥ att du vill ta bort vald enhet? - + The device will be removed permanently from this application as well as all other applications. Enheten kommer tas bort permanent frÃ¥n bÃ¥de detta program sÃ¥väl som alla andra program. @@ -240,32 +240,32 @@ Adresskod - + Please press a button on your remote Tryck en knapp pÃ¥ din fjärrkontroll - + If you have a TellStick Duo connected,<br>you can use it to scan the code of the remote control Om du har en TellStick Duo ansluten,<br>kan du använda den för att hitta rätt enhet och inställningar - + You must choose a device Du mÃ¥ste välja en enhet - + Please select the device you have. Välj den enhet du har. - + The device must have a name. Enheten mÃ¥ste ha ett namn. - + Please fill in a name in the field under 'Name' Skriv in ett namn i fältet 'Namn' From 033cf796174446f5fff5bbfad1cbf1e4af35c0d8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 23 May 2013 11:41:04 +0200 Subject: [PATCH 2164/2215] Bumped version to 2.1.2 Beta1 --- telldus-gui/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index 5354d13a..d74d0e6e 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -8,10 +8,10 @@ endif(COMMAND cmake_policy) SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) -SET(PACKAGE_PATCH_VERSION 1) +SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION} Beta1") SET(BRANDING "telldus" CACHE STRING "The brand to use") From 8449c3a0a82aae7b2000b8bf08d5624bcfc16549 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 May 2013 12:03:10 +0200 Subject: [PATCH 2165/2215] Add icon for upgrading TellStick --- telldus-gui/Plugins/Controllers/CMakeLists.txt | 1 + .../Plugins/Controllers/ControllerView.qml | 3 +-- .../Plugins/Controllers/btn_action_upgrade.png | Bin 0 -> 1692 bytes 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 telldus-gui/Plugins/Controllers/btn_action_upgrade.png diff --git a/telldus-gui/Plugins/Controllers/CMakeLists.txt b/telldus-gui/Plugins/Controllers/CMakeLists.txt index 6e2366e8..338942e2 100644 --- a/telldus-gui/Plugins/Controllers/CMakeLists.txt +++ b/telldus-gui/Plugins/Controllers/CMakeLists.txt @@ -31,6 +31,7 @@ SET( Plugin_PATH "com.telldus.controllers" ) SET( Plugin_EXTRA btn_action_remove.png + btn_action_upgrade.png ControllerUpgradeDialog.qml ControllerView.qml header_bg.png diff --git a/telldus-gui/Plugins/Controllers/ControllerView.qml b/telldus-gui/Plugins/Controllers/ControllerView.qml index 8fc17c7f..1cfb4d33 100644 --- a/telldus-gui/Plugins/Controllers/ControllerView.qml +++ b/telldus-gui/Plugins/Controllers/ControllerView.qml @@ -77,8 +77,7 @@ BorderImage { } } Image { - source: "btn_action_remove.png" - rotation: 90 + source: "btn_action_upgrade.png" visible: controller.upgradable MouseArea { anchors.fill: parent diff --git a/telldus-gui/Plugins/Controllers/btn_action_upgrade.png b/telldus-gui/Plugins/Controllers/btn_action_upgrade.png new file mode 100644 index 0000000000000000000000000000000000000000..daa6131a74850a432d3d9c36b1dc4dd6372f002e GIT binary patch literal 1692 zcmV;N24ne&P)VV- zK#L(Ig1k&bF$NRG2#O>SHsS+AT<8LJ?u-i`7!p_NhLxJ=MoHYTK+$LrVk8vtL3pIF z;bkekkG8k>-p=zJ&zU(hb7optkvQ$#^O!T||Nrm*|L^=moOAr2S62QIkw2K3nRzCY z$-FJP8^zqx`zc5mI_`PiUyVlN)8XOa6JmV5v zh#~EH(2r)cN7GYNA1)gjIwZQbAtxHba>FnV%H^bl1fZmaBU%B~lHOB~h{Ab_2RweW zr&N0PN5sXB~zL8~wgFK6S<+;x~<8y>fPaI=&{-YBB4V;L4x zKg{Vl>|D7YdQ!w`sB9GiiXBP;OCq3WP((t(b$;?BuG(kO;C0l^34hLog&}XfZ}C{} zl!&d2A47}sJt!Aepv&sTvk$(O+9`Q;2nDiXK=UZYWUd=3Wd%BJ8-LV(0xL39+P8c` z68d3UkLOBnpflHnY&C~J-5-!M@~Ar%xDG?nyDiq=z(D76BvaCc}Su`>Rg#RhlV)=)3zbP4kNiovAcW#OUg??>g}HXZfrO9!MK^l z>DEzURR(olL)IEYih@$V3IQJ>9te-AJLuHrCNOI@g#sq}y%l)6^b$I{@FK&@@|UI5WN}q)3a1H0C4?0ZJV*8fQ4n5m{ovWgJzSz}Ghp!MxVO z^UGhsj#aPv3&$qURP@+g%q=*bUa%(@1~ zJy?87%rVS~z?^PQMZD5%&*Dzw4hq?VKOqBEFfMYPdEaWzW46^#`9u%~w6F0y1@2fo z@PtTHQ``=0+k<0sxZ-ABY!+uEBA@%u9Gm%TEz`!z(z=k!6vBZUBDX{eEPzkgTR->| zx(l6RQxSqv3Awqij1AXv;W=X7v7=|UEn8P;Wn%O2&cwcyBI$^VMXAIUPSIf$9w_qN zv*X9{@h|Uzv5cRtO!9xegq~u*zpiCBQ5C@&!Y$uFUyUBdcx_6ck=)!6N_KY@uxI05>|S#qI@;rcL{&!7iO7-3gbFZ^ z&u46n#kJ&UST&5^`Vs$(pTX72W!RpDhX&SSP5BW#Is78}9~g?k=7~ZoD90#vg{Z(o z1sG4z^n#wyi;!f6On0l5NiXHno0Cw$7%`&FQvph(a~6d)W+G!#o%!`4M-018F%+J- ziiiXX4YAQ;N>C-f2$>_|E`lpO_ literal 0 HcmV?d00001 From 27e5b82ee1663a136987f4c08452ff8a663f24af Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 May 2013 12:03:32 +0200 Subject: [PATCH 2166/2215] Update icon for Controllers plugin --- telldus-gui/Plugins/Controllers/icon.png | Bin 754 -> 1618 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/telldus-gui/Plugins/Controllers/icon.png b/telldus-gui/Plugins/Controllers/icon.png index 4badd42f0dafbb110ec9bb0c2ebe1ed0d957c1ec..a71ba8800ba5737140c7348862dd575414d408af 100644 GIT binary patch delta 1565 zcmV+&2IBeh1=0+VNPh+NNkl}4idpie?&YrjM z%5@#%d^nB=(+X_W4J>oZxn@tYP4x4z%h&mM0}!47vD_r31E*Y=l`j;o{qyy42LPr{ zG6=4LF)ha=%l!HBxTio0VQ7q-YNbMo0;C{3W6MVx9OR8aszcyVztxO!ES8p4&;fF~zjUL^_9meQ*%1GMTI&tJW&1Yvrf zYgd*5A?!l22+#1;XOlq>R#pR^VAAvaGN3ZFG;Y|HO@9F-S1C|0zYfWnDh+^4h|E~1 zig5EnIAeFi){l3A6P(`u3s}5(0o^R<`$c?)9fapP@JeOqmg+5X{^`zMyt;jN)X)RV z8D|Y-ID;XJA6nVcbkK>-NJ;5Jwcxo^Si+@eIXp^%evXLf{of+YX46$+J^FMyU%Y$w zzV`S~PJgTAWNbdUOb5%0XLhu9T!`8ot&Dl^-83h1GRLN}s>xHz9Nf^Q*w2m7>HiEs z8Cdh;MfmCa@9(1sn>8yu@7ojI)`xpep!0kdED-YVl7jhUE51@i)Y!4u+T}}{)}B7w zJvwxtExK&R2$T@ZZnV(2^fsdA)_(%t0~uEUJUQ4FVY z(0_G}o@1ybAe?|7Y45|c?;oZPVLqP0G2k_&3W|@TL&Hh0`#ONU{D{8hipuY zg%FLH$O{dVCWKHVrVjr+fFoUCA7%fQTCANLt4fKupYWD?00U%0vb3+Rz#)A~xp+G`S!D{wXBe-us7X}APdk_8a zQK~2L+!GJ3=)WohC0N6=s?sf8MSt%hIQ(gpC)PC-jw9hUV$WwZMd?ad(ifEr_uy&nwfex%LCnC+erqq;xPpF#cupJEjvVGQ$|f+7%7` z_X1CC{iO4a-mHAIdk7o56Mv}g=^w(r6Un1%7us!;BJ6F`j-3ieCm|FJBSnH!-SS$6{sQ0+0Tu=TG{v$YZpjyp P00000NkvXXu0mjfecS!> delta 694 zcmV;n0!jVS4Dtn#NPhy9Nklbmu?ZVBL)Iy2P>_UgVK0kd=omOk-Iq!Sk zJ@x6iIPZCX-}m|cp5OC(qMqkPTt+ljKa1%!)WBRAgu8IrOMk=%BaS2LB0#}kz$!Qg zJ+K-szz?WI#5WfKd5(fF!cy1-h0qLZp#rACm7J{rUq7AcBb!sW1<6BEam5{$I63ypy?8EAv%3;ALa0ivUlI5_FHe zw-u;_WF*UxpMS-FOvEx+2P4Xd(Xa%V1yit~mAO?G)X0KR1f(q3s#;(cY==K#TVPpV zE(=P+6p*r@F|9s?Zh=S84OVdA7i@;VVOn4rzaMr;z=|-pVakHDlWjpUbCGtz%CPD{ zp=!M?cN^?Z`>jXf3iMpC$1z`A%Jd4}K`+c0^N5|4eSgpm37+2>*m2CuY@fe{hw{1! z4k#behczmvpcanVDM_xp4?@6ed3_wZl=b5c>xQbJ9@bmqf{0|+77)CeX^UQXbAsRz z^#XSwt~znZZw}ZCp6bNgm7%S6N|vcn^(|l{JcpR$?uw~JEAcD9TCgv$$Wg#T_zpAu z3iz!p_kYt-z=*o!q+bF3YQf()3b1;y20r^0@B|KmZN*O+2Dbz15gdkReg)iCmD{W0 zlF6u34OpU*?Yj`w>P1zm^&K#OoG(8KA5^v*C_+~QxfvnCI-mvxcmUNBl)8ji!24>^ zZ^1Q!p9uPDc9iM5%58`8!oJ!rtfjgw+c8~7@Gq8J-HsP99f5rcR-lG-03Jg-!3SKn c%Rd1I0Ev{!`I2XhSO5S307*qoM6N<$g4F#@R{#J2 From b52c80f98863483f27bad097df3efbd1fe1c9903 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 May 2013 12:04:05 +0200 Subject: [PATCH 2167/2215] Add firmware 10 for TellStick Duo --- .../Controllers/firmware/TellStickDuo.hex | 1742 +++++++++-------- telldus-gui/Plugins/Controllers/tellstick.cpp | 2 +- 2 files changed, 961 insertions(+), 783 deletions(-) diff --git a/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex b/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex index 185fc536..5d615751 100644 --- a/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex +++ b/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex @@ -1,788 +1,966 @@ :0400000014EF00F009 -:10000800FACF8CF4FBCF8DF4E9CF8EF483ED14F0A6 -:10001800D8CF7AF4E8CF7BF4E0CF7CF454EF13F038 -:1000280004EE24F07C0EF66E000EF76E10EE0DF066 -:1000380035EC00F000EE00F014EE24F02EEC00F0A9 +:10000800FACFB6F4FBCFB7F4E9CFB8F4BCED19F0EA +:10001800D8CFA4F4E8CFA5F4E0CFA6F48CEF18F07D +:1000280004EE33F07C0EF66E000EF76E10EE27F03D +:1000380035EC00F000EE00F014EE33F02EEC00F09A :1000480005EE00F011EE00F02EEC00F0000EF86E58 -:10005800D6EF16F0EE6AE550E150FCE1E250FAE125 +:100058004CEF1CF0EE6AE550E150FCE1E250FAE1A9 :1000680012000900F5CFEEFFE550E150FAE1E25049 -:10007800F8E11200000100000100FFFFF3FF80FF1C -:10008800FF00000E040104013C6F000E04013D6FE7 -:10009800000E04013E6F000E04013F6F0401370E8D -:1000A800040104015D6F0401040E04015E6F040184 -:1000B800350E040104015B6F0401040E04015C6F3A -:1000C8002FEC16F00401370E04010401566F0401E9 -:1000D800040E0401576F0401350E04010401546F26 -:1000E8000401040E0401556FE1EC10F0010E040147 -:1000F8000401386F000E0401396F000E04013A6FD5 -:10010800000E04013B6F000E04010401406F000E55 -:100118000401416F040104014151800A800F200E3F -:10012800D8B4405DD8A001D001D001D06FD004016F -:10013800370E04010401566F0401040E0401576FC1 -:100148000401350E04010401546F0401040E040176 -:10015800556FE1EC10F004010401426F0401370E01 -:1001680004010401566F0401040E0401576F0401D1 -:10017800350E04010401546F0401040E0401556F87 -:10018800E1EC10F004010401436F1BD025D00401F9 -:1001980004013851040104013C13040104013951DC -:1001A800040104013D13040104013A51040104014E -:1001B8003E13040104013B51040104013F130CD018 -:1001C80029D143C455F442C454F4B3EC16F0000AE0 -:1001D800DDE0010ADCE0F4D70401D89004013837E7 -:1001E8000401393704013A3704013B37040104019B -:1001F800404B412B040104014151800A800F200E1D -:10020800D8B4405DD8A001D001D091D704013CC436 -:1002180044F404013DC445F404013EC446F4040119 -:100228003FC447F40401441F451F461F471F110ED2 -:1002380006D0D89004014733463345334433E82E7B -:10024800F8D7FF0E040144150401486F000E04019D -:1002580045150401496F000E0401461504014A6F53 -:10026800000E0401471504014B6F04013CC44CF413 -:1002780004013DC44DF404013EC44EF404013FC4DE -:100288004FF4190E06D0D89004014F334E334D3336 -:100298004C33E82EF8D7FF0E04014C150401506FBB -:1002A800000E04014D150401516F000E04014E1596 -:1002B8000401526F000E04014F150401536F04012D -:1002C8004B51040153190EE104014A51040152191A -:1002D80009E1040149510401511904E1040148519B -:1002E80004015019D8B401D001D001D093D0FF0E29 -:1002F80004013CC444F404013DC445F404013EC473 -:1003080046F404013FC447F40401441F451F461F37 -:10031800471F040144150401486F000E04014515E8 -:100328000401496F000E0401461504014A6F000ECE -:100338000401471504014B6FFF0E04013CC44CF443 -:1003480004013DC44DF404013EC44EF404013FC40D -:100358004FF44DC44CF44EC44DF44FC44EF4040154 -:100368004F6B04014C150401506F000E04014D152C -:100378000401516F000E04014E150401526F000E66 -:1003880004014F150401536F04014B510401531923 -:100398000EE104014A510401521909E104014951CD -:1003A8000401511904E10401485104015019D8B459 -:1003B80001D001D001D02ED0C9EC17F0F10E040104 -:1003C8000401566F790E0401576F8C0E0401040165 -:1003D800546F790E0401556F9AEC17F03CC456F42B -:1003E8003DC457F43EC458F43FC459F4E30E040125 -:1003F8000401546F790E0401556F02EC0EF00401EC -:10040800446F020E04010401546F04014451BBEC13 -:1004180017F000D012000401630E040104016A6F92 -:100428000401040E04016B6F81D1040104016951B8 -:10043800250AD8B401D001D005D069C472F438ECCB -:1004480017F074D10401706F000E04010401686F85 -:10045800040170514BD07DD104010401688F61D033 -:1004680004016AC4E9FF04016BC4EAFF0401020E37 -:1004780004016A27000E04016B230401EECF6CF41B -:100488000401EDCF6DF4040104016D516C11D8A481 -:1004980001D001D007D0A60E040104016C6F790EBB -:1004A80004016D6F10D004016CC4F6FF04016DC423 -:1004B800F7FF08000401F5CF72F438EC17F00401D7 -:1004C80004016C4B6D2B04016CC4F6FF04016DC470 -:1004D800F7FF0800F5500009D8A401D001D0E3D7F0 -:1004E80025D1C00E0401040168131BD0040161C4A6 -:1004F800F6FF040162C4F7FF04010401614B622B9B -:1005080008000401F5CF69F404016951000AA3E069 -:10051800580AA2E02B0AA4E0060AE3E00D0A9CE0D0 -:10052800DFD704016AC4E9FF04016BC4EAFF0401D0 -:10053800020E04016A27000E04016B230401EECFAA -:100548006CF40401EDCF6DF478D00401706F010EE6 -:1005580004010401696F0401705104010401695127 -:10056800050AD8A401D001D001D02AD00401040181 -:100578006951020DFC0EF324F66EF76A780EF72225 -:100588000900F5CF70F40900F5CF71F4040170513A -:10059800040104016C5D04017151040104016D59E9 -:1005A800D8B001D001D001D00BD004010401692BCF -:1005B800040104016951050AD8A401D001D0D6D795 -:1005C80045D00401706F010E04010401696F040134 -:1005D8007051040104016951040AD8A401D001D062 -:1005E80001D0EED7040104016951020D060EF3246F -:1005F800F66EF76A790EF7220900F5CF70F4090054 -:10060800F5CF71F404017051040104016C5D04011B -:100618007151040104016D59D8B001D001D001D045 -:10062800CFD704010401692B040104016951040AAC -:10063800D8A401D001D0D6D709D00401040168514B -:10064800C00B800ABEE0400A80E000D069C467F4AD -:1006580064D056D0040104016751020DFC0EF32446 -:10066800F66EF76A780EF72209000401F5CF74F4E4 -:100678000A000401F5CF75F46CC472F46DC473F408 -:1006880043EC11F072C472F473C473F40A0E0401DB -:100698000401746F000E0401756FA2EC13F00401DD -:1006A80004017251300F04010401696F32D0040152 -:1006B80004016751020D060EF324F66EF76A790EEF -:1006C800F72209000401F5CF74F40A000401F5CFFC -:1006D80075F46CC472F46DC473F443EC11F00F0E2E -:1006E800040104017217390E040104017225F66E23 -:1006F800F76A790EF72208000401F5CF69F409D0EA -:10070800040104016851C00B800AD1E0400AA2E04C -:1007180000D069C472F438EC17F0040104016707CB -:1007280004016729D8A401D001D093D7040161C47A -:10073800F6FF040162C4F7FF04010401614B622B58 -:1007480008000401F5CF69F40401696701D001D0FC -:100758006CD600D0120004014B6F000E0401040196 -:10076800386F04014B51000E040104013D6F000E67 -:1007780004013E6F000E04013F6F000E0401406F3C -:10078800010E04010401416F000E0401426F000EC6 -:100798000401436F000E0401446F0401370E040185 -:1007A80004015D6F0401040E04015E6F0401350E3F -:1007B800040104015B6F0401040E04015C6F2FEC5B -:1007C80016F00401370E04010401566F0401040EEB -:1007D8000401576F0401350E04010401546F04012C -:1007E800040E0401556FE1EC10F035C43BF436C437 -:1007F8003CF40401040137C439F4040104013A6BE0 -:10080800000E04010401456F000E0401466F040147 -:1008180004014651800A800F200ED8B4455DD8A047 -:1008280001D001D001D059D00401370E04010401D0 -:100838004F6F0401040E0401506F0401350E0401CA -:1008480004014D6F0401040E04014E6FEEEC13F029 -:1008580004010401496F040104014951020AD8A4A2 -:1008680001D001D001D0EDD0040104014951D8B420 -:1008780001D001D018D00401040141510401040140 -:100888003D13040104014251040104013E13040113 -:1008980004014351040104013F13040104014451BC -:1008A8000401040140130401D890040141370401F4 -:1008B8004237040143370401443704010401454B1E -:1008C800462B040104014651800A800F200ED8B43B -:1008D800455DD8A001D001D0A7D7000E04010401BE -:1008E800476F000E0401486F040104014851800A53 -:1008F800800F040ED8B4475DD8A001D001D001D034 -:100908004AD00401370E040104014F6F0401040E9C -:100918000401506F0401350E040104014D6F0401F8 -:10092800040E04014E6FEEEC13F0040104014A6F4B -:10093800040104014A51020AD8A401D001D001D00F -:1009480080D0040104014A51D8B401D001D013D099 -:1009580047C44BF4010E04014C6F04014B2B03D028 -:10096800D89004014C3704014B2FFAD704014C519D -:1009780004010401381304010401474B482B040106 -:1009880004014851800A800F040ED8B4475DD8A0EE -:1009980001D001D0B6D70401040138510C0AD8B4EB -:1009A80001D001D001D04DD0C9EC17F0B40E04012C -:1009B8000401566F790E0401576FCE0E040104012D -:1009C800546F790E0401556F9AEC17F07A0E0401F2 -:1009D8000401566F790E0401576F8C0E040104014F -:1009E800546F790E0401556F9AEC17F0250E040127 -:1009F8000401566F790E0401576FC80E04010401F3 -:100A0800546F790E0401556F9AEC17F03DC456F4F3 -:100A18003EC457F43FC458F440C459F4E30E0401EB -:100A28000401546F790E0401556F02EC0EF00401B5 -:100A38004B6F010E04010401546F04014B51BBECD0 -:100A480017F01200040104013551D8B401D001D0C7 -:100A580005D0030E04010401362704D0030E040157 -:100A68000401365F2AD10B0E04010401366501D05A -:100A780001D009D0170E04010401366101D001D05C -:100A880002D0012A25D1030E04010401366501D0E4 -:100A980001D01CD00D0E04010401366101D001D033 -:100AA80015D0190E016401D001D00AD00401376FA6 -:100AB800010E086E04013751000E196E000E1A6EF1 -:100AC8000401376F000E016E0401375101D136C49D -:100AD8003AF435C439F439EC14F039C41BF43AC487 -:100AE8001CF4040104011C29FE0ED8B41B19D8A457 -:100AF80001D001D003D087EC17F0EAD0040104013B -:100B08001B29D8B41C29D8A401D001D001D0E0D029 -:100B18001A501910D8A401D001D006D0040104013C -:100B28001B511A6E196A43D0040104011B51191292 -:100B3800040104011C511A1211D00401376F060E6A -:100B4800026E0401375127D00401376F080E026E78 -:100B58000401375120D087EC17F0BAD019C037F408 -:100B68001AC038F40FD0040137514D0AEDE0F3D71D -:100B7800040137512D0AE8E0EED7040137514C0A39 -:100B8800DCE0E9D7040138510A0AEDE0100AF0E088 -:100B9800F00AF3E0E0D70401376F020E086E040193 -:100BA80037510401376F000E016E0401375190D0A0 -:100BB80036C43AF435C439F439EC14F039C41BF4AA -:100BC8003AC41CF4040104011C29FE0ED8B41B19F4 -:100BD800D8A401D001D003D087EC17F079D0040154 -:100BE80004011B29D8B41C29D8A401D001D001D0F4 -:100BF8006FD00F0E0124E96EEA6A000EEA220401A2 -:100C08001BC4EFFF012A0206026601D001D05ED79D -:100C180087EC17F0C9EC17F0B40E04010401566F05 -:100C2800790E0401576FCE0E04010401546F790E3A -:100C38000401556F9AEC17F0BB0E04010401566FBE -:100C4800790E0401576F8C0E04010401546F790E5C -:100C58000401556F9AEC17F0040119C056F4040109 -:100C68001AC057F404010401586B0401596BC80EEB -:100C780004010401546F790E0401556F02EC0EF063 -:100C880001C049F40F0E04010401476F000E04016E -:100C9800486FE30E04010401456F790E0401466FA5 -:100CA80033EC0FF00401376F010E04010401546F97 -:100CB80004013751BBEC17F00BD00850000A01E1D2 -:100CC800D2D6010A01E103D7030A01E171D700D0A6 -:100CD8001200000E04010401386F000E0401396F80 -:100CE800000E04013A6F000E04013B6F010E04016F -:100CF80004013C6F000E04013D6F000E04013E6FBD -:100D0800000E04013F6F0401370E040104015D6FFA -:100D18000401040E04015E6F0401350E0401040190 -:100D28005B6F0401040E04015C6F2FEC16F00401E4 -:100D3800370E04010401566F0401040E0401576FB5 -:100D48000401350E04010401546F0401040E04016A -:100D5800556FE1EC10F0000E04010401406F000E25 -:100D68000401416F040104014151800A800F200EE3 -:100D7800D8B4405DD8A001D001D001D0A1D00401E1 -:100D8800370E04010401566F0401040E0401576F65 -:100D98000401350E04010401546F0401040E04011A -:100DA800556FE1EC10F004010401426F0401370EA5 -:100DB80004010401566F0401040E0401576F040175 -:100DC800350E04010401546F0401040E0401556F2B -:100DD800E1EC10F004010401436F0401370E040133 -:100DE8000401566F0401040E0401576F0401350E07 -:100DF80004010401546F0401040E0401556FE1EC71 -:100E080010F004010401446F0401370E04010401C9 -:100E1800566F0401040E0401576F0401350E0401D6 -:100E28000401546F0401040E0401556FE1EC10F045 -:100E380004010401456F1BD029D0040104013C5171 -:100E4800040104013813040104013D5104010401A3 -:100E58003913040104013E51040104013A13040149 -:100E680004013F51040104013B1310D067D045C46D -:100E78004AF444C449F443C448F442C447F40BEC6C -:100E880015F0000AD9E0010AD8E0F0D70401D8909B -:100E980004013C3704013D3704013E3704013F3764 -:100EA80004010401404B412B040104014151800A13 -:100EB800800F200ED8B4405DD8A001D001D05FD7F4 -:100EC800C9EC17F09E0E04010401566F790E040157 -:100ED800576F8C0E04010401546F790E0401556F8D -:100EE8009AEC17F0570E04010401566F790E0401AD -:100EF800576FC80E04010401546F790E0401556F31 -:100F08009AEC17F038C456F439C457F43AC458F474 -:100F18003BC459F4E30E04010401546F790E040133 -:100F2800556F02EC0EF00401466F020E0401040135 -:100F3800546F04014651BBEC17F000D012000401B5 -:100F4800346F000E04010401316F04013451A0D044 -:100F58002EC45DF417C05BF418C05CF48BEC16F07B -:100F6800D8A001D001D02AD0960E0E6401D001D0AD -:100F780006D017C02CF418C02DF42EC42FF40E5030 -:100F8800D8B401D001D00CD00EC036F40401346FAF -:100F9800000E04010401356F0401345126EC05F0FC -:100FA800042A0401346F000E0E6E0401345104014A -:100FB800346F000E056E0401345122D00E6601D044 -:100FC80001D006D017C02AF418C02BF42EC41FF481 -:100FD8000450D8B401D001D00CD004C036F40401B8 -:100FE800346F010E04010401356F0401345126ECFD -:100FF80005F00E2A0401346F000E046E040134510A -:101008000401D8902E33040104012E6701D001D0C9 -:1010180015D00401346F800E040104012E6F040101 -:101028003451174A182A1850020A1710D8A401D0A8 -:1010380001D004D0000E176E000E186E185004016F -:1010480004012D1904E11750040104012C19D8A436 -:1010580001D001D00ED0040104012E510401040175 -:101068002F6301D001D005D0040104012C690401CB -:101078002D690E50960AD8A401D001D009D00401D8 -:10108800346F010E04010401316F040134510DD095 -:10109800040104012151181804E10401040120513C -:1010A8001718D8A401D001D053D70401040131671F -:1010B80001D001D001D078D00550D8B401D001D0EA -:1010C80001D072D02AC437F42BC438F42CC435F4B8 -:1010D8002DC436F4A9EC12F035C432F436C433F416 -:1010E8000401040133BF01D001D00DD00401040173 -:1010F8003351800A800F320ED8B4325DD8B001D097 -:1011080001D001D051D0040104013351800A800F6D -:101118009E0ED8B4325DD8A001D001D00CD0040105 -:1011280004013351800A800FA30ED8B4325DD8A0D1 -:1011380001D001D000D01FC437F42AC435F42BC421 -:1011480036F46DEC06F01FC437F42AC435F42BC40A -:1011580036F409EC0AF01FC437F42AC435F42BC45A -:1011680036F43EEC0CF01FC437F42AC435F42BC413 -:1011780036F42CEC0BF01FC437F42AC435F42BC416 -:1011880036F4AFEC03F01FC437F42AC435F42BC48B -:1011980036F445EC00F087EC17F00401346F010ECB -:1011A800056E0401345100D012000401356F0B0E96 -:1011B80004010401326F040135510401356F0A0E30 -:1011C80004010401336F04013551010E04010401C7 -:1011D8003B6F000E04013C6FFD0E04010401396FE2 -:1011E800790E04013A6F1B0E04010401376F000EDB -:1011F8000401386FFFEC12F0040138513711D8A4FC -:1012080001D001D011D0050E04010401636F000E56 -:101218000401646F850E04010401616F790E0401F5 -:10122800626F0FEC02F0F0D0010E040104013B6F75 -:10123800000E04013C6FFB0E04010401396F790EA6 -:1012480004013A6F1B0E04010401376F000E0401FC -:10125800386FFFEC12F0040138513711D8A401D0CF -:1012680001D00AD0D40E04010401616F790E040183 -:10127800626F0FEC02F0C8D00401356F000E040154 -:101288000401346F040135510401356F000E040167 -:101298000401316F04013551B0D098D0040134C431 -:1012A80035F40401366B010E04013527000E362390 -:1012B8001B0E04013525E96E000E04013621EA6E85 -:1012C800EF5004010401326F04010401342B92D061 -:1012D800040134C435F40401366B010E04013527CA -:1012E800000E36231B0E04013525E96E000E04019D -:1012F8003621EA6EEF5004010401336F0401040142 -:10130800342B78D033C43AF432C439F4010E0401D2 -:101318000401342504010401376F0401386B000E01 -:101328000401382351EC12F00401356F010E040159 -:101338000401316F04013551D90E04010401616FB4 -:10134800790E0401626F0FEC02F054D033C43AF402 -:1013580032C439F4010E04010401342504010401E6 -:10136800376F0401386B000E04013823F9EC11F0D3 -:101378000401356F010E04010401316F0401355178 -:10138800DE0E04010401616F790E0401626F0FEC37 -:1013980002F030D01B0E040104013425E96EEA6A1C -:1013A800000EEA22EF500401356F040135510401A3 -:1013B8000401636F0401646B0E0E04010401616F84 -:1013C800790E0401626F0FEC02F01ED01B0E0401AF -:1013D80004013425E96EEA6A000EEA22EF50500A49 -:1013E80001E15CD7020A01E173D7010A8BE0070A21 -:1013F800ADE0D0D704010401342B040104013151BC -:10140800D8B401D001D049D71200000E040104015C -:101418003C6F000E04013D6F000E04013E6F000E8C -:1014280004013F6F010E04010401386F000E04012E -:10143800396F000E04013A6F000E04013B6F04017E -:10144800370E040104015D6F0401040E04015E6F90 -:101458000401350E040104015B6F0401040E04014C -:101468005C6F2FEC16F00401370E04010401566F6F -:101478000401040E0401576F0401350E0401040130 -:10148800546F0401040E0401556FE1EC10F0000ED6 -:1014980004010401406F000E0401416F04010401BE -:1014A8004151800A800F0C0ED8B4405DD8A001D0FD -:1014B80001D001D08ED00401370E04010401566F0B -:1014C8000401040E0401576F0401350E04010401E0 -:1014D800546F0401040E0401556FE1EC10F004018F -:1014E8000401426F0401370E04010401566F040120 -:1014F800040E0401576F0401350E04010401546FF2 -:101508000401040E0401556FE1EC10F0040104011C -:10151800436F0401370E04010401566F0401040EE1 -:101528000401576F0401350E04010401546F0401CE -:10153800040E0401556FE1EC10F004010401446F3E -:101548000401370E04010401566F0401040E04015E -:10155800576F0401350E04010401546F0401040E91 -:101568000401556FE1EC10F004010401456F04011A -:10157800D89004013C3704013D3704013E3704018B -:101588003F3706D016D0040104013C8112D05FD049 -:1015980045C44AF444C449F443C448F442C447F433 -:1015A800CCEC14F0000AEEE0010AEDE0030AEFE0EB -:1015B80000D004010401404B412B040104014151B6 -:1015C800800A800F0C0ED8B4405DD8A001D001D09D -:1015D80072D7C9EC17F09E0E04010401566F790EFC -:1015E8000401576F8C0E04010401546F790E040135 -:1015F800556F9AEC17F0640E04010401566F790ECA -:101608000401576FC80E04010401546F790E0401D8 -:10161800556F9AEC17F03CC456F43DC457F43EC4D9 -:1016280058F43FC459F4E30E04010401546F790ED1 -:101638000401556F02EC0EF00401466F020E04011E -:101648000401546F04014651BBEC17F000D012009E -:10165800000E04010401386F000E0401396F000EFA -:1016680004013A6F000E04013B6F010E04010401EE -:101678003C6F000E04013D6F000E04013E6F000E2A -:1016880004013F6F0401370E040104015D6F04017A -:10169800040E04015E6F0401350E040104015B6F42 -:1016A8000401040E04015C6F2FEC16F0000E040117 -:1016B8000401406F000E0401416F0401040141510F -:1016C800800A800F180ED8B4405DD8A001D001D090 -:1016D80001D0A1D00401370E04010401566F0401A2 -:1016E800040E0401576F0401350E04010401546F00 -:1016F8000401040E0401556FE1EC10F0040104012B -:10170800426F0401370E04010401566F0401040EF0 -:101718000401576F0401350E04010401546F0401DC -:10172800040E0401556FE1EC10F004010401436F4D -:101738000401370E04010401566F0401040E04016C -:10174800576F0401350E04010401546F0401040E9F -:101758000401556FE1EC10F004010401446F040129 -:10176800370E04010401566F0401040E0401576F7B -:101778000401350E04010401546F0401040E040130 -:10178800556FE1EC10F004010401456F1BD029D01E -:10179800040104013C51040104013813040104014B -:1017A8003D51040104013913040104013E510401AF -:1017B80004013A13040104013F51040104013B13DD -:1017C80010D057D045C44AF444C449F443C448F43B -:1017D80042C447F44AEC15F0000AD9E0010AD8E0FF -:1017E800F0D70401D89004013C3704013D370401C7 -:1017F8003E3704013F3704010401404B412B0401EB -:1018080004014151800A800F180ED8B4405DD8A059 -:1018180001D001D05FD7C9EC17F04A0E04010401CA -:10182800566F790E0401576F8C0E04010401546F32 -:10183800790E0401556F9AEC17F038C456F439C480 -:1018480057F43AC458F43BC459F4E30E04010401B4 -:10185800546F790E0401556F02EC0EF00401466FC7 -:10186800020E04010401546F04014651BBEC17F049 -:1018780000D012000401370E040104015D6F040159 -:10188800040E04015E6F0401350E040104015B6F50 -:101898000401040E04015C6F2FEC16F0040E040121 -:1018A80004013D6F000E04013E6F040104013EAFC8 -:1018B80001D001D001D07ED00401436F000E040195 -:1018C80004013F6F04014351000E04010401406FFD -:1018D800000E0401416F040104014151800A800F88 -:1018E800080ED8B4405DD8A001D001D001D04AD0AC -:1018F8000401370E04010401476F0401040E0401BA -:10190800486F0401350E04010401456F0401040EFB -:101918000401466F89EC15F004010401426F0401CB -:1019280004014251020AD8A401D001D001D088D0C4 -:10193800040104014251D8B401D001D013D040C4ED -:1019480043F4010E0401446F0401432B03D0D890E3 -:10195800040144370401432FFAD704014451040118 -:1019680004013F1304010401404B412B040104010D -:101978004151800A800F080ED8B4405DD8A001D02C -:1019880001D0B6D70401380E040104013D25E96EE3 -:10199800EA6A0401040EEA2204013FC4EFFF0401CD -:1019A80004013D07D8A03E07040104013EAF01D061 -:1019B80001D082D7C9EC17F0B40E04010401566FA8 -:1019C800790E0401576FCE0E04010401546F790E8D -:1019D8000401556F9AEC17F06F0E04010401566F5D -:1019E800790E0401576F8C0E04010401546F790EAF -:1019F8000401556F9AEC17F00401436F050E0401BA -:101A08000401496F040143510401380E0401040123 -:101A1800476F0401040E0401486FE30E040104013A -:101A2800456F790E0401466F33EC0FF00401436FE4 -:101A3800010E04010401546F04014351BBEC17F07B -:101A4800120004014C6F000E04010401496F0401E7 -:101A58004C51030E04010401496501D001D001D0A5 -:101A680023D0040104014951040104013F25E96E12 -:101A78000401000E040104014021EA6E0401450E30 -:101A8800040104014925E16EE26A0401040EE22220 -:101A9800EFCFE7FF04010401492B030E0401040101 -:101AA800496501D001D0DDD7050E040104013F25A9 -:101AB80004014C6F000E04010401402104014D6F24 -:101AC8004CC443F44DC444F40096000E0C6E0094CC -:101AD800040100EE04F004013F51E92604014051DD -:101AE800EA22EF5004010401426F04010401426735 -:101AF80001D001D001D081D004010401426701D096 -:101B080001D001D072D043C4E9FF44C4EAFFEF50CA -:101B180004010401416F04014C6F000E040104012B -:101B28004A6F04014C51030E040104014A6501D0B7 -:101B380001D001D050D041C44CF4C00E04014C1760 -:101B4800060E04014D6FD89004014C3304014D2F4B -:101B5800FAD704014C51040104014B6F0401450EEE -:101B6800040104014B25E96EEA6A0401040EEA2225 -:101B7800010EEF6201D001D002D0008613D004011B -:101B8800450E040104014B25E96EEA6A0401040EBE -:101B9800EA22EF500D6EB18000D000A401D001D030 -:101BA800FCD700940401D8904137D89041370401FC -:101BB8000401420704010401426701D001D001D0A9 -:101BC8000AD0040104014A2B030E040104014A65EA -:101BD80001D001D0B0D704010401434B442B0401C8 -:101BE8000401426701D001D08ED7009400D000A430 -:101BF80001D001D0FCD7B1908998120054C463F485 -:101C080055C464F4C20E04010401616F790E040125 -:101C1800626F0FEC02F00401595156115711581117 -:101C2800D8A401D001D00AD0F30E04010401616FD9 -:101C3800790E0401626F0FEC02F071D004015D6F40 -:101C4800010E040104015A6F04015D5104015D6F26 -:101C5800000E040104015B6F04015D51070E0401CD -:101C680004015B6501D001D001D059D0040156C4EC -:101C78005DF4040157C45EF4040158C45FF4040120 -:101C880059C460F41D0E06D0D890040160335F3348 -:101C98005E335D33E82EF8D704015D510F0B040164 -:101CA80004015C6F040104015C6701D001D008D015 -:101CB800040104015A05D8A401D001D001D018D0DC -:101CC800040104015CC463F404010401646BEA0EBA -:101CD80004010401616F790E0401626F0FEC02F0D8 -:101CE80004015D6F000E040104015A6F04015D5187 -:101CF8000401040ED8900401563704015737040133 -:101D0800583704015937E82EF5D7040104015B2B35 -:101D1800070E040104015B6501D001D0A7D79C0E12 -:101D280004010401616F790E0401626F0FEC02F087 -:101D38001200036601D001D017D0030E040104017C -:101D48003E6501D001D007D00C0E040104013E65A8 -:101D580001D001D002D0FE0E81D004013F6F010EE8 -:101D6800036E04013F5178D00304D8A401D001D0F8 -:101D780026D00B0E040104013E6501D001D007D026 -:101D8800160E040104013E6501D001D008D00401FB -:101D98003F6F000E036E04013F51FE0E5FD00090AE -:101DA800040104013DA101D0008004013F6F020E2F -:101DB800036E04013F51000E00B0010E4FD00350D6 -:101DC800020AD8A401D001D047D0040104013D5132 -:101DD800D8B401D001D015D0030E040104013E652A -:101DE80001D001D00ED00D0E040104013E6101D0D6 -:101DF80001D007D004013F6F000E036E04013F516C -:101E080029D00B0E040104013E6501D001D00ED08B -:101E1800170E040104013E6101D001D007D004016E -:101E28003F6F010E036E04013F5114D0030E0401ED -:101E380004013E6501D001D00DD00D0E040104014E -:101E48003E6101D001D006D004013F6F000E036E41 -:101E580004013F51FF0E02D0FF0E00D0120045C40E -:101E680063F446C464F4ED0E04010401616F790E55 -:101E78000401626F0FEC02F004014B6F000E0401C5 -:101E880004014A6F04014B51040104014951040142 -:101E980004014A5DD8A001D001D001D04BD0040183 -:101EA80004014A51040104014725E96E0401000EAA -:101EB800040104014821EA6EEF5004014B6F0F0E34 -:101EC80004014B1704014B5104010401656F04011F -:101ED800666B040104014A51040104014725E96EB7 -:101EE8000401000E040104014821EA6EEF500401C8 -:101EF8004C6F04014C3B0F0E4C1704014C5104016C -:101F08000401636F0401646BE80E04010401616F4E -:101F1800790E0401626F0FEC02F0040104014A2BF0 -:101F2800040104014951040104014A5DD8A001D00B -:101F380001D0B5D79C0E04010401616F790E04012C -:101F4800626F0FEC02F012000401D8901D370401F3 -:101F580004019951D8B401D001D01BD00401040167 -:101F68001E2B040104011E51030AD8A401D001D07C -:101F780005D0070E040104011D130AD0030E040145 -:101F880004011E6501D001D003D0040104011D81A4 -:101F980008D004019A6F000E040104011E6F0401A9 -:101FA8009A510401D890223704010401232B04011B -:101FB80004011DAF01D001D004D004010401228125 -:101FC80000D0040104012351080AD8A401D001D08B -:101FD80029D004019A6F000E04010401236F040143 -:101FE8009A511B0E040104012025E96E020E04011A -:101FF80004012121EA6E040122C4EFFF0401040157 -:10200800204B212B040104012151020A2011D8A4DC -:1020180001D001D007D0000E04010401206F000E8A -:102028000401216F1200040104012651D8B401D023 -:1020380001D024D0040104012551040104012427FE -:102048007E0E04010401246501D001D004D00401EE -:102058000401256911D004010401246701D001D0CD -:102068000BD004018A6F010E04010401256F0401DD -:102078008A5104010401260724C4BEFF0401040197 -:102088002951D8B401D001D024D004010401285129 -:102098000401040127277E0E04010401276501D0ED -:1020A80001D004D004010401286911D004010401FD -:1020B800276701D001D00BD004018A6F010E0401FB -:1020C8000401286F04018A5104010401290727C467 -:1020D800BBFF04010401266701D001D002D0000E25 -:1020E800BE6E04010401296701D001D002D0000EA0 -:1020F800BB6E12000096000E0C6E00943FC4E9FF00 -:1021080040C4EAFFEF500D6EB18000D000A401D0AA -:1021180001D0FCD7010E04010401416F000E040137 -:10212800426F2FD0040104014151040104013F25ED -:10213800E96E040104014251040104014021EA6EE0 -:10214800010EEF6201D001D002D0008616D00094B3 -:10215800040104014151040104013F25E96E040111 -:1021680004014251040104014021EA6EEF500D6E52 -:1021780000D000A401D001D0FCD704010401414BD8 -:10218800422B040104014151040104013F25E96E79 -:10219800040104014251040104014021EA6EEF5098 -:1021A800D8A401D001D0BED7009400D000A401D09B -:1021B80001D0FCD7B1908998120004015A6F000E23 -:1021C80004010401596F04015A5156C4E9FF57C468 -:1021D800EAFFEF50040104015D6F54C4E9FF55C4E0 -:1021E800EAFF0401EECF5BF40401EDCF5CF48BEC65 -:1021F80016F0D8B001D002D0010E01D0000E0401B3 -:102208000401586F04010401592B56C45DF457C4E6 -:102218005EF454C45BF455C45CF42FEC16F056C459 -:10222800E9FF57C4EAFFEF50040104015D6F54C48D -:10223800E9FF55C4EAFF0401EECF5BF40401EDCFDA -:102248005CF48BEC16F0D8B001D002D0010E01D0AE -:10225800000E040104015819D8B401D001D004D0EB -:102268000401040159510AD0040104015929D8A4D0 -:1022780001D001D002D0000E01D0C4D71200000E48 -:1022880004010401776F000E0401786F0401040152 -:1022980075517411D8B401D001D047D00401796FB9 -:1022A800010E04010401766F0401795109D004017B -:1022B800D890040174370401753704010401762BA2 -:1022C8000401040175AF01D001D0F1D70401D89001 -:1022D80004017737040178370401040174510401BB -:1022E8000401725D0401040175510401040173596C -:1022F800D8A001D001D00FD0040104017451040109 -:102308000401725F04010401755104010401735B47 -:102318000401040177810401D89004017533040194 -:10232800743304010401762FD1D777C472F478C4CA -:1023380073F400D01200000EAB6EAB8EAB88AC907D -:10234800AC8AAC94B896948E949C06D00401AECF17 -:1023580031F404010401326B9EBA01D001D0F6D7E2 -:102368000401336F400EAF6E040133519F9A9F985A -:10237800F28C9D8A9D98CD909E90000ECF6E000E97 -:10238800CE6ECD9ACD98CD92000E04010401386F1F -:10239800020E0401396F000E04010401366F000EAD -:1023A8000401376F1B0E04010401346F000E040191 -:1023B800356F19EC17F0000E04010401386F010E97 -:1023C8000401396F2D0E04010401366F000E04015B -:1023D800376F0501000E04010401346F0501050E75 -:1023E8000401356F19EC17F01200E6EC17F0040140 -:1023F8003D6F000E040104013B6F04013D5140D0C4 -:1024080004013D6F020E040104013F6F04013D51B8 -:10241800EAEC17F01B0E04013D6F000E3E6F04013D -:102428000401375104013D27040104013851040116 -:102438003E233DC43FF43EC440F425EC0DF00401B6 -:102448003D6F000E040104013C6F04013D510BD0A7 -:102458000D0E04013D6FF90EE82EFED73D2FFCD777 -:10246800040104013C2B0401040139510401040155 -:102478003C5DD8A001D001D0EBD7040104013B2B6F -:10248800040104013A51040104013B5DD8A001D0C4 -:1024980001D0B6D7DCEC17F01200E6EC17F0040117 -:1024A8003D6F000E040104013B6F04013D5140D013 -:1024B80004013D6F020E040104013F6F04013D5108 -:1024C800EAEC17F01B0E04013D6F000E3E6F04018D -:1024D8000401375104013D27040104013851040166 -:1024E8003E233DC43FF43EC440F47EEC10F00401AA -:1024F8003D6F000E040104013C6F04013D510BD0F7 -:102508000D0E04013D6FF90EE82EFED73D2FFCD7C6 -:10251800040104013C2B04010401395104010401A4 -:102528003C5DD8A001D001D0EBD7040104013B2BBE -:10253800040104013A51040104013B5DD8A001D013 -:1025480001D0B6D7DCEC17F01200040104013529DC -:10255800D8B43629D8A401D001D006D0040104018A -:1025680035690401366946D0040104013851800AEE -:102578000401396F0401355104010401375D040178 -:1025880004013651800A04013959D8A001D001D07C -:1025980012D004010401355104010401375D04011E -:1025A8000401356F0401040136510401040138594E -:1025B8000401366F1FD0000E0401396F020E3A6F06 -:1025C8000401040135510401395F04010401365145 -:1025D80004013A5B0401040137510401392504015F -:1025E8000401356F04010401385104013A21040142 -:1025F800366F00D012003ED037C4E9FF38C4EAFF76 -:10260800EF50D8B401D001D014D0040139C4F6FF7A -:1026180004013AC4F7FF0800F5CF3DF437C4E9FFD9 -:1026280038C4EAFFEF5004013D19D8B401D001D0F5 -:1026380019D037C4E9FF38C4EAFFEF5004013D6FF1 -:10264800040139C4F6FF04013AC4F7FF0800F55045 -:1026580004013D5D04010401376F0401386BD8A003 -:1026680038071DD004010401374B382B040104013D -:10267800394B3A2B040104013B07D8A03C0704015D -:102688003B29D8B43C29D8A401D001D0B5D7000E35 -:1026980004010401376F000E0401386F00D01200E6 -:1026A800FACF7DF4FBCF7EF4E9CF7FF4EACF80F454 -:1026B800E1CF81F4E2CF82F4D9CF83F4DACF84F486 -:1026C800F3CF85F4F4CF86F4F6CF87F4F7CF88F408 -:1026D800F8CF89F49EAA01D001D002D0C6EC15F03B -:1026E8009EA801D001D002D05EEC16F09EA201D0C7 -:1026F80001D003D017EC10F09E9289C4F8FF88C46B -:10270800F7FF87C4F6FF86C4F4FF85C4F3FF84C4CB -:10271800DAFF83C4D9FF82C4E2FF81C4E1FF80C429 -:10272800EAFF7FC4E9FF7EC4FBFF7DC4FAFF7CC4D7 -:10273800E0FF7BC4E8FF7AC4D8FF1000040104015D -:1027480075517411D8B401D001D03ED00401776F0F -:10275800010E04010401766F0401775109D00401C8 -:10276800D890040174370401753704010401762BED -:102778000401040175AF01D001D0F1D704010401AF -:10278800745104010401725D0401040175510401CE -:1027980004017359D8A001D001D00CD00401040160 -:1027A800745104010401725F0401040175510401AC -:1027B8000401735B0401D890040175330401743378 -:1027C80004010401762FDAD772C472F473C473F467 -:1027D80000D012004FC456F450C457F44DC454F4FA -:1027E8004EC455F4E1EC10F004010401526F130ECD -:1027F80004010401526501D001D009D0290E040159 -:102808000401526101D001D002D0000E2DD04FC476 -:1028180056F450C457F44DC454F44EC455F4E1EC86 -:1028280010F004010401516F010E04010401526506 -:1028380001D001D017D0150E04010401526101D056 -:1028480001D010D0010E04010401516501D001D05E -:1028580009D0150E04010401516101D001D002D044 -:10286800010E02D0020E00D012003AC43EF439C460 -:102878003DF49DEC0EF0040104013B6F04010401DA -:102888003B51FE0AD8A401D001D008D0FE0E0401A5 -:102898000401396FFF0E04013A6F30D004010401BE -:1028A8003B29D8A401D001D006D00401040139691C -:1028B80004013A6923D0D8900632040104013B513F -:1028C800D8B401D001D001D0068E0B2A080E0B60B7 -:1028D80001D001D006D004010401396904013A6924 -:1028E8000DD004013C6F000E0B6E04013C51040135 -:1028F80006C039F4040104013A6B00D01200060046 -:10290800EACF8FF4E1CF90F4E2CF91F4D9CF92F4EB -:10291800DACF93F4F3CF94F4F4CF95F4F6CF96F49A -:10292800F7CF97F4F8CF98F4F2A401D001D00BD0E8 -:10293800000E81B8010E04010401996FA8EC0FF094 -:10294800000ED66EF294A1A201D001D006D0B368D1 -:10295800C90EB26E72EC17F0A19298C4F8FF97C432 -:10296800F7FF96C4F6FF95C4F4FF94C4F3FF93C42D -:10297800DAFF92C4D9FF91C4E2FF90C4E1FF8FC48B -:10298800EAFF8EC4E9FF8DC4FBFF8CC4FAFF110077 -:102998000F0E04010401476501D001D017D00A0EBB -:1029A80004010401486101D001D010D00F0E0401C8 -:1029B8000401496501D001D009D00A0E04010401BF -:1029C8004A6101D001D002D0000E20D00A0E0401C5 -:1029D8000401476101D001D017D00F0E0401040192 -:1029E800486501D001D010D00F0E040104014965DB -:1029F80001D001D009D00A0E040104014A6101D0B6 -:102A080001D002D0010E02D0020E00D012000F0E2B -:102A180004010401476501D001D017D00A0E040152 -:102A28000401486101D001D010D00A0E040104014C -:102A3800496101D001D009D00A0E040104014A619C -:102A480001D001D002D0000E20D00A0E04010401EA -:102A5800476101D001D017D00A0E04010401486172 -:102A680001D001D010D00F0E04010401496501D036 -:102A780001D009D00A0E040104014A6101D001D035 -:102A880002D0010E02D0020E00D012000D0E040179 -:102A98000401476101D001D017D00D0E04010401D3 -:102AA800486101D001D010D00D0E04010401496124 -:102AB80001D001D009D0100E040104014A6501D0EB -:102AC80001D002D0010E20D00D0E0401040147618F -:102AD80001D001D017D0100E04010401486501D0BF -:102AE80001D010D00D0E04010401496101D001D0BC -:102AF80009D00D0E040104014A6101D001D002D0B1 -:102B0800000E02D0020E00D0120047C456F448C48A -:102B180057F445C454F446C455F4E1EC10F00401EC -:102B28000401496F47C456F448C457F445C454F4E3 -:102B380046C455F4E1EC10F0040104014A6F0D0E8F -:102B480004010401496501D001D009D00D0E04012A -:102B580004014A6501D001D002D0000E12D00A0E3D -:102B680004010401496101D001D009D00D0E04010E -:102B780004014A6501D001D002D0010E02D0020E34 -:102B880000D01200AECF8AF4ABA201D001D002D09F -:102B9800AB98AB8800A201D001D001D029D00401A4 -:102BA80004018A512B0AD8A401D001D00BD0CD90B2 -:102BB80000821B0E0724E96EEA6A000EEA22000E64 -:102BC800EF6E16D01B0E0724E96EEA6A000EEA22A1 -:102BD80004018AC4EFFF072A000ECF6E000ECE6EE6 -:102BE800CD809E9004018B6F000E0A6E04018B51FC -:102BF80012009EA001D001D00CD01E0E0A6401D094 -:102C080001D005D0CD90000E076E009201D00A2A9F -:102C18009E9000B201D001D001D01CD0D9EC08F0B0 -:102C2800000E04010401386F020E0401396F000E12 -:102C380004010401366F000E0401376F1B0E0401F6 -:102C48000401346F000E0401356F19EC17F0000E03 -:102C5800076E009212005DC4E9FF5EC4EAFFD890D7 -:102C6800EF365DC4E9FF5EC4EAFFEF50D8A401D097 -:102C780001D01FD05DC4E9FF5EC4EAFF010EEF6E0C -:102C88005BC4E9FF5CC4EAFFEE50ED10D8A401D0A4 -:102C980001D008D05BC4E9FF5CC4EAFF000EEE6E09 -:102CA800020EED6E5BC4E9FF5CC4EAFFEE06000E9F -:102CB800ED5A120030C48AF4040104018A29D8A408 -:102CC80001D001D009D004018B6F000E040104016A -:102CD8008A6F04018B5103D0040104018A2B095027 -:102CE800040104018A6301D001D002D09D980ED05E -:102CF8000501000E040104018A25E96EEA6A05014E -:102D0800050EEA22EF50AD6E8AC430F412001B0E95 -:102D1800040104015B25E96E020E040104015C2133 -:102D2800EA6EEF50040104015E6F040104015E5174 -:102D380004015DC45FF40401606B5FBF60070401B8 -:102D48005F17000E6017040160515F11D8B401D0FD -:102D580001D002D0D88002D0D89000D012000D0E39 -:102D680004010401546101D001D009D00D0E040101 -:102D78000401556101D001D002D0000E12D0180E06 -:102D880004010401546501D001D009D00D0E0401DD -:102D98000401556101D001D002D0010E02D0020E0B -:102DA80000D01200F9EC16F0E1EC17F09FEC11F0EE -:102DB800ACEC17F0D3EC17F057EC17F0050E040144 -:102DC8000401636F000E0401646F830E04010401A3 -:102DD800616F790E0401626F0FEC02F0A3EC07F04B -:102DE800FDEC15F0FBD714EF00F0000EC26E0401E5 -:102DF800316F0F0EC16E04013151070EB46E000E13 -:102E0800806E000E926E000E946E000E956E000E8F -:102E1800826E000E836E000E936E000E816E89988E -:102E28009298949294949296120034C43AF435C4C9 -:102E38003BF40BD03AC4E9FF3BC4EAFF040136C4B3 -:102E4800EFFF040104013A4B3B2B0401040138074E -:102E5800D8A0390704013829D8B43929D8A401D011 -:102E680001D0E8D700D0120000D0095004010401B5 -:102E78003019D8B401D001D0F8D70501000E0924C3 -:102E8800E96EEA6A0501050EEA22040172C4EFFF41 -:102E98000928D8A401D001D003D0000E096E01D0B2 -:102EA800092A9D881200CA82CA9CCA8ACA98CA96E8 -:102EB800000EBD6E000EBA6EBA86BA84BD86BD8499 -:102EC800BD9ABD98BA9ABA98000EBE6E000EBB6E37 -:102ED8009E92CB689F929D82CA8412000C6601D094 -:102EE80001D00AD00DC00CF0008400B601D001D08A -:102EF80002D0897801D000960C50D8B401D001D006 -:102F080001D00C0612000401396F000E0B6E04018B -:102F180039510401396F000E036E0401395104015F -:102F2800396F000E086E04013951120056C465F459 -:102F380057C466F454C463F455C464F4AD0E040174 -:102F48000401616F790E0401626F0FEC02F0120048 -:102F5800D594D592D590D596D59AD58CF294F28AF7 -:102F680092969388F184D58EEDEC17F01200220E1C -:102F780004010401616F790E0401626F0FEC02F025 -:102F880054C455F4F3EC17F01200F50E04010401D3 -:102F9800616F790E0401626F0FEC02F012009294D7 -:102FA80092988998B19AB198A082A282B1901200A1 -:102FB800EDEC17F0D58EB1901200D08EF28EF28C17 -:102FC800F28E1200D59EF0EC17F012003FC429F4DF -:102FD800120089948986120089848996120055C442 -:042FE80026F41200B9 -:1078FC0001000A006400E8031027010010000001D9 -:10790C000010556E6B6E6F776E20636F6D6D616ED0 -:10791C006420282575290D0A0074656D70657261E7 -:10792C007475726568756D6964697479003031328B -:10793C003334353637383941424344454600657651 -:10794C006572666C6F75726973680073656C666CD2 -:10795C006561726E696E6700636F646573776974D5 -:10796C0063680066696E656F6666736574006D6149 -:10797C006E646F6C796E000D0A2B5625750D0A001E -:10798C0070726F746F636F6C0025733A3078255882 -:10799C003B006172637465636800286E756C6C29BA -:1079AC000025733A25733B0073656E736F72006F1D -:1079BC007265676F6E0025733A3078006D6F646581 -:1079CC006C00636C617373002B4E0D0A002B530D0E -:1079DC000A002B540D0A0064617461002558255867 -:1079EC000025733A00783130002B57002B52004E93 -:0479FC000056000031 +:10007800F8E1120074656D70657261747572656877 +:10008800756D696469747900010000000001000061 +:100098000100FFFFF3FFFFFF80FFFF0085D1040190 +:1000A80004015F51D8B401D001D014D04C0E040122 +:1000B8000401606501D001D00DD0520E0401040185 +:1000C800606101D001D006D00401716F010E0F6E7E +:1000D800040171517DD1190E04010401606501D03C +:1000E80001D00ED01E0E04010401606101D001D0C0 +:1000F80007D00401716F030E0F6E0401715168D1AE +:10010800270E04010401606501D001D00ED02C0E29 +:1001180004010401606101D001D007D00401716FAE +:10012800040E0F6E0401715153D1FFEC1AF050D137 +:10013800180E04010401606501D001D0F6D71D0E28 +:1001480004010401606101D001D0EFD70401716F8F +:10015800050E0F6E040171513BD1030E0401040119 +:10016800606501D001D0E1D7090E04010401606186 +:1001780001D001D0DAD70401716F070E0F6E0401A8 +:10018800715126D10E6601D001D02DD0010E040187 +:100198000401606501D001D00ED0050E04010401F0 +:1001A800606101D001D007D00401716F010E0E6E9D +:1001B800040171510DD1040E04010401606501D0E0 +:1001C80001D00ED0080E04010401606101D001D0F5 +:1001D80007D00401716F020E0E6E04017151F8D040 +:1001E800FFEC1AF0F5D00E04D8A401D001D023D02A +:1001F800040E04010401606501D001D096D7080EF1 +:1002080004010401606101D001D08FD70401716F2E +:10021800000E0E6E04017151040104012D4B2E2BAA +:100228000401D890040147370401483704014937CD +:1002380004014A37CDD00E50020AD8A401D001D00B +:1002480027D0010E04010401606501D001D06DD7EB +:10025800050E04010401606101D001D066D70401D4 +:10026800716F000E0E6E04017151040104012D4BD3 +:100278002E2B04010401475109120401D8900401EE +:100288004737040148370401493704014A37A0D0E9 +:10029800FFEC1AF09DD00E6601D001D02DD0030ED0 +:1002A80004010401606501D001D00ED0090E0401DB +:1002B8000401606101D001D007D00401716F010E03 +:1002C8000E6E0401715184D0080E040104016065AA +:1002D80001D001D00ED0100E04010401606101D0DC +:1002E80001D007D00401716F020E0E6E0401715126 +:1002F8006FD0FFEC1AF06CD00E04D8A401D001D056 +:1003080023D0080E04010401606501D001D00DD787 +:10031800100E04010401606101D001D006D7040168 +:10032800716F000E0E6E04017151040104012D4B12 +:100338002E2B0401D89004014737040148370401E3 +:10034800493704014A3744D00E50020AD8A401D0D4 +:1003580001D027D0030E04010401606501D001D04B +:10036800E4D6090E04010401606101D001D0DDD694 +:100378000401716F000E0E6E040171510401040135 +:100388002D4B2E2B04010401475109120401D8906A +:1003980004014737040148370401493704014A3743 +:1003A80017D0FFEC1AF014D00F50000A01E177D6ED +:1003B800010A01E190D6020A01E1E4D6070A01E147 +:1003C800B7D6010A01E1C9D6020A01E164D700D013 +:1003D800040104012D51080A2E11D8A401D001D01E +:1003E8004DD0032A050E036001D001D033D0095047 +:1003F8001324136E000E1420146E000E1520156EB3 +:10040800000E1620166E040E036001D001D010D025 +:1004180013C072F414C073F415C074F40401716B42 +:1004280071C413F072C414F073C415F074C416F0D8 +:1004380009501724176E000E1820186E000E192088 +:10044800196E000E1A201A6E0401716F000E096EE3 +:1004580004017151000E040104012D6F000E040106 +:100468002E6F010E04010401476F000E0401486F4E +:10047800000E0401496F000E04014A6F0F50030A71 +:10048800D8A401D001D04ED00350040AD8A401D07A +:1004980001D048D013C061F414C062F415C063F4ED +:1004A80016C064F4FFEC1AF051EC1DF0BB0E040109 +:1004B8000401806F790E0401816F7E0E040104012E +:1004C8007E6F790E04017F6F22EC1DF0330E04015C +:1004D8000401806F790E0401816FC70E04010401C5 +:1004E8007E6F790E04017F6F22EC1DF061C480F4E9 +:1004F80062C481F463C482F464C483F4DD0E04012D +:1005080004017E6F790E04017F6F79EC13F004010A +:10051800716F010E040104017E6F0401715143ECF7 +:100528001DF0A4D00F50070AD8A401D001D09DD047 +:100538000350050AD8A401D001D097D0095004016E +:100548000401656F0401666B0401676B0401686B45 +:1005580017C069F418C06AF419C06BF41AC06CF4B7 +:1005680013C06DF414C06EF415C06FF416C070F4A7 +:10057800FFEC1AF004010401655104010401692526 +:100588000401716F040104016651040104016A2128 +:100598000401726F040104016751040104016B2115 +:1005A8000401736F040104016851040104016C2102 +:1005B8000401746FFF0E040171150401756F000EBC +:1005C800040172150401766F000E0401731504010D +:1005D800776F000E040174150401786F0401750526 +:1005E800761177117811D8B401D001D001D03ED05E +:1005F80051EC1DF0BB0E04010401806F790E04015B +:10060800816F7E0E040104017E6F790E04017F6FF5 +:1006180022EC1DF0240E04010401806F790E040100 +:10062800816FC70E040104017E6F790E04017F6F8C +:1006380022EC1DF06DC480F46EC481F46FC482F4A2 +:1006480070C483F4DD0E040104017E6F790E040189 +:100658007F6F79EC13F00401716F010E040104013E +:100668007E6F0401715143EC1DF000D012000401AB +:100678008D0E04010401946F0401040E0401956FAA +:10068800DFD1040104019351250AD8B401D001D067 +:1006980005D093C49CF4AEEC1CF0D2D104019A6F3F +:1006A800000E04010401926F04019A5161D0DBD15C +:1006B8007ED004010401928F7AD0040194C4E9FF2A +:1006C800040195C4EAFF0401020E04019427000EF8 +:1006D800040195230401EECF96F40401EDCF97F4BD +:1006E8000401040197519611D8A401D001D007D074 +:1006F8009F0E04010401966F790E0401976F1BD0B9 +:10070800040104019651F66EE96E050EEA6E0401C5 +:1007180004019751EA6403D0EA6EEF5003D0F76EF4 +:100728000800F550040104019C6FAEEC1CF00401B4 +:100738000401964B972B040104019651F66EE96E5D +:10074800050EEA6E040104019751EA6403D0EA6ECB +:10075800EF5003D0F76E0800F5500009D8A401D077 +:1007680001D0CED76DD1C00E0401040192131FD061 +:1007780004018BC4F6FF04018CC4F7FF04010401D3 +:100788008B4B8C2B08000401F5CF93F40401935193 +:10079800000A8DE0580A8DE03C0A8AE00D0A88E0DC +:1007A8001A0A8BE0060ADFE00D0A83E0DBD70401B2 +:1007B80004019251C00BD8A401D001D025D0040166 +:1007C80094C4E9FF040195C4EAFF0401020E040180 +:1007D8009427000E040195230401EECF96F404013A +:1007E800EDCF97F40401040197AF01D001D00BD0ED +:1007F800030E04010401921304010401966D04011F +:10080800971FD8B0972B13D0040194C4E9FF0401B3 +:1008180095C4EAFF0401020E04019427000E0401A6 +:1008280095230401EECF96F40401EDCF97F478D028 +:1008380004019A6F010E04010401936F04019A5197 +:10084800040104019351050AD8A401D001D001D0B4 +:100858002AD0040104019351020DEA0EF324F66E26 +:10086800F76A780EF7220900F5CF9AF40900F5CF58 +:100878009BF404019A5104010401965D04019B5103 +:10088800040104019759D8B001D001D001D00BD090 +:1008980004010401932B040104019351050AD8A40F +:1008A80001D001D0D6D748D004019A6F010E0401B7 +:1008B8000401936F04019A51040104019351040A3D +:1008C800D8A401D001D001D0EED70401040193517E +:1008D800020DF40EF324F66EF76A780EF72209007B +:1008E800F5CF9AF40900F5CF9BF404019A5104015D +:1008F8000401965D04019B51040104019759D8B085 +:1009080001D001D001D0CFD704010401932B0401F9 +:1009180004019351040AD8A401D001D0D6D70CD031 +:10092800040104019251C00B000A82E0800ABCE075 +:10093800400A01E17DD700D0040104019251030B64 +:10094800D8B401D001D00AD004019A6F2D0E040149 +:1009580004019C6F04019A51AEEC1CF093C491F40D +:1009680066D056D0040104019151020DEA0EF32419 +:10097800F66EF76A780EF72209000401F5CF9EF4A7 +:100988000A000401F5CF9FF496C49CF497C49DF423 +:1009980026EC16F09CC49CF49DC49DF40A0E040138 +:1009A80004019E6F000E04019F6FDAEC18F0040139 +:1009B80004019C51300F04010401936F34D00401E9 +:1009C80004019151020DF40EF324F66EF76A780EC5 +:1009D800F72209000401F5CF9EF40A000401F5CFBF +:1009E8009FF496C49CF497C49DF426EC16F00F0E61 +:1009F800040104019C17130E040104019C25F66EE2 +:100A0800F76A790EF72208000401F5CF93F40BD0AA +:100A1800040104019251C00B000AA4E0800ACFE04F +:100A2800400AA0E000D093C49CF4AEEC1CF0040192 +:100A38000401910704019129D8A401D001D091D7CC +:100A480004018BC4F6FF04018CC4F7FF0401040100 +:100A58008B4B8C2B08000401F5CF93F404019367AA +:100A680001D001D00ED600D01200000E04010401FE +:100A7800666F000E0401676F000E0401686F000EB8 +:100A88000401696F0401610E04010401876F040108 +:100A9800040E0401886F04015F0E04010401856FD0 +:100AA8000401040E0401866FA5EC1BF00401610E1D +:100AB80004010401806F0401040E0401816F040124 +:100AC8005F0E040104017E6F0401040E04017F6FB0 +:100AD800C4EC15F0010E04010401626F000E04015C +:100AE800636F000E0401646F000E0401656F000E51 +:100AF800040104016A6F000E04016B6F0401040114 +:100B08006B51800A800F200ED8B46A5DD8A001D03E +:100B180001D001D070D00401610E04010401806F7E +:100B28000401040E0401816F04015F0E0401040135 +:100B38007E6F0401040E04017F6FC4EC15F00401FC +:100B480004016C6F0401610E04010401806F04014B +:100B5800040E0401816F04015F0E040104017E6F1D +:100B68000401040E04017F6FC4EC15F004010401B4 +:100B78006D6F1CD026D004010401625104010401E8 +:100B8800661304010401635104010401671304019D +:100B9800040164510401040168130401040165514E +:100BA8000401040169130DD0000E2CD16DC47FF42B +:100BB8006CC47EF429EC1CF0000ADCE0010ADBE0DE +:100BC800F3D70401D89004016237040163370401A4 +:100BD800643704016537040104016A4B6B2B040177 +:100BE80004016B51800A800F200ED8B46A5DD8A02A +:100BF80001D001D090D7040166C46EF4040167C423 +:100C08006FF4040168C470F4040169C471F4040148 +:100C18006E1F6F1F701F711F110E06D0D890040130 +:100C2800713370336F336E33E82EF8D7FF0E04013B +:100C38006E150401726F000E04016F150401736FC5 +:100C4800000E040170150401746F000E0401711583 +:100C58000401756F040166C476F4040167C477F46F +:100C6800040168C478F4040169C479F4190E06D043 +:100C7800D89004017933783377337633E82EF8D770 +:100C8800FF0E0401761504017A6F000E0401771532 +:100C980004017B6F000E0401781504017C6F000EBF +:100CA8000401791504017D6F0401755104017D1952 +:100CB8000EE10401745104017C1909E10401735126 +:100CC80004017B1904E10401725104017A19D8B4B2 +:100CD80001D001D002D0000E95D0FF0E040166C4E9 +:100CE8006EF4040167C46FF4040168C470F404016D +:100CF80069C471F404016E1F6F1F701F711F040116 +:100D08006E150401726F000E04016F150401736FF4 +:100D1800000E040170150401746F000E04017115B2 +:100D28000401756FFF0E040166C476F4040167C4FC +:100D380077F4040168C478F4040169C479F477C4C9 +:100D480076F478C477F479C478F40401796B0401F3 +:100D5800761504017A6F000E0401771504017B6F84 +:100D6800000E0401781504017C6F000E040179154A +:100D780004017D6F0401755104017D190EE1040120 +:100D8800745104017C1909E10401735104017B19B0 +:100D980004E10401725104017A19D8B401D001D0D8 +:100DA80002D0000E2FD051EC1DF0F00E040104010A +:100DB800806F790E0401816F7E0E040104017E6F3D +:100DC800790E04017F6F22EC1DF066C480F467C4BD +:100DD80081F468C482F469C483F4DD0E040104015B +:100DE8007E6F790E04017F6F79EC13F004016E6F4A +:100DF800020E040104017E6F04016E5143EC1DF0E4 +:100E0800010E00D01200000E040104016A6F000EEA +:100E180004016B6F000E04016C6F000E04016D6F0E +:100E2800010E04010401666F000E0401676F000ED5 +:100E38000401686F000E0401696F000E04010401CB +:100E4800626F000E0401636F000E04010401646FF9 +:100E5800000E0401656F0401610E04010401876F2F +:100E68000401040E0401886F04015F0E04010401EB +:100E7800856F0401040E0401866FA5EC1BF00401C4 +:100E8800610E04010401806F0401040E0401816FE6 +:100E980004015F0E040104017E6F0401040E0401C5 +:100EA8007F6FC4EC15F0040104016551800A800FBE +:100EB800240ED8B4645DD8A001D001D001D018D1D7 +:100EC8000401610E04010401806F0401040E040191 +:100ED800816F04015F0E040104017E6F0401040E9A +:100EE80004017F6FC4EC15F0040104016E6F040166 +:100EF800610E04010401806F0401040E0401816F76 +:100F080004015F0E040104017E6F0401040E040154 +:100F18007F6FC4EC15F0040104016F6F0401610ECA +:100F280004010401806F0401040E0401816F0401AF +:100F38005F0E040104017E6F0401040E04017F6F3B +:100F4800C4EC15F004010401706F0401610E040182 +:100F58000401806F0401040E0401816F04015F0E17 +:100F6800040104017E6F0401040E04017F6FC4ECC8 +:100F780015F004010401716F7CD00401040165516E +:100F8800800A800F200ED8B4645DD8A001D001D0AB +:100F98001AD004016AC472F404016BC473F4040126 +:100FA8006CC474F404016DC475F4D89004017533ED +:100FB80074337333723372C46AF473C46BF474C4D5 +:100FC8006CF475C46DF465D0040104016551800AA0 +:100FD800800F200ED8B4645DD8A001D001D01AD0FB +:100FE80004016AC472F404016BC473F404016CC490 +:100FF80074F404016DC475F4D89004017533743326 +:101008007333723372C46AF473C46BF474C46CF4CB +:1010180075C46DF4040104016651040104016A13E6 +:10102800040104016751040104016B130401040164 +:101038006851040104016C1304010401695104019D +:1010480004016D1326D0040104016551800A800F44 +:101058001F0ED8B4645DD8A001D001D008D0010E0D +:1010680004010401626F000E0401636F12D0000EC8 +:101078007ED071C479F470C478F46FC477F46EC408 +:1010880076F405EC1AF0000A01E177D7010A9CE032 +:10109800DAD70401040163516211D8B401D001D038 +:1010A80001D026D0040104016551800A800F1F0E6B +:1010B800D8B4645DD8B001D001D00AD00401D8906A +:1010C800040166370401673704016837040169378A +:1010D80004010401644B652B040104016551800A75 +:1010E800800F240ED8B4645DD8A001D001D0E8D612 +:1010F80051EC1DF0970E04010401806F790E040174 +:10110800816F7E0E040104017E6F790E04017F6FEA +:1011180022EC1DF0330E04010401806F790E0401E6 +:10112800816FC70E040104017E6F790E04017F6F81 +:1011380022EC1DF06AC480F46BC481F46CC482F4A0 +:101148006DC483F4DD0E040104017E6F790E040181 +:101158007F6F79EC13F00401726F020E0401040131 +:101168007E6F0401725143EC1DF0010E00D0120095 +:1011780004015E6F000E040104015A6F04015E5100 +:10118800C4D057C487F41DC085F41EC086F401EC92 +:101198001CF0D8A001D001D03CD0960E0401040167 +:1011A8002B6501D001D006D01DC053F41EC054F4E5 +:1011B80057C458F4040104012B51D8B401D001D00C +:1011C80018D02BC460F404015E6F000E0401040102 +:1011D8005F6F04015E511FEC0DF02BC460F4040135 +:1011E8005E6F000E040104015F6F04015E5152EC52 +:1011F80000F0122A04015E6F000E040104012B6F37 +:1012080004015E5104015E6F000E066E04015E511A +:1012180032D0040104012B6701D001D006D01DC0D3 +:1012280051F41EC052F457C42CF41250D8B401D053 +:1012380001D018D012C060F404015E6F010E0401E1 +:1012480004015F6F04015E511FEC0DF012C060F4E1 +:1012580004015E6F010E040104015F6F04015E5119 +:1012680052EC00F0040104012B2B04015E6F000E08 +:10127800126E04015E510401D89057330401040131 +:10128800576701D001D015D004015E6F800E0401AC +:101298000401576F04015E511D4A1E2A1E50020A9E +:1012A8001D10D8A401D001D004D0000E1D6E000E70 +:1012B8001E6E1E5004010401541904E11D5004015E +:1012C80004015319D8A401D001D00ED0040104019F +:1012D800575104010401586301D001D005D004011D +:1012E8000401536904015469040104012B51960A4D +:1012F800D8A401D001D009D004015E6F010E040109 +:1013080004015A6F04015E510DD0040104013051EB +:101318001E1804E1040104012F511D18D8A401D09E +:1013280001D02FD7040104015A6701D001D001D0A0 +:10133800A2D00650D8B401D001D001D09CD051C45D +:1013480061F452C462F453C45FF454C460F48CEC86 +:1013580017F05FC45CF460C45DF4040104015DBF70 +:1013680001D001D00DD0040104015D51800A800F25 +:10137800320ED8B45C5DD8B001D001D001D07BD09A +:10138800040104015D51800A800F9E0ED8B45C5D93 +:10139800D8A001D001D00CD0040104015D51800A0D +:1013A800800FA30ED8B45C5DD8A001D001D000D0C6 +:1013B80004015E6F000E040104015B6F04015E51BD +:1013C8002CC461F451C45FF452C460F407EC07F014 +:1013D800040104015B272CC461F451C45FF452C4B6 +:1013E80060F4A8EC0FF0040104015B272CC461F43D +:1013F80051C45FF452C460F4BEEC0BF00401040164 +:101408005B272CC461F451C45FF452C460F4CDEC82 +:1014180010F0040104015B272CC461F451C45FF48B +:1014280052C460F440EC0AF0040104015B272CC4A8 +:1014380061F451C45FF452C460F439EC05F004015E +:1014480004015B2704015E6F010E066E04015E5104 +:10145800040104015B51D8B401D001D00BD0000EB7 +:101468001D6E000E1E6E000E040104012F6F000E8B +:101478000401306F00D012000401756F000E0401E2 +:101488000401626F04017551000E04010401676FC5 +:10149800000E0401686F000E0401696F000E04015C +:1014A8006A6F010E040104016B6F000E04016C6F7A +:1014B800000E04016D6F000E04016E6F0401610ED1 +:1014C80004010401876F0401040E0401886F0401FC +:1014D8005F0E04010401856F0401040E0401866F88 +:1014E800A5EC1BF00401610E04010401806F0401E6 +:1014F800040E0401816F04015F0E040104017E6F74 +:101508000401040E04017F6FC4EC15F05FC465F498 +:1015180060C466F40401040161C463F404010401B5 +:10152800646B000E040104016F6F000E0401706FFC +:10153800040104017051800A800F200ED8B46F5D39 +:10154800D8A001D001D001D05AD00401610E040105 +:101558000401796F0401040E04017A6F04015F0E1F +:1015680004010401776F0401040E0401786F71EC23 +:1015780019F004010401736F040104017351020A94 +:10158800D8A401D001D002D0000EF3D00401040188 +:101598007351D8B401D001D018D0040104016B51A3 +:1015A800040104016713040104016C5104010401DE +:1015B8006813040104016D51040104016913040155 +:1015C80004016E51040104016A130401D890040156 +:1015D8006B3704016C3704016D3704016E37040161 +:1015E80004016F4B702B040104017051800A800FB5 +:1015F800200ED8B46F5DD8A001D001D0A6D7000EB8 +:1016080004010401716F000E0401726F04010401EA +:101618007251800A800F040ED8B4715DD8A001D031 +:1016280001D001D04BD00401610E04010401796F8F +:101638000401040E04017A6F04015F0E0401040121 +:10164800776F0401040E0401786F71EC19F004013E +:101658000401746F040104017451020AD8A401D072 +:1016680001D002D0000E85D0040104017451D8B411 +:1016780001D001D013D071C475F4010E0401766F46 +:101688000401752B03D0D890040176370401752F17 +:10169800FAD704017651040104016213040104011C +:1016A800714B722B040104017251800A800F040EE1 +:1016B800D8B4715DD8A001D001D0B5D70401040118 +:1016C80062510C0AD8B401D001D002D0000E51D01A +:1016D80051EC1DF0A60E04010401806F790E04017F +:1016E800816FCD0E040104017E6F790E04017F6FB6 +:1016F80022EC1DF0750E04010401806F790E0401BF +:10170800816F7E0E040104017E6F790E04017F6FE4 +:1017180022EC1DF00401330E04010401806F040162 +:10172800040E0401816FC70E040104017E6F790E57 +:1017380004017F6F22EC1DF067C480F468C481F453 +:1017480069C482F46AC483F4DD0E040104017E6F67 +:10175800790E04017F6F79EC13F00401756F010EA7 +:10176800040104017E6F0401755143EC1DF0010E64 +:1017780000D012000401610E04010401876F040106 +:10178800040E0401886F04015F0E04010401856FD3 +:101798000401040E0401866FA5EC1BF00401726FAE +:1017A800000E04010401626F04017251040E040169 +:1017B80004016A6F000E04016B6F040104016BAF32 +:1017C80001D001D001D08AD00401726F000E04014B +:1017D80004016E6F04017251000E040104016F6F61 +:1017E800000E0401706F040104017051800A800F1B +:1017F800080ED8B46F5DD8A001D001D001D04BD06D +:101808000401610E04010401766F0401040E040151 +:10181800776F04015F0E04010401746F0401040E64 +:101828000401756FC2EC1AF004010401716F040120 +:1018380004017151020AD8A401D001D002D0000ECF +:10184800F9D0040104017151D8B401D001D013D0EA +:101858006FC472F4010E0401736F0401722B03D07C +:10186800D890040173370401722FFAD70401735119 +:10187800040104016E13040104016F4B702B040171 +:1018880004017051800A800F080ED8B46F5DD8A08B +:1018980001D001D0B5D7040104016A51040A6B11C3 +:1018A800D8A401D001D002D06EC462F40401650E40 +:1018B800040104016A25E96EEA6A0401040EEA22B9 +:1018C80004016EC4EFFF040104016A07D8A06B0786 +:1018D800040104016BAF01D001D076D7000E0401DA +:1018E8000401636F000E0401646F000E040104011B +:1018F8006C6F000E04016D6F040104016D51800AC4 +:10190800800F040ED8B46C5DD8A001D001D001D0EE +:1019180033D00401726F310E04010401766F0401A3 +:1019280072510401650E040104016C25E96EEA6A2E +:101938000401040EEA22EF5004010401756F63C428 +:1019480074F437EC18F00401736F04017351040147 +:101958000401636F0401646B040104016C4B6D2B7B +:10196800040104016D51800A800F040ED8B46C5D27 +:10197800D8A001D001D0CDD7040162C472F404010B +:10198800736B0401040164510401731905E1040136 +:101998000401635104017219D8B401D001D002D0F6 +:1019A800000E48D051EC1DF0A60E04010401806F12 +:1019B800790E0401816FCD0E040104017E6F790E4A +:1019C80004017F6F22EC1DF04D0E04010401806FAD +:1019D800790E0401816F7E0E040104017E6F790E79 +:1019E80004017F6F22EC1DF00401726F050E0401E3 +:1019F8000401786F040172510401650E04010401A9 +:101A0800766F0401040E0401776FDD0E04010401F2 +:101A1800746F790E0401756F14EC14F00401726F81 +:101A2800010E040104017E6F0401725143EC1DF0A4 +:101A3800010E00D01200040104015F51D8B401D096 +:101A480001D005D0030E04010401602704D0030E61 +:101A580004010401605F3CD10C0E040104016065BF +:101A680001D001D009D0170E04010401606101D032 +:101A780001D002D0082A37D1030E040104016065A1 +:101A880001D001D01CD00E0E04010401606101D008 +:101A980001D015D0190E086401D001D00AD0040174 +:101AA800616F010E0B6E04016151000E1B6E000E7A +:101AB8001C6E0401616F000E086E0401615113D1A0 +:101AC80060C464F45FC463F426EC19F063C427F4BB +:101AD80064C428F4040104012829FE0ED8B4271987 +:101AE800D8A401D001D003D0CDEC1CF0FCD0040167 +:101AF80004012729D8B42829D8A401D001D001D0BD +:101B0800F2D01C501B10D8A401D001D006D004017B +:101B1800040127511C6E1B6A51D00401040127518E +:101B28001B120401040128511C121FD00401616F0B +:101B3800060E076E040161513F0E04010401556F42 +:101B4800000E0401566F2ED00401616F080E076E57 +:101B5800040161514F0E04010401556F000E040188 +:101B6800566F20D0CDEC1CF0BED01BC061F41CC059 +:101B780062F40FD0040161514D0AE6E0F3D7040185 +:101B880061512D0AE1E0EED7040161514C0ACEE023 +:101B9800E9D7040162510A0AEDE0100AF0E0F00A00 +:101BA800F3E0E0D70401616F020E0B6E040161518E +:101BB8000401616F000E086E0401615194D060C485 +:101BC80064F45FC463F426EC19F063C427F464C4B6 +:101BD80028F4040104012829FE0ED8B42719D8A432 +:101BE80001D001D003D0CDEC1CF07DD0040104015C +:101BF8002729D8B42829D8A401D001D001D073D07E +:101C080004011F0E0824E96EEA6A0401040EEA22A0 +:101C1800040127C4EFFF082A0706076601D001D090 +:101C28004ED7CDEC1CF051EC1DF0A60E04010401BA +:101C3800806F790E0401816FCD0E040104017E6F5F +:101C4800790E04017F6F22EC1DF0B40E040104012B +:101C5800806F790E0401816F7E0E040104017E6F8E +:101C6800790E04017F6F22EC1DF004011BC080F483 +:101C780004011CC081F404010401826B0401836B1C +:101C8800C70E040104017E6F790E04017F6F79ECA1 +:101C980013F008C078F404011F0E04010401766FE4 +:101CA8000401040E0401776FDD0E04010401746F52 +:101CB800790E0401756F14EC14F00401616F010EC4 +:101CC800040104017E6F0401615143EC1DF00BD047 +:101CD8000B50000A01E1C0D6010A01E1F1D6030A5E +:101CE80001E16DD700D0120004015E6F0B0E0401F4 +:101CF80004015B6F04015E5104015E6F0A0E04016A +:101D080004015C6F04015E51010E04010401646F5B +:101D1800000E0401656FFA0E04010401626F790E6A +:101D28000401636F1F0E04010401606F020E0401B9 +:101D3800616FE2EC17F0040161516011D8A401D081 +:101D480001D011D00A0E040104018D6F000E0401A8 +:101D58008E6F650E040104018B6F790E04018C6F80 +:101D68003BEC03F0F0D0010E04010401646F000E97 +:101D78000401656FFC0E04010401626F790E040111 +:101D8800636F1F0E04010401606F020E0401616F8E +:101D9800E2EC17F0040161516011D8A401D001D020 +:101DA8000AD0E70E040104018B6F790E04018C6FD1 +:101DB8003BEC03F0C8D004015E6F000E040104017F +:101DC8005D6F04015E5104015E6F000E04010401A1 +:101DD8005A6F04015E51B0D098D004015DC45EF41E +:101DE80004015F6B010E04015E27000E5F231F0EC6 +:101DF80004015E25E96E020E04015F21EA6EEF50D0 +:101E0800040104015B6F040104015D2B92D00401FD +:101E18005DC45EF404015F6B010E04015E27000ED1 +:101E28005F231F0E04015E25E96E020E04015F2187 +:101E3800EA6EEF50040104015C6F040104015D2B9C +:101E480078D05CC463F45BC462F4010E040104013D +:101E58005D2504010401606F0401616B000E04013B +:101E6800612334EC17F004015E6F010E04010401D4 +:101E78005A6F04015E51D30E040104018B6F790E71 +:101E880004018C6F3BEC03F054D05CC463F45BC476 +:101E980062F4010E040104015D2504010401606F70 +:101EA8000401616B000E04016123DCEC16F00401EF +:101EB8005E6F010E040104015A6F04015E51E20EC7 +:101EC800040104018B6F790E04018C6F3BEC03F065 +:101ED80030D01F0E040104015D25E96EEA6A020E86 +:101EE800EA22EF5004015E6F04015E51040104010F +:101EF8008D6F04018E6BFC0E040104018B6F780E4C +:101F080004018C6F3BEC03F01ED01F0E040104018A +:101F18005D25E96EEA6A020EEA22EF50500A01E1F5 +:101F28005CD7020A01E173D7010A8BE0070AADE02A +:101F3800D0D7040104015D2B040104015A51D8B41F +:101F480001D001D049D71200000E04010401666FC8 +:101F5800000E0401676F000E0401686F000E040193 +:101F6800696F010E04010401626F000E0401636FC2 +:101F7800000E0401646F000E0401656F0401610E18 +:101F880004010401876F0401040E0401886F040131 +:101F98005F0E04010401856F0401040E0401866FBD +:101FA800A5EC1BF00401610E04010401806F04011B +:101FB800040E0401816F04015F0E040104017E6FA9 +:101FC8000401040E04017F6FC4EC15F0000E040137 +:101FD80004016A6F000E04016B6F040104016B5168 +:101FE800800A800F0C0ED8B46A5DD8A001D001D049 +:101FF80001D08FD00401610E04010401806F040137 +:10200800040E0401816F04015F0E040104017E6F58 +:102018000401040E04017F6FC4EC15F004010401EF +:102028006C6F0401610E04010401806F0401040E49 +:102038000401816F04015F0E040104017E6F040135 +:10204800040E04017F6FC4EC15F0040104016D6FE8 +:102058000401610E04010401806F0401040E0401EF +:10206800816F04015F0E040104017E6F0401040EF8 +:1020780004017F6FC4EC15F0040104016E6F0401C4 +:10208800610E04010401806F0401040E0401816FD4 +:1020980004015F0E040104017E6F0401040E0401B3 +:1020A8007F6FC4EC15F0040104016F6F0401D89030 +:1020B800040166370401673704016837040169378A +:1020C80007D017D004010401668113D0000E60D038 +:1020D8006FC474F46EC473F46DC472F46CC471F498 +:1020E80083EC1AF0000AEDE0010AECE0030AEEE0E6 +:1020F80000D0040104016A4B6B2B040104016B51ED +:10210800800A800F0C0ED8B46A5DD8A001D001D027 +:1021180071D751EC1DF0970E04010401806F790E00 +:102128000401816F7E0E040104017E6F790E0401A3 +:102138007F6F22EC1DF0580E04010401806F790EA8 +:102148000401816FC70E040104017E6F790E04013A +:102158007F6F22EC1DF066C480F467C481F468C404 +:1021680082F469C483F4DD0E040104017E6F790EE4 +:1021780004017F6F79EC13F00401706F020E040103 +:1021880004017E6F0401705143EC1DF0010E00D074 +:102198001200000E04010401626F000E0401636F57 +:1021A800000E0401646F000E0401656F010E040146 +:1021B8000401666F000E0401676F000E0401686F6A +:1021C800000E0401696F0401610E04010401876FA8 +:1021D8000401040E0401886F04015F0E0401040168 +:1021E800856F0401040E0401866FA5EC1BF0000E38 +:1021F800040104016A6F000E04016B6F04010401FD +:102208006B51800A800F180ED8B46A5DD8A001D02F +:1022180001D001D0A2D00401610E04010401806F35 +:102228000401040E0401816F04015F0E040104011E +:102238007E6F0401040E04017F6FC4EC15F00401E5 +:1022480004016C6F0401610E04010401806F040134 +:10225800040E0401816F04015F0E040104017E6F06 +:102268000401040E04017F6FC4EC15F0040104019D +:102278006D6F0401610E04010401806F0401040EF6 +:102288000401816F04015F0E040104017E6F0401E3 +:10229800040E04017F6FC4EC15F0040104016E6F95 +:1022A8000401610E04010401806F0401040E04019D +:1022B800816F04015F0E040104017E6F0401040EA6 +:1022C80004017F6FC4EC15F0040104016F6F1CD08A +:1022D8002AD00401040166510401040162130401B7 +:1022E80004016751040104016313040104016851E6 +:1022F8000401040164130401040169510401040187 +:10230800651311D0000E58D06FC474F46EC473F402 +:102318006DC472F46CC471F444EC1AF0000AD8E08D +:10232800010AD7E0EFD70401D89004016637040109 +:1023380067370401683704016937040104016A4BEF +:102348006B2B040104016B51800A800F180ED8B45E +:102358006A5DD8A001D001D05ED751EC1DF0400EC7 +:1023680004010401806F790E0401816F7E0E04015F +:1023780004017E6F790E04017F6F22EC1DF062C4A8 +:1023880080F463C481F464C482F465C483F4DD0E0C +:10239800040104017E6F790E04017F6F79EC13F05C +:1023A8000401706F020E040104017E6F0401705174 +:1023B80043EC1DF0010E00D012000401756F000EF1 +:1023C80004010401726F04017551030E0401040134 +:1023D800726501D001D001D023D0040104017251EB +:1023E800040104016825E96E0401000E04010401DA +:1023F8006921EA6E04016E0E040104017225E16E82 +:10240800E26A0401040EE222EFCFE7FF04010401AF +:10241800722B030E04010401726501D001D0DDD7CF +:10242800050E0401040168250401756F000E0401FE +:10243800040169210401766F75C46CF476C46DF4E7 +:102448000096000E116E0094040100EE04F00401E1 +:102458006851E92604016951EA22EF500401040198 +:102468006B6F040104016B6701D001D001D081D0EA +:10247800040104016B6701D001D001D072D06CC493 +:10248800E9FF6DC4EAFFEF50040104016A6F04011B +:10249800756F000E04010401736F04017551030E7A +:1024A80004010401736501D001D001D050D06AC481 +:1024B80075F4C00E04017517060E0401766FD890E6 +:1024C800040175330401762FFAD70401755104010C +:1024D8000401746F04016E0E040104017425E96E91 +:1024E800EA6A0401040EEA22010EEF6201D001D06B +:1024F80002D0008613D004016E0E04010401742575 +:10250800E96EEA6A0401040EEA22EF50106EB18007 +:1025180000D000A401D001D0FCD700940401D890C9 +:102528006A37D8906A37040104016B070401040173 +:102538006B6701D001D001D00AD004010401732BCC +:10254800030E04010401736501D001D0B0D7040162 +:1025580004016C4B6D2B040104016B6701D001D0A1 +:102568008ED7009400D000A401D001D0FCD7B19040 +:1025780089981200026601D001D020D0030E040110 +:102588000401686501D001D007D00D0E04010401D3 +:10259800686501D001D00BD0870E040104018B6F50 +:1025A800790E04018C6F3BEC03F0FE0E9DD0040104 +:1025B800696F010E026E0401695194D00204D8A417 +:1025C80001D001D042D00C0E04010401686501D08D +:1025D80001D007D0160E04010401686501D001D0AE +:1025E80024D00CC069F404016A6B0401040156513B +:1025F80004016A1905E1040104015551040169192E +:10260800D8B401D001D011D08F0E040104018B6F12 +:10261800790E04018C6F3BEC03F00401696F000E26 +:10262800026E04016951FE0E5FD00090040104019E +:1026380067A101D000800401696F020E026E0401D7 +:102648006951000E00B0010E4FD00250020AD8A402 +:1026580001D001D047D0040104016751D8B401D09A +:1026680001D015D0030E04010401686501D001D022 +:102678000ED00E0E04010401686101D001D007D00C +:102688000401696F000E026E0401695129D00C0E15 +:1026980004010401686501D001D00ED0170E0401B1 +:1026A8000401686101D001D007D00401696F010EEF +:1026B800026E0401695114D0030E04010401686517 +:1026C80001D001D00DD00E0E04010401686101D0C3 +:1026D80001D006D00401696F000E026E0401695131 +:1026E800FF0E02D0FF0E00D012007EC48DF47FC40E +:1026F8008EF4C10E040104018B6F790E04018C6FF6 +:102708003BEC03F004018351801181118211D8A49C +:1027180001D001D00AD0F20E040104018B6F790EAA +:1027280004018C6F3BEC03F071D00401876F010E3C +:1027380004010401846F040187510401876F000EAE +:1027480004010401856F04018751070E0401040187 +:10275800856501D001D001D059D0040180C487F427 +:10276800040181C488F4040182C489F4040183C487 +:102778008AF41D0E06D0D89004018A338933883331 +:102788008733E82EF8D7040187510F0B04010401A1 +:10279800866F04010401866701D001D008D00401C6 +:1027A80004018405D8A401D001D001D018D00401B7 +:1027B800040186C48DF4040104018E6BDA0E040151 +:1027C80004018B6F790E04018C6F3BEC03F004015C +:1027D800876F000E04010401846F0401875104010E +:1027E800040ED89004018037040181370401823730 +:1027F80004018337E82EF5D704010401852B070E61 +:1028080004010401856501D001D0A7D7730E040126 +:1028180004018B6F790E04018C6F3BEC03F01200FE +:1028280074C48DF475C48EF4EC0E040104018B6F2E +:10283800790E04018C6F3BEC03F004017A6F000EF3 +:1028480004010401796F04017A51040104017851EB +:1028580004010401795DD8A001D001D001D04BD08A +:10286800040104017951040104017625E96E04018B +:10287800000E040104017721EA6EEF5004017A6F1B +:102888000F0E04017A1704017A51040104018F6FB5 +:102898000401906B040104017951040104017625B7 +:1028A800E96E0401000E040104017721EA6EEF507D +:1028B80004017B6F04017B3B0F0E7B1704017B51E6 +:1028C800040104018D6F04018E6BD80E040104010C +:1028D8008B6F790E04018C6F3BEC03F0040104014B +:1028E800792B04010401785104010401795DD8A011 +:1028F80001D001D0B5D7730E040104018B6F790E96 +:1029080004018C6F3BEC03F012000401D8902A37C5 +:1029180004010401C351D8B401D001D01BD0040173 +:102928000401292B040104012951030AD8A401D068 +:1029380001D005D0070E040104012A130AD0030EA2 +:1029480004010401296501D001D003D00401040168 +:102958002A8108D00401C46F000E04010401296F04 +:102968000401C4510401D890323704010401312B09 +:10297800040104012AAF01D001D004D004010401EC +:10298800328100D0040104013151080AD8A401D0D1 +:1029980001D029D00401C46F000E04010401316F75 +:1029A8000401C4511F0E040104012F25E96E000E15 +:1029B800040104013021EA6E040132C4EFFF04016E +:1029C80004012F4B302B040104013051020A2F114E +:1029D800D8A401D001D007D0000E040104012F6F44 +:1029E800000E0401306F1200040104014D51D8B4E7 +:1029F80001D001D024D0040104014C510401040188 +:102A08004B277E0E040104014B6501D001D004D090 +:102A1800040104014C6911D0040104014B6701D081 +:102A280001D00BD00401B46F010E040104014C6FF6 +:102A38000401B451040104014D074BC4BEFF040155 +:102A480004015051D8B401D001D024D004010401AC +:102A58004F51040104014E277E0E040104014E6506 +:102A680001D001D004D0040104014F6911D0040140 +:102A780004014E6701D001D00BD00401B46F010EE0 +:102A8800040104014F6F0401B4510401040150070B +:102A98004EC4BBFF040104014D6701D001D002D030 +:102AA800000EBE6E04010401506701D001D002D0AF +:102AB800000EBB6E12000096000E116E009468C4E2 +:102AC800E9FF69C4EAFFEF50106EB18000D000A49E +:102AD80001D001D0FCD79D92010E040104016A6F58 +:102AE800000E04016B6F2FD0040104016A51040128 +:102AF80004016825E96E040104016B510401040115 +:102B08006921EA6E010EEF6201D001D002D0008681 +:102B180016D00094040104016A51040104016825D7 +:102B2800E96E040104016B51040104016921EA6E94 +:102B3800EF50106E00D000A401D001D0FCD70401E2 +:102B480004016A4B6B2B040104016A51040104015E +:102B58006825E96E040104016B510401040169212F +:102B6800EA6EEF50D8A401D001D0BED79D82009460 +:102B780000D000A401D001D0FCD7B19089981200F0 +:102B88000401846F000E04010401836F0401845161 +:102B980080C4E9FF81C4EAFFEF5004010401876F94 +:102BA8007EC4E9FF7FC4EAFF0401EECF85F4040187 +:102BB800EDCF86F401EC1CF0D8B001D002D0010EA4 +:102BC80001D0000E04010401826F04010401832B6B +:102BD80080C487F481C488F47EC485F47FC486F4F5 +:102BE800A5EC1BF080C4E9FF81C4EAFFEF500401A3 +:102BF8000401876F7EC4E9FF7FC4EAFF0401EECFBA +:102C080085F40401EDCF86F401EC1CF0D8B001D0B6 +:102C180002D0010E01D0000E040104018219D8B4BB +:102C280001D001D004D00401040183510AD0040169 +:102C380004018329D8A401D001D002D0000E01D00C +:102C4800C4D71200000E04010401A16F000E040194 +:102C5800A26F040104019F519E11D8B401D001D084 +:102C680047D00401A36F010E04010401A06F040101 +:102C7800A35109D00401D89004019E3704019F375D +:102C880004010401A02B040104019FAF01D001D06D +:102C9800F1D70401D8900401A1370401A237040137 +:102CA80004019E51040104019C5D040104019F512B +:102CB800040104019D59D8A001D001D00FD004010E +:102CC80004019E51040104019C5F040104019F5109 +:102CD800040104019D5B04010401A1810401D89051 +:102CE80004019F3304019E3304010401A02FD1D7AE +:102CF800A1C49CF4A2C49DF400D01200000EAB6ED7 +:102D0800AB8EAB88AC90AC8AAC94B896948E949CFD +:102D180006D00401AECF5AF4040104015B6B9EBADD +:102D280001D001D0F6D704015C6F400EAF6E0401EC +:102D38005C519F9A9F98F28C9D8A9D98CD909E9009 +:102D4800000ECF6E000ECE6ECD9ACD98CD92000EAD +:102D580004010401616F020E0401626F000E040198 +:102D680004015F6F000E0401606F1F0E040104016F +:102D78005D6F020E04015E6F8FEC1CF0000E040103 +:102D88000401616F010E0401626F2D0E040104013C +:102D98005F6F000E0401606F0501000E040104015D +:102DA8005D6F0501050E04015E6F8FEC1CF01200CB +:102DB8006EEC1DF00401666F000E04010401646FDF +:102DC8000401665140D00401666F020E040104013B +:102DD800686F0401665175EC1DF01F0E0401666FE3 +:102DE800020E676F040104016051040166270401A3 +:102DF800040161510401672366C468F467C469F477 +:102E0800E1EC11F00401666F000E04010401656F26 +:102E1800040166510BD00D0E0401666FF90EE82E01 +:102E2800FED7662FFCD704010401652B04010401B9 +:102E3800625104010401655DD8A001D001D0EBD72F +:102E480004010401642B0401040163510401040119 +:102E5800645DD8A001D001D0B6D769EC1DF012008E +:102E68006EEC1DF00401666F000E04010401646F2E +:102E78000401665140D00401666F020E040104018A +:102E8800686F0401665175EC1DF01F0E0401666F32 +:102E9800020E676F040104016051040166270401F2 +:102EA800040161510401672366C468F467C469F4C6 +:102EB8005FEC15F00401666F000E04010401656FF4 +:102EC800040166510BD00D0E0401666FF90EE82E51 +:102ED800FED7662FFCD704010401652B0401040109 +:102EE800625104010401655DD8A001D001D0EBD77F +:102EF80004010401642B0401040163510401040169 +:102F0800645DD8A001D001D0B6D769EC1DF01200DD +:102F1800040104015F29D8B46029D8A401D001D0E4 +:102F280006D0040104015F690401606946D0040108 +:102F380004016251800A0401636F04015F510401B6 +:102F48000401615D040104016051800A04016359B0 +:102F5800D8A001D001D012D0040104015F510401AE +:102F68000401615D040104015F6F04010401605103 +:102F78000401040162590401606F1FD0000E0401AE +:102F8800636F020E646F040104015F510401635F03 +:102F98000401040160510401645B040104016151EE +:102FA80004016325040104015F6F040104016251F7 +:102FB800040164210401606F00D012003ED060C497 +:102FC800E9FF61C4EAFFEF50D8B401D001D014D0B2 +:102FD800040162C4F6FF040163C4F7FF0800F5CFDB +:102FE80066F460C4E9FF61C4EAFFEF5004016619A2 +:102FF800D8B401D001D019D060C4E9FF61C4EAFF98 +:10300800EF500401666F040162C4F6FF040163C453 +:10301800F7FF0800F5500401665D04010401606FC4 +:103028000401616BD8A061071DD004010401604B45 +:10303800612B04010401624B632B04010401640742 +:10304800D8A0650704016429D8B46529D8A401D09B +:1030580001D0B5D7000E04010401606F000E040111 +:10306800616F00D01200800E04010401796F000E18 +:1030780004017A6F040104017A517911D8A401D0AE +:1030880001D001D040D00401000E040174BF010E2C +:1030980004010401776F0401786B04010401755180 +:1030A8000401040179150009D8B401D001D00CD06D +:1030B8000401040178517711000ED8B4010E0401FF +:1030C8000401776F0401786B0401D8907437040108 +:1030D800040178517711D8B401D001D006D0040189 +:1030E8000401765104010401741B0401D890040101 +:1030F8007A3304017933040104017A517911D8A48F +:1031080001D001D0C0D704010401745100D01200CD +:10311800FACFA7F4FBCFA8F4E9CFA9F4EACFAAF431 +:10312800E1CFABF4E2CFACF4D9CFADF4DACFAEF463 +:10313800F3CFAFF4F4CFB0F4F6CFB1F4F7CFB2F4E5 +:10314800F8CFB3F49EAA01D001D002D03CEC1BF01A +:103158009EA801D001D002D0D4EC1BF09EA201D0D1 +:1031680001D003D0F8EC14F09E92B3C4F8FFB2C4B7 +:10317800F7FFB1C4F6FFB0C4F4FFAFC4F3FFAEC4A9 +:10318800DAFFADC4D9FFACC4E2FFABC4E1FFAAC407 +:10319800EAFFA9C4E9FFA8C4FBFFA7C4FAFFA6C4B5 +:1031A800E0FFA5C4E8FFA4C4D8FF1000040104018F +:1031B8009F519E11D8B401D001D03ED00401A16F17 +:1031C800010E04010401A06F0401A15109D00401FA +:1031D800D89004019E3704019F3704010401A02BF5 +:1031E800040104019FAF01D001D0F1D7040104010B +:1031F8009E51040104019C5D040104019F510401D6 +:1032080004019D59D8A001D001D00CD004010401BB +:103218009E51040104019C5F040104019F510401B3 +:1032280004019D5B0401D89004019F3304019E337F +:1032380004010401A02FDAD79CC49CF49DC49DF41A +:1032480000D0120064C468F463C467F4BEEC12F0E2 +:1032580004010401656F040104016551FE0AD8A444 +:1032680001D001D008D0FE0E04010401636FFF0EE7 +:103278000401646F31D0040104016529D8A401D088 +:1032880001D006D00401040163690401646924D0F3 +:10329800D8900532040104016551D8B401D001D099 +:1032A80001D0058E0C2A042A080E046001D001D032 +:1032B80006D0040104016369040164690DD00401A6 +:1032C800666F000E046E04016651040105C063F4C4 +:1032D80004010401646B00D0120079C480F47AC43C +:1032E80081F477C47EF478C47FF4C4EC15F004014B +:1032F80004017C6F1D0E040104017C6501D001D01E +:1033080009D0290E040104017C6101D001D002D04A +:10331800000E2DD079C480F47AC481F477C47EF489 +:1033280078C47FF4C4EC15F0040104017B6F090E26 +:10333800040104017C6501D001D017D0150E0401E9 +:1033480004017C6101D001D010D0090E04010401F0 +:103358007B6501D001D009D0150E040104017B6101 +:1033680001D001D002D0010E02D0020E00D012000E +:103378000600EACFB9F4E1CFBAF4E2CFBBF4D9CF73 +:10338800BCF4DACFBDF4F3CFBEF4F4CFBFF4F6CF7C +:10339800C0F4F7CFC1F4F8CFC2F4F2A401D001D041 +:1033A8000BD0000E81B8010E04010401C36F89EC33 +:1033B80014F0000ED66EF294A1A201D001D006D06E +:1033C800B368C90EB26EEBEC1CF0A192C2C4F8FF50 +:1033D800C1C4F7FFC0C4F6FFBFC4F4FFBEC4F3FF07 +:1033E800BDC4DAFFBCC4D9FFBBC4E2FFBAC4E1FF65 +:1033F800B9C4EAFFB8C4E9FFB7C4FBFFB6C4FAFF13 +:1034080011000F0E04010401766501D001D017D018 +:103418000A0E04010401776101D001D010D00A0E10 +:1034280004010401786101D001D009D00A0E040119 +:103438000401796101D001D002D0000E20D00A0E1B +:1034480004010401766101D001D017D00A0E0401ED +:103458000401776101D001D010D00F0E04010401DE +:10346800786501D001D009D00A0E04010401796100 +:1034780001D001D002D0010E02D0020E00D01200FD +:103488000D0E04010401716101D001D017D00D0E99 +:1034980004010401726101D001D010D00D0E0401A5 +:1034A8000401736101D001D009D0100E0401040198 +:1034B800746501D001D002D0010E20D00D0E040198 +:1034C8000401716101D001D017D0100E040104016C +:1034D800726501D001D010D00D0E04010401736192 +:1034E80001D001D009D00D0E04010401746101D08E +:1034F80001D002D0000E02D0020E00D012000F0E32 +:1035080004010401716501D001D017D00A0E04012D +:103518000401726101D001D010D00F0E0401040122 +:10352800736501D001D009D00A0E04010401746149 +:1035380001D001D002D0000E20D00A0E04010401EF +:10354800716101D001D017D00F0E0401040172651A +:1035580001D001D010D00F0E04010401736501D011 +:1035680001D009D00A0E04010401746101D001D010 +:1035780002D0010E02D0020E00D0120076C480F4F0 +:1035880077C481F474C47EF475C47FF4C4EC15F078 +:1035980004010401786F76C480F477C481F474C49C +:1035A8007EF475C47FF4C4EC15F004010401796F4E +:1035B8000D0E04010401786501D001D009D00D0E6B +:1035C80004010401796501D001D002D0000E12D0A7 +:1035D8000B0E04010401786101D001D009D00D0E51 +:1035E80004010401796501D001D002D0010E02D096 +:1035F800020E00D012000401796F000E0E6E040155 +:103608007951000E176E000E186E000E196E000E1E +:103618001A6E000E136E000E146E000E156E000E5C +:10362800166E010E04010401476F000E0401486F75 +:10363800000E0401496F000E04014A6F0401796FFE +:10364800000E0F6E04017951000E040104012D6F64 +:10365800000E04012E6F0401796F000E036E040141 +:1036680079510401796F000E096E04017951120035 +:10367800AECFB4F4ABA201D001D002D0AB98AB88E6 +:1036880000A201D001D001D029D004010401B45115 +:103698002B0AD8A401D001D00BD0CD9000821F0EE8 +:1036A8000124E96EEA6A020EEA22000EEF6E16D0D5 +:1036B8001F0E0124E96EEA6A020EEA220401B4C46C +:1036C800EFFF012A000ECF6E000ECE6ECD809E90C9 +:1036D8000401B56F000E0D6E0401B55112009EA0D5 +:1036E80001D001D00CD01E0E0D6401D001D005D040 +:1036F800CD90000E016E009201D00D2A9E9000B26E +:1037080001D001D001D01CD078EC0EF0000E0401DD +:103718000401616F020E0401626F000E04010401CE +:103728005F6F000E0401606F1F0E040104015D6FDE +:10373800020E04015E6F8FEC1CF0000E016E009209 +:10374800120087C4E9FF88C4EAFFD890EF3687C41F +:10375800E9FF88C4EAFFEF50D8A401D001D01FD0F8 +:1037680087C4E9FF88C4EAFF010EEF6E85C4E9FF4C +:1037780086C4EAFFEE50ED10D8A401D001D008D0DD +:1037880085C4E9FF86C4EAFF000EEE6E020EED6EF8 +:1037980085C4E9FF86C4EAFFEE06000EED5A120062 +:1037A80059C4B4F404010401B429D8A401D001D047 +:1037B80009D00401B56F000E04010401B46F0401BF +:1037C800B55103D004010401B42B0A5004010401CB +:1037D800B46301D001D002D09D980ED00501000E2F +:1037E80004010401B425E96EEA6A0501050EEA221E +:1037F800EF50AD6EB4C459F412001F0E0401040159 +:103808008525E96E000E040104018621EA6EEF5059 +:1038180004010401886F040104018851040187C46C +:1038280089F404018A6B89BF8A0704018917000E8D +:103838008A1704018A518911D8B401D001D002D065 +:10384800D88002D0D89000D012000D0E04010401D7 +:103858007E6101D001D009D00D0E040104017F6101 +:1038680001D001D002D0000E12D0180E04010401BC +:103878007E6501D001D009D00D0E040104017F61DD +:1038880001D001D002D0010E02D0020E00D01200E9 +:103898006FEC1CF064EC1DF082EC16F034EC1DF0BB +:1038A8005BEC1DF007EC1DF00A0E040104018D6F9E +:1038B800000E04018E6F630E040104018B6F790EF4 +:1038C80004018C6F3BEC03F0BCEC08F073EC1BF0CC +:1038D800FBD714EF00F0000EC26E04015A6F0F0EF2 +:1038E800C16E04015A51070EB46E000E806E000EB0 +:1038F800926E000E946E000E956E000E826E000E93 +:10390800836E000E936E000E816E89989298949241 +:103918009494929612005DC463F45EC464F40BD070 +:1039280063C4E9FF64C4EAFF04015FC4EFFF040154 +:103938000401634B642B040104016107D8A06207EA +:1039480004016129D8B46229D8A401D001D0E8D7EC +:1039580000D0120000D00A50040104015919D8B44B +:1039680001D001D0F8D70501000E0A24E96EEA6AF1 +:103978000501050EEA2204019CC4EFFF0A28D8A419 +:1039880001D001D003D0000E0A6E01D00A2A9D880A +:1039980012000401636F000E046E040163510401F8 +:1039A800636F000E026E040163510401636F000E21 +:1039B8000C6E040163510401636F000E0B6E040169 +:1039C8006351040104015569040156691200116626 +:1039D80001D001D011D00084106601D001D001D0EF +:1039E80011D010C011F0000E106E00B601D001D039 +:1039F80002D0897801D000961150D8B401D001D0F6 +:103A080001D011061200CA82CA9CCA8ACA98CA96EC +:103A1800000EBD6E000EBA6EBA86BA84BD86BD842D +:103A2800BD9ABD98BA9ABA98000EBE6E000EBB6ECB +:103A38009E92CB689F929D82CA84120080C48FF4A4 +:103A480081C490F47EC48DF47FC48EF4AD0E04015D +:103A580004018B6F790E04018C6F3BEC03F01200AC +:103A6800D594D592D590D596D59AD58CF294F28ADC +:103A780092969388F184D58E78EC1DF01200100E82 +:103A8800040104018B6F790E04018C6F3BEC03F089 +:103A98007EC47FF472EC1DF01200F40E04010401E0 +:103AA8008B6F790E04018C6F3BEC03F0120092943B +:103AB80092988998B19AB198A082A282B190120086 +:103AC800D08EF28EF28CF28E120078EC1DF0D58E2C +:103AD800B1901200D59E7BEC1DF012007FC44DF40E +:103AE800120068C450F412008994898612008984EF +:043AF8008996120099 +:1078EA0001000A006400E8031027010010000001EB +:1078FA000010556E6B6E6F776E20636F6D6D616EE3 +:10790A006420282575290D0A003031323334353682 +:10791A003738394142434445460073656C666C65A5 +:10792A0061726E696E6776320073656C666C65614A +:10793A00726E696E670065766572666C6F757269DC +:10794A0073680066696E656F666673657400636F57 +:10795A006465737769746368000D0A2B5625750D83 +:10796A000A0025733A307825583B006D616E646FC2 +:10797A006C796E0070726F746F636F6C00413A209D +:10798A0025690D0A00423A2025690D0A00617263D1 +:10799A007465636800286E756C6C290073656E7374 +:1079AA006F720025733A25733B006F7265676F6EBD +:1079BA000068617374610025733A3078006D6F64F2 +:1079CA00656C00636C617373002B530D0A002558B4 +:1079DA0025580064617461002B540D0A002B4E0D6A +:1079EA000A0025733A00783130002B57002B5200D9 +:0679FA0056004E000000E3 :020000040030CA :04000000FF36FFFECA :02000600BFFF3A diff --git a/telldus-gui/Plugins/Controllers/tellstick.cpp b/telldus-gui/Plugins/Controllers/tellstick.cpp index eaa3397c..a9758ab0 100644 --- a/telldus-gui/Plugins/Controllers/tellstick.cpp +++ b/telldus-gui/Plugins/Controllers/tellstick.cpp @@ -59,7 +59,7 @@ bool TellStick::isUpgradable() const { } else if (type() == 2) { //TellStick Duo - if (firmware < 5) { + if (firmware < 10) { return true; } } From 1009a430c8432383149d2a1c66f1b84752c0bdab Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 29 May 2013 12:20:06 +0200 Subject: [PATCH 2168/2215] Enable the Controllers plugin as default. This closes #86 --- telldus-gui/Plugins/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/CMakeLists.txt b/telldus-gui/Plugins/CMakeLists.txt index 3ba4155d..382f6744 100644 --- a/telldus-gui/Plugins/CMakeLists.txt +++ b/telldus-gui/Plugins/CMakeLists.txt @@ -8,7 +8,7 @@ IF (BUILD_LIBTELLDUS-GUI) SET(BUILD_PLUGIN_SYSTRAY TRUE CACHE BOOL "Build plugin 'Systray'") ENDIF (BUILD_LIBTELLDUS-GUI) -SET(BUILD_PLUGIN_CONTROLLERS FALSE CACHE BOOL "Build plugin 'Controllers admin plugin'") +SET(BUILD_PLUGIN_CONTROLLERS TRUE CACHE BOOL "Build plugin 'Controllers admin plugin'") SET(BUILD_PLUGIN_DBUS FALSE CACHE BOOL "Build plugin 'DBus'") SET(BUILD_PLUGIN_LIVE FALSE CACHE BOOL "Build plugin 'Telldus Live!'") SET(BUILD_PLUGIN_SCHEDULERGUISIMPLE FALSE CACHE BOOL "Build plugin 'Simple Scheduler GUI'") From 64ed7d4afab5a68b46d5acb8b9cee79b072ef808 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 3 Jun 2013 12:08:30 +0200 Subject: [PATCH 2169/2215] Inital Oregon Scientific v3 support (F824) --- telldus-core/service/ProtocolOregon.cpp | 53 +++++++++++++++++++++++++ telldus-core/service/ProtocolOregon.h | 1 + 2 files changed, 54 insertions(+) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 6882019a..4fb962b5 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -19,6 +19,8 @@ std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) { return decodeEA4C(data); } else if (model.compare(L"0x1A2D") == 0) { return decode1A2D(data); + } else if (model.compare(L"0xF824") == 0) { + return decodeF824(data); } return ""; @@ -125,3 +127,54 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { return retString.str(); } + +std::string ProtocolOregon::decodeF824(const std::string &data) { + + uint64_t value = TelldusCore::hexTo64l(data); + + uint8_t crcCheck = value & 0xF; //PROBABLY crc + value >>= 4; + uint8_t messageChecksum1 = value & 0xF; + value >>= 4; + uint8_t messageChecksum2 = value & 0xF; + value >>= 4; + uint8_t unknown = value & 0xF; + value >>= 4; + uint8_t hum1 = value & 0xF; + value >>= 4; + uint8_t hum2 = value & 0xF; + value >>= 4; + uint8_t neg = value & 0xF; + value >>= 4; + uint8_t temp1 = value & 0xF; + value >>= 4; + uint8_t temp2 = value & 0xF; + value >>= 4; + uint8_t temp3 = value & 0xF; + value >>= 4; + uint8_t battery = value & 0xF; //PROBABLY battery + value >>= 4; + uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); + uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); + value >>= 8; + uint8_t channel = value & 0xF; + checksum += unknown + hum1 + hum2 + neg + temp1 + temp2 + temp3 + battery + channel + 0xF + 0x8 + 0x2 + 0x4; + + if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ + //checksum error + return ""; + } + + double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; + if (neg) { + temperature = -temperature; + } + int humidity = (hum1 * 10.0) + hum2; + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:F824;id:" << static_cast(rollingcode) + << ";temp:" << std::fixed << std::setprecision(1) << temperature + << ";humidity:" << humidity << ";"; + + return retString.str(); +} diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index 1da70dc1..f0c757a8 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -18,6 +18,7 @@ public: protected: static std::string decodeEA4C(const std::string &data); static std::string decode1A2D(const std::string &data); + static std::string decodeF824(const std::string &data); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ From 668dd99ac278cfd419d67879b141678facea630a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 13 Jun 2013 12:18:10 +0200 Subject: [PATCH 2170/2215] unistd.h must be explicitly included on some platforms to have access to for example environ. This closes #313 --- telldus-core/service/EventUpdateManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index d237c5ba..cf6b8718 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #endif // _LINUX #include From 35028b1c827910db32264a2789c94fba16852073 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 2 Sep 2013 16:28:39 +0200 Subject: [PATCH 2171/2215] Added support for rain and wind sensors (Oregon Scientific) in telldus-core --- telldus-core/client/telldus-core.cpp | 22 +++- telldus-core/client/telldus-core.h | 5 + telldus-core/service/DeviceManager.cpp | 5 + telldus-core/service/ProtocolOregon.cpp | 123 +++++++++++++++++++++ telldus-core/service/ProtocolOregon.h | 2 + telldus-core/tdtool/main.cpp | 140 +++++++++++++++++++++++- 6 files changed, 291 insertions(+), 6 deletions(-) diff --git a/telldus-core/client/telldus-core.cpp b/telldus-core/client/telldus-core.cpp index fdb1f3e7..c9a977b6 100644 --- a/telldus-core/client/telldus-core.cpp +++ b/telldus-core/client/telldus-core.cpp @@ -73,6 +73,16 @@ * The sensor can report the temperature. * @def TELLSTICK_HUMIDITY * The sensor can report the humidity. + * @def TELLSTICK_RAINRATE + * The sensor can report rain fall rate. + * @def TELLSTICK_RAINTOTAL + * The sensor can report total rain fall. + * @def TELLSTICK_WINDDIRECTION + * The sensor can report wind direction. + * @def TELLSTICK_WINDAVERAGE + * The sensor can report average wind speed. + * @def TELLSTICK_WINDGUST + * The sensor can report gust wind speed. * **//* @} */ @@ -255,8 +265,10 @@ * @param id * The unique id for the sensor. * @param dataType - * The type that @a value is. Can be one of @ref TELLSTICK_TEMPERATURE or - * @ref TELLSTICK_HUMIDITY. + * The type that @a value is. Can be one of @ref TELLSTICK_TEMPERATURE, + * @ref TELLSTICK_HUMIDITY, @ref TELLSTICK_RAINTOTAL, + * @ref TELLSTICK_RAINRATE, @ref TELLSTICK_WINDDIRECTION, + * @ref TELLSTICK_WINDAVERAGE or @ref TELLSTICK_WINDGUST. * @param value * A human readable string of the data. * @param timestamp @@ -1135,8 +1147,10 @@ int WINAPI tdSensor(char *protocol, int protocolLen, char *model, int modelLen, * @param[in] id * The id of the sensor. * @param[in] dataType - * Which sensor value to retrive (one of @ref TELLSTICK_TEMPERATURE or @ref - * TELLSTICK_HUMIDITY). + * Which sensor value to retrive (one of @ref TELLSTICK_TEMPERATURE, + * @ref TELLSTICK_HUMIDITY, @ref TELLSTICK_RAINTOTAL, + * @ref TELLSTICK_RAINRATE, @ref TELLSTICK_WINDDIRECTION, + * @ref TELLSTICK_WINDAVERAGE or @ref TELLSTICK_WINDGUST. * @param[out] value * A by ref string where the value will be placed. * @param[in] len diff --git a/telldus-core/client/telldus-core.h b/telldus-core/client/telldus-core.h index c50804ea..21a9bf9a 100644 --- a/telldus-core/client/telldus-core.h +++ b/telldus-core/client/telldus-core.h @@ -118,6 +118,11 @@ extern "C" { // Sensor value types #define TELLSTICK_TEMPERATURE 1 #define TELLSTICK_HUMIDITY 2 +#define TELLSTICK_RAINRATE 4 +#define TELLSTICK_RAINTOTAL 8 +#define TELLSTICK_WINDDIRECTION 16 +#define TELLSTICK_WINDAVERAGE 32 +#define TELLSTICK_WINDGUST 64 // Error codes #define TELLSTICK_SUCCESS 0 diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index e33e66d2..82b8cba4 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -722,6 +722,11 @@ void DeviceManager::handleSensorMessage(const ControllerMessage &msg) { setSensorValueAndSignal("temp", TELLSTICK_TEMPERATURE, sensor, msg, t); setSensorValueAndSignal("humidity", TELLSTICK_HUMIDITY, sensor, msg, t); + setSensorValueAndSignal("rainrate", TELLSTICK_RAINRATE, sensor, msg, t); + setSensorValueAndSignal("raintotal", TELLSTICK_RAINTOTAL, sensor, msg, t); + setSensorValueAndSignal("winddirection", TELLSTICK_WINDDIRECTION, sensor, msg, t); + setSensorValueAndSignal("windaverage", TELLSTICK_WINDAVERAGE, sensor, msg, t); + setSensorValueAndSignal("windgust", TELLSTICK_WINDGUST, sensor, msg, t); } void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const { diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 4fb962b5..79dc3614 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -21,6 +21,10 @@ std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) { return decode1A2D(data); } else if (model.compare(L"0xF824") == 0) { return decodeF824(data); + } else if (model.compare(L"0x1984") == 0 || model.compare(L"0x1994") == 0) { + return decode1984(data, model); + } else if (model.compare(L"0x2914") == 0) { + return decode2914(data); } return ""; @@ -73,6 +77,71 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { return retString.str(); } +std::string ProtocolOregon::decode1984(const std::string &data, const std::wstring &model) { + + //wind + uint64_t value = TelldusCore::hexTo64l(data); + + uint8_t crcCheck = value & 0xF; //PROBABLY crc + value >>= 4; + uint8_t messageChecksum1 = value & 0xF; + value >>= 4; + uint8_t messageChecksum2 = value & 0xF; + + value >>= 4; + uint8_t avg1 = value & 0xF; + value >>= 4; + uint8_t avg2 = value & 0xF; + value >>= 4; + uint8_t avg3 = value & 0xF; + value >>= 4; + uint8_t gust1 = value & 0xF; + value >>= 4; + uint8_t gust2 = value & 0xF; + value >>= 4; + uint8_t gust3 = value & 0xF; + value >>= 4; + uint8_t unknown1 = value & 0xF; + value >>= 4; + uint8_t unknown2 = value & 0xF; + value >>= 4; + uint8_t direction = value & 0xF; + + value >>= 4; + uint8_t battery = value & 0xF; //PROBABLY battery + value >>= 4; + uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); + uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); + value >>= 8; + uint8_t channel = value & 0xF; + checksum += unknown1 + unknown2 + avg1 + avg2 + avg3 + gust1 + gust2 + gust3 + direction + battery + channel; + + if (model.compare(L"0x1984") == 0) { + checksum += 0x1 + 0x9 + 0x8 + 0x4; + } + else { + checksum += 0x1 + 0x9 + 0x9 + 0x4; + } + + if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ + //checksum error + return ""; + } + + + double avg = ((avg1 * 100) + (avg2 * 10) + avg3)/10.0; + double gust = ((gust1 * 100) + (gust2 * 10) + gust3)/10.0; + float directiondegree = 22.5 * direction; + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:1984;id:" << static_cast(rollingcode) + << ";winddirection:" << directiondegree + << ";windaverage:" << std::fixed << std::setprecision(1) << avg + << ";windgust:" << std::fixed << std::setprecision(1) << gust << ";"; + + return retString.str(); +} + std::string ProtocolOregon::decode1A2D(const std::string &data) { uint64_t value = TelldusCore::hexTo64l(data); // checksum2 not used yet @@ -128,6 +197,60 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { return retString.str(); } +std::string ProtocolOregon::decode2914(const std::string &data) { + + //rain + uint64_t value = TelldusCore::hexTo64l(data); + + uint8_t messageChecksum1 = value & 0xF; + value >>= 4; + uint8_t messageChecksum2 = value & 0xF; + + value >>= 4; + uint8_t totRain1 = value & 0xF; + value >>= 4; + uint8_t totRain2 = value & 0xF; + value >>= 4; + uint8_t totRain3 = value & 0xF; + value >>= 4; + uint8_t totRain4 = value & 0xF; + value >>= 4; + uint8_t totRain5 = value & 0xF; + value >>= 4; + uint8_t totRain6 = value & 0xF; + value >>= 4; + uint8_t rainRate1 = value & 0xF; + value >>= 4; + uint8_t rainRate2 = value & 0xF; + value >>= 4; + uint8_t rainRate3 = value & 0xF; + value >>= 4; + uint8_t rainRate4 = value & 0xF; + + value >>= 4; + uint8_t battery = value & 0xF; //PROBABLY battery + value >>= 4; + uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); + uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); + value >>= 8; + uint8_t channel = value & 0xF; + checksum += totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 + rainRate1 + rainRate2 + rainRate3 + rainRate4 + battery + channel + 0x2 + 0x9 + 0x1 + 0x4; + + if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ + //checksum error + return ""; + } + + double totRain = ((totRain1 * 100000) + (totRain2 * 10000) + (totRain3 * 1000) + (totRain4 * 100) + (totRain5 * 10) + totRain6)/1000.0*25.4; + double rainRate = ((rainRate1 * 1000) + (rainRate2 * 100) + (rainRate3 * 10) + rainRate4)/100.0*25.4; + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:2914;id:" << static_cast(rollingcode) + << ";raintotal:" << std::fixed << std::setprecision(1) << totRain + << ";rainrate:" << std::fixed << std::setprecision(1) << rainRate << ";"; + return retString.str(); +} + std::string ProtocolOregon::decodeF824(const std::string &data) { uint64_t value = TelldusCore::hexTo64l(data); diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index f0c757a8..dbf4aaa5 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -19,6 +19,8 @@ protected: static std::string decodeEA4C(const std::string &data); static std::string decode1A2D(const std::string &data); static std::string decodeF824(const std::string &data); + static std::string decode1984(const std::string &data, const std::wstring &model); + static std::string decode2914(const std::string &data); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ diff --git a/telldus-core/tdtool/main.cpp b/telldus-core/tdtool/main.cpp index c21b1e98..b75d281b 100644 --- a/telldus-core/tdtool/main.cpp +++ b/telldus-core/tdtool/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "../client/telldus-core.h" #ifdef _WINDOWS @@ -140,13 +141,27 @@ int list_devices() { int sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); if(sensorStatus == 0){ - printf("\n\nSENSORS:\n\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "LAST UPDATED"); + printf("\n\nSENSORS:\n\n%-20s\t%-20s\t%-5s\t%-5s\t%-8s\t%-20s\t%-20s\t%-20s\n", "PROTOCOL", "MODEL", "ID", "TEMP", "HUMIDITY", "RAIN", "WIND", "LAST UPDATED"); } while(sensorStatus == 0){ char tempvalue[DATA_LENGTH]; tempvalue[0] = 0; char humidityvalue[DATA_LENGTH]; humidityvalue[0] = 0; + char windvalue[DATA_LENGTH]; + windvalue[0] = 0; + char winddirectionvalue[DATA_LENGTH]; + winddirectionvalue[0] = 0; + char windaveragevalue[DATA_LENGTH]; + windaveragevalue[0] = 0; + char windgustvalue[DATA_LENGTH]; + windgustvalue[0] = 0; + char rainvalue[DATA_LENGTH]; + rainvalue[0] = 0; + char raintotvalue[DATA_LENGTH]; + raintotvalue[0] = 0; + char rainratevalue[DATA_LENGTH]; + rainratevalue[0] = 0; char timeBuf[80]; timeBuf[0] = 0; time_t timestamp = 0; @@ -162,7 +177,98 @@ int list_devices() { strcat(humidityvalue, "%"); strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); } - printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, timeBuf); + + if (dataTypes & TELLSTICK_RAINRATE) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINRATE, rainratevalue, DATA_LENGTH, (int *)×tamp); + strcat(rainratevalue, " mm/h, "); + strcat(rainvalue, rainratevalue); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + + if (dataTypes & TELLSTICK_RAINTOTAL) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINTOTAL, raintotvalue, DATA_LENGTH, (int *)×tamp); + //TODO detta blir väl fel, kan väl hamna i andra ordningar, eller hur? + strcat(raintotvalue, " mm"); + strcat(rainvalue, raintotvalue); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + + if (dataTypes & TELLSTICK_WINDDIRECTION) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDDIRECTION, winddirectionvalue, DATA_LENGTH, (int *)×tamp); + //TODO or use charToInteger in common? + std::stringstream inputstream; + inputstream << winddirectionvalue; + int direction; + inputstream >> direction; + direction = direction / 22.5; + std::string directionabbrev = "N"; + switch (direction) { + case 1: + directionabbrev = "NNE"; + break; + case 2: + directionabbrev = "NE"; + break; + case 3: + directionabbrev = "ENE"; + break; + case 4: + directionabbrev = "E"; + break; + case 5: + directionabbrev = "ESE"; + break; + case 6: + directionabbrev = "SE"; + break; + case 7: + directionabbrev = "SSE"; + break; + case 8: + directionabbrev = "S"; + break; + case 9: + directionabbrev = "SSW"; + break; + case 10: + directionabbrev = "SW"; + break; + case 11: + directionabbrev = "WSW"; + break; + case 12: + directionabbrev = "W"; + break; + case 13: + directionabbrev = "WNW"; + break; + case 14: + directionabbrev = "NW"; + break; + case 15: + directionabbrev = "NNW"; + break; + } + strcat(windvalue, directionabbrev.c_str()); + strcat(windvalue, ", "); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + + if (dataTypes & TELLSTICK_WINDAVERAGE) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDAVERAGE, windaveragevalue, DATA_LENGTH, (int *)×tamp); + strcat(windaveragevalue, " m/s ("); + strcat(windvalue, windaveragevalue); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + + if (dataTypes & TELLSTICK_WINDGUST) { + tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDGUST, windgustvalue, DATA_LENGTH, (int *)×tamp); + strcat(windgustvalue, " m/s) "); + strcat(windvalue, windgustvalue); + strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", localtime(×tamp)); + } + + printf("%-20s\t%-20s\t%-5i\t%-5s\t%-8s\t%-20s\t%-20s\t%-20s\n", protocol, model, sensorId, tempvalue, humidityvalue, rainvalue, windvalue, timeBuf); sensorStatus = tdSensor(protocol, DATA_LENGTH, model, DATA_LENGTH, &sensorId, &dataTypes); } @@ -209,6 +315,36 @@ int list_kv_sensors() { printf("\thumidity=%s", humidityvalue); } + if (dataTypes & TELLSTICK_WINDDIRECTION) { + char winddirectionvalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDDIRECTION, winddirectionvalue, DATA_LENGTH, (int *)×tamp); + printf("\twinddirection=%s", winddirectionvalue); + } + + if (dataTypes & TELLSTICK_WINDAVERAGE) { + char windaveragevalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDAVERAGE, windaveragevalue, DATA_LENGTH, (int *)×tamp); + printf("\twindaverage=%s", windaveragevalue); + } + + if (dataTypes & TELLSTICK_WINDGUST) { + char windgustvalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_WINDGUST, windgustvalue, DATA_LENGTH, (int *)×tamp); + printf("\twindgust=%s", windgustvalue); + } + + if (dataTypes & TELLSTICK_RAINRATE) { + char rainratevalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINRATE, rainratevalue, DATA_LENGTH, (int *)×tamp); + printf("\trainrate=%s", rainratevalue); + } + + if (dataTypes & TELLSTICK_RAINTOTAL) { + char raintotalvalue[DATA_LENGTH]; + tdSensorValue(protocol, model, sensorId, TELLSTICK_RAINTOTAL, raintotalvalue, DATA_LENGTH, (int *)×tamp); + printf("\traintotal=%s", raintotalvalue); + } + if (dataTypes & (TELLSTICK_TEMPERATURE | TELLSTICK_HUMIDITY)) { /* timestamp has been set, print time & age */ /* (age is more useful on e.g. embedded systems From 979bee617419bfdaa9268d4374568f7cf482adf8 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 9 Sep 2013 14:20:46 +0200 Subject: [PATCH 2172/2215] Added device type RollerTrol, this closes #310 --- telldus-gui/TelldusGui/data/telldus/devices.xml | 3 +++ .../TelldusGui/data/telldus/resources.qrc | 1 + .../TelldusGui/images/vendors/rollertrol.png | Bin 0 -> 7651 bytes 3 files changed, 4 insertions(+) create mode 100644 telldus-gui/TelldusGui/images/vendors/rollertrol.png diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index 1ed81603..fc77b004 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -126,6 +126,9 @@ Blinds Blinds (version 2) + + Blinds + Projector screen diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index b0214c11..7b3e0a59 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -49,6 +49,7 @@ ../../images/vendors/nexa.png ../../images/vendors/otio.png ../../images/vendors/proove.png + ../../images/vendors/rollertrol.png ../../images/vendors/roxcore.png ../../images/vendors/rusta.png ../../images/vendors/sartano.png diff --git a/telldus-gui/TelldusGui/images/vendors/rollertrol.png b/telldus-gui/TelldusGui/images/vendors/rollertrol.png new file mode 100644 index 0000000000000000000000000000000000000000..4fc3c0617b524c7d57d41dab26f699e0bca670ef GIT binary patch literal 7651 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 Date: Wed, 11 Sep 2013 14:05:56 +0200 Subject: [PATCH 2173/2215] Fix for sensor plugin in TelldusCenter in Linux. This closes #181 kind of. --- telldus-gui/Plugins/QML/CMakeLists.txt | 4 ++++ telldus-gui/Plugins/QML/qmlview.cpp | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/telldus-gui/Plugins/QML/CMakeLists.txt b/telldus-gui/Plugins/QML/CMakeLists.txt index d008a815..6098a415 100644 --- a/telldus-gui/Plugins/QML/CMakeLists.txt +++ b/telldus-gui/Plugins/QML/CMakeLists.txt @@ -2,6 +2,9 @@ SET(QT_USE_QTDECLARATIVE TRUE) SET( Plugin_NAME "QMLLoader" ) +if(COMMAND cmake_policy) + cmake_policy(SET CMP0005 NEW) +endif(COMMAND cmake_policy) SET( Plugin_SRCS scriptfunctionwrapper.cpp @@ -30,5 +33,6 @@ ELSEIF (APPLE) SET(QT_COMPONENTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/declarative") ELSE() SET(QT_COMPONENTS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/declarative") + ADD_DEFINITIONS( -DPLUGIN_LIB_PATH=${CMAKE_INSTALL_PREFIX}/${PLUGIN_LIB_FULL_PATH}/declarative ) ENDIF() INCLUDE( ${CMAKE_SOURCE_DIR}/3rdparty/qt-components-desktop.cmake NO_POLICY_SCOPE ) diff --git a/telldus-gui/Plugins/QML/qmlview.cpp b/telldus-gui/Plugins/QML/qmlview.cpp index 5fd8d2f7..09849f85 100644 --- a/telldus-gui/Plugins/QML/qmlview.cpp +++ b/telldus-gui/Plugins/QML/qmlview.cpp @@ -6,6 +6,9 @@ #include #include +#define DEFINE_STRING_HELPER(X) #X +#define DEFINE_STRING(X) DEFINE_STRING_HELPER(X) + class QMLView::PrivateData { public: QDir baseDir; @@ -32,6 +35,10 @@ QMLView::QMLView(const QDir &dir, const QScriptValue &object) : paths << pluginsDir.absolutePath(); } +#if defined(Q_OS_UNIX) + paths << DEFINE_STRING(PLUGIN_LIB_PATH); +#endif + eng->setImportPathList(paths); d = new PrivateData; From 103eaf05e0c5c849ecfe033aae349642fec4fa31 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 11 Sep 2013 14:29:46 +0200 Subject: [PATCH 2174/2215] Inital commit, support for rain and wind sensors. --- telldus-gui/Plugins/Sensors/CMakeLists.txt | 2 + telldus-gui/Plugins/Sensors/SensorView.qml | 30 ++++++ telldus-gui/Plugins/Sensors/__init__.js | 98 +++++++++++++++--- telldus-gui/Plugins/Sensors/icon_rain.png | Bin 0 -> 1524 bytes telldus-gui/Plugins/Sensors/icon_wind.png | Bin 0 -> 456 bytes telldus-gui/Plugins/Sensors/sensor.cpp | 32 +++++- telldus-gui/Plugins/Sensors/sensor.h | 15 +++ .../Plugins/TelldusCore/tellduscoreplugin.cpp | 5 + 8 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 telldus-gui/Plugins/Sensors/icon_rain.png create mode 100644 telldus-gui/Plugins/Sensors/icon_wind.png diff --git a/telldus-gui/Plugins/Sensors/CMakeLists.txt b/telldus-gui/Plugins/Sensors/CMakeLists.txt index 92042b57..a6fa5c58 100644 --- a/telldus-gui/Plugins/Sensors/CMakeLists.txt +++ b/telldus-gui/Plugins/Sensors/CMakeLists.txt @@ -28,7 +28,9 @@ SET( Plugin_EXTRA header_bg.png icon.png icon_humidity.png + icon_rain.png icon_temp.png + icon_wind.png main.qml HeaderTitle.qml row_bg.png diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml index f577b9d0..49ae32f3 100644 --- a/telldus-gui/Plugins/Sensors/SensorView.qml +++ b/telldus-gui/Plugins/Sensors/SensorView.qml @@ -110,6 +110,36 @@ Item{ icon: "icon_humidity.png" lastUpdated: visible ? modelData.sensorValue(2).lastUpdated : new Date() } + SensorValue { + visible: modelData.hasRainRate + text: visible ? modelData.sensorValue(4).value + ' mm/h' : '' + icon: "icon_rain.png" + lastUpdated: visible ? modelData.sensorValue(4).lastUpdated : new Date() + } + SensorValue { + visible: modelData.hasRainTotal + text: visible ? modelData.sensorValue(8).value + ' mm' : '' + icon: "icon_rain.png" + lastUpdated: visible ? modelData.sensorValue(8).lastUpdated : new Date() + } + SensorValue { + visible: modelData.hasWindDirection + text: visible ? getWindDirection.callWith(modelData.sensorValue(16).value): '' + icon: "icon_wind.png" + lastUpdated: visible ? modelData.sensorValue(16).lastUpdated : new Date() + } + SensorValue { + visible: modelData.hasWindAverage + text: visible ? modelData.sensorValue(32).value + ' m/s' : '' + icon: "icon_wind.png" + lastUpdated: visible ? modelData.sensorValue(32).lastUpdated : new Date() + } + SensorValue { + visible: modelData.hasWindGust + text: visible ? '(' + modelData.sensorValue(64).value + ' m/s)' : '' + icon: "icon_wind.png" + lastUpdated: visible ? modelData.sensorValue(64).lastUpdated : new Date() + } } } diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js index 5012dba4..c83a43a4 100644 --- a/telldus-gui/Plugins/Sensors/__init__.js +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -27,12 +27,18 @@ com.telldus.sensors = function() { } tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_TEMPERATURE); tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_HUMIDITY); + tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_RAINRATE); + tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_RAINTOTAL); + tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_WINDDIRECTION); + tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_WINDAVERAGE); + tryFetchValue(p, m, id, types, com.telldus.core.TELLSTICK_WINDGUST); } com.telldus.core.sensorEvent.connect(sensorEvent); view = new com.telldus.qml.view({ - deleteSensor: deleteSensor + deleteSensor: deleteSensor, + getWindDirection: getWindDirection }); view.setProperty('sensorModel', sensorList); @@ -82,6 +88,44 @@ com.telldus.sensors = function() { } } + function getWindDirection(degrees){ + var number = degrees/22.5; + switch(number){ + case 1: + return 'NNE'; + case 2: + return 'NE'; + case 3: + return 'ENE'; + case 4: + return 'E'; + case 5: + return 'ESE'; + case 6: + return 'SE'; + case 7: + return 'SSE'; + case 8: + return 'S'; + case 9: + return 'SSW'; + case 10: + return 'SW'; + case 11: + return 'WSW'; + case 12: + return 'W'; + case 13: + return 'WNW'; + case 14: + return 'NW'; + case 15: + return 'NNW'; + default: + return 'N'; + } + } + function loadSensorModel(){ var settings = new com.telldus.settings(); var sensors = new com.telldus.qml.array(); @@ -99,6 +143,46 @@ com.telldus.sensors = function() { return sensors; } + function pickSensorValues(sensor){ + var allValues = new Array(); + if(sensor.hasHumidity){ + var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_HUMIDITY); + var value = {type: com.telldus.core.TELLSTICK_HUMIDITY, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; + allValues.push(value); + } + if(sensor.hasRainRate){ + var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_RAINRATE); + var value = {type: com.telldus.core.TELLSTICK_RAINRATE, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; + allValues.push(value); + } + if(sensor.hasRainTotal){ + var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_RAINTOTAL); + var value = {type: com.telldus.core.TELLSTICK_RAINTOTAL, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; + allValues.push(value); + } + if(sensor.hasTemperature){ + var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_TEMPERATURE); + var value = {type: com.telldus.core.TELLSTICK_TEMPERATURE, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; + allValues.push(value); + } + if(sensor.hasWindDirection){ + var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_WINDDIRECTION); + var value = {type: com.telldus.core.TELLSTICK_WINDDIRECTION, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; + allValues.push(value); + } + if(sensor.hasWindAverage){ + var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_WINDAVERAGE); + var value = {type: com.telldus.core.TELLSTICK_WINDAVERAGE, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; + allValues.push(value); + } + if(sensor.hasWindGust){ + var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_WINDGUST); + var value = {type: com.telldus.core.TELLSTICK_WINDGUST, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; + allValues.push(value); + } + return allValues; + } + function saveSensorModel(){ var settings = new com.telldus.settings(); var sensorProperties = new Array(); @@ -106,17 +190,7 @@ com.telldus.sensors = function() { for (var i = 0; i < sensorList.length; ++i) { var sensor = sensorList.get(i); - var allValues = new Array(); - if(sensor.hasHumidity){ - var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_HUMIDITY); - var value = {type: com.telldus.core.TELLSTICK_HUMIDITY, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; - allValues.push(value); - } - if(sensor.hasTemperature){ - var sensorValue = sensor.sensorValue(com.telldus.core.TELLSTICK_TEMPERATURE); - var value = {type: com.telldus.core.TELLSTICK_TEMPERATURE, lastUpdated: sensorValue.lastUpdated, value: sensorValue.value}; - allValues.push(value); - } + var allValues = pickSensorValues(sensor); var sensorProp = {protocol:sensor.protocol, model:sensor.model, id:sensor.id, values:allValues, name:sensor.name, showInList:sensor.showInList}; sensorProperties.push(sensorProp); diff --git a/telldus-gui/Plugins/Sensors/icon_rain.png b/telldus-gui/Plugins/Sensors/icon_rain.png new file mode 100644 index 0000000000000000000000000000000000000000..2adf5435776542e0a6e1a67ce432a2cd5179e4b2 GIT binary patch literal 1524 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*u2 z3kW+vM8)s`00neOL_t(Y$F){zj1^TD{=QrF>haJlo>CwcGHd+*${edm1VQbh1;itj!|Bu&#aP5*y?Bz@oaeV-%%<*dhX zoEjq{0G(R#Mu3M()1>oWdcS+e9t_cQk0N4>X~waORf$NFBqAap0YFFq0s=ykm5Lt( zK_v*F{93K%SAu$CXU=_Y$wzCao;ca_6aj)DSAVmu^NVih$rff+mSt(0mNAgbBNF(& z7X%gG_dU;BvA(-~{tEyqzPEBi_lB*#_s_n#;`>3R>Q{V{k1g%I@UCaakEuBm08N@^ zS%xTz8jVKS2oID-9LHIfiHL}FEMM!*y!G!-y(xuc)|SuK+OK+cu=s9b=z6f=3d!W>bL{{UbUfjuO>OIbyC-JcfL7qHh_-h zpBu3R6ltwRyKUtjR@dq2~QFTTI}`Tu@$iUS``ZOO~zqnGEVtv-8Vu(*h(XJNpNgt=%-lQmnP6*4p=d zfS?c*!OE`gZMz4q{ma>h2L8&jH5W{uI(dA{Po`zXCQajdT>y}&F$(!0fuI1S%sB10 z*R=iVCrA46rJY;*_6}FK{q^{rRT~CJv!n_V4hTXh3WT-R^E`KKV^8mg>o$M&eebUQ zjm7tQ(W*{&FnV#2l7K@b1}q0j*i zl2oc=`MO75Teg17j^RR{G_K{=S%1FyZ!>Du%GBBa?CaO-p1JM#31f5008NrO2USu8 zaBd0NynWAg3p-YC`u>-&+wWVCSu*$P!1t=Y*E;d2VwMCz;v7_isz7oSgey00xqRLW zjX3$`40>d(`o?{;FF5m*%v$CUgFrKBD);D62KeRH9qscMkH|WJdem%RuxQoBtvMAF z1*Jjd-$4R9_to1MEFK8s!&n1R)6BYmao;{Yl<#u~Zj3?Ru<%u5vMG~~u2%dJS+DqB z>%_6OYH-sNOUt%*jY_TcsM;t9x_bH)@rM&9xkb>`)A#NtT~EBVq8>NTJL8m7e=~W) z*dsnz^Y!T`9ZT}-A9gPP;@d`?O#j{S|G4U+nP*K4d?g}3?Aq5~k4~R*oC7(IV`#0@ zG);|3O=^rW#-zsBg2LWd@p)grF3I5T=l`>Q%XatNH0cAcyqB2NF?N<^X=+S*fM~7# za?40wsqzN^m^I^!;mQ*D-o01OEcM;GG_Vu1+&pQN=`DOJ?zuyV-n zJfxI71S^)LB59H&zp@PGkcZ}iGif$#>?QADNRudlNRou4Qc5)%jq*Y?*s=K`f#8Y- zi@w{w8$iDfM^^&?S!N+1d60R!RuT}b*Xv3t8e_E9naw5~J)vwKDThKJz-ODcJ^jwd ztrN$^CVhC$Wo4yVDhl$F!%c(i-o3~3yq1<0T5FRe85kHa#g$$i z@xsA>LIiY|O_QZ@6ltw1mCBegV}c-{YnUWS!Z3`YC`l4)?O|W7l~O?v)M~ZSqellp aK=Oa$T!E9m+z!Px#24YJ`L;&~z_W<~U>c5x(000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2i*w^ z3M3$ZbOf0I00BrzL_t(o!|l~SOWRQt#_>-YDOAv@Sd0ILxOC{!LdhEtq@W{|l%UHA{0Mf-O(^^xIKw^5{c_K_&r>K& zywOcP&}HQSIY7@p`pX#4oY%0O0-#tZmGA2xU>dWi;2FvoLp3Vt2>zfJ7aigl4NT$} zz6DUS5j1s%w=KP1EaE#pVHJC+0PfRe?8FzWU^nUqj&Oy67~RJd08Q=SHACO+CaEp5h!^IO!z72tMO9{`WBU@d2BtryfBCPcRzk z*cUeZA~IqlUT6q~j8*ry3!sL-nez>PVh+y(;$2v9BW$>idHhb51=*l_A63L49^oRO yZ&L$g)rdXGeIN&DD?qj73wGR!7xEqGgzfvalues.contains(TELLSTICK_RAINRATE); +} + +bool Sensor::hasRainTotal() const { + return d->values.contains(TELLSTICK_RAINTOTAL); +} + bool Sensor::hasTemperature() const { return d->values.contains(TELLSTICK_TEMPERATURE); } +bool Sensor::hasWindDirection() const { + return d->values.contains(TELLSTICK_WINDDIRECTION); +} + +bool Sensor::hasWindAverage() const { + return d->values.contains(TELLSTICK_WINDAVERAGE); +} + +bool Sensor::hasWindGust() const { + return d->values.contains(TELLSTICK_WINDGUST); +} + QObject * Sensor::sensorValue(int type) { return (d->values.contains(type) ? d->values[type] : 0); } @@ -90,6 +110,16 @@ void Sensor::setValue(int type, const QString &value, const QDateTime ×tamp emit hasTemperatureChanged(); } else if (type == TELLSTICK_HUMIDITY) { emit hasHumidityChanged(); + } else if (type == TELLSTICK_RAINRATE) { + emit hasRainRateChanged(); + } else if (type == TELLSTICK_RAINTOTAL) { + emit hasRainTotalChanged(); + } else if (type == TELLSTICK_WINDDIRECTION) { + emit hasWindDirectionChanged(); + } else if (type == TELLSTICK_WINDAVERAGE) { + emit hasWindAverageChanged(); + } else if (type == TELLSTICK_WINDGUST) { + emit hasWindGustChanged(); } } diff --git a/telldus-gui/Plugins/Sensors/sensor.h b/telldus-gui/Plugins/Sensors/sensor.h index 6683e305..82a32f81 100644 --- a/telldus-gui/Plugins/Sensors/sensor.h +++ b/telldus-gui/Plugins/Sensors/sensor.h @@ -13,6 +13,11 @@ class Sensor : public QObject Q_OBJECT Q_PROPERTY(bool hasHumidity READ hasHumidity NOTIFY hasHumidityChanged) Q_PROPERTY(bool hasTemperature READ hasTemperature NOTIFY hasTemperatureChanged) + Q_PROPERTY(bool hasRainRate READ hasRainRate NOTIFY hasRainRateChanged) + Q_PROPERTY(bool hasRainTotal READ hasRainTotal NOTIFY hasRainTotalChanged) + Q_PROPERTY(bool hasWindDirection READ hasWindDirection NOTIFY hasWindDirectionChanged) + Q_PROPERTY(bool hasWindAverage READ hasWindAverage NOTIFY hasWindAverageChanged) + Q_PROPERTY(bool hasWindGust READ hasWindGust NOTIFY hasWindGustChanged) Q_PROPERTY(int id READ id WRITE setId NOTIFY idChanged) Q_PROPERTY(QString model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) @@ -36,7 +41,12 @@ public: QString protocol() const; void setProtocol(const QString &protocol); + bool hasRainRate() const; + bool hasRainTotal() const; bool hasTemperature() const; + bool hasWindDirection() const; + bool hasWindAverage() const; + bool hasWindGust() const; bool showInList() const; Q_INVOKABLE QObject *sensorValue(int type); @@ -47,7 +57,12 @@ public: signals: void idChanged(); void hasHumidityChanged(); + void hasRainRateChanged(); + void hasRainTotalChanged(); void hasTemperatureChanged(); + void hasWindDirectionChanged(); + void hasWindAverageChanged(); + void hasWindGustChanged(); void modelChanged(); void nameChanged(); void protocolChanged(); diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp index 131e1ee0..8cd79979 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp @@ -32,6 +32,11 @@ void TelldusCorePlugin::initialize ( const QString & key, QScriptEngine * engine value.setProperty("TELLSTICK_TEMPERATURE", TELLSTICK_TEMPERATURE); value.setProperty("TELLSTICK_HUMIDITY", TELLSTICK_HUMIDITY); + value.setProperty("TELLSTICK_RAINRATE", TELLSTICK_RAINRATE); + value.setProperty("TELLSTICK_RAINTOTAL", TELLSTICK_RAINTOTAL); + value.setProperty("TELLSTICK_WINDDIRECTION", TELLSTICK_WINDDIRECTION); + value.setProperty("TELLSTICK_WINDAVERAGE", TELLSTICK_WINDAVERAGE); + value.setProperty("TELLSTICK_WINDGUST", TELLSTICK_WINDGUST); engine->globalObject().property("com").property("telldus").setProperty("core", value); } From b73eae288f8c0800b0e073a1047c9362dfbc0da4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 11 Sep 2013 14:32:33 +0200 Subject: [PATCH 2175/2215] Possiblity to add sensors from TelldusCenter to be visible in Telldus Live! This closes #186. --- telldus-gui/Plugins/Live/LiveMessageToken.cpp | 8 +++ telldus-gui/Plugins/Live/LiveMessageToken.h | 2 + telldus-gui/Plugins/Live/__init__.js | 61 +++++++++++++++++- telldus-gui/Plugins/Sensors/SensorList.qml | 12 +++- telldus-gui/Plugins/Sensors/SensorView.qml | 16 ++++- telldus-gui/Plugins/Sensors/__init__.js | 62 +++++++++++++++++-- telldus-gui/Plugins/Sensors/sensor.cpp | 12 +++- telldus-gui/Plugins/Sensors/sensor.h | 4 ++ 8 files changed, 168 insertions(+), 9 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.cpp b/telldus-gui/Plugins/Live/LiveMessageToken.cpp index 9c64f6d0..8ef4f84f 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.cpp +++ b/telldus-gui/Plugins/Live/LiveMessageToken.cpp @@ -166,3 +166,11 @@ void LiveMessageTokenScriptWrapper::set(const QString &key, const QString &value token.stringVal = value; p_token.dictVal[key] = token; } + +void LiveMessageTokenScriptWrapper::set(const QString &key, const QDateTime value) { + p_token.valueType = LiveMessageToken::Dictionary; + LiveMessageToken token; + token.valueType = LiveMessageToken::Int; + token.intVal = value.toMSecsSinceEpoch(); + p_token.dictVal[key] = token; +} diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.h b/telldus-gui/Plugins/Live/LiveMessageToken.h index a94f476d..5806ecfe 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.h +++ b/telldus-gui/Plugins/Live/LiveMessageToken.h @@ -2,6 +2,7 @@ #define LIVEMESSAGETOKEN_H #include +#include #include #include #include @@ -42,6 +43,7 @@ public slots: void set(const QString &key, int value); void set(const QString &key, const QString &value); + void set(const QString &key, const QDateTime value); private: LiveMessageToken p_token; diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 1fbb20f0..0ebaec0c 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -69,6 +69,10 @@ com.telldus.live = function() { } } + function isRegisteredToLive(){ + return isRegistered; + } + function registered(msg) { if (menuId > 0) { com.telldus.systray.removeMenuItem(menuId); @@ -115,6 +119,58 @@ com.telldus.live = function() { socket.sendMessage(msg); } + function sendSensorsReport(sensorList) { + if (!isRegistered) { + return; + } + msg = new LiveMessage("SensorsReport"); + + list = new LiveMessageToken(); + for( i in sensorList ) { + sensorFrame = new LiveMessageToken(); + sensor = new LiveMessageToken(); + sensor.set('name', sensorList[i].name); + sensor.set('protocol', sensorList[i].protocol); + sensor.set('model', sensorList[i].model); + sensor.set('sensor_id', sensorList[i].id); + var valueList = new LiveMessageToken(); + for( j in sensorList[i].values ){ + valueElement = new LiveMessageToken() + valueElement.set('type', sensorList[i].values[j].type); + valueElement.set('lastUp', sensorList[i].values[j].lastUpdated); + valueElement.set('value', sensorList[i].values[j].value); + valueList.add(valueElement); + } + sensorFrame.add(sensor); + sensorFrame.add(valueList); + list.add(sensorFrame); + } + msg.appendToken(list); + socket.sendMessage(msg); + } + + function sendSensorValues(sensor, sensorvalues){ + if (!isRegistered) { + return; + } + msg = new LiveMessage("SensorEvent"); + sensortoken = new LiveMessageToken(); + sensortoken.set('protocol', sensor.protocol); + sensortoken.set('model', sensor.model); + sensortoken.set('sensor_id', sensor.id); + var valueList = new LiveMessageToken(); + for( j=0; j 0){ + com.telldus.live.sendSensorsReport(liveSensors); + } + } + function sensorEvent(protocol, model, id, dataType, value, timestamp, avoidSave) { var sensor = 0; @@ -222,6 +268,12 @@ com.telldus.sensors = function() { } sensor.setValue(dataType, value, timestamp); + if (sensor.sendToLive){ + sensorValues = pickSensorValues(sensor) + if (allValuesUpdated(sensorValues)) { + com.telldus.live.sendSensorValues(sensor, sensorValues); + } + } if(!avoidSave){ saveSensorModel(); diff --git a/telldus-gui/Plugins/Sensors/sensor.cpp b/telldus-gui/Plugins/Sensors/sensor.cpp index 64b730fd..9723b2d8 100644 --- a/telldus-gui/Plugins/Sensors/sensor.cpp +++ b/telldus-gui/Plugins/Sensors/sensor.cpp @@ -5,7 +5,7 @@ class Sensor::PrivateData { public: - bool hasTemperature, hasHumidity, hasRainRate, hasRainTotal, hasWindDirection, hasWindAverage, hasWindGust, showInList; + bool hasTemperature, hasHumidity, hasRainRate, hasRainTotal, hasWindDirection, hasWindAverage, hasWindGust, showInList, sendToLive; int id; QString model, name, protocol; QDateTime lastUpdated; @@ -18,6 +18,7 @@ Sensor::Sensor(QObject *parent) : d = new PrivateData; d->id = 0; d->showInList = false; + d->sendToLive = false; } Sensor::~Sensor() { @@ -131,3 +132,12 @@ void Sensor::setShowInList(bool show){ d->showInList = show; emit showInListChanged(); } + +bool Sensor::sendToLive() const{ + return d->sendToLive; +} + +void Sensor::setSendToLive(bool send){ + d->sendToLive = send; + emit sendToLiveChanged(); +} diff --git a/telldus-gui/Plugins/Sensors/sensor.h b/telldus-gui/Plugins/Sensors/sensor.h index 82a32f81..66615f24 100644 --- a/telldus-gui/Plugins/Sensors/sensor.h +++ b/telldus-gui/Plugins/Sensors/sensor.h @@ -23,6 +23,7 @@ class Sensor : public QObject Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString protocol READ protocol WRITE setProtocol NOTIFY protocolChanged) Q_PROPERTY(bool showInList READ showInList WRITE setShowInList NOTIFY showInListChanged) + Q_PROPERTY(bool sendToLive READ sendToLive WRITE setSendToLive NOTIFY sendToLiveChanged) public: explicit Sensor(QObject *parent = 0); @@ -48,11 +49,13 @@ public: bool hasWindAverage() const; bool hasWindGust() const; bool showInList() const; + bool sendToLive() const; Q_INVOKABLE QObject *sensorValue(int type); Q_INVOKABLE void setValue(int type, const QString &value, const QDateTime ×tamp); Q_INVOKABLE void setName(const QString &name); Q_INVOKABLE void setShowInList(bool show); + Q_INVOKABLE void setSendToLive(bool send); signals: void idChanged(); @@ -67,6 +70,7 @@ signals: void nameChanged(); void protocolChanged(); void showInListChanged(); + void sendToLiveChanged(); private: class PrivateData; From 7c84ee3921fb9c0b2fc776bc0b66d5eaecd4fdb3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 11 Sep 2013 14:33:31 +0200 Subject: [PATCH 2176/2215] Changed image to make it more generic --- .../TelldusGui/images/devices/hasta.png | Bin 14273 -> 14188 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/telldus-gui/TelldusGui/images/devices/hasta.png b/telldus-gui/TelldusGui/images/devices/hasta.png index 3e6f9288727bd3f8d2d02724dd7adca56151065f..7cc9e40080989ca5a006d233023a39060e95a552 100644 GIT binary patch literal 14188 zcmbt*Ra6{2(=fCYE$;5_PSN6Si@R=dEAA8)U)+ip_r({t#R?R6e~P=ietj?h>pwY@ ziCkndnKQ{5iPlh)M@J<=g@c1bS5%Mz{KM)017yU1tth}# zD$C2jz5lQN>MBe5H-qA;VBii1hlcw+A%`k*sFwgvl)DHrsI4QK$nJo>rRs?V6GlWn)ObR|aNvY6J z>^}-+W0a}C8aqSs`~z11yu1m0T{YWPX5P3KSI^sDbDtFBZM)SMHH_IUDEL6!n^U5=9m@aE<9prJBH=4` z+%_D1d*X2Z$%Uix;1LKU(2FxL=KZEvK3XhAA8qcE5!b9Z*&(e`-*X+|S_ zZ`fkqWQ54+AZ31VdBuHnWNlMBtAow8m``9JjM;-Gh3IvU6;#zJbm&uu z^}JTs*};^@Nn#}%Z$qoL&^#)%2^;chh-!*XZcAH9-y-^tzl+B5uN0>FQ0`x_hqxZ6 zBI@dQ?r$dUe;Et?E?#g2+|tt~ZfI{CRjS>T)`vK5P(>=J*YN-(pm;b^;4~K& zGA^wNAu|H4yqGjC&gckNtr=-d0hAA;>IM9^2UXl!;)E@Hup&#v0vRNXhQJSz zit77t+?UPVLEvID?szPh;NYyclY{+z_aBEd-TotjtK6v><`lmsTv%(Xh3XD)8jd9? zM7|cIj)6>0d(#PKCM~h8P=1tyq5u@hEFXSAsXXEozcXu%^JBC1NF}$jW6rbmot1ni zgU^quw5abMe7PLjY^$( zV!0P}D2t(Dofe&3@)C^h5HB3e$>OByQmkjZ+eul=ccK>Zz2ph=R1kE_4lD{xsEs{> zr39a_PvmDnD$Gi8;wUrXOwI_s_!Bg+bw_255UCMBD1~bY(I3DFz*Q#rdYeqHG=f3L zbO4J;iKx$jUC*-PpMa2#^ITbhl()z`Qpm+BfznU$!<5B@9RHV%Ae;BFwuUDlM`bd~ zQ=Ewbi*?OE0lxzvQ)9zI?Ilv5ur$$~R_UM#FdDUG29@W+pH8J&q+H!Ab6&rH;&SE$ zA4453Z;I|4*P%U6Wv{jf3O)3qZf}<_R|A_L&B1@CdE>jeP0HiOnOBRo@dYbTHP8A` zScp~!8`!{g+yL{+z@=umBDPdkh2L0NSf>W1d&RQM+cJZDca5*gwM6d@)8E8ZgWt-+ zZ|71t8~Y+8UWO93+bS08Hk^@o`-!q9#O&CsG=3&S4(HuRxgi{=A`mL&z$L|yIwuei zzO?&^6`$MC0@S-i5#12Y&v3>6BZUBebDYq~aB}(RYLx@t=OCwl>1B@feNsH|*yQi_ zWY0TiaLd1qc3zFt8@`F%E_lDcjGp|3%UHjX2WxKrycF}@{Zies+9&#UCapGh7)fz@ zenAP;I)ovuImR<3NM!6&gY1vHBooVb`t00 zxTf8hULh6&uNtrpJ54y^YR!9rCe~b{+lN+UHavo8fbB5D9h+u@$>{Q)glyYd->R|b z?)YJkK^%14Yd=Fi_p0LgzQ#LzvIlCuWR{*@CZjgiuBtm9cwf^}tU$wSJ@wzPuBlUV zGw#bBWP<*Wf3Wzc)4J)bk3sF@E(^Yw$D*ZWWyT|%UJ{=}h9N?}jOYCjhwlaU%8b}~ z(cls(i!}ebZ6b?RDl%}&R~qVaOR$tfcv9$qJp;x^OLZ(?Sn6qN`A*h55j1|obL^Va z;O;`RqhT4?@;V&&qH9>4v3a%=>F{}PdC@e`5te&BR@s9ycoY%F|e0PUe~$mj#taVYL0&iM;40NT^(%MqhU z?BuA4tBYf<^Hh(AJS?vaKO`pulriqN4TItdi=`rDx2`EBe^;4@$};Z`?W(K}jMrwm z5iO!ph`&+^kb2+RoSnBgU%f5Oy1-B23y|wXFR?i}SXE_3eTd6;06v5;G>nhm+}>-| z*k`RGYL0Ohtn?58#ABs4pW5RNlXw#>!#=8&C!GJW!nhaiIGemp7jQwBN?E9PD@QS4 zl`Ns8{@Q^9iql5KMk2zuY?4ADb_(q24`d%U5 zu-xkKUL_vP%9g%B!hHNLFYq{+C3-!e74|&(msnDRp2^!BD9__Mg|!liL38S#8uJOJ zkYs0HNT8P~=)xflkd@JjXv(h$s@aR0WoSH8^S>BIDr?Ewr|23wKUx>yf_PBml$%ZqR&}XZyevJwnm;on8sfcZSIn(7+%M>@c?$Oa zxsC@`rEomeKEK8_>AQ42BKqehzaLW-4-oZtoO3w7&nlCj0y|!(?6HcUMK<|AFsDY` zQHLq`i)#{TvB_F@@^!Nw9x`J^z9J+^u5j25j|7_xeL1eYHt;SJ^Es+?*V{gnH~a0C zHpHhBV=BN#qBjTwU>7dM;Ug#*(G<%N#YKO#CMxpypk#T1$07o*Yr!qDvQOs&jzx+0 zRIGimK474XJ-Rcid1#9|B6X-=c-go=p5C+BSkf0+uAhPG<=@V%or{=ah#YVE5}cA; zkqZQkFy&rt`>#O51}AV66SXGYd)`Ods%WgSKD^x;0> zJ|-kc1TkLsJ*Q+nNzW*b`>HlLvpK`p>h)L^zDlJ$ic{Q@d$pfvz*y((~e|^xzFP2%NkeaW-*F@I_36NNo zO`FCKjQ)xVWE#dYtY`Z2W%O_jyj6#fN#wo&>h@1qPI2OFyLG1=7UYS)y^zMNTi!Ez zTldEly?r7Lm%5x(Rdq75$zEN}&tDH`rK_rGB~xNd9pf)Mqd(z zSY96*?n*}#KJ`JF89YPuc?deqUKC|d&F}};U~~=(kKJf)1<}NqNazGiK5S;vc0cgC zeD`wPlXw|G%f9d}+ht^?M44E?af$JKQ1fyhq9$<2KKR_-V2(0|PAM}qhQ+E%#LTuz zo!jv9`mb@i=WU{ceW`(=jHX0`=TAi&!+}xfQ^OD>v!9a$5+-kBMkA&{3;(``4`AAf zTS5=A3{+f^63Z7M0hk&{1*cjG+d_(MOj@~De<}J0o!mz`r6!MQT0O?IajQ_#dcM*K z_232E`Gq}NfsTM7e9D$*+2|uu*6PSSpX+lOAVaU`JcHK!L@nV!jkUFH1fRbYZ8;)0 z(M4dao@rpVK2&X&8O&tNj>{7^6PK`6@?#`c7F5z^xSO=OMYxT zSDZ9^YV;^nRT>tGN*vPS_tqn51Yjx{0B5g%(!qqY(QAL03y0!0XgLe$mJZ z;h4Qk2;tP$5AM9RUqQmGseOWwwfqQrn67Hr^|{q9zx1?aBS$epo#Lh`r%pk(@HJPS z`k(^l{s8p9Rcz<66^SJHpvj75#E)wb+OQuTpmqH^ui|`im$9*o#&x~(x^%Qg+THYg z-`uD#Lgp(n%ULU-@p!{q`>zGZ zMJ-7zb&P4d7Ez!XKhSjIv!Ord;FvLsALpQiFhjUc9; zv18p+m&8^+7dciz`y5%p>7;@{fR419C-JI`ls>g?;V%O7Xas6D(5aOM(e^KPv|M{> z5WMbGLW7nq4mfI>f#*k)40CSj(u&{Vp58|AA4c~XUQCJ2KE~^(bx9-!Wm$ z10_4YW^)^9LL#X3`=uvLa^cn-bu)M|?2ou!m&mc({MC%F?gnX&WNucOQaQIRpMHKV7H`{PxQr|M}=PS!?O#=Ox^l#MuRV&RO1d%~uF^b$i|+`D>stC%xn3&|Sa@Q0#Ni zo+)C_y@J>zL%?TlfP#uZ*l3dm8~1qZ+*6@@BL0~ zSp9=ic(eJ2WxA0CLU8MTn+lit)R(})qYVb87COU3J!Y${6dFg) zo{lqze1UCh?@-bBQ>x|U#Eph2GBBsjv;RD_5@?c`+ zefDpzMkI^SOVI?(J@#T_G=qlLu)R_;MY7q29gC(yZRMZ5&#D2#1tp5cn=KcdVMX8X zli>DExNpsF4jLv^wK0u-P1kESzwee`ft0@i_q@ncJ{z&lUdHCCmaWn`jt#jv3SS3; zG@}Hvgg#?Ir0?5FXX}T)5iw&eQy z{T{aBAKf{!_#R_SdurGbgbpv(yA$2S+{VlV2icv8C;yABW$<*F@ndgpZ?}y&lvo2cX&0~tQARxvP3{*{S9>B4&wJ?zRz?b|;N|eAdAJJ{ zWJb~pbDT0woygmE)AcrIAIpr6Qm!|1JWm(r4eq=&oYSI3>v?>`3T;cJ@F2eqKVp6ltS}_O*;&0}-8iOHR{ePE!(?D} z*O0dz<(y23b}0!>5igo@j@Q>Er$sS~7yjV?Qp18@cfpsVvq&)| z+)zlaWD75c2`be;kq$^VC)jS_~T?Ho8RBui)ZcFh6{92kP8#xKN`Zv{!ss8 zec&*Q4I8F|m&#CZw38y!yji3BEwDb-)1N1Q)-ZoI{ilAlabA_TTes?&Gcf-4?qfhu!DGWRg3%AplSb7`OODSA5+36>yyC2%sXR`0pyWF*QQWWgdQ2VpJ678>j=5;KjYd4V_2vBg z8%dQL5dBR2_-DQ$IT|N4=5liG%3->31yf~2G1|UfMZYR}fLqG2H7|1iu^3>-v&;}G z#IWo8&o~;BMzU;7;4+P)8}J`X=gS8WaW%qE*@fTdU^UL)jf2;T84Jo^jqvsH3n@^f!HLzbf@^&M}>El6YEzl6nenaLA zmOr^22+U-Nn08ienl=Aa{m_NQ$4jwndNJS!AQK*{hdjafG{DeEeoDX=!31s7|Ds_e zMLJ~l%qO`D^8B(-?yW8qi_JPO>$$IpM8PJWBQ{(4J6~sUHA2?mB{e1myQKTWuGA0v zW~D+tDJAd^Iz*=EC{3TEkUjZzJc?InzP`?S%JKJDU20+a%J6&<0%MAZz3@$uCl zw#w&(rCkT+O3rc1TMuvEx~^O#N}r&0dc{5UE}iht9pkaF*tC)C!*$h#!Dq3cN8e)6 z4E%+aR1Fa-1ok$*boL4zdpcA$c>qTwTjkP?4o&xL;ZHMYIevSRwn%#*kc|=!=)rN@n}opj(vq73HxPkuXySCu*+EwwqsZ` z`HOZ8P|P<1ofs5jsZmhT_C={1`w@KY<@V6K`Eu7zJlRvf!4y*4T;A;(>$yJntfhSW zy$G;;GxbC5#cEa6Y-&-DYZ**$pT+{QqSi*IcI4xbtdYTC)K+>O7?tw-0x(4dGtABn z%w)+{)Pd_HCcpQ~V~H@2hGV=;lwH0u$i3S-IA&j32|S)v4E0v*Z}RlUybgL*6^DwJ5@CML7?`>@)6A)uxhXk=cb7# z-xy0Ef+cdzX}_(VS_&tUhc+#2D-9qD+{K&${_Y zu}fL)62o2SU_i(ceMB%?Ur$cB>X`)CY86j+q7AQpZ*)urSkEx0a~v})=Fs+3$3oNb z6p75WX;LfgjIvU;C22WU_jj~l#PX-(cNyz2!Dw~R?NL?jWf*03T)ZgvVf?c$B-~PO zc(VG{)D)em!f`^MhqZWh=SzbD(O*$5j|)dhB_)>VU)35=JijkJx@e(SDVoj4P;|M4 zQb^nM#0a;InP7lL&vg;M90p%Fj39n}O)i;Z2V`m#%>;t0oL*pbXeHikbA4?`Le zT1ZBy$16|hxbS4q6`h`@}Uxpr|L`=ehjR%#!1efN)B5~jh!+b2EO zLnocb|15}_8hnOUAi*bzHm=DHfuu2Sv5<}sV#2(GxjpuE^{&f_lFYoUjB1{&Ekg-u zVdm-N*W*zWinP}%p zf>Z^JF)dy_MegTlEYlztuy{6+os&s6!JcaJ!{|0iD6X0l)iv{lwP#kU)V zrE??+;-s(@w6V*3+94sv_Ac#wXO3vXEMjol0%UH)f2vMq<_Xx%2Plvcq*i?%kx)+| zC9U=SG|lJe$&v;kz2Ec=<7HTT3WHnABgTa)nxuf%?Tu77TLgCN1Vj!AaJ zm3N9gf39!xm#D=uFJVtH*PC=3%vo5mr%$=8uv`t474@?k!sDs9?V3e&q78>ocY<|aIL;k95 zNchp*TPJ#PM%wNVM4)zfzvd(grOp1!S)1LfaDGtVDQD*?Qw!f{RHKjJT9)_o>L zzj{rq-n@J87HYDlOnj@*W>KKVma=T>Q{X~w(xo~Yxy(8L5fkNrj|&1~>nQsGMDx7n zu;t0T4$LNAUrSE9ukXMl{4p*p!7VJEuWy8u2{k92RrB;M6iwT;5}tBio4AmjAvBEV zj2?-{WPe1hoa?2~@Gb{P>*z{T9Fd|~$v4F2raB)3&CkR$5$BQ>mBe%D-`w=zYxtaT zGz2iNpZOIx1LVpGXS0&UnX;VW;0XTvUn~HF*g*%(g`%K{PPBf8f4|ZSW4T%Q5n^ys zzioDGu_0z9{5ojgI4ip4Wo0A4ddIeLSy#WR{_efqdcQThbmwhj1^)YVDj+(4oDjT^ zUqmpL3eI*QfL&(YA^(7!pZwW7*s%WmnAWY{ra_~K!!{=8pi%1FRg9&d-V1eV z=#~yP|u&ZeJ8E=}L(g+UngAB!X7UQ@Mk5ip(gTOUlkgL+9FZj}J|9tj4i zVABz)><18pKV~bj(rL!N@x)y)t|ZboG4NnctM2;cg;>z*N{_>Jdirk!hPadVK|4_w}HaqY{~oe7-1T zXb1;IQ;T&y`&`-W_my@fHewh6QQHx$Ya0d^=R~RizBEy+DAOx;^1O;>BnzV0)gkvJB!O#mfp{GH*B3QMRI>GE)s`Zkhq&0;{>A(7QHuIaO#dW zD#&D2uF9>n5a)bQ{*kYC{rcC5L4dum#CNyS!@5oTB;WPqEju60^>IgD=zD_dyXP;c z;VPYot5A5isAluh^Q3sAgsa#^pLfuBu}SQvnb-C@W+__pUo{-!MLB(Tj3_K(BPM+6 zLM(Kq&$^b0U+KtCz9;QTh)F#zc5L|={CiI0PqBuP3)1R84dF!4seqj9k`OAl{O8xz zMemmUCxwn_bPX)%y;iSVHc2dAO?FIfI6LONcaH)3r?Zs)e{J@*E+@@Y!1?X2Y$nQNUg2-~4Y;cJ4@V=O@g$cI)4WHa8P7E4c%ewB! zw8#YDv4+%)WuN6)5TqcU8w`>OA^Kf#lMghS1yK&oP;kkBFaKh145XnMGA}kIm zMq8P{$g(C$WblUy8dzVye&;DQsDiA-GHJm$0#FYJ8cIpmuz09mNDG`4JzTn<{PGS^ z6T7tSjtj7?A9C!0*E;u)UJrV1d{iFYI%<>kHs@B0n_fs9b`IFN-IjP;TQG9!+vz9` z+(V>1HVIOwAaTY+cx`IcnOzVFxx4dPSzRUO`W0u)p=>{O^eu^qIV#q=VM1*-?-T`7 z>}Iyi@+?yvH)P_>@EWO+5HL#k{!?Jre5uZ2&F$%O2|DhUAU-z#eAdu>eI~;Bpwkt{ zmhKj+wp}(0n|KP58q`THN3EBmoniu4CMEv*Y`)CIK5Y@A%T0n*R)yw$iBw)50klMY zRKvk1S|!3xkHIt$-q`w+5+6wUun=>UzlS=Rf5kEg;0`}F`S!B*mVQcNX8&bie9?H` zvy$}IwEKF(YF^cQeQ=4~`z3+2(`nCvmGkT*u(QYE?zc{ajjB5bqv+-^k+gcZz3?s7 zWri&NjGK$jK(0T5h*@VxjT656$1!mMH40<1P&$3-N3t1aYQgj*d-0x20=TJ9k!D()F6wD9<23xr|_ zl9ZJ!aDHCDX*!RADNVsc)h9h1k`58GS&K&cXdG}k|8nLXdEvB22@qyHd;1td;`(1I zsY@Q#W0Amop1>$U3&US9IDm6c-=*j z{n&4HnOVObd9k1A_OA(;)y+1^VZL$MMdB{aAxxjrA7`gBNk!$d04Yj=utVVCMi3c9sBTbUYp+e-a}{5%fZ4Kx4`4mW?-u=(-xvazOZz0){_Ewhe&={Nn>8c<3QbzuQ*K4=^ z)`;rfBBq=0)mEYbXWWjDR*r)7&98{zUCD49YS zm3tm;3%LSet0;z4junr9&$H%cZ&p(@BWN|TA$N)d@3f5=wLfr5#^xz$~g-mhabKllh2ZaCjVphx1I z?@jMPLh#8Xc&vu3Y4b-PHqtpab;S;5^^U&-3mD6%s-psWxVRCt2!&hR40?WFUV<1w z27$Q8xW{|NHo6+jXVS*YT6%u!Vz(Ek-vZex%kl#cd83b-7mpSyi7b$ZOA64siZ#VgyP@EIiqfYAfBlJ2AjygrCSzpG z`4C+mNzw!%6qZJ&!A)ecuph!6O#gcgu=9>fko8=Pws}>LKGHI(em)CMTrHLOliOlC zG7#NzN;7-tKrS&)*ZEmeUvhZ23#gy{y?3Lds;YEjqM+mSssz(|NQ`&+t;Go5^>Dzy ztmh7fOInL_XUt_i^3wmRB=iS@A4jeSI{oMOt<3A!LP6k`T5RbgD#99)Bn>A(1&4cC zcR7b*eC;5z;yOqG@S8h^apgq=b!4Da3Yb1w)M3ysXL-ZVoI>Xx)PxQZ-UuJ(L=HnWvEySMa)##9{b9n7fb=j6U1Ye)tK{Ok5*_JUWas|Ha8BvZ#Ja za+r~`nu?a%4&hziz)g7 zXXJdBuo*ZkcKW@baTZE7&^ z&XaF9`D|d5J5FqqGxWtKfilyMLa5Dd>H_^l1y{3r+HF_ZYz|}7p^SWsv#@{GM!Xlp zDA40(_%&q)m_%B4s=LabCF*(Pn<-g@p$z^3iMK&C0FWZnbO0i&x}JJS#XJ48wtJlMXk4QgN6i zl}JI7%&J5SOq@n4lLN}OMx9vFq1qApieC$X`kdx+BtPi5QH0|alM!lgn%ENsn5>F` zQf!~_C9*LMSD_BeUipj;nCg3fBt+H2-U0e>8Kz#u@|2!?l{z?ZHI=H^0||Mnc6n9QDg0Na7AP90jW+Ko1=0ysc$9f-bIQx3(7 zE}g!vIJ}n%i|F$TQD~i<-62g(3WQ$lK9CJRi3p7rp9H0W!az__hHTjLULM@!*i^$k z#KRq`ucWE!+gJqe^lWmmGd3w;eM1aGe~&Lp5RMt+tkUZhIUFdui@NG6i!AAGU~~fC zcqgh|OABtgPYUOVyj zFkofHu*-hgmY7}?4|qn)3wT`44MD?LX)7q6)Y6BOr|`tnDpi61Z%TS7k2F2TD$LSl zx`7Q4G^UQ5*1msa#OQ+LIxe68+{C6|7n0kunq+ss-UVHqd5SvqK@x__pjs7U!IE*P zKS?QIAzINzCCm)6P^(ztluWNAGKDRmDjV|E)}cD`M})d6uw~1%)2-0N<7_ceX~f9b zf^`xsn8Q$#3ax$r8SPDGB|IK;YyGw|y)m99n1(iZb8#VEMgQoW#eZYBN$AO$Rr}IF zQPK0Z*UZ*)t5^%vXzWX*<0seaP!qLnG2vW0&S72NWn`^CWXKNmtKzqk%ZFC$7JWsw z5S=76g%V4o$r|c*O|)s=hU^Y|PR3QZ^l>Au;@DbYmF9&kjA}$n?`?=jFW9`n!DyoG z>7u2uib`Zqqe|ecunjbt*+<*{9F}@ch3ozC;}F{0m)J_Sd0W$%B4n>l$n@#2A*wbXFz5sxOa!7;i_P55R|gSPD!a&*VGQy`$*xHd|ZdW?;H8)n(u1u7@e3 z>ksQ^KD*?&ZT^K5acrht+~7Gh3tAk?cG4OMNknGHGi8W9FXJjS#V9u%o!#sJaUp9U z;@y(v&7jCFYH<$D(eAqyM&rt+(hVqrC6md;vbKH|*dkzK*$>MMMP)U~ay#{`&CYag z-*R^S3(NnnSZtW<@3fr4Uskv9;IZ$dWMiRa99vgz8OsY7cjG34fn}RBd&-AYbQapD zfso+74u6WkKbOiJx!kd(D^hpsueBrlHu-_cw~L#J6|>(&OWA^SB!o)ekkiz}g%32t zut^rxlAI|*PurMkxD8Wmj}*VvM5V!7y$z`@=*4Na4ZRR+UA({WNulD!EV-2z0}>X# zFNZn%U7kK>Kf11jC0sVf3EDC39aB}eYzC!7QUoS#2e$+VzIkr%csZ5Xv}f++`y76T zT4mSimTSkxVu;z^2fhJK@p*R0|2W*wjLr6{d zKAGL)vRQi&$tnS|*0HXlhi|g>xuL_0*Lm={i|%zw>3VQt%2h45oJDeCxh^#mp)Ca$ z8DnlC;AHp!f%>y^JGw;~H-p7=DE*(n>rc9dPW*-u9QV^HUvIx;Omj!;e!Fy6kJ*qA z*GF~FY&;7%?vI7XSiUGTe%(Ps4-dcveR91nCO&D@6WjM5Ok2djt5|Sq(%fG27^_p^ zh_pgulmD}zD70zIJKV4qn&@TO=Uq35L1f)Fl~9?6>=1Y`kVwvj$Btm3Ax9EM@06p0 zW~kqJy~64-?wd9re52LyQIAH=vMEOMU*-k3g+A~tmXrNB=<%@s+&B2lBgD#^vR_u~ z%&~mCr}wFWwDWw!&cn-#+h@l%UVQ7<5vDHLO;*aNN=<4%a98QlMzPR1mrG;m&33F| zF$sFhtGps1KRTZ#NpKBpblvz+kb;`IM^IP?25?hxRh}JzAdwVJb#8(ADh~0b@I_o9 zfEXG2axNOMgN%g+{4pq-vNagBmp{Y!H#4E>ipG%OxaI4+vB#wj*>i{VF*mDKs}Bra zo@J+Cv|JOKlAL#pVnr2I*$y~J7<Qu);=C4zkc$hYDW#~llt`mfg?$6YV=?DYC4q@8n6U~ zCR`V_2+xqXC^@8#AWB<+pU{cY`=!8tGw>~S^^4oR2}#TY6y?}TP3+cq;>-R{Fel6b zvbuSd6Mb8>2WqJt$O!2k1Y_)_2`0+JOX4UJo@mFA1i70E2{)PLP#+vKPK|W3p)t^+qyHYi%CHWD_@9pF$ZuLMY)MeEvpwU0WU2;ibED`m>e!=!&$b`a zv6v9%WpIbHgrYTBWaKq1ak@5^%kmy(mI=)U?I_!}5c4Uovgejf?pLz2U49NI^%&ri z?%UVQ?;^%Eg=0bEfd0s15SNl9)UbaaDy}TL%0gJyzjPWmEU}P<#vc*oB(TcH$sm93 z%ORs>?@ck--y~5Cc9$7BIw>Nq`e^$>zj1Yo`Riyv*bD>Ma?4PMPIA}4sH%Tb{B;M$ zygej{H{}{0JgF+UKDt!z|G{-VPB1?VNY28=o=zVJASuF@V}jFS(UWy?!4!@udrS`= zXl+zK7Ja;F6!KmpM*qaewy??Tb&|K{sud`I^yB%=okhvnrOAgw5$gjr=-~ic+erp% z4kvl1wR&u0dqTYCx>$>}&|bg#Jf2M<+}+&{cP$QwySubspx6P$3lw+faCZ(U#fu(JaVxF||NdS+ zub*T#n`|bNO=fl{*?bbCsjh&HL56{ZgoLf6D5w38r~i-8Q2v!-$R6AO7_yhPf(%ma zB>CaL28xx6f*jK8|8jnJS;{{Ny1U{hFC-*Pg8vaRQq~XBe?nAmB{g|eI2r(#hYEF- zb`lAR8c9h`TGxN&B**SE`S3++-dW~yW_*Ts85_XGfooTf5P9Zi2+GrF_3MP2^7bAd)gD!R z74bRxU7=H^p7Z}-33lju*~fi7Jm1LHdCABF+>Gn*H(qY5xFw9@khlC7jlbYnUxG`l7U<-05gu9MzufiT(R~|h;C*<&%M{WcN8B+<_2laW zoT}^TaH`SV-*aw%D)iMF15tmz|QXU!>2A+q&`J zi$3MdC?}#YiV>BMmMXLHYQP-zWOsIF6;c`+ebDc~8$cCSOI#)o5^WD>40Kn%h}V*y>W*Sa<>-0@BY zUz++NJQtAt?;kOj>@&I_2ICU{1m*@_J62US_%dw7!{MwyWKek$rrml$T#x*Lq3zfg zcMHYM^sH8qF#sW9Kh}JXY7s=&!+^6y=wHefk$XDZHDM3P>(jnnad6PQcXMotxz!I( zGew6jx;aH1dj5Sd`6~y;Azyi#l3k;WBBW{e?x?nYQZm6XBZqtaux9le_MC6wg3D@f zXMNTCVpVE%K3ix^>MJ zNzC(RIo!G@uo6y0nI21?oVE)h&Ok3S>Q5H{T7Kb10pp|M)|=x1s1GIp^vBA!hZQq*$sy zl+A{l{=&2bS_8ijzKM`JCap9brIxafX?RD5YQs34B%tk>@W%;%{FvO)zXtS*81 zdPAI9KMNG!htOe;N1D2fq!Z7MTL3K4zm&g=)~4KMdGn=(T9K5%E~PYUVyjMwCxIY7 z@i)s$o3=2<7Y%tmDrnE(^VVLRp-Z>gBjdqhu6SSWTxc}g2!W@Bzt)UUsM6BBx;3c` zFuvY|js~Pu?hAZoF;c2e83N(M2Zk!>BAXalCfZxIS>q*MM_6&&KjxcMyvRQJScWJp z`}Yz&%KKa}OZsN~nbMg5&6xs)#r=eF+@W`7DU{=}W=a{O(7b!cUAP*B9s+r117|`` za>}I6#2;4us?EdOEatxC(7SGR^5*l?S)Lk0&STW=aqZtuV&(4=4|91`qURAIT?su= zjW##q&W7}-cON<%R7Z_a@gq+e05ZUc_wy1=H^2e1m6jM6+(`M9*fr4$Y`_orK@i<2GPhQZtHm$}g2Z;LkoxgDGDLIY;ykx0S*&k(SyI+5c}<4*x4 zJ$isaB$MCHJrN|QuYnCx&#i4y*}cS1Rm7$%gO|d#?kqvw9B_Zj|gqVcHKJm-nfy`1yc!)9SwM^qE7c+0w^^Bd>Px8dnmr$=gDI05$4Ul} z#Z|-{RLfMdn)u|2{S*qU9GMc`;*B{Hl?({`6B*##u&#`x8g#uzk(Rbv-#_m%ue_T> zgo4whco!n(9qRb!1|-5db$W<>9`qbvA^IG6dZlybwc!un>qdywX^17o<4C4SuKLZn zyXNpS>tPFwN31BLZ3wa8`_@48*nyEKqBF13MSXQNMWl+<^_qr5$^{hJqs?+->Y9^$ z&)mOkahK0#E8H|*Z%DIRNk=#nU)Jo-HvHC!dhTHZG+}1?xnv^o$Gg>z+X%n)Bp}X2 ze#;k)Y98BPE8J#Ib|cz*VQruP^Ih_fPtS9`JN7YqVSrzs{H}T!ZW~1Q->%g0^^iR4 z;`ms;r%S$_HEqa(r{DfjG#0M~d!S#4dkFuT1;*5*Ps$u!gHqVX==r{YRdrcCR=H&h zS9-2|t+i*fVKKOBQKx~Hh^e{sBOuNY^E1CI5SSeIv;~jkYADy{4V>6U z;k#$c1@!&mTJMdt%z;9JXev8L`>of_jVN=qj{()Ff)}v}CdLsgIr+Frpk!jiYn?cK z28&W4wE&wnPE|mqU|P1FJO;UD!f?0!nlJErcwyS@j|_M=^4UG52Kjr)mXcG<-Ak}* zXb5w-Ac(e<#f@UzPshtvcT#&zu?k z^Kehe*i3N8y_Q5Q@Uh>SduwHCZR33P4T$WU(>uhhu8$>726UAye~ z5cO8f|48efPLHpZQyVb=6{q-A#4Bw!!U{V#=qU3`_wFXvM%{J>9Lh8JVOk)1q2Hxg zEJGVAg~u}6PTpMp^ZDV5G?fkL>7Z@a@fe>)yUrVV6?cKnlb z(0unD@-LBBp%&qX zhCG+3+BrDaYJ2la&(P`8u@M1dO$~bzo9JbfBWAvjDxd(ANAl@l>V-VAXn`VJB89d} zIxUcc8_(SY>2Sd(IbA>3j#(05rQ2zAGYog(BvC-}Zh>KC43g2(y>eo(S993*=|uI- zVzd4HH@DUcG6g)P4Bc7Tk=S*aTwNA5Ak6_=YLZA_T+rWH){h(N(J)=HbEo*uHBav^VF1s8?038!h9uCn#&4hKXd)wrcLGTn zGBzl9w?3cQRfn|-Stztr1%tm)wfx-c%;opkf`DNSJG*|3@Dt9-YquKK;4OpcvZAKx zejtUuS^A1Z$)DpdN}Ng@ix$Pd3tb}53AU5GOmzuUIIp+b9ZVGJ{R2q48HTBK=%}TF z*x#iOB6Z$3qd+A9^Me@_y`EMx1H1(9!%RwvlOf=gX=r`1^dk{k6*c{UFQ78430VCF zV+I61AzYcjH+Im4lI)VcVa2CsR1r?g(IRh{{Q{oKS_*oF20;-vtzlcf!K^!mi4vE1 z#?I|G8;G+4yY=8IO{N#-45xL0x#^Y1?H}s+GCZ~=M4BR{Cbcvr@hQ`6=CkU>??Pfw zPHZ&hqyRxnQ-_{WzCU{O;Q4ifrGmC=<16r!Rmo41cS|)V36mBf!D%RFDPK3pE27uMfjMI;CwGs{19x41L2V!6yvly%EFopaJdC82DK% ziLdmlf;o(6zVs_?YnvxbFR$szCg#YPwOS!J@abI6hG77E{zrx5z5!+t!z>S1IGITS zKo^0A<)1t3RM)Fw?1UK?R0;8({iDsjob++-c%+ciyuyaUhv08oEQUp6(WJ%g{C@K= z=H4$=cEj67-D)*$dDx8J7FtBKRXHIZ1Im__B6Zq8Ii3sB+ZFsxI_`g(8TAkncxO(7 zblGSg$r&s8aF;#ctgd-C2T;+*VVk?qLxGSglP%u5kY8VqA&=KLzdET@4PC$>w%NmT z5}=2*{i+(M?R&qlf%pCumaDop4py4cub}ggp~@nVg`8Y_Y0Q^g8FYX=T{$}zVwRF1 zVf8jLiYhFoCKNHp8J5~{qADPIt7^*;AkR>j-IOzL&@G~a7Ud7+uB}B=c}E9{jINBX zk0zup#xz8GYmY5QN&_H+WDNcJN?;KCJwK{XUpGRQJ1xiD$#uo4iuF7obYUh4IziML zMt^r?EIg8hcz)KC8G<37O_4<1CRRbobL!~^b!Lkxl*&^NPOE6PF$PfuFK?etvFsc2&UHA&NWF@wmqq<+s}Ht;uTbk<9Np+%=XTQPbPSyL0Y{WQj@|A8C<@HS@WO+jC( zm@#43ukn(v3vc~?_}{_JZ^R#A9RrNHh|d$D(4(@tyrA1|8ogGB>hu_wxMmCa#TyhQ zhaeG6tZ_p=`r;Tcd!?3K!NJ@&wTrW-IHv1c9^32K-!lGS4^Hv505a7~?-#XIZ>03_ zj86{ynGIp@f-43d2TvDgMcmzAE6V}>y&mF3#K8yrU~)xp`CXsms)M8AXC0JIU2_2O6mN8fSSp+ zOPtgFh?F|fzhXNU8nW%6**K3!(?3MV*3lOESdXNY>mM}Bo2Zp0+iE$1t;#~~miC%C zS6W6~+aVJpcN;rV972}mC#T{ghb$)qxD>Jv`@P7L`MXnfbGI`p{^D2Pq;c^v9fZ;7 zjF=*tG|keDT)9ri104#KSA3{(xEbiup%(<&y4u3MvqFEbCm7cQE@TzX`xXpV@0!=< z>P!v&B=1GQtq2+wj^}oNKSaex{T=^c!pI;)86~2Twu<7znGZ7nf1&g~>`FQt)fK3c zP4a!HVmm%QtJ-WMv)&srZH`QcO1lZKbg?{iT21@DYsN+c5}lDgo;JxH-_W^7k~JPu zk|s_e;rGyvI`uMOP?v#7U{4e$`Had)4o#bz5Bah?K9A5_6cjI7pxa`IJY89;jq2{o z{xY>T)rU)YJk^MfD;q(GpQ2PW8&8NCd#3$4HUw14zal56?;Ly>tt_y7xNnpIe?EFD z4JJT|tJ5>Y+~>56Od7mL{34kRRe=k44e!xiT3sFEr3J zc&+g}d5u~Ig%t=$@V`#zUcgux{7)ak$FNjM7M549ca0+U1OFYt3~xFW1T*En0&2p3 zOiW9zfBA+%&!=BW#E#8SsWpqPN}AGS1;L4Cb8+OMdE^;OELwndxAZ)JAwi}Ty^s>< zb)Q{isjg#3M;uk1*AI+Zc0H_&xYj^#YHxFoW=_X3<1y3ICz8!%qe!VMlg7&#vg_T1 z$M-lbExckQTy{D*s3y$i+KKDEl|-@I**pkmet2;kX;lvY%DEEA-I@MQAb891c-2?G z>OYB&Z+fJOBKh$=fk%>L6W>0nnU*E4zUM@`aaBp-yX^FPOY%dVpMfYYY z!=uilL2lh@P}-?VR$RIS!k+W1NjR0IQe1#n2AA~`-fS*iMgvnu@ZOz%fZb#sbO65! zLe^0n(!Z+0pwV7A;^c~hq%L8V$T?hF=K6G8+D0G0&vU#z7fR7{xk_Hw*k$IC!|q^i zM|=4N|E+O0G;*R)eq7Olpo(~@rhDYE_ zwES3l;SYx&W-eqsHw%lCC-*xph?FbyJRgK$KS5}7?cXm7=C+;ep#wpUt|XXQ3sgE) z!-DKbEY)|9#^)avm17sQoa&E88CcSywF?q+Cn-T#uHel+l#Zad-<33xp6|z#*o-@V zG#k81)VK(?;LAy2^tE;m0UrifVG<@+weU{~STFuXgyy~9Bdqw{kn8(K(_Ijq? zS0!#8k*)eIKqZ@3NK74xit;Lm77K%Z;i@gGVNM<85n#MK9T$ZbTS^@xnFz*f#|A@H zXML2)QV3c3d6u!xwo9t7r}^6+BGCYN%LBSlIpIu*Q~Rot@y6wo3Noc|Fq^Si$ekbu z&O=)JfPyUo@EQ01g|JmHm1rd`_SM?Q94J=58TBuo)rUK z0V+uYmYeyu`lK^M_0khq6g)^%&7W3GVFq7i3Zx9|XYe?RDjY~BTm}zJuKNcKR5S6B zRy`KyOuPn3B+uL2wm)GRx0~zwwYn@Hf*u~Kq^nj zx?+UN<-TcQBB(~nx*{4lwmbU=(*|RgC*f4HM!%v7s~Bk76phYiSvdfRRIM~|vR`^3 z&=U9m*tm zH7?JZ3G}A7GSlDHESHmwNv?_iss{olk$)&MrlQV6m$h*Dm$%bJ`dZ(iF=m%mOZm zW@|?juJ-DW&w@7Fgz;-t+KozdtGWC)kFSC&CNBKbee0)FlaPOV^V4wJlIZ(tr>zC;Q5 zN%#Tpes~`^-kr7X9GfYGI&)b=95(I+*#tQz;)Q46@R7HEsw4gNP2F*6poCIwEmA&H z@$P%QJZq7$|KwGamT=5?#xBpqWKo(62GDdZ9Ant%r=o*b0$PQ<`|85H1|cLHMq%&z z1dVjfAESK+n^056uQ6zoGkQ6DX9Uu%s*c&@%dyTl>B6Q-v z=y0~V6pq#S4}C_t%WO$qzg*5Rt5okeXwBQW$?>EU{UMkX6`wRud%M1PHj#%J^Ce9$ zRBr!(A6kzdoM+VhYe0Uyf^cO_0L!8zO(A)r8BZPn!eE0J&}0;q)hUv{v;LUY(?du{;gFU6o&{eBa_#ziK$7)$$J zx+G;cZl8ebTY5ib?M{JnMnJcO>G(dEqOPICbt04k_rnbkqYhj=Jgp}Z-afGVxlcD&Xvf)C$PJjd9=yES^ET8g)A+BS zw%Xw7^U-m3aBXJ3E>ZWIX%pwCulq(#t(GoZ~H<1CVb?F-T#J&2tYoTZRPv(KGp-^UV+Ukih8D5fOzVh1L4 zffu}+Ug*b+@c6fz33CbSO+mMqg2fmY%4z3_&zHD@T*GKk>lb{HbPkJ$26{yYZvVd+ zP1w%16Fy;(Q~~*o5&Y!RuPBiEe{mX8!>;OZXW8`UOZBXeDMMcpwV;}nr7jNYF)Lq9 zq36uKn6~8IxT0nrA2%2zh!&3Pdi!z1+5|+rhyQd^8kP`8uTgMz-=YT0Yinm#L#;uh za+5yR;amd&wFjFk{}rd|T1kH@aAv;7Fss>n+ASM&+^6`6Q>SJO-Z9+)PxV+H6iVzX zRN+!tU_|Z$#r^qm;*!}|g{oh|^(v0=rJu;j?dW6q;|X!XQTPgeyhE>G;zWGs&Xhn& zT>c(>(okOcVfBJg36OO%%|HB^rbw;;JoA8h(z8tE+I6giv*bhIyM_=%I+*4ptKlA? zxXCm5zJLCGD6Nxfw7U-yr{U>%m2q0P9(aD~?KcsxkXYEZF!fDcn~#BhorN|=Hm_%$ z1C&51dz>%e%orETu576Y+{!2XWn7;MV8t1}sGjeR-;*}Xd*lj+gB3rGaP3fY`D87Y!_`~ z`qcTJiq$6b&usfZw#VDu^Ez3ZYg{GUkDtIb{9}C9?&PQr^w1Kdx1{o<=ok-g-l7WV zFwI97es9?$53K>oIHq`u7a(|Qi8$0d$U}cyqDuG=oln|?&l^~txOV<^`J-b=(Y9}^ zn)mSJ^Hx+GYVyg1E3LNk`PVe=SL?a%3E>fQqnI>8hWe&jIq8bxaV|nR`>XsE!sLmUMEnLB+i^Q{`P7ER2n^VeG$T288RM_0XPYU92udQIWBH0$)9R ztVGl8=%xNeP|`6yuX2qW;q-!U-N)NDoSETQ`{TiPxXEc*9y-j$r)b{M#wP9`QE-5nk1uyAHx#rl5@CLLhdK2bc zRpFyiT3pGKseMy#;T_+#BmgbwugmVaex#qo{bfp0+JjAV$MtQv-^;w+_g{9HtU3qSMP2OD0 zlFHH=;o;=TH%1QlP>p3Fwu8B$ZcNfNBN-j-EM53r6&qYx08KaC4L zCLRQhr>X+s)XrPL7y!$V9L<}x-bUV(5~n#+Cddm-(z(t7>+J8}a@F*aJ#Us_e34dZ zsyy+jSxrtei*Q-P8o)w_5+lCgp7z<80%d^a)Gk5Y&UaeeE%@XHy3vih zF!-E3tm(n0Rl{yg&tOkM((I|%_27@rlrISzhaoE#l>lGT&sE3O)ko9e&kK9{Z!-JT z7{&sKdjoeingbR?a1l%D z0$pq_iJlry=|QI*r$w(v-8wky@#1y8DX4CelF;Xb%sc;XN6`_^9kQ6U-=FKH4$94S zX$(b965o)0R2hnBXXt2IP5e2XMEDroRUGb(FDETmVFDt>ge2~eM#o>^Cu{p9DlQ+T zrl^Z;2ls%V*D9w0k4l!;B3g9%NJ7?iITqd7z2Cl0O71sV>`dTpO^zvqy>oV7tuQbn zCyE_;4w%WSDRu(H5zfo;GEdoB;Iq9qV;Rnp%~rD}lLrs7=pBxFRxAl#w7qQ+!`=MJ zoapg8H~aNi%B8vGlWm_SMt8t~BXmEndmm{Nv{`hHh#l)BSu_c~3c)SIXf9AE&x(kz zC!@ea=4sGmk&8ek(Ova}1t4hx1{*7=U8>>jWZE0$=dj?)?`E~h?%kl1rU>%GqpGN{t#IN9b zTb>K0V>4X{sD%l{pK&i8C{gq$%70#17Xy=d zv9i?fFc`2$BGwVS{OnP;7CIQ47wvdyn)qz2g-pl0Y>wtY@SBC-f$?=qIwl*Jd?db4 zO(9XO?*1t|LF+1`JDvHREP8p#8lGa)iMDBiP_-j)Qs;%S(BSGfZ zUCe!n)o$;9xRi7L77^=FyltVq%Nl|0`;k1m*@B>2`>^{LqFT2Wf)X^=Umr(Q&_#1( zkwkE4Dy6HXN%7Dl5@w=bC~{{}Xt*$nG0;(PEXV#mR?#)4#>!_kI4BRl!6P*=l6l{M zWn^$Gdi7^VLTvxPap9X{@IA-nVKl$*2zKUeAM43Qb{@N-5%J?7;24 zk#(`HlslJyYgBE&%bi-=BoJrCVbKeZ59v*W$<6Z#wob3CC_6c^va?TEH-1QVsmdI- zYNKXJo)qd_y$beoU$V>-C*t*bWJ40^aKxsX_$0?{{w(`56+t8W)qU}h(E=_oBKab= zc-9JUnS46${-bx}+h7R05QStYql@k!V-V@Z46?|P#Y+`&Rf1F@JfCffn&eO=jO6Xf ze@v?5t4PR1^0N_Wjr!rSZY;r~^L2xVW@q&6a)Vc+`uy~DU-=CD`+qMor^hPcpAo^v zDJ_=Kca+#s=`Wijj>Px@wRKBt($A2RRYU}D#3~tBY@q|{$RXYtdvw1grBZLXmMc!@Bs?_ba_KK&T z^SpkW6?Ry~MRx3y)^Y3cu{wxfGU<%DYD5>U(48wux<*;`o@$DNop*U{=;@qUg*Pu+ zoX#6O{lYc^5v~;ry7hfV9{iZq0L*bI#;0}a#Xq}tQe)pBnt` ziXh^g@;IKw)_<23ihR@4kOJsw=^a{9=o;=`I(<<5=#XQ@x6%mqKBQb<@yxqR;@DKU-Ipx>ljWUf0 zxbA7q#H8@)H#;Qt?7w+>-#d3=UeF?L8-l6~0a5+OcIF=HRDDepEi1#hlIQ)_8XE#J zoq zr}r0m46z+>u0H8U;ndQcEOJI)3fzKL3PkjkB1DEn8s*C9QT_- zBnkrn1{Mx%h+3w}gG+`s;_ZNpLu52RwCNESn;V0kmhCXVc!1Q!5&P{>VZ1MUx#79{ z%=@LCls(BgHx!X` z=ZfpT^Ut>O;!k^Sj7+#I!mQTt{HAVMheKjmf)16ZD#|FKgC`ntHz!wh!5muM7ob;r zJuD;jBi5TwX~9ne*HJpe8%;NRoX1wdpX;h2rv?yt`EN>?_#8$G2jvmyA#%k45Va~~ zIzKH^x)93EAYBYp#eyE-^4qVOA7Ig-#cNbYRD4h%{1`QmvLQGfoa9a3{Qxt1Qme&SSOUwyt+u^jOp=8zR%pbuWmwM= zQ-sGfs37tUxPW5WTu}NcpMVt1WuH2Oz(j^qL!5x0hzi*M>ab7ol)H59*hwt=Z9R~9 zZjUiu_Kw=EON;Cy?gG4T$H_y6BuqjN^|HwX#hDjZMR+ouN>84cB*R?s!u)T!pMKz* zge`WHcO6ff$4MJ#Zu6697cb z4WN0gdLA)OVKno3t3c_2SC$vJmlat^pvaY-NwmtseY9z42{33LBdu#<4-)^kU5 z3lBKvESbXyr;mM`A-q7 z)45E1lrJ9E*!<>xke9Rm;_GqPnR?Il$bLYO7Aopl#}4DRh+0Vt!AOp^j05BmlRC zKvkqJn8nyXm+U_fC`k{G|3Q@QQINH6+#RkI=?Gojacb}P5)$|A8kqERD^OwgJ&>4i z+w@`3`l%FW)o3ahuH>CPiK9|>jN}G<4x;=%$pJsTHut$*KlEd?uJrim!dMzGhO*e= zLidx@5?w{H2!an&WK*$F!u%pl%|+V8eJ>q9+b~SXXs+S79%aZvCqN8h;lsBMvtApb z(IUL*lmr&r6uHE6r^n#QX~#Ow<`A^-ori7B)k&CV%v7tTT{HrDBFGZe))W!Vz2BxJFfd1G(zErLwvXw(~^;$J1Ni^6XC+f zT+gN;lpgs_MyMs8onBd*oHbQ|sb*XxI9(qo<$sEO0_+s@w1H9f&J*&s)9grM4rv zN73NE^+(8A+K=1LqDR^r!S#;xU4HRXffjyJEDw`8t>&xZ@Vh0%cK1|!)>>!-Pqtgj zupL#i?XQFR^m*%lnn8{O2PXJ7>3J2$kLtW!b;J5DQ#$rx*KYmXC~$mxFkY!7a!pzR z{`+5@UOZ}32+9a~@`Y${B(;o63?ZHpG7Q+1?`WLbcsQq~10Ob+2+L_SP&jup(NDO79lU@S<3Wny-;}i5ZMEAO*enZXEchM?E}rG>SdVvl z@Nee3hVk4^Utz5a1?e8AmP)FFD+xQmz@I3R-HhU2s!%#_qh*ZoG}1= zaK6#cxy8oRzB?@xLWHnb2^eyw(M>u>C7fubM#wtw57|wNmHew*ix7@d1c;EzrywAs zb(|$0PDMESfd?lAdoH(9Z@#45k&O?H9MeSB4HLbvvpV~eW9GF-uriuh8p|5Ds?uru z1;tO~rsBxpN6hDvJQDZxE^?3L)?Z(KXdIg-hHkX=GUVljy*LOgSjua%TN|=q?;`Hq9`jI$q^*i87_D=~cSJ!@b`>%dIZ#YbD*gC8>k)Gbjb`L7N@SSQxz~z=XG4C?n&^imet9pukrq?cbIB z&c@V{^3GPNJmo^5gBQJ>h72>V;ZJ^;4%y}3y%;q@owksXo@!e~T6^wYP3bqREs2^I(v!xi;d6L^xG!2(lZ`x22?EJZ!8^6S#atgJ4fA4Ih})1lK0v3&wqj_#g>!; z7e5qnc}N*nZDwHdHDL`a(N_>YafyJ?WP$ULdL2@NM*l7Ce;8zZ*2E98JDWr=mvox1 zKgJKD4OtuiM3%`kN_}AYO(9se z)P~Cl?M*L)4@G4~=n&LY?|&Y@c<|#%qzZ9RW{pyXGDs?D_zfg>oUT9&?$Ig1z=vt~is08^wstbB>F`~jG$G${)o$#Y+lxHILtQCBBxH8uro z@LPrqRFvh82=D*6JeT)h!$vi%<*j%<;J0*!6GOR%dNj!I4Qu1x6{il(77*VgS}Wfu zZ0s-%G3Ck}(@qIpjNVQD5Q-7t94znNLHBZ;HfgiMQ!Q8$a7nrhRg%RH4NK5k%?fYVumL z(_IcmO$Xv=lIWQlB2GGA*H!;#-*C4n3wx$Sg>mC102B{J)q21P0LDVAlFVb`XL9+E z3s|Wqe`1i^+AOktGN-}(>^jiy^ZvK#)`r(Odn<3~vl-H=`&G@p#iuBA)gl|EqEwiD z1OTHi^{3v<+*~|PQIOcUsOP|Pna>Z;$4@^5w;&yFj%XJ){x@>fTje$3cla&*PB(RR z#{NQvoc5gz+C_$fW;3A2JT7KuhZp_!A?$Pws{EfNA Date: Wed, 11 Sep 2013 14:44:45 +0200 Subject: [PATCH 2177/2215] Fixed whitespace error, according to Google style guidelines --- telldus-gui/Plugins/Sensors/__init__.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js index 01308f5f..4270068e 100644 --- a/telldus-gui/Plugins/Sensors/__init__.js +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -11,7 +11,7 @@ com.telldus.sensors = function() { var sensorData = 0; sensorList = loadSensorModel(); sensorList.rowsRemoved.connect(function(){saveSensorModel();}); - sensorList.rowsInserted.connect(function(){saveSensorModel(); sendSensorReport();}); + sensorList.rowsInserted.connect(function(){saveSensorModel(); sendSensorReport();}); while(sensorData = com.telldus.core.sensor()) { var p = sensorData["protocol"]; From 194ca572955d45de20502e8ce69d6f8d2bd20858 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 12 Sep 2013 11:54:16 +0200 Subject: [PATCH 2178/2215] Fixed telldus-core segfault because of config file path not set in correct order --- telldus-core/service/CMakeLists.txt | 17 ++++++++--------- telldus-core/service/SettingsConfuse.cpp | 5 +++++ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/telldus-core/service/CMakeLists.txt b/telldus-core/service/CMakeLists.txt index 520bc95c..595d551c 100644 --- a/telldus-core/service/CMakeLists.txt +++ b/telldus-core/service/CMakeLists.txt @@ -94,6 +94,14 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) IF (UNIX AND NOT APPLE) SET(SCRIPT_PATH "/usr/local/share/telldus/scripts" CACHE PATH "The paths for scripts to execute on sensor events") + SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) + IF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") + SET(DEFAULT_STATE_INSTALL_DIR "/var/spool") + ELSE () + SET(DEFAULT_STATE_INSTALL_DIR "/var/state") + ENDIF () + SET(STATE_INSTALL_DIR "${DEFAULT_STATE_INSTALL_DIR}" CACHE PATH "The directory to store state information of the devices") + ENDIF() ######## Platforms-specific, non configurable ######## @@ -247,15 +255,6 @@ ENDIF (UNIX) IF (UNIX AND NOT APPLE) INSTALL(TARGETS ${telldus-service_TARGET} RUNTIME DESTINATION sbin) - SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" ) - - IF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - SET(DEFAULT_STATE_INSTALL_DIR "/var/spool") - ELSE () - SET(DEFAULT_STATE_INSTALL_DIR "/var/state") - ENDIF () - SET(STATE_INSTALL_DIR "${DEFAULT_STATE_INSTALL_DIR}" CACHE PATH "The directory to store state information of the devices") - INSTALL(FILES tellstick.conf DESTINATION ${SYSCONF_INSTALL_DIR} ) diff --git a/telldus-core/service/SettingsConfuse.cpp b/telldus-core/service/SettingsConfuse.cpp index 9c30fb7f..05030417 100644 --- a/telldus-core/service/SettingsConfuse.cpp +++ b/telldus-core/service/SettingsConfuse.cpp @@ -13,6 +13,7 @@ #include "service/config.h" #include "client/telldus-core.h" #include "common/Strings.h" +#include "service/Log.h" class Settings::PrivateData { public: @@ -405,12 +406,14 @@ bool readConfig(cfg_t **cfg) { FILE *fp = fopen(CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle if (!fp) { + Log::warning("Unable to open config file, %s", CONFIG_FILE); return false; } (*cfg) = cfg_init(opts, CFGF_NOCASE); if (cfg_parse_fp((*cfg), fp) == CFG_PARSE_ERROR) { (*cfg) = 0; fclose(fp); + Log::warning("Unable to parse config file, %s", CONFIG_FILE); return false; } @@ -432,12 +435,14 @@ bool readVarConfig(cfg_t **cfg) { FILE *fp = fopen(VAR_CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle if (!fp) { + Log::warning("Unable to open var config file, %s", VAR_CONFIG_FILE); return false; } (*cfg) = cfg_init(opts, CFGF_NOCASE); if (cfg_parse_fp((*cfg), fp) == CFG_PARSE_ERROR) { (*cfg) = 0; fclose(fp); + Log::warning("Unable to parse var config file, %s", VAR_CONFIG_FILE); return false; } From f812ec4307b121d42c183f82def0e5cb61901076 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 Sep 2013 13:56:21 +0200 Subject: [PATCH 2179/2215] Removed blank lines at start/end of code blocks according to Google style guidelines whitespace/blank_line --- telldus-core/service/ProtocolOregon.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 79dc3614..21417d70 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -78,7 +78,6 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { } std::string ProtocolOregon::decode1984(const std::string &data, const std::wstring &model) { - //wind uint64_t value = TelldusCore::hexTo64l(data); @@ -198,7 +197,6 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { } std::string ProtocolOregon::decode2914(const std::string &data) { - //rain uint64_t value = TelldusCore::hexTo64l(data); @@ -252,7 +250,6 @@ std::string ProtocolOregon::decode2914(const std::string &data) { } std::string ProtocolOregon::decodeF824(const std::string &data) { - uint64_t value = TelldusCore::hexTo64l(data); uint8_t crcCheck = value & 0xF; //PROBABLY crc From b9f28d6e6e5a48900885441a861a85620b229a4b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 Sep 2013 14:04:41 +0200 Subject: [PATCH 2180/2215] Added whitespaces to comments according to Google style guidelines "whitespace/comments" --- telldus-core/service/ProtocolOregon.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 21417d70..46efa76c 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -78,10 +78,10 @@ std::string ProtocolOregon::decodeEA4C(const std::string &data) { } std::string ProtocolOregon::decode1984(const std::string &data, const std::wstring &model) { - //wind + // wind uint64_t value = TelldusCore::hexTo64l(data); - uint8_t crcCheck = value & 0xF; //PROBABLY crc + uint8_t crcCheck = value & 0xF; // PROBABLY crc value >>= 4; uint8_t messageChecksum1 = value & 0xF; value >>= 4; @@ -107,7 +107,7 @@ std::string ProtocolOregon::decode1984(const std::string &data, const std::wstri uint8_t direction = value & 0xF; value >>= 4; - uint8_t battery = value & 0xF; //PROBABLY battery + uint8_t battery = value & 0xF; // PROBABLY battery value >>= 4; uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); @@ -123,7 +123,7 @@ std::string ProtocolOregon::decode1984(const std::string &data, const std::wstri } if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ - //checksum error + // checksum error return ""; } @@ -197,7 +197,7 @@ std::string ProtocolOregon::decode1A2D(const std::string &data) { } std::string ProtocolOregon::decode2914(const std::string &data) { - //rain + // rain uint64_t value = TelldusCore::hexTo64l(data); uint8_t messageChecksum1 = value & 0xF; @@ -226,7 +226,7 @@ std::string ProtocolOregon::decode2914(const std::string &data) { uint8_t rainRate4 = value & 0xF; value >>= 4; - uint8_t battery = value & 0xF; //PROBABLY battery + uint8_t battery = value & 0xF; // PROBABLY battery value >>= 4; uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); @@ -235,7 +235,7 @@ std::string ProtocolOregon::decode2914(const std::string &data) { checksum += totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 + rainRate1 + rainRate2 + rainRate3 + rainRate4 + battery + channel + 0x2 + 0x9 + 0x1 + 0x4; if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ - //checksum error + // checksum error return ""; } @@ -252,7 +252,7 @@ std::string ProtocolOregon::decode2914(const std::string &data) { std::string ProtocolOregon::decodeF824(const std::string &data) { uint64_t value = TelldusCore::hexTo64l(data); - uint8_t crcCheck = value & 0xF; //PROBABLY crc + uint8_t crcCheck = value & 0xF; // PROBABLY crc value >>= 4; uint8_t messageChecksum1 = value & 0xF; value >>= 4; @@ -272,7 +272,7 @@ std::string ProtocolOregon::decodeF824(const std::string &data) { value >>= 4; uint8_t temp3 = value & 0xF; value >>= 4; - uint8_t battery = value & 0xF; //PROBABLY battery + uint8_t battery = value & 0xF; // PROBABLY battery value >>= 4; uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); @@ -281,7 +281,7 @@ std::string ProtocolOregon::decodeF824(const std::string &data) { checksum += unknown + hum1 + hum2 + neg + temp1 + temp2 + temp3 + battery + channel + 0xF + 0x8 + 0x2 + 0x4; if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ - //checksum error + // checksum error return ""; } From 87845ca31e0463ef3774212d1f8e3636efbff119 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 Sep 2013 14:06:42 +0200 Subject: [PATCH 2181/2215] Moved "else" to same line as previous closing braces, according to Google style guidelines "whitespace/newline" --- telldus-core/service/ProtocolOregon.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 46efa76c..7b86f991 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -117,8 +117,7 @@ std::string ProtocolOregon::decode1984(const std::string &data, const std::wstri if (model.compare(L"0x1984") == 0) { checksum += 0x1 + 0x9 + 0x8 + 0x4; - } - else { + } else { checksum += 0x1 + 0x9 + 0x9 + 0x4; } From fd5ffa3ad43813f20de9718c713155f5df914c12 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 Sep 2013 14:08:11 +0200 Subject: [PATCH 2182/2215] Added missing space before braces, according to Google style guidelines "whitespace/braces" --- telldus-core/service/ProtocolOregon.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index 7b86f991..f1764846 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -121,7 +121,7 @@ std::string ProtocolOregon::decode1984(const std::string &data, const std::wstri checksum += 0x1 + 0x9 + 0x9 + 0x4; } - if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ + if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { // checksum error return ""; } @@ -233,7 +233,7 @@ std::string ProtocolOregon::decode2914(const std::string &data) { uint8_t channel = value & 0xF; checksum += totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 + rainRate1 + rainRate2 + rainRate3 + rainRate4 + battery + channel + 0x2 + 0x9 + 0x1 + 0x4; - if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ + if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { // checksum error return ""; } @@ -279,7 +279,7 @@ std::string ProtocolOregon::decodeF824(const std::string &data) { uint8_t channel = value & 0xF; checksum += unknown + hum1 + hum2 + neg + temp1 + temp2 + temp3 + battery + channel + 0xF + 0x8 + 0x2 + 0x4; - if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2){ + if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { // checksum error return ""; } From c77c84886ab5efa13f915ca12ac9b1e0d02941c6 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 Sep 2013 14:11:13 +0200 Subject: [PATCH 2183/2215] Ugly temporary fix for segfault in TelldusCenter --- telldus-core/common/EventHandler_unix.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 46fc949a..15372b78 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -24,6 +24,7 @@ public: EventHandler::EventHandler() { d = new PrivateData; + printf(""); pthread_cond_init(&d->event, NULL); pthread_mutex_init(&d->mutex, NULL); } From 702aef6eab3a0beba64dfa8a78f9e9e1b6aad29b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 Sep 2013 16:46:36 +0200 Subject: [PATCH 2184/2215] Updated 3rd party module qtsingleapplication to latest version --- .../3rdparty/qtsingleapplication/INSTALL.TXT | 2 +- .../qtsingleapplication/LGPL_EXCEPTION.txt | 10 - .../3rdparty/qtsingleapplication/LICENSE.GPL3 | 674 ------------------ .../3rdparty/qtsingleapplication/LICENSE.LGPL | 504 ------------- .../3rdparty/qtsingleapplication/README.TXT | 28 +- .../3rdparty/qtsingleapplication/common.pri | 4 +- .../3rdparty/qtsingleapplication/configure | 87 --- .../qtsingleapplication/configure.bat | 80 +++ .../qtsingleapplication/doc/html/classic.css | 189 ++++- .../qtsingleapplication/doc/html/index.html | 8 +- .../doc/html/qtlockedfile-members.html | 165 ----- .../doc/html/qtlockedfile.html | 111 --- .../qtsingleapplication-example-loader.html | 75 +- .../qtsingleapplication-example-trivial.html | 75 +- .../doc/html/qtsingleapplication-members.html | 412 +++++------ .../html/qtsingleapplication-obsolete.html | 14 +- .../doc/html/qtsingleapplication.dcf | 13 - .../doc/html/qtsingleapplication.html | 142 ++-- .../doc/html/qtsingleapplication.index | 134 ++-- .../doc/html/qtsingleapplication.qch | Bin 48128 -> 0 bytes .../doc/html/qtsingleapplication.qhp | 58 +- ...singlecoreapplication-example-console.html | 75 +- .../html/qtsinglecoreapplication-members.html | 202 +++--- .../doc/html/qtsinglecoreapplication.html | 80 ++- .../qtsingleapplication/doc/index.qdoc | 42 +- .../examples/console/console.qdoc | 78 +- .../examples/console/main.cpp | 84 +-- .../examples/loader/loader.pro | 1 + .../examples/loader/loader.qdoc | 78 +- .../examples/loader/main.cpp | 92 ++- .../examples/trivial/main.cpp | 80 +-- .../examples/trivial/trivial.qdoc | 78 +- .../qtsingleapplication/src/qtlocalpeer.cpp | 98 +-- .../qtsingleapplication/src/qtlocalpeer.h | 90 ++- .../qtsingleapplication/src/qtlockedfile.cpp | 78 +- .../qtsingleapplication/src/qtlockedfile.h | 88 ++- .../src/qtlockedfile_unix.cpp | 78 +- .../src/qtlockedfile_win.cpp | 84 ++- .../src/qtsingleapplication.cpp | 136 ++-- .../src/qtsingleapplication.h | 92 +-- .../src/qtsingleapplication.pri | 1 + .../src/qtsinglecoreapplication.cpp | 78 +- .../src/qtsinglecoreapplication.h | 84 ++- 43 files changed, 1601 insertions(+), 2981 deletions(-) delete mode 100644 telldus-gui/3rdparty/qtsingleapplication/LGPL_EXCEPTION.txt delete mode 100644 telldus-gui/3rdparty/qtsingleapplication/LICENSE.GPL3 delete mode 100644 telldus-gui/3rdparty/qtsingleapplication/LICENSE.LGPL create mode 100644 telldus-gui/3rdparty/qtsingleapplication/configure.bat delete mode 100644 telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile-members.html delete mode 100644 telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile.html delete mode 100644 telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qch diff --git a/telldus-gui/3rdparty/qtsingleapplication/INSTALL.TXT b/telldus-gui/3rdparty/qtsingleapplication/INSTALL.TXT index 8d41864d..bbb74a9d 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/INSTALL.TXT +++ b/telldus-gui/3rdparty/qtsingleapplication/INSTALL.TXT @@ -166,7 +166,7 @@ If you have installed the documentation into Qt Assistant, and want to uninstall 1. In Assistant, open the Edit->Preferences dialog and choose the Documentation tab. In the list of Registered Documentation, select - the item com.trolltech.qtsolutions.some-package_version, and click + the item com.nokia.qtsolutions.some-package_version, and click the Remove button. For Qt versions prior to 4.4, do instead the following: diff --git a/telldus-gui/3rdparty/qtsingleapplication/LGPL_EXCEPTION.txt b/telldus-gui/3rdparty/qtsingleapplication/LGPL_EXCEPTION.txt deleted file mode 100644 index 0b56ff1e..00000000 --- a/telldus-gui/3rdparty/qtsingleapplication/LGPL_EXCEPTION.txt +++ /dev/null @@ -1,10 +0,0 @@ -Nokia Qt LGPL Exception version 1.0 - -As a special exception to the GNU Lesser General Public License -version 2.1, the object code form of a "work that uses the Library" -may incorporate material from a header file that is part of the -Library. You may distribute such object code under terms of your -choice, provided that the incorporated material (i) does not exceed -more than 5% of the total size of the Library; and (ii) is limited to -numerical parameters, data structure layouts, accessors, macros, -inline functions and templates. diff --git a/telldus-gui/3rdparty/qtsingleapplication/LICENSE.GPL3 b/telldus-gui/3rdparty/qtsingleapplication/LICENSE.GPL3 deleted file mode 100644 index 94a9ed02..00000000 --- a/telldus-gui/3rdparty/qtsingleapplication/LICENSE.GPL3 +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/telldus-gui/3rdparty/qtsingleapplication/LICENSE.LGPL b/telldus-gui/3rdparty/qtsingleapplication/LICENSE.LGPL deleted file mode 100644 index 5ab7695a..00000000 --- a/telldus-gui/3rdparty/qtsingleapplication/LICENSE.LGPL +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/telldus-gui/3rdparty/qtsingleapplication/README.TXT b/telldus-gui/3rdparty/qtsingleapplication/README.TXT index f12dc98c..06abb095 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/README.TXT +++ b/telldus-gui/3rdparty/qtsingleapplication/README.TXT @@ -1,7 +1,33 @@ -Single Application v2.6 +Qt Solutions Component: Single Application The QtSingleApplication component provides support for applications that can be only started once per user. +Version history: + +2.0: - Version 1.3 ported to Qt 4. + +2.1: - Fix compilation problem on Mac. + +2.2: - Really fix the Mac compilation problem. + - Mac: fix crash due to wrong object releasing. + - Mac: Fix memory leak. + +2.3: - Windows: Force creation of internal widget to make it work + with Qt 4.2. + +2.4: - Fix the system for automatic window raising on message + reception. NOTE: minor API change. + +2.5: - Mac: Fix isRunning() to work and report correctly. + +2.6: - - initialize() is now obsolete, no longer necessary to call + it + - - Fixed race condition where multiple instances migth be started + - - QtSingleCoreApplication variant provided for non-GUI (console) + usage + - Complete reimplementation. Visible changes: + - LGPL release. + diff --git a/telldus-gui/3rdparty/qtsingleapplication/common.pri b/telldus-gui/3rdparty/qtsingleapplication/common.pri index b45a4fc2..bae27173 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/common.pri +++ b/telldus-gui/3rdparty/qtsingleapplication/common.pri @@ -1,6 +1,6 @@ -infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtsingleapplication-uselib +exists(config.pri):infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtsingleapplication-uselib TEMPLATE += fakelib -QTSINGLEAPPLICATION_LIBNAME = $$qtLibraryTarget(QtSolutions_SingleApplication-2.6) +QTSINGLEAPPLICATION_LIBNAME = $$qtLibraryTarget(QtSolutions_SingleApplication-head) TEMPLATE -= fakelib QTSINGLEAPPLICATION_LIBDIR = $$PWD/lib unix:qtsingleapplication-uselib:!qtsingleapplication-buildlib:QMAKE_RPATHDIR += $$QTSINGLEAPPLICATION_LIBDIR diff --git a/telldus-gui/3rdparty/qtsingleapplication/configure b/telldus-gui/3rdparty/qtsingleapplication/configure index 674d286a..3c4edfff 100755 --- a/telldus-gui/3rdparty/qtsingleapplication/configure +++ b/telldus-gui/3rdparty/qtsingleapplication/configure @@ -5,97 +5,10 @@ if [ "x$1" != "x" -a "x$1" != "x-library" ]; then echo echo "-library: Build the component as a dynamic library (DLL). Default is to" echo " include the component source code directly in the application." - echo " A DLL may be preferable for technical or licensing (LGPL) reasons." echo exit 0 fi - -# only ask to accept the license text once -if [ ! -f .licenseAccepted ]; then -# determine if opensource or commercial package - if [ -f LICENSE.LGPL ]; then - # opensource edition - while true; do - echo - echo "You are licensed to use this software under the terms of" - echo "the GNU General Public License (GPL) version 3, or" - echo "the GNU Lesser General Public License (LGPL) version 2.1" - echo "with certain additional extra rights as specified in the" - echo "Nokia Qt LGPL Exception version 1.0." - echo - echo "Type 'G' to view the GNU General Public License (GPL) version 3." - echo "Type 'L' to view the GNU Lesser General Public License (LGPL) version 2.1." - echo "Type 'E' to view the Nokia Qt LGPL Exception version 1.0." - echo "Type 'yes' to accept this license offer." - echo "Type 'no' to decline this license offer." - echo - echo "Do you accept the terms of this license? " - read answer - echo - - if [ "x$answer" = "xno" ]; then - echo "You are not licensed to use this software." - echo - exit 1 - elif [ "x$answer" = "xyes" ]; then - echo license accepted > .licenseAccepted - break - elif [ "x$answer" = "xe" -o "x$answer" = "xE" ]; then - more LGPL_EXCEPTION.txt - elif [ "x$answer" = "xl" -o "x$answer" = "xL" ]; then - more LICENSE.LGPL - elif [ "x$answer" = "xg" -o "x$answer" = "xG" ]; then - more LICENSE.GPL3 - fi - done - else - while true; do - echo - echo "Please choose your region." - echo - echo "Type 1 for North or South America." - echo "Type 2 for anywhere outside North and South America." - echo - echo "Select: " - read region - if [ "x$region" = "x1" ]; then - licenseFile=LICENSE.US - break; - elif [ "x$region" = "x2" ]; then - licenseFile=LICENSE.NO - break; - fi - done - while true; do - echo - echo "License Agreement" - echo - echo "Type '?' to view the Qt Solutions Commercial License." - echo "Type 'yes' to accept this license offer." - echo "Type 'no' to decline this license offer." - echo - echo "Do you accept the terms of this license? " - read answer - echo - - if [ "x$answer" = "xno" ]; then - echo "You are not licensed to use this software." - echo - exit 1 - elif [ "x$answer" = "xyes" ]; then - echo license accepted > .licenseAccepted - cp "$licenseFile" LICENSE - rm LICENSE.US - rm LICENSE.NO - break - elif [ "x$answer" = "x?" ]; then - more "$licenseFile" - fi - done - fi -fi - rm -f config.pri if [ "x$1" = "x-library" ]; then echo "Configuring to build this component as a dynamic library." diff --git a/telldus-gui/3rdparty/qtsingleapplication/configure.bat b/telldus-gui/3rdparty/qtsingleapplication/configure.bat new file mode 100644 index 00000000..9bf19870 --- /dev/null +++ b/telldus-gui/3rdparty/qtsingleapplication/configure.bat @@ -0,0 +1,80 @@ +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: +:: +:: Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +:: Contact: http://www.qt-project.org/legal +:: +:: This file is part of the Qt Solutions component. +:: +:: $QT_BEGIN_LICENSE:BSD$ +:: You may use this file under the terms of the BSD license as follows: +:: +:: "Redistribution and use in source and binary forms, with or without +:: modification, are permitted provided that the following conditions are +:: met: +:: * Redistributions of source code must retain the above copyright +:: notice, this list of conditions and the following disclaimer. +:: * Redistributions in binary form must reproduce the above copyright +:: notice, this list of conditions and the following disclaimer in +:: the documentation and/or other materials provided with the +:: distribution. +:: * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +:: of its contributors may be used to endorse or promote products derived +:: from this software without specific prior written permission. +:: +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +:: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +:: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +:: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +:: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +:: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +:: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +:: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +:: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +:: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +:: +:: $QT_END_LICENSE$ +:: +::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: + +@echo off + +rem +rem "Main" +rem + +if not "%1"=="" ( + if not "%1"=="-library" ( + call :PrintUsage + goto EOF + ) +) + +if exist config.pri. del config.pri +if "%1"=="-library" ( + echo Configuring to build this component as a dynamic library. + echo SOLUTIONS_LIBRARY = yes > config.pri +) + +echo . +echo This component is now configured. +echo . +echo To build the component library (if requested) and example(s), +echo run qmake and your make or nmake command. +echo . +echo To remove or reconfigure, run make (nmake) distclean. +echo . +goto EOF + +:PrintUsage +echo Usage: configure.bat [-library] +echo . +echo -library: Build the component as a dynamic library (DLL). Default is to +echo include the component source directly in the application. +echo A DLL may be preferable for technical or licensing (LGPL) reasons. +echo . +goto EOF + + +:EOF diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/classic.css b/telldus-gui/3rdparty/qtsingleapplication/doc/html/classic.css index 0ff9e7db..b8cae8e1 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/classic.css +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/classic.css @@ -1,12 +1,105 @@ +BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { + font-family: Arial, Geneva, Helvetica, sans-serif; +} +H1 { + text-align: center; + font-size: 160%; +} +H2 { + font-size: 120%; +} +H3 { + font-size: 100%; +} + h3.fn,span.fn { - margin-left: 1cm; - text-indent: -1cm; + background-color: #eee; + border-width: 1px; + border-style: solid; + border-color: #ddd; + font-weight: bold; + padding: 6px 0px 6px 10px; + margin: 42px 0px 0px 0px; +} + +hr { + border: 0; + color: #a0a0a0; + background-color: #ccc; + height: 1px; + width: 100%; + text-align: left; + margin: 34px 0px 34px 0px; +} + +table.valuelist { + border-width: 1px 1px 1px 1px; + border-style: solid; + border-color: #dddddd; + border-collapse: collapse; + background-color: #f0f0f0; +} + +table.indextable { + border-width: 1px 1px 1px 1px; + border-style: solid; + border-collapse: collapse; + background-color: #f0f0f0; + border-color:#555; + font-size: 100%; +} + +table td.largeindex { + border-width: 1px 1px 1px 1px; + border-collapse: collapse; + background-color: #f0f0f0; + border-color:#555; + font-size: 120%; +} + +table.valuelist th { + border-width: 1px 1px 1px 2px; + padding: 4px; + border-style: solid; + border-color: #666; + color:white; + background-color:#666; +} + +th.titleheader { + border-width: 1px 0px 1px 0px; + padding: 2px; + border-style: solid; + border-color: #666; + color:white; + background-color:#555; + background-image:url('images/gradient.png')}; + background-repeat: repeat-x; + font-size: 100%; +} + + +th.largeheader { + border-width: 1px 0px 1px 0px; + padding: 4px; + border-style: solid; + border-color: #444; + color:white; + background-color:#555555; + font-size: 120%; +} + +p { + + margin-left: 4px; + margin-top: 8px; + margin-bottom: 8px; } a:link { - color: #004faf; + color: #0046ad; text-decoration: none } @@ -40,22 +133,40 @@ a.compat:visited text-decoration: none } -td.postheader -{ - font-family: sans-serif -} - -tr.address -{ - font-family: sans-serif -} - body { background: #ffffff; color: black } +table.generic, table.annotated +{ + border-width: 1px; + border-color:#bbb; + border-style:solid; + border-collapse:collapse; +} + +table td.memItemLeft { + width: 180px; + padding: 2px 0px 0px 8px; + margin: 4px; + border-width: 1px; + border-color: #E0E0E0; + border-style: none; + font-size: 100%; + white-space: nowrap +} + +table td.memItemRight { + padding: 2px 8px 0px 8px; + margin: 4px; + border-width: 1px; + border-color: #E0E0E0; + border-style: none; + font-size: 100%; +} + table tr.odd { background: #f0f0f0; color: black; @@ -77,17 +188,17 @@ table.annotated td { table tr pre { - padding-top: none; - padding-bottom: none; - padding-left: none; - padding-right: none; + padding-top: 0px; + padding-bottom: 0px; + padding-left: 0px; + padding-right: 0px; border: none; background: none } tr.qt-style { - background: #a2c511; + background: #96E066; color: black } @@ -99,6 +210,14 @@ body pre color: black } +table tr.qt-code pre +{ + padding: 0.2em; + border: #e7e7e7 1px solid; + background: #f1f1f1; + color: black +} + span.preprocessor, span.preprocessor a { color: darkblue; @@ -129,3 +248,37 @@ span.string,span.char { font-size: 0.65em } + +.qmlitem { + padding: 0; +} + +.qmlname { + white-space: nowrap; +} + +.qmltype { + text-align: center; + font-size: 160%; +} + +.qmlproto { + background-color: #eee; + border-width: 1px; + border-style: solid; + border-color: #ddd; + font-weight: bold; + padding: 6px 10px 6px 10px; + margin: 42px 0px 0px 0px; +} + +.qmlreadonly { + float: right; + color: red +} + +.qmldoc { +} + +*.qmlitem p { +} diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/index.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/index.html index 921eaaf6..af9dab10 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/index.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/index.html @@ -2,7 +2,7 @@ - + Single Application @@ -18,7 +18,7 @@

Description

The QtSingleApplication component provides support for applications that can be only started once per user.

For some applications it is useful or even critical that they are started only once by any user. Future attempts to start the application should activate any already running instance, and possibly perform requested actions, e.g. loading a file, in that instance.

-

The QtSingleApplication class provides an interface to detect a running instance, and to send command strings to that instance. For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui.

+

The QtSingleApplication class provides an interface to detect a running instance, and to send command strings to that instance. For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui.

Classes

    @@ -41,8 +41,8 @@


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile-members.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile-members.html deleted file mode 100644 index b5fd97b9..00000000 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile-members.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - List of All Members for QtLockedFile - - - - - - - -
  Home

List of All Members for QtLockedFile

-

This is the complete list of members for QtLockedFile, including inherited members.

-

- -
-

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile.html deleted file mode 100644 index 7842e98a..00000000 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtlockedfile.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - QtLockedFile Class Reference - - - - - - - -
  Home

QtLockedFile Class Reference

-

The QtLockedFile class extends QFile with advisory locking functions. More...

-
 #include <QtLockedFile>

Inherits QFile.

- - -

Public Types

-
    -
  • enum LockMode { ReadLock, WriteLock, NoLock }
  • -
- -

Public Functions

- -
    -
  • 23 public functions inherited from QFile
  • -
  • 32 public functions inherited from QIODevice
  • -
  • 29 public functions inherited from QObject
  • -
-

Additional Inherited Members

-
    -
  • 1 property inherited from QObject
  • -
  • 1 public slot inherited from QObject
  • -
  • 4 signals inherited from QIODevice
  • -
  • 1 signal inherited from QObject
  • -
  • 1 public type inherited from QObject
  • -
  • 14 static public members inherited from QFile
  • -
  • 4 static public members inherited from QObject
  • -
  • 5 protected functions inherited from QIODevice
  • -
  • 7 protected functions inherited from QObject
  • -
  • 2 protected variables inherited from QObject
  • -
- -
-

Detailed Description

-

The QtLockedFile class extends QFile with advisory locking functions.

-

A file may be locked in read or write mode. Multiple instances of QtLockedFile, created in multiple processes running on the same machine, may have a file locked in read mode. Exactly one instance may have it locked in write mode. A read and a write lock cannot exist simultaneously on the same file.

-

The file locks are advisory. This means that nothing prevents another process from manipulating a locked file using QFile or file system functions offered by the OS. Serialization is only guaranteed if all processes that access the file use QLockedFile. Also, while holding a lock on a file, a process must not open the same file again (through any API), or locks can be unexpectedly lost.

-

The lock provided by an instance of QtLockedFile is released whenever the program terminates. This is true even when the program crashes and no destructors are called.

-
-

Member Type Documentation

-

enum QtLockedFile::LockMode

-

This enum describes the available lock modes.

-

- - - - -
ConstantValueDescription
QtLockedFile::ReadLock1A read lock.
QtLockedFile::WriteLock2A write lock.
QtLockedFile::NoLock0Neither a read lock nor a write lock.

-
-

Member Function Documentation

-

QtLockedFile::QtLockedFile ()

-

Constructs an unlocked QtLockedFile object. This constructor behaves in the same way as QFile::QFile().

-

See also QFile::QFile().

-

QtLockedFile::QtLockedFile ( const QString & name )

-

Constructs an unlocked QtLockedFile object with file name. This constructor behaves in the same way as QFile::QFile(const QString&).

-

See also QFile::QFile().

-

QtLockedFile::~QtLockedFile ()

-

Destroys the QtLockedFile object. If any locks were held, they are released.

-

bool QtLockedFile::isLocked () const

-

Returns true if this object has a in read or write lock; otherwise returns false.

-

See also lockMode().

-

bool QtLockedFile::lock ( LockMode mode, bool block = true )

-

Obtains a lock of type mode. The file must be opened before it can be locked.

-

If block is true, this function will block until the lock is aquired. If block is false, this function returns false immediately if the lock cannot be aquired.

-

If this object already has a lock of type mode, this function returns true immediately. If this object has a lock of a different type than mode, the lock is first released and then a new lock is obtained.

-

This function returns true if, after it executes, the file is locked by this object, and false otherwise.

-

See also unlock(), isLocked(), and lockMode().

-

LockMode QtLockedFile::lockMode () const

-

Returns the type of lock currently held by this object, or QtLockedFile::NoLock.

-

See also isLocked().

-

bool QtLockedFile::open ( OpenMode mode )

-

Opens the file in OpenMode mode.

-

This is identical to QFile::open(), with the one exception that the Truncate mode flag is disallowed. Truncation would conflict with the advisory file locking, since the file would be modified before the write lock is obtained. If truncation is required, use resize(0) after obtaining the write lock.

-

Returns true if successful; otherwise false.

-

See also QFile::open() and QFile::resize().

-

bool QtLockedFile::unlock ()

-

Releases a lock.

-

If the object has no lock, this function returns immediately.

-

This function returns true if, after it executes, the file is not locked by this object, and false otherwise.

-

See also lock(), isLocked(), and lockMode().

-


- - - - -
Copyright © 2009 NokiaTrademarks
Qt Solutions
- diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-loader.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-loader.html index c225c000..6a366329 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-loader.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-loader.html @@ -2,7 +2,7 @@ - + Loading Documents @@ -17,47 +17,38 @@

The application in this example loads or prints the documents passed as commandline parameters to further instances of this application.

 /****************************************************************************
  **
- ** This file is part of a Qt Solutions component.
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
  **
- ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ ** This file is part of the Qt Solutions component.
  **
- ** Contact:  Qt Software Information (qt-info@nokia.com)
+ ** You may use this file under the terms of the BSD license as follows:
  **
- ** Commercial Usage
- ** Licensees holding valid Qt Commercial licenses may use this file in
- ** accordance with the Qt Solutions Commercial License Agreement provided
- ** with the Software or, alternatively, in accordance with the terms
- ** contained in a written agreement between you and Nokia.
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
  **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain
- ** additional rights. These rights are described in the Nokia Qt LGPL
- ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
- ** package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- ** Please note Third Party Software included with Qt Solutions may impose
- ** additional restrictions and it is the user's responsibility to ensure
- ** that they have met the licensing requirements of the GPL, LGPL, or Qt
- ** Solutions Commercial license and the relevant license of the Third
- ** Party Software they are using.
- **
- ** If you are unsure which license is appropriate for your use, please
- ** contact the sales department at qt-sales@nokia.com.
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  **
  ****************************************************************************/
 
@@ -85,14 +76,14 @@
  private:
      QMdiArea *workspace;
  };
-

The user interface in this application is a QMainWindow subclass with a QMdiArea as the central widget. It implements a slot handleMessage() that will be connected to the messageReceived() signal of the QtSingleApplication class.

+

The user interface in this application is a QMainWindow subclass with a QMdiArea as the central widget. It implements a slot handleMessage() that will be connected to the messageReceived() signal of the QtSingleApplication class.

 MainWindow::MainWindow()
  {
      workspace = new QMdiArea(this);
 
      setCentralWidget(workspace);
  }
-

The MainWindow constructor creates a minimal user interface.

+

The MainWindow constructor creates a minimal user interface.

 void MainWindow::handleMessage(const QString& message)
  {
      enum Action {
@@ -177,8 +168,8 @@
 

If the message could not be sent the application starts up. Note that false is passed to the call to setActivationWindow() to prevent automatic activation for every message received, e.g. when the application should just print a file. Instead, the message handling function determines whether activation is requested, and signals that by emitting the needToShow() signal. This is then simply connected directly to QtSingleApplication's activateWindow() slot.


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-trivial.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-trivial.html index a9186b7b..5e60cfa4 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-trivial.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-example-trivial.html @@ -2,7 +2,7 @@ - + A Trivial Example @@ -15,50 +15,41 @@

A Trivial Example

The application in this example has a log-view that displays messages sent by further instances of the same application.

-

The example demonstrates the use of the QtSingleApplication class to detect and communicate with a running instance of the application using the sendMessage() API. The messageReceived() signal is used to display received messages in a QTextEdit log.

+

The example demonstrates the use of the QtSingleApplication class to detect and communicate with a running instance of the application using the sendMessage() API. The messageReceived() signal is used to display received messages in a QTextEdit log.

 /****************************************************************************
  **
- ** This file is part of a Qt Solutions component.
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
  **
- ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ ** This file is part of the Qt Solutions component.
  **
- ** Contact:  Qt Software Information (qt-info@nokia.com)
+ ** You may use this file under the terms of the BSD license as follows:
  **
- ** Commercial Usage
- ** Licensees holding valid Qt Commercial licenses may use this file in
- ** accordance with the Qt Solutions Commercial License Agreement provided
- ** with the Software or, alternatively, in accordance with the terms
- ** contained in a written agreement between you and Nokia.
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
  **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain
- ** additional rights. These rights are described in the Nokia Qt LGPL
- ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
- ** package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- ** Please note Third Party Software included with Qt Solutions may impose
- ** additional restrictions and it is the user's responsibility to ensure
- ** that they have met the licensing requirements of the GPL, LGPL, or Qt
- ** Solutions Commercial license and the relevant license of the Third
- ** Party Software they are using.
- **
- ** If you are unsure which license is appropriate for your use, please
- ** contact the sales department at qt-sales@nokia.com.
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  **
  ****************************************************************************/
 
@@ -99,12 +90,12 @@
 
      return instance.exec();

The logview object is also set as the application's activation window. Every time a message is received, the window will be raised and activated automatically.

-

The messageReceived() signal is also connected to the QTextEdit's append() slot. Every message received from further instances of this application will be displayed in the log.

+

The messageReceived() signal is also connected to the QTextEdit's append() slot. Every message received from further instances of this application will be displayed in the log.

Finally the event loop is entered.


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-members.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-members.html index 5bc438ce..c995ce3f 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-members.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-members.html @@ -2,7 +2,7 @@ - + List of All Members for QtSingleApplication @@ -14,214 +14,222 @@   Home

List of All Members for QtSingleApplication

This is the complete list of members for QtSingleApplication, including inherited members.

-

+


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-obsolete.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-obsolete.html index cc812ca0..0d07dfae 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-obsolete.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication-obsolete.html @@ -2,7 +2,7 @@ - + Obsolete Members for QtSingleApplication @@ -15,17 +15,17 @@

Obsolete Members for QtSingleApplication

The following class members are obsolete. They are provided to keep old source code working. We strongly advise against using them in new code.

-

Public Functions

-
    -
  • void initialize ( bool dummy = true )   (obsolete)
  • -
+

Public Functions

+ + +
void initialize ( bool dummy = true )   (obsolete)

Member Function Documentation

void QtSingleApplication::initialize ( bool dummy = true )


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.dcf b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.dcf index 4335ec65..d81f87fb 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.dcf +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.dcf @@ -1,19 +1,6 @@
-
- QtLockedFile - LockMode - QtLockedFile::WriteLock - QtLockedFile::NoLock - QtLockedFile::ReadLock - isLocked - lock - lockMode - open - unlock -
-
QtSingleApplication activateWindow diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.html index 70929a7d..2754a3b9 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.html @@ -2,7 +2,7 @@ - + QtSingleApplication Class Reference @@ -14,62 +14,67 @@   Home

QtSingleApplication Class Reference

The QtSingleApplication class provides an API to detect and communicate with running instances of an application. More...

-
 #include <QtSingleApplication>

Inherits QApplication.

+
 #include <QtSingleApplication>

Inherits QApplication.

+
-

Public Functions

+

Public Functions

+ + + + + + + + + + + +
QtSingleApplication ( int & argc, char ** argv, bool GUIenabled = true )
QtSingleApplication ( const QString & appId, int & argc, char ** argv )
QtSingleApplication ( int & argc, char ** argv, Type type )
QtSingleApplication ( Display * dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )
QtSingleApplication ( Display * dpy, int & argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )
QtSingleApplication ( Display * dpy, const QString & appId, int argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )
QWidget * activationWindow () const
QString id () const
bool isRunning ()
void setActivationWindow ( QWidget * aw, bool activateOnMessage = true )
- +
-

Public Slots

+

Public Slots

+ + + +
void activateWindow ()
bool sendMessage ( const QString & message, int timeout = 5000 )
- +
-

Signals

+

Signals

+ + +
void messageReceived ( const QString & message )
-

Additional Inherited Members


@@ -77,10 +82,10 @@

The QtSingleApplication class provides an API to detect and communicate with running instances of an application.

This class allows you to create applications where only one instance should be running at a time. I.e., if the user tries to launch another instance, the already running instance will be activated instead. Another usecase is a client-server system, where the first started instance will assume the role of server, and the later instances will act as clients of that server.

By default, the full path of the executable file is used to determine whether two processes are instances of the same application. You can also provide an explicit identifier string that will be compared instead.

-

The application should create the QtSingleApplication object early in the startup phase, and call isRunning() or sendMessage() to find out if another instance of this application is already running. Startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance in the sendMessage() function.

-

If isRunning() or sendMessage() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. The application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal. The messageReceived() signal will be emitted when the application receives messages from another instance of the same application.

-

If isRunning() or sendMessage() returns true, another instance is already running, and the application should terminate or enter client mode.

-

If a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot.

+

The application should create the QtSingleApplication object early in the startup phase, and call isRunning() to find out if another instance of this application is already running. If isRunning() returns false, it means that no other instance is running, and this instance has assumed the role as the running instance. In this case, the application should continue with the initialization of the application user interface before entering the event loop with exec(), as normal.

+

The messageReceived() signal will be emitted when the running application receives messages from another instance of the same application. When a message is received it might be helpful to the user to raise the application so that it becomes visible. To facilitate this, QtSingleApplication provides the setActivationWindow() function and the activateWindow() slot.

+

If isRunning() returns true, another instance is already running. It may be alerted to the fact that another instance has started by using the sendMessage() function. Also data such as startup parameters (e.g. the name of the file the user wanted this new instance to open) can be passed to the running instance with this function. Then, the application should terminate (or enter client mode).

+

If isRunning() returns true, but sendMessage() fails, that is an indication that the running instance is frozen.

Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does not make use of all QtSingleApplication's functionality (see the examples for that).

 // Original
  int main(int argc, char **argv)
@@ -88,7 +93,6 @@
      QApplication app(argc, argv);
 
      MyMainWidget mmw;
-
      mmw.show();
      return app.exec();
  }
@@ -99,62 +103,60 @@
      QtSingleApplication app(argc, argv);
 
      if (app.isRunning())
-         return 0;
+         return !app.sendMessage(someDataString);
 
      MyMainWidget mmw;
-
      app.setActivationWindow(&mmw);
-
      mmw.show();
      return app.exec();
  }
-

Once this QtSingleApplication instance is destroyed(for example, when the user quits), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance.

-

For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library.

+

Once this QtSingleApplication instance is destroyed (normally when the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance.

+

For console (non-GUI) applications, QtSingleCoreApplication may be used instead of this class, to avoid the dependency on the QtGui library.

See also QtSingleCoreApplication.


Member Function Documentation

QtSingleApplication::QtSingleApplication ( int & argc, char ** argv, bool GUIenabled = true )

-

Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc, argv, and GUIenabled are passed on to the QAppliation constructor.

+

Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc, argv, and GUIenabled are passed on to the QAppliation constructor.

If you are creating a console application (i.e. setting GUIenabled to false), you may consider using QtSingleCoreApplication instead.

-

QtSingleApplication::QtSingleApplication ( const QString & appId, int & argc, char ** argv )

+

QtSingleApplication::QtSingleApplication ( const QString & appId, int & argc, char ** argv )

Creates a QtSingleApplication object with the application identifier appId. argc and argv are passed on to the QAppliation constructor.

-

QtSingleApplication::QtSingleApplication ( int & argc, char ** argv, Type type )

-

Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc, argv, and type are passed on to the QAppliation constructor.

-

QtSingleApplication::QtSingleApplication ( Display * dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

-

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). dpy, visual, and cmap are passed on to the QApplication constructor.

-

QtSingleApplication::QtSingleApplication ( Display * dpy, int & argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

-

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.

-

QtSingleApplication::QtSingleApplication ( Display * dpy, const QString & appId, int argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

-

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be appId. dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.

+

QtSingleApplication::QtSingleApplication ( int & argc, char ** argv, Type type )

+

Creates a QtSingleApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc, argv, and type are passed on to the QAppliation constructor.

+

QtSingleApplication::QtSingleApplication ( Display * dpy, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

+

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). dpy, visual, and cmap are passed on to the QApplication constructor.

+

QtSingleApplication::QtSingleApplication ( Display * dpy, int & argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

+

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be QCoreApplication::applicationFilePath(). dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.

+

QtSingleApplication::QtSingleApplication ( Display * dpy, const QString & appId, int argc, char ** argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 )

+

Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier will be appId. dpy, argc, argv, visual, and cmap are passed on to the QApplication constructor.

void QtSingleApplication::activateWindow ()   [slot]

De-minimizes, raises, and activates this application's activation window. This function does nothing if no activation window has been set.

This is a convenience function to show the user that this application instance has been activated when he has tried to start another instance.

This function should typically be called in response to the messageReceived() signal. By default, that will happen automatically, if an activation window has been set.

-

See also setActivationWindow(), messageReceived(), and initialize().

-

QWidget * QtSingleApplication::activationWindow () const

+

See also setActivationWindow(), messageReceived(), and initialize().

+

QWidget * QtSingleApplication::activationWindow () const

Returns the applications activation window if one has been set by calling setActivationWindow(), otherwise returns 0.

See also setActivationWindow().

-

QString QtSingleApplication::id () const

+

QString QtSingleApplication::id () const

Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application.

bool QtSingleApplication::isRunning ()

Returns true if another instance of this application is running; otherwise false.

This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session).

See also sendMessage().

-

void QtSingleApplication::messageReceived ( const QString & message )   [signal]

+

void QtSingleApplication::messageReceived ( const QString & message )   [signal]

This signal is emitted when the current instance receives a message from another instance of this application.

See also sendMessage(), setActivationWindow(), and activateWindow().

-

bool QtSingleApplication::sendMessage ( const QString & message, int timeout = 5000 )   [slot]

+

bool QtSingleApplication::sendMessage ( const QString & message, int timeout = 5000 )   [slot]

Tries to send the text message to the currently running instance. The QtSingleApplication object in the running instance will emit the messageReceived() signal when it receives the message.

This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within timeout milliseconds, this function return false.

See also isRunning() and messageReceived().

-

void QtSingleApplication::setActivationWindow ( QWidget * aw, bool activateOnMessage = true )

+

void QtSingleApplication::setActivationWindow ( QWidget * aw, bool activateOnMessage = true )

Sets the activation window of this application to aw. The activation window is the widget that will be activated by activateWindow(). This is typically the application's main window.

If activateOnMessage is true (the default), the window will be activated automatically every time a message is received, just prior to the messageReceived() signal being emitted.

See also activationWindow(), activateWindow(), and messageReceived().


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.index b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.index index dafe15c4..56052c2a 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.index +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.index @@ -2,111 +2,89 @@ - - - - - - - - - + + + + - - - + + + + - - - + + + + + + + + - - - - - - + + + - - - + + + - - - + + + - - - + + + - - - - - + + + + + - - - - - - + + + + + + - - + + - - + + - + - + - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qch b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qch deleted file mode 100644 index 03a09bc06637643bac47eca155406e4f6af8d6d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48128 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í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 rnuxEq|1mrL8H(`lXRtq`0ip&_Ba diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qhp b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qhp index 5bddacce..ff42d9df 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qhp +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsingleapplication.qhp @@ -1,6 +1,6 @@ - com.trolltech.qtsolutions.qtsingleapplication_2.6 + com.nokia.qtsolutions.qtsingleapplication_head qdoc qt @@ -13,45 +13,33 @@ qtsingleapplication
-
-
-
-
+
+
+
+
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - qtlockedfile.html qtsingleapplication.html index.html qtsingleapplication-example-trivial.html diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-example-console.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-example-console.html index 7a845bde..18a9ae89 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-example-console.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-example-console.html @@ -2,7 +2,7 @@ - + A non-GUI example @@ -28,47 +28,38 @@

main.cpp:

 /****************************************************************************
  **
- ** This file is part of a Qt Solutions component.
+ ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+ ** Contact: http://www.qt-project.org/legal
  **
- ** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ ** This file is part of the Qt Solutions component.
  **
- ** Contact:  Qt Software Information (qt-info@nokia.com)
+ ** You may use this file under the terms of the BSD license as follows:
  **
- ** Commercial Usage
- ** Licensees holding valid Qt Commercial licenses may use this file in
- ** accordance with the Qt Solutions Commercial License Agreement provided
- ** with the Software or, alternatively, in accordance with the terms
- ** contained in a written agreement between you and Nokia.
+ ** "Redistribution and use in source and binary forms, with or without
+ ** modification, are permitted provided that the following conditions are
+ ** met:
+ **   * Redistributions of source code must retain the above copyright
+ **     notice, this list of conditions and the following disclaimer.
+ **   * Redistributions in binary form must reproduce the above copyright
+ **     notice, this list of conditions and the following disclaimer in
+ **     the documentation and/or other materials provided with the
+ **     distribution.
+ **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+ **     the names of its contributors may be used to endorse or promote
+ **     products derived from this software without specific prior written
+ **     permission.
  **
- ** GNU Lesser General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU Lesser
- ** General Public License version 2.1 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.LGPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU Lesser General Public License version 2.1 requirements
- ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
- **
- ** In addition, as a special exception, Nokia gives you certain
- ** additional rights. These rights are described in the Nokia Qt LGPL
- ** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
- ** package.
- **
- ** GNU General Public License Usage
- ** Alternatively, this file may be used under the terms of the GNU
- ** General Public License version 3.0 as published by the Free Software
- ** Foundation and appearing in the file LICENSE.GPL included in the
- ** packaging of this file.  Please review the following information to
- ** ensure the GNU General Public License version 3.0 requirements will be
- ** met: http://www.gnu.org/copyleft/gpl.html.
- **
- ** Please note Third Party Software included with Qt Solutions may impose
- ** additional restrictions and it is the user's responsibility to ensure
- ** that they have met the licensing requirements of the GPL, LGPL, or Qt
- ** Solutions Commercial license and the relevant license of the Third
- ** Party Software they are using.
- **
- ** If you are unsure which license is appropriate for your use, please
- ** contact the sales department at qt-sales@nokia.com.
+ ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  **
  ****************************************************************************/
 
@@ -103,9 +94,9 @@
 
      if (app.isRunning()) {
          QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid()));
-         bool sentok = app.sendMessage(msg);
+         bool sentok = app.sendMessage(msg, 2000);
          QString rep("Another instance is running, so I will exit.");
-         rep += sentok ? " Message sent ok." : " Message sending failed.";
+         rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen.";
          report(rep);
          return 0;
      } else {
@@ -120,8 +111,8 @@
  #include "main.moc"


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-members.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-members.html index 91c857e2..69fb8581 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-members.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication-members.html @@ -2,7 +2,7 @@ - + List of All Members for QtSingleCoreApplication @@ -14,113 +14,113 @@   Home

List of All Members for QtSingleCoreApplication

This is the complete list of members for QtSingleCoreApplication, including inherited members.

-

+


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication.html b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication.html index a1198146..a20cf2f4 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication.html +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/html/qtsinglecoreapplication.html @@ -2,7 +2,7 @@ - + QtSingleCoreApplication Class Reference @@ -14,81 +14,85 @@   Home

QtSingleCoreApplication Class Reference

A variant of the QtSingleApplication class for non-GUI applications. More...

-
 #include <QtSingleCoreApplication>

Inherits QCoreApplication.

+
 #include <QtSingleCoreApplication>

Inherits QCoreApplication.

+
-

Public Functions

+

Public Functions

+ + + + + +
QtSingleCoreApplication ( int & argc, char ** argv )
QtSingleCoreApplication ( const QString & appId, int & argc, char ** argv )
QString id () const
bool isRunning ()
- +
-

Public Slots

+

Public Slots

+ + +
bool sendMessage ( const QString & message, int timeout = 5000 )
    -
  • bool sendMessage ( const QString & message, int timeout = 5000 )
  • -
- +
-

Signals

+

Signals

+ + +
void messageReceived ( const QString & message )
-

Additional Inherited Members


Detailed Description

A variant of the QtSingleApplication class for non-GUI applications.

-

This class is a variant of QtSingleApplication suited for use in console (non-GUI) applications. It is an extension of QCoreApplication (instead of QApplication). It does not require the QtGui library.

+

This class is a variant of QtSingleApplication suited for use in console (non-GUI) applications. It is an extension of QCoreApplication (instead of QApplication). It does not require the QtGui library.

The API and usage is identical to QtSingleApplication, except that functions relating to the "activation window" are not present, for obvious reasons. Please refer to the QtSingleApplication documentation for explanation of the usage.

A QtSingleCoreApplication instance can communicate to a QtSingleApplication instance if they share the same application id. Hence, this class can be used to create a light-weight command-line tool that sends commands to a GUI application.

See also QtSingleApplication.


Member Function Documentation

QtSingleCoreApplication::QtSingleCoreApplication ( int & argc, char ** argv )

-

Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc and argv are passed on to the QCoreAppliation constructor.

-

QtSingleCoreApplication::QtSingleCoreApplication ( const QString & appId, int & argc, char ** argv )

+

Creates a QtSingleCoreApplication object. The application identifier will be QCoreApplication::applicationFilePath(). argc and argv are passed on to the QCoreAppliation constructor.

+

QtSingleCoreApplication::QtSingleCoreApplication ( const QString & appId, int & argc, char ** argv )

Creates a QtSingleCoreApplication object with the application identifier appId. argc and argv are passed on to the QCoreAppliation constructor.

-

QString QtSingleCoreApplication::id () const

+

QString QtSingleCoreApplication::id () const

Returns the application identifier. Two processes with the same identifier will be regarded as instances of the same application.

bool QtSingleCoreApplication::isRunning ()

Returns true if another instance of this application is running; otherwise false.

This function does not find instances of this application that are being run by a different user (on Windows: that are running in another session).

See also sendMessage().

-

void QtSingleCoreApplication::messageReceived ( const QString & message )   [signal]

+

void QtSingleCoreApplication::messageReceived ( const QString & message )   [signal]

This signal is emitted when the current instance receives a message from another instance of this application.

See also sendMessage().

-

bool QtSingleCoreApplication::sendMessage ( const QString & message, int timeout = 5000 )   [slot]

+

bool QtSingleCoreApplication::sendMessage ( const QString & message, int timeout = 5000 )   [slot]

Tries to send the text message to the currently running instance. The QtSingleCoreApplication object in the running instance will emit the messageReceived() signal when it receives the message.

This function returns true if the message has been sent to, and processed by, the current instance. If there is no instance currently running, or if the running instance fails to process the message within timeout milliseconds, this function return false.

See also isRunning() and messageReceived().


- - + +
Copyright © 2009 NokiaTrademarksCopyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
diff --git a/telldus-gui/3rdparty/qtsingleapplication/doc/index.qdoc b/telldus-gui/3rdparty/qtsingleapplication/doc/index.qdoc index 9c3308d8..6a2a768a 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/doc/index.qdoc +++ b/telldus-gui/3rdparty/qtsingleapplication/doc/index.qdoc @@ -1,3 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + /*! \page index.html \title Single Application @@ -44,4 +84,4 @@ - */ \ No newline at end of file +*/ diff --git a/telldus-gui/3rdparty/qtsingleapplication/examples/console/console.qdoc b/telldus-gui/3rdparty/qtsingleapplication/examples/console/console.qdoc index b1d42818..77b0d736 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/examples/console/console.qdoc +++ b/telldus-gui/3rdparty/qtsingleapplication/examples/console/console.qdoc @@ -1,47 +1,41 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ /*! \page qtsinglecoreapplication-example-console.html diff --git a/telldus-gui/3rdparty/qtsingleapplication/examples/console/main.cpp b/telldus-gui/3rdparty/qtsingleapplication/examples/console/main.cpp index f083f072..652feb93 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/examples/console/main.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/examples/console/main.cpp @@ -1,52 +1,46 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include "qtsinglecoreapplication.h" -#include +#include void report(const QString& msg) @@ -77,9 +71,9 @@ int main(int argc, char **argv) if (app.isRunning()) { QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid())); - bool sentok = app.sendMessage(msg); + bool sentok = app.sendMessage(msg, 2000); QString rep("Another instance is running, so I will exit."); - rep += sentok ? " Message sent ok." : " Message sending failed."; + rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen."; report(rep); return 0; } else { diff --git a/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.pro b/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.pro index 673497a4..3e52586b 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.pro +++ b/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.pro @@ -1,3 +1,4 @@ +greaterThan(QT_MAJOR_VERSION, 4): QT += printsupport TEMPLATE = app include(../../src/qtsingleapplication.pri) diff --git a/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.qdoc b/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.qdoc index f2afb559..bfd15d06 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.qdoc +++ b/telldus-gui/3rdparty/qtsingleapplication/examples/loader/loader.qdoc @@ -1,47 +1,41 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ /*! \page qtsingleapplication-example-loader.html diff --git a/telldus-gui/3rdparty/qtsingleapplication/examples/loader/main.cpp b/telldus-gui/3rdparty/qtsingleapplication/examples/loader/main.cpp index 9f810bb0..f55e57ac 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/examples/loader/main.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/examples/loader/main.cpp @@ -1,57 +1,51 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include class MainWindow : public QMainWindow { diff --git a/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/main.cpp b/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/main.cpp index 1e6cf74a..69e102f3 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/main.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/main.cpp @@ -1,51 +1,45 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include -#include +#include class TextEdit : public QTextEdit { diff --git a/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/trivial.qdoc b/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/trivial.qdoc index d57cc13a..9491cb65 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/trivial.qdoc +++ b/telldus-gui/3rdparty/qtsingleapplication/examples/trivial/trivial.qdoc @@ -1,47 +1,41 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ /*! \page qtsingleapplication-example-trivial.html diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.cpp b/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.cpp index 1d494a73..332b0643 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.cpp @@ -1,62 +1,58 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include "qtlocalpeer.h" -#include -#include +#include +#include #if defined(Q_OS_WIN) -#include -#include +#include +#include typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) +#include #include +#include #endif namespace QtLP_Private { @@ -164,8 +160,11 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout) QDataStream ds(&socket); ds.writeBytes(uMsg.constData(), uMsg.size()); bool res = socket.waitForBytesWritten(timeout); - res &= socket.waitForReadyRead(timeout); // wait for ack - res &= (socket.read(qstrlen(ack)) == ack); + if (res) { + res &= socket.waitForReadyRead(timeout); // wait for ack + if (res) + res &= (socket.read(qstrlen(ack)) == ack); + } return res; } @@ -191,13 +190,14 @@ void QtLocalPeer::receiveConnection() uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); if (got < 0) { - qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString(); + qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } QString message(QString::fromUtf8(uMsg)); socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); + socket->waitForDisconnected(1000); // make sure client reads ack delete socket; emit messageReceived(message); //### (might take a long time to return) } diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.h b/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.h index 1169e1fb..1b533b1a 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.h +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtlocalpeer.h @@ -1,57 +1,51 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ +#ifndef QTLOCALPEER_H +#define QTLOCALPEER_H -#include -#include -#include +#include +#include +#include -namespace QtLP_Private { #include "qtlockedfile.h" -} class QtLocalPeer : public QObject { @@ -79,3 +73,5 @@ protected: private: static const char* ack; }; + +#endif // QTLOCALPEER_H diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.cpp b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.cpp index d4fad753..c142a863 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.cpp @@ -1,47 +1,41 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include "qtlockedfile.h" diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.h b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.h index e229484d..84c18e5c 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.h +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile.h @@ -1,58 +1,52 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #ifndef QTLOCKEDFILE_H #define QTLOCKEDFILE_H -#include +#include #ifdef Q_OS_WIN -#include +#include #endif -#if defined(Q_WS_WIN) +#if defined(Q_OS_WIN) # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) # define QT_QTLOCKEDFILE_EXPORT # elif defined(QT_QTLOCKEDFILE_IMPORT) @@ -68,6 +62,8 @@ # define QT_QTLOCKEDFILE_EXPORT #endif +namespace QtLP_Private { + class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile { public: @@ -97,5 +93,5 @@ private: #endif LockMode m_lock_mode; }; - +} #endif diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_unix.cpp b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_unix.cpp index f5997ba4..976c1b9e 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_unix.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_unix.cpp @@ -1,47 +1,41 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_win.cpp b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_win.cpp index 8bbaa53b..5e212620 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_win.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtlockedfile_win.cpp @@ -1,57 +1,55 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include "qtlockedfile.h" #include -#include +#include #define MUTEX_PREFIX "QtLockedFile mutex " // Maximum number of concurrent read locks. Must not be greater than MAXIMUM_WAIT_OBJECTS #define MAX_READERS MAXIMUM_WAIT_OBJECTS +#if QT_VERSION >= 0x050000 +#define QT_WA(unicode, ansi) unicode +#endif + Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate) { if (mutexname.isEmpty()) { diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp b/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp index 2ab0bbd9..d0fb15d7 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.cpp @@ -1,53 +1,47 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ #include "qtsingleapplication.h" #include "qtlocalpeer.h" -#include +#include /*! @@ -68,28 +62,31 @@ that will be compared instead. The application should create the QtSingleApplication object early - in the startup phase, and call isRunning() or sendMessage() to - find out if another instance of this application is already - running. Startup parameters (e.g. the name of the file the user - wanted this new instance to open) can be passed to the running - instance in the sendMessage() function. + in the startup phase, and call isRunning() to find out if another + instance of this application is already running. If isRunning() + returns false, it means that no other instance is running, and + this instance has assumed the role as the running instance. In + this case, the application should continue with the initialization + of the application user interface before entering the event loop + with exec(), as normal. - If isRunning() or sendMessage() returns false, it means that no - other instance is running, and this instance has assumed the role - as the running instance. The application should continue with the - initialization of the application user interface before entering - the event loop with exec(), as normal. The messageReceived() - signal will be emitted when the application receives messages from - another instance of the same application. + The messageReceived() signal will be emitted when the running + application receives messages from another instance of the same + application. When a message is received it might be helpful to the + user to raise the application so that it becomes visible. To + facilitate this, QtSingleApplication provides the + setActivationWindow() function and the activateWindow() slot. - If isRunning() or sendMessage() returns true, another instance is - already running, and the application should terminate or enter - client mode. + If isRunning() returns true, another instance is already + running. It may be alerted to the fact that another instance has + started by using the sendMessage() function. Also data such as + startup parameters (e.g. the name of the file the user wanted this + new instance to open) can be passed to the running instance with + this function. Then, the application should terminate (or enter + client mode). - If a message is received it might be helpful to the user to raise - the application so that it becomes visible. To facilitate this, - QtSingleApplication provides the setActivationWindow() function - and the activateWindow() slot. + If isRunning() returns true, but sendMessage() fails, that is an + indication that the running instance is frozen. Here's an example that shows how to convert an existing application to use QtSingleApplication. It is very simple and does @@ -103,7 +100,6 @@ QApplication app(argc, argv); MyMainWidget mmw; - mmw.show(); return app.exec(); } @@ -114,19 +110,17 @@ QtSingleApplication app(argc, argv); if (app.isRunning()) - return 0; + return !app.sendMessage(someDataString); MyMainWidget mmw; - app.setActivationWindow(&mmw); - mmw.show(); return app.exec(); } \endcode - Once this QtSingleApplication instance is destroyed(for example, - when the user quits), when the user next attempts to run the + Once this QtSingleApplication instance is destroyed (normally when + the process exits or crashes), when the user next attempts to run the application this instance will not, of course, be encountered. The next instance to call isRunning() or sendMessage() will assume the role as the new running instance. @@ -176,6 +170,7 @@ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char * sysInit(appId); } +#if QT_VERSION < 0x050000 /*! Creates a QtSingleApplication object. The application identifier @@ -189,7 +184,7 @@ QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type) } -#if defined(Q_WS_X11) +# if defined(Q_WS_X11) /*! Special constructor for X11, ref. the documentation of QApplication's corresponding constructor. The application identifier @@ -227,7 +222,8 @@ QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int { sysInit(appId); } -#endif +# endif // Q_WS_X11 +#endif // QT_VERSION < 0x050000 /*! diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.h b/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.h index b73f5d66..049406f7 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.h +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.h @@ -1,55 +1,51 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ +#ifndef QTSINGLEAPPLICATION_H +#define QTSINGLEAPPLICATION_H -#include +#include class QtLocalPeer; -#if defined(Q_WS_WIN) +#if defined(Q_OS_WIN) # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) # define QT_QTSINGLEAPPLICATION_EXPORT # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) @@ -72,12 +68,14 @@ class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication public: QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(const QString &id, int &argc, char **argv); +#if QT_VERSION < 0x050000 QtSingleApplication(int &argc, char **argv, Type type); -#if defined(Q_WS_X11) +# if defined(Q_WS_X11) QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); -#endif +# endif // Q_WS_X11 +#endif // QT_VERSION < 0x050000 bool isRunning(); QString id() const; @@ -103,3 +101,5 @@ private: QtLocalPeer *peer; QWidget *actWin; }; + +#endif // QTSINGLEAPPLICATION_H diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.pri b/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.pri index 5909f049..6f2bced9 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.pri +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtsingleapplication.pri @@ -2,6 +2,7 @@ include(../common.pri) INCLUDEPATH += $$PWD DEPENDPATH += $$PWD QT *= network +greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets qtsingleapplication-uselib:!qtsingleapplication-buildlib { LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.cpp b/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.cpp index 9b7fc40b..56345373 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.cpp +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.cpp @@ -1,47 +1,41 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ diff --git a/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.h b/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.h index f4738d5d..b87fffe4 100644 --- a/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.h +++ b/telldus-gui/3rdparty/qtsingleapplication/src/qtsinglecoreapplication.h @@ -1,51 +1,47 @@ /**************************************************************************** ** -** This file is part of a Qt Solutions component. -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Qt Software Information (qt-info@nokia.com) -** -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Solutions Commercial License Agreement provided -** with the Software or, alternatively, in accordance with the terms -** contained in a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** Please note Third Party Software included with Qt Solutions may impose -** additional restrictions and it is the user's responsibility to ensure -** that they have met the licensing requirements of the GPL, LGPL, or Qt -** Solutions Commercial license and the relevant license of the Third -** Party Software they are using. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Solutions component. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names +** of its contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** ****************************************************************************/ +#ifndef QTSINGLECOREAPPLICATION_H +#define QTSINGLECOREAPPLICATION_H -#include +#include class QtLocalPeer; @@ -71,3 +67,5 @@ Q_SIGNALS: private: QtLocalPeer* peer; }; + +#endif // QTSINGLECOREAPPLICATION_H From d3b0a279b850816fb4a11b85ec7a7610353ba253 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 Sep 2013 17:15:24 +0200 Subject: [PATCH 2185/2215] Fix for Debian-build (missing uinstd.h) --- telldus-gui/Plugins/Controllers/tellstick.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-gui/Plugins/Controllers/tellstick.cpp b/telldus-gui/Plugins/Controllers/tellstick.cpp index a9758ab0..a541dfc2 100644 --- a/telldus-gui/Plugins/Controllers/tellstick.cpp +++ b/telldus-gui/Plugins/Controllers/tellstick.cpp @@ -7,6 +7,8 @@ #ifdef _WINDOWS #include +#else +#include #endif #include "ftd2xx.h" From 17a269e7c14eddede0d030853625969304fe522f Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 16 Sep 2013 13:51:41 +0200 Subject: [PATCH 2186/2215] The ugly temporary fix for segfault in TelldusCenter did not suffice. Trying this instead. --- telldus-core/common/EventHandler_unix.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 15372b78..5aa80e29 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -24,7 +24,7 @@ public: EventHandler::EventHandler() { d = new PrivateData; - printf(""); + pthread_cond_init(&d->event, NULL); pthread_cond_init(&d->event, NULL); pthread_mutex_init(&d->mutex, NULL); } From 6880ca5555779a44ebfd7cf38748ce9ec6f4f774 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 17 Sep 2013 12:42:21 +0200 Subject: [PATCH 2187/2215] Bumped version to 2.1.2 Beta7 --- telldus-core/CMakeLists.txt | 4 ++-- telldus-gui/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index a21f3d25..edaed5d1 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -11,9 +11,9 @@ ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) -SET(PACKAGE_PATCH_VERSION 1) +SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "") +SET(PACKAGE_SUBVERSION "beta7") SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index d74d0e6e..a22f2fb8 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -11,7 +11,7 @@ SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION} Beta1") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta7") SET(BRANDING "telldus" CACHE STRING "The brand to use") From 9bd208992d960a10673a72abac251598b2a5d705 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 20 Sep 2013 14:14:17 +0200 Subject: [PATCH 2188/2215] Fix build error for QtDesktop in Linux --- telldus-gui/3rdparty/qt-components-desktop.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-gui/3rdparty/qt-components-desktop.cmake b/telldus-gui/3rdparty/qt-components-desktop.cmake index d76bec8c..86d05348 100644 --- a/telldus-gui/3rdparty/qt-components-desktop.cmake +++ b/telldus-gui/3rdparty/qt-components-desktop.cmake @@ -92,3 +92,7 @@ ELSE() LIBRARY_OUTPUT_DIRECTORY ${QT_COMPONENTS_OUTPUT_DIR}/plugin ) ENDIF() + +IF(UNIX) + INSTALL(DIRECTORY "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/declarative" DESTINATION "${PLUGIN_LIB_FULL_PATH}") +ENDIF(UNIX) From 405f2f7f700caf9bef3a23b30da821f1c9e2be20 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 20 Sep 2013 14:22:28 +0200 Subject: [PATCH 2189/2215] Bumped version to 2.1.2 Beta8 --- telldus-core/CMakeLists.txt | 2 +- telldus-gui/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index edaed5d1..0a94a00a 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -13,7 +13,7 @@ SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "beta7") +SET(PACKAGE_SUBVERSION "beta8") SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index a22f2fb8..8ed6fdb5 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -11,7 +11,7 @@ SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta7") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta8") SET(BRANDING "telldus" CACHE STRING "The brand to use") From 80ef685e7eba408a9882e5ad54c41174e1a70b3c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Oct 2013 14:52:12 +0200 Subject: [PATCH 2190/2215] Add new CA certificates --- telldus-gui/Plugins/Live/GeoTrustGlobalCA.pem | 20 ++++++++++++++++ telldus-gui/Plugins/Live/Live.qrc | 2 ++ telldus-gui/Plugins/Live/LiveObject.cpp | 2 ++ telldus-gui/Plugins/Live/RapidSSLCA.pem | 23 +++++++++++++++++++ 4 files changed, 47 insertions(+) create mode 100644 telldus-gui/Plugins/Live/GeoTrustGlobalCA.pem create mode 100644 telldus-gui/Plugins/Live/RapidSSLCA.pem diff --git a/telldus-gui/Plugins/Live/GeoTrustGlobalCA.pem b/telldus-gui/Plugins/Live/GeoTrustGlobalCA.pem new file mode 100644 index 00000000..bcb25297 --- /dev/null +++ b/telldus-gui/Plugins/Live/GeoTrustGlobalCA.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg +R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 +9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq +fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv +iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU +1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ +bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW +MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA +ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l +uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn +Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS +tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF +PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un +hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV +5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== +-----END CERTIFICATE----- diff --git a/telldus-gui/Plugins/Live/Live.qrc b/telldus-gui/Plugins/Live/Live.qrc index 5af20a56..d9e2d682 100644 --- a/telldus-gui/Plugins/Live/Live.qrc +++ b/telldus-gui/Plugins/Live/Live.qrc @@ -1,5 +1,7 @@ Equifax_Secure_CA.pem + GeoTrustGlobalCA.pem + RapidSSLCA.pem diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 213a3747..c892ae3f 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -37,6 +37,8 @@ LiveObject::LiveObject( QScriptEngine *engine, QObject * parent ) d->registered = false; QSslSocket::addDefaultCaCertificates(":/Equifax_Secure_CA.pem"); + QSslSocket::addDefaultCaCertificates(":/GeoTrustGlobalCA.pem"); + QSslSocket::addDefaultCaCertificates(":/RapidSSLCA.pem"); d->socket = new QSslSocket(this); d->socket->setProtocol( QSsl::TlsV1 ); connect(d->socket, SIGNAL(encrypted()), this, SLOT(p_connected())); diff --git a/telldus-gui/Plugins/Live/RapidSSLCA.pem b/telldus-gui/Plugins/Live/RapidSSLCA.pem new file mode 100644 index 00000000..71af595e --- /dev/null +++ b/telldus-gui/Plugins/Live/RapidSSLCA.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID1TCCAr2gAwIBAgIDAjbRMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMTAwMjE5MjI0NTA1WhcNMjAwMjE4MjI0NTA1WjA8MQswCQYDVQQG +EwJVUzEXMBUGA1UEChMOR2VvVHJ1c3QsIEluYy4xFDASBgNVBAMTC1JhcGlkU1NM +IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3H4Vsce2cy1rfa0 +l6P7oeYLUF9QqjraD/w9KSRDxhApwfxVQHLuverfn7ZB9EhLyG7+T1cSi1v6kt1e +6K3z8Buxe037z/3R5fjj3Of1c3/fAUnPjFbBvTfjW761T4uL8NpPx+PdVUdp3/Jb +ewdPPeWsIcHIHXro5/YPoar1b96oZU8QiZwD84l6pV4BcjPtqelaHnnzh8jfyMX8 +N8iamte4dsywPuf95lTq319SQXhZV63xEtZ/vNWfcNMFbPqjfWdY3SZiHTGSDHl5 +HI7PynvBZq+odEj7joLCniyZXHstXZu8W1eefDp6E63yoxhbK1kPzVw662gzxigd +gtFQiwIDAQABo4HZMIHWMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUa2k9ahhC +St2PAmU5/TUkhniRFjAwHwYDVR0jBBgwFoAUwHqYaI2J+6sFZAwRfap9ZbjKzE4w +EgYDVR0TAQH/BAgwBgEB/wIBADA6BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3Js +Lmdlb3RydXN0LmNvbS9jcmxzL2d0Z2xvYmFsLmNybDA0BggrBgEFBQcBAQQoMCYw +JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdlb3RydXN0LmNvbTANBgkqhkiG9w0B +AQUFAAOCAQEAq7y8Cl0YlOPBscOoTFXWvrSY8e48HM3P8yQkXJYDJ1j8Nq6iL4/x +/torAsMzvcjdSCIrYA+lAxD9d/jQ7ZZnT/3qRyBwVNypDFV+4ZYlitm12ldKvo2O +SUNjpWxOJ4cl61tt/qJ/OCjgNqutOaWlYsS3XFgsql0BYKZiZ6PAx2Ij9OdsRu61 +04BqIhPSLT90T+qvjF+0OJzbrs6vhB6m9jRRWXnT43XcvNfzc9+S7NIgWW+c+5X4 +knYYCnwPLKbK3opie9jzzl9ovY8+wXS7FXI6FoOpC+ZNmZzYV+yoAVHHb1c0XqtK +LEL2TxyJeN4mTvVvk0wVaydWTQBUbHq3tw== +-----END CERTIFICATE----- From ce86c90c8b5aacd718399a9da916a958174a3caf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Oct 2013 16:10:33 +0200 Subject: [PATCH 2191/2215] This is not relevant in OS X --- telldus-gui/3rdparty/qt-components-desktop.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/3rdparty/qt-components-desktop.cmake b/telldus-gui/3rdparty/qt-components-desktop.cmake index 86d05348..6c4f6eda 100644 --- a/telldus-gui/3rdparty/qt-components-desktop.cmake +++ b/telldus-gui/3rdparty/qt-components-desktop.cmake @@ -93,6 +93,6 @@ ELSE() ) ENDIF() -IF(UNIX) +IF(UNIX AND NOT APPLE) INSTALL(DIRECTORY "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/declarative" DESTINATION "${PLUGIN_LIB_FULL_PATH}") -ENDIF(UNIX) +ENDIF() From 0886564e9445e8cacbe6374285b08211bffa10a0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Oct 2013 16:11:24 +0200 Subject: [PATCH 2192/2215] Add codesigning on OS X --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 34 ++++++++++--------- telldus-gui/TelldusCenter/CMakeLists.txt | 2 +- telldus-gui/TelldusGui/CMakeLists.txt | 4 +-- telldus-gui/cmake/FindSignTool.cmake | 19 +++++++---- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 4ee6386b..061f2a3d 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -98,15 +98,29 @@ IF(Plugin_SRCS) TARGET_LINK_LIBRARIES( ${Plugin_NAME} ${Plugin_LIBRARIES} ) IF (APPLE) + SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES + PREFIX "" + ) + ELSEIF (WIN32) + SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES + PREFIX "Plugins/script/" + ) + ELSE () + SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script + ) + INSTALL(TARGETS ${Plugin_NAME} + LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script" + ) + ENDIF () + SIGN(${Plugin_NAME}) + IF(APPLE) ADD_CUSTOM_COMMAND(TARGET ${Plugin_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${Plugin_NAME}.dylib ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script COMMENT "Copy plugin ${Plugin_NAME} to destination bundle" ) - SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES - PREFIX "" - ) INSTALL(CODE " GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE) SET(app \"\${DESTDIR}/Applications/TelldusCenter.app\") @@ -137,19 +151,7 @@ IF(Plugin_SRCS) ENDFOREACH() ") - ELSEIF (WIN32) - SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES - PREFIX "Plugins/script/" - ) - ELSE (APPLE) - SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script - ) - INSTALL(TARGETS ${Plugin_NAME} - LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script" - ) - ENDIF (APPLE) - SIGN(${Plugin_NAME}) + ENDIF() ELSE(Plugin_SRCS) ADD_CUSTOM_TARGET(${Plugin_NAME} ALL SOURCES ${Plugin_FILES} ${Plugin_TARGET_FILES} diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index b8b64def..09958496 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -151,7 +151,6 @@ TARGET_LINK_LIBRARIES( ${telldus-center_TARGET} ${telldus-center_LIBRARIES} ) SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist ) -SIGN(${telldus-center_TARGET}) IF (APPLE) SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} @@ -161,6 +160,7 @@ IF (APPLE) COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script/" ) ENDIF (APPLE) +SIGN(${telldus-center_TARGET}) IF (UNIX) IF (GENERATE_MAN) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 845ea9c1..dbbd0f35 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -143,8 +143,6 @@ ENDIF (UNIX) TARGET_LINK_LIBRARIES( ${telldus-gui_TARGET} ${telldus-gui_LIBRARIES} ) -SIGN(${telldus-gui_TARGET}) - SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES FRAMEWORK TRUE # PUBLIC_HEADER ${telldus-gui_HDRS} @@ -153,6 +151,8 @@ SET_TARGET_PROPERTIES(${telldus-gui_TARGET} PROPERTIES INSTALL_NAME_DIR "/Library/Frameworks" ) +SIGN(${telldus-gui_TARGET}) + IF (WIN32) ADD_CUSTOM_COMMAND( TARGET ${telldus-gui_TARGET} POST_BUILD diff --git a/telldus-gui/cmake/FindSignTool.cmake b/telldus-gui/cmake/FindSignTool.cmake index db63e164..40462d99 100644 --- a/telldus-gui/cmake/FindSignTool.cmake +++ b/telldus-gui/cmake/FindSignTool.cmake @@ -1,10 +1,10 @@ -IF(WIN32) +IF(WIN32 OR APPLE) SET(SIGN_FILES FALSE CACHE BOOL "Sign files ofter build") ENDIF() FUNCTION(SIGN TARGET) - IF (NOT WIN32) + IF (NOT WIN32 AND NOT APPLE) RETURN() ENDIF() IF (NOT SIGN_FILES) @@ -12,8 +12,15 @@ FUNCTION(SIGN TARGET) ENDIF() GET_TARGET_PROPERTY(file ${TARGET} LOCATION) GET_FILENAME_COMPONENT(filename ${file} NAME) - ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD - COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} - COMMENT "Signing file ${filename}" - ) + IF (WIN32) + ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD + COMMAND signtool.exe sign /a /t http://timestamp.verisign.com/scripts/timstamp.dll ${file} + COMMENT "Signing file ${filename}" + ) + ELSEIF(APPLE) + ADD_CUSTOM_COMMAND( TARGET ${TARGET} POST_BUILD + COMMAND codesign -v --force --sign "Developer ID Application: Telldus Technologies AB" ${file} + COMMENT "Signing file ${filename}" + ) + ENDIF() ENDFUNCTION() From 22fe154ee3e29e05339263ba7d33c25a6f2d689a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 18 Nov 2013 16:53:34 +0100 Subject: [PATCH 2193/2215] Updated sensor value icons --- telldus-gui/Plugins/Sensors/icon_humidity.png | Bin 1684 -> 1411 bytes telldus-gui/Plugins/Sensors/icon_rain.png | Bin 1524 -> 1520 bytes telldus-gui/Plugins/Sensors/icon_temp.png | Bin 1644 -> 1377 bytes telldus-gui/Plugins/Sensors/icon_wind.png | Bin 456 -> 1579 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/telldus-gui/Plugins/Sensors/icon_humidity.png b/telldus-gui/Plugins/Sensors/icon_humidity.png index 29b02e26676f112bf67aec6d5438028f90622ed3..798e89e258e5df4007dca4cc01b43bcbc7a23d34 100644 GIT binary patch delta 1356 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 P00000NkvXXu0mjfBlg=^ delta 1517 zcmVbV)=(R7l6Q zR%whCRTlofTlMPk&_+NIT-uQtg_%(!#!NIOB;(SI<2GseXMdvNLZUy+xW$Di1Dc7( zg&5-!M+KvivcW)jjj$R#i7(8=HwIdGFPG z@7%L}=X~c3R>Q{V{k1g%I@UCaakEuBm0Dn!IW?6RBV>@@7I^z`>#J<|6mwJVHieHSg+TWh!7=C z1Q|EYoX1~Z@bY^<(~B>@zxw(Aesbfb=MLshKDxB?-A^~(c*!{|uoMw!t)n=OqBtt# z>W5xt+bv6$t@)V@>QS@v%Wu;HBquxj2bQhfG=IcWthJ`r+V_2cpb!+n%C7Ehy9ciQ z%h`tp{>rj77fhczd3?)Hre(z@P2+l90FbFM3i%*`pa7)IIPJIBwEgKPNBZ%lom>0% z4p+DR_4u7t8wN+SqzV!a2tp_dgtgZ5Ja=qkPw$88Hh=Yf@2>rg%|GtC{n@uqnlyge z34h0&d+L<)rl0I7<7tQ(W*{&FnV#2l7K@b1}q0j*il2oc=`MO75Teg17 zj^RR{G_K{=S%1FyZ!>Du%GBBa?CaO-p1JM#31f5008NrO2USu8aBd0NynWAg3p-YC z`u>-&+wWVCSu*$P!1t=Y*E;d2VwMCz;(r`egQ`Gs6oe}`Zn=Ek3ynDWVPzLzr)*bEh7mvs~fO^zyU$AJ^#;rLO69uI~<=;U9JNMPw z7c3qKY|xvO$&S_B0ucf*I$oLpK_c7IgVp!txC4mzdNsc9vynYD{{7Xs!Kn%Sc|S@&^Ez zHRFuo$`bhAy;sgG_1(JVA!-T$MM~R4*6ZQy`+Q7`#w>0X%yH)6-WGBMeoEpZ2$Y9; zKo=dn(?%SAVP!D1(m~!(gNZsAM;5-2a2$tXfe8Sgq_tKlRn+OQa>(yIq<@q=1S^)L zB59H&zp@PGkcZ}iGif$#>?QADNRudlNRou4Qc5)%jq*Y?*s=K`f#8Y-i@w{w8$iDf zM^^&?S!N+1d60R!RuT}b*Xv3t8e_E9naw5~J)vwKDThKJz-ODcJ^jwdtrN$^CVhC$ zWo4yVDhl$F!%c(i-o3~3yk?e`7FuhQBpDbOFvhgBwA5;&Jin5kDC+B$Y4O6re?kOw zmrawUaTIB-E0xNaF=K)tplg^UNy0FUq9{ocYwclQt(8(i5Y%e5(W6HPK|u0<;#`4~ TzT6Jg00000NkvXXu0mjf{IBn9 diff --git a/telldus-gui/Plugins/Sensors/icon_temp.png b/telldus-gui/Plugins/Sensors/icon_temp.png index 67a720dbebd64cab28dee2ea3589caf58d70375b..876e238049d75565533c0afbc8b7dd9508c5efd0 100644 GIT binary patch delta 1322 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 M07*qoM6N<$g83-+%>V!Z delta 430 zcmV;f0a5;|49EkJB!2;OQb$4nuFf3k00006VoOIv0Qdm+0QiFHznB03010qNS#tmY z3ljhU3ljkVnw%H_000McNliru-3bc{Bp`ou1epK;0Z2(iK~z}7?bSa^+ffw8@lP5l zRM4qdi~okWbm-DT$r}))pdh{m7g6Za;tLQ|kgj%i>Qp+GQh#XaY!P+xPZUbsDn>{| zl%UHA{0Mf-O(^^xIKw^5{c_K_&r>K&ywOcP&}HQSIY7@p`pX#4oY%0O0-#tZmGA2x zU>dWi;2FvoLp3Vt2>zfJ7aigl4NT$}z6DUS5j1s%w=KP1EaE#pVHJC+0PfRe?8FzW zU^nUqj&Oy67=PWz6aY=_;5AB^!7IGPH6G(@YJjFHSa0bq1w?K{Il%v$1x-D~6rSQ7 zTR7DU)G{30@9BVK3-g^X4Aw+o<#znSw5eqs*K z1L9p+a3gHEj(Pk}l?B_S9q5Ga Y0PLberPZ3jEdT%j07*qoM6N<$f|J;_X8-^I From 22fbc6b9df9e7fe4c5a464ef653d0aa8b55ee185 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Nov 2013 09:39:07 +0100 Subject: [PATCH 2194/2215] Bumped version to 2.1.2 Beta9 --- telldus-core/CMakeLists.txt | 2 +- telldus-gui/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 0a94a00a..e146c507 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -13,7 +13,7 @@ SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "beta8") +SET(PACKAGE_SUBVERSION "beta9") SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index 8ed6fdb5..386b7cb6 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -11,7 +11,7 @@ SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta8") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta9") SET(BRANDING "telldus" CACHE STRING "The brand to use") From bd8388364d848eaf1554048d833582bd9c041313 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 21 Nov 2013 10:22:39 +0100 Subject: [PATCH 2195/2215] Added missing translation --- telldus-gui/Plugins/Sensors/translation_sv.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-gui/Plugins/Sensors/translation_sv.ts b/telldus-gui/Plugins/Sensors/translation_sv.ts index f2a21a81..5c9ea45d 100644 --- a/telldus-gui/Plugins/Sensors/translation_sv.ts +++ b/telldus-gui/Plugins/Sensors/translation_sv.ts @@ -26,6 +26,10 @@ Visible in list Visas i lista + + Send to Telldus Live! + Visa i Telldus Live! + Sensor information Sensorinformation From 813c9696fcc02711e5a86f80ada95b79da1394b3 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 22 Nov 2013 11:07:05 +0100 Subject: [PATCH 2196/2215] Only show "Send to live" when live is activated --- telldus-gui/Plugins/Live/__init__.js | 3 +++ telldus-gui/Plugins/Sensors/SensorList.qml | 8 +++++--- telldus-gui/Plugins/Sensors/SensorView.qml | 4 ++-- telldus-gui/Plugins/Sensors/__init__.js | 16 ++++++++++++---- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index 0ebaec0c..f65e4ebf 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -97,6 +97,9 @@ com.telldus.live = function() { function registrationLinkVisible(visibleParam){ configUI.findChild('registrationLink').visible = visibleParam; + if (com.telldus.sensors) { + com.telldus.sensors.showLiveOptions(!visibleParam); + } } function sendDevicesReport() { diff --git a/telldus-gui/Plugins/Sensors/SensorList.qml b/telldus-gui/Plugins/Sensors/SensorList.qml index c6317e6c..32979119 100644 --- a/telldus-gui/Plugins/Sensors/SensorList.qml +++ b/telldus-gui/Plugins/Sensors/SensorList.qml @@ -51,8 +51,8 @@ Column { text: qsTr("Send to Telldus Live!") anchors.right: sensorinformationTitle.left horizontalAlignment: Text.AlignHCenter - visible: main.state == "EDIT" - width: 150 + visible: main.state == "EDIT" && showLiveOptions + width: showLiveOptions ? 150 : 0 } HeaderTitle { id: sensorinformationTitle @@ -70,7 +70,9 @@ Column { } Repeater { model: sensorModel - delegate: SensorView{ state: main.state == "EDIT" ? 'EDIT' : ''} + delegate: SensorView { + state: main.state == "EDIT" ? 'EDIT' : '' + } } Row{ spacing: 20 diff --git a/telldus-gui/Plugins/Sensors/SensorView.qml b/telldus-gui/Plugins/Sensors/SensorView.qml index 407040d2..85f8c3a9 100644 --- a/telldus-gui/Plugins/Sensors/SensorView.qml +++ b/telldus-gui/Plugins/Sensors/SensorView.qml @@ -96,13 +96,13 @@ Item{ Item { id: sendtolivecheckbox height: 40 - width: 150 + width: showLiveOptions ? 150 : 0 anchors.right: sensorInfo.left CheckBox { id: checkBoxSTL anchors.centerIn: parent width: checkBoxSTL.height - visible: sensorViewItem.state == "EDIT" + visible: sensorViewItem.state == "EDIT" && showLiveOptions checked: modelData.sendToLive onClicked: modelData.setSendToLive(!modelData.sendToLive) } diff --git a/telldus-gui/Plugins/Sensors/__init__.js b/telldus-gui/Plugins/Sensors/__init__.js index 4270068e..5fa90e20 100644 --- a/telldus-gui/Plugins/Sensors/__init__.js +++ b/telldus-gui/Plugins/Sensors/__init__.js @@ -7,6 +7,7 @@ __postInit__ = function() { com.telldus.sensors = function() { var sensorList; + var view; function init() { var sensorData = 0; sensorList = loadSensorModel(); @@ -51,6 +52,7 @@ com.telldus.sensors = function() { } } view.setProperty('initialViewMode', initialViewMode); + view.setProperty('showLiveOptions', (!com.telldus.live || !com.telldus.live.isRegisteredToLive())); saveSensorModel(); view.load("main.qml"); application.addWidget("sensors.gui", "icon.png", view); @@ -224,9 +226,14 @@ com.telldus.sensors = function() { settings.setValue("sensors", sensorProperties); } + function showLiveOptions(status){ + if(view){ + view.setProperty('showLiveOptions', status); + } + } + function sendSensorReport(){ - //TODO Only show "sendToLive" if Telldus Live! is activated - if(!com.telldus.live.isRegisteredToLive()){ + if(!com.telldus.live || !com.telldus.live.isRegisteredToLive()){ return; } @@ -268,7 +275,7 @@ com.telldus.sensors = function() { } sensor.setValue(dataType, value, timestamp); - if (sensor.sendToLive){ + if (com.telldus.live && com.telldus.live.isRegisteredToLive() && sensor.sendToLive){ sensorValues = pickSensorValues(sensor) if (allValuesUpdated(sensorValues)) { com.telldus.live.sendSensorValues(sensor, sensorValues); @@ -281,7 +288,8 @@ com.telldus.sensors = function() { } return { //Public functions - init:init + init:init, + showLiveOptions: showLiveOptions } }(); From 46e3d8f61f801adde20b61ca46dd71392b4d7c74 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 22 Nov 2013 12:06:56 +0100 Subject: [PATCH 2197/2215] Bumped version to 2.1.2 Beta10 --- telldus-core/CMakeLists.txt | 2 +- telldus-gui/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index e146c507..5e450257 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -13,7 +13,7 @@ SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "beta9") +SET(PACKAGE_SUBVERSION "beta10") SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index 386b7cb6..4d1f9be5 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -11,7 +11,7 @@ SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta9") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta10") SET(BRANDING "telldus" CACHE STRING "The brand to use") From 0f7937711fefbbdfd5d1394c598c2ea092c248d2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 8 Jan 2014 12:01:37 +0100 Subject: [PATCH 2198/2215] Fixes for callback hangings in Linux --- telldus-core/common/EventHandler.h | 4 +++- telldus-core/common/EventHandler_unix.cpp | 27 +++++++++++++++++++---- telldus-core/common/Thread.cpp | 4 +++- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/telldus-core/common/EventHandler.h b/telldus-core/common/EventHandler.h index 99be16c7..abca38c0 100644 --- a/telldus-core/common/EventHandler.h +++ b/telldus-core/common/EventHandler.h @@ -27,7 +27,9 @@ namespace TelldusCore { class PrivateData; PrivateData *d; bool listIsSignalled(); - +#ifndef _WINDOWS + bool isSignalled(); +#endif friend class Event; }; } diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index 5aa80e29..a5be1b17 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -4,8 +4,10 @@ // Copyright: See COPYING file that comes with this distribution // // +#include #include #include +#include #include #include "common/EventHandler.h" #include "common/Event.h" @@ -20,6 +22,7 @@ public: pthread_mutex_t mutex; std::list eventList; TelldusCore::Mutex listMutex; + bool isSignalled; }; EventHandler::EventHandler() { @@ -27,6 +30,7 @@ EventHandler::EventHandler() { pthread_cond_init(&d->event, NULL); pthread_cond_init(&d->event, NULL); pthread_mutex_init(&d->mutex, NULL); + d->isSignalled = false; } EventHandler::~EventHandler(void) { @@ -49,6 +53,10 @@ EventRef EventHandler::addEvent() { return event; } +bool EventHandler::isSignalled() { + return d->isSignalled; +} + bool EventHandler::listIsSignalled() { TelldusCore::MutexLocker locker(&d->listMutex); @@ -63,6 +71,7 @@ bool EventHandler::listIsSignalled() { void EventHandler::signal(Event *event) { pthread_mutex_lock(&d->mutex); + d->isSignalled = true; // event->setSignaled(); pthread_cond_signal(&d->event); pthread_mutex_unlock(&d->mutex); @@ -70,12 +79,22 @@ void EventHandler::signal(Event *event) { bool EventHandler::waitForAny() { pthread_mutex_lock(&d->mutex); - while(!listIsSignalled()) { - pthread_cond_wait(&d->event, &d->mutex); + int ret; + while(!isSignalled()) { + timeval now; + gettimeofday(&now, NULL); + long int abstime_ns_large = now.tv_usec*1000 + 60000000000; //add 60 seconds wait (5 seconds before)? + timespec abstime = { now.tv_sec + (abstime_ns_large / 1000000000), abstime_ns_large % 1000000000 }; + ret = pthread_cond_timedwait(&d->event, &d->mutex, &abstime); + if (ret == ETIMEDOUT){ + continue; + } + } + if(!listIsSignalled()){ + d->isSignalled = false; } pthread_mutex_unlock(&d->mutex); - - return true; + return listIsSignalled(); } } // namespace TelldusCore diff --git a/telldus-core/common/Thread.cpp b/telldus-core/common/Thread.cpp index f428dfcd..dd5f4b17 100644 --- a/telldus-core/common/Thread.cpp +++ b/telldus-core/common/Thread.cpp @@ -55,7 +55,9 @@ void Thread::startAndLock(Mutex *lock) { d->threadStarted = handler.addEvent(); d->mutex = lock; this->start(); - handler.waitForAny(); + while (!handler.waitForAny()) { + continue; + } d->threadStarted.reset(); } From 89b4253d54086cdfa7699a1b2ee1de20f5ab2440 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 8 Jan 2014 12:23:30 +0100 Subject: [PATCH 2199/2215] Code cleanup for callback hangings in Linux --- telldus-core/common/EventHandler.h | 8 +++++--- telldus-core/common/EventHandler_unix.cpp | 12 ++++-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/telldus-core/common/EventHandler.h b/telldus-core/common/EventHandler.h index abca38c0..620d370e 100644 --- a/telldus-core/common/EventHandler.h +++ b/telldus-core/common/EventHandler.h @@ -7,6 +7,11 @@ #ifndef TELLDUS_CORE_COMMON_EVENTHANDLER_H_ #define TELLDUS_CORE_COMMON_EVENTHANDLER_H_ +#ifdef _MSC_VER +typedef unsigned __int64 uint64_t; +#else +#include +#endif #include "common/Event.h" namespace TelldusCore { @@ -27,9 +32,6 @@ namespace TelldusCore { class PrivateData; PrivateData *d; bool listIsSignalled(); -#ifndef _WINDOWS - bool isSignalled(); -#endif friend class Event; }; } diff --git a/telldus-core/common/EventHandler_unix.cpp b/telldus-core/common/EventHandler_unix.cpp index a5be1b17..6c65339c 100644 --- a/telldus-core/common/EventHandler_unix.cpp +++ b/telldus-core/common/EventHandler_unix.cpp @@ -53,10 +53,6 @@ EventRef EventHandler::addEvent() { return event; } -bool EventHandler::isSignalled() { - return d->isSignalled; -} - bool EventHandler::listIsSignalled() { TelldusCore::MutexLocker locker(&d->listMutex); @@ -80,17 +76,17 @@ void EventHandler::signal(Event *event) { bool EventHandler::waitForAny() { pthread_mutex_lock(&d->mutex); int ret; - while(!isSignalled()) { + while (!d->isSignalled) { timeval now; gettimeofday(&now, NULL); - long int abstime_ns_large = now.tv_usec*1000 + 60000000000; //add 60 seconds wait (5 seconds before)? + uint64_t abstime_ns_large = now.tv_usec*1000 + 60000000000; // add 60 seconds wait (5 seconds before)? timespec abstime = { now.tv_sec + (abstime_ns_large / 1000000000), abstime_ns_large % 1000000000 }; ret = pthread_cond_timedwait(&d->event, &d->mutex, &abstime); - if (ret == ETIMEDOUT){ + if (ret == ETIMEDOUT) { continue; } } - if(!listIsSignalled()){ + if (!listIsSignalled()) { d->isSignalled = false; } pthread_mutex_unlock(&d->mutex); From fbaa8ccbbd31a3fa1ae262d608e6e310851a4882 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 12:26:37 +0100 Subject: [PATCH 2200/2215] Add convenience function to supply a EventDataRef to Event::signal() --- telldus-core/common/Event.cpp | 6 +++++- telldus-core/common/Event.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/telldus-core/common/Event.cpp b/telldus-core/common/Event.cpp index 40dbea8d..7cb30558 100644 --- a/telldus-core/common/Event.cpp +++ b/telldus-core/common/Event.cpp @@ -61,9 +61,13 @@ void EventBase::signal() { } void EventBase::signal(EventData *eventData) { + this->signal(EventDataRef(eventData)); +} + +void EventBase::signal(EventDataRef eventData) { { TelldusCore::MutexLocker locker(&d->mutex); - d->eventDataList.push_back(EventDataRef(eventData)); + d->eventDataList.push_back(eventData); } sendSignal(); } diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index 6d662d89..2482b99d 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -42,6 +42,7 @@ namespace TelldusCore { bool isSignaled(); void signal(); virtual void signal(EventData *eventData); + void signal(EventDataRef eventData); EventDataRef takeSignal(); protected: From f7336b34f91142026ecf8a4f647effe8595ae6b0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 11:45:19 +0100 Subject: [PATCH 2201/2215] Rewrite our callback dispatcher. Instead of dynamically create new threads for each callback they are now precreated when they are registered. Each callback will now be called using the same thread each time. --- telldus-core/client/CallbackDispatcher.cpp | 158 +++++++++++++----- telldus-core/client/CallbackDispatcher.h | 60 +++++-- .../client/CallbackMainDispatcher.cpp | 108 ++++-------- telldus-core/client/CallbackMainDispatcher.h | 10 +- telldus-core/client/Client.cpp | 11 +- 5 files changed, 197 insertions(+), 150 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 2cae6ebb..d27ac5cd 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -8,64 +8,136 @@ */ #include "client/CallbackDispatcher.h" +#include "common/Event.h" +#include "common/EventHandler.h" namespace TelldusCore { -TDEventDispatcher::TDEventDispatcher(EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) - :Thread(), doneRunning(false), callbackData(cbd), callback(cb), callbackExecuted(cbDone) { - this->startAndLock(&callback->mutex); +class TDEventDispatcher::PrivateData { +public: + EventHandler eventHandler; + EventRef stopEvent, callbackEvent; + int id; + void *func, *context; +}; + +TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) //EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) + :Thread() { + d = new PrivateData; + d->stopEvent = d->eventHandler.addEvent(); + d->callbackEvent = d->eventHandler.addEvent(); + d->id = id; + d->func = func; + d->context = context; + this->start(); } TDEventDispatcher::~TDEventDispatcher() { + printf("Stopping dispatcher\n"); + d->stopEvent->signal(); this->wait(); + delete d; } -bool TDEventDispatcher::done() const { - return doneRunning; +int TDEventDispatcher::id() const { + return d->id; +} + +void TDEventDispatcher::queue(EventDataRef eventData) { + d->callbackEvent->signal(eventData); } void TDEventDispatcher::run() { - this->fireEvent(); - doneRunning = true; - callbackExecuted->signal(); -} - -void TDEventDispatcher::fireEvent() { - if (callback->type == CallbackStruct::DeviceEvent) { - DeviceEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; + while (true) { + d->eventHandler.waitForAny(); + if (d->stopEvent->isSignaled()) { + break; } - ((TDDeviceEvent)callback->event)(data->deviceId, data->deviceState, data->deviceStateValue.c_str(), callback->id, callback->context); - - } else if (callback->type == CallbackStruct::DeviceChangeEvent) { - DeviceChangeEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; + if (d->callbackEvent->isSignaled()) { + TelldusCore::EventDataRef eventData = d->callbackEvent->takeSignal(); + this->execute(eventData); } - ((TDDeviceChangeEvent)callback->event)(data->deviceId, data->changeEvent, data->changeType, callback->id, callback->context); - - } else if (callback->type == CallbackStruct::RawDeviceEvent) { - RawDeviceEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; - } - ((TDRawDeviceEvent)callback->event)(data->data.c_str(), data->controllerId, callback->id, callback->context); - - } else if (callback->type == CallbackStruct::SensorEvent) { - SensorEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; - } - ((TDSensorEvent)callback->event)(data->protocol.c_str(), data->model.c_str(), data->id, data->dataType, data->value.c_str(), data->timestamp, callback->id, callback->context); - - } else if (callback->type == CallbackStruct::ControllerEvent) { - ControllerEventCallbackData *data = dynamic_cast(callbackData.get()); - if (!data) { - return; - } - ((TDControllerEvent)callback->event)(data->controllerId, data->changeEvent, data->changeType, data->newValue.c_str(), callback->id, callback->context); } } +TDDeviceEventDispatcher::TDDeviceEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDDeviceEventDispatcher::execute(EventDataRef eventData) { + DeviceEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDDeviceEvent)d->func)(data->deviceId, data->deviceState, data->deviceStateValue.c_str(), d->id, d->context); +} + +CallbackStruct::CallbackType TDDeviceEventDispatcher::type() { + return CallbackStruct::DeviceEvent; +} + +TDDeviceChangeEventDispatcher::TDDeviceChangeEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDDeviceChangeEventDispatcher::execute(EventDataRef eventData) { + DeviceChangeEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDDeviceChangeEvent)d->func)(data->deviceId, data->changeEvent, data->changeType, d->id, d->context); +} + +CallbackStruct::CallbackType TDDeviceChangeEventDispatcher::type() { + return CallbackStruct::DeviceChangeEvent; +} + +TDRawDeviceEventDispatcher::TDRawDeviceEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDRawDeviceEventDispatcher::execute(EventDataRef eventData) { + RawDeviceEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDRawDeviceEvent)d->func)(data->data.c_str(), data->controllerId, d->id, d->context); +} + +CallbackStruct::CallbackType TDRawDeviceEventDispatcher::type() { + return CallbackStruct::RawDeviceEvent; +} + +TDSensorEventDispatcher::TDSensorEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDSensorEventDispatcher::execute(EventDataRef eventData) { + SensorEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDSensorEvent)d->func)(data->protocol.c_str(), data->model.c_str(), data->id, data->dataType, data->value.c_str(), data->timestamp, d->id, d->context); +} + +CallbackStruct::CallbackType TDSensorEventDispatcher::type() { + return CallbackStruct::SensorEvent; +} + +TDControllerEventDispatcher::TDControllerEventDispatcher(int id, void *func, void *context) + :TDEventDispatcher(id, func, context) +{} + +void TDControllerEventDispatcher::execute(EventDataRef eventData) { + ControllerEventCallbackData *data = dynamic_cast(eventData.get()); + if (!data) { + return; + } + ((TDControllerEvent)d->func)(data->controllerId, data->changeEvent, data->changeType, data->newValue.c_str(), d->id, d->context); +} + +CallbackStruct::CallbackType TDControllerEventDispatcher::type() { + return CallbackStruct::ControllerEvent; +} + } // namespace TelldusCore diff --git a/telldus-core/client/CallbackDispatcher.h b/telldus-core/client/CallbackDispatcher.h index ee2b11f0..4b387906 100644 --- a/telldus-core/client/CallbackDispatcher.h +++ b/telldus-core/client/CallbackDispatcher.h @@ -19,12 +19,6 @@ namespace TelldusCore { - /*template struct CallbackStruct { - T event; - int id; - void *context; - TelldusCore::Mutex mutex; - };*/ struct CallbackStruct { enum CallbackType { DeviceEvent, DeviceChangeEvent, RawDeviceEvent, SensorEvent, ControllerEvent }; CallbackType type; @@ -33,9 +27,6 @@ namespace TelldusCore { void *context; TelldusCore::Mutex mutex; }; - /*typedef CallbackStruct DeviceChangeEvent; - typedef CallbackStruct RawDeviceEvent; - typedef CallbackStruct SensorEvent;*/ class CallbackData: public EventDataBase { public: @@ -86,17 +77,52 @@ namespace TelldusCore { class TDEventDispatcher : public Thread { public: - TDEventDispatcher(EventDataRef callbackData, CallbackStruct *callback, TelldusCore::EventRef cbDone); + TDEventDispatcher(int id, void *func, void *context); virtual ~TDEventDispatcher(); - bool done() const; + int id() const; + void queue(EventDataRef eventData); + virtual CallbackStruct::CallbackType type() = 0; protected: + class PrivateData; + PrivateData *d; + virtual void run(); - bool doneRunning; - private: - void fireEvent(); - EventDataRef callbackData; - CallbackStruct *callback; - EventRef callbackExecuted; + virtual void execute(EventDataRef eventData) = 0; + }; + class TDDeviceEventDispatcher : public TDEventDispatcher { + public: + TDDeviceEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDDeviceChangeEventDispatcher : public TDEventDispatcher { + public: + TDDeviceChangeEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDRawDeviceEventDispatcher : public TDEventDispatcher { + public: + TDRawDeviceEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDSensorEventDispatcher : public TDEventDispatcher { + public: + TDSensorEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); + }; + class TDControllerEventDispatcher : public TDEventDispatcher { + public: + TDControllerEventDispatcher(int id, void *func, void *context); + virtual CallbackStruct::CallbackType type(); + protected: + virtual void execute(EventDataRef eventData); }; } diff --git a/telldus-core/client/CallbackMainDispatcher.cpp b/telldus-core/client/CallbackMainDispatcher.cpp index 585c65b0..5b495449 100644 --- a/telldus-core/client/CallbackMainDispatcher.cpp +++ b/telldus-core/client/CallbackMainDispatcher.cpp @@ -13,52 +13,60 @@ namespace TelldusCore { -typedef std::list CallbackList; +typedef std::list CallbackList; class CallbackMainDispatcher::PrivateData { public: - EventHandler eventHandler; - EventRef stopEvent, generalCallbackEvent, janitor; - Mutex mutex; - std::list > eventThreadList; - CallbackList callbackList; - int lastCallbackId; }; -CallbackMainDispatcher::CallbackMainDispatcher() -:Thread() { +CallbackMainDispatcher::CallbackMainDispatcher() { d = new PrivateData; - d->stopEvent = d->eventHandler.addEvent(); - d->generalCallbackEvent = d->eventHandler.addEvent(); - d->janitor = d->eventHandler.addEvent(); // Used for cleanups - d->lastCallbackId = 0; } CallbackMainDispatcher::~CallbackMainDispatcher(void) { - d->stopEvent->signal(); - wait(); { - MutexLocker locker(&d->mutex); + TelldusCore::MutexLocker locker(&d->mutex); + for(CallbackList::iterator it = d->callbackList.begin(); it != d->callbackList.end(); ++it) { + delete (*it); + } } delete d; } -EventRef CallbackMainDispatcher::retrieveCallbackEvent() { - return d->generalCallbackEvent; +void CallbackMainDispatcher::execute(CallbackStruct::CallbackType type, EventData *eventData) { + { + TelldusCore::MutexLocker locker(&d->mutex); + EventDataRef eventDataRef(eventData); + for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { + if ( (*callback_it)->type() != type ) { + continue; + } + (*callback_it)->queue(eventDataRef); + } + } } int CallbackMainDispatcher::registerCallback(CallbackStruct::CallbackType type, void *eventFunction, void *context) { TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; - CallbackStruct *callback = new CallbackStruct; - callback->type = type; - callback->event = eventFunction; - callback->id = id; - callback->context = context; + TelldusCore::TDEventDispatcher *callback; + if (type == CallbackStruct::DeviceEvent) { + callback = new TelldusCore::TDDeviceEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::DeviceChangeEvent) { + callback = new TelldusCore::TDDeviceChangeEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::RawDeviceEvent) { + callback = new TelldusCore::TDRawDeviceEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::SensorEvent) { + callback = new TelldusCore::TDSensorEventDispatcher(id, eventFunction, context); + } else if (type == CallbackStruct::ControllerEvent) { + callback = new TelldusCore::TDControllerEventDispatcher(id, eventFunction, context); + } else { + return -1; + } d->callbackList.push_back(callback); return id; } @@ -68,7 +76,7 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { { TelldusCore::MutexLocker locker(&d->mutex); for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { - if ( (*callback_it)->id != callbackId ) { + if ( (*callback_it)->id() != callbackId ) { continue; } newEventList.splice(newEventList.begin(), d->callbackList, callback_it); @@ -77,9 +85,6 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { } if (newEventList.size()) { CallbackList::iterator it = newEventList.begin(); - { // Lock and unlock to make sure no one else uses the object - TelldusCore::MutexLocker locker( &(*it)->mutex ); - } delete (*it); newEventList.erase(it); return TELLSTICK_SUCCESS; @@ -87,53 +92,4 @@ int CallbackMainDispatcher::unregisterCallback(int callbackId) { return TELLSTICK_ERROR_NOT_FOUND; } -void CallbackMainDispatcher::run() { - while(!d->stopEvent->isSignaled()) { - if (!d->eventHandler.waitForAny()) { - continue; - } - - if(d->generalCallbackEvent->isSignaled()) { - EventDataRef eventData = d->generalCallbackEvent->takeSignal(); - - CallbackData *cbd = dynamic_cast(eventData.get()); - if (!cbd) { - continue; - } - TelldusCore::MutexLocker locker(&d->mutex); - for(CallbackList::iterator callback_it = d->callbackList.begin(); callback_it != d->callbackList.end(); ++callback_it) { - if ( (*callback_it)->type == cbd->type ) { - std::tr1::shared_ptr ptr(new TelldusCore::TDEventDispatcher(eventData, *callback_it, d->janitor)); - d->eventThreadList.push_back(ptr); - } - } - } - if (d->janitor->isSignaled()) { - // Clear all of them if there is more than one - while(d->janitor->isSignaled()) { - d->janitor->popSignal(); - } - this->cleanupCallbacks(); - } - } -} - -void CallbackMainDispatcher::cleanupCallbacks() { - bool again = false; - - // Device Event - do { - again = false; - MutexLocker locker(&d->mutex); - std::list >::iterator it = d->eventThreadList.begin(); - for (; it != d->eventThreadList.end(); ++it) { - if ((*it)->done()) { - d->eventThreadList.erase(it); - again = true; - break; - } - } - } while (again); -} - } // namespace TelldusCore diff --git a/telldus-core/client/CallbackMainDispatcher.h b/telldus-core/client/CallbackMainDispatcher.h index 764780e3..911d21a4 100644 --- a/telldus-core/client/CallbackMainDispatcher.h +++ b/telldus-core/client/CallbackMainDispatcher.h @@ -12,29 +12,23 @@ #include "client/CallbackDispatcher.h" #include "common/Thread.h" -#include "common/Event.h" -#include "common/EventHandler.h" namespace TelldusCore { - class CallbackMainDispatcher : public Thread + class CallbackMainDispatcher { public: CallbackMainDispatcher(void); ~CallbackMainDispatcher(void); - EventRef retrieveCallbackEvent(); + void execute(TelldusCore::CallbackStruct::CallbackType type, EventData *eventData); int registerCallback( TelldusCore::CallbackStruct::CallbackType type, void *eventFunction, void *context ); int unregisterCallback( int callbackId ); - protected: - void run(); - private: class PrivateData; PrivateData *d; - void cleanupCallbacks(void); }; } diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index cf4e5e33..3cd095ce 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -33,7 +33,6 @@ Client::Client() d->running = true; d->sensorCached = false; d->controllerCached = false; - d->callbackMainDispatcher.start(); start(); } @@ -105,20 +104,20 @@ void Client::run() { data->deviceId = Message::takeInt(&clientMessage); data->changeEvent = Message::takeInt(&clientMessage); data->changeType = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::DeviceChangeEvent, data); } else if(type == L"TDDeviceEvent") { DeviceEventCallbackData *data = new DeviceEventCallbackData(); data->deviceId = Message::takeInt(&clientMessage); data->deviceState = Message::takeInt(&clientMessage); data->deviceStateValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::DeviceEvent, data); } else if(type == L"TDRawDeviceEvent") { RawDeviceEventCallbackData *data = new RawDeviceEventCallbackData(); data->data = TelldusCore::wideToString(Message::takeString(&clientMessage)); data->controllerId = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::RawDeviceEvent, data); } else if(type == L"TDSensorEvent") { SensorEventCallbackData *data = new SensorEventCallbackData(); @@ -128,7 +127,7 @@ void Client::run() { data->dataType = Message::takeInt(&clientMessage); data->value = TelldusCore::wideToString(Message::takeString(&clientMessage)); data->timestamp = Message::takeInt(&clientMessage); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::SensorEvent, data); } else if(type == L"TDControllerEvent") { ControllerEventCallbackData *data = new ControllerEventCallbackData(); @@ -136,7 +135,7 @@ void Client::run() { data->changeEvent = Message::takeInt(&clientMessage); data->changeType = Message::takeInt(&clientMessage); data->newValue = TelldusCore::wideToString(Message::takeString(&clientMessage)); - d->callbackMainDispatcher.retrieveCallbackEvent()->signal(data); + d->callbackMainDispatcher.execute(CallbackStruct::ControllerEvent, data); } else { clientMessage = L""; // cleanup, if message contained garbage/unhandled data From 25542e7f90b3bcf4d3ae2be0b1d7795bc63fa3c8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 14:09:15 +0100 Subject: [PATCH 2202/2215] Remove old code --- telldus-core/client/CallbackDispatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index d27ac5cd..ae9e1722 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -21,7 +21,7 @@ public: void *func, *context; }; -TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) //EventDataRef cbd, CallbackStruct *cb, EventRef cbDone) +TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) :Thread() { d = new PrivateData; d->stopEvent = d->eventHandler.addEvent(); From 4d366f483eccc817378be5cd95926ef49b4c5151 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 14:12:29 +0100 Subject: [PATCH 2203/2215] Remove debug code --- telldus-core/client/CallbackDispatcher.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index ae9e1722..99c9a6a7 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -33,7 +33,6 @@ TDEventDispatcher::TDEventDispatcher(int id, void *func, void *context) } TDEventDispatcher::~TDEventDispatcher() { - printf("Stopping dispatcher\n"); d->stopEvent->signal(); this->wait(); delete d; From 6842c248185c840d7eab6bc1f37b12e1b66eb3d4 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 14:12:47 +0100 Subject: [PATCH 2204/2215] Made the loop a bit smaller --- telldus-core/client/CallbackDispatcher.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/telldus-core/client/CallbackDispatcher.cpp b/telldus-core/client/CallbackDispatcher.cpp index 99c9a6a7..a1f72263 100644 --- a/telldus-core/client/CallbackDispatcher.cpp +++ b/telldus-core/client/CallbackDispatcher.cpp @@ -47,11 +47,8 @@ void TDEventDispatcher::queue(EventDataRef eventData) { } void TDEventDispatcher::run() { - while (true) { + while (!d->stopEvent->isSignaled()) { d->eventHandler.waitForAny(); - if (d->stopEvent->isSignaled()) { - break; - } if (d->callbackEvent->isSignaled()) { TelldusCore::EventDataRef eventData = d->callbackEvent->takeSignal(); this->execute(eventData); From 4b181e30e32464f0f5757aee5644edabadb238fd Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 8 Jan 2014 14:59:17 +0100 Subject: [PATCH 2205/2215] Use signals to allow us to exit the application and do proper cleanup --- examples/cpp/callbacks/main.cpp | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/examples/cpp/callbacks/main.cpp b/examples/cpp/callbacks/main.cpp index f3e2d3b1..5afeeaaf 100644 --- a/examples/cpp/callbacks/main.cpp +++ b/examples/cpp/callbacks/main.cpp @@ -1,13 +1,16 @@ #include +#include #include #include +bool running; + class Events { public: Events(); ~Events(); void deviceEvent(int deviceId, int method, const char *data); - + static void deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *context); private: @@ -43,15 +46,30 @@ void Events::deviceEventCallback(int deviceId, int method, const char *data, int } } +void signalHandler(int sig) { + if (sig == SIGINT) { + printf("Shutting down\n"); + running = false; + } +} + +void run() { + Events ev; + + running = true; + + printf("Listening for events, press control-c to quit...\n"); + //Our own simple eventloop + while(running) { + sleep(1); + } +} + int main(void) { tdInit(); - Events ev; - - //Our own simple eventloop - while(1) { - sleep(100); - } + signal(SIGINT, signalHandler); + run(); tdClose(); From c9567f3698ec342c83cecc62183e4f78d5f71418 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 13 Jan 2014 14:39:15 +0100 Subject: [PATCH 2206/2215] Added support for Oregon Scientific C844 (pool thermometer) --- telldus-core/service/ProtocolOregon.cpp | 48 +++++++++++++++++++++++++ telldus-core/service/ProtocolOregon.h | 1 + 2 files changed, 49 insertions(+) diff --git a/telldus-core/service/ProtocolOregon.cpp b/telldus-core/service/ProtocolOregon.cpp index f1764846..3fcfe6dc 100644 --- a/telldus-core/service/ProtocolOregon.cpp +++ b/telldus-core/service/ProtocolOregon.cpp @@ -25,6 +25,9 @@ std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) { return decode1984(data, model); } else if (model.compare(L"0x2914") == 0) { return decode2914(data); + } else if (model.compare(L"0xC844") == 0 || model.compare(L"0xEC40") == 0) { + // C844 - pool thermometer + return decodeC844(data, model); } return ""; @@ -297,3 +300,48 @@ std::string ProtocolOregon::decodeF824(const std::string &data) { return retString.str(); } + +std::string ProtocolOregon::decodeC844(const std::string &data, const std::wstring &model) { + uint64_t value = TelldusCore::hexTo64l(data); + + uint8_t messageChecksum1 = value & 0xF; + value >>= 4; + uint8_t messageChecksum2 = value & 0xF; + value >>= 4; + uint8_t neg = value & 0xF; + value >>= 4; + uint8_t temp1 = value & 0xF; + value >>= 4; + uint8_t temp2 = value & 0xF; + value >>= 4; + uint8_t temp3 = value & 0xF; + value >>= 4; + uint8_t battery = value & 0xF; // PROBABLY battery + value >>= 4; + uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF); + uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF); + value >>= 8; + uint8_t channel = value & 0xF; + checksum += neg + temp1 + temp2 + temp3 + battery + channel; + + if (model.compare(L"0xC844") == 0) { + checksum += 0xC + 0x8 + 0x4 + 0x4; + } else { + checksum += 0xE + 0xC + 0x4 + 0x0; + } + + if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) { + // checksum error + return ""; + } + + double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0; + if (neg) { + temperature = -temperature; + } + + std::stringstream retString; + retString << "class:sensor;protocol:oregon;model:C844;id:" << static_cast(rollingcode) + << ";temp:" << std::fixed << std::setprecision(1) << temperature << ";"; + return retString.str(); +} diff --git a/telldus-core/service/ProtocolOregon.h b/telldus-core/service/ProtocolOregon.h index dbf4aaa5..cc68fe86 100644 --- a/telldus-core/service/ProtocolOregon.h +++ b/telldus-core/service/ProtocolOregon.h @@ -21,6 +21,7 @@ protected: static std::string decodeF824(const std::string &data); static std::string decode1984(const std::string &data, const std::wstring &model); static std::string decode2914(const std::string &data); + static std::string decodeC844(const std::string &data, const std::wstring &model); }; #endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_ From 94dfe84e1d7e9f3d26be5266975b7d212994884f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 4 Feb 2014 11:07:06 +0100 Subject: [PATCH 2207/2215] There is no need for Event::signal(EventData *) to be virtual. It is not subclassed anywhere --- telldus-core/common/Event.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-core/common/Event.h b/telldus-core/common/Event.h index 6d662d89..c0847eb4 100644 --- a/telldus-core/common/Event.h +++ b/telldus-core/common/Event.h @@ -41,7 +41,7 @@ namespace TelldusCore { void popSignal(); bool isSignaled(); void signal(); - virtual void signal(EventData *eventData); + void signal(EventData *eventData); EventDataRef takeSignal(); protected: From 5fa802ecf94e9dead1acf4fc7413b37395c9d179 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 4 Feb 2014 12:41:50 +0100 Subject: [PATCH 2208/2215] Updated included firmware to TellStick Duo v12 and TellStick Net v17. --- .../Controllers/firmware/TellStickDuo.hex | 1989 +-- .../Controllers/firmware/TellStickNet.hex | 10025 +++++++++------- 2 files changed, 6586 insertions(+), 5428 deletions(-) diff --git a/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex b/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex index 5d615751..c1f9e16e 100644 --- a/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex +++ b/telldus-gui/Plugins/Controllers/firmware/TellStickDuo.hex @@ -1,966 +1,1045 @@ :0400000014EF00F009 -:10000800FACFB6F4FBCFB7F4E9CFB8F4BCED19F0EA -:10001800D8CFA4F4E8CFA5F4E0CFA6F48CEF18F07D -:1000280004EE33F07C0EF66E000EF76E10EE27F03D -:1000380035EC00F000EE00F014EE33F02EEC00F09A +:10000800FACFCCF4FBCFCDF4E9CFCEF4DAED1BF088 +:10001800D8CFBAF4E8CFBBF4E0CFBCF4AAEF1AF01B +:1000280004EE48F07C0EF66E000EF76E10EE28F027 +:1000380035EC00F000EE00F014EE48F02EEC00F085 :1000480005EE00F011EE00F02EEC00F0000EF86E58 -:100058004CEF1CF0EE6AE550E150FCE1E250FAE1A9 +:10005800B2EF1EF0EE6AE550E150FCE1E250FAE141 :1000680012000900F5CFEEFFE550E150FAE1E25049 :10007800F8E1120074656D70657261747572656877 :10008800756D696469747900010000000001000061 -:100098000100FFFFF3FFFFFF80FFFF0085D1040190 -:1000A80004015F51D8B401D001D014D04C0E040122 -:1000B8000401606501D001D00DD0520E0401040185 -:1000C800606101D001D006D00401716F010E0F6E7E -:1000D800040171517DD1190E04010401606501D03C -:1000E80001D00ED01E0E04010401606101D001D0C0 -:1000F80007D00401716F030E0F6E0401715168D1AE -:10010800270E04010401606501D001D00ED02C0E29 -:1001180004010401606101D001D007D00401716FAE -:10012800040E0F6E0401715153D1FFEC1AF050D137 -:10013800180E04010401606501D001D0F6D71D0E28 -:1001480004010401606101D001D0EFD70401716F8F -:10015800050E0F6E040171513BD1030E0401040119 -:10016800606501D001D0E1D7090E04010401606186 -:1001780001D001D0DAD70401716F070E0F6E0401A8 -:10018800715126D10E6601D001D02DD0010E040187 -:100198000401606501D001D00ED0050E04010401F0 -:1001A800606101D001D007D00401716F010E0E6E9D -:1001B800040171510DD1040E04010401606501D0E0 -:1001C80001D00ED0080E04010401606101D001D0F5 -:1001D80007D00401716F020E0E6E04017151F8D040 -:1001E800FFEC1AF0F5D00E04D8A401D001D023D02A -:1001F800040E04010401606501D001D096D7080EF1 -:1002080004010401606101D001D08FD70401716F2E -:10021800000E0E6E04017151040104012D4B2E2BAA -:100228000401D890040147370401483704014937CD -:1002380004014A37CDD00E50020AD8A401D001D00B -:1002480027D0010E04010401606501D001D06DD7EB -:10025800050E04010401606101D001D066D70401D4 -:10026800716F000E0E6E04017151040104012D4BD3 -:100278002E2B04010401475109120401D8900401EE -:100288004737040148370401493704014A37A0D0E9 -:10029800FFEC1AF09DD00E6601D001D02DD0030ED0 -:1002A80004010401606501D001D00ED0090E0401DB -:1002B8000401606101D001D007D00401716F010E03 -:1002C8000E6E0401715184D0080E040104016065AA -:1002D80001D001D00ED0100E04010401606101D0DC -:1002E80001D007D00401716F020E0E6E0401715126 -:1002F8006FD0FFEC1AF06CD00E04D8A401D001D056 -:1003080023D0080E04010401606501D001D00DD787 -:10031800100E04010401606101D001D006D7040168 -:10032800716F000E0E6E04017151040104012D4B12 -:100338002E2B0401D89004014737040148370401E3 -:10034800493704014A3744D00E50020AD8A401D0D4 -:1003580001D027D0030E04010401606501D001D04B -:10036800E4D6090E04010401606101D001D0DDD694 -:100378000401716F000E0E6E040171510401040135 -:100388002D4B2E2B04010401475109120401D8906A -:1003980004014737040148370401493704014A3743 -:1003A80017D0FFEC1AF014D00F50000A01E177D6ED +:100098000100FFFFF3FFFFFF80FFFFFF85D1040191 +:1000A80004017551D8B401D001D014D04C0E04010C +:1000B8000401766501D001D00DD0520E040104016F +:1000C800766101D001D006D00401876F010E126E4F +:1000D800040187517DD1190E04010401766501D010 +:1000E80001D00ED01E0E04010401766101D001D0AA +:1000F80007D00401876F030E126E0401875168D17F +:10010800270E04010401766501D001D00ED02C0E13 +:1001180004010401766101D001D007D00401876F82 +:10012800040E126E0401875153D165EC1DF050D1B5 +:10013800180E04010401766501D001D0F6D71D0E12 +:1001480004010401766101D001D0EFD70401876F63 +:10015800050E126E040187513BD1030E0401040100 +:10016800766501D001D0E1D7090E0401040176615A +:1001780001D001D0DAD70401876F070E126E04018F +:10018800875126D1156601D001D02DD0010E04016A +:100198000401766501D001D00ED0050E04010401DA +:1001A800766101D001D007D00401876F010E156E6A +:1001B800040187510DD1040E04010401766501D0B4 +:1001C80001D00ED0080E04010401766101D001D0DF +:1001D80007D00401876F020E156E04018751F8D00D +:1001E80065EC1DF0F5D01504D8A401D001D023D0BA +:1001F800040E04010401766501D001D096D7080EDB +:1002080004010401766101D001D08FD70401876F02 +:10021800000E156E0401875104010401464B472B5B +:100228000401D89004015C3704015D3704015E378E +:1002380004015F37CDD01550020AD8A401D001D0EF +:1002480027D0010E04010401766501D001D06DD7D5 +:10025800050E04010401766101D001D066D70401BE +:10026800876F000E156E0401875104010401464B87 +:10027800472B040104015C5113120401D8900401B6 +:100288005C3704015D3704015E3704015F37A0D095 +:1002980065EC1DF09DD0156601D001D02DD0030E60 +:1002A80004010401766501D001D00ED0090E0401C5 +:1002B8000401766101D001D007D00401876F010ED7 +:1002C800156E0401875184D0080E04010401766577 +:1002D80001D001D00ED0100E04010401766101D0C6 +:1002E80001D007D00401876F020E156E04018751F3 +:1002F8006FD065EC1DF06CD01504D8A401D001D0E6 +:1003080023D0080E04010401766501D001D00DD771 +:10031800100E04010401766101D001D006D7040152 +:10032800876F000E156E0401875104010401464BC6 +:10033800472B0401D89004015C3704015D370401A0 +:100348005E3704015F3744D01550020AD8A401D0A3 +:1003580001D027D0030E04010401766501D001D035 +:10036800E4D6090E04010401766101D001D0DDD67E +:100378000401876F000E156E040187510401040102 +:10038800464B472B040104015C5113120401D89019 +:1003980004015C3704015D3704015E3704015F37EF +:1003A80017D065EC1DF014D01250000A01E177D681 :1003B800010A01E190D6020A01E1E4D6070A01E147 :1003C800B7D6010A01E1C9D6020A01E164D700D013 -:1003D800040104012D51080A2E11D8A401D001D01E -:1003E8004DD0032A050E036001D001D033D0095047 -:1003F8001324136E000E1420146E000E1520156EB3 -:10040800000E1620166E040E036001D001D010D025 -:1004180013C072F414C073F415C074F40401716B42 -:1004280071C413F072C414F073C415F074C416F0D8 -:1004380009501724176E000E1820186E000E192088 -:10044800196E000E1A201A6E0401716F000E096EE3 -:1004580004017151000E040104012D6F000E040106 -:100468002E6F010E04010401476F000E0401486F4E -:10047800000E0401496F000E04014A6F0F50030A71 -:10048800D8A401D001D04ED00350040AD8A401D07A -:1004980001D048D013C061F414C062F415C063F4ED -:1004A80016C064F4FFEC1AF051EC1DF0BB0E040109 -:1004B8000401806F790E0401816F7E0E040104012E -:1004C8007E6F790E04017F6F22EC1DF0330E04015C -:1004D8000401806F790E0401816FC70E04010401C5 -:1004E8007E6F790E04017F6F22EC1DF061C480F4E9 -:1004F80062C481F463C482F464C483F4DD0E04012D -:1005080004017E6F790E04017F6F79EC13F004010A -:10051800716F010E040104017E6F0401715143ECF7 -:100528001DF0A4D00F50070AD8A401D001D09DD047 -:100538000350050AD8A401D001D097D0095004016E -:100548000401656F0401666B0401676B0401686B45 -:1005580017C069F418C06AF419C06BF41AC06CF4B7 -:1005680013C06DF414C06EF415C06FF416C070F4A7 -:10057800FFEC1AF004010401655104010401692526 -:100588000401716F040104016651040104016A2128 -:100598000401726F040104016751040104016B2115 -:1005A8000401736F040104016851040104016C2102 -:1005B8000401746FFF0E040171150401756F000EBC -:1005C800040172150401766F000E0401731504010D -:1005D800776F000E040174150401786F0401750526 -:1005E800761177117811D8B401D001D001D03ED05E -:1005F80051EC1DF0BB0E04010401806F790E04015B -:10060800816F7E0E040104017E6F790E04017F6FF5 -:1006180022EC1DF0240E04010401806F790E040100 -:10062800816FC70E040104017E6F790E04017F6F8C -:1006380022EC1DF06DC480F46EC481F46FC482F4A2 -:1006480070C483F4DD0E040104017E6F790E040189 -:100658007F6F79EC13F00401716F010E040104013E -:100668007E6F0401715143EC1DF000D012000401AB -:100678008D0E04010401946F0401040E0401956FAA -:10068800DFD1040104019351250AD8B401D001D067 -:1006980005D093C49CF4AEEC1CF0D2D104019A6F3F -:1006A800000E04010401926F04019A5161D0DBD15C -:1006B8007ED004010401928F7AD0040194C4E9FF2A -:1006C800040195C4EAFF0401020E04019427000EF8 -:1006D800040195230401EECF96F40401EDCF97F4BD -:1006E8000401040197519611D8A401D001D007D074 -:1006F8009F0E04010401966F790E0401976F1BD0B9 -:10070800040104019651F66EE96E050EEA6E0401C5 -:1007180004019751EA6403D0EA6EEF5003D0F76EF4 -:100728000800F550040104019C6FAEEC1CF00401B4 -:100738000401964B972B040104019651F66EE96E5D -:10074800050EEA6E040104019751EA6403D0EA6ECB -:10075800EF5003D0F76E0800F5500009D8A401D077 -:1007680001D0CED76DD1C00E0401040192131FD061 -:1007780004018BC4F6FF04018CC4F7FF04010401D3 -:100788008B4B8C2B08000401F5CF93F40401935193 -:10079800000A8DE0580A8DE03C0A8AE00D0A88E0DC -:1007A8001A0A8BE0060ADFE00D0A83E0DBD70401B2 -:1007B80004019251C00BD8A401D001D025D0040166 -:1007C80094C4E9FF040195C4EAFF0401020E040180 -:1007D8009427000E040195230401EECF96F404013A -:1007E800EDCF97F40401040197AF01D001D00BD0ED -:1007F800030E04010401921304010401966D04011F -:10080800971FD8B0972B13D0040194C4E9FF0401B3 -:1008180095C4EAFF0401020E04019427000E0401A6 -:1008280095230401EECF96F40401EDCF97F478D028 -:1008380004019A6F010E04010401936F04019A5197 -:10084800040104019351050AD8A401D001D001D0B4 -:100858002AD0040104019351020DEA0EF324F66E26 -:10086800F76A780EF7220900F5CF9AF40900F5CF58 -:100878009BF404019A5104010401965D04019B5103 -:10088800040104019759D8B001D001D001D00BD090 -:1008980004010401932B040104019351050AD8A40F -:1008A80001D001D0D6D748D004019A6F010E0401B7 -:1008B8000401936F04019A51040104019351040A3D -:1008C800D8A401D001D001D0EED70401040193517E -:1008D800020DF40EF324F66EF76A780EF72209007B -:1008E800F5CF9AF40900F5CF9BF404019A5104015D -:1008F8000401965D04019B51040104019759D8B085 -:1009080001D001D001D0CFD704010401932B0401F9 -:1009180004019351040AD8A401D001D0D6D70CD031 -:10092800040104019251C00B000A82E0800ABCE075 -:10093800400A01E17DD700D0040104019251030B64 -:10094800D8B401D001D00AD004019A6F2D0E040149 -:1009580004019C6F04019A51AEEC1CF093C491F40D -:1009680066D056D0040104019151020DEA0EF32419 -:10097800F66EF76A780EF72209000401F5CF9EF4A7 -:100988000A000401F5CF9FF496C49CF497C49DF423 -:1009980026EC16F09CC49CF49DC49DF40A0E040138 -:1009A80004019E6F000E04019F6FDAEC18F0040139 -:1009B80004019C51300F04010401936F34D00401E9 -:1009C80004019151020DF40EF324F66EF76A780EC5 -:1009D800F72209000401F5CF9EF40A000401F5CFBF -:1009E8009FF496C49CF497C49DF426EC16F00F0E61 -:1009F800040104019C17130E040104019C25F66EE2 -:100A0800F76A790EF72208000401F5CF93F40BD0AA -:100A1800040104019251C00B000AA4E0800ACFE04F -:100A2800400AA0E000D093C49CF4AEEC1CF0040192 -:100A38000401910704019129D8A401D001D091D7CC -:100A480004018BC4F6FF04018CC4F7FF0401040100 -:100A58008B4B8C2B08000401F5CF93F404019367AA -:100A680001D001D00ED600D01200000E04010401FE -:100A7800666F000E0401676F000E0401686F000EB8 -:100A88000401696F0401610E04010401876F040108 -:100A9800040E0401886F04015F0E04010401856FD0 -:100AA8000401040E0401866FA5EC1BF00401610E1D -:100AB80004010401806F0401040E0401816F040124 -:100AC8005F0E040104017E6F0401040E04017F6FB0 -:100AD800C4EC15F0010E04010401626F000E04015C -:100AE800636F000E0401646F000E0401656F000E51 -:100AF800040104016A6F000E04016B6F0401040114 -:100B08006B51800A800F200ED8B46A5DD8A001D03E -:100B180001D001D070D00401610E04010401806F7E -:100B28000401040E0401816F04015F0E0401040135 -:100B38007E6F0401040E04017F6FC4EC15F00401FC -:100B480004016C6F0401610E04010401806F04014B -:100B5800040E0401816F04015F0E040104017E6F1D -:100B68000401040E04017F6FC4EC15F004010401B4 -:100B78006D6F1CD026D004010401625104010401E8 -:100B8800661304010401635104010401671304019D -:100B9800040164510401040168130401040165514E -:100BA8000401040169130DD0000E2CD16DC47FF42B -:100BB8006CC47EF429EC1CF0000ADCE0010ADBE0DE -:100BC800F3D70401D89004016237040163370401A4 -:100BD800643704016537040104016A4B6B2B040177 -:100BE80004016B51800A800F200ED8B46A5DD8A02A -:100BF80001D001D090D7040166C46EF4040167C423 -:100C08006FF4040168C470F4040169C471F4040148 -:100C18006E1F6F1F701F711F110E06D0D890040130 -:100C2800713370336F336E33E82EF8D7FF0E04013B -:100C38006E150401726F000E04016F150401736FC5 -:100C4800000E040170150401746F000E0401711583 -:100C58000401756F040166C476F4040167C477F46F -:100C6800040168C478F4040169C479F4190E06D043 -:100C7800D89004017933783377337633E82EF8D770 -:100C8800FF0E0401761504017A6F000E0401771532 -:100C980004017B6F000E0401781504017C6F000EBF -:100CA8000401791504017D6F0401755104017D1952 -:100CB8000EE10401745104017C1909E10401735126 -:100CC80004017B1904E10401725104017A19D8B4B2 -:100CD80001D001D002D0000E95D0FF0E040166C4E9 -:100CE8006EF4040167C46FF4040168C470F404016D -:100CF80069C471F404016E1F6F1F701F711F040116 -:100D08006E150401726F000E04016F150401736FF4 -:100D1800000E040170150401746F000E04017115B2 -:100D28000401756FFF0E040166C476F4040167C4FC -:100D380077F4040168C478F4040169C479F477C4C9 -:100D480076F478C477F479C478F40401796B0401F3 -:100D5800761504017A6F000E0401771504017B6F84 -:100D6800000E0401781504017C6F000E040179154A -:100D780004017D6F0401755104017D190EE1040120 -:100D8800745104017C1909E10401735104017B19B0 -:100D980004E10401725104017A19D8B401D001D0D8 -:100DA80002D0000E2FD051EC1DF0F00E040104010A -:100DB800806F790E0401816F7E0E040104017E6F3D -:100DC800790E04017F6F22EC1DF066C480F467C4BD -:100DD80081F468C482F469C483F4DD0E040104015B -:100DE8007E6F790E04017F6F79EC13F004016E6F4A -:100DF800020E040104017E6F04016E5143EC1DF0E4 -:100E0800010E00D01200000E040104016A6F000EEA -:100E180004016B6F000E04016C6F000E04016D6F0E -:100E2800010E04010401666F000E0401676F000ED5 -:100E38000401686F000E0401696F000E04010401CB -:100E4800626F000E0401636F000E04010401646FF9 -:100E5800000E0401656F0401610E04010401876F2F -:100E68000401040E0401886F04015F0E04010401EB -:100E7800856F0401040E0401866FA5EC1BF00401C4 -:100E8800610E04010401806F0401040E0401816FE6 -:100E980004015F0E040104017E6F0401040E0401C5 -:100EA8007F6FC4EC15F0040104016551800A800FBE -:100EB800240ED8B4645DD8A001D001D001D018D1D7 -:100EC8000401610E04010401806F0401040E040191 -:100ED800816F04015F0E040104017E6F0401040E9A -:100EE80004017F6FC4EC15F0040104016E6F040166 -:100EF800610E04010401806F0401040E0401816F76 -:100F080004015F0E040104017E6F0401040E040154 -:100F18007F6FC4EC15F0040104016F6F0401610ECA -:100F280004010401806F0401040E0401816F0401AF -:100F38005F0E040104017E6F0401040E04017F6F3B -:100F4800C4EC15F004010401706F0401610E040182 -:100F58000401806F0401040E0401816F04015F0E17 -:100F6800040104017E6F0401040E04017F6FC4ECC8 -:100F780015F004010401716F7CD00401040165516E -:100F8800800A800F200ED8B4645DD8A001D001D0AB -:100F98001AD004016AC472F404016BC473F4040126 -:100FA8006CC474F404016DC475F4D89004017533ED -:100FB80074337333723372C46AF473C46BF474C4D5 -:100FC8006CF475C46DF465D0040104016551800AA0 -:100FD800800F200ED8B4645DD8A001D001D01AD0FB -:100FE80004016AC472F404016BC473F404016CC490 -:100FF80074F404016DC475F4D89004017533743326 -:101008007333723372C46AF473C46BF474C46CF4CB -:1010180075C46DF4040104016651040104016A13E6 -:10102800040104016751040104016B130401040164 -:101038006851040104016C1304010401695104019D -:1010480004016D1326D0040104016551800A800F44 -:101058001F0ED8B4645DD8A001D001D008D0010E0D -:1010680004010401626F000E0401636F12D0000EC8 -:101078007ED071C479F470C478F46FC477F46EC408 -:1010880076F405EC1AF0000A01E177D7010A9CE032 -:10109800DAD70401040163516211D8B401D001D038 -:1010A80001D026D0040104016551800A800F1F0E6B -:1010B800D8B4645DD8B001D001D00AD00401D8906A -:1010C800040166370401673704016837040169378A -:1010D80004010401644B652B040104016551800A75 -:1010E800800F240ED8B4645DD8A001D001D0E8D612 -:1010F80051EC1DF0970E04010401806F790E040174 -:10110800816F7E0E040104017E6F790E04017F6FEA -:1011180022EC1DF0330E04010401806F790E0401E6 -:10112800816FC70E040104017E6F790E04017F6F81 -:1011380022EC1DF06AC480F46BC481F46CC482F4A0 -:101148006DC483F4DD0E040104017E6F790E040181 -:101158007F6F79EC13F00401726F020E0401040131 -:101168007E6F0401725143EC1DF0010E00D0120095 -:1011780004015E6F000E040104015A6F04015E5100 -:10118800C4D057C487F41DC085F41EC086F401EC92 -:101198001CF0D8A001D001D03CD0960E0401040167 -:1011A8002B6501D001D006D01DC053F41EC054F4E5 -:1011B80057C458F4040104012B51D8B401D001D00C -:1011C80018D02BC460F404015E6F000E0401040102 -:1011D8005F6F04015E511FEC0DF02BC460F4040135 -:1011E8005E6F000E040104015F6F04015E5152EC52 -:1011F80000F0122A04015E6F000E040104012B6F37 -:1012080004015E5104015E6F000E066E04015E511A -:1012180032D0040104012B6701D001D006D01DC0D3 -:1012280051F41EC052F457C42CF41250D8B401D053 -:1012380001D018D012C060F404015E6F010E0401E1 -:1012480004015F6F04015E511FEC0DF012C060F4E1 -:1012580004015E6F010E040104015F6F04015E5119 -:1012680052EC00F0040104012B2B04015E6F000E08 -:10127800126E04015E510401D89057330401040131 -:10128800576701D001D015D004015E6F800E0401AC -:101298000401576F04015E511D4A1E2A1E50020A9E -:1012A8001D10D8A401D001D004D0000E1D6E000E70 -:1012B8001E6E1E5004010401541904E11D5004015E -:1012C80004015319D8A401D001D00ED0040104019F -:1012D800575104010401586301D001D005D004011D -:1012E8000401536904015469040104012B51960A4D -:1012F800D8A401D001D009D004015E6F010E040109 -:1013080004015A6F04015E510DD0040104013051EB -:101318001E1804E1040104012F511D18D8A401D09E -:1013280001D02FD7040104015A6701D001D001D0A0 -:10133800A2D00650D8B401D001D001D09CD051C45D -:1013480061F452C462F453C45FF454C460F48CEC86 -:1013580017F05FC45CF460C45DF4040104015DBF70 -:1013680001D001D00DD0040104015D51800A800F25 -:10137800320ED8B45C5DD8B001D001D001D07BD09A -:10138800040104015D51800A800F9E0ED8B45C5D93 -:10139800D8A001D001D00CD0040104015D51800A0D -:1013A800800FA30ED8B45C5DD8A001D001D000D0C6 -:1013B80004015E6F000E040104015B6F04015E51BD -:1013C8002CC461F451C45FF452C460F407EC07F014 -:1013D800040104015B272CC461F451C45FF452C4B6 -:1013E80060F4A8EC0FF0040104015B272CC461F43D -:1013F80051C45FF452C460F4BEEC0BF00401040164 -:101408005B272CC461F451C45FF452C460F4CDEC82 -:1014180010F0040104015B272CC461F451C45FF48B -:1014280052C460F440EC0AF0040104015B272CC4A8 -:1014380061F451C45FF452C460F439EC05F004015E -:1014480004015B2704015E6F010E066E04015E5104 -:10145800040104015B51D8B401D001D00BD0000EB7 -:101468001D6E000E1E6E000E040104012F6F000E8B -:101478000401306F00D012000401756F000E0401E2 -:101488000401626F04017551000E04010401676FC5 -:10149800000E0401686F000E0401696F000E04015C -:1014A8006A6F010E040104016B6F000E04016C6F7A -:1014B800000E04016D6F000E04016E6F0401610ED1 -:1014C80004010401876F0401040E0401886F0401FC -:1014D8005F0E04010401856F0401040E0401866F88 -:1014E800A5EC1BF00401610E04010401806F0401E6 -:1014F800040E0401816F04015F0E040104017E6F74 -:101508000401040E04017F6FC4EC15F05FC465F498 -:1015180060C466F40401040161C463F404010401B5 -:10152800646B000E040104016F6F000E0401706FFC -:10153800040104017051800A800F200ED8B46F5D39 -:10154800D8A001D001D001D05AD00401610E040105 -:101558000401796F0401040E04017A6F04015F0E1F -:1015680004010401776F0401040E0401786F71EC23 -:1015780019F004010401736F040104017351020A94 -:10158800D8A401D001D002D0000EF3D00401040188 -:101598007351D8B401D001D018D0040104016B51A3 -:1015A800040104016713040104016C5104010401DE -:1015B8006813040104016D51040104016913040155 -:1015C80004016E51040104016A130401D890040156 -:1015D8006B3704016C3704016D3704016E37040161 -:1015E80004016F4B702B040104017051800A800FB5 -:1015F800200ED8B46F5DD8A001D001D0A6D7000EB8 -:1016080004010401716F000E0401726F04010401EA -:101618007251800A800F040ED8B4715DD8A001D031 -:1016280001D001D04BD00401610E04010401796F8F -:101638000401040E04017A6F04015F0E0401040121 -:10164800776F0401040E0401786F71EC19F004013E -:101658000401746F040104017451020AD8A401D072 -:1016680001D002D0000E85D0040104017451D8B411 -:1016780001D001D013D071C475F4010E0401766F46 -:101688000401752B03D0D890040176370401752F17 -:10169800FAD704017651040104016213040104011C -:1016A800714B722B040104017251800A800F040EE1 -:1016B800D8B4715DD8A001D001D0B5D70401040118 -:1016C80062510C0AD8B401D001D002D0000E51D01A -:1016D80051EC1DF0A60E04010401806F790E04017F -:1016E800816FCD0E040104017E6F790E04017F6FB6 -:1016F80022EC1DF0750E04010401806F790E0401BF -:10170800816F7E0E040104017E6F790E04017F6FE4 -:1017180022EC1DF00401330E04010401806F040162 -:10172800040E0401816FC70E040104017E6F790E57 -:1017380004017F6F22EC1DF067C480F468C481F453 -:1017480069C482F46AC483F4DD0E040104017E6F67 -:10175800790E04017F6F79EC13F00401756F010EA7 -:10176800040104017E6F0401755143EC1DF0010E64 -:1017780000D012000401610E04010401876F040106 -:10178800040E0401886F04015F0E04010401856FD3 -:101798000401040E0401866FA5EC1BF00401726FAE -:1017A800000E04010401626F04017251040E040169 -:1017B80004016A6F000E04016B6F040104016BAF32 -:1017C80001D001D001D08AD00401726F000E04014B -:1017D80004016E6F04017251000E040104016F6F61 -:1017E800000E0401706F040104017051800A800F1B -:1017F800080ED8B46F5DD8A001D001D001D04BD06D -:101808000401610E04010401766F0401040E040151 -:10181800776F04015F0E04010401746F0401040E64 -:101828000401756FC2EC1AF004010401716F040120 -:1018380004017151020AD8A401D001D002D0000ECF -:10184800F9D0040104017151D8B401D001D013D0EA -:101858006FC472F4010E0401736F0401722B03D07C -:10186800D890040173370401722FFAD70401735119 -:10187800040104016E13040104016F4B702B040171 -:1018880004017051800A800F080ED8B46F5DD8A08B -:1018980001D001D0B5D7040104016A51040A6B11C3 -:1018A800D8A401D001D002D06EC462F40401650E40 -:1018B800040104016A25E96EEA6A0401040EEA22B9 -:1018C80004016EC4EFFF040104016A07D8A06B0786 -:1018D800040104016BAF01D001D076D7000E0401DA -:1018E8000401636F000E0401646F000E040104011B -:1018F8006C6F000E04016D6F040104016D51800AC4 -:10190800800F040ED8B46C5DD8A001D001D001D0EE -:1019180033D00401726F310E04010401766F0401A3 -:1019280072510401650E040104016C25E96EEA6A2E -:101938000401040EEA22EF5004010401756F63C428 -:1019480074F437EC18F00401736F04017351040147 -:101958000401636F0401646B040104016C4B6D2B7B -:10196800040104016D51800A800F040ED8B46C5D27 -:10197800D8A001D001D0CDD7040162C472F404010B -:10198800736B0401040164510401731905E1040136 -:101998000401635104017219D8B401D001D002D0F6 -:1019A800000E48D051EC1DF0A60E04010401806F12 -:1019B800790E0401816FCD0E040104017E6F790E4A -:1019C80004017F6F22EC1DF04D0E04010401806FAD -:1019D800790E0401816F7E0E040104017E6F790E79 -:1019E80004017F6F22EC1DF00401726F050E0401E3 -:1019F8000401786F040172510401650E04010401A9 -:101A0800766F0401040E0401776FDD0E04010401F2 -:101A1800746F790E0401756F14EC14F00401726F81 -:101A2800010E040104017E6F0401725143EC1DF0A4 -:101A3800010E00D01200040104015F51D8B401D096 -:101A480001D005D0030E04010401602704D0030E61 -:101A580004010401605F3CD10C0E040104016065BF -:101A680001D001D009D0170E04010401606101D032 -:101A780001D002D0082A37D1030E040104016065A1 -:101A880001D001D01CD00E0E04010401606101D008 -:101A980001D015D0190E086401D001D00AD0040174 -:101AA800616F010E0B6E04016151000E1B6E000E7A -:101AB8001C6E0401616F000E086E0401615113D1A0 -:101AC80060C464F45FC463F426EC19F063C427F4BB -:101AD80064C428F4040104012829FE0ED8B4271987 -:101AE800D8A401D001D003D0CDEC1CF0FCD0040167 -:101AF80004012729D8B42829D8A401D001D001D0BD -:101B0800F2D01C501B10D8A401D001D006D004017B -:101B1800040127511C6E1B6A51D00401040127518E -:101B28001B120401040128511C121FD00401616F0B -:101B3800060E076E040161513F0E04010401556F42 -:101B4800000E0401566F2ED00401616F080E076E57 -:101B5800040161514F0E04010401556F000E040188 -:101B6800566F20D0CDEC1CF0BED01BC061F41CC059 -:101B780062F40FD0040161514D0AE6E0F3D7040185 -:101B880061512D0AE1E0EED7040161514C0ACEE023 -:101B9800E9D7040162510A0AEDE0100AF0E0F00A00 -:101BA800F3E0E0D70401616F020E0B6E040161518E -:101BB8000401616F000E086E0401615194D060C485 -:101BC80064F45FC463F426EC19F063C427F464C4B6 -:101BD80028F4040104012829FE0ED8B42719D8A432 -:101BE80001D001D003D0CDEC1CF07DD0040104015C -:101BF8002729D8B42829D8A401D001D001D073D07E -:101C080004011F0E0824E96EEA6A0401040EEA22A0 -:101C1800040127C4EFFF082A0706076601D001D090 -:101C28004ED7CDEC1CF051EC1DF0A60E04010401BA -:101C3800806F790E0401816FCD0E040104017E6F5F -:101C4800790E04017F6F22EC1DF0B40E040104012B -:101C5800806F790E0401816F7E0E040104017E6F8E -:101C6800790E04017F6F22EC1DF004011BC080F483 -:101C780004011CC081F404010401826B0401836B1C -:101C8800C70E040104017E6F790E04017F6F79ECA1 -:101C980013F008C078F404011F0E04010401766FE4 -:101CA8000401040E0401776FDD0E04010401746F52 -:101CB800790E0401756F14EC14F00401616F010EC4 -:101CC800040104017E6F0401615143EC1DF00BD047 -:101CD8000B50000A01E1C0D6010A01E1F1D6030A5E -:101CE80001E16DD700D0120004015E6F0B0E0401F4 -:101CF80004015B6F04015E5104015E6F0A0E04016A -:101D080004015C6F04015E51010E04010401646F5B -:101D1800000E0401656FFA0E04010401626F790E6A -:101D28000401636F1F0E04010401606F020E0401B9 -:101D3800616FE2EC17F0040161516011D8A401D081 -:101D480001D011D00A0E040104018D6F000E0401A8 -:101D58008E6F650E040104018B6F790E04018C6F80 -:101D68003BEC03F0F0D0010E04010401646F000E97 -:101D78000401656FFC0E04010401626F790E040111 -:101D8800636F1F0E04010401606F020E0401616F8E -:101D9800E2EC17F0040161516011D8A401D001D020 -:101DA8000AD0E70E040104018B6F790E04018C6FD1 -:101DB8003BEC03F0C8D004015E6F000E040104017F -:101DC8005D6F04015E5104015E6F000E04010401A1 -:101DD8005A6F04015E51B0D098D004015DC45EF41E -:101DE80004015F6B010E04015E27000E5F231F0EC6 -:101DF80004015E25E96E020E04015F21EA6EEF50D0 -:101E0800040104015B6F040104015D2B92D00401FD -:101E18005DC45EF404015F6B010E04015E27000ED1 -:101E28005F231F0E04015E25E96E020E04015F2187 -:101E3800EA6EEF50040104015C6F040104015D2B9C -:101E480078D05CC463F45BC462F4010E040104013D -:101E58005D2504010401606F0401616B000E04013B -:101E6800612334EC17F004015E6F010E04010401D4 -:101E78005A6F04015E51D30E040104018B6F790E71 -:101E880004018C6F3BEC03F054D05CC463F45BC476 -:101E980062F4010E040104015D2504010401606F70 -:101EA8000401616B000E04016123DCEC16F00401EF -:101EB8005E6F010E040104015A6F04015E51E20EC7 -:101EC800040104018B6F790E04018C6F3BEC03F065 -:101ED80030D01F0E040104015D25E96EEA6A020E86 -:101EE800EA22EF5004015E6F04015E51040104010F -:101EF8008D6F04018E6BFC0E040104018B6F780E4C -:101F080004018C6F3BEC03F01ED01F0E040104018A -:101F18005D25E96EEA6A020EEA22EF50500A01E1F5 -:101F28005CD7020A01E173D7010A8BE0070AADE02A -:101F3800D0D7040104015D2B040104015A51D8B41F -:101F480001D001D049D71200000E04010401666FC8 -:101F5800000E0401676F000E0401686F000E040193 -:101F6800696F010E04010401626F000E0401636FC2 -:101F7800000E0401646F000E0401656F0401610E18 -:101F880004010401876F0401040E0401886F040131 -:101F98005F0E04010401856F0401040E0401866FBD -:101FA800A5EC1BF00401610E04010401806F04011B -:101FB800040E0401816F04015F0E040104017E6FA9 -:101FC8000401040E04017F6FC4EC15F0000E040137 -:101FD80004016A6F000E04016B6F040104016B5168 -:101FE800800A800F0C0ED8B46A5DD8A001D001D049 -:101FF80001D08FD00401610E04010401806F040137 -:10200800040E0401816F04015F0E040104017E6F58 -:102018000401040E04017F6FC4EC15F004010401EF -:102028006C6F0401610E04010401806F0401040E49 -:102038000401816F04015F0E040104017E6F040135 -:10204800040E04017F6FC4EC15F0040104016D6FE8 -:102058000401610E04010401806F0401040E0401EF -:10206800816F04015F0E040104017E6F0401040EF8 -:1020780004017F6FC4EC15F0040104016E6F0401C4 -:10208800610E04010401806F0401040E0401816FD4 -:1020980004015F0E040104017E6F0401040E0401B3 -:1020A8007F6FC4EC15F0040104016F6F0401D89030 -:1020B800040166370401673704016837040169378A -:1020C80007D017D004010401668113D0000E60D038 -:1020D8006FC474F46EC473F46DC472F46CC471F498 -:1020E80083EC1AF0000AEDE0010AECE0030AEEE0E6 -:1020F80000D0040104016A4B6B2B040104016B51ED -:10210800800A800F0C0ED8B46A5DD8A001D001D027 -:1021180071D751EC1DF0970E04010401806F790E00 -:102128000401816F7E0E040104017E6F790E0401A3 -:102138007F6F22EC1DF0580E04010401806F790EA8 -:102148000401816FC70E040104017E6F790E04013A -:102158007F6F22EC1DF066C480F467C481F468C404 -:1021680082F469C483F4DD0E040104017E6F790EE4 -:1021780004017F6F79EC13F00401706F020E040103 -:1021880004017E6F0401705143EC1DF0010E00D074 -:102198001200000E04010401626F000E0401636F57 -:1021A800000E0401646F000E0401656F010E040146 -:1021B8000401666F000E0401676F000E0401686F6A -:1021C800000E0401696F0401610E04010401876FA8 -:1021D8000401040E0401886F04015F0E0401040168 -:1021E800856F0401040E0401866FA5EC1BF0000E38 -:1021F800040104016A6F000E04016B6F04010401FD -:102208006B51800A800F180ED8B46A5DD8A001D02F -:1022180001D001D0A2D00401610E04010401806F35 -:102228000401040E0401816F04015F0E040104011E -:102238007E6F0401040E04017F6FC4EC15F00401E5 -:1022480004016C6F0401610E04010401806F040134 -:10225800040E0401816F04015F0E040104017E6F06 -:102268000401040E04017F6FC4EC15F0040104019D -:102278006D6F0401610E04010401806F0401040EF6 -:102288000401816F04015F0E040104017E6F0401E3 -:10229800040E04017F6FC4EC15F0040104016E6F95 -:1022A8000401610E04010401806F0401040E04019D -:1022B800816F04015F0E040104017E6F0401040EA6 -:1022C80004017F6FC4EC15F0040104016F6F1CD08A -:1022D8002AD00401040166510401040162130401B7 -:1022E80004016751040104016313040104016851E6 -:1022F8000401040164130401040169510401040187 -:10230800651311D0000E58D06FC474F46EC473F402 -:102318006DC472F46CC471F444EC1AF0000AD8E08D -:10232800010AD7E0EFD70401D89004016637040109 -:1023380067370401683704016937040104016A4BEF -:102348006B2B040104016B51800A800F180ED8B45E -:102358006A5DD8A001D001D05ED751EC1DF0400EC7 -:1023680004010401806F790E0401816F7E0E04015F -:1023780004017E6F790E04017F6F22EC1DF062C4A8 -:1023880080F463C481F464C482F465C483F4DD0E0C -:10239800040104017E6F790E04017F6F79EC13F05C -:1023A8000401706F020E040104017E6F0401705174 -:1023B80043EC1DF0010E00D012000401756F000EF1 -:1023C80004010401726F04017551030E0401040134 -:1023D800726501D001D001D023D0040104017251EB -:1023E800040104016825E96E0401000E04010401DA -:1023F8006921EA6E04016E0E040104017225E16E82 -:10240800E26A0401040EE222EFCFE7FF04010401AF -:10241800722B030E04010401726501D001D0DDD7CF -:10242800050E0401040168250401756F000E0401FE -:10243800040169210401766F75C46CF476C46DF4E7 -:102448000096000E116E0094040100EE04F00401E1 -:102458006851E92604016951EA22EF500401040198 -:102468006B6F040104016B6701D001D001D081D0EA -:10247800040104016B6701D001D001D072D06CC493 -:10248800E9FF6DC4EAFFEF50040104016A6F04011B -:10249800756F000E04010401736F04017551030E7A -:1024A80004010401736501D001D001D050D06AC481 -:1024B80075F4C00E04017517060E0401766FD890E6 -:1024C800040175330401762FFAD70401755104010C -:1024D8000401746F04016E0E040104017425E96E91 -:1024E800EA6A0401040EEA22010EEF6201D001D06B -:1024F80002D0008613D004016E0E04010401742575 -:10250800E96EEA6A0401040EEA22EF50106EB18007 -:1025180000D000A401D001D0FCD700940401D890C9 -:102528006A37D8906A37040104016B070401040173 -:102538006B6701D001D001D00AD004010401732BCC -:10254800030E04010401736501D001D0B0D7040162 -:1025580004016C4B6D2B040104016B6701D001D0A1 -:102568008ED7009400D000A401D001D0FCD7B19040 -:1025780089981200026601D001D020D0030E040110 -:102588000401686501D001D007D00D0E04010401D3 -:10259800686501D001D00BD0870E040104018B6F50 -:1025A800790E04018C6F3BEC03F0FE0E9DD0040104 -:1025B800696F010E026E0401695194D00204D8A417 -:1025C80001D001D042D00C0E04010401686501D08D -:1025D80001D007D0160E04010401686501D001D0AE -:1025E80024D00CC069F404016A6B0401040156513B -:1025F80004016A1905E1040104015551040169192E -:10260800D8B401D001D011D08F0E040104018B6F12 -:10261800790E04018C6F3BEC03F00401696F000E26 -:10262800026E04016951FE0E5FD00090040104019E -:1026380067A101D000800401696F020E026E0401D7 -:102648006951000E00B0010E4FD00250020AD8A402 -:1026580001D001D047D0040104016751D8B401D09A -:1026680001D015D0030E04010401686501D001D022 -:102678000ED00E0E04010401686101D001D007D00C -:102688000401696F000E026E0401695129D00C0E15 -:1026980004010401686501D001D00ED0170E0401B1 -:1026A8000401686101D001D007D00401696F010EEF -:1026B800026E0401695114D0030E04010401686517 -:1026C80001D001D00DD00E0E04010401686101D0C3 -:1026D80001D006D00401696F000E026E0401695131 -:1026E800FF0E02D0FF0E00D012007EC48DF47FC40E -:1026F8008EF4C10E040104018B6F790E04018C6FF6 -:102708003BEC03F004018351801181118211D8A49C -:1027180001D001D00AD0F20E040104018B6F790EAA -:1027280004018C6F3BEC03F071D00401876F010E3C -:1027380004010401846F040187510401876F000EAE -:1027480004010401856F04018751070E0401040187 -:10275800856501D001D001D059D0040180C487F427 -:10276800040181C488F4040182C489F4040183C487 -:102778008AF41D0E06D0D89004018A338933883331 -:102788008733E82EF8D7040187510F0B04010401A1 -:10279800866F04010401866701D001D008D00401C6 -:1027A80004018405D8A401D001D001D018D00401B7 -:1027B800040186C48DF4040104018E6BDA0E040151 -:1027C80004018B6F790E04018C6F3BEC03F004015C -:1027D800876F000E04010401846F0401875104010E -:1027E800040ED89004018037040181370401823730 -:1027F80004018337E82EF5D704010401852B070E61 -:1028080004010401856501D001D0A7D7730E040126 -:1028180004018B6F790E04018C6F3BEC03F01200FE -:1028280074C48DF475C48EF4EC0E040104018B6F2E -:10283800790E04018C6F3BEC03F004017A6F000EF3 -:1028480004010401796F04017A51040104017851EB -:1028580004010401795DD8A001D001D001D04BD08A -:10286800040104017951040104017625E96E04018B -:10287800000E040104017721EA6EEF5004017A6F1B -:102888000F0E04017A1704017A51040104018F6FB5 -:102898000401906B040104017951040104017625B7 -:1028A800E96E0401000E040104017721EA6EEF507D -:1028B80004017B6F04017B3B0F0E7B1704017B51E6 -:1028C800040104018D6F04018E6BD80E040104010C -:1028D8008B6F790E04018C6F3BEC03F0040104014B -:1028E800792B04010401785104010401795DD8A011 -:1028F80001D001D0B5D7730E040104018B6F790E96 -:1029080004018C6F3BEC03F012000401D8902A37C5 -:1029180004010401C351D8B401D001D01BD0040173 -:102928000401292B040104012951030AD8A401D068 -:1029380001D005D0070E040104012A130AD0030EA2 -:1029480004010401296501D001D003D00401040168 -:102958002A8108D00401C46F000E04010401296F04 -:102968000401C4510401D890323704010401312B09 -:10297800040104012AAF01D001D004D004010401EC -:10298800328100D0040104013151080AD8A401D0D1 -:1029980001D029D00401C46F000E04010401316F75 -:1029A8000401C4511F0E040104012F25E96E000E15 -:1029B800040104013021EA6E040132C4EFFF04016E -:1029C80004012F4B302B040104013051020A2F114E -:1029D800D8A401D001D007D0000E040104012F6F44 -:1029E800000E0401306F1200040104014D51D8B4E7 -:1029F80001D001D024D0040104014C510401040188 -:102A08004B277E0E040104014B6501D001D004D090 -:102A1800040104014C6911D0040104014B6701D081 -:102A280001D00BD00401B46F010E040104014C6FF6 -:102A38000401B451040104014D074BC4BEFF040155 -:102A480004015051D8B401D001D024D004010401AC -:102A58004F51040104014E277E0E040104014E6506 -:102A680001D001D004D0040104014F6911D0040140 -:102A780004014E6701D001D00BD00401B46F010EE0 -:102A8800040104014F6F0401B4510401040150070B -:102A98004EC4BBFF040104014D6701D001D002D030 -:102AA800000EBE6E04010401506701D001D002D0AF -:102AB800000EBB6E12000096000E116E009468C4E2 -:102AC800E9FF69C4EAFFEF50106EB18000D000A49E -:102AD80001D001D0FCD79D92010E040104016A6F58 -:102AE800000E04016B6F2FD0040104016A51040128 -:102AF80004016825E96E040104016B510401040115 -:102B08006921EA6E010EEF6201D001D002D0008681 -:102B180016D00094040104016A51040104016825D7 -:102B2800E96E040104016B51040104016921EA6E94 -:102B3800EF50106E00D000A401D001D0FCD70401E2 -:102B480004016A4B6B2B040104016A51040104015E -:102B58006825E96E040104016B510401040169212F -:102B6800EA6EEF50D8A401D001D0BED79D82009460 -:102B780000D000A401D001D0FCD7B19089981200F0 -:102B88000401846F000E04010401836F0401845161 -:102B980080C4E9FF81C4EAFFEF5004010401876F94 -:102BA8007EC4E9FF7FC4EAFF0401EECF85F4040187 -:102BB800EDCF86F401EC1CF0D8B001D002D0010EA4 -:102BC80001D0000E04010401826F04010401832B6B -:102BD80080C487F481C488F47EC485F47FC486F4F5 -:102BE800A5EC1BF080C4E9FF81C4EAFFEF500401A3 -:102BF8000401876F7EC4E9FF7FC4EAFF0401EECFBA -:102C080085F40401EDCF86F401EC1CF0D8B001D0B6 -:102C180002D0010E01D0000E040104018219D8B4BB -:102C280001D001D004D00401040183510AD0040169 -:102C380004018329D8A401D001D002D0000E01D00C -:102C4800C4D71200000E04010401A16F000E040194 -:102C5800A26F040104019F519E11D8B401D001D084 -:102C680047D00401A36F010E04010401A06F040101 -:102C7800A35109D00401D89004019E3704019F375D -:102C880004010401A02B040104019FAF01D001D06D -:102C9800F1D70401D8900401A1370401A237040137 -:102CA80004019E51040104019C5D040104019F512B -:102CB800040104019D59D8A001D001D00FD004010E -:102CC80004019E51040104019C5F040104019F5109 -:102CD800040104019D5B04010401A1810401D89051 -:102CE80004019F3304019E3304010401A02FD1D7AE -:102CF800A1C49CF4A2C49DF400D01200000EAB6ED7 -:102D0800AB8EAB88AC90AC8AAC94B896948E949CFD -:102D180006D00401AECF5AF4040104015B6B9EBADD -:102D280001D001D0F6D704015C6F400EAF6E0401EC -:102D38005C519F9A9F98F28C9D8A9D98CD909E9009 -:102D4800000ECF6E000ECE6ECD9ACD98CD92000EAD -:102D580004010401616F020E0401626F000E040198 -:102D680004015F6F000E0401606F1F0E040104016F -:102D78005D6F020E04015E6F8FEC1CF0000E040103 -:102D88000401616F010E0401626F2D0E040104013C -:102D98005F6F000E0401606F0501000E040104015D -:102DA8005D6F0501050E04015E6F8FEC1CF01200CB -:102DB8006EEC1DF00401666F000E04010401646FDF -:102DC8000401665140D00401666F020E040104013B -:102DD800686F0401665175EC1DF01F0E0401666FE3 -:102DE800020E676F040104016051040166270401A3 -:102DF800040161510401672366C468F467C469F477 -:102E0800E1EC11F00401666F000E04010401656F26 -:102E1800040166510BD00D0E0401666FF90EE82E01 -:102E2800FED7662FFCD704010401652B04010401B9 -:102E3800625104010401655DD8A001D001D0EBD72F -:102E480004010401642B0401040163510401040119 -:102E5800645DD8A001D001D0B6D769EC1DF012008E -:102E68006EEC1DF00401666F000E04010401646F2E -:102E78000401665140D00401666F020E040104018A -:102E8800686F0401665175EC1DF01F0E0401666F32 -:102E9800020E676F040104016051040166270401F2 -:102EA800040161510401672366C468F467C469F4C6 -:102EB8005FEC15F00401666F000E04010401656FF4 -:102EC800040166510BD00D0E0401666FF90EE82E51 -:102ED800FED7662FFCD704010401652B0401040109 -:102EE800625104010401655DD8A001D001D0EBD77F -:102EF80004010401642B0401040163510401040169 -:102F0800645DD8A001D001D0B6D769EC1DF01200DD -:102F1800040104015F29D8B46029D8A401D001D0E4 -:102F280006D0040104015F690401606946D0040108 -:102F380004016251800A0401636F04015F510401B6 -:102F48000401615D040104016051800A04016359B0 -:102F5800D8A001D001D012D0040104015F510401AE -:102F68000401615D040104015F6F04010401605103 -:102F78000401040162590401606F1FD0000E0401AE -:102F8800636F020E646F040104015F510401635F03 -:102F98000401040160510401645B040104016151EE -:102FA80004016325040104015F6F040104016251F7 -:102FB800040164210401606F00D012003ED060C497 -:102FC800E9FF61C4EAFFEF50D8B401D001D014D0B2 -:102FD800040162C4F6FF040163C4F7FF0800F5CFDB -:102FE80066F460C4E9FF61C4EAFFEF5004016619A2 -:102FF800D8B401D001D019D060C4E9FF61C4EAFF98 -:10300800EF500401666F040162C4F6FF040163C453 -:10301800F7FF0800F5500401665D04010401606FC4 -:103028000401616BD8A061071DD004010401604B45 -:10303800612B04010401624B632B04010401640742 -:10304800D8A0650704016429D8B46529D8A401D09B -:1030580001D0B5D7000E04010401606F000E040111 -:10306800616F00D01200800E04010401796F000E18 -:1030780004017A6F040104017A517911D8A401D0AE -:1030880001D001D040D00401000E040174BF010E2C -:1030980004010401776F0401786B04010401755180 -:1030A8000401040179150009D8B401D001D00CD06D -:1030B8000401040178517711000ED8B4010E0401FF -:1030C8000401776F0401786B0401D8907437040108 -:1030D800040178517711D8B401D001D006D0040189 -:1030E8000401765104010401741B0401D890040101 -:1030F8007A3304017933040104017A517911D8A48F -:1031080001D001D0C0D704010401745100D01200CD -:10311800FACFA7F4FBCFA8F4E9CFA9F4EACFAAF431 -:10312800E1CFABF4E2CFACF4D9CFADF4DACFAEF463 -:10313800F3CFAFF4F4CFB0F4F6CFB1F4F7CFB2F4E5 -:10314800F8CFB3F49EAA01D001D002D03CEC1BF01A -:103158009EA801D001D002D0D4EC1BF09EA201D0D1 -:1031680001D003D0F8EC14F09E92B3C4F8FFB2C4B7 -:10317800F7FFB1C4F6FFB0C4F4FFAFC4F3FFAEC4A9 -:10318800DAFFADC4D9FFACC4E2FFABC4E1FFAAC407 -:10319800EAFFA9C4E9FFA8C4FBFFA7C4FAFFA6C4B5 -:1031A800E0FFA5C4E8FFA4C4D8FF1000040104018F -:1031B8009F519E11D8B401D001D03ED00401A16F17 -:1031C800010E04010401A06F0401A15109D00401FA -:1031D800D89004019E3704019F3704010401A02BF5 -:1031E800040104019FAF01D001D0F1D7040104010B -:1031F8009E51040104019C5D040104019F510401D6 -:1032080004019D59D8A001D001D00CD004010401BB -:103218009E51040104019C5F040104019F510401B3 -:1032280004019D5B0401D89004019F3304019E337F -:1032380004010401A02FDAD79CC49CF49DC49DF41A -:1032480000D0120064C468F463C467F4BEEC12F0E2 -:1032580004010401656F040104016551FE0AD8A444 -:1032680001D001D008D0FE0E04010401636FFF0EE7 -:103278000401646F31D0040104016529D8A401D088 -:1032880001D006D00401040163690401646924D0F3 -:10329800D8900532040104016551D8B401D001D099 -:1032A80001D0058E0C2A042A080E046001D001D032 -:1032B80006D0040104016369040164690DD00401A6 -:1032C800666F000E046E04016651040105C063F4C4 -:1032D80004010401646B00D0120079C480F47AC43C -:1032E80081F477C47EF478C47FF4C4EC15F004014B -:1032F80004017C6F1D0E040104017C6501D001D01E -:1033080009D0290E040104017C6101D001D002D04A -:10331800000E2DD079C480F47AC481F477C47EF489 -:1033280078C47FF4C4EC15F0040104017B6F090E26 -:10333800040104017C6501D001D017D0150E0401E9 -:1033480004017C6101D001D010D0090E04010401F0 -:103358007B6501D001D009D0150E040104017B6101 -:1033680001D001D002D0010E02D0020E00D012000E -:103378000600EACFB9F4E1CFBAF4E2CFBBF4D9CF73 -:10338800BCF4DACFBDF4F3CFBEF4F4CFBFF4F6CF7C -:10339800C0F4F7CFC1F4F8CFC2F4F2A401D001D041 -:1033A8000BD0000E81B8010E04010401C36F89EC33 -:1033B80014F0000ED66EF294A1A201D001D006D06E -:1033C800B368C90EB26EEBEC1CF0A192C2C4F8FF50 -:1033D800C1C4F7FFC0C4F6FFBFC4F4FFBEC4F3FF07 -:1033E800BDC4DAFFBCC4D9FFBBC4E2FFBAC4E1FF65 -:1033F800B9C4EAFFB8C4E9FFB7C4FBFFB6C4FAFF13 -:1034080011000F0E04010401766501D001D017D018 -:103418000A0E04010401776101D001D010D00A0E10 -:1034280004010401786101D001D009D00A0E040119 -:103438000401796101D001D002D0000E20D00A0E1B -:1034480004010401766101D001D017D00A0E0401ED -:103458000401776101D001D010D00F0E04010401DE -:10346800786501D001D009D00A0E04010401796100 -:1034780001D001D002D0010E02D0020E00D01200FD -:103488000D0E04010401716101D001D017D00D0E99 -:1034980004010401726101D001D010D00D0E0401A5 -:1034A8000401736101D001D009D0100E0401040198 -:1034B800746501D001D002D0010E20D00D0E040198 -:1034C8000401716101D001D017D0100E040104016C -:1034D800726501D001D010D00D0E04010401736192 -:1034E80001D001D009D00D0E04010401746101D08E -:1034F80001D002D0000E02D0020E00D012000F0E32 -:1035080004010401716501D001D017D00A0E04012D -:103518000401726101D001D010D00F0E0401040122 -:10352800736501D001D009D00A0E04010401746149 -:1035380001D001D002D0000E20D00A0E04010401EF -:10354800716101D001D017D00F0E0401040172651A -:1035580001D001D010D00F0E04010401736501D011 -:1035680001D009D00A0E04010401746101D001D010 -:1035780002D0010E02D0020E00D0120076C480F4F0 -:1035880077C481F474C47EF475C47FF4C4EC15F078 -:1035980004010401786F76C480F477C481F474C49C -:1035A8007EF475C47FF4C4EC15F004010401796F4E -:1035B8000D0E04010401786501D001D009D00D0E6B -:1035C80004010401796501D001D002D0000E12D0A7 -:1035D8000B0E04010401786101D001D009D00D0E51 -:1035E80004010401796501D001D002D0010E02D096 -:1035F800020E00D012000401796F000E0E6E040155 -:103608007951000E176E000E186E000E196E000E1E -:103618001A6E000E136E000E146E000E156E000E5C -:10362800166E010E04010401476F000E0401486F75 -:10363800000E0401496F000E04014A6F0401796FFE -:10364800000E0F6E04017951000E040104012D6F64 -:10365800000E04012E6F0401796F000E036E040141 -:1036680079510401796F000E096E04017951120035 -:10367800AECFB4F4ABA201D001D002D0AB98AB88E6 -:1036880000A201D001D001D029D004010401B45115 -:103698002B0AD8A401D001D00BD0CD9000821F0EE8 -:1036A8000124E96EEA6A020EEA22000EEF6E16D0D5 -:1036B8001F0E0124E96EEA6A020EEA220401B4C46C -:1036C800EFFF012A000ECF6E000ECE6ECD809E90C9 -:1036D8000401B56F000E0D6E0401B55112009EA0D5 -:1036E80001D001D00CD01E0E0D6401D001D005D040 -:1036F800CD90000E016E009201D00D2A9E9000B26E -:1037080001D001D001D01CD078EC0EF0000E0401DD -:103718000401616F020E0401626F000E04010401CE -:103728005F6F000E0401606F1F0E040104015D6FDE -:10373800020E04015E6F8FEC1CF0000E016E009209 -:10374800120087C4E9FF88C4EAFFD890EF3687C41F -:10375800E9FF88C4EAFFEF50D8A401D001D01FD0F8 -:1037680087C4E9FF88C4EAFF010EEF6E85C4E9FF4C -:1037780086C4EAFFEE50ED10D8A401D001D008D0DD -:1037880085C4E9FF86C4EAFF000EEE6E020EED6EF8 -:1037980085C4E9FF86C4EAFFEE06000EED5A120062 -:1037A80059C4B4F404010401B429D8A401D001D047 -:1037B80009D00401B56F000E04010401B46F0401BF -:1037C800B55103D004010401B42B0A5004010401CB -:1037D800B46301D001D002D09D980ED00501000E2F -:1037E80004010401B425E96EEA6A0501050EEA221E -:1037F800EF50AD6EB4C459F412001F0E0401040159 -:103808008525E96E000E040104018621EA6EEF5059 -:1038180004010401886F040104018851040187C46C -:1038280089F404018A6B89BF8A0704018917000E8D -:103838008A1704018A518911D8B401D001D002D065 -:10384800D88002D0D89000D012000D0E04010401D7 -:103858007E6101D001D009D00D0E040104017F6101 -:1038680001D001D002D0000E12D0180E04010401BC -:103878007E6501D001D009D00D0E040104017F61DD -:1038880001D001D002D0010E02D0020E00D01200E9 -:103898006FEC1CF064EC1DF082EC16F034EC1DF0BB -:1038A8005BEC1DF007EC1DF00A0E040104018D6F9E -:1038B800000E04018E6F630E040104018B6F790EF4 -:1038C80004018C6F3BEC03F0BCEC08F073EC1BF0CC -:1038D800FBD714EF00F0000EC26E04015A6F0F0EF2 -:1038E800C16E04015A51070EB46E000E806E000EB0 -:1038F800926E000E946E000E956E000E826E000E93 -:10390800836E000E936E000E816E89989298949241 -:103918009494929612005DC463F45EC464F40BD070 -:1039280063C4E9FF64C4EAFF04015FC4EFFF040154 -:103938000401634B642B040104016107D8A06207EA -:1039480004016129D8B46229D8A401D001D0E8D7EC -:1039580000D0120000D00A50040104015919D8B44B -:1039680001D001D0F8D70501000E0A24E96EEA6AF1 -:103978000501050EEA2204019CC4EFFF0A28D8A419 -:1039880001D001D003D0000E0A6E01D00A2A9D880A -:1039980012000401636F000E046E040163510401F8 -:1039A800636F000E026E040163510401636F000E21 -:1039B8000C6E040163510401636F000E0B6E040169 -:1039C8006351040104015569040156691200116626 -:1039D80001D001D011D00084106601D001D001D0EF -:1039E80011D010C011F0000E106E00B601D001D039 -:1039F80002D0897801D000961150D8B401D001D0F6 -:103A080001D011061200CA82CA9CCA8ACA98CA96EC -:103A1800000EBD6E000EBA6EBA86BA84BD86BD842D -:103A2800BD9ABD98BA9ABA98000EBE6E000EBB6ECB -:103A38009E92CB689F929D82CA84120080C48FF4A4 -:103A480081C490F47EC48DF47FC48EF4AD0E04015D -:103A580004018B6F790E04018C6F3BEC03F01200AC -:103A6800D594D592D590D596D59AD58CF294F28ADC -:103A780092969388F184D58E78EC1DF01200100E82 -:103A8800040104018B6F790E04018C6F3BEC03F089 -:103A98007EC47FF472EC1DF01200F40E04010401E0 -:103AA8008B6F790E04018C6F3BEC03F0120092943B -:103AB80092988998B19AB198A082A282B190120086 -:103AC800D08EF28EF28CF28E120078EC1DF0D58E2C -:103AD800B1901200D59E7BEC1DF012007FC44DF40E -:103AE800120068C450F412008994898612008984EF -:043AF8008996120099 -:1078EA0001000A006400E8031027010010000001EB -:1078FA000010556E6B6E6F776E20636F6D6D616EE3 -:10790A006420282575290D0A003031323334353682 -:10791A003738394142434445460073656C666C65A5 -:10792A0061726E696E6776320073656C666C65614A -:10793A00726E696E670065766572666C6F757269DC -:10794A0073680066696E656F666673657400636F57 -:10795A006465737769746368000D0A2B5625750D83 -:10796A000A0025733A307825583B006D616E646FC2 -:10797A006C796E0070726F746F636F6C00413A209D -:10798A0025690D0A00423A2025690D0A00617263D1 -:10799A007465636800286E756C6C290073656E7374 -:1079AA006F720025733A25733B006F7265676F6EBD -:1079BA000068617374610025733A3078006D6F64F2 -:1079CA00656C00636C617373002B530D0A002558B4 -:1079DA0025580064617461002B540D0A002B4E0D6A +:1003D800040104014651080A4711D8A401D001D0EC +:1003E8004DD0042A050E046001D001D033D013503B +:1003F8001A241A6E000E1B201B6E000E1C201C6E89 +:10040800000E1D201D6E040E046001D001D010D016 +:100418001AC088F41BC089F41CC08AF40401876BD5 +:1004280087C41AF088C41BF089C41CF08AC41DF064 +:1004380013502424246E000E2520256E000E26203D +:10044800266E000E2720276E0401876F000E136E9C +:1004580004018751000E04010401466F000E0401D7 +:10046800476F010E040104015C6F000E04015D6F0B +:10047800000E04015E6F000E04015F6F1250030A44 +:10048800D8A401D001D04ED00450040AD8A401D079 +:1004980001D048D01AC077F41BC078F41CC079F496 +:1004A8001DC07AF465EC1DF0D7EC1FF0C70E0401EF +:1004B8000401966F790E0401976F850E04010401FB +:1004C800946F790E0401956FA8EC1FF0500E04018B +:1004D8000401966F790E0401976FC10E040104019F +:1004E800946F790E0401956FA8EC1FF077C496F409 +:1004F80078C497F479C498F47AC499F4DD0E0401A9 +:100508000401946F790E0401956F1FEC15F0040136 +:10051800876F010E04010401946F04018751C9EC2F +:100528001FF0A4D01250070AD8A401D001D09DD042 +:100538000450050AD8A401D001D097D01350040163 +:1005480004017B6F04017C6B04017D6B04017E6BED +:1005580024C07FF425C080F426C081F427C082F42B +:100568001AC083F41BC084F41CC085F41DC086F433 +:1005780065EC1DF0040104017B51040104017F2591 +:100588000401876F040104017C51040104018021E6 +:100598000401886F040104017D51040104018121D3 +:1005A8000401896F040104017E51040104018221C0 +:1005B80004018A6FFF0E0401871504018B6F000E7A +:1005C8000401881504018C6F000E040189150401CB +:1005D8008D6F000E04018A1504018E6F04018B05CE +:1005E8008C118D118E11D8B401D001D001D03ED01C +:1005F800D7EC1FF0C70E04010401966F790E0401B1 +:10060800976F850E04010401946F790E0401956FAC +:10061800A8EC1FF0340E04010401966F790E040152 +:10062800976FC10E04010401946F790E0401956F50 +:10063800A8EC1FF083C496F484C497F485C498F496 +:1006480086C499F4DD0E04010401946F790E040147 +:10065800956F1FEC15F00401876F010E040104016A +:10066800946F04018751C9EC1FF000D012000401F7 +:1006780004017551D8B401D001D004D0040104019B +:10068800762B03D0040104017607C9D1050E0401B5 +:100698000401766501D001D009D00C0E04010401D3 +:1006A800766101D001D002D0162AC7D10D0E0401FF +:1006B8000401766501D001D019D0160E0401040199 +:1006C800766101D001D012D0140E166401D001D089 +:1006D8000DD00401776F010E0B6E040177510401F0 +:1006E800776F030E166E04017751A7D1D5EC1EF073 +:1006F800A4D10D0E04010401766501D001D0F6D70E +:10070800160E04010401766101D001D0EFD7160658 +:10071800166601D001D00AD0000E206E000E216EA0 +:100728000401776F020E0B6E0401775186D176C4EF +:100738007AF475C479F4BAEC15F079C441F47AC442 +:1007480042F4040104014229FE0ED8B44119D8A488 +:1007580001D001D003D0D5EC1EF06FD10401040103 +:100768004129D8B44229D8A401D001D001D065D1FB +:1007780021502010D8A401D001D006D004010401D2 +:100788004151216E206A7AD004010401415120129E +:10079800040104014251211228D00401776F070E89 +:1007A800040104016E6F040177515CD00401776F76 +:1007B800050E040104016E6F0401775153D0040142 +:1007C800776F080E040104016E6F040177514AD057 +:1007D8000401776F090E040104016E6F040177515B +:1007E80041D0040104016E693DD020C077F421C0D6 +:1007F80078F427D004017751840AE1E0100ADFE099 +:10080800F0D704017751140ADAE0EBD704017751E5 +:10081800100AC3E0E6D704017751600AD9E0E1D7AE +:1008280004017751440AC2E0DCD704017751740A05 +:10083800BDE0D7D704017751240AAFE0900AADE0B4 +:10084800D0D704017851190AD5E0300ADAE0040A51 +:10085800DDE0700AE0E0950AE3E0100AE6E0200A2D +:10086800E9E0BFD70401776F030E0B6E04017751DF +:100878000401776F000E066E04017751DED076C44E +:100888007AF475C479F4BAEC15F079C441F47AC4F1 +:1008980042F4040104014229FE0ED8B44119D8A437 +:1008A80001D001D038D0040104016EAF01D001D0CD +:1008B8001DD704010401756701D001D017D7D8905E +:1008C8000401040144310401786F04010401433137 +:1008D8000401776F380E0401775D000E7859D8A0AF +:1008E80001D001D003D71E0E04010401766501D0A2 +:1008F80001D0FCD60401776F000E040104016E6F6D +:1009080004017751000E04010401416F000E040137 +:10091800426F00D00DD0040104014129D8B4422906 +:10092800D8A401D001D001D088D0040104016E07F9 +:100938000401300E0624E96EEA6A0401040EEA2274 +:10094800040141C4EFFF062A040104016E6701D0C7 +:1009580001D057D0D5EC1EF0D7EC1FF0AD0E040136 +:100968000401966F790E0401976FCD0E04010401FE +:10097800946F790E0401956FA8EC1FF0A60E040180 +:100988000401966F790E0401976F850E0401040126 +:10099800946F790E0401956FA8EC1FF0040120C034 +:1009A80096F4040121C097F404010401986B040132 +:1009B800996BC10E04010401946F790E0401956FBF +:1009C8001FEC15F006C08EF40401300E040104017A +:1009D8008C6F0401040E04018D6FDD0E0401040107 +:1009E8008A6F790E04018B6F32EC16F00401776F71 +:1009F800010E04010401946F04017751C9EC1FF042 +:100A08001CD0910E04010401435D010E04014459F8 +:100A1800D8A001D001D08AD6D5EC1EF00ED00B504C +:100A2800000A01E133D6010A01E163D6030A01E1B4 +:100A38007ED6010A01E123D700D01200000E04017E +:100A480004017C6F000E04017D6F000E04017E6FAF +:100A5800000E04017F6F0401770E040104019D6FED +:100A68000401040E04019E6F0401750E04010401C3 +:100A78009B6F0401040E04019C6F0BEC1EF0040133 +:100A8800770E04010401966F0401040E0401976FA8 +:100A98000401750E04010401946F0401040E04019D +:100AA800956FE2EC17F0010E04010401786F000E57 +:100AB8000401796F000E04017A6F000E04017B6F48 +:100AC800000E04010401806F000E0401816F04010F +:100AD80004018151800A800F200ED8B4805DD8A00F +:100AE80001D001D001D070D00401770E04010401B7 +:100AF800966F0401040E0401976F0401750E04013A +:100B08000401946F0401040E0401956FE2EC17F0E0 +:100B180004010401826F0401770E04010401966F39 +:100B28000401040E0401976F0401750E0401040109 +:100B3800946F0401040E0401956FE2EC17F00401B0 +:100B48000401836F1CD026D00401040178510401EC +:100B580004017C13040104017951040104017D138B +:100B6800040104017A51040104017E130401040103 +:100B78007B51040104017F130DD0000E2CD183C4D6 +:100B880095F482C494F48FEC1EF0000ADCE0010AAC +:100B9800DBE0F3D70401D8900401783704017937F2 +:100BA80004017A3704017B3704010401804B812B4F +:100BB800040104018151800A800F200ED8B4805DA1 +:100BC800D8A001D001D090D704017CC484F40401DA +:100BD8007DC485F404017EC486F404017FC487F4CF +:100BE8000401841F851F861F871F110E06D0D89009 +:100BF80004018733863385338433E82EF8D7FF0E14 +:100C0800040184150401886F000E04018515040190 +:100C1800896F000E0401861504018A6F000E040115 +:100C2800871504018B6F04017CC48CF404017DC416 +:100C38008DF404017EC48EF404017FC48FF4190E70 +:100C480006D0D89004018F338E338D338C33E82E41 +:100C5800F8D7FF0E04018C150401906F000E0401F3 +:100C68008D150401916F000E04018E150401926F19 +:100C7800000E04018F150401936F04018B510401C8 +:100C880093190EE104018A510401921909E1040142 +:100C980089510401911904E1040188510401901952 +:100CA800D8B401D001D002D0000E95D0FF0E0401B7 +:100CB8007CC484F404017DC485F404017EC486F4F4 +:100CC80004017FC487F40401841F851F861F871FC2 +:100CD800040184150401886F000E040185150401C0 +:100CE800896F000E0401861504018A6F000E040145 +:100CF800871504018B6FFF0E04017CC48CF404017A +:100D08007DC48DF404017EC48EF404017FC48FF485 +:100D18008DC48CF48EC48DF48FC48EF404018F6B53 +:100D280004018C150401906F000E04018D15040157 +:100D3800916F000E04018E150401926F000E0401DC +:100D48008F150401936F04018B51040193190EE16F +:100D580004018A510401921909E10401895104012D +:100D6800911904E10401885104019019D8B401D003 +:100D780001D002D0000E2FD0D7EC1FF0F00E0401E6 +:100D88000401966F790E0401976F850E0401040122 +:100D9800946F790E0401956FA8EC1FF07CC496F44B +:100DA8007DC497F47EC498F47FC499F4DD0E0401E1 +:100DB8000401946F790E0401956F1FEC15F004017E +:100DC800846F020E04010401946F04018451C9EC7C +:100DD8001FF0010E00D012000401A30E040104014B +:100DE800AA6F0401040E0401AB6F96D1040104013B +:100DF800A951250AD8B401D001D005D0A9C4B2F4AC +:100E080034EC1FF089D10401B06F000E0401040115 +:100E1800A86F0401B05160D092D104010401A88FD9 +:100E280076D00401AAC4E9FF0401ABC4EAFF0401B7 +:100E3800020E0401AA27000E0401AB230401EECF21 +:100E4800ACF40401EDCFADF404010401AD51AC11D3 +:100E5800D8A401D001D007D09F0E04010401AC6FC3 +:100E6800790E0401AD6F1BD004010401AC51F66E7C +:100E7800E96E050EEA6E04010401AD51EA6403D07F +:100E8800EA6EEF5003D0F76E0800F5500401040134 +:100E9800B26F34EC1FF004010401AC4BAD2B04011C +:100EA8000401AC51F66EE96E050EEA6E0401040108 +:100EB800AD51EA6403D0EA6EEF5003D0F76E080034 +:100EC800F5500009D8A401D001D0CED725D1C00E45 +:100ED80004010401A8131BD00401A1C4F6FF0401F6 +:100EE800A2C4F7FF04010401A14BA22B08000401CE +:100EF800F5CFA9F40401A951000A8EE0580A8DE043 +:100F08002B0A8FE0060AE3E00D0A87E0DFD7040129 +:100F1800AAC4E9FF0401ABC4EAFF0401020E0401FC +:100F2800AA27000E0401AB230401EECFACF40401A0 +:100F3800EDCFADF478D00401B06F010E04010401C7 +:100F4800A96F0401B05104010401A951050AD8A4EC +:100F580001D001D001D02AD004010401A951020D09 +:100F6800FA0EF324F66EF76A780EF7220900F5CF29 +:100F7800B0F40900F5CFB1F40401B0510401040143 +:100F8800AC5D0401B15104010401AD59D8B001D0E0 +:100F980001D001D00BD004010401A92B04010401E4 +:100FA800A951050AD8A401D001D0D6D745D004014B +:100FB800B06F010E04010401A96F0401B0510401CE +:100FC8000401A951040AD8A401D001D001D0EED758 +:100FD80004010401A951020D040EF324F66EF76A08 +:100FE800790EF7220900F5CFB0F40900F5CFB1F476 +:100FF8000401B05104010401AC5D0401B1510401C4 +:101008000401AD59D8B001D001D001D0CFD7040127 +:101018000401A92B04010401A951040AD8A401D090 +:1010280001D0D6D709D004010401A851C00B800A09 +:10103800BEE0400A80E000D0A9C4A7F464D056D02E +:1010480004010401A751020DFA0EF324F66EF76AA3 +:10105800780EF72209000401F5CFB4F40A00040160 +:10106800F5CFB5F4ACC4B2F4ADC4B3F444EC18F0A5 +:10107800B2C4B2F4B3C4B3F40A0E04010401B46FE9 +:10108800000E0401B56FF8EC1AF004010401B25126 +:10109800300F04010401A96F32D004010401A751E3 +:1010A800020D040EF324F66EF76A790EF722090092 +:1010B8000401F5CFB4F40A000401F5CFB5F4ACC4CB +:1010C800B2F4ADC4B3F444EC18F00F0E04010401FB +:1010D800B217230E04010401B225F66EF76A790EE1 +:1010E800F72208000401F5CFA9F409D0040104018E +:1010F800A851C00B800AD1E0400AA2E000D0A9C4E0 +:10110800B2F434EC1FF004010401A7070401A72975 +:10111800D8A401D001D093D70401A1C4F6FF0401DB +:10112800A2C4F7FF04010401A14BA22B080004018B +:10113800F5CFA9F40401A96701D001D057D600D092 +:101148001200000E04010401806F000E0401816F7B +:10115800000E0401826F000E0401836F010E04016A +:1011680004017C6F000E04017D6F000E04017E6F88 +:10117800000E04017F6F000E04010401786F000E59 +:101188000401796F000E040104017A6F000E040156 +:101198007B6F0401770E040104019D6F0401040EA6 +:1011A80004019E6F0401750E040104019B6F040184 +:1011B800040E04019C6F0BEC1EF00401770E040171 +:1011C8000401966F0401040E0401976F0401750E63 +:1011D80004010401946F0401040E0401956FE2EC0C +:1011E80017F0040104017B51800A800F240ED8B443 +:1011F8007A5DD8A001D001D001D018D10401770EB2 +:1012080004010401966F0401040E0401976F0401A0 +:10121800750E04010401946F0401040E0401956F16 +:10122800E2EC17F004010401846F0401770E040155 +:101238000401966F0401040E0401976F0401750EF2 +:1012480004010401946F0401040E0401956FE2EC9B +:1012580017F004010401856F0401770E04010401ED +:10126800966F0401040E0401976F0401750E0401C2 +:101278000401946F0401040E0401956FE2EC17F069 +:1012880004010401866F0401770E04010401966FBE +:101298000401040E0401976F0401750E0401040192 +:1012A800946F0401040E0401956FE2EC17F0040139 +:1012B8000401876F7CD0040104017B51800A800FF0 +:1012C800200ED8B47A5DD8A001D001D01AD004017C +:1012D80080C488F4040181C489F4040182C48AF4B6 +:1012E800040183C48BF4D89004018B338A33893387 +:1012F800883388C480F489C481F48AC482F48BC496 +:1013080083F465D0040104017B51800A800F200E0C +:10131800D8B47A5DD8A001D001D01AD0040180C415 +:1013280088F4040181C489F4040182C48AF40401A4 +:1013380083C48BF4D89004018B338A338933883380 +:1013480088C480F489C481F48AC482F48BC483F489 +:10135800040104017C510401040180130401040107 +:101368007D51040104018113040104017E5104012B +:1013780004018213040104017F5104010401831351 +:1013880026D0040104017B51800A800F1F0ED8B4B7 +:101398007A5DD8A001D001D008D0010E0401040163 +:1013A800786F000E0401796F12D0000E7ED087C4CA +:1013B8008FF486C48EF485C48DF484C48CF46BECED +:1013C8001CF0000A01E177D7010A9CE0DAD7040192 +:1013D800040179517811D8B401D001D001D026D0B8 +:1013E800040104017B51800A800F1F0ED8B47A5D76 +:1013F800D8B001D001D00AD00401D89004017C37BC +:1014080004017D3704017E3704017F37040104019C +:101418007A4B7B2B040104017B51800A800F240E38 +:10142800D8B47A5DD8A001D001D0E8D6D7EC1FF0A7 +:10143800970E04010401966F790E0401976F850ECB +:1014480004010401946F790E0401956FA8EC1FF054 +:10145800500E04010401966F790E0401976FC10EB6 +:1014680004010401946F790E0401956FA8EC1FF034 +:1014780080C496F481C497F482C498F483C499F420 +:10148800DD0E04010401946F790E0401956F1FECC1 +:1014980015F00401886F020E04010401946F040121 +:1014A8008851C9EC1FF0010E00D012000401746FBE +:1014B800000E04010401706F04017451E2D06CC481 +:1014C8009DF418C09BF419C09CF467EC1EF0D8A0DA +:1014D80001D001D04AD0960E040104013D6501D027 +:1014E80001D006D018C068F419C069F46CC46DF452 +:1014F800040104013D51D8B401D001D024D03DC429 +:1015080076F40401746F000E04010401756F040180 +:101518007451DBEC0EF03DC476F40401746F000ED8 +:1015280004010401756F040174513BEC03F03DC4E0 +:1015380076F40401746F000E04010401756F040150 +:10154800745152EC00F0040104013C2B0401746F47 +:10155800000E040104013D6F040174510401746F0D +:10156800000E176E0401745142D0040104013D6756 +:1015780001D001D006D018C066F419C067F46CC455 +:101588003BF4040104013C51D8B401D001D024D06B +:101598003CC476F40401746F010E04010401756FF4 +:1015A80004017451DBEC0EF03CC476F40401746F52 +:1015B800010E04010401756F040174513BEC03F042 +:1015C8003CC476F40401746F010E04010401756FC4 +:1015D8000401745152EC00F0040104013D2B040194 +:1015E800746F000E040104013C6F0401745104017E +:1015F800D8906C33040104016C6701D001D015D078 +:101608000401746F800E040104016C6F04017451AD +:10161800184A192A1950020A1810D8A401D001D062 +:1016280004D0000E186E000E196E19500401040142 +:10163800691904E11850040104016819D8A401D0FB +:1016480001D00ED0040104016C51040104016D6342 +:1016580001D001D005D00401040168690401696959 +:10166800040104013D51960AD8A401D001D009D043 +:101678000401746F010E04010401706F04017451B8 +:101688000DD0040104014051191804E104010401BA +:101698003F511818D8A401D001D011D70401040172 +:1016A800706701D001D001D0A2D01750D8B401D0B2 +:1016B80001D001D09CD066C477F467C478F468C4BC +:1016C80075F469C476F4AAEC19F075C472F476C49A +:1016D80073F40401040173BF01D001D00DD00401DB +:1016E80004017351800A800F320ED8B4725DD8B0ED +:1016F80001D001D001D07BD0040104017351800ACC +:10170800800F9E0ED8B4725DD8A001D001D00CD045 +:10171800040104017351800A800FA30ED8B4725DCE +:10172800D8A001D001D000D00401746F000E0401CC +:101738000401716F040174513BC477F466C475F4F5 +:1017480067C476F4A5EC08F00401040171273BC4D2 +:1017580077F466C475F467C476F425EC10F00401D8 +:10176800040171273BC477F466C475F467C476F442 +:101778007AEC0DF00401040171273BC477F466C4C8 +:1017880075F467C476F485EC12F00401040171273E +:101798003BC477F466C475F467C476F4FCEC0BF0CC +:1017A8000401040171273BC477F466C475F467C467 +:1017B80076F422EC05F00401040171270401746F2A +:1017C800010E176E04017451040104017151D8B45B +:1017D80001D001D00BD0000E186E000E196E000E4D +:1017E800040104013F6F000E0401406F00D0120095 +:1017F80004018B6F000E04010401786F04018B5102 +:10180800000E040104017D6F000E04017E6F000EBE +:1018180004017F6F000E0401806F010E04010401B2 +:10182800816F000E0401826F000E0401836F000EA9 +:101838000401846F0401770E040104019D6F040103 +:10184800040E04019E6F0401750E040104019B6FD0 +:101858000401040E04019C6F0BEC1EF00401770ECA +:1018680004010401966F0401040E0401976F04013A +:10187800750E04010401946F0401040E0401956FB0 +:10188800E2EC17F075C47BF476C47CF4040104011F +:1018980077C479F4040104017A6B000E0401040191 +:1018A800856F000E0401866F040104018651800AC9 +:1018B800800F200ED8B4855DD8A001D001D001D00A +:1018C8005AD00401770E040104018F6F0401040E3D +:1018D8000401906F0401750E040104018D6F040169 +:1018E800040E04018E6F44EC1BF004010401896F9F +:1018F800040104018951020AD8A401D001D002D000 +:10190800000EF3D0040104018951D8B401D001D0EC +:1019180018D0040104018151040104017D1304015C +:1019280004018251040104017E130401040183515E +:10193800040104017F13040104018451040104011A +:1019480080130401D890040181370401823704010F +:1019580083370401843704010401854B862B040175 +:1019680004018651800A800F200ED8B4855DD8A066 +:1019780001D001D0A6D7000E04010401876F000E24 +:101988000401886F040104018851800A800F040E45 +:10199800D8B4875DD8A001D001D001D04BD00401C4 +:1019A800770E040104018F6F0401040E0401906F87 +:1019B8000401750E040104018D6F0401040E040175 +:1019C8008E6F44EC1BF0040104018A6F04010401CA +:1019D8008A51020AD8A401D001D002D0000E85D0C5 +:1019E800040104018A51D8B401D001D013D087C4AE +:1019F8008BF4010E04018C6F04018B2B03D0D8905B +:101A080004018C3704018B2FFAD704018C5104018F +:101A18000401781304010401874B882B0401040195 +:101A28008851800A800F040ED8B4875DD8A001D0F1 +:101A380001D0B5D70401040178510C0AD8B401D0FB +:101A480001D002D0000E51D0D7EC1FF0AD0E04012A +:101A58000401966F790E0401976FCD0E04010401FD +:101A6800946F790E0401956FA8EC1FF0730E0401B2 +:101A78000401966F790E0401976F850E0401040125 +:101A8800946F790E0401956FA8EC1FF00401480EBD +:101A980004010401966F0401040E0401976FC10E3E +:101AA80004010401946F790E0401956FA8EC1FF0EE +:101AB8007DC496F47EC497F47FC498F480C499F4E6 +:101AC800DD0E04010401946F790E0401956F1FEC7B +:101AD80015F004018B6F010E04010401946F0401D9 +:101AE8008B51C9EC1FF0010E00D012000401770ED3 +:101AF800040104019D6F0401040E04019E6F04019A +:101B0800750E040104019B6F0401040E04019C6F0F +:101B18000BEC1EF00401886F000E04010401786FBD +:101B280004018851040E04010401806F000E0401B1 +:101B3800816F0401040181AF01D001D001D08AD0A6 +:101B48000401886F000E04010401846F04018851A8 +:101B5800000E04010401856F000E0401866F040164 +:101B680004018651800A800F080ED8B4855DD8A07C +:101B780001D001D001D04BD00401770E040104013B +:101B88008C6F0401040E04018D6F0401750E0401AD +:101B980004018A6F0401040E04018B6F28EC1DF008 +:101BA80004010401876F040104018751020AD8A4C3 +:101BB80001D001D002D0000EF9D0040104018751F0 +:101BC800D8B401D001D013D085C488F4010E040123 +:101BD800896F0401882B03D0D89004018937040148 +:101BE800882FFAD7040189510401040184130401E0 +:101BF8000401854B862B040104018651800A800F5D +:101C0800080ED8B4855DD8A001D001D0B5D704019D +:101C180004018051040A8111D8A401D001D002D056 +:101C280084C478F404017B0E040104018025E96E64 +:101C3800EA6A0401040EEA22040184C4EFFF0401E5 +:101C480004018007D8A081070401040181AF01D0F5 +:101C580001D076D7000E04010401796F000E04014B +:101C68007A6F000E04010401826F000E0401836F75 +:101C7800040104018351800A800F040ED8B4825DE8 +:101C8800D8A001D001D001D033D00401886F310E23 +:101C9800040104018C6F0401885104017B0E0401C6 +:101CA80004018225E96EEA6A0401040EEA22EF5073 +:101CB800040104018B6F79C48AF455EC1AF004010D +:101CC800896F0401895104010401796F04017A6B59 +:101CD80004010401824B832B040104018351800A0F +:101CE800800F040ED8B4825DD8A001D001D0CDD722 +:101CF800040178C488F40401896B040104017A5151 +:101D08000401891905E104010401795104018819C4 +:101D1800D8B401D001D002D0000E48D0D7EC1FF0C3 +:101D2800AD0E04010401966F790E0401976FCD0E74 +:101D380004010401946F790E0401956FA8EC1FF05B +:101D4800680E04010401966F790E0401976F850EE1 +:101D580004010401946F790E0401956FA8EC1FF03B +:101D68000401886F050E040104018E6F0401885177 +:101D780004017B0E040104018C6F0401040E0401AC +:101D88008D6FDD0E040104018A6F790E04018B6FDB +:101D980032EC16F00401886F010E04010401946FFF +:101DA80004018851C9EC1FF0010E00D01200040193 +:101DB80004017551D8B401D001D005D0030E040137 +:101DC8000401762704D0030E04010401765F2DD1A7 +:101DD8000B0E04010401766501D001D009D0170E5D +:101DE80004010401766101D001D002D0072A28D16C +:101DF800030E04010401766501D001D01CD00E0E3B +:101E080004010401766101D001D015D0190E0764D0 +:101E180001D001D00AD00401776F010E0C6E0401C5 +:101E28007751000E1E6E000E1F6E0401776F000EB4 +:101E3800076E0401775104D176C47AF475C479F435 +:101E48008FEC1BF079C422F07AC423F02328FE0E0D +:101E5800D8B42218D8A401D001D003D053EC1FF075 +:101E6800EFD02228D8B42328D8A401D001D001D09B +:101E7800E7D01F501E10D8A401D001D004D02250A2 +:101E88001F6E1E6A4DD022501E1223501F121FD0E3 +:101E98000401776F060E096E040177513F0E0401A5 +:101EA80004016A6F000E04016B6F2ED00401776F76 +:101EB800080E096E040177514F0E040104016A6F80 +:101EC800000E04016B6F20D053EC1FF0B9D01EC078 +:101ED80077F41FC078F40FD0040177514D0AE6E07B +:101EE800F3D7040177512D0AE1E0EED704017751C9 +:101EF8004C0ACEE0E9D7040178510A0AEDE0100A4D +:101F0800F0E0F00AF3E0E0D70401776F020E0C6E00 +:101F1800040177510401776F000E076E04017751B1 +:101F28008FD076C47AF475C479F48FEC1BF079C439 +:101F380022F07AC423F02328FE0ED8B42218D8A49D +:101F480001D001D003D053EC1FF07AD02228D8B4A6 +:101F58002328D8A401D001D001D072D00401280EC2 +:101F68000724E96EEA6A0401040EEA2222C0EFFFA0 +:101F7800072A0906096601D001D05DD753EC1FF086 +:101F8800D7EC1FF0AD0E04010401966F790E040121 +:101F9800976FCD0E04010401946F790E0401956FBB +:101FA800A8EC1FF0A60E04010401966F790E040137 +:101FB800976F850E04010401946F790E0401956FE3 +:101FC800A8EC1FF004011EC096F404011FC097F48A +:101FD80004010401986B0401996BC10E040104010A +:101FE800946F790E0401956F1FEC15F007C08EF4FD +:101FF8000401280E040104018C6F0401040E04017D +:102008008D6FDD0E040104018A6F790E04018B6F58 +:1020180032EC16F00401776F010E04010401946F8D +:1020280004017751C9EC1FF00BD00C50000A01E1F4 +:10203800CFD6010A01E100D7030A01E172D700D027 +:102048001200000E040104017C6F000E04017D6F74 +:10205800000E04017E6F000E04017F6F010E040163 +:102068000401786F000E0401796F000E04017A6F85 +:10207800000E04017B6F0401770E040104019D6FBB +:102088000401040E04019E6F0401750E040104018D +:102098009B6F0401040E04019C6F0BEC1EF00401FD +:1020A800770E04010401966F0401040E0401976F72 +:1020B8000401750E04010401946F0401040E040167 +:1020C800956FE2EC17F0000E04010401806F000E1A +:1020D8000401816F040104018151800A800F0C0EF4 +:1020E800D8B4805DD8A001D001D001D08FD0040130 +:1020F800770E04010401966F0401040E0401976F22 +:102108000401750E04010401946F0401040E040116 +:10211800956FE2EC17F004010401826F0401770E59 +:1021280004010401966F0401040E0401976F040171 +:10213800750E04010401946F0401040E0401956FE7 +:10214800E2EC17F004010401836F0401770E040127 +:102158000401966F0401040E0401976F0401750EC3 +:1021680004010401946F0401040E0401956FE2EC6C +:1021780017F004010401846F0401770E04010401BF +:10218800966F0401040E0401976F0401750E040193 +:102198000401946F0401040E0401956FE2EC17F03A +:1021A80004010401856F0401D89004017C370401FF +:1021B8007D3704017E3704017F3707D017D004012B +:1021C80004017C8113D0000E6BD085C48AF484C4CA +:1021D80089F483C488F482C487F4AAEC1CF0000A4A +:1021E800EDE0010AECE0030AEEE000D0040104018E +:1021F800804B812B040104018151800A800F0C0E51 +:10220800D8B4805DD8A001D001D071D704017F5126 +:102218007C117D117E11D8A401D001D002D0000E0E +:102228003FD0D7EC1FF0970E04010401966F790E8A +:102238000401976F850E04010401946F790E04015F +:10224800956FA8EC1FF05D0E04010401966F790EDE +:102258000401976FC10E04010401946F790E040103 +:10226800956FA8EC1FF07CC496F47DC497F47EC4E7 +:1022780098F47FC499F4DD0E04010401946F790E7B +:102288000401956F1FEC15F00401866F020E04011E +:102298000401946F04018651C9EC1FF0010E00D0AF +:1022A80012000401746F0B0E04010401716F040124 +:1022B80074510401746F0A0E04010401726F040161 +:1022C8007451010E040104017A6F000E04017B6F42 +:1022D800FC0E04010401786F790E0401796F280E51 +:1022E80004010401766F020E0401776F00EC1AF006 +:1022F800040177517611D8A401D001D011D00C0E69 +:1023080004010401A36F000E0401A46F7E0E0401F2 +:102318000401A16F790E0401A26FF0EC06F0F0D071 +:10232800010E040104017A6F000E04017B6FFA0E9E +:1023380004010401786F790E0401796F280E0401F5 +:102348000401766F020E0401776F00EC1AF00401A5 +:1023580077517611D8A401D001D00AD0D30E040148 +:102368000401A16F790E0401A26FF0EC06F0C8D049 +:102378000401746F000E04010401736F04017451A9 +:102388000401746F000E04010401706F040174519C +:10239800B0D098D0040173C474F40401756B010EB5 +:1023A80004017427000E7523280E04017425E96EB4 +:1023B800020E04017521EA6EEF5004010401716FE9 +:1023C80004010401732B92D0040173C474F4040152 +:1023D800756B010E04017427000E7523280E040185 +:1023E8007425E96E020E04017521EA6EEF500401AE +:1023F8000401726F04010401732B78D072C479F45C +:1024080071C478F4010E0401040173250401040168 +:10241800766F0401776B000E04017723FAEC18F04D +:102428000401746F010E04010401706F04017451FA +:10243800E20E04010401A16F790E0401A26FF0EC11 +:1024480006F054D072C479F471C478F4010E040112 +:102458000401732504010401766F0401776B000EF3 +:102468000401772352EC19F00401746F010E040182 +:102478000401706F04017451E70E04010401A16F97 +:10248800790E0401A26FF0EC06F030D0280E04019A +:1024980004017325E96EEA6A020EEA22EF5004018C +:1024A800746F0401745104010401A36F0401A46B47 +:1024B8000C0E04010401A16F790E0401A26FF0EC67 +:1024C80006F01ED0280E040104017325E96EEA6A9D +:1024D800020EEA22EF50500A01E15CD7020A01E13C +:1024E80073D7010A8BE0070AADE0D0D704010401D5 +:1024F800732B040104017051D8B401D001D049D71D +:102508001200000E04010401786F000E0401796FB7 +:10251800000E04017A6F000E04017B6F010E0401A6 +:1025280004017C6F000E04017D6F000E04017E6FB4 +:10253800000E04017F6F0401770E040104019D6FF2 +:102548000401040E04019E6F0401750E04010401C8 +:102558009B6F0401040E04019C6F0BEC1EF0000E2F +:1025680004010401806F000E0401816F040104015D +:102578008151800A800F180ED8B4805DD8A001D090 +:1025880001D001D0A2D00401770E04010401966F96 +:102598000401040E0401976F0401750E040104017F +:1025A800946F0401040E0401956FE2EC17F0040126 +:1025B8000401826F0401770E04010401966F04017F +:1025C800040E0401976F0401750E04010401946F51 +:1025D8000401040E0401956FE2EC17F004010401F4 +:1025E800836F0401770E04010401966F0401040E41 +:1025F8000401976F0401750E04010401946F04012E +:10260800040E0401956FE2EC17F004010401846FD5 +:102618000401770E04010401966F0401040E0401FD +:10262800976F0401750E04010401946F0401040EF0 +:102638000401956FE2EC17F004010401856F1CD0CA +:102648002AD0040104017C51040104017813040117 +:1026580004017D51040104017913040104017E5130 +:10266800040104017A13040104017F5104010401E7 +:102678007B1311D0000E58D085C48AF484C489F421 +:1026880083C488F482C487F4E9EC1CF0000AD8E01B +:10269800010AD7E0EFD70401D89004017C37040180 +:1026A8007D3704017E3704017F3704010401804B24 +:1026B800812B040104018151800A800F180ED8B4BF +:1026C800805DD8A001D001D05ED7D7EC1FF0430EB3 +:1026D80004010401966F790E0401976F850E0401B9 +:1026E8000401946F790E0401956FA8EC1FF078C46B +:1026F80096F479C497F47AC498F47BC499F4DD0EFF +:1027080004010401946F790E0401956F1FEC15F014 +:102718000401866F020E04010401946F04018651BE +:10272800C9EC1FF0010E00D0120004018B6F000EDF +:1027380004010401886F04018B51030E0401040194 +:10274800886501D001D001D023D00401040188514B +:10275800040104017E25E96E0401000E0401040150 +:102768007F21EA6E0401840E040104018825E16ECC +:10277800E26A0401040EE222EFCFE7FF040104013C +:10278800882B030E04010401886501D001D0DDD730 +:10279800050E040104017E2504018B6F000E04015F +:1027A80004017F2104018C6F8BC482F48CC483F4F0 +:1027B8000096000E116E0094040100EE04F004016E +:1027C8007E51E92604017F51EA22EF5004010401F9 +:1027D800816F04010401816701D001D001D081D04B +:1027E80004010401816701D001D001D072D082C4F4 +:1027F800E9FF83C4EAFFEF5004010401806F04017C +:102808008B6F000E04010401896F04018B51030EC4 +:1028180004010401896501D001D001D050D080C4E1 +:102828008BF4C00E04018B17060E04018C6FD89030 +:1028380004018B3304018C2FFAD704018B51040156 +:1028480004018A6F0401840E040104018A25E96EDB +:10285800EA6A0401040EEA22010EEF6201D001D0F7 +:1028680002D0008613D00401840E040104018A25D5 +:10287800E96EEA6A0401040EEA22EF500D6EB18097 +:1028880000D000A401D001D0FCD700940401D89056 +:102898008037D890803704010401810704010401BE +:1028A800816701D001D001D00AD004010401892B2D +:1028B800030E04010401896501D001D0B0D70401D9 +:1028C8000401824B832B04010401816701D001D0EC +:1028D8008ED7009400D000A401D001D0FCD7B190CD +:1028E80089981200026601D001D017D0030E0401A6 +:1028F80004017E6501D001D007D00D0E040104014A +:102908007E6501D001D002D0FE0E94D004017F6F05 +:10291800010E026E04017F518BD00204D8A401D0AD +:1029280001D039D00B0E040104017E6501D001D01D +:1029380007D0160E040104017E6501D001D01BD01A +:102948000FC07FF40401806B040104016B51040182 +:10295800801905E1040104016A5104017F19D8B402 +:1029680001D001D008D004017F6F000E026E04016F +:102978007F51FE0E5FD00090040104017DA101D0BB +:10298800008004017F6F020E026E04017F51000E69 +:1029980000B0010E4FD00250020AD8A401D001D0D5 +:1029A80047D0040104017D51D8B401D001D015D01D +:1029B800030E040104017E6501D001D00ED00E0E75 +:1029C800040104017E6101D001D007D004017F6FAA +:1029D800000E026E04017F5129D00B0E0401040180 +:1029E8007E6501D001D00ED0170E040104017E616E +:1029F80001D001D007D004017F6F010E026E0401DF +:102A08007F5114D0030E040104017E6501D001D06A +:102A18000DD00E0E040104017E6101D001D006D054 +:102A280004017F6F000E026E04017F51FF0E02D079 +:102A3800FF0E00D0120094C4A3F495C4A4F4BB0EF6 +:102A480004010401A16F790E0401A26FF0EC06F0F5 +:102A580004019951961197119811D8A401D001D069 +:102A68000AD0F20E04010401A16F790E0401A26FCD +:102A7800F0EC06F071D004019D6F010E0401040111 +:102A88009A6F04019D5104019D6F000E0401040119 +:102A98009B6F04019D51070E040104019B6501D041 +:102AA80001D001D059D0040196C49DF4040197C403 +:102AB8009EF4040198C49FF4040199C4A0F41D0E67 +:102AC80006D0D8900401A0339F339E339D33E82E5F +:102AD800F8D704019D510F0B040104019C6F0401F8 +:102AE80004019C6701D001D008D0040104019A05B3 +:102AF800D8A401D001D001D018D0040104019CC48D +:102B0800A3F404010401A46BDA0E04010401A16F0B +:102B1800790E0401A26FF0EC06F004019D6F000E1F +:102B2800040104019A6F04019D510401040ED89018 +:102B3800040196370401973704019837040199373F +:102B4800E82EF5D7040104019B2B070E04010401AC +:102B58009B6501D001D0A7D7950E04010401A16F90 +:102B6800790E0401A26FF0EC06F012007AC47FF42B +:102B780079C47EF423EC1CF0040104017B6F056624 +:102B880001D001D006D004017C6F000E0A6E04014A +:102B98007C51040104017B51FE0AD8A401D001D064 +:102BA80008D0FE0E04010401796FFF0E04017A6F4C +:102BB80054D0040104017B29D8A401D001D006D047 +:102BC80004010401796904017A6947D01450040AA0 +:102BD800D8A401D001D009D00A3AF00E0A1604018F +:102BE8007C6F000E146E04017C51040104017B51BA +:102BF800D8B401D001D011D014C07CF4010E040166 +:102C08007D6F04017C2B03D0D89004017D3704012B +:102C18007C2FFAD704017D510A12052A142A080EBE +:102C2800056001D001D006D00401040179690401CE +:102C38007A6913D004017C6F000E056E04017C5183 +:102C480004017C6F000E146E04017C5104010AC05B +:102C580079F4040104017A6B00D012008AC4A3F449 +:102C68008BC4A4F4EC0E04010401A16F790E0401D5 +:102C7800A26FF0EC06F00401906F000E040104014D +:102C88008F6F04019051040104018E510401040165 +:102C98008F5DD8A001D001D001D04BD00401040130 +:102CA8008F51040104018C25E96E0401000E040112 +:102CB80004018D21EA6EEF500401906F0F0E04019C +:102CC80090170401905104010401A56F0401A66B3B +:102CD800040104018F51040104018C25E96E0401EB +:102CE800000E040104018D21EA6EEF500401916F7A +:102CF8000401913B0F0E9117040191510401040145 +:102D0800A36F0401A46BD80E04010401A16F790E0E +:102D18000401A26FF0EC06F0040104018F2B0401FA +:102D280004018E51040104018F5DD8A001D001D0A7 +:102D3800B5D7950E04010401A16F790E0401A26FA5 +:102D4800F0EC06F012000401D8903A3704010401AF +:102D5800D951D8B401D001D01BD004010401392BBA +:102D6800040104013951030AD8A401D001D005D0C7 +:102D7800070E040104013A130AD0030E04010401EA +:102D8800396501D001D003D0040104013A8108D08B +:102D98000401DA6F000E04010401396F0401DA51ED +:102DA8000401D8904537040104013E2B04010401B5 +:102DB8003AAF01D001D004D004010401458100D00C +:102DC800040104013E51080AD8A401D001D029D039 +:102DD8000401DA6F000E040104013E6F0401DA51A8 +:102DE800280E040104013F25E96E000E04010401C8 +:102DF8004021EA6E040145C4EFFF040104013F4B82 +:102E0800402B040104014051020A3F11D8A401D00B +:102E180001D007D0000E040104013F6F000E040129 +:102E2800406F1200040104016251D8B401D001D0EE +:102E380024D00401040161510401040160277E0EBD +:102E480004010401606501D001D004D0040104012B +:102E5800616911D004010401606701D001D00BD071 +:102E68000401CA6F010E04010401616F0401CA5113 +:102E780004010401620760C4BEFF04010401655136 +:102E8800D8B401D001D024D0040104016451040154 +:102E9800040163277E0E04010401636501D001D09B +:102EA80004D004010401646911D0040104016367BA +:102EB80001D001D00BD00401CA6F010E0401040136 +:102EC800646F0401CA5104010401650763C4BBFFB0 +:102ED80004010401626701D001D002D0000EBE6E69 +:102EE80004010401656701D001D002D0000EBB6E59 +:102EF80012000096000E116E00947EC4E9FF7FC494 +:102F0800EAFFEF500D6EB18000D000A401D001D0CF +:102F1800FCD79D92010E04010401806F000E04018C +:102F2800816F2FD0040104018051040104017E2522 +:102F3800E96E040104018151040104017F21EA6E54 +:102F4800010EEF6201D001D002D0008616D00094A5 +:102F5800040104018051040104017E25E96E040185 +:102F680004018151040104017F21EA6EEF500D6EC6 +:102F780000D000A401D001D0FCD704010401804B8B +:102F8800812B040104018051040104017E25E96EAE +:102F9800040104018151040104017F21EA6EEF500C +:102FA800D8A401D001D0BED79D82009400D000A43F +:102FB80001D001D0FCD7B1908998120004019A6F12 +:102FC800000E04010401996F04019A5196C4E9FFA7 +:102FD80097C4EAFFEF50040104019D6F94C4E9FF10 +:102FE80095C4EAFF0401EECF9BF40401EDCF9CF4F5 +:102FF80067EC1EF0D8B001D002D0010E01D0000E4F +:1030080004010401986F04010401992B96C49DF4EE +:1030180097C49EF494C49BF495C49CF40BEC1EF0E6 +:1030280096C4E9FF97C4EAFFEF50040104019D6FBD +:1030380094C4E9FF95C4EAFF0401EECF9BF40401B0 +:10304800EDCF9CF467EC1EF0D8B001D002D0010E91 +:1030580001D0000E040104019819D8B401D001D0A0 +:1030680004D00401040199510AD0040104019929EA +:10307800D8A401D001D002D0000E01D0C4D71200CC +:10308800000E04010401B76F000E0401B86F0401BB +:103098000401B551B411D8B401D001D047D004010E +:1030A800B96F010E04010401B66F0401B95109D0CA +:1030B8000401D8900401B4370401B53704010401B0 +:1030C800B62B04010401B5AF01D001D0F1D704013A +:1030D800D8900401B7370401B83704010401B4518A +:1030E80004010401B25D04010401B55104010401A5 +:1030F800B359D8A001D001D00FD004010401B451B4 +:1031080004010401B25F04010401B5510401040182 +:10311800B35B04010401B7810401D8900401B533FD +:103128000401B43304010401B62FD1D7B7C4B2F4F3 +:10313800B8C4B3F400D01200000EAB6EAB8EAB88EF +:10314800AC90AC8AAC94B896948E949C06D004014A +:10315800AECF70F404010401716B9EBA01D001D0A6 +:10316800F6D70401726F400EAF6E040172519F9A38 +:103178009F98F28C9D8A9D98CD909E90000ECF6E60 +:10318800000ECE6ECD9ACD98CD92000E04010401AA +:10319800776F020E0401786F000E04010401756F49 +:1031A800000E0401766F280E04010401736F020EED +:1031B8000401746F15EC1FF0000E04010401776F11 +:1031C800010E0401786F2D0E04010401756F000EC5 +:1031D8000401766F0501000E04010401736F0501F7 +:1031E800050E0401746F15EC1FF01200F4EC1FF0CB +:1031F80004017C6F000E040104017A6F04017C5104 +:1032080040D004017C6F020E040104017E6F0401AA +:103218007C51FEEC1FF0280E04017C6F020E7D6FBE +:1032280004010401765104017C270401040177514B +:1032380004017D237CC47EF47DC47FF47DEC17F00B +:1032480004017C6F000E040104017B6F04017C51B2 +:103258000BD00D0E04017C6FF90EE82EFED77C2FE3 +:10326800FCD7040104017B2B0401040178510401FB +:1032780004017B5DD8A001D001D0EBD70401040183 +:103288007A2B040104017951040104017A5DD8A064 +:1032980001D001D0B6D7EAEC1FF01200F4EC1FF011 +:1032A80004017C6F000E040104017A6F04017C5153 +:1032B80040D004017C6F020E040104017E6F0401FA +:1032C8007C51FEEC1FF0280E04017C6F020E7D6F0E +:1032D80004010401765104017C270401040177519B +:1032E80004017D237CC47EF47DC47FF499EC13F043 +:1032F80004017C6F000E040104017B6F04017C5102 +:103308000BD00D0E04017C6FF90EE82EFED77C2F32 +:10331800FCD7040104017B2B04010401785104014A +:1033280004017B5DD8A001D001D0EBD704010401D2 +:103338007A2B040104017951040104017A5DD8A0B3 +:1033480001D001D0B6D7EAEC1FF012000401040145 +:103358007529D8B47629D8A401D001D006D00401A3 +:10336800040175690401766946D0040104017851A5 +:10337800800A0401796F0401755104010401775D25 +:10338800040104017651800A04017959D8A001D0BA +:1033980001D012D004010401755104010401775DC4 +:1033A80004010401756F040104017651040104014C +:1033B80078590401766F1FD0000E0401796F020E50 +:1033C8007A6F0401040175510401795F0401040155 +:1033D800765104017A5B04010401775104017925CF +:1033E80004010401756F04010401785104017A2174 +:1033F8000401766F00D012003ED076C4E9FF77C48E +:10340800EAFFEF50D8B401D001D014D0040178C439 +:10341800F6FF040179C4F7FF0800F5CF7CF476C401 +:10342800E9FF77C4EAFFEF5004017C19D8B401D052 +:1034380001D019D076C4E9FF77C4EAFFEF50040140 +:103448007C6F040178C4F6FF040179C4F7FF080013 +:10345800F55004017C5D04010401766F0401776B6B +:10346800D8A077071DD004010401764B772B0401FF +:103478000401784B792B040104017A07D8A07B0753 +:1034880004017A29D8B47B29D8A401D001D0B5D7B2 +:10349800000E04010401766F000E0401776F00D05E +:1034A8001200800E040104018F6F000E0401906F5A +:1034B8000401040190518F11D8A401D001D001D08A +:1034C80040D00401000E04018ABF010E040104016A +:1034D8008D6F04018E6B040104018B5104010401FA +:1034E8008F150009D8B401D001D00CD00401040113 +:1034F8008E518D11000ED8B4010E040104018D6F98 +:1035080004018E6B0401D8908A37040104018E519E +:103518008D11D8B401D001D006D0040104018C511A +:10352800040104018A1B0401D890040190330401AA +:103538008F330401040190518F11D8A401D001D018 +:10354800C0D7040104018A5100D01200FACFBDF49B +:10355800FBCFBEF4E9CFBFF4EACFC0F4E1CFC1F4AA +:10356800E2CFC2F4D9CFC3F4DACFC4F4F3CFC5F4B1 +:10357800F4CFC6F4F6CFC7F4F7CFC8F4F8CFC9F440 +:103588009EAA01D001D002D0A2EC1DF09EA801D0C5 +:1035980001D002D03AEC1EF09EA201D001D003D097 +:1035A80016EC17F09E92C9C4F8FFC8C4F7FFC7C449 +:1035B800F6FFC6C4F4FFC5C4F3FFC4C4DAFFC3C42E +:1035C800D9FFC2C4E2FFC1C4E1FFC0C4EAFFBFC45F +:1035D800E9FFBEC4FBFFBDC4FAFFBCC4E0FFBBC427 +:1035E800E8FFBAC4D8FF100004010401B551B411B2 +:1035F800D8B401D001D03ED00401B76F010E040148 +:103608000401B66F0401B75109D00401D890040130 +:10361800B4370401B53704010401B62B04010401D1 +:10362800B5AF01D001D0F1D704010401B4510401B0 +:103638000401B25D04010401B55104010401B35948 +:10364800D8A001D001D00CD004010401B451040168 +:103658000401B25F04010401B55104010401B35B24 +:103668000401D8900401B5330401B4330401040102 +:10367800B62FDAD7B2C4B2F4B3C4B3F400D0120090 +:103688008FC496F490C497F48DC494F48EC495F4C2 +:10369800E2EC17F004010401926F1D0E040104010D +:1036A800926501D001D009D0290E0401040192616C +:1036B80001D001D002D0000E2DD08FC496F490C452 +:1036C80097F48DC494F48EC495F4E2EC17F00401D9 +:1036D8000401916F090E04010401926501D001D023 +:1036E80017D0150E04010401926101D001D010D049 +:1036F800090E04010401916501D001D009D0150E0D +:1037080004010401916101D001D002D0010E02D060 +:10371800020E00D012007AC47EF479C47DF476ECEF +:1037280014F0040104017B6F040104017B51FE0ABB +:10373800D8A401D001D008D0FE0E04010401796F8D +:10374800FF0E04017A6F31D0040104017B29D8A44B +:1037580001D001D006D004010401796904017A6915 +:1037680024D0D8900832040104017B51D8B401D088 +:1037780001D001D0088E0F2A032A080E036001D059 +:1037880001D006D004010401796904017A690DD0D9 +:1037980004017C6F000E036E04017C51040108C013 +:1037A80079F4040104017A6B00D012000600EACF14 +:1037B800CFF4E1CFD0F4E2CFD1F4D9CFD2F4DACF3D +:1037C800D3F4F3CFD4F4F4CFD5F4F6CFD6F4F7CFBF +:1037D800D7F4F8CFD8F4F2A401D001D00BD0000E62 +:1037E80081B8010E04010401D96FA7EC16F0000E90 +:1037F800D66EF294A1A201D001D006D0B368C90E4A +:10380800B26E71EC1FF0A192D8C4F8FFD7C4F7FFCD +:10381800D6C4F6FFD5C4F4FFD4C4F3FFD3C4DAFF8B +:10382800D2C4D9FFD1C4E2FFD0C4E1FFCFC4EAFFBC +:10383800CEC4E9FFCDC4FBFFCCC4FAFF11000D0EC6 +:10384800040104017F6501D001D020D0160E0401C7 +:1038580004017F6101D001D019D00401040143A102 +:1038680001D001D002D0FE0E31D0020E04010401B5 +:10387800432504010401436F000E0401040144219F +:103888000401446F040104017E5120D0050E040197 +:1038980004017F6501D001D017D00C0E040104018A +:1038A8007F6101D001D010D004010401434B442BA7 +:1038B8000401040143B101D001D004D00401040182 +:1038C8007E5104D0FF0E02D0FE0E00D012000F0E63 +:1038D800040104018C6501D001D017D00A0E04013F +:1038E80004018D6101D001D010D00A0E0401040139 +:1038F8008E6101D001D009D00A0E040104018F6144 +:1039080001D001D002D0000E20D00A0E040104011B +:103918008C6101D001D017D00A0E040104018D6119 +:1039280001D001D010D00F0E040104018E6501D022 +:1039380001D009D00A0E040104018F6101D001D021 +:1039480002D0010E02D0020E00D012000F0E0401A8 +:103958000401876501D001D017D00A0E04010401C3 +:10396800886101D001D010D00F0E040104018965CF +:1039780001D001D009D00A0E040104018A6101D0E6 +:1039880001D002D0000E20D00A0E04010401876184 +:1039980001D001D017D00F0E04010401886501D0B1 +:1039A80001D010D00F0E04010401896501D001D0A7 +:1039B80009D00A0E040104018A6101D001D002D0A5 +:1039C800010E02D0020E00D012000D0E04010401F7 +:1039D800876101D001D017D00D0E04010401886160 +:1039E80001D001D010D00D0E04010401896101D06D +:1039F80001D009D0100E040104018A6501D001D05C +:103A080002D0010E20D00D0E04010401876101D0FF +:103A180001D017D0100E04010401886501D001D02F +:103A280010D00D0E04010401896101D001D009D024 +:103A38000D0E040104018A6101D001D002D0000EEC +:103A480002D0020E00D012008CC496F48DC497F4F4 +:103A58008AC494F48BC495F4E2EC17F004010401D1 +:103A68008E6F8CC496F48DC497F48AC494F48BC476 +:103A780095F4E2EC17F0040104018F6F0D0E0401B8 +:103A880004018E6501D001D009D00D0E0401040196 +:103A98008F6501D001D002D0000E12D00B0E0401A8 +:103AA80004018E6101D001D009D00D0E040104017A +:103AB8008F6501D001D002D0010E02D0020E00D0D5 +:103AC800120004018F6F000E156E04018F51000E55 +:103AD800246E000E256E000E266E000E276E000E58 +:103AE8001A6E000E1B6E000E1C6E000E1D6E010E6F +:103AF800040104015C6F000E04015D6F000E0401F7 +:103B08005E6F000E04015F6F04018F6F000E126E6E +:103B180004018F51000E04010401466F000E0401D8 +:103B2800476F04018F6F000E046E04018F5104016A +:103B38008F6F000E136E04018F511200AECFCAF4BE +:103B4800ABA201D001D002D0AB98AB8800A201D0C3 +:103B580001D001D029D004010401CA512B0AD8A4EC +:103B680001D001D00BD0CD900082280E0124E96E3F +:103B7800EA6A020EEA22000EEF6E16D0280E012421 +:103B8800E96EEA6A020EEA220401CAC4EFFF012ABA +:103B9800000ECF6E000ECE6ECD809E900401CB6FCE +:103BA800000E106E0401CB5112009EA001D001D06E +:103BB8000CD01E0E106401D001D005D0CD90000E9F +:103BC800016E009201D0102A9E9000B201D001D05F +:103BD80001D01CD055EC11F0000E04010401776FE0 +:103BE800020E0401786F000E04010401756F000EC7 +:103BF8000401766F280E04010401736F020E04019C +:103C0800746F15EC1FF0000E016E009212009DC437 +:103C1800E9FF9EC4EAFFD890EF369DC4E9FF9EC431 +:103C2800EAFFEF50D8A401D001D01FD09DC4E9FF0E +:103C38009EC4EAFF010EEF6E9BC4E9FF9CC4EAFF35 +:103C4800EE50ED10D8A401D001D008D09BC4E9FFF4 +:103C58009CC4EAFF000EEE6E020EED6E9BC4E9FFF7 +:103C68009CC4EAFFEE06000EED5A12006FC4CAF4B7 +:103C780004010401CA29D8A401D001D009D0040143 +:103C8800CB6F000E04010401CA6F0401CB5103D0AD +:103C980004010401CA2B0E5004010401CA6301D0B7 +:103CA80001D002D09D980ED00501000E0401040138 +:103CB800CA25E96EEA6A0501050EEA22EF50AD6EE3 +:103CC800CAC46FF41200280E040104019B25E96E92 +:103CD800000E040104019C21EA6EEF500401040166 +:103CE8009E6F040104019E5104019DC49FF40401C8 +:103CF800A06B9FBFA00704019F17000EA017040127 +:103D0800A0519F11D8B401D001D002D0D88002D0E0 +:103D1800D89000D012000D0E04010401946101D066 +:103D280001D009D00D0E04010401956101D001D024 +:103D380002D0000E12D0180E04010401946501D0BF +:103D480001D009D00D0E04010401956101D001D004 +:103D580002D0010E02D0020E00D01200F5EC1EF0C7 +:103D6800EFEC1FF0A0EC18F0BAEC1FF0E1EC1FF03C +:103D78008DEC1FF00C0E04010401A36F000E04016A +:103D8800A46F7C0E04010401A16F790E0401A26FD7 +:103D9800F0EC06F05AEC0AF0D9EC1DF0FBD714EF62 +:103DA80000F00401796F000E0B6E040179510401D3 +:103DB800796F000E166E04017951000E040104019A +:103DC800436F000E0401446F0401796F000E056E05 +:103DD800040179510401796F000E146E04017951C0 +:103DE8001200000EC26E0401706F0F0EC16E040146 +:103DF8007051070EB46E000E806E000E926E000EAB +:103E0800946E000E956E000E826E000E836E000E8C +:103E1800936E000E816E89989298949294949296DB +:103E2800120073C479F474C47AF40BD079C4E9FF2E +:103E38007AC4EAFF040175C4EFFF04010401794B59 +:103E48007A2B040104017707D8A0780704017729A1 +:103E5800D8B47829D8A401D001D0E8D700D012006E +:103E680000D00E50040104016F19D8B401D001D05C +:103E7800F8D70501000E0E24E96EEA6A0501050E61 +:103E8800EA220401B2C4EFFF0E28D8A401D001D061 +:103E980003D0000E0E6E01D00E2A9D881200040178 +:103EA800796F000E036E040179510401796F000ED9 +:103EB800026E040179510401796F000E0F6E04013E +:103EC80079510401796F000E0C6E040179510401D7 +:103ED80004016A6904016B691200116601D001D0FE +:103EE80011D000840D6601D001D001D011D00DC0D1 +:103EF80011F0000E0D6E00B601D001D002D0897805 +:103F080001D000961150D8B401D001D001D01106CB +:103F18001200CA82CA9CCA8ACA98CA96000EBD6E86 +:103F2800000EBA6EBA86BA84BD86BD84BD9ABD98A5 +:103F3800BA9ABA98000EBE6E000EBB6E9E92CB68FF +:103F48009F929D82CA84120096C4A5F497C4A6F4D1 +:103F580094C4A3F495C4A4F4B40E04010401A16F9D +:103F6800790E0401A26FF0EC06F01200D594D592F8 +:103F7800D590D596D59AD58CF294F28A9296938854 +:103F8800F184D58E01EC20F01200200E040104010A +:103F9800A16F790E0401A26FF0EC06F094C495F4B9 +:103FA800FBEC1FF01200F40E04010401A16F790E5E +:103FB8000401A26FF0EC06F012009294929889988E +:103FC800B19AB198A082A282B190120001EC20F0BF +:103FD800D58EB1901200D08EF28EF28CF28E120035 +:103FE800D59EF8EC1FF0120089848996120095C4BA +:103FF80062F412007EC465F4120089948986120066 +:1078FA0001000A006400E8031027010010000001DB +:10790A000010556E6B6E6F776E20636F6D6D616ED2 +:10791A006420282575290D0A003031323334353672 +:10792A003738394142434445460073656C666C6595 +:10793A0061726E696E6776320065766572666C6F23 +:10794A0075726973680073656C666C6561726E69DD +:10795A006E6700636F64657377697463680066694C +:10796A006E656F6666736574006D616E646F6C79BF +:10797A006E000D0A2B5625750D0A0070726F746F12 +:10798A00636F6C0025733A307825583B0061726347 +:10799A007465636800286E756C6C29006F72656780 +:1079AA006F6E0073656E736F720025733A25733BB1 +:1079BA000025733A3078006D6F64656C00686173F6 +:1079CA00746100636C617373002B4E0D0A002558B5 +:1079DA0025580064617461002B530D0A002B540D65 :1079EA000A0025733A00783130002B57002B5200D9 -:0679FA0056004E000000E3 +:0679FA004E0056000000E3 :020000040030CA :04000000FF36FFFECA :02000600BFFF3A diff --git a/telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex b/telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex index 81fc3c2e..b23930dd 100644 --- a/telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex +++ b/telldus-gui/Plugins/Controllers/firmware/TellStickNet.hex @@ -1,4476 +1,5555 @@ :0400000014EF00F009 -:10000800FACFE3F7FBCFE4F7E9CFE5F7D7EF16F040 -:10001800D8CFCBF7E8CFCCF7E0CFCDF78FEF16F0FE -:1000280006EEB5F0000EF66E000EF76E010EF86ED5 -:1000380010EE31F042EC00F0F86A00EE00F010EE3D -:10004800FFF03BEC00F001EE00F012EEFFF03BECAD -:1000580000F004EE00F010EEFFF03BEC00F005EECF -:1000680000F011EEB5F03BEC00F0F8EF04F0EE6AAA -:10007800E550E150FCE1E250FAE112000900F5CF49 -:10008800EEFFE550E150FAE1E250F8E11200070115 -:10009800BB6F140E326E0701BB510701BB6F450ED3 -:1000A80007010701A76F0701BB510701BB6F000ECE -:1000B80007010701A86F0701BB51140E07010701CB -:1000C800A52507010701A96F000E07010701A62151 -:1000D8000701AA6F154A162A15C0ABF716C0ACF768 -:1000E800000E07010701AD6F000E0701AE6F070193 -:1000F800BB6F640E07010701AF6F0701BB51A4C7AF -:10010800B0F7000E07010701B16F000E0701B26FCB -:100118003CC6B3F73DC6B4F73EC6B5F73FC6B6F71B -:10012800A2C7E9FFA3C7EAFF0701EECFB7F70701A8 -:10013800EECFB8F70701EECFB9F70701EECFBAF760 -:100148000701A70E07010701BC6F0701070E07018A -:10015800BD6F52EC0FF0140E07010701BE6F000EC1 -:100168000701BF6F0701A70E07010701BC6F070151 -:10017800070E0701BD6F38EC06F0BCC7B1F7BDC765 -:10018800B2F7140E07010701A52507010701BF6F84 -:10019800000E07010701A6210701C06F0701BB6F09 -:1001A800000E07010701BE6F0701BB51040E0701CE -:1001B8000701A22507010701BC6F000E070107010F -:1001C800A3210701BD6FA9EC12F0140E0701070166 -:1001D800C46F000E0701C56F0701A70E07010701CD -:1001E800C26F0701070E0701C36FB8EC1FF000D0FC -:1001F8001200040E07010701C66F000E0701C76F42 -:100208000701210E07010701C46F0701070E070147 -:10021800C56FA4EC19F0070107012151080A221142 -:10022800D8A401D001D090D01FC73FF720C740F70E -:10023800140E070107013D6F000E07013E6F46ECE3 -:1002480016F007013E513D11D8B401D001D001D0BC -:100258007BD00701256F000E07010701216F0701F9 -:100268002551080E070107012327080E070107017A -:10027800236101D001D00CD007010701242B07010D -:100288000701246701D001D003D007010701232B00 -:1002980000D01CEC1EF00009D8B401D001D0F9D769 -:1002A800DD0E07010701AE6F0A0E0701AF6F86EC7E -:1002B80022F01FC7A5F720C7A6F70701256F010E73 -:1002C80007010701A46F070125511DC7A2F71EC723 -:1002D800A3F74BEC00F0040E07010701C46F000EF2 -:1002E8000701C56F0701210E07010701C26F07014A -:1002F800070E0701C36FB8EC1FF0FC0E07010701DA -:100308001F2507010701B26FFF0E07010701202112 -:100318000701B36FFF0E07010701B06FFF0E07015A -:10032800B16FFF0E07010701AE6FFF0E0701AF6F38 -:10033800F8ECD1F000D07CEC22F00009D8B401D060 -:1003480001D0F9D780EC1FF0120007010F6F000EE3 -:10035800070107010E6F07010F5197D00701070129 -:100368000D513A0AD8A401D001D016D000010001DD -:10037800F051EF11D8A401D001D007D007010F6FB9 -:10038800020E266E07010F5106D007010F6F010EEE -:10039800266E07010F5184D000010001EF3B0001D8 -:1003A800F03BF00E0001F0170001EF510F0B0001B8 -:1003B800F013F00E0001EF170DC73FF7FDEC12F038 -:1003C80007010F6F07010F5100010001EF1368D0FB -:1003D80003D0070107010E2B06016F0E0701070165 -:1003E8000E25E96EEA6A0601060EEA22EF50D8A445 -:1003F80001D001D0EED706016F0E070107010E25C7 -:10040800E96EEA6A0601060EEA2207010DC7EFFF48 -:1004180000010001EF07D8A0F00700010001F0512A -:10042800EF11D8A401D001D0B6D7262A39D00701B8 -:1004380007010D51690AD8B401D001D002D026684D -:10044800AAD7262A2DD0070107010D51730AD8A46F -:1004580001D001D007D007010F6F000E266E0701EB -:100468000F511ED00D3A0E3AF00E0E160D500F0B0E -:100478000E12F00E0D160DC73FF7FDEC12F0070136 -:100488000F6F07010F510D120BD02650000A01E122 -:1004980065D7010A9DE0030ACAE0010AD4E000D04A -:1004A800120000D01CEC1EF00009D8B401D001D015 -:1004B800F9D7CF0E07010701AE6F0A0E0701AF6F1C -:1004C80086EC22F078C7E9FF79C7EAFF010EEE6EE5 -:1004D800000EED6E020E070107017825E96E000E89 -:1004E800070107017921EA6E000EEE6E080EED6E27 -:1004F800040E070107017825E96E000E07010701C0 -:100508007921EA6E060EEF6E050E070107017825C0 -:10051800E96E000E070107017921EA6E040EEF6EFD -:10052800060E07010701B26F000E0701B36F690ECF -:1005380007017A6F060E7B6F7AC7B0F77BC7B1F7F2 -:10054800080E07010701782507010701AE6F000EA5 -:100558000701070179210701AF6F18EC1AF00E0E99 -:10056800070107017825E96E000E070107017921C7 -:10057800EA6E06013CC6EEFF06013DC6EEFF060127 -:100588003EC6EEFF06013FC6EEFF78C77CF779C787 -:100598007DF79FEC11F01C0E07010701BF6F000EDD -:1005A8000701C06F07017A6F060E07010701BE6FCA -:1005B80007017A51120E0701070178250701070183 -:1005C800BC6F000E0701070179210701BD6FA9EC77 -:1005D80012F01C0E07010701C46F000E0701C56F5A -:1005E80078C7C2F779C7C3F7B8EC1FF080EC1FF0E3 -:1005F800010E00D0120021C733F722C734F7F1ECFF -:1006080013F00701276F690E07010701486F0701FB -:100618002751D0EC1DF00701070124512311D8A45C -:1006280001D001D00BD00701276F300E0701070159 -:10063800486F07012751D0EC1DF07CD00701276FC8 -:10064800000E07010701266F07012751070107015F -:10065800255107010701265DD8A001D001D001D09E -:1006680021D0070107012651070107012325E96E5B -:100678000701000E070107012421EA6EEF50300A36 -:10068800D8B401D001D001D00DD007010701262B25 -:1006980007010701255107010701265DD8A001D0F0 -:1006A80001D0DFD707010701255107010701265DA2 -:1006B800D8A001D001D001D03DD0070107012651B3 -:1006C800070107012325E96E0701000E070107014D -:1006D8002421EA6EEF50070107013C6F59EC1DF029 -:1006E80007010701486FD0EC1DF0070107012651EB -:1006F800070107012325E96E0701000E070107011D -:100708002421EA6EEF5007010701486F31EC1DF014 -:1007180007010701486FD0EC1DF007010701262BE0 -:1007280007010701255107010701265DD8A001D05F -:1007380001D0C3D70701276F730E07010701486F60 -:1007480007012751D0EC1DF012000E010E01D967E8 -:1007580001D001D002D0000EA1D0346601D001D062 -:1007680004D026EC1BF0000E99D0FBC0FDF3FCC0B2 -:10077800FEF3FDC3E0FEFEC3E1FE140E0701070110 -:10078800C66F000E0701C76F0701210E0701070199 -:10079800C46F0701070E0701C56FA4EC19F033C732 -:1007A800BEF734C7BFF7B8EC21F0BEC733F7BFC7F1 -:1007B80034F7CE0E07010701215D0A0E0701225901 -:1007C800D8B001D001D023D00701070121B101D051 -:1007D80001D01DD00701070126BF01D001D017D0D5 -:1007E8000701070125B901D001D011D0EF0E07018B -:1007F8000701235D050E07012459D8B001D001D0A7 -:1008080006D00701070125BF01D001D001D0FF00A4 -:1008180021C7FBF022C7FCF0060E07010701B26FE3 -:10082800000E0701B36F2D0E0701356F070E366FE7 -:1008380035C7B0F736C7B1F71DC7AEF71EC7AFF754 -:1008480018EC1AF01FC7E9FF20C7EAFFFF0EEF6E8A -:10085800070107013451080AD8A401D001D016D0E5 -:10086800070107013351D8B401D001D008D00701DE -:1008780007013351060AD8A401D001D007D01FC7F9 -:10088800E9FF20C7EAFF070133C7EFFF0701356F0C -:10089800000E346E07013551010E00D012004CC70E -:1008A800E9FF4DC7EAFFEECF50F7EECF51F7EECF95 -:1008B80052F7EECF53F700010001E8510701531931 -:1008C80011E100010001E751070152190BE1000194 -:1008D8000001E6510701511905E100010001E55148 -:1008E80007015019D8B401D001D06CD00001000123 -:1008F800E85106010601471914E100010001E7511A -:100908000601060146190DE100010001E651060144 -:100918000601451906E100010001E551060106013D -:100928004419D8A401D001D05CD04CC7E9FF4DC709 -:10093800EAFFEECF50F7EECF51F7EECF52F7EECFFA -:1009480053F7060106013C51070150190701546F7E -:10095800060106013D51070151190701556F0601AE -:1009680006013E51070152190701566F060106019B -:100978003F51070153190701576F060106014051FE -:10098800070154150701586F060106014151070177 -:1009980055150701596F0601060142510701561501 -:1009A80007015A6F06010601435107015715070150 -:1009B8005B6F07015B51581159115A11D8B401D016 -:1009C80001D00FD000EEE9F007014EC7E1FF0701A3 -:1009D8004FC7E2FF060EEECFE6FFE82EFCD7010E6A -:1009E80002D0000E00D01200000E07010701006FB0 -:1009F800000E0701016F000E0701026F000E0701CC -:100A0800036F000E0E010E01B66F000E0E010E01EF -:100A1800B76F000E926E000E936E000E946E000E6D -:100A2800956E000E966E000E976E000E986E000E74 -:100A3800806E000E816E000E826E000E836E000EB8 -:100A4800846E000E856E0701046F400E9B6E0701D1 -:100A580004510701046F0F0EC16E07010451AEEC7B -:100A680022F0E5EC21F040EC1EF0D6EC22F0A5ECEB -:100A7800E4F0F0EC22F0D7EC21F08DEC1BF0420E04 -:100A8800070107010B6F370E07010C6F0701046F91 -:100A9800140E070107010A6F0701045127EC1FF024 -:100AA8005CECBCF0DEEC22F019EC22F00701070147 -:100AB800005107010701A35D0701046F0701070142 -:100AC800015107010701A4590701056F0701070133 -:100AD800025107010701A5590701066F0701070120 -:100AE800035107010701A6590701076FF20E045DBC -:100AF8009E0E0559000E0659000E07010759D8A089 -:100B080001D001D00AD019EC22F0A3C700F7A4C77E -:100B180001F7A5C702F7A6C703F7CFECCAF0B7ECF1 -:100B280022F00400BDD714EF00F00701386F000E63 -:100B380007010701366F070138510701386F000EAA -:100B480007010701376F0701385121D00401000E52 -:100B58002524E96EEA6A0401040EEA22EF5007012F -:100B68000701356F252A0701070135513A0AD8A42C -:100B780001D001D001D010D00701373BF00E371754 -:100B880035C73FF7FDEC12F0070107013713C70E11 -:100B9800256401D001D0DAD7070137C738F7070134 -:100BA800396BFF0E07010701342507013A6F07016A -:100BB8003B6BFF0E07013B2307013B51800A0701EE -:100BC8003C6F0701385107013A5D07013951800A26 -:100BD80007013C59D8B001D001D006D00701070160 -:100BE80037512526000E3FD00701386F000E070148 -:100BF8000701366F070138511BD00401000E252468 -:100C0800E96EEA6A0401040EEA2207010701365177 -:100C1800070107013225E16E0701000E07010701F0 -:100C28003321E26EEFCFE7FF252A07010701362BB4 -:100C380007010701375107010701365DD8A001D028 -:100C480001D0DBD70701070137510701070132251A -:100C5800E96E0701000E070107013321EA6E000E55 -:100C6800EF6E010E00D01200D89007010701BF31C6 -:100C780007010701C16F07010701BE310701C06FF6 -:100C8800BCC7C2F7BDC7C3F7000E07010701C46F91 -:100C9800000E0701C56F000E0701C66F000E0701A1 -:100CA800C76F23D00701C2C7E9FF0701C3C7EAFF1F -:100CB8000701020E0701C227000E0701C323EECF6A -:100CC800C8F7EDCFC9F70701C85107010701C427C5 -:100CD8000701C95107010701C523000E07010701D4 -:100CE800C623000E07010701C72307010701C00734 -:100CF800D8A0C1070701C029D8B4C129D8A401D0F8 -:100D080001D0D0D707010701BEA101D001D013D06F -:100D1800C2C7E9FFC3C7EAFFEF500701C86F070161 -:100D2800C85107010701C427000E0701C5230701A1 -:100D3800C6230701C723070107EEC6F0EECFC8F7A1 -:100D4800EDCFC9F707010701C4510701C8270701FB -:100D58000701C5510701C9230701C8C7C4F707011F -:100D6800C9C7C5F707010701C66B0701C76B0701AC -:100D780007EEC6F0EE5007010701C427ED50070142 -:100D88000701C52307010701C41D07010701BC6F3F -:100D980007010701C51D0701BD6F00D012004CC730 -:100DA80050F74DC751F7070150C7F6FF070151C764 -:100DB800F7FF000EF86E08000701F5CF4FF707019F -:100DC8000701504B512B070107014F51D8B401D0EF -:100DD80001D020D0070107014F512E0AD8B401D005 -:100DE80001D018D0070107014F512F0AD8B401D0FC -:100DF80001D010D0070107014F512C0AD8B401D0F7 -:100E080001D008D0070107014F513E0AD8A401D0EC -:100E180001D0C9D7070107014C5107010701505DEF -:100E28000701526F07015205070107014E6F4EC7B0 -:100E380053F763EC1FF0070107014EC755F7070189 -:100E48000701566B4CC753F74DC754F7A8EC17F07A -:100E5800010E070107015327000E0701542307015C -:100E680007015351070107014C2707010701545196 -:100E7800070107014D23070107014F51D8B401D0DD -:100E880001D018D0070107014F512F0AD8B401D05B -:100E980001D010D0070107014F512C0AD8B401D056 -:100EA80001D008D0070107014F513E0AD8A401D04C -:100EB80001D001D001D077D70701526F000E07018A -:100EC8000701536F0701525163EC1FF0120007012D -:100ED8001B6F000E07010701186F07011B5107015F -:100EE800070116AF01D001D00FD007010701156D1A -:100EF8000701161FD8B0162B07011B6F010E07013B -:100F08000701186F07011B510701070114AF01D032 -:100F180001D00BD007010701136D0701141FD8B0CA -:100F2800142B010E07010701181B000E070107010A -:100F3800196F000E07011A6F0701070116511511E5 -:100F4800D8B401D001D047D007011B6F010E0701AB -:100F58000701176F07011B5109D00701D890070136 -:100F680015370701163707010701172B0701070176 -:100F780016AF01D001D0F1D70701D8900701193772 -:100F880007011A3707010701155107010701135D0A -:100F9800070107011651070107011459D8A001D00C -:100FA80001D00FD007010701155107010701135F91 -:100FB80007010701165107010701145B0701070123 -:100FC80019810701D8900701163307011533070166 -:100FD8000701172FD1D7070107011851D8B401D03D -:100FE80001D007D007010701196D07011A1FD8B0F2 -:100FF8001A2B19C713F71AC714F700D01200246662 -:1010080001D001D017D0030E07010701156501D0E3 -:1010180001D007D00C0E07010701156501D001D0DA -:1010280002D0FE0E81D00701166F010E246E070153 -:10103800165178D02404D8A401D001D026D00B0EA4 -:1010480007010701156501D001D007D0160E070169 -:101058000701156501D001D008D00701166F000EF1 -:10106800246E07011651FE0E5FD00090070107019C -:1010780014A101D000800701166F020E246E07012B -:101088001651000E00B0010E4FD02450020AD8A409 -:1010980001D001D047D0070107011451D8B401D0BD -:1010A80001D015D0030E07010701156501D001D045 -:1010B8000ED00D0E07010701156101D001D007D030 -:1010C8000701166F000E246E0701165129D00B0E6A -:1010D80007010701156501D001D00ED0170E0701D1 -:1010E8000701156101D001D007D00701166F010E65 -:1010F800246E0701165114D0030E07010701156568 -:1011080001D001D00DD00D0E07010701156101D0E6 -:1011180001D006D00701166F000E246E0701165184 -:10112800FF0E02D0FF0E00D012004CC750F74DC77B -:1011380051F750C7E9FF51C7EAFFEF500701070110 -:101148004F6F07010701504B512B070107014F5102 -:10115800D8B401D001D020D0070107014F512E0A81 -:10116800D8B401D001D018D0070107014F512F0A78 -:10117800D8B401D001D010D0070107014F512C0A73 -:10118800D8B401D001D008D0070107014F513E0A59 -:10119800D8A401D001D0CDD7070107014C510701D0 -:1011A8000701505D0701526F07015205070107014A -:1011B8004E6F4EC753F763EC1FF0070107014EC788 -:1011C80055F707010701566B4CC753F74DC754F73E -:1011D800EBEC17F0010E070107015327000E07017A -:1011E8005423070107015351070107014C27070141 -:1011F80007015451070107014D23070107014F510A -:10120800D8B401D001D018D0070107014F512F0AD7 -:10121800D8B401D001D010D0070107014F512C0AD2 -:10122800D8B401D001D008D0070107014F513E0AB8 -:10123800D8A401D001D001D001D07BD70701526FCB -:10124800000E07010701536F0701525163EC1FF0AD -:101258001200010E07010701566F000E0701576FB4 -:1012680007010701626907010701636907010701AF -:1012780064690701070165690701070166690701D4 -:10128800070167694CC74EF74DC74FF74CC7E9FFD1 -:101298004DC7EAFFEECF6CF7EECF6DF7EECF6EF7E6 -:1012A800EECF6FF7060106013C5107016C190701E3 -:1012B800706F060106013D5107016D190701716F35 -:1012C800060106013E5107016E190701726F0601FA -:1012D80006013F5107016F190701736F06010601E7 -:1012E8004051070170150701746F0601060141514D -:1012F800070171150701756F0601060142510701C3 -:1013080072150701766F060106014351070173152F -:101318000701776F07017751741175117611D8B4E9 -:1013280001D001D009D00601440E070107014E6F14 -:101338000601060E07014F6F4EC7E9FF4FC7EAFFC8 -:101348000701EECF68F70701EECF69F70701EECF87 -:101358006AF70701EECF6BF70701500E0701070187 -:10136800786F0701070E0701796F55EC02F012003C -:1013780023500E0D0101590EF324070107014E6F8A -:1013880007014F6B0101010E07014F23080E1324BB -:10139800070107014C6F000E142007014D6F0C0E5A -:1013A800070107014E25E96E000E070107014F21CD -:1013B800EA6E0701EECFBEF70701EDCFBFF7B8EC35 -:1013C80021F0BEC750F7BFC751F70A0E0701070142 -:1013D8004E25E96E000E070107014F21EA6E07014D -:1013E800EECFBEF70701EDCFBFF7B8EC21F0BEC7CF -:1013F80052F7BFC753F74CC7BEF74DC7BFF7B8EC96 -:1014080021F0BEC754F7BFC755F7000E0701070103 -:10141800566F000E0701576FDD0E07010701AE6F0B -:101428000A0E0701AF6F86EC22F04CC7A5F74DC72F -:10143800A6F70701586F110E07010701A46F0701EE -:1014480058514EC7A2F74FC7A3F74BEC00F0080E50 -:1014580007010701C46F000E0701C56F0701500E91 -:1014680007010701C26F0701070E0701C36FB8EC38 -:101478001FF080EC1FF0000E136E000E146E0601B4 -:101488000601E069120041C760F784EC0EF0F5C36D -:1014980043F7070107014351070AD8B401D001D027 -:1014A80010D00701070143510B0AD8B401D001D06D -:1014B80008D0000E07010701416F000E0701426FB7 -:1014C80068D0030103EEE7F0030113EEE5F0E652FE -:1014D800EE52ED50E55C02E1EF50E75CD8A001D098 -:1014E80001D03AD0030103EEE5F0EECF44F7EDCF9B -:1014F80045F703010301E7510701445F03010301B5 -:10150800E8510701455B030103EEE1F0EECF46F732 -:10151800EDCF47F703010301DF510701465F0301E0 -:101528000301E0510701475BFF0E0701462507014C -:10153800486FFF0E070147210701496F0701445112 -:101548000701485D07010701416F07014551070180 -:1015580049590701426F1DD0030103EEE7F0EECFB2 -:1015680044F7EDCF45F703010301E5510701445F57 -:1015780003010301E6510701455BFF0E07014425FE -:1015880007010701416FFF0E070145210701426F5F -:1015980000D012007BD046C7B2F747C7B3F744C79D -:1015A800B0F745C7B1F741C7AEF742C7AFF718EC78 -:1015B8001AF075D0070107014129D8B44229D8B4D7 -:1015C80001D001D006D041C7AEF742C7AFF786ECCD -:1015D80022F0100E07010701486F000E0701496F3E -:1015E8004CD007010701485107010701465D070173 -:1015F80007014951070107014759D8B001D001D067 -:1016080004D046C748F747C749F748C7B2F749C79C -:10161800B3F744C7B0F745C7B1F707014A0E07014A -:101628000701AE6F0701070E0701AF6F18EC1AF03C -:1016380048C7C4F749C7C5F707014A0E070107019C -:10164800C26F0701070E0701C36FB8EC1FF007014F -:1016580007014851070107014427000E0701070148 -:10166800452307010701485107010701465F0701A4 -:101678000701495107010701475B07010701475166 -:101688004611D8A401D001D0ACD709D00701070171 -:101698004351000A8FE0010A01E17DD700D0120012 -:1016A8002FC7E9FF30C7EAFF010EEE6E230EEE6E7C -:1016B800450EEE6E670EED6EED52ED52040E07010B -:1016C80007012F25E96E000E070107013021EA6E98 -:1016D800890EEE6EAB0EEE6ECD0EEE6EEF0EED6E6B -:1016E800ED52ED52080E070107012F25E96E000E95 -:1016F800070107013021EA6EFE0EEE6EDC0EEE6E7B -:10170800BA0EEE6E980EED6EED52ED520C0E07010C -:1017180007012F25E96E000E070107013021EA6E47 -:10172800760EEE6E540EEE6E320EEE6E100EED6EFE -:10173800ED52ED52100E070107012F25E96E000E3C -:10174800070107013021EA6EF00EEE6EE10EEE6E33 -:10175800D20EEE6EC30EED6EED52ED52140E070171 -:1017680007012F25E96E000E070107013021EA6EF7 -:10177800000EEE6E000EEE6E000EEE6E000EED6EBA -:10178800ED52ED52580E070107012F25E96E000EA4 -:10179800070107013021EA6E010EEF6E1200D9CE63 -:1017A800A6F7EECEA4F7EFCEA5F707010701A651DD -:1017B8000E010E01D96301D001D0F1D7ECCEA6F706 -:1017C800EDCEA7F707010701A45107010701A65DA0 -:1017D80007010701A55107010701A759D8B001D092 -:1017E80001D01ED00701A4C7A8F70701A5C7A9F70C -:1017F80007010701A6510701A85F07010701A751C3 -:101808000701A95B0701A851CD0807010701A26FCD -:101818000701A951D8A0E82A0A080701A36F35D003 -:1018280007010701A75107010701A51906E10701EB -:101838000701A65107010701A419D8A401D001D0B6 -:1018480008D0CD0E07010701A26F0A0E0701A36F8A -:101858001CD00701A6C7A8F70701A7C7A9F7070162 -:101868000701A4510701A85F07010701A551070156 -:10187800A95BFF0E0701A82507010701A26FFF0E4C -:101888000701A9210701A36F00D012006DD029D04C -:10189800ACC7B2F7ADC7B3F7A9C7B0F7AAC7B1F7D6 -:1018A800A6C7AEF7A7C7AFF718EC1AF022D0070102 -:1018B8000701A629D8B4A729D8B401D001D006D0E9 -:1018C800A6C7AEF7A7C7AFF786EC22F0ACC7C4F738 -:1018D800ADC7C5F7A9C7C2F7AAC7C3F7B8EC1FF0C9 -:1018E80008D007010701A851000AE1E0010AD0E089 -:1018F80000D042D031D007010701A929D8B4AA29BC -:10190800D8B401D001D006D0A9C7AEF7AAC7AFF79F -:1019180090EC22F0ACC7C6F7ADC7C7F7A6C7C4F7A7 -:10192800A7C7C5F7A4EC19F0E4D7ACC7B2F7ADC7A1 -:10193800B3F7A9C7B0F7AAC7B1F7A6C7AEF7A7C745 -:10194800AFF7F8ECD1F000D07CEC22F00009D8B465 -:1019580001D001D0F9D7CDD707010701A851000A56 -:10196800E4E0010AC8E0C5D707010701AB51000A46 -:10197800C1E0010A8CE000D012000DC713F77FEC1C -:1019880010F013C710F714C711F707010701115119 -:101998001011D8A401D001D002D0000E63D00DC719 -:1019A80060F784EC0EF0070107010F510E11D8B44F -:1019B80001D001D01BD0010E07010701AC6F000E4A -:1019C8000701AD6FFAC3ABF7EBC3A9F7ECC3AAF7EE -:1019D8000701126F010E07010701A86F07011251D5 -:1019E8000EC7A6F70FC7A7F74AEC0CF0030103EEE2 -:1019F800EBF0EE2A000EED22030113EEE3F0E652BF -:101A0800EE52ED50E55C02E1EF50E75CD8B001D052 -:101A180001D004D0E1C3EBF3E2C3ECF30701070103 -:101A280010051111D8A401D001D003D00301F78506 -:101A380017D003010301F6BB01D001D011D0030177 -:101A4800F68B55EC20F01F0E0701070170250301E6 -:101A58000301F16F000E0701070171210301F26F05 -:101A6800010E00D0120001D000D007010701345147 -:101A78000701376F0701070135510701386F070163 -:101A8800344B352B37C7F6FF38C7F7FF000EF86E13 -:101A98000E0EF76403D00800F55005D0F6CFE9FF25 -:101AA800F7CFEAFFEF500701396F070132C7F6FF9A -:101AB800070133C7F7FF000EF86E0E0EF76403D068 -:101AC8000800F55005D0F6CFE9FFF7CFEAFFEF5051 -:101AD80007013A6F0701395107013A5D070107010C -:101AE800366F0701366701D001D023D007010701FF -:101AF80032510701376F0701070133510701386F6A -:101B08000701324B332B37C7F6FF38C7F7FF000EF4 -:101B1800F86E0E0EF76403D00800F55005D0F6CF26 -:101B2800E9FFF7CFEAFFEF500009D8A401D001D0B0 -:101B38009BD707010701365107010701326F0701DB -:101B4800336B070132BF330700D01200000E0701C4 -:101B580007013A6F000E07013B6F000E07013C6F4B -:101B6800000E07013D6F3FEC21F00009D8A401D019 -:101B780001D00ED0000E07010701326F000E0701D9 -:101B8800336F000E0701346F000E0701356F4AD01E -:101B9800252A3AD00401000E2524E96EEA6A0401D8 -:101BA800040EEA22EF5007013E6F07013E5107017C -:101BB8000701366F0701376B0701386B0701396B6F -:101BC800252A07013651730A371138113911D8A45B -:101BD80001D001D001D01DD00701040ED890070113 -:101BE8003A3707013B3707013C3707013D37E82EF5 -:101BF800F5D736C73FF7FDEC12F007013E6F070136 -:101C08003E51070107013A13C70E256401D001D0E0 -:101C1800C1D73AC732F73BC733F73CC734F73DC79C -:101C280035F700D0120077ECE7F0D8C4F8F3D9C440 -:101C3800F9F3DFC3E5F3E0C3E6F3DFC3E7F3E0C39B -:101C4800E8F3E1C3E9F3E2C3EAF3E1C3EBF3E2C388 -:101C5800ECF30701716F0D0E07010701706F0701A3 -:101C6800715103010301F6A701D001D008D0070183 -:101C7800716F040E07010701706F0701715170C77A -:101C8800F5F30301F6910301F6930301F6950B00B2 -:101C98000E000301F6990301F69B0301F69D03016B -:101CA800F69F0301F7910301F7930301F7950301E9 -:101CB800F7970301F7890401EA910401EA93040103 -:101CC800EA970401EA99DFC3D4F4E0C3D5F41FEC22 -:101CD80015F072C7CCF473C7CDF41FEC15F072C7BA -:101CE800CEF473C7CFF404010401E8690401E9697B -:101CF800010E04010401DA6F000E0401DB6F12000B -:101D080007010701605106010601E46301D001D013 -:101D180001D05CD006010601E451FE0AD8B401D016 -:101D280001D022D01C0E07010701B26F000E070177 -:101D3800B36F0301DF0E07010701B06F0301030E44 -:101D48000701B16F06010601E4511C0D00016F0E79 -:101D5800F32407010701AE6F0701AF6B0001000E06 -:101D68000701AF2318EC1AF060C7E4F60701070172 -:101D78006051FE0AD8A401D001D001D027D01C0E92 -:101D880007010701B26F000E0701B36F07010701D2 -:101D980060511C0D6F0E0701616F000E626FF350EA -:101DA80007016127E86AF3BEE8680701622361C793 -:101DB800B0F762C7B1F70301DF0E07010701AE6F85 -:101DC8000301030E0701AF6F18EC1AF0120021C0CF -:101DD80025F05CD00701316F040E07010701346F4D -:101DE8000701315107012D0E07010701326F070165 -:101DF800070E0701336F99EC05F00009D8A401D04C -:101E080001D002D0000E49D007012D0E07010701AD -:101E1800346F0701070E0701356F2BC732F72CC740 -:101E280033F737EC0DF0070133513211D8A401D044 -:101E380001D002D0010E31D03FEC21F00009D8B416 -:101E480001D001D003D0AAEC0DF011D00701316FF9 -:101E5800000E07010701346F07013151000E070119 -:101E68000701326F000E0701336F99EC05F004018A -:101E7800000E2524E96EEA6A0401040EEA22730EB4 -:101E8800EF6201D001D002D0000E07D0C70E256442 -:101E980001D001D09FD7000E00D01200020E07011A -:101EA8000701BC25E96E000E07010701BD21EA6E96 -:101EB8000701EECFBEF70701EDCFBFF7B8EC21F071 -:101EC800020E07010701BC25E96E000E0701070194 -:101ED800BD21EA6E0701BEC7EEFF0701BFC7EDFFD0 -:101EE800040E07010701BC25E96E000E0701070172 -:101EF800BD21EA6E0701EECFBEF70701EDCFBFF7B0 -:101F0800B8EC21F0040E07010701BC25E96E000EAC -:101F180007010701BD21EA6E0701BEC7EEFF0701F1 -:101F2800BFC7EDFF0A0E07010701BC25E96E000EC9 -:101F380007010701BD21EA6E0701EECFBEF70701D1 -:101F4800EDCFBFF7B8EC21F00A0E07010701BC2559 -:101F5800E96E000E07010701BD21EA6E0701BEC741 -:101F6800EEFF0701BFC7EDFF12000094000E2A6EB6 -:101F780000922BC7E9FF2CC7EAFFEF502B6EB18008 -:101F880000D000A201D001D0FCD7010E0701070143 -:101F98002D6F000E07012E6F2FD0070107012D515D -:101FA800070107012B25E96E070107012E510701DB -:101FB80007012C21EA6E010EEF6201D001D002D098 -:101FC800008416D00092070107012D51070107016F -:101FD8002B25E96E070107012E51070107012C2166 -:101FE800EA6EEF502B6E00D000A201D001D0FCD7D2 -:101FF800070107012D4B2E2B070107012D51070162 -:1020080007012B25E96E070107012E51070107017A -:102018002C21EA6EEF50D8A401D001D0BED700928F -:1020280000D000A201D001D0FCD7B190899812004D -:1020380000EE8BF017EE0DF0140EEECFE6FFE82E53 -:10204800FCD719EC22F0A3C7B1F6A4C7B2F6A5C70E -:10205800B3F6A6C7B4F60701216F140E07010701EE -:10206800346F0701215107010D0E07010701326F77 -:102078000701070E0701336F99EC05F00009D8A492 -:1020880001D001D001D036D0DA0E07010701346F34 -:10209800FF0E0701356F07010D0E07010701326FAB -:1020A8000701070E0701336F37EC0DF007013351B5 -:1020B8003211D8A401D001D003D03FECD7F01AD008 -:1020C800570E07010701346FFF0E0701356F07012F -:1020D8000D0E07010701326F0701070E0701336F65 -:1020E80037EC0DF0070133513211D8A401D001D0DB -:1020F80001D0FF00120013C760F784EC0EF0030153 -:1021080003EEEBF0030113EEE9F0E652EE52ED5068 -:10211800E55C02E1EF50E75CD8A001D001D012D015 -:1021280003010301EB5103010301E95D0701070105 -:10213800136F03010301EC5103010301EA5907017D -:10214800146F3AD0030103EEE9F0EECF15F7EDCFA7 -:1021580016F703010301E1510701155F03010301AC -:10216800E2510701165B030103EEE3F0EECF17F728 -:10217800EDCF18F703010301EB510701175F0301C6 -:102188000301EC510701185B0701155107011725D9 -:102198000701196F070116510701182107011A6F66 -:1021A800010E0701192507010701136F000E07012A -:1021B8001A210701146F00D012000701316F000EB9 -:1021C80007010701306F070131512DC7E9FF2EC7FD -:1021D800EAFFEF5007010701346F2BC7E9FF2CC74F -:1021E800EAFF0701EECF32F70701EDCF33F709EC2D -:1021F8001DF0D8B001D002D0010E01D0000E0701A9 -:1022080007012F6F07010701302B2DC734F72EC7A1 -:1022180035F72BC732F72CC733F753EC1CF02DC713 -:10222800E9FF2EC7EAFFEF5007010701346F2BC7FC -:10223800E9FF2CC7EAFF0701EECF32F70701EDCF20 -:1022480033F709EC1DF0D8B001D002D0010E01D04F -:10225800000E070107012F19D8B401D001D004D00E -:102268000701070130510AD0070107013029D8A416 -:1022780001D001D002D0000E01D0C4D71200010154 -:10228800000E070107012F6F0101010E0701306FD2 -:1022980054EC0BF00401000E070107013C6F040128 -:1022A800040E07013D6F1FEC17F03CC733F73DC71D -:1022B80034F70401000E07010701316F0401040E11 -:1022C8000701326F0101000E070107012F6F01019D -:1022D800010E0701306F3AECDFF0200E070107010D -:1022E800336F000E0701346F8E0E07010701316F3F -:1022F800FE0E0701326F0101000E070107012F6F63 -:102308000101010E0701306F68ECDEF000019F0E3D -:1023180007010701316F0001000E0701326F01014B -:10232800000E070107012F6F0101010E0701306F31 -:1023380008ECB2F012007CC7E9FF7DC7EAFF07018D -:10234800EECFBEF70701EDCFBFF7B8EC21F07CC7A1 -:10235800E9FF7DC7EAFF0701BEC7EEFF0701BFC758 -:10236800EDFF020E070107017C25E96E000E07014B -:1023780007017D21EA6E0701EECFBEF70701EDCF19 -:10238800BFF7B8EC21F0020E070107017C25E96EC2 -:10239800000E070107017D21EA6E0701BEC7EEFFA7 -:1023A8000701BFC7EDFF060E070107017C25E96E8F -:1023B800000E070107017D21EA6E0701EECFBEF787 -:1023C8000701EDCFBFF7B8EC21F0060E07010701B2 -:1023D8007C25E96E000E070107017D21EA6E0701E1 -:1023E800BEC7EEFF0701BFC7EDFF120042D013C7FB -:1023F800E9FF14C7EAFFEF50D8B401D001D016D0D6 -:10240800070115C7F6FF070116C7F7FF000EF86E9C -:102418000800F5CF19F713C7E9FF14C7EAFFEF5013 -:1024280007011919D8B401D001D01BD013C7E9FF8F -:1024380014C7EAFFEF500701196F070115C7F6FF28 -:10244800070116C7F7FF000EF86E0800F5500701E0 -:10245800195D07010701136F0701146BD8A0140752 -:102468001DD007010701134B142B07010701154B5A -:10247800162B070107011707D8A018070701172906 -:10248800D8B41829D8A401D001D0B1D7000E0701BB -:102498000701136F000E0701146F00D01200070127 -:1024A80007010C29D8B40D29D8A401D001D006D031 -:1024B800070107010C6907010D6946D007010701EB -:1024C8000F51800A0701106F07010C51070107011E -:1024D8000E5D070107010D51800A07011059D8A0A8 -:1024E80001D001D012D0070107010C5107010701E3 -:1024F8000E5D070107010C6F070107010D51070168 -:1025080007010F5907010D6F1FD0000E0701106F4B -:10251800020E116F070107010C510701105F070137 -:1025280007010D510701115B070107010E51070152 -:102538001025070107010C6F070107010F5107015B -:10254800112107010D6F00D01200CF0E0E010E01F0 -:10255800E26F0A0E0E01E36F0701DC0E0701BF27C9 -:102568000A0E0701C023BFC7E6FEC0C7E7FE060E76 -:1025780007010701C46F000E0701C56FBCC7C2F78A -:10258800BDC7C3F7B8EC1FF0060E07010701C46FFB -:10259800000E0701C56F0601690E07010701C26F2A -:1025A8000601060E0701C36FB8EC1FF00701C16FE3 -:1025B800080E07010701C26F0701C151BEEC22F0E6 -:1025C8000701C16F060E07010701C26F0701C1515C -:1025D80007010701BE6701D001D008D00701C16F0C -:1025E800000E07010701C26F0701C151BEEC22F0BE -:1025F800120020D0000E50D0010E4ED0020E4CD04A -:10260800030E4AD0040E48D0050E46D0060E44D01C -:10261800070E42D0080E40D0090E3ED00A0E3CD01C -:102628000B0E3AD00C0E38D00D0E36D00E0E34D01C -:102638000F0E32D0070107013F51300ADBE0010AD3 -:10264800DBE0030ADBE0010ADBE0070ADBE0010A62 -:10265800DBE0030ADBE0010ADBE00F0ADBE0010A4A -:10266800DBE0780ADBE0030ADBE0010ADBE0070ACB -:10267800DBE0010ADBE0030ADBE0270ACFE0030A1C -:10268800CFE0010ACFE0070ACFE0010ACFE0030A52 -:10269800CFE000D0000E00D01200000E07010701A5 -:1026A8007C6F000E07017D6F000E07017E6F000E24 -:1026B80007017F6F0701070174A101D001D018D06D -:1026C800070107017851070107017C270701070166 -:1026D8007951070107017D23070107017A51070195 -:1026E80007017E23070107017B51070107017F23AB -:1026F8000701D890070178370701793707017A373A -:1027080007017B370701D890070177330701763334 -:102718000701753307017433070177517411751177 -:102728007611D8A401D001D0C5D77CC774F77DC76E -:1027380075F77EC776F77FC777F700D012000301D9 -:102748000301FB510F5C03010301FC511058D8B081 -:1027580001D001D008D006010601E3512318D8B4EE -:1027680001D001D001D038D00F5003010301FB5D27 -:1027780007010701516F105003010301FC590701BC -:10278800526F070107014F5107010701515D07010A -:1027980007015051070107015259D8B001D001D0A3 -:1027A80004D051C74FF752C750F74FC7C6F750C7A5 -:1027B800C7F74DC7C4F74EC7C5F7A4EC19F0C4C78F -:1027C8004FF7C5C750F7070107014F510F260701FB -:1027D80007015051102200D0120033C73CF734C70C -:1027E8003DF71FEC17F0070107013C5107010701EE -:1027F8003C6F59EC1DF007010701366F33C73CF7F2 -:1028080034C73DF71FEC17F0070107013C510701DA -:102818000701486F31EC1DF007010701356F07010B -:1028280007013651300AD8B401D001D004D036C7D8 -:1028380048F7D0EC1DF035C748F7D0EC1DF007017C -:10284800376F3A0E07010701486F07013751D0EC7F -:102858001DF033C73EF734C73FF70401000E0701E8 -:1028680007013C6F0401040E07013D6F65EC17F08A -:10287800120037C73CF738C73DF71FEC17F00701C0 -:1028880007013C51070107013C6F59EC1DF0070196 -:1028980007013A6F37C73CF738C73DF71FEC17F009 -:1028A800070107013C5107010701486F31EC1DF092 -:1028B80007010701396F070107013A51300AD8B4F7 -:1028C80001D001D004D03AC748F7D0EC1DF039C781 -:1028D80048F7D0EC1DF007013B6F3A0E07010701DE -:1028E800486F07013B51D0EC1DF037C73EF738C79A -:1028F8003FF70401000E070107013C6F0401040EB5 -:1029080007013D6F65EC17F0120026C72DF727C7A2 -:102918002EF724C72BF725C72CF7E1EC10F0070199 -:102928000701296F130E07010701296501D001D09E -:1029380009D0290E07010701296101D001D002D071 -:10294800000E2DD026C72DF727C72EF724C72BF743 -:1029580025C72CF7E1EC10F007010701286F010EDD -:1029680007010701296501D001D017D0150E07010D -:102978000701296101D001D010D0010E070107011C -:10298800286501D001D009D0150E0701070128617B -:1029980001D001D002D0010E02D0020E00D01200E8 -:1029A800D8901A3607010701F051D8B401D001D0E8 -:1029B80011D01B2A1B50030AD8A401D001D003D080 -:1029C800070E1A1206D0030E1B6401D001D001D0E5 -:1029D8001A8006D00701F16F000E1B6E0701F15136 -:1029E800D8901F36192A1AAE01D001D002D01F8004 -:1029F80000D01950080AD8A401D001D01BD0070173 -:102A0800F16F000E196E0701F151DF0E1724E96E00 -:102A1800010E1820EA6E1FC0EFFF174A182A185037 -:102A2800020A1710D8A401D001D004D0000E176EE6 -:102A3800000E186E1200296601D001D009D0010ECF -:102A480007010701746F000E0701756F7DEC20F018 -:102A58006D0E07010701786F4E0E0701796FC60EDC -:102A680007017A6F410E07017B6FA1C674F7A2C6F2 -:102A780075F7A3C676F7A4C677F751EC13F0390EAD -:102A880007010701742506010601A16F300E070131 -:102A9800070175210601A26F000E070107017621C3 -:102AA8000601A36F000E0701070177210601A46F35 -:102AB800FF0E0601A31507010701726F7F0E0601BD -:102AC800A4150701736F00D01200366601D001D03B -:102AD80023D007011F6F010E366E07011F51070132 -:102AE8001F6F000E070107011E6F07011F51000E1F -:102AF800070107011E6501D001D001D00DD00501E5 -:102B08000501C869070107011E2B000E070107010F -:102B18001E6501D001D0F3D705010501C829D8B435 -:102B280001D001D007D0C8C54CF787EC1AF00501D1 -:102B38000501C86907011F6F010E05010501C96F6D -:102B480007011F5107011F6F000E05010501CA6F1C -:102B580007011F510501CA890501CA83120011C75F -:102B680015F710C714F703EC08F007010701126FF7 -:102B7800070107011251FE0AD8A401D001D008D0DC -:102B8800FE0E07010701106FFF0E0701116F30D00D -:102B9800070107011229D8A401D001D006D00701E6 -:102BA800070110690701116923D0D8900232070183 -:102BB80007011251D8B401D001D001D0028E202AC9 -:102BC800080E206001D001D006D007010701106966 -:102BD800070111690DD00701136F000E206E070160 -:102BE8001351070102C010F707010701116B00D04C -:102BF800120099C7A5F69AC7A6F69BC7A7F69CC761 -:102C0800A8F69DC79FF7080E070107019F6101D02D -:102C180001D001D015D0A8C69EF7A7C6A8F6A6C6AB -:102C2800A7F6A5C6A6F69EC7A5F6080E07010701D2 -:102C38009F5F080E070107019F6101D001D0EBD704 -:102C4800070107019F6701D001D001D011D006010B -:102C5800D890A8BFD880A537A637A737A8370701C7 -:102C680007019F07070107019F6701D001D0EFD730 -:102C7800A5C699F7A6C69AF7A7C69BF7A8C69CF754 -:102C880000D012000301FDC345F70301FEC346F758 -:102C9800070107013D5107014527070107013E517B -:102CA80007014623140E0701452507010701436F55 -:102CB800000E070146210701446FCE0E07010701E8 -:102CC800435D0A0E07014459D8A001D001D007D0AE -:102CD8000701CE0E0701435F0A0E0701445BE0CEF1 -:102CE80041F7E1CE42F743C7E0FE44C7E1FE3FC7E4 -:102CF800A2F740C7A3F7D3ECE0F0A2C743F7A3C7F6 -:102D080044F741C7E0FE42C7E1FE43C73DF744C769 -:102D18003EF700D01200FACFCEF7FBCFCFF7E9CFBE -:102D2800D0F7EACFD1F7E1CFD2F7E2CFD3F7D9CFB7 -:102D3800D4F7DACFD5F7F3CFD6F7F4CFD7F7F6CF66 -:102D4800D8F7F7CFD9F7F8CFDAF7F2A401D001D046 -:102D580002D007EC21F09EA201D001D003D0E8EC0C -:102D6800E3F09E92DAC7F8FFD9C7F7FFD8C7F6FF96 -:102D7800D7C7F4FFD6C7F3FFD5C7DAFFD4C7D9FF43 -:102D8800D3C7E2FFD2C7E1FFD1C7EAFFD0C7E9FF47 -:102D9800CFC7FBFFCEC7FAFFCDC7E0FFCCC7E8FF20 -:102DA800CBC7D8FF1000EACFE6F7E1CFE7F7E2CFCD -:102DB800E8F7D9CFE9F7DACFEAF7F3CFEBF7F4CFB3 -:102DC800ECF7F6CFEDF7F7CFEEF7F8CFEFF7A4A6CD -:102DD80001D001D00BD0E20E786E000E81B8010E42 -:102DE80007010701F06FD4EC14F0A496A1A201D05A -:102DF80001D006D0B368C40EB26E01EC20F0A192E7 -:102E0800EFC7F8FFEEC7F7FFEDC7F6FFECC7F4FF13 -:102E1800EBC7F3FFEAC7DAFFE9C7D9FFE8C7E2FF64 -:102E2800E7C7E1FFE6C7EAFFE5C7E9FFE4C7FBFF3D -:102E3800E3C7FAFF11003CC73EF73DC73FF701D093 -:102E480000D0070107013E510701406F0701070144 -:102E58003F510701416F07013E4B3F2B40C7F6FF2B -:102E680041C7F7FF000EF86E0E0EF76403D0080096 -:102E7800F55005D0F6CFE9FFF7CFEAFFEF5000098C -:102E8800D8A401D001D0DCD707013EC740F707011D -:102E98003FC741F7070107013C510701405F0701A0 -:102EA80007013D510701415BFF0E0701402507015E -:102EB80007013C6FFF0E0701412107013D6F00D05C -:102EC80012003CC740F73DC741F704D0070107018E -:102ED800404B412B40C7E9FF41C7EAFFEF50D8A458 -:102EE80001D001D0F3D700D0070107013E510701F7 -:102EF800426F070107013F510701436F07013E4B2E -:102F08003F2B42C7F6FF43C7F7FF000EF86E0701D5 -:102F180040C7E1FF070141C7E2FF07010701404B36 -:102F2800412B0E0EF76403D00800F55005D0F6CFFC -:102F3800E9FFF7CFEAFFEF50E76EE750D8A401D0DA -:102F480001D0D1D700D012001150C00807010701E5 -:102F5800576F1250D8A0E82A05080701586F0701D3 -:102F68000701555107010701575D07010701565130 -:102F7800070107015859D8B001D001D004D057C76C -:102F880055F758C756F7070107015551112607018C -:102F98000701565112221150135C12501458D8B020 -:102FA80001D001D004D011C013F012C014F055C7DD -:102FB8005BF756C75CF753C759F754C75AF7C8ECBD -:102FC8001EF055C753F756C754F700D012001150DA -:102FD800C00807010701576F1250D8A0E82A050852 -:102FE8000701586F07010701555107010701575D90 -:102FF800070107015651070107015859D8B001D0F8 -:1030080001D004D057C755F758C756F7070107012D -:103018005551112607010701565112221150135C10 -:1030280012501458D8B001D001D004D011C013F0F8 -:1030380012C014F055C7C4F756C7C5F753C7C2F72F -:1030480054C7C3F7B8EC1FF055C753F756C754F722 -:1030580000D0120007014C0E070107014D6F070150 -:10306800070E07014E6F86EC1EF00009D8A401D0A8 -:1030780001D001D02DD0070107014C51C00BC00A67 -:10308800D8A401D001D00CD007014C0E07010701CC -:103098004D6F0701070E07014E6F86EC1EF018D022 -:1030A800070107014C6701D001D001D011D00701F9 -:1030B80007014CC74FF707010701506B000E0701C6 -:1030C80007014D6F000E07014E6FA3EC13F0C2D736 -:1030D80012000F0E070107011E6501D001D017D09D -:1030E8000A0E070107011F6101D001D010D00F0E91 -:1030F80007010701206501D001D009D00A0E070198 -:103108000701216101D001D002D0000E20D00A0EA3 -:10311800070107011E6101D001D017D00F0E07016A -:1031280007011F6501D001D010D00F0E070107015C -:10313800206501D001D009D00A0E070107012161DD -:1031480001D001D002D0010E02D0020E00D0120030 -:103158000F0E070107011E6501D001D017D00A0E16 -:10316800070107011F6101D001D010D00A0E070125 -:103178000701206101D001D009D00A0E070107011B -:10318800216101D001D002D0000E20D00A0E070123 -:1031980007011E6101D001D017D00A0E07010701EF -:1031A8001F6101D001D010D00F0E07010701206563 -:1031B80001D001D009D00A0E07010701216101D011 -:1031C80001D002D0010E02D0020E00D012000D0E66 -:1031D800070107011E6101D001D017D00D0E0701AC -:1031E80007011F6101D001D010D00D0E07010701A2 -:1031F800206101D001D009D0100E07010701216517 -:1032080001D001D002D0010E20D00D0E0701070118 -:103218001E6101D001D017D0100E070107011F65EC -:1032280001D001D010D00D0E07010701206101D097 -:1032380001D009D00D0E07010701216101D001D08D -:1032480002D0000E02D0020E00D012001EC72DF7C9 -:103258001FC72EF71CC72BF71DC72CF7E1EC10F082 -:1032680007010701206F1EC72DF71FC72EF71CC7C0 -:103278002BF71DC72CF7E1EC10F007010701216FB0 -:103288000D0E07010701206501D001D009D00D0EF0 -:1032980007010701216501D001D002D0000E12D02C -:1032A8000A0E07010701206101D001D009D00D0ED7 -:1032B80007010701216501D001D002D0010E02D01B -:1032C800020E00D0120043EC11F00701146F000E3B -:1032D80007010701136F07011451130E07010701B6 -:1032E800136501D001D001D028D0380E070107019D -:1032F8001325E96EEA6A000EEA22EF500701146FFF -:1033080000019F0E070107011325E96EEA6A000113 -:10331800000EEA22EF5007011419D8B401D001D0E9 -:1033280002D0000E0CD007010701132B130E070162 -:103338000701136501D001D0D8D7010E00D01200C3 -:10334800C6C7C9F7C7C7CAF707010701C551C411DE -:10335800D8B401D001D01AD00BD0C4C7E9FFC5C773 -:10336800EAFF0E01FACEEFFF07010701C44BC52B98 -:1033780007010701C907D8A0CA070701C929D8B496 -:10338800CA29D8A401D001D0E8D710D002D0FACEEB -:10339800C8F707010701C907D8A0CA070701C92943 -:1033A800D8B4CA29D8A401D001D0F1D7C6C7C4F768 -:1033B800C7C7C5F700D0120007010E6F000E07013E -:1033C80007010D6F07010E511BD00DC711F707013B -:1033D8000E6FA00E07010701106F07010E5168EC70 -:1033E800E2F007010701105109C7E9FF0AC7EAFF20 -:1033F800EF6E07010701094B0A2B070107010D2B87 -:1034080007010DC70EF707010F6B070107010B51E5 -:1034180007010E5D070107010C5107010F59D8A0DC -:1034280001D001D0D2D71200B0C7B6F7B1C7B7F7ED -:10343800AEC7B4F7AFC7B5F720D00701B6C7F6FFD8 -:103448000701B7C7F7FF000EF86EB4C7E1FFB5C7AD -:10345800E2FF0E0EF76403D00800F55005D0F6CF52 -:10346800E9FFF7CFEAFFEF50E76E07010701B64B18 -:10347800B72B07010701B44BB52B07010701B207AA -:10348800D8A0B3070701B229D8B4B329D8A401D06A -:1034980001D0D3D700D012001CEC1EF00009D8A42C -:1034A80001D001D008D0000E070107014C6F000EB3 -:1034B80007014D6F27D006010601E05107010701FA -:1034C8004C19D8B401D001D00FD04CC7E0F6000E8B -:1034D800136E000E146E000E070107014E6F000EEA -:1034E80007014F6F91EC20F04CC723F01350C00830 -:1034F800070107014C6F1450D8A0E82A05080701F6 -:103508004D6F00D01200040E070107014C6501D071 -:1035180001D001D02CD0070107014C510E0DF3CF7B -:103528004DF70C0E07014D270101590E07014D25D6 -:10353800E96EEA6A0101010EEA22000EEE6E000E43 -:10354800ED6E070107014C510E0D0101590EF324D0 -:10355800E96EEA6A0101010EEA22000EEE6E000E23 -:10356800EE6E000EEE6E000EED6EED52ED52120094 -:103578000001B30E07010701336F0001000E0701B8 -:10358800346F2DC731F72EC732F706ECC1F00009AA -:10359800D8B401D001D00AD037820701306F070EA6 -:1035A80006010601E56F0701305116D0000E04012F -:1035B8000401EF6F000E0401F06F2DC7F1F42EC760 -:1035C800F2F40701306F000E06010601E56F0701EE -:1035D80030512FC733F0379212000001B30E0701A4 -:1035E8000701336F0001000E0701346F2DC731F753 -:1035F8002EC732F789ECC2F00009D8B401D001D047 -:103608000AD037820701306F070E06010601E56F01 -:103618000701305116D02DC7EFF42EC7F0F4000E75 -:1036280004010401F16F000E0401F26F0701306F0D -:10363800000E06010601E56F070130512FC733F070 -:10364800379212003450D8B401D001D001D02DD017 -:1036580007014E6F010E346E07014E51FF0E000137 -:103668000001FB25070107014C6FFF0E0001000157 -:10367800FC2107014D6FCE0E070107014C5D0A0EB4 -:1036880007014D59D8A001D001D007D0CD0E0701B0 -:1036980007014C6F0A0E07014D6F0E01FE8D4CC7D6 -:1036A800ECFE4DC7EDFE0E01FC9D1200000E070159 -:1036B8000701646F000E0701656F0701070160A12C -:1036C80001D001D00CD007010701625107010701A1 -:1036D80064270701070163510701070165230701F3 -:1036E800D89007016237070163370701D8900701AF -:1036F8006133070160330701070161516011D8A4E4 -:1037080001D001D0DAD764C760F765C761F700D088 -:1037180012000701086F000E276E07010851060105 -:10372800688F7AECC5F016C774F717C775F77DEC84 -:1037380020F0BCECDCF0A8EC1EF0E8EC1EF045EC48 -:10374800C8F00701086F000E070107011D6F070188 -:10375800085169EC15F00601060168BD01D001D0D9 -:103768000AD00701086F000E07010701096F07015A -:103778000851EAEC1FF012000301FDC37DF70301B5 -:10378800FEC37EF707010701795107017D2707016D -:1037980007017A5107017E23140E07017D250701D1 -:1037A80007017B6F000E07017E2107017C6FCE0E9B -:1037B800070107017B5D0A0E07017C59D8A001D0DB -:1037C80001D007D00701CE0E07017B5F0A0E070163 -:1037D8007C5B7BC7E0FE7CC7E1FE12004CC723F090 -:1037E80006010601E351070107014C19D8B401D0BD -:1037F80001D008D0000E070107014C6F000E070129 -:103808004D6F1CD01EA001D001D00AD01E90000E12 -:10381800070107014E6F000E07014F6F69EC20F09A -:103828000F5003010301FB5D070107014C6F1050A6 -:1038380003010301FC5907014D6F00D01200320E3D -:10384800070107015A6F000E07015B6F000E0701A1 -:103858000701586F000E0701596F06016F0E070127 -:103868000701566F0601060E0701576F08EC1FF097 -:10387800000E0D6E000E0E6E07010D6F000E226E0B -:1038880007010D5107010D6F000E076E07010D515D -:1038980007010D6F000E266E07010D51120034C787 -:1038A800E9FF35C7EAFFD890EF3634C7E9FF35C7D7 -:1038B800EAFFEF50D8A401D001D01FD034C7E9FFE8 -:1038C80035C7EAFF010EEF6E32C7E9FF33C7EAFFDB -:1038D800EE50ED10D8A401D001D008D032C7E9FFCE -:1038E80033C7EAFF000EEE6E020EED6E32C7E9FF37 -:1038F80033C7EAFFEE06000EED5A120015C7C9FFDE -:10390800C6AE01D001D002D0FF0E25D000D0C7B07E -:1039180001D001D0FCD700D0C5CF16F71F0E070184 -:10392800161716C717F70701186B000EC7B4010E54 -:1039380007011713000E1813070118511711D8A4FF -:1039480001D001D0E9D7C5AC01D001D002D0FE0E1C -:1039580002D0000E00D0120007010701A75107018D -:103968000701A41B07010701A45107010701A71BB1 -:1039780007010701A75107010701A41B0701070158 -:10398800A65107010701A51B07010701A55107015A -:103998000701A61B07010701A65107010701A51B7F -:1039A800A4C7A4F7A5C7A5F7A6C7A6F7A7C7A7F7EB -:1039B80000D0120041C760F784EC0EF077ECE7F016 -:1039C800040104EED4F0030113EEE5F0E652EE52E2 -:1039D800ED50E518EFCFE8FFD8B4E718D8B401D018 -:1039E80001D012D00701426F010E07010701716F64 -:1039F800070142510701436F100E07010701706F5D -:103A080007014351B4EC9BF01200DF0E07010701D8 -:103A18003225E96E010E070107013321EA6EEF50E6 -:103A280007010701356F070107013551070134C741 -:103A380036F70701376B36BF370707013617000E11 -:103A48003717070137513611D8B401D001D002D049 -:103A5800D88002D0D89000D012000F0E07010701BD -:103A68004817300E07010701482507010701496F6C -:103A780007014A6B000E07014A23090E07010701D7 -:103A8800486501D001D00CD0370E07010701482541 -:103A980007010701496F07014A6B000E07014A2316 -:103AA80007010701495100D0120007013C3B0F0EE6 -:103AB8003C17300E070107013C25070107013D6F40 -:103AC80007013E6B000E07013E23090E070107019F -:103AD8003C6501D001D00CD0370E070107013C2509 -:103AE800070107013D6F07013E6B000E07013E23EA -:103AF800070107013D5100D01200070107014D5190 -:103B08004BC7E9FF4CC7EAFFEF6201D001D005D0EF -:103B18004BC74BF74CC74CF717D007014BC7E9FF0A -:103B280007014CC7EAFF070107014B4B4C2BEF502D -:103B3800D8A401D001D0E1D7000E070107014B6FCF -:103B4800000E07014C6F00D0120023C7B4FE00F02E -:103B58000701276F010E0E010E01B26F07012751F1 -:103B680000F000D00E010E018AB101D001D0FAD7C1 -:103B78000701276F000E0E010E01B26F07012751D2 -:103B880000F0B8CE25F700F0B9CE26F725C723F701 -:103B980026C724F700D01200000E070107014D6F59 -:103BA800000E07014E6F0401000E070107014B6F5D -:103BB8000401040E07014C6F81EC1DF04BC749F757 -:103BC8004CC74AF7070107014A514911D8B401D037 -:103BD80001D007D049C7E9FF4AC7EAFF070148C72C -:103BE800EFFF1200C80E070107015A6F000E070108 -:103BF8005B6F000E07010701586F000E0701596F30 -:103C08000401000E07010701566F0401040E0701A5 -:103C1800576F08EC1FF007012F6F000E256E070184 -:103C28002F5107012F6F000E0C6E07012F51120044 -:103C38000E010E01DFB701D001D002D0010E1BD05A -:103C480019EC22F01C5007010701A35F1D50070162 -:103C58000701A45B7A0E07010701A35D000E0701A7 -:103C6800A459D8A001D001D004D00E01DF9780EC70 -:103C78001FF0000E00D012009E92CB68CA82CA9C28 -:103C8800CA8ACA88CA869F929D82CA84000EBD6E5F -:103C9800000EBA6EBA86BA84BA9EBA9CBD86BD8436 -:103CA800BD9EBD9CBD86BD84BA86BA84BD9ABD98AA -:103CB800BA9ABA98000EBE6E000EBB6E12000D0EB8 -:103CC800070107012B6101D001D009D00D0E0701B2 -:103CD80007012C6101D001D002D0000E12D0180EBD -:103CE800070107012B6501D001D009D00D0E07018E -:103CF80007012C6101D001D002D0010E02D0020EC2 -:103D080000D0120003010301FB510F5C0301030102 -:103D1800FC511058D8B001D001D008D006010601D6 -:103D2800E3512318D8B401D001D002D0000E0BD033 -:103D3800C3EC22F04DC7E9FF4EC7EAFFEF6E0F4A0A -:103D4800102A010E00D0120000010001E9690001EB -:103D58000001EA6900010001EB6900010001EC695A -:103D680000010001ED6900010001EE69000E00018B -:103D78000001E56F000E0001E66F000E0001E76F1D -:103D8800000E0001E86F120011D0070159C7F6FFB5 -:103D980007015AC7F7FF000EF86E0800F5CFF3FFCA -:103DA80007010701594B5A2BF3CFFAFE0701070108 -:103DB8005B07D8A05C0707015B29D8B45C29D8A4A5 -:103DC80001D001D0E2D7120007010A6F000E0701E7 -:103DD8000701096F07010A51040E07010701096568 -:103DE80001D001D001D00ED009C74CF787EC1AF0EA -:103DF80007010701092B040E07010701096501D016 -:103E080001D0F2D71E82120056C75CF757C75DF77C -:103E18000BD05CC7E9FF5DC7EAFF070158C7EFFF92 -:103E2800070107015C4B5D2B070107015A07D8A062 -:103E38005B0707015A29D8B45B29D8A401D001D05F -:103E4800E8D700D012000AC7B4FE0BC7F3FF0CC7AF -:103E5800F4FFF250C00B070107010D6F3F0EF21679 -:103E6800F3CFB6FE00F0F4CFB7FE070107010D51FE -:103E7800F21200D00E010E018AB101D001D0FAD79A -:103E88001200E1C641F747EC0AF07D0E0701070171 -:103E9800415D000E07014259D8B001D001D001D0D0 -:103EA8000DD0F6EC1DF0C10E07010701376FFF0EAC -:103EB8000701386F3DEC14F092ECDDF01200C00EF3 -:103EC800115C050E1258D8A001D001D001D013D032 -:103ED80053C7C2F7BEEC22F0114A122A1150135CE4 -:103EE80012501458D8B001D001D004D011C013F02A -:103EF80012C014F000D012000E01DF8F0E01DF9FF8 -:103F0800080E07010701A26F00D007010701A207E9 -:103F18000701A229D8A401D001D0F7D70E01FC933C -:103F28000E01DF8719EC22F0A3C71CF0A4C71DF00F -:103F3800120006010601E229D8B401D001D007D049 -:103F4800E2C64CF787EC1AF006010601E2690701A0 -:103F5800306F070E06010601E56F070130513790F3 -:103F68003730010B00D012000CD0C2C7E9FFC3C71D -:103F7800EAFFEF50F36E07010701C24BC32BF3CFE3 -:103F8800FAFE07010701C407D8A0C5070701C4291D -:103F9800D8B4C529D8A401D001D0E7D712000701A9 -:103FA8000D6F010E06010601C96F07010D510601CB -:103FB8000601C669BB6819EC22F0A3C7CAF6A4C7F4 -:103FC800CBF6A5C7CCF6A6C7CDF6120005010501AC -:103FD800C829D8B401D001D007D0C8C54CF787ECA0 -:103FE8001AF005010501C86907010A6F000E0501ED -:103FF8000501C96F07010A5112002A6601D001D0D4 -:104008000AD02BC02AF0008200B401D001D002D01F -:10401800897801D000942A50D8B401D001D001D0B9 -:104028002A0612000401000E2524E96EEA6A04013A -:10403800040EEA22EF50680AD8B401D001D002D0A9 -:10404800000E04D02528216E010E00D01200F28A3D -:1040580000F0F29AD6CFF4F5D7CFF5F5A9C6F6F564 -:10406800AAC6F7F5ABC6F8F5ACC6F9F5F2B401D0B7 -:1040780001D0EDD7F28A1200F28A00F0F29AD6CF78 -:10408800F4F5D7CFF5F5A9C6F6F5AAC6F7F5ABC688 -:10409800F8F5ACC6F9F5F2B401D001D0EDD7F28A43 -:1040A800120040EC20F0F5C574F7F6C575F7F7C5B2 -:1040B80076F7F8C577F774C770F775C771F776C7DD -:1040C80072F777C773F700D01200080E07010701CF -:1040D8004E2507010701776F000E070107014F21E1 -:1040E8000701786FA8EC21F04EC70FF04FC710F00A -:1040F80012000701060174C7A1F60701060175C77A -:10410800A2F606010601A36B0601A46B0701766FF0 -:10411800010E296E070176511200F90E07010701F9 -:104128004E2507010701AE6F0A0E070107014F214F -:104138000701AF6F86EC22F04EC711F04FC712F09F -:10414800120030C73CF731C73DF71FEC17F03CC7EA -:1041580035F73DC736F730C733F731C734F72FC7C0 -:1041680032F7ADECCFF000D01200948694883F0E61 -:10417800C716000EC66E000EC56EC686C78E82862E -:104188008288C68A0701096F430EC86E0701095164 -:10419800120030C73CF731C73DF71FEC17F03CC79A -:1041A80035F73DC736F730C733F731C734F72FC770 -:1041B80032F710ECCCF000D012002BC72CF7EDEC46 -:1041C80022F09AEC22F00009D8A401D001D003D043 -:1041D800F6EC1DF004D046EC22F092ECDDF0120073 -:1041E8000701106F000E206E070110510701106FB4 -:1041F800000E246E070110510701106F000E086EA3 -:10420800070110511200F2A401D001D00ED0010E06 -:1042180006010601A927000E0601AA23000E0601C1 -:10422800AB23000E0601AC23F29412000701226FA3 -:10423800010E07010701236F07012251A9EC1DF0A8 -:10424800230EE96E070EEA6EEF30E832010B00D05C -:1042580012000AC73CF70BC73DF71FEC17F03CC725 -:1042680055F73DC756F70AC753F70BC754F7EBEC9A -:1042780017F000D012000401000E2524E96EEA6A46 -:104288000401040EEA22EF50690AD8B401D002D022 -:10429800010E01D0000E00D012001EB201D001D0D4 -:1042A8000DD026EC1BF0000E03010301FB6F000E7E -:1042B8000301FC6F06010601E3691E8212000AC7AA -:1042C8003CF70BC73DF71FEC17F03CC755F73DC748 -:1042D80056F70AC753F70BC754F7A8EC17F000D0E6 -:1042E8001200E1C641F747EC0AF0F6EC1DF0880E23 -:1042F80007010701376FFF0E0701386F3DEC14F017 -:1043080067EC22F0120031C737F732C738F73DECB7 -:1043180014F033C737F734C738F735C739F736C716 -:104328003AF7C4ECE6F012000DC760F784EC0EF023 -:1043380003010301F551070AD8B401D002D0010ED8 -:1043480001D0000E00D01200325007010701772576 -:1043580007010701796F000E07010701782107019E -:104368007A6FC0EC1BF01200BEC7C1F7BFC7C2F717 -:10437800C2C7C0F7C1C7C2F7C0C7C1F7C1C7BEF738 -:10438800C2C7BFF700D012002DC733F72EC734F7C6 -:104398002FC735F730C736F72BC731F72CC732F799 -:1043A80087EC21F01200000ED76E000ED66EF19445 -:1043B800F294F28A0701086F870ED56E070108513B -:1043C800120076927690769C769A7688769676849F -:1043D800A4967768A38697949388A58612002FC71A -:1043E80033F730C734F7F1EC13F031C737F732C77A -:1043F80038F73DEC14F0120020C725F71EC723F745 -:104408001FC724F71CC721F71DC722F7FFEC02F0CE -:1044180012002BEC20F0F4C5DFF7F5C5E0F7F6C580 -:10442800E1F7F7C5E2F700D0120040EC20F0F4C540 -:10443800A3F7F5C5A4F7F6C5A5F7F7C5A6F700D005 -:1044480012000DC760F784EC0EF00301F6970DC754 -:104458002DF729ECE3F0120007010E6F020E06019A -:104468000601D26F07010E510DC7CFF612000701E2 -:104478000E6F020E06010601C96F07010E510DC726 -:10448800C6F6120007012C6F730E07010701486F6B -:1044980007012C51D0EC1DF012002DC731F72EC7A3 -:1044A80032F72BC72FF72CC730F7F3EC21F01200A7 -:1044B80019EC22F0A3C7ADF6A4C7AEF6A5C7AFF6B0 -:1044C800A6C7B0F6120007012B6F680E0701070197 -:1044D800486F07012B51D0EC1DF0120037A001D016 -:1044E80001D002D0000E03D03780010E00D0120098 -:1044F8000E010E01DFAB01D002D0010E01D0000E7B -:1045080000D01200E2CEB0F7E3CEB1F7AEC7E2FEBC -:10451800AFC7E3FE00D01200E0CEB0F7E1CEB1F7AE -:10452800AEC7E0FEAFC7E1FE00D012002850030A74 -:10453800D8B401D002D0010E01D0000E00D0120074 -:104548000C50040AD8B401D002D0010E01D0000EDC -:1045580000D01200979292988998B19AB198A08247 -:10456800A282B19012003BECD5F0F0ECBDF02EEC3D -:10457800B5F01200C2C7F3FFF3CFFAFE12000E0126 -:104588000E01FA5100D012000501CA51010B00D0EA -:104598001200EAEC22F0B190768412007694E4ECF2 -:1045A80022F01200D08EF28EF28C12000601060163 -:1045B800E0691200E4ECDBF01200225000D0120097 -:1045C8008E828E9412002BC7D1F612008E928E84A2 -:0C45D80012002CC7C8F61200D18012009F -:10FE62002F7365727665722F61737369676E3F6572 -:10FE72006D6265646465643D312670726F746F6390 -:10FE82006F6C56657273696F6E3D32004841505215 -:10FE920041445539505553544557553355334136DE -:10FEA2004845504151454652455045500000005E7C -:10FEB20001E80367005357415138544845433245DE -:10FEC200424139484546454A3552555354454845BD -:10FED2005939323754000D0A436F6E6E6563746987 -:10FEE2006F6E3A20636C6F73650D0A0D0A007465BC -:10FEF2006D706572617475726568756D6964697437 -:10FF0200790020485454502F312E300D0A486F7317 -:10FF1200743A200054656C6C537469636B4E65745B -:10FF22003A0054656C6C537469636B204E657400BF -:10FF320065766572666C6F75726973680073656C5D -:10FF4200666C6561726E696E6700636F6465737774 -:10FF52006974636800646973636F6E6E65637400CD -:10FF620066696E656F66667365740070726F746F32 -:10FF7200636F6C005265676973746572006D616EC0 -:10FF8200646F6C796E0052617744617461006172D2 -:10FF920063746563680076657273696F6E0073657A -:10FFA2006E736F7200736563726574006F7265675A -:10FFB2006F6E006D6F64656C00636C6173730050EB -:10FFC200696E670047455420006861736800736872 -:10FFD200613100646174610073656E640078313070 -:10FFE2000032383A006D6163006B65790041434B22 -:0EFFF200006F730052005300330050000000F7 +:10000800FACFE2F8FBCFE3F8E9CFE4F815EF35F0E3 +:10001800D8CFC9F8E8CFCAF8E0CFCBF8C3EF34F0AF +:1000280007EE56F0000EF66E000EF76E010EF86E33 +:1000380010EE51F036EC00F0F86A00EE00F017EE22 +:1000480056F02FEC00F00EEE7EF010EE02F02FECE2 +:1000580000F0A1EF1DF0EE6AE550E150FCE1E2503E +:10006800FAE112000900F5CFEEFFE550E150FAE1A0 +:10007800E250F8E112000E010E01D96746EF00F0D8 +:1000880048EF00F09DEF00F05AEC42F0070107013D +:100098001A5108010801A15F070107011B51080156 +:1000A8000801A25B450E08010801A15D000E0801C8 +:1000B800A259D8A062EF00F064EF00F09AEF00F0C8 +:1000C8000801356F110E08010801376F0801355115 +:1000D80039EC3FF0370EE96E080EEA6E010EE9269C +:1000E800000EEA22EF500801366F080136A57FEFAF +:1000F80000F081EF00F08DEF00F006010601D5B3A6 +:1001080088EF00F08AEF00F08BEF00F08D7292EF2D +:1001180000F00601D5930601D5978D925AEC42F06E +:10012800A1C81AF7A2C81BF70601D595000E5EEF05 +:1001380001F00601D58306010601D5B1A6EF00F04E +:10014800A8EF00F0ADEF00F02EEC3CF0000E5EEFF3 +:1001580001F0FCC6DBF6FDC6DCF6DBC6E0FEDCC65D +:10016800E1FE140E08010801C46F000E0801C56FF6 +:100178000801210E08010801C26F0801080E0801D4 +:10018800C36F6DEC38F033C8BCF834C8BDF82FEC39 +:1001980043F0BCC833F8BDC834F8CE0E08010801D6 +:1001A800215D0A0E08012259D8B0DDEF00F0DFEF1B +:1001B80000F011EF01F00801080121B1E6EF00F0AD +:1001C800E8EF00F011EF01F00801080126BFEFEF9A +:1001D80000F0F1EF00F011EF01F00801080125B976 +:1001E800F8EF00F0FAEF00F011EF01F0EF0E080160 +:1001F8000801235D050E08012459D8B006EF01F067 +:1002080008EF01F011EF01F00801080125BF0FEF19 +:1002180001F011EF01F012EF01F0FF0021C8FCF628 +:1002280022C8FDF6060E08010801B06F000E08018D +:10023800B16F2D0E0801356F080E366F35C8AEF850 +:1002480036C8AFF81DC8ACF81EC8ADF858EC3AF07F +:100258001FC8E9FF20C8EAFFFF0EEF6E080108017A +:100268003451080AD8A43BEF01F03DEF01F059EFF3 +:1002780001F0080108013351D8B445EF01F047EF08 +:1002880001F052EF01F0080108013351060AD8A421 +:1002980050EF01F052EF01F059EF01F01FC8E9FFEC +:1002A80020C8EAFF080133C8EFFF0601D591010E07 +:1002B8005EEF01F012006FEC42F0250E0801080114 +:1002C8000B6F000E08010C6F0001DB0E080108011E +:1002D800096F0001000E08010A6F95EC3AF0000161 +:1002E8000001DB29D8A47BEF01F07DEF01F0ADEF31 +:1002F80001F00801086F000E00010001E06F08011D +:1003080008510801086F000E00010001DF6F0801A5 +:1003180008510801086F000E00010001DE6F080196 +:1003280008510801086F540E00010001DD6F080133 +:1003380008510801086FCA0E00010001DC6F0801AE +:1003480008510801086FAC0E00010001DB6F0801BD +:100358000851060E08010801B06F000E0801B16FC0 +:100368000001DB0E08010801AE6F0001000E080154 +:10037800AF6F0001990E08010801AC6F0001000E73 +:100388000801AD6F58EC3AF0C00E00010001806F13 +:10039800A80E0001816F000E0001826F330E00016C +:1003A800836FFF0E00010001846FFF0E0001856F4F +:1003B800FF0E0001866F000E0001876F000100012B +:1003C800EC29D8B4EAEF01F0ECEF01F00AEF02F003 +:1003D80000010001ED29D8B4F4EF01F0F6EF01F0C7 +:1003E8000AEF02F000010001EE29D8B4FEEF01F097 +:1003F80000EF02F00AEF02F000010001EF29D8A493 +:1004080008EF02F00AEF02F051EF02F00001988DB8 +:100418000001988FC00E000100016C6FA80E00014A +:100428006D6F000E00016E6F330E00016F6FFF0ECF +:1004380000010001706FFF0E0001716FFF0E0001D7 +:10044800726F000E0001736FC00E00010001746F1F +:10045800A80E0001756F000E0001766F010E0001F5 +:10046800776FC00E00010001786FA80E0001796F48 +:10047800000E00017A6F010E00017B6F000E000173 +:1004880000017C6F000E00017D6F000E00017E6F81 +:10049800000E00017F6F7DEF02F00001989D0001C2 +:1004A800989FECC06CF0EDC06DF0EEC06EF0EFC040 +:1004B8006FF0F0C070F0F1C071F0F2C072F0F3C0EC +:1004C80073F0F4C074F0F5C075F0F6C076F0F7C0BC +:1004D80077F0F8C078F0F9C079F0FAC07AF0FBC08C +:1004E8007BF0FCC07CF0FDC07DF0FEC07EF0FFC05C +:1004F8007FF012003FC8E9FF40C8EAFFEECF47F897 +:10050800EECF48F8EECF49F8EECF4AF800010001E7 +:100518006F5108014A1911E1000100016E510801EB +:1005280049190BE1000100016D510801481905E165 +:10053800000100016C5108014719D8A4A6EF02F088 +:10054800A8EF02F0ABEF02F0FF0E9AEF03F00801FC +:10055800080143690201000E08010801456F020104 +:10056800020E0801466F0801476F000E08010801D6 +:10057800446F08014751040E080108014465C7EF9C +:1005880002F0C9EF02F0CBEF02F058EF03F0020ED1 +:10059800080108013D25E96E000E080108013E2109 +:1005A800EA6E0C0E080108014525E16E000E0801EF +:1005B80008014621E26EE652EE52ED50E518EFCF03 +:1005C800E8FFD8B4E718D8A4ECEF02F0EEEF02F099 +:1005D80044EF03F03DC8E9FF3EC8EAFF0A0E0801F0 +:1005E80008014525E16E000E080108014621E26E6A +:1005F800E652EE52ED50E518EFCFE8FFD8B4E71811 +:10060800D8A409EF03F00BEF03F042EF03F03FC863 +:10061800E9FF40C8EAFFEECF47F8EECF48F8EECF43 +:1006280049F8EECF4AF845C8E9FF46C8EAFFEECFD9 +:100638004BF8EECF4CF8EECF4DF8EECF4EF8080160 +:100648004A5108014E190EE10801495108014D1996 +:1006580009E10801485108014C1904E10801475112 +:1006680008014B19D8A43BEF03F03DEF03F042EF2C +:1006780003F00801080144519AEF03F044C843F815 +:10068800170E080108014527000E08014623080136 +:100698000801442B040E08010801446556EF03F0D5 +:1006A80058EF03F0CBEF02F0080108014329D8B452 +:1006B80060EF03F062EF03F095EF03F00801080123 +:1006C8004351170D0201000EF32408010801456F7C +:1006D8000801466B0201020E080146230A0E0801B2 +:1006E8000801B06F000E0801B16F3FC8AEF840C8EE +:1006F800AFF845C8ACF846C8ADF858EC3AF03DC874 +:10070800E9FF3EC8EAFF0A0E080108014525E16E27 +:10071800000E080108014621E26EEECFE6FFEDCF9C +:10072800E5FF0801080143519AEF03F01200C2CF18 +:1007380029F8C0CF2AF8D5CF2BF8D6CF2DF8D7CFA8 +:100748002CF8010EC26E08012E6F3F0EC06E080114 +:100758002E5108012E6F880ED56E08012E51080102 +:100768002E6F000E080108011A6F08012E51000EA5 +:1007780008010801216F000E0801226F000E080110 +:10078800236F000E0801246F000E080108011D6F79 +:10079800000E08011E6F7BEC22F00801080174C8E6 +:1007A80025F80801080175C826F808010801276B13 +:1007B8000801286B000ED76E000ED66EC2820400A8 +:1007C800E6EF03F0C2B2EBEF03F0EDEF03F0E6EF74 +:1007D80003F0D6CF1FF8D7CF20F87BEC22F074C8EF +:1007E8001BF875C81CF8080108011F510801080109 +:1007F8002127080108012051080108012223000EC1 +:10080800080108012323000E0801080124231A0EF9 +:100818000801215DF20E080122599E0E0801235994 +:10082800000E080108012459D8A01DEF04F01FEF9D +:1008380004F03DEF04F07BEC22F00801080174514C +:1008480008010801251B0801080175510801080164 +:10085800261B7BEC22F008010801745108010801ED +:10086800271B08010801755108010801281B9FEF83 +:1008780004F0080108012051080108011E1906E1C9 +:10088800080108011F51080108011D19D8A44FEFDC +:1008980004F051EF04F053EF04F09DEF04F0080169 +:1008A8001DC82EF808011EC82FF8080108011F519D +:1008B80008012E5F08010801205108012F5B08017B +:1008C80008011B5108012E27080108011C510801C5 +:1008D8002F2308012EC830F808012FC831F8080165 +:1008E8000801326B0801336B54EC36F01FC81DF851 +:1008F80020C81EF80801D8900801253708012637B6 +:1009080008012737080128377BEC22F00801080185 +:1009180074AF91EF04F093EF04F096EF04F0080140 +:1009280008012581080108011A3F9DEF04F09FEF97 +:1009380004F0DEEF03F029C8C2FF2AC8C0FF2CC8A4 +:10094800D7FF2DC8D6FF2BC8D5FF25C816F826C84F +:1009580017F827C818F828C819F8B3EF04F01200D8 +:100968000C0E08010801796F000E08017A6FF9EC86 +:1009780042F04BEC44F008010801756F75C878F82F +:10098800F00E080178170801D89078330801D8903C +:100998007831EC0F08010801756F080108017567C7 +:1009A800D8EF04F0DAEF04F0E3EF04F0180E0801D2 +:1009B8000801726F020E0801736FC0EF05F0070E91 +:1009C80008010801C46F000E0801C56F000E080178 +:1009D8000801C26F000E0801C36F6DEC38F0ABEF71 +:1009E80005F04BEC44F008010801746F0801080198 +:1009F800746701EF05F003EF05F005EF05F0B7EFB9 +:100A080005F0080108017405D8A40DEF05F00FEFF3 +:100A180005F011EF05F0ABEF05F00801080174517E +:100A2800020AD8A41AEF05F01CEF05F076EF05F0DE +:100A3800030E08010801756124EF05F026EF05F0A3 +:100A480028EF05F0B7EF05F0000E08010801766FF2 +:100A5800000E0801776F4BEC44F008010801746F31 +:100A6800080108017451040AD8A43DEF05F03FEFCE +:100A780005F049EF05F04BEC44F008010801776FE9 +:100A88004BEC44F008010801766F180E08010801C4 +:100A9800765D020E08017759D8B055EF05F057EF8B +:100AA80005F059EF05F0B7EF05F0B50E080108019C +:100AB800765D050E08017759D8A065EF05F067EF58 +:100AC80005F070EF05F0B40E08010801726F050E0D +:100AD8000801736FC0EF05F076C872F877C873F82D +:100AE800C0EF05F0020E0801080175617EEF05F000 +:100AF80080EF05F082EF05F0B7EF05F04BEC44F01E +:100B080008010801746F08010801745108010801FF +:100B1800756191EF05F093EF05F095EF05F0B7EFEC +:100B280005F00801080174C8C4F808010801C56B7C +:100B3800000E08010801C26F000E0801C36F6DECBA +:100B480038F008010801745108010801755F0801AF +:100B58000801750708017529D8A4B5EF05F0B7EFA6 +:100B680005F0F5EF04F0180E08010801726F020E87 +:100B78000801736FC0EF05F01200000E06010601B0 +:100B8800CE6F000E0601CF6F080E08010801C46F72 +:100B9800000E0801C56F0801280E08010801C26F80 +:100BA8000801080E0801C36F6DEC38F028C8BCF8BE +:100BB80029C8BDF82FEC43F0BCC828F8BDC829F8EF +:100BC8002AC8BCF82BC8BDF82FEC43F0BCC82AF8DB +:100BD800BDC82BF82CC8BCF82DC8BDF82FEC43F0C5 +:100BE800F80E08010801BC25080108012C6FFF0E4A +:100BF80008010801BD2108012D6F080108012F51C6 +:100C08002E11D8B40AEF06F00CEF06F093EF06F0B9 +:100C18001DC8E9FF1EC8EAFF0801EECF30F8080139 +:100C2800EECF31F80801EECF32F80801EECF33F8F5 +:100C38001FC8E9FF20C8EAFF0801EECF34F8080111 +:100C4800EECF35F80801EECF36F80801EECF37F8C9 +:100C580008013C6F000E08010801386F08013C517B +:100C680008013C6F110E08010801396F08013C5159 +:100C780021C83AF822C83BF83AC8BCF83BC8BDF8C6 +:100C88002FEC43F0BCC83AF8BDC83BF80C0E08017D +:100C98000801BC6F000E0801BD6F0801300E080185 +:100CA8000801BA6F0801080E0801BB6FF2EC1EF0CC +:100CB80008010801BA1D08010801246F080108018C +:100CC800BB1D0801256F000E08010801796F000E91 +:100CD80008017A6FF9EC42F021C8A0F822C8A1F8FF +:100CE8000EEC10F0A0C826F8A1C827F8080108EEF5 +:100CF80026F00801EE5208012551ED18080124C814 +:100D0800E8FFD8B4EF18D8B48CEF06F08EEF06F0F1 +:100D180093EF06F02EEC3CF0000EC5EF06F01FC86E +:100D280041F820C842F81DC83FF81EC840F808011D +:100D3800280E080108013D6F0801080E08013E6FE2 +:100D48007EEC02F008010801236F0801080123293D +:100D5800D8A4B1EF06F0B3EF06F0B8EF06F02EEC2A +:100D68003CF0000EC5EF06F023C8A3F72CC8CEF65A +:100D78002DC8CFF607010F8107010F93010EC5EFAC +:100D880006F01200C8EF06F0C5CF12F81F0E0801D2 +:100D9800121712C813F80801146B000EC7B4010E1D +:100DA80008011313000E1413080114511311D8A4C9 +:100DB800E0EF06F0E2EF06F0C8EF06F0C580E5EFD9 +:100DC80006F0C5B0EAEF06F0ECEF06F0E5EF06F046 +:100DD800A1A6F1EF06F0F3EF06F0FAEF06F008012E +:100DE8000801106908011169C6EF07F010C82FF84B +:100DF80019EC3AF00009D8B404EF07F006EF07F051 +:100E080010EF07F0C584FD0E08010801106FFF0EF2 +:100E18000801116FC6EF07F0C5BC15EF07F017EF13 +:100E280007F0B4EF07F011C82FF819EC3AF00009F1 +:100E3800D8B421EF07F023EF07F02DEF07F0C584B2 +:100E4800FD0E08010801106FFF0E0801116FC6EFB3 +:100E580007F0C5BC32EF07F034EF07F0A8EF07F052 +:100E6800C58237EF07F0C5B23CEF07F03EEF07F059 +:100E780037EF07F0A1A643EF07F045EF07F04CEF77 +:100E880007F008010801106908011169C6EF07F0A9 +:100E9800080108011029080108012F6F19EC3AF020 +:100EA8000009D8B45AEF07F05CEF07F066EF07F0D7 +:100EB800C584FD0E08010801106FFF0E0801116FAF +:100EC800C6EF07F0C5BC6BEF07F06DEF07F09CEFBE +:100ED80007F0C58670EF07F0C5B675EF07F077EF36 +:100EE80007F070EF07F0C58AC5887BEF07F0C5B833 +:100EF80080EF07F082EF07F07BEF07F0C58485EFFE +:100F080007F0C5B48AEF07F08CEF07F085EF07F01C +:100F1800A1A691EF07F093EF07F09AEF07F0080109 +:100F28000801106908011169C6EF07F0A6EF07F07C +:100F3800C584FE0E08010801106FFF0E0801116F2D +:100F4800C6EF07F0B2EF07F0C584FE0E08010801EE +:100F5800106FFF0E0801116FC6EF07F0BEEF07F024 +:100F6800C584FE0E08010801106FFF0E0801116FFD +:100F7800C6EF07F00801C9CF10F808010801116B86 +:100F8800C6EF07F01200A0C8E9FFA1C8EAFF0801F0 +:100F9800EECFBCF80801EDCFBDF82FEC43F0A0C8A8 +:100FA800E9FFA1C8EAFF0801BCC8EEFF0801BDC8F7 +:100FB800EDFF020E08010801A025E96E000E0801E8 +:100FC8000801A121EA6E0801EECFBCF80801EDCFB7 +:100FD800BDF82FEC43F0020E08010801A025E96EC8 +:100FE800000E08010801A121EA6E0801BCC8EEFF45 +:100FF8000801BDC8EDFF040E08010801A025E96E2F +:10100800000E08010801A121EA6E0801EECFA2F83E +:101018000801EECFA3F80801EECFA4F80801EECF3F +:10102800A5F82BEC3EF0040E08010801A025E96E96 +:10103800000E08010801A121EA6E0801A2C8EEFF0E +:101048000801A3C8EEFF0801A4C8EEFF0801A5C85F +:10105800EDFFED52ED52080E08010801A025E96EDA +:10106800000E08010801A121EA6E0801EECFA2F8DE +:101078000801EECFA3F80801EECFA4F80801EECFDF +:10108800A5F82BEC3EF0080E08010801A025E96E32 +:10109800000E08010801A121EA6E0801A2C8EEFFAE +:1010A8000801A3C8EEFF0801A4C8EEFF0801A5C8FF +:1010B800EDFFED52ED520E0E08010801A025E96E74 +:1010C800000E08010801A121EA6E0801EECFBCF864 +:1010D8000801EDCFBDF82FEC43F00E0E0801080112 +:1010E800A025E96E000E08010801A121EA6E080199 +:1010F800BCC8EEFF0801BDC8EDFF100E08010801CD +:10110800A025E96E000E08010801A121EA6E080178 +:10111800EECFBCF80801EDCFBDF82FEC43F0100E70 +:1011280008010801A025E96E000E08010801A121A7 +:10113800EA6E0801BCC8EEFF0801BDC8EDFF120E3B +:1011480008010801A025E96E000E08010801A12187 +:10115800EA6E0801EECFBCF80801EDCFBDF82FEC20 +:1011680043F0120E08010801A025E96E000E0801DF +:101178000801A121EA6E0801BCC8EEFF0801BDC83C +:10118800EDFF12001DC8E9FF1EC8EAFF0801EECFF7 +:1011980028F80801EECF29F80801EECF2AF808014F +:1011A800EECF2BF81FC8E9FF20C8EAFF0801EECFF1 +:1011B8002CF80801EECF2DF80801EECF2EF8080123 +:1011C800EECF2FF80801486F000E08010801306FB4 +:1011D800080148510801486F060E08010801316FDF +:1011E8000801485121C832F822C833F832C8BCF87F +:1011F80033C8BDF82FEC43F0BCC832F8BDC833F88B +:101208000C0E08010801BC6F000E0801BD6F080133 +:10121800280E08010801BA6F0801080E0801BB6F03 +:10122800F2EC1EF008010801BA1D08010801246F3C +:1012380008010801BB1D0801256F21C8A0F822C8B4 +:10124800A1F80EEC10F0A0C826F8A1C827F80801EC +:101258000801275108010801251906E108010801BC +:101268002651080108012419D8B43DEF09F03FEFD1 +:1012780009F043EF09F02EEC3CF0BBEF09F0000E4B +:1012880008010801796F000E08017A6FF9EC42F045 +:10129800140E08010801C46F000E0801C56F08018B +:1012A800340E08010801C26F0801080E0801C36F57 +:1012B8006DEC38F00801340E08010801A06F080130 +:1012C800080E0801A16FC7EC07F0080140390F0BA1 +:1012D8000801486F0801D89048370801D890483568 +:1012E800EC0F08010801236F0801080123510801C8 +:1012F8000801215D0801486F000E08010801225904 +:101308000801496FEC0E0801482508010801216F02 +:10131800FF0E080149210801226F1DC84CF81EC89C +:101328004DF80801340E080108014A6F0801080E3B +:1013380008014B6F91ECB2F00009D8B4A6EF09F0A0 +:10134800A8EF09F0B7EF09F021C84CF822C84DF80A +:101358000801340E080108014A6F0801080E080147 +:101368004B6F29EC80F02EEC3CF0BBEF09F012003B +:10137800070107019D29D8A4C4EF09F0C6EF09F0B9 +:10138800EEEF09F0000E08010801536F000E080186 +:10139800546F450E08010801516F000E0801526F85 +:1013A8000801166F000E08010801506F0801165158 +:1013B800000E080108014C6F000E08014D6F000E69 +:1013C80008014E6F000E08014F6F22ECD7F007019D +:1013D80007019D6F070107019D29D8A4F6EF09F0C1 +:1013E800F8EF09F0FAEF09F0B0EF0AF09DC74CF8F2 +:1013F800D9EC39F008014D514C11D8A406EF0AF088 +:1014080008EF0AF00AEF0AF0B0EF0AF00001000155 +:101418006C510001000170150801166F00010001F0 +:101428006D510001000171150801176F00010001DD +:101438006E510001000172150801186F00010001CA +:101448006F510001000173150801196F05010501AD +:10145800DA5100010001701508011A6F0501050134 +:10146800DB5100010001711508011B6F0501050121 +:10147800DC5100010001721508011C6F050105010E +:10148800DD5100010001731508011D6F0801195194 +:1014980008011D190EE10801185108011C1909E17C +:1014A8000801175108011B1904E108011651080128 +:1014B8001A19D8B462EF0AF064EF0AF068EF0AF07C +:1014C8008FEC41F0B0EF0AF0060E08010801B06F8A +:1014D800000E0801B16F990E0801166F000E176F04 +:1014E80016C8AEF817C8AFF80801080E08010801B9 +:1014F800AC6F0801080E0801AD6F58EC3AF06CC0EB +:101508000EF86DC00FF86EC010F86FC011F80A0E13 +:1015180008010801BC6F000E0801BD6F0801080E24 +:1015280008010801BA6F0801080E0801BB6FF2EC48 +:101538001EF0BAC812F8BBC813F8D0920801080EFA +:1015480008010801146F0801080E0801156F15C875 +:10155800F4FF14C8F3FFFF00120096EF0BF01C0E07 +:1015680008010801C46F000E0801C56F08011D0EAF +:1015780008010801C26F0801080E0801C36F6DEC6D +:1015880038F02EEC3CF008011D0E080108017C6FB4 +:101598000801080E08017D6F9EEC30F00801080173 +:1015A8001D051E11D8A4DBEF0AF0DDEF0AF0F3EFFA +:1015B8000AF0080108012151060AD8A4E6EF0AF04A +:1015C800E8EF0AF0F3EF0AF0080108012251040AD3 +:1015D800D8B4F1EF0AF0F3EF0AF0F5EF0AF0A2EF52 +:1015E8000BF0080108012351020A2411D8A4FFEFC7 +:1015F8000AF001EF0BF015EF0BF008EE25F014EEF2 +:10160800DDF0060EEECFE6FFE82E06EF0BF02BC856 +:10161800D9F42CC8DAF42DC8DBF42EC8DCF4A2EF18 +:101628000BF00801080123052411D8A41EEF0BF0C4 +:1016380020EF0BF05EEF0BF0000100016F51080185 +:101648000801381914E1000100016E510801080170 +:1016580037190DE1000100016D5108010801361923 +:1016680006E1000100016C51080108013519D8B4E0 +:1016780040EF0BF042EF0BF044EF0BF0A2EF0BF052 +:101688002BC859F62CC85AF62DC85BF62EC85CF63E +:1016980008EE25F016EE5DF0060EEECFE6FFE82E1A +:1016A80051EF0BF00801396F010E07010701366F82 +:1016B80008013951020E08010801236F000E0801C4 +:1016C800246F06EE5DF018EE2FF0060EEECFE6FF63 +:1016D800E82E6AEF0BF059C635F85AC636F85BC6DD +:1016E80037F85CC638F808011D0E08010801786F44 +:1016F8000801080E0801796F98EC1BF00009D8A4BE +:1017080088EF0BF08AEF0BF08CEF0BF0A2EF0BF0E9 +:101718000801396F000E07010701366F08013951BA +:10172800A0EF0BF0070107013651000A01E117D7B6 +:10173800010AC0E0A0EF0BF0A2EF0BF01200FDECE5 +:1017480040F00009D8A4ABEF0BF0ADEF0BF0AFEF12 +:101758000BF089EF0CF07B0E08010801566FFF0EA5 +:101768000801576F4CEC27F00009D8A4BEEF0BF026 +:10177800C0EF0BF0C2EF0BF089EF0CF0C9EC26F0CC +:1017880065C832F866C833F867C834F868C835F8E9 +:1017980008013229D8B43329D8B43429D8B4352922 +:1017A800D8A4D9EF0BF0DBEF0BF0EBEF0BF0000157 +:1017B800988D0001988F0801366F000E0801080106 +:1017C800376F08013651ABEC42F089EF0CF0600E30 +:1017D80008010801566FFF0E0801576F4CEC27F0FF +:1017E8000009D8A4FAEF0BF0FCEF0BF0FEEF0BF0BA +:1017F80089EF0CF0C9EC26F065C82EF866C82FF8FA +:1018080067C830F868C831F8500E08010801566FEB +:10181800FF0E0801576F4CEC27F00009D8A417EF0A +:101828000CF019EF0CF01BEF0CF089EF0CF0C9EC81 +:1018380026F065C82AF866C82BF867C82CF868C867 +:101848002DF8C50E08010801566FFF0E0801576FE5 +:101858004CEC27F00009D8A434EF0CF036EF0CF06C +:1018680038EF0CF089EF0CF0C9EC26F065C822F8C7 +:1018780066C823F867C824F868C825F8D40E080194 +:101888000801566FFF0E0801576F4CEC27F000094E +:10189800D8A451EF0CF053EF0CF055EF0CF089EF92 +:1018A8000CF0C9EC26F065C826F866C827F867C8A2 +:1018B80028F868C829F80001989D32C86CF033C828 +:1018C8006DF034C86EF035C86FF02EC870F02FC8B0 +:1018D80071F030C872F031C873F02AC874F02BC8A0 +:1018E80075F02CC876F02DC877F022C878F023C898 +:1018F80079F024C87AF025C87BF026C87CF027C880 +:101908007DF028C87EF029C87FF012000701070182 +:101918007D51D8B492EF0CF094EF0CF0C1EF0CF0BD +:10192800070107017C51070107017A277E0E07018D +:1019380007017A65A2EF0CF0A4EF0CF0A9EF0CF008 +:10194800070107017C69BDEF0CF0070107017A6701 +:10195800B0EF0CF0B2EF0CF0BDEF0CF00801DA6F4D +:10196800010E070107017C6F0801DA510701070121 +:101978007D077AC7BBFF23EF0DF0070107017E51F2 +:10198800020AD8A4CAEF0CF0CCEF0CF0D0EF0CF0A0 +:101998007BC7BBFF23EF0DF0070107017E05D8A425 +:1019A800D8EF0CF0DAEF0CF021EF0DF0D1EC43F0AA +:1019B800070107017F5108010801DE5D0801DA6FA0 +:1019C80007010701805108010801DF590801DB6F91 +:1019D80007010701815108010801E0590801DC6F7E +:1019E80007010701825108010801E1590801DD6F6B +:1019F800F30EDA5D9E0EDB59000EDC59000E08016D +:101A0800DD59D8A00AEF0DF00CEF0DF01FEF0DF027 +:101A1800070107017B51FF0A070107017B6F7BC79D +:101A2800BBFFD1EC43F0DEC87FF7DFC880F7E0C822 +:101A380081F7E1C882F723EF0DF0000EBB6E0701B6 +:101A480007018651D8B42BEF0DF02DEF0DF05AEFAA +:101A58000DF00701070185510701070183277E0E55 +:101A68000701070183653BEF0DF03DEF0DF042EFF5 +:101A78000DF007010701856956EF0DF00701070111 +:101A8800836749EF0DF04BEF0DF056EF0DF00801AD +:101A9800DA6F010E07010701856F0801DA510701A6 +:101AA8000701860783C7BEFF6BEF0DF0070107012B +:101AB8008751020AD8A463EF0DF065EF0DF069EFC6 +:101AC8000DF084C7BEFF6BEF0DF0000EBE6E120066 +:101AD80008010F6F000E080108010E6F08010F5171 +:101AE8003DEF0EF0080108010D513A0AD8A47FEF26 +:101AF8000DF081EF0DF0A0EF0DF007010701015186 +:101B08000011D8A48AEF0DF08CEF0DF096EF0DF0D0 +:101B180008010F6F020E070107012F6F08010F510F +:101B28009EEF0DF008010F6F010E070107012F6FDF +:101B380008010F514CEF0EF007010701003B0701A8 +:101B4800013BF00E07010117070100510F0B0701B8 +:101B58000113F00E070100170DC872F82DEC2DF0D7 +:101B680008010F6F08010F510701070100134CEF1F +:101B78000EF0C2EF0DF0080108010E2B0101C80E8E +:101B8800080108010E25E96EEA6A0101010EEA2240 +:101B9800EF50D8A4D2EF0DF0D4EF0DF0BFEF0DF059 +:101BA8000101C80E080108010E25E96EEA6A010163 +:101BB800010EEA2208010DC8EFFF0701070100071F +:101BC800D8A001070701070101510011D8A4EFEFC0 +:101BD8000DF0F1EF0DF09EEF0DF0070107012F2B2F +:101BE8004CEF0EF0080108010D51690AD8B4FFEF57 +:101BF8000DF001EF0EF006EF0EF0070107012F6957 +:101C08009EEF0DF0070107012F2B4CEF0EF0080196 +:101C180008010D51730AD8A414EF0EF016EF0EF058 +:101C280020EF0EF008010F6F000E070107012F6F5C +:101C380008010F514CEF0EF007010701273B070180 +:101C4800283BF00E07012817070127510F0B070142 +:101C58002813F00E070127170DC872F82DEC2DF088 +:101C680008010F6F08010F510701070127134CEFF7 +:101C78000EF0070107012F51000A01E133D7010ACD +:101C880001E177D7030AAEE0010AC1E04CEF0EF09C +:101C98001200A1C768F8BEEC20F068C854F869C8FB +:101CA80055F80101000E08010801596F0101010EE4 +:101CB80008015A6F3DEC37F01A0E08010801592740 +:101CC800000E08015A230801080159510801545D02 +:101CD800080108015A5108015559D8B076EF0EF09D +:101CE80078EF0EF07CEF0EF065EC3FF02DEF0FF083 +:101CF80022EC2FF0E20E08010801576FFF0E0801D1 +:101D0800586FA1C756F830EC42F00801546F000E26 +:101D180008010801536F08015451130E0801080106 +:101D2800536599EF0EF09BEF0EF09DEF0EF0D8EF94 +:101D38000EF00401E30E080108015325E96EEA6A72 +:101D48000401040EEA22EF5008010801586F0DEC57 +:101D58003FF008010801576FA1C756F801EC15F0CC +:101D68000401E30E080108015325E96EEA6A04013B +:101D7800040EEA22EF5008010801646FE1EC3EF01E +:101D880008010801576FA1C756F801EC15F00801C2 +:101D98000801532B130E080108015365D6EF0EF006 +:101DA800D8EF0EF09DEF0EF00101000E08010801BA +:101DB800596F0101010E08015A6F3DEC37F0080117 +:101DC8000801595108010801586F0DEC3FF008014E +:101DD8000801576FA1C756F801EC15F00101000E74 +:101DE80008010801596F0101010E08015A6F3DEC05 +:101DF80037F008010801595108010801646FE1EC46 +:101E08003EF008010801576FA1C756F801EC15F01C +:101E18000801546F3A0E08010801576F0801545120 +:101E2800A1C756F801EC15F00101000E08010801E0 +:101E3800576F0101010E0801586FA1C756F845EC0C +:101E480042F0A1C768F8F6EC3BF065EC3FF016EC01 +:101E580044F01200FC0E92160E01FE8B96928D92A3 +:101E680036EF0FF00E010E01FDA13DEF0FF03FEF31 +:101E78000FF036EF0FF00801096F000E060106019A +:101E8800D56F080109510601D581000E060106012A +:101E9800FC6F000E0601FD6F000E0E010E01E86FCB +:101EA800000E0E01E96FCD0E0E010E01EC6F0A0E49 +:101EB8000E010E01ED6FCD0E0E010E01EA6F0A0E36 +:101EC8000E01EB6FCE0E0E010E01E46F0A0E0E012D +:101ED800E56FCE0E0E010E01E26F0A0E0E01E36FE2 +:101EE8000801096F000E08010801C06F08010951B7 +:101EF80064EC44F00801096F0D0E0E010E01A06F8D +:101F08000801095100F00801096F320E0E010E0197 +:101F1800A26F0801095100F00801096F120E0E01A5 +:101F28000E01A46F0801095100F00801096F400E65 +:101F38000E010E01A36F0801095100F00801096F95 +:101F4800120E0E010E01A66F0801095100F00801DA +:101F5800096F0C0E0E010E01A76F0801095100F060 +:101F68000801096FEE0E0E010E01AA6F0801095152 +:101F780000F00801096F050E0E010E01AB6F080194 +:101F8800095100F099C084FE00F09AC085FE00F067 +:101F98009BC082FE00F09CC083FE00F09DC080FEC6 +:101FA80000F09EC081FE00F0100E080108010B6FC2 +:101FB800010E08010C6F0801096F100E08010801D5 +:101FC8000A6F0801095199EC40F0720E08010801E6 +:101FD8000B6F340E08010C6F0801096F140E08010D +:101FE80008010A6F0801095199EC40F0000E080138 +:101FF80008010B6F000E08010C6F0801096F000E35 +:10200800080108010A6F0801095199EC40F00E0116 +:10201800DF851200F1C6A8F8F2C6A9F8F3C6AAF837 +:10202800F4C6ABF8E0CEA2F8E1CEA3F8A9EF10F021 +:10203800A0C8A6F8A1C8A7F8150E08010801A05D58 +:10204800000E0801A159D8A02CEF10F02EEF10F0C7 +:1020580035EF10F0140E08010801A66F000E0801F4 +:10206800A76FA6C8C4F8A7C8C5F80801AC0E080130 +:102078000801C26F0801080E0801C36F6DEC38F043 +:1020880008010801A65108010801A05F080108011C +:10209800A75108010801A15B08010801A6A157EF93 +:1020A80010F059EF10F069EF10F00801AC0E0801BC +:1020B8000801A625E96EEA6A0801080EEA22000E60 +:1020C800EF6E08010801A64BA72B0801AC0E08010A +:1020D8000801A46F0801080E0801A56F9EEF10F013 +:1020E8000801A4C8E9FF0801A5C8EAFF0801020E13 +:1020F8000801A427000E0801A523EECFC0F8EDCFF4 +:10210800C1F80801C05108010801A8270801C151F8 +:1021180008010801A923000E08010801AA23000EDE +:1021280008010801AB23020E08010801A65F000E92 +:102138000801A75B08010801A751A611D8A4A7EFB9 +:1021480010F0A9EF10F074EF10F008010801A15188 +:10215800A011D8A4B2EF10F0B4EF10F01CEF10F0FB +:10216800A2C8E0FEA3C8E1FE08010801A8510801C1 +:102178000801AA2508010801A86F08010801A9514A +:1021880008010801AB210801A96F0801AA6BD8B0A2 +:10219800AA2B0801AB6B080108EEAAF0EE50080163 +:1021A8000801A827ED5008010801A9230801080122 +:1021B800A81D08010801A06F08010801A91D080150 +:1021C800A16FE7EF10F01200140E0801080158255E +:1021D800E96E000E080108015921EA6EEF50080166 +:1021E800606F3F0E08016017180E0801602708018C +:1021F80060510801080158250801616FE86A080163 +:1022080060BFE8680801080159210801626F61C8C8 +:102218005EF862C85FF8140E080108015825E96ED7 +:10222800000E080108015921EA6E080108015C51F5 +:10223800EE2608015D51EE22000EEE22ED22ED524F +:10224800ED52B5EF11F008015AC8F6FF08015BC856 +:10225800F7FF000EF86E5EC8E9FF5FC8EAFF0800E6 +:10226800F5CFEFFF080108015A4B5B2B0801080165 +:102278005E4B5F2B580E0801080158250801606F56 +:10228800000E0801080159210801616F0801615118 +:10229800080108015F1905E10801605108010801FA +:1022A8005E19D8A45AEF11F05CEF11F0B0EF11F0FD +:1022B800100E08010801582508010801836F000E57 +:1022C8000801080159210801846F0C0E0801080152 +:1022D800582508010801816F000E080108015921DD +:1022E8000801826F080E0801080158250801080135 +:1022F8007F6F000E0801080159210801806F040E44 +:10230800080108015825080108017D6F000E080121 +:102318000801592108017E6F58C87BF859C87CF814 +:10232800180E08010801582508010801796F000EE8 +:1023380008010801592108017A6F80EC9BF0180EFA +:10234800080108015825080108015E6F000E080100 +:102358000801592108015F6F080108015C07D8A02E +:102368005D07080108015D515C11D8A4BEEF11F0AA +:10237800C0EF11F027EF11F01200140E0801080148 +:102388005825E96E000E080108015921EA6EEF5040 +:102398000801606F3F0E08016017180E08016027DA +:1023A800080160510801080158250801616FE86AB1 +:1023B800080160BFE8680801080159210801626F37 +:1023C80061C85EF862C85FF8140E08010801582554 +:1023D800E96E000E080108015921EA6E080108019A +:1023E8005C51EE2608015D51EE22000EEE22ED2230 +:1023F800ED52ED5289EF12F05AC8E9FF5BC8EAFFC7 +:102408005EC8E1FF5FC8E2FFEFCFE7FF0801080100 +:102418005A4B5B2B080108015E4B5F2B580E0801D5 +:10242800080158250801606F000E080108015921AC +:102438000801616F08016151080108015F1905E190 +:1024480008016051080108015E19D8A42EEF12F0A6 +:1024580030EF12F084EF12F0100E08010801582531 +:1024680008010801836F000E0801080159210801BD +:10247800846F0C0E08010801582508010801816FB6 +:10248800000E0801080159210801826F080E080191 +:1024980008015825080108017F6F000E080108018E +:1024A80059210801806F040E080108015825080108 +:1024B80008017D6F000E08010801592108017E6F8F +:1024C80058C87BF859C87CF8180E08010801582527 +:1024D80008010801796F000E080108015921080157 +:1024E8007A6F80EC9BF0180E080108015825080146 +:1024F80008015E6F000E08010801592108015F6F8D +:10250800080108015C07D8A05D07080108015D51B2 +:102518005C11D8A492EF12F094EF12F000EF12F0D1 +:102528001200000E080108012D659DEF12F09FEFC3 +:1025380012F0A1EF12F065EF13F02DC871F81DEC41 +:102548002BF00BC00DF00CC00EF043EF13F0DCECD9 +:1025580040F06CEC33F065EF13F06CEC33F065EFA2 +:1025680013F008012E6F010E08010801736F0801AE +:102578002E5108012F6F110E08010801726F080112 +:102588002F519FECA1F030502F10D8A4CEEF12F0AD +:10259800D0EF12F0D2EF12F0E5EF12F000EE29F0D2 +:1025A80010EE07F0E652EE52ED50E518EFCFE8FFD7 +:1025B800D8B4E718D8A4E3EF12F0E5EF12F0B5EFBE +:1025C80012F008012E6F080E176E08012E5165EFE4 +:1025D80013F008012E6F010E08010801736F08013E +:1025E8002E5108012F6F110E08010801726F0801A2 +:1025F8002F519FECA1F030502F10D8A406EF13F004 +:1026080008EF13F00AEF13F01DEF13F000EE29F0B6 +:1026180010EE07F0E652EE52ED50E518EFCFE8FF66 +:10262800D8B4E718D8A41BEF13F01DEF13F0EDEFA3 +:1026380012F008012E6F0C0E176E08012E5165EF6F +:1026480013F008012E6F0D0E176E08012E5165EF5D +:1026580013F008012E6F000E08010801736F0801BE +:102668002E5108012F6F140E08010801726F08011E +:102678002F519FECA1F06CEC33F065EF13F017507D +:10268800000A01E16AD7010A01E161D7030A01E101 +:1026980064D7010A01E161D7060A01E15ED7030A9E +:1026A80001E15FD7010A01E15CD70F0AD2E0010A14 +:1026B800D0E0020A8EE0070ACCE0020AC2E02DEF61 +:1026C80013F012000801606F690E08010801646FB9 +:1026D800080160518FEC3FF0080156515311541115 +:1026E8005511D8A47AEF13F07CEF13F088EF13F0AC +:1026F8000801606F300E08010801646F080160511D +:102708008FEC3FF02CEF14F00801606F000E080109 +:102718000801576F08016051070E08010801576545 +:1027280098EF13F09AEF13F09CEF13F0C9EF13F042 +:102738000801580E080108015725E96EEA6A0801E0 +:10274800080EEA2253C864F8E1EC3EF0EF6E040E7E +:102758000801606FD8900801080156330801553305 +:1027680008015433080153330801602FAEEF13F00A +:1027780008010801572B070E080108015765C7EF24 +:1027880013F0C9EF13F09CEF13F00801606F080E07 +:1027980008010801576F08016051080108015767CF +:1027A800D8EF13F0DAEF13F0DCEF13F001EF14F0C9 +:1027B80057C860F8FF0E080160270801580E080185 +:1027C8006025E96EEA6A0801080EEA22EF50300A2D +:1027D800D8B4F1EF13F0F3EF13F0F5EF13F001EFC6 +:1027E80014F0080108015707080108015767FFEFAF +:1027F80013F001EF14F0DCEF13F00801080157673C +:1028080008EF14F00AEF14F00CEF14F02CEF14F0AA +:1028180057C860F8FF0E080160270801580E080124 +:102828006025E96EEA6A0801080EEA22EF500801FD +:102838000801646F8FEC3FF0080108015707080191 +:10284800080157672AEF14F02CEF14F00CEF14F07E +:102858000801606F730E08010801646F0801605178 +:102868008FEC3FF01200140E08010801C46F000E2F +:102878000801C56F0801270E08010801C26F080189 +:10288800080E0801C36F6DEC38F0080108012751E4 +:10289800F00B400AD8B453EF14F055EF14F058EF8A +:1028A80014F0000E00EF15F01F0E080108012D1599 +:1028B80008013B6FFF0E080108012E1508013C6F47 +:1028C80008013C513B11D8B46CEF14F06EEF14F0D2 +:1028D80071EF14F0000E00EF15F027C83BF80F0E4B +:1028E80008013B170801D8903B370801D8903B35C1 +:1028F80006010601FA6F06010801FAC63FF8080149 +:102908000801406B000E080108013D6F000E080128 +:102918003E6FF0EC36F03DC825F83EC826F80601B3 +:102928000801FAC67BF8080108017C6B64EC3CF0EE +:102938000801080126512511D8B4A5EF14F0A7EF16 +:1029480014F0AAEF14F0000E00EF15F00801270E9E +:1029580008010801BA6F0801080E0801BB6F5FEC97 +:102968002CF0080108011E511D11D8B4BEEF14F057 +:10297800C0EF14F0D0EF14F01DC8E9FF1EC8EAFF3D +:10298800080137C8EEFF080138C8EEFF080139C84A +:10299800EEFF08013AC8EEFF1FC8E9FF20C8EAFFAA +:1029A800080133C8EEFF080134C8EEFF080135C836 +:1029B800EEFF080136C8EEFF21C8E9FF22C8EAFF8A +:1029C800080130C8EFFF06010601FA5108010801A5 +:1029D800295D08013B6F000E080108012A5908010A +:1029E8003C6F23C8E9FF24C8EAFF3BC8EEFF3CC898 +:1029F800EDFF010E00EF15F01200000E08010801AE +:102A0800566509EF15F00BEF15F00DEF15F0C7EF50 +:102A180015F056C871F81DEC2BF056C868F8BEECD6 +:102A280020F068C858F869C859F8080108015951D0 +:102A38005811D8A422EF15F024EF15F026EF15F061 +:102A4800C7EF15F00801080158055911D8A42FEF50 +:102A580015F031EF15F035EF15F056C868F8F6ECBB +:102A68003BF019B03AEF15F03CEF15F067EF15F0B1 +:102A780000EE03F0EECF5AF8EDCF5BF801500801F5 +:102A88005A5F025008015B5BD89008015B3108016E +:102A98005D6F08015A3108015C6F0801080158513F +:102AA80008015C5D08010801595108015D59D8A069 +:102AB80060EF15F062EF15F067EF15F056C868F88B +:102AC800F6EC3BF01980010E08010801AA6F000E10 +:102AD8000801AB6F08015A6F010E08010801A96FC0 +:102AE80008015A510801570E08010801A76F08018B +:102AF800080E0801A86F1CC0A6F807C0A4F808C0F3 +:102B0800A5F8A0EC23F000EE03F010EE07F0E62A9B +:102B1800000EE522E652EE52ED50E55C02E1EF5080 +:102B2800E75CD8A09AEF15F09CEF15F0A0EF15F030 +:102B380001C007F002C008F0080108015805591142 +:102B4800D8A4A9EF15F0ABEF15F0B1EF15F056C802 +:102B580068F8F6EC3BF0C5EF15F018BAB6EF15F0CB +:102B6800B8EF15F0C5EF15F0188A5AEC42F0060ECA +:102B780008010801A125136E000E08010801A22111 +:102B8800146EC7EF15F0120006EE95F018EE0DF072 +:102B9800140EEECFE6FFE82ECDEF15F00801216FF9 +:102BA800140E08010801676F0801215108010D0E74 +:102BB80008010801656F0801080E0801666F0EEC30 +:102BC80018F00009D8A4EBEF15F0EDEF15F0EFEFD2 +:102BD80015F08CEF16F0000E08010801676FFF0E64 +:102BE8000801686F08010D0E08010801656F0801EA +:102BF800080E0801666F49EC29F008016651651155 +:102C0800D8A409EF16F00BEF16F00FEF16F070ECE2 +:102C180034F08CEF16F0B60E08010801676FFF0E4E +:102C28000801686F08010D0E08010801656F0801A9 +:102C3800080E0801666F49EC29F008016651651114 +:102C4800D8A429EF16F02BEF16F02FEF16F0CCECE6 +:102C5800D3F08CEF16F09F0E08010801676FFF0E86 +:102C68000801686F08010D0E08010801656F080169 +:102C7800080E0801666F49EC29F0080166516511D4 +:102C8800D8A449EF16F04BEF16F04FEF16F0A3EC6F +:102C98000BF08CEF16F0770E08010801676FFF0E36 +:102CA8000801686F08010D0E08010801656F080129 +:102CB800080E0801666F49EC29F008016651651194 +:102CC800D8A469EF16F06BEF16F06FEF16F0C5ECAD +:102CD80029F08CEF16F00C0E08010801676FFF0E43 +:102CE8000801686F08010D0E08010801656F0801E9 +:102CF800080E0801666F49EC29F008016651651154 +:102D0800D8A489EF16F08BEF16F08CEF16F0FF00C1 +:102D18001200040E08010801C46F000E0801C56FF7 +:102D28000801210E08010801C26F0801080E0801F8 +:102D3800C36F6DEC38F0080108012151080A22110F +:102D4800D8A4A9EF16F0ABEF16F04DEF17F01FC897 +:102D58003FF820C840F8140E080108013D6F000E26 +:102D680008013E6FF0EC36F008013E513D11D8B431 +:102D7800C0EF16F0C2EF16F0C4EF16F04DEF17F0E3 +:102D88000801256F000E08010801216F080125516F +:102D9800080E080108012327080E0801080123610D +:102DA800D8EF16F0DAEF16F0E9EF16F0080108018F +:102DB800242B080108012467E4EF16F0E6EF16F06B +:102DC800E9EF16F008010801232BEBEF16F0CBEC26 +:102DD8003DF00009D8B4F3EF16F0F5EF16F0EBEF7D +:102DE80016F0DD0E08010801AC6F0A0E0801AD6F80 +:102DF8000BEC44F01FC8A3F820C8A4F80801256FFD +:102E0800010E08010801A26F080125511DC8A0F88C +:102E18001EC8A1F8CAEC18F0040E08010801C26F18 +:102E2800000E0801C36F0801210E08010801C06FD8 +:102E38000801080E0801C16FBBEC40F0FC0E080148 +:102E480008011F2508010801B06FFF0E08010801DD +:102E580020210801B16FFF0E08010801AE6FFF0EB7 +:102E68000801AF6FFF0E08010801AC6FFF0E0801E3 +:102E7800AD6F3CECDDF041EF17F08EEC43F000094C +:102E8800D8B449EF17F04BEF17F041EF17F003EC08 +:102E980039F0120027C838F828C839F867EC35F037 +:102EA80008012D6F690E08010801646F08012D5192 +:102EB8008FEC3FF0080108012A512911D8A467EFC7 +:102EC80017F069EF17F075EF17F008012D6F300E46 +:102ED80008010801646F08012D518FEC3FF003EFE2 +:102EE80018F008012D6F000E080108012C6F080169 +:102EF8002D51080108012B51080108012C5DD8A0AB +:102F080088EF17F08AEF17F08CEF17F0B4EF17F08F +:102F1800080108012C51080108012925E96E08015A +:102F2800000E080108012A21EA6EEF50300AD8B4D1 +:102F3800A0EF17F0A2EF17F0A4EF17F0B4EF17F017 +:102F4800080108012C2B080108012B510801080170 +:102F58002C5DD8A0B2EF17F0B4EF17F08CEF17F094 +:102F6800080108012B51080108012C5DD8A0BFEF0A +:102F780017F0C1EF17F0C3EF17F003EF18F00801CF +:102F880008012C51080108012925E96E0801000EE5 +:102F9800080108012A21EA6EEF5008010801586F5C +:102FA8000DEC3FF008010801646F8FEC3FF0080159 +:102FB80008012C51080108012925E96E0801000EB5 +:102FC800080108012A21EA6EEF5008010801646F20 +:102FD800E1EC3EF008010801646F8FEC3FF0080156 +:102FE80008012C2B080108012B51080108012C5D50 +:102FF800D8A001EF18F003EF18F0C3EF17F008019D +:103008002D6F730E08010801646F08012D518FECB4 +:103018003FF0120008016B6F000E08010801696F8C +:1030280008016B5108016B6F000E080108016A6FF7 +:1030380008016B5149EF18F00101000E0401040169 +:10304800FF25E96EEA6A0101010EEA22EF50080144 +:103058000801686F04010401FF2B08010801685189 +:103068003A0AD8A43AEF18F03CEF18F03EEF18F0FF +:1030780053EF18F008016A3BF00E6A1768C872F837 +:103088002DEC2DF0080108016A13C70E0401040194 +:10309800FF6551EF18F053EF18F020EF18F0080112 +:1030A8006AC86BF808016C6BFF0E080108016725F8 +:1030B80008016D6F08016E6BFF0E08016E23080191 +:1030C8006E51800A08016F6F08016B5108016D5D30 +:1030D80008016C51800A08016F59D8B076EF18F0D2 +:1030E80078EF18F081EF18F0080108016A5104011F +:1030F8000401FF27000EC9EF18F008016B6F000EDE +:1031080008010801696F08016B51AAEF18F0010165 +:10311800000E04010401FF25E96EEA6A0101010EAF +:10312800EA22080108016951080108016525E16ED4 +:103138000801000E080108016621E26EEFCFE7FFE3 +:1031480004010401FF2B08010801692B080108018B +:103158006A5108010801695DD8A0B5EF18F0B7EF0A +:1031680018F08BEF18F0080108016A5108010801EE +:103178006525E96E0801000E080108016621EA6E5E +:10318800000EEF6E010EC9EF18F012000801B96FBA +:10319800140E06010601FA6F0801B9510801B96F4A +:1031A800450E08010801A56F0801B9510801B96F5A +:1031B800000E08010801A66F0801B951140E080194 +:1031C8000801A32508010801A76F000E08010801DE +:1031D800A4210801A86F07010701204B212B20C754 +:1031E800A9F821C7AAF8000E08010801AB6F000E64 +:1031F8000801AC6F0801B96F640E08010801AD6FD2 +:103208000801B951A2C8AEF8000E08010801AF6F55 +:10321800000E0801B06F6CC0B1F86DC0B2F86EC096 +:10322800B3F86FC0B4F8A0C8E9FFA1C8EAFF080165 +:10323800EECFB5F80801EECFB6F80801EECFB7F833 +:103248000801EECFB8F80801A50E08010801BA6F09 +:103258000801080E0801BB6F5FEC2CF0140E080182 +:103268000801BC6F000E0801BD6F0801A50E08011A +:103278000801BA6F0801080E0801BB6FF2EC1EF0D6 +:10328800BAC8AFF8BBC8B0F8140E08010801A325E6 +:1032980008010801BD6F000E08010801A4210801FA +:1032A800BE6F0801B96F000E08010801BC6F080164 +:1032B800B951040E08010801A02508010801BA6FD8 +:1032C800000E08010801A1210801BB6FC4EC33F00E +:1032D800140E08010801C26F000E0801C36F08012F +:1032E800A50E08010801C06F0801080E0801C16F8A +:1032F800BBEC40F080EF19F012004CC850F84DC8F4 +:1033080051F8080150C8F6FF080151C8F7FF000E30 +:10331800F86E08000801F5CF4FF808010801504B76 +:10332800512B080108014F51D8B49DEF19F09FEFB8 +:1033380019F0CBEF19F0080108014F512E0AD8B443 +:10334800A8EF19F0AAEF19F0CBEF19F0080108015E +:103358004F512F0AD8B4B3EF19F0B5EF19F0CBEFEE +:1033680019F0080108014F512C0AD8B4BEEF19F022 +:10337800C0EF19F0CBEF19F0080108014F513E0AD0 +:10338800D8A4C9EF19F0CBEF19F085EF19F00801AF +:1033980008014C5108010801505D0801526F0801ED +:1033A8005205080108014E6F4EC853F867EC3DF00E +:1033B800080108014EC855F808010801566B4CC8A9 +:1033C80053F84DC854F853EC31F0010E08010801C8 +:1033D8005327000E0801542308010801535108011E +:1033E80008014C27080108015451080108014D2320 +:1033F800080108014F51D8B404EF1AF006EF1AF08B +:1034080027EF1AF0080108014F512F0AD8B40FEF1F +:103418001AF011EF1AF027EF1AF0080108014F51BE +:103428002C0AD8B41AEF1AF01CEF1AF027EF1AF08A +:10343800080108014F513E0AD8A425EF1AF027EFDA +:103448001AF029EF1AF02BEF1AF085EF19F008019E +:10345800526F000E08010801536F0801525167ECC2 +:103468003DF012004CC850F84DC851F850C8E9FF5B +:1034780051C8EAFFEF50080108014F6F0801080121 +:10348800504B512B080108014F51D8B44EEF1AF098 +:1034980050EF1AF07CEF1AF0080108014F512E0A7C +:1034A800D8B459EF1AF05BEF1AF07CEF1AF0080164 +:1034B80008014F512F0AD8B464EF1AF066EF1AF0DA +:1034C8007CEF1AF0080108014F512C0AD8B46FEFAD +:1034D8001AF071EF1AF07CEF1AF0080108014F5149 +:1034E8003E0AD8A47AEF1AF07CEF1AF03AEF1AF0F5 +:1034F800080108014C5108010801505D0801526F8C +:1035080008015205080108014E6F4EC853F867ECD0 +:103518003DF0080108014EC855F808010801566B2E +:103528004CC853F84DC854F8F9EC30F0010E0801B6 +:1035380008015327000E08015423080108015351BC +:10354800080108014C270801080154510801080125 +:103558004D23080108014F51D8B4B5EF1AF0B7EF61 +:103568001AF0D8EF1AF0080108014F512F0AD8B401 +:10357800C0EF1AF0C2EF1AF0D8EF1AF008010801EC +:103588004F512C0AD8B4CBEF1AF0CDEF1AF0D8EF80 +:103598001AF0080108014F513E0AD8A4D6EF1AF0D4 +:1035A800D8EF1AF0DAEF1AF0DCEF1AF03AEF1AF067 +:1035B8000801526F000E08010801536F08015251AB +:1035C80067EC3DF012004CC8E9FF4DC8EAFFEECFAA +:1035D80050F8EECF51F8EECF52F8EECF53F8040181 +:1035E8000401DC510801531911E104010401DB5104 +:1035F800080152190BE104010401DA5108015119BB +:1036080005E104010401D95108015019D8B40FEF9C +:103618001BF011EF1BF083EF1BF004010401DC51D8 +:1036280000010001771914E104010401DB510001D4 +:10363800000176190DE104010401DA5100010001CD +:10364800751906E104010401D9510001000174193A +:10365800D8A431EF1BF033EF1BF094EF1BF04CC8EC +:10366800E9FF4DC8EAFFEECF50F8EECF51F8EECFA4 +:1036780052F8EECF53F8000100016C5108015019BF +:103688000801546F000100016D510801511908012A +:10369800556F000100016E51080152190801566F5B +:1036A800000100016F51080153190801576F00010B +:1036B80000017051080154150801586F00010001FC +:1036C8007151080155150801596F00010001725127 +:1036D8000801561508015A6F0001000173510801CD +:1036E800571508015B6F08015B51581159115A11A0 +:1036F800D8B481EF1BF083EF1BF094EF1BF004EEBE +:10370800DDF008014EC8E1FF08014FC8E2FF060ED0 +:10371800EECFE6FFE82E8CEF1BF0010E97EF1BF0C3 +:10372800000E97EF1BF012009AEF1BF0CBEC3DF068 +:103738000009D8B4A2EF1BF0A4EF1BF09AEF1BF01E +:10374800CF0E08010801AC6F0A0E0801AD6F0BEC33 +:1037580044F078C8E9FF79C8EAFF010EEE6E000E62 +:10376800ED6E020E080108017825E96E000E0801C9 +:1037780008017921EA6E000EEE6E080EED6E040E59 +:10378800080108017825E96E000E08010801792171 +:10379800EA6E060EEF6E050E080108017825E96E3F +:1037A800000E080108017921EA6E040EEF6E060E7C +:1037B80008010801B06F000E0801B16F990E0801E9 +:1037C8007A6F000E7B6F7AC8AEF87BC8AFF8080E28 +:1037D80008010801782508010801AC6F000E0801EE +:1037E800080179210801AD6F58EC3AF00E0E080176 +:1037F80008017825E96E000E080108017921EA6EB2 +:1038080000016CC0EEFF00016DC0EEFF00016EC04C +:10381800EEFF00016FC0EEFF78C87CF879C87DF82C +:103828009EEC30F01C0E08010801BD6F000E080167 +:10383800BE6F08017A6F060E08010801BC6F080107 +:103848007A51120E08010801782508010801BA6F9B +:10385800000E0801080179210801BB6FC4EC33F0A0 +:103868001C0E08010801C26F000E0801C36F78C85A +:10387800C0F879C8C1F8BBEC40F003EC39F0010E90 +:1038880046EF1CF0120008011B6F000E080108012A +:10389800186F08011B510801080116AF56EF1CF0FC +:1038A80058EF1CF067EF1CF008010801156D0801BE +:1038B800161FD8B0162B08011B6F010E080108014E +:1038C800186F08011B510801080114AF6EEF1CF0B6 +:1038D80070EF1CF07BEF1CF008010801136D080164 +:1038E800141FD8B0142B010E08010801181B000E74 +:1038F80008010801196F000E08011A6F0801080174 +:1039080016511511D8B48BEF1CF08DEF1CF0DCEFBD +:103918001CF008011B6F010E08010801176F080150 +:103928001B51A0EF1CF00801D890080115370801B9 +:10393800163708010801172B0801080116AFA7EF71 +:103948001CF0A9EF1CF097EF1CF00801D8900801B3 +:10395800193708011A37080108011551080108012B +:10396800135D080108011651080108011459D8A06F +:10397800C0EF1CF0C2EF1CF0D1EF1CF008010801E9 +:10398800155108010801135F0801080116510801C3 +:103998000801145B0801080119810801D890080181 +:1039A80016330801153308010801172FA9EF1CF079 +:1039B800080108011851D8B4E4EF1CF0E6EF1CF038 +:1039C800EDEF1CF008010801196D08011A1FD8B0A5 +:1039D8001A2B19C813F81AC814F8F3EF1CF01200C0 +:1039E800990E08010801566FFF0E0801576F4CEC3D +:1039F80027F00009D8A403EF1DF005EF1DF007EF2D +:103A08001DF0A0EF1DF0C9EC26F065C8F8F566C8F2 +:103A1800F9F567C8FAF568C8FBF5CF0E0801080183 +:103A2800566FFF0E0801576F4CEC27F00009D8A419 +:103A380020EF1DF022EF1DF024EF1DF0A0EF1DF088 +:103A4800C9EC26F065C814F766C815F78C0E08018E +:103A58000801566FFF0E0801576F4CEC27F000095C +:103A6800D8A439EF1DF03BEF1DF03DEF1DF0A0EF9E +:103A78001DF0C9EC26F065C818F766C819F76DEC93 +:103A880044F00801556F000E08010801536F080142 +:103A98005551090E08010801536555EF1DF057EF00 +:103AA8001DF059EF1DF09EEF1DF00801556F020E35 +:103AB80008010801566F0801555177EC44F039ECBC +:103AC8002AF00801556F000E08010801546F08011B +:103AD80055510A0E08010801546575EF1DF077EF7E +:103AE8001DF079EF1DF091EF1DF00E0E0801556FD6 +:103AF800850EE82E7DEF1DF0552F7DEF1DF000D0CF +:103B080008010801542B0A0E0801080154658FEFBB +:103B18001DF091EF1DF079EF1DF008010801532BFE +:103B2800090E0801080153659CEF1DF09EEF1DF07A +:103B380059EF1DF05FEC44F01200000E0801080177 +:103B4800006F000E0801016F000E0801026F000EE1 +:103B58000801036F000E0E010E01B66F000E0E0174 +:103B68000E01B76F000E926E000E936E000E946EEB +:103B7800000E956E000E966E000E976E000E986EF3 +:103B8800000E806E000E816E000E826E000E836E37 +:103B9800000E846E000E856E0801046F400E9B6E49 +:103BA800080104510801046F0F0EC16E0801045189 +:103BB80042EC44F09CEC43F002EC3DF069EC44F03C +:103BC8005FEC01F0FEECE7F080EC43F0D1EC3AF06A +:103BD800420E080108010B6F370E08010C6F08012F +:103BE800046F140E080108010A6F0801045199ECCA +:103BF80040F0CBECCCF07DEC44F0C4EC43F0080191 +:103C08000801005108010801A15D0801046F0801BD +:103C18000801015108010801A2590801056F0801AE +:103C28000801025108010801A3590801066F08019B +:103C38000801035108010801A4590801076FF20E91 +:103C4800045D9E0E0559000E0659000E080107591D +:103C5800D8A031EF1EF033EF1EF03DEF1EF0C4EC9C +:103C680043F0A1C800F8A2C801F8A3C802F8A4C884 +:103C780003F81AECC7F050ECE2F0EFECC4F019ECE2 +:103C8800B6F046EC26F00400FDEF1DF014EF00F04E +:103C980012C817F811C816F882EC2FF008010801AD +:103CA800136F0701070113675CEF1EF05EEF1EF04C +:103CB80066EF1EF00801146F000E070107013B6F45 +:103CC80008011451080108011351FE0AD8A46FEF26 +:103CD8001EF071EF1EF07AEF1EF0FE0E08010801CB +:103CE800116FFF0E0801126FF1EF1EF008010801B5 +:103CF8001329D8A482EF1EF084EF1EF08BEF1EF07C +:103D080008010801116908011269F1EF1EF00701A5 +:103D180007011151040AD8A494EF1EF096EF1EF083 +:103D2800A2EF1EF007013B3BF00E3B170801146F92 +:103D3800000E07010701116F08011451080108015D +:103D48001351D8B4AAEF1EF0ACEF1EF0C1EF1EF06D +:103D580011C714F8010E0801156F0801142BB8EFEC +:103D68001EF0D890080115370801142FB5EF1EF082 +:103D780008011551070107013B1307010701132B20 +:103D880007010701112B080E070107011361CFEF87 +:103D98001EF0D1EF1EF0D8EF1EF0080108011169DE +:103DA80008011269F1EF1EF00801146F000E0701F7 +:103DB8000701136F080114510801146F000E070161 +:103DC8000701116F08011451070108013BC711F8D9 +:103DD80008010801126BF1EF1EF01200D8900801DB +:103DE8000801BD3108010801BF6F08010801BC3195 +:103DF8000801BE6FBAC8C0F8BBC8C1F8000E0801F8 +:103E08000801C26F000E0801C36F000E0801C46FDD +:103E1800000E0801C56F34EF1FF00801C0C8E9FFA4 +:103E28000801C1C8EAFF0801020E0801C027000EF8 +:103E38000801C123EECFC6F8EDCFC7F80801C65177 +:103E480008010801C2270801C75108010801C32356 +:103E5800000E08010801C423000E08010801C5234B +:103E680008010801BE07D8A0BF070801BE29D8B4B9 +:103E7800BF29D8A442EF1FF044EF1FF011EF1FF045 +:103E880008010801BCA14BEF1FF04DEF1FF060EFD8 +:103E98001FF0C0C8E9FFC1C8EAFFEF500801C66FAC +:103EA8000801C65108010801C227000E0801C323F2 +:103EB8000801C4230801C52308010801C2510801EB +:103EC8000801C42508010801C26F08010801C3518F +:103ED80008010801C5210801C36F0801C46BD8B0E7 +:103EE800C42B0801C56B080108EEC4F0EE500801A8 +:103EF8000801C227ED5008010801C3230801080181 +:103F0800C21D08010801BA6F08010801C31D080194 +:103F1800BB6F8FEF1FF01200000E08010801376F0A +:103F2800000E0801386F000E0801396F000E0801F5 +:103F38003A6F08013551321133113411D8B4A7EF53 +:103F48001FF0A9EF1FF01CEF20F008013B6F010ED6 +:103F580008010801366F08013B51C0EF1FF0080146 +:103F6800D89008013237080133370801343708017F +:103F7800353708010801362B0801080135AFC7EFAE +:103F88001FF0C9EF1FF0B3EF1FF00801D890080128 +:103F98003737080138370801393708013A37080137 +:103FA80008013251080108012E5D0801080133514A +:103FB800080108012F5908010801345108010801B6 +:103FC8003059080108013551080108013159D8A0B4 +:103FD800F0EF1FF0F2EF1FF00DEF20F008010801DD +:103FE8003251080108012E5F080108013351080108 +:103FF80008012F5B08010801345108010801305BF2 +:1040080008010801355108010801315B0801080160 +:1040180037810801D8900801353308013433080185 +:1040280033330801323308010801362FC9EF1FF076 +:1040380037C82EF838C82FF839C830F83AC831F8D8 +:1040480026EF20F0120007010701A529D8A42FEFB9 +:1040580020F031EF20F056EF20F0FEC653F8FFC6EF +:1040680054F8FEC651F8FFC652F80801336F040E23 +:1040780008010801506F08013351630E0801346FBD +:10408800060E356F080134C84CF8080135C84DF8DC +:10409800080108014E6B08014F6B22ECD7F00701AD +:1040A8000701A56F07010701A529D8A45EEF20F035 +:1040B80060EF20F062EF20F0BDEF20F0A5C74CF8CC +:1040C80093EC39F008014D514C11D8A46EEF20F053 +:1040D80070EF20F072EF20F0BDEF20F0DEEC43F03F +:1040E80036C82FF837C830F82FC859F830C85AF8EA +:1040F8003DEC37F059C82DF85AC82EF8000E0801C3 +:104108000801316F000E0801326FA3EF20F008019B +:1041180008013151080108012F25E96E080108013D +:104128003251080108013021EA6EEF5008010801F8 +:10413800536F67EC3DF008010801314B322B080141 +:1041480008013251800A0801336F08012D51080116 +:104158000801315D080108012E51800A0801335910 +:10416800D8A0B9EF20F0BBEF20F08BEF20F053EC94 +:1041780021F01200000E080108016865C6EF20F062 +:10418800C8EF20F0D1EF20F0000E08010801686F99 +:10419800000E0801696F52EF21F068C871F81DEC34 +:1041A8002BF017C06AF8080108016A51070AD8B449 +:1041B800E0EF20F0E2EF20F0F6EF20F00801080130 +:1041C8006A510B0AD8B4EBEF20F0EDEF20F0F6EFD0 +:1041D80020F0000E08010801686F000E0801696FE1 +:1041E80052EF21F000EE09F010EE07F0E652EE5221 +:1041F800ED50E55C02E1EF50E75CD8A006EF21F056 +:1042080008EF21F039EF21F000EE07F0EECF6BF860 +:10421800EDCF6CF8095008016B5F0A5008016C5B20 +:1042280000EE03F0EECF6DF8EDCF6EF80150080107 +:104238006D5F025008016E5BFF0E08016D250801D5 +:104248006F6FFF0E08016E210801706F08016B5136 +:1042580008016F5D08010801686F08016C510801C9 +:1042680070590801696F52EF21F000EE09F0EECFA6 +:104278006BF8EDCF6CF8075008016B5F0850080128 +:104288006C5BFF0E08016B2508010801686FFF0EC3 +:1042980008016C210801696F52EF21F01200070133 +:1042A80007010D51170D0201000EF3240801080142 +:1042B8004E6F08014F6B0201020E08014F23080ED2 +:1042C80006010601BC25080108014C6F000E060115 +:1042D8000601BD2108014D6F0C0E080108014E258D +:1042E800E96E000E080108014F21EA6E0801EECFC1 +:1042F800BCF80801EDCFBDF82FEC43F0BCC850F86E +:10430800BDC851F80A0E080108014E25E96E000ED5 +:10431800080108014F21EA6E0801EECFBCF8080138 +:10432800EDCFBDF82FEC43F0BCC852F8BDC853F828 +:104338004CC8BCF84DC8BDF82FEC43F0BCC854F8C5 +:10434800BDC855F8000E08010801566F000E080197 +:10435800576FDD0E08010801AC6F0A0E0801AD6F3A +:104368000BEC44F04CC8A3F84DC8A4F80801586FEA +:10437800110E08010801A26F080158514EC8A0F893 +:104388004FC8A1F8CAEC18F0080E08010801C26F5E +:10439800000E0801C36F0801500E08010801C06F24 +:1043A8000801080E0801C16FBBEC40F003EC39F0BE +:1043B800000E06010601BC6F000E0601BD6F070165 +:1043C8000701A069120070EF22F06DC8B0F86EC83E +:1043D800B1F86BC8AEF86CC8AFF868C8ACF869C873 +:1043E800ADF858EC3AF07AEF22F008010801682994 +:1043F800D8B46929D8B403EF22F005EF22F00BEF07 +:1044080022F068C8ACF869C8ADF80BEC44F0100E9F +:10441800080108016F6F000E0801706F63EF22F04A +:10442800080108016F51080108016D5D08010801C4 +:104438007051080108016E59D8B025EF22F027EF16 +:1044480022F02BEF22F06DC86FF86EC870F86FC8B5 +:10445800B0F870C8B1F86BC8AEF86CC8AFF808010E +:10446800710E08010801AC6F0801080E0801AD6F54 +:1044780058EC3AF06FC8C2F870C8C3F80801710E5A +:1044880008010801C06F0801080E0801C16FBBECE4 +:1044980040F0080108016F51080108016B27000E60 +:1044A800080108016C23080108016F51080108017F +:1044B8006D5F080108017051080108016E5B080171 +:1044C80008016E516D11D8A46CEF22F06EEF22F046 +:1044D80014EF22F07AEF22F0080108016A51000A6D +:1044E80084E0010A01E171D77AEF22F01200080195 +:1044F800776F000E08010801766F080177510E0EDC +:104508000801080176658BEF22F08DEF22F08FEF1E +:1045180022F007EF23F0010E070107018C150801AF +:10452800776F000E070107018D150801786F000EDF +:10453800070107018E150801796F000E07010701B1 +:104548008F1508017A6F08017751000808017B6F01 +:10455800000E0801785508017C6F000E0801795596 +:1045680008017D6F000E08017A5508017E6F010E63 +:1045780008017B1508017F6F000E08017C150801F2 +:10458800806F000E08017D150801816FD00E0801AB +:104598007E150801826F07018CC783F807018DC754 +:1045A80084F807018EC785F807018FC786F8D89069 +:1045B8000801863385338433833308017F5108012A +:1045C8008319070107018C6F0801805108018419BC +:1045D80007018D6F080181510801851907018E6F48 +:1045E800080182510801861907018F6F0801080127 +:1045F800762B0E0E08010801766505EF23F007EF0C +:1046080023F08FEF22F08CC774F88DC775F80DEF83 +:1046180023F01200010E08010801566F000E080170 +:10462800576F0801080162690801080163690801F8 +:1046380008016469080108016569080108016669DB +:104648000801080167694CC84EF84DC84FF84CC8B6 +:10465800E9FF4DC8EAFFEECF6CF8EECF6DF8EECF6C +:104668006EF8EECF6FF8000100016C5108016C196B +:104678000801706F000100016D5108016D190801F2 +:10468800716F000100016E5108016E190801726F07 +:10469800000100016F5108016F190801736F0001D3 +:1046A80000017051080170150801746F00010001C4 +:1046B8007151080171150801756F000100017251EF +:1046C800080172150801766F000100017351080195 +:1046D80073150801776F08017751741175117611F8 +:1046E800D8B479EF23F07BEF23F084EF23F00001B7 +:1046F800740E080108014E6F0001000E08014F6F8B +:104708004EC8E9FF4FC8EAFF0801EECF68F8080174 +:10471800EECF69F80801EECF6AF80801EECF6BF822 +:104728000801500E08010801786F0801080E0801F9 +:10473800796F98EC1BF0120022EF24F0D2EF23F0EF +:10474800AAC8B0F8ABC8B1F8A7C8AEF8A8C8AFF8FF +:10475800A4C8ACF8A5C8ADF858EC3AF0DBEF23F0E4 +:1047680008010801A429D8B4A529D8B4BEEF23F0BC +:10477800C0EF23F0C6EF23F0A4C8ACF8A5C8ADF885 +:104788000BEC44F0AAC8C2F8ABC8C3F8A7C8C0F875 +:10479800A8C8C1F8BBEC40F0DBEF23F00801080122 +:1047A800A651000ADDE0010ACBE0DBEF23F02CEF95 +:1047B80024F019EF24F008010801A729D8B4A82982 +:1047C800D8B4E9EF23F0EBEF23F0F1EF23F0A7C81B +:1047D800ACF8A8C8ADF82CEC44F0AAC8C4F8ABC82B +:1047E800C5F8A4C8C2F8A5C8C3F86DEC38F0DBEF6B +:1047F80023F0AAC8B0F8ABC8B1F8A7C8AEF8A8C8E3 +:10480800AFF8A4C8ACF8A5C8ADF83CECDDF00DEFE6 +:1048180024F08EEC43F00009D8B415EF24F017EF1C +:1048280024F00DEF24F0DBEF23F008010801A65176 +:10483800000ADFE0010ABFE0DBEF23F0080108010E +:10484800A951000AB6E0010A01E178D72CEF24F05B +:1048580012002FEF24F0C5CF2CF81F0E08012C17DB +:104868002CC82DF808012E6B000EC7B4010E0801E4 +:104878002D13000E2E1308012E512D11D8A447EF29 +:1048880024F049EF24F02FEF24F0C5804CEF24F0FA +:10489800C5B051EF24F053EF24F04CEF24F0A1A65B +:1048A80058EF24F05AEF24F05CEF24F0B6EF24F030 +:1048B80029C82FF819EC3AF00009D8B466EF24F0AB +:1048C80068EF24F06BEF24F0C584B6EF24F0C5BC84 +:1048D80070EF24F072EF24F09EEF24F02AC82FF82E +:1048E80019EC3AF00009D8B47CEF24F07EEF24F0FC +:1048F80081EF24F0C584B6EF24F0C5BC86EF24F020 +:1049080088EF24F099EF24F02BC82FF819EC3AF02F +:104918000009D8B492EF24F094EF24F097EF24F034 +:10492800C584B6EF24F09CEF24F0C584B6EF24F0DC +:10493800A1EF24F0C584B6EF24F0C584A4EF24F0D9 +:10494800C5B4A9EF24F0ABEF24F0A4EF24F0A1A69E +:10495800B0EF24F0B2EF24F0B4EF24F0B6EF24F077 +:10496800B6EF24F0120007010701A451070107015F +:104978009F63C1EF24F0C3EF24F0C5EF24F03EEFAE +:1049880025F0070107019F51FE0AD8B4CEEF24F0A5 +:10499800D0EF24F019EF25F0270E08010801AA6FBF +:1049A800000E0801AB6F0801A06F010E0801080195 +:1049B800A96F0801A0511D0E08010801A76F000E7C +:1049C8000801A86F070107019F511C0DF3CFA1F83B +:1049D8001B0E0801A1270401BD0E0801A125E96EDF +:1049E800EA6A0401040EEA22EF5008010801A66FE2 +:1049F800070107019F511C0D0401BD0EF324E96E48 +:104A0800EA6A0401040EEA22EECFA2F8EDCFA3F879 +:104A1800D90E0801A22508010801A46FFF0E08019C +:104A2800A3210801A56FA0EC23F0A4C79FF7270EC8 +:104A380008010801AA6F000E0801AB6F1CC0A9F895 +:104A4800D90E012408010801A76FFF0E02200801F2 +:104A5800A86F0801A06F010E08010801A66F0801E0 +:104A6800A0511D0E08010801A46F000E0801A56FD2 +:104A7800A0EC23F012000701D89033370801080191 +:104A8800F051D8B44AEF25F04CEF25F06FEF25F040 +:104A980007010701262B070107012651030AD8A49D +:104AA80058EF25F05AEF25F060EF25F0070E0701C3 +:104AB800070133136DEF25F0030E07010701266583 +:104AC80068EF25F06AEF25F06DEF25F00701070183 +:104AD800338177EF25F00801F16F000E0701070118 +:104AE800266F0801F1510701D890393707010701EE +:104AF8003F2B0701070133AF84EF25F086EF25F040 +:104B08008BEF25F00701070139818BEF25F00701AD +:104B180007013F51080AD8A494EF25F096EF25F035 +:104B2800C2EF25F00801F16F000E070107013F6F82 +:104B38000801F151B30E06010601D825E96E020EEF +:104B480006010601D921EA6E070139C7EFFF060100 +:104B58000601D84BD92B06010601D951020AD811F2 +:104B6800D8A4B9EF25F0BBEF25F0C2EF25F0000E71 +:104B780006010601D86F000E0601D96F1200D9CEC2 +:104B8800A4F8EECEA2F8EFCEA3F808010801A451CC +:104B98000E010E01D963D3EF25F0D5EF25F0C3EF51 +:104BA80025F0ECCEA4F8EDCEA5F808010801A25135 +:104BB80008010801A45D08010801A35108010801C2 +:104BC800A559D8B0EAEF25F0ECEF25F00BEF26F069 +:104BD8000801A2C8A6F80801A3C8A7F80801080197 +:104BE800A4510801A65F08010801A5510801A75BA7 +:104BF8000801A651CD0808010801A06F0801A751B6 +:104C0800D8A0E82A0A080801A16F45EF26F0080194 +:104C18000801A55108010801A31906E108010801C6 +:104C2800A45108010801A219D8A41DEF26F01FEF0E +:104C380026F028EF26F0CD0E08010801A06F0A0E15 +:104C48000801A16F45EF26F00801A4C8A6F80801DD +:104C5800A5C8A7F808010801A2510801A65F080124 +:104C68000801A3510801A75BFF0E0801A62508014A +:104C78000801A06FFF0E0801A7210801A16F45EFE9 +:104C880026F01200BFEF26F04A0E08010801536F04 +:104C9800A50E0801546F4A0E08010801516FA50EB0 +:104CA8000801526F0801096F040E08010801506FCE +:104CB80008010951000E080108014C6F000E080197 +:104CC8004D6F000E08014E6F000E08014F6F22EC69 +:104CD800D7F006010601E66F06010601E629D8A409 +:104CE80078EF26F07AEF26F07CEF26F0C8EF26F072 +:104CF8000801096F010E070107013E6F08010951FC +:104D0800C8EF26F0E6C64CF8D9EC39F008014D5149 +:104D18004C11D8A492EF26F094EF26F096EF26F0E7 +:104D2800C8EF26F065EC3FF0A9EF26F00801080E61 +:104D3800080108014D6F0801080E08014E6F35EC97 +:104D48003DF008C864F88FEC3FF0E6C64CF8D9ECA3 +:104D580039F008014D514C11D8A4B5EF26F0B7EF42 +:104D680026F09AEF26F08FEC41F0C8EC15F065ECD0 +:104D78003FF0C8EF26F0070107013E51000A84E022 +:104D8800010AC0E0C8EF26F01200000E0801080171 +:104D98006D6F000E08016E6F000E08016F6F000E38 +:104DA8000801706F77EC41F00009D8A4DEEF26F017 +:104DB800E0EF26F0EFEF26F0000E08010801656F1E +:104DC800000E0801666F000E0801676F000E0801EB +:104DD800686F4BEF27F004010401FF2B37EF27F032 +:104DE8000101000E04010401FF25E96EEA6A0101D0 +:104DF800010EEA22EF500801716F08017151080194 +:104E08000801696F08016A6B08016B6B08016C6B1C +:104E180004010401FF2B08016951730A6A116B111F +:104E28006C11D8A41AEF27F01CEF27F01EEF27F01B +:104E380041EF27F00801040ED89008016D370801EA +:104E48006E3708016F3708017037E82E20EF27F01A +:104E580069C872F82DEC2DF00801716F08017151C5 +:104E6800080108016D13C70E04010401FF653FEF37 +:104E780027F041EF27F0F4EF26F06DC865F86EC80B +:104E880066F86FC867F870C868F84BEF27F012002B +:104E98002DC7FFF4BEEF27F00801646F0C0E080160 +:104EA8000801676F080164510801580E08010801DC +:104EB800656F0801080E0801666F0EEC18F000090E +:104EC800D8A469EF27F06BEF27F06EEF27F0000EFC +:104ED800CBEF27F00801580E08010801676F080199 +:104EE800080E0801686F56C865F857C866F849EC97 +:104EF80029F0080166516511D8A485EF27F087EFDE +:104F080027F08AEF27F0010ECBEF27F077EC41F07E +:104F18000009D8B492EF27F094EF27F098EF27F024 +:104F2800C9EC26F0A9EF27F00801646F000E08010C +:104F38000801676F08016451000E08010801656FD8 +:104F4800000E0801666F0EEC18F00101000E040156 +:104F58000401FF25E96EEA6A0101010EEA22730ED7 +:104F6800EF62B9EF27F0BBEF27F0BEEF27F0000E96 +:104F7800CBEF27F0C70E04010401FF65C6EF27F049 +:104F8800C8EF27F050EF27F0000ECBEF27F0120004 +:104F980058C8E9FF59C8EAFF010EEE6E230EEE6EFF +:104FA800450EEE6E670EED6EED52ED52040E0801E1 +:104FB80008015825E96E000E080108015921EA6E1A +:104FC800890EEE6EAB0EEE6ECD0EEE6EEF0EED6E42 +:104FD800ED52ED52080E080108015825E96E000E41 +:104FE800080108015921EA6EFE0EEE6EDC0EEE6E27 +:104FF800BA0EEE6E980EED6EED52ED520C0E0801E3 +:1050080008015825E96E000E080108015921EA6EC9 +:10501800760EEE6E540EEE6E320EEE6E100EED6ED5 +:10502800ED52ED52100E080108015825E96E000EE8 +:10503800080108015921EA6EF00EEE6EE10EEE6EDF +:10504800D20EEE6EC30EED6EED52ED52140E080147 +:1050580008015825E96E000E080108015921EA6E79 +:10506800000EEE6E000EEE6E000EEE6E000EED6E91 +:10507800ED52ED52580E080108015825E96E000E50 +:10508800080108015921EA6E010EEF6E12000DC8E1 +:1050980013F894EC2DF013C810F814C811F808018F +:1050A800080111511011D8A45CEF28F05EEF28F028 +:1050B80061EF28F0000EC9EF28F00DC871F81DEC5B +:1050C8002BF0080108010F510E11D8B46EEF28F02B +:1050D80070EF28F08BEF28F0010E08010801AA6F85 +:1050E800000E0801AB6F1CC0A9F80DC0A7F80EC0D0 +:1050F800A8F80801126F010E08010801A66F08013F +:1051080012510EC8A4F80FC8A5F8A0EC23F000EEC1 +:105118000DF0EE2A000EED2210EE05F0E652EE52EA +:10512800ED50E55C02E1EF50E75CD8B09EEF28F067 +:10513800A0EF28F0A4EF28F003C00DF004C00EF093 +:105148000801080110051111D8A4ADEF28F0AFEF40 +:1051580028F0B2EF28F01984C6EF28F018BAB7EF94 +:1051680028F0B9EF28F0C6EF28F0188A5AEC42F078 +:105178001F0E08010801A125136E000E0801080181 +:10518800A221146E010EC9EF28F012000094000E3F +:10519800070107010E6F009253C8E9FF54C8EAFFE0 +:1051A800EF5007010701126FB180DBEF28F000A272 +:1051B800E0EF28F0E2EF28F0DBEF28F09D92010EF7 +:1051C80008010801556F000E0801566F25EF29F0F8 +:1051D800080108015551080108015325E96E080125 +:1051E80008015651080108015421EA6E010EEF62C8 +:1051F80000EF29F002EF29F005EF29F0008421EFF4 +:1052080029F00092080108015551080108015325A9 +:10521800E96E080108015651080108015421EA6E97 +:10522800EF5007010701126F1AEF29F000A21FEFD4 +:1052380029F021EF29F01AEF29F008010801554B50 +:10524800562B080108015551080108015325E96E3C +:10525800080108015651080108015421EA6EEF506F +:10526800D8A439EF29F03BEF29F0ECEF28F09D8224 +:1052780000923FEF29F000A244EF29F046EF29F011 +:105288003FEF29F0B190899812004DEF29F04DEFCA +:1052980029F008010801675108016A6F080108012F +:1052A800685108016B6F0801674B682B6AC8F6FFE5 +:1052B8006BC8F7FF000EF86E0E0EF76403D00800F7 +:1052C800F55005D0F6CFE9FFF7CFEAFFEF50080118 +:1052D8006C6F080165C8F6FF080166C8F7FF000E85 +:1052E800F86E0E0EF76403D00800F55005D0F6CF1F +:1052F800E9FFF7CFEAFFEF5008016D6F08016C5125 +:1053080008016D5D08010801696F080169678FEF81 +:1053180029F091EF29F0B7EF29F00801080165514C +:1053280008016A6F08010801665108016B6F0801DE +:10533800654B662B6AC8F6FF6BC8F7FF000EF86E60 +:105348000E0EF76403D00800F55005D0F6CFE9FF3C +:10535800F7CFEAFFEF500009D8A4B5EF29F0B7EF6F +:1053680029F04BEF29F008010801695108010801EB +:10537800656F0801666B080165BF6607C4EF29F011 +:1053880012000001000198ADCCEF29F0CEEF29F012 +:10539800FDEF29F000010001EC690001ED69000151 +:1053A800EE690001EF6900010001F0690001F1698F +:1053B8000001F2690001F36900010001F4690001CC +:1053C800F5690001F6690001F76900010001F86953 +:1053D8000001F9690001FA690001FB690001000197 +:1053E800FC690001FD690001FE690001FF6925EF04 +:1053F8002AF06CC0ECF06DC0EDF06EC0EEF06FC03E +:10540800EFF070C0F0F071C0F1F072C0F2F073C04C +:10541800F3F074C0F4F075C0F5F076C0F6F077C01C +:10542800F7F078C0F8F079C0F9F07AC0FAF07BC0EC +:10543800FBF07CC0FCF07DC0FDF07EC0FEF07FC0BC +:10544800FFF0250E08010801246F000E0801256FE2 +:105458000001DB0E08010801226F0001000E08019F +:10546800236F4DEC39F0FF0012008988050E080102 +:10547800566F300EE82E3EEF2AF0562F3EEF2AF0F8 +:1054880089982B0E0801566F560EE82E49EF2AF020 +:10549800562F49EF2AF004000801566F020E080142 +:1054A8000801586F08015651FBC557F840EC30F019 +:1054B8000801566F080E08010801586F0801565177 +:1054C800FAC557F840EC30F00801566F080E08018D +:1054D8000801586F08015651F9C557F840EC30F0EB +:1054E8000801566F080E08010801586F0801565147 +:1054F800F8C557F840EC30F0B4EC3EF0070107016E +:1055080018051911D8A48BEF2AF08DEF2AF091EF26 +:105518002AF05AEC3EF093EF2AF0B4EC3EF0080182 +:10552800566F040E08010801586F0801565114C738 +:1055380057F840EC30F08988050E0801566F300E98 +:10554800E82EA4EF2AF0562FA4EF2AF0899812002B +:105558000801326F000E08010801316F080132514D +:105568002EC8E9FF2FC8EAFFEF5008010801356F80 +:105578002CC8E9FF2DC8EAFF0801EECF33F808016F +:10558800EDCF34F887EC3EF0D8B0CDEF2AF0D0EF6D +:105598002AF0010ED1EF2AF0000E08010801306F41 +:1055A80008010801312B2EC835F82FC836F82CC849 +:1055B80033F82DC834F899EC3CF02EC8E9FF2FC811 +:1055C800EAFFEF5008010801356F2CC8E9FF2DC824 +:1055D800EAFF0801EECF33F80801EDCF34F887EC85 +:1055E8003EF0D8B0FAEF2AF0FDEF2AF0010EFEEFF8 +:1055F8002AF0000E080108013019D8B406EF2BF084 +:1056080008EF2BF00DEF2BF00801080131511CEFCA +:105618002BF0080108013129D8A415EF2BF017EF5A +:105628002BF01AEF2BF0000E1CEF2BF0D4EF2AF022 +:10563800120008010801715107010701A46327EF4F +:105648002BF029EF2BF02BEF2BF08AEF2BF0070133 +:105658000701A451FE0AD8B434EF2BF036EF2BF033 +:1056680056EF2BF01C0E08010801B06F000E080160 +:10567800B16F010E08010801AE6F000E0801AF6F8F +:1056880007010701A4511C0D0401BD0EF3240801F4 +:105698000801AC6F0801AD6B0401040E0801AD23CD +:1056A80058EC3AF071C8A4F7080108017151FE0AD4 +:1056B800D8A461EF2BF063EF2BF065EF2BF08AEFA6 +:1056C8002BF01C0E08010801B06F000E0801B16F25 +:1056D8000801080171511C0DBD0E0801726F040EFE +:1056E800736FF35008017227E86AF3BEE86808018F +:1056F800732372C8AEF873C8AFF8010E0801080129 +:10570800AC6F000E0801AD6F58EC3AF012008DEF47 +:105718002BF0C5CF2AF81F0E08012A172AC82BF824 +:1057280008012C6B000EC7B4010E08012B13000EE4 +:105738002C1308012C512B11D8A4A5EF2BF0A7EF9F +:105748002BF08DEF2BF0C580AAEF2BF0C5B0AFEF93 +:105758002BF0B1EF2BF0AAEF2BF0A1A6B6EF2BF0B0 +:10576800B8EF2BF0BAEF2BF0F7EF2BF029C82FF892 +:1057780019EC3AF0C0EF2BF0DBEF2BF0C582C5EF48 +:105788002BF0C5B2CAEF2BF0CCEF2BF0C5EF2BF006 +:10579800A1A6D1EF2BF0D3EF2BF0D5EF2BF0F7EF3D +:1057A8002BF029C82FF819EC3AF0DBEF2BF0C5BC29 +:1057B800E0EF2BF0E2EF2BF0C2EF2BF0C584E5EF22 +:1057C8002BF0C5B4EAEF2BF0ECEF2BF0E5EF2BF064 +:1057D800A1A6F1EF2BF0F3EF2BF0F5EF2BF0F7EF9D +:1057E8002BF0F7EF2BF0120006010601CE5106014F +:1057F8000601D25D06010601CF5106010601D35903 +:10580800D8B009EF2CF00BEF2CF018EF2CF00701B3 +:105818000701A351070107010D19D8B416EF2CF0A1 +:1058280018EF2CF01AEF2CF05EEF2CF006010601B1 +:10583800D25106010601CE5D08010801516F06012B +:105848000601D35106010601CF590801526F08011C +:1058580008014F5108010801515D08010801505124 +:10586800080108015259D8B03CEF2CF03EEF2CF05B +:1058780042EF2CF051C84FF852C850F84FC8C4F83E +:1058880050C8C5F84DC8C2F84EC8C3F86DEC38F01A +:10589800C2C84FF8C3C850F8080108014F510601A3 +:1058A8000601D22708010801505106010601D32339 +:1058B8005EEF2CF01200020E08010801BA25E96E0D +:1058C800000E08010801BB21EA6E0801EECFBCF802 +:1058D8000801EDCFBDF82FEC43F0020E08010801D6 +:1058E800BA25E96E000E08010801BB21EA6E08011D +:1058F800BCC8EEFF0801BDC8EDFF040E0801080191 +:10590800BA25E96E000E08010801BB21EA6E0801FC +:10591800EECFBCF80801EDCFBDF82FEC43F0040E34 +:1059280008010801BA25E96E000E08010801BB212B +:10593800EA6E0801BCC8EEFF0801BDC8EDFF0A0EFB +:1059480008010801BA25E96E000E08010801BB210B +:10595800EA6E0801EECFBCF80801EDCFBDF82FECD8 +:1059680043F00A0E08010801BA25E96E000E080185 +:105978000801BB21EA6E0801BCC8EEFF0801BDC8DA +:10598800EDFF120012C816F811C815F80CECE7F074 +:1059980008010801136F080108011351FE0AD8A471 +:1059A800D8EF2CF0DAEF2CF0E3EF2CF0FE0E080124 +:1059B8000801116FFF0E0801126F2CEF2DF008017E +:1059C80008011329D8A4EBEF2CF0EDEF2CF0F4EF3D +:1059D8002CF0080108011169080112692CEF2DF05B +:1059E8000701D8903533080108011351D8B4FFEFE7 +:1059F8002CF001EF2DF004EF2DF007010701358F92 +:105A080007010701292B070107012C2B080E0701A5 +:105A180007012C6112EF2DF014EF2DF01BEF2DF084 +:105A2800080108011169080112692CEF2DF008011D +:105A3800146F000E070107012C6F080114510701AC +:105A4800080135C711F808010801126B2CEF2DF079 +:105A580012005FEF2DF0000E93EF2DF0010E93EF83 +:105A68002DF0020E93EF2DF0030E93EF2DF0040EA0 +:105A780093EF2DF0050E93EF2DF0060E93EF2DF01A +:105A8800070E93EF2DF0080E93EF2DF0090E93EF0C +:105A98002DF00A0E93EF2DF00B0E93EF2DF00C0E58 +:105AA80093EF2DF00D0E93EF2DF00E0E93EF2DF0DA +:105AB8000F0E93EF2DF0080108017251300ACBE068 +:105AC800010ACCE0030ACDE0010ACEE0070ACFE0E4 +:105AD800010AD0E0030AD1E0010AD2E00F0AD3E0BC +:105AE800010AD4E0780AD5E0030AD6E0010AD7E033 +:105AF800070AD8E0010AD9E0030ADAE0270AC9E070 +:105B0800030ACAE0010ACBE0070ACCE0010ACDE0AB +:105B1800030ACEE090EF2DF0000E93EF2DF0120067 +:105B2800000E0801080113659CEF2DF09EEF2DF083 +:105B3800A7EF2DF0000E08010801136F000E0801F1 +:105B4800146FF9EF2DF013C871F81DEC2BF000EE6F +:105B58000DF010EE0BF0E652EE52ED50E55C02E16E +:105B6800EF50E75CD8A0BBEF2DF0BDEF2DF0C8EFEC +:105B78002DF00D500B5C08010801136F0E500C58E6 +:105B88000801146FF9EF2DF000EE0BF0EECF15F8C9 +:105B9800EDCF16F803500801155F04500801165B95 +:105BA80000EE05F0EECF17F8EDCF18F80D5008010C +:105BB800175F0E500801185B0801155108011725D9 +:105BC8000801196F080116510801182108011A6FF8 +:105BD800010E0801192508010801136F000E0801BC +:105BE8001A210801146FF9EF2DF0120045EF2EF07D +:105BF80013C8E9FF14C8EAFFEF50D8B406EF2EF037 +:105C080008EF2EF021EF2EF0080115C8F6FF080165 +:105C180016C8F7FF000EF86E0800F5CF19F813C87C +:105C2800E9FF14C8EAFFEF5008011919D8B41FEFAB +:105C38002EF021EF2EF03DEF2EF013C8E9FF14C827 +:105C4800EAFFEF500801196F080115C8F6FF0801AF +:105C580016C8F7FF000EF86E0800F5500801195D28 +:105C680008010801136F0801146BD8A014075EEF30 +:105C78002EF008010801134B142B08010801154BDD +:105C8800162B080108011707D8A0180708011729BB +:105C9800D8B41829D8A453EF2EF055EF2EF0FCEF06 +:105CA8002DF0000E08010801136F000E0801146F93 +:105CB8005EEF2EF01200800E08010801276F000E1B +:105CC8000801286F0801080128512711D8A46FEF8F +:105CD8002EF071EF2EF073EF2EF0BCEF2EF00801CE +:105CE800000E080122BF010E08010801256F0801F6 +:105CF800266B08010801235108010801271500092E +:105D0800D8B489EF2EF08BEF2EF097EF2EF0080124 +:105D1800080126512511000ED8B4010E080108010A +:105D2800256F0801266B0801D89022370801080161 +:105D380026512511D8B4A3EF2EF0A5EF2EF0ABEF26 +:105D48002EF008010801245108010801221B08014E +:105D5800D890080128330801273308010801285181 +:105D68002711D8A4BAEF2EF0BCEF2EF073EF2EF067 +:105D7800080108012251C1EF2EF0120027C82EF8A1 +:105D880028C82FF825C82CF826C82DF8ACEC2AF01E +:105D9800080108012A6F1D0E080108012A65D7EFBE +:105DA8002EF0D9EF2EF0E6EF2EF0290E08010801AB +:105DB8002A61E1EF2EF0E3EF2EF0E6EF2EF0000E71 +:105DC80021EF2FF027C82EF828C82FF825C82CF85F +:105DD80026C82DF8ACEC2AF008010801296F090E35 +:105DE800080108012A65FBEF2EF0FDEF2EF01EEFEB +:105DF8002FF0150E080108012A6105EF2FF007EFB3 +:105E08002FF01EEF2FF0090E0801080129650FEF8A +:105E18002FF011EF2FF01EEF2FF0150E08010801DB +:105E2800296119EF2FF01BEF2FF01EEF2FF0010E55 +:105E380021EF2FF0020E21EF2FF012000601000EC5 +:105E480008010801586F0601060E0801596FCCECCD +:105E580027F00101000E08010801596F0101010E28 +:105E680008015A6F3DEC37F059C856F85AC857F828 +:105E780056C85CF857C85DF80101000E0801080112 +:105E88005A6F0101010E08015B6F0601000E08013F +:105E98000801586F0601060E0801596FC1EC11F090 +:105EA800200E080108015C6F000E08015D6F470EA7 +:105EB800080108015A6FFE0E08015B6F0601000E0B +:105EC80008010801586F0601060E0801596FE8EC31 +:105ED80010F00401E30E080108015A6F0401040ED2 +:105EE80008015B6F0601000E08010801586F0601E2 +:105EF800060E0801596F89ECB9F012000D0E080161 +:105F0800080117658AEF2FF08CEF2FF0B4EF2FF010 +:105F1800160E08010801176194EF2FF096EF2FF085 +:105F2800B4EF2FF006010601C4A19DEF2FF09FEFFB +:105F38002FF0A2EF2FF0FE0EE0EF2FF0020E060179 +:105F48000601C42506010601C46F000E06010601FC +:105F5800C5210601C56F080108011651E0EF2FF0B1 +:105F6800050E080108011765BCEF2FF0BEEF2FF0F2 +:105F7800DDEF2FF00C0E080108011761C6EF2FF0B6 +:105F8800C8EF2FF0DDEF2FF006010601C44BC52B3B +:105F980006010601C4B1D3EF2FF0D5EF2FF0DAEFE9 +:105FA8002FF0080108011651E0EF2FF0FF0EE0EF87 +:105FB8002FF0FE0EE0EF2FF01200080108010D2966 +:105FC800D8B40E29D8A4EBEF2FF0EDEF2FF0F4EFB3 +:105FD8002FF0080108010D6908010E693FEF30F044 +:105FE800080108011051800A0801116F08010D51BC +:105FF800080108010F5D080108010E51800A080117 +:106008001159D8A00AEF30F00CEF30F01FEF30F044 +:10601800080108010D51080108010F5D0801080178 +:106028000D6F080108010E510801080110590801F7 +:106038000E6F3FEF30F0000E0801116F020E126F65 +:10604800080108010D510801115F080108010E51EE +:106058000801125B080108010F5108011125080108 +:1060680008010D6F080108011051080112210801EB +:106078000E6F3FEF30F0120008015B6F010E080150 +:1060880008015A6F08015B5108015B6F000E080197 +:106098000801596F08015B5158C85BF8FF0E0801E9 +:1060A8005B27010E08015C6F08015B2B5FEF30F086 +:1060B800D89008015C3708015B2F5CEF30F00801CD +:1060C8005C51080108015A6F08015B6F000E080156 +:1060D8000801596F08015B5190EF30F00801080181 +:1060E8005751080108015A150009D8B47EEF30F05D +:1060F80080EF30F084EF30F05AEC3EF086EF30F06D +:10610800B4EC3EF00801D89008015A3108010801A2 +:106118005A6F08010801592B080108015851080154 +:106128000801595DD8A09BEF30F09DEF30F072EF79 +:1061380030F012007CC8E9FF7DC8EAFF0801EECF05 +:10614800BCF80801EDCFBDF82FEC43F07CC8E9FF9F +:106158007DC8EAFF0801BCC8EEFF0801BDC8EDFF15 +:10616800020E080108017C25E96E000E08010801ED +:106178007D21EA6E0801EECFBCF80801EDCFBDF82D +:106188002FEC43F0020E080108017C25E96E000E91 +:10619800080108017D21EA6E0801BCC8EEFF08016C +:1061A800BDC8EDFF060E080108017C25E96E000E4A +:1061B800080108017D21EA6E0801EECFBCF808014C +:1061C800EDCFBDF82FEC43F0060E080108017C2541 +:1061D800E96E000E080108017D21EA6E0801BCC8BD +:1061E800EEFF0801BDC8EDFF120004010401FB51D8 +:1061F800C00808010801576F04010401FC51D8A028 +:10620800E82A05080801586F0801080155510801D6 +:106218000801575D0801080156510801080158593D +:10622800D8B019EF31F01BEF31F01FEF31F057C83C +:1062380055F858C856F808010801555104010401D9 +:10624800FB2708010801565104010401FC2304013D +:106258000401FB5106010601BC5D04010401FC5167 +:1062680006010601BD59D8B03CEF31F03EEF31F0E0 +:1062780042EF31F0FBC4BCF6FCC4BDF655C8C2F809 +:1062880056C8C3F853C8C0F854C8C1F8BBEC40F0AE +:1062980055C853F856C854F852EF31F012000401AB +:1062A8000401FB51C00808010801576F04010401EB +:1062B800FC51D8A0E82A05080801586F0801080110 +:1062C800555108010801575D080108015651080198 +:1062D80008015859D8B073EF31F075EF31F079EF04 +:1062E80031F057C855F858C856F8080108015551F3 +:1062F80004010401FB2708010801565104010401A7 +:10630800FC2304010401FB5106010601BC5D0401E4 +:106318000401FC5106010601BD59D8B096EF31F0D1 +:1063280098EF31F09CEF31F0FBC4BCF6FCC4BDF62D +:1063380055C85BF856C85CF853C859F854C85AF899 +:106348002EEC40F055C853F856C854F8ACEF31F06D +:1063580012000F0E080108012465B5EF31F0B7EF00 +:1063680031F0D8EF31F00A0E080108012561BFEFBE +:1063780031F0C1EF31F0D8EF31F00A0E0801080111 +:106388002661C9EF31F0CBEF31F0D8EF31F00A0ECA +:10639800080108012761D3EF31F0D5EF31F0D8EFCC +:1063A80031F0000E06EF32F00A0E080108012461F0 +:1063B800E0EF31F0E2EF31F003EF32F00A0E0801BE +:1063C80008012561EAEF31F0ECEF31F003EF32F02C +:1063D8000F0E080108012665F4EF31F0F6EF31F0F1 +:1063E80003EF32F00A0E080108012761FEEF31F0D1 +:1063F80000EF32F003EF32F0010E06EF32F0020E3A +:1064080006EF32F012000F0E080108011F650FEFAA +:1064180032F011EF32F032EF32F00A0E08010801C3 +:10642800206119EF32F01BEF32F032EF32F00F0E2D +:1064380008010801216523EF32F025EF32F032EF31 +:1064480032F00A0E0801080122612DEF32F02FEF19 +:1064580032F032EF32F0000E60EF32F00A0E08012F +:1064680008011F613AEF32F03CEF32F05DEF32F095 +:106478000F0E08010801206544EF32F046EF32F0B4 +:106488005DEF32F00F0E0801080121654EEF32F082 +:1064980050EF32F05DEF32F00A0E08010801226178 +:1064A80058EF32F05AEF32F05DEF32F0010E60EF44 +:1064B80032F0020E60EF32F012000D0E08010801F2 +:1064C8001F6169EF32F06BEF32F08CEF32F00D0E96 +:1064D80008010801206173EF32F075EF32F08CEF9C +:1064E80032F00D0E0801080121617DEF32F07FEFD7 +:1064F80032F08CEF32F0100E08010801226587EFA8 +:1065080032F089EF32F08CEF32F0010EBAEF32F050 +:106518000D0E080108011F6194EF32F096EF32F07A +:10652800B7EF32F0100E0801080120659EEF32F037 +:10653800A0EF32F0B7EF32F00D0E0801080121612B +:10654800A8EF32F0AAEF32F0B7EF32F00D0E0801E3 +:1065580008012261B2EF32F0B4EF32F0B7EF32F057 +:10656800000EBAEF32F0020EBAEF32F01200000E4F +:1065780008010801156F000E0801166F000E0801CA +:10658800176F000E0801186F080108010DA1CFEF61 +:1065980032F0D1EF32F0E9EF32F008010801115181 +:1065A800080108011527080108011251080108010E +:1065B80016230801080113510801080117230801CF +:1065C800080114510801080118230801D89008018E +:1065D8001137080112370801133708011437080169 +:1065E800D8900801103308010F3308010E33080151 +:1065F8000D33080110510D110E110F11D8A407EF1A +:1066080033F009EF33F0C8EF32F015C80DF816C8AB +:106618000EF817C80FF818C810F813EF33F0120067 +:10662800C2C8F7F4C3C8F8F4C4C8F9F4C5C8FAF482 +:10663800C6C8C8F8080E08010801C86126EF33F07B +:1066480028EF33F02AEF33F042EF33F0FAC4C7F8FB +:10665800F9C4FAF4F8C4F9F4F7C4F8F4C7C8F7F4BD +:10666800080E08010801C85F080E08010801C86182 +:1066780040EF33F042EF33F02AEF33F0080108011E +:10668800C86749EF33F04BEF33F04DEF33F061EF6C +:1066980033F00401D890FABFD880F737F837F937C4 +:1066A800FA3708010801C80708010801C8675FEF41 +:1066B80033F061EF33F04DEF33F0F7C4C2F8F8C4AC +:1066C800C3F8F9C4C4F8FAC4C5F86BEF33F0120084 +:1066D800B7EC24F02DC01AF02EC01BF001C007F053 +:1066E80002C008F001C009F002C00AF003C00BF0B4 +:1066F80004C00CF003C00DF004C00EF00801736F65 +:106708000D0E08010801726F0801735118A68FEF6A +:1067180033F091EF33F099EF33F00801736F040E03 +:1067280008010801726F0801735172C817F01890B8 +:10673800189218940B000E001898189A189C189E16 +:10674800199019921994199619883F903F923F967B +:106758003F9801C029F002C02AF07BEC22F074C8EF +:1067680021F075C822F07BEC22F074C823F075C8BC +:1067780024F03D683E68010E2F6E000E306E120048 +:10678800CF0E0E010E01E26F0A0E0E01E36F080133 +:10679800DC0E0801BD270A0E0801BE23BDC8E6FEAF +:1067A800BEC8E7FE060E08010801C26F000E080108 +:1067B800C36FBAC8C0F8BBC8C1F8BBEC40F0060E3E +:1067C80008010801C26F000E0801C36F0001990E8D +:1067D80008010801C06F0001000E0801C16FBBEC81 +:1067E80040F00801BF6F080E08010801C06F0801DA +:1067F800BF5164EC44F00801BF6F060E08010801A0 +:10680800C06F0801BF5108010801BC670EEF34F0E2 +:1068180010EF34F018EF34F00801BF6F000E0801D4 +:106828000801C06F0801BF5164EC44F01200070171 +:1068380007013A6722EF34F024EF34F04EEF34F0DA +:1068480008011F6F010E070107013A6F08011F5168 +:1068580008011F6F000E080108011E6F08011F5173 +:10686800000E080108011E653CEF34F03EEF34F0DD +:1068780040EF34F04EEF34F04468080108011E2B55 +:10688800000E080108011E654CEF34F04EEF34F09D +:1068980040EF34F04428D8B454EF34F056EF34F0D5 +:1068A8005BEF34F044C04CF8A3EC36F044680801C0 +:1068B8001F6F010E00010001456F08011F510801FB +:1068C8001F6F000E00010001466F08011F510001F3 +:1068D80046890001468312000A0E08010801B06FBC +:1068E800000E0801B16F06010601E651170D000EF2 +:1068F8000801226F020E236FF35008012227E86A6D +:10690800F3BEE8680801232322C8AEF823C8AFF80D +:106918000601630E08010801AC6F0601060E0801A6 +:10692800AD6F58EC3AF006010601E651170DF3CFAA +:1069380022F80A0E080122270201000E080122256A +:10694800E96EEA6A0201020EEA220601EECFFEF6BD +:106958000601EDCFFFF607010701A529D8B4B7EF67 +:1069680034F0B9EF34F0C2EF34F0A5C74CF8A3EC1B +:1069780036F007010701A569C2EF34F01200FACF1B +:10698800CCF8FBCFCDF8E9CFCEF8EACFCFF8E1CFFE +:10699800D0F8E2CFD1F8D9CFD2F8DACFD3F8F3CF05 +:1069A800D4F8F4CFD5F8F6CFD6F8F7CFD7F8F8CF94 +:1069B800D8F8F5CFD9F8F2A4E4EF34F0E6EF34F0E4 +:1069C800E8EF34F004EC42F09EA2EDEF34F0EFEF84 +:1069D80034F0F2EF34F08AEC0CF09E92D9C8F5FF4F +:1069E800D8C8F8FFD7C8F7FFD6C8F6FFD5C8F4FF50 +:1069F800D4C8F3FFD3C8DAFFD2C8D9FFD1C8E2FFA1 +:106A0800D0C8E1FFCFC8EAFFCEC8E9FFCDC8FBFF79 +:106A1800CCC8FAFFCBC8E0FFCAC8E8FFC9C8D8FF8E +:106A28001000EACFE5F8E1CFE6F8E2CFE7F8D9CFF2 +:106A3800E8F8DACFE9F8F3CFEAF8F4CFEBF8F6CFD5 +:106A4800ECF8F7CFEDF8F8CFEEF8F5CFEFF8A4A60D +:106A580030EF35F032EF35F03DEF35F0E20E786E7D +:106A6800000E81B8010E08010801F06F3FEC25F017 +:106A7800A496A1A242EF35F044EF35F04AEF35F085 +:106A8800B368C40EB26ECEEC3CF0A192EFC8F5FF2D +:106A9800EEC8F8FFEDC8F7FFECC8F6FFEBC8F4FF47 +:106AA800EAC8F3FFE9C8DAFFE8C8D9FFE7C8E2FF98 +:106AB800E6C8E1FFE5C8EAFFE4C8E9FFE3C8FBFF71 +:106AC800E2C8FAFF110038C859F839C85AF83DEC3D +:106AD80037F008010801595108010801586F0DECF9 +:106AE8003FF0080108013B6F38C859F839C85AF80F +:106AF8003DEC37F008010801595108010801646F9D +:106B0800E1EC3EF0080108013A6F080108013B5129 +:106B1800300AD8B492EF35F094EF35F098EF35F0AD +:106B28003BC864F88FEC3FF03AC864F88FEC3FF04C +:106B380008013C6F3A0E08010801646F08013C51D6 +:106B48008FEC3FF038C85AF839C85BF80101000EDD +:106B580008010801586F0101010E0801596F89ECFD +:106B680037F0120053C859F854C85AF83DEC37F0BA +:106B780008010801595108010801586F0DEC3FF050 +:106B880008010801566F53C859F854C85AF83DEC23 +:106B980037F008010801595108010801646FE1EC58 +:106BA8003EF008010801556F080108015651300AE6 +:106BB800D8B4E1EF35F0E3EF35F0E7EF35F056C83C +:106BC80064F88FEC3FF055C864F88FEC3FF008018B +:106BD800576F3A0E08010801646F080157518FEC8E +:106BE8003FF053C85AF854C85BF80101000E080179 +:106BF8000801586F0101010E0801596F89EC37F03F +:106C080012000801276F000E06010601D66F080161 +:106C18002751000E06010601CA6F000E0601CB6F50 +:106C2800000E0601CC6F000E0601CD6F000E0501A7 +:106C38000501FC6F000E0501FD6F000E0501FE6FDA +:106C4800000E0501FF6F010E07010701906F000E8E +:106C58000701916F000E0701926F000E0701936FF5 +:106C68000801276F000E070107010A6F0801275165 +:106C7800000E07010701166F000E0701176F0801C4 +:106C8800276F000E06010601E86F08012751080169 +:106C9800276F000E070107010C6F0801275112002A +:106CA8008CC735F88DC736F88EC737F88FC738F8D0 +:106CB80008013351301131113211D8A466EF36F082 +:106CC80068EF36F075EF36F0010E08010801306FF5 +:106CD800000E0801316F000E0801326F000E080126 +:106CE800336F30C88CF731C88DF732C88EF733C888 +:106CF8008FF70801396F000E08010801346F080189 +:106D080039510F0E0801080134658DEF36F08FEF09 +:106D180036F091EF36F0A0EF36F07BEC22F0080168 +:106D28000801342B0F0E0801080134659EEF36F078 +:106D3800A0EF36F091EF36F0A2EF36F01200040E15 +:106D4800080108014C65ABEF36F0ADEF36F0AFEF58 +:106D580036F0EFEF36F0080108014C51170DF3CF6C +:106D68004DF80C0E08014D270201000E08014D25B3 +:106D7800E96EEA6A0201020EEA22000EEE6E000EC9 +:106D8800ED6E080108014C51170D0201000EF324A5 +:106D9800E96EEA6A0201020EEA22000EEE6E000EA9 +:106DA800EE6E000EEE6E000EED6EED52ED52080125 +:106DB80008014C51170DF3CF4DF80E0E08014D2761 +:106DC8000201000E08014D25E96EEA6A0201020E71 +:106DD800EA22040EEF6E12000601DBC645F8060132 +:106DE800DCC646F8080108013D510801452708019D +:106DF80008013E5108014623140E080145250801E3 +:106E08000801436F000E080146210801446FCE0EA9 +:106E180008010801435D0A0E08014459D8A017EF7C +:106E280037F019EF37F020EF37F00801CE0E0801E0 +:106E3800435F0A0E0801445BE0CE41F8E1CE42F818 +:106E480043C8E0FE44C8E1FE3FC8A0F840C8A1F826 +:106E58000EEC10F0A0C843F8A1C844F841C8E0FE01 +:106E680042C8E1FE43C83DF844C83EF83CEF37F05D +:106E7800120059C85BF85AC85CF845EF37F045EF7F +:106E880037F0080108015B5108015D6F080108012E +:106E98005C5108015E6F08015B4B5C2B5DC8F6FF17 +:106EA8005EC8F7FF000EF86E0E0EF76403D00800F8 +:106EB800F55005D0F6CFE9FFF7CFEAFFEF5000090C +:106EC800D8A469EF37F06BEF37F043EF37F00801DC +:106ED8005BC85DF808015CC85EF8080108015951F3 +:106EE80008015D5F080108015A5108015E5BFF0E49 +:106EF80008015D2508010801596FFF0E08015E2190 +:106F080008015A6F88EF37F0120058C85CF859C862 +:106F18005DF893EF37F0080108015C4B5D2B5CC806 +:106F2800E9FF5DC8EAFFEF50D8A49DEF37F09FEF67 +:106F380037F08FEF37F0A1EF37F0080108015A5109 +:106F480008015E6F080108015B5108015F6F0801C5 +:106F58005A4B5B2B5EC8F6FF5FC8F7FF000EF86E52 +:106F680008015CC8E1FF08015DC8E2FF08010801EB +:106F78005C4B5D2B0E0EF76403D00800F55005D06E +:106F8800F6CFE9FFF7CFEAFFEF50E76EE750D8A456 +:106F9800D0EF37F0D2EF37F09FEF37F0D4EF37F07C +:106FA800120008014C0E080108014D6F0801080E77 +:106FB80008014E6F35EC3DF00009D8A4E6EF37F034 +:106FC800E8EF37F0EAEF37F020EF38F00801080172 +:106FD8004C51C00BC00AD8A4F4EF37F0F6EF37F0E5 +:106FE80003EF38F008014C0E080108014D6F080145 +:106FF800080E08014E6F35EC3DF020EF38F008011F +:1070080008014C670AEF38F00CEF38F00EEF38F053 +:1070180020EF38F0080108014CC84FF808010801B2 +:10702800506B000E080108014D6F000E08014E6FED +:10703800F8EC2BF0D5EF37F0120024C82EF825C84D +:107048002FF822C82CF823C82DF8ACEC2AF0080138 +:107058000801266F24C82EF825C82FF822C82CF856 +:1070680023C82DF8ACEC2AF008010801276F0D0E93 +:1070780008010801266543EF38F045EF38F052EF74 +:1070880038F00D0E0801080127654DEF38F04FEF75 +:1070980038F052EF38F0000E6CEF38F00B0E0801A4 +:1070A800080126615AEF38F05CEF38F069EF38F0E4 +:1070B8000D0E08010801276564EF38F066EF38F017 +:1070C80069EF38F0010E6CEF38F0020E6CEF38F013 +:1070D8001200C4C8C6F8C5C8C7F808010801C351DA +:1070E800C211D8B47AEF38F07CEF38F09DEF38F061 +:1070F8008BEF38F061CF7EFEC2C8E9FFC3C8EAFF54 +:107108000E017ECEEFFF08010801C24BC32B080118 +:107118000801C607D8A0C7070801C629D8B4C729D7 +:10712800D8A499EF38F09BEF38F07EEF38F0B1EF44 +:1071380038F0A1EF38F061CF7EFE08010801C607DC +:10714800D8A0C7070801C629D8B4C729D8A4AFEF63 +:1071580038F0B1EF38F09FEF38F0C4C8C2F8C5C8AE +:10716800C3F8B7EF38F0120022EC2FF00801146FC3 +:10717800000E08010801136F08011451130E0801CD +:1071880008011365CAEF38F0CCEF38F0CEEF38F0CD +:10719800FFEF38F00501E40E080108011325E96E38 +:1071A800EA6A0501050EEA22EF500801146F04018E +:1071B800E30E080108011325E96EEA6A0401040ECA +:1071C800EA22EF5008011419D8B4EDEF38F0EFEFC8 +:1071D80038F0F2EF38F0000E02EF39F0080108013C +:1071E800132B130E080108011365FDEF38F0FFEFAC +:1071F80038F0CEEF38F0010E02EF39F012000E0130 +:10720800DF8F0E01DF9F080E08010801A06F0DEF48 +:1072180039F008010801A0070801A029D8A417EF30 +:1072280039F019EF39F00DEF39F00E01FC93060132 +:107238000601D5B322EF39F024EF39F044EF39F0E5 +:1072480006010601D5B52BEF39F02DEF39F044EFE3 +:1072580039F05AEC42F0A1C81AF7A2C81BF7060188 +:10726800D58506010601D5A73CEF39F03EEF39F088 +:1072780041EF39F08D8242EF39F08D920601D577D2 +:107288000E01DF87C4EC43F0A1C81EF7A2C81FF7A0 +:1072980012000801276F000E08010801266F080177 +:1072A80027517CEF39F022C8E9FF23C8EAFFEF50E5 +:1072B800080108012B6F26C82AF80801276FA00EBD +:1072C80008010801296F080127512DEC24F0080155 +:1072D8000801224B232B0801276FA00E0801080183 +:1072E800296F080127518BEC2BF008010801262B88 +:1072F800080126C827F80801286B0801080124514D +:107308000801275D08010801255108012859D8A05E +:1073180090EF39F092EF39F057EF39F01200CBECDB +:107328003DF00009D8A49BEF39F09DEF39F0A6EFA6 +:1073380039F0000E080108014C6F000E08014D6F6E +:10734800D8EF39F007010701A051080108014C19CD +:10735800D8B4B1EF39F0B3EF39F0C5EF39F04CC814 +:10736800A0F7000E06010601BC6F000E0601BD6FF6 +:10737800000E080108014E6F000E08014F6FBFECA8 +:1073880042F04CC80DF706010601BC51C0080801BF +:1073980008014C6F06010601BD51D8A0E82A05086E +:1073A80008014D6FD8EF39F012004CC80DF70701EE +:1073B8000701A351080108014C19D8B4E6EF39F0C8 +:1073C800E8EF39F0F1EF39F0000E080108014C6FD1 +:1073D800000E08014D6F18EF3AF0070107010FA1E1 +:1073E800F8EF39F0FAEF39F005EF3AF007010F91AD +:1073F800000E080108014E6F000E08014F6F83EC64 +:1074080042F006010601D25106010601CE5D0801CF +:1074180008014C6F06010601D35106010601CF5938 +:1074280008014D6F18EF3AF012002FC8C9FFC6AE19 +:1074380020EF3AF022EF3AF025EF3AF0FF0E57EF3F +:107448003AF027EF3AF0C7B02CEF3AF02EEF3AF0C7 +:1074580027EF3AF030EF3AF0C5CF30F81F0E0801A9 +:10746800301730C831F80801326B000EC7B4010E6E +:1074780008013113000E3213080132513111D8A41A +:1074880048EF3AF04AEF3AF030EF3AF0C5AC4FEF38 +:107498003AF051EF3AF054EF3AF0FE0E57EF3AF067 +:1074A800000E57EF3AF01200AEC8B4F8AFC8B5F8FE +:1074B800ACC8B2F8ADC8B3F882EF3AF00801B4C866 +:1074C800F6FF0801B5C8F7FF000EF86EB2C8E1FF75 +:1074D800B3C8E2FF0E0EF76403D00800F55005D0DC +:1074E800F6CFE9FFF7CFEAFFEF50E76E0801080192 +:1074F800B44BB52B08010801B24BB32B08010801A6 +:10750800B007D8A0B1070801B029D8B4B129D8A4C8 +:1075180090EF3AF092EF3AF062EF3AF094EF3AF0E7 +:10752800120008010E6F000E080108010D6F080116 +:107538000E51BAEF3AF00DC811F808010E6FA00EFF +:1075480008010801106F08010E51C6EC06F0080189 +:107558000801105109C8E9FF0AC8EAFFEF6E0801DF +:107568000801094B0A2B080108010D2B08010DC859 +:107578000EF808010F6B080108010B5108010E5D98 +:10758800080108010C5108010F59D8A0CEEF3AF0B4 +:10759800D0EF3AF09FEF3AF012000801086F000EA2 +:1075A80007010701556F080108510001988F9BECEE +:1075B80003F016C830F817C831F818C832F819C8D7 +:1075C80033F854EC36F02EEC0FF01DEC41F0B8EC2B +:1075D8003FF0C9ECDFF00801086F000E0801080150 +:1075E8001D6F080108511BEC34F00001000198BD23 +:1075F80000EF3BF002EF3BF00CEF3BF00801086FA7 +:10760800000E08010801096F080108511AEC42F040 +:1076180012000401B30E08010801336F0401040EBF +:107628000801346F2DC831F82EC832F812ECD2F0A8 +:107638000009D8B422EF3BF024EF3BF030EF3BF0E9 +:10764800070108830801306F070E07010701A66FBD +:107658000801305147EF3BF02DC806F72EC807F751 +:10766800000E07010701226F000E0701236F0801B2 +:10767800306F000E07010701A66F080130512FC8AF +:107688003CF70701089312000401B30E0801080132 +:10769800336F0401040E0801346F2DC831F82EC869 +:1076A80032F892ECCEF00009D8B45DEF3BF05FEF12 +:1076B8003BF06BEF3BF0070108830801306F070EC2 +:1076C80007010701A66F0801305182EF3BF0000E59 +:1076D80007010701066F000E0701076F2DC822F783 +:1076E8002EC823F70801306F000E07010701A66FA7 +:1076F800080130512FC83CF7070108931200000E0B +:1077080008010801646F000E0801656F080108018F +:1077180060A191EF3BF093EF3BF09FEF3BF0080146 +:107728000801625108010801642708010801635132 +:107738000801080165230801D8900801623708018B +:1077480063370801D89008016133080160330801E4 +:10775800080161516011D8A4B4EF3BF0B6EF3BF0DB +:107768008AEF3BF064C860F865C861F8BCEF3BF08D +:107778001200320E080108015D6F000E08015E6FED +:10778800000E080108015B6F000E08015C6F010123 +:10779800C80E08010801596F0101010E08015A6F4E +:1077A80053EC40F0000E07010701276F000E070198 +:1077B800286F08010D6F000E070107012E6F0801E1 +:1077C8000D5108010D6F000E070107011D6F08011B +:1077D8000D5108010D6F000E070107012F6F0801F9 +:1077E8000D511200000E080108016865FEEF3BF01C +:1077F80000EF3CF002EF3CF02DEF3CF068C871F868 +:107808001DEC2BF0B7EC24F000EE29F010EE07F099 +:10781800E652EE52ED50E518EFCFE8FFD8B4E7187E +:10782800D8B419EF3CF01BEF3CF02DEF3CF0080109 +:10783800696F010E08010801736F08016951080199 +:107848006A6F100E08010801726F08016A519FECF7 +:10785800A1F0120006010601D5A135EF3CF037EF83 +:107868003CF039EF3CF063EF3CF00601D581FF0EA8 +:1078780006010601FC25080108014C6FFF0E0601F0 +:107888000601FD2108014D6FCE0E080108014C5D6F +:107898000A0E08014D59D8A054EF3CF056EF3CF0C1 +:1078A8005DEF3CF0CD0E080108014C6F0A0E08018F +:1078B8004D6F0E01FE8D4CC8ECFE4DC8EDFE12005A +:1078C8000601DBC67FF80601DCC680F8080108015E +:1078D8007B5108017F27080108017C51080180239A +:1078E800140E08017F25080108017D6F000E0801AC +:1078F800802108017E6FCE0E080108017D5D0A0E09 +:1079080008017E59D8A08BEF3CF08DEF3CF094EF46 +:107918003CF00801CE0E08017D5F0A0E08017E5B6F +:107928007DC8E0FE7EC8E1FE120035C8E9FF36C812 +:10793800EAFFD890EF3635C8E9FF36C8EAFFEF50BE +:10794800D8A4A9EF3CF0ABEF3CF0CDEF3CF035C844 +:10795800E9FF36C8EAFF010EEF6E33C8E9FF34C805 +:10796800EAFFEE50ED10D8A4BCEF3CF0BEEF3CF0BF +:10797800C6EF3CF033C8E9FF34C8EAFF000EEE6EEC +:10798800020EED6E33C8E9FF34C8EAFFEE06000EBA +:10799800ED5A1200070107010E67D5EF3CF0D7EF4B +:1079A8003CF0F4EF3CF00082070107011267DFEFBB +:1079B8003CF0E1EF3CF0E3EF3CF001EF3DF012C7A3 +:1079C8000EF7000E07010701126F00B4EEEF3CF04E +:1079D800F0EF3CF0F3EF3CF08978F4EF3CF00094E2 +:1079E800070107010E51D8B4FCEF3CF0FEEF3CF064 +:1079F80001EF3DF0070107010E0712009E92CB68C8 +:107A0800CA82CA9CCA8ACA88CA869F929D82CA8428 +:107A1800000EBD6E000EBA6EBA86BA84BA9EBA9CC3 +:107A2800BD86BD84BD9EBD9CBD86BD84BA86BA8414 +:107A3800BD9ABD98BA9ABA98000EBE6E000EBB6E7B +:107A48000801086F000E07010701866F0801085139 +:107A58000801086F000E070107017D6F0801085132 +:107A6800120006010601CE5106010601D25D06018B +:107A78000601CF5106010601D359D8B046EF3DF0B3 +:107A880048EF3DF055EF3DF007010701A35107010D +:107A980007010D19D8B453EF3DF055EF3DF058EFFD +:107AA8003DF0000E66EF3DF04BEC44F04DC8E9FFA9 +:107AB8004EC8EAFFEF6E06010601D24BD32B010E2A +:107AC80066EF3DF01200C00E04010401FB5D050ED7 +:107AD8000401FC59D8A073EF3DF075EF3DF077EF46 +:107AE8003DF098EF3DF053C8C0F864EC44F0040151 +:107AF8000401FB4BFC2B04010401FB5106010601A8 +:107B0800BC5D04010401FC5106010601BD59D8B051 +:107B180090EF3DF092EF3DF096EF3DF0FBC4BCF6E0 +:107B2800FCC4BDF698EF3DF012000D0E08010801E7 +:107B38002C61A1EF3DF0A3EF3DF0B0EF3DF00D0E4D +:107B4800080108012D61ABEF3DF0ADEF3DF0B0EF5E +:107B58003DF0000ECAEF3DF0180E080108012C6533 +:107B6800B8EF3DF0BAEF3DF0C7EF3DF00D0E08015C +:107B780008012D61C2EF3DF0C4EF3DF0C7EF3DF0C5 +:107B8800010ECAEF3DF0020ECAEF3DF012000E01E1 +:107B98000E01DFB7D2EF3DF0D4EF3DF0D7EF3DF067 +:107BA800010EFAEF3DF0C4EC43F0070107011E5146 +:107BB80008010801A15F070107011F510801080119 +:107BC800A25B7A0E08010801A15D000E0801A25906 +:107BD800D8A0F1EF3DF0F3EF3DF0F7EF3DF00E01E7 +:107BE800DF9703EC39F0000EFAEF3DF012000801C0 +:107BF8000801695167C8E9FF68C8EAFFEF6207EF43 +:107C08003EF009EF3EF00FEF3EF067C867F868C82E +:107C180068F82AEF3EF0080167C8E9FF080168C85C +:107C2800EAFF08010801674B682BEF50D8A41FEF43 +:107C38003EF021EF3EF0FBEF3DF0000E0801080199 +:107C4800676F000E0801686F2AEF3EF01200080106 +:107C58000801A55108010801A21B08010801A25149 +:107C680008010801A51B08010801A5510801080120 +:107C7800A21B08010801A45108010801A31B08015F +:107C88000801A35108010801A41B08010801A45117 +:107C980008010801A31BA2C8A2F8A3C8A3F8A4C896 +:107CA800A4F8A5C8A5F859EF3EF012008988050E7A +:107CB80008015D6F300EE82E5FEF3EF05D2F5FEF3D +:107CC8003EF08998150E08015D6F6C0EE82E6AEF7C +:107CD8003EF05D2F6AEF3EF08988050E08015D6F62 +:107CE800300EE82E75EF3EF05D2F75EF3EF0899867 +:107CF800050E08015D6F300EE82E80EF3EF05D2F17 +:107D080080EF3EF01200B30E080108013325E96E3A +:107D1800020E080108013421EA6EEF50080108013B +:107D2800366F080108013651080135C837F80801CF +:107D3800386B37BF380708013717000E38170801A6 +:107D480038513711D8B4ABEF3EF0ADEF3EF0B0EF9D +:107D58003EF0D880B3EF3EF0D890B3EF3EF012007B +:107D68008988050E08015D6F300EE82EB9EF3EF0E8 +:107D78005D2FB9EF3EF08998050E08015D6F300E52 +:107D8800E82EC4EF3EF05D2FC4EF3EF08988050E63 +:107D980008015D6F300EE82ECFEF3EF05D2FCFEF7C +:107DA8003EF08998150E08015D6F6C0EE82EDAEF2B +:107DB8003EF05D2FDAEF3EF012000F0E08010801C9 +:107DC8006417300E08010801642508010801656F71 +:107DD8000801666B000E08016623090E08010801F8 +:107DE8006465F9EF3EF0FBEF3EF007EF3FF0370E2A +:107DF80008010801642508010801656F0801666B20 +:107E0800000E080166230801080165510CEF3FF0D8 +:107E180012000801583B0F0E5817300E08010801D0 +:107E2800582508010801596F08015A6B000E08010E +:107E38005A23090E08010801586525EF3FF027EF7E +:107E48003FF033EF3FF0370E0801080158250801CD +:107E58000801596F08015A6B000E08015A230801DE +:107E68000801595138EF3FF0120037C8B4FE00F04E +:107E780008013B6F010E0E010E01B26F08013B5164 +:107E880000F047EF3FF00E010E018AB14EEF3FF0D0 +:107E980050EF3FF047EF3FF008013B6F000E0E0137 +:107EA8000E01B26F08013B5100F0B8CE39F800F06E +:107EB800B9CE3AF839C837F83AC838F864EF3FF01D +:107EC8001200C80E080108015D6F000E08015E6F00 +:107ED800000E080108015B6F000E08015C6F0101CC +:107EE800000E08010801596F0101010E08015A6FBF +:107EF80053EC40F00801566F000E04010401FF6FB7 +:107F0800080156510801566F000E06010601D76F89 +:107F1800080156511200000E08010801696F000E91 +:107F280008016A6F0101000E08010801676F01016D +:107F3800010E0801686FFBEC3DF067C865F868C87A +:107F480066F80801080166516511D8B4AEEF3FF034 +:107F5800B0EF3FF0B7EF3FF065C8E9FF66C8EAFF4A +:107F6800080164C8EFFF120008010A6F000E08013B +:107F78000801096F08010A51040E08010801096582 +:107F8800C8EF3FF0CAEF3FF0CCEF3FF0DDEF3FF036 +:107F980009C84CF8A3EC36F008010801092B040EB7 +:107FA800080108010965DBEF3FF0DDEF3FF0CCEF9A +:107FB8003FF007010F8312000801116F000E07013F +:107FC80007012A6F080111510801116F000E0701FE +:107FD8000701106F08011151000E06010601C46F58 +:107FE800000E0601C56F0801116F000E0701070199 +:107FF800136F080111510801116F000E07010701E5 +:10800800116F0801115112000801116F000E0701CC +:1080180007012C6F080111510801116F000E0701AB +:1080280007010B6F080111510801116F000E0701BC +:108038000701296F080111510801116F000E07018E +:1080480007012B6F08011151070107019869070102 +:108058009969120042EF40F0080159C8F6FF08017B +:108068005AC8F7FF000EF86E08000E01F5CF7EFE25 +:1080780008010801594B5A2B7ECE61FF08010801FF +:108088005B07D8A05C0708015B29D8B45C29D8A491 +:1080980050EF40F052EF40F030EF40F0120059C876 +:1080A8005FF85AC860F864EF40F05FC8E9FF60C83D +:1080B800EAFF08015BC8EFFF080108015F4B602B6E +:1080C800080108015D07D8A05E0708015D29D8B43A +:1080D8005E29D8A472EF40F074EF40F059EF40F0F9 +:1080E80076EF40F01200A1C768F8BEEC20F07D0ED4 +:1080F80008010801685D000E08016959D8B087EFCA +:1081080040F089EF40F08BEF40F098EF40F065ECDD +:108118003FF0BB0E08010801536FFF0E0801546FB2 +:10812800B6EC35F04DEC0EF012000AC8B4FE0BC8E0 +:108138007EFE0CC87FFEF250C00B080108010D6FCF +:108148003F0EF2167ECEB6FE00F07FCEB7FE0801D7 +:1081580008010D51F212B1EF40F00E010E018AB183 +:10816800B8EF40F0BAEF40F0B1EF40F01200CBEFBB +:1081780040F0C0C8E9FFC1C8EAFFEF500E010E0188 +:108188007E6F08010801C04BC12B7ECE61FF08013C +:108198000801C207D8A0C3070801C229D8B4C32957 +:1081A800D8A4D9EF40F0DBEF40F0BDEF40F012006B +:1081B80007010701A229D8B4E4EF40F0E6EF40F048 +:1081C800EDEF40F0A2C74CF8A3EC36F00701070129 +:1081D800A2690801306F070E07010701A66F0801A1 +:1081E80030510701089107010831010BFCEF40F0FD +:1081F80012000101000E04010401FF25E96EEA6A7C +:108208000101010EEA22EF50680AD8B40EEF41F0DE +:1082180010EF41F013EF41F0000E1CEF41F00401A4 +:108228000401FF29070107012D6F010E1CEF41F022 +:10823800120004010401DD6904010401DE6904017E +:108248000401DF6904010401E06904010401E16932 +:1082580004010401E269000E04010401D96F000E53 +:108268000401DA6F000E0401DB6F000E0401DC6FFD +:108278001200000E080108010D6545EF41F047EFB7 +:1082880041F04AEF41F0000E5BEF41F00DC871F884 +:108298001DEC2BF01750070AD8B455EF41F058EFF2 +:1082A80041F0010E59EF41F0000E5BEF41F0120072 +:1082B80037EC44F027EC20F02CC82DF874EC44F08F +:1082C80051EC43F00009D8A46CEF41F06EEF41F097 +:1082D80072EF41F065EC3FF076EF41F037EC44F097 +:1082E8004DEC0EF012000101000E04010401FF25FF +:1082F800E96EEA6A0101010EEA22EF50690AD8B470 +:1083080088EF41F08BEF41F0010E8CEF41F0000E49 +:108318008EEF41F01200070107010FB396EF41F00D +:1083280098EF41F0A6EF41F02EEC3CF0000E06016C +:108338000601CE6F000E0601CF6F07010701A36982 +:1083480007010F831200F28A00F0F29AD6CFFAF1F1 +:10835800D7CFFBF1EDC6FCF1EEC6FDF1EFC6FEF19D +:10836800F0C6FFF1F2B4BBEF41F0BDEF41F0A7EF6B +:1083780041F0F28A1200F28A00F0F29AD6CFFAF1AE +:10838800D7CFFBF1EDC6FCF1EEC6FDF1EFC6FEF16D +:10839800F0C6FFF1F2B4D3EF41F0D5EF41F0BFEFF3 +:1083A80041F0F28A120008010D6F010E0701070162 +:1083B8007E6F08010D51070107017B69BB68C4EC9A +:1083C80043F0A1C87FF7A2C880F7A3C881F7A4C863 +:1083D80082F71200000E080108010D65F6EF41F062 +:1083E800F8EF41F0FAEF41F003EF42F00DC871F8F1 +:1083F8001DEC2BF018960DC82DF895EC12F0120014 +:10840800F2A409EF42F00BEF42F019EF42F0010E2F +:1084180006010601ED27000E0601EE23000E0601F7 +:10842800EF23000E0601F023F29412004428D8B47A +:1084380020EF42F022EF42F027EF42F044C04CF820 +:10844800A3EC36F0446808010A6F000E0001000131 +:10845800456F08010A51120057C859F858C85AF808 +:108468003DEC37F059C85CF85AC85DF857C85AF857 +:1084780058C85BF856C859F88CECE3F044EF42F062 +:10848800120057C859F858C85AF83DEC37F059C87F +:108498005CF85AC85DF857C85AF858C85BF856C807 +:1084A80059F883ECDEF059EF42F01200A7EC41F0E6 +:1084B800FBC1A5F8FCC1A6F8FDC1A7F8FEC1A8F844 +:1084C800A5C8A1F8A6C8A2F8A7C8A3F8A8C8A4F880 +:1084D8006EEF42F01200948694883F0EC716000E85 +:1084E800C66E000EC56EC686C78E82868288C68A0C +:1084F8000801096F430EC86E080109511200080EE1 +:10850800080108014E2508010801796F000E0801CD +:1085180008014F2108017A6FF9EC42F04EC8D2F6F3 +:108528004FC8D3F612000801226F010E0801080196 +:10853800376F0801225139EC3FF0370EE96E080E0B +:10854800EA6EEF30E832010BAAEF42F012000001A8 +:1085580000014567B2EF42F0B4EF42F0BEEF42F0DF +:108568000801386F010E00010001456F08013851FC +:10857800000146911200F90E080108014E25080174 +:108588000801AC6F0A0E080108014F210801AD6F00 +:108598000BEC44F04EC8FBF44FC8FCF412000AC8B8 +:1085A80059F80BC85AF83DEC37F059C855F85AC86D +:1085B80056F80AC853F80BC854F8F9EC30F0E5EF50 +:1085C80042F012000AC859F80BC85AF83DEC37F0C7 +:1085D80059C855F85AC856F80AC853F80BC854F879 +:1085E80053EC31F0F8EF42F0120006010601FA519F +:1085F800080108017925080108017B6F000E0801B0 +:1086080008017A2108017C6F64EC3CF01200A1C7D4 +:1086180068F8BEEC20F065EC3FF0680E0801080130 +:10862800536FFF0E0801546FB6EC35F021EC44F09F +:1086380012000701070108A124EF43F026EF43F0D9 +:1086480029EF43F0000E2EEF43F007010881010ED9 +:108658002EEF43F01200BCC8BFF8BDC8C0F8C0C8B0 +:10866800BEF8BFC8C0F8BEC8BFF8BFC8BCF8C0C80D +:10867800BDF83FEF43F0120032C838F833C839F874 +:1086880067EC35F034C853F835C854F836C855F88F +:1086980037C856F866EC13F0120006010601E551DA +:1086A800030AD8B45AEF43F05DEF43F0010E5EEFD2 +:1086B80043F0000E60EF43F0120006010601D751A7 +:1086C800040AD8B46AEF43F06DEF43F0010E6EEF81 +:1086D80043F0000E70EF43F012002EC834F82FC894 +:1086E80035F830C836F831C837F82CC832F82DC8F4 +:1086F80033F840EC43F01200000ED76E000ED66E31 +:10870800F194F294F28A0801086F870ED56E080179 +:10871800085112000E010E01DFAB95EF43F098EF00 +:1087280043F0010E99EF43F0000E9BEF43F0120067 +:1087380076927690769C769A768876967684A496C3 +:108748007768A38697949388A586120030C838F86E +:1087580031C839F867EC35F032C853F833C854F8E3 +:10876800B6EC35F0120026C82BF824C829F825C81D +:108778002AF822C827F823C828F84EEC17F0120068 +:10878800A7EC41F0FAC1A1F8FBC1A2F8FCC1A3F81B +:10879800FDC1A4F8D0EF43F01200BFEC41F0FAC1DC +:1087A800DEF8FBC1DFF8FCC1E0F8FDC1E1F8DDEF60 +:1087B80043F012000101000E08010801366F0101A3 +:1087C800010E0801376FE9EF43F0120008010E6F40 +:1087D800020E070107017E6F08010E510DC87BF7D5 +:1087E80012002EC832F82FC833F82CC830F82DC81C +:1087F80031F8AAEC43F0120008010E6F020E0701CF +:108808000701876F08010E510DC884F71200E2CEE8 +:10881800AEF8E3CEAFF8ACC8E2FEADC8E3FE15EFA4 +:1088280044F01200C4EC43F0A1C8E9F6A2C8EAF685 +:10883800A3C8EBF6A4C8ECF6120008012C6F680E6A +:1088480008010801646F08012C518FEC3FF01200F9 +:10885800E0CEAEF8E1CEAFF8ACC8E0FEADC8E1FEC0 +:1088680036EF44F0120008012D6F730E080108015D +:10887800646F08012D518FEC3FF012009792929887 +:108888008998B19AB198A082A282B190120061CF62 +:108898007EFE0E010E017E5152EF44F012000001DF +:1088A8004651010B58EF44F01200070107012E5101 +:1088B8005EEF44F012007AEC44F0B1907684120036 +:1088C800C0C87EFE7ECE61FF1200D08EF28EF28C82 +:1088D8001200769471EC44F012008E828E9412008D +:1088E8002DC87DF7120056C886F712008E928E8426 +:0888F8001200BCEC09F01200B3 +:10FE16002F7365727665722F61737369676E3F65BE +:10FE26006D6265646465643D312670726F746F63DC +:10FE36006F6C56657273696F6E3D32266D61633DF8 +:10FE46000048415052414455395055535445575531 +:10FE56003355334136484550415145465245504544 +:10FE6600500000005E01E8036700535741513854C3 +:10FE76004845433245424139484546454A3552553B +:10FE860053544548455939323754000D0A436F6E6D +:10FE96006E656374696F6E3A20636C6F73650D0AE5 +:10FEA6000D0A0020485454502F312E300D0A486F49 +:10FEB60073743A200073656C666C6561726E696E68 +:10FEC6006776320054656C6C537469636B4E657467 +:10FED6003A0054656C6C537469636B204E6574000C +:10FEE60073656C666C6561726E696E6700657665D2 +:10FEF60072666C6F7572697368007265676C697398 +:10FF060074656E657200646973636F6E6E656374A3 +:10FF16000066696E656F666673657400636F646517 +:10FF26007377697463680070726F746F636F6C00C7 +:10FF36005265676973746572006D616E646F6C7982 +:10FF46006E0076657273696F6E00676174657761BE +:10FF5600790061726374656368006E65746D6173C0 +:10FF66006B0052617744617461006F7265676F6EF2 +:10FF760000736176656970007365637265740073FA +:10FF8600656E736F72006D6574686F6400636C6193 +:10FF9600737300686F7573650073657469700068C4 +:10FFA60061737461006D6F64656C006461746100F7 +:10FFB60073656E640050696E6700686173680064FB +:10FFC6006E7331007368613100756E697400646E1A +:10FFD60073320047455420006D61630032383A00A1 +:10FFE6006B65790041434B00783130003137006F43 +:0AFFF6007300520050005300000099 :020000040001F9 -:100000006170692E74656C6C6475732E636F6D001E -:1000100000000100000000000000000100000000DE -:100020000000FFFFF3FF80FFFFFEFEFFFEFFFFFE6D -:1000300007000D0E070107014A25E96E000E0701B2 -:1000400007014B21EA6EEF50070107014F6F080EC1 -:10005000070107014A25E96E000E070107014B2140 -:10006000EA6E0701EECF64F70701EECF65F70701EF -:10007000EECF66F70701EECF67F7040E0701070121 -:100080004A25E96E000E070107014B21EA6E0701C0 -:10009000EECF58F70701EECF59F70701EECF5AF729 -:1000A0000701EECF5BF70301F6910301F69303011D -:1000B000F6950B000E0003010301F6B901D001D043 -:1000C0001BD019EC22F0740E07010701A3250301D0 -:1000D0000301ED6F350E07010701A4210301EE6F47 -:1000E000060E07010701A5210301EF6F000E0701AE -:1000F0000701A6210301F06F5BD1070107014FA59E -:1001000001D001D004D017EC0EF086EF8EF007017D -:1001100007014FA901D001D01ED064C7CCF465C738 -:10012000CDF466C7CEF467C7CFF40701686F000E41 -:1001300007010701716F070168510701696F040E1C -:1001400007010701706F07016951B4EC9BF017ECD0 -:100150000EF086EF8EF0070107014FA301D001D00A -:100160003AD0010E07010701582504010401D06FA0 -:10017000000E0701070159210401D16F000E07018C -:1001800007015A210401D26F000E070107015B210C -:100190000401D36F03ECDBF070C7EBF471C7ECF430 -:1001A0000701686F010E07010701716F07016851B0 -:1001B0000701696F120E07010701706F070169518E -:1001C000B4EC9BF00701686F060E03010301F56FA5 -:1001D0000701685102D017EC0EF086EF8EF0070190 -:1001E00007014FA501D001D002D086EF8EF00701A4 -:1001F00007014FA901D001D04BD00701070167517A -:1002000004010401CF1914E107010701665104013B -:100210000401CE190DE10701070165510401040134 -:10022000CD1906E107010701645104010401CC194D -:10023000D8B401D001D02CD0CCC458F7CDC459F7D4 -:10024000CEC45AF7CFC45BF764C7CCF465C7CDF40E -:1002500066C7CEF467C7CFF40701686F010E0701C8 -:100260000701716F070168510701696F040E0701EB -:100270000701706F07016951B4EC9BF058C7CCF4CB -:1002800059C7CDF45AC7CEF45BC7CFF486EF8EF0D2 -:10029000070107014FA301D001D087D0010E07014C -:1002A0000701582504010401D06F000E0701070162 -:1002B00059210401D16F000E070107015A210401E1 -:1002C000D26F000E070107015B210401D36F0E0EF0 -:1002D000070107014A25E96E000E070107014B21BE -:1002E000EA6E0401EECFDAF40401EDCFDBF403ECA7 -:1002F000DBF070C7EBF471C7ECF4070107014FA9FD -:1003000001D001D038D00701686F010E0701070145 -:10031000716F070168510701696F100E070107012E -:10032000706F07016951B4EC9BF00701686F070E0D -:1003300003010301F56F0701685119EC22F0740EF7 -:1003400007010701A32503010301ED6F350E070126 -:100350000701A4210301EE6F060E07010701A52185 -:100360000301EF6F000E07010701A6210301F06FE3 -:100370000301F6991AD00701686F010E0701070102 -:10038000716F070168510701696F120E07010701BC -:10039000706F07016951B4EC9BF00701686F060E9E -:1003A00003010301F56F0701685186EF8EF00AD053 -:1003B00003010301F551040A01E19FD6010A01E19D -:1003C0000ED7F5D74CC752F74DC753F707010701B2 -:1003D0004FA101D001D004D007010701524B532B8C -:1003E000070107014FA301D001D004D00701070185 -:1003F000524B532B030103EEEBF0030113EEE9F034 -:10040000E652EE52ED50E55C02E1EF50E75CD8A019 -:1004100001D001D030D0030103EEE9F0EECF68F750 -:10042000EDCF69F703010301EB510701685F030199 -:100430000301EC510701695B030103EEE3F0EECF2A -:100440006AF7EDCF6BF703010301E15107016A5F22 -:1004500003010301E25107016B5B070168510701CA -:100460006A5D07010701506F0701695107016B5968 -:100470000701516F1CD0030103EEEBF0EECF68F7DC -:10048000EDCF69F703010301E9510701685F03013B -:100490000301EA510701695BFF0E070168250701A7 -:1004A0000701506FFF0E070169210701516F040119 -:1004B0000401D05107010701585D07010701606F72 -:1004C00004010401D1510701070159590701616F66 -:1004D00004010401D251070107015A590701626F53 -:1004E00004010401D351070107015B590701636F40 -:1004F00060C754F761C755F70701686F000E070121 -:1005000007014E6F0701685107010701535152114E -:10051000D8B401D001D0F9D00701070151515011D1 -:10052000D8B401D001D0F0D00701070163BF01D0DA -:1005300001D02FD00701070150510701686F070153 -:10054000070151510701696F07016A6B07016B6B66 -:100550000701685107010701605D07016951070143 -:100560000701615907016A51070107016259070133 -:100570006B51070107016359D8B001D001D009D0F0 -:100580000701686F010E070107014E6F07016851EF -:100590006CD00701070152510701070160250701CF -:1005A000686F070107015351070107016121070126 -:1005B000696F000E07010701622107016A6F000ED3 -:1005C00007010701632107016B6F07016B51800A67 -:1005D000800F08E1000E6A5D05E1000E695D02E131 -:1005E000010E685DD8A001D001D03FD007010701FE -:1005F000525107010701505D0701686F07010701AC -:1006000053510701070151590701696F07016A6BCF -:10061000070169BF6A0707016A5107016B6F07018C -:100620006B51800A07016C6F0701070160510701D8 -:10063000685D070107016151070169590701070159 -:10064000625107016A59070107016351800A0701D6 -:100650006C59D8A001D001D008D00701686F010EF5 -:10066000070107014E6F070168510701070150514B -:100670000701686F0701070151510701696F070101 -:100680006A6B07016B6B070107016351800A070161 -:100690006C6F0701685107010701605D070169512F -:1006A00007010701615907016A51070107016259F2 -:1006B00007016B51800A07016C59D8B001D001D0F5 -:1006C00023D0070154C768F7070155C769F7070129 -:1006D000070152510701682707010701535107011C -:1006E000692307016951800A800F010ED8B4685D43 -:1006F000D8A001D001D008D00701686F010E070112 -:1007000007014E6F0701685146D007016351601120 -:1007100061116211D8A401D001D009D00701686F1E -:10072000010E070107014E6F0701685134D0070120 -:10073000070163BF01D001D02ED00701070150513E -:100740000701686F0701070151510701696F070130 -:100750006A6B07016B6B0701685107010701605D58 -:100760000701695107010701615907016A51070132 -:100770000701625907016B51070107016359D8B09E -:1007800001D001D008D00701686F010E07010701F1 -:100790004E6F07016851070107014E6701D001D074 -:1007A0001AD0070107014FB501D001D012D00701BF -:1007B000686F010E07010701716F0701685107019A -:1007C000696F100E07010701706F07016951B4ECE2 -:1007D0009BF086EF8EF0070107014F51060BD8B44E -:1007E00001D001D004D017EC0EF086EF8EF0070197 -:1007F00007014FB901D001D002D086EF8EF09DEFF6 -:1008000088F007010701675104010401CF1914E1C1 -:1008100007010701665104010401CE190DE107012A -:100820000701655104010401CD1906E10701070123 -:10083000645104010401CC19D8B401D001D02CD0EA -:10084000CCC458F7CDC459F7CEC45AF7CFC45BF720 -:1008500064C7CCF465C7CDF466C7CEF467C7CFF4E0 -:100860000701686F010E07010701716F07016851E9 -:100870000701696F040E07010701706F07016951D5 -:10088000B4EC9BF058C7CCF459C7CDF45AC7CEF49A -:100890005BC7CFF486EF8EF00701686F070E030188 -:1008A0000301F56F0701685104010401D4510301EC -:1008B0000301E55D07010701566F04010401D551ED -:1008C00003010301E6590701576F0701070157AFFD -:1008D00001D001D01BD0030103EEE1F0EECF68F7A9 -:1008E000EDCF69F703010301DF510701685F0301E1 -:1008F0000301E0510701695B070168510701070126 -:10090000562707016951070107015723070107010E -:10091000565104010401CC25070107015C6F070152 -:100920000701575104010401CD2107015D6F000E3D -:1009300004010401CE2107015E6F000E04010401D1 -:10094000CF2107015F6F070107016451070107010C -:100950005C5D0701686F0701070165510701070129 -:100960005D590701696F070107016651070107011A -:100970005E5907016A6F0701070167510701070107 -:100980005F5907016B6F07016BAF01D001D014D025 -:100990000701686F000E07010701716F07016851B9 -:1009A0000701696F100E07010701706F0701695198 -:1009B000B4EC9BF086EF8EF003010301E7510401D4 -:1009C0000401D45D0701686F03010301E8510401CC -:1009D0000401D5590701696F07016A6B070169BFF7 -:1009E0006A0707016A5107016B6F0701685104012B -:1009F0000401CC5D070107015C6F07016951040127 -:100A00000401CD5907015D6F07016A51040104011A -:100A1000CE5907015E6F07016B5104010401CF59E4 -:100A200007015F6F030103EEE7F0040114EED4F059 -:100A3000E652EE52ED50E55C02E1EF50E75CD8B0D3 -:100A400001D001D028D003010301DF5103010301CC -:100A5000E15D0701686F03010301E0510301030138 -:100A6000E2590701696F07016A6B07016B6B0701A8 -:100A70006851070107015C5F070169510701070120 -:100A80005D5B07016A51070107015E5B07016B515E -:100A9000070107015F5B070107015C5107010701BF -:100AA000645D070107015C6F070107015D510701E4 -:100AB0000701655907015D6F070107015E510701D5 -:100AC0000701665907015E6F070107015F510701C2 -:100AD0000701675907015F6F070107015F51800A2E -:100AE000800F0BE1000E07015E5D07E1000E0701BC -:100AF0005D5D03E1010E07015C5DD8A001D001D06E -:100B00003BD103010301DF5103010301E15D070153 -:100B1000686F03010301E05103010301E25907017A -:100B2000696F07016A6B07016B6B070107015C5175 -:100B30000701685D070107015D5107016959070158 -:100B400007015E5107016A59070107015F5107015B -:100B50006B59D8A001D001D00FD10401EA9704014C -:100B6000EA990301F791E7C356F7E8C357F707017E -:100B700007015C5103010301E727070107015D51EC -:100B800003010301E8230701070156510401040191 -:100B9000D45D07010701575104010401D559D8A0BC -:100BA00001D001D039D0030103EEE7F0040114EEC7 -:100BB000D4F0E652EE52ED50E55C02E1EF50E75C16 -:100BC000D8B001D001D027D0030103EEE7F0EECF7B -:100BD00068F7EDCF69F704010401D4510701685F9C -:100BE00004010401D5510701695B07016851040143 -:100BF0000401CC270701695104010401CD23000E33 -:100C000004010401CE23000E04010401CF23E7C335 -:100C1000D4F4E8C3D5F457D0030103EEE1F0EECFEE -:100C200068F7EDCF69F703010301DF510701685F42 -:100C300003010301E0510701695B04010401D45180 -:100C40000701682507010701566F04010401D5510A -:100C5000070169210701576F03010301E7510701EC -:100C60000701565D03010301E851070107015759C8 -:100C7000D8B001D001D027D0030103EEE7F0EECFCA -:100C800068F7EDCF69F70701070156510701685F63 -:100C90000701070157510701695B0701685104010A -:100CA0000401CC270701695104010401CD23000E82 -:100CB00004010401CE23000E04010401CF23E7C385 -:100CC000D4F4E8C3D5F4030103EEE1F0030113EE1D -:100CD000E7F0E652EE52ED50E55C02E1EF50E75CE2 -:100CE000D8A001D001D01BD0030103EEE1F0EECF7C -:100CF00068F7EDCF69F703010301DF510701685F72 -:100D000003010301E0510701695B07016851030119 -:100D10000301E75F0701695103010301E85B030178 -:100D200003EEE1F0040114EED4F0E652EE52ED5081 -:100D3000E55C02E1EF50E75CD8A001D001D01BD008 -:100D4000030103EEE1F0EECF68F7EDCF69F70301A1 -:100D50000301DF510701685F03010301E05107014F -:100D6000695B0701685104010401D45F07016951FF -:100D700004010401D55B93D0040104EED4F0030117 -:100D800013EEE7F0E652EE52ED50E518EFCFE8FF34 -:100D9000D8B4E718D8B401D001D081D0040104013F -:100DA000EAA701D001D079D004010401EAA901D059 -:100DB00001D071D003010301E75104010401D45DA6 -:100DC0000701686F03010301E85104010401D559CB -:100DD0000701696F07016A6B070169BF6A070701AD -:100DE0006A5107016B6F0701685104010401CC5F70 -:100DF0000701695104010401CD5B07016A51040137 -:100E00000401CE5B07016B5104010401CF5B0301B8 -:100E100003EEE7F0040114EED4F0E652EE52ED508A -:100E2000E55C02E1EF50E75CD8B001D001D02DD0F5 -:100E300003010301DF5103010301E15D0701686F55 -:100E400003010301E05103010301E2590701696F46 -:100E500007016A6B070169BF6A0707016A51070149 -:100E60006B6F0701685104010401CC5F07016951F0 -:100E700004010401CD5B07016A5104010401CE5B4A -:100E800007016B5104010401CF5BE7C3D4F4E8C34D -:100E9000D5F40301F7850401EA890401EA87030117 -:100EA00003EEE5F0030113EEE7F0E652EE52ED50EB -:100EB000E518EFCFE8FFD8B4E718D8A401D001D0E7 -:100EC00049D003010301F7B701D001D01ED019ECBE -:100ED00022F0740E07010701A32503010301ED6F42 -:100EE000350E07010701A4210301EE6F060E07016D -:100EF0000701A5210301EF6F000E07010701A621DD -:100F00000301F06F0301F69925D00701070167512E -:100F100004010401CF1914E107010701665104011E -:100F20000401CE190DE10701070165510401040117 -:100F3000CD1906E107010701645104010401CC1930 -:100F4000D8A401D001D006D00301F6990301F79788 -:100F50000401EA9104010401DB51DA11D8A401D0A3 -:100F600001D012D00E0E070107014A25E96E000ECE -:100F7000070107014B21EA6EEE50ED10D8B401D005 -:100F800001D002D00301F7830E0E070107014A25A5 -:100F9000E96E000E070107014B21EA6E0401EECF56 -:100FA000DAF40401EDCFDBF403010301F551080A83 -:100FB000D8A401D001D045D0070107016751040131 -:100FC0000401CF1914E1070107016651040104016E -:100FD000CE190DE107010701655104010401CD1986 -:100FE00006E107010701645104010401CC19D8A4EA -:100FF00001D001D025D019EC22F0BA0E070107016B -:10100000A32503010301ED6F1A0E07010701A421B7 -:101010000301EE6F030E07010701A5210301EF6F26 -:10102000000E07010701A6210301F06F0301F689F5 -:101030000701686F090E03010301F56F070168518D -:1010400058D003010301F551090AD8A401D001D0F9 -:1010500025D0070107014FB101D001D01ED064C7D0 -:10106000CCF465C7CDF466C7CEF467C7CFF40701EB -:10107000686F000E07010701716F070168510701D2 -:10108000696F140E07010701706F07016951B4EC15 -:101090009BF017EC0EF086EF8EF02BD003010301CE -:1010A000F5510A0AD8A401D001D023D007010701C5 -:1010B000675104010401CF1914E1070107016651CA -:1010C00004010401CE190DE1070107016551040176 -:1010D0000401CD1906E1070107016451040104016F -:1010E000CC19D8A401D001D002D017EC0EF086EFB5 -:1010F0008EF041D007010701675104010401CF19A7 -:1011000014E107010701665104010401CE190DE144 -:1011100007010701655104010401CD1906E107012A -:101120000701645104010401CC19D8A401D001D0F5 -:1011300002D017EC0EF086EF8EF003010301F5519B -:10114000060A02E101EF84F0010A02E154EF84F0A3 -:101150000F0A02E154EF84F0010A02E154EF84F037 -:10116000030A02E154EF84F0010A02E154EF84F033 -:10117000070AC0E0BED7070107014FAB01D001D07D -:1011800002D086EF8EF003010301F5510B0AD8A4BB -:1011900001D001D002D086EF8EF003010301F5519A -:1011A0000A0AD8A401D001D002D086EF8EF0030144 -:1011B0000301F5510C0AD8A401D001D002D086EF6A -:1011C0008EF0070107014D514C11D8B401D002D067 -:1011D0003BEF8DF0070107015551800A800F010E8A -:1011E000D8B4545DD8B001D001D0BBD10C0E0701EA -:1011F00007014A25E96E000E070107014B21EA6E3F -:10120000EF380F0B0701686F68C769F707016A6B52 -:10121000D890070169376A37D890070169376A376C -:101220000701070154510701695D07010701776F45 -:1012300007010701555107016A590701786FA8ECAA -:1012400021F0070107015451070107014C2707014D -:1012500007015551070107014D23070107014C51B3 -:1012600007010701505D070107014D510701070103 -:101270005159D8B001D001D004D050C74CF751C754 -:101280004DF7070107014C5104010401D027070164 -:1012900007014D5104010401D123000E0401040192 -:1012A000D223000E04010401D323030103EEE9F06D -:1012B000EECF68F7EDCF69F7070107014C51070141 -:1012C0006827070107014D5107016923070168518C -:1012D00003010301E35D0701695103010301E459BF -:1012E000D8B001D001D07FD0030103EEE3F0EECF00 -:1012F00068F7EDCF69F703010301E9510701685F62 -:1013000003010301EA510701695B010E070168252A -:1013100007010701566F000E070169210701576F8A -:1013200056C7ACF757C7ADF70701686F000E070146 -:101330000701AB6F07016851FF0E07010701A96F95 -:10134000FF0E0701AA6FFAC3A8F7E9C3A6F7EAC31D -:10135000A7F74AEC0CF007010701565107010701F6 -:101360004C5D07010701AC6F0701070157510701E9 -:1013700007014D590701AD6F0701686F000E0701A6 -:101380000701AB6F07016851FF0E07010701A96F45 -:10139000FF0E0701AA6FFAC3A8F7E1C3A6F7E2C3DD -:1013A000A7F74AEC0CF007014CC768F707014DC7D7 -:1013B00069F70701070156510701685F0701070137 -:1013C00057510701695B03010301E15107016825DA -:1013D00003010301E96F03010301E25107016921E0 -:1013E0000301EA6F27D04CC7ACF74DC7ADF7070133 -:1013F000686F000E07010701AB6F07016851FF0E10 -:1014000007010701A96FFF0E0701AA6FFAC3A8F72A -:10141000E9C3A6F7EAC3A7F74AEC0CF007010701F6 -:101420004C5103010301E927070107014D51030155 -:101430000301EA2304010401E829D8B4E929D8B456 -:1014400001D001D08DD0070107014C5104010401E6 -:10145000E85F070107014D5104010401E95B040144 -:101460000401E85104010401DC2507010701566F5E -:1014700004010401E95104010401DD210701576F52 -:101480000701070157AF01D001D006D004010401C4 -:10149000E8690401E96964D0040104EEE8F0EE5261 -:1014A000ED50800A800F010ED8B4EF5CD8B001D0A7 -:1014B00001D056D007010701565104010401D0277D -:1014C00007010701575104010401D123000E040153 -:1014D0000401D223000E04010401D32307010701F4 -:1014E000565103010301E927070107015751030181 -:1014F0000301EA23030103EEE9F0030113EEE3F035 -:10150000E652EE52ED50E55C02E1EF50E75CD8B0F8 -:1015100001D001D020D0030103EEE3F0EECF68F755 -:10152000EDCF69F703010301E1510701685F030192 -:101530000301E2510701695B010E07016827000EF4 -:1015400069230701685103010301E95F070169513C -:1015500003010301EA5B04010401E8690401E9698C -:101560008AD2070107015551800A800F010ED8B4B5 -:10157000545DD8A001D001D07ED207014CC768F7D6 -:1015800007014DC769F70701070154510701682793 -:101590000701070155510701692307016851070138 -:1015A0000701505D07016951070107015159D8B082 -:1015B00001D001D011D007010701545107010701E3 -:1015C000505D070107014C6F0701070155510701E5 -:1015D0000701515907014D6F0C0E070107014A25FC -:1015E000E96E000E070107014B21EA6EEF380F0B81 -:1015F0000701686F68C769F707016A6BD890070130 -:1016000069376A37D890070169376A3769C777F74A -:101610006AC778F7A8EC21F0030103EEE9F0EECFFA -:1016200068F7EDCF69F707010701545107016827F3 -:1016300007010701555107016923070107014C51B3 -:1016400007016827070107014D51070169230701B9 -:10165000685103010301E35D0701695103010301BF -:10166000E459D8B001D001D0CDD0030103EEE3F0AE -:10167000EECF68F7EDCF69F703010301E9510701E8 -:10168000685F03010301EA510701695B010E07016D -:101690006827000E69230701070154510701685D9F -:1016A00007010701566F07010701555107016959E5 -:1016B0000701576F0701070157BF01D001D051D073 -:1016C00056C7ACF757C7ADF70701686F000E0701A3 -:1016D0000701AB6F07016851FF0E07010701A96FF2 -:1016E000FF0E0701AA6FFAC3A8F7070107015451BB -:1016F00003010301E92507010701A66F070107019F -:10170000555103010301EA210701A76F4AEC0CF0D0 -:10171000070107015651070107014C5D0701070149 -:10172000AC6F070107015751070107014D59070128 -:10173000AD6F0701686F000E07010701AB6F07016E -:101740006851FF0E07010701A96FFF0E0701AA6F7D -:10175000FAC3A8F7E1C3A6F7E2C3A7F74AEC0CF077 -:1017600050D04CC7ACF74DC7ADF70701686F000EFE -:1017700007010701AB6F07016851FF0E0701070161 -:10178000A96FFF0E0701AA6FFAC3A8F7030103EEC2 -:10179000E3F0EECF69F7EDCF6AF703010301E15102 -:1017A0000701695F03010301E25107016A5B03015D -:1017B00003EEE9F0EECF6BF7EDCF6CF70701070111 -:1017C000545107016B2707010701555107016C238D -:1017D0000701695107016B5D07016D6F07016A51D0 -:1017E00007016C5907016E6FFF0E07016D25070198 -:1017F0000701A66FFF0E07016E210701A76F4AECD4 -:101800000CF028D04CC7ACF74DC7ADF70701686F97 -:10181000000E07010701AB6F07016851FF0E0701BA -:101820000701A96FFF0E0701AA6FFAC3A8F7070106 -:101830000701545103010301E92507010701A66FC0 -:1018400007010701555103010301EA210701A76FB1 -:101850004AEC0CF004010401E829D8B4E929D8A421 -:1018600001D001D009D054C7E8F455C7E9F44CC7FA -:10187000DCF44DC7DDF4FFD004010401E851070199 -:101880000701545D04010401E9510701070155599D -:10189000D8B001D001D075D0070154C768F707014F -:1018A00055C769F7070107014C5107016827070170 -:1018B00007014D5107016923040104EEE8F0EECF62 -:1018C0006AF7EDCF6BF704010401DC5107016A27C9 -:1018D00004010401DD5107016B2307016851070171 -:1018E0006A5D0701695107016B59D8A001D001D089 -:1018F0001ED0070154C768F7070155C769F70701EC -:1019000007014C5107016827070107014D510701E5 -:10191000692304010401E8510701685D0401040121 -:10192000E95107016959D8B001D001D005D04CC7A1 -:10193000DCF44DC7DDF420D0040104EEE8F0EECF76 -:1019400068F7EDCF69F704010401DC51070168274E -:1019500004010401DD510701692307010701545106 -:101960000701685D04010401DC6F0701070155519F -:10197000070169590401DD6F54C7E8F455C7E9F45C -:101980007AD0070154C768F7070155C769F70701FF -:1019900007014C5107016827070107014D51070155 -:1019A0006923040104EEE8F0EECF6AF7EDCF6BF7A0 -:1019B00004010401DC5107016A2704010401DD511F -:1019C00007016B230701685107016A5D070169512F -:1019D00007016B59D8B001D001D04DD0040104EEFD -:1019E000E8F0EECF68F7EDCF69F704010401DC51B0 -:1019F0000701682704010401DD510701692307017C -:101A0000070154510701685D07010701555107019E -:101A10006959D8A001D001D02ED0070154C768F76A -:101A2000070155C769F7070107014C5107016827EE -:101A3000070107014D510701692304010401E85121 -:101A40000701685F04010401E9510701695B0401B2 -:101A50000401DC510701685F04010401DD51070145 -:101A6000695B0701685104010401DC270701695122 -:101A700004010401DD230701070153515211D8B4B9 -:101A800001D001D040D003010301F551070AD8B4B9 -:101A900001D001D004D0E9C3EBF3EAC3ECF30301B6 -:101AA0000301F6AF01D001D015D00701686F010E18 -:101AB00007010701716F070168510701696F100E77 -:101AC00007010701706F07016951B4EC9BF077ECD7 -:101AD000E7F019D00301F68F03010301F6BD01D031 -:101AE00001D011D00301F68D55EC20F00F0E070147 -:101AF0000701702503010301F36F000E07010701C1 -:101B000071210301F46F070107014FA101D001D03A -:101B1000FDD00701070152510701070158250701B0 -:101B2000686F070107015351070107015921070198 -:101B3000696F000E070107015A2107016A6F000E45 -:101B4000070107015B2107016B6F010E040104010E -:101B5000D02507016C6F000E04010401D12107019B -:101B60006D6F000E04010401D22107016E6F000E9B -:101B700004010401D32107016F6F07016B510701B5 -:101B80006F190EE107016A5107016E1909E107019A -:101B9000695107016D1904E10701685107016C19CA -:101BA000D8A401D001D0B2D0010E04010401D02785 -:101BB000000E0401D123000E0401D223000E040103 -:101BC000D32385D00701686F0C0E03010301F56F65 -:101BD000070168510701686F010E07010701716F66 -:101BE000070168510701696F110E07010701706F46 -:101BF00007016951B4EC9BF089D00701686F0B0EA7 -:101C000003010301F56F0701685155EC20F01F0E29 -:101C100007010701702503010301F36F000E07019F -:101C2000070171210301F46F5FD0070107016751BC -:101C300004010401CF1914E10701070166510401F1 -:101C40000401CE190DE107010701655104010401EA -:101C5000CD1906E107010701645104010401CC1903 -:101C6000D8A401D001D015D00701686F000E07017C -:101C70000701716F070168510701696F100E0701B5 -:101C80000701706F07016951B4EC9BF017EC0EF07F -:101C90003DD00701686F0A0E03010301F56F0701CC -:101CA000685122D00701686F000E07010701716FAC -:101CB000070168510701696F100E07010701706F76 -:101CC00007016951B4EC9BF017EC0EF01FD0030133 -:101CD0000301F551060A01E175D7010A8EE00F0AEA -:101CE000A4E0010ADFE0DDD70701686F010E0701FC -:101CF0000701716F070168510701696F100E070135 -:101D00000701706F07016951B4EC9BF012000701E5 -:101D1000276F000E070107011E6F07012751000EF4 -:101D2000070107011E6501D001D002D0C0EF94F079 -:101D30001EC760F784EC0EF00701276F000E070145 -:101D40000701206F070127510701276F000E0701C8 -:101D500007011F6F070127510701276F000E0701B9 -:101D600007011D6F0701275103010301F7B301D0DC -:101D700001D006D003010301F7A501D001D018D08E -:101D80001CEC1EF00009D8B401D001D011D007011D -:101D9000276F100E07010701206F07012751070168 -:101DA00007011F6B0301F7A503D0070107011F2BD4 -:101DB00003010301F6AB01D001D025D055EC20F092 -:101DC00007010701705103010301F15D0701276F4E -:101DD00007010701715103010301F2590701286F3F -:101DE00007012851800A800F010ED8B4275DD8B0B2 -:101DF00001D001D008D00701276F100E070107019D -:101E0000206F0701275103010301F6AD01D001D076 -:101E100025D055EC20F007010701705103010301A3 -:101E2000F35D0701276F07010701715103010301EA -:101E3000F4590701286F07012851800A800F010E0D -:101E4000D8B4275DD8B001D001D008D00701276FE2 -:101E5000100E07010701206F07012751030103013D -:101E6000F5510B0AD8A401D001D02DD055EC20F0AB -:101E700007010701705103010301F35D0701276F9B -:101E800007010701715103010301F4590701286F8C -:101E900007012851800A800F010ED8B4275DD8B001 -:101EA00001D001D010D00701276F110E07010701E3 -:101EB000206F070127510701276F0C0E0301030153 -:101EC000F56F0701275103010301F551040AD8A456 -:101ED00001D001D066D1000E07010701216F000E6D -:101EE0000701226F030E07010701215D000E0701A4 -:101EF0002259D8A001D001D001D053D10701070148 -:101F00002151140DF3CF27F7100E070127270601E3 -:101F1000000E07012725E96EEA6A0601060EEA228D -:101F2000EE50ED10D8A401D001D001D03AD1030178 -:101F300003EEF8F0070107012151140DF3CF27F745 -:101F4000100E070127270601000E07012725E16E65 -:101F5000E26A0601060EE222E652EE52ED50E51864 -:101F6000EFCFE8FFD8B4E718D8A401D001D00AD148 -:101F700077ECE7F00A0E07010701B26F000E0701C8 -:101F8000B36F070107012151140D000E0701276FE0 -:101F9000060E286FF35007012727E86AF3BEE868AA -:101FA0000701282327C7B0F728C7B1F70401DE0EC1 -:101FB00007010701AE6F0401040E0701AF6F18ECB3 -:101FC0001AF0070107012151140DF3CF27F70A0E6C -:101FD000070127270601000E07012725E96EEA6A97 -:101FE0000601060EEA220401EECFD6F40401EDCF7D -:101FF000D7F4070107012151140DF3CF27F70C0E79 -:10200000070127270601000E07012725E96EEA6A66 -:102010000601060EEA22EECF28F7EECF29F7EECF23 -:102020002AF7EECF2BF7010E070128250401040142 -:10203000D06F000E070129210401D16F000E0701A6 -:102040002A210401D26F000E07012B210401D36F56 -:10205000040104EEE0F0EECF27F7EDCF28F70401FE -:102060000401DE510701272704010401DF510701A4 -:10207000282304010401D651070127270401040184 -:10208000D7510701282304010401D851070127195A -:1020900003010301F86F04010401D9510701281954 -:1020A0000301F96F0701276F120E07010701206F67 -:1020B000070127510701276F060E03010301F56F82 -:1020C00007012751140E07010701626F000E070177 -:1020D000636F070107012151020807010701606FC3 -:1020E000070107012251D8A0E82A00080701616F03 -:1020F0005AEC1BF060C7ACF761C7ADF70701276F5B -:10210000010E07010701AB6F070127510701070106 -:102110002129140D000E0701286F060E296FF350B8 -:1021200007012827E86AF3BEE8680701292328C7C2 -:10213000A9F729C7AAF707012A6F010E07010701AE -:10214000A86F07012A51070107012151140D000E44 -:1021500007012B6F060E2C6FF35007012B27E86A3F -:10216000F3BEE86807012C232BC7A6F72CC7A7F7F7 -:102170004AEC0CF0000E06010601386F000E060155 -:10218000396F0FD007010701214B222B030E0701E6 -:102190000701215D000E07012259D8A001D001D00E -:1021A000ADD6070107012051D8B401D001D010D01D -:1021B000070107011F51D8B401D002D0010E01D090 -:1021C000000E07010701716F20C770F7B4EC9BF098 -:1021D00003010301F6B901D001D088D00301030146 -:1021E000F551070AD8A401D001D04FD019EC22F044 -:1021F00003010301ED5107010701A35D0701276FEB -:1022000003010301EE5107010701A4590701286FDB -:1022100003010301EF5107010701A5590701296FC8 -:1022200003010301F05107010701A65907012A6FB5 -:1022300007012AAF01D001D001D097D30301F65195 -:10224000070B060AD8A401D001D020D0070107014E -:10225000206B0301F6A703D007010701202B1EC73F -:102260002DF729ECE3F01EC72DF729ECE3F0070169 -:102270000701206701D001D008D00701276F0E0E9B -:1022800003010301F56F070127516FD377ECE7F0E6 -:102290000701276F020E07010701716F0701275120 -:1022A0000701286F100E07010701706F0701285101 -:1022B000B4EC9BF019EC22F0740E07010701A32582 -:1022C00003010301ED6F350E07010701A42103018E -:1022D000EE6F060E07010701A5210301EF6F000E47 -:1022E00007010701A6210301F06F3FD319EC22F08B -:1022F00003010301ED5107010701A35D0701276FEA -:1023000003010301EE5107010701A4590701286FDA -:1023100003010301EF5107010701A5590701296FC7 -:1023200003010301F05107010701A65907012A6FB4 -:1023300007012AAF01D001D001D017D377ECE7F025 -:1023400043D272EC22F00009D8B401D001D02BD0D6 -:102350000701276F010E03010301F56F07012751E4 -:1023600004010401EAA501D001D00FD00701276FB5 -:10237000010E070107012F6F07012751DEC42DF75A -:10238000DFC42EF7BCEC1AF00ED00701276F010E48 -:10239000070107012F6F07012751DEC42DF7DFC4A6 -:1023A0002EF7F1EC1AF035D20701230E07010701D1 -:1023B0002D6F0701070E07012E6F8FEC95F00009B6 -:1023C000D8B401D001D0EFD79DEC1FF00009D8B4EC -:1023D00001D001D050D023C7DEF424C7DFF425C7D5 -:1023E000E0F426C7E1F40701276F020E03010301A1 -:1023F000F56F07012751040104EEE0F0EECF27F757 -:10240000EDCF28F704010401DE510701272704015D -:102410000401DF510701282304010401D6510701FB -:10242000272704010401D7510701282304010401CF -:10243000D8510701271903010301F86F04010401B2 -:10244000D951070128190301F96F0701276F000E01 -:1024500004010401ED6F07012751270E0401040157 -:10246000C86F000E0401C96F000E0401CA6F000E90 -:102470000401CB6F23D019EC22F0740E0701070181 -:10248000A32503010301ED6F350E07010701A42108 -:102490000301EE6F060E07010701A5210301EF6F8F -:1024A000000E07010701A6210301F06F0701276F46 -:1024B000000E03010301F56F07012751AAD155EC66 -:1024C00020F070C7F1F371C7F2F30401DE0E0701CB -:1024D00007014C6F0401040E07014D6F2DEC09F04C -:1024E0000701276F030E03010301F56F0701275151 -:1024F00090D10401E20E070107014E6F0401040EA2 -:1025000007014F6F0401DE0E070107014C6F040144 -:10251000040E07014D6F53EC04F00009D8A401D05C -:1025200001D03BD055EC20F003010301F15107012C -:102530000701705F03010301F25107010701715B9D -:1025400007010701705104010401C85D070107017B -:10255000715104010401C959D8B001D001D023D769 -:10256000060E04010401ED6101D001D00DD004017B -:102570000401ED2B0401D8900401C8370401C937C8 -:102580000401CA370401CB370701276F020E03018C -:102590000301F56F070127513CD10701276F020E98 -:1025A00007010701206F070127510701276F000E60 -:1025B000070107011F6F070127510701276F050E4C -:1025C00003010301F56F0701275123D10701276F8D -:1025D000020E07010701206F070127510701276F2E -:1025E000010E070107011F6F0701275112D1020ECB -:1025F00004010401ED6101D001D011D00701276F62 -:10260000120E07010701206F070127510701276FED -:10261000010E070107011F6F07012751C4D60301EF -:102620000301F6A701D001D011D00701276F140EC6 -:1026300007010701206F070127510701276F010ECE -:10264000070107011D6F0701275108D00701276FF8 -:10265000020E07010701206F07012751DAD0050E8E -:1026600004010401ED6101D001D011D00701276FF1 -:10267000100E07010701206F070127510701276F7F -:10268000010E070107011F6F070127518CD60701B3 -:10269000276F080E03010301F56F0701275107019A -:1026A000276F110E07010701206F07012751B1D0D5 -:1026B000050E04010401ED6101D001D011D0070124 -:1026C000276F110E07010701206F0701275107012E -:1026D000276F010E070107011F6F0701275163D6FE -:1026E0000701276F140E07010701206F070127510B -:1026F0000701276F010E070107011D6F0701275111 -:1027000088D00701276F140E07010701206F07010A -:1027100027510701276F010E070107011D6F0701F0 -:10272000275177D0050E04010401ED6101D001D0DD -:1027300011D00701276F100E07010701206F070155 -:1027400027510701276F010E070107011F6F0701BE -:10275000275129D60701276F140E07010701206FA3 -:10276000070127510701276F010E070107011D6FA0 -:10277000070127514ED0050E04010401ED6101D07F -:1027800001D011D00701276F110E07010701206F3B -:10279000070127510701276F010E070107011F6F6E -:1027A0000701275100D60701276F140E0701070103 -:1027B000206F070127510701276F010E070107014D -:1027C0001D6F0701275125D003010301F551000AB0 -:1027D00001E1B7D5010A01E1E7D5030A01E16FD6AE -:1027E000010A01E186D6060A01E1F0D6030A01E1F9 -:1027F000FED6010A01E133D70F0A01E159D7010AD8 -:1028000080E0030A8FE0010A01E129D7070AB3E05B -:10281000CAD5070107012051D8B401D001D09CD0FE -:10282000070107011F51D8B401D001D089D004019C -:102830000401ED2B0401D8900401C8370401C93705 -:102840000401CA370401CB3703010301E751040136 -:102850000401D45D0701276F03010301E85104015E -:102860000401D5590701286F0701296B070128BF0B -:1028700029070701295107012A6F07012751040180 -:102880000401CC5F0701285104010401CD5B07015D -:10289000295104010401CE5B07012A5104010401FE -:1028A000CF5B030103EEE7F0040114EED4F0E6522F -:1028B000EE52ED50E55C02E1EF50E75CD8B001D09C -:1028C00001D02DD003010301DF5103010301E15DBC -:1028D0000701276F03010301E05103010301E259DE -:1028E0000701286F0701296B070128BF2907070186 -:1028F000295107012A6F0701275104010401CC5F08 -:102900000701285104010401CD5B0701295104018D -:102910000401CE5B07012A5104010401CF5BE7C328 -:10292000D4F4E8C3D5F40701276F000E07010701AF -:10293000716F0701275120C770F7B4EC9BF00CD0E2 -:102940000701276F010E07010701716F070127516A -:1029500020C770F7B4EC9BF0070107011D51D8B4F4 -:1029600001D001D002D017EC0EF0070107011E2B99 -:10297000000E070107011E6501D002D098EF8EF00E -:10298000000E07010701216F000E0701226F030EE1 -:1029900007010701215D000E07012259D8A001D0CF -:1029A00001D001D0BBD0070107012151140DF3CF95 -:1029B00027F7100E070127270601000E070127251C -:1029C000E96EEA6A0601060EEA22EE50ED10D8A47E -:1029D00001D001D001D0A2D0070107012151140D6F -:1029E000F3CF27F7120E070127270601000E070174 -:1029F0002725E96EEA6A0601060EEA22EECF28F7DD -:102A0000EDCF29F755EC20F0070128510701070108 -:102A1000705D07012A6F07012951070107017159EC -:102A200007012B6FDD0E07012A5D010E2B59D8A07F -:102A300001D001D064D0140E07010701626F000EAF -:102A40000701636F07010701215102080701070110 -:102A5000606F070107012251D8A0E82A000807018A -:102A6000616F5AEC1BF060C7ACF761C7ADF70701A7 -:102A7000276F010E07010701AB6F070127510701FF -:102A800007012129140D000E0701286F060E296F7A -:102A9000F35007012827E86AF3BEE86807012923F5 -:102AA00028C7A9F729C7AAF707012A6F010E07014E -:102AB0000701A86F07012A51070107012151140DD1 -:102AC000000E07012B6F060E2C6FF35007012B270A -:102AD000E86AF3BEE86807012C232BC7A6F72CC7CA -:102AE000A7F74AEC0CF0000E06010601386F000E45 -:102AF0000601396F070107012107D8A02207070146 -:102B00000701214B222B030E07010701215D000E57 -:102B100007012259D8A001D001D045D712008FEF6C -:102B20009BF00701486F000E2C6E0701485107010A -:102B3000486F000E2D6E070148510601480E07012F -:102B400007014C6F0601060E07014D6F2DEC09F0D1 -:102B50002C2A19EC22F0A3C7F7F4A4C7F8F4A5C7F0 -:102B6000F9F4A6C7FAF40701486F020E0601060140 -:102B7000E56F07014851B1EF9BF00001B70E070167 -:102B800007014E6F0001000E07014F6F0601480E4E -:102B9000070107014C6F0601060E07014D6F53EC4C -:102BA00004F00009D8A401D001D046D019EC22F0DD -:102BB00004010401F75107010701A35D0701486FF4 -:102BC00004010401F85107010701A4590701496FE5 -:102BD00004010401F95107010701A55907014A6FD2 -:102BE00004010401FA5107010701A65907014B6FBF -:102BF000F30E485D9E0E4959000E4A59000E07011A -:102C00004B59D8A001D001D015D00701486F010E53 -:102C100006010601E56F07014851020E2C6401D040 -:102C200001D008D00701486F060E06010601E56FC6 -:102C300007014851B1EF9BF048C6B3F049C6B4F064 -:102C40004AC6B5F04BC6B6F00701486F030E060141 -:102C50000601E56F07014851350E07010701506F66 -:102C6000000E0701516F0001B30E070107014E6FFF -:102C70000001000E07014F6F000E070107014C6FA6 -:102C8000000E07014D6F9EECE1F006010601E26FB8 -:102C900006010601E229D8A401D001D002D0B1EF8B -:102CA0009BF00701486F040E06010601E56F07015E -:102CB0004851E2C64CF750EC1AF007014D514C1147 -:102CC000D8A401D001D002D0B1EF9BF000010001E7 -:102CD000F14BF22BF2C053F763EC1FF0F1C053F746 -:102CE00063EC1FF00701486F010E07010701536FE6 -:102CF0000701485163EC1FF00701486F000E070100 -:102D00000701536F0701485163EC1FF00701486F3B -:102D1000000E07010701536F0701485163EC1FF0D4 -:102D20000701486F010E07010701536F0701485162 -:102D300063EC1FF00701486F000E07010701536F96 -:102D40000701485163EC1FF00701486F000E0701AF -:102D50000701536F0701485163EC1FF00701486FEB -:102D6000000E07010701536F0701485163EC1FF084 -:102D70000701486F000E07010701536F0701485113 -:102D800063EC1FF00701486F000E07010701536F46 -:102D90000701485163EC1FF00701486F000E07015F -:102DA0000701536F0701485163EC1FF00401040150 -:102DB000F051EF11D8B401D001D007D0EFC44CF7D7 -:102DC000F0C44DF799EC08F006D0F1C44CF7F2C40A -:102DD0004DF7D3EC06F00701486F000E070107011D -:102DE000536F0701485163EC1FF033C053F763EC96 -:102DF0001FF00701486F000E07010701536F07011D -:102E0000485163EC1FF00701486F010E07010701ED -:102E1000536F0701485163EC1FF0BCEC09F019EC4B -:102E200022F0A3C7F7F4A4C7F8F4A5C7F9F4A6C71E -:102E3000FAF40701486F050E06010601E56F070168 -:102E40004851B1EF9BF0E2C64CF7F2EC1BF00701E2 -:102E50004D514C11D8A401D001D039D019EC22F039 -:102E600004010401F75107010701A35D0701486F41 -:102E700004010401F85107010701A4590701496F32 -:102E800004010401F95107010701A55907014A6F1F -:102E900004010401FA5107010701A65907014B6F0C -:102EA000F30E485D9E0E4959000E4A59000E070167 -:102EB0004B59D8A001D001D0BDD60701486F060EEE -:102EC00006010601E56F07014851B1EF9BF00701CC -:102ED0003D0E070107014D6F0701070E07014E6FF9 -:102EE00086EC1EF007013C0E070107014D6F07013C -:102EF000070E07014E6F86EC1EF000010001F25133 -:102F0000070107013D1906E100010001F151070128 -:102F100007013C19D8B401D001D004D051EC21F004 -:102F2000B1EF9BF007013F0E070107014D6F07014D -:102F3000070E07014E6F86EC1EF007013E0E0701DB -:102F400007014D6F0701070E07014E6F86EC1EF05B -:102F50000701410E070107014D6F0701070E070129 -:102F60004E6F86EC1EF00701400E070107014D6F02 -:102F70000701070E07014E6F86EC1EF00701430E96 -:102F8000070107014D6F0701070E07014E6F86EC21 -:102F90001EF00701420E070107014D6F0701070EE2 -:102FA00007014E6F86EC1EF00701450E0701070171 -:102FB0004D6F0701070E07014E6F86EC1EF00701EB -:102FC000440E070107014D6F0701070E07014E6F01 -:102FD00086EC1EF00701470E070107014D6F070140 -:102FE000070E07014E6F86EC1EF00701460E070123 -:102FF00007014D6F0701070E07014E6F86EC1EF0AB -:103000002ED02EEC18F00701310E070107014D6F8D -:103010000701070E07014E6F86EC1EF00701300E08 -:10302000070107014D6F0701070E07014E6F86EC80 -:103030001EF00701310E070107014D6F0701070E52 -:1030400007014E6F86EC1EF00701300E07010701E5 -:103050004D6F0701070E07014E6F86EC1EF007014A -:1030600007014007D8A0410707014029D8B44129EA -:10307000D8A401D001D0C5D7D0D02EEC18F00701CC -:10308000330E070107014D6F0701070E07014E6F51 -:1030900086EC1EF00701320E070107014D6F070194 -:1030A000070E07014E6F86EC1EF00701350E070173 -:1030B00007014D6F0701070E07014E6F86EC1EF0EA -:1030C0000701340E070107014D6F0701070E0701C5 -:1030D0004E6F86EC1EF00701390E070107014D6F98 -:1030E0000701070E07014E6F86EC1EF00701380E30 -:1030F000070107014D6F0701070E07014E6F86ECB0 -:103100001EF00701370E070107014D6F0701070E7B -:1031100007014E6F86EC1EF00701360E070107010E -:103120004D6F0701070E07014E6F86EC1EF0070179 -:103130003B0E070107014D6F0701070E07014E6F98 -:1031400086EC1EF007013A0E070107014D6F0701DB -:10315000070E07014E6F86EC1EF0070107013205CE -:103160003311D8A401D001D03FD0070107013405A5 -:103170003511D8A401D001D037D0070107013A5149 -:10318000040A3B11D8A401D001D02ED0378200010F -:10319000B30E070107014D6F0001000E07014E6FCE -:1031A00086EC1EF00001B40E070107014D6F00010F -:1031B000000E07014E6F86EC1EF00001B50E0701F0 -:1031C00007014D6F0001000E07014E6F86EC1EF0E7 -:1031D0000001B60E070107014D6F0001000E070147 -:1031E0004E6F86EC1EF0E2D10BD007012F0E0701C7 -:1031F00007014D6F0701070E07014E6F86EC1EF0A9 -:10320000070107013A07D8A03B0707013A29D8B4BC -:103210003B29D8A401D001D0E8D707010701420714 -:10322000D8A0430707014229D8B44329D8A401D024 -:1032300001D023D7D0D02EEC18F00701330E0701B0 -:1032400007014D6F0701070E07014E6F86EC1EF058 -:103250000701320E070107014D6F0701070E070135 -:103260004E6F86EC1EF00701350E070107014D6F0A -:103270000701070E07014E6F86EC1EF00701340EA2 -:10328000070107014D6F0701070E07014E6F86EC1E -:103290001EF00701390E070107014D6F0701070EE8 -:1032A00007014E6F86EC1EF00701380E070107017B -:1032B0004D6F0701070E07014E6F86EC1EF00701E8 -:1032C000370E070107014D6F0701070E07014E6F0B -:1032D00086EC1EF00701360E070107014D6F07014E -:1032E000070E07014E6F86EC1EF007013B0E07012B -:1032F00007014D6F0701070E07014E6F86EC1EF0A8 -:1033000007013A0E070107014D6F0701070E07017C -:103310004E6F86EC1EF00701070132053311D8A469 -:1033200001D001D03FD00701070134053511D8A4E1 -:1033300001D001D037D0070107013A51040A3B11EF -:10334000D8A401D001D02ED037820001B30E0701DE -:1033500007014D6F0001000E07014E6F86EC1EF055 -:103360000001B40E070107014D6F0001000E0701B7 -:103370004E6F86EC1EF00001B50E070107014D6F80 -:103380000001000E07014E6F86EC1EF00001B60E24 -:10339000070107014D6F0001000E07014E6F86EC1B -:1033A0001EF004D10BD007012F0E070107014D6F4E -:1033B0000701070E07014E6F86EC1EF0070107019B -:1033C0003A07D8A03B0707013A29D8B43B29D8A42B -:1033D00001D001D0E8D7070107014407D8A045076D -:1033E00007014429D8B44529D8A401D001D023D756 -:1033F000D0D02EEC18F00701330E070107014D6FF6 -:103400000701070E07014E6F86EC1EF00701320E12 -:10341000070107014D6F0701070E07014E6F86EC8C -:103420001EF00701350E070107014D6F0701070E5A -:1034300007014E6F86EC1EF00701340E07010701ED -:103440004D6F0701070E07014E6F86EC1EF0070156 -:10345000390E070107014D6F0701070E07014E6F77 -:1034600086EC1EF00701380E070107014D6F0701BA -:10347000070E07014E6F86EC1EF00701370E07019D -:1034800007014D6F0701070E07014E6F86EC1EF016 -:103490000701360E070107014D6F0701070E0701EF -:1034A0004E6F86EC1EF007013B0E070107014D6FC2 -:1034B0000701070E07014E6F86EC1EF007013A0E5A -:1034C000070107014D6F0701070E07014E6F86ECDC -:1034D0001EF00701070132053311D8A401D001D035 -:1034E0003FD00701070134053511D8A401D001D020 -:1034F00037D0070107013A51040A3B11D8A401D083 -:1035000001D02ED037820001B30E070107014D6FA5 -:103510000001000E07014E6F86EC1EF00001B40E94 -:10352000070107014D6F0001000E07014E6F86EC89 -:103530001EF00001B50E070107014D6F0001000EDE -:1035400007014E6F86EC1EF00001B60E0701070161 -:103550004D6F0001000E07014E6F86EC1EF026D065 -:103560000BD007012F0E070107014D6F0701070E52 -:1035700007014E6F86EC1EF0070107013A07D8A03D -:103580003B0707013A29D8B43B29D8A401D001D080 -:10359000E8D7070107014607D8A0470707014629D2 -:1035A000D8B44729D8A401D001D023D751EC21F0B9 -:1035B000E2C64CF787EC1AF006010601E269070142 -:1035C000486F070E06010601E56F0701485137B243 -:1035D00001D001D00DD0000E00010001B36F000E2C -:1035E0000001B46F000E0001B56F000E0001B66F50 -:1035F0002DC7E9FF2EC7EAFF0001B3C0EEFF0001AF -:10360000B4C0EEFF0001B5C0EEFF0001B6C0EEFF92 -:10361000010EA9D0010E2D6401D001D010D02DC70C -:10362000E9FF2EC7EAFF000EEE6E000EEE6E000EF2 -:10363000EE6E000EED6EED52ED52010E94D02D2A7D -:1036400006014F514C114D114E11D8B401D002D08A -:103650001AEF96F0060106014C5106010601481BBF -:10366000060106014D5106010601491B060106012E -:103670004E51060106014A1B060106014F51060183 -:1036800006014B1B060106014851060106014C1BB1 -:10369000060106014951060106014D1B06010601FE -:1036A0004A51060106014E1B060106014B51060157 -:1036B00006014F1B060106014C5106010601481B7D -:1036C000060106014D5106010601491B06010601CE -:1036D0004E51060106014A1B060106014F51060123 -:1036E00006014B1B0701486F000E2C6E0701485165 -:1036F00006010601E229D8B401D001D007D0E2C604 -:103700004CF787EC1AF006010601E2690701486FE1 -:10371000010E06010601E56F0701485122D006019E -:103720000601E551000A02E191EF95F0010A02E17C -:103730009DEF95F0030A02E1BDEF95F0010A02E169 -:103740002CEF96F0070A02E159EF96F0010A02E128 -:1037500023EF97F0030A01E15DD7010A01E137D7B2 -:1037600000D0000E00D0120077ECE7F0070107014F -:1037700070A101D001D005D00301F787070107012F -:1037800070910301F69B0301F69D0301F69F03016F -:10379000F7930301F7950301F79100D01CEC1EF09D -:1037A0000009D8B401D001D0F9D707010701705141 -:1037B000060BD8B401D001D008D0000E07010701D4 -:1037C000766F000E0701776FD2D2040104EED4F0B9 -:1037D000030113EEE5F0E652EE52ED50E518EFCF9F -:1037E000E8FFD8B4E718D8A401D001D019D0000E52 -:1037F00007010701766F000E0701776F03010301D0 -:10380000F7A701D001D00BD004010401DB51DA117C -:10381000D8B401D001D003D0070107017081A7D22D -:10382000030103EEE5F0040114EED4F0E652EE528B -:10383000ED50E55C02E1EF50E75CD8B001D001D07B -:10384000F7D004010401D45103010301E55D070130 -:103850000701766F04010401D55103010301E65904 -:103860000701776FDAC474F7DBC475F7030103EE61 -:10387000E7F0040114EED4F0E652EE52ED50E55CB0 -:1038800002E1EF50E75CD8A001D001D01CD00401C8 -:1038900004EED4F0EECF9CF7EDCF9DF703010301CA -:1038A000E75107019C5F03010301E85107019D5B9C -:1038B00007019C5107010701745F07019D51070132 -:1038C0000701755B38D0030103EEE7F0EECF9CF7FC -:1038D000EDCF9DF704010401D45107019C5F040161 -:1038E0000401D55107019D5B030103EEE1F0EECF2A -:1038F0009EF7EDCF9FF703010301DF5107019E5FA4 -:1039000003010301E05107019F5B07019C5107017F -:103910009E5D0701A06F07019D5107019F59070197 -:10392000A16F0701A05107010701745F0701A151B1 -:1039300007010701755B07010701765107010701C0 -:10394000745D070107017751070107017559D8B068 -:1039500001D001D004D074C776F775C777F7070197 -:103960000701765104010401EB5D0701070177515E -:1039700004010401EC59D8B001D001D006D0EBC449 -:1039800076F7ECC477F70301F78503010301F7A786 -:1039900001D001D025D007010701755107010701AA -:1039A000771906E10701070174510701070176192C -:1039B000D8B401D001D014D0040104EEEBF007011B -:1039C000EE5207017751ED18070176C7E8FFD8B42A -:1039D000EF18D8B401D001D003D0070107017081DE -:1039E00076C7ACF777C7ADF7FAC3ABF7D4C4A9F77E -:1039F000D5C4AAF707019C6F000E07010701A86F45 -:103A000007019C51050E07010701A66F0B0E070168 -:103A1000A76F4AEC0CF0070107017651040104017D -:103A2000D42707010701775104010401D5239FD151 -:103A300004010401D45103010301E15D0701070101 -:103A4000866F04010401D55103010301E259070106 -:103A5000876F070107EE86F0EECF9CF7EDCF9DF75D -:103A600003010301E55107019C2703010301E6510E -:103A700007019D2303010301DF5107019C5D07013D -:103A80000701766F03010301E05107019D5907010A -:103A9000776FDAC474F7DBC475F7030103EEE7F060 -:103AA000040114EED4F0E652EE52ED50E55C02E172 -:103AB000EF50E75CD8A001D001D01CD0040104EE87 -:103AC000D4F0EECF9CF7EDCF9DF703010301E75152 -:103AD00007019C5F03010301E85107019D5B07019A -:103AE0009C5107010701745F07019D510701070100 -:103AF000755B38D0030103EEE7F0EECF9CF7EDCF16 -:103B00009DF704010401D45107019C5F04010401E5 -:103B1000D55107019D5B030103EEE1F0EECF9EF767 -:103B2000EDCF9FF703010301DF5107019E5F030102 -:103B30000301E05107019F5B07019C5107019E5D56 -:103B40000701A06F07019D5107019F590701A16F50 -:103B50000701A05107010701745F0701A151070187 -:103B60000701755B07010701765107010701745DC5 -:103B7000070107017751070107017559D8B001D036 -:103B800001D004D074C776F775C777F7070107012E -:103B9000765104010401EB5D07010701775104012F -:103BA0000401EC59D8B001D001D006D0EBC476F7AF -:103BB000ECC477F70301F78503010301F7A701D0F0 -:103BC00001D025D0070107017551070107017719B9 -:103BD00006E1070107017451070107017619D8B4FE -:103BE00001D001D014D0040104EEEBF00701EE5235 -:103BF00007017751ED18070176C7E8FFD8B4EF1831 -:103C0000D8B401D001D003D00701070170810701AA -:103C10000701865107010701765D070107018751FA -:103C2000070107017759D8B001D001D004D076C779 -:103C300086F777C787F786C7ACF787C7ADF7FAC3AC -:103C4000ABF7D4C4A9F7D5C4AAF707019C6F000E3F -:103C500007010701A86F07019C51050E0701070125 -:103C6000A66F0B0E0701A76F4AEC0CF007010701C6 -:103C7000865107010701765D07010701866F07017D -:103C8000070187510701070177590701876F07016E -:103C9000070187518611D8B401D001D030D086C732 -:103CA000ACF787C7ADF7FAC3ABF7DFC3A9F7E0C33B -:103CB000AAF707019C6F000E07010701A86F070113 -:103CC0009C51030103EEE1F0EECF9DF7EDCF9EF79F -:103CD00004010401D45107019D5F04010401D55181 -:103CE00007019E5B050E07019D2507010701A66FD1 -:103CF0000B0E07019E210701A76F4AEC0CF007018C -:103D00000701765104010401D42707010701775107 -:103D100004010401D523030103EEE1F0040114EED4 -:103D2000D4F0E652EE52ED50E55C02E1EF50E75C74 -:103D3000D8A001D001D01BD0030103EEE1F0EECFFB -:103D40009CF7EDCF9DF703010301DF5107019C5F55 -:103D500003010301E05107019D5B07019C51040130 -:103D60000401D45F07019D5104010401D55B0701E3 -:103D7000070177517611D8A401D001D008D00701EE -:103D800007017051030BD8B401D001D04CD007010A -:103D9000070177517611D8B401D001D003D00701C3 -:103DA000070170870701070171A101D001D015D06B -:103DB00007019C6F000E04010401ED6F07019C5187 -:103DC000F20E04010401C86F9E0E0401C96F000EBB -:103DD0000401CA6F000E0401CB6F19EC22F004013C -:103DE0000401C85107010701A32503010301ED6F79 -:103DF00004010401C95107010701A4210301EE6F69 -:103E000004010401CA5107010701A5210301EF6F55 -:103E100004010401CB5107010701A6210301F06F42 -:103E20000301F68973D00701070171A301D001D006 -:103E30002AD0010E07019C6F03010301F651070B05 -:103E400007019D6F07019C5107019D270301030195 -:103E5000F65107019D19F80B07019D190301030194 -:103E6000F66F04010401CC07000E0401CD5B0401D0 -:103E7000CE5B0401CF5B010E07010701766F000ED8 -:103E80000701776F43D003010301F6A901D001D0E8 -:103E90003DD00701070171B101D001D014D0040158 -:103EA0000401ED51D8B401D001D00DD004010401BA -:103EB000ED070401D8900401CB330401CA33040197 -:103EC000C9330401C83319EC22F004010401C851BC -:103ED00007010701A32503010301ED6F040104019C -:103EE000C95107010701A4210301EE6F0401040178 -:103EF000CA5107010701A5210301EF6F0401040165 -:103F0000CB5107010701A6210301F06FD8C488F740 -:103F1000D9C489F7D6C48AF7D7C48BF7CCC48CF739 -:103F2000CDC48DF7CEC48EF7CFC48FF7D0C490F731 -:103F3000D1C491F7D2C492F7D3C493F73F0E0701CF -:103F40009517070194910701949307019495070130 -:103F500094970B000E0070C795F7000E070107013C -:103F60009A6F000E07019B6F07010701765104014C -:103F70000401CC2707010701775104010401CD2377 -:103F8000000E04010401CE23000E04010401CF231E -:103F90000701070170A301D001D033D00701070149 -:103FA00070B901D001D00DD0000E07010701906F4C -:103FB000000E0701916F000E0701926F000E0701BE -:103FC000936F04010401EAA301D001D00BD00701D3 -:103FD00007018C07000E07018D5B07018E5B07014F -:103FE0008F5B0FD0010E04010401CC27000E0401E9 -:103FF000CD23000E0401CE23000E0401CF230401C3 -:10400000EA830701070170A101D001D020D004018B -:104010000401EAA101D001D00BD0070107018C07F0 -:10402000000E07018D5B07018E5B07018F5B0FD0D0 -:10403000010E04010401CC27000E0401CD23000E63 -:104040000401CE23000E0401CF230401EA81030101 -:1040500003EEEBF0030113EEE9F0E652EE52ED5001 -:10406000E55C02E1EF50E75CD8A001D001D030D090 -:10407000030103EEE9F0EECF9CF7EDCF9DF70301CE -:104080000301EB5107019C5F03010301EC510701A0 -:104090009D5B030103EEE3F0EECF9EF7EDCF9FF7BC -:1040A00003010301E15107019E5F03010301E25196 -:1040B00007019F5B07019C5107019E5D07010701F6 -:1040C000966F07019D5107019F590701976F1CD0FB -:1040D000030103EEEBF0EECF9CF7EDCF9DF703016C -:1040E0000301E95107019C5F03010301EA51070144 -:1040F0009D5BFF0E07019C2507010701966FFF0ED0 -:1041000007019D210701976FD3EC0BF0C00E07014B -:104110000701A22507010701726FFF0E07010701C2 -:10412000A3210701736F0701070173AF01D001D00D -:1041300007D0000E07010701726F000E0701736FB1 -:1041400007010701965107010701725D0701070189 -:104150009751070107017359D8B001D001D004D09D -:1041600072C796F773C797F70701880E0701070113 -:10417000A26F0701070E0701A36F40ECD6F0140EE3 -:10418000070107017627000E0701772307019451E5 -:104190000F0B50090701946F0701070170A301D0AD -:1041A00001D038D0040E070107017627000E070161 -:1041B000772307019C6F020E07010701786F070143 -:1041C0009C5107019C6F040E07010701796F0701DD -:1041D0009C51020E070107017A6F140E07017B6FD5 -:1041E000010E07019C6F0701070194390F0B0701AE -:1041F0009D6F07019C5107019D2707019D3B07010A -:104200000701945107019D190F0B07019D19070123 -:104210000701946F3CC67CF73DC67DF73EC67EF72E -:104220003FC67FF7DEC480F7DFC481F7E0C482F7C2 -:10423000E1C483F707019C6F000E07010701846F3B -:1042400007019C5107019C6F060E07010701856F4E -:1042500007019C5176C786F777C787F786C7BEF7F1 -:1042600087C7BFF7B8EC21F0BEC786F7BFC787F78F -:104270000C0E07010701BE6F000E0701BF6F07019B -:104280007C0E07010701BC6F0701070E0701BD6F18 -:1042900038EC06F007010701BC1D07010701986F04 -:1042A00007010701BD1D0701996FDD0E0701070119 -:1042B000AE6F0A0E0701AF6F86EC22F076C7A5F746 -:1042C00077C7A6F707019C6F060E07010701A46FC9 -:1042D00007019C510401DE0E07010701A26F0401D2 -:1042E000040E0701A36F4BEC00F0140E0701070149 -:1042F000C46F000E0701C56F0701880E0701070193 -:10430000C26F0701070E0701C36FB8EC1FF007016A -:10431000070170A301D001D012D0040E07010701DC -:10432000C46F000E0701C56F0701780E0701070172 -:10433000C26F0701070E0701C36FB8EC1FF0F10E43 -:1043400007010701AE6F0A0E0701AF6F90EC22F074 -:1043500076C7A2F777C7A3F7D3ECE0F0A2C772F74E -:10436000A3C773F7010E07010701AE6F0B0E07011C -:10437000AF6F86EC22F0020E07010701C46F000E3A -:104380000701C56F0701720E07010701C26F070120 -:10439000070E0701C36FB8EC1FF080EC1FF012008E -:1043A00001019F0E07010701606F0101010E070166 -:1043B000616F52C7E9FF53C7EAFF0701EECF66F707 -:1043C0000701EECF67F70701EECF68F70701EECFE1 -:1043D00069F754C7E9FF55C7EAFF0701EECF7AF73F -:1043E0000701EECF7BF70701EECF7CF70701EECF99 -:1043F0007DF756C7E9FF57C7EAFF0701EECF72F70F -:104400000701EECF73F70701EECF74F70701EECF88 -:1044100075F758C7E9FF59C7EAFF0701EECF76F7EE -:104420000701EECF77F70701EECF78F70701EECF60 -:1044300079F75AC7E9FF5BC7EAFF0701EECF62F7DA -:104440000701EECF63F70701EECF64F70701EECF68 -:1044500065F79F0E0701866F010E876F0701070141 -:1044600051510701871905E1070107015051070163 -:104470008619D8A401D001D078D00701866F000E2C -:10448000070107015F6F070186510F0E0701070142 -:104490005F6501D001D001D067D0030E070107018D -:1044A0005025E96E000E070107015121EA6EEF5019 -:1044B000070107015E6F50C7E9FF51C7EAFF030E0E -:1044C000070107015025E16E000E07010701512188 -:1044D000E26EEFCFE7FF50C7E9FF51C7EAFF0701E0 -:1044E0005EC7EFFF010E070107015025E96E000EC0 -:1044F000070107015121EA6EEF50070107015E6FC6 -:10450000020E070107015025E96E000E07010701A1 -:104510005121EA6E010E070107015025E16E000EE0 -:10452000070107015121E26EEFCFE7FF020E0701FD -:1045300007015025E96E000E070107015121EA6EBF -:1045400007015EC7EFFF040E070107015027000EA9 -:1045500007015123070107015F2B0F0E0701070118 -:104560005F6501D001D099D7AFD00701866F000EEB -:10457000070107015F6F070186510F0E0701070151 -:104580005F6501D001D001D09FD050C7E9FF51C76E -:10459000EAFF070107015F51040DF3CF86F7030E11 -:1045A00007018627070186510701070160250701DA -:1045B000876FE86A070186BFE86807010701612184 -:1045C0000701886F87C7E1FF88C7E2FFEFCFE7FFEA -:1045D00007010701504B512B50C7E9FF51C7EAFFB4 -:1045E000070107015F51040DF3CF86F7020E0701A3 -:1045F0008627070186510701070160250701876F9C -:10460000E86A070186BFE868070107016121070121 -:10461000886F87C7E1FF88C7E2FFEFCFE7FF070199 -:104620000701504B512B50C7E9FF51C7EAFF070163 -:1046300007015F51040DF3CF86F7010E07018627AE -:10464000070186510701070160250701876FE86AA6 -:10465000070186BFE8680701070161210701886F2C -:1046600087C7E1FF88C7E2FFEFCFE7FF0701070138 -:10467000504B512B50C7E9FF51C7EAFF0701070113 -:104680005F51040DF3500701070160250701866F94 -:10469000E86AF3BEE8680701070161210701876F37 -:1046A00086C7E1FF87C7E2FFEFCFE7FF07010701FA -:1046B000504B512B070107015F2B0F0E070107011C -:1046C0005F6501D001D061D70701866F0D0E07012C -:1046D00007015E6F070186510701866F080E07010B -:1046E00007015D6F070186510701866F020E070102 -:1046F00007015C6F070186510701866F000E0701F5 -:1047000007015F6F070186514F0E070107015F65C3 -:1047100001D001D001D0D5D3140E070107015F618C -:1047200001D001D074D007017AC786F707017BC793 -:1047300087F707017CC788F707017DC789F707015D -:10474000861F871F881F891F0701070176510701F0 -:10475000861507018A6F0701070177510701871541 -:1047600007018B6F070107017851070188150701C1 -:104770008C6F0701070179510701891507018D6FBA -:10478000070107017251070107017A1507018E6FB2 -:10479000070107017351070107017B1507018F6F9F -:1047A000070107017451070107017C150701906F8C -:1047B000070107017551070107017D150701916F79 -:1047C00007018A5107018E11070107016A6F07016E -:1047D0008B5107018F1107016B6F07018C51070186 -:1047E000901107016C6F07018D51070191110701AD -:1047F0006D6F990E070107016E6F790E07016F6FDC -:10480000820E0701706F5A0E0701716F50D1130E9F -:10481000070107015F6501D001D052D0280E0701C2 -:1048200007015F6101D001D04BD007010701725130 -:10483000070107017A190701866F07010701735104 -:10484000070107017B190701876F070107017451F1 -:10485000070107017C190701886F070107017551DE -:10486000070107017D190701896F070107017651CB -:1048700007018619070107016A6F070107017751D0 -:104880000701871907016B6F0701070178510701BD -:10489000881907016C6F0701070179510701891910 -:1048A00007016D6FA10E070107016E6FEB0E070187 -:1048B0006F6FD90E0701706F6E0E0701716FF7D021 -:1048C000270E070107015F6501D001D0A6D03C0E7D -:1048D000070107015F6101D001D09FD007010701E7 -:1048E00076510701070172150701866F070107015D -:1048F00077510701070173150701876F070107014A -:1049000078510701070174150701886F0701070136 -:1049100079510701070175150701896F0701070123 -:104920007651070107017A1507018A6F0701070110 -:104930007751070107017B1507018B6F07010701FD -:104940007851070107017C1507018C6F07010701EA -:104950007951070107017D1507018D6F07010701D7 -:104960007251070107017A1507018E6F07010701D0 -:104970007351070107017B1507018F6F07010701BD -:104980007451070107017C150701906F07010701AA -:104990007551070107017D150701916F07018A51C4 -:1049A00007018E110701926F07018B5107018F11CB -:1049B0000701936F07018C51070190110701946F54 -:1049C00007018D51070191110701956F070186516C -:1049D00007019211070107016A6F0701875107015B -:1049E000931107016B6F07018851070194110701AB -:1049F0006C6F070189510701951107016D6FDC0E7E -:104A0000070107016E6FBC0E07016F6F1B0E0701D8 -:104A1000706F8F0E0701716F4AD007010701725145 -:104A2000070107017A190701866F07010701735112 -:104A3000070107017B190701876F070107017451FF -:104A4000070107017C190701886F070107017551EC -:104A5000070107017D190701896F070107017651D9 -:104A600007018619070107016A6F070107017751DE -:104A70000701871907016B6F0701070178510701CB -:104A8000881907016C6F070107017951070189191E -:104A900007016D6FD60E070107016E6FC10E07018A -:104AA0006F6F620E0701706FCA0E0701716F0F0EF4 -:104AB000070107015F6501D001D01DD10701070182 -:104AC0005E51040DF3500701070160250701866F51 -:104AD000E86AF3BEE8680701070161210701876FF3 -:104AE00086C7E9FF87C7EAFF0701EECF7EF7070118 -:104AF000EECF7FF70701EECF80F70701EECF81F70A -:104B0000070107015D51040DF350070107016025FE -:104B10000701866FE86AF3BEE868070107016121B3 -:104B20000701876F86C7E9FF87C7EAFF0701EECF56 -:104B300082F70701EECF83F70701EECF84F7070175 -:104B4000EECF85F7070107018251070107017E1BA0 -:104B5000070107018351070107017F1B07010701B7 -:104B6000845107010701801B0701070185510701D7 -:104B70000701811B070107015C51040DF350070178 -:104B8000070160250701866FE86AF3BEE868070140 -:104B9000070161210701876F86C7E9FF87C7EAFF21 -:104BA0000701EECF82F70701EECF83F70701EECFC3 -:104BB00084F70701EECF85F707010701825107014E -:104BC00007017E1B070107018351070107017F1BB6 -:104BD00007010701845107010701801B0701070135 -:104BE000855107010701811B070107015F510F0B69 -:104BF000040DF3500701070160250701866FE86A7D -:104C0000F3BEE8680701070161210701876F86C7C6 -:104C1000E9FF87C7EAFF0701EECF82F70701EECF72 -:104C200083F70701EECF84F70701EECF85F7070181 -:104C300007018251070107017E1B0701070183510C -:104C4000070107017F1B07010701845107010701C5 -:104C5000801B07010701855107010701811B07011F -:104C6000866F010E070107019D6F070186517EC700 -:104C700099F77FC79AF780C79BF781C79CF7FDEC30 -:104C800015F0070107015F510F0B040DF3500701E9 -:104C9000070160250701876FE86AF3BEE86807012E -:104CA000070161210701886F87C7E9FF88C7EAFF0D -:104CB000070199C7EEFF07019AC7EEFF07019BC7DF -:104CC000EEFF07019CC7EDFFED52ED520701070112 -:104CD0005E2B070107015D2B070107015C2B0F0EFF -:104CE000070107015E170F0E070107015D170F0E81 -:104CF000070107015C17070107015F510F0B040D46 -:104D0000F3500701070160250701866FE86AF3BECB -:104D1000E8680701070161210701876F86C7E9FF7E -:104D200087C7EAFFEECF88F7EECF89F7EECF8AF795 -:104D3000EECF8BF707018C6F050E070107019D6F02 -:104D400007018C5166C799F767C79AF768C79BF741 -:104D500069C79CF7FDEC15F00701885107010701B1 -:104D6000992507018D6F07018951070107019A21D4 -:104D700007018E6F07018A51070107019B21070177 -:104D80008F6F07018B51070107019C210701906F6D -:104D9000070107016A5107018D250701916F07017E -:104DA00007016B5107018E210701926F070107016F -:104DB0006C5107018F210701936F070107016D51A6 -:104DC000070190210701946F070107016251070154 -:104DD00091250701956F0701070163510701922192 -:104DE0000701966F0701070164510701932107012D -:104DF000976F070107016551070194210701986F1B -:104E0000070107016E5107019525070107017E6F14 -:104E1000070107016F510701962107017F6F070105 -:104E200007017051070197210701806F07010701F2 -:104E30007151070198210701816F76C762F777C723 -:104E400063F778C764F779C765F772C776F773C7F2 -:104E500077F774C778F775C779F70701866F1E0E65 -:104E6000070107019D6F070186517AC799F77BC734 -:104E70009AF77CC79BF77DC79CF7FDEC15F099C7A7 -:104E800072F79AC773F79BC774F79CC775F766C725 -:104E90007AF767C77BF768C77CF769C77DF77EC776 -:104EA00066F77FC767F780C768F781C769F70701AB -:104EB00007015F2B4F0E070107015F6501D001D08D -:104EC0002BD452C7E9FF53C7EAFF07010701665118 -:104ED000EE2607016751EE2207016851EE22070115 -:104EE0006951ED22ED52ED5254C7E9FF55C7EAFF73 -:104EF000070107017A51EE2607017B51EE220701D7 -:104F00007C51EE2207017D51ED22ED52ED5256C744 -:104F1000E9FF57C7EAFF070107017251EE260701B3 -:104F20007351EE2207017451EE2207017551ED22F3 -:104F3000ED52ED5258C7E9FF59C7EAFF07010701D3 -:104F40007651EE2607017751EE2207017851EE22C5 -:104F500007017951ED22ED52ED525AC7E9FF5BC7C7 -:104F6000EAFF070107016251EE2607016351EE22B5 -:104F700007016451EE2207016551ED22ED52ED5219 -:104F8000120007011E6F000E070107011D6F0701C8 -:104F90001E51000E070107011D6501D001D001D08F -:104FA00082D34CD376D3430E07010701506F000E16 -:104FB0000701516F000E070107014E6F000E070138 -:104FC0004F6F440E070107014C6F000E07014D6F34 -:104FD0009EECE1F005010501C86F05010501C82936 -:104FE000D8A401D001D001D054D307011E6F020E06 -:104FF00005010501C96F07011E513C0E05010501A0 -:10500000CF6F000E0501D06F000E0501D16F000EAD -:105010000501D26F07011E6F000E05010501EB6F40 -:1050200007011E510501CA910501CA951AEC21F02C -:105030000009D8A401D001D001D02BD3C8C54CF7AA -:1050400050EC1AF02C0E070107014C5D010E070110 -:105050004D59D8B001D001D001D01BD30501CA7978 -:105060000A0E070107015A6F000E07015B6FFF0E62 -:1050700007010701586F000E0701596F050105016F -:10508000C8510E0D0101590EF32407010701566F97 -:105090000701576B0101010E0701572308EC1FF0B0 -:1050A00007011E6F000E07010701236F07011E5144 -:1050B00007011F6F010E07010701226F07011F5132 -:1050C00029ECB8F019EC22F0A3C7CBF5A4C7CCF5B6 -:1050D000A5C7CDF5A6C7CEF507011E6F030E0501C6 -:1050E0000501C96F07011E51D4D2C8C54CF7F2ECB7 -:1050F0001BF0FA0E070107014C5D000E07014D5928 -:10510000D8B001D001D038D019EC22F0050105014A -:10511000CB5107010701A35D07011E6F05010501C2 -:10512000CC5107010701A45907011F6F05010501B3 -:10513000CD5107010701A5590701206F05010501A0 -:10514000CE5107010701A6590701216FE40E1E5D2C -:105150003D0E1F59010E2059000E07012159D8A0FC -:1051600001D001D01FD707011E6F020E05010501F6 -:10517000C96F07011E518DD20501CA8754ECABF0EF -:10518000020AD8B401D001D001D083D207011E6F2A -:10519000040E05010501C96F07011E51C8C54CF772 -:1051A00050EC1AF0020E070107014C5D010E0701D9 -:1051B0004D59D8B001D001D001D06BD20A0E0701F1 -:1051C00007015A6F000E07015B6FFF0E0701070111 -:1051D000586F000E0701596F05010501C8510E0DEA -:1051E0000101590EF32407010701566F0701576BA0 -:1051F0000101010E0701572308EC1FF007011E6F84 -:10520000000E07010701236F07011E5107011F6FE1 -:10521000030E07010701226F07011F5129ECB8F0A7 -:1052200019EC22F0A3C7CBF5A4C7CCF5A5C7CDF5E3 -:10523000A6C7CEF507011E6F050E05010501C96F52 -:1052400007011E5126D2C8C54CF7F2EC1BF0FA0E2E -:10525000070107014C5D000E07014D59D8B001D080 -:1052600001D038D019EC22F005010501CB5107011E -:105270000701A35D07011E6F05010501CC51070160 -:105280000701A45907011F6F05010501CD51070151 -:105290000701A5590701206F05010501CE5107013E -:1052A0000701A6590701216FE40E1E5D3D0E1F592F -:1052B000010E2059000E07012159D8A001D001D0BC -:1052C00071D607011E6F020E05010501C96F0701A6 -:1052D0001E51DFD17AD0C8C54CF787EC1AF0050112 -:1052E0000501C86919EC22F0A3C7CBF5A4C7CCF51A -:1052F000A5C7CDF5A6C7CEF507011E6F060E0501A1 -:105300000501C96F07011E510501CA830501CA8144 -:1053100005010501EBA101D001D008D0D7C53CF6AD -:10532000D8C53DF6D9C53EF6DAC53FF605010501FB -:10533000EBA501D001D008D0DFC540F6E0C541F6AD -:10534000E1C542F6E2C543F605010501EBA301D034 -:1053500001D008D0DBC544F6DCC545F6DDC546F610 -:10536000DEC547F605010501EBA701D001D008D045 -:10537000E3C548F6E4C549F6E5C54AF6E6C54BF689 -:10538000000E060106014C6F000E06014D6F000E67 -:1053900006014E6F000E06014F6F05010501EBA9D6 -:1053A00001D001D008D0E7C54CF6E8C54DF6E9C5F7 -:1053B0004EF6EAC54FF6F6D507011E6F020E05013F -:1053C0000501C96F07011E51EDD554ECABF0050A7C -:1053D00082E0030AF1E0E6D519EC22F005010501AF -:1053E000CB5107010701A35D07011E6F05010501F0 -:1053F000CC5107010701A45907011F6F05010501E1 -:10540000CD5107010701A5590701206F05010501CD -:10541000CE5107010701A6590701216FF20E1E5D4B -:105420009E0E1F59000E2059000E07012159D8B0B9 -:1054300001D001D001D02DD1020E0501CF5D000EAB -:105440000501D059000E0501D159000E05010501D5 -:10545000D259D8A001D001D018D0F20E0501050113 -:10546000CB279E0E0501CC23000E0501CD23000E97 -:105470000501CE2305010501CF07000E0501D05B14 -:105480000501D15B0501D25B04D1430E0701070181 -:10549000506F000E0701516F000E070107014E6F9C -:1054A000000E07014F6F440E070107014C6F000EFD -:1054B00007014D6F9EECE1F005010501C86F050184 -:1054C0000501C829D8A401D001D001D0E2D007013C -:1054D0001E6F070E05010501C96F07011E51C8C5E2 -:1054E0004CF750EC1AF0020E070107014C5D010E5B -:1054F00007014D59D8B001D001D001D0CAD0070161 -:105500001E6F010E07010701236F07011E510701DE -:105510001F6F030E07010701226F07011F5129ECBE -:10552000B8F00501CA9519EC22F0A3C7CBF5A4C7C2 -:10553000CCF5A5C7CDF5A6C7CEF505010501C92B4C -:10554000A8D0C8C54CF7F2EC1BF0FA0E0701070112 -:105550004C5D000E07014D59D8B001D001D041D0AB -:1055600019EC22F005010501CB5107010701A35DEC -:1055700007011E6F05010501CC5107010701A45960 -:1055800007011F6F05010501CD5107010701A5594D -:105590000701206F05010501CE5107010701A6593A -:1055A0000701216FE40E1E5D3D0E1F59010E2059AB -:1055B000000E07012159D8A001D001D0F3D4050174 -:1055C00005EEC9F0EF2A0C0EEF6401D001D008D02F -:1055D00007011E6F020E05010501C96F07011E516B -:1055E00058D025D0C8C54CF787EC1AF00501050145 -:1055F000C86919EC22F0A3C7CBF5A4C7CCF5A5C7A1 -:10560000CDF5A6C7CEF507011E6F060E05010501F3 -:10561000C96F07011E510501CA83C4D407011E6F5B -:10562000020E05010501C96F07011E51BBD454ECE0 -:10563000ABF0050AD7E0030AF1E0B4D40501050197 -:10564000C951000A01E1AED4010A01E1ACD4030A58 -:1056500001E1D3D4010A01E148D5070A01E19ED551 -:10566000010A01E1F0D5030A01E1B6D6010A01E120 -:1056700036D70F0A01E165D7010A01E130D7030AE5 -:1056800001E15FD7010A01E12AD7070A01E159D7F1 -:1056900000D0070107011D2B000E070107011D6542 -:1056A00001D001D07ED4120007012B6F000E07013C -:1056B0000701236F07012B510701250E0701070181 -:1056C0004D6F0701070E07014E6F86EC1EF00701B4 -:1056D00007012551020AD8A401D001D00FD31C0E16 -:1056E000070107014E6F000E07014F6F69EC20F0B4 -:1056F00007012B6F000E07010701266F07012B51D1 -:10570000050E07010701266501D001D001D02CD07C -:105710000701250E070107014D6F0701070E07015D -:105720004E6F86EC1EF026C72BF72D0E07012B2798 -:1057300006013C0E07012B25E96EEA6A0601060EFA -:10574000EA22EF50070107012519D8B401D001D092 -:1057500001D014D307010701262B050E070107010D -:10576000266501D001D0D4D705010501CAB501D005 -:1057700001D01DD0100E070107014E6F000E07016A -:105780004F6F69EC20F0040E070107014F6F000E08 -:105790000701506F0501D70E070107014D6F050185 -:1057A000050E07014E6FA3EC13F00501EB81F00E1F -:1057B000070107014E6F000E07014F6F69EC20F0E3 -:1057C00007012B6F000E07010701226F07012B5104 -:1057D0000701250E070107014D6F0701070E07019D -:1057E0004E6F86EC1EF00009D8A401D001D009D07C -:1057F00007012B6F010E07010701226F07012B51D3 -:105800007DD25CD20701250E070107014D6F07010C -:10581000070E07014E6F86EC1EF0070107012505F4 -:10582000D8A401D001D01BD00701230E0701070126 -:105830004D6F0701070E07014E6F86EC1EF0050144 -:105840000501CAA501D001D009D0070107012351E4 -:10585000020AD8A401D001D001D090D201D08ED2BA -:1058600046D20701250E070107014D6F0701070EFC -:1058700007014E6F86EC1EF0070107012551040A4F -:10588000D8A401D001D0EBD705010501CAA501D0EC -:1058900001D026D007012B6F000E07010701266FEC -:1058A00007012B51030E07010701266501D001D026 -:1058B00001D015D00701250E070107014D6F070123 -:1058C000070E07014E6F86EC1EF007010701262B1D -:1058D000030E07010701266501D001D0EBD714D0D4 -:1058E000040E070107014F6F000E0701506F0501FD -:1058F000DF0E070107014D6F0501050E07014E6F11 -:10590000A3EC13F00501EB85ABD70701240E0701CB -:1059100007014D6F0701070E07014E6F86EC1EF061 -:10592000030E07010701246501D001D098D70501B6 -:105930000501CAA501D001D026D007012B6F000EAA -:1059400007010701266F07012B51030E070107010D -:10595000266501D001D001D015D00701250E070121 -:1059600007014D6F0701070E07014E6F86EC1EF011 -:1059700007010701262B030E07010701266501D049 -:1059800001D0EBD714D0040E070107014F6F000EB2 -:105990000701506F0501DB0E070107014D6F05017F -:1059A000050E07014E6FA3EC13F00501EB8300D049 -:1059B000040E07010701245F0BD00701250E070124 -:1059C00007014D6F0701070E07014E6F86EC1EF0B1 -:1059D00007010701240707012429D8A401D001D019 -:1059E000ECD785D10701240E070107014D6F070190 -:1059F000070E07014E6F86EC1EF0040E070107012B -:105A0000246101D001D001D0B9D105010501CAB589 -:105A100001D001D018D0040E070107014F6F000E0E -:105A20000701506F0501E30E070107014D6F0501E6 -:105A3000050E07014E6FA3EC13F00501EB87040E72 -:105A400007010701245F030E07010701246501D048 -:105A500001D01ED005010501CAB501D001D018D072 -:105A6000040E070107014F6F000E0701506F05017B -:105A7000E70E070107014D6F0501050E07014E6F87 -:105A8000A3EC13F00501EB89040E07010701245F65 -:105A90000BD00701250E070107014D6F0701070E07 -:105AA00007014E6F86EC1EF007010701240707016E -:105AB0002429D8A401D001D0ECD719D10701250E93 -:105AC000070107014D6F0701070E07014E6F86ECB6 -:105AD0001EF0070107012551040AD8A401D001D006 -:105AE000BED607012A0E070107014D6F0701070EF9 -:105AF00007014E6F86EC1EF00701290E0701070112 -:105B00004D6F0701070E07014E6F86EC1EF007016F -:105B1000280E070107014D6F0701070E07014E6FA1 -:105B200086EC1EF00701270E070107014D6F0701E4 -:105B3000070E07014E6F86EC1EF092D607012B6F01 -:105B4000010E07010701226F07012B51D0D0070179 -:105B5000250E070107014D6F0701070E07014E6F64 -:105B600086EC1EF0070107012551040AD8A401D0D4 -:105B700001D075D605010501CAA501D001D026D0F6 -:105B800007012B6F000E07010701266F07012B513C -:105B9000030E07010701266501D001D001D015D001 -:105BA0000701250E070107014D6F0701070E0701C9 -:105BB0004E6F86EC1EF007010701262B030E07012E -:105BC0000701266501D001D0EBD756D00501D20ED2 -:105BD000070107014D6F0501050E07014E6F86ECA9 -:105BE0001EF00501D10E070107014D6F0501050EDD -:105BF00007014E6F86EC1EF00501D00E070107016C -:105C00004D6F0501050E07014E6F86EC1EF0050174 -:105C1000CF0E070107014D6F0501050E07014E6FFD -:105C200086EC1EF00501CFC52BF70501D0C52CF77A -:105C30000501D1C52DF70501D2C52EF7060E06D0F8 -:105C4000D89007012E332D332C332B33E82EF8D781 -:105C500007012B5105010501CF5F07012C510501FB -:105C60000501D05B07012D5105010501D15B07013D -:105C70002E5105010501D25BF3D50701240E070162 -:105C800007014D6F0701070E07014E6F86EC1EF0EE -:105C90000BD00701250E070107014D6F0701070E05 -:105CA00007014E6F86EC1EF007010701240707016C -:105CB0002429D8A401D001D0ECD719D007010701BD -:105CC0002551010A01E1CDD5020A01E11ED6050ADE -:105CD00001E188D6350A01E13AD7060A01E192D5F9 -:105CE000030A01E1EBD6C90A01E128D7C6D70701AB -:105CF00007012251D8B401D001D06AD507010701AC -:105D00002351020AD8A401D001D00BD027C7D3F564 -:105D100028C7D4F529C7D5F52AC7D6F50501CA8500 -:105D200027D0070107012A5105010501D61914E101 -:105D300007010701295105010501D5190DE10701E9 -:105D40000701285105010501D41906E107010701E2 -:105D5000275105010501D319D8B401D001D008D0CD -:105D600007012B6F000E07010701236F07012B515D -:105D700051EC21F007010701235104D051EC21F02F -:105D8000000E00D01200020E070107014A25E96E3D -:105D9000000E070107014B21EA6EEE50ED10D8A46A -:105DA00001D001D002D0000E32D30701546FFE0E95 -:105DB000070107014E6F07015451020E0701070149 -:105DC0004A25E96E000E070107014B21EA6EEECF6E -:105DD00054F7EDCF55F74AC7E9FF4BC7EAFFEECFBF -:105DE00056F7EDCF57F74CC7E9FF4DC7EAFFEECFA7 -:105DF00058F7EDCF59F7020E070107014C25E96E60 -:105E0000000E070107014D21EA6EEECF5AF7EDCFE4 -:105E10005BF70701585107015A2507015C6F07011D -:105E2000595107015B2107015D6F070156510701B9 -:105E30005C2507015E6F0701575107015D210701CE -:105E40005F6F0701545107015E1907010701506F89 -:105E50000701555107015F190701516F0701546F81 -:105E6000000E070107014F6F07015451000E070193 -:105E700007014F6501D001D001D0A4D04FC760F712 -:105E800084EC0EF003010301F5510D0AD8A401D0F2 -:105E900001D001D08DD003010301F551040AD8A42B -:105EA00001D001D01CD0020E070107014A25E96E7E -:105EB000000E070107014B21EA6E030113EEF8F013 -:105EC000E652EE52ED50E518EFCFE8FFD8B4E718F0 -:105ED000D8A401D001D002D04FC74EF769D003013A -:105EE00003EEF8F00701EE5207015151ED180701DA -:105EF00050C7E8FFD8B4EF18D8B401D001D001D012 -:105F000057D077ECE7F0040104EED8F0020E070159 -:105F100007014A25E16E000E070107014B21E26EE1 -:105F2000E652EE52ED50E518EFCFE8FFD8B4E7188F -:105F3000D8A401D001D03CD0040104EED6F04AC769 -:105F4000E1FF4BC7E2FFE652EE52ED50E518EFCF0E -:105F5000E8FFD8B4E718D8A401D001D029D04CC7A5 -:105F6000E9FF4DC7EAFFEECF54F7EECF55F7EECF7E -:105F700056F7EECF57F704010401E1510701571915 -:105F800011E104010401E051070156190BE104017C -:105F90000401DF510701551905E104010401DE5137 -:105FA00007015419D8A401D001D002D0010E2FD27C -:105FB000070107014F2B000E070107014F6501D0B4 -:105FC00001D05CD7070107014E51FE0AD8B401D0B9 -:105FD00001D048D04EC760F784EC0EF077ECE7F0C4 -:105FE000070107014E51FE0AD8B401D001D03AD0C2 -:105FF00050C7F8F351C7F9F30A0E07010701B26F52 -:10600000000E0701B36F4CC7B0F74DC7B1F70401DD -:10601000DE0E07010701AE6F0401040E0701AF6F2A -:1060200018EC1AF04AC7E9FF4BC7EAFF0401EECFAC -:10603000D6F40401EDCFD7F4020E070107014A257B -:10604000E96E000E070107014B21EA6E0401EECF55 -:10605000D8F40401EDCFD9F4DFC3D4F4E0C3D5F410 -:10606000010ED5D10D0E070107014A25E96E000E7C -:10607000070107014B21EA6EEF500701546F07013A -:1060800054B301D001D002D0000EC1D106010601E7 -:1060900039513811D8B401D001D002D0000EB7D197 -:1060A000000E07010701526F000E0701536F030E28 -:1060B00007010701525D000E07015359D8A001D016 -:1060C00001D001D0C8D0070107015251140DF3CF00 -:1060D00054F7100E070154270601000E070154253E -:1060E000E96EEA6A0601060EEA22EE50ED10D8A427 -:1060F00001D001D001D0AFD0020E070107014A251F -:10610000E96E000E070107014B21EA6E0701070146 -:106110005251140DF3CF54F7100E07015427060106 -:10612000000E07015425E16EE26A0601060EE22226 -:10613000E652EE52ED50E518EFCFE8FFD8B4E7187D -:10614000D8B401D001D001D077D04AC7E9FF4BC7FE -:10615000EAFF070107015251140DF3CF54F70A0E5D -:10616000070154270601000E07015425E16EE26A7B -:106170000601060EE222E652EE52ED50E518EFCF90 -:10618000E8FFD8B4E718D8B401D001D001D054D07A -:106190004CC7E9FF4DC7EAFFEECF54F7EECF55F7F6 -:1061A000EECF56F7EECF57F7070107015251140D06 -:1061B0000601000EF324E96EEA6A0601060EEA22E1 -:1061C000EECF58F7EECF59F7EECF5AF7EECF5BF799 -:1061D0000701575107015B190EE1070156510701ED -:1061E0005A1909E1070155510701591904E107013D -:1061F000545107015819D8B401D001D001D01CD096 -:1062000055EC20F0070107015251140DF3CF54F75C -:10621000120E070154270601000E07015425E96EEE -:10622000EA6A0601060EEA22070170C7EEFF0701BF -:1062300071C7EDFF000EEBD007010701524B532B46 -:10624000030E07010701525D000E07015359D8A044 -:1062500001D001D038D70701546F000E07010701A4 -:106260004F6F07015451000E070107014F6501D020 -:1062700001D001D0CAD04FC760F784EC0EF0030103 -:106280000301F6B701D001D001D0B5D077ECE7F02B -:10629000020E070107014A25E96E000E07010701FA -:1062A0004B21EA6E040114EED8F0E652EE52ED50A6 -:1062B000E518EFCFE8FFD8B4E718D8B401D001D083 -:1062C00001D099D00A0E07010701B26F000E070135 -:1062D000B36F4CC7B0F74DC7B1F707010701525173 -:1062E000140D0601000EF32407010701AE6F07012C -:1062F000AF6B0601060E0701AF2318EC1AF04AC770 -:10630000E9FF4BC7EAFF070107015251140DF3CF14 -:1063100054F70A0E070154270601000E0701542501 -:10632000E16EE26A0601060EE222EECFE6FFEDCF55 -:10633000E5FF040E070107014A25E96E000E07017B -:1063400007014B21EA6E070107015251140DF3CFEB -:1063500054F70C0E070154270601000E07015425BF -:10636000E16EE26A0601060EE222EECFE6FFEECF14 -:10637000E6FFEECFE6FFEDCFE5FFE552E552020E78 -:10638000070107014A25E96E000E070107014B21AD -:10639000EA6E070107015251140DF3CF54F7100EA6 -:1063A000070154270601000E07015425E16EE26A39 -:1063B0000601060EE222EECFE6FFEDCFE5FF55EC3B -:1063C00020F0070107015251140DF3CF54F7120EBC -:1063D000070154270601000E07015425E96EEA6AF9 -:1063E0000601060EEA22070170C7EEFF070171C71A -:1063F000EDFF000E0CD0070107014F2B000E070127 -:1064000007014F6501D001D036D7000E00D0120031 -:106410002FC7E9FF30C7EAFF0701EECF38F70701C2 -:10642000EECF39F70701EECF3AF70701EECF3BF792 -:10643000040E070107012F25E96E000E0701070171 -:106440003021EA6E0701EECF3CF70701EECF3DF7B2 -:106450000701EECF3EF70701EECF3FF7080E070129 -:1064600007012F25E96E000E070107013021EA6EB2 -:106470000701EECF40F70701EECF41F70701EECF5E -:1064800042F70701EECF43F70C0E070107012F2556 -:10649000E96E000E070107013021EA6E0701EECF19 -:1064A00044F70701EECF45F70701EECF46F70701A6 -:1064B000EECF47F7100E070107012F25E96E000EFA -:1064C000070107013021EA6E0701EECF48F7070107 -:1064D000EECF49F70701EECF4AF70701EECF4BF7B2 -:1064E000180E070107012F2507010701366F000E5F -:1064F0000701070130210701376F140E070107015B -:106500002F25E96E000E070107013021EA6EEF50DA -:1065100007014C6F3F0E07014C1707014C51070153 -:106520000701362507014D6FE86A07014CBFE8688F -:1065300007010701372107014E6F4DC734F74EC7DA -:1065400035F707014C6F000E07010701336F070194 -:106550004C5117D036C7E9FF37C7EAFF01019F0E3C -:10656000070107013325E16EE26A0101010EE22213 -:10657000EFCFE7FF07010701364B372B0701070174 -:10658000332B07010701355107010701371906E1D0 -:10659000070107013451070107013619D8A401D0BA -:1065A00001D0D8D701019F0E070107013325E96EFD -:1065B000EA6A0101010EEA22800EEF6E070107016F -:1065C000332B380E07010701336501D001D05ED0AF -:1065D0003F0E07010701336501D001D001D016D06D -:1065E00001019F0E070107013325E96EEA6A0101E7 -:1065F000010EEA22000EEF6E07010701332B3F0E5A -:1066000007010701336501D001D0EAD70701480E21 -:10661000070107015A6F0701070E07015B6F0701AA -:10662000440E07010701586F0701070E0701596F54 -:106630000701400E07010701566F0701070E07010A -:10664000576F07013C0E07010701546F0701070E42 -:106650000701556F0701380E07010701526F070147 -:10666000070E0701536F01019F0E07010701506FCD -:106670000101010E0701516FD0ECA1F007014C6F31 -:10668000000E07010701336F07014C51370E070158 -:106690000701336501D001D001D016D001019F0E52 -:1066A000070107013325E96EEA6A0101010EEA22BA -:1066B000000EEF6E07010701332B370E07010701AC -:1066C000336501D001D0EAD7140E070107012F2549 -:1066D000E96E000E070107013021EA6EEF50070155 -:1066E0004C6F0701D8904C370701D8904C37070101 -:1066F000D8904C3501010101DE6F140E070107012E -:106700002F25E96E000E070107013021EA6EEECF5A -:106710004CF7EECF4DF7EECF4EF7EECF4FF7060E1C -:1067200006D0D89007014F334E334D334C33E82E0B -:10673000F8D707014C5101010101DD6F140E07016B -:1067400007012F25E96E000E070107013021EA6ECF -:10675000EECF4CF7EECF4DF7EECF4EF7EECF4FF733 -:106760000E0E06D0D89007014F334E334D334C33C5 -:10677000E82EF8D707014C5101010101DC6F140E1E -:10678000070107012F25E96E000E070107013021DF -:10679000EA6EEECF4CF7EECF4DF7EECF4EF7EECFE1 -:1067A0004FF7160E06D0D89007014F334E334D33B6 -:1067B0004C33E82EF8D707014C5101010101DB6F82 -:1067C000140E070107012F25E96E000E07010701CE -:1067D0003021EA6EEECF4CF7EECF4DF7EECF4EF70D -:1067E000EECF4FF71E0E06D0D89007014F334E3331 -:1067F0004D334C33E82EF8D707014C51010101010C -:10680000DA6F07014C6F000E01010101D96F07011A -:106810004C5107014C6F000E01010101D86F0701B7 -:106820004C5107014C6F000E01010101D76F0701A8 -:106830004C510701480E070107015A6F0701070E67 -:1068400007015B6F0701440E07010701586F07013D -:10685000070E0701596F0701400E07010701566F28 -:106860000701070E0701576F07013C0E07010701DB -:10687000546F0701070E0701556F0701380E070116 -:106880000701526F0701070E0701536F01019F0EA9 -:1068900007010701506F0101010E0701516FD0EC94 -:1068A000A1F031C7E9FF32C7EAFF07013BC7EFFF9D -:1068B00007010701314B322B31C7E9FF32C7EAFF2D -:1068C00007013AC7EFFF07010701314B322B31C7F0 -:1068D000E9FF32C7EAFF070139C7EFFF07010701E8 -:1068E000314B322B31C7E9FF32C7EAFF070138C706 -:1068F000EFFF07010701314B322B31C7E9FF32C7E8 -:10690000EAFF07013FC7EFFF07010701314B322BB9 -:1069100031C7E9FF32C7EAFF07013EC7EFFF0701B2 -:106920000701314B322B31C7E9FF32C7EAFF0701BC -:106930003DC7EFFF07010701314B322B31C7E9FF9C -:1069400032C7EAFF07013CC7EFFF07010701314BE0 -:10695000322B31C7E9FF32C7EAFF070143C7EFFF18 -:1069600007010701314B322B31C7E9FF32C7EAFF7C -:10697000070142C7EFFF07010701314B322B31C737 -:10698000E9FF32C7EAFF070141C7EFFF070107012F -:10699000314B322B31C7E9FF32C7EAFF070140C74D -:1069A000EFFF07010701314B322B31C7E9FF32C737 -:1069B000EAFF070147C7EFFF07010701314B322B01 -:1069C00031C7E9FF32C7EAFF070146C7EFFF0701FA -:1069D0000701314B322B31C7E9FF32C7EAFF07010C -:1069E00045C7EFFF07010701314B322B31C7E9FFE4 -:1069F00032C7EAFF070144C7EFFF07010701314B28 -:106A0000322B31C7E9FF32C7EAFF07014BC7EFFF5F -:106A100007010701314B322B31C7E9FF32C7EAFFCB -:106A200007014AC7EFFF07010701314B322B31C77E -:106A3000E9FF32C7EAFF070149C7EFFF0701070176 -:106A4000314B322B31C7E9FF32C7EAFF070148C794 -:106A5000EFFF07010701314B322B12000701096FCD -:106A6000000E070107011D6F07010951C8EC22F054 -:106A70000009D8A401D001D030D00701096F000E61 -:106A8000070107010D6F070109513BEC22F00701D7 -:106A9000096FFF0E070107010D6F0701095130EC67 -:106AA00022F02850D8B401D001D016D0E1C62DF77D -:106AB00029ECE3F0E1C60DF725EC22F00701096FA0 -:106AC000FE0E06010601E16F070109510701096F7A -:106AD000000E286E07010951BBD2E1C60DF798ECF4 -:106AE00021F00009D8A401D001D010D0010E2864F3 -:106AF00001D001D00BD0060E286001D001D006D005 -:106B00000701096F060E286E0701095185D2E1ECD5 -:106B100022F00009D8A401D001D015D00701096FD7 -:106B2000FF0E070107010D6F070109513BEC22F031 -:106B30000701096FFF0E070107010D6F07010951DA -:106B400030EC22F085D20701096FFF0E0701070123 -:106B50000D6F070109513BEC22F00701096F000E90 -:106B6000070107010D6F0701095130EC22F0070101 -:106B7000096F000E07010701146F070109510DC0CD -:106B800012F70EC013F707010A6F010E0701070184 -:106B9000116F07010A516F0E07010B6F060E0C6F84 -:106BA00007010BC70DF707010CC70EF70701070117 -:106BB0000F6B0701106B7DECBFF006010601E16F62 -:106BC0000701096F010E286E0701095119EC22F027 -:106BD000A3C7FBF4A4C7FCF4A5C7FDF4A6C7FEF445 -:106BE00037D2E1C60DF798EC21F00009D8A401D006 -:106BF00001D036D019EC22F004010401FB51070149 -:106C00000701A35D0701096F04010401FC5107019D -:106C10000701A45907010A6F04010401FD5107018E -:106C20000701A55907010B6F04010401FE5107017B -:106C30000701A65907010C6F5D0E095DA00E0A59E8 -:106C4000120E0B59000E07010C59D8A001D001D02B -:106C500006D00701096F060E286E07010951F8D109 -:106C600019EC22F0A3C7B1F6A4C7B2F6A5C7B3F6D4 -:106C7000A6C7B4F60701096F020E286E0701095175 -:106C8000E7D10701096F000E070107010D6F07012A -:106C900009513BEC22F00701096F000E07010701C3 -:106CA0000D6F0701095130EC22F011ECD3F0070110 -:106CB000096F030E286E07010951CAD119EC22F0A1 -:106CC00006010601AD5107010701A35D0701096F28 -:106CD00006010601AE5107010701A45907010A6F19 -:106CE00006010601AF5107010701A55907010B6F06 -:106CF00006010601B05107010701A65907010C6FF3 -:106D0000710E095D810E0A594A0E0B59000E0701DA -:106D10000C59D8A001D001D003D045EC1FF098D178 -:106D200019EC22F006010601B15107010701A35D2C -:106D30000701096F06010601B25107010701A459B5 -:106D400007010A6F06010601B35107010701A559A2 -:106D500007010B6F06010601B45107010701A6598F -:106D600007010C6F510E095D840E0A59DF0E0B5995 -:106D7000000E07010C59D8A001D001D007D007019F -:106D8000096F080E286E0701095162D1E1C613F799 -:106D90007FEC10F0070114511311D8B401D001D0C9 -:106DA00011D019EC22F0A3C7FBF4A4C7FCF4A5C7CB -:106DB000FDF4A6C7FEF40701096F040E286E070153 -:106DC000095146D145D119EC22F004010401FB51CF -:106DD00007010701A35D0701096F04010401FC51CC -:106DE00007010701A45907010A6F04010401FD51BD -:106DF00007010701A55907010B6F04010401FE51AA -:106E000007010701A65907010C6FE50E095D3D0E4C -:106E10000A59010E0B59000E07010C59D8A001D0D8 -:106E200001D009D0F6EC1DF00701096F030E286EA2 -:106E3000070109510DD1E1C613F77FEC10F00701EE -:106E400014511311D8A401D001D001D001D1E1C651 -:106E500013F77FEC10F0070114511311D8A401D0DF -:106E600001D001D0AFD70701080E070107010E6F4F -:106E70000701070E07010F6FE1C60DF7C1EC0CF01B -:106E80000009D8A401D001D001D09CD708C70DF7C4 -:106E900080ECCEF019EC22F0A3C7FBF4A4C7FCF4FD -:106EA000A5C7FDF4A6C7FEF4A4EC22F00009D8B4EF -:106EB00001D001D007D00701096F050E286E070128 -:106EC000095180D7C4D71CEC10F0F6EC1DF0070177 -:106ED000096F030E286E07010951BAD0E1C62DF7DC -:106EE00029ECE3F0E1C60DF725EC22F00701096F6C -:106EF000080E286E07010951ABD07AECC5F07F0E61 -:106F0000070107011617000E070117170A0E0701E0 -:106F10000701162500010001F36F000E07010701AC -:106F200017210001F46F19EC22F0A3C7FBF4A4C7EA -:106F3000FCF4A5C7FDF4A6C7FEF4D3EC1FF00701CF -:106F4000096F000E070107010D6F0701095130ECB1 -:106F500022F00701096F090E286E0701095178D048 -:106F600019EC22F004010401FB5107010701A35DA4 -:106F70000701096F04010401FC5107010701A4592D -:106F800007010A6F04010401FD5107010701A5591A -:106F900007010B6F04010401FE5107010701A65907 -:106FA00007010C6FF20E07010701786F9E0E0701B3 -:106FB000796F000E07017A6F000E07017B6F0001E9 -:106FC0000701F3C074F700010701F4C075F707016A -:106FD000000E070175BFFF0E0701766F0701776F7F -:106FE00051EC13F00701095107010701745D070116 -:106FF0000A5107010701755907010B5107010701E4 -:10700000765907010C51070107017759D8B001D013 -:1070100001D0D8D6FF001CD02850000A01E177D556 -:10702000010A01E1DED5030A01E12BD6010A01E1E3 -:1070300045D6070A01E1C7D6010A01E144D7030A90 -:1070400001E14CD70E0A01E158D7010A89E000D0CE -:1070500012000701296F010E07010701536F070195 -:10706000295163EC1FF00701296F010E0701070189 -:10707000536F0701295163EC1FF00701296F060EBA -:1070800007010701536F0701295163EC1FF0070146 -:10709000296F000E07010701536F0701295163ECA7 -:1070A0001FF00701296F120E07010701536F070137 -:1070B000295163EC1FF00701296F230E0701070117 -:1070C000536F0701295163EC1FF00701296F340E3C -:1070D00007010701536F0701295163EC1FF00701F6 -:1070E000296F560E07010701536F0701295163EC01 -:1070F0001FF00701296F000E07010701536F0701F9 -:10710000295163EC1FF00701296F000E07010701E9 -:10711000536F0701295163EC1FF00701296F800E9F -:1071200007010701536F0701295105010501CAA98C -:1071300001D001D008D00701296F000E0701070117 -:10714000536F0701295163EC1FF00701296F000EEF -:1071500007010701536F0701295163EC1FF0070175 -:1071600007012251030AD8A401D001D01AD0070187 -:1071700007012351D8B401D001D013D0040E070168 -:107180000701556F000E0701566F0501D70E070165 -:107190000701536F0501050E0701546FEBEC17F063 -:1071A00028D00701296F000E07010701536F07015F -:1071B000295163EC1FF00701296F000E0701070139 -:1071C000536F0701295163EC1FF00701296F000E6F -:1071D00007010701536F0701295163EC1FF00701F5 -:1071E000296F000E07010701536F0701295163EC56 -:1071F0001FF00701296F000E07010701246F070127 -:1072000029510B0E07010701246501D001D001D0DF -:1072100014D00701296F000E07010701536F070102 -:10722000295163EC1FF007010701242B0B0E070106 -:107230000701246501D001D0ECD7060E0701070134 -:10724000556F000E0701566F0601690E0701070111 -:10725000536F0601060E0701546FEBEC17F00701A0 -:10726000296F000E07010701246F07012951C90E7C -:1072700007010701246501D001D001D014D0070116 -:10728000296F000E07010701536F0701295163ECB5 -:107290001FF007010701242BC90E07010701246510 -:1072A00001D001D0ECD70701296F630E0701070158 -:1072B000536F0701295163EC1FF00701296F820EFC -:1072C00007010701536F0701295163EC1FF0070104 -:1072D000296F530E07010701536F0701295163EC12 -:1072E0001FF00701296F630E07010701536F0701A4 -:1072F000295163EC1FF00701296F350E07010701C3 -:10730000536F0701295163EC1FF00701296F010E2C -:1073100007010701536F0701295163EC1FF022C7D2 -:1073200053F763EC1FF0070107012205D8A401D031 -:1073300001D002D00501CA95070107012251030AB5 -:10734000D8A401D001D02AD007010701236701D0BA -:1073500001D024D00701296F360E07010701536FB2 -:107360000701295163EC1FF00701296F040E070183 -:107370000701536F0701295163EC1FF0D6C553F77E -:1073800063EC1FF0D5C553F763EC1FF0D4C553F77A -:1073900063EC1FF0D3C553F763EC1FF00701296FAF -:1073A000370E07010701536F0701295163EC1FF0E6 -:1073B0000701296F040E07010701536F07012951C7 -:1073C00063EC1FF00701296F010E07010701536FDE -:1073D0000701295163EC1FF00701296F030E070114 -:1073E0000701536F0701295163EC1FF00701296F53 -:1073F000060E07010701536F0701295163EC1FF0C7 -:107400000701296F0C0E07010701536F070129516E -:1074100063EC1FF0070107012251030AD8A401D031 -:1074200001D007D0070107012351D8B401D001D002 -:1074300010D0070107012205D8A401D001D02FD018 -:107440000501DA51D711D811D911D8B401D001D022 -:1074500026D00701296F320E07010701536F07017C -:10746000295163EC1FF00701296F040E0701070182 -:10747000536F0701295163EC1FF0040E0701070148 -:10748000556F000E0701566F0501D70E0701070162 -:10749000536F0501050E0701546FEBEC17F0070160 -:1074A000296FFF0E07010701536F0701295163EC94 -:1074B0001FF00AD00701296F000E07010701536F63 -:1074C0000701295163EC1FF02C0E135C010E1458B8 -:1074D000D8A001D001D0EED73CC625F73DC626F78F -:1074E0003EC627F73FC628F707010701236701D0EB -:1074F00001D00DD0000E060106013C6F000E060102 -:107500003D6F000E06013E6F000E06013F6FBCECA2 -:1075100009F025C73CF626C73DF627C73EF628C723 -:107520003FF61200000E07010701136F000E07015E -:10753000146F000E0701156F000E0701166F07018B -:107540000E0E07010701346F0701070E0701356FA3 -:1075500007010C0E07010701326F0701070E070133 -:10756000336F53EC1CF007010E0E070107012D6F5E -:107570000701070E07012E6F07010C0E0701070117 -:107580002B6F0701070E07012C6FE1EC10F0010EC5 -:10759000070107010F6F000E0701106F000E0701B2 -:1075A000116F000E0701126F000E07010701176F20 -:1075B000000E0701186F070107011851800A800F9C -:1075C000200ED8B4175DD8A001D001D001D06FD063 -:1075D00007010E0E070107012D6F0701070E0701B6 -:1075E0002E6F07010C0E070107012B6F0701070E15 -:1075F00007012C6FE1EC10F007010701196F07017B -:107600000E0E070107012D6F0701070E07012E6FF0 -:1076100007010C0E070107012B6F0701070E070179 -:107620002C6FE1EC10F0070107011A6F1BD025D079 -:10763000070107010F510701070113130701070194 -:107640001051070107011413070107011151070128 -:10765000070115130701070112510701070116134E -:107660000CD029D11AC72CF719C72BF763EC1EF0E1 -:10767000000ADDE0010ADCE0F4D70701D890070139 -:107680000F370701103707011137070112370701BC -:107690000701174B182B070107011851800A800FAB -:1076A000200ED8B4175DD8A001D001D091D7070122 -:1076B00013C71BF7070114C71CF7070115C71DF7F0 -:1076C000070116C71EF707011B1F1C1F1D1F1E1FCA -:1076D000110E06D0D89007011E331D331C331B3307 -:1076E000E82EF8D7FF0E07011B1507011F6F000ECC -:1076F00007011C150701206F000E07011D1507016A -:10770000216F000E07011E150701226F070113C725 -:1077100023F7070114C724F7070115C725F7070149 -:1077200016C726F7190E06D0D89007012633253341 -:1077300024332333E82EF8D7FF0E07012315070162 -:10774000276F000E070124150701286F000E07019F -:1077500025150701296F000E0701261507012A6F5D -:107760000701225107012A190EE1070121510701E2 -:10777000291909E1070120510701281904E107012E -:107780001F5107012719D8B401D001D001D093D0DF -:10779000FF0E070113C71BF7070114C71CF70701EA -:1077A00015C71DF7070116C71EF707011B1F1C1F72 -:1077B0001D1F1E1F07011B1507011F6F000E07016C -:1077C0001C150701206F000E07011D150701216F11 -:1077D000000E07011E150701226FFF0E070113C7D8 -:1077E00023F7070114C724F7070115C725F7070179 -:1077F00016C726F724C723F725C724F726C725F77A -:107800000701266B070123150701276F000E0701EB -:1078100024150701286F000E070125150701296FA0 -:10782000000E0701261507012A6F070122510701E3 -:107830002A190EE1070121510701291909E1070160 -:1078400020510701281904E107011F5107012719D9 -:10785000D8B401D001D001D02ED075EC21F0DF0ECC -:10786000070107012D6FFF0E07012E6F6D0E070137 -:1078700007012B6FFF0E07012C6F51EC22F013C78D -:107880002DF714C72EF715C72FF716C730F7D50EEB -:10789000070107012B6FFF0E07012C6FC8EC21F0C9 -:1078A00007011B6F020E070107012B6F07011B5118 -:1078B000E1EC20F000D012000601060168AD01D015 -:1078C00001D044D01AEC21F007010701106F070125 -:1078D000070110512F18D8B401D001D024D010C7FF -:1078E0002FF007010701106701D001D01CD050C64E -:1078F0003CF651C63DF652C63EF653C63FF654C658 -:1079000040F655C641F656C642F657C643F606013E -:10791000688F0701116F000E070107011D6F070136 -:10792000115169EC15F0C1ECA7F00701116F000EC1 -:10793000070107011D6F07011151C8EC22F0000972 -:10794000D8B401D001D002D00601689F87EC8EF038 -:10795000DAEC22F051EC21F00701080E07010701D3 -:107960001F6F0701070E0701206F0001C10E0701FD -:1079700007011D6F0001000E07011E6FA9EC03F047 -:107980000009D8A401D001D001D029D11DD107EC24 -:10799000E0F024D107010A0E07010701236F070158 -:1079A000070E0701246F0701090E07010701216F68 -:1079B0000701070E0701226F0001BD0E0701070135 -:1079C0001F6F0001000E0701206F07010C0E070159 -:1079D00007011D6F0701070E07011E6F5DECE5F043 -:1079E0000009D8A401D001D001D0F8D007010701C7 -:1079F0000905D8A401D001D09FD0060106013F514E -:107A0000070107010F1914E1060106013E510701A4 -:107A100007010E190DE1060106013D51070107019D -:107A20000D1906E1060106013C51070107010C1979 -:107A3000D8B401D001D070D007010C29D8B40D29D9 -:107A4000D8B40E29D8B40F29D8B401D001D064D04D -:107A5000060140C611F7060141C612F7060142C6EB -:107A600013F7060143C614F70701111F121F131F56 -:107A7000141F060106013C510601060140150701CD -:107A8000156F060106013D5106010601411507016A -:107A9000166F060106013E51060106014215070157 -:107AA000176F060106013F51060106014315070144 -:107AB000186F07011151070115110701196F07010F -:107AC00012510701161107011A6F0701135107011F -:107AD000171107011B6F0701145107011811070146 -:107AE0001C6F070107010F5107011C1911E1070164 -:107AF00007010E5107011B190BE1070107010D5189 -:107B000007011A1905E1070107010C5107011919AD -:107B1000D8A401D001D00FD00AC71FF70BC720F798 -:107B20000001BD0E070107011D6F0001000E0701D6 -:107B30001E6FFDEC00F052D0070107010951060A43 -:107B4000D8A401D001D019D00AC721F70BC722F75A -:107B500007010C0E070107011F6F0701070E070140 -:107B6000206F0001BD0E070107011D6F0001000E0F -:107B700007011E6F2EECD9F031D007010701095122 -:107B8000110AD8A401D001D0D6D70AC721F70BC754 -:107B900022F707010C0E070107011F6F0701070EEF -:107BA0000701206F0001BD0E070107011D6F0001D5 -:107BB000000E07011E6F37ECD8F00009D8B401D0D1 -:107BC00001D001D00CD00AD0070107010851000AEA -:107BD00001E1E0D6060A01E1DAD600D0BBD61200F8 -:107BE0000701096F000E070107011D6F0701095109 -:107BF000C8EC22F00009D8A401D001D01ED0075053 -:107C0000D8B401D001D018D0DEC62DF729ECE3F0AE -:107C1000DEC60DF725EC22F00701096FFE0E060106 -:107C20000601DE6F0701095123EC1CF00701096F03 -:107C3000000E076E070109515FD14FD10701096F8F -:107C4000010E076E070109510701096F000E0701B8 -:107C50000701146F07010951500E07010701126F48 -:107C6000000E0701136F07010A6F010E07010701DC -:107C7000116F07010A51B50E07010B6F060E0C6F4D -:107C800007010BC70DF707010CC70EF70701070126 -:107C90000F6B0701106B7DECBFF006010601DE6F74 -:107CA00006010601DE51FE0AD8A401D001D007D09A -:107CB0000701096F000E076E070109511DD119EC6C -:107CC00022F0A3C7F3F4A4C7F4F4A5C7F5F4A6C73C -:107CD000F6F412D1DEC60DF798EC21F00009D8A415 -:107CE00001D001D036D019EC22F004010401F35187 -:107CF00007010701A35D0701096F04010401F451A5 -:107D000007010701A45907010A6F04010401F55195 -:107D100007010701A55907010B6F04010401F65182 -:107D200007010701A65907010C6F5D0E095DA00E42 -:107D30000A59120E0B59000E07010C59D8A001D098 -:107D400001D006D00701096F040E076E0701095123 -:107D5000D3D00701096F020E076E07010951CCD07D -:107D6000DEC641F747EC0AF07D0E07010701415DD1 -:107D7000000E07014259D8B001D001D001D0BCD0CB -:107D8000C60E07010701306FFF0E0701316FDEC617 -:107D90002FF7A5EC20F0620E07010701306FFE0EF1 -:107DA0000701316FDEC62FF7A5EC20F0040E0701A6 -:107DB0000701306FFF0E0701316FDEC62FF7A5EC0C -:107DC00020F00601B50E07010701306F0601060E0F -:107DD0000701316FDEC62FF7CDEC20F0D80E07017A -:107DE0000701306FFE0E0701316FDEC62FF7A5ECDD -:107DF00020F0DEC641F7DEEC1CF00701096F000E33 -:107E0000316E070109510701096F030E076E070163 -:107E1000095172D00701080E070107010E6F070113 -:107E2000070E07010F6FDEC60DF7C1EC0CF000095D -:107E3000D8A401D001D001D023D0030E316401D0E9 -:107E400001D005D008C70DF7A9EC01F018D0070143 -:107E5000070108510A0AD8B401D001D008D007019F -:107E6000070108510D0AD8A401D001D002D0312A4F -:107E700006D00701096F000E316E07010951CAD7FC -:107E8000DEC60DF798EC21F00009D8A401D001D08E -:107E900006D00701096F040E076E070109512CD0A7 -:107EA000DEC62DF729ECE3F0DEC60DF725EC22F057 -:107EB0000701096FFE0E06010601DE6F0701095179 -:107EC0000701096F010E226E070109510701096FB1 -:107ED000050E076E070109510FD00750000A01E196 -:107EE000ADD6010A01E1F6D6030A01E139D7010A4C -:107EF00091E0070AD5E000D012000701166F000ECE -:107F000007010701156F07011651000E0701070150 -:107F1000156501D001D001D076D115C760F784EC8A -:107F20000EF003010301F5510D0AD8B401D001D0C0 -:107F300001D05FD177ECE7F004010401EE510701B5 -:107F400007011419D8B401D001D001D052D1180EB4 -:107F500004010401EB6F020E0401EC6F070107013D -:107F6000116701D001D013D012C7D8F413C7D9F4C8 -:107F70000301F6870701166F040E03010301F56F75 -:107F80000701165112C7F8F313C7F9F32ED1000EEB -:107F900000010001FD5D040E0001FE59D8A001D0D2 -:107FA00001D00BD0890E00010001FD5D130E000110 -:107FB000FE59D8A001D001D007D0000E0001000169 -:107FC000FD6F040E0001FE6FFDC0D8F4FEC0D9F4B1 -:107FD00000010001FD4BFE2B12C7D6F413C7D7F4E6 -:107FE00019EC22F0A3C7EDF3A4C7EEF3A5C7EFF396 -:107FF000A6C7F0F30301F689E9D00DC7DEF40EC77A -:10800000DFF40FC7E0F410C7E1F4070107011151D5 -:10801000020AD8B401D002D0010E01D0000E07012F -:10802000166F0701164716470401EA510701161992 -:10803000FB0B16190401EA6F0701166F000E03010E -:108040000301F56F07011651D0D0070107EE0FF0BD -:10805000EECF16F7EDCF17F7070107010D51070116 -:108060001627070107010E51070117230701070112 -:1080700012510701162707010701135107011723A2 -:1080800004010401D8510701161903010301F86F17 -:1080900004010401D951070117190301F96F0DC734 -:1080A000DEF40EC7DFF40FC7E0F410C7E1F40701F8 -:1080B000166F000E04010401ED6F07011651270E23 -:1080C00004010401C86F000E0401C96F000E040111 -:1080D000CA6F000E0401CB6F0701166F020E030179 -:1080E0000301F56F0701165180D007010DC7F6FF98 -:1080F00007010EC7F7FF000EF86E0900F5CF16F75F -:108100000900F5CF17F7070100EE02F007010D5146 -:10811000E92607010E51EA22EECF18F7EDCF19F745 -:10812000070116510701182507011A6F070117519A -:108130000701192107011B6F0701070112510701F0 -:108140001A2707010701135107011B23040104012A -:10815000D85107011A1903010301F86F0401040142 -:10816000D95107011B190301F96F0A0E0701070115 -:10817000B26F000E0701B36F0DC7B0F70EC7B1F7AE -:108180000401DE0E07010701AE6F0401040E0701B2 -:10819000AF6F18EC1AF00701166F050E030103010B -:1081A000F56F070116510701166F010E0701070150 -:1081B000716F070116510701176F020E07010701C2 -:1081C000706F07011751B4EC9BF00FD00701070146 -:1081D0001151010A01E111D7030A01E10ED7010A89 -:1081E00001E133D7070A81E000D0070107011551EB -:1081F0000CD007010701152B000E070107011565BB -:1082000001D001D08AD6FE0E00D0120007013C6FCB -:10821000000E07010701356F07013C5107013C6F54 -:10822000000E07010701366F07013C51000E0701E0 -:108230000701386F000E0701396F000E07013A6F12 -:10824000000E07013B6FE7D0030E070107013665FB -:1082500001D001D001D0FBD0300E07010701375FFC -:1082600007010701356701D001D00AD0090E0701C7 -:108270000701376501D001D002D0000E49D1B7D037 -:10828000070107013551030AD8A401D001D054D009 -:10829000070107013751FE0AD8B401D001D002D03E -:1082A000000E36D1060E0701385D050E070139595B -:1082B000020E07013A59000E070107013B59D8A0E9 -:1082C00001D001D002D0000E23D1070107013651A1 -:1082D000070107013325E96E0701000E07010701B9 -:1082E0003421EA6E0701070139510A0DF3CF3CF73B -:1082F000070107013A51640DF35007013C250701BE -:1083000007013825EF6E07010701362B07013C6F87 -:10831000000E07010701356F07013C51000E0701F0 -:108320000701386F000E0701396F000E07013A6F21 -:10833000000E07013B6F6FD0070107013751FE0A9E -:10834000D8A401D001D04AD0060E0701385D050E31 -:1083500007013959020E07013A59000E07010701BA -:108360003B59D8A001D001D002D0000ED1D00701D6 -:1083700007013651070107013325E96E0701000E99 -:10838000070107013421EA6E0701070139510A0D7F -:10839000F3CF3CF7070107013A51640DF350070191 -:1083A0003C25070107013825EF6E07010701362B31 -:1083B00007013C6F000E07010701356F07013C51B3 -:1083C000000E07010701386F000E0701396F000E1C -:1083D00007013A6F000E07013B6F1DD0090E070120 -:1083E0000701376501D001D002D0000E91D00701FE -:1083F0000701352B070107013AC73BF707010701C2 -:1084000039C73AF70701070138C739F707010701EC -:10841000386B37C738F707010701315107013C6F47 -:1084200007010701325107013D6F0701314B322B24 -:108430003CC7F6FF3DC7F7FF000EF86E08000701C6 -:10844000F5CF37F70701376701D001D0FDD6070117 -:1084500007013751D8B401D001D02AD00701070154 -:1084600037512F0AD8B401D001D022D0070107011B -:1084700037510D0AD8B401D001D01AD00701070135 -:1084800037510A0AD8B401D001D012D00701070130 -:108490003751200AD8B401D001D00AD00701070112 -:1084A0003751090AD8B401D001D002D0000E30D023 -:1084B000060E0701385D050E07013959020E070146 -:1084C0003A59000E070107013B59D8A001D001D04D -:1084D00002D0000E1DD0030E070107013325E96EFF -:1084E000000E070107013421EA6E07010701395127 -:1084F0000A0DF3CF3CF7070107013A51640DF35021 -:1085000007013C25070107013825EF6E010E00D059 -:10851000120007013C6F000E07010701356F0701CC -:108520003C5107013C6F000E07010701366F070140 -:108530003C51000E07010701386F000E0701396F2B -:10854000000E07013A6F000E07013B6FE7D0030EE4 -:1085500007010701366501D001D001D0F2D0300EFD -:1085600007010701375F07010701356701D001D017 -:108570000AD0090E07010701376501D001D002D0EA -:10858000000E40D1B7D0070107013551030AD8A426 -:1085900001D001D054D0070107013751FE0AD8B4E9 -:1085A00001D001D002D0000E2DD1060E0701385D9A -:1085B000050E07013959020E07013A59000E07014D -:1085C00007013B59D8A001D001D002D0000E1AD12A -:1085D000070107013651070107013325E96E07013D -:1085E000000E070107013421EA6E07010701395126 -:1085F0000A0DF3CF3CF7070107013A51640DF35020 -:1086000007013C25070107013825EF6E0701070127 -:10861000362B07013C6F000E07010701356F07017C -:108620003C51000E07010701386F000E0701396F3A -:10863000000E07013A6F000E07013B6F6FD0070174 -:1086400007013751FE0AD8A401D001D04AD0060E46 -:108650000701385D050E07013959020E07013A5925 -:10866000000E070107013B59D8A001D001D002D06C -:10867000000EC8D007010701365107010701332555 -:10868000E96E0701000E070107013421EA6E0701B8 -:10869000070139510A0DF3CF3CF7070107013A51A1 -:1086A000640DF35007013C25070107013825EF6EE3 -:1086B00007010701362B07013C6F000E0701070178 -:1086C000356F07013C51000E07010701386F000E9E -:1086D0000701396F000E07013A6F000E07013B6F6B -:1086E0001DD0090E07010701376501D001D002D066 -:1086F000000E88D007010701352B070107013AC793 -:108700003BF70701070139C73AF70701070138C7E7 -:1087100039F707010701386B37C738F7070131C749 -:10872000E9FF070132C7EAFF07010701314B322B8E -:10873000EF5007010701376F0701376701D001D0FC -:1087400006D7070107013751D8B401D001D02AD08C -:108750000701070137512F0AD8B401D001D022D028 -:108760000701070137510D0AD8B401D001D01AD042 -:108770000701070137510A0AD8B401D001D012D03D -:10878000070107013751200AD8B401D001D00AD01F -:10879000070107013751090AD8B401D001D002D02E -:1087A000000E30D0060E0701385D050E070139595D -:1087B000020E07013A59000E070107013B59D8A0E4 -:1087C00001D001D002D0000E1DD0030E0701070119 -:1087D0003325E96E000E070107013421EA6E070117 -:1087E000070139510A0DF3CF3CF7070107013A5150 -:1087F000640DF35007013C25070107013825EF6E92 -:10880000010E00D012000701226F000E07010701C0 -:108810000F6F07012251000E07010701146F000EB0 -:108820000701156F000E0701166F000E0701176F85 -:10883000010E07010701186F000E0701196F000EE6 -:1088400007011A6F000E07011B6F07010E0E0701CB -:108850000701346F0701070E0701356F07010C0E82 -:1088600007010701326F0701070E0701336F53EC51 -:108870001CF007010E0E070107012D6F0701070EFF -:1088800007012E6F07010C0E070107012B6F07016F -:10889000070E07012C6FE1EC10F00CC712F70DC7A3 -:1088A00013F7070107010EC710F707010701116B46 -:1088B000000E070107011C6F000E07011D6F070165 -:1088C00007011D51800A800F200ED8B41C5DD8A06E -:1088D00001D001D001D059D007010E0E07010701C8 -:1088E000266F0701070E0701276F07010C0E07010E -:1088F0000701246F0701070E0701256F89EC14F0AB -:1089000007010701206F070107012051020AD8A4BF -:1089100001D001D001D0EDD0070107012051D8B41A -:1089200001D001D018D00701070118510701070134 -:108930001413070107011951070107011513070156 -:1089400007011A51070107011613070107011B51FF -:108950000701070117130701D8900701183707010E -:10896000193707011A3707011B37070107011C4B8D -:108970001D2B070107011D51800A800F200ED8B45E -:108980001C5DD8A001D001D0A7D7000E07010701B8 -:108990001E6F000E07011F6F070107011F51800A9C -:1089A000800F040ED8B41E5DD8A001D001D001D034 -:1089B0004AD007010E0E07010701266F0701070EB7 -:1089C0000701276F07010C0E07010701246F07013C -:1089D000070E0701256F89EC14F007010701216FCD -:1089E000070107012151020AD8A401D001D001D00A -:1089F00080D0070107012151D8B401D001D013D094 -:108A00001EC722F7010E0701236F0701222B03D097 -:108A1000D890070123370701222FFAD707012351E6 -:108A2000070107010F13070107011E4B1F2B070149 -:108A300007011F51800A800F040ED8B41E5DD8A014 -:108A400001D001D0B6D7070107010F510C0AD8B4E5 -:108A500001D001D001D04DD075EC21F0A00E07015E -:108A600007012D6FFF0E07012E6FBB0E07010701D7 -:108A70002B6FFF0E07012C6F51EC22F07F0E0701C8 -:108A800007012D6FFF0E07012E6F6D0E0701070105 -:108A90002B6FFF0E07012C6F51EC22F0F00E070137 -:108AA00007012D6FFE0E07012E6FB50E070107019E -:108AB0002B6FFF0E07012C6F51EC22F014C72DF71E -:108AC00015C72EF716C72FF717C730F7D50E0701B2 -:108AD00007012B6FFF0E07012C6FC8EC21F0070177 -:108AE000226F010E070107012B6F07012251E1ECF4 -:108AF00020F01200C2CF29F7C0CF2AF7D5CF2BF72D -:108B0000D6CF2DF7D7CF2CF7010EC26E07012E6FEF -:108B10003F0EC06E07012E5107012E6F880ED56ED5 -:108B200007012E5107012E6F000E070107011A6F72 -:108B300007012E51000E07010701216F000E0701EA -:108B4000226F000E0701236F000E0701246F000E35 -:108B5000070107011D6F000E07011E6F1FEC15F0C6 -:108B60000701070172C725F70701070173C726F739 -:108B70000701000E070126BFFF0E0701276F07013F -:108B8000286F000ED76E000ED66EC282040000D091 -:108B9000C2B201D001D0FCD7D6CF1FF7D7CF20F774 -:108BA0001FEC15F072C71BF773C71CF7070107010D -:108BB0001F51070107012127070107012051070164 -:108BC00007012223000E070107012323000E0701DE -:108BD000070124231A0E0701215DF20E0701225915 -:108BE0009E0E07012359000E070107012459D8A042 -:108BF00001D001D083D01FEC15F00701070172519D -:108C000007012E6F07010701735107012F6F07013D -:108C1000306B0701316B1E0ED89007012E372F37AE -:108C200030373137E82EF8D71FEC15F0070172C73F -:108C300032F7070173C733F7000E070133BFFF0E8A -:108C4000346F356F0F0ED890070132373337343712 -:108C50003537E82EF8D71FEC15F0070172C736F745 -:108C6000070173C737F7000E070137BFFF0E386FD4 -:108C7000396F070132510701361107013A6F0701B9 -:108C800033510701371107013B6F070134510701C9 -:108C9000381107013C6F07013551070139110701F0 -:108CA0003D6F07012E5107013A1107013E6F070181 -:108CB0002F5107013B1107013F6F07013051070199 -:108CC0003C110701406F0701315107013D110701B8 -:108CD000416F07013E5107010701251B07013F5165 -:108CE00007010701261B0701405107010701271B48 -:108CF0000701415107010701281B58D0070107014F -:108D00002051070107011E1906E1070107011F5144 -:108D1000070107011D19D8A401D001D001D045D009 -:108D200007011DC72EF707011EC72FF7070107010F -:108D30001F5107012E5F07010701205107012F5B1B -:108D4000070107011B5107012E2507010701746F59 -:108D5000070107011C5107012F210701756F7DECE9 -:108D600020F01FC71DF720C71EF70701D890070185 -:108D700025370701263707012737070128371FEC5A -:108D800015F0070107017351800A400F000ED8B497 -:108D9000725DD8A001D001D003D007010701258161 -:108DA000070107011A3F01D001D0EBD629C7C2FF46 -:108DB0002AC7C0FF2CC7D7FF2DC7D6FF2BC7D5FFAB -:108DC00025C716F726C717F727C718F728C719F7B3 -:108DD00000D01200070107010C51D8B401D001D016 -:108DE00005D0030E070107010D2704D0030E07016C -:108DF00007010D5F3ED10B0E070107010D6501D084 -:108E000001D009D0170E070107010D6101D001D073 -:108E100002D0032A39D1030E070107010D6501D0E5 -:108E200001D01FD00D0E070107010D6101D001D047 -:108E300018D0190E036401D001D00DD007010E6FB8 -:108E4000010E086E07010E51000E00010001F56FC2 -:108E5000000E0001F66F07010E6F000E036E070192 -:108E60000E5112D10DC711F70CC710F7B3EC15F066 -:108E700010C7F7F011C7F8F000010001F829FE0E45 -:108E8000D8B4F719D8A401D001D003D0F4EC20F065 -:108E9000FBD000010001F729D8B4F829D8A401D0EB -:108EA00001D001D0F1D000010001F651F511D8A494 -:108EB00001D001D009D000010001F75100010001EB -:108EC000F66F0001F56B49D000010001F751000178 -:108ED0000001F51300010001F85100010001F61333 -:108EE00011D007010E6F060E0A6E07010E5129D030 -:108EF00007010E6F080E0A6E07010E5122D0F4EC26 -:108F000020F0C2D00001F5C00EF70001F6C00FF747 -:108F10000FD007010E514D0AEBE0F1D707010E51BA -:108F20002D0AE6E0ECD707010E514C0ADAE0E7D74C -:108F300007010F510A0AEDE0100AF0E0F00AF3E031 -:108F4000DED707010E6F020E086E07010E510701F2 -:108F50000E6F000E036E07010E5196D00DC711F76C -:108F60000CC710F7B3EC15F010C7F7F011C7F8F005 -:108F700000010001F829FE0ED8B4F719D8A401D0D9 -:108F800001D003D0F4EC20F07FD000010001F729DC -:108F9000D8B4F829D8A401D001D001D075D00001EF -:108FA000C70E0324E96EEA6A0001000EEA220001FE -:108FB000F7C0EFFF032A0A060A6601D001D051D795 -:108FC000F4EC20F075EC21F0A00E070107012D6FE5 -:108FD000FF0E07012E6FBB0E070107012B6FFF0E5F -:108FE00007012C6F51EC22F0AE0E070107012D6F27 -:108FF000FF0E07012E6F6D0E070107012B6FFF0E8D -:1090000007012C6F51EC22F000010701F5C02DF78C -:1090100000010701F6C02EF7070107012F6B0701BA -:10902000306BB50E070107012B6FFF0E07012C6F88 -:10903000C8EC21F003C020F70001C70E07010701AB -:109040001E6F0001000E07011F6FD50E07010701FB -:109050001C6FFF0E07011D6F00EC22F007010E6F61 -:10906000010E070107012B6F07010E51E1EC20F003 -:109070000BD00850000A01E1BED6010A01E1F2D688 -:10908000030A01E16BD700D01200C00E07010701EF -:10909000126F100E0701136F00010001FE51FD1148 -:1090A000D8A401D001D019D07AECC5F0FF0E070189 -:1090B000070116150701146F070E070107011715A1 -:1090C0000701156F000E0701142500010001FD6F57 -:1090D000040E070115210001FE6F3C0E0701070178 -:1090E0005A6F000E07015B6F000E07010701586FF2 -:1090F000000E0701596F0601000E07010701566FA8 -:109100000601060E0701576F08EC1FF00701146FE8 -:10911000000E07010701096F070114510701146FC1 -:10912000000E070107010B6F07011451000E070124 -:1091300007010B6501D001D001D0EDD00BC760F75E -:1091400084EC0EF0070107010B51060DF3CF14F765 -:10915000010E07011427AF0E07011425F66EF76AFA -:10916000FE0EF722F86A000EF82208000701F5CF7C -:109170000AF7070107010B51060DF3CF14F7020E92 -:1091800007011427AF0E07011425F66EF76AFE0ECD -:10919000F722F86A000EF82209000701F5CF10F750 -:1091A0000A000701F5CF11F7070107010B51060D62 -:1091B000F3CF14F7040E07011427AF0E070114258F -:1091C000F66EF76AFE0EF722F86A000EF822090022 -:1091D0000701F5CF0EF70A000701F5CF0FF731D0E1 -:1091E00012C70CF713C70DF7070110C714F70701D3 -:1091F00011C715F7070107010E51070114270701D1 -:1092000007010F5107011523290E07011427000E2E -:1092100015230701145107010701122707011551F2 -:1092200007010701132300D0FD0E07010701125D9E -:109230001F0E07011359D8B001D001D0F5D707D0C0 -:10924000FFD7070107010A51000ACAE0F9D70AC788 -:10925000FAF3270E070107010C2503010301DF6F55 -:10926000000E070107010D210301E06F0301DFC3B9 -:1092700014F70301E0C315F70701070110510701B7 -:10928000142707010701115107011523010E0701DA -:10929000142503010301E16F000E070115210301ED -:1092A000E26F070107010E5103010301E1250301EC -:1092B0000301E36F070107010F5103010301E221DD -:1092C0000301E46F0701146F0D0E03010301F56F35 -:1092D000070114510301F69777ECE7F00701070146 -:1092E0000B51060DAF0EF324F66EF76AFE0EF72251 -:1092F000F86A000EF82208000401F5CFEEF417EC2E -:109300000EF0070107010B2B000E070107010B658B -:1093100001D001D013D712000701070143690101F1 -:10932000590E07010701456F0101010E0701466F44 -:109330000701476F000E07010701446F07014751FE -:10934000040E07010701446501D001D001D0E8D027 -:10935000020E070107013D25E96E000E0701070116 -:109360003E21EA6E0C0E070107014525E16E000E55 -:10937000070107014621E26EE652EE52ED50E51874 -:10938000EFCFE8FFD8B4E718D8A401D001D0B7D008 -:109390003DC7E9FF3EC7EAFF0A0E07010701452561 -:1093A000E16E000E070107014621E26EE652EE5221 -:1093B000ED50E518EFCFE8FFD8B4E718D8A401D0F6 -:1093C00001D09BD03FC7E9FF40C7EAFFEECF47F788 -:1093D000EECF48F7EECF49F7EECF4AF745C7E9FFA2 -:1093E00046C7EAFFEECF4BF7EECF4CF7EECF4DF787 -:1093F000EECF4EF707014A5107014E190EE1070162 -:10940000495107014D1909E10701485107014C195C -:1094100004E10701475107014B19D8B401D001D02D -:1094200068D041C7E9FF42C7EAFFEECF47F7EECF6A -:1094300048F7EECF49F7EECF4AF707014729D8B4EE -:109440004829D8B44929D8B44A29D8B401D001D080 -:1094500050D041C7E9FF42C7EAFFEECF47F7EECF52 -:1094600048F7EECF49F7EECF4AF7060140C64BF773 -:10947000060141C64CF7060142C64DF7060143C638 -:109480004EF707014B1F4C1F4D1F4E1F06010601D3 -:109490003C5107014B1107014F6F060106013D5179 -:1094A00007014C110701506F060106013E510701EB -:1094B0004D110701516F060106013F5107014E1181 -:1094C0000701526F07014A51070152190EE10701C6 -:1094D00049510701511909E1070148510701501984 -:1094E00004E10701475107014F19D8A401D001D069 -:1094F00004D007010701445151D044C743F70E0E71 -:10950000070107014527000E070146230701070150 -:10951000442B040E07010701446501D001D018D780 -:10952000070107014329D8B401D001D033D0070186 -:10953000070143510E0D0101590EF32407010701E4 -:10954000456F0701466B0101010E070146230A0E14 -:1095500007010701B26F000E0701B36F3FC7B0F7F5 -:1095600040C7B1F745C7AEF746C7AFF718EC1AF0DA -:109570003DC7E9FF3EC7EAFF0A0E0701070145257F -:10958000E16E000E070107014621E26EEECFE6FF15 -:10959000EDCFE5FF07010701435100D0120007019D -:1095A0000B6F000E07010701086F07010B51ABD0CD -:1095B000DBC634F7FEC532F7FFC533F709EC1DF003 -:1095C000D8A001D001D02AD0960E056401D001D0D8 -:1095D00006D0FEC5D9F6FFC5DAF6DBC6DCF60550C7 -:1095E000D8B401D001D00CD005C00DF707010B6F26 -:1095F000000E070107010C6F07010B51EAECC6F0E2 -:10960000062A07010B6F000E056E07010B510701BB -:109610000B6F000E016E07010B5122D0056601D0C1 -:1096200001D006D0FEC5D7F6FFC5D8F6DBC604F0DC -:109630000650D8B401D001D00CD006C00DF70701F8 -:109640000B6F010E070107010C6F07010B51EAECCC -:10965000C6F0052A07010B6F000E066E07010B51BD -:109660000601D890DB3306010601DB6701D001D08B -:109670001CD007010B6F800E06010601DB6F07018E -:109680000B5105010501FE4BFF2B05010501FF51A3 -:10969000020AFE11D8A401D001D007D0000E0501A6 -:1096A0000501FE6F000E0501FF6F05010501FF5169 -:1096B00006010601DA1906E105010501FE51060160 -:1096C0000601D919D8A401D001D00ED00601060197 -:1096D000DB5106010601DC6301D001D005D0060193 -:1096E0000601D9690601DA690550960AD8A401D0A5 -:1096F00001D009D007010B6F010E07010701086FA8 -:1097000007010B510DD0185005010501FF1904E1A7 -:10971000175005010501FE19D8A401D001D048D782 -:1097200007010701086701D001D001D078D00150AE -:10973000D8B401D001D001D072D0D7C60EF7D8C6A8 -:109740000FF7D9C60CF7DAC60DF753EC12F00CC7B9 -:1097500009F70DC70AF7070107010ABF01D001D0B9 -:109760000DD0070107010A51800A800F320ED8B4CC -:10977000095DD8B001D001D001D051D00701070157 -:109780000A51800A800F9E0ED8B4095DD8A001D07E -:1097900001D00CD0070107010A51800A800FA30EE7 -:1097A000D8B4095DD8A001D001D000D004C00EF714 -:1097B000D7C60CF7D8C60DF74AECCDF004C00EF7AB -:1097C000D7C60CF7D8C60DF7D5ECD0F004C00EF70D -:1097D000D7C60CF7D8C60DF71CECDAF004C00EF7AC -:1097E000D7C60CF7D8C60DF729ECD4F004C00EF795 -:1097F000D7C60CF7D8C60DF703ECC4F004C00EF7BB -:10980000D7C60CF7D8C60DF792ECBAF0F4EC20F0FE -:1098100007010B6F010E016E07010B5100D0120002 -:10982000000E07010701396F000E07013A6F32C7BA -:1098300060F784EC0EF032C741F747EC0AF041C7FD -:1098400037F742C738F70701070138513711D8A455 -:1098500001D001D00CD032C741F7DEEC1CF0000E75 -:1098600007010701326F000E0701336F12D137C7AE -:109870003BF738C73CF707010701375107010701DC -:10988000355D070107013851070107013659D8B086 -:1098900001D001D004D035C73BF736C73CF70301F0 -:1098A0000301F7B101D001D02ED0030103EEE1F0A6 -:1098B000EECF3DF7EDCF3EF703010301DF51070186 -:1098C0003D5F03010301E05107013E5BD8900701B2 -:1098D0003E310701406F07013D3107013F6F07012E -:1098E0000701375107013F5D0701070138510701A3 -:1098F0004059D8A001D001D006D032C741F7DEECE4 -:109900001CF00301F781030103EEE5F0EECF3DF714 -:10991000EDCF3EF7070107013B5107013D27070146 -:1099200007013C5107013E2303010301E1510701F7 -:109930003D5D03010301E25107013E59D8A001D06A -:1099400001D045D003010301E55103010301E15DAD -:1099500007010701396F03010301E6510301030108 -:10996000E25907013A6F39C7ACF73AC7ADF70701BB -:109970003D6F010E07010701AB6F07013D5133C772 -:10998000A9F734C7AAF7FAC3A8F7E5C3A6F7E6C351 -:10999000A7F74AEC0CF0070107013951070107014D -:1099A0003327070107013A51070107013423070153 -:1099B00007013951070107013B5F070107013A51D0 -:1099C000070107013C5BDFC3E5F3E0C3E6F33BC7F8 -:1099D000ACF73CC7ADF707013D6F010E070107016A -:1099E000AB6F07013D5133C7A9F734C7AAF7FAC3D4 -:1099F000A8F7E5C3A6F7E6C3A7F74AEC0CF0070102 -:109A000007013B5103010301E527070107013C5111 -:109A100003010301E623070107013751070107018D -:109A2000355D070107013851070107013659D8A0F4 -:109A300001D001D005D032C741F7DEEC1CF017D0C1 -:109A400003010301F6BB01D001D011D00301F68B55 -:109A500055EC20F0060E07010701702503010301F4 -:109A6000F16F000E0701070171210301F26F070179 -:109A700007013951070107013B2507010701326F33 -:109A8000070107013A51070107013C210701336F24 -:109A900000D01200000E070107010F6F000E070132 -:109AA000106F000E0701116F000E0701126F010EFB -:109AB00007010701136F000E0701146F000E070165 -:109AC000156F000E0701166F07010E0E0701070143 -:109AD000346F0701070E0701356F07010C0E0701F0 -:109AE0000701326F0701070E0701336F53EC1CF0BB -:109AF00007010E0E070107012D6F0701070E070171 -:109B00002E6F07010C0E070107012B6F0701070ECF -:109B100007012C6FE1EC10F0000E07010701176F31 -:109B2000000E0701186F070107011851800A800F06 -:109B3000200ED8B4175DD8A001D001D001D0A1D09B -:109B400007010E0E070107012D6F0701070E070120 -:109B50002E6F07010C0E070107012B6F0701070E7F -:109B600007012C6FE1EC10F007010701196F0701E5 -:109B70000E0E070107012D6F0701070E07012E6F5B -:109B800007010C0E070107012B6F0701070E0701E4 -:109B90002C6FE1EC10F0070107011A6F07010E0EA0 -:109BA000070107012D6F0701070E07012E6F07013F -:109BB0000C0E070107012B6F0701070E07012C6F21 -:109BC000E1EC10F0070107011B6F07010E0E070102 -:109BD00007012D6F0701070E07012E6F07010C0EFD -:109BE000070107012B6F0701070E07012C6FE1EC3E -:109BF00010F0070107011C6F1BD029D007010701D6 -:109C00001351070107010F13070107011451070141 -:109C1000070110130701070115510701070111136F -:109C200007010701165107010701121310D067D071 -:109C30001CC721F71BC720F71AC71FF719C71EF744 -:109C4000ACEC18F0000AD9E0010AD8E0F0D707011F -:109C5000D89007011337070114370701153707019B -:109C6000163707010701174B182B07010701185179 -:109C7000800A800F200ED8B4175DD8A001D001D083 -:109C80005FD775EC21F0900E070107012D6FFF0ED5 -:109C900007012E6F6D0E070107012B6FFF0E0701E5 -:109CA0002C6F51EC22F03F0E070107012D6FFF0EC4 -:109CB00007012E6FB50E070107012B6FFF0E07017D -:109CC0002C6F51EC22F00FC72DF710C72EF711C7DC -:109CD0002FF712C730F7D50E070107012B6FFF0EC4 -:109CE00007012C6FC8EC21F007011D6F020E070160 -:109CF00007012B6F07011D51E1EC20F000D012008D -:109D00000C6601D001D03FD00DC748F7D0EC1DF054 -:109D1000030E07010701176F000E0701186FE30E0E -:109D200007010701156FFF0E0701166F0401000EF2 -:109D300007010701136F0401040E0701146FFAEC09 -:109D400011F0070114511311D8A401D001D007D08C -:109D500007010F6F010E0C6E07010F5113D00401A4 -:109D600004010251D8B401D001D00CD001C400F4D8 -:109D700002C401F407010F6F000E04010401026F19 -:109D800007010F51E9D00C04D8A401D001D092D022 -:109D90000DC748F7D0EC1DF00401000E07010701C4 -:109DA0003C6F0401040E07013D6F1FEC17F0070123 -:109DB0003C512B0A3D11D8A401D001D07AD0070123 -:109DC0000F6F030E070107010E6F07010F512A0ED7 -:109DD000070107010E6501D001D001D05CD0020E51 -:109DE00007010701156F000E0701166FFD0E070131 -:109DF00007010E2507010701136F0701146BFF0E02 -:109E0000070114236BEC07F0380E07010701132537 -:109E1000E96EEA6A000EEA2207010EC70FF7070192 -:109E2000106B010E07010F27000E10230401000E16 -:109E300007010F25E16E0401040E07011021E26EF7 -:109E4000E750070107013F6FFDEC12F00701116FAA -:109E50000401000E070107010E25E16EE26A04010C -:109E6000040EE222E750070107013F6FFDEC12F0FC -:109E70000701126F07011239F00B07011111EF6E84 -:109E8000020E070107010E272A0E070107010E65C2 -:109E900001D001D0A4D7F6EC1DF007010F6F020E20 -:109EA0000C6E07010F5107010F6F000E2E6E070198 -:109EB0000F5152D00C50020AD8A401D001D01AD0B0 -:109EC000070107010D513A0AD8A401D001D009D0E9 -:109ED000F6EC1DF007010F6F030E0C6E07010F511A -:109EE00008D02E3AF00E2E160DC73FF7FDEC12F0FB -:109EF0002E1232D00C50030AD8A401D001D01AD0AF -:109F00000DC748F7D0EC1DF02E062E6601D001D00B -:109F100010D067EC19F00009D8B401D001D007D0F7 -:109F200007010F6F040E0C6E07010F5102D0F6EC03 -:109F30001DF012D00C50040AD8A401D001D00CD0CE -:109F4000F6EC1DF00DC748F7D0EC1DF007010F6FC0 -:109F5000010E0C6E07010F511200000E07010701E0 -:109F6000396F000E07013A6F32C760F784EC0EF0CC -:109F700032C741F747EC0AF041C737F742C738F715 -:109F80000701070138513711D8A401D001D00CD0F6 -:109F900032C741F7DEEC1CF0000E07010701326FFB -:109FA000000E0701336F00D103010301F7B101D0A7 -:109FB00001D02ED0030103EEE1F0EECF3DF7EDCF5F -:109FC0003EF703010301DF5107013D5F0301030178 -:109FD000E05107013E5BD89007013E310701406F19 -:109FE00007013D3107013F6F0701070137510701A5 -:109FF0003F5D07010701385107014059D8A001D042 -:10A0000001D006D032C741F7DEEC1CF00301F78126 -:10A0100037C73BF738C73CF707010701375107013E -:10A020000701355D0701070138510701070136595E -:10A03000D8B001D001D004D035C73BF736C73CF7C4 -:10A04000030103EEE5F0EECF3DF7EDCF3EF707015C -:10A0500007013B5107013D27070107013C5107015B -:10A060003E2303010301E15107013D5D03010301AB -:10A07000E25107013E59D8A001D001D03BD00301E5 -:10A080000301E55103010301E15D07010701396F98 -:10A0900003010301E65103010301E25907013A6F8D -:10A0A00039C746F73AC747F733C744F734C745F7C8 -:10A0B000FAC343F7E5C341F7E6C342F7CEEC0AF033 -:10A0C000070107013951070107013327000E070176 -:10A0D00007013423070107013951070107013B5FDD -:10A0E000070107013A51070107013C5BDFC3E5F3B4 -:10A0F000E0C3E6F33BC746F73CC747F733C744F72F -:10A1000034C745F7FAC343F7E5C341F7E6C342F75F -:10A11000CEEC0AF0070107013B5103010301E527DB -:10A12000070107013C5103010301E6230701070171 -:10A13000375107010701355D070107013851070154 -:10A1400007013659D8A001D001D005D032C741F758 -:10A15000DEEC1CF017D003010301F6BB01D001D0E7 -:10A1600011D00301F68B55EC20F0060E0701070114 -:10A17000702503010301F16F000E07010701712132 -:10A180000301F26F070107013951070107013B2560 -:10A1900007010701326F070107013A510701070163 -:10A1A0003C210701336F00D01200000E07010701A8 -:10A1B000136F000E0701146F000E0701156F000EDC -:10A1C0000701166F010E070107010F6F000E07014F -:10A1D000106F000E0701116F000E0701126F0701CB -:10A1E0000E0E07010701346F0701070E0701356FD7 -:10A1F00007010C0E07010701326F0701070E070167 -:10A20000336F53EC1CF007010E0E070107012D6F91 -:10A210000701070E07012E6F07010C0E070107014A -:10A220002B6F0701070E07012C6FE1EC10F0000EF9 -:10A2300007010701176F000E0701186F07010701DB -:10A240001851800A800F0C0ED8B4175DD8A001D029 -:10A2500001D001D08ED007010E0E070107012D6F2E -:10A260000701070E07012E6F07010C0E07010701FA -:10A270002B6F0701070E07012C6FE1EC10F00701AF -:10A280000701196F07010E0E070107012D6F070166 -:10A29000070E07012E6F07010C0E070107012B6F38 -:10A2A0000701070E07012C6FE1EC10F00701070111 -:10A2B0001A6F07010E0E070107012D6F0701070E28 -:10A2C00007012E6F07010C0E070107012B6F070115 -:10A2D000070E07012C6FE1EC10F0070107011B6F5F -:10A2E00007010E0E070107012D6F0701070E070179 -:10A2F0002E6F07010C0E070107012B6F0701070ED8 -:10A3000007012C6FE1EC10F0070107011C6F07013A -:10A31000D8900701133707011437070115370701D4 -:10A32000163706D016D007010701138112D05FD06F -:10A330001CC721F71BC720F71AC71FF719C71EF73D -:10A340006DEC18F0000AEEE0010AEDE0030AEFE020 -:10A3500000D007010701174B182B070107011851FF -:10A36000800A800F0C0ED8B4175DD8A001D001D0A0 -:10A3700072D775EC21F0900E070107012D6FFF0ECB -:10A3800007012E6F6D0E070107012B6FFF0E0701EE -:10A390002C6F51EC22F04C0E070107012D6FFF0EC0 -:10A3A00007012E6FB50E070107012B6FFF0E070186 -:10A3B0002C6F51EC22F013C72DF714C72EF715C7D9 -:10A3C0002FF716C730F7D50E070107012B6FFF0EC9 -:10A3D00007012C6FC8EC21F007011D6F020E070169 -:10A3E00007012B6F07011D51E1EC20F000D0120096 -:10A3F0000701BA6F000E07010701B56F0701BA51D7 -:10A400000701BA6F000E07010701B46F0701BA51C7 -:10A4100007010701AE29D8B4AF29D8A401D001D0D3 -:10A420000CD00701BA6F010E07010701B56F0701D4 -:10A43000BA51E2CEAEF7E3CEAFF707010701B0297C -:10A44000D8B4B129D8A401D001D00CD00701BA6F7B -:10A45000010E07010701B46F0701BA51E0CEB0F752 -:10A46000E1CEB1F7020E07010701B25D000E070150 -:10A47000B359D8B001D001D03AD0E0CEB6F7E1CE92 -:10A48000B7F7E2CEB8F7E3CEB9F7B0C7E0FEB1C791 -:10A49000E1FEAEC7E2FEAFC7E3FE07D0C3EC22F099 -:10A4A00007010701C26FBEEC22F007010701B207E6 -:10A4B000D8A0B3070701B229D8B4B329D8A401D0D2 -:10A4C00001D0ECD707010701B46701D001D004D057 -:10A4D000B6C7E0FEB7C7E1FE07010701B56701D0C7 -:10A4E00001D004D0B8C7E2FEB9C7E3FE99D0070196 -:10A4F0000701B551D8B401D001D015D0070107012B -:10A50000B25107010701AE2507010701B86F070126 -:10A510000701B35107010701AF210701B96FB8C7A0 -:10A52000E2FEB9C7E3FEFF0E07010701B0250701F0 -:10A53000BA6FFF0E07010701B1210701BB6F0701C9 -:10A54000BA5107010701B2270701BB5107010701F3 -:10A55000B32300D00E010E01DFBB01D001D0FAD72A -:10A56000B0C7F0FEB1C7F1FEAEC7F4FEAFC7F5FE4F -:10A57000CE0E07010701B05D0A0E0701B159D8B030 -:10A5800001D001D012D0CE0E07010701B25D0A0E34 -:10A590000701B359D8A001D001D007D00701CE0ED2 -:10A5A0000701B25F0A0E0701B35BB2C7F2FEB3C781 -:10A5B000F3FE0E01DF990E01DF8B00D00E010E01BC -:10A5C000DFBB01D001D0FAD707010701B451D8B4DD -:10A5D00001D001D025D007010701B24BB32BCE0E1D -:10A5E00007010701B05D0A0E0701B159D8B001D0CB -:10A5F00001D012D0CE0E07010701B25D0A0E07018D -:10A60000B359D8A001D001D007D00701CE0E070161 -:10A61000B25F0A0E0701B35BB2C7E0FEB3C7E1FE4B -:10A620001200000E070107010D6F000E07010E6FEB -:10A63000E1C641F747EC0AF07D0E07010701415DD5 -:10A64000000E07014259D8B001D001D001D000D18D -:10A65000120E070107015A6F000E07015B6F000E13 -:10A6600007010701586F000E0701596F4C0E0701D3 -:10A670000701566F000E0701576F08EC1FF0070126 -:10A6800007010E51800A800F060ED8B40D5DD8A0C8 -:10A6900001D001D001D04FD00701D89007010D356E -:10A6A00007010F6F4C0E07010F25E96EEA6A000ED5 -:10A6B000EA2200015E0E070107010D25E16EE26A44 -:10A6C0000001000EE222E750070107013C6F59EC40 -:10A6D0001DF0EF6E0701D89007010D3507010F6FD0 -:10A6E000010E07010F274C0E07010F25E96EEA6ADC -:10A6F000000EEA2200015E0E070107010D25E16E42 -:10A70000E26A0001000EE222E75007010701486FEC -:10A7100031EC1DF0EF6E070107010D4B0E2B070109 -:10A7200007010E51800A800F060ED8B40D5DD8A027 -:10A7300001D001D0B1D7F6EC1DF0760E070107016C -:10A74000376FFF0E0701386F3DEC14F067EC22F015 -:10A75000B70E07010701316FFE0E0701326FEB0ED6 -:10A76000070107012F6FFF0E0701306FF3EC21F097 -:10A770004C0E07010701316F000E0701326FE70E23 -:10A78000070107012F6FFF0E0701306FF3EC21F077 -:10A79000640E07010F6F000E106F0FC731F710C75F -:10A7A00032F7A70E070107012F6FFF0E0701306F69 -:10A7B000F3EC21F0D00E07010701316FFF0E070106 -:10A7C000326FCB0E070107012F6FFF0E0701306FAD -:10A7D000F3EC21F046EC22F067EC22F0020E0701C8 -:10A7E0000701336F000E0701346F000E0701356F4C -:10A7F000000E0701366F6D0E07010701316FFF0E66 -:10A800000701326F87EC21F0FA0E07010701316F63 -:10A81000FF0E0701326F980E070107012F6FFF0E21 -:10A820000701306FF3EC21F0240E07010701316FAF -:10A83000FF0E0701326FF30E070107012F6FFF0EA6 -:10A840000701306FF3EC21F046EC22F092ECDDF0E2 -:10A850001200000E070107010F6F000E0701106FB5 -:10A86000000E0701116F000E0701126F010E0701A4 -:10A870000701136F000E0701146F000E0701156F1B -:10A88000000E0701166F07010E0E07010701346F56 -:10A890000701070E0701356F07010C0E07010701BD -:10A8A000326F0701070E0701336F53EC1CF0000EE7 -:10A8B00007010701176F000E0701186F0701070155 -:10A8C0001851800A800F180ED8B4175DD8A001D097 -:10A8D00001D001D0A1D007010E0E070107012D6F95 -:10A8E0000701070E07012E6F07010C0E0701070174 -:10A8F0002B6F0701070E07012C6FE1EC10F0070129 -:10A900000701196F07010E0E070107012D6F0701DF -:10A91000070E07012E6F07010C0E070107012B6FB1 -:10A920000701070E07012C6FE1EC10F0070107018A -:10A930001A6F07010E0E070107012D6F0701070EA1 -:10A9400007012E6F07010C0E070107012B6F07018E -:10A95000070E07012C6FE1EC10F0070107011B6FD8 -:10A9600007010E0E070107012D6F0701070E0701F2 -:10A970002E6F07010C0E070107012B6F0701070E51 -:10A9800007012C6FE1EC10F0070107011C6F1BD0D1 -:10A9900029D0070107011351070107010F13070110 -:10A9A0000701145107010701101307010701155191 -:10A9B00007010701111307010701165107010701DC -:10A9C000121310D057D01CC721F71BC720F71AC786 -:10A9D0001FF719C71EF7EBEC18F0000AD9E0010ABF -:10A9E000D8E0F0D70701D8900701133707011437D3 -:10A9F000070115370701163707010701174B182BF9 -:10AA0000070107011851800A800F180ED8B4175D8E -:10AA1000D8A001D001D05FD775EC21F0320E07012C -:10AA200007012D6FFF0E07012E6F6D0E0701070145 -:10AA30002B6FFF0E07012C6F51EC22F00FC72DF783 -:10AA400010C72EF711C72FF712C730F7D50E070121 -:10AA500007012B6FFF0E07012C6FC8EC21F00701D7 -:10AA60001D6F020E070107012B6F07011D51E1EC5D -:10AA700020F000D01200F5D05F0E07010701506FE3 -:10AA8000760E0701516F000E070107014E6F000E91 -:10AA900007014F6F5F0E070107014C6F760E07012C -:10AAA0004D6F9EECE1F0306E3028D8A401D001D07B -:10AAB00001D0E5D00B2AE3D030C04CF7F2EC1BF00C -:10AAC00007014D514C11D8A401D001D001D0D7D0ED -:10AAD0000701080E070107014D6F0701070E070167 -:10AAE0004E6F86EC1EF051EC21F007010701085172 -:10AAF000440AD8B401D001D001D0C1D00B2A0A0E2B -:10AB000007010701B26F000E0701B36F0001BD0E10 -:10AB100007010701B06F0001000E0701B16F30504F -:10AB20000E0D0101590EF32407010701AE6F070155 -:10AB3000AF6B0101010E0701AF2318EC1AF030C012 -:10AB40004CF750EC1AF007014D514C11D8A401D02C -:10AB500001D001D094D0160E070107010A6FFF0E35 -:10AB600007010B6F63EC21F00701096F000E07016D -:10AB70000701086F07010951050E07010701086564 -:10AB800001D001D001D03CD008C709F72D0E070134 -:10AB9000092706013C0E07010925E96EEA6A06014C -:10ABA000060EEA22EF50070107013C6F59EC1DF039 -:10ABB00007010701536F63EC1FF008C709F72D0E5B -:10ABC0000701092706013C0E07010925E96EEA6A1B -:10ABD0000601060EEA22EF5007010701486F31EC2B -:10ABE0001DF007010701536F63EC1FF00701070118 -:10ABF000082B050E07010701086501D001D0C4D755 -:10AC00000701096F3A0E07010701536F0701095148 -:10AC100063EC1FF00001640E070107010A6F0001D9 -:10AC2000000E07010B6F2DEC21F00701096F3A0EA2 -:10AC300007010701536F0701095163EC1FF0FA0E7A -:10AC4000070107010A6FFF0E07010B6F63EC21F08C -:10AC5000BCEC09F00701096F010E0B6E07010951E9 -:10AC60000ED00B50000A01E107D7010A01E124D7F9 -:10AC7000030A01E164D7010A01E11DD700D01200E7 -:10AC8000A2C7E9FFA3C7EAFF0701EECFBEF707019E -:10AC9000EDCFBFF7B8EC21F0A2C7E9FFA3C7EAFFE9 -:10ACA0000701BEC7EEFF0701BFC7EDFF020E070198 -:10ACB0000701A225E96E000E07010701A321EA6E34 -:10ACC0000701EECFBEF70701EDCFBFF7B8EC21F0DB -:10ACD000020E07010701A225E96E000E0701070118 -:10ACE000A321EA6E0701BEC7EEFF0701BFC7EDFF54 -:10ACF000040E07010701A225E96E000E07010701F6 -:10AD0000A321EA6E0701EECFA4F70701EECFA5F766 -:10AD10000701EECFA6F70701EECFA7F7B0EC1CF0C6 -:10AD2000040E07010701A225E96E000E07010701C5 -:10AD3000A321EA6E0701A4C7EEFF0701A5C7EEFF36 -:10AD40000701A6C7EEFF0701A7C7EDFFED52ED52C1 -:10AD5000080E07010701A225E96E000E0701070191 -:10AD6000A321EA6E0701EECFA4F70701EECFA5F706 -:10AD70000701EECFA6F70701EECFA7F7B0EC1CF066 -:10AD8000080E07010701A225E96E000E0701070161 -:10AD9000A321EA6E0701A4C7EEFF0701A5C7EEFFD6 -:10ADA0000701A6C7EEFF0701A7C7EDFFED52ED5261 -:10ADB0000E0E07010701A225E96E000E070107012B -:10ADC000A321EA6E0701EECFBEF70701EDCFBFF773 -:10ADD000B8EC21F00E0E07010701A225E96E000E66 -:10ADE00007010701A321EA6E0701BEC7EEFF0701B5 -:10ADF000BFC7EDFF100E07010701A225E96E000E87 -:10AE000007010701A321EA6E0701EECFBEF7070194 -:10AE1000EDCFBFF7B8EC21F0100E07010701A22516 -:10AE2000E96E000E07010701A321EA6E0701BEC704 -:10AE3000EEFF0701BFC7EDFF120E07010701A225B4 -:10AE4000E96E000E07010701A321EA6E0701EECFAC -:10AE5000BEF70701EDCFBFF7B8EC21F0120E0701E6 -:10AE60000701A225E96E000E07010701A321EA6E82 -:10AE70000701BEC7EEFF0701BFC7EDFF12000701C4 -:10AE80002A6F0B0E07010701226F07012A510701E4 -:10AE90002A6F0A0E07010701236F07012A5116ECDA -:10AEA00020F00009D8A401D001D001D0DFD0FC0EE1 -:10AEB000070107012B6FFF0E07012C6FEBEC0EF063 -:10AEC0000009D8B401D001D008D0AAEC0DF00701D8 -:10AED0000701325107010701226FF60E0701070132 -:10AEE0002B6FFF0E07012C6FEBEC0EF00009D8B4AE -:10AEF00001D001D008D0AAEC0DF0070107013251B2 -:10AF000007010701236FF80E070107012B6FFF0EE2 -:10AF100007012C6FEBEC0EF00009D8A401D001D092 -:10AF200001D0A4D007012A6FC80E07010701346FB2 -:10AF300007012A510501000E07010701326F0501C3 -:10AF4000050E0701336F99EC05F00009D8A401D074 -:10AF500001D001D08BD0EF0E070107012B6FFF0E40 -:10AF600007012C6FEBEC0EF00009D8B401D001D032 -:10AF700030D0AAEC0DF032C724F733C725F734C719 -:10AF800026F735C727F7E1C641F747EC0AF07D0EF3 -:10AF900007010701415D000E07014259D8A001D009 -:10AFA00001D017D0F6EC1DF0EF0E07010701376F47 -:10AFB000FF0E0701386F3DEC14F024C737F725C7A3 -:10AFC00038F726C739F727C73AF7C4ECE6F092EC12 -:10AFD000DDF0D2EC22F007012A6F000E0701070115 -:10AFE000286F07012A5136D007012A6F020E070188 -:10AFF00007012B6F07012A51E7EC22F00501000E33 -:10B00000070107012B6F0501050E07012C6FB9EC35 -:10B010000FF007012A6F000E07010701296F0701D2 -:10B020002A510BD00E0E07012A6F830EE82EFED791 -:10B030002A2FFCD707010701292B070107012251FD -:10B0400007010701295DD8A001D001D0EBD7070186 -:10B050000701282B07010701235107010701285D7C -:10B06000D8A001D001D0C0D7CDEC22F01200000E44 -:10B0700003010301FB6F000E0301FC6F080E0701C3 -:10B080000701C66F000E0701C76F0701280E0701F1 -:10B090000701C46F0701070E0701C56FA4EC19F083 -:10B0A00028C7BEF729C7BFF7B8EC21F0BEC728F7FD -:10B0B000BFC729F72AC7BEF72BC7BFF7B8EC21F0E7 -:10B0C000BEC72AF7BFC72BF72CC7BEF72DC7BFF7E0 -:10B0D000B8EC21F0F80E07010701BE2507010701B2 -:10B0E0002C6FFF0E07010701BF2107012D6F07011C -:10B0F00007012F512E11D8B401D001D083D01DC724 -:10B10000E9FF1EC7EAFF0701EECF30F70701EECFD8 -:10B1100031F70701EECF32F70701EECF33F71FC744 -:10B12000E9FF20C7EAFF0701EECF34F70701EECFB2 -:10B1300035F70701EECF36F70701EECF37F70701F6 -:10B140003C6F000E07010701386F07013C510701F2 -:10B150003C6F110E07010701396F07013C5121C7F0 -:10B160003AF722C73BF73AC7BEF73BC7BFF7B8EC81 -:10B1700021F0BEC73AF7BFC73BF70C0E0701070126 -:10B18000BE6F000E0701BF6F0701300E07010701F8 -:10B19000BC6F0701070E0701BD6F38EC06F0070111 -:10B1A0000701BC1D07010701246F07010701BD1D31 -:10B1B0000701256F000E07010701776F000E0701D9 -:10B1C000786FA8EC21F021C7A2F722C7A3F7D3EC30 -:10B1D000E0F0A2C726F7A3C727F7070107EE26F07E -:10B1E0000701EE5207012551ED18070124C7E8FFBA -:10B1F000D8B4EF18D8B401D001D004D026EC1BF09D -:10B20000000E2BD01FC741F720C742F71DC73FF7DD -:10B210001EC740F70701280E070107013D6F070110 -:10B22000070E07013E6F8CECC9F007010701236F81 -:10B23000070107012329D8A401D001D004D026ECAE -:10B240001BF0000E0AD023C7E3F62CC7FBF32DC773 -:10B25000FCF31E801E92010E00D012001DC7E9FFF4 -:10B260001EC7EAFF0701EECF28F70701EECF29F747 -:10B270000701EECF2AF70701EECF2BF71FC7E9FF33 -:10B2800020C7EAFF0701EECF2CF70701EECF2DF71D -:10B290000701EECF2EF70701EECF2FF70701486F1A -:10B2A000000E07010701306F070148510701486F81 -:10B2B000060E07010701316F0701485121C732F718 -:10B2C00022C733F732C7BEF733C7BFF7B8EC21F058 -:10B2D000BEC732F7BFC733F70C0E07010701BE6FB9 -:10B2E000000E0701BF6F0701280E07010701BC6FA1 -:10B2F0000701070E0701BD6F38EC06F007010701D3 -:10B30000BC1D07010701246F07010701BD1D0701CF -:10B31000256F21C7A2F722C7A3F7D3ECE0F0A2C79D -:10B3200026F7A3C727F707010701275107010701E0 -:10B33000251906E107010701265107010701241914 -:10B34000D8B401D001D003D026EC1BF074D0000E8D -:10B3500007010701776F000E0701786FA8EC21F055 -:10B36000140E07010701C66F000E0701C76F070122 -:10B37000340E07010701C46F0701070E0701C56FEF -:10B38000A4EC19F00701340E07010701A26F0701B1 -:10B39000070E0701A36F40ECD6F0070140390F0BF1 -:10B3A0000701486F0701D89048370701D890483502 -:10B3B000EC0F07010701236F070107012351070164 -:10B3C0000701215D0701486F000E0701070122599F -:10B3D0000701496FEC0E0701482507010701216F9E -:10B3E000FF0E070149210701226F1DC74CF71EC739 -:10B3F0004DF70701340E070107014A6F0701070ED9 -:10B4000007014B6FC3ECAEF00009D8B401D001D0F6 -:10B410000FD021C74CF722C74DF70701340E0701A3 -:10B4200007014A6F0701070E07014B6F19EC80F007 -:10B4300026EC1BF000D0120007010E0E07010701D9 -:10B44000346F0701070E0701356F07010C0E070166 -:10B450000701326F0701070E0701336F53EC1CF031 -:10B46000040E07010701146F000E0701156F070195 -:10B47000070115AF01D001D001D07ED007011A6FAE -:10B48000000E07010701166F07011A51000E070190 -:10B490000701176F000E0701186F07010701185108 -:10B4A000800A800F080ED8B4175DD8A001D001D053 -:10B4B00001D04AD007010E0E070107011E6F0701D8 -:10B4C000070E07011F6F07010C0E070107011C6F14 -:10B4D0000701070E07011D6F2AEC19F0070107018C -:10B4E000196F070107011951020AD8A401D001D030 -:10B4F00001D088D0070107011951D8B401D001D07B -:10B5000013D017C71AF7010E07011B6F07011A2B7B -:10B5100003D0D89007011B3707011A2FFAD707016C -:10B520001B5107010701161307010701174B182BC1 -:10B53000070107011851800A800F080ED8B4175D63 -:10B54000D8A001D001D0B6D707010F0E070107011F -:10B550001425E96EEA6A0701070EEA22070116C7F9 -:10B56000EFFF070107011407D8A01507070107011E -:10B5700015AF01D001D082D775EC21F0A00E0701E4 -:10B5800007012D6FFF0E07012E6FBB0E070107018C -:10B590002B6FFF0E07012C6F51EC22F0620E07019A -:10B5A00007012D6FFF0E07012E6F6D0E07010701BA -:10B5B0002B6FFF0E07012C6F51EC22F007011A6F61 -:10B5C000050E07010701206F07011A5107010F0E31 -:10B5D000070107011E6F0701070E07011F6FD50E38 -:10B5E000070107011C6FFF0E07011D6F00EC22F021 -:10B5F00007011A6F010E070107012B6F07011A518E -:10B60000E1EC20F012000C0E07010701776F000E2D -:10B610000701786FA8EC21F0C3EC22F007010701C5 -:10B62000736F73C776F7F00E070176170701D8908E -:10B6300076330701D8907631EC0F07010701736F5D -:10B6400007010701736701D001D008D0180E070168 -:10B650000701706F020E0701716FB5D0070E070169 -:10B660000701C66F000E0701C76F000E0701070133 -:10B67000C46F000E0701C56FA4EC19F093D0C3ECA2 -:10B6800022F007010701726F07010701726701D0FD -:10B6900001D001D090D0070107017205D8A401D0D4 -:10B6A00001D001D07FD0070107017251020AD8A44E -:10B6B00001D001D04AD0030E07010701736101D008 -:10B6C00001D001D078D0000E07010701746F000E81 -:10B6D0000701756FC3EC22F007010701726F0701C4 -:10B6E00007017251040AD8A401D001D00AD0C3ECDA -:10B6F00022F007010701756FC3EC22F00701070173 -:10B70000746F180E07010701745D020E0701755969 -:10B71000D8B001D001D001D04ED0B50E070107013D -:10B72000745D050E07017559D8A001D001D008D06D -:10B73000B40E07010701706F050E0701716F43D04A -:10B7400074C770F775C771F73ED0020E0701070185 -:10B75000736101D001D001D02ED0C3EC22F00701DB -:10B760000701726F07010701725107010701736139 -:10B7700001D001D001D01FD00701070172C7C6F761 -:10B7800007010701C76B000E07010701C46F000E18 -:10B790000701C56FA4EC19F00701070172510701F9 -:10B7A0000701735F07010701730707017329D8A415 -:10B7B00001D001D064D7180E07010701706F020E87 -:10B7C0000701716F00D0120006010601DD29D8A41F -:10B7D00001D001D01AD0000E07010701506F000EF2 -:10B7E0000701516F000E070107014E6F000E0701A0 -:10B7F0004F6F450E070107014C6F000E07014D6F9B -:10B800009EECE1F006010601DD6F06010601DD296F -:10B81000D8A401D001D001D0AED0DDC64CF7F2ECF7 -:10B820001BF007014D514C11D8A401D001D001D01B -:10B83000A2D0060106013C51060106014015070190 -:10B84000166F060106013D5106010601411507016B -:10B85000176F060106013E51060106014215070158 -:10B86000186F060106013F51060106014315070145 -:10B87000196F00010001BD510601060140150701C5 -:10B880001A6F00010001BE510601060141150701B2 -:10B890001B6F00010001BF5106010601421507019F -:10B8A0001C6F00010001C05106010601431507018C -:10B8B0001D6F0701195107011D190EE107011851EC -:10B8C00007011C1909E10701175107011B1904E1C0 -:10B8D0000701165107011A19D8B401D001D003D0BD -:10B8E00051EC21F048D0060E07010701B26F000E9F -:10B8F0000701B36F690E0701166F060E176F16C7A3 -:10B90000B0F717C7B1F70701080E07010701AE6FBF -:10B910000701070E0701AF6F18EC1AF03CC60EF7CF -:10B920003DC60FF73EC610F73FC611F70A0E0701D6 -:10B930000701BE6F000E0701BF6F0701080E070168 -:10B940000701BC6F0701070E0701BD6F38EC06F059 -:10B95000BCC712F7BDC713F7D0920701080E070145 -:10B960000701146F0701070E0701156F15C7F4FFD4 -:10B9700014C7F3FFFF001200FC0E92160E01FE8B9F -:10B9800000D00E010E01FDA101D001D0FAD70701B0 -:10B99000096F010E346E07010951000E000100010C -:10B9A000FB6F000E0001FC6F000E0E010E01E86F30 -:10B9B000000E0E01E96FCD0E0E010E01EC6F0A0EA6 -:10B9C0000E010E01ED6FCD0E0E010E01EA6F0A0E93 -:10B9D0000E01EB6FCE0E0E010E01E46F0A0E0E018A -:10B9E000E56FCE0E0E010E01E26F0A0E0E01E36F3F -:10B9F0000701096F000E07010701C26F0701095116 -:10BA0000BEEC22F00701096F0D0E0E010E01A06FB2 -:10BA10000701095100F00701096F320E0E010E01F6 -:10BA2000A26F0701095100F00701096F120E0E0104 -:10BA30000E01A46F0701095100F00701096F400EC4 -:10BA40000E010E01A36F0701095100F00701096FF4 -:10BA5000120E0E010E01A66F0701095100F0070139 -:10BA6000096F0C0E0E010E01A76F0701095100F0BE -:10BA70000701096FEE0E0E010E01AA6F07010951B1 -:10BA800000F00701096F050E0E010E01AB6F0701F3 -:10BA9000095100F069C684FE00F06AC685FE00F018 -:10BAA0006BC682FE00F06CC683FE00F06DC680FEA1 -:10BAB00000F06EC681FE00F0100E070107010B6F4B -:10BAC000010E07010C6F0701096F100E0701070136 -:10BAD0000A6F0701095127EC1FF0720E07010701D9 -:10BAE0000B6F340E07010C6F0701096F140E07016D -:10BAF00007010A6F0701095127EC1FF0000E07012B -:10BB000007010B6F000E07010C6F0701096F000E94 -:10BB1000070107010A6F0701095127EC1FF00E0109 -:10BB2000DF851200E1C641F747EC0AF041C72DF767 -:10BB300042C72EF70401000E070107013C6F040104 -:10BB4000040E07013D6F1FEC17F01A0E07010701E5 -:10BB50003C27000E07013D23070107013C51070167 -:10BB60002D5D070107013D5107012E59D8B001D0C5 -:10BB700001D003D0F6EC1DF0AAD043EC11F0E30E97 -:10BB800007010701306FFF0E0701316FE1C62FF784 -:10BB9000A5EC20F007012D6F000E070107012C6FA7 -:10BBA00007012D51130E070107012C6501D001D0AB -:10BBB00001D038D000019F0E070107012C25E96E46 -:10BBC000EA6A0001000EEA22EF50070107013C6F0C -:10BBD00059EC1DF007010701306FE1C62FF711EC9A -:10BBE000E6F000019F0E070107012C25E96EEA6AC5 -:10BBF0000001000EEA22EF5007010701486F31EC07 -:10BC00001DF007010701306FE1C62FF711ECE6F0D8 -:10BC1000070107012C2B130E070107012C6501D02A -:10BC200001D0C8D70401000E070107013C6F0401D1 -:10BC3000040E07013D6F1FEC17F0070107013C518F -:10BC4000070107013C6F59EC1DF007010701306F38 -:10BC5000E1C62FF711ECE6F00401000E0701070121 -:10BC60003C6F0401040E07013D6F1FEC17F0070144 -:10BC700007013C5107010701486F31EC1DF0070136 -:10BC80000701306FE1C62FF711ECE6F007012D6FC9 -:10BC90003A0E07010701306F07012D51E1C62FF75A -:10BCA00011ECE6F00401000E07010701306F0401FA -:10BCB000040E0701316FE1C62FF7CDEC20F0E1C68D -:10BCC00041F7DEEC1CF0F6EC1DF05CEC22F012000B -:10BCD000140E070107012F25E96E000E0701070169 -:10BCE0003021EA6EEF500701376F3F0E070137171B -:10BCF000180E0701372707013751070107012F25C4 -:10BD00000701386FE86A070137BFE86807010701D4 -:10BD100030210701396F38C735F739C736F7140EA8 -:10BD2000070107012F25E96E000E070107013021E9 -:10BD3000EA6E070107013351EE2607013451EE2266 -:10BD4000000EEE22ED22ED52ED528BD0070131C7ED -:10BD5000F6FF070132C7F7FF000EF86E35C7E9FF9F -:10BD600036C7EAFF0800F5CFEFFF07010701314BA7 -:10BD7000322B07010701354B362B580E07010701FF -:10BD80002F250701376F000E07010701302107013A -:10BD9000386F0701385107010701361905E107011E -:10BDA0003751070107013519D8A401D001D054D06B -:10BDB000100E070107012F25070107015A6F000E1A -:10BDC00007010701302107015B6F0C0E0701070116 -:10BDD0002F2507010701586F000E070107013021C9 -:10BDE0000701596F080E070107012F2507010701F9 -:10BDF000566F000E0701070130210701576F040E2F -:10BE0000070107012F2507010701546F000E0701E5 -:10BE1000070130210701556F2FC752F730C753F77D -:10BE2000180E070107012F2507010701506F000EAB -:10BE30000701070130210701516FD0ECA1F0180E66 -:10BE4000070107012F2507010701356F000E0701C4 -:10BE5000070130210701366F070107013307D8A01A -:10BE600034070701070134513311D8A401D001D0A0 -:10BE70006DD71200140E070107012F25E96E000E81 -:10BE8000070107013021EA6EEF500701376F3F0EBF -:10BE900007013717180E0701372707013751070128 -:10BEA00007012F250701386FE86A070137BFE868E7 -:10BEB0000701070130210701396F38C735F739C746 -:10BEC00036F7140E070107012F25E96E000E070152 -:10BED00007013021EA6E070107013351EE26070101 -:10BEE0003451EE22000EEE22ED22ED52ED5286D0BC -:10BEF00031C7E9FF32C7EAFF35C7E1FF36C7E2FFC6 -:10BF0000EFCFE7FF07010701314B322B0701070194 -:10BF1000354B362B580E070107012F250701376FC8 -:10BF2000000E0701070130210701386F0701385162 -:10BF300007010701361905E107013751070107011C -:10BF40003519D8A401D001D054D0100E0701070133 -:10BF50002F25070107015A6F000E07010701302145 -:10BF600007015B6F0C0E070107012F250701070171 -:10BF7000586F000E0701070130210701596F080EA5 -:10BF8000070107012F2507010701566F000E070162 -:10BF9000070130210701576F040E070107012F2504 -:10BFA00007010701546F000E070107013021070147 -:10BFB000556F2FC752F730C753F7180E0701070107 -:10BFC0002F2507010701506F000E070107013021DF -:10BFD0000701516FD0ECA1F0180E070107012F25C2 -:10BFE00007010701356F000E070107013021070126 -:10BFF000366F070107013307D8A03407070107018F -:10C0000034513311D8A401D001D072D71200C2D05C -:10C010001C0E07010701C66F000E0701C76F07015D -:10C020001D0E07010701C46F0701070E0701C56F49 -:10C03000A4EC19F026EC1BF007011D0E0701070107 -:10C040007C6F0701070E07017D6F9FEC11F0070160 -:10C0500007011D051E11D8A401D001D010D0070181 -:10C0600007012151060AD8A401D001D008D0070148 -:10C0700007012251040AD8B401D001D001D092D0D6 -:10C08000070107012351020A2411D8A401D001D0CD -:10C0900012D007EE25F010EEE9F0060EEECFE6FF27 -:10C0A000E82EFCD72BC7E5F02CC7E6F02DC7E7F04C -:10C0B0002EC7E8F077D00701070123052411D8A483 -:10C0C00001D001D037D0060106013F510701070119 -:10C0D000381914E1060106013E510701070137191D -:10C0E0000DE1060106013D5107010701361906E180 -:10C0F000060106013C51070107013519D8B401D0EA -:10C1000001D001D04FD02BC7DBF02CC7DCF02DC7FE -:10C11000DDF02EC7DEF007EE25F010EEDFF0060EA4 -:10C12000EECFE6FFE82EFCD70701396F010E096E4E -:10C1300007013951020E07010701236F000E0701A5 -:10C14000246F00EEDFF017EE2FF0060EEECFE6FFC5 -:10C15000E82EFCD7DBC035F7DCC036F7DDC037F79B -:10C16000DEC038F707011D0E07010701786F0701D0 -:10C17000070E0701796F55EC02F00009D8A401D031 -:10C1800001D001D00FD00701396F000E096E0701F1 -:10C19000395107D00950000A01E13AD7010ACAE033 -:10C1A00000D000D01200FAC5AAF7FBC5ABF7FCC55A -:10C1B000ACF7FDC5ADF7E0CEA4F7E1CEA5F783D08F -:10C1C000A2C7A8F7A3C7A9F7150E07010701A25D2B -:10C1D000000E0701A359D8A001D001D007D0140E3A -:10C1E00007010701A86F000E0701A96FA8C7C6F7CE -:10C1F000A9C7C7F70701AE0E07010701C46F070102 -:10C20000070E0701C56FA4EC19F007010701A8513B -:10C2100007010701A25F07010701A95107010701F3 -:10C22000A35B07010701A8A101D001D010D007012D -:10C23000AE0E07010701A825E96EEA6A0701070E9D -:10C24000EA22000EEF6E07010701A84BA92B070198 -:10C25000AE0E07010701A66F0701070E0701A76FC2 -:10C260002AD00701A6C7E9FF0701A7C7EAFF070110 -:10C27000020E0701A627000E0701A723EECFC2F783 -:10C28000EDCFC3F70701C25107010701AA27070134 -:10C29000C35107010701AB23000E07010701AC23BF -:10C2A000000E07010701AD23020E07010701A85F79 -:10C2B000000E0701A95B07010701A951A811D8A425 -:10C2C00001D001D0CED707010701A351A211D8A4F4 -:10C2D00001D001D075D7A4C7E0FEA5C7E1FE0701D4 -:10C2E0000701AA5107010701AC2507010701AA6F41 -:10C2F00007010701AB5107010701AD210701AB6F32 -:10C300000701AC6BD8B0AC2B0701AD6B070107EE92 -:10C31000ACF0EE5007010701AA27ED500701070115 -:10C32000AB2307010701AA1D07010701A26F07013F -:10C330000701AB1D0701A36F00D012000101590EC8 -:10C3400007010701536F0101010E0701546F070137 -:10C35000556F000E07010701526F07015551040E7A -:10C3600007010701526501D001D001D0AED00C0EFB -:10C37000070107015325E96E000E0701070154214B -:10C38000EA6EEE50ED10D8A401D001D08DD00C0E85 -:10C39000070107015325E96E000E0701070154212B -:10C3A000EA6E07014CC7EEFF07014DC7EDFF07011D -:10C3B00007014D514C11D8A401D001D031D0010E4C -:10C3C00000010001F95D200E0001FA59D8B001D03A -:10C3D00001D00BD0000E00010001F95D100E00012C -:10C3E000FA59D8B001D001D007D0000E00010001E9 -:10C3F000F96F100E0001FA6F0C0E070107015325AB -:10C40000E96E000E070107015421EA6E0001F9C030 -:10C41000EEFF0001FAC0EDFF00010001F94BFA2B1D -:10C42000070107014F514E11D8B401D001D012D0ED -:10C430000A0E07010701B26F000E0701B36F4EC766 -:10C44000B0F74FC7B1F753C7AEF754C7AFF718EC03 -:10C450001AF014D00A0E070107015A6F000E0701E7 -:10C460005B6FFF0E07010701586F000E0701596F40 -:10C4700053C756F754C757F708EC1FF00A0E0701C9 -:10C4800007015325E96E000E070107015421EA6EEA -:10C49000070150C7EEFF070151C7EDFF52C723F058 -:10C4A00007010701525113D00E0E07010701532750 -:10C4B000000E0701542307010701522B040E070148 -:10C4C0000701526501D001D052D7FF0E00D01200F3 -:10C4D00000D0C5CF12F71F0E0701121712C713F7AE -:10C4E0000701146B000EC7B4010E07011313000EF1 -:10C4F0001413070114511311D8A401D001D0E9D7A6 -:10C50000C58000D0C5B001D001D0FCD7A1A601D014 -:10C5100001D006D00701070110690701116998D001 -:10C5200010C715F782EC1CF00009D8B401D001D077 -:10C5300009D0C584FD0E07010701106FFF0E07012A -:10C54000116F86D0C5BC01D001D072D011C715F7CC -:10C5500082EC1CF00009D8B401D001D009D0C58408 -:10C56000FD0E07010701106FFF0E0701116F70D05C -:10C57000C5BC01D001D052D0C58200D0C5B201D017 -:10C5800001D0FCD7A1A601D001D006D00701070138 -:10C590001069070111695CD0070107011029070123 -:10C5A0000701156F82EC1CF00009D8B401D001D04E -:10C5B00009D0C584FD0E07010701106FFF0E0701AA -:10C5C000116F46D0C5BC01D001D01ED0C58600D0A9 -:10C5D000C5B601D001D0FCD7C58AC58800D0C5B882 -:10C5E00001D001D0FCD7C58400D0C5B401D001D0A2 -:10C5F000FCD7A1A601D001D006D007010701106920 -:10C600000701116925D009D0C584FE0E0701070175 -:10C61000106FFF0E0701116F1BD009D0C584FE0EED -:10C6200007010701106FFF0E0701116F11D009D02C -:10C63000C584FE0E07010701106FFF0E0701116F81 -:10C6400007D00701C9CF10F707010701116B00D010 -:10C6500012002DC760F784EC0EF0E9C3EBF3EAC3D8 -:10C66000ECF392D09DEC1FF017EC0EF0B0D017EC6D -:10C670000EF0ADD007012E6F010E07010701716F9B -:10C6800007012E5107012F6F110E07010701706F6F -:10C6900007012F51B4EC9BF004010401DB51DA11C6 -:10C6A000D8A401D001D001D012D0040104EED4F0FE -:10C6B000030113EEE5F0E652EE52ED50E518EFCF30 -:10C6C000E8FFD8B4E718D8A401D001D0D3D7070128 -:10C6D0002E6F080E03010301F56F07012E5177D06D -:10C6E00007012E6F010E07010701716F07012E511F -:10C6F00007012F6F110E07010701706F07012F51FE -:10C70000B4EC9BF004010401DB51DA11D8A401D090 -:10C7100001D001D012D0040104EED4F0030113EED5 -:10C72000E5F0E652EE52ED50E518EFCFE8FFD8B451 -:10C73000E718D8A401D001D0D3D707012E6F0C0E73 -:10C7400003010301F56F07012E5141D007012E6F40 -:10C750000D0E03010301F56F07012E5138D00701BB -:10C760002E6F000E07010701716F07012E5107019F -:10C770002F6F140E07010701706F07012F51B4ECE2 -:10C780009BF017EC0EF023D003010301F551000AD2 -:10C7900001E16DD7010A01E165D7030A01E167D71D -:10C7A000010A01E164D7060A01E161D7030A01E148 -:10C7B00061D7010A01E15ED70F0AD1E0010ACFE09B -:10C7C000020A8EE0070ACBE0020AC0E0C8D71200D6 -:10C7D00006010601C851D8B401D001D025D0060108 -:10C7E0000601C75106010601C5277E0E0601060196 -:10C7F000C56501D001D004D006010601C76911D07A -:10C8000006010601C56701D001D00BD00701DB6F1F -:10C81000010E06010601C76F0701DB510601060183 -:10C82000C807C5C6BBFF57D006010601C951020A99 -:10C83000D8A401D001D003D0C6C6BBFF4CD006019E -:10C840000601C905D8A401D001D043D00DEC22F0D7 -:10C8500006010601CA5107010701DF5D0701DB6F11 -:10C8600006010601CB5107010701E0590701DC6F02 -:10C8700006010601CC5107010701E1590701DD6FEF -:10C8800006010601CD5107010701E2590701DE6FDC -:10C89000F30EDB5D9E0EDC59000EDD59000E070124 -:10C8A000DE59D8A001D001D013D006010601C6512F -:10C8B000FF0A06010601C66FC6C6BBFF0DEC22F0DB -:10C8C000DFC7CAF6E0C7CBF6E1C7CCF6E2C7CDF6C4 -:10C8D00002D0000EBB6E06010601D151D8B401D0C2 -:10C8E00001D025D006010601D05106010601CE2750 -:10C8F0007E0E06010601CE6501D001D004D00601EE -:10C900000601D06911D006010601CE6701D001D021 -:10C910000BD00701DB6F010E06010601D06F070186 -:10C92000DB5106010601D107CEC6BEFF0DD00601C0 -:10C930000601D251020AD8A401D001D003D0CFC63B -:10C94000BEFF02D0000EBE6E1200B9EC20F0110E38 -:10C95000070107010B6F000E07010C6F00015E0E4F -:10C9600007010701096F0001000E07010A6FE0ECE3 -:10C9700019F05E28D8A401D001D02ED00701086F8D -:10C98000000E00010001636F070108510701086FE5 -:10C99000000E00010001626F070108510701086FD6 -:10C9A000000E00010001616F070108510701086FC7 -:10C9B000540E00010001606F070108510701086F64 -:10C9C000CA0E000100015F6F070108510701086FDF -:10C9D000AC0E5E6E070108510601688D0601688F76 -:10C9E000060E07010701B26F000E0701B36F0001C9 -:10C9F0005E0E07010701B06F0001000E0701B16F65 -:10CA00000601690E07010701AE6F0601060E070158 -:10CA1000AF6F18EC1AF0C00E060106013C6FA80EAD -:10CA200006013D6F000E06013E6F330E06013F6F9B -:10CA30003CC650F63DC651F63EC652F63FC653F6CA -:10CA4000FF0E06010601406FFF0E0601416FFF0E4B -:10CA50000601426F000E0601436F40C654F641C600 -:10CA600055F642C656F643C657F6C00E06010601F5 -:10CA7000446FA80E0601456F000E0601466F010EB9 -:10CA80000601476FC00E06010601486FA80E060199 -:10CA9000496F000E06014A6F010E06014B6F000E32 -:10CAA000060106014C6F000E06014D6F000E0601D7 -:10CAB0004E6F000E06014F6F1200140E07010701A2 -:10CAC000C66F000E0701C76F0701270E0701070198 -:10CAD000C46F0701070E0701C56FA4EC19F0070129 -:10CAE00007012751F00B400AD8B401D001D002D081 -:10CAF000000E96D01F0E070107012D1507013B6F91 -:10CB0000FF0E070107012E1507013C6F07013C517D -:10CB10003B11D8B401D001D002D0000E81D027C77C -:10CB20003BF70F0E07013B170701D8903B37070172 -:10CB3000D8903B35326E070132C03FF7070107013D -:10CB4000406B000E070107013D6F000E07013E6FAD -:10CB500046EC16F03DC725F73EC726F7070132C061 -:10CB600079F7070107017A6BC0EC1BF00701070199 -:10CB700026512511D8B401D001D002D0000E50D0DA -:10CB80000701270E07010701BC6F0701070E070108 -:10CB9000BD6F52EC0FF0070107011E511D11D8B4F3 -:10CBA00001D001D010D01DC7E9FF1EC7EAFF070161 -:10CBB00037C7EEFF070138C7EEFF070139C7EEFFA1 -:10CBC00007013AC7EEFF1FC7E9FF20C7EAFF0701C9 -:10CBD00033C7EEFF070134C7EEFF070135C7EEFF8D -:10CBE000070136C7EEFF21C7E9FF22C7EAFF0701A9 -:10CBF00030C7EFFF325007010701295D07013B6F86 -:10CC0000000E070107012A5907013C6F23C7E9FFFE -:10CC100024C7EAFF3BC7EEFF3CC7EDFF010E00D083 -:10CC200012002FC760F784EC0EF02FC741F747ECD6 -:10CC30000AF041C731F742C732F707010701325105 -:10CC40003111D8A401D001D001D09DD00701070136 -:10CC500031053211D8A401D001D004D02FC741F73B -:10CC6000DEEC1CF003010301F7B101D001D02ED09E -:10CC7000030103EEE1F0EECF33F7EDCF34F703011C -:10CC80000301DF510701335F03010301E051070195 -:10CC9000345BD890070134310701366F0701333117 -:10CCA0000701356F0701070131510701355D0701A4 -:10CCB0000701325107013659D8A001D001D006D062 -:10CCC0002FC741F7DEEC1CF00301F781010E0701CD -:10CCD0000701AC6F000E0701AD6F0701336F010E46 -:10CCE00007010701AB6F070133510701300E070140 -:10CCF0000701A96F0701070E0701AA6FFAC3A8F77A -:10CD0000E5C3A6F7E6C3A7F74AEC0CF0030103EE70 -:10CD1000E1F0030113EEE5F0E62A000EE522E6520B -:10CD2000EE52ED50E55C02E1EF50E75CD8A001D097 -:10CD300001D004D0DFC3E5F3E0C3E6F30701070148 -:10CD400031053211D8A401D001D005D02FC741F749 -:10CD5000DEEC1CF017D003010301F6BB01D001D0BB -:10CD600011D00301F68B55EC20F0060E07010701E8 -:10CD7000702503010301F16F000E07010701712106 -:10CD80000301F26F00D012000701446F690E070122 -:10CD90000701486F07014451D0EC1DF007013A51DB -:10CDA000371138113911D8A401D001D00BD00701A7 -:10CDB000446F300E07010701486F07014451D0EC62 -:10CDC0001DF08AD00701446F000E070107013B6F79 -:10CDD00007014451070E070107013B6501D001D04F -:10CDE00001D029D007013C0E070107013B25E96E60 -:10CDF000EA6A0701070EEA2237C748F731EC1DF04F -:10CE0000EF6E040E0701446FD890070107013A3313 -:10CE10000701393307013833070137330701442F3E -:10CE2000F3D7070107013B2B070E070107013B65FD -:10CE300001D001D0D7D70701446F080E07010701C1 -:10CE40003B6F07014451070107013B6701D001D047 -:10CE500001D01ED03BC744F7FF0E0701442707014E -:10CE60003C0E07014425E96EEA6A0701070EEA2233 -:10CE7000EF50300AD8B401D001D001D009D0070159 -:10CE800007013B07070107013B6701D001D0E2D74B -:10CE9000070107013B6701D001D001D01DD03BC77E -:10CEA00044F7FF0E0701442707013C0E0701442504 -:10CEB000E96EEA6A0701070EEA22EF50070107014F -:10CEC000486FD0EC1DF0070107013B070701070180 -:10CED0003B6701D001D0E3D70701446F730E070110 -:10CEE0000701486F07014451D0EC1DF01200060104 -:10CEF0000601E45106010601DF6301D001D001D033 -:10CF00007ED006010601DF51FE0AD8B401D001D05F -:10CF10004BD0270E07010701AC6F000E0701AD6F64 -:10CF20000701A26F010E07010701AB6F0701A251B4 -:10CF30000401C80E07010701A96F0401040E0701CF -:10CF4000AA6F06010601DF511C0DF3CFA3F71B0EDC -:10CF50000701A32700016F0E0701A325E96EEA6A06 -:10CF60000001000EEA22EF5007010701A86F060139 -:10CF70000601DF511C0D00016F0EF324E96EEA6A11 -:10CF80000001000EEA22EECFA4F7EDCFA5F7D90EEF -:10CF90000701A42507010701A66FFF0E0701A521C0 -:10CFA0000701A76F4AEC0CF0E4C6DFF6270E070175 -:10CFB0000701AC6F000E0701AD6FFAC3ABF7D90ED6 -:10CFC00003010301DF2507010701A96FFF0E03011C -:10CFD0000301E0210701AA6F0701A26F010E0701FB -:10CFE0000701A86F0701A2510401C80E070107013C -:10CFF000A66F0401040E0701A76F4AEC0CF01200A3 -:04FFF8009EFFFDFF6C +:1000000074656D706572617475726568756D69642B +:10001000697479006170692E74656C6C6475732EF7 +:10002000636F6D000000010000000000000000018F +:100030000000000000009E9FFE4101000000FFFF45 +:10004000F3FFFFFFFF80FFFFFEFEFFFEFFFFFEFF4F +:1000500007000D0E080108014A25E96E000E08018F +:1000600008014B21EA6EEF50080108014F6F080E9E +:10007000080108014A25E96E000E080108014B211C +:10008000EA6E0801EECF66F80801EECF67F80801C6 +:10009000EECF68F80801EECF69F8040E08010801F8 +:1000A0004A25E96E000E080108014B21EA6E08019D +:1000B000EECF5AF80801EECF5BF80801EECF5CF8FE +:1000C0000801EECF5DF81890189218940B000E00FE +:1000D00018B86DEF80F06FEF80F085EF80F0C4EC22 +:1000E00043F0740E08010801A1250F6E350E0801BA +:1000F0000801A221106E060E08010801A321116E4D +:10010000000E08010801A421126EDDEF81F0080144 +:1001100008014FA58EEF80F090EF80F094EF80F013 +:100120006CEC33F0D6EF8DF0080108014FA99BEF7E +:1001300080F09DEF80F0BBEF80F066C821F067C8CB +:1001400022F068C823F069C824F008016A6F000E25 +:1001500008010801736F08016A5108016B6F040EF2 +:1001600008010801726F08016B519FECA1F06CEC63 +:1001700033F0D6EF8DF0080108014FA3C2EF80F0F5 +:10018000C4EF80F0F8EF80F0010E080108015A2555 +:10019000256E000E080108015B21266E000E080185 +:1001A00008015C21276E000E080108015D21286E00 +:1001B000B4EC04F072C840F073C841F008016A6FF3 +:1001C000010E08010801736F08016A5108016B6F85 +:1001D000120E08010801726F08016B519FECA1F02B +:1001E00008016A6F060E176E08016A51FAEF80F077 +:1001F0006CEC33F0D6EF8DF0080108014FA503EF4A +:1002000081F005EF81F007EF81F0D6EF8DF0080166 +:1002100008014FA90EEF81F010EF81F056EF81F049 +:1002200008010801695124180EE10801080168510C +:10023000231809E1080108016751221804E10801A7 +:10024000080166512118D8B428EF81F02AEF81F017 +:1002500056EF81F021C05AF822C05BF823C05CF849 +:1002600024C05DF866C821F067C822F068C823F092 +:1002700069C824F008016A6F010E08010801736F54 +:1002800008016A5108016B6F040E08010801726FC2 +:1002900008016B519FECA1F05AC821F05BC822F015 +:1002A0005CC823F05DC824F0D6EF8DF0080108018A +:1002B0004FA35DEF81F05FEF81F0D9EF81F0010E88 +:1002C000080108015A25256E000E080108015B216E +:1002D000266E000E080108015C21276E000E080141 +:1002E00008015D21286E0E0E080108014A25E96EFD +:1002F000000E080108014B21EA6EEECF2FF0EDCF82 +:1003000030F0B4EC04F072C840F073C841F008015A +:1003100008014FA98EEF81F090EF81F0C1EF81F0DD +:1003200008016A6F010E08010801736F08016A5124 +:1003300008016B6F100E08010801726F08016B5104 +:100340009FECA1F008016A6F070E176E08016A5151 +:10035000C4EC43F0740E08010801A1250F6E350EA0 +:1003600008010801A221106E060E08010801A32150 +:10037000116E000E08010801A421126E1898D9EF21 +:1003800081F008016A6F010E08010801736F08010E +:100390006A5108016B6F120E08010801726F0801A3 +:1003A0006B519FECA1F008016A6F060E176E0801F1 +:1003B0006A51D6EF8DF0E6EF81F01750040A01E1A3 +:1003C000A6D6010A01E118D7DBEF81F04CC854F83A +:1003D0004DC855F8080108014FA1F1EF81F0F3EF86 +:1003E00081F0F7EF81F008010801544B552B08010B +:1003F00008014FA3FEEF81F000EF82F004EF82F0DE +:1004000008010801544B552B00EE0DF010EE0BF0D7 +:10041000E652EE52ED50E55C02E1EF50E75CD8A009 +:1004200014EF82F016EF82F03DEF82F000EE0BF059 +:10043000EECF6AF8EDCF6BF80D5008016A5F0E50F1 +:1004400008016B5B00EE05F0EECF6CF8EDCF6DF8B8 +:10045000035008016C5F045008016D5B08016A518C +:1004600008016C5D08010801526F08016B51080119 +:100470006D590801536F54EF82F000EE0DF0EECF8E +:100480006AF8EDCF6BF80B5008016A5F0C50080159 +:100490006B5BFF0E08016A2508010801526FFF0E11 +:1004A00008016B210801536F2550080108015A5DAE +:1004B00008010801626F2650080108015B59080114 +:1004C000636F2750080108015C590801646F2850C8 +:1004D000080108015D590801656F62C856F863C8D4 +:1004E00057F808016A6F000E080108014E6F0801F5 +:1004F0006A510801080155515411D8B482EF82F0B5 +:1005000084EF82F094EF83F00801080153515211F7 +:10051000D8B48DEF82F08FEF82F092EF83F0080174 +:10052000080165BF96EF82F098EF82F0CBEF82F082 +:1005300008010801525108016A6F0801080153516E +:1005400008016B6F08016C6B08016D6B08016A5143 +:1005500008010801625D08016B5108010801635937 +:1005600008016C5108010801645908016D51080126 +:1005700008016559D8B0BFEF82F0C1EF82F0CBEF30 +:1005800082F008016A6F010E080108014E6F080130 +:100590006A513DEF83F00801080154510801080138 +:1005A000622508016A6F0801080155510801080118 +:1005B000632108016B6F000E080108016421080126 +:1005C0006C6F000E08010801652108016D6F0801BC +:1005D0006D51800A800F08E1000E6C5D05E1000E90 +:1005E0006B5D02E1010E6A5DD8A0F9EF82F0FBEFCE +:1005F00082F03DEF83F00801080154510801080121 +:10060000525D08016A6F080108015551080108018F +:10061000535908016B6F08016C6B08016BBF6C07C5 +:1006200008016C5108016D6F08016D51800A0801C5 +:100630006E6F08010801625108016A5D0801080136 +:10064000635108016B5908010801645108016C5994 +:10065000080108016551800A08016E59D8A033EFDE +:1006600083F035EF83F03DEF83F008016A6F010EF0 +:10067000080108014E6F08016A5108010801525132 +:1006800008016A6F08010801535108016B6F0801E6 +:100690006C6B08016D6B080108016551800A080147 +:1006A0006E6F08016A5108010801625D08016B5113 +:1006B00008010801635908016C51080108016459D7 +:1006C00008016D51800A08016E59D8B06AEF83F0B5 +:1006D0006CEF83F092EF83F0080156C86AF80801C6 +:1006E00057C86BF808010801545108016A2708012E +:1006F0000801555108016B2308016B51800A800FD6 +:10070000010ED8B46A5DD8A088EF83F08AEF83F039 +:1007100092EF83F008016A6F010E080108014E6F25 +:1007200008016A51E4EF83F0080165516211631119 +:100730006411D8A49EEF83F0A0EF83F0AAEF83F0BA +:1007400008016A6F010E080108014E6F08016A5125 +:10075000E4EF83F00801080165BFB1EF83F0B3EF68 +:1007600083F0E4EF83F008010801525108016A6F39 +:1007700008010801535108016B6F08016C6B0801F7 +:100780006D6B08016A5108010801625D08016B5137 +:1007900008010801635908016C51080108016459F6 +:1007A00008016D51080108016559D8B0DAEF83F0EE +:1007B000DCEF83F0E4EF83F008016A6F010E0801BB +:1007C00008014E6F08016A51080108014E67EBEFFE +:1007D00083F0EDEF83F00AEF84F0080108014FB5D4 +:1007E000F4EF83F0F6EF83F008EF84F008016A6F0E +:1007F000010E08010801736F08016A5108016B6F4F +:10080000100E08010801726F08016B519FECA1F0F6 +:10081000D6EF8DF0080108014F51060BD8B413EF45 +:1008200084F015EF84F019EF84F06CEC33F0D6EF20 +:100830008DF0080108014FB920EF84F022EF84F019 +:1008400024EF84F0D6EF8DF04DEF88F00801080119 +:10085000695124180EE1080108016851231809E1C3 +:10086000080108016751221804E1080108016651D6 +:100870002118D8B43EEF84F040EF84F06CEF84F0A0 +:1008800021C05AF822C05BF823C05CF824C05DF890 +:1008900066C821F067C822F068C823F069C824F050 +:1008A00008016A6F010E08010801736F08016A519F +:1008B00008016B6F040E08010801726F08016B518B +:1008C0009FECA1F05AC821F05BC822F05CC823F06D +:1008D0005DC824F0D6EF8DF008016A6F070E176E21 +:1008E00008016A512950075C08010801586F2A5015 +:1008F00008580801596F0801080159AF82EF84F0C8 +:1009000084EF84F09AEF84F000EE03F0EECF6AF803 +:10091000EDCF6BF8015008016A5F025008016B5B74 +:1009200008016A5108010801582708016B510801A4 +:100930000801592308010801585121240801080120 +:100940005E6F080108015951222008015F6F000EF7 +:1009500023200801606F000E24200801616F080148 +:1009600008016651080108015E5D08016A6F08010F +:1009700008016751080108015F5908016B6F080100 +:100980000801685108010801605908016C6F0801ED +:100990000801695108010801615908016D6F0801DA +:1009A0006DAFD5EF84F0D7EF84F0EBEF84F0080162 +:1009B0006A6F000E08010801736F08016A5108018F +:1009C0006B6F100E08010801726F08016B519FECEC +:1009D000A1F0D6EF8DF00950295C08016A6F0A502A +:1009E0002A5808016B6F08016C6B08016BBF6C071C +:1009F00008016C5108016D6F08016A51215C080102 +:100A000008015E6F08016B51225808015F6F0801F1 +:100A10006C5123580801606F08016D51245808017A +:100A2000616F00EE09F010EE29F0E652EE52ED5043 +:100A3000E55C02E1EF50E75CD8B021EF85F023EFF1 +:100A400085F043EF85F00150035C08016A6F0250A6 +:100A5000045808016B6F08016C6B08016D6B08018D +:100A60006A51080108015E5F08016B510801080125 +:100A70005F5B08016C5108010801605B08016D5162 +:100A800008010801615B080108015E5108010801C5 +:100A9000665D080108015E6F080108015F510801E9 +:100AA0000801675908015F6F0801080160510801DA +:100AB000080168590801606F0801080161510801C7 +:100AC000080169590801616F080108016151800A34 +:100AD000800F0BE1000E0801605D07E1000E0801C8 +:100AE0005F5D03E1010E08015E5DD8A07AEF85F03D +:100AF0007CEF85F07DEF86F00150035C08016A6FA2 +:100B00000250045808016B6F08016C6B08016D6B93 +:100B1000080108015E5108016A5D080108015F5182 +:100B200008016B5908010801605108016C5908015E +:100B30000801615108016D59D8A0A1EF85F0A3EF1C +:100B400085F07DEF86F03F963F98199009C058F8E0 +:100B50000AC059F8080108015E5109260801080178 +:100B60005F510A22080108015851295C0801080157 +:100B700059512A58D8A0BFEF85F0C1EF85F0EFEFAB +:100B800085F000EE09F010EE29F0E652EE52ED503D +:100B9000E55C02E1EF50E75CD8B0D1EF85F0D3EF30 +:100BA00085F0EDEF85F000EE09F0EECF6AF8EDCFBD +:100BB0006BF8295008016A5F2A5008016B5B080135 +:100BC0006A51212608016B512222000E2322000EB9 +:100BD000242209C029F00AC02AF033EF86F000EE83 +:100BE00003F0EECF6AF8EDCF6BF8015008016A5FB1 +:100BF000025008016B5B295008016A2508010801B1 +:100C0000586F2A5008016B210801596F09500801DB +:100C10000801585D0A50080108015959D8B013EF6E +:100C200086F015EF86F033EF86F000EE09F0EECF98 +:100C30006AF8EDCF6BF808010801585108016A5FA6 +:100C400008010801595108016B5B08016A5121260E +:100C500008016B512222000E2322000E242209C01B +:100C600029F00AC02AF000EE03F010EE09F0E65277 +:100C7000EE52ED50E55C02E1EF50E75CD8A043EFA7 +:100C800086F045EF86F057EF86F000EE03F0EECFEA +:100C90006AF8EDCF6BF8015008016A5F0250080155 +:100CA0006B5B08016A51095E08016B510A5A00EE3C +:100CB00003F010EE29F0E652EE52ED50E55C02E151 +:100CC000EF50E75CD8A067EF86F069EF86F07BEF26 +:100CD00086F000EE03F0EECF6AF8EDCF6BF801502E +:100CE00008016A5F025008016B5B08016A51295EC6 +:100CF00008016B512A5AF1EF86F000EE29F010EE50 +:100D000009F0E652EE52ED50E518EFCFE8FFD8B407 +:100D1000E718D8B48EEF86F090EF86F0F1EF86F00A +:100D20003FA695EF86F097EF86F0F0EF86F03FA8AC +:100D30009CEF86F09EEF86F0EFEF86F00950295C7D +:100D400008016A6F0A502A5808016B6F08016C6B22 +:100D500008016BBF6C0708016C5108016D6F080139 +:100D60006A51215E08016B51225A08016C51235AC5 +:100D700008016D51245A00EE09F010EE29F0E652F8 +:100D8000EE52ED50E55C02E1EF50E75CD8B0CBEFFE +:100D900086F0CDEF86F0EAEF86F00150035C0801A3 +:100DA0006A6F0250045808016B6F08016C6B0801F0 +:100DB0006BBF6C0708016C5108016D6F08016A5127 +:100DC000215E08016B51225A08016C51235A080117 +:100DD0006D51245A09C029F00AC02AF019843F88AD +:100DE0003F8600EE07F010EE09F0E652EE52ED50AD +:100DF000E518EFCFE8FFD8B4E718D8A402EF87F0E2 +:100E000004EF87F047EF87F019B609EF87F00BEF93 +:100E100087F024EF87F0C4EC43F0740E080108015A +:100E2000A1250F6E350E08010801A221106E060ED5 +:100E300008010801A321116E000E08010801A42178 +:100E4000126E189847EF87F00801080169512418BD +:100E50000EE1080108016851231809E108010801A1 +:100E60006751221804E10801080166512118D8A42D +:100E70003CEF87F03EEF87F047EF87F03FA043EF6E +:100E800087F045EF87F047EF87F01898199600EE46 +:100E900021F0EECF6AF8EDCF6BF80801080166513A +:100EA00008016A5F08010801675108016B5B0E0EBB +:100EB000080108014A25E96E000E080108014B21CE +:100EC000EA6EEECF6CF8EDCF6DF808016A510801BB +:100ED0006C5D08010801506F08016B5108016D59E4 +:100EE0000801516F30502F10D8A479EF87F07BEFB5 +:100EF00087F087EF87F00801080151515011D8B4ED +:100F000084EF87F086EF87F087EF87F0198250C86B +:100F10002FF051C830F01750080AD8A492EF87F08C +:100F200094EF87F0D4EF87F0080108016951241885 +:100F30000EE1080108016851231809E108010801C0 +:100F40006751221804E10801080166512118D8A44C +:100F5000ACEF87F0AEEF87F0D2EF87F03FA0B3EFB2 +:100F600087F0B5EF87F0D2EF87F0C4EC43F0BA0E0C +:100F700008010801A1250F6E1A0E08010801A2211F +:100F8000106E030E08010801A321116E000E080166 +:100F90000801A421126E188808016A6F090E176EE5 +:100FA00008016A512DEF88F01750090AD8A4DBEF29 +:100FB00087F0DDEF87F006EF88F0080108014FB1F8 +:100FC000E4EF87F0E6EF87F004EF88F066C821F0E1 +:100FD00067C822F068C823F069C824F008016A6F66 +:100FE000000E08010801736F08016A5108016B6F58 +:100FF000140E08010801726F08016B519FECA1F0FB +:101000006CEC33F0D6EF8DF02DEF88F017500A0A14 +:10101000D8A40DEF88F00FEF88F02DEF88F00801CD +:101020000801695124180EE10801080168512318CC +:1010300009E1080108016751221804E108010801CB +:1010400066512118D8A427EF88F029EF88F02BEFFC +:1010500088F06CEC33F0D6EF8DF065EF88F0080186 +:101060000801695124180EE108010801685123188C +:1010700009E1080108016751221804E1080108018B +:1010800066512118D8A447EF88F049EF88F04BEF5C +:1010900088F06CEC33F0D6EF8DF01750060A02E1C1 +:1010A00026EF84F0010A01E11DD40F0A01E11AD4F0 +:1010B000010A01E117D4030A01E114D4010A01E194 +:1010C00011D4070ACCE02DEF88F0080108014FABDE +:1010D0006CEF88F06EEF88F070EF88F0D6EF8DF04F +:1010E00017500B0AD8A477EF88F079EF88F07BEFE0 +:1010F00088F0D6EF8DF017500A0AD8A482EF88F056 +:1011000084EF88F086EF88F0D6EF8DF017500C0A48 +:10111000D8A48DEF88F08FEF88F091EF88F0D6EFAC +:101120008DF0080108014D514C11D8B49AEF88F0A8 +:101130009CEF88F09AEF8CF0080108015751800A63 +:10114000800F010ED8B4565DD8B0A9EF88F0ABEF90 +:1011500088F032EF8AF00C0E080108014A25E96E8A +:10116000000E080108014B21EA6EEF380F0B080151 +:101170006A6F6AC86BF808016C6BD89008016B370E +:101180006C37D89008016B376C370801080156514D +:1011900008016B5D08010801796F080108015751CA +:1011A00008016C5908017A6FF9EC42F00801080156 +:1011B0005651080108014C27080108015751080140 +:1011C00008014D23080108014C5108010801525D36 +:1011D000080108014D51080108015359D8B0F3EF37 +:1011E00088F0F5EF88F0F9EF88F052C84CF853C852 +:1011F0004DF8080108014C512526080108014D5100 +:101200002622000E2722000E282200EE0BF0EECF41 +:101210006AF8EDCF6BF8080108014C5108016A2704 +:10122000080108014D5108016B2308016A51055C52 +:1012300008016B510658D8B020EF89F022EF89F0F1 +:1012400096EF89F000EE05F0EECF6AF8EDCF6BF87F +:101250000B5008016A5F0C5008016B5B010E08011E +:101260006A2508010801586F000E08016B2108016A +:10127000596F58C8AAF859C8ABF808016A6F000E30 +:1012800008010801A96F08016A51FF0E0801080151 +:10129000A76FFF0E0801A86F1CC0A6F80BC0A4F82A +:1012A0000CC0A5F8A0EC23F0080108015851080172 +:1012B00008014C5D08010801AA6F08010801595195 +:1012C000080108014D590801AB6F08016A6F000E53 +:1012D00008010801A96F08016A51FF0E0801080101 +:1012E000A76FFF0E0801A86F1CC0A6F803C0A4F8E2 +:1012F00004C0A5F8A0EC23F008014CC86AF8080166 +:101300004DC86BF808010801585108016A5F0801CF +:101310000801595108016B5B035008016A250B6EE7 +:10132000045008016B210C6EB9EF89F04CC8AAF883 +:101330004DC8ABF808016A6F000E08010801A96FDB +:1013400008016A51FF0E08010801A76FFF0E08018E +:10135000A86F1CC0A6F80BC0A4F80CC0A5F8A0ECA0 +:1013600023F0080108014C510B26080108014D51DA +:101370000C223D28D8B43E28D8B4C1EF89F0C3EF81 +:1013800089F030EF8AF0080108014C513D5E0801F8 +:1013900008014D513E5A3D50312408010801586F53 +:1013A0003E5032200801596F0801080159AFDBEFA8 +:1013B00089F0DDEF89F0E1EF89F03D683E6830EFBC +:1013C0008AF000EE3DF0EE52ED50800A800F010EE3 +:1013D000D8B4EF5CD8B0EFEF89F0F1EF89F030EFDF +:1013E0008AF00801080158512526080108015951C1 +:1013F0002622000E2722000E28220801080158513B +:101400000B260801080159510C2200EE0BF010EEDA +:1014100005F0E652EE52ED50E55C02E1EF50E75C7C +:10142000D8B015EF8AF017EF8AF02EEF8AF000EEB1 +:1014300005F0EECF6AF8EDCF6BF8035008016A5F54 +:10144000045008016B5B010E08016A27000E6B2334 +:1014500008016A510B5E08016B510C5A3D683E68E9 +:101460009AEF8CF0080108015751800A800F010E95 +:10147000D8B4565DD8A03FEF8AF041EF8AF09AEFDA +:101480008CF008014CC86AF808014DC86BF80801D7 +:101490000801565108016A2708010801575108013F +:1014A0006B2308016A5108010801525D08016B5164 +:1014B000080108015359D8B060EF8AF062EF8AF052 +:1014C00073EF8AF008010801565108010801525DC6 +:1014D000080108014C6F0801080157510801080173 +:1014E000535908014D6F0C0E080108014A25E96E99 +:1014F000000E080108014B21EA6EEF380F0B0801BE +:101500006A6F6AC86BF808016C6BD89008016B377A +:101510006C37D89008016B376C376BC879F86CC89A +:101520007AF8F9EC42F000EE0BF0EECF6AF8EDCF6E +:101530006BF808010801565108016A2708010801E3 +:10154000575108016B23080108014C5108016A2713 +:10155000080108014D5108016B2308016A51055C1F +:1015600008016B510658D8B0B8EF8AF0BAEF8AF08C +:101570007DEF8BF000EE05F0EECF6AF8EDCF6BF863 +:101580000B5008016A5F0C5008016B5B010E0801EB +:101590006A27000E6B2308010801565108016A5D95 +:1015A00008010801586F08010801575108016B59DB +:1015B0000801596F0801080159BFE1EF8AF0E3EF14 +:1015C0008AF031EF8BF058C8AAF859C8ABF8080177 +:1015D0006A6F000E08010801A96F08016A51FF0E29 +:1015E00008010801A76FFF0E0801A86F1CC0A6F82C +:1015F0000801080156510B2408010801A46F0801D5 +:10160000080157510C200801A56FA0EC23F0080138 +:1016100008015851080108014C5D08010801AA6F32 +:10162000080108015951080108014D590801AB6F23 +:1016300008016A6F000E08010801A96F08016A51CC +:10164000FF0E08010801A76FFF0E0801A86F1CC05C +:10165000A6F803C0A4F804C0A5F8A0EC23F07BEF23 +:101660008BF04CC8AAF84DC8ABF808016A6F000EA1 +:1016700008010801A96F08016A51FF0E080108015D +:10168000A76FFF0E0801A86F1CC0A6F800EE05F0BA +:10169000EECF6BF8EDCF6CF8035008016B5F045090 +:1016A00008016C5B00EE0BF0EECF6DF8EDCF6EF83D +:1016B00008010801565108016D270801080157511A +:1016C00008016E2308016B5108016D5D08016F6F01 +:1016D00008016C5108016E590801706FFF0E080176 +:1016E0006F2508010801A46FFF0E08017021080191 +:1016F000A56FA0EC23F0A1EF8BF04CC8AAF84DC861 +:10170000ABF808016A6F000E08010801A96F080113 +:101710006A51FF0E08010801A76FFF0E0801A86FAC +:101720001CC0A6F80801080156510B240801080145 +:10173000A46F0801080157510C200801A56FA0EC07 +:1017400023F03D28D8B43E28D8A4A9EF8BF0ABEF06 +:101750008BF0B5EF8BF056C83DF057C83EF04CC843 +:1017600031F04DC832F09AEF8CF03D50080108017D +:10177000565D3E50080108015759D8B0C2EF8BF0B2 +:10178000C4EF8BF030EF8CF0080156C86AF80801FE +:1017900057C86BF8080108014C5108016A27080175 +:1017A00008014D5108016B2300EE3DF0EECF6CF8BF +:1017B000EDCF6DF8315008016C27325008016D23D0 +:1017C00008016A5108016C5D08016B5108016D59EF +:1017D000D8A0EDEF8BF0EFEF8BF00CEF8CF0080161 +:1017E00056C86AF8080157C86BF8080108014C513F +:1017F00008016A27080108014D5108016B233D507B +:1018000008016A5D3E5008016B59D8B00AEF8CF0B0 +:101810000CEF8CF012EF8CF04CC831F04DC832F068 +:101820002AEF8CF000EE3DF0EECF6AF8EDCF6BF8CA +:10183000315008016A27325008016B230801080162 +:10184000565108016A5D316E0801080157510801BF +:101850006B59326E56C83DF057C83EF09AEF8CF087 +:10186000080156C86AF8080157C86BF80801080152 +:101870004C5108016A27080108014D5108016B23EA +:1018800000EE3DF0EECF6CF8EDCF6DF83150080171 +:101890006C27325008016D2308016A5108016C5D04 +:1018A00008016B5108016D59D8B059EF8CF05BEF0E +:1018B0008CF09AEF8CF000EE3DF0EECF6AF8EDCFB1 +:1018C0006BF8315008016A27325008016B23080178 +:1018D0000801565108016A5D0801080157510801C5 +:1018E0006B59D8A076EF8CF078EF8CF09AEF8CF0F3 +:1018F000080156C86AF8080157C86BF808010801C2 +:101900004C5108016A27080108014D5108016B2359 +:101910003D5008016A5F3E5008016B5B3150080181 +:101920006A5F325008016B5B08016A513126080179 +:101930006B5132220801080155515411D8B4A3EF5C +:101940008CF0A5EF8CF0E4EF8CF01750070AD8B4B8 +:10195000ACEF8CF0AEEF8CF0B2EF8CF00BC00DF072 +:101960000CC00EF018AEB7EF8CF0B9EF8CF0CFEFE3 +:101970008CF008016A6F010E08010801736F0801FD +:101980006A5108016B6F100E08010801726F08019F +:101990006B519FECA1F0B7EC24F0E4EF8CF0188EC3 +:1019A00018BCD5EF8CF0D7EF8CF0E4EF8CF0188CEE +:1019B0005AEC42F00F0E08010801A125156E000E29 +:1019C00008010801A221166E080108014FA1EBEFE2 +:1019D0008CF0EDEF8CF0D6EF8DF00801080154513A +:1019E000080108015A2508016A6F080108015551CC +:1019F000080108015B2108016B6F000E0801080156 +:101A00005C2108016C6F000E080108015D210801CE +:101A10006D6F010E252408016E6F000E262008014F +:101A20006F6F000E27200801706F000E282008013C +:101A3000716F08016D51080171190EE108016C51B7 +:101A40000801701909E108016B5108016F1904E1DF +:101A500008016A5108016E19D8A431EF8DF033EFF7 +:101A60008DF0D6EF8DF0010E2526000E2622000EF9 +:101A70002722000E2822B9EF8DF008016A6F0C0EA4 +:101A8000176E08016A5108016A6F010E080108010A +:101A9000736F08016A5108016B6F110E080108018C +:101AA000726F08016B519FECA1F0D6EF8DF0080129 +:101AB0006A6F0B0E176E08016A515AEC42F01F0E46 +:101AC00008010801A125156E000E08010801A221D8 +:101AD000166EC4EF8DF008010801695124180EE15B +:101AE000080108016851231809E10801080167513C +:101AF000221804E10801080166512118D8A483EFD7 +:101B00008DF085EF8DF09BEF8DF008016A6F000E70 +:101B100008010801736F08016A5108016B6F100E0C +:101B200008010801726F08016B519FECA1F06CEC89 +:101B300033F0D6EF8DF008016A6F0A0E176E0801B8 +:101B40006A51C4EF8DF008016A6F000E08010801A8 +:101B5000736F08016A5108016B6F100E08010801CC +:101B6000726F08016B519FECA1F06CEC33F0D6EF73 +:101B70008DF01750060A81E0010A99E00F0AABE0E8 +:101B8000010AE1E0A1EF8DF008016A6F010E080182 +:101B90000801736F08016A5108016B6F100E08018C +:101BA0000801726F08016B519FECA1F0120008014F +:101BB000276F000E080108011E6F08012751000E53 +:101BC000080108011E65E7EF8DF0E9EF8DF0EBEFFE +:101BD0008DF0F6EF93F01EC871F81DEC2BF00801A4 +:101BE000276F000E08010801206F08012751080126 +:101BF000276F000E080108011F6F08012751080117 +:101C0000276F000E080108011D6F0801275119B246 +:101C10000CEF8EF00EEF8EF015EF8EF019A413EF8F +:101C20008EF015EF8EF02DEF8EF0CBEC3DF000092D +:101C3000D8B41DEF8EF01FEF8EF02DEF8EF008015F +:101C4000276F100E08010801206F08012751000EB0 +:101C500019B4010E080108011F6F18AA32EF8EF0A7 +:101C600034EF8EF058EF8EF05AEC42F00801080184 +:101C7000A151135C0801276F08010801A2511458F3 +:101C80000801286F08012851800A800F010ED8B47E +:101C9000275DD8B04EEF8EF050EF8EF058EF8EF0FB +:101CA0000801276F100E08010801206F0801275155 +:101CB00018AC5DEF8EF05FEF8EF083EF8EF05AEC94 +:101CC00042F008010801A151155C0801276F0801C5 +:101CD0000801A25116580801286F08012851800AEE +:101CE000800F010ED8B4275DD8B079EF8EF07BEF6E +:101CF0008EF083EF8EF00801276F100E08010801A7 +:101D0000206F0801275117500B0AD8A48AEF8EF0D4 +:101D10008CEF8EF0B6EF8EF05AEC42F0080108011D +:101D2000A151155C0801276F08010801A25116583E +:101D30000801286F08012851800A800F010ED8B4CD +:101D4000275DD8B0A6EF8EF0A8EF8EF0B6EF8EF03C +:101D50000801276F110E08010801206F08012751A3 +:101D60000801276F0C0E176E080127511750040A3F +:101D7000D8A4BDEF8EF0BFEF8EF018EF90F0000EFC +:101D800008010801216F000E0801226F030E0801EF +:101D90000801215D000E08012259D8A0D2EF8EF073 +:101DA000D4EF8EF0D6EF8EF018EF90F00801080116 +:101DB0002151140DF3CF27F8100E08012727000139 +:101DC0009F0E08012725E96EEA6A0001000EEA224B +:101DD000EE50ED10D8A4EFEF8EF0F1EF8EF0F3EFB0 +:101DE0008EF018EF90F000EE1AF008010801215172 +:101DF000140DF3CF27F8100E0801272700019F0EBE +:101E000008012725E16EE26A0001000EE222E65297 +:101E1000EE52ED50E518EFCFE8FFD8B4E718D8A49C +:101E200014EF8FF016EF8FF006EF90F0B7EC24F080 +:101E30000A0E08010801B06F000E0801B16F080119 +:101E400008012151140D9F0E0801276F000E286F05 +:101E5000F35008012727E86AF3BEE8680801282341 +:101E600027C8AEF828C8AFF8330E08010801AC6FD8 +:101E7000000E0801AD6F58EC3AF00801080121513D +:101E8000140DF3CF27F80A0E0801272700019F0E33 +:101E900008012725E96EEA6A0001000EEA22EECF6A +:101EA0002BF0EDCF2CF0080108012151140DF3CFD8 +:101EB00027F80C0E0801272700019F0E080127258F +:101EC000E96EEA6A0001000EEA22EECF28F8EECFB2 +:101ED00029F8EECF2AF8EECF2BF8010E08012825BD +:101EE000256E000E08012921266E000E08012A2108 +:101EF000276E000E08012B21286E00EE35F0EECF84 +:101F000027F8EDCF28F8335008012727345008016F +:101F100028232B50080127272C50080128232D5057 +:101F2000080127191A6E2E50080128191B6E080186 +:101F3000276F120E08010801206F080127510801C0 +:101F4000276F060E176E08012751140E08010801AD +:101F5000626F000E0801636F080108012151020839 +:101F600008010801606F080108012251D8A0E82A81 +:101F700000080801616F83EC3BF060C8AAF861C8F3 +:101F8000ABF80801276F010E08010801A96F0801CD +:101F90002751080108012129140D9F0E0801286FFF +:101FA000000E296FF35008012827E86AF3BEE8689D +:101FB0000801292328C8A7F829C8A8F808012A6F0A +:101FC000010E08010801A66F08012A510801080145 +:101FD0002151140D9F0E08012B6F000E2C6FF35032 +:101FE00008012B27E86AF3BEE86808012C232BC8F8 +:101FF000A4F82CC8A5F8A0EC23F0000E0001000105 +:10200000D76F000E0001D86F18EF90F0080108019B +:10201000214B222B030E08010801215D000E08014F +:102020002259D8A016EF90F018EF90F0D6EF8EF06E +:10203000080108012051D8B420EF90F022EF90F071 +:1020400035EF90F0080108011F51D8B42AEF90F045 +:102050002DEF90F0010E2EEF90F0000E0801080118 +:10206000736F20C872F89FECA1F018B83AEF90F0A7 +:102070003CEF90F0BEEF90F01750070AD8A443EF62 +:1020800090F045EF90F090EF90F0C4EC43F00F50DB +:1020900008010801A15D0801276F1050080108011F +:1020A000A2590801286F115008010801A35908011D +:1020B000296F125008010801A45908012A6F08016C +:1020C0002AAF65EF90F067EF90F069EF90F0E9EFDD +:1020D00093F01850070B060AD8A471EF90F073EF35 +:1020E00090F092EF90F0000E18B6010E0801080172 +:1020F000206F1EC82DF895EC12F01EC82DF895EC37 +:1021000012F008010801206788EF90F08AEF90F044 +:1021100090EF90F00801276F0E0E176E08012751FF +:10212000E9EF93F0B7EC24F00801276F020E0801E5 +:102130000801736F080127510801286F100E08016C +:102140000801726F080128519FECA1F0C4EC43F024 +:10215000740E08010801A1250F6E350E0801080153 +:10216000A221106E060E08010801A321116E000EB7 +:1021700008010801A421126EE9EF93F0C4EC43F0CA +:102180000F5008010801A15D0801276F10500801D8 +:102190000801A2590801286F115008010801A3592C +:1021A0000801296F125008010801A45908012A6F7B +:1021B00008012AAFDEEF90F0E0EF90F0E2EF90F050 +:1021C000E9EF93F0B7EC24F02DEF93F01DEC43F022 +:1021D0000009D8B4EEEF90F0F0EF90F01BEF91F023 +:1021E0000801276F010E176E080127513FA4FBEF6E +:1021F00090F0FDEF90F00DEF91F00801276F010EC8 +:10220000080108012F6F0801275133C02DF834C091 +:102210002EF848EC3BF01BEF91F00801276F010E00 +:10222000080108012F6F0801275133C02DF834C071 +:102230002EF80DEC3BF052EF93F00801230E08014D +:1022400008012D6F0801080E08012E6FD3EC94F0E1 +:102250000009D8B42EEF91F030EF91F01BEF91F020 +:10226000DCEC40F00009D8B438EF91F03AEF91F08F +:1022700072EF91F023C833F024C834F025C835F04C +:1022800026C836F00801276F020E176E0801275185 +:1022900000EE35F0EECF27F8EDCF28F833500801E7 +:1022A00027273450080128232B50080127272C50BA +:1022B000080128232D50080127191A6E2E500801F5 +:1022C00028191B6E0801276F000E426E0801275166 +:1022D000270E1D6E000E1E6E000E1F6E000E206E6D +:1022E0008EEF91F0C4EC43F0740E08010801A125B3 +:1022F0000F6E350E08010801A221106E060E0801AE +:102300000801A321116E000E08010801A421126E1C +:102310000801276F000E176E0801275152EF93F046 +:102320005AEC42F0A1C813F0A2C814F0330E080111 +:1023300008014C6F000E08014D6F0EEC23F00801F0 +:10234000276F030E176E0801275152EF93F0370ED7 +:10235000080108014E6F000E08014F6F330E08018F +:1023600008014C6F000E08014D6FE7EC1AF00009F0 +:10237000D8A4BDEF91F0BFEF91F0EEEF91F05AECE1 +:1023800042F0135008010801A15F14500801080130 +:10239000A25B08010801A1511D5C08010801A251BE +:1023A0001E58D8B0D6EF91F0D8EF91F01BEF91F016 +:1023B000060E4260DEEF91F0E0EF91F0E6EF91F073 +:1023C000422AD8901D361E361F3620360801276F48 +:1023D000020E176E0801275152EF93F00801276F84 +:1023E000020E08010801206F080127510801276F1C +:1023F000000E080108011F6F080127510801276F0F +:10240000050E176E0801275152EF93F00801276F50 +:10241000020E08010801206F080127510801276FEB +:10242000010E080108011F6F0801275100EE42F05C +:10243000030EEF641EEF92F020EF92F01BEF91F08D +:102440000801276F040E426E08012751200E1D6EF1 +:10245000EF0E1E6E090E1F6E000E206E52EF93F0EF +:10246000020E426036EF92F038EF92F04AEF92F0AF +:102470000801276F120E08010801206F080127517B +:102480000801276F010E080108011F6F080127517D +:102490001BEF91F018A64FEF92F051EF92F063EF1F +:1024A00092F00801276F140E08010801206F08013F +:1024B00027510801276F010E080108011D6F08014F +:1024C00027516BEF92F00801276F020E08010801F7 +:1024D000206F0801275152EF93F0050E426073EF11 +:1024E00092F075EF92F087EF92F00801276F100ECF +:1024F00008010801206F080127510801276F010E0C +:10250000080108011F6F080127511BEF91F0080116 +:10251000276F080E176E080127510801276F110E4B +:1025200008010801206F0801275152EF93F0050EB2 +:1025300042609DEF92F09FEF92F0B1EF92F00801B0 +:10254000276F110E08010801206F080127510801AB +:10255000276F010E080108011F6F080127511BEFAB +:1025600091F00801276F140E08010801206F08017F +:1025700027510801276F010E080108011D6F08018E +:10258000275152EF93F00801276F140E080108013C +:10259000206F080127510801276F010E080108016B +:1025A0001D6F0801275152EF93F0050E4260DBEFDB +:1025B00092F0DDEF92F0EFEF92F00801276F100E2E +:1025C00008010801206F080127510801276F010E3B +:1025D000080108011F6F080127511BEF91F0080146 +:1025E000276F140E08010801206F08012751080108 +:1025F000276F010E080108011D6F0801275152EFD6 +:1026000093F0050E426007EF93F009EF93F01BEF94 +:1026100093F00801276F110E08010801206F0801CF +:1026200027510801276F010E080108011F6F0801DB +:1026300027511BEF91F00801276F140E08010801C4 +:10264000206F080127510801276F010E08010801BA +:102650001D6F0801275152EF93F01750000A01E156 +:10266000B5D5010A01E1E9D5030A01E159D6010A0C +:1026700001E16DD6060A01E1C9D6030A01E1F0D6EF +:10268000010A01E12AD70F0A01E151D7010A01E14C +:102690007AD7030A8AE0010A01E11FD7070AB1E0ED +:1026A0001BEF91F0080108012051D8B45AEF93F0C4 +:1026B0005CEF93F0DDEF93F0080108011F51D8B4EF +:1026C00064EF93F066EF93F0D1EF93F0422AD89045 +:1026D0001D361E361F3620360950295C08010801B8 +:1026E000216F0A502A580801226F00EE09F010EEFF +:1026F00029F0E652EE52ED50E55C02E1EF50E75C66 +:10270000D8B085EF93F087EF93F09DEF93F000EE54 +:1027100003F0EECF27F8EDCF28F801500801275F2E +:1027200002500801285B08012751080108012127F0 +:10273000080128510801080122230801080121513C +:102740000801276F0801080122510801286F0801BC +:10275000296B08012A6B08012751215E08012851C5 +:10276000225A08012951235A08012A51245A0801E2 +:10277000080121512F26080108012251302209C0E9 +:1027800029F00AC02AF00801276F000E080108018D +:10279000736F0801275120C872F89FECA1F0DDEF9C +:1027A00093F00801276F010E08010801736F0801FB +:1027B000275120C872F89FECA1F0080108011D51B3 +:1027C000D8B4E5EF93F0E7EF93F0E9EF93F06CEC1A +:1027D00033F0080108011E2B000E080108011E65D8 +:1027E000F4EF93F0F6EF93F0EBEF8DF0000E0801AD +:1027F0000801216F000E0801226F030E0801080175 +:10280000215D000E08012259D8A009EF94F00BEFCA +:1028100094F00DEF94F0D2EF94F0080108012151EB +:10282000140DF3CF27F8100E0801272700019F0E83 +:1028300008012725E96EEA6A0001000EEA22EE503F +:10284000ED10D8A426EF94F028EF94F02AEF94F03E +:10285000D2EF94F0080108012151140DF3CF27F8AD +:10286000120E0801272700019F0E08012725E96E97 +:10287000EA6A0001000EEA22EECF28F8EDCF29F82F +:102880005AEC42F00801285108010801A15D080135 +:102890002A6F0801295108010801A25908012B6F6C +:1028A000DD0E08012A5D010E2B59D8A05AEF94F0D5 +:1028B0005CEF94F0C0EF94F0140E08010801626F11 +:1028C000000E0801636F0801080121510208080188 +:1028D0000801606F080108012251D8A0E82A000809 +:1028E0000801616F83EC3BF060C8AAF861C8ABF8DF +:1028F0000801276F010E08010801A96F080127517F +:10290000080108012129140D9F0E0801286F000EEF +:10291000296FF35008012827E86AF3BEE868080128 +:10292000292328C8A7F829C8A8F808012A6F010E8A +:1029300008010801A66F08012A5108010801215168 +:10294000140D9F0E08012B6F000E2C6FF350080121 +:102950002B27E86AF3BEE86808012C232BC8A4F8EB +:102960002CC8A5F8A0EC23F0000E00010001D76FE1 +:10297000000E0001D86F080108012107D8A0220726 +:1029800008010801214B222B030E08010801215DDB +:10299000000E08012259D8A0D0EF94F0D2EF94F0A5 +:1029A0000DEF94F0120059EF9BF00801486F000EF4 +:1029B00007010701326F080148510801486F000EF6 +:1029C00007010701386F080148510001780E08011E +:1029D00008014C6F0001000E08014D6F0EEC23F052 +:1029E00007010701322BC4EC43F0A1C8C6F6A2C808 +:1029F000C7F6A3C8C8F6A4C8C9F60801486F020EF6 +:102A000007010701A66F080148517CEF9BF0040104 +:102A1000B70E080108014E6F0401040E08014F6F44 +:102A20000001780E080108014C6F0001000E08013A +:102A30004D6FE7EC1AF00009D8A421EF95F023EFD1 +:102A400095F071EF95F0C4EC43F006010601C65114 +:102A500008010801A15D0801486F06010601C75180 +:102A600008010801A2590801496F06010601C85171 +:102A700008010801A35908014A6F06010601C9515E +:102A800008010801A45908014B6FF30E485D9E0E22 +:102A90004959000E4A59000E08014B59D8A053EF6E +:102AA00095F055EF95F06FEF95F00801486F010E26 +:102AB00007010701A66F08014851020E070107012F +:102AC000326565EF95F067EF95F06FEF95F00801CF +:102AD000486F060E07010701A66F080148517CEFF9 +:102AE0009BF078C0B3F479C0B4F47AC0B5F47BC07D +:102AF000B6F40801486F030E07010701A66F08012D +:102B00004851350E08010801536F000E0801546F3B +:102B1000000E08010801516F000E0801526F0801F4 +:102B2000486F040E08010801506F08014851B30EA8 +:102B30000801496F040E4A6F080149C84CF80801A2 +:102B40004AC84DF8080108014E6B08014F6B22EC92 +:102B5000D7F007010701A26F07010701A229D8A436 +:102B6000B4EF95F0B6EF95F0B8EF95F07CEF9BF0F1 +:102B70000801486F040E07010701A66F08014851BC +:102B8000A2C74CF893EC39F008014D514C11D8A470 +:102B9000CCEF95F0CEEF95F0D0EF95F07CEF9BF079 +:102BA00006010601E34BE42BE4C653F867EC3DF065 +:102BB000E3C653F867EC3DF00801486F010E0801C9 +:102BC0000801536F0801485167EC3DF00801486F58 +:102BD000000E08010801536F0801485167EC3DF0F1 +:102BE0000801486F000E08010801536F08014851A1 +:102BF00067EC3DF00801486F010E08010801536FB2 +:102C00000801485167EC3DF00801486F000E0801CB +:102C10000801536F0801485167EC3DF00801486F07 +:102C2000000E08010801536F0801485167EC3DF0A0 +:102C30000801486F000E08010801536F0801485150 +:102C400067EC3DF00801486F000E08010801536F62 +:102C50000801485167EC3DF00801486F000E08017B +:102C60000801536F0801485167EC3DF00801486FB7 +:102C7000000E08010801536F0801485167EC3DF050 +:102C80000701070107510611D8B449EF96F04BEF41 +:102C900096F053EF96F006C74CF807C74DF836ECA0 +:102CA0001AF059EF96F022C74CF823C74DF881EC83 +:102CB00019F00801486F000E08010801536F080160 +:102CC000485167EC3DF03CC753F867EC3DF0080114 +:102CD000486F000E08010801536F0801485167EC66 +:102CE0003DF00801486F010E08010801536F08010B +:102CF000485167EC3DF053EC21F0C4EC43F0A1C81F +:102D0000C6F6A2C8C7F6A3C8C8F6A4C8C9F6080183 +:102D1000486F050E07010701A66F080148517CEFB7 +:102D20009BF0A2C74CF8D9EC39F008014D514C1179 +:102D3000D8A49DEF96F09FEF96F0DBEF96F0C4ECF1 +:102D400043F006010601C65108010801A15D080112 +:102D5000486F06010601C75108010801A259080180 +:102D6000496F06010601C85108010801A35908016D +:102D70004A6F06010601C95108010801A45908015A +:102D80004B6FF30E485D9E0E4959000E4A59000ED6 +:102D900008014B59D8A0CFEF96F0D1EF96F06FEF26 +:102DA00095F00801486F060E07010701A66F08019C +:102DB00048517CEF9BF008013D0E080108014D6F62 +:102DC0000801080E08014E6F35EC3DF008013C0E7D +:102DD000080108014D6F0801080E08014E6F35EC1F +:102DE0003DF006010601E451080108013D1906E124 +:102DF00006010601E351080108013C19D8B403EFAC +:102E000097F005EF97F009EF97F08FEC41F07CEF2A +:102E10009BF008013F0E080108014D6F0801080EE4 +:102E200008014E6F35EC3DF008013E0E0801080127 +:102E30004D6F0801080E08014E6F35EC3DF008019A +:102E4000410E080108014D6F0801080E08014E6F80 +:102E500035EC3DF00801400E080108014D6F0801F6 +:102E6000080E08014E6F35EC3DF00801430E0801D5 +:102E700008014D6F0801080E08014E6F35EC3DF05A +:102E80000801420E080108014D6F0801080E0801F3 +:102E90004E6F35EC3DF00801450E080108014D6FFD +:102EA0000801080E08014E6F35EC3DF00801440E94 +:102EB000080108014D6F0801080E08014E6F35EC3E +:102EC0003DF00801470E080108014D6F0801080E8A +:102ED00008014E6F35EC3DF00801460E080108016F +:102EE0004D6F0801080E08014E6F35EC3DF0A7EF5D +:102EF00097F0D5EC37F00801310E080108014D6F4D +:102F00000801080E08014E6F35EC3DF00801300E47 +:102F1000080108014D6F0801080E08014E6F35ECDD +:102F20003DF00801310E080108014D6F0801080E3F +:102F300008014E6F35EC3DF00801300E0801080124 +:102F40004D6F0801080E08014E6F35EC3DF0080189 +:102F500008014007D8A0410708014029D8B44129F9 +:102F6000D8A4B5EF97F0B7EF97F079EF97F098EF17 +:102F700098F0D5EC37F00801330E080108014D6FC9 +:102F80000801080E08014E6F35EC3DF00801320EC5 +:102F9000080108014D6F0801080E08014E6F35EC5D +:102FA0003DF00801350E080108014D6F0801080EBB +:102FB00008014E6F35EC3DF00801340E08010801A0 +:102FC0004D6F0801080E08014E6F35EC3DF0080109 +:102FD000390E080108014D6F0801080E08014E6FF7 +:102FE00035EC3DF00801380E080108014D6F08016D +:102FF000080E08014E6F35EC3DF00801370E080150 +:1030000008014D6F0801080E08014E6F35EC3DF0C8 +:103010000801360E080108014D6F0801080E08016D +:103020004E6F35EC3DF008013B0E080108014D6F75 +:103030000801080E08014E6F35EC3DF008013A0E0C +:10304000080108014D6F0801080E08014E6F35ECAC +:103050003DF00801080132053311D8A432EF98F091 +:1030600034EF98F07BEF98F0080108013405351132 +:10307000D8A43DEF98F03FEF98F07BEF98F008016F +:1030800008013A51040A3B11D8A449EF98F04BEFDC +:1030900098F07BEF98F0070108830401B30E080154 +:1030A00008014D6F0401040E08014E6F35EC3DF030 +:1030B0000401B40E080108014D6F0401040E08015B +:1030C0004E6F35EC3DF00401B50E080108014D6F5F +:1030D0000401040E08014E6F35EC3DF00401B60EFC +:1030E000080108014D6F0401040E08014E6F35EC14 +:1030F0003DF08AEF9AF088EF98F008012F0E080152 +:1031000008014D6F0801080E08014E6F35EC3DF0C7 +:10311000080108013A07D8A03B0708013A29D8B4AA +:103120003B29D8A496EF98F098EF98F07DEF98F0AF +:10313000080108014207D8A0430708014229D8B472 +:103140004329D8A4A6EF98F0A8EF98F0B9EF97F02C +:1031500089EF99F0D5EC37F00801330E080108012A +:103160004D6F0801080E08014E6F35EC3DF0080167 +:10317000320E080108014D6F0801080E08014E6F5C +:1031800035EC3DF00801350E080108014D6F0801CE +:10319000080E08014E6F35EC3DF00801340E0801B1 +:1031A00008014D6F0801080E08014E6F35EC3DF027 +:1031B0000801390E080108014D6F0801080E0801C9 +:1031C0004E6F35EC3DF00801380E080108014D6FD7 +:1031D0000801080E08014E6F35EC3DF00801370E6E +:1031E000080108014D6F0801080E08014E6F35EC0B +:1031F0003DF00801360E080108014D6F0801080E68 +:1032000008014E6F35EC3DF008013B0E0801080146 +:103210004D6F0801080E08014E6F35EC3DF00801B6 +:103220003A0E080108014D6F0801080E08014E6FA3 +:1032300035EC3DF00801080132053311D8A423EF25 +:1032400099F025EF99F06CEF99F008010801340529 +:103250003511D8A42EEF99F030EF99F06CEF99F07A +:10326000080108013A51040A3B11D8A43AEF99F039 +:103270003CEF99F06CEF99F0070108830401B30E5D +:10328000080108014D6F0401040E08014E6F35EC72 +:103290003DF00401B40E080108014D6F0401040E55 +:1032A00008014E6F35EC3DF00401B50E0801080130 +:1032B0004D6F0401040E08014E6F35EC3DF0040122 +:1032C000B60E080108014D6F0401040E08014E6F8F +:1032D00035EC3DF08AEF9AF079EF99F008012F0E66 +:1032E000080108014D6F0801080E08014E6F35EC0A +:1032F0003DF0080108013A07D8A03B0708013A2928 +:10330000D8B43B29D8A487EF99F089EF99F06EEFF4 +:1033100099F0080108014407D8A04507080144298D +:10332000D8B44529D8A497EF99F099EF99F0AAEF6E +:1033300098F07AEF9AF0D5EC37F00801330E0801D7 +:1033400008014D6F0801080E08014E6F35EC3DF085 +:103350000801320E080108014D6F0801080E08012E +:103360004E6F35EC3DF00801350E080108014D6F38 +:103370000801080E08014E6F35EC3DF00801340ECF +:10338000080108014D6F0801080E08014E6F35EC69 +:103390003DF00801390E080108014D6F0801080EC3 +:1033A00008014E6F35EC3DF00801380E08010801A8 +:1033B0004D6F0801080E08014E6F35EC3DF0080115 +:1033C000370E080108014D6F0801080E08014E6F05 +:1033D00035EC3DF00801360E080108014D6F08017B +:1033E000080E08014E6F35EC3DF008013B0E080158 +:1033F00008014D6F0801080E08014E6F35EC3DF0D5 +:1034000008013A0E080108014D6F0801080E080175 +:103410004E6F35EC3DF00801080132053311D8A498 +:1034200014EF9AF016EF9AF05DEF9AF00801080198 +:1034300034053511D8A41FEF9AF021EF9AF05DEF13 +:103440009AF0080108013A51040A3B11D8A42BEF65 +:103450009AF02DEF9AF05DEF9AF0070108830401CE +:10346000B30E080108014D6F0401040E08014E6FF0 +:1034700035EC3DF00401B40E080108014D6F040164 +:10348000040E08014E6F35EC3DF00401B50E080145 +:1034900008014D6F0401040E08014E6F35EC3DF03C +:1034A0000401B60E080108014D6F0401040E080165 +:1034B0004E6F35EC3DF08AEF9AF06AEF9AF0080112 +:1034C0002F0E080108014D6F0801080E08014E6F0C +:1034D00035EC3DF0080108013A07D8A03B07080188 +:1034E0003A29D8B43B29D8A478EF9AF07AEF9AF029 +:1034F0005FEF9AF0080108014607D8A047070801C6 +:103500004629D8B44729D8A488EF9AF08AEF9AF0D0 +:103510009BEF99F08FEC41F0A2C74CF8A3EC36F08A +:1035200007010701A2690801486F070E070107019B +:10353000A66F080148510701070108B3A2EF9AF0EE +:10354000A4EF9AF0B1EF9AF0000E04010401B36FFA +:10355000000E0401B46F000E0401B56F000E0401EB +:10356000B66F2DC8E9FF2EC8EAFF0401B3C4EEFF11 +:103570000401B4C4EEFF0401B5C4EEFF0401B6C4F7 +:10358000EEFF010E7FEF9BF0010E0701070138658A +:10359000CCEF9AF0CEEF9AF0DFEF9AF02DC8E9FF6A +:1035A0002EC8EAFF000EEE6E000EEE6E000EEE6EFE +:1035B000000EED6EED52ED52010E7FEF9BF0070114 +:1035C0000701382B00017F517C117D117E11D8B489 +:1035D000ECEF9AF0EEEF9AF06FEF95F0000100013A +:1035E0007C5100010001781B000100017D510001A8 +:1035F0000001791B000100017E51000100017A1BCE +:10360000000100017F51000100017B1B000100014E +:103610007851000100017C1B00010001795100017B +:1036200000017D1B000100017A51000100017E1B99 +:10363000000100017B51000100017F1B000100011E +:103640007C5100010001781B000100017D51000147 +:103650000001791B000100017E51000100017A1B6D +:10366000000100017F51000100017B1B0801486F30 +:10367000000E07010701326F0801485107010701D9 +:10368000A229D8B446EF9BF048EF9BF04FEF9BF098 +:10369000A2C74CF8A3EC36F007010701A2690801A4 +:1036A000486F010E07010701A66F080148517CEF22 +:1036B0009BF007010701A651000A02E1D5EF94F043 +:1036C000010A02E1E5EF94F0030A02E107EF95F049 +:1036D000010A02E181EF95F0070A02E1C0EF95F0DF +:1036E000010A02E191EF96F0030A01E14DD7010AC8 +:1036F00001E121D77CEF9BF0000E7FEF9BF01200E1 +:103700000201730E08010801896F0201020E08010F +:103710008A6F7BC8E9FF7CC8EAFF0801EECF8FF80B +:103720000801EECF90F80801EECF91F80801EECF36 +:1037300092F87DC8E9FF7EC8EAFF0801EECFA3F842 +:103740000801EECFA4F80801EECFA5F80801EECFEE +:10375000A6F87FC8E9FF80C8EAFF0801EECF9BF812 +:103760000801EECF9CF80801EECF9DF80801EECFDE +:103770009EF881C8E9FF82C8EAFF0801EECF9FF8F2 +:103780000801EECFA0F80801EECFA1F80801EECFB6 +:10379000A2F883C8E9FF84C8EAFF0801EECF8BF8DE +:1037A0000801EECF8CF80801EECF8DF80801EECFBE +:1037B0008EF8730E0801AF6F020EB06F080108019A +:1037C0007A510801B01905E1080108017951080191 +:1037D000AF19D8A4EEEF9BF0F0EF9BF070EF9CF0E8 +:1037E0000801AF6F000E08010801886F0801AF5192 +:1037F0000F0E08010801886500EF9CF002EF9CF0B5 +:1038000004EF9CF06EEF9CF0030E0801080179258F +:10381000E96E000E080108017A21EA6EEF500801F6 +:103820000801876F79C8E9FF7AC8EAFF030E08012B +:1038300008017925E16E000E080108017A21E26E87 +:10384000EFCFE7FF79C8E9FF7AC8EAFF080187C828 +:10385000EFFF010E080108017925E96E000E08014D +:1038600008017A21EA6EEF5008010801876F020E05 +:10387000080108017925E96E000E080108017A2186 +:10388000EA6E010E080108017925E16E000E0801BB +:1038900008017A21E26EEFCFE7FF020E080108016E +:1038A0007925E96E000E080108017A21EA6E080107 +:1038B00087C8EFFF040E080108017927000E0801F0 +:1038C0007A2308010801882B0F0E0801080188657A +:1038D0006CEF9CF06EEF9CF004EF9CF026EF9DF0F7 +:1038E0000801AF6F000E08010801886F0801AF5191 +:1038F0000F0E08010801886580EF9CF082EF9CF0B4 +:1039000084EF9CF026EF9DF079C8E9FF7AC8EAFFC2 +:10391000080108018851040DF3CFAFF8030E080128 +:10392000AF270801AF510801080189250801B06FD0 +:10393000E86A0801AFBFE868080108018A210801A8 +:10394000B16FB0C8E1FFB1C8E2FFEFCFE7FF0801F8 +:103950000801794B7A2B79C8E9FF7AC8EAFF080198 +:1039600008018851040DF3CFAFF8020E0801AF270C +:103970000801AF510801080189250801B06FE86A04 +:103980000801AFBFE868080108018A210801B16F8A +:10399000B0C8E1FFB1C8E2FFEFCFE7FF08010801BF +:1039A000794B7A2B79C8E9FF7AC8EAFF0801080148 +:1039B0008851040DF3CFAFF8010E0801AF270801BD +:1039C000AF510801080189250801B06FE86A0801B4 +:1039D000AFBFE868080108018A210801B16FB0C8CB +:1039E000E1FFB1C8E2FFEFCFE7FF08010801794B23 +:1039F0007A2B79C8E9FF7AC8EAFF080108018851E3 +:103A0000040DF3500801080189250801AF6FE86A29 +:103A1000F3BEE868080108018A210801B06FAFC849 +:103A2000E1FFB0C8E2FFEFCFE7FF08010801794BE3 +:103A30007A2B08010801882B0F0E08010801886500 +:103A400024EF9DF026EF9DF084EF9CF00801AF6F0E +:103A50000D0E08010801876F0801AF510801AF6F13 +:103A6000080E08010801866F0801AF510801AF6F09 +:103A7000020E08010801856F0801AF510801AF6F00 +:103A8000000E08010801886F0801AF514F0E0801B0 +:103A9000080188654EEF9DF050EF9DF052EF9DF0CC +:103AA0003FEFA1F0140E0801080188615AEF9DF064 +:103AB0005CEF9DF0D1EF9DF00801A3C8AFF80801BD +:103AC000A4C8B0F80801A5C8B1F80801A6C8B2F8A2 +:103AD0000801AF1FB01FB11FB21F080108019F519D +:103AE0000801AF150801B36F08010801A0510801D2 +:103AF000B0150801B46F08010801A1510801B11502 +:103B00000801B56F08010801A2510801B2150801AA +:103B1000B66F080108019B5108010801A3150801AF +:103B2000B76F080108019C5108010801A41508019C +:103B3000B86F080108019D5108010801A515080189 +:103B4000B96F080108019E5108010801A615080176 +:103B5000BA6F0801B3510801B71108010801936F4A +:103B60000801B4510801B8110801946F0801B5515A +:103B70000801B9110801956F0801B6510801BA1181 +:103B80000801966F990E08010801976F790E0801D8 +:103B9000986F820E0801996F5A0E08019A6F2FEFE5 +:103BA0009FF0130E080108018865D9EF9DF0DBEF47 +:103BB0009DF031EF9EF0280E080108018861E3EFC7 +:103BC0009DF0E5EF9DF031EF9EF0080108019B515B +:103BD00008010801A3190801AF6F080108019C51F1 +:103BE00008010801A4190801B06F080108019D51DE +:103BF00008010801A5190801B16F080108019E51CB +:103C000008010801A6190801B26F080108019F51B7 +:103C10000801AF1908010801936F08010801A051BC +:103C20000801B0190801946F08010801A1510801A9 +:103C3000B1190801956F08010801A2510801B219D4 +:103C40000801966FA10E08010801976FEB0E08019D +:103C5000986FD90E0801996F6E0E08019A6F2FEFB9 +:103C60009FF0270E08010801886539EF9EF03BEFB1 +:103C70009EF0E5EF9EF03C0E08010801886143EFDD +:103C80009EF045EF9EF0E5EF9EF0080108019F5180 +:103C9000080108019B150801AF6F08010801A05138 +:103CA000080108019C150801B06F08010801A15125 +:103CB000080108019D150801B16F08010801A25112 +:103CC000080108019E150801B26F080108019F5103 +:103CD00008010801A3150801B36F08010801A051EC +:103CE00008010801A4150801B46F08010801A151D9 +:103CF00008010801A5150801B56F08010801A251C6 +:103D000008010801A6150801B66F080108019B51BA +:103D100008010801A3150801B76F080108019C51AB +:103D200008010801A4150801B86F080108019D5198 +:103D300008010801A5150801B96F080108019E5185 +:103D400008010801A6150801BA6F0801B35108015E +:103D5000B7110801BB6F0801B4510801B81108017F +:103D6000BC6F0801B5510801B9110801BD6F080108 +:103D7000B6510801BA110801BE6F0801AF51080120 +:103D8000BB1108010801936F0801B0510801BC1173 +:103D90000801946F0801B1510801BD110801956F28 +:103DA0000801B2510801BE110801966FDC0E08012E +:103DB0000801976FBC0E0801986F1B0E0801996FE0 +:103DC0008F0E08019A6F2FEF9FF0080108019B5199 +:103DD00008010801A3190801AF6F080108019C51EF +:103DE00008010801A4190801B06F080108019D51DC +:103DF00008010801A5190801B16F080108019E51C9 +:103E000008010801A6190801B26F080108019F51B5 +:103E10000801AF1908010801936F08010801A051BA +:103E20000801B0190801946F08010801A1510801A7 +:103E3000B1190801956F08010801A2510801B219D2 +:103E40000801966FD60E08010801976FC10E080190 +:103E5000986F620E0801996FCA0E08019A6F0F0ED3 +:103E600008010801886537EF9FF039EF9FF056EFA2 +:103E7000A0F0080108018751040DF3500801080162 +:103E800089250801AF6FE86AF3BEE86808010801F8 +:103E90008A210801B06FAFC8E9FFB0C8EAFF080186 +:103EA000EECFA7F80801EECFA8F80801EECFA9F8E9 +:103EB0000801EECFAAF8080108018651040DF3505D +:103EC0000801080189250801AF6FE86AF3BEE868B8 +:103ED000080108018A210801B06FAFC8E9FFB0C826 +:103EE000EAFF0801EECFABF80801EECFACF808010D +:103EF000EECFADF80801EECFAEF808010801AB51E6 +:103F000008010801A71B08010801AC5108010801BC +:103F1000A81B08010801AD5108010801A91B0801EF +:103F20000801AE5108010801AA1B080108018551CA +:103F3000040DF3500801080189250801AF6FE86AF4 +:103F4000F3BEE868080108018A210801B06FAFC814 +:103F5000E9FFB0C8EAFF0801EECFABF80801EECFE9 +:103F6000ACF80801EECFADF80801EECFAEF80801CD +:103F70000801AB5108010801A71B08010801AC5159 +:103F800008010801A81B08010801AD51080108013A +:103F9000A91B08010801AE5108010801AA1B08016C +:103FA000080188510F0B040DF35008010801892501 +:103FB0000801AF6FE86AF3BEE868080108018A21CA +:103FC0000801B06FAFC8E9FFB0C8EAFF0801EECF43 +:103FD000ABF80801EECFACF80801EECFADF8080160 +:103FE000EECFAEF808010801AB5108010801A71B8C +:103FF00008010801AC5108010801A81B08010801CB +:10400000AD5108010801A91B08010801AE510801C2 +:104010000801AA1B0801AF6F010E08010801C66F55 +:104020000801AF51A7C8C2F8A8C8C3F8A9C8C4F806 +:10403000AAC8C5F814EC33F00801080188510F0B29 +:10404000040DF3500801080189250801B06FE86AE2 +:10405000F3BEE868080108018A210801B16FB0C801 +:10406000E9FFB1C8EAFF0801C2C8EEFF0801C3C8F2 +:10407000EEFF0801C4C8EEFF0801C5C8EDFFED5210 +:10408000ED5208010801872B08010801862B080161 +:104090000801852B0F0E0801080187170F0E080174 +:1040A000080186170F0E080108018517080108018D +:1040B00088510F0B040DF3500801080189250801F0 +:1040C000AF6FE86AF3BEE868080108018A210801B9 +:1040D000B06FAFC8E9FFB0C8EAFFEECFB1F8EECFDE +:1040E000B2F8EECFB3F8EECFB4F80801B56F050E15 +:1040F00008010801C66F0801B5518FC8C2F890C801 +:10410000C3F891C8C4F892C8C5F814EC33F008019C +:10411000B15108010801C2250801B66F0801B2516A +:1041200008010801C3210801B76F0801B351080154 +:104130000801C4210801B86F0801B4510801080141 +:10414000C5210801B96F0801080193510801B6257E +:104150000801BA6F0801080194510801B72108014C +:10416000BB6F0801080195510801B8210801BC6F17 +:104170000801080196510801B9210801BD6F080125 +:1041800008018B510801BA250801BE6F080108011A +:104190008C510801BB210801BF6F080108018D5136 +:1041A0000801BC210801C06F080108018E510801F7 +:1041B000BD210801C16F0801080197510801BE2502 +:1041C00008010801A76F0801080198510801BF21E3 +:1041D0000801A86F0801080199510801C0210801D0 +:1041E000A96F080108019A510801C1210801AA6FAD +:1041F0009FC88BF8A0C88CF8A1C88DF8A2C88EF80B +:104200009BC89FF89CC8A0F89DC8A1F89EC8A2F8BA +:104210000801AF6F1E0E08010801C66F0801AF51FB +:10422000A3C8C2F8A4C8C3F8A5C8C4F8A6C8C5F8EE +:1042300014EC33F0C2C89BF8C3C89CF8C4C89DF8FE +:10424000C5C89EF88FC8A3F890C8A4F891C8A5F86F +:1042500092C8A6F8A7C88FF8A8C890F8A9C891F87E +:10426000AAC892F808010801882B4F0E080108011E +:1042700088653DEFA1F03FEFA1F052EF9DF07BC8C4 +:10428000E9FF7CC8EAFF080108018F51EE2608010A +:104290009051EE2208019151EE2208019251ED2237 +:1042A000ED52ED527DC8E9FF7EC8EAFF0801080122 +:1042B000A351EE260801A451EE220801A551EE22D9 +:1042C0000801A651ED22ED52ED527FC8E9FF80C8EA +:1042D000EAFF080108019B51EE2608019C51EE22DD +:1042E00008019D51EE2208019E51ED22ED52ED5242 +:1042F00081C8E9FF82C8EAFF080108019F51EE2644 +:104300000801A051EE220801A151EE220801A2519C +:10431000ED22ED52ED5283C8E9FF84C8EAFF08019F +:1043200008018B51EE2608018C51EE2208018D51B7 +:10433000EE2208018E51ED22ED52ED521200B7EC43 +:1043400024F00801080172A1A8EFA1F0AAEFA1F0E2 +:10435000AEEFA1F01986080108017291189A189C15 +:10436000189E199219941990B6EFA1F0CBEC3DF07C +:104370000009D8B4BEEFA1F0C0EFA1F0B6EFA1F0F4 +:10438000080108017251060BD8B4C9EFA1F0CBEFB8 +:10439000A1F0D4EFA1F0000E08010801766F000E25 +:1043A0000801776F74EFA3F000EE29F010EE07F02C +:1043B000E652EE52ED50E518EFCFE8FFD8B4E7181B +:1043C000D8A4E5EFA1F0E7EFA1F0F0EFA1F0000E27 +:1043D00008010801766F000E0801776F44EFA3F023 +:1043E00000EE07F010EE29F0E652EE52ED50E55CDB +:1043F00002E1EF50E75CD8B000EFA2F002EFA2F0CC +:1044000057EFA2F02950075C08010801766F2A5087 +:1044100008580801776F0801080176512F5C0801E0 +:10442000080177513058D8B018EFA2F01AEFA2F077 +:104430001EEFA2F02FC076F830C077F8080108010F +:104440007651405C0801080177514158D8B02BEFF4 +:10445000A2F02DEFA2F032EFA2F040C076F841C0FA +:1044600077F8198476C8AAF877C8ABF81CC0A9F801 +:1044700029C0A7F82AC0A8F808019C6F000E0801FF +:104480000801A66F08019C51050E08010801A46FE0 +:104490000B0E0801A56FA0EC23F00801080176516E +:1044A00029260801080177512A2244EFA3F0295058 +:1044B000035C08010801866F2A5004580801876FC1 +:1044C000080108EE86F0EECF9CF8EDCF9DF807507E +:1044D00008019C27085008019D23015008019C5D9C +:1044E00008010801766F025008019D590801776F95 +:1044F0000801080176512F5C0801080177513058F6 +:10450000D8B085EFA2F087EFA2F08BEFA2F02FC01A +:1045100076F830C077F8080108017651405C080150 +:10452000080177514158D8B098EFA2F09AEFA2F065 +:104530009FEFA2F040C076F841C077F819840801D7 +:104540000801865108010801765D080108018751BC +:10455000080108017759D8B0B0EFA2F0B2EFA2F08D +:10456000B6EFA2F076C886F877C887F886C8AAF8AA +:1045700087C8ABF81CC0A9F829C0A7F82AC0A8F8BA +:1045800008019C6F000E08010801A66F08019C51EC +:10459000050E08010801A46F0B0E0801A56FA0EC21 +:1045A00023F008010801865108010801765D080121 +:1045B0000801866F08010801875108010801775931 +:1045C0000801876F0801080187518611D8B4EBEF05 +:1045D000A2F0EDEFA2F018EFA3F086C8AAF887C802 +:1045E000ABF81CC0A9F801C0A7F802C0A8F80801E0 +:1045F0009C6F000E08010801A66F08019C5100EE97 +:1046000003F0EECF9DF8EDCF9EF8295008019D5F95 +:104610002A5008019E5B050E08019D25080108012E +:10462000A46F0B0E08019E210801A56FA0EC23F0DA +:1046300008010801765129260801080177512A222C +:1046400000EE03F010EE29F0E652EE52ED50E55C7C +:1046500002E1EF50E75CD8A030EFA3F032EFA3F017 +:1046600044EFA3F000EE03F0EECF9CF8EDCF9DF801 +:10467000015008019C5F025008019D5B08019C519C +:10468000295E08019D512A5A19A649EFA3F04BEF64 +:10469000A3F074EFA3F000EE2FF00801EE52080132 +:1046A0007751ED18080176C8E8FFD8B4EF18D8B4F0 +:1046B0005CEFA3F05EEFA3F074EFA3F000EE40F028 +:1046C0000801EE5208017751ED18080176C8E8FF9D +:1046D000D8B4EF18D8B46FEFA3F071EFA3F074EF74 +:1046E000A3F00801080172810801080177517611D1 +:1046F000D8A47DEFA3F07FEFA3F08AEFA3F0080129 +:1047000008017251030BD8B488EFA3F08AEFA3F02D +:10471000D0EFA3F00801080176512F5E08010801CF +:104720007751305A0801080177517611D8B49BEFC0 +:10473000A3F09DEFA3F0A0EFA3F00801080172879A +:104740000801080173A1A7EFA3F0A9EFA3F0B7EF49 +:10475000A3F008019C6F000E426E08019C51F20EFE +:104760001D6E9E0E1E6E000E1F6E000E206EC4EC9F +:1047700043F01D5008010801A1250F6E1E500801CD +:104780000801A221106E1F5008010801A321116E1B +:10479000205008010801A421126E18882DEFA4F002 +:1047A0000801080173A3D7EFA3F0D9EFA3F0F9EF45 +:1047B000A3F0010E08019C6F1850070B08019D6FB4 +:1047C00008019C5108019D27185008019D19F80BFC +:1047D00008019D19186E2106000E225A235A245AE8 +:1047E000010E08010801766F000E0801776F2DEFAA +:1047F000A4F018A8FEEFA3F000EFA4F02DEFA4F0B2 +:104800000801080173B107EFA4F009EFA4F017EF56 +:10481000A4F04250D8B40FEFA4F011EFA4F017EFBA +:10482000A4F04206D89020321F321E321D32C4EC52 +:1048300043F01D5008010801A1250F6E1E5008010C +:104840000801A221106E1F5008010801A321116E5A +:10485000205008010801A421126E2DC088F82EC036 +:1048600089F82BC08AF82CC08BF821C08CF822C0A4 +:104870008DF823C08EF824C08FF825C090F826C08C +:1048800091F827C092F828C093F83F0E08019517B9 +:104890000801949108019493080194950801949754 +:1048A0000B000E0072C895F8000E080108019A6FFF +:1048B000000E08019B6F08010801765121260801AE +:1048C000080177512222000E2322000E2422080123 +:1048D000080172A36EEFA4F070EFA4F0A2EFA4F0B1 +:1048E0000801080172B977EFA4F079EFA4F086EF20 +:1048F000A4F0000E08010801906F000E0801916FEE +:10490000000E0801926F000E0801936F3FA28BEF1B +:10491000A4F08DEFA4F099EFA4F0080108018C0732 +:10492000000E08018D5B08018E5B08018F5BA2EF12 +:10493000A4F0010E2126000E2222000E2322000EDA +:1049400024223F820801080172A1A9EFA4F0ABEF75 +:10495000A4F0C7EFA4F03FA0B0EFA4F0B2EFA4F032 +:10496000BEEFA4F0080108018C07000E08018D5B62 +:1049700008018E5B08018F5BC7EFA4F0010E2126B2 +:10498000000E2222000E2322000E24223F8000EE81 +:104990000DF010EE0BF0E652EE52ED50E55C02E148 +:1049A000EF50E75CD8A0D7EFA4F0D9EFA4F000EF68 +:1049B000A5F000EE0BF0EECF9CF8EDCF9DF80D507A +:1049C00008019C5F0E5008019D5B00EE05F0EECFE4 +:1049D0009EF8EDCF9FF8035008019E5F0450080138 +:1049E0009F5B08019C5108019E5D08010801966FBC +:1049F00008019D5108019F590801976F17EFA5F015 +:104A000000EE0DF0EECF9CF8EDCF9DF80B500801B5 +:104A10009C5F0C5008019D5BFF0E08019C2508015E +:104A20000801966FFF0E08019D210801976FC3ECE6 +:104A300025F0A0C874F8A1C875F8400E0801080157 +:104A4000745D000E08017559D8B029EFA5F02BEF61 +:104A5000A5F034EFA5F0000E08010801746F000EF8 +:104A60000801756F3BEFA5F0400E08010801745F67 +:104A7000000E0801755B0801080196510801080144 +:104A8000745D080108019751080108017559D8B0F3 +:104A90004CEFA5F04EEFA5F052EFA5F074C896F8D4 +:104AA00075C897F80801880E08010801A06F080171 +:104AB000080E0801A16FC7EC07F0140E08010801E9 +:104AC0007627000E08017723080194510F0B500937 +:104AD0000801946F0801080172A371EFA5F073EF4C +:104AE000A5F0ABEFA5F0040E080108017627000E33 +:104AF0000801772308019C6F020E08010801786FF6 +:104B000008019C5108019C6F040E08010801796F8F +:104B100008019C51020E080108017A6F180E080165 +:104B20007B6F010E08019C6F0801080194390F0B7F +:104B300008019D6F08019C5108019D2708019D3BBC +:104B400008010801945108019D190F0B08019D19D6 +:104B500008010801946F6CC07CF86DC07DF86EC0D0 +:104B60007EF86FC07FF833C080F834C081F835C05C +:104B700082F836C083F808019C6F000E0801080116 +:104B8000846F08019C5108019C6F060E0801080102 +:104B9000856F08019C5176C886F877C887F886C863 +:104BA000BCF887C8BDF82FEC43F0BCC886F8BDC878 +:104BB00087F80C0E08010801BC6F000E0801BD6FDC +:104BC00008017C0E08010801BA6F0801080E0801EF +:104BD000BB6FF2EC1EF008010801BA1D08010801C4 +:104BE000986F08010801BB1D0801996FDD0E0801CF +:104BF0000801AC6F0A0E0801AD6F0BEC44F076C8EB +:104C0000A3F877C8A4F808019C6F060E08010801F4 +:104C1000A26F08019C51330E08010801A06F000E1D +:104C20000801A16FCAEC18F0140E08010801C26F48 +:104C3000000E0801C36F0801880E08010801C06F4B +:104C40000801080E0801C16FBBEC40F00801080123 +:104C500072A32DEFA6F02FEFA6F041EFA6F0040E01 +:104C600008010801C26F000E0801C36F0801780E29 +:104C700008010801C06F0801080E0801C16FBBECF4 +:104C800040F0F10E08010801AC6F0A0E0801AD6F8B +:104C90002CEC44F076C8A0F877C8A1F80EEC10F020 +:104CA000A0C874F8A1C875F8010E08010801AC6F1E +:104CB0000B0E0801AD6F0BEC44F0020E0801080169 +:104CC000C26F000E0801C36F0801740E08010801CD +:104CD000C06F0801080E0801C16FBBEC40F003EC87 +:104CE00039F0120008011E6F000E080108011D6F47 +:104CF00008011E51000E080108011D6582EFA6F093 +:104D000084EFA6F086EFA6F0C7EFAAF07CEFAAF03A +:104D1000BAEFAAF0430E08010801536F000E080114 +:104D2000546F440E08010801516F000E0801526FC4 +:104D300008011E6F000E08010801506F08011E5186 +:104D4000000E080108014C6F000E08014D6F000EA7 +:104D500008014E6F000E08014F6F22ECD7F0446E31 +:104D60004428D8A4B6EFA6F0B8EFA6F0BAEFA6F0A4 +:104D7000BAEFAAF008011E6F020E00010001456F94 +:104D800008011E51000E000100014B6F000E0001D2 +:104D90004C6F000E00014D6F000E00014E6F3C0E77 +:104DA000000100014F6F000E0001506F000E000166 +:104DB000516F000E0001526F08011E6F000E0001BE +:104DC00000016B6F08011E510001469100014695DC +:104DD00097EC42F00009D8A4F0EFA6F0F2EFA6F0AD +:104DE000F4EFA6F0BAEFAAF044C04CF893EC39F017 +:104DF0002C0E080108014C5D010E08014D59D8B078 +:104E000004EFA7F006EFA7F008EFA7F0BAEFAAF0BB +:104E1000000146790A0E080108015D6F000E0801C5 +:104E20005E6FFF0E080108015B6F000E08015C6FEA +:104E30004450170D0201000EF32408010801596FB8 +:104E400008015A6B0201020E08015A2353EC40F08C +:104E500008011E6F000E08010801236F08011E5192 +:104E600008011F6F010E08010801226F08011F5180 +:104E7000CCECBCF0C4EC43F0A1C847F0A2C848F0A9 +:104E8000A3C849F0A4C84AF000014E514B114C117F +:104E90004D11D8A44EEFA7F050EFA7F05AEFA7F0AE +:104EA000C4EC43F0A1C84BF0A2C84CF0A3C84DF02D +:104EB000A4C84EF008011E6F030E00010001456FEB +:104EC00008011E51BAEFAAF044C04CF8D9EC39F0F1 +:104ED000FA0E080108014C5D000E08014D59D8B0CA +:104EE00074EFA7F076EFA7F0BFEFA7F0C4EC43F0A4 +:104EF00000010001475108010801A15D08011E6F72 +:104F000000010001485108010801A25908011F6F62 +:104F100000010001495108010801A3590801206F4F +:104F2000000100014A5108010801A4590801216F3C +:104F3000E40E1E5D3D0E1F59010E2059000E0801A2 +:104F40002159D8A0A6EFA7F0A8EFA7F088EFA6F008 +:104F500008011E6F020E00010001456F08011E517D +:104F6000000E00010001576F000E0001586F000E87 +:104F70000001596F000E00015A6FBAEFAAF000014C +:104F80004687C8ECAAF0020AD8B4C9EFA7F0CBEF65 +:104F9000A7F0CDEFA7F0BAEFAAF008011E6F040E3C +:104FA00000010001456F08011E51000E00010001C3 +:104FB0004B6F000E00014C6F000E00014D6F000E94 +:104FC00000014E6F44C04CF893EC39F0020E08011A +:104FD00008014C5D010E08014D59D8B0F2EFA7F061 +:104FE000F4EFA7F0F6EFA7F0BAEFAAF00A0E080167 +:104FF00008015D6F000E08015E6FFF0E08010801D9 +:105000005B6F000E08015C6F4450170D0201000E2B +:10501000F32408010801596F08015A6B0201020EBE +:1050200008015A2353EC40F008011E6F000E0801DE +:105030000801236F08011E5108011F6F030E0801AC +:105040000801226F08011F51CCECBCF0C4EC43F006 +:10505000A1C847F0A2C848F0A3C849F0A4C84AF0C4 +:1050600000010001452BBAEFAAF044C04CF8D9EC7E +:1050700039F0FA0E080108014C5D000E08014D5987 +:10508000D8B045EFA8F047EFA8F08FEFA8F0C4EC38 +:1050900043F000010001475108010801A15D08012A +:1050A0001E6F00010001485108010801A2590801C2 +:1050B0001F6F00010001495108010801A3590801AF +:1050C000206F000100014A5108010801A45908019C +:1050D000216F2E0E1E5D500E1F59090E2059000E15 +:1050E00008012159D8A077EFA8F079EFA8F088EF50 +:1050F000A6F0000100EE45F0EF2A0B0EEF6483EFFF +:10510000A8F085EFA8F08DEFA8F008011E6F020E41 +:1051100000010001456F08011E51BAEFAAF01AEF15 +:10512000A9F044C04CF8A3EC36F04468C4EC43F05A +:10513000A1C847F0A2C848F0A3C849F0A4C84AF0E3 +:1051400008011E6F0C0E00010001456F08011E5181 +:105150000001468300014681000100016BA1B3EF0D +:10516000A8F0B5EFA8F0BDEFA8F057C06CF058C09C +:105170006DF059C06EF05AC06FF0000100016BA5D0 +:10518000C4EFA8F0C6EFA8F0CEEFA8F05FC070F0B3 +:1051900060C071F061C072F062C073F00001000184 +:1051A0006BA3D5EFA8F0D7EFA8F0DFEFA8F05BC0B6 +:1051B00074F05CC075F05DC076F05EC077F0000101 +:1051C00000016BA7E6EFA8F0E8EFA8F0F0EFA8F079 +:1051D00063C078F064C079F065C07AF066C07BF097 +:1051E000000E000100017C6F000E00017D6F000EBB +:1051F00000017E6F000E00017F6F000100016BA9AE +:1052000004EFA9F006EFA9F00EEFA9F067C07CF05B +:1052100068C07DF069C07EF06AC07FF088EFA6F0BC +:1052200008011E6F020E00010001456F08011E51AA +:1052300088EFA6F0C8ECAAF0050A01E172D7030ACC +:10524000EFE088EFA6F0C4EC43F000010001475105 +:1052500008010801A15D08011E6F0001000148510D +:1052600008010801A25908011F6F000100014951FE +:1052700008010801A3590801206F000100014A51EB +:1052800008010801A4590801216FF20E1E5D9E0E4F +:105290001F59000E2059000E08012159D8B053EFB4 +:1052A000A9F055EFA9F057EFA9F0BAEFAAF0020E56 +:1052B00000014F5D000E00015059000E00015159D0 +:1052C000000E000100015259D8A069EFA9F06BEF60 +:1052D000A9F084EFA9F0F20E0001000147279E0E0D +:1052E00000014823000E00014923000E00014A235B +:1052F000000100014F07000E0001505B0001515BEF +:105300000001525BBAEFAAF0430E08010801536F87 +:10531000000E0801546F440E08010801516F000E81 +:105320000801526F08011E6F000E08010801506F3E +:1053300008011E51000E080108014C6F000E080103 +:105340004D6F000E08014E6F000E08014F6F22ECEA +:10535000D7F0446E4428D8A4B0EFA9F0B2EFA9F07A +:10536000B4EFA9F0BAEFAAF008011E6F0D0E00010C +:105370000001456F08011E5144C04CF893EC39F010 +:10538000020E080108014C5D010E08014D59D8B00C +:10539000CCEFA9F0CEEFA9F0D0EFA9F0BAEFAAF0C8 +:1053A00008011E6F010E08010801236F08011E513C +:1053B00008011F6F030E08010801226F08011F5129 +:1053C000CCECBCF000014695C4EC43F0A1C847F01A +:1053D000A2C848F0A3C849F0A4C84AF000010001DF +:1053E000452BBAEFAAF044C04CF8D9EC39F0FA0ECC +:1053F000080108014C5D000E08014D59D8B003EFBB +:10540000AAF005EFAAF04DEFAAF0C4EC43F00001BA +:105410000001475108010801A15D08011E6F00014C +:105420000001485108010801A25908011F6F00013D +:105430000001495108010801A3590801206F00012A +:1054400000014A5108010801A4590801216F2E0EDC +:105450001E5D500E1F59090E2059000E08012159DA +:10546000D8A035EFAAF037EFAAF088EFA6F0000138 +:1054700000EE45F0EF2A120EEF6441EFAAF043EF81 +:10548000AAF04BEFAAF008011E6F020E0001000106 +:10549000456F08011E51BAEFAAF074EFAAF044C09C +:1054A0004CF8A3EC36F04468C4EC43F0A1C847F0D4 +:1054B000A2C848F0A3C849F0A4C84AF008011E6F6A +:1054C0000C0E00010001456F08011E5100014683CA +:1054D00088EFA6F008011E6F020E00010001456F63 +:1054E00008011E5188EFA6F0C8ECAAF0050AD7E023 +:1054F000030AF0E088EFA6F0000100014551000A20 +:1055000001E106D4010A01E105D4030A01E147D40F +:10551000010A01E1D9D4070A01E154D5010A01E1E8 +:10552000A4D5030A01E14ED5010A01E19ED50F0A77 +:1055300001E148D5010A01E198D5030A01E142D50C +:10554000010A01E192D5070A01E17DD6010A01E1D4 +:1055500013D7030A01E147D7010A01E10DD71F0A5A +:1055600001E141D7010A01E107D7030A01E13BD775 +:10557000BAEFAAF0080108011D2B000E080108016E +:105580001D65C5EFAAF0C7EFAAF086EFA6F01200DE +:1055900008012B6F000E08010801236F08012B5131 +:1055A0000801250E080108014D6F0801080E0801C9 +:1055B0004E6F35EC3DF0080108012551020AD8A4D0 +:1055C000E4EFAAF0E6EFAAF069EFAEF01C0E0801D6 +:1055D00008014E6F000E08014F6F83EC42F0080186 +:1055E0002B6F000E08010801266F08012B51050ED4 +:1055F000080108012665FFEFAAF001EFABF003EF09 +:10560000ABF036EFABF00801250E080108014D6F35 +:105610000801080E08014E6F35EC3DF026C82BF846 +:105620002D0E08012B2700016C0E08012B25E96EB9 +:10563000EA6A0001000EEA22EF500801080125196C +:10564000D8B425EFABF027EFABF029EFABF0B1EF1B +:10565000AEF008010801262B050E08010801266599 +:1056600034EFABF036EFABF003EFABF0000100012D +:1056700046B53DEFABF03FEFABF05CEFABF0100E9B +:10568000080108014E6F000E08014F6F83EC42F0D5 +:10569000040E080108014F6F000E0801506F000151 +:1056A000570E080108014D6F0001000E08014E6FF2 +:1056B000F8EC2BF000016B81F00E080108014E6F31 +:1056C000000E08014F6F83EC42F008012B6F000EB3 +:1056D00008010801226F08012B510801250E08015D +:1056E00008014D6F0801080E08014E6F35EC3DF0C2 +:1056F0000009D8A47EEFABF080EFABF08AEFABF0FF +:1057000008012B6F010E08010801226F08012B51BF +:1057100069EFAEF045EFAEF00801250E0801080173 +:105720004D6F0801080E08014E6F35EC3DF0080181 +:1057300008012505D8A49FEFABF0A1EFABF0C4EFB3 +:10574000ABF00801230E080108014D6F0801080E97 +:1057500008014E6F35EC3DF00001000146A5B3EFA6 +:10576000ABF0B5EFABF0C2EFABF00801080123518D +:10577000020AD8A4BEEFABF0C0EFABF0C2EFABF0C3 +:10578000B1EFAEF0C6EFABF0B1EFAEF05FEFAEF061 +:105790000801250E080108014D6F0801080E0801D7 +:1057A0004E6F35EC3DF0080108012551040AD8A4DC +:1057B000DCEFABF0DEEFABF0C4EFABF000010001CB +:1057C00046A5E5EFABF0E7EFABF015EFACF0080165 +:1057D0002B6F000E08010801266F08012B51030EE4 +:1057E000080108012665F7EFABF0F9EFABF0FBEF2E +:1057F000ABF013EFACF00801250E080108014D6F66 +:105800000801080E08014E6F35EC3DF00801080153 +:10581000262B030E08010801266511EFACF013EFEB +:10582000ACF0FBEFABF029EFACF0040E080108017F +:105830004F6F000E0801506F00015F0E0801080154 +:105840004D6F0001000E08014E6FF8EC2BF00001C7 +:105850006B85C6EFABF00801240E080108014D6FFF +:105860000801080E08014E6F35EC3DF0030E0801EB +:10587000080124653EEFACF040EFACF0C4EFABF0B4 +:105880000001000146A547EFACF049EFACF077EF1F +:10589000ACF008012B6F000E08010801266F08010B +:1058A0002B51030E08010801266559EFACF05BEFA0 +:1058B000ACF05DEFACF075EFACF00801250E08011F +:1058C00008014D6F0801080E08014E6F35EC3DF0E0 +:1058D00008010801262B030E08010801266573EF55 +:1058E000ACF075EFACF05DEFACF08BEFACF0040E0C +:1058F000080108014F6F000E0801506F00015B0E98 +:10590000080108014D6F0001000E08014E6FF8EC10 +:105910002BF000016B838DEFACF0040E0801080141 +:10592000245F9EEFACF00801250E080108014D6FC1 +:105930000801080E08014E6F35EC3DF00801080122 +:10594000240708012429D8A4A8EFACF0AAEFACF0F2 +:1059500093EFACF05FEFAEF00801240E08010801F0 +:105960004D6F0801080E08014E6F35EC3DF0040E36 +:10597000080108012461BFEFACF0C1EFACF0C3EF48 +:10598000ACF0B1EFAEF00001000146B5CAEFACF0EB +:10599000CCEFACF0E4EFACF0040E080108014F6F5F +:1059A000000E0801506F0001630E080108014D6FE1 +:1059B0000001000E08014E6FF8EC2BF000016B8720 +:1059C000040E08010801245F030E08010801246584 +:1059D000ECEFACF0EEEFACF00FEFADF0000100013A +:1059E00046B5F5EFACF0F7EFACF00FEFADF0040E0D +:1059F000080108014F6F000E0801506F0001670E8B +:105A0000080108014D6F0001000E08014E6FF8EC0F +:105A10002BF000016B89040E08010801245F1CEFC4 +:105A2000ADF00801250E080108014D6F0801080EB0 +:105A300008014E6F35EC3DF008010801240708010C +:105A40002429D8A426EFADF028EFADF011EFADF08A +:105A50005FEFAEF00801250E080108014D6F080147 +:105A6000080E08014E6F35EC3DF008010801255184 +:105A7000040AD8A43EEFADF040EFADF0C4EFABF0B8 +:105A800008012A0E080108014D6F0801080E0801DF +:105A90004E6F35EC3DF00801290E080108014D6FED +:105AA0000801080E08014E6F35EC3DF00801280E84 +:105AB000080108014D6F0801080E08014E6F35EC12 +:105AC0003DF00801270E080108014D6F0801080E7E +:105AD00008014E6F35EC3DF0C6EFABF008012B6FBF +:105AE000010E08010801226F08012B515FEFAEF093 +:105AF0000801250E080108014D6F0801080E080174 +:105B00004E6F35EC3DF0080108012551040AD8A478 +:105B10008CEFADF08EEFADF0C4EFABF00001000103 +:105B200046A595EFADF097EFADF0C5EFADF00801EC +:105B30002B6F000E08010801266F08012B51030E80 +:105B4000080108012665A7EFADF0A9EFADF0ABEFB6 +:105B5000ADF0C3EFADF00801250E080108014D6F4F +:105B60000801080E08014E6F35EC3DF008010801F0 +:105B7000262B030E080108012665C1EFADF0C3EF27 +:105B8000ADF0ABEFADF01DEFAEF00001520E08012D +:105B900008014D6F0001000E08014E6F35EC3DF01D +:105BA0000001510E080108014D6F0001000E0801AF +:105BB0004E6F35EC3DF00001500E080108014D6FAD +:105BC0000001000E08014E6F35EC3DF000014F0E54 +:105BD000080108014D6F0001000E08014E6F35EC01 +:105BE0003DF000014FC02BF8000150C02CF800011F +:105BF00051C02DF8000152C02EF8060E06EFAEF08F +:105C0000D89008012E332D332C332B33E82E00EFA0 +:105C1000AEF008012B51000100014F5F08012C512B +:105C200000010001505B08012D5100010001515B92 +:105C300008012E5100010001525BC6EFABF00801D4 +:105C4000240E080108014D6F0801080E08014E6F6F +:105C500035EC3DF037EFAEF00801250E08010801E4 +:105C60004D6F0801080E08014E6F35EC3DF008013C +:105C70000801240708012429D8A441EFAEF043EF1E +:105C8000AEF02CEFAEF05FEFAEF008010801255149 +:105C9000010A01E17DD5020A01E1DDD5050A01E134 +:105CA0005BD6350A01E124D7060A01E135D5030A9E +:105CB00001E1D0D6C90A01E111D71FEFAEF008010A +:105CC00008012251D8B467EFAEF069EFAEF06DEF86 +:105CD000ABF0080108012351020AD8A472EFAEF01C +:105CE00074EFAEF080EFAEF027C853F028C854F040 +:105CF00029C855F02AC856F000014685AAEFAEF033 +:105D0000080108012A5100010001561914E1080197 +:105D1000080129510001000155190DE10801080190 +:105D2000285100010001541906E10801080127511A +:105D3000000100015319D8B4A0EFAEF0A2EFAEF00D +:105D4000AAEFAEF008012B6F000E08010801236FC7 +:105D500008012B518FEC41F0080108012351B6EFE7 +:105D6000AEF08FEC41F0000EB6EFAEF01200DDEFBA +:105D7000B0F0080108010D51D8B4C1EFAEF0C3EF87 +:105D8000AEF0DFEFAEF0550E080108010E65CBEF67 +:105D9000AEF0CDEFAEF0DFEFAEF05C0E0801080123 +:105DA0000E61D5EFAEF0D7EFAEF0DFEFAEF0080149 +:105DB0001F6F010E070107010A6F08011F51F4EF61 +:105DC000B0F01B0E080108010E65E9EFAEF0EBEF35 +:105DD000AEF0FFEFAEF0200E080108010E61F3EF08 +:105DE000AEF0F5EFAEF0FFEFAEF008011F6F030E5F +:105DF000070107010A6F08011F51F4EFB0F02A0EE6 +:105E0000080108010E6507EFAFF009EFAFF01DEFD5 +:105E1000AFF02F0E080108010E6111EFAFF013EF84 +:105E2000AFF01DEFAFF008011F6F040E070107016F +:105E30000A6F08011F51F4EFB0F005EC36F0F4EFF3 +:105E4000B0F01A0E080108010E6529EFAFF02BEF34 +:105E5000AFF01DEFAFF0200E080108010E6133EF27 +:105E6000AFF035EFAFF01DEFAFF008011F6F050E7B +:105E7000070107010A6F08011F51F4EFB0F0030E8C +:105E8000080108010E6547EFAFF049EFAFF01DEFD5 +:105E9000AFF0090E080108010E6151EFAFF053EFAA +:105EA000AFF01DEFAFF008011F6F070E07010701EC +:105EB0000A6F08011F51F4EFB0F006010601D66722 +:105EC00064EFAFF066EFAFF0A6EFAFF0010E0801A0 +:105ED00008010E656EEFAFF070EFAFF084EFAFF03A +:105EE000050E080108010E6178EFAFF07AEFAFF010 +:105EF00084EFAFF008011F6F010E06010601D66F97 +:105F000008011F51F4EFB0F0040E080108010E65FE +:105F10008CEFAFF08EEFAFF0A2EFAFF0080E0801FC +:105F200008010E6196EFAFF098EFAFF0A2EFAFF07F +:105F300008011F6F020E06010601D66F08011F51EE +:105F4000F4EFB0F005EC36F0F4EFB0F00601060126 +:105F5000D605D8A4AEEFAFF0B0EFAFF0DCEFAFF006 +:105F6000040E080108010E65B8EFAFF0BAEFAFF00C +:105F70001DEFAFF0080E080108010E61C2EFAFF08F +:105F8000C4EFAFF01DEFAFF008011F6F000E060168 +:105F90000601D66F08011F5107010701164B172B89 +:105FA0000701D89007019037070191370701923711 +:105FB00007019337F4EFB0F006010601D651020A4B +:105FC000D8A4E5EFAFF0E7EFAFF019EFB0F0010EB6 +:105FD000080108010E65EFEFAFF0F1EFAFF01DEF34 +:105FE000AFF0050E080108010E61F9EFAFF0FBEF0D +:105FF000AFF01DEFAFF008011F6F000E06010601A4 +:10600000D66F08011F5107010701164B172B070117 +:1060100007019051070107010C130701D8900701F0 +:106020009037070191370701923707019337F4EF53 +:10603000B0F005EC36F0F4EFB0F006010601D667DB +:1060400024EFB0F026EFB0F066EFB0F0030E0801D9 +:1060500008010E652EEFB0F030EFB0F044EFB0F075 +:10606000090E080108010E6138EFB0F03AEFB0F008 +:1060700044EFB0F008011F6F010E06010601D66F54 +:1060800008011F51F4EFB0F0080E080108010E6579 +:106090004CEFB0F04EEFB0F062EFB0F0100E080130 +:1060A00008010E6156EFB0F058EFB0F062EFB0F0BB +:1060B00008011F6F020E06010601D66F08011F516D +:1060C000F4EFB0F005EC36F0F4EFB0F006010601A5 +:1060D000D605D8A46EEFB0F070EFB0F09CEFB0F042 +:1060E000080E080108010E6578EFB0F07AEFB0F005 +:1060F0001DEFAFF0100E080108010E6182EFB0F045 +:1061000084EFB0F01DEFAFF008011F6F000E060125 +:106110000601D66F08011F5107010701164B172B07 +:106120000701D8900701903707019137070192378F +:1061300007019337F4EFB0F006010601D651020AC9 +:10614000D8A4A5EFB0F0A7EFB0F0D9EFB0F0030EF0 +:10615000080108010E65AFEFB0F0B1EFB0F01DEF30 +:10616000AFF0090E080108010E61B9EFB0F0BBEF06 +:10617000B0F01DEFAFF008011F6F000E0601060121 +:10618000D66F08011F5107010701164B172B070196 +:1061900007019051070107010C130701D89007016F +:1061A0009037070191370701923707019337F4EFD2 +:1061B000B0F005EC36F0F4EFB0F0070107010A513A +:1061C000000A01E1D6D5010A01E1FBD5020A01E18D +:1061D00074D6070A01E135D6010A01E150D6020A58 +:1061E00001E12BD7F4EFB0F0070107011651080ABF +:1061F0001711D8A4FEEFB0F000EFB1F07CEFB1F0D2 +:1062000006010601E82B050E06010601E8610BEF09 +:10621000B1F00DEFB1F068EFB1F0070107010C51DB +:1062200005010501FC2505010501FC6F000E0501B6 +:106230000501FD210501FD6F000E05010501FE218F +:106240000501FE6F000E05010501FF210501FF6F2D +:10625000040E06010601E86130EFB1F032EFB1F053 +:1062600045EFB1F00501FCC520F80501FDC521F899 +:106270000501FEC522F808011F6B1FC8FCF520C8E8 +:10628000FDF521C8FEF522C8FFF5070107010C51F5 +:1062900006010601CA2506010601CA6F000E0601A5 +:1062A0000601CB210601CB6F000E06010601CC21B1 +:1062B0000601CC6F000E06010601CD210601CD6F4F +:1062C00008011F6F000E070107010C6F08011F5125 +:1062D000000E07010701166F000E0701176F010E70 +:1062E00007010701906F000E0701916F000E070173 +:1062F000926F000E0701936F070107010A51030A0D +:10630000D8A485EFB1F087EFB1F0DBEFB1F0060173 +:106310000601E851040AD8A490EFB1F092EFB1F071 +:10632000DBEFB1F0FCC50FF8FDC510F8FEC511F8A4 +:10633000FFC512F805EC36F00BEC43F0A50E080192 +:1063400008012E6FFF0E08012F6F2D0E08010801A6 +:106350002C6FFF0E08012D6FF5EC43F0E60E0801DF +:1063600008012E6FFE0E08012F6FAB0E0801080109 +:106370002C6FFF0E08012D6FF5EC43F00FC82EF8BF +:1063800010C82FF811C830F812C831F8B10E080142 +:1063900008012C6FFF0E08012D6F71EC43F008010E +:1063A0001F6F010E080108012C6F08011F515CECE2 +:1063B00041F090EFB2F0070107010A51070AD8A493 +:1063C000E4EFB1F0E6EFB1F08EEFB2F006010601B6 +:1063D000E851050AD8A4EFEFB1F0F1EFB1F08EEF7C +:1063E000B2F0070107010C5108010801136F080101 +:1063F000146B0801156B0801166BCAC617F8CBC6DB +:1064000018F8CCC619F8CDC61AF8FCC51BF8FDC59E +:106410001CF8FEC51DF8FFC51EF805EC36F0080196 +:106420000801135108010801172508011F6F080111 +:10643000080114510801080118210801206F080102 +:10644000080115510801080119210801216F0801EF +:1064500008011651080108011A210801226FFF0ED8 +:1064600008011F150801236F000E080120150801FF +:10647000246F000E080121150801256F000E080188 +:1064800022150801266F0801230524112511261164 +:10649000D8B44DEFB2F04FEFB2F051EFB2F090EF51 +:1064A000B2F00BEC43F0A50E080108012E6FFF0EB1 +:1064B00008012F6F2D0E080108012C6FFF0E080137 +:1064C0002D6FF5EC43F0BB0E080108012E6FFE0E98 +:1064D00008012F6FAB0E080108012C6FFF0E080199 +:1064E0002D6FF5EC43F01BC82EF81CC82FF81DC803 +:1064F00030F81EC831F8B10E080108012C6FFF0EEC +:1065000008012D6F71EC43F008011F6F010E0801A7 +:1065100008012C6F08011F515CEC41F090EFB2F0C4 +:106520001200020E080108014A25E96E000E08015A +:1065300008014B21EA6EEE50ED10D8A4A2EFB2F0A4 +:10654000A4EFB2F0A7EFB2F0000E18EFB6F008011A +:10655000546FFE0E080108014E6F08015451020EDF +:10656000080108014A25E96E000E080108014B21C7 +:10657000EA6EEECF54F8EDCF55F84AC8E9FF4BC8A4 +:10658000EAFFEECF56F8EDCF57F84CC8E9FF4DC8FB +:10659000EAFFEECF58F8EDCF59F8020E08010801D6 +:1065A0004C25E96E000E080108014D21EA6EEECF80 +:1065B0005AF8EDCF5BF80801585108015A25080137 +:1065C0005C6F0801595108015B2108015D6F0801EA +:1065D000565108015C2508015E6F080157510801FA +:1065E0005D2108015F6F0801545108015E1908011F +:1065F0000801506F0801555108015F190801516FDA +:106600000801546F000E080108014F6F0801545132 +:10661000000E080108014F6510EFB3F012EFB3F060 +:1066200014EFB3F0C4EFB3F04FC871F81DEC2BF0CA +:1066300017500D0AD8A41FEFB3F021EFB3F023EFEA +:10664000B3F0B7EFB3F01750040AD8A42AEFB3F0B1 +:106650002CEFB3F04BEFB3F0020E080108014A250E +:10666000E96E000E080108014B21EA6E10EE1AF0E7 +:10667000E652EE52ED50E518EFCFE8FFD8B4E71838 +:10668000D8A445EFB3F047EFB3F049EFB3F04FC8EC +:106690004EF8B7EFB3F000EE1AF00801EE52080121 +:1066A0005151ED18080150C8E8FFD8B4EF18D8B41C +:1066B0005CEFB3F05EEFB3F060EFB3F0B7EFB3F0C1 +:1066C000B7EC24F000EE2DF0020E080108014A2577 +:1066D000E16E000E080108014B21E26EE652EE5217 +:1066E000ED50E518EFCFE8FFD8B4E718D8A47BEF5A +:1066F000B3F07DEFB3F0B7EFB3F000EE2BF04AC884 +:10670000E1FF4BC8E2FFE652EE52ED50E518EFCF45 +:10671000E8FFD8B4E718D8A490EFB3F092EFB3F045 +:10672000B7EFB3F04CC8E9FF4DC8EAFFEECF54F81D +:10673000EECF55F8EECF56F8EECF57F836500801A9 +:1067400057190BE135500801561907E1345008017B +:10675000551903E1335008015419D8A4B2EFB3F02E +:10676000B4EFB3F0B7EFB3F0010E18EFB6F00801D5 +:1067700008014F2B000E080108014F65C2EFB3F06E +:10678000C4EFB3F014EFB3F0080108014E51FE0A54 +:10679000D8B4CDEFB3F0CFEFB3F015EFB4F04EC8EF +:1067A00071F81DEC2BF0B7EC24F0080108014E51F4 +:1067B000FE0AD8B4DEEFB3F0E0EFB3F015EFB4F0BB +:1067C00050C81AF051C81BF00A0E08010801B06F3A +:1067D000000E0801B16F4CC8AEF84DC8AFF8330ECB +:1067E00008010801AC6F000E0801AD6F58EC3AF0DB +:1067F0004AC8E9FF4BC8EAFFEECF2BF0EDCF2CF0F3 +:10680000020E080108014A25E96E000E0801080180 +:106810004B21EA6EEECF2DF0EDCF2EF001C029F026 +:1068200002C02AF0010E18EFB6F00D0E08010801A3 +:106830004A25E96E000E080108014B21EA6EEF506F +:106840000801546F080154B328EFB4F02AEFB4F0F4 +:106850002DEFB4F0000E18EFB6F000010001D85192 +:10686000D711D8B436EFB4F038EFB4F03BEFB4F052 +:10687000000E18EFB6F0000E08010801526F000E6E +:106880000801536F030E08010801525D000E080154 +:106890005359D8A04EEFB4F050EFB4F052EFB4F02B +:1068A0002EEFB5F0080108015251140DF3CF54F842 +:1068B000100E0801542700019F0E08015425E96EAF +:1068C000EA6A0001000EEA22EE50ED10D8A46BEF48 +:1068D000B4F06DEFB4F06FEFB4F02EEFB5F0020E40 +:1068E000080108014A25E96E000E080108014B2144 +:1068F000EA6E080108015251140DF3CF54F8100E3E +:106900000801542700019F0E08015425E16EE26A38 +:106910000001000EE222E652EE52ED50E518EFCFF4 +:10692000E8FFD8B4E718D8B498EFB4F09AEFB4F011 +:106930009CEFB4F01CEFB5F04AC8E9FF4BC8EAFF82 +:10694000080108015251140DF3CF54F80A0E080142 +:10695000542700019F0E08015425E16EE26A0001F0 +:10696000000EE222E652EE52ED50E518EFCFE8FFBE +:10697000D8B4E718D8B4BFEFB4F0C1EFB4F0C3EFA8 +:10698000B4F01CEFB5F04CC8E9FF4DC8EAFFEECFFC +:1069900054F8EECF55F8EECF56F8EECF57F8080181 +:1069A00008015251140D00019F0EF324E96EEA6AAA +:1069B0000001000EEA22EECF58F8EECF59F8EECFE4 +:1069C0005AF8EECF5BF80801575108015B190EE148 +:1069D0000801565108015A1909E1080155510801E9 +:1069E000591904E10801545108015819D8B4FBEFB2 +:1069F000B4F0FDEFB4F0FFEFB4F01CEFB5F05AECDB +:106A000042F0080108015251140DF3CF54F8120E50 +:106A10000801542700019F0E08015425E96EEA6A17 +:106A20000001000EEA220801A1C8EEFF0801A2C879 +:106A3000EDFF000E18EFB6F008010801524B532B82 +:106A4000030E08010801525D000E08015359D8A039 +:106A50002CEFB5F02EEFB5F052EFB4F00801546F03 +:106A6000000E080108014F6F08015451000E080183 +:106A700008014F653EEFB5F040EFB5F042EFB5F0DD +:106A800015EFB6F04FC871F81DEC2BF018B64BEFB0 +:106A9000B5F04DEFB5F04FEFB5F008EFB6F0B7EC4D +:106AA00024F0020E080108014A25E96E000E0801D3 +:106AB00008014B21EA6E10EE2DF0E652EE52ED5039 +:106AC000E518EFCFE8FFD8B4E718D8B46AEFB5F00F +:106AD0006CEFB5F06EEFB5F008EFB6F00A0E0801F6 +:106AE0000801B06F000E0801B16F4CC8AEF84DC878 +:106AF000AFF8080108015251140D00019F0EF32454 +:106B000008010801AC6F0801AD6B0001000E08011F +:106B1000AD2358EC3AF04AC8E9FF4BC8EAFF080138 +:106B200008015251140DF3CF54F80A0E08015427EE +:106B300000019F0E08015425E16EE26A0001000E7B +:106B4000E222EECFE6FFEDCFE5FF040E08010801DB +:106B50004A25E96E000E080108014B21EA6E080182 +:106B600008015251140DF3CF54F80C0E08015427AC +:106B700000019F0E08015425E16EE26A0001000E3B +:106B8000E222EECFE6FFEECFE6FFEECFE6FFEDCF5F +:106B9000E5FFE552E552020E080108014A25E96EBB +:106BA000000E080108014B21EA6E0801080152514C +:106BB000140DF3CF54F8100E0801542700019F0E56 +:106BC00008015425E16EE26A0001000EE222EECFD8 +:106BD000E6FFEDCFE5FF5AEC42F008010801525103 +:106BE000140DF3CF54F8120E0801542700019F0E24 +:106BF00008015425E96EEA6A0001000EEA22080144 +:106C0000A1C8EEFF0801A2C8EDFF000E18EFB6F014 +:106C1000080108014F2B000E080108014F6513EF12 +:106C2000B6F015EFB6F042EFB5F0000E18EFB6F083 +:106C300012000801096F000E080108011D6F08010C +:106C4000095153EC44F00009D8A429EFB6F02BEF1A +:106C5000B6F063EFB6F00801096F000E08010801F5 +:106C60000D6F08010951EAEC43F00801096FFF0EAE +:106C7000080108010D6F0801095100EC44F00601FC +:106C80000601E551D8B447EFB6F049EFB6F061EF31 +:106C9000B6F0A1C72DF895EC12F0A1C70DF8EEECF7 +:106CA00041F00801096FFE0E07010701A16F0801FD +:106CB00009510801096F000E06010601E56F080180 +:106CC000095188EFB9F0A1C70DF83DEC41F000097A +:106CD000D8A46DEFB6F06FEFB6F08BEFB6F0010E03 +:106CE00006010601E56577EFB6F079EFB6F08BEFB8 +:106CF000B6F0060E06010601E56181EFB6F083EFFE +:106D0000B6F08BEFB6F00801096F060E060106011A +:106D1000E56F0801095169EFB9F059EC44F0000939 +:106D2000D8A495EFB6F097EFB6F0ADEFB6F0080146 +:106D3000096FFF0E080108010D6F08010951EAEC07 +:106D400043F00801096FFF0E080108010D6F0801EB +:106D5000095100EC44F088EFB9F00801096FFF0E0B +:106D6000080108010D6F08010951EAEC43F0080120 +:106D7000096F000E080108010D6F0801095100ECB0 +:106D800044F00801096F000E08010801146F0801A2 +:106D9000095127C712F828C713F808010A6F010E16 +:106DA00008010801116F08010A51C80E08010B6F94 +:106DB000010E0C6F08010BC80DF808010CC80EF885 +:106DC000080108010F6B0801106B3FECDAF00701B6 +:106DD0000701A16F0801096F010E06010601E56FA9 +:106DE00008010951C4EC43F0A1C8C0F6A2C8C1F61D +:106DF000A3C8C2F6A4C8C3F688EFB9F0A1C70DF8BE +:106E00003DEC41F00009D8A408EFB7F00AEFB7F065 +:106E100046EFB7F0C4EC43F006010601C05108018B +:106E20000801A15D0801096F06010601C1510801B1 +:106E30000801A25908010A6F06010601C2510801A2 +:106E40000801A35908010B6F06010601C35108018F +:106E50000801A45908010C6F5D0E095DA00E0A59C6 +:106E6000120E0B59000E08010C59D8A03AEFB7F0DA +:106E70003CEFB7F044EFB7F00801096F060E0601CA +:106E80000601E56F0801095188EFB9F0C4EC43F041 +:106E9000A1C802F7A2C803F7A3C804F7A4C805F75E +:106EA0000801096F020E06010601E56F080109518C +:106EB00088EFB9F00801096F000E080108010D6F95 +:106EC00008010951EAEC43F00801096F000E0801BE +:106ED00008010D6F0801095100EC44F0C0ECE4F02A +:106EE0000801096F030E06010601E56F080109514B +:106EF00088EFB9F0C4EC43F006010601E95108013E +:106F00000801A15D0801096F06010601EA510801A7 +:106F10000801A25908010A6F06010601EB51080198 +:106F20000801A35908010B6F06010601EC51080185 +:106F30000801A45908010C6F710E095D810E0A59F0 +:106F40004A0E0B59000E08010C59D8A0AAEFB7F051 +:106F5000ACEFB7F0B0EFB7F077EC40F088EFB9F0F6 +:106F6000C4EC43F007010701025108010801A15DCB +:106F70000801096F07010701035108010801A2591F +:106F800008010A6F07010701045108010801A3590C +:106F900008010B6F07010701055108010801A459F9 +:106FA00008010C6F510E095D840E0A59DF0E0B5952 +:106FB000000E08010C59D8A0E0EFB7F0E2EFB7F0EF +:106FC000ECEFB7F00801096F080E06010601E56F46 +:106FD0000801095188EFB9F0A1C713F894EC2DF01E +:106FE000080114511311D8B4F8EFB7F0FAEFB7F065 +:106FF0000EEFB8F0C4EC43F0A1C8C0F6A2C8C1F6C9 +:10700000A3C8C2F6A4C8C3F60801096F040E06019E +:107010000601E56F0801095188EFB9F088EFB9F072 +:10702000C4EC43F006010601C05108010801A15D4E +:107030000801096F06010601C15108010801A259A2 +:1070400008010A6F06010601C25108010801A3598F +:1070500008010B6F06010601C35108010801A4597C +:1070600008010C6FE50E095D3D0E0A59010E0B5922 +:10707000000E08010C59D8A040EFB8F042EFB8F06C +:107080004EEFB8F065EC3FF00801096F030E060102 +:107090000601E56F0801095188EFB9F0A1C713F89F +:1070A00094EC2DF0080114511311D8A45AEFB8F044 +:1070B0005CEFB8F05EEFB8F088EFB9F0A1C713F855 +:1070C00094EC2DF0080114511311D8A46AEFB8F014 +:1070D0006CEFB8F06EEFB8F00EEFB8F00801080EE4 +:1070E000080108010E6F0801080E08010F6FA1C703 +:1070F0000DF84BEC28F00009D8A481EFB8F083EF2D +:10710000B8F085EFB8F00EEFB8F008C80DF8C1EC94 +:10711000DBF0C4EC43F0A1C8C0F6A2C8C1F6A3C816 +:10712000C2F6A4C8C3F661EC43F00009D8B49BEFE3 +:10713000B8F09DEFB8F0A7EFB8F00801096F050EA1 +:1071400006010601E56F080109510EEFB8F05EEF88 +:10715000B8F0C4EC43F0A1C802F7A2C803F7A3C873 +:1071600004F7A4C805F7C8EC15F065EC3FF008017A +:10717000096F030E06010601E56F0801095188EF4A +:10718000B9F0A1C72DF895EC12F0A1C70DF8EEECFF +:1071900041F00801096F080E06010601E56F0801BC +:1071A000095188EFB9F09BEC03F07F0E080108014C +:1071B0001617000E080117170A0E080108011625F8 +:1071C00007010701246F000E0801080117210701BC +:1071D000256FC4EC43F0A1C8C0F6A2C8C1F6A3C88D +:1071E000C2F6A4C8C3F6D7EC41F00801096F000E3F +:1071F000080108010D6F0801095100EC44F0080175 +:10720000096F090E06010601E56F0801095188EFB3 +:10721000B9F0C4EC43F006010601C05108010801B1 +:10722000A15D0801096F06010601C15108010801AD +:10723000A25908010A6F06010601C251080108019E +:10724000A35908010B6F06010601C351080108018B +:10725000A45908010C6FF20E08010801116F9E0E6F +:107260000801126F000E0801136F000E0801146F61 +:107270000701080124C70DF80701080125C70EF80A +:107280000801000E08010EBFFF0E08010F6F080174 +:10729000106FBBEC32F008010951080108010D5DC7 +:1072A00008010A51080108010E5908010B51080193 +:1072B00008010F5908010C51080108011059D8B0F4 +:1072C00064EFB9F066EFB9F00EEFB8F0FF0088EFA9 +:1072D000B9F006010601E551000A01E11ED5010AD7 +:1072E00001E18CD5030A01E1E5D5010A01E102D6ED +:1072F000070A01E195D6010A01E12BD7030A01E152 +:1073000040D70E0A01E14FD7010A83E088EFB9F0B8 +:10731000120058C8E9FF59C8EAFF0801EECF61F82A +:107320000801EECF62F80801EECF63F80801EECF56 +:1073300064F8040E080108015825E96E000E0801E2 +:1073400008015921EA6E0801EECF65F80801EECF79 +:1073500066F80801EECF67F80801EECF68F8080E6E +:10736000080108015825E96E000E0801080159219D +:10737000EA6E0801EECF69F80801EECF6AF808015D +:10738000EECF6BF80801EECF6CF80C0E0801080187 +:107390005825E96E000E080108015921EA6E08011E +:1073A000EECF6DF80801EECF6EF80801EECF6FF862 +:1073B0000801EECF70F8100E080108015825E96E9B +:1073C000000E080108015921EA6E0801EECF71F89C +:1073D0000801EECF72F80801EECF73F80801EECF86 +:1073E00074F8180E080108015825080108015F6F9C +:1073F000000E0801080159210801606F140E0801F0 +:1074000008015825E96E000E080108015921EA6EAD +:10741000EF500801756F3F0E08017517080175518F +:10742000080108015F250801766FE86A080175BF49 +:10743000E8680801080160210801776F76C85DF8E7 +:1074400077C85EF80801756F000E080108015C6FCF +:107450000801755143EFBAF05FC8E9FF60C8EAFF61 +:107460000201730E080108015C25E16EE26A020167 +:10747000020EE222EFCFE7FF080108015F4B602B0D +:10748000080108015C2B080108015E510801080190 +:10749000601906E1080108015D51080108015F1942 +:1074A000D8A455EFBAF057EFBAF02CEFBAF00201BA +:1074B000730E080108015C25E96EEA6A0201020EFA +:1074C000EA22800EEF6E080108015C2B380E0801DD +:1074D00008015C656EEFBAF070EFBAF0D5EFBAF064 +:1074E0003F0E080108015C6578EFBAF07AEFBAF058 +:1074F0007CEFBAF095EFBAF00201730E08010801B3 +:107500005C25E96EEA6A0201020EEA22000EEF6EC5 +:10751000080108015C2B3F0E080108015C6593EF30 +:10752000BAF095EFBAF07CEFBAF00801710E0801DD +:107530000801836F0801080E0801846F08016D0EB1 +:1075400008010801816F0801080E0801826F080117 +:10755000690E080108017F6F0801080E0801806F9D +:107560000801650E080108017D6F0801080E080179 +:107570007E6F0801610E080108017B6F0801080E8B +:1075800008017C6F0201730E08010801796F020186 +:10759000020E08017A6F80EC9BF00801756F000EF7 +:1075A000080108015C6F08017551370E08010801D8 +:1075B0005C65DDEFBAF0DFEFBAF0E1EFBAF0FAEFB9 +:1075C000BAF00201730E080108015C25E96EEA6A4F +:1075D0000201020EEA22000EEF6E080108015C2B88 +:1075E000370E080108015C65F8EFBAF0FAEFBAF05F +:1075F000E1EFBAF0140E080108015825E96E000EFB +:10760000080108015921EA6EEF500801756F080161 +:10761000D89075370801D89075370801D89075351E +:1076200002010201B26F140E080108015825E96E2B +:10763000000E080108015921EA6EEECF75F8EECF71 +:1076400076F8EECF77F8EECF78F8060E2EEFBBF097 +:10765000D89008017833773376337533E82E28EFE6 +:10766000BBF00801755102010201B16F140E08014F +:1076700008015825E96E000E080108015921EA6E3B +:10768000EECF75F8EECF76F8EECF77F8EECF78F84C +:107690000E0E51EFBBF0D890080178337733763374 +:1076A0007533E82E4BEFBBF0080175510201020162 +:1076B000B06F140E080108015825E96E000E08018C +:1076C00008015921EA6EEECF75F8EECF76F8EECFCD +:1076D00077F8EECF78F8160E74EFBBF0D89008016B +:1076E0007833773376337533E82E6EEFBBF00801CD +:1076F000755102010201AF6F140E080108015825EF +:10770000E96E000E080108015921EA6EEECF75F806 +:10771000EECF76F8EECF77F8EECF78F81E0E97EF33 +:10772000BBF0D89008017833773376337533E82E81 +:1077300091EFBBF00801755102010201AE6F080123 +:10774000756F000E02010201AD6F0801755108014D +:10775000756F000E02010201AC6F0801755108013E +:10776000756F000E02010201AB6F0801755108012F +:10777000710E08010801836F0801080E0801846F6B +:1077800008016D0E08010801816F0801080E08014B +:10779000826F0801690E080108017F6F0801080E59 +:1077A0000801806F0801650E080108017D6F08015E +:1077B000080E08017E6F0801610E080108017B6F49 +:1077C0000801080E08017C6F0201730E0801080110 +:1077D000796F0201020E08017A6F80EC9BF05AC8A3 +:1077E000E9FF5BC8EAFF080164C8EFFF0801080170 +:1077F0005A4B5B2B5AC8E9FF5BC8EAFF080163C814 +:10780000EFFF080108015A4B5B2B5AC8E9FF5BC820 +:10781000EAFF080162C8EFFF080108015A4B5B2B21 +:107820005AC8E9FF5BC8EAFF080161C8EFFF080119 +:1078300008015A4B5B2B5AC8E9FF5BC8EAFF0801F5 +:1078400068C8EFFF080108015A4B5B2B5AC8E9FFD3 +:107850005BC8EAFF080167C8EFFF080108015A4B3F +:107860005B2B5AC8E9FF5BC8EAFF080166C8EFFF57 +:10787000080108015A4B5B2B5AC8E9FF5BC8EAFFB5 +:10788000080165C8EFFF080108015A4B5B2B5AC875 +:10789000E9FF5BC8EAFF08016CC8EFFF08010801B7 +:1078A0005A4B5B2B5AC8E9FF5BC8EAFF08016BC85B +:1078B000EFFF080108015A4B5B2B5AC8E9FF5BC870 +:1078C000EAFF08016AC8EFFF080108015A4B5B2B69 +:1078D0005AC8E9FF5BC8EAFF080169C8EFFF080161 +:1078E00008015A4B5B2B5AC8E9FF5BC8EAFF080145 +:1078F00070C8EFFF080108015A4B5B2B5AC8E9FF1B +:107900005BC8EAFF08016FC8EFFF080108015A4B86 +:107910005B2B5AC8E9FF5BC8EAFF08016EC8EFFF9E +:10792000080108015A4B5B2B5AC8E9FF5BC8EAFF04 +:1079300008016DC8EFFF080108015A4B5B2B5AC8BC +:10794000E9FF5BC8EAFF080174C8EFFF08010801FE +:107950005A4B5B2B5AC8E9FF5BC8EAFF080173C8A2 +:10796000EFFF080108015A4B5B2B5AC8E9FF5BC8BF +:10797000EAFF080172C8EFFF080108015A4B5B2BB0 +:107980005AC8E9FF5BC8EAFF080171C8EFFF0801A8 +:1079900008015A4B5B2B1200000E08010801296FE9 +:1079A000000E08012A6F000E08012B6F000E08015F +:1079B0002C6F00014E514B114C114D11D8B4E3EF17 +:1079C000BCF0E5EFBCF01FEFBDF0C4EC43F00001EC +:1079D00000014B5108010801A15D080108012E6F4B +:1079E000000100014C5108010801A25908012F6F44 +:1079F000000100014D5108010801A3590801306F31 +:107A0000000100014E5108010801A4590801316F1D +:107A1000F20E08010801326F9E0E0801336F000E4E +:107A20000801346F000E0801356F90EC1FF02EC86E +:107A300029F82FC82AF830C82BF831C82CF80801CB +:107A40002D6F010E08010801536F08012D5167ECDD +:107A50003DF008012D6F010E08010801536F080168 +:107A60002D5167EC3DF008012D6F060E080108014D +:107A7000536F08012D5167EC3DF008012D6F000E8A +:107A800008010801536F08012D5167EC3DF0080112 +:107A90002D6F120E08010801536F08012D5167EC7C +:107AA0003DF008012D6F230E08010801536F0801F6 +:107AB0002D5167EC3DF008012D6F340E08010801CF +:107AC000536F08012D5167EC3DF008012D6F560EE4 +:107AD00008010801536F08012D5167EC3DF02AC8D9 +:107AE00053F867EC3DF029C853F867EC3DF0080106 +:107AF0002D6F800E08010801536F08012D51000100 +:107B0000000146A986EFBDF088EFBDF090EFBDF013 +:107B100008012D6F000E08010801536F08012D5157 +:107B200067EC3DF008012D6F000E08010801536F4E +:107B300008012D5167EC3DF0080108012251030AAC +:107B4000D8A4A5EFBDF0A7EFBDF0C5EFBDF00801CB +:107B500008012351D8B4AFEFBDF0B1EFBDF0C5EFD0 +:107B6000BDF0040E08010801556F000E0801566FA4 +:107B70000001570E08010801536F0001000E0801B3 +:107B8000546FF9EC30F0EDEFBDF008012D6F000EF1 +:107B900008010801536F08012D5167EC3DF0080101 +:107BA0002D6F000E08010801536F08012D5167EC7D +:107BB0003DF008012D6F000E08010801536F080108 +:107BC0002D5167EC3DF008012D6F000E08010801F2 +:107BD000536F08012D5167EC3DF008012D6F000E29 +:107BE00008010801246F08012D510B0E080108013E +:107BF0002465FDEFBDF0FFEFBDF001EFBEF018EF23 +:107C0000BEF008012D6F000E08010801536F080136 +:107C10002D5167EC3DF008010801242B0B0E0801E3 +:107C20000801246516EFBEF018EFBEF001EFBEF0BC +:107C3000060E08010801556F000E0801566F00017D +:107C4000990E08010801536F0001000E0801546FDE +:107C5000F9EC30F008012D6F000E08010801246FC7 +:107C600008012D51C90E0801080124653AEFBEF044 +:107C70003CEFBEF03EEFBEF055EFBEF008012D6FB9 +:107C8000000E08010801536F08012D5167EC3DF00B +:107C900008010801242BC90E08010801246553EFCF +:107CA000BEF055EFBEF03EEFBEF008012D6F630E43 +:107CB00008010801536F08012D5167EC3DF00801E0 +:107CC0002D6F820E08010801536F08012D5167ECDA +:107CD0003DF008012D6F530E08010801536F080194 +:107CE0002D5167EC3DF008012D6F630E080108016E +:107CF000536F08012D5167EC3DF008012D6F350ED3 +:107D000008010801536F08012D5167EC3DF008018F +:107D10002D6F010E08010801536F08012D5167EC0A +:107D20003DF022C853F867EC3DF008010801220538 +:107D3000D8A49DEFBEF09FEFBEF0A1EFBEF0000112 +:107D40004695080108012251030AD8A4AAEFBEF003 +:107D5000ACEFBEF0D9EFBEF0080108012367B3EF26 +:107D6000BEF0B5EFBEF0D9EFBEF008012D6F360EB4 +:107D700008010801536F08012D5167EC3DF008011F +:107D80002D6F040E08010801536F08012D5167EC97 +:107D90003DF056C053F867EC3DF055C053F867EC22 +:107DA0003DF054C053F867EC3DF053C053F867EC16 +:107DB0003DF008012D6F370E08010801536F0801CF +:107DC0002D5167EC3DF008012D6F040E08010801EC +:107DD000536F08012D5167EC3DF008012D6F010E26 +:107DE00008010801536F08012D5167EC3DF00801AF +:107DF0002D6F030E08010801536F08012D5167EC28 +:107E00003DF008012D6F060E08010801536F0801AF +:107E10002D5167EC3DF008012D6F0C0E0801080193 +:107E2000536F08012D5167EC3DF008010801225104 +:107E3000030AD8A41EEFBFF020EFBFF02AEFBFF077 +:107E4000080108012351D8B428EFBFF02AEFBFF092 +:107E500040EFBFF0080108012205D8A432EFBFF0BF +:107E600034EFBFF066EFBFF000015A5157115811BF +:107E70005911D8B43EEFBFF040EFBFF066EFBFF04E +:107E800008012D6F320E08010801536F08012D51B2 +:107E900067EC3DF008012D6F040E08010801536FD7 +:107EA00008012D5167EC3DF0040E08010801556FE3 +:107EB000000E0801566F0001570E08010801536FAC +:107EC0000001000E0801546FF9EC30F008012D6F2D +:107ED000FF0E08010801536F08012D5167EC3DF0BA +:107EE0007CEFBFF008012D6F000E08010801536FF1 +:107EF00008012D5167EC3DF02C0E06010601BC5D1A +:107F0000010E0601BD59D8A088EFBFF08AEFBFF07F +:107F100072EFBFF06CC025F86DC026F86EC027F870 +:107F20006FC028F808010801236799EFBFF09BEFA5 +:107F3000BFF0A8EFBFF0000E000100016C6F000E53 +:107F400000016D6F000E00016E6F000E00016F6F7B +:107F500053EC21F025C86CF026C86DF027C86EF0F0 +:107F600028C86FF012000801226F000E08010801F6 +:107F70001D6F08012251040E080108011D65C3EFA1 +:107F8000BFF0C5EFBFF0C7EFBFF071EFC2F008015F +:107F900008011D51170DF3CF22F80E0E08012227FC +:107FA0000201000E08012225E96EEA6A0201020EB2 +:107FB000EA22EF50050AD8B4E0EFBFF0E2EFBFF0DD +:107FC000FCEFBFF0080108011D51170DF3CF22F897 +:107FD0000E0E080122270201000E08012225E96E7B +:107FE000EA6A0201020EEA22040EEF62FAEFBFF023 +:107FF000FCEFBFF0FEEFBFF064EFC2F03EEFC2F067 +:108000001DEC43F00009D8B408EFC0F00AEFC0F04F +:1080100075EFC0F0080108011D51170DF3CF22F8CC +:108020000E0E080122270201000E08012225E96E2A +:10803000EA6A0201020EEA22000EEF6E0801080150 +:108040001D51170DF3CF22F8140E0801222702014B +:10805000000E08012225E96EEA6A0201020EEA22F8 +:10806000EF500801236F080123A139EFC0F03BEF67 +:10807000C0F059EFC0F00801226F010E080108019D +:108080002F6F08012251080108011D51170D02012F +:10809000000EF324E96EEA6A0201020EEA220801E8 +:1080A000EECF2DF80801EDCF2EF848EC3BF075EF40 +:1080B000C0F00801226F010E080108012F6F0801AE +:1080C0002251080108011D51170D0201000EF32471 +:1080D000E96EEA6A0201020EEA220801EECF2DF8EB +:1080E0000801EDCF2EF80DEC3BF064EFC2F0080173 +:1080F0001E0E080108012D6F0801080E08012E6FE1 +:10810000D3EC94F00009D8B488EFC0F08AEFC0F047 +:1081100075EFC0F0DCEC40F00009D8B492EFC0F08D +:1081200094EFC0F0F2EFC0F0080108011D51170DE7 +:108130000201000EF324E96EEA6A0201020EEA224D +:1081400008011EC8EEFF08011FC8EEFF080120C885 +:10815000EEFF080121C8EEFF080108011D51170DAF +:10816000F3CF22F80E0E080122270201000E0801AB +:108170002225E96EEA6A0201020EEA22020EEF6E81 +:10818000080108011D51170DF3CF22F8130E080145 +:1081900022270201000E08012225E96EEA6A020187 +:1081A000020EEA22000EEF6E080108011D51170DA4 +:1081B000F3CF22F80F0E080122270201000E08015A +:1081C0002225E96EEA6A0201020EEA22270EEE6E0D +:1081D000000EEE6E000EEE6E000EED6EED52ED52E4 +:1081E00006EFC1F0080108011D51170DF3CF22F869 +:1081F0000E0E080122270201000E08012225E96E59 +:10820000EA6A0201020EEA22010EEF6E64EFC2F08A +:108210005AEC42F0080108011D51170DF3CF22F866 +:10822000150E080122270201000E08012225E96E21 +:10823000EA6A0201020EEA220801A1C8EEFF080163 +:10824000A2C8EDFF080108011D51170D0201000E23 +:10825000F324080108014C6F08014D6B0201020E66 +:1082600008014D230EEC23F0080108011D51170DE4 +:10827000F3CF22F80E0E080122270201000E08019A +:108280002225E96EEA6A0201020EEA22030EEF6E6F +:1082900064EFC2F0080108011D51170DF3CF22F859 +:1082A000040E080122270201000E08012225080100 +:1082B00008014E6F08014F6B0201020E08014F23A7 +:1082C000080108011D51170D0201000EF3240801D9 +:1082D00008014C6F08014D6B0201020E08014D238D +:1082E000E7EC1AF00009D8A478EFC1F07AEFC1F0FA +:1082F00026EFC2F0080108011D51170DF3CF22F837 +:10830000150E080122270201000E08012225E96E40 +:10831000EA6A0201020EEA22EECF23F8EDCF24F83A +:108320005AEC42F00801235108010801A15D08013F +:10833000256F0801245108010801A2590801266F80 +:10834000080108011D51170DF3CF27F80F0E080182 +:1083500027270201000E08012725E96EEA6A0201BB +:10836000020EEA22EECF28F8EDCF29F808012551B8 +:108370000801285D0801265108012959D8B0C3EF2A +:10838000C1F0C5EFC1F024EFC2F0080108011D5192 +:10839000170DF3CF22F8130E080122270201000E59 +:1083A00008012225E96EEA6A0201020EEA22EF5074 +:1083B0000801236F060E0801235DD8B0E2EFC1F07B +:1083C000E4EFC1F010EFC2F0080108011D51170DD4 +:1083D000F3CF22F8130E080122270201000E080134 +:1083E0002225E96EEA6A0201020EEA22EF2A08015A +:1083F00008011D51170DF3CF22F80F0E0801222797 +:108400000201000E08012225E96EEA6A0201020E4D +:10841000EA22D890EE36EE36EE36ED36ED52ED52DB +:10842000080108011D51170DF3CF22F80E0E0801A7 +:1084300022270201000E08012225E96EEA6A0201E4 +:10844000020EEA22020EEF6E75EFC0F0080108017D +:108450001D51170DF3CF22F80E0E0801222702013D +:10846000000E08012225E96EEA6A0201020EEA22E4 +:10847000050EEF6E64EFC2F064EFC2F00801080170 +:108480001D51170DF3CF22F80E0E0801222702010D +:10849000000E08012225E96EEA6A0201020EEA22B4 +:1084A000EF50000A01E123D6010A01E1A9D5030A30 +:1084B00001E1AED6010A01E1EDD6070A01E115D6C8 +:1084C000010ADAE03CEFC2F0080108011D2B040E9E +:1084D000080108011D656FEFC2F071EFC2F0C7EF30 +:1084E000BFF01200080108010D51D8B47AEFC2F0B4 +:1084F0007CEFC2F081EFC2F0080108010E2B84EF7F +:10850000C2F0080108010E07DDEFC4F0050E0801F6 +:1085100008010E658EEFC2F090EFC2F09FEFC2F03F +:108520000C0E080108010E6198EFC2F09AEFC2F03C +:108530009FEFC2F007010701102BEEEFC4F00D0E04 +:10854000080108010E65A7EFC2F0A9EFC2F0CFEF56 +:10855000C2F0160E080108010E61B1EFC2F0B3EFD0 +:10856000C2F0CFEFC2F0140E070107011065BBEF98 +:10857000C2F0BDEFC2F0CFEFC2F008010F6F010EE5 +:10858000070107012A6F08010F5108010F6F030E41 +:1085900007010701106F08010F51EEEFC4F0E0EC86 +:1085A0003FF0EEEFC4F00D0E080108010E65DBEFA1 +:1085B000C2F0DDEFC2F0CFEFC2F0160E08010801E5 +:1085C0000E61E5EFC2F0E7EFC2F0CFEFC2F00701B6 +:1085D00007011007070107011067F1EFC2F0F3EF81 +:1085E000C2F002EFC3F0000E06010601E16F000EBB +:1085F0000601E26F08010F6F020E070107012A6FE3 +:1086000008010F51EEEFC4F00EC812F80DC811F8B2 +:108610004CEC1EF011C8BAF612C8BBF606010601F2 +:10862000BB29FE0ED8B4BA19D8A419EFC3F01BEFBA +:10863000C3F01FEFC3F0E0EC3FF0EEEFC4F0060133 +:108640000601BA29D8B4BB29D8A429EFC3F02BEF6F +:10865000C3F02DEFC3F0EEEFC4F006010601E251C6 +:10866000E111D8A436EFC3F038EFC3F042EFC3F006 +:1086700006010601BA5106010601E26F0601E16B2F +:10868000E8EFC3F006010601BA5106010601E11345 +:1086900006010601BB5106010601E2137DEFC3F09E +:1086A00008010F6F070E070107019A6F08010F51AC +:1086B000D8EFC3F008010F6F050E070107019A6F8D +:1086C00008010F51D8EFC3F008010F6F080E070122 +:1086D00007019A6F08010F51D8EFC3F008010F6F1F +:1086E000090E070107019A6F08010F51D8EFC3F077 +:1086F000070107019A69D8EFC3F00601E1C60FF838 +:108700000601E2C610F80801C2EFC3F008010F51DC +:10871000840ADAE0100AD8E078EFC3F008010F51BC +:10872000200ABEE078EFC3F008010F51140ACCE034 +:1087300078EFC3F008010F51100AB2E078EFC3F0F0 +:1087400008010F51600ACAE078EFC3F008010F5129 +:10875000440AB0E078EFC3F008010F51740AAAE0B0 +:1087600078EFC3F008010F51400AA4E0300AA2E0FC +:1087700078EFC3F008010F51240A92E0900A90E0CC +:1087800078EFC3F008011051190AC0E0040AC6E0EE +:10879000340ACAE0040ACEE0700AD2E0950AD6E0B4 +:1087A000100ADAE0340ADEE0140AE4E078EFC3F0FD +:1087B00008010F6F030E070107012A6F08010F510F +:1087C00008010F6F000E070107011C6F08010F5110 +:1087D000EEEFC4F00EC812F80DC811F84CEC1EF004 +:1087E00011C8BAF612C8BBF606010601BB29FE0E77 +:1087F000D8B4BA19D8A4FFEFC3F001EFC4F047EF23 +:10880000C4F0070107019AAF08EFC4F00AEFC4F003 +:10881000CFEFC2F0080108010D6711EFC4F013EFAC +:10882000C4F0CFEFC2F0D89006010601C5310801AF +:10883000106F06010601C43108010F6F380E0801E0 +:108840000F5D000E1059D8A028EFC4F02AEFC4F035 +:10885000CFEFC2F01E0E080108010E6532EFC4F022 +:1088600034EFC4F0CFEFC2F008010F6F000E070124 +:1088700007019A6F08010F51000E06010601BA6F39 +:10888000000E0601BB6F45EFC4F058EFC4F00601BF +:108890000601BA29D8B4BB29D8A451EFC4F053EFCC +:1088A000C4F055EFC4F0EEEFC4F0070107019A07DA +:1088B0000601A90E070107011C25E96EEA6A0601F7 +:1088C000060EEA220601BAC6EFFF070107011C2BBC +:1088D000070107019A676FEFC4F071EFC4F0CBEFA7 +:1088E000C4F0E0EC3FF00BEC43F0850E080108010A +:1088F0002E6FFF0E08012F6F930E080108012C6FD9 +:10890000FF0E08012D6FF5EC43F0700E0801080111 +:108910002E6FFF0E08012F6F2D0E080108012C6F1E +:10892000FF0E08012D6FF5EC43F006010801E1C6CA +:108930002EF806010801E2C62FF808010801306B85 +:108940000801316BAB0E080108012C6FFF0E080106 +:108950002D6F71EC43F01CC726F80601A90E080123 +:108960000801246F0601060E0801256FB10E0801EB +:108970000801226FFF0E0801236FB7EC43F00801D6 +:108980000F6F010E080108012C6F08010F515CECFC +:1089900041F0EEEFC4F0910E06010601C45D010E38 +:1089A0000601C559D8A0D7EFC4F0D9EFC4F002EF43 +:1089B000C3F0E0EC3FF0EEEFC4F0070107012A51ED +:1089C000000A01E1A3D5010A01E1EDD5030A01E1A5 +:1089D0001BD6010A01E1FED6EEEFC4F01200080139 +:1089E000096F000E080108011D6F0801095153ECC1 +:1089F00044F00009D8A4FFEFC4F001EFC5F027EF61 +:108A0000C5F0070107011D51D8B409EFC5F00BEF00 +:108A1000C5F025EFC5F09EC72DF895EC12F09EC766 +:108A20000DF8EEEC41F00801096FFE0E0701070199 +:108A30009E6F08010951BDEC3BF00801096F000E63 +:108A4000070107011D6F0801095119EFC7F006EF73 +:108A5000C7F00801096F010E070107011D6F08012A +:108A600009510801096F000E08010801146F08017F +:108A70000951500E08010801126F000E0801136F12 +:108A800008010A6F010E08010801116F08010A515F +:108A90006A0E08010B6F070E0C6F08010BC80DF86A +:108AA00008010CC80EF8080108010F6B0801106BD3 +:108AB0003FECDAF0070107019E6F070107019E51A5 +:108AC000FE0AD8A466EFC5F068EFC5F072EFC5F0F6 +:108AD0000801096F000E070107011D6F0801095108 +:108AE00019EFC7F0C4EC43F0A1C8F5F6A2C8F6F63A +:108AF000A3C8F7F6A4C8F8F619EFC7F09EC70DF89B +:108B00003DEC41F00009D8A488EFC5F08AEFC5F02C +:108B1000C6EFC5F0C4EC43F006010601F5510801AB +:108B20000801A15D0801096F06010601F65108015F +:108B30000801A25908010A6F06010601F751080150 +:108B40000801A35908010B6F06010601F85108013D +:108B50000801A45908010C6F5D0E095DA00E0A59A9 +:108B6000120E0B59000E08010C59D8A0BAEFC5F02F +:108B7000BCEFC5F0C4EFC5F00801096F040E070192 +:108B800007011D6F0801095119EFC7F00801096FAE +:108B9000020E070107011D6F0801095119EFC7F007 +:108BA0009EC768F8BEEC20F07D0E08010801685DE4 +:108BB000000E08016959D8B0E0EFC5F0E2EFC5F04A +:108BC000E4EFC5F019EFC7F0D90E08010801576F9F +:108BD000FF0E0801586F9EC756F830EC42F0160E93 +:108BE00008010801576FFE0E0801586F9EC756F81E +:108BF00030EC42F00801096F000E06010601E76F34 +:108C000008010951050E06010601E7650AEFC6F0E5 +:108C10000CEFC6F00EEFC6F049EFC6F00001DB0E18 +:108C200006010601E725E96EEA6A0001000EEA2264 +:108C3000EF5008010801586F0DEC3FF008010801E2 +:108C4000576F9EC756F801EC15F00001DB0E0601C8 +:108C50000601E725E96EEA6A0001000EEA22EF50FC +:108C600008010801646FE1EC3EF008010801576F4C +:108C70009EC756F801EC15F006010601E72B050E1C +:108C800006010601E76547EFC6F049EFC6F00EEFB3 +:108C9000C6F0A90E08010801576FFE0E0801586FB3 +:108CA0009EC756F830EC42F007016A0E0801080131 +:108CB000576F0701070E0801586F9EC756F845EC1D +:108CC00042F0910E08010801576FFE0E0801586F1F +:108CD0009EC756F830EC42F09EC768F8F6EC3BF0C1 +:108CE0000801096F000E06010601E76F080109512E +:108CF0000801096F030E070107011D6F08010951E3 +:108D000019EFC7F00801080E080108010E6F0801ED +:108D1000080E08010F6F9EC70DF84BEC28F00009F4 +:108D2000D8A495EFC6F097EFC6F099EFC6F0CEEF56 +:108D3000C6F0030E06010601E765A1EFC6F0A3EF3A +:108D4000C6F0A9EFC6F008C80DF86CEC0DF0CCEF3A +:108D5000C6F00801080108510A0AD8B4B2EFC6F0FB +:108D6000B4EFC6F0BFEFC6F00801080108510D0AC4 +:108D7000D8A4BDEFC6F0BFEFC6F0C4EFC6F0060141 +:108D80000601E72BCCEFC6F00801096F000E0601C3 +:108D90000601E76F0801095182EFC6F09EC70DF882 +:108DA0003DEC41F00009D8A4D8EFC6F0DAEFC6F0E8 +:108DB000E2EFC6F00801096F040E070107011D6FFD +:108DC0000801095119EFC7F09EC72DF895EC12F074 +:108DD0009EC70DF8EEEC41F00801096FFE0E070189 +:108DE00007019E6F080109510801096F010E070173 +:108DF00007012E6F080109510801096F050E0701CF +:108E000007011D6F0801095119EFC7F0070107019C +:108E10001D51000A01E11DD6010A01E16FD6030AC6 +:108E200001E1BED6010A01E16DD7070ACDE019EFD5 +:108E3000C7F0120008010C6F000E08010801086F4E +:108E400008010C5133EFC8F09BC735F8BEC633F8A4 +:108E5000BFC634F887EC3EF0D8A031EFC7F033EF4F +:108E6000C7F086EFC7F0960E06010601D4653BEF0A +:108E7000C7F03DEFC7F043EFC7F0BEC696F7BFC6D9 +:108E800097F79BC79CF706010601D451D8B44BEF66 +:108E9000C7F04DEFC7F071EFC7F0D4C60EF8080168 +:108EA0000C6F000E080108010D6F08010C5155EC04 +:108EB000D0F0D4C60EF808010C6F000E08010801AE +:108EC0000D6F08010C5172ECC2F0D4C60EF8080107 +:108ED0000C6F000E080108010D6F08010C51B7EC72 +:108EE000AEF006010601FB2B08010C6F000E060117 +:108EF0000601D46F08010C5108010C6F000E070128 +:108F00000701376F08010C51CEEFC7F006010601CB +:108F1000D4678DEFC7F08FEFC7F095EFC7F0BEC6EF +:108F200094F7BFC695F79BC7DAF606010601FB5119 +:108F3000D8B49DEFC7F09FEFC7F0C3EFC7F0FBC6F3 +:108F40000EF808010C6F010E080108010D6F0801F1 +:108F50000C5155ECD0F0FBC60EF808010C6F010E59 +:108F6000080108010D6F08010C5172ECC2F0FBC63C +:108F70000EF808010C6F010E080108010D6F0801C1 +:108F80000C51B7ECAEF006010601D42B08010C6FB2 +:108F9000000E06010601FB6F08010C510701D89075 +:108FA0009B33070107019B67D8EFC7F0DAEFC7F0E3 +:108FB000F9EFC7F008010C6F800E070107019B6FE6 +:108FC00008010C5106010601BE4BBF2B060106012C +:108FD000BF51020ABE11D8A4F0EFC7F0F2EFC7F0FC +:108FE000F9EFC7F0000E06010601BE6F000E060184 +:108FF000BF6F06010601BF5107010701971906E17E +:1090000006010601BE51070107019619D8A40BEF0E +:10901000C8F00DEFC8F01EEFC8F0070107019B5123 +:10902000070107019C6317EFC8F019EFC8F01EEFA6 +:10903000C8F0070107019669070197690601060153 +:10904000D451960AD8A427EFC8F029EFC8F033EF1F +:10905000C8F008010C6F010E08010801086F080133 +:109060000C5147EFC8F006010601D951060106016F +:10907000BF1906E106010601D85106010601BE1915 +:10908000D8A445EFC8F047EFC8F024EFC7F00801B7 +:10909000080108674EEFC8F050EFC8F052EFC8F073 +:1090A00010EFC9F0070107013751D8B45AEFC8F0E3 +:1090B0005CEFC8F05EEFC8F010EFC9F094C70FF88E +:1090C00095C710F896C70DF897C70EF8E1EC2FF08A +:1090D0000DC80AF80EC80BF8080108010BBF73EFA2 +:1090E000C8F075EFC8F086EFC8F0080108010B5111 +:1090F000800A800F320ED8B40A5DD8B082EFC8F073 +:1091000084EFC8F086EFC8F010EFC9F0080108013D +:109110000B51800A800F9E0ED8B40A5DD8A093EF41 +:10912000C8F095EFC8F0A4EFC8F0080108010B5192 +:10913000800A800FA30ED8B40A5DD8A0A2EFC8F0B1 +:10914000A4EFC8F0A4EFC8F008010C6F000E0801EE +:109150000801096F08010C51DAC60FF894C70DF821 +:1091600095C70EF8F8ECCAF0080108010927DAC61D +:109170000FF894C70DF895C70EF80FECE1F0080151 +:1091800008010927DAC60FF894C70DF895C70EF83D +:10919000B8ECD8F0080108010927DAC60FF894C71F +:1091A0000DF895C70EF8EBECE5F00801080109276A +:1091B000DAC60FF894C70DF895C70EF881ECD5F014 +:1091C000080108010927DAC60FF894C70DF895C7FA +:1091D0000EF811ECC9F008010801092708010C6F0D +:1091E000010E07010701376F08010C510801080142 +:1091F0000951D8B4FEEFC8F000EFC9F00EEFC9F086 +:10920000000E06010601BE6F000E0601BF6F000EC4 +:1092100006010601D86F000E0601D96F10EFC9F0E4 +:109220001200000E08010801146F000E0801156FEE +:10923000000E0801166F000E0801176F08010F0ECF +:1092400008010801356F0801080E0801366F080192 +:109250000D0E08010801336F0801080E0801346F74 +:1092600099EC3CF008010F0E080108012E6F08016F +:10927000080E08012F6F08010D0E080108012C6F60 +:109280000801080E08012D6FACEC2AF0010E080150 +:109290000801106F000E0801116F000E0801126F17 +:1092A000000E0801136F000E08010801186F000E70 +:1092B0000801196F080108011951800A800F200E5A +:1092C000D8B4185DD8A067EFC9F069EFC9F06BEFAB +:1092D000C9F0E3EFC9F008010F0E080108012E6F75 +:1092E0000801080E08012F6F08010D0E0801080182 +:1092F0002C6F0801080E08012D6FACEC2AF0080154 +:1093000008011A6F08010F0E080108012E6F0801ED +:10931000080E08012F6F08010D0E080108012C6FBF +:109320000801080E08012D6FACEC2AF008010801B5 +:109330001B6FBAEFC9F0C6EFC9F008010801105160 +:10934000080108011413080108011151080108015E +:10935000151308010801125108010801161308012C +:1093600008011351080108011713C6EFC9F0000ED8 +:10937000F7EFCAF01BC82DF81AC82CF899EC3DF08D +:10938000000AD9E0010AD9E0B7EFC9F00801D89086 +:109390000801103708011137080112370801133787 +:1093A00008010801184B192B080108011951800AFE +:1093B000800F200ED8B4185DD8A0E1EFC9F0E3EF1C +:1093C000C9F06BEFC9F0080114C81CF8080115C8F2 +:1093D0001DF8080116C81EF8080117C81FF8080173 +:1093E0001C1F1D1F1E1F1F1F110EFDEFC9F0D8905F +:1093F00008011F331E331D331C33E82EF7EFC9F06D +:10940000FF0E08011C150801206F000E08011D1534 +:109410000801216F000E08011E150801226F000EC1 +:1094200008011F150801236F080114C824F808015A +:1094300015C825F8080116C826F8080117C827F826 +:10944000190E29EFCAF0D8900801273326332533A7 +:109450002433E82E23EFCAF0FF0E0801241508017B +:10946000286F000E080125150801296F000E08015C +:10947000261508012A6F000E0801271508012B6F19 +:109480000801235108012B190EE10801225108019E +:109490002A1909E1080121510801291904E10801EB +:1094A000205108012819D8B458EFCAF05AEFCAF071 +:1094B0005DEFCAF0000EF7EFCAF0FF0E080114C806 +:1094C0001CF8080115C81DF8080116C81EF8080187 +:1094D00017C81FF808011C1F1D1F1E1F1F1F080192 +:1094E0001C150801206F000E08011D150801216FD1 +:1094F000000E08011E150801226F000E08011F153D +:109500000801236FFF0E080114C824F8080115C8CC +:1095100025F8080116C826F8080117C827F825C835 +:1095200024F826C825F827C826F80801276B080163 +:1095300024150801286F000E080125150801296F60 +:10954000000E0801261508012A6F000E08012715D4 +:1095500008012B6F0801235108012B190EE10801A6 +:10956000225108012A1909E108012151080129198C +:1095700004E10801205108012819D8B4C2EFCAF04B +:10958000C4EFCAF0C7EFCAF0000EF7EFCAF00BEC59 +:1095900043F0EE0E080108012E6FFF0E08012F6F39 +:1095A0002D0E080108012C6FFF0E08012D6FF5EC40 +:1095B00043F014C82EF815C82FF816C830F817C88D +:1095C00031F8B10E080108012C6FFF0E08012D6F54 +:1095D00071EC43F008011C6F020E080108012C6FAA +:1095E00008011C515CEC41F0010EF7EFCAF01200CB +:1095F000000E08010801186F000E0801196F000E17 +:1096000008011A6F000E08011B6F010E0801080106 +:10961000146F000E0801156F000E0801166F000E82 +:109620000801176F000E08010801106F000E0801F5 +:10963000116F000E08010801126F000E0801136F70 +:1096400008010F0E08010801356F0801080E080116 +:10965000366F08010D0E08010801336F0801080E6E +:109660000801346F99EC3CF008010F0E0801080165 +:109670002E6F0801080E08012F6F08010D0E08015A +:1096800008012C6F0801080E08012D6FACEC2AF0C0 +:10969000080108011351800A800F240ED8B4125D0E +:1096A000D8A055EFCBF057EFCBF059EFCBF08AEFC6 +:1096B000CCF008010F0E080108012E6F0801080EFA +:1096C00008012F6F08010D0E080108012C6F080119 +:1096D000080E08012D6FACEC2AF0080108011C6F80 +:1096E00008010F0E080108012E6F0801080E08017D +:1096F0002F6F08010D0E080108012C6F0801080EDC +:1097000008012D6FACEC2AF0080108011D6F08015B +:109710000F0E080108012E6F0801080E08012F6FB7 +:1097200008010D0E080108012C6F0801080E080140 +:109730002D6FACEC2AF0080108011E6F08010F0E16 +:10974000080108012E6F0801080E08012F6F08019B +:109750000D0E080108012C6F0801080E08012D6F7D +:10976000ACEC2AF0080108011F6F40EFCCF00801B3 +:1097700008011351800A800F200ED8B4125DD8A0C2 +:10978000C4EFCBF0C6EFCBF0E0EFCBF0080118C888 +:1097900020F8080119C821F808011AC822F80801A0 +:1097A0001BC823F8D89008012333223321332033F8 +:1097B00020C818F821C819F822C81AF823C81BF8BD +:1097C00051EFCCF0080108011351800A800F200EE0 +:1097D000D8B4125DD8A0EFEFCBF0F1EFCBF00BEFE8 +:1097E000CCF0080118C820F8080119C821F80801B0 +:1097F0001AC822F808011BC823F8D890080123339F +:1098000022332133203320C818F821C819F822C880 +:109810001AF823C81BF808010801145108010801AF +:10982000181308010801155108010801191308014E +:1098300008011651080108011A13080108011751FF +:10984000080108011B1351EFCCF008010801135166 +:10985000800A800F1F0ED8B4125DD8A032EFCCF072 +:1098600034EFCCF03DEFCCF0010E08010801106F91 +:10987000000E0801116F51EFCCF0000ECAEFCCF0D2 +:109880001FC827F81EC826F81DC825F81CC824F8CC +:10989000ADEC31F0000A01E16AD7010A93E025EF4F +:1098A000CCF00801080111511011D8B45AEFCCF0D6 +:1098B0005CEFCCF05EEFCCF08AEFCCF00801080151 +:1098C0001351800A800F1F0ED8B4125DD8B06BEF11 +:1098D000CCF06DEFCCF077EFCCF00801D890080118 +:1098E0001437080115370801163708011737080122 +:1098F0000801124B132B080108011351800A800F35 +:10990000240ED8B4125DD8A088EFCCF08AEFCCF04A +:1099100059EFCBF00BEC43F0580E080108012E6F05 +:10992000FF0E08012F6F2D0E080108012C6FFF0E8E +:1099300008012D6FF5EC43F0E60E080108012E6FCB +:10994000FE0E08012F6FAB0E080108012C6FFF0EF1 +:1099500008012D6FF5EC43F018C82EF819C82FF840 +:109960001AC830F81BC831F8B10E080108012C6F75 +:10997000FF0E08012D6F71EC43F00801206F020EFD +:10998000080108012C6F080120515CEC41F0010E28 +:10999000CAEFCCF012000001000198ADD2EFCCF07C +:1099A000D4EFCCF023EFCDF097EC42F008010801A2 +:1099B000106F080108011051070107013119D8B4CF +:1099C000E4EFCCF0E6EFCCF00DEFCDF010C831F7BE +:1099D000080108011067EFEFCCF0F1EFCCF00DEFCC +:1099E000CDF080C06CF081C06DF082C06EF083C09D +:1099F0006FF084C070F085C071F086C072F087C0CF +:109A000073F00001988F0801116F000E0801080122 +:109A10001D6F080111511BEC34F072ECA6F0080127 +:109A2000116F000E080108011D6F0801115153EC60 +:109A300044F00009D8B41FEFCDF021EFCDF023EFB3 +:109A4000CDF00001989FD7EC8DF0B3ECBFF08FEC18 +:109A500041F00801080E080108011F6F0801080EF7 +:109A60000801206F0501DE0E080108011D6F0501C8 +:109A7000050E08011E6F3FEC00F00009D8A443EF6B +:109A8000CDF045EFCDF047EFCDF091EFCEF084EF84 +:109A9000CEF0B1EC0AF08FEFCEF008010A0E08010B +:109AA0000801236F0801080E0801246F0801090E40 +:109AB00008010801216F0801080E0801226F050145 +:109AC000DA0E080108011F6F0501050E0801206F5D +:109AD00008010C0E080108011D6F0801080E08019D +:109AE0001E6F37EC14F00009D8A479EFCDF07BEFAE +:109AF000CDF07DEFCDF08FEFCEF008010801090524 +:109B0000D8A485EFCDF087EFCDF030EFCEF0000197 +:109B100000016F51080108010F1914E10001000153 +:109B20006E51080108010E190DE1000100016D518F +:109B3000080108010D1906E1000100016C5108013E +:109B400008010C19D8B4A7EFCDF0A9EFCDF01FEFA5 +:109B5000CEF008010C29D8B40D29D8B40E29D8B4F8 +:109B60000F29D8B4B6EFCDF0B8EFCDF01FEFCEF09F +:109B7000000170C011F8000171C012F8000172C03C +:109B800013F8000173C014F80801111F121F131FEE +:109B9000141F000100016C51000100017015080143 +:109BA000156F000100016D510001000171150801E0 +:109BB000166F000100016E510001000172150801CD +:109BC000176F000100016F510001000173150801BA +:109BD000186F08011151080115110801196F0801CA +:109BE00012510801161108011A6F080113510801DA +:109BF000171108011B6F0801145108011811080101 +:109C00001C6F080108010F5108011C1911E108011E +:109C100008010E5108011B190BE1080108010D5143 +:109C200008011A1905E1080108010C510801191968 +:109C3000D8A41DEFCEF01FEFCEF02EEFCEF00AC865 +:109C40001FF80BC820F80501DA0E080108011D6F86 +:109C50000501050E08011E6F8DEC16F08FEFCEF09A +:109C6000080108010951060AD8A439EFCEF03BEFEC +:109C7000CEF055EFCEF00AC821F80BC822F8080143 +:109C80000C0E080108011F6F0801080E0801206F63 +:109C90000501DA0E080108011D6F0501050E080116 +:109CA0001E6FC6EC08F08FEFCEF0080108010951D5 +:109CB000110AD8A45EEFCEF060EFCEF02EEFCEF01A +:109CC0000AC821F80BC822F808010C0E0801080187 +:109CD0001F6F0801080E0801206F0501DA0E080148 +:109CE00008011D6F0501050E08011E6FC1EC05F08E +:109CF0000009D8B47EEFCEF080EFCEF082EFCEF048 +:109D000091EFCEF08FEFCEF0080108010851000A64 +:109D100001E1C3D6060A01E1BCD68FEFCEF027EFF2 +:109D2000CDF0120008013C6F000E08010801356FEC +:109D300008013C5108013C6F000E08010801366F14 +:109D400008013C51000E08010801386F000E08019F +:109D5000396F000E08013A6F000E08013B6FBCEF2F +:109D6000CFF0030E080108013665B9EFCEF0BBEF66 +:109D7000CEF0BDEFCEF0DBEFCFF0300E08010801E2 +:109D8000375F080108013567C8EFCEF0CAEFCEF0A3 +:109D9000D9EFCEF0090E080108013765D2EFCEF0F9 +:109DA000D4EFCEF0D7EFCEF0000E54EFD0F0A8EF06 +:109DB000CFF0080108013551030AD8A4E2EFCEF034 +:109DC000E4EFCEF041EFCFF0080108013751FE0A71 +:109DD000D8B4EDEFCEF0EFEFCEF0F2EFCEF0000E14 +:109DE00054EFD0F0060E0801385D050E0801395910 +:109DF000020E08013A59000E080108013B59D8A08B +:109E000004EFCFF006EFCFF009EFCFF0000E54EFE4 +:109E1000D0F0080108013651080108013325E96E28 +:109E20000801000E080108013421EA6E080108014A +:109E300039510A0DF3CF3CF8080108013A51640D7D +:109E4000F35008013C25080108013825EF6E080190 +:109E50000801362B08013C6F000E08010801356F20 +:109E600008013C51000E08010801386F000E08017E +:109E7000396F000E08013A6F000E08013B6FBCEF0E +:109E8000CFF0080108013751FE0AD8A44AEFCFF0FD +:109E90004CEFCFF09BEFCFF0060E0801385D050EBA +:109EA00008013959020E08013A59000E080108014B +:109EB0003B59D8A05EEFCFF060EFCFF063EFCFF06B +:109EC000000E54EFD0F008010801365108010801D6 +:109ED0003325E96E0801000E080108013421EA6EFD +:109EE0000801080139510A0DF3CF3CF808010801B7 +:109EF0003A51640DF35008013C250801080138254A +:109F0000EF6E08010801362B08013C6F000E0801B6 +:109F10000801356F08013C51000E08010801386F37 +:109F2000000E0801396F000E08013A6F000E08019B +:109F30003B6FBCEFCFF0090E080108013765A3EFB6 +:109F4000CFF0A5EFCFF0A8EFCFF0000E54EFD0F098 +:109F500008010801352B080108013AC83BF808013F +:109F6000080139C83AF80801080138C839F8080169 +:109F70000801386B37C838F8080108013151080169 +:109F80003C6F08010801325108013D6F0801314B57 +:109F9000322B3CC8F6FF3DC8F7FF000EF86E0800F4 +:109FA0000801F5CF37F808013767D9EFCFF0DBEFBD +:109FB000CFF0B1EFCEF0080108013751D8B4E3EF8C +:109FC000CFF0E5EFCFF01FEFD0F0080108013751D7 +:109FD0002F0AD8B4EEEFCFF0F0EFCFF01FEFD0F0B4 +:109FE0000801080137510D0AD8B4F9EFCFF0FBEFA3 +:109FF000CFF01FEFD0F00801080137510A0AD8B49A +:10A0000004EFD0F006EFD0F01FEFD0F00801080108 +:10A010003751200AD8B40FEFD0F011EFD0F01FEF76 +:10A02000D0F0080108013751090AD8B41AEFD0F06E +:10A030001CEFD0F01FEFD0F0000E54EFD0F0060E62 +:10A040000801385D050E08013959020E08013A5918 +:10A05000000E080108013B59D8A031EFD0F033EFD2 +:10A06000D0F036EFD0F0000E54EFD0F0030E080120 +:10A0700008013325E96E000E080108013421EA6E5B +:10A080000801080139510A0DF3CF3CF80801080115 +:10A090003A51640DF35008013C25080108013825A8 +:10A0A000EF6E010E54EFD0F01200080108010D51BF +:10A0B000D8B45DEFD0F05FEFD0F065EFD0F0030ED5 +:10A0C000080108010E2769EFD0F0030E080108010E +:10A0D0000E5F03EFD2F00B0E080108010E6573EF5F +:10A0E000D0F075EFD0F084EFD0F0170E0801080122 +:10A0F0000E617DEFD0F07FEFD0F084EFD0F007015C +:10A100000701092B11EFD2F0030E080108010E65BB +:10A110008CEFD0F08EEFD0F0B9EFD0F00E0E08013A +:10A1200008010E6196EFD0F098EFD0F0B9EFD0F0C3 +:10A13000190E070107010965A0EFD0F0A2EFD0F0DA +:10A14000B1EFD0F008010F6F010E070107012B6F6F +:10A1500008010F51000E06010601DF6F000E060117 +:10A16000E06F08010F6F000E07010701096F08017A +:10A170000F5111EFD2F00EC812F80DC811F8C6EC4D +:10A180002CF011C8FDF412C8FEF404010401FE29EC +:10A19000FE0ED8B4FD19D8A4D0EFD0F0D2EFD0F095 +:10A1A000D6EFD0F008EC40F011EFD2F0040104013A +:10A1B000FD29D8B4FE29D8A4E0EFD0F0E2EFD0F02A +:10A1C000E4EFD0F011EFD2F006010601E051DF110B +:10A1D000D8A4EDEFD0F0EFEFD0F0F9EFD0F004011C +:10A1E0000401FD5106010601E06F0601DF6B62EF1D +:10A1F000D1F004010401FD5106010601DF13040141 +:10A200000401FE5106010601E0132DEFD1F0080113 +:10A210000F6F060E07010701346F08010F513F0E43 +:10A2200007010701986F000E0701996F52EFD1F0F7 +:10A2300008010F6F080E07010701346F08010F5165 +:10A240004F0E07010701986F000E0701996F52EF3B +:10A25000D1F008EC40F011EFD2F00601DFC60FF8A4 +:10A260000601E0C610F8080148EFD1F008010F51CF +:10A270004D0ADEE029EFD1F008010F512D0AD8E098 +:10A2800029EFD1F008010F514C0AC1E029EFD1F0BC +:10A29000080110510A0AEAE0100AEEE0F00AF2E0C2 +:10A2A00029EFD1F008010F6F020E070107012B6F94 +:10A2B00008010F5108010F6F000E07010701096F18 +:10A2C00008010F5111EFD2F00EC812F80DC811F8A5 +:10A2D000C6EC2CF011C8FDF412C8FEF40401040110 +:10A2E000FE29FE0ED8B4FD19D8A479EFD1F07BEF8A +:10A2F000D1F07FEFD1F008EC40F011EFD2F0040183 +:10A300000401FD29D8B4FE29D8A489EFD1F08BEF40 +:10A31000D1F08DEFD1F011EFD2F00601B20E0701AE +:10A3200007010925E96EEA6A0601060EEA22040120 +:10A33000FDC4EFFF07010701092B070107013407DF +:10A34000070107013467A7EFD1F0A9EFD1F0B9EF0A +:10A35000D0F008EC40F00BEC43F0850E080108014A +:10A360002E6FFF0E08012F6F930E080108012C6F4E +:10A37000FF0E08012D6FF5EC43F0700E0801080187 +:10A380002E6FFF0E08012F6F2D0E080108012C6F94 +:10A39000FF0E08012D6FF5EC43F006010801DFC642 +:10A3A0002EF806010801E0C62FF808010801306BFD +:10A3B0000801316BAB0E080108012C6FFF0E08017C +:10A3C0002D6F71EC43F009C726F80601B20E0801A3 +:10A3D0000801246F0601060E0801256FB10E080161 +:10A3E0000801226FFF0E0801236FB7EC43F008014C +:10A3F0000F6F010E080108012C6F08010F515CEC72 +:10A4000041F011EFD2F0070107012B51000A01E1E1 +:10A4100062D6010A01E1AFD6030A01E155D711EF77 +:10A42000D2F0120008013C6F000E08010801356FE0 +:10A4300008013C5108013C6F000E08010801366F0D +:10A4400008013C51000E08010801386F000E080198 +:10A45000396F000E08013A6F000E08013B6F3CEFA8 +:10A46000D3F0030E08010801366539EFD2F03BEF57 +:10A47000D2F03DEFD2F052EFD3F0300E08010801D8 +:10A48000375F08010801356748EFD2F04AEFD2F094 +:10A4900059EFD2F0090E08010801376552EFD2F0EA +:10A4A00054EFD2F057EFD2F0000ECBEFD3F028EFFD +:10A4B000D3F0080108013551030AD8A462EFD2F0A5 +:10A4C00064EFD2F0C1EFD2F0080108013751FE0A63 +:10A4D000D8B46DEFD2F06FEFD2F072EFD2F0000E81 +:10A4E000CBEFD3F0060E0801385D050E080139598F +:10A4F000020E08013A59000E080108013B59D8A084 +:10A5000084EFD2F086EFD2F089EFD2F0000ECBEFDD +:10A51000D3F0080108013651080108013325E96E1E +:10A520000801000E080108013421EA6E0801080143 +:10A5300039510A0DF3CF3CF8080108013A51640D76 +:10A54000F35008013C25080108013825EF6E080189 +:10A550000801362B08013C6F000E08010801356F19 +:10A5600008013C51000E08010801386F000E080177 +:10A57000396F000E08013A6F000E08013B6F3CEF87 +:10A58000D3F0080108013751FE0AD8A4CAEFD2F06F +:10A59000CCEFD2F01BEFD3F0060E0801385D050EAC +:10A5A00008013959020E08013A59000E0801080144 +:10A5B0003B59D8A0DEEFD2F0E0EFD2F0E3EFD2F0DB +:10A5C000000ECBEFD3F00801080136510801080155 +:10A5D0003325E96E0801000E080108013421EA6EF6 +:10A5E0000801080139510A0DF3CF3CF808010801B0 +:10A5F0003A51640DF35008013C2508010801382543 +:10A60000EF6E08010801362B08013C6F000E0801AF +:10A610000801356F08013C51000E08010801386F30 +:10A62000000E0801396F000E08013A6F000E080194 +:10A630003B6F3CEFD3F0090E08010801376523EFAB +:10A64000D3F025EFD3F028EFD3F0000ECBEFD3F00B +:10A6500008010801352B080108013AC83BF8080138 +:10A66000080139C83AF80801080138C839F8080162 +:10A670000801386B37C838F8080131C8E9FF08010C +:10A6800032C8EAFF08010801314B322BEF500801B4 +:10A690000801376F0801376750EFD3F052EFD3F05E +:10A6A00031EFD2F0080108013751D8B45AEFD3F096 +:10A6B0005CEFD3F096EFD3F00801080137512F0A71 +:10A6C000D8B465EFD3F067EFD3F096EFD3F008017D +:10A6D000080137510D0AD8B470EFD3F072EFD3F000 +:10A6E00096EFD3F00801080137510A0AD8B47BEF7E +:10A6F000D3F07DEFD3F096EFD3F008010801375186 +:10A70000200AD8B486EFD3F088EFD3F096EFD3F0D9 +:10A71000080108013751090AD8B491EFD3F093EF3B +:10A72000D3F096EFD3F0000ECBEFD3F0060E080176 +:10A73000385D050E08013959020E08013A59000E1C +:10A74000080108013B59D8A0A8EFD3F0AAEFD3F035 +:10A75000ADEFD3F0000ECBEFD3F0030E08010801EC +:10A760003325E96E000E080108013421EA6E080164 +:10A77000080139510A0DF3CF3CF8080108013A519C +:10A78000640DF35008013C25080108013825EF6EDF +:10A79000010ECBEFD3F012000801526F0B0E08012F +:10A7A0000801226F080152510801526F0A0E080178 +:10A7B0000801236F0801525106EE6DF018EE3CF0CF +:10A7C000140EEECFE6FFE82EE1EFD3F006EE81F0B7 +:10A7D00018EE28F0140EEECFE6FFE82EEBEFD3F0E4 +:10A7E000FDEC40F00009D8A4F8EFD3F0FAEFD3F075 +:10A7F000FCEFD3F080EFD5F0FA0E08010801566F98 +:10A80000FF0E0801576F4CEC27F00009D8B40BEF8E +:10A81000D4F00DEFD4F015EFD4F0C9EC26F0080118 +:10A820000801655108010801226FF80E08010801AE +:10A83000566FFF0E0801576F4CEC27F00009D8B493 +:10A8400024EFD4F026EFD4F02EEFD4F0C9EC26F0AC +:10A8500008010801655108010801236F2D0E080148 +:10A860000801566FFF0E0801576F4CEC27F00009E6 +:10A87000D8B43DEFD4F03FEFD4F0B4EFD4F00801FA +:10A88000526F140E08010801676F08015251080148 +:10A890003C0E08010801656F0801080E0801666F8B +:10A8A0000EEC18F0AB0E08010801566FFF0E080100 +:10A8B000576F4CEC27F00009D8B461EFD4F063EF88 +:10A8C000D4F076EFD4F00801526F140E080108019D +:10A8D000676F080152510801280E08010801656FD1 +:10A8E0000801080E0801666F0EEC18F0580E0801FA +:10A8F0000801676FFF0E0801686F08013C0E080130 +:10A900000801656F0801080E0801666F49EC29F01F +:10A91000080166516511D8A490EFD4F092EFD4F0FD +:10A92000AEEFD4F0E60E08010801676FFE0E0801D5 +:10A93000686F0801280E08010801656F0801080EFC +:10A940000801666F49EC29F0080166516511D8B419 +:10A95000ACEFD4F0AEEFD4F0B0EFD4F080EFD5F0A0 +:10A96000F4EC1CF080EFD5F0FC0E08010801566FE6 +:10A97000FF0E0801576F4CEC27F00009D8A4C3EF75 +:10A98000D4F0C5EFD4F0C7EFD4F080EFD5F00801D4 +:10A99000526FC80E08010801676F08015251050186 +:10A9A000000E08010801656F0501050E0801666FBC +:10A9B0000EEC18F00009D8A4E0EFD4F0E2EFD4F0E8 +:10A9C000E4EFD4F080EFD5F0EA0E08010801566FED +:10A9D000FF0E0801576F4CEC27F00009D8B4F3EFD5 +:10A9E000D4F0F5EFD4F028EFD5F0C9EC26F065C827 +:10A9F00024F866C825F867C826F868C827F8A1C7EC +:10AA000068F8BEEC20F07D0E08010801685D000EBC +:10AA100008016959D8A00FEFD5F011EFD5F028EF54 +:10AA2000D5F065EC3FF0EA0E08010801536FFF0E08 +:10AA30000801546FB6EC35F024C853F825C854F813 +:10AA400026C855F827C856F866EC13F04DEC0EF002 +:10AA50006DEC44F00801526F000E08010801506FC0 +:10AA60000801525171EFD5F00801526F020E080132 +:10AA70000801566F0801525177EC44F00501000EB1 +:10AA800008010801536F0501050E0801546FCAEC57 +:10AA900028F00801526F000E08010801516F0801EB +:10AAA000525161EFD5F00E0E0801526F850EE82E5F +:10AAB00057EFD5F0522F57EFD5F000D0080108011D +:10AAC000512B08010801225108010801515DD8A04D +:10AAD0006CEFD5F06EEFD5F053EFD5F0080108011B +:10AAE000502B08010801235108010801505DD8A02E +:10AAF0007CEFD5F07EEFD5F034EFD5F05FEC44F08D +:10AB000012000801236F000E08010801106F0801F0 +:10AB10002351000E08010801156F000E0801166F81 +:10AB2000000E0801176F000E0801186F010E0801D2 +:10AB30000801196F000E08011A6F000E08011B6F43 +:10AB4000000E08011C6F08010F0E08010801356F87 +:10AB50000801080E0801366F08010D0E08010801F2 +:10AB6000336F0801080E0801346F99EC3CF00801BE +:10AB70000F0E080108012E6F0801080E08012F6F43 +:10AB800008010D0E080108012C6F0801080E0801CC +:10AB90002D6FACEC2AF00DC813F80EC814F808019C +:10ABA00008010FC811F808010801126B000E080116 +:10ABB00008011D6F000E08011E6F080108011E51DB +:10ABC000800A800F200ED8B41D5DD8A0EAEFD5F022 +:10ABD000ECEFD5F0EEEFD5F052EFD6F008010F0E06 +:10ABE00008010801276F0801080E0801286F0801F5 +:10ABF0000D0E08010801256F0801080E0801266FD7 +:10AC0000C2EC2EF008010801216F08010801215152 +:10AC1000020AD8A40EEFD6F010EFD6F013EFD6F05C +:10AC2000000E21EFD7F0080108012151D8B41BEF25 +:10AC3000D6F01DEFD6F035EFD6F008010801195116 +:10AC4000080108011513080108011A51080108013B +:10AC50001613080108011B51080108011713080108 +:10AC600008011C510801080118130801D8900801B7 +:10AC7000193708011A3708011B3708011C3708016A +:10AC800008011D4B1E2B080108011E51800A800F70 +:10AC9000200ED8B41D5DD8A050EFD6F052EFD6F0FC +:10ACA000EEEFD5F0000E080108011F6F000E08013D +:10ACB000206F080108012051800A800F040ED8B4CB +:10ACC0001F5DD8A066EFD6F068EFD6F06AEFD6F039 +:10ACD000C1EFD6F008010F0E08010801276F080127 +:10ACE000080E0801286F08010D0E08010801256FE4 +:10ACF0000801080E0801266FC2EC2EF008010801B9 +:10AD0000226F080108012251020AD8A48AEFD6F066 +:10AD10008CEFD6F08FEFD6F0000E21EFD7F00801C0 +:10AD200008012251D8B497EFD6F099EFD6F0AEEFE4 +:10AD3000D6F01FC823F8010E0801246F0801232B49 +:10AD4000A5EFD6F0D890080124370801232FA2EFF1 +:10AD5000D6F0080124510801080110130801080168 +:10AD60001F4B202B080108012051800A800F040E80 +:10AD7000D8B41F5DD8A0BFEFD6F0C1EFD6F06AEF10 +:10AD8000D6F00801080110510C0AD8B4CAEFD6F069 +:10AD9000CCEFD6F0CFEFD6F0000E21EFD7F00BECD2 +:10ADA00043F0850E080108012E6FFF0E08012F6F7A +:10ADB000930E080108012C6FFF0E08012D6FF5ECB2 +:10ADC00043F03F0E080108012E6FFF0E08012F6FA0 +:10ADD0002D0E080108012C6FFF0E08012D6FF5ECF8 +:10ADE00043F00701560E080108012E6F0701070EF8 +:10ADF00008012F6FAB0E080108012C6FFF0E080130 +:10AE00002D6FF5EC43F015C82EF816C82FF817C8AB +:10AE100030F818C831F8B10E080108012C6FFF0E88 +:10AE200008012D6F71EC43F00801236F010E08013A +:10AE300008012C6F080123515CEC41F0010E21EF59 +:10AE4000D7F012000201000E08010801566F02013E +:10AE5000020E0801576F0801586F000E0801080123 +:10AE6000556F08015851040E0801080155653BEF64 +:10AE7000D7F03DEFD7F03FEFD7F0B4EFD8F00C0E9E +:10AE8000080108015625E96E000E08010801572146 +:10AE9000EA6EEE50ED10D8A450EFD7F052EFD7F095 +:10AEA000A0EFD8F00C0E080108015625E96E000E3F +:10AEB000080108015721EA6E080151C8EEFF080198 +:10AEC00052C8EDFF0801080152515111D8A46BEF8F +:10AED000D7F06DEFD7F0A4EFD7F0010E0601060111 +:10AEE000DD5D200E0601DE59D8B079EFD7F07BEF9B +:10AEF000D7F089EFD7F0000E06010601DD5D100ED8 +:10AF00000601DE59D8B087EFD7F089EFD7F090EF80 +:10AF1000D7F0000E06010601DD6F100E0601DE6F90 +:10AF20000C0E080108015625E96E000E0801080103 +:10AF30005721EA6E0601DDC6EEFF0601DEC6EDFF13 +:10AF400006010601DD4BDE2B080108015051D8B483 +:10AF5000ACEFD7F0AEEFD7F0BAEFD7F008014F5112 +:10AF60004C114D114E11D8A4B8EFD7F0BAEFD7F06D +:10AF7000DCEFD7F00A0E080108015D6F000E080132 +:10AF80005E6FFF0E080108015B6F000E08015C6F29 +:10AF900056C859F857C85AF853EC40F00E0E08013D +:10AFA00008015625E96E000E080108015721EA6ED6 +:10AFB000050EEF6E89EFD8F07AEFD8F056C8E9FFAA +:10AFC00057C8EAFF08014CC8EEFF08014DC8EEFF64 +:10AFD00008014EC8EEFF08014FC8EEFF0801080146 +:10AFE0005051020AD8B4F7EFD7F0FAEFD7F0010EBC +:10AFF000FBEFD7F0000E0801586F140E080108018E +:10B000005625E96E000E080108015721EA6EEF503F +:10B0100008015819FE0B5819EF6E0E0E08010801B1 +:10B020005625E96E000E080108015721EA6E010E4F +:10B03000EF6E89EFD8F056C8E9FF57C8EAFF08015C +:10B040004CC8EEFF08014DC8EEFF08014EC8EEFFE8 +:10B0500008014FC8EEFF130E080108015625E96EDE +:10B06000000E080108015721EA6E000EEF6E0F0E68 +:10B07000080108015625E96E000E08010801572154 +:10B08000EA6E270EEE6E000EEE6E000EEE6E000EF5 +:10B09000ED6EED52ED520E0E080108015625E96ED7 +:10B0A000000E080108015721EA6E020EEF6E89EFCB +:10B0B000D8F00A0E08010801B06F000E0801B16F48 +:10B0C0004CC8AEF84DC8AFF856C8ACF857C8ADF884 +:10B0D00058EC3AF00E0E080108015625E96E000EF4 +:10B0E000080108015721EA6E050EEF6E89EFD8F0CE +:10B0F00089EFD8F0080108015051010A01E15ED73B +:10B10000030A01E15BD7010A96E0070AD2E078EF73 +:10B11000D8F00A0E080108015625E96E000E080154 +:10B1200008015721EA6E080153C8EEFF080154C810 +:10B13000EDFF55C80DF7080108015551B7EFD8F0DC +:10B14000170E080108015627000E080157230801B1 +:10B150000801552B040E080108015565B2EFD8F01F +:10B16000B4EFD8F03FEFD7F0FF0EB7EFD8F01200F2 +:10B1700008010F0E08010801356F0801080E0801CB +:10B18000366F08010D0E08010801336F0801080E23 +:10B190000801346F99EC3CF00801206F000E0801A3 +:10B1A0000801106F08012051040E08010801186FF2 +:10B1B000000E0801196F0801080119AFE2EFD8F07D +:10B1C000E4EFD8F0E6EFD8F086EFD9F00801206F71 +:10B1D000000E080108011C6F08012051000E080133 +:10B1E00008011D6F000E08011E6F080108011E51A5 +:10B1F000800A800F080ED8B41D5DD8A002EFD9F0E8 +:10B2000004EFD9F006EFD9F05DEFD9F008010F0E89 +:10B2100008010801246F0801080E0801256F0801C4 +:10B220000D0E08010801226F0801080E0801236FA6 +:10B2300021EC38F0080108011F6F080108011F51B7 +:10B24000020AD8A426EFD9F028EFD9F02BEFD9F0D5 +:10B25000000E3EEFDAF0080108011F51D8B433EFB9 +:10B26000D9F035EFD9F04AEFD9F01DC820F8010E1A +:10B270000801216F0801202B41EFD9F0D890080177 +:10B2800021370801202F3EEFD9F008012151080194 +:10B2900008011C13080108011D4B1E2B08010801A1 +:10B2A0001E51800A800F080ED8B41D5DD8A05BEF38 +:10B2B000D9F05DEFD9F006EFD9F008010801185177 +:10B2C000040A1911D8A467EFD9F069EFD9F06BEF30 +:10B2D000D9F01CC810F80801130E08010801182540 +:10B2E000E96EEA6A0801080EEA2208011CC8EFFFAD +:10B2F000080108011807D8A019070801080119AFAB +:10B3000084EFD9F086EFD9F0E6EFD8F0000E08010F +:10B310000801116F000E0801126F000E08010801EC +:10B320001A6F000E08011B6F080108011B51800AEB +:10B33000800F040ED8B41A5DD8A0A1EFD9F0A3EF06 +:10B34000D9F0A5EFD9F0DBEFD9F00801206F310E6D +:10B3500008010801246F080120510801130E08019B +:10B3600008011A25E96EEA6A0801080EEA22EF5080 +:10B3700008010801236F11C822F85FEC2EF00801C4 +:10B38000216F0801215108010801116F0801126B9A +:10B39000080108011A4B1B2B080108011B51800AE8 +:10B3A000800F040ED8B41A5DD8A0D9EFD9F0DBEF26 +:10B3B000D9F0A5EFD9F0080110C820F80801216BD9 +:10B3C0000801080112510801211905E108010801CD +:10B3D000115108012019D8B4F0EFD9F0F2EFD9F0EB +:10B3E000F5EFD9F0000E3EEFDAF00BEC43F0850EEE +:10B3F000080108012E6FFF0E08012F6F930E080140 +:10B4000008012C6FFF0E08012D6FF5EC43F0170EAD +:10B41000080108012E6FFF0E08012F6F2D0E080185 +:10B4200008012C6FFF0E08012D6FF5EC43F00801A9 +:10B43000206F050E08010801266F08012051080140 +:10B44000130E08010801246F0801080E0801256F7A +:10B45000B10E08010801226FFF0E0801236FB7EC3F +:10B4600043F00801206F010E080108012C6F08014C +:10B4700020515CEC41F0010E3EEFDAF012000801C1 +:10B48000166F000E08010801156F08011651000E15 +:10B490000801080115654FEFDAF051EFDAF053EFCC +:10B4A000DAF0BDEFDBF015C871F81DEC2BF017508A +:10B4B0000D0AD8B45EEFDAF060EFDAF062EFDAF09E +:10B4C000B0EFDBF0B7EC24F0435008010801141989 +:10B4D000D8B46DEFDAF06FEFDAF071EFDAF0B0EFC9 +:10B4E000DBF0180E406E020E416E08010801116774 +:10B4F0007CEFDAF07EEFDAF08FEFDAF012C82DF0A1 +:10B5000013C82EF018860801166F040E176E080176 +:10B51000165112C81AF013C81BF0ABEFDBF0000E87 +:10B5200006010601D05D040E0601D159D8A09BEF9B +:10B53000DAF09DEFDAF0ABEFDAF0890E06010601E2 +:10B54000D05D130E0601D159D8A0A9EFDAF0ABEF08 +:10B55000DAF0B2EFDAF0000E06010601D06F040E49 +:10B560000601D16FD0C62DF0D1C62EF0060106011E +:10B57000D04BD12B12C82BF013C82CF0C4EC43F0E5 +:10B58000A1C80FF0A2C810F0A3C811F0A4C812F00F +:10B5900018889BEFDBF00DC833F00EC834F00FC8ED +:10B5A00035F010C836F0080108011151020AD8B46C +:10B5B000DCEFDAF0DFEFDAF0010EE0EFDAF0000EA8 +:10B5C0000801166F0801164716473F500801161963 +:10B5D000FB0B16193F6E0801166F000E176E08015F +:10B5E0001651ABEFDBF0080108EE0FF0EECF16F8C6 +:10B5F000EDCF17F8080108010D51080116270801C1 +:10B6000008010E5108011723080108011251080111 +:10B610001627080108011351080117232D500801AE +:10B6200016191A6E2E50080117191B6E0DC833F02B +:10B630000EC834F00FC835F010C836F00801166F88 +:10B64000000E426E08011651270E1D6E000E1E6E72 +:10B65000000E1F6E000E206E0801166F020E176E90 +:10B6600008011651ABEFDBF008010DC8F6FF080129 +:10B670000EC8F7FF000EF86E0900F5CF16F80900A6 +:10B68000F5CF17F8080100EE02F008010D51E92688 +:10B6900008010E51EA22EECF18F8EDCF19F8080193 +:10B6A00016510801182508011A6F080117510801E1 +:10B6B000192108011B6F08010801125108011A27FE +:10B6C00008010801135108011B232D5008011A1904 +:10B6D0001A6E2E5008011B191B6E0A0E0801080174 +:10B6E000B06F000E0801B16F0DC8AEF80EC8AFF80C +:10B6F000330E08010801AC6F000E0801AD6F58EC65 +:10B700003AF00801166F050E176E08011651080170 +:10B71000166F010E08010801736F08011651080128 +:10B72000176F020E08010801726F080117519FEC94 +:10B73000A1F0ABEFDBF0080108011151010A01E1B2 +:10B740002AD7030A01E127D7010A01E14CD7070AEA +:10B750008BE0ABEFDBF0080108011551C0EFDBF027 +:10B7600008010801152B000E080108011565BBEF43 +:10B77000DBF0BDEFDBF053EFDAF0FE0EC0EFDBF0F5 +:10B78000120006010601D767C8EFDBF0CAEFDBF055 +:10B7900013EFDCF00DC864F88FEC3FF0030E0801E6 +:10B7A0000801176F000E0801186FE20E080108016A +:10B7B000156FFF0E0801166F0101000E0801080148 +:10B7C000136F0101010E0801146FFAEC2DF008014E +:10B7D00014511311D8A4EFEFDBF0F1EFDBF0FBEF26 +:10B7E000DBF008010F6F010E06010601D76F08019B +:10B7F0000F5111EFDCF0010101010251D8B403EF48 +:10B80000DCF005EFDCF011EFDCF001C100F102C16A +:10B8100001F108010F6F000E01010101026F080123 +:10B820000F513BEFDDF006010601D705D8A41BEF51 +:10B83000DCF01DEFDCF0C0EFDCF00DC864F88FEC3D +:10B840003FF00101000E08010801596F0101010ECE +:10B8500008015A6F3DEC37F0080159512B0A5A1173 +:10B86000D8A435EFDCF037EFDCF0BEEFDCF00801F8 +:10B870000F6F030E080108010E6F08010F512A0E09 +:10B88000080108010E6547EFDCF049EFDCF04BEFF3 +:10B89000DCF0ACEFDCF0020E08010801156F000EC1 +:10B8A0000801166FFD0E080108010E2508010801A8 +:10B8B000136F0801146BFF0E0801142347EC1CF0F2 +:10B8C0000501E40E080108011325E96EEA6A050185 +:10B8D000050EEA2208010EC80FF80801106B010ED0 +:10B8E00008010F27000E10230101000E08010F258B +:10B8F000E16E0101010E08011021E26EE75008011E +:10B900000801726F2DEC2DF00801116F0101000E7E +:10B91000080108010E25E16EE26A0101010EE22232 +:10B92000E75008010801726F2DEC2DF00801126F2D +:10B9300008011239F00B08011111EF6E020E080117 +:10B9400008010E272A0E080108010E65AAEFDCF097 +:10B95000ACEFDCF04BEFDCF065EC3FF008010F6F73 +:10B96000020E06010601D76F08010F5108010F6F83 +:10B97000000E070107013D6F08010F513BEFDDF09D +:10B9800006010601D751020AD8A4C9EFDCF0CBEFBB +:10B99000DCF0EFEFDCF0080108010D513A0AD8A401 +:10B9A000D4EFDCF0D6EFDCF0E2EFDCF065EC3FF05A +:10B9B00008010F6F030E06010601D76F08010F5132 +:10B9C000EDEFDCF007013D3BF00E3D170DC872F8BE +:10B9D0002DEC2DF0070107013D133BEFDDF00601D3 +:10B9E0000601D751030AD8A4F8EFDCF0FAEFDCF037 +:10B9F00022EFDDF00DC864F88FEC3FF0070107017E +:10BA00003D07070107013D6708EFDDF00AEFDDF0B4 +:10BA100020EFDDF0B8EC38F00009D8B412EFDDF01B +:10BA200014EFDDF01EEFDDF008010F6F040E0601CC +:10BA30000601D76F08010F5120EFDDF065EC3FF0F4 +:10BA40003BEFDDF006010601D751040AD8A42BEF25 +:10BA5000DDF02DEFDDF03BEFDDF065EC3FF00DC8E4 +:10BA600064F88FEC3FF008010F6F010E060106012C +:10BA7000D76F08010F5112000801B86F000E0801BE +:10BA80000801B36F0801B8510801B86F000E080132 +:10BA90000801B26F0801B85108010801AC29D8B4F7 +:10BAA000AD29D8A456EFDDF058EFDDF064EFDDF0FE +:10BAB0000801B86F010E08010801B36F0801B85101 +:10BAC000E2CEACF8E3CEADF808010801AE29D8B457 +:10BAD000AF29D8A46EEFDDF070EFDDF07CEFDDF084 +:10BAE0000801B86F010E08010801B26F0801B851D2 +:10BAF000E0CEAEF8E1CEAFF8020E08010801B05D6D +:10BB0000000E0801B159D8B088EFDDF08AEFDDF002 +:10BB1000CFEFDDF0E0CEB4F8E1CEB5F8E2CEB6F886 +:10BB2000E3CEB7F8AEC8E0FEAFC8E1FEACC8E2FEB7 +:10BB3000ADC8E3FEA3EFDDF04BEC44F008010801D3 +:10BB4000C06F64EC44F008010801B007D8A0B10749 +:10BB50000801B029D8B4B129D8A4B1EFDDF0B3EF12 +:10BB6000DDF09CEFDDF008010801B267BAEFDDF00F +:10BB7000BCEFDDF0C0EFDDF0B4C8E0FEB5C8E1FE1B +:10BB800008010801B367C7EFDDF0C9EFDDF0CDEFC5 +:10BB9000DDF0B6C8E2FEB7C8E3FE82EFDEF00801D2 +:10BBA0000801B351D8B4D7EFDDF0D9EFDDF0EEEFF7 +:10BBB000DDF008010801B05108010801AC250801B9 +:10BBC0000801B66F08010801B15108010801AD2153 +:10BBD0000801B76FB6C8E2FEB7C8E3FEFF0E080162 +:10BBE0000801AE250801B86FFF0E08010801AF215A +:10BBF0000801B96F0801B85108010801B027080110 +:10BC0000B95108010801B12306EFDEF00E010E0163 +:10BC1000DFBB0DEFDEF00FEFDEF006EFDEF0AEC8BB +:10BC2000F0FEAFC8F1FEACC8F4FEADC8F5FECE0E16 +:10BC300008010801AE5D0A0E0801AF59D8B023EF24 +:10BC4000DEF025EFDEF03AEFDEF0CE0E080108015F +:10BC5000B05D0A0E0801B159D8A031EFDEF033EF24 +:10BC6000DEF03AEFDEF00801CE0E0801B05F0A0EFA +:10BC70000801B15BB0C8F2FEB1C8F3FE0E01DF9956 +:10BC80000E01DF8B44EFDEF00E010E01DFBB4BEF48 +:10BC9000DEF04DEFDEF044EFDEF008010801B251B6 +:10BCA000D8B455EFDEF057EFDEF082EFDEF008019A +:10BCB0000801B04BB12BCE0E08010801AE5D0A0E93 +:10BCC0000801AF59D8B067EFDEF069EFDEF07EEF24 +:10BCD000DEF0CE0E08010801B05D0A0E0801B15970 +:10BCE000D8A075EFDEF077EFDEF07EEFDEF0080132 +:10BCF000CE0E0801B05F0A0E0801B15BB0C8E0FECD +:10BD0000B1C8E1FE1200000E08010801606F000ECC +:10BD10000801616F000E08010801596592EFDEF01D +:10BD200094EFDEF09DEFDEF0000E08010801596F80 +:10BD3000000E08015A6FC8EFDFF059C871F81DEC0A +:10BD40002BF059C868F8BEEC20F068C85EF869C8E6 +:10BD50005FF8080108015F515E11D8A4B2EFDEF070 +:10BD6000B4EFDEF0C1EFDEF059C868F8F6EC3BF056 +:10BD7000000E08010801596F000E08015A6FC8EF44 +:10BD8000DFF05EC862F85FC863F8080108015E5121 +:10BD9000080108015C5D080108015F510801080104 +:10BDA0005D59D8B0D6EFDEF0D8EFDEF0DCEFDEF094 +:10BDB0005CC862F85DC863F819B0E1EFDEF0E3EF4C +:10BDC000DEF00EEFDFF000EE03F0EECF64F8EDCF23 +:10BDD00065F801500801645F02500801655BD89066 +:10BDE000080165310801676F080164310801666F59 +:10BDF000080108015E510801665D080108015F51F4 +:10BE000008016759D8A007EFDFF009EFDFF00EEF68 +:10BE1000DFF059C868F8F6EC3BF0198000EE07F047 +:10BE2000EECF64F8EDCF65F8080108016251080112 +:10BE300064270801080163510801652303500801C4 +:10BE4000645D045008016559D8A029EFDFF02BEF9D +:10BE5000DFF068EFDFF00750035C08010801606F56 +:10BE6000085004580801616F60C8AAF861C8ABF8AF +:10BE70000801646F010E08010801A96F08016451EF +:10BE80005AC8A7F85BC8A8F81CC0A6F807C0A4F851 +:10BE900008C0A5F8A0EC23F00801080160510801D2 +:10BEA00008015A27080108016151080108015B23B4 +:10BEB00008010801605108010801625F08010801DA +:10BEC000615108010801635B01C007F002C008F07E +:10BED00062C8AAF863C8ABF80801646F010E0801D4 +:10BEE0000801A96F080164515AC8A7F85BC8A8F8EF +:10BEF0001CC0A6F807C0A4F808C0A5F8A0EC23F061 +:10BF0000080108016251072608010801635108224F +:10BF1000080108015E51080108015C5D0801080183 +:10BF20005F51080108015D59D8A099EFDFF09BEF40 +:10BF3000DFF0A1EFDFF059C868F8F6EC3BF0B5EFA1 +:10BF4000DFF018BAA6EFDFF0A8EFDFF0B5EFDFF013 +:10BF5000188A5AEC42F0060E08010801A125136E5A +:10BF6000000E08010801A221146E080108016051A9 +:10BF700008010801622508010801596F080108013C +:10BF8000615108010801632108015A6FC8EFDFF011 +:10BF90001200C00E08010801126F100E0801136F85 +:10BFA00006010601D151D011D8A4D9EFDFF0DBEFA3 +:10BFB000DFF0F4EFDFF09BEC03F0FF0E0801080167 +:10BFC00016150801146F070E08010801171508015E +:10BFD000156F000E0801142506010601D06F040E2E +:10BFE000080115210601D16F3C0E080108015D6FA3 +:10BFF000000E08015E6F000E080108015B6F000E65 +:10C0000008015C6F00019F0E08010801596F0001D3 +:10C01000000E08015A6F53EC40F00801146F000E37 +:10C0200008010801096F080114510801146F000E7E +:10C03000080108010B6F08011451000E08010801E6 +:10C040000B6525EFE0F027EFE0F029EFE0F00EEFD1 +:10C05000E1F00BC871F81DEC2BF0080108010B5141 +:10C06000060DF3CF14F8010E08011427680E08011D +:10C070001425F66EF76AFE0EF722F86A000EF82213 +:10C0800008000801F5CF0AF8080108010B51060D58 +:10C09000F3CF14F8020E08011427680E08011425C6 +:10C0A000F66EF76AFE0EF722F86A000EF822090013 +:10C0B0000801F5CF10F80A000801F5CF11F80801C2 +:10C0C00008010B51060DF3CF14F8040E08011427D4 +:10C0D000680E08011425F66EF76AFE0EF722F86A5C +:10C0E000000EF82209000801F5CF0EF80A00080139 +:10C0F000F5CF0FF8B3EFE0F012C80CF813C80DF845 +:10C10000080110C814F8080111C815F80801080141 +:10C110000E5108011427080108010F5108011523C9 +:10C12000290E08011427000E1523080114510801D7 +:10C130000801122708011551080108011323A1EF76 +:10C14000E0F0FD0E08010801125D1F0E08011359F1 +:10C15000D8B0ADEFE0F0AFEFE0F0A1EFE0F0BAEF74 +:10C16000E0F0B1EFE0F0080108010A51000AC4E074 +:10C17000B1EFE0F00AC81CF0270E080108010C25F9 +:10C18000016E000E080108010D21026E01C014F8B5 +:10C1900002C015F808010801105108011427080110 +:10C1A0000801115108011523010E08011425036E21 +:10C1B000000E08011521046E080108010E51032428 +:10C1C000056E080108010F510420066E0801146F66 +:10C1D0000D0E176E080114511896B7EC24F00801E3 +:10C1E00008010B51060D680EF324F66EF76AFE0E79 +:10C1F000F722F86A000EF8220800F5CF43F06CEC45 +:10C2000033F0080108010B2B000E080108010B6533 +:10C210000CEFE1F00EEFE1F029EFE0F01200000E7C +:10C2200008010801146F000E0801156F000E0801C7 +:10C23000166F000E0801176F010E08010801106F3C +:10C24000000E0801116F000E0801126F000E0801A8 +:10C25000136F08010F0E08010801356F0801080E61 +:10C260000801366F08010D0E08010801336F08013F +:10C27000080E0801346F99EC3CF008010F0E08011C +:10C2800008012E6F0801080E08012F6F08010D0E1E +:10C29000080108012C6F0801080E08012D6FACEC95 +:10C2A0002AF0000E08010801186F000E0801196F2E +:10C2B000080108011951800A800F0C0ED8B4185DCE +:10C2C000D8A065EFE1F067EFE1F069EFE1F000EF92 +:10C2D000E2F008010F0E080108012E6F0801080E98 +:10C2E00008012F6F08010D0E080108012C6F0801CD +:10C2F000080E08012D6FACEC2AF0080108011A6F36 +:10C3000008010F0E080108012E6F0801080E080130 +:10C310002F6F08010D0E080108012C6F0801080E8F +:10C3200008012D6FACEC2AF0080108011B6F080111 +:10C330000F0E080108012E6F0801080E08012F6F6B +:10C3400008010D0E080108012C6F0801080E0801F4 +:10C350002D6FACEC2AF0080108011C6F08010F0ECC +:10C36000080108012E6F0801080E08012F6F08014F +:10C370000D0E080108012C6F0801080E08012D6F31 +:10C38000ACEC2AF0080108011D6F0801D8900801E3 +:10C390001437080115370801163708011737DBEF86 +:10C3A000E1F0EDEFE1F0080108011481EDEFE1F0BB +:10C3B000000E4FEFE2F01DC822F81CC821F81BC880 +:10C3C00020F81AC81FF807EC32F0000AEAE0010A68 +:10C3D000EAE0030AEDE0EDEFE1F008010801184B97 +:10C3E000192B080108011951800A800F0C0ED8B4CE +:10C3F000185DD8A0FEEFE1F000EFE2F069EFE1F0A8 +:10C4000008011751141115111611D8A40AEFE2F002 +:10C410000CEFE2F00FEFE2F0000E4FEFE2F00BEC6A +:10C4200043F0580E080108012E6FFF0E08012F6F10 +:10C430002D0E080108012C6FFF0E08012D6FF5EC81 +:10C4400043F0220E080108012E6FFF0E08012F6F26 +:10C45000AB0E080108012C6FFF0E08012D6FF5ECE3 +:10C4600043F014C82EF815C82FF816C830F817C8AE +:10C4700031F8B10E080108012C6FFF0E08012D6F75 +:10C4800071EC43F008011E6F020E080108012C6FC9 +:10C4900008011E515CEC41F0010E4FEFE2F012007A +:10C4A0007AEFE3F05F0E08010801536F760E080182 +:10C4B000546F5F0E08010801516F760E0801526F2C +:10C4C0000801096F040E08010801506F08010951A5 +:10C4D000000E080108014C6F000E08014D6F000EA0 +:10C4E00008014E6F000E08014F6F22ECD7F00601D5 +:10C4F0000601F96F06010601F929D8A482EFE2F0DE +:10C5000084EFE2F086EFE2F08BEFE3F00701070142 +:10C51000302B8BEFE3F0F9C64CF8D9EC39F0080179 +:10C520004D514C11D8A497EFE2F099EFE2F09BEF58 +:10C53000E2F08BEFE3F00801080E080108014D6FEF +:10C540000801080E08014E6F35EC3DF08FEC41F00C +:10C55000080108010851440AD8B4B1EFE2F0B3EF82 +:10C56000E2F0B5EFE2F08BEFE3F007010701302BCB +:10C570000A0E08010801B06F000E0801B16F050135 +:10C58000DA0E08010801AE6F0501050E0801AF6F54 +:10C5900006010601F951170D0201000EF3240801EE +:10C5A0000801AC6F0801AD6B0201020E0801AD235A +:10C5B00058EC3AF0F9C64CF893EC39F008014D51BB +:10C5C0004C11D8A4E6EFE2F0E8EFE2F0EAEFE2F097 +:10C5D0008BEFE3F0CA0E080108010A6FFE0E080196 +:10C5E0000B6FE6EC42F00801096F000E080108012C +:10C5F000086F08010951050E08010801086503EFDD +:10C60000E3F005EFE3F007EFE3F046EFE3F008C8EF +:10C6100009F82D0E0801092700016C0E08010925F3 +:10C62000E96EEA6A0001000EEA22EF5008010801F3 +:10C63000586F0DEC3FF008010801536F67EC3DF0B7 +:10C6400008C809F82D0E0801092700016C0E080121 +:10C650000925E96EEA6A0001000EEA22EF5008019E +:10C660000801646FE1EC3EF008010801536F67ECCC +:10C670003DF008010801082B050E080108010865B6 +:10C6800044EFE3F046EFE3F007EFE3F00801096F52 +:10C690003A0E08010801536F0801095167EC3DF09B +:10C6A0000001E10E080108010A6F0001000E0801F7 +:10C6B0000B6FD3EC42F00801096F3A0E0801080134 +:10C6C000536F0801095167EC3DF0F20E08010801B3 +:10C6D0000A6FFF0E08010B6FE6EC42F053EC21F0FD +:10C6E0000801096F010E07010701306F08010951A8 +:10C6F0008BEFE3F0070107013051000A01E1D2D6C8 +:10C70000010A01E108D7030A01E154D7010A01E156 +:10C7100000D78BEFE3F01200000E08010801606FF4 +:10C72000000E0801616F000E0801080159659BEFBA +:10C73000E3F09DEFE3F0A6EFE3F0000E080108013F +:10C74000596F000E08015A6FBFEFE4F059C871F835 +:10C750001DEC2BF059C868F8BEEC20F068C85EF8F4 +:10C7600069C85FF8080108015F515E11D8A4BBEFEA +:10C77000E3F0BDEFE3F0CAEFE3F059C868F8F6EC78 +:10C780003BF0000E08010801596F000E08015A6FB6 +:10C79000BFEFE4F019B0CFEFE3F0D1EFE3F0FCEF3F +:10C7A000E3F000EE03F0EECF64F8EDCF65F8015052 +:10C7B0000801645F02500801655BD890080165318B +:10C7C0000801676F080164310801666F08010801FC +:10C7D0005E510801665D080108015F510801675953 +:10C7E000D8A0F5EFE3F0F7EFE3F0FCEFE3F059C882 +:10C7F00068F8F6EC3BF019805EC862F85FC863F831 +:10C80000080108015E51080108015C5D080108018A +:10C810005F51080108015D59D8B011EFE4F013EF42 +:10C82000E4F017EFE4F05CC862F85DC863F800EE6E +:10C8300007F0EECF64F8EDCF65F80801080162510A +:10C8400008016427080108016351080165230350AA +:10C850000801645D045008016559D8A032EFE4F086 +:10C8600034EFE4F067EFE4F00750035C08010801DF +:10C87000606F085004580801616F60C86DF861C8A6 +:10C880006EF85AC86BF85BC86CF81CC06AF807C031 +:10C8900068F808C069F8E7EC21F008010801605168 +:10C8A000080108015A27000E080108015B2308014E +:10C8B0000801605108010801625F08010801615127 +:10C8C00008010801635B01C007F002C008F062C8FC +:10C8D0006DF863C86EF85AC86BF85BC86CF81CC07A +:10C8E0006AF807C068F808C069F8E7EC21F00801A9 +:10C8F0000801625107260801080163510822080156 +:10C9000008015E51080108015C5D080108015F51E2 +:10C91000080108015D59D8A090EFE4F092EFE4F02F +:10C9200098EFE4F059C868F8F6EC3BF0ACEFE4F0AF +:10C9300018BA9DEFE4F09FEFE4F0ACEFE4F0188A52 +:10C940005AEC42F0060E08010801A125136E000EF4 +:10C9500008010801A221146E0801080160510801B4 +:10C960000801622508010801596F08010801615199 +:10C9700008010801632108015A6FBFEFE4F01200BB +:10C98000000E080108010D6F000E08010E6FA1C70F +:10C9900068F8BEEC20F07D0E08010801685D000E0D +:10C9A00008016959D8B0D7EFE4F0D9EFE4F0DBEF34 +:10C9B000E4F0EAEFE5F0120E080108015D6F000EE9 +:10C9C00008015E6F000E080108015B6F000E080190 +:10C9D0005C6F0501C80E08010801596F0501050EBD +:10C9E00008015A6F53EC40F0080108010E51800A0B +:10C9F000800F060ED8B40D5DD8A001EFE5F003EF6F +:10CA0000E5F005EFE5F05BEFE5F00801D8900801EF +:10CA10000D3508010F6F0501C80E08010F25E96EDD +:10CA2000EA6A0501050EEA220001DB0E0801080191 +:10CA30000D25E16EE26A0001000EE222E7500801D6 +:10CA40000801586F0DEC3FF0EF6E0801D890080117 +:10CA50000D3508010F6F010E08010F270501C80EE3 +:10CA600008010F25E96EEA6A0501050EEA220001B8 +:10CA7000DB0E080108010D25E16EE26A0001000EDF +:10CA8000E222E75008010801646FE1EC3EF0EF6E2E +:10CA9000080108010D4B0E2B080108010E51800AF8 +:10CAA000800F060ED8B40D5DD8A059EFE5F05BEF0E +:10CAB000E5F005EFE5F065EC3FF0360E0801080102 +:10CAC000536FFF0E0801546FB6EC35F021EC44F0C3 +:10CAD000700E08010801326FFE0E0801336FE60E7A +:10CAE00008010801306FFF0E0801316FAAEC43F016 +:10CAF0000501C80E08010801326F0501050E080185 +:10CB0000336FDE0E08010801306FFF0E0801316F30 +:10CB1000AAEC43F0E10E08010F6F000E106F0FC872 +:10CB200032F810C833F87E0E08010801306FFF0E8E +:10CB30000801316FAAEC43F0CA0E08010801326FF8 +:10CB4000FF0E0801336FC00E08010801306FFF0EA1 +:10CB50000801316FAAEC43F037EC44F021EC44F0CB +:10CB6000020E08010801346F000E0801356F000E37 +:10CB70000801366F000E0801376F2D0E08010801FD +:10CB8000326FFF0E0801336F40EC43F0F20E0801E4 +:10CB90000801326FFF0E0801336F480E08010801CB +:10CBA000306FFF0E0801316FAAEC43F0D80E080178 +:10CBB0000801326FFE0E0801336FF50E08010801FF +:10CBC000306FFF0E0801316FAAEC43F037EC44F0F0 +:10CBD0004DEC0EF01200000E08010801106F000E5F +:10CBE0000801116F000E0801126F000E0801136F8B +:10CBF000010E08010801146F000E0801156F000EE8 +:10CC00000801166F000E0801176F08010F0E0801CA +:10CC10000801356F0801080E0801366F08010D0E76 +:10CC200008010801336F0801080E0801346F99EC00 +:10CC30003CF0000E08010801186F000E0801196F82 +:10CC4000080108011951800A800F180ED8B4185D28 +:10CC5000D8A02DEFE6F02FEFE6F031EFE6F0DBEFB6 +:10CC6000E6F008010F0E080108012E6F0801080EFA +:10CC700008012F6F08010D0E080108012C6F080133 +:10CC8000080E08012D6FACEC2AF0080108011A6F9C +:10CC900008010F0E080108012E6F0801080E080197 +:10CCA0002F6F08010D0E080108012C6F0801080EF6 +:10CCB00008012D6FACEC2AF0080108011B6F080178 +:10CCC0000F0E080108012E6F0801080E08012F6FD2 +:10CCD00008010D0E080108012C6F0801080E08015B +:10CCE0002D6FACEC2AF0080108011C6F08010F0E33 +:10CCF000080108012E6F0801080E08012F6F0801B6 +:10CD00000D0E080108012C6F0801080E08012D6F97 +:10CD1000ACEC2AF0080108011D6FAEEFE6F0BEEFA3 +:10CD2000E6F0080108011451080108011013080178 +:10CD300008011551080108011113080108011651D5 +:10CD40000801080112130801080117510801080120 +:10CD50001313BEEFE6F0000E0BEFE7F01DC822F84C +:10CD60001CC821F81BC820F81AC81FF861EC32F063 +:10CD7000000AD5E0010AD5E0ABEFE6F00801D89053 +:10CD8000080114370801153708011637080117374D +:10CD900008010801184B192B080108011951800AD4 +:10CDA000800F180ED8B4185DD8A0D9EFE6F0DBEFED +:10CDB000E6F031EFE6F00BEC43F0F30E080108016A +:10CDC0002E6FFE0E08012F6F2D0E080108012C6F2B +:10CDD000FF0E08012D6FF5EC43F010C82EF811C8B6 +:10CDE0002FF812C830F813C831F8B10E0801080145 +:10CDF0002C6FFF0E08012D6F71EC43F008011E6FC0 +:10CE0000020E080108012C6F08011E515CEC41F074 +:10CE1000010E0BEFE7F01200070107010B6713EF9C +:10CE2000E7F015EFE7F036EFE7F0030E0801080131 +:10CE300016651DEFE7F01FEFE7F029EFE7F00D0EA5 +:10CE400008010801166527EFE7F029EFE7F02CEF5E +:10CE5000E7F0FE0EFDEFE7F00801176F010E070186 +:10CE600007010B6F08011751FAEFE7F007010701FF +:10CE70000B05D8A43EEFE7F040EFE7F08AEFE7F0CC +:10CE80000B0E08010801166548EFE7F04AEFE7F0DE +:10CE900054EFE7F0160E08010801166552EFE7F0AF +:10CEA00054EFE7F076EFE7F0070129C717F808011C +:10CEB000186B0701070199510801181905E10701CD +:10CEC0000701985108011719D8B469EFE7F06BEF23 +:10CED000E7F076EFE7F00801176F000E0701070192 +:10CEE0000B6F08011751FE0EFDEFE7F000900801EF +:10CEF000080115A17DEFE7F000800801176F020E11 +:10CF0000070107010B6F08011751000E00B0010E59 +:10CF1000FDEFE7F0070107010B51020AD8A493EFD8 +:10CF2000E7F095EFE7F0FAEFE7F008010801155197 +:10CF3000D8B49DEFE7F09FEFE7F0BDEFE7F0030E09 +:10CF4000080108011665A7EFE7F0A9EFE7F0BDEFCC +:10CF5000E7F00E0E080108011661B1EFE7F0B3EF3C +:10CF6000E7F0BDEFE7F00801176F000E07010701BA +:10CF70000B6F08011751F7EFE7F00B0E08010801DE +:10CF80001665C5EFE7F0C7EFE7F0DBEFE7F0170E48 +:10CF9000080108011661CFEFE7F0D1EFE7F0DBEF12 +:10CFA000E7F00801176F010E070107010B6F080179 +:10CFB0001751F7EFE7F0030E080108011665E3EFDC +:10CFC000E7F0E5EFE7F0F7EFE7F00E0E08010801F4 +:10CFD0001661EDEFE7F0EFEFE7F0F7EFE7F00801AC +:10CFE000176F000E070107010B6F08011751FF0EA5 +:10CFF000FDEFE7F0FF0EFDEFE7F01200D180120029 +:04FFF8009EF7FDFF74 :00000001FF From c5420592994cf0abe3d125b89749c35d910eb63a Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 14 Feb 2014 10:26:19 +0100 Subject: [PATCH 2209/2215] Bumped version to 2.1.2_rc1 --- telldus-core/CMakeLists.txt | 2 +- telldus-gui/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 5e450257..3f6ae5a1 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -13,7 +13,7 @@ SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "beta10") +SET(PACKAGE_SUBVERSION "rc1") SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index 4d1f9be5..b6563518 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -11,7 +11,7 @@ SET(PACKAGE_MINOR_VERSION 1) SET(PACKAGE_PATCH_VERSION 2) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta10") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_rc1") SET(BRANDING "telldus" CACHE STRING "The brand to use") From 1f93cf91f873e1e4570f83f6bfce72dd388e6f40 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 6 Mar 2014 14:13:29 +0100 Subject: [PATCH 2210/2215] Small fix that might or might not fix "EFAULT (bad address)"-errors when executing scripts on events --- telldus-core/service/EventUpdateManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index cf6b8718..a76d5ca1 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -226,7 +226,7 @@ void EventUpdateManager::executeScripts(EventUpdateData *data) { newEnv[i] = new char[env.at(i).length()+1]; snprintf(newEnv[i], env.at(i).length()+1, "%s", env.at(i).c_str()); } - newEnv[env.size()] = 0; // Mark end of array + newEnv[env.size()] = NULL; // Mark end of array for(StringList::iterator it = d->fileList[dir].begin(); it != d->fileList[dir].end(); ++it) { executeScript(TelldusCore::formatf("%s/%s/%s", SCRIPT_PATH, dir.c_str(), (*it).c_str()), (*it), newEnv); @@ -249,7 +249,7 @@ void EventUpdateManager::executeScript(std::string script, const std::string &na if (pid == 0) { char *n = new char[name.length()+1]; snprintf(n, name.length()+1, "%s", name.c_str()); - static char * argv[] = { n }; + static char * argv[] = { n, NULL }; execve(script.c_str(), argv, env); delete[] n; Log::error("Could not execute %s (%i): %s", script.c_str(), errno, strerror(errno)); From ed3ce34422fc6cfd44d1f32d35cf6c092479a311 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 18 Mar 2014 20:40:34 +0100 Subject: [PATCH 2211/2215] Only create the socket once. If we fail to connect is we should try to reuse it later. --- telldus-core/common/Socket_unix.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/telldus-core/common/Socket_unix.cpp b/telldus-core/common/Socket_unix.cpp index 2ee1d7c8..79dc086f 100644 --- a/telldus-core/common/Socket_unix.cpp +++ b/telldus-core/common/Socket_unix.cpp @@ -38,7 +38,7 @@ public: Socket::Socket() { d = new PrivateData; - d->socket = 0; + d->socket = -1; d->connected = false; FD_ZERO(&d->infds); } @@ -51,7 +51,7 @@ Socket::Socket(SOCKET_T socket) { } Socket::~Socket(void) { - if(d->socket) { + if(d->socket >= 0) { close(d->socket); } delete d; @@ -61,8 +61,10 @@ void Socket::connect(const std::wstring &server) { struct sockaddr_un remote; socklen_t len; - if ((d->socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) { - return; + if (d->socket == -1) { + if ((d->socket = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) { + return; + } } #if defined(_MACOSX) int op = fcntl(d->socket, F_GETFD); From 95f93cd6d316a910c5d4d2d518f772e43b7caa20 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 9 Apr 2015 12:49:21 +0200 Subject: [PATCH 2212/2215] Add dependency on client for tdtool. Build fails if parallel building is used otherwise --- telldus-core/tdtool/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-core/tdtool/CMakeLists.txt b/telldus-core/tdtool/CMakeLists.txt index c9aeb07b..eacc2dac 100644 --- a/telldus-core/tdtool/CMakeLists.txt +++ b/telldus-core/tdtool/CMakeLists.txt @@ -13,6 +13,7 @@ SET(tdtool_SRCS ADD_EXECUTABLE(tdtool ${tdtool_SRCS} ) +ADD_DEPENDENCIES(tdtool ${telldus-core_TARGET}) SIGN(tdtool) INCLUDE_DIRECTORIES( From 47eac0a3566a51f3f19cef3ac32dfa42221928d8 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 31 Oct 2016 08:39:51 +0100 Subject: [PATCH 2213/2215] Add note about third party python library tellcore-py --- docs/01-telldus-core.dox | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/01-telldus-core.dox b/docs/01-telldus-core.dox index b5987450..0102d138 100644 --- a/docs/01-telldus-core.dox +++ b/docs/01-telldus-core.dox @@ -341,8 +341,11 @@ * * \subsection sec_ol_pyhon Python * - * There is no native Python support for TellStick yet. To use telldus-core in Python, + * To use telldus-core in Python, * please have look at the ctypes library. It contains cdll and * windll to load any dynamic link libraries. * + * There is also a third party library available: + * https://github.com/erijo/tellcore-py + * */ From 0b6bc134666ab9db80d2320fe9775f7e3cd0f2ba Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 28 Jun 2017 15:46:32 +0200 Subject: [PATCH 2214/2215] Specifying chars as unsigned where needed --- telldus-core/service/ProtocolIkea.cpp | 14 +++++------ telldus-core/service/ProtocolX10.cpp | 36 +++++++++++++-------------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/telldus-core/service/ProtocolIkea.cpp b/telldus-core/service/ProtocolIkea.cpp index 6b96434a..2c19f858 100644 --- a/telldus-core/service/ProtocolIkea.cpp +++ b/telldus-core/service/ProtocolIkea.cpp @@ -23,7 +23,7 @@ int ProtocolIkea::methods() const { std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) { const char B1[] = {84, 84, 0}; - const char B0[] = {170, 0}; + const unsigned char B0[] = {170, 0}; int intSystem = this->getIntParameter(L"system", 1, 16)-1; int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true"); @@ -86,13 +86,13 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co else checksum1++; } else { - strChannels.append(B0); + strChannels.append(reinterpret_cast(B0)); } } strReturn.append(strChannels); // System + Units - strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum - strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum + strReturn.append(checksum1 %2 == 0 ? B1 : reinterpret_cast(B0)); // 1st checksum + strReturn.append(checksum2 %2 == 0 ? B1 : reinterpret_cast(B0)); // 2nd checksum int intLevel = 0; if (level <= 12) { @@ -138,12 +138,12 @@ std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Co else checksum2++; } else { - strReturn.append(B0); + strReturn.append(reinterpret_cast(B0)); } } - strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum - strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum + strReturn += checksum1 %2 == 0 ? B1 : reinterpret_cast(B0); // 1st checksum + strReturn += checksum2 %2 == 0 ? B1 : reinterpret_cast(B0); // 2nd checksum strReturn.append("+"); diff --git a/telldus-core/service/ProtocolX10.cpp b/telldus-core/service/ProtocolX10.cpp index b3af1230..fc9cda35 100644 --- a/telldus-core/service/ProtocolX10.cpp +++ b/telldus-core/service/ProtocolX10.cpp @@ -22,7 +22,7 @@ int ProtocolX10::methods() const { std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) { const unsigned char S = 59, L = 169; const char B0[] = {S, S, 0}; - const char B1[] = {S, L, 0}; + const unsigned char B1[] = {S, L, 0}; const unsigned char START_CODE[] = {'S', 255, 1, 255, 1, 255, 1, 100, 255, 1, 180, 0}; const unsigned char STOP_CODE[] = {S, 0}; @@ -42,73 +42,73 @@ std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Cont for( int i = 0; i < 4; ++i ) { if (intHouse & 1) { - strReturn.append(B1); + strReturn.append(reinterpret_cast(B1)); strComplement.append(B0); } else { strReturn.append(B0); - strComplement.append(B1); + strComplement.append(reinterpret_cast(B1)); } intHouse >>= 1; } strReturn.append( B0 ); - strComplement.append( B1 ); + strComplement.append( reinterpret_cast(B1) ); if (intCode >= 8) { - strReturn.append(B1); + strReturn.append(reinterpret_cast(B1)); strComplement.append(B0); } else { strReturn.append(B0); - strComplement.append(B1); + strComplement.append(reinterpret_cast(B1)); } strReturn.append( B0 ); - strComplement.append( B1 ); + strComplement.append( reinterpret_cast(B1) ); strReturn.append( B0 ); - strComplement.append( B1 ); + strComplement.append( reinterpret_cast(B1) ); strReturn.append( strComplement ); strComplement = ""; strReturn.append( B0 ); - strComplement.append( B1 ); + strComplement.append( reinterpret_cast(B1) ); if (intCode >> 2 & 1) { // Bit 2 of intCode - strReturn.append(B1); + strReturn.append(reinterpret_cast(B1)); strComplement.append(B0); } else { strReturn.append(B0); - strComplement.append(B1); + strComplement.append(reinterpret_cast(B1)); } if (method == TELLSTICK_TURNON) { strReturn.append(B0); - strComplement.append(B1); + strComplement.append(reinterpret_cast(B1)); } else if (method == TELLSTICK_TURNOFF) { - strReturn.append(B1); + strReturn.append(reinterpret_cast(B1)); strComplement.append(B0); } else { return ""; } if (intCode & 1) { // Bit 0 of intCode - strReturn.append(B1); + strReturn.append(reinterpret_cast(B1)); strComplement.append(B0); } else { strReturn.append(B0); - strComplement.append(B1); + strComplement.append(reinterpret_cast(B1)); } if (intCode >> 1 & 1) { // Bit 1 of intCode - strReturn.append(B1); + strReturn.append(reinterpret_cast(B1)); strComplement.append(B0); } else { strReturn.append(B0); - strComplement.append(B1); + strComplement.append(reinterpret_cast(B1)); } for( int i = 0; i < 3; ++i ) { strReturn.append( B0 ); - strComplement.append( B1 ); + strComplement.append( reinterpret_cast(B1) ); } strReturn.append( strComplement ); From cc326285c5d9e5d35ef50c97ddab57539e602594 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 28 Jun 2017 15:48:56 +0200 Subject: [PATCH 2215/2215] Bumped version to 2.1.3-beta1 --- telldus-core/CMakeLists.txt | 4 ++-- telldus-gui/CMakeLists.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 3f6ae5a1..01cde2b9 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -11,9 +11,9 @@ ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) -SET(PACKAGE_PATCH_VERSION 2) +SET(PACKAGE_PATCH_VERSION 3) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(PACKAGE_SUBVERSION "rc1") +SET(PACKAGE_SUBVERSION "beta1") SET(PACKAGE_SOVERSION 2) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index b6563518..ed193422 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -8,10 +8,10 @@ endif(COMMAND cmake_policy) SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 1) -SET(PACKAGE_PATCH_VERSION 2) +SET(PACKAGE_PATCH_VERSION 3) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") -SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_rc1") +SET(DISPLAYED_VERSION "${PACKAGE_VERSION}_beta1") SET(BRANDING "telldus" CACHE STRING "The brand to use")

Telldus Center %1

" + QMessageBox::about(this, tr("About TelldusCenter"), + tr("

TelldusCenter %1

" "

Copyright © 2010 Telldus Technologies AB

").arg(VERSION_STRING(VERSION))); } From 75debda9ee406b7d278b068bff484fdaa0e2f08d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 10:39:05 +0000 Subject: [PATCH 1599/2215] Info.plist is now configured by CMake and the version number is replaced by the current version --- telldus-gui/TelldusCenter/CMakeLists.txt | 9 ++++++++- telldus-gui/TelldusCenter/{Info.plist => Info.plist.in} | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) rename telldus-gui/TelldusCenter/{Info.plist => Info.plist.in} (88%) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 71295563..b7bdb20d 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -68,6 +68,13 @@ IF (APPLE) #### Mac OS X #### INCLUDE_DIRECTORIES( /usr/include/QtUiTools ) + CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + ${CMAKE_CURRENT_BINARY_DIR}/Info.plist + ) + LIST(APPEND telldus-center_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in + ) ELSEIF (WIN32) #### Windows #### ADD_DEFINITIONS( -DUNICODE ) @@ -139,7 +146,7 @@ SET_SOURCE_FILES_PROPERTIES(${telldus-center_RESOURCES} PROPERTIES MACOSX_PACKAG TARGET_LINK_LIBRARIES( ${telldus-center_TARGET} ${telldus-center_LIBRARIES} ) SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES - MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist ) IF (APPLE) SET_TARGET_PROPERTIES(${telldus-center_TARGET} PROPERTIES diff --git a/telldus-gui/TelldusCenter/Info.plist b/telldus-gui/TelldusCenter/Info.plist.in similarity index 88% rename from telldus-gui/TelldusCenter/Info.plist rename to telldus-gui/TelldusCenter/Info.plist.in index e6d0072b..280b5ed2 100644 --- a/telldus-gui/TelldusCenter/Info.plist +++ b/telldus-gui/TelldusCenter/Info.plist.in @@ -17,8 +17,8 @@ CFBundleName TelldusCenter CFBundleShortVersionString - TelldusCenter 2.0.0 + TelldusCenter ${PACKAGE_VERSION} CFBundleVersion - 2.0.0 + ${PACKAGE_VERSION} From 3bdada5b885e3dd615461fe7f1717d73917caf4d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 11:51:31 +0000 Subject: [PATCH 1600/2215] Ugly workaround agains the crash when TelldusCenter exits. We are now leaking instead (only at shutdown though) --- .../TelldusCenter/scriptenvironment.cpp | 40 ++++++++++--------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/telldus-gui/TelldusCenter/scriptenvironment.cpp b/telldus-gui/TelldusCenter/scriptenvironment.cpp index fdc172e7..dfc9335d 100644 --- a/telldus-gui/TelldusCenter/scriptenvironment.cpp +++ b/telldus-gui/TelldusCenter/scriptenvironment.cpp @@ -18,7 +18,7 @@ public: class ScriptEnvironment::PrivateData { public: - QScriptEngine scriptEngine; + QScriptEngine *scriptEngine; QHash intervalHash; QHash timeoutHash; }; @@ -27,59 +27,61 @@ ScriptEnvironment::ScriptEnvironment(QObject *parent) : QObject(parent) { d = new PrivateData; + d->scriptEngine = new QScriptEngine(); - connect(&d->scriptEngine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(scriptException(const QScriptValue&))); - d->scriptEngine.installTranslatorFunctions(); + connect(d->scriptEngine, SIGNAL(signalHandlerException(const QScriptValue &)), this, SLOT(scriptException(const QScriptValue&))); + d->scriptEngine->installTranslatorFunctions(); //Self is our new global object - QScriptValue self = d->scriptEngine.newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeSuperClassContents); + QScriptValue self = d->scriptEngine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeSuperClassContents); { //Copy everything from our old global object - QScriptValueIterator it(d->scriptEngine.globalObject()); + QScriptValueIterator it(d->scriptEngine->globalObject()); while (it.hasNext()) { it.next(); self.setProperty(it.scriptName(), it.value(), it.flags()); } } self.setProperty("self", self); - d->scriptEngine.setGlobalObject(self); + d->scriptEngine->setGlobalObject(self); - QScriptValue application = d->scriptEngine.newQObject(parent); - d->scriptEngine.globalObject().setProperty("application", application); + QScriptValue application = d->scriptEngine->newQObject(parent); + d->scriptEngine->globalObject().setProperty("application", application); //Create configuration dialog - QScriptValue configurationDialogObject = d->scriptEngine.newQObject(new ConfigurationDialog(&d->scriptEngine), QScriptEngine::ScriptOwnership, QScriptEngine::ExcludeSuperClassContents); - d->scriptEngine.globalObject().property("application").setProperty("configuration", configurationDialogObject); + QScriptValue configurationDialogObject = d->scriptEngine->newQObject(new ConfigurationDialog(d->scriptEngine), QScriptEngine::ScriptOwnership, QScriptEngine::ExcludeSuperClassContents); + d->scriptEngine->globalObject().property("application").setProperty("configuration", configurationDialogObject); //Collect garbage (ie our old global object) - d->scriptEngine.collectGarbage(); + d->scriptEngine->collectGarbage(); } ScriptEnvironment::~ScriptEnvironment() { foreach(TimerObj *tim, d->timeoutHash){ delete tim; } +// delete d->scriptEngine; //This seems to crash for some reason? delete d; } QDir ScriptEnvironment::currentDir() const { - QScriptContextInfo info(d->scriptEngine.currentContext()->parentContext()); + QScriptContextInfo info(d->scriptEngine->currentContext()->parentContext()); QFileInfo fileinfo(info.fileName()); return fileinfo.dir(); } QScriptEngine *ScriptEnvironment::engine() const { - return &d->scriptEngine; + return d->scriptEngine; } void ScriptEnvironment::scriptException(const QScriptValue & exception) { - qDebug() << "ScriptException:" << d->scriptEngine.uncaughtExceptionLineNumber() << exception.toString(); + qDebug() << "ScriptException:" << d->scriptEngine->uncaughtExceptionLineNumber() << exception.toString(); qDebug() << "Backtrace:"; - foreach( QString row, d->scriptEngine.uncaughtExceptionBacktrace() ) { + foreach( QString row, d->scriptEngine->uncaughtExceptionBacktrace() ) { qDebug() << row; } - d->scriptEngine.clearExceptions(); + d->scriptEngine->clearExceptions(); } void ScriptEnvironment::include(const QString &filename) { @@ -90,11 +92,11 @@ void ScriptEnvironment::include(const QString &filename) { QString fileContents = file.readAll(); file.close(); - QScriptContext *ctx = d->scriptEngine.currentContext(); + QScriptContext *ctx = d->scriptEngine->currentContext(); ctx->setActivationObject(ctx->parentContext()->activationObject()); - d->scriptEngine.evaluate(fileContents, dir.filePath(filename)); + d->scriptEngine->evaluate(fileContents, dir.filePath(filename)); } void ScriptEnvironment::timerEvent(QTimerEvent *event) { @@ -125,7 +127,7 @@ void ScriptEnvironment::timerEvent(QTimerEvent *event) { } if (expression.isString()) { - d->scriptEngine.evaluate(expression.toString()); + d->scriptEngine->evaluate(expression.toString()); } else if (expression.isFunction()) { expression.call(); } From c958ef46f1c22ca71c9a7287a80b10dfcf33c5be Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 11:55:15 +0000 Subject: [PATCH 1601/2215] Removed the dependency for QCA for now. Using sha1 instead of sha512 for signatures is enough --- telldus-gui/Plugins/Live/CMakeLists.txt | 3 --- telldus-gui/Plugins/Live/LiveObject.cpp | 16 ---------------- 2 files changed, 19 deletions(-) diff --git a/telldus-gui/Plugins/Live/CMakeLists.txt b/telldus-gui/Plugins/Live/CMakeLists.txt index 7afa0a3e..18d607ac 100644 --- a/telldus-gui/Plugins/Live/CMakeLists.txt +++ b/telldus-gui/Plugins/Live/CMakeLists.txt @@ -34,9 +34,6 @@ CONFIGURE_FILE( INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/parsed/) -FIND_PACKAGE(QCA REQUIRED) -SET( Plugin_LIBRARIES ${QCA_LIBRARY} ) - SET(TELLDUS_LIVE_PUBLIC_KEY "" CACHE STRING "Telldus Live! public key") SET(TELLDUS_LIVE_PRIVATE_KEY "" CACHE STRING "Telldus Live! private key") SET(TELLDUS_LIVE_URI "https://api.telldus.com/server/assign" CACHE STRING "Telldus Live! Connection URI") diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index bf75d4ad..dc36ebb3 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -18,7 +17,6 @@ public: bool registered; QUrl registerUrl; QString uuid, hashMethod; - QCA::Initializer qcaInit; QNetworkAccessManager *manager; QList serverList; QDateTime serverRefreshTime; @@ -36,12 +34,6 @@ LiveObject::LiveObject( QScriptEngine *engine, QObject * parent ) { d = new PrivateData; d->hashMethod = "sha1"; - foreach(QString hash, QStringList() << "sha512" << "sha256") { - if (QCA::isSupported(hash.toUtf8())) { - d->hashMethod = hash; - break; - } - } d->registered = false; d->socket = new QSslSocket(this); d->socket->setProtocol( QSsl::TlsV1 ); @@ -264,14 +256,6 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { } QByteArray LiveObject::signatureForMessage( const QByteArray &message ) { - if (QCA::isSupported(d->hashMethod.toUtf8())) { - QCA::Hash signature(d->hashMethod); - signature.update(message); - signature.update(TELLDUS_LIVE_PRIVATE_KEY); - return signature.final().toByteArray().toHex(); - } - - //Fallback to builtin function QCryptographicHash signature( QCryptographicHash::Sha1 ); signature.addData(message); signature.addData(TELLDUS_LIVE_PRIVATE_KEY); From b5534d309e9237609d1bb3cba6d9cf89ccf71cff Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 23 Feb 2011 13:08:01 +0000 Subject: [PATCH 1602/2215] Callback example (with timer), for python --- .../python/Callback functions/callbacks.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 bindings/python/Callback functions/callbacks.py diff --git a/bindings/python/Callback functions/callbacks.py b/bindings/python/Callback functions/callbacks.py new file mode 100644 index 00000000..2108fd28 --- /dev/null +++ b/bindings/python/Callback functions/callbacks.py @@ -0,0 +1,76 @@ +from ctypes import c_int, c_ubyte, c_void_p, POINTER, string_at #imports allowing the use of our library +from threading import Timer +import time +import platform + +#platform specific imports: +if (platform.system() == 'Windows'): + #Windows + from ctypes import windll, WINFUNCTYPE + lib = windll.LoadLibrary('TelldusCore.dll') #import our library +else: + #Linux + from ctypes import cdll, CFUNCTYPE + lib = cdll.LoadLibrary('libtelldus-core.so.2') #import our library + +timers = {} #timerlist + +def turnOn(): + print "turning on" + lib.tdTurnOn(1) + +def turnOff(): + print "turning off" + lib.tdTurnOff(1) + +#function to be called when a device event occurs +def callbackfunction(deviceId, method, value, callbackId, context): + global timers + + print "callback!" + + if (deviceId == 1): + # is turning on deviceId 1 here, so just return if events for that device are picked up + return + + t = 0 + print "Received event for device %d" % (deviceId,) + if (deviceId in timers): + # a timer already exists for this device, it might be running so interrupt it + # Many devices (for example motion detectors) resends their messages many times to ensure that they + # are received correctly. In this example, we don't want to run the turnOn/turnOff methods every time, instead we + # start a timer, and run the method when the timer is finished. For every incoming event on this device, the timer + # is restarted. + t = timers[deviceId] + t.cancel() + if (method == 1): + #on + t = Timer(0.5, turnOn) #start timer with 0.5 second delay (adjust the delay to suit your needs), then turn on + else: + #off + t = Timer(0.5, turnOff) #start timer with 0.5 second delay (adjust the delay to suit your needs), then turn off + + t.start() + timers[deviceId] = t #put timer in list, to allow later cancellation + +#function to be called when device event occurs, even for unregistered devices +def rawcallbackfunction(data, controllerId, callbackId, context): + print string_at(data) + +if (platform.system() == 'Windows'): + CMPFUNC = WINFUNCTYPE(c_void_p, c_int, c_int, POINTER(c_ubyte), c_int, c_void_p) #first is return type + CMPFUNCRAW = WINFUNCTYPE(c_void_p, POINTER(c_ubyte), c_int, c_int, c_void_p) +else: + CMPFUNC = CFUNCTYPE(c_void_p, c_int, c_int, POINTER(c_ubyte), c_int, c_void_p) + CMPFUNCRAW = CFUNCTYPE(c_void_p, POINTER(c_ubyte), c_int, c_int, c_void_p) + +cmp_func = CMPFUNC(callbackfunction) +cmp_funcraw = CMPFUNCRAW(rawcallbackfunction) + +lib.tdInit() +lib.tdRegisterDeviceEvent(cmp_func, 0) +#lib.tdRegisterRawDeviceEvent(cmp_funcraw, 0) #uncomment this, and comment out tdRegisterDeviceEvent, to see data for not registered devices + +print "Waiting for events..." +while(1): + time.sleep(0.5) #don't exit \ No newline at end of file From 6f8a48ab8d3c7dc3042a5e719d98000bd27de9ee Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 13:09:27 +0000 Subject: [PATCH 1603/2215] Display the reason for the error in a server assign request --- telldus-gui/Plugins/Live/LiveObject.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index dc36ebb3..31dc0f6b 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -225,7 +225,12 @@ void LiveObject::sslErrors( const QList & errors ) { } void LiveObject::serverAssignReply( QNetworkReply *r ) { - qDebug() << "Server assign reply"; + r->deleteLater(); + if (r->error() != QNetworkReply::NoError) { + emit errorChanged(r->errorString()); + emit statusChanged("Error retrieving server list"); + return; + } QXmlStreamReader xml(r); xml.readNextStartElement(); // enter @@ -252,7 +257,6 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { emit statusChanged("Retrying in " + QString::number(timeout) + " seconds..."); QTimer::singleShot(timeout * 1000, this, SLOT(connectToServer())); } - r->deleteLater(); } QByteArray LiveObject::signatureForMessage( const QByteArray &message ) { From a9ce4cd79d90998f2ba8ced96397734863f112ed Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 13:35:31 +0000 Subject: [PATCH 1604/2215] Better sizehint for the categorylist in the configuration dialog --- telldus-gui/TelldusCenter/configurationdialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusCenter/configurationdialog.cpp b/telldus-gui/TelldusCenter/configurationdialog.cpp index c608f111..9767eff8 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.cpp +++ b/telldus-gui/TelldusCenter/configurationdialog.cpp @@ -18,7 +18,7 @@ class CategoryListWidget : public QListWidget { public: CategoryListWidget(QWidget *parent = 0) : QListWidget(parent) { - setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); setSelectionMode(QAbstractItemView::SingleSelection); setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); } @@ -27,7 +27,7 @@ public: int width = sizeHintForColumn(0) + frameWidth() * 2 + 5; if (verticalScrollBar()->isVisible()) width += verticalScrollBar()->width(); - return QSize(width, 100); + return QSize(width, 200); } }; From 7213d98d3291f583d53ade713f86ab210b108c40 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 13:47:28 +0000 Subject: [PATCH 1605/2215] Show large icons with text under the icon in the category widget --- telldus-gui/TelldusCenter/configurationdialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-gui/TelldusCenter/configurationdialog.cpp b/telldus-gui/TelldusCenter/configurationdialog.cpp index 9767eff8..938dc77b 100644 --- a/telldus-gui/TelldusCenter/configurationdialog.cpp +++ b/telldus-gui/TelldusCenter/configurationdialog.cpp @@ -51,6 +51,9 @@ ConfigurationDialog::ConfigurationDialog(QScriptEngine *engine, QWidget *parent) QHBoxLayout *mainLayout = new QHBoxLayout(); d->listWidget = new CategoryListWidget(this); + d->listWidget->setViewMode(QListView::IconMode); + d->listWidget->setFlow(QListView::TopToBottom); + d->listWidget->setMovement(QListView::Static); connect(d->listWidget, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), this, SLOT(currentItemChanged(QListWidgetItem*,QListWidgetItem*))); mainLayout->addWidget(d->listWidget); From 72575f5474707ac1be37d73af0c7fdbd89931b39 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 23 Feb 2011 14:26:31 +0000 Subject: [PATCH 1606/2215] Note about best practise when DeviceEvent/RawDeviceEvent is executing other controlling events --- docs/telldus-core.dox | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/telldus-core.dox b/docs/telldus-core.dox index b3f7fb73..a34afe64 100644 --- a/docs/telldus-core.dox +++ b/docs/telldus-core.dox @@ -210,6 +210,12 @@ * thread used by the application and some measures must be taken to synchronize * it with the main thread. * + * Many devices (for example motion detectors) resends their messages many times + * to ensure that they are received correctly. If a deviceeventcallback or + * rawdeviceeventcallback in turn is calling a controlling function, for example tdTurnOn, + * it may be neccessary to implement some solution to wait for the device to finish its + * resending, before executing the controlling function. See how this can be done in the python example. + * * \subsection sec_events_callbacks Callbacks * * telldus-core currently implements three different callback function for @@ -227,6 +233,8 @@ * etc. * - const char *data - For some methods this contains data. For TELLSTICK_DIM * this hold the current value. + * - int callbackId - id of callback + * - void *context - see "Registering for callbacks" for description * * \subsubsection sec_events_callbacks_devicechangeevent DeviceChangeEvent * This event is fired when the data around a device is changed. It can only be @@ -247,6 +255,8 @@ * - TELLSTICK_CHANGE_NAME - Use tdGetName() to read the new name. * - TELLSTICK_CHANGE_PROTOCOL - Use tdGetProtocol() to read the new value. * - TELLSTICK_CHANGE_MODEL - Use tdGetModel() to read the new value. + * - int callbackId - id of callback + * - void *context - see "Registering for callbacks" for description * * \subsubsection sec_events_callbacks_rawdeviceevent RawDeviceEvent * @@ -254,6 +264,12 @@ * any preprocessing. This can be used to get events from devices not already * configured. * + * Parameters: + * - const char *data - raw device data + * - int controllerId - id of receiving controller, can identify the TellStick if several exists in the system + * - int callbackId - id of callback + * - void *context - see "Registering for callbacks" for description + * * \subsection sec_events_example Example * * \section sec_other_languages Notes using other languages than C/C++ From 58a33f8f6da57c5112cb2bb95d7d2017b9be86ed Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 15:09:53 +0000 Subject: [PATCH 1607/2215] Added support for Qt-resources in plugins --- telldus-gui/Plugins/TelldusCenterPlugin.cmake | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index 92a2db86..ebbc6b75 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -10,6 +10,9 @@ endif(COMMAND cmake_policy) QT4_WRAP_CPP( Plugin_MOC_SRCS ${Plugin_MOC_HDRS} ) QT4_AUTOMOC ( ${Plugin_SRCS} ) +IF(Plugin_RESOURCES) + QT4_ADD_RESOURCES(Plugin_RSRCS ${Plugin_RESOURCES}) +ENDIF(Plugin_RESOURCES) SET( Plugin_LIBRARIES ${Plugin_LIBRARIES} @@ -63,6 +66,7 @@ IF(Plugin_SRCS) ADD_LIBRARY(${Plugin_NAME} SHARED ${Plugin_SRCS} ${Plugin_HDRS} + ${Plugin_RSRCS} ${Plugin_MOC_HDRS} ${Plugin_MOC_SRCS} ${Plugin_MOC_HDRS} From fbac40337b2cef34101bb28df44708e5e99716b3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 15:12:22 +0000 Subject: [PATCH 1608/2215] We ship our CA Certificate in those cases it isn't available on the target platform. This happens for instance on a newly installed Windows or where Internet Explorer is not used. --- telldus-gui/Plugins/Live/CMakeLists.txt | 4 ++++ .../Plugins/Live/Equifax_Secure_CA.pem | 19 +++++++++++++++++++ telldus-gui/Plugins/Live/Live.qrc | 5 +++++ telldus-gui/Plugins/Live/LiveObject.cpp | 3 +++ 4 files changed, 31 insertions(+) create mode 100644 telldus-gui/Plugins/Live/Equifax_Secure_CA.pem create mode 100644 telldus-gui/Plugins/Live/Live.qrc diff --git a/telldus-gui/Plugins/Live/CMakeLists.txt b/telldus-gui/Plugins/Live/CMakeLists.txt index 18d607ac..343a6546 100644 --- a/telldus-gui/Plugins/Live/CMakeLists.txt +++ b/telldus-gui/Plugins/Live/CMakeLists.txt @@ -22,6 +22,10 @@ SET( Plugin_MOC_HDRS LiveObject.h ) +SET( Plugin_RESOURCES + Live.qrc +) + SET( Plugin_EXTRA configuration.ui icon.png diff --git a/telldus-gui/Plugins/Live/Equifax_Secure_CA.pem b/telldus-gui/Plugins/Live/Equifax_Secure_CA.pem new file mode 100644 index 00000000..ed0bd764 --- /dev/null +++ b/telldus-gui/Plugins/Live/Equifax_Secure_CA.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV +UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy +dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 +MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx +dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f +BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A +cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC +AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ +MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm +aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw +ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj +IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF +MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA +A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y +7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh +1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 +-----END CERTIFICATE----- diff --git a/telldus-gui/Plugins/Live/Live.qrc b/telldus-gui/Plugins/Live/Live.qrc new file mode 100644 index 00000000..5af20a56 --- /dev/null +++ b/telldus-gui/Plugins/Live/Live.qrc @@ -0,0 +1,5 @@ + + + Equifax_Secure_CA.pem + + diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 31dc0f6b..ebaa2ec3 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -35,6 +35,8 @@ LiveObject::LiveObject( QScriptEngine *engine, QObject * parent ) d = new PrivateData; d->hashMethod = "sha1"; d->registered = false; + + QSslSocket::addDefaultCaCertificates(":/Equifax_Secure_CA.pem"); d->socket = new QSslSocket(this); d->socket->setProtocol( QSsl::TlsV1 ); connect(d->socket, SIGNAL(encrypted()), this, SLOT(p_connected())); @@ -213,6 +215,7 @@ void LiveObject::sslErrors( const QList & errors ) { case QSslError::SelfSignedCertificate: continue; default: + qDebug() << "SSL" << error.errorString(); everythingOK = false; emit statusChanged("SSL Error"); emit errorChanged(error.errorString()); From 78122bad754529c9e43578ed64163c813c5ba379 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 16:03:58 +0000 Subject: [PATCH 1609/2215] Trigger error messages again --- telldus-gui/TelldusGui/device.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index a0d65349..6e3b9f55 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -233,9 +233,9 @@ void Device::deviceChangedSlot(int deviceId, int eventId, int changeType) { void Device::triggerEvent( int messageId ) { if (messageId != TELLSTICK_SUCCESS) { -// char *message = tdGetErrorString( messageId ); -// emit showMessage( "", message, "" ); -// tdReleaseString( message ); + char *message = tdGetErrorString( messageId ); + emit showMessage( "", message, "" ); + tdReleaseString( message ); } } From f5f0714c85daec3c4fdf7f04c7b74f2a252a30cf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 16:06:46 +0000 Subject: [PATCH 1610/2215] Fixed function Device::stop(), it was both misspelled and not declared --- telldus-gui/TelldusGui/device.cpp | 2 +- telldus-gui/TelldusGui/device.h | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 6e3b9f55..3b2a6d89 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -171,7 +171,7 @@ void Device::down() { triggerEvent( tdDown( d->id ) ); } -void Device::stops() { +void Device::stop() { triggerEvent( tdStop( d->id ) ); } diff --git a/telldus-gui/TelldusGui/device.h b/telldus-gui/TelldusGui/device.h index 38f370bf..f9ef8650 100644 --- a/telldus-gui/TelldusGui/device.h +++ b/telldus-gui/TelldusGui/device.h @@ -33,7 +33,7 @@ public: int lastSentCommand() const; QString lastSentValue() const; - int methods() const; + int methods() const; static void remove(int deviceId); @@ -47,6 +47,7 @@ public slots: void execute(); void up(); void down(); + void stop(); void learn(); signals: @@ -55,9 +56,9 @@ signals: void nameChanged( int deviceId, const QString &newName ); void methodsChanged( int deviceId ); void stateChanged( int deviceId ); -// void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); + void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); // void eventTriggered( const QString &name, const QString &title ); - + private slots: void deviceChangedSlot(int deviceId, int eventId, int changeType); From 429620b9570b4ef2bfe7abb46d58fed95c50fe0e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 16:17:15 +0000 Subject: [PATCH 1611/2215] Connect the showMessage() signals from the devices --- telldus-gui/TelldusGui/devicemodel.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index 7b0886cf..8010a5dc 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -24,11 +24,12 @@ DeviceModel::DeviceModel(QObject *parent) for( int i = 0; i < numberOfDevices; ++i ) { int id = tdGetDeviceId(i); Device *device = new Device(id, SUPPORTED_METHODS, this); + connect(device, SIGNAL(showMessage(QString,QString,QString)), this, SIGNAL(showMessage(QString,QString,QString))); devices.append(device); connect(device, SIGNAL(stateChanged(int)), this, SLOT(deviceStateChanged(int)), Qt::QueuedConnection); connect(device, SIGNAL(nameChanged(int,QString)), this, SLOT(nameChanged(int,QString)), Qt::QueuedConnection); } - + deviceChangeCallbackId = tdRegisterDeviceChangeEvent( reinterpret_cast(&DeviceModel::deviceChangeEvent), this); } @@ -77,9 +78,9 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const { Device *device = devices[index.row()]; int lastSentCommand = device->lastSentCommand(); return QIcon( QString(":/images/state_%1.png").arg(lastSentCommand) ); - } else if (role == Qt::TextAlignmentRole) { - return Qt::AlignCenter; - } + } else if (role == Qt::TextAlignmentRole) { + return Qt::AlignCenter; + } } else if (index.column() == 1) { if (role == Qt::DisplayRole) { return devices[index.row()]->name(); @@ -143,6 +144,7 @@ void DeviceModel::deviceChanged( int deviceId, int eventType, int changeType ) { //We are not running in the DeviceModel-thread here. Move the device to the correct thread device->moveToThread(this->thread()); device->setParent(this); + connect(device, SIGNAL(showMessage(QString,QString,QString)), this, SIGNAL(showMessage(QString,QString,QString))); devices.append(device); connect(device, SIGNAL(stateChanged(int)), this, SLOT(deviceStateChanged(int))); connect(device, SIGNAL(nameChanged(int,QString)), this, SLOT(nameChanged(int,QString))); @@ -157,7 +159,7 @@ void DeviceModel::deviceChanged( int deviceId, int eventType, int changeType ) { endRemoveRows(); } } - + } void DeviceModel::nameChanged(int deviceId, const QString &) { From 18b56f2069a2b27c159f6f56cd77de15a74625f3 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 23 Feb 2011 16:18:14 +0000 Subject: [PATCH 1612/2215] No need to moc devicesplugin.h, it doesn't contain any QObject subclasses --- telldus-gui/Plugins/Devices/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/Devices/CMakeLists.txt b/telldus-gui/Plugins/Devices/CMakeLists.txt index c8e705c0..455ecb21 100644 --- a/telldus-gui/Plugins/Devices/CMakeLists.txt +++ b/telldus-gui/Plugins/Devices/CMakeLists.txt @@ -5,10 +5,10 @@ SET( Plugin_SRCS ) SET( Plugin_HDRS + devicesplugin.h ) SET( Plugin_MOC_HDRS - devicesplugin.h ) SET( Plugin_PATH "com.telldus.gui" ) From 75affe3f5c619903a1fe884cf65bb8ffb3d1179f Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 24 Feb 2011 10:20:12 +0000 Subject: [PATCH 1613/2215] Exported tdUp(), tdDown() and tdStop() to the script engine --- .../Plugins/TelldusCore/tellduscoreobject.cpp | 24 +++++++++++++++++++ .../Plugins/TelldusCore/tellduscoreobject.h | 15 +++++++----- .../Plugins/TelldusCore/tellduscoreplugin.cpp | 7 ++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp index 4a9528c4..ada1a586 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp @@ -77,6 +77,30 @@ int TelldusCoreObject::turnOff(int deviceId) { return retval; } +int TelldusCoreObject::up(int deviceId) { + int retval = tdUp( deviceId ); + if (retval != TELLSTICK_SUCCESS) { + triggerError(deviceId, retval); + } + return retval; +} + +int TelldusCoreObject::down(int deviceId) { + int retval = tdDown( deviceId ); + if (retval != TELLSTICK_SUCCESS) { + triggerError(deviceId, retval); + } + return retval; +} + +int TelldusCoreObject::stop(int deviceId) { + int retval = tdStop( deviceId ); + if (retval != TELLSTICK_SUCCESS) { + triggerError(deviceId, retval); + } + return retval; +} + void TelldusCoreObject::triggerError(int deviceId, int errorId) { char *errorString = tdGetErrorString( errorId ); QString message = QString::fromUtf8( errorString ); diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h index b7a8acb2..d8e14a78 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h @@ -10,7 +10,7 @@ class TelldusCoreObject : public QObject public: TelldusCoreObject( QObject * parent = 0 ); virtual ~TelldusCoreObject(); - + signals: void deviceChange( int deviceId, int eventId ); void deviceEvent( int deviceId, int method, const QString &data ); @@ -25,19 +25,22 @@ public slots: int lastSentCommand( int deviceId, int methodsSupported ); QString lastSentValue( int deviceId ); int methods( int deviceId, int methodsSupported ); - + int turnOn( int deviceId ); int turnOff( int deviceId ); - + int up( int deviceId ); + int down( int deviceId ); + int stop( int deviceId ); + private: void triggerError( int, int ); - + static void WINAPI deviceChangeEventCallback(int deviceId, int eventId, int changeType, int callbackId, void *context); static void WINAPI deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *context); - + int deviceEventId; int deviceChangeEventId; - + }; #endif // TELLDUSCOREOBJECT_H diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp index a9fde239..cdc8d9b6 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreplugin.cpp @@ -21,12 +21,15 @@ void TelldusCorePlugin::initialize ( const QString & key, QScriptEngine * engine value.setProperty("TELLSTICK_BELL", TELLSTICK_BELL); value.setProperty("TELLSTICK_TOGGLE", TELLSTICK_TOGGLE); value.setProperty("TELLSTICK_DIM", TELLSTICK_DIM); - + value.setProperty("TELLSTICK_UP", TELLSTICK_UP); + value.setProperty("TELLSTICK_DOWN", TELLSTICK_DOWN); + value.setProperty("TELLSTICK_STOP", TELLSTICK_STOP); + value.setProperty("TELLSTICK_DEVICE_ADDED", TELLSTICK_DEVICE_ADDED); value.setProperty("TELLSTICK_DEVICE_CHANGED", TELLSTICK_DEVICE_CHANGED); value.setProperty("TELLSTICK_DEVICE_REMOVED", TELLSTICK_DEVICE_REMOVED); value.setProperty("TELLSTICK_DEVICE_STATE_CHANGED", TELLSTICK_DEVICE_STATE_CHANGED); - + engine->globalObject().property("com").property("telldus").setProperty("core", value); } } From 3800071f98ef53c946f2b8dd0ab0207efddb6935 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 25 Feb 2011 10:05:41 +0000 Subject: [PATCH 1614/2215] Corrected spelling mistake --- scheduler/DeviceScheduler/frmSchedule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scheduler/DeviceScheduler/frmSchedule.cs b/scheduler/DeviceScheduler/frmSchedule.cs index 2dc74ac0..76139a72 100644 --- a/scheduler/DeviceScheduler/frmSchedule.cs +++ b/scheduler/DeviceScheduler/frmSchedule.cs @@ -136,7 +136,7 @@ namespace DeviceScheduler cboMonthJan.Checked = (months.IndexOf("January") > -1); cboMonthFeb.Checked = (months.IndexOf("February") > -1); cboMonthMar.Checked = (months.IndexOf("March") > -1); - cboMonthApr.Checked = (months.IndexOf("Arpil") > -1); + cboMonthApr.Checked = (months.IndexOf("April") > -1); cboMonthMay.Checked = (months.IndexOf("May") > -1); cboMonthJune.Checked = (months.IndexOf("June") > -1); cboMonthJuly.Checked = (months.IndexOf("July") > -1); From 365eaee9510daf31d7bcaa29c4e53b98c9e1c068 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 25 Feb 2011 13:38:26 +0000 Subject: [PATCH 1615/2215] Added ecosavers --- .../TelldusGui/data/telldus/devices.xml | 6 ++ .../TelldusGui/data/telldus/resources.qrc | 100 +++++++++--------- telldus-gui/TelldusGui/editdevicedialog.cpp | 4 + .../TelldusGui/images/devices/ecosavers.png | Bin 0 -> 19835 bytes .../TelldusGui/images/vendors/ecosavers.png | Bin 0 -> 7923 bytes 5 files changed, 61 insertions(+), 49 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/ecosavers.png create mode 100644 telldus-gui/TelldusGui/images/vendors/ecosavers.png diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index 2ccffaac..c4ca2b5f 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -26,6 +26,9 @@ Self Learning + + Self Learning + Code Switch @@ -118,5 +121,8 @@ Projector screen + + Projector screen + diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index 5dfca93a..095867a1 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -1,51 +1,53 @@ - - devices.xml - ../../images/devices/arctech_cs.png - ../../images/devices/arctech_sl.png - ../../images/devices/bell.png - ../../images/devices/byebye.png - ../../images/devices/brennenstuhl_cs.png - ../../images/devices/conrad-rsl888.png - ../../images/devices/elro.png - ../../images/devices/elro-ab600.png - ../../images/devices/fr004r.png - ../../images/devices/goobay.png - ../../images/devices/gao_cs.png - ../../images/devices/gao_sl.png - ../../images/devices/hq_cs.png - ../../images/devices/koppla.png - ../../images/devices/otio.png - ../../images/devices/projectorscreen.png - ../../images/devices/risingsun_cs.png - ../../images/devices/sartano.png - ../../images/devices/upm_sl.png - ../../images/devices/waveman_cs.png - ../../images/devices/x10.png - ../../images/devices/zke-2603.png - ../../images/vendors/byebyelogo.png - ../../images/vendors/chacon.png - ../../images/vendors/coco.png - ../../images/vendors/conrad.png - ../../images/vendors/brennenstuhl.png - ../../images/vendors/elro.png - ../../images/vendors/goobay.png - ../../images/vendors/gao.png - ../../images/vendors/homeeasy.png - ../../images/vendors/hq.png - ../../images/vendors/ikea.png - ../../images/vendors/intertechno.png - ../../images/vendors/kappa.png - ../../images/vendors/kjelloco.png - ../../images/vendors/klikaanklikuit.png - ../../images/vendors/nexa.png - ../../images/vendors/otio.png - ../../images/vendors/proove.png - ../../images/vendors/roxcore.png - ../../images/vendors/rusta.png - ../../images/vendors/sartano.png - ../../images/vendors/upm.png - ../../images/vendors/waveman.png - ../../images/vendors/x10.png - + + devices.xml + ../../images/devices/arctech_cs.png + ../../images/devices/arctech_sl.png + ../../images/devices/bell.png + ../../images/devices/byebye.png + ../../images/devices/brennenstuhl_cs.png + ../../images/devices/conrad-rsl888.png + ../../images/devices/ecosavers.png + ../../images/devices/elro.png + ../../images/devices/elro-ab600.png + ../../images/devices/fr004r.png + ../../images/devices/goobay.png + ../../images/devices/gao_cs.png + ../../images/devices/gao_sl.png + ../../images/devices/hq_cs.png + ../../images/devices/koppla.png + ../../images/devices/otio.png + ../../images/devices/projectorscreen.png + ../../images/devices/risingsun_cs.png + ../../images/devices/sartano.png + ../../images/devices/upm_sl.png + ../../images/devices/waveman_cs.png + ../../images/devices/x10.png + ../../images/devices/zke-2603.png + ../../images/vendors/byebyelogo.png + ../../images/vendors/chacon.png + ../../images/vendors/coco.png + ../../images/vendors/conrad.png + ../../images/vendors/brennenstuhl.png + ../../images/vendors/ecosavers.png + ../../images/vendors/elro.png + ../../images/vendors/goobay.png + ../../images/vendors/gao.png + ../../images/vendors/homeeasy.png + ../../images/vendors/hq.png + ../../images/vendors/ikea.png + ../../images/vendors/intertechno.png + ../../images/vendors/kappa.png + ../../images/vendors/kjelloco.png + ../../images/vendors/klikaanklikuit.png + ../../images/vendors/nexa.png + ../../images/vendors/otio.png + ../../images/vendors/proove.png + ../../images/vendors/roxcore.png + ../../images/vendors/rusta.png + ../../images/vendors/sartano.png + ../../images/vendors/upm.png + ../../images/vendors/waveman.png + ../../images/vendors/x10.png + diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index eeb336fa..7eddfa76 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -159,6 +159,10 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f ((DeviceSettingArctechSelflearning *)d->deviceSettings[12])->setRemoteMinMax(1,33554432); ((DeviceSettingArctechSelflearning *)d->deviceSettings[12])->setUnitMinMax(1,16); d->deviceSettings[13] = new DeviceSettingUnitcode(device, this); + //Ecosavers + d->deviceSettings[14] = new DeviceSettingArctechSelflearning(device, this); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[14])->setRemoteMinMax(1,1048575); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[14])->setUnitMinMax(1,4); foreach( DeviceSetting *s, d->deviceSettings ) { connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&)), s, SLOT(setValue(const QString&, const QString&))); diff --git a/telldus-gui/TelldusGui/images/devices/ecosavers.png b/telldus-gui/TelldusGui/images/devices/ecosavers.png new file mode 100644 index 0000000000000000000000000000000000000000..502466059bf38451286906264e9c3b882b44d3e9 GIT binary patch literal 19835 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 BQA+>- literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/ecosavers.png b/telldus-gui/TelldusGui/images/vendors/ecosavers.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d44cbd643090d82f70b938e88f7e8177ce1cdb GIT binary patch literal 7923 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 literal 0 HcmV?d00001 From 5e5df3f656df2eca11536a5aa9c862e1c0940703 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 25 Feb 2011 15:20:01 +0000 Subject: [PATCH 1616/2215] Added class DeviceSettingSelflearning. DeviceSettingArctechSelflearning should subclass this class --- telldus-gui/TelldusGui/CMakeLists.txt | 2 + .../TelldusGui/devicesettingselflearning.cpp | 80 +++++++++++++++++++ .../TelldusGui/devicesettingselflearning.h | 45 +++++++++++ 3 files changed, 127 insertions(+) create mode 100644 telldus-gui/TelldusGui/devicesettingselflearning.cpp create mode 100644 telldus-gui/TelldusGui/devicesettingselflearning.h diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index eb1f1229..21110926 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -24,6 +24,7 @@ SET( telldus-gui_SRCS devicesettingnexabell.cpp devicesettingrisingsun.cpp devicesettingsartano.cpp + devicesettingselflearning.cpp devicesettingunitcode.cpp devicesettingupm.cpp devicesetting.cpp @@ -51,6 +52,7 @@ SET( telldus-gui_MOC_HDRS devicesettingnexabell.h devicesettingrisingsun.h devicesettingsartano.h + devicesettingselflearning.h devicesettingunitcode.h devicesettingupm.h devicesetting.h diff --git a/telldus-gui/TelldusGui/devicesettingselflearning.cpp b/telldus-gui/TelldusGui/devicesettingselflearning.cpp new file mode 100644 index 00000000..9ae1c4a0 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingselflearning.cpp @@ -0,0 +1,80 @@ +// +// C++ Implementation: devicesettingselflearning +// +// Description: +// +// +// Author: Micke Prag , (C) 2011 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#include "devicesettingselflearning.h" +#include "device.h" +#include +#include +#include +#include +#include + +DeviceSettingSelflearning::DeviceSettingSelflearning(Device *device, QWidget *parent) + : DeviceSetting(device, parent) +{ + QGridLayout *gridLayout = new QGridLayout(this); + gridLayout->setSpacing(6); + gridLayout->setMargin(9); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + + gridLayout->addItem( new QSpacerItem(20, 109, QSizePolicy::Minimum, QSizePolicy::Expanding), 0, 0 ); + + QLabel *labelRemotecodeTitle = new QLabel(this); + labelRemotecodeTitle->setObjectName(QString::fromUtf8("labelRemotecodeTitle")); + labelRemotecodeTitle->setAlignment(Qt::AlignCenter); + labelRemotecodeTitle->setText( tr("Remote code") ); + gridLayout->addWidget(labelRemotecodeTitle, 1, 0); + + spinRemotecode = new QSpinBox(this); + spinRemotecode->setObjectName(QString::fromUtf8("unitcode")); + spinRemotecode->setMinimum(1); + spinRemotecode->setMaximum(67108863); + gridLayout->addWidget(spinRemotecode, 2, 0); + + gridLayout->addItem( new QSpacerItem(20, 109, QSizePolicy::Minimum, QSizePolicy::Expanding), 3, 0 ); + + spinRemotecode->setValue( device->parameter("house", "1").toInt() ); + + QPushButton *randomButton = new QPushButton( tr("Randomize"), this); + connect(randomButton, SIGNAL(clicked()), this, SLOT(randomizeCode())); + gridLayout->addWidget( randomButton, 3, 0 ); + + //Seed the random number generator at widget creation + srand( (unsigned int)time( NULL ) ); + +} + + +DeviceSettingSelflearning::~DeviceSettingSelflearning() +{ +} + +void DeviceSettingSelflearning::saveParameters() { + p_device->setParameter( "house", QString::number(spinRemotecode->value()) ); +} + +void DeviceSettingSelflearning::setValue( const QString &name, const QString &value ) { + if (name == "house") { + spinRemotecode->setValue(value.toInt()); + } +} + + +void DeviceSettingSelflearning::setRemoteMinMax(int min, int max) { + spinRemotecode->setMinimum(min); + spinRemotecode->setMaximum(max); +} + +void DeviceSettingSelflearning::randomizeCode() { + int randomNumber = rand() % spinRemotecode->maximum() + spinRemotecode->minimum(); //Generate ranom number between min and max + + spinRemotecode->setValue(randomNumber); +} diff --git a/telldus-gui/TelldusGui/devicesettingselflearning.h b/telldus-gui/TelldusGui/devicesettingselflearning.h new file mode 100644 index 00000000..8ee4e540 --- /dev/null +++ b/telldus-gui/TelldusGui/devicesettingselflearning.h @@ -0,0 +1,45 @@ +// +// C++ Interface: devicesettingnexa +// +// Description: +// +// +// Author: Fredrik Jacobsson , (C) 2009 +// +// Copyright: See COPYING file that comes with this distribution +// +// +#ifndef DEVICESETTINGSELFLEARNING_H +#define DEVICESETTINGSELFLEARNING_H + +#include "devicesetting.h" + +class QGridLayout; +class QSpinBox; +class QLabel; + +/** + @author Micke Prag +*/ +class DeviceSettingSelflearning : public DeviceSetting +{ +Q_OBJECT +public: + DeviceSettingSelflearning(Device *device, QWidget *parent = 0); + + virtual ~DeviceSettingSelflearning(); + + virtual void setRemoteMinMax(int min, int max); + +public slots: + virtual void saveParameters(); + virtual void setValue( const QString &name, const QString &value ); + +protected slots: + void randomizeCode(); + +protected: + QSpinBox *spinRemotecode; +}; + +#endif From 340b8eef7f8bf35a420a5bf1adc6571e04eac838 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 25 Feb 2011 15:20:46 +0000 Subject: [PATCH 1617/2215] Added Kingpin KP100 --- telldus-gui/TelldusGui/data/telldus/devices.xml | 4 ++-- .../TelldusGui/data/telldus/resources.qrc | 2 ++ telldus-gui/TelldusGui/editdevicedialog.cpp | 4 ++++ telldus-gui/TelldusGui/images/devices/kp100.png | Bin 0 -> 6989 bytes .../TelldusGui/images/vendors/kingpin.png | Bin 0 -> 5051 bytes 5 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/kp100.png create mode 100644 telldus-gui/TelldusGui/images/vendors/kingpin.png diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index c4ca2b5f..cff993a1 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -121,8 +121,8 @@ Projector screen - - Projector screen + + KP100 diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index 095867a1..57c67880 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -16,6 +16,7 @@ ../../images/devices/gao_sl.png ../../images/devices/hq_cs.png ../../images/devices/koppla.png + ../../images/devices/kp100.png ../../images/devices/otio.png ../../images/devices/projectorscreen.png ../../images/devices/risingsun_cs.png @@ -38,6 +39,7 @@ ../../images/vendors/ikea.png ../../images/vendors/intertechno.png ../../images/vendors/kappa.png + ../../images/vendors/kingpin.png ../../images/vendors/kjelloco.png ../../images/vendors/klikaanklikuit.png ../../images/vendors/nexa.png diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 7eddfa76..1c269b56 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -12,6 +12,7 @@ #include "devicesettingnexabell.h" #include "devicesettingrisingsun.h" #include "devicesettingsartano.h" +#include "devicesettingselflearning.h" #include "devicesettingunitcode.h" #include "devicesettingupm.h" @@ -163,6 +164,9 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f d->deviceSettings[14] = new DeviceSettingArctechSelflearning(device, this); ((DeviceSettingArctechSelflearning *)d->deviceSettings[14])->setRemoteMinMax(1,1048575); ((DeviceSettingArctechSelflearning *)d->deviceSettings[14])->setUnitMinMax(1,4); + //Kingpin + d->deviceSettings[15] = new DeviceSettingSelflearning(device, this); + ((DeviceSettingSelflearning *)d->deviceSettings[15])->setRemoteMinMax(1,1048575); foreach( DeviceSetting *s, d->deviceSettings ) { connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&)), s, SLOT(setValue(const QString&, const QString&))); diff --git a/telldus-gui/TelldusGui/images/devices/kp100.png b/telldus-gui/TelldusGui/images/devices/kp100.png new file mode 100644 index 0000000000000000000000000000000000000000..c8a420e87c1c37b6bcfb9012cd67c8e20cae6f48 GIT binary patch literal 6989 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/kingpin.png b/telldus-gui/TelldusGui/images/vendors/kingpin.png new file mode 100644 index 0000000000000000000000000000000000000000..fca5d13d49e14a8d2ea3ecc94867e24f148f4906 GIT binary patch literal 5051 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%0D8;5^KBKyH6k|)R=ju9=KuaP(plAkk1Wk%O%Ul1 R{r^6jDa)(L6}>R|^gmN%*_i+U literal 0 HcmV?d00001 From f82768b7b6586f76a743300236631ac35d5e0b95 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 25 Feb 2011 16:19:33 +0000 Subject: [PATCH 1618/2215] Support for tdUp(), tdDown() and tdStop() in systray --- telldus-gui/Plugins/Devices/__init__.js | 28 +++++++++++++++++-- telldus-gui/Plugins/Devices/devicesplugin.cpp | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/Devices/__init__.js b/telldus-gui/Plugins/Devices/__init__.js index 25641f4b..e217c508 100644 --- a/telldus-gui/Plugins/Devices/__init__.js +++ b/telldus-gui/Plugins/Devices/__init__.js @@ -4,7 +4,10 @@ var devices = new Array(); var methodsSupported = com.telldus.core.TELLSTICK_TURNON | com.telldus.core.TELLSTICK_TURNOFF | com.telldus.core.TELLSTICK_BELL - | com.telldus.core.TELLSTICK_DIM; + | com.telldus.core.TELLSTICK_DIM + | com.telldus.core.TELLSTICK_UP + | com.telldus.core.TELLSTICK_DOWN + | com.telldus.core.TELLSTICK_STOP; __postInit__ = function() { com.telldus.core.deviceChange.connect(deviceChange); @@ -12,6 +15,14 @@ __postInit__ = function() { application.addWidget("devices.default", ":/images/devices.png", com.telldus.gui); } +function down() { + com.telldus.core.down( this.id ); +} + +function stop() { + com.telldus.core.stop( this.id ); +} + function turnOn() { com.telldus.core.turnOn( this.id ); } @@ -20,6 +31,10 @@ function turnOff() { com.telldus.core.turnOff( this.id ); } +function up() { + com.telldus.core.up( this.id ); +} + function dim() { com.telldus.core.dim( this.id, this.value ); } @@ -55,7 +70,7 @@ function deviceChange( deviceId, eventType ) { addMethodsSubmenu(obj); return; } - + var index = -1; //Find the device for (var i=0; i < devices.length; ++i) { @@ -88,6 +103,9 @@ function addMethodsSubmenu( obj ) { if (methods & com.telldus.core.TELLSTICK_TURNON) { com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( qsTr("On"), obj.menuId )).triggered.connect( obj, turnOn ); } + if (methods & com.telldus.core.TELLSTICK_UP) { + com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( qsTr("Up"), obj.menuId )).triggered.connect( obj, up ); + } if (methods & com.telldus.core.TELLSTICK_DIM) { com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( "90%", obj.menuId )).triggered.connect( {id: obj.id, value: 230}, dim ); com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( "80%", obj.menuId )).triggered.connect( {id: obj.id, value: 204}, dim ); @@ -99,9 +117,15 @@ function addMethodsSubmenu( obj ) { com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( "20%", obj.menuId )).triggered.connect( {id: obj.id, value: 51}, dim ); com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( "10%", obj.menuId )).triggered.connect( {id: obj.id, value: 25}, dim ); } + if (methods & com.telldus.core.TELLSTICK_STOP) { + com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( qsTr("Stop"), obj.menuId )).triggered.connect( obj, stop ); + } if (methods & com.telldus.core.TELLSTICK_TURNOFF) { com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( qsTr("Off"), obj.menuId )).triggered.connect( obj, turnOff ); } + if (methods & com.telldus.core.TELLSTICK_DOWN) { + com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( qsTr("Down"), obj.menuId )).triggered.connect( obj, down ); + } if (methods & com.telldus.core.TELLSTICK_BELL) { com.telldus.systray.menuItem(com.telldus.systray.addMenuItem( qsTr("Bell"), obj.menuId )).triggered.connect( obj, bell ); } diff --git a/telldus-gui/Plugins/Devices/devicesplugin.cpp b/telldus-gui/Plugins/Devices/devicesplugin.cpp index a18cbcdf..417cc48e 100644 --- a/telldus-gui/Plugins/Devices/devicesplugin.cpp +++ b/telldus-gui/Plugins/Devices/devicesplugin.cpp @@ -15,7 +15,7 @@ DevicesPlugin::~DevicesPlugin() { } void DevicesPlugin::initialize ( const QString & key, QScriptEngine * engine ) { - if (key == "com.telldus.gui") { + if (key == "com.telldus.gui") { QWidget *deviceWidget = tdDeviceWidget(0); connect(deviceWidget, SIGNAL(showMessage(const QString &, const QString &, const QString &)), qApp, SIGNAL(showMessage(const QString &, const QString &, const QString &))); connect(deviceWidget, SIGNAL(eventTriggered(const QString &, const QString &)), qApp, SLOT(eventTriggered(const QString &, const QString &))); From fc0f379af817475a30a9d50e8071ebe1b6e6c48c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 25 Feb 2011 16:33:55 +0000 Subject: [PATCH 1619/2215] Implemented tdStop() in our devicewidget --- telldus-gui/TelldusGui/devicemodel.cpp | 4 +++- telldus-gui/TelldusGui/methodwidget.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index 8010a5dc..3b68b568 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -13,7 +13,7 @@ inline double round(double x) { } #endif -const int SUPPORTED_METHODS = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_UP | TELLSTICK_DOWN; +const int SUPPORTED_METHODS = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; DeviceModel::DeviceModel(QObject *parent) @@ -69,6 +69,8 @@ QVariant DeviceModel::data(const QModelIndex &index, int role) const { return tr("up"); case TELLSTICK_DOWN: return tr("down"); + case TELLSTICK_STOP: + return tr("stopped"); case TELLSTICK_DIM: int value = (int)round(device->lastSentValue().toFloat()/255*100); return tr("%1%").arg(value); diff --git a/telldus-gui/TelldusGui/methodwidget.cpp b/telldus-gui/TelldusGui/methodwidget.cpp index 3b0c7186..8bf363d6 100644 --- a/telldus-gui/TelldusGui/methodwidget.cpp +++ b/telldus-gui/TelldusGui/methodwidget.cpp @@ -12,7 +12,7 @@ class MethodWidget::PrivateData { public: Device *device; QToolButton *turnOff, *turnOn, *bell, *learn, - *dim25, *dim50, *dim75, + *dim25, *dim50, *dim75, *execute, *up, *down, *stop; }; @@ -37,7 +37,7 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); layout->setSpacing(0); - + d->turnOff->setIcon( QIcon(":/images/state_2.png") ); d->turnOff->setVisible( false ); layout->addWidget( d->turnOff ); @@ -58,7 +58,7 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) d->turnOn->setIcon( QIcon(":/images/state_1.png") ); d->turnOn->setVisible( false ); layout->addWidget( d->turnOn ); - + d->bell->setIcon( QIcon(":/images/bell.png") ); d->bell->setVisible( false ); layout->addWidget( d->bell ); @@ -78,7 +78,7 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) d->stop->setIcon( QIcon(":/images/state_2.png") ); //TODO d->stop->setVisible( false ); layout->addWidget( d->stop ); - + layout->addStretch(); d->learn->setText( tr("Learn") ); @@ -96,7 +96,7 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) connect(d->execute, SIGNAL(clicked()), device, SLOT(execute())); connect(d->up, SIGNAL(clicked()), device, SLOT(up())); connect(d->down, SIGNAL(clicked()), device, SLOT(down())); - connect(d->stop, SIGNAL(clicked()), device, SLOT(turnOff())); + connect(d->stop, SIGNAL(clicked()), device, SLOT(stop())); updateMethods(device->methods()); From 8aeebf4de506a6fc52e647b07ae7efb49bbe7861 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 28 Feb 2011 12:50:46 +0000 Subject: [PATCH 1620/2215] New icon --- .../images/TelldusCenter_logo.ico | Bin 28838 -> 82726 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/telldus-gui/TelldusCenter/images/TelldusCenter_logo.ico b/telldus-gui/TelldusCenter/images/TelldusCenter_logo.ico index ed2a73f648e43b5cdf4207df99bf28a95b6536a4..e9cfae84d16ad04c299578491141a47edfe9f3e8 100644 GIT binary patch literal 82726 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
sV8nF(Dp}RxZTH-&~ zhJ7Q(o^^MpZf@=HckHUm(|KdR4i6hOVjU1ecVKC;{der9%Ucfo7Xg18HCi1ILw8`w zK3%gKwf|4B|M$GRV|QKNih0=u?~nKvDD-L#7mX*|C-?Wlb~msJ*CIrV`%r~ zc`Jec65wy6MymtjPb|&gZx6gRBK}V({F|xq-?Q#RyGQK8|1+d6nQfy+tOH^QEW?5S zbJ+i%_5T?V>$-+L&l>(uU`pIy1o6zePRzA3 zpyA&P&t4$@-+%mWzg?^R5np4DjT*5IcC88!Vo6MiEr{o)APs*zT(cbT*;AnBo7meo zf8{@Z^H$1|IoC47eGm`P%SMe*2gHsT5=&xAY(cE!#9FKShWN8xc$R&@rcIl?5IE5> zYS-#O8}^M5d)8TE7dXKol2{T`VhbY1THR+E(D2vV0Id)3?C0;k-Z6hoprkMJ#+n(} z02?(L9i)eQEBrri@p^~SwqLXTrft85zhN8j+*2qoPdw4|Mc9B%h3i5jbt%gL+5#Ij zd>sI*0$>&}!Ew_QO`E@n66D?dx%&o+o#%4pR9}51%JC zYPdRJ{Ula#p|el?@!x;*8Zcy=&$@5g?re#300qiF}2l^G$L3*v?7tJXyTE7r` zu=oReKN~e59S{>@LyQctr@x;VYJGmK-=|@2de-a!+X&hKenj{SMVKA$P(ruU|0fZsEn zm+kEBnm1`;|Kb<_c%x(Rq>)=v!~IJN*Dpf3TP!>mqWtO4ytYyO=s>SyP3OcQc=E{2 zpa0{{j>N{^-i}z&=Cj@tJ9FbbQ_KzTHT-!tYzsJcRDDU>0`hw0KYsgGo6p|wJF-W+ zxwA$N2%kM_fX+tsuLJ6uI;ZY|!JEK>bGFZ-pU*naz8ObT*|oVcz_i$h zWVw2g^9lA%?3&ZofSv|D2YSAg_}oTys{>89JUm-x~;+0q9dUh!u5Wf271@ zB=^bxpmJ7cH?j-thXXc00J9B%xpY_$SA~NiU~AYJ_M^JNX*4irv=Ur@r1~Fw!g(yP zV014yjQJQ#sB;T{qCSlW=8aW`>jc1ULMJ$mQ-$Y*u2^i;1q;W0ie=R2CC1(1W!w{i zrhvOi54es04Bis~-$}qy(~sac8St2>f>81&z>LZ#s=?K?4+71}7mH3K_QQ(n7+lZit!D8;i_Gz<0VnR?Ykzu2TnL!|Wc2wbp>kw2=s$^`8j0(S?hp z5rS-Zh_(L`QF8`h(X8?Cu{A`H-7qY*F~jn?gWzgo2~WETSY&ICa7P0~ISqr4gAszA zenP^c|AxQA3@n*96JCzf;O$_GrSs+>aQ;+;FEB&gqET43U^bS_cfu-H6ZpH>Ak29- zT%8vp&V3@1J$^)@$9Qa9Y6h>x^Wp90ihw1Kh+R4pE8ScW<~|ou?oJ3^;))1&7bNXg1nZ)r zkQEbvP0^7^q4bXE71+1d4;xpGJ82_|Qdc1}bqkKC$0BE2G77h^$I0!9 zIJ|ue3b$>+)yz2jymJR~Gm}xiYXb^*C*W{qI?n9cio9KED9PH4(mm^OVRt%m_wGT( z-fgJNPD0_n3{>w+!Nu%U-{9NLd_hY#S_qdQT1bT4imC!OOtxOO}nzvgA*M*aa*<{!cBQ#q(C z*pG|($5B&o67_`#ajWn!E}S`yJ7;ro`|NR4o-M%5bNRS;HXpwgpF~qhKJJ{)$IY^0 z)LkgTz4FuerMw)!Un;`gE2XHrQjYr-WqA0@CETm3z@zF4Jglig^RLyoce@II)>h$P zb+_=Op%%{?f5Vfe``kRxDl47es>q^A=ie%{sBvjbaZaT0))Qh(iPT$1l>m@{6(l7p z-$_!Y2VLK}NOj)zUUB<;01?!V@Hg0i9*LFlvh9ip{%s@Fh-FK@+kTlKHORt*L+doaDue zKQBz})>X2OODn6+_DC+ed$*Ak`p_<@^q^YhP=6qlrS%>Axb2X8kME+4<8<;7vS{wseqJ2PRL-*WnW*7fYA%4qqPni~!$9P2Mi1F=Zt5uC=F5kwFe{pe1oJ_SOoLpMjBL3iQ z=Dq~}v%4}^K=~(+wa2cD{5O*s|H`W7j#0bwi&^}O&z3}V0AE?vD?X14zXX2EGuZ%G z1}D?y=f}UX+E@la`73kxsEkwj#e94pneNH?EK#65CUlbm{KLu;I+UCh$z6W#`ZpHp zOINC@el^8?-R@Jx4FBxe5@(t2$!bgHl_!SA=iQfye@n|vDG24SJl5v0@bmGrB^zLA z<*#PB)9uH{FD{v;7++bTSo_Lf|CW|V#=pm=j zc7e5b%)#4_rN^HfzKtOKgx^@*IKQiGb4HFd{0W(bzxV)8w)$mxORv!M^Ze;YbpN%q zG)eidFBtvIf0_V{<=UI#7?nZc=i~3tl&f#MKxLwn*QPu!0OI?4IQ)`S3Cs4AW1PHV_MGQNpxFP%d!-EL2}U31|J^vLI+porrvGLZ zeuiIM5+PUrvVyOioV?=q)igi(Q|$kv`<{{}!y<+5v+;M=Ub2o$kC_$7U4A~kvt0d4 z3nn@_g>E`hbN?}W`aNlBdED}-p+H|U{I<#5+$V^CrH)*4Mr`&e75HClDp&uqf%QO9psQ!xARn%-PdH{&psu@FP_nH{651hSr5Fty+gfSCrLS|Y?WES z);$9J>I=ql&9m?yFD~c%Uz}?ory%yGt(3Cnu!)wlot&&K$LLF$s~D#hTxYYMF#K_H z?kf+Y@SiFd;FqShh4IqzJ`{3&eSJ+S-!(P+=&UWc#^Cw*jdw2?%i(KU_;1cWMQdMf z{FVC1E4&o>WtDxD!gEfBma2o5{KVg{CcYzqFLY&;R?vuhu7o&>wN$3*vt{ zq|X z5I^5uk&e(z=aocLP0hZnnGY}Yzwz$%0v|O^IeSfG|CHmE6+-;{Z8~4b>2$1s(5D@4 ze*B15;9~z7e3Yg!AQjT41SG{BKWDX zH26683BR~_H&20*3`Sd7a$H%{Z1v42e{$#&_>Bz&uc&2B9siVU7Ja_|#rZz3<35cJ zf>zTpaNc^2wn2R7#r`)nHC#BR7+%vZA)}DNbNJ=?ujfARyYbUJw;sOv`1uR&1&qLb ze*7Q(-cVDf7+y!yn8rTmJ~#Yd(|sN5PbA<@qOFUUu(GV@l@Q zz-Q>>eCGP8lFH(=nptvoA>Vth1No_X;!4FSZH1y3pWx}r=cET4Yw{GCX&TU-FNi+j zmlvO$p{7W${W6949Qv`W^;SABf4zHe$uR(KHpo^YJTBM!Za49077lPV{)z zwE2%=5*q65G0(zSPDQFf(tCdVE01p;Af?iw48vzTUoWpYHj{?&^x8Alw9gS-d+z#I zR8$sbn6_v1l6pPfB#TLth8Y_(XziCM3aXrsUEmKr{`e#K{q~yen{gWAD;chbfJnv=6^7F&sQ+yH}{I&Y+G$W;)UxH=rsHa_eZp?{x{dqz`xAigot}k zS(qKw?uZfhLUB-Ev6RPiW^cf`_rHQ3koW5hUOD=DdP81cc)Ssb*X7`I)=l8Oew!Vz zVY{U*Za z;0L^N8=PVX0xnk79^iafgf8;G@_0t){)vr0dgvAABs;unJCb^@ zevt@#$by~h9faijA3pqrV;Qm2Uc>uWMIXRCpOJL^5!(R?;Dzr$8>_Du<)ryfcsuYc zR@&MFOoDb+J$fRs|EEp}u74FdpWyboBTw>L$fel=cEE@kK|8NMdctkO$$MGr31#bZ4@ULGumX_c?;`PzKRU|{EyG9?Xr_DdN1*c6w zi$Emt>Gd0hJ~KI(2A-lu-k@yA9ADc1x3T}`k3S)Lq#Zf`22hGkt=q$IB;N}%lcU{f z*eh=0jY`|WZ)m7tk&pJ6I^=DjfBWsr@M#}>t$>gIHbT$EO))-=z9w?LtRN?CeYnTe z5pTzL)&U#o>(7mTF?e!x_`JUh{Rf4@;j{amd;9hHF=12Kuaq6jNh5F%TVv{@Lc_nQ z(1!i~g?;xe*n+b?c)^j(^z{TzuD@My^1+7v{)E1Gt`}^o3! z`+OTdb)e1Rt>fOSw0^*U&+%`4e`A06aP~iF?;HO;c0lkic<(C$!v6q#-}vw83JBeQ zPh(I5{(am8Qt(%LGS1zP`-&IkTmI&Ub|JOMnEu2+@K-;%CZ%9GA_k+_7)&+L#7}*)~M-sQ#NUEp9Ze%w) zcY_`Aj4`e;yHVXSZ**78AKeAcKT`XnyJHcZoqp^Bcb5OLJEgnPSqTfqbiv}WR5zvv zoW}OR65=6qr(-D{K6JQ@>q*>X-Rb-hycs{)I5pxaBR%3JTQt5W9Dh>7;tAb}v#clF zje21I_)p<7;S+e7bcMU|NANIFf{&>ZJc*lZzVYYqne;KjrgTBjzUoBlag%}}936~5E@B5r0cEVud` z!B*OcvsOj)%>SUX8X{+Ez}rd>K{NVd{p?SWK!?Z7L0B=XA3|sKN1)Bu2%oKwuvuRt zWEKx0vv~-fJrIHRgAh9BdxY2%-`N~P#4H$&SZ6vGj>0;R>4^2RCjKxZr21PTC2$6I z22V#ym@TrxW+6Sw0ehpJk-2Iaa*5OHzy=Q--QbVx#9*9A^v98e2prrTi2UT0#M2dx z@*S&@m$?a7a<>p?)(%`fPFz_>_JZEE6K~dT{BnF3YL6el_58!QeEJAVPM^c=(lhv- zj{34fR1yExrSlhYpVD{BiqKGAh+7xW;~^dQE}h4NOJ(@u>J|L!W(}U!|AxQ*_#Lf} zT13P7L*g|f&`U}{Kbh~>s_lz~Vx~t-b4jnpT#E6eR@lD?5rt7{b zT$ge`{1mZ%ce1bU533U$ei$)gl)-|u9no%m`!3%W-gnffQAS4Qi_QD?HCnMV#=wYV z^5n^18%zt@xGRQBQ`TW+e0tXAU`jEuwQ^5NT^llgw3V$u99;i>|h9)Et_Y*q+=uN&8;(OPPL~wm2op#4^zh6 zA3D+8%I9UAXULx~88_o1I_A^dsEDJH&5tg`(a5+O8BZgdAB9|v&SO-ubbKcfXQRjX zE^rz93CG#!IiVYTjrg363usIrTFvr+ISel)fCt<7zA7gtYh^9%ecSHrJHmdUQ4WFT`6DZ{$=hnos}9@jf!X zM~>@p`WIMY`3)9Y3=(lZuCVS6pXvXH<9ZCC`I7NHdQATo{xiNtn6)l~i1#sq=1k97 zgK4h(7M^qw{APWRFx&4q{>LDC;Ke)kN95e0ST&FA=8i!qk!CJmFbpyD5cG32L5SmI z;(Z*BH8hVdcO8d#w=sxyHNt8)V{GvtyQLP`OvISc9`;D~os3wY*@#`{f-U~jkr*%w zp+4T&9N5Y^~KkSLM!=7k2 zWX8H8JJucPt9+3Yw}{Gvus_a|xEOu0XMHG+Z45x}rZ61d7=?pLQP{P41G19VqIhd0 z_9SmYMshMrQ&-|>%6jCd#vy-eBF?78qF~2z>`Y5XA1%N=Vf4i7G$MI-SnHdmCOzTy&^u3kmcwQ@YZ zUWU8Zui(iq6}VSjPP~g(@u=zsJ%1|kfcO_%Ze8Oz7$4ofiO0YF%JDD$d8ZD~8|(3} z#=H3Uy#};CypMl3|G~`!v_R|9rch;TtI|uPooXee*4`h#l63FXozqjIzAzIyD{-d1 znS89|xyDWDV@ga7iCC;e=ed3%wsaPVQq1!g&(?J5-CN23=EIHMsXpjTxgX_w_f}^z z^2)Q8mWOsq>L16~-ic6B@7+7>=$U0*xH|SRE%#Z=qbFWU>Ld5o-CCxkuKvyXqeth9 zs?|rXxbfsk#RPRF-`cv16FyZ}pO~JPJ(;WT$3%TvXiAFfr=N~KTvxYIo$~Jc&!qLE zgh;*_@y(a&Uv6ort94@a@n_Dg{8Us)iEpT|-=@a8JL_1r?VdA77fRQwt2-Td*l=er zuOF}9mr+G$(s+Dx{x6IBO0wjTA-jG&UcZG$&J_7kf=Pc8-rU_y&z?Pe*syJK zzyAIE8Eh{q+QqM-Iwtcf|9aMP_jm}epP}KPej6^GIlHumQBpEa}r{;Kape@xJ z_V2gm(#1<_S&|b2lJ9MoEVAVd8brxKgA%S@yp(3h(wy*>1`Zr(U`UGn?6%*$cx{i} zAOnH9T!myS6)18X}WPZez9Dw1<5$qjKZH&qP^{? zmgVKd&eg%rblfO&xe7snIVTEh`Bk%K@z3&~t@1^ZC3FKyW@Xdt{%y5xQ>gM5pp*x6 z2@>tPxM|_7elV;&!n{S;Y@ITajvzWj>lC&@6pCP-GH;}KZNk^5A1fYlJyNkg(t@gv}if-+9JZyI=^n zmI$6V2`d(i<@lo)&YOibi-sa>fe}_NG=TSfbGSQNBf!ZL8(c@g-`N`8E_U4dBFxnS z3GU)p2KgI$t2>R-WW^kl$9JObZX)TT8sFiXiGSDCMDs>)^#{S>y^D*HzR*rG_6rq z<6LS2vQkrVC~XtUx5wacdIIuyY{IEst8r*Y8nqrL65+?_Z>Ynz+I6MdOm+oYqG)-^YdGki7T4UcQ2RXx2v>&Ca&lQ*BMuIC4Q^=1%KRNd*%vm z&2sP8TWGGO^-A3>{JZ`ptyym4>0Mg0&|2lsrY3GC;AXPc){b)p3k~cHPG`-?5Tk_wC~pQf0uNV=@1tki7v9dM7F0C+gZ=foi$WDca|*F zU?QO;o0q6k?bg%v$nD!d+jSQ*`1Ks)m35KCvb#Xd*l$N>X69B6Nd!>~DjJ)fymSOV8X7j6nf-FEmMhXw5sAi}lm|llgl=51LDXfkuiq}z>F>6qpy0&W zAYoqmJZI%E0{f?toV}VwMlIPl1@K!_Q8DnPALE`lyFi$iwx6;zrSa)g`i=JEW;;$p zBeay+|7t1Jn;b#*1qJ59y!5%hv(KJJX8s_RtKh@e)*jUo>XG~8f5AXup3Yig(J*rM z*>dvQwc>4~)u>cOE2^TN@SDN~N-E@jNx_NpTcxbT_F5WaW;y$Wg}Du7=2~j5g|*DS z!c=H)5OI*~DSQ$(Qb`pp1EVnpDjJ-*>HgX#vTs_;wMIoM(>52B6cm(L2@9lbxr_$w zo%p3{Lo@C)H8FS-p?ZJcz2{2`O0oyGi7#$Yt#2xslYM=-&|GCwV!?TWU;YZ_DkeYE zuBoZ1zWzX8&KuS;2VYR)AZ$>KCX>=ovAW#M%$u4nTZ+&Ko_W8cuatIQS<%u^8JO^} znS*b-zDz|>Pw%kf#^MSEP%P9I~L2a7%weUZ3yM^6B%)a?yZQ(L4Z2^L| z*0MuoWPkpkiLgasjp(2A`!33P@)w(bIQxgy8P@7r!b)}PtczrSp5TQ=a_7E|JNfeu z^S=6Iw5eEC-87ZV%g&eW7$|2ZDiGLH_sM#lZC??%w${MJi#J#Urx%FZ6xb0jm_W$> z!JjP;8gCYFi<&=FOIuj3uiH27@(pHxVTHE1R8%cWIL7DZ=k82d>1HudS65W3udBb7 z%$fZT6M1vmLGwjlf6h`L&xQ6DLv^)vg@tt1)mwX&%x{!kJZi2bQ7)I%A2)8`Kz&^u z-GTc0!b<&tS|;18nfZ;2rx$1q6jcZnB+oiJk~uD|t7Ubdww|*;9Vpo=k*36N4#{PS z93}O2bpzP*huN0~>JOBz<>y}VU#_}Z=G$ok;>?T4{3WUis&uu-uBl}c5VJ1~9N31r zqCQcXj`rB_iid3eWBos{Oh>N`MfqYqJsoX5hvZr|gOGV`eQB!QE13@_OClQ48SAv> zO7mlG0wVM3!dMfX!SXPIlEIQPcB)gz##6N|Gz0MGpQhT&8H)$&N$SX?xqp-5J_g%w zx<{*z7f<>3FPr^pFYk}A)Eg|;d0A@kLh=2}<`1&o7iB$M?`1ZUb;HH?KXw03b>X%s zTk85qNget0NRfOiw0}&-#e3FySq~okt*EyB#9+si`w!^$zgE0wTa=f*>F~kr+em3R zhNYyW#IFqVa From a69f11df8fc0c1d6b039dd4bf9860e8cdde6475d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Wed, 2 Mar 2011 08:42:40 +0000 Subject: [PATCH 1621/2215] Group methods are now updated when devices are added/removed, when a group has been edited. Note: Group methods will not be updated if a child device has its type changed or if a child group has its methods changed. --- telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp | 2 +- telldus-gui/Plugins/TelldusCore/__init__.js | 2 +- telldus-gui/TelldusGui/device.cpp | 3 +++ telldus-gui/TelldusGui/methodwidget.cpp | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp b/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp index a3596341..5ed58a5e 100644 --- a/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp +++ b/telldus-gui/Plugins/QML/scriptfunctionwrapper.cpp @@ -27,7 +27,7 @@ QScriptValue ScriptFunctionWrapper::call() { } QScriptValue ScriptFunctionWrapper::callWith(const QScriptValue &val) { - qDebug() << "Call called" << d->name; + //qDebug() << "Call called" << d->name; QScriptEngine *eng = val.engine(); if (!eng) { qDebug() << "We cannot access the script-engine, fail!"; diff --git a/telldus-gui/Plugins/TelldusCore/__init__.js b/telldus-gui/Plugins/TelldusCore/__init__.js index fcbcd38b..410b197a 100644 --- a/telldus-gui/Plugins/TelldusCore/__init__.js +++ b/telldus-gui/Plugins/TelldusCore/__init__.js @@ -22,7 +22,7 @@ __postInit__ = function() { } function deviceChangeEvent( deviceId, eventType ) { - print("DeviceChangeEvent", deviceId, eventType); + //print("DeviceChangeEvent", deviceId, eventType); if (eventType == com.telldus.core.TELLSTICK_DEVICE_ADDED) { devices.push(new Device(com.telldus.core.getDeviceId(i))); return; diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 3b2a6d89..92633ff6 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -81,6 +81,9 @@ QString &Device::name() const { } void Device::setParameter( const QString &name, const QString &value ) { + if(name == "devices"){ + d->protocolChanged = true; + } d->settings[name] = value; } diff --git a/telldus-gui/TelldusGui/methodwidget.cpp b/telldus-gui/TelldusGui/methodwidget.cpp index 8bf363d6..ac30ac29 100644 --- a/telldus-gui/TelldusGui/methodwidget.cpp +++ b/telldus-gui/TelldusGui/methodwidget.cpp @@ -96,7 +96,7 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) connect(d->execute, SIGNAL(clicked()), device, SLOT(execute())); connect(d->up, SIGNAL(clicked()), device, SLOT(up())); connect(d->down, SIGNAL(clicked()), device, SLOT(down())); - connect(d->stop, SIGNAL(clicked()), device, SLOT(stop())); + //TODO connect(d->stop, SIGNAL(clicked()), device, SLOT(stop())); updateMethods(device->methods()); From e4b90eff4fb8340db48a7acfcc8932a5654b9a11 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 2 Mar 2011 09:32:48 +0000 Subject: [PATCH 1622/2215] Methods should be updated from our new signal TELLSTICK_CHANGE_METHOD --- telldus-gui/TelldusGui/device.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 92633ff6..9121cbe3 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -223,8 +223,7 @@ void Device::deviceChangedSlot(int deviceId, int eventId, int changeType) { break; } - case TELLSTICK_CHANGE_PROTOCOL: - case TELLSTICK_CHANGE_MODEL: + case TELLSTICK_CHANGE_METHOD: int methods = tdMethods(d->id, d->supportedMethods); if (methods != d->methods) { d->methods = methods; From 70194457a9d6a5416b186a97edb90dfc6ecc12a5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 14:15:40 +0000 Subject: [PATCH 1623/2215] Added functions DeviceModel::haveError() and DeviceModel::errorString() --- telldus-gui/TelldusGui/devicemodel.cpp | 16 ++++++++++++++++ telldus-gui/TelldusGui/devicemodel.h | 8 ++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusGui/devicemodel.cpp b/telldus-gui/TelldusGui/devicemodel.cpp index 3b68b568..aea4b4f6 100644 --- a/telldus-gui/TelldusGui/devicemodel.cpp +++ b/telldus-gui/TelldusGui/devicemodel.cpp @@ -21,6 +21,10 @@ DeviceModel::DeviceModel(QObject *parent) { connect(this, SIGNAL(deviceChange(int,int,int)), this, SLOT(deviceChanged(int,int,int)), Qt::QueuedConnection); int numberOfDevices = tdGetNumberOfDevices(); + errorNo = 0; + if (numberOfDevices < 0) { //Error + errorNo = numberOfDevices; + } for( int i = 0; i < numberOfDevices; ++i ) { int id = tdGetDeviceId(i); Device *device = new Device(id, SUPPORTED_METHODS, this); @@ -117,6 +121,18 @@ QVariant DeviceModel::headerData ( int section, Qt::Orientation orientation, int return QVariant(); } +bool DeviceModel::haveError() const { + return errorNo != 0; +} + +QString DeviceModel::errorString() const { + char *error = tdGetErrorString(errorNo); + QString errorStr = QString::fromUtf8( error ); + tdReleaseString(error); + return errorStr; +} + + Device *DeviceModel::device( const QModelIndex &index ) { if (index.row() >= devices.size()) { return 0; diff --git a/telldus-gui/TelldusGui/devicemodel.h b/telldus-gui/TelldusGui/devicemodel.h index b7a30e70..d152cc86 100644 --- a/telldus-gui/TelldusGui/devicemodel.h +++ b/telldus-gui/TelldusGui/devicemodel.h @@ -21,7 +21,10 @@ public: Device *device( const QModelIndex & ); int deviceId( const QModelIndex & ); - + + bool haveError() const; + QString errorString() const; + signals: void deviceChange(int deviceId, int, int); void showMessage( const QString &title, const QString &message, const QString &detailedMessage ); @@ -38,7 +41,7 @@ private: void triggerCellUpdate(int row, int column); // static void deviceEvent(int deviceId, int method, const char *data, int callbackId, void *context); static void WINAPI deviceChangeEvent(int deviceId, int, int, int, void *); - + // void connectDeviceSignals( Device *device ) const; // int deviceId( const QModelIndex &index ) const; // int deviceId( int index ) const; @@ -46,6 +49,7 @@ private: // mutable QHash indexToId; QList devices; int deviceChangeCallbackId; + int errorNo; }; #endif // DEVICEMODEL_H From dec6018464afb37310a825a54e816bee3e78e6e0 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 3 Mar 2011 14:17:29 +0000 Subject: [PATCH 1624/2215] Set the widget enabled false and emit an error if we cannot connect to the service --- telldus-gui/TelldusGui/devicewidget.cpp | 17 +++++++++++++++-- telldus-gui/TelldusGui/devicewidget.h | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusGui/devicewidget.cpp b/telldus-gui/TelldusGui/devicewidget.cpp index 0c4cefbe..b4bab2e4 100644 --- a/telldus-gui/TelldusGui/devicewidget.cpp +++ b/telldus-gui/TelldusGui/devicewidget.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -28,7 +29,7 @@ DeviceWidget::DeviceWidget(QWidget *parent) : connect( &deviceView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(listActivated(const QModelIndex &)) ); connect(&model, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); connect(&model, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); - + QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(&deviceView); @@ -68,6 +69,14 @@ DeviceWidget::DeviceWidget(QWidget *parent) : buttonLayout->addStretch(); layout->addLayout( buttonLayout ); + + if (model.haveError()) { + //We emit the signal in the next "event loop". + //This to allow the signals to be connected from our parent object + QTimer::singleShot(0, this, SLOT(emitError())); + this->setEnabled( false ); + } + } DeviceWidget::~DeviceWidget() @@ -85,6 +94,10 @@ void DeviceWidget::changeEvent(QEvent *e) } } +void DeviceWidget::emitError() { + emit showMessage("", model.errorString(), ""); +} + void DeviceWidget::addDevice() { Device device(0, 0); @@ -102,7 +115,7 @@ void DeviceWidget::addDevice() { void DeviceWidget::addGroup() { //Device *device = model.newDevice(); Device device(0, 0); - + EditGroupDialog *dialog = new EditGroupDialog(&device, &model); if (dialog->exec() == QDialog::Accepted) { device.save(); diff --git a/telldus-gui/TelldusGui/devicewidget.h b/telldus-gui/TelldusGui/devicewidget.h index 916923e3..06a53dfb 100644 --- a/telldus-gui/TelldusGui/devicewidget.h +++ b/telldus-gui/TelldusGui/devicewidget.h @@ -28,6 +28,7 @@ private slots: void addGroup(); void deleteDevice(); void editDevice(); + void emitError(); private: DeviceModel model; From 37dcc1ff4fcf5f11bcd9280eb550cb5ba68dffd0 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 3 Mar 2011 15:19:23 +0000 Subject: [PATCH 1625/2215] Code cleanup, todos examined --- telldus-gui/TelldusGui/device.cpp | 3 --- telldus-gui/TelldusGui/editgroupdialog.cpp | 16 ++++++++-------- telldus-gui/TelldusGui/methodwidget.cpp | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/telldus-gui/TelldusGui/device.cpp b/telldus-gui/TelldusGui/device.cpp index 9121cbe3..c413c356 100644 --- a/telldus-gui/TelldusGui/device.cpp +++ b/telldus-gui/TelldusGui/device.cpp @@ -81,9 +81,6 @@ QString &Device::name() const { } void Device::setParameter( const QString &name, const QString &value ) { - if(name == "devices"){ - d->protocolChanged = true; - } d->settings[name] = value; } diff --git a/telldus-gui/TelldusGui/editgroupdialog.cpp b/telldus-gui/TelldusGui/editgroupdialog.cpp index 582b0b38..ff26b768 100644 --- a/telldus-gui/TelldusGui/editgroupdialog.cpp +++ b/telldus-gui/TelldusGui/editgroupdialog.cpp @@ -131,12 +131,12 @@ void EditGroupDialog::setDevicesVisible(){ devices << device.toInt(); } - for (int i = 0; i < model->rowCount(); ++i){ - int id = model->deviceId(model->index(i, 0)); - if (id == device->id()) { - //shouldnt be able to add itself, check that here - availableProxyModel->hideRow(i); - } else if (devices.contains(id)) { + for (int i = 0; i < model->rowCount(); ++i){ + int id = model->deviceId(model->index(i, 0)); + if (id == device->id()) { + //shouldnt be able to add itself, check that here + availableProxyModel->hideRow(i); + } else if (devices.contains(id)) { availableProxyModel->hideRow(i); addedProxyModel->showRow(i); } @@ -201,8 +201,8 @@ void ProxyModel::showAllRows() { QString ProxyModel::getShownIds(){ QStringList addedIds; - foreach (int index, rows){ //TODO why does this crash when debugging? Unsafe? - if(index >= 0){ //TODO why can this be + foreach (int index, rows){ + if(index >= 0){ DeviceModel *model = reinterpret_cast(this->sourceModel()); if (model) { int deviceId = model->deviceId(model->index(index, 0)); diff --git a/telldus-gui/TelldusGui/methodwidget.cpp b/telldus-gui/TelldusGui/methodwidget.cpp index ac30ac29..8bf363d6 100644 --- a/telldus-gui/TelldusGui/methodwidget.cpp +++ b/telldus-gui/TelldusGui/methodwidget.cpp @@ -96,7 +96,7 @@ MethodWidget::MethodWidget( Device *device, QWidget *parent ) connect(d->execute, SIGNAL(clicked()), device, SLOT(execute())); connect(d->up, SIGNAL(clicked()), device, SLOT(up())); connect(d->down, SIGNAL(clicked()), device, SLOT(down())); - //TODO connect(d->stop, SIGNAL(clicked()), device, SLOT(stop())); + connect(d->stop, SIGNAL(clicked()), device, SLOT(stop())); updateMethods(device->methods()); From af2ae018cb24b13ec1d070ae75b6ca6271e5356d Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Thu, 3 Mar 2011 16:03:00 +0000 Subject: [PATCH 1626/2215] Code cleanup, printouts removed --- telldus-gui/Plugins/Live/LiveMessageToken.cpp | 2 -- telldus-gui/Plugins/Live/LiveObject.cpp | 10 ++++------ telldus-gui/TelldusCenter/message.cpp | 2 -- telldus-gui/TelldusCenter/tellduscenterapplication.cpp | 1 - 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/telldus-gui/Plugins/Live/LiveMessageToken.cpp b/telldus-gui/Plugins/Live/LiveMessageToken.cpp index 328aa53b..03b204ce 100644 --- a/telldus-gui/Plugins/Live/LiveMessageToken.cpp +++ b/telldus-gui/Plugins/Live/LiveMessageToken.cpp @@ -57,7 +57,6 @@ LiveMessageToken LiveMessageToken::parseToken(const QByteArray &string, int* sta ++(*start); int index = string.indexOf('s', (*start)); if (index < 0) { - qDebug() << "Error in" << string; return d; } bool ok; @@ -87,7 +86,6 @@ LiveMessageToken LiveMessageToken::parseToken(const QByteArray &string, int* sta } else { //String int index = string.indexOf(':', (*start)); if (index < 0) { - qDebug() << "Error in" << string; return d; } bool ok; diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index ebaa2ec3..3acb4fe8 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -93,13 +93,13 @@ void LiveObject::disconnect() { void LiveObject::readyRead() { QByteArray ba = d->socket->readAll(); - qDebug() << ba; + //qDebug() << ba; QScopedPointer envelope(LiveMessage::fromByteArray(ba)); QString signature = envelope->name(); QScopedPointer msg(LiveMessage::fromByteArray(envelope->arg(0).stringVal.toUtf8())); if (signatureForMessage(envelope->arg(0).stringVal.toUtf8()) != signature) { - qDebug() << "HASH mismatch!" << msg->name(); + //qDebug() << "HASH mismatch!" << msg->name(); return; } @@ -203,8 +203,6 @@ void LiveObject::stateChanged( QAbstractSocket::SocketState socketState ) { emit statusChanged("Reconnecting in " + QString::number(timeout) + " seconds..."); } else if (socketState == QAbstractSocket::ConnectingState) { emit statusChanged("Connecting..."); - } else { - //qDebug() << "State:" << socketState; } } @@ -215,7 +213,7 @@ void LiveObject::sslErrors( const QList & errors ) { case QSslError::SelfSignedCertificate: continue; default: - qDebug() << "SSL" << error.errorString(); + //qDebug() << "SSL" << error.errorString(); everythingOK = false; emit statusChanged("SSL Error"); emit errorChanged(error.errorString()); @@ -251,7 +249,7 @@ void LiveObject::serverAssignReply( QNetworkReply *r ) { } if (found) { - qDebug() << "Servers found, retry direct..."; + //qDebug() << "Servers found, retry direct..."; d->serverRefreshTime = QDateTime::currentDateTime(); QTimer::singleShot(0, this, SLOT(connectToServer())); } else { diff --git a/telldus-gui/TelldusCenter/message.cpp b/telldus-gui/TelldusCenter/message.cpp index 96a90515..8342fc59 100644 --- a/telldus-gui/TelldusCenter/message.cpp +++ b/telldus-gui/TelldusCenter/message.cpp @@ -2,7 +2,6 @@ #include #include #include -#include Message::Message(QWidget *parent) :QWidget(parent) @@ -20,7 +19,6 @@ Message::Message(QWidget *parent) } Message::~Message() { - qDebug() << "Why am I dying?"; } void Message::showMessage( const QString &title, const QString &message, const QString &detailedMessage ) { diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 32570409..79e412ce 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -132,7 +132,6 @@ void TelldusCenterApplication::loadScripts() { if (extension.startsWith("...")) { continue; } -// qDebug() << "Loading extension:" << extension; foreach(QDir dir, this->libraryPaths()) { dir.cd("script"); QString path = extension; From d3b4f68537bcba85d13fd12371309c8263069709 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 09:26:42 +0000 Subject: [PATCH 1627/2215] Fixed correct output path of translation file under Linux --- telldus-gui/TelldusCenter/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index b7bdb20d..d2bea629 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -125,7 +125,7 @@ ELSE (UPDATE_TRANSLATIONS) ) ELSEIF (UNIX) SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_SOURCE_DIR}/TelldusCenter + OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter ) ENDIF (APPLE) QT4_ADD_TRANSLATION(telldus-center_QM ${telldus-center_TS}) From a35ee15a1524e85e217d8ab6ad709b1a23ecb59b Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 09:32:40 +0000 Subject: [PATCH 1628/2215] Fixed correct output path of translation file under Linux --- telldus-gui/TelldusGui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 21110926..c44b3dd4 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -122,7 +122,7 @@ ELSE (UPDATE_TRANSLATIONS) ) ELSEIF (UNIX) SET_SOURCE_FILES_PROPERTIES(${telldus-gui_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_SOURCE_DIR}/TelldusCenter + OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter ) ENDIF (APPLE) QT4_ADD_TRANSLATION(telldus-gui_QM ${telldus-gui_TS}) From 7cda531bbb0d588815002d1ee6aba954c6112ff4 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 4 Mar 2011 09:54:55 +0000 Subject: [PATCH 1629/2215] Translations updated for plugins --- telldus-gui/Plugins/Devices/translation_sv.ts | 21 ++++++++++++++++--- telldus-gui/Plugins/Systray/translation_sv.ts | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/Devices/translation_sv.ts b/telldus-gui/Plugins/Devices/translation_sv.ts index 6764fb94..8d4bd2e0 100644 --- a/telldus-gui/Plugins/Devices/translation_sv.ts +++ b/telldus-gui/Plugins/Devices/translation_sv.ts @@ -4,17 +4,32 @@ __init__ - + On På - + + Up + Upp + + + + Stop + Stopp + + + Off Av - + + Down + Ner + + + Bell Ring diff --git a/telldus-gui/Plugins/Systray/translation_sv.ts b/telldus-gui/Plugins/Systray/translation_sv.ts index 25e46a38..e430076a 100644 --- a/telldus-gui/Plugins/Systray/translation_sv.ts +++ b/telldus-gui/Plugins/Systray/translation_sv.ts @@ -4,7 +4,7 @@ __init__ - + &Quit &Avsluta From 8f937294c3be621dd4ec239e6cf34aefa4b78593 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 09:56:43 +0000 Subject: [PATCH 1630/2215] Updated swedish translations for telldus-gui --- telldus-gui/TelldusGui/TelldusGui_sv.ts | 141 ++++++++++++++++++------ 1 file changed, 108 insertions(+), 33 deletions(-) diff --git a/telldus-gui/TelldusGui/TelldusGui_sv.ts b/telldus-gui/TelldusGui/TelldusGui_sv.ts index 9dc8e881..c8ce04a0 100644 --- a/telldus-gui/TelldusGui/TelldusGui_sv.ts +++ b/telldus-gui/TelldusGui/TelldusGui_sv.ts @@ -4,39 +4,54 @@ DeviceModel - + on på - + off av - + + up + upp + + + + down + ner + + + + stopped + stoppad + + + %1% - + unknown %1 - okänd %1 + okänt %1 - + State - Läge + Status - + Device name Enhetsnamn - + Action - Styr + Utför @@ -54,7 +69,7 @@ Randomize - + Slumpa @@ -62,7 +77,7 @@ Unitcode - Enhetskod + Enhetskod @@ -114,6 +129,27 @@ Huskod + + DeviceSettingSelflearning + + + Remote code + Fjärrkontrollskod + + + + Randomize + Slumpa + + + + DeviceSettingUnitcode + + + Unit code + Enhetskod + + DeviceSettingUpm @@ -135,88 +171,127 @@ DeviceWidget - + New device... Ny enhet... - + New group... Ny grupp... - + New Ny - + Edit Redigera - + Remove - Ta bort + Fjärrkontrollskod - + Are you sure you want to remove the selected device? - Är du säker på att du vill ta bort den valda enheten? + Är du säker på att du vill ta bort vald enhet? - + The device will be removed permanently from this application as well as all other applications. - Enheten kommer att permanent tas bort från detta och alla andra program. + Enheten kommer tas bort permanent från både detta program såväl som alla andra program. EditDeviceDialog - + + + Scan + Scanna + + + + Stop + Stoppa + + + Device Enhet - + &Name: &Namn: - + Choose a device above Välj en enhet ovan - + Addresscode Adresskod - + + Please press a button on your remote + Tryck en knapp på din fjärrkontroll + + + + If you have a TellStick Duo connected,<br>you can use it to scan the code of the remote control + Om du har en TellStick Duo ansluten,<br>kan du använda den för att hitta rätt enhet och inställningar + + + You must choose a device Du måste välja en enhet - + Please select the device you have. Välj den enhet du har. - + The device must have a name. Enheten måste ha ett namn. - + Please fill in a name in the field under 'Name' - Fyll i ett namn i rutan 'Namn' + Skriv in ett namn i fältet 'Namn' + + + + EditGroupDialog + + + &Name: + &Namn: + + + + The device must have a name. + Enheten måste ha ett namn. + + + + Please fill in a name in the field under 'Name' + Skriv in ett namn i fältet 'Namn' MethodWidget - + Learn Lär upp @@ -226,7 +301,7 @@ Not a Telldus device-file - Inte en Telldus-enhets-fil + Inte en Telldus enhetsfil From 5c9f2c37fcffbe0d01c675cf6605d0676fe7e50e Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 10:02:37 +0000 Subject: [PATCH 1631/2215] Updated swedish translations for TelldusCenter --- telldus-gui/TelldusCenter/TelldusCenter_sv.ts | 38 ++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/telldus-gui/TelldusCenter/TelldusCenter_sv.ts b/telldus-gui/TelldusCenter/TelldusCenter_sv.ts index 06e99faf..8f144e01 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter_sv.ts +++ b/telldus-gui/TelldusCenter/TelldusCenter_sv.ts @@ -4,50 +4,54 @@ MainWindow - - Telldus Center + + TelldusCenter - + &File &Arkiv - + + &Configure + &Inställningar + + + &Quit &Avsluta - + &Help &Hjälp - + About &Qt Om &Qt - - About &Telldus Center - Om &Telldus Center + + About &TelldusCenter + Om &TelldusCenter - + Pages Sidor - - About Telldus Center - Om Telldus Center + + About TelldusCenter + Om TelldusCenter - - <center><img src=':/images/TelldusCenter_128.png' width=128 height=128 /><h2>Telldus Center 2.0.0_beta2</h2><p>Copyright &copy; 2009 Telldus Technologies AB<p></center> - <center><img src=':/images/TelldusCenter_128.png' width=128 height=128 /><h2>Telldus Center 2.0.0_beta1</h2><p>Copyright &copy; 2009 Telldus Technologies AB<p></center> - + + <center><img src=':/images/TelldusCenter_128.png' width=128 height=128 /><h2>TelldusCenter %1</h2><p>Copyright &copy; 2010 Telldus Technologies AB<p></center> + From 40c3301a29bcafb1ea38703da5b2b7b6e2fe6939 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 4 Mar 2011 10:19:17 +0000 Subject: [PATCH 1632/2215] Plugin translation added --- telldus-gui/Plugins/Live/__init__.js | 2 +- telldus-gui/Plugins/Live/translation_sv.ts | 30 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 telldus-gui/Plugins/Live/translation_sv.ts diff --git a/telldus-gui/Plugins/Live/__init__.js b/telldus-gui/Plugins/Live/__init__.js index a255ee79..64a851ea 100644 --- a/telldus-gui/Plugins/Live/__init__.js +++ b/telldus-gui/Plugins/Live/__init__.js @@ -25,7 +25,7 @@ com.telldus.live = function() { isRegistered = false; if (com.telldus.systray && !menuId) { separatorId = com.telldus.systray.addSeparator(); - menuId = com.telldus.systray.addMenuItem( "Activate Telldus Live!" ); + menuId = com.telldus.systray.addMenuItem( qsTr("Activate Telldus Live!") ); com.telldus.systray.menuItem(menuId).triggered.connect(socket.activate); } } diff --git a/telldus-gui/Plugins/Live/translation_sv.ts b/telldus-gui/Plugins/Live/translation_sv.ts new file mode 100644 index 00000000..6cdfaf84 --- /dev/null +++ b/telldus-gui/Plugins/Live/translation_sv.ts @@ -0,0 +1,30 @@ + + + + + LiveObject + + + Default browser could not be opened + Standardwebbläsaren kunde inte öppnas + + + + We could not open your default internet browser + Vi kunde inte öppna din standardwebbläsare + + + + Please copy the following url and enter it in your browser:<br><a href='%1'>%1</a> + Kopiera följande URL och klistra in i din webbläsare:<br><a href='%1'>%1</a> + + + + __init__ + + + Activate Telldus Live! + Aktivera Telldus Live! + + + From dfdc8042a3b445acf9bfe87cbbad694ab9b263ef Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 12:54:45 +0000 Subject: [PATCH 1633/2215] Updated translation dir for TelldusGui on OS X --- telldus-gui/TelldusGui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index c44b3dd4..1878f679 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -118,7 +118,7 @@ IF (UPDATE_TRANSLATIONS) ELSE (UPDATE_TRANSLATIONS) IF (APPLE) SET_SOURCE_FILES_PROPERTIES(${telldus-gui_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter.app/Contents/Resources + OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Resources ) ELSEIF (UNIX) SET_SOURCE_FILES_PROPERTIES(${telldus-gui_TS} PROPERTIES From 185ee4b0f96faa0e2ddf8be06c6a18227e91a26c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 12:55:00 +0000 Subject: [PATCH 1634/2215] Bumped version --- telldus-gui/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index 763cbfd7..c3b2e01b 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -8,7 +8,7 @@ endif(COMMAND cmake_policy) SET(PACKAGE_MAJOR_VERSION 2) SET(PACKAGE_MINOR_VERSION 0) -SET(PACKAGE_PATCH_VERSION 103) +SET(PACKAGE_PATCH_VERSION 104) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) From be3f08402cdbdd1b9fb8c4ce0d41d6dd08509b8d Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 13:38:59 +0000 Subject: [PATCH 1635/2215] Typo in translation --- telldus-gui/TelldusGui/TelldusGui_sv.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/TelldusGui_sv.ts b/telldus-gui/TelldusGui/TelldusGui_sv.ts index c8ce04a0..a72a7f8f 100644 --- a/telldus-gui/TelldusGui/TelldusGui_sv.ts +++ b/telldus-gui/TelldusGui/TelldusGui_sv.ts @@ -193,7 +193,7 @@ Remove - Fjärrkontrollskod + Ta bort From 87230c67fc9f162e36534eead5bd98d3ae4eebbf Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 13:40:03 +0000 Subject: [PATCH 1636/2215] Fixed output path for translations to TelldusCenter --- telldus-gui/TelldusCenter/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index d2bea629..17e786c9 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -121,7 +121,7 @@ IF (UPDATE_TRANSLATIONS) ELSE (UPDATE_TRANSLATIONS) IF (APPLE) SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES - OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/TelldusCenter.app/Contents/Resources + OUTPUT_LOCATION ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Resources ) ELSEIF (UNIX) SET_SOURCE_FILES_PROPERTIES(${telldus-center_TS} PROPERTIES From 8576b4e1d7c0b2595d5068c918b398c0061e0e6a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 13:40:35 +0000 Subject: [PATCH 1637/2215] Added QAction::menuRole to the preferences menu item --- telldus-gui/TelldusCenter/mainwindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 1578d4d9..1fbc33b4 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -86,6 +86,7 @@ void MainWindow::setupMenu() { // File QMenu *fileMenu = menuBar()->addMenu(tr("&File")); QAction *config = fileMenu->addAction(tr("&Configure"), this, SLOT(slotConfigure())); + config->setMenuRole(QAction::PreferencesRole); fileMenu->addSeparator(); QAction *quit = fileMenu->addAction(tr("&Quit"), qApp, SLOT(quit())); quit->setMenuRole( QAction::QuitRole ); From ac04adc3a4272ae6df91b5ea8d58c905aa2ce21c Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 4 Mar 2011 17:18:40 +0000 Subject: [PATCH 1638/2215] Updated install_name_tool script to fit version 2.0.104 --- .../TelldusCenter/install_name_tool.sh | 97 +++++++------------ 1 file changed, 35 insertions(+), 62 deletions(-) diff --git a/telldus-gui/TelldusCenter/install_name_tool.sh b/telldus-gui/TelldusCenter/install_name_tool.sh index 0df4c48a..356fbee9 100755 --- a/telldus-gui/TelldusCenter/install_name_tool.sh +++ b/telldus-gui/TelldusCenter/install_name_tool.sh @@ -1,7 +1,7 @@ #!/bin/bash -PLUGINS="Devices SystrayIcon TelldusCorePlugin" -VERSION="2.0.2" +PLUGINS="Devices SystrayIcon TelldusCorePlugin TelldusLive" +VERSION="2.0.104" copy_framework() { echo "Copy framework $1" @@ -9,10 +9,6 @@ copy_framework() { cp -R /Library/Frameworks/$1.framework/ TelldusCenter.app/Contents/Frameworks/$1.framework/ } -copy_plugin_translations() { - cp Plugins/script/$1/*.qm TelldusCenter.app/Contents/Plugins/script/$1/ -} - strip_qt_development_files() { # Strip development-files rm -r ${2}/${1}_debug.dSYM @@ -30,10 +26,6 @@ change_telldus_core() { } - -if [ ! -d /Library/Frameworks/TelldusCore.framework/Versions/Current/Frameworks ]; then - mkdir /Library/Frameworks/TelldusCore.framework/Versions/Current/Frameworks -fi if [ ! -d /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries ]; then mkdir /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries fi @@ -41,33 +33,32 @@ if [ ! -d TelldusCenter.app/Contents/Frameworks ]; then mkdir TelldusCenter.app/Contents/Frameworks fi -### QtCore ### -if [ ! -d /Library/Frameworks/TelldusCore.framework/Versions/Current/Frameworks/QtCore.framework ]; then - echo "Copy framework QtCore" - cp -R /Library/Frameworks/QtCore.framework /Library/Frameworks/TelldusCore.framework/Versions/Current/Frameworks/ - install_name_tool -id "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4.0/QtCore" /Library/Frameworks/TelldusCore.framework/Versions/Current/Frameworks/QtCore.framework/Versions/4.0/QtCore - - strip_qt_development_files QtCore /Library/Frameworks/TelldusCore.framework/Versions/Current/Frameworks/QtCore.framework -fi - ### TelldusCore ### echo "Fixing TelldusCore" -if [ ! -f /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/libftd2xx.0.1.4.dylib ]; then - echo "Copy libftd2xx.0.1.4.dylib" - cp /usr/local/lib/libftd2xx.0.1.4.dylib /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/ - install_name_tool -id "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.0.1.4.dylib" /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/libftd2xx.0.1.4.dylib +FTD2XX_VERSION="1.0.2" +if [ ! -f /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib ]; then + echo "Copy libftd2xx.${FTD2XX_VERSION}.dylib" + cp /usr/local/lib/libftd2xx.${FTD2XX_VERSION}.dylib /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/ + install_name_tool -id "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib" /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib fi install_name_tool -id /Library/Frameworks/TelldusCore.framework/TelldusCore /Library/Frameworks/TelldusCore.framework/TelldusCore -install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4.0/QtCore" /Library/Frameworks/TelldusCore.framework/TelldusCore -install_name_tool -change /usr/local/lib/libftd2xx.0.1.4.dylib "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.0.1.4.dylib" /Library/Frameworks/TelldusCore.framework/TelldusCore +install_name_tool -change /usr/local/lib/libftd2xx.${FTD2XX_VERSION}.dylib "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib" /Library/Frameworks/TelldusCore.framework/TelldusCore + +### QtCore ### +if [ ! -d TelldusCenter.app/Contents/Frameworks/QtCore.framework ]; then + FRAMEWORK="TelldusCenter.app/Contents/Frameworks/QtCore.framework/QtCore" + copy_framework QtCore + strip_qt_development_files QtCore TelldusCenter.app/Contents/Frameworks/QtCore.framework + install_name_tool -id @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore ${FRAMEWORK} +fi ### QtGui ### if [ ! -d TelldusCenter.app/Contents/Frameworks/QtGui.framework ]; then FRAMEWORK="TelldusCenter.app/Contents/Frameworks/QtGui.framework/QtGui" copy_framework QtGui strip_qt_development_files QtGui TelldusCenter.app/Contents/Frameworks/QtGui.framework - install_name_tool -id @executable_path/../Frameworks/QtGui.framework/Versions/4.0/QtGui ${FRAMEWORK} - install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4/QtCore" ${FRAMEWORK} + install_name_tool -id @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui ${FRAMEWORK} + install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore ${FRAMEWORK} fi ### QtNetwork ### @@ -75,8 +66,8 @@ if [ ! -d TelldusCenter.app/Contents/Frameworks/QtNetwork.framework ]; then FRAMEWORK="TelldusCenter.app/Contents/Frameworks/QtNetwork.framework/QtNetwork" copy_framework QtNetwork strip_qt_development_files QtNetwork TelldusCenter.app/Contents/Frameworks/QtNetwork.framework - install_name_tool -id @executable_path/../Frameworks/QtNetwork.framework/Versions/4.0/QtNetwork ${FRAMEWORK} - install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4/QtCore" ${FRAMEWORK} + install_name_tool -id @executable_path/../Frameworks/QtNetwork.framework/Versions/4/QtNetwork ${FRAMEWORK} + install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore ${FRAMEWORK} fi ### QtScript ### @@ -84,61 +75,43 @@ if [ ! -d TelldusCenter.app/Contents/Frameworks/QtScript.framework ]; then FRAMEWORK="TelldusCenter.app/Contents/Frameworks/QtScript.framework/QtScript" copy_framework QtScript strip_qt_development_files QtScript TelldusCenter.app/Contents/Frameworks/QtScript.framework - install_name_tool -id @executable_path/../Frameworks/QtScript.framework/Versions/4.0/QtScript ${FRAMEWORK} - install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4/QtCore" ${FRAMEWORK} + install_name_tool -id @executable_path/../Frameworks/QtScript.framework/Versions/4/QtScript ${FRAMEWORK} + install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore ${FRAMEWORK} fi ### TelldusGui ### -if [ -L TelldusCenter.app/Contents/Frameworks/TelldusGui.framework ]; then - echo "Framework TelldusGui is a symlink, removing" - rm TelldusCenter.app/Contents/Frameworks/TelldusGui.framework -fi if [ ! -d TelldusCenter.app/Contents/Frameworks/TelldusGui.framework ]; then FRAMEWORK="TelldusCenter.app/Contents/Frameworks/TelldusGui.framework/TelldusGui" copy_framework TelldusGui install_name_tool -id @executable_path/../Frameworks/TelldusGui.framework/Versions/2/TelldusGui ${FRAMEWORK} - install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4.0/QtCore" ${FRAMEWORK} - install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4.0/QtGui ${FRAMEWORK} + install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore ${FRAMEWORK} + install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui ${FRAMEWORK} fi ### TelldusCenter ### echo "Fixing TelldusCenter" -install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4.0/QtCore" TelldusCenter.app/Contents/MacOS/TelldusCenter -install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4.0/QtGui TelldusCenter.app/Contents/MacOS/TelldusCenter -install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @executable_path/../Frameworks/QtNetwork.framework/Versions/4.0/QtNetwork TelldusCenter.app/Contents/MacOS/TelldusCenter -install_name_tool -change QtScript.framework/Versions/4/QtScript @executable_path/../Frameworks/QtScript.framework/Versions/4.0/QtScript TelldusCenter.app/Contents/MacOS/TelldusCenter - -if [ -L TelldusCenter.app/Contents/Plugins/script/com ]; then - echo "Scripts is a symlink, export from subversion" - rm TelldusCenter.app/Contents/Plugins/script/com - svn export http://svn.telldus.com/svn/tellstick/branches/2.0/telldus-gui/TelldusCenter/Plugins/script/com TelldusCenter.app/Contents/Plugins/script/com -fi - +install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore TelldusCenter.app/Contents/MacOS/TelldusCenter +install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui TelldusCenter.app/Contents/MacOS/TelldusCenter +install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @executable_path/../Frameworks/QtNetwork.framework/Versions/4/QtNetwork TelldusCenter.app/Contents/MacOS/TelldusCenter +install_name_tool -change QtScript.framework/Versions/4/QtScript @executable_path/../Frameworks/QtScript.framework/Versions/4/QtScript TelldusCenter.app/Contents/MacOS/TelldusCenter ### Plugins ### for plugin in $PLUGINS; do - PLUGIN_PATH="TelldusCenter.app/Contents/Plugins/script/lib${plugin}.dylib" + PLUGIN_PATH="TelldusCenter.app/Contents/Plugins/script/${plugin}.dylib" echo "Fixing plugin ${plugin}" - install_name_tool -id lib${plugin}.dylib $PLUGIN_PATH - install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4.0/QtCore" $PLUGIN_PATH - install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4.0/QtGui $PLUGIN_PATH - install_name_tool -change QtScript.framework/Versions/4/QtScript @executable_path/../Frameworks/QtScript.framework/Versions/4.0/QtScript $PLUGIN_PATH + install_name_tool -id ${plugin}.dylib $PLUGIN_PATH + install_name_tool -change QtCore.framework/Versions/4/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/4/QtCore $PLUGIN_PATH + install_name_tool -change QtGui.framework/Versions/4/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/4/QtGui $PLUGIN_PATH + install_name_tool -change QtScript.framework/Versions/4/QtScript @executable_path/../Frameworks/QtScript.framework/Versions/4/QtScript $PLUGIN_PATH + install_name_tool -change QtNetwork.framework/Versions/4/QtNetwork @executable_path/../Frameworks/QtNetwork.framework/Versions/4/QtNetwork $PLUGIN_PATH change_telldus_core $PLUGIN_PATH TPATH=`otool -L $PLUGIN_PATH | grep "/TelldusGui " | cut -f2 | cut -d ' ' -f1` if [ "$TPATH" != "" ]; then echo " Plugin ${plugin} is linked to TelldusGui" - install_name_tool -change $TPATH @executable_path/../Frameworks/TelldusGui.framework/Versions/2/TelldusGui $PLUGIN_PATH + install_name_tool -change $TPATH @executable_path/../Frameworks/TelldusGui.framework/TelldusGui $PLUGIN_PATH fi done -### I18N ### - -echo "Copy translation files" -copy_plugin_translations com/telldus/gui -copy_plugin_translations com/telldus/systray - echo "Fixing tdtool" change_telldus_core /usr/local/bin/tdtool -install_name_tool -change QtCore.framework/Versions/4/QtCore "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Frameworks/QtCore.framework/Versions/4/QtCore" /usr/local/bin/tdtool -install_name_tool -change /usr/local/lib/libftd2xx.0.1.4.dylib "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.0.1.4.dylib" /usr/local/bin/tdtool From e90cf53c6f760aadb65f583aa8eb84f6b9cb7344 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 8 Mar 2011 09:33:33 +0000 Subject: [PATCH 1639/2215] CMake-files updated for installation of Telldus Center on Linux --- telldus-gui/CMakeLists.txt | 3 +++ telldus-gui/Plugins/TelldusCenterPlugin.cmake | 13 +++++++++---- telldus-gui/TelldusCenter/CMakeLists.txt | 7 ++++++- .../TelldusCenter/tellduscenterapplication.cpp | 14 +++++++++++--- telldus-gui/TelldusGui/CMakeLists.txt | 10 +++++----- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index c3b2e01b..b36a4be5 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -25,6 +25,9 @@ SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") IF (WIN32) SET(TELLDUSCORE_INCLUDE_DIR "" CACHE PATH "Path to the directory which contains telldus-core.h") +ELSEIF(UNIX) + SET(PLUGIN_LIB_PATH "lib" CACHE STRING "Relative path to the directory to install TelldusCenter plugin libraries into") + SET(PLUGIN_LIB_FULL_PATH "${PLUGIN_LIB_PATH}/telldus/tellduscenter/plugins") ENDIF (WIN32) if(BUILD_LIBTELLDUS-GUI) diff --git a/telldus-gui/Plugins/TelldusCenterPlugin.cmake b/telldus-gui/Plugins/TelldusCenterPlugin.cmake index ebbc6b75..7647675c 100644 --- a/telldus-gui/Plugins/TelldusCenterPlugin.cmake +++ b/telldus-gui/Plugins/TelldusCenterPlugin.cmake @@ -35,14 +35,14 @@ SET(translation_sources ${Plugin_SRCS}) IF(Plugin_PATH) STRING(REPLACE "." "/" - path ${Plugin_PATH} + Plugin_PATH_relative ${Plugin_PATH} ) IF (APPLE) - SET(Plugin_PATH "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script/${path}") + SET(Plugin_PATH "${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/TelldusCenter.app/Contents/Plugins/script/${Plugin_PATH_relative}") ELSEIF (WIN32) - SET(Plugin_PATH "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/Plugins/script/${path}") + SET(Plugin_PATH "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/Plugins/script/${Plugin_PATH_relative}") ELSE (APPLE) - SET(Plugin_PATH "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script/${path}") + SET(Plugin_PATH "${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script/${Plugin_PATH_relative}") ENDIF (APPLE) LIST(APPEND translation_sources @@ -89,6 +89,9 @@ IF(Plugin_SRCS) SET_TARGET_PROPERTIES(${Plugin_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/TelldusCenter/Plugins/script ) + INSTALL(TARGETS ${Plugin_NAME} + LIBRARY DESTINATION "${PLUGIN_LIB_FULL_PATH}/script" + ) ENDIF (APPLE) ELSE(Plugin_SRCS) ADD_CUSTOM_TARGET(${Plugin_NAME} ALL @@ -109,6 +112,8 @@ IF(Plugin_PATH) COMMAND ${CMAKE_COMMAND} -E copy ${_FILE} ${Plugin_PATH} COMMENT "Copy ${_FILENAME} for plugin ${Plugin_NAME}" ) + INSTALL(FILES ${_FILE} DESTINATION "${PLUGIN_LIB_FULL_PATH}/script/${Plugin_PATH_relative}") ENDFOREACH(_FILE) ENDIF(Plugin_PATH) + diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 17e786c9..7e20732b 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -6,6 +6,7 @@ INCLUDE( ${QT_USE_FILE} ) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) + cmake_policy(SET CMP0005 NEW) endif(COMMAND cmake_policy) ######## Non configurable options ######## @@ -99,7 +100,7 @@ ELSEIF (WIN32) #### Windows #### ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.rc ) ELSE (APPLE) #### Linux #### - + ADD_DEFINITIONS( -DPLUGIN_LIB_PATH=${CMAKE_INSTALL_PREFIX}/${PLUGIN_LIB_FULL_PATH} ) ENDIF (APPLE) ######## QtSingleApplication ######## @@ -158,3 +159,7 @@ IF (APPLE) ) ENDIF (APPLE) +INSTALL(TARGETS ${telldus-center_TARGET} + RUNTIME DESTINATION bin +) + diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 79e412ce..270ac015 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -11,6 +11,9 @@ #include "plugintree.h" #include "scriptenvironment.h" +#define DEFINE_STRING_HELPER(X) #X +#define DEFINE_STRING(X) DEFINE_STRING_HELPER(X) + class TelldusCenterPlugin; typedef QList PluginList; @@ -95,12 +98,17 @@ void TelldusCenterApplication::loadPlugins() { pluginsDir.cdUp(); } #endif - if (!pluginsDir.cd("Plugins")) { - return; + + if (pluginsDir.cd("Plugins")) { + this->setLibraryPaths( QStringList(pluginsDir.absolutePath()) ); } - this->setLibraryPaths( QStringList(pluginsDir.absolutePath()) ); +#if defined(Q_OS_UNIX) + QStringList paths = QStringList() << DEFINE_STRING(PLUGIN_LIB_PATH); + this->setLibraryPaths( paths ); +#endif + QScriptValue mainWindowObject = d->scriptEnvironment->engine()->newQObject(d->mainWindow); d->scriptEnvironment->engine()->globalObject().property("application").setProperty("mainwindow", mainWindowObject); diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index 1878f679..f1fba39d 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -142,9 +142,9 @@ TARGET_LINK_LIBRARIES( ${telldus-gui_TARGET} ${telldus-gui_LIBRARIES} ) SET_PROPERTY(TARGET ${telldus-gui_TARGET} PROPERTY FRAMEWORK TRUE ) -SET_PROPERTY(TARGET ${telldus-gui_TARGET} - PROPERTY PUBLIC_HEADER ${telldus-gui_HDRS} -) +#SET_PROPERTY(TARGET ${telldus-gui_TARGET} +# PROPERTY PUBLIC_HEADER ${telldus-gui_HDRS} +#) SET_PROPERTY(TARGET ${telldus-gui_TARGET} PROPERTY VERSION ${PACKAGE_VERSION} @@ -154,6 +154,6 @@ SET_PROPERTY(TARGET ${telldus-gui_TARGET} ) INSTALL(TARGETS ${telldus-gui_TARGET} - DESTINATION lib + LIBRARY DESTINATION lib # PUBLIC_HEADER DESTINATION ${HEADER_DIR} - ) +) From d6e9aa29ef7d79f27673e0f35e264d38848828a5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 8 Mar 2011 10:07:03 +0000 Subject: [PATCH 1640/2215] Changed CFBundleIdentifier --- telldus-gui/TelldusCenter/Info.plist.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/Info.plist.in b/telldus-gui/TelldusCenter/Info.plist.in index 280b5ed2..75272158 100644 --- a/telldus-gui/TelldusCenter/Info.plist.in +++ b/telldus-gui/TelldusCenter/Info.plist.in @@ -11,7 +11,7 @@ CFBundleExecutable TelldusCenter CFBundleIdentifier - com.telldus.center + com.telldus.tellduscenter CFBundleInfoDictionaryVersion 6.0 CFBundleName From 7adda8214c99b0f1cfcb94a01eddbf2a6a3ba67a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Tue, 8 Mar 2011 11:31:11 +0000 Subject: [PATCH 1641/2215] ftd2xx is not referenced by telldus-core anymore but TelldusService --- telldus-gui/TelldusCenter/install_name_tool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusCenter/install_name_tool.sh b/telldus-gui/TelldusCenter/install_name_tool.sh index 356fbee9..720b9282 100755 --- a/telldus-gui/TelldusCenter/install_name_tool.sh +++ b/telldus-gui/TelldusCenter/install_name_tool.sh @@ -42,7 +42,7 @@ if [ ! -f /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/l install_name_tool -id "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib" /Library/Frameworks/TelldusCore.framework/Versions/Current/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib fi install_name_tool -id /Library/Frameworks/TelldusCore.framework/TelldusCore /Library/Frameworks/TelldusCore.framework/TelldusCore -install_name_tool -change /usr/local/lib/libftd2xx.${FTD2XX_VERSION}.dylib "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib" /Library/Frameworks/TelldusCore.framework/TelldusCore +install_name_tool -change /usr/local/lib/libftd2xx.${FTD2XX_VERSION}.dylib "/Library/Frameworks/TelldusCore.framework/Versions/${VERSION}/Libraries/libftd2xx.${FTD2XX_VERSION}.dylib" /Library/Telldus/TelldusService ### QtCore ### if [ ! -d TelldusCenter.app/Contents/Frameworks/QtCore.framework ]; then From 07fafbe61c80549e3f6a93c357b6d2f92c49497a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 10 Mar 2011 08:01:47 +0000 Subject: [PATCH 1642/2215] Added protection against compiling the sources from trunk. It is not supported adn you should really know what you are doing. --- telldus-core/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/telldus-core/CMakeLists.txt b/telldus-core/CMakeLists.txt index 9eb1ce16..cd0f71d3 100644 --- a/telldus-core/CMakeLists.txt +++ b/telldus-core/CMakeLists.txt @@ -2,6 +2,11 @@ PROJECT( telldus-core ) CMAKE_MINIMUM_REQUIRED( VERSION 2.6.0 ) +OPTION(FORCE_COMPILE_FROM_TRUNK FALSE "Accept compiling source from trunk. This is unsupported and highly unrecommended") +IF(NOT FORCE_COMPILE_FROM_TRUNK) + MESSAGE(FATAL_ERROR "You are compiling sources from trunk. Don't do that!") +ENDIF(NOT FORCE_COMPILE_FROM_TRUNK) + IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") INCLUDE_DIRECTORIES(/usr/local/include) LINK_DIRECTORIES(/usr/local/lib) From 1d863031c03288a574212e18188fe3dc1323328a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 18 Mar 2011 11:03:57 +0000 Subject: [PATCH 1643/2215] Added icons for up/down/stop --- telldus-gui/TelldusGui/images/down.png | Bin 502 -> 339 bytes telldus-gui/TelldusGui/images/stop.png | Bin 0 -> 202 bytes telldus-gui/TelldusGui/images/up.png | Bin 490 -> 342 bytes telldus-gui/TelldusGui/methodwidget.cpp | 2 +- telldus-gui/TelldusGui/telldusgui.qrc | 31 ++++++++++++------------ 5 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/stop.png diff --git a/telldus-gui/TelldusGui/images/down.png b/telldus-gui/TelldusGui/images/down.png index 06cfe7e5dd3f8da8036d3f76896c66ebb91863a3..7e04c6a1e462efd3f951380668db5e70504f9ffb 100644 GIT binary patch delta 312 zcmV-80muIK1JeSKB!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o0002> zNkl^A@vj4n&xl+Sy0`kzXJlkdpsD5m{(m^^tl4rAs{=s5Z&EnW z5!4R}h~4qHrHMdyEugjKc(Wlj96`u( zg5>}ujv&Tzq6#8%96_w*M3;o5ID!<*Nh*qoaRjNBlUx_za|Ah-lT{gEa|F4TlU*Ak zJAx9+p%v4AvN3VM^vM2zX<_=5n87&OEFX2ir~^hFFwhPF2rvLRto|2%)$lF=0000< KMNUMnLSTY2>Wjkw delta 476 zcmV<20VDp?0`>!tB!2;OQb$4qH^)s=00009a7bBm000G_000G_0i=J)s{jB19(q(* zbYXRLXm4@=0C?I9E=f&G%u@(REh;X~&jSD_dj)I*u_{sk00D7HL_t(o!|j((CS92Ptil{2331 zv@K@8o!KeP+k7?C%=f)d@AE$I`wm1FvRNjZYGI@eW*Xo=_U(`@s62-{-9811ItjxE z;5a#J9M1H*tdO%}VN>wG09XcjWeUKFCJqIuLxg2eSbxs4f?*S54LSrrY=vGdb7Q&cUkDs^P^{U>iJ_!aP8!2yVVV=+?Y6j)*4a-6VO={PXaNu4!4Ck7YEL$29)GS*o!xTm`y|0D}V{5N+b08 zny~`0umg90IiG~fCg=}jh!u$CJ$U%Z`5auez+j-0v{f={?ND;cb-pOYv`RUps2{dK zY#wR+{&c=7rAW4^QWmjz7o<;AbT*_AQ8OJzB`sI7?YF~xnB_cf`iB+So4o?!Dc48t Svg>vL0000yJ=REtzeBeh9gN57&4g-do{en?;S9#q*lAf-9F6*2UngDAjM^*p; literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/up.png b/telldus-gui/TelldusGui/images/up.png index 856309c13b89cfb8f9a47ebf1192d20f41853e78..bed9abb63549b30e8a392357c63a5a0a303b8e36 100644 GIT binary patch delta 315 zcmV-B0mT051J(kNB!3xnMObuGZ)S9NVRB^vL1b@YWgtmyVP|DhWnpA_ami&o0002^ zNkloSq4csm ztT(O##I_apaF()MPv~R^;w|(lx7G1ljw;Z@dB$=+Pk^QTE6_e0XkV?91Ukbr4oDGb zLLt#PpPAgg9Ow*3eU#`y2%v`q`oM=edPtxz+*blazw;L&9AoFf`m&0>^;c zNDQ4&Z=6^__%v@AM%PGabjK8?V+ygWiu=RqEr=hIC=dmrK0Wbd60_p>hB!2;OQb$4qH^)s=00009a7bBm000G_000G_0i=J)s{jB19(q(* zbYXRLXm4@=0C?I9E=f&G%u@(REh;X~&jSD_dj)I*u_{sk00Cu5L_t(o!|j(nO9Md= zhMydPL=h~+N-#}85EVZV6)Ov|P^{9~`3J1T%E~UCm0)3GCx6&#BM2f|BsLN(L~Im6 z5;dS0#Ut^(Vw-S5@A4tSF1*LFv&%EPJ99e+w*BYU2Xjf-)2q{Rct51p;4TB7W3aET zXv^ROu)F~e6{vX1fjbTdGR2w>AB2@ncrq2 z8x9|Vw4$w83x95umu4W_0o{#aN3`;-LwNlOZd8V-R_uzLcf-@=XFqy@Or zHYCHsqh5Mtm1aTVMjuiNuC)zALE$kkt-SOK3pe_bmf$u4Q@-cx2aiKeffU!IQnm3} z_B8Y+d?v0!L0kV)-CvfrbrkwiO}LP$D=4~P@w~=r=SkrxaFG4=ePSK34p;}Q1J(iS zK$u$IIn~4UG2}xOqmiH!ykb-LyNV?$KIXzZT-blcAnhAdown->setVisible( false ); layout->addWidget( d->down ); - d->stop->setIcon( QIcon(":/images/state_2.png") ); //TODO + d->stop->setIcon( QIcon(":/images/stop.png") ); d->stop->setVisible( false ); layout->addWidget( d->stop ); diff --git a/telldus-gui/TelldusGui/telldusgui.qrc b/telldus-gui/TelldusGui/telldusgui.qrc index 418c89b8..e8662ab4 100644 --- a/telldus-gui/TelldusGui/telldusgui.qrc +++ b/telldus-gui/TelldusGui/telldusgui.qrc @@ -1,17 +1,18 @@ - - images/bell.png - images/list-add.png - images/list-edit.png - images/list-remove.png - images/state_1.png - images/state_2.png - images/state_16.png - images/state_dimmed_25.png - images/state_dimmed_50.png - images/state_dimmed_75.png - images/execute.png - images/up.png - images/down.png - + + images/bell.png + images/list-add.png + images/list-edit.png + images/list-remove.png + images/state_1.png + images/state_2.png + images/state_16.png + images/state_dimmed_25.png + images/state_dimmed_50.png + images/state_dimmed_75.png + images/execute.png + images/up.png + images/down.png + images/stop.png + From 119ac6565cb0fc115ea2746386501d7fd66347b1 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 18 Mar 2011 14:44:38 +0000 Subject: [PATCH 1644/2215] Added TelldusCenter manpages --- telldus-gui/CMakeLists.txt | 1 + telldus-gui/TelldusCenter/CMakeLists.txt | 15 +++ .../TelldusCenter/tellduscenter.man.xml | 107 ++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 telldus-gui/TelldusCenter/tellduscenter.man.xml diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index b36a4be5..d1427b9f 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -22,6 +22,7 @@ SET(BUILD_LIBTELLDUS-GUI TRUE CACHE BOOL "Build libtelldus-gui") SET(BUILD_TELLDUS-CENTER TRUE CACHE BOOL "Build TelldusCenter") SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") +SET(GENERATE_MAN FALSE CACHE BOOL "Enable generation of man-files") IF (WIN32) SET(TELLDUSCORE_INCLUDE_DIR "" CACHE PATH "Path to the directory which contains telldus-core.h") diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index 7e20732b..b7de9e97 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -159,6 +159,21 @@ IF (APPLE) ) ENDIF (APPLE) +IF (UNIX) + IF (GENERATE_MAN) + ADD_CUSTOM_COMMAND( + TARGET ${telldus-center_TARGET} + POST_BUILD + + COMMAND xsltproc --nonet --param man.charmap.use.subset "0" /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.man.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating man file TelldusCenter.1" + ) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.1 DESTINATION share/man/man1) + ENDIF (GENERATE_MAN) +ENDIF (UNIX) + + INSTALL(TARGETS ${telldus-center_TARGET} RUNTIME DESTINATION bin ) diff --git a/telldus-gui/TelldusCenter/tellduscenter.man.xml b/telldus-gui/TelldusCenter/tellduscenter.man.xml new file mode 100644 index 00000000..cd197606 --- /dev/null +++ b/telldus-gui/TelldusCenter/tellduscenter.man.xml @@ -0,0 +1,107 @@ + +.
will be generated. You may view the +manual page with: nroff -man .
| less'. A typical entry +in a Makefile or Makefile.am is: + +DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl +XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" + +manpage.1: manpage.xml + $(XP) $(DB2MAN) $< + +The xsltproc binary is found in the xsltproc package. The XSL files are in +docbook-xsl. A description of the parameters you can use can be found in the +docbook-xsl-doc-* packages. Please remember that if you create the nroff +version in one of the debian/rules file targets (such as build), you will need +to include xsltproc and docbook-xsl in your Build-Depends control field. +Alternatively use the xmlto command/package. That will also automatically +pull in xsltproc and docbook-xsl. + +Notes for using docbook2x: docbook2x-man does not automatically create the +AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as + ... . + +To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections +read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be +found in the docbook-xsl-doc-html package. + +Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` + +General documentation about man-pages and man-page-formatting: +man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ + +--> + + + + + + + + + + + + + +]> + + + + &dhtitle; + &dhpackage; + + + &dhfirstname; + &dhsurname; + Wrote this manpage for the Debian system. +
+ &dhemail; +
+
+
+ + 2011 + &dhusername; + + + This manual page was written for the Debian system + (and may be used by others). + Permission is granted to copy, distribute and/or modify this + document under the terms of the GNU General Public License, + Version 2 or (at your option) any later version published by + the Free Software Foundation. + On Debian systems, the complete text of the GNU General Public + License can be found in + /usr/share/common-licenses/GPL. + +
+ + &dhucpackage; + &dhsection; + + + &dhpackage; + Program to control and edit devices used by Telldus TellStick + + + DESCRIPTION + &dhpackage; is the graphical program to control, add, remove or edit devices for use with Telldus TellStick. TellStick is a USB-interface to various remote controlled RF receivers on 433,92 MHz. + +
+ From c412c594904c07b770356e760f2215dac0342aed Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 18 Mar 2011 14:47:02 +0000 Subject: [PATCH 1645/2215] Fix for TelldusCenter unix menu entry (patch fix-unix-menu-entry.patch) --- telldus-gui/TelldusCenter/CMakeLists.txt | 2 + .../TelldusCenter/images/tellduscenter.xpm | 354 ++++++++++++++++++ .../TelldusCenter/tellduscenter.desktop | 8 + 3 files changed, 364 insertions(+) create mode 100644 telldus-gui/TelldusCenter/images/tellduscenter.xpm create mode 100644 telldus-gui/TelldusCenter/tellduscenter.desktop diff --git a/telldus-gui/TelldusCenter/CMakeLists.txt b/telldus-gui/TelldusCenter/CMakeLists.txt index b7de9e97..d69723c6 100644 --- a/telldus-gui/TelldusCenter/CMakeLists.txt +++ b/telldus-gui/TelldusCenter/CMakeLists.txt @@ -171,6 +171,8 @@ IF (UNIX) ) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/TelldusCenter.1 DESTINATION share/man/man1) ENDIF (GENERATE_MAN) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/images/tellduscenter.xpm DESTINATION share/pixmaps) + INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tellduscenter.desktop DESTINATION share/applications) ENDIF (UNIX) diff --git a/telldus-gui/TelldusCenter/images/tellduscenter.xpm b/telldus-gui/TelldusCenter/images/tellduscenter.xpm new file mode 100644 index 00000000..7505a299 --- /dev/null +++ b/telldus-gui/TelldusCenter/images/tellduscenter.xpm @@ -0,0 +1,354 @@ +/* XPM */ +static char * icon_TelldusCenter_32x32_xpm[] = { +"32 32 319 2", +" c None", +". c #8EA0C3", +"+ c #97AACF", +"@ c #99ACD2", +"# c #96AACF", +"$ c #8FA1C5", +"% c #8DA0C5", +"& c #92A6CC", +"* c #8CA0C5", +"= c #91A6CB", +"- c #8FA4C9", +"; c #93A9D1", +"> c #899EC3", +", c #899FC4", +"' c #899EC4", +") c #93A9D2", +"! c #8CA5CD", +"~ c #859BC2", +"{ c #859CC2", +"] c #8DA6CE", +"^ c #89A3CD", +"/ c #829AC2", +"( c #7E97BF", +"_ c #7A94BD", +": c #7F98C1", +"< c #89A4CE", +"[ c #86A2CB", +"} c #7F99C0", +"| c #7F9AC0", +"1 c #7F98C0", +"2 c #7691BB", +"3 c #94AACB", +"4 c #BBC8DE", +"5 c #829CC2", +"6 c #7893BD", +"7 c #809AC0", +"8 c #86A2CC", +"9 c #83A0CB", +"0 c #7C98C0", +"a c #7D98C0", +"b c #7A95BE", +"c c #7491BC", +"d c #A4B7D2", +"e c #F1F4F9", +"f c #FFFFFF", +"g c #DCE3ED", +"h c #88A0C5", +"i c #83A1CB", +"j c #819FCA", +"k c #7A96BF", +"l c #7A97BF", +"m c #7391BB", +"n c #7795BE", +"o c #BDCBDF", +"p c #FCFCFE", +"q c #EAEFF5", +"r c #95ACCC", +"s c #6E8EBA", +"t c #7896BE", +"u c #7E9FCA", +"v c #7896BF", +"w c #7796BF", +"x c #6E8EBB", +"y c #84A0C5", +"z c #D8E0ED", +"A c #F7F9FB", +"B c #A6BAD5", +"C c #6F90BB", +"D c #7594BE", +"E c #7F9FCA", +"F c #7C9ECA", +"G c #7695BF", +"H c #7696BF", +"I c #7393BE", +"J c #6B8DBA", +"K c #9BB2D1", +"L c #EDF2F7", +"M c #FDFEFE", +"N c #B8C8DE", +"O c #7091BC", +"P c #7D9ECA", +"Q c #7A9DC9", +"R c #7495BE", +"S c #6E90BC", +"T c #7093BD", +"U c #B6C7DD", +"V c #FEFEFF", +"W c #CDD9E8", +"X c #7898C0", +"Y c #6C8FBB", +"Z c #7B9EC9", +"` c #7A9ECA", +" . c #7295BF", +".. c #7195BF", +"+. c #6E92BD", +"@. c #81A1C5", +"#. c #D5E0EC", +"$. c #E4EAF2", +"%. c #87A5C8", +"&. c #6D92BC", +"*. c #7B9FCA", +"=. c #6F9AC7", +"-. c #7196C0", +";. c #7296C0", +">. c #6C92BD", +",. c #799CC4", +"'. c #DEE6F0", +"). c #FAFBFD", +"!. c #FEFEFE", +"~. c #D7E1ED", +"{. c #C4D5E5", +"]. c #D4DFEB", +"^. c #EFF3F8", +"/. c #FCFDFE", +"(. c #F9FBFC", +"_. c #E3EAF2", +":. c #7D9FC5", +"<. c #6D92BD", +"[. c #6F95BF", +"}. c #6C98C7", +"|. c #548DBE", +"1. c #598AB7", +"2. c #6590BC", +"3. c #6B93BE", +"4. c #7498C1", +"5. c #84A4C8", +"6. c #86A6C9", +"7. c #E4EBF3", +"8. c #C2D2E4", +"9. c #A9C1D9", +"0. c #A1B9D5", +"a. c #90ADCE", +"b. c #AAC2DA", +"c. c #F3F6FA", +"d. c #DCE5F0", +"e. c #82A3C8", +"f. c #85A5C8", +"g. c #7398C1", +"h. c #6991BD", +"i. c #618EBA", +"j. c #5689B6", +"k. c #528CBE", +"l. c #5690C0", +"m. c #5187B5", +"n. c #5188B5", +"o. c #558AB7", +"p. c #5A8CB8", +"q. c #5888B6", +"r. c #5F8EBA", +"s. c #DCE6F0", +"t. c #D4E1EC", +"u. c #B2C8DE", +"v. c #C6D6E6", +"w. c #E0E8F1", +"x. c #B3C8DE", +"y. c #85A8CA", +"z. c #D2DFEC", +"A. c #5A89B7", +"B. c #5688B7", +"C. c #578AB7", +"D. c #5389B6", +"E. c #5790C1", +"F. c #5B94C2", +"G. c #578CB8", +"H. c #568BB8", +"I. c #558BB8", +"J. c #5188B6", +"K. c #DAE5EF", +"L. c #D8E3EE", +"M. c #BBCEE1", +"N. c #A7C0D9", +"O. c #81A7CA", +"P. c #C6D8E7", +"Q. c #C7D8E7", +"R. c #7AA3C6", +"S. c #CEDDEB", +"T. c #5087B6", +"U. c #528AB7", +"V. c #568CB8", +"W. c #5B93C3", +"X. c #6097C7", +"Y. c #5B8FBC", +"Z. c #5B90BC", +"`. c #588EBB", +" + c #5A8FBB", +".+ c #DAE5F0", +"++ c #D5E2ED", +"@+ c #9BBBD6", +"#+ c #C4D7E7", +"$+ c #DBE7F0", +"%+ c #79A4C8", +"&+ c #CADBE9", +"*+ c #AAC5DB", +"=+ c #99B9D5", +"-+ c #CFDFEB", +";+ c #568CB9", +">+ c #598FBB", +",+ c #6098C7", +"'+ c #649AC9", +")+ c #5F92BE", +"!+ c #5C90BD", +"~+ c #EBF1F7", +"{+ c #C7D9E8", +"]+ c #8CB1D0", +"^+ c #96B8D4", +"/+ c #DFE9F2", +"(+ c #7FA8CB", +"_+ c #DEE9F2", +":+ c #82AACC", +"<+ c #E7EFF5", +"[+ c #D1E0EC", +"}+ c #5A8FBC", +"|+ c #5D91BD", +"1+ c #659CC9", +"2+ c #689ECB", +"3+ c #6395C1", +"4+ c #6093C0", +"5+ c #DCE7F1", +"6+ c #DAE6F0", +"7+ c #CEDEEC", +"8+ c #FBFCFD", +"9+ c #94B7D4", +"0+ c #BFD4E5", +"a+ c #A7C4DC", +"b+ c #C1D5E6", +"c+ c #A1C0D9", +"d+ c #C5D7E8", +"e+ c #D2E1ED", +"f+ c #5D92BF", +"g+ c #6194C0", +"h+ c #699ECC", +"i+ c #6CA2CD", +"j+ c #6699C3", +"k+ c #6397C2", +"l+ c #E2ECF3", +"m+ c #ECF3F8", +"n+ c #6799C3", +"o+ c #4E89B9", +"p+ c #C3D6E7", +"q+ c #D5E3EE", +"r+ c #98BAD6", +"s+ c #BFD5E6", +"t+ c #AAC6DD", +"u+ c #B2CBE1", +"v+ c #D3E2EE", +"w+ c #6296C1", +"x+ c #6498C2", +"y+ c #6CA2CF", +"z+ c #70A6D0", +"A+ c #6A9DC5", +"B+ c #679BC4", +"C+ c #E2ECF4", +"D+ c #EFF4F9", +"E+ c #76A5CA", +"F+ c #5C94C0", +"G+ c #C6D9E9", +"H+ c #EDF3F8", +"I+ c #CBDDEB", +"J+ c #D6E4EF", +"K+ c #C9DBEA", +"L+ c #C3D7E8", +"M+ c #C3D8E8", +"N+ c #D3E3EE", +"O+ c #669AC3", +"P+ c #689CC4", +"Q+ c #70A6D1", +"R+ c #73AAD4", +"S+ c #6DA1C8", +"T+ c #6A9FC7", +"U+ c #6DA0C9", +"V+ c #E4EDF5", +"W+ c #EEF4F9", +"X+ c #E1EBF3", +"Y+ c #DBE7F1", +"Z+ c #699DC6", +"`+ c #6BA0C7", +" @ c #73ABD4", +".@ c #77ADD6", +"+@ c #71A4CB", +"@@ c #70A4CA", +"#@ c #6FA3CB", +"$@ c #B6D0E4", +"%@ c #D3E2EF", +"&@ c #D5E4F0", +"*@ c #D7E6F1", +"=@ c #D0E1EE", +"-@ c #CFE0ED", +";@ c #CFE0EE", +">@ c #D1E1EE", +",@ c #B0CCE2", +"'@ c #6DA1CA", +")@ c #70A4CB", +"!@ c #78AED7", +"~@ c #7AB1D9", +"{@ c #75A8CD", +"]@ c #6FA4CB", +"^@ c #6EA3CB", +"/@ c #74A8CD", +"(@ c #7CB1D9", +"_@ c #7FB5DC", +":@ c #79ABD0", +"<@ c #79ACD0", +"[@ c #78ABCF", +"}@ c #80B6DC", +"|@ c #85BBE1", +"1@ c #7CAFD2", +"2@ c #7DAFD3", +"3@ c #85BCE1", +"4@ c #82B5D7", +"5@ c #85BADD", +"6@ c #80B3D6", +"7@ c #81B4D6", +"8@ c #84B9DC", +"9@ c #87BADC", +"0@ c #8EC5E8", +"a@ c #8DC3E6", +"b@ c #8EC5E7", +"c@ c #88BCDE", +"d@ c #415B6B", +" ", +" ", +" . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # $ ", +" % & * % % % % % % % % % % % % % % % % % % % % % % * = - ", +" ; > , ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' , > ) ", +" ! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ { { { ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ] ", +" ^ / / / / / / / / / / / / ( _ : / / / / / / / / / / / < ", +" [ } } } } } } } } } | 1 2 3 4 5 6 7 } } } } } } } } } 8 ", +" 9 0 0 0 0 0 0 0 0 a b c d e f g h c 0 0 0 0 0 0 0 0 0 i ", +" j k k k k k k k l m n o p f f f q r s t k k k k k k k j ", +" u v v v v v v w x y z f f f f f f A B C D v v v v v v E ", +" F G G G G H I J K L f f f f f f f f M N O O H G G G G P ", +" Q R R R R S T U V f f f f f f f f f f f W X Y R R R R Z ", +" ` ... .+.@.#.f f f f f f f f f f f f f f $.%.&. ... .*. ", +" =.-.;.>.,.'.).!.f ~.{.].^.f f f f f f f /.(._.:.<.;.[.}. ", +" |.1.2.3.4.5.6.7.f 8.9.0.a.b.c.f f f f f d.e.f.g.h.i.j.k. ", +" l.m.n.o.p.q.r.s.f t.u.v.w.x.y.7.f f f f z.A.B.C.D.m.n.E. ", +" F.G.H.H.I.J.H.K.f L.M.N.O.P.Q.R.L f f f S.T.U.I.H.V.G.W. ", +" X.Y.Y.Y.Z.`. +.+f ++@+#+$+%+&+*+=+f f f -+;+>+Z.Y.Y.Y.,+ ", +" '+)+)+)+)+!+)+$+f ~+{+]+^+/+(+_+:+<+f f [+}+|+)+)+)+)+1+ ", +" 2+3+3+3+3+4+3+5+f 6+7+8+9+0+a+b+c+d+f f e+f+g+3+3+3+3+h+ ", +" i+j+j+j+j+k+j+l+m+n+o+p+q+r+s+t+u+u+f f v+w+x+j+j+j+j+y+ ", +" z+A+A+A+A+B+A+C+D+E+F+G+H+I+J+K+L+M+f f N+O+P+A+A+A+A+Q+ ", +" R+S+S+S+S+T+U+V+f W+X+f f f f f f f f f Y+Z+`+S+S+S+S+ @ ", +" .@+@+@+@+@@@#@$@%@&@*@=@-@-@;@;@>@=@-@%@,@'@)@+@+@+@+@!@ ", +" ~@{@{@{@{@{@{@]@^@^@^@^@^@^@^@^@^@^@^@^@]@/@{@{@{@{@{@(@ ", +" _@:@:@:@:@:@<@[@[@[@[@[@[@[@[@[@[@[@[@[@[@<@:@:@:@:@:@}@ ", +" |@1@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@2@1@3@ ", +" 4@5@6@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@7@6@8@8@ ", +" 9@0@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@a@b@c@d@ ", +" ", +" "}; diff --git a/telldus-gui/TelldusCenter/tellduscenter.desktop b/telldus-gui/TelldusCenter/tellduscenter.desktop new file mode 100644 index 00000000..893ebf9d --- /dev/null +++ b/telldus-gui/TelldusCenter/tellduscenter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=TelldusCenter +Comment=A program to control and edit devices used by Telldus TellStick +Exec=TelldusCenter +Icon=tellduscenter +Terminal=false +Type=Application +Categories=Utility; From 541e8e0ba40efbb90bd9fbc05ab94e28d5f56807 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 18 Mar 2011 14:50:04 +0000 Subject: [PATCH 1646/2215] Fix so only explicitly specified symbols are exported (patch fix-exported-symbols.patch) --- telldus-gui/TelldusGui/CMakeLists.txt | 4 ++++ telldus-gui/TelldusGui/telldusgui.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index f1fba39d..b02d28dc 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -137,6 +137,10 @@ ADD_LIBRARY(${telldus-gui_TARGET} SHARED ${telldus-gui_QM} ) +IF (UNIX) + SET_TARGET_PROPERTIES( ${telldus-gui_TARGET} PROPERTIES COMPILE_FLAGS "-fPIC -fvisibility=hidden") +ENDIF (UNIX) + TARGET_LINK_LIBRARIES( ${telldus-gui_TARGET} ${telldus-gui_LIBRARIES} ) SET_PROPERTY(TARGET ${telldus-gui_TARGET} diff --git a/telldus-gui/TelldusGui/telldusgui.h b/telldus-gui/TelldusGui/telldusgui.h index 22c814c2..eca17e5e 100644 --- a/telldus-gui/TelldusGui/telldusgui.h +++ b/telldus-gui/TelldusGui/telldusgui.h @@ -18,7 +18,7 @@ #define WINAPI __stdcall #else #define WINAPI - #define TELLDUSGUI_API + #define TELLDUSGUI_API __attribute__ ((visibility("default"))) #endif class QWidget; From 829e8e2e661ba236327955a014068a4819e007eb Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 18 Mar 2011 14:52:41 +0000 Subject: [PATCH 1647/2215] Changed configuration order in live plugin, so that it is configured correctly (patch fix-live-configuration.path) --- telldus-gui/Plugins/Live/CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/telldus-gui/Plugins/Live/CMakeLists.txt b/telldus-gui/Plugins/Live/CMakeLists.txt index 343a6546..38146414 100644 --- a/telldus-gui/Plugins/Live/CMakeLists.txt +++ b/telldus-gui/Plugins/Live/CMakeLists.txt @@ -31,6 +31,10 @@ SET( Plugin_EXTRA icon.png ) +SET(TELLDUS_LIVE_PUBLIC_KEY "" CACHE STRING "Telldus Live! public key") +SET(TELLDUS_LIVE_PRIVATE_KEY "" CACHE STRING "Telldus Live! private key") +SET(TELLDUS_LIVE_URI "https://api.telldus.com/server/assign" CACHE STRING "Telldus Live! Connection URI") + CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/parsed/config.h @@ -38,8 +42,4 @@ CONFIGURE_FILE( INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/parsed/) -SET(TELLDUS_LIVE_PUBLIC_KEY "" CACHE STRING "Telldus Live! public key") -SET(TELLDUS_LIVE_PRIVATE_KEY "" CACHE STRING "Telldus Live! private key") -SET(TELLDUS_LIVE_URI "https://api.telldus.com/server/assign" CACHE STRING "Telldus Live! Connection URI") - INCLUDE( ../TelldusCenterPlugin.cmake NO_POLICY_SCOPE ) From bdbc0e07596557c78770e49df0179028b6d45a62 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 22 Mar 2011 11:20:17 +0000 Subject: [PATCH 1648/2215] Added condition in CMakeLists.txt for TelldusGui so that install library only is evaluated on Linux, allowing it to compile on windows platform too. --- telldus-gui/TelldusGui/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/telldus-gui/TelldusGui/CMakeLists.txt b/telldus-gui/TelldusGui/CMakeLists.txt index b02d28dc..89d7ec60 100644 --- a/telldus-gui/TelldusGui/CMakeLists.txt +++ b/telldus-gui/TelldusGui/CMakeLists.txt @@ -157,7 +157,9 @@ SET_PROPERTY(TARGET ${telldus-gui_TARGET} PROPERTY SOVERSION ${PACKAGE_SOVERSION} ) +if (UNIX) INSTALL(TARGETS ${telldus-gui_TARGET} LIBRARY DESTINATION lib # PUBLIC_HEADER DESTINATION ${HEADER_DIR} ) +endif (UNIX) From 6ac0d706a58d85062d2decd2fcc1e2cc8e902bb2 Mon Sep 17 00:00:00 2001 From: Fredrik Jacobsson Date: Tue, 12 Apr 2011 09:28:07 +0000 Subject: [PATCH 1649/2215] Added anslut logo, anslut_sl picture and mandolyn logo --- .../TelldusGui/images/devices/anslut_sl.png | Bin 0 -> 10032 bytes .../TelldusGui/images/vendors/anslut.png | Bin 0 -> 9862 bytes .../TelldusGui/images/vendors/mandolyn.png | Bin 0 -> 1264 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/anslut_sl.png create mode 100644 telldus-gui/TelldusGui/images/vendors/anslut.png create mode 100644 telldus-gui/TelldusGui/images/vendors/mandolyn.png diff --git a/telldus-gui/TelldusGui/images/devices/anslut_sl.png b/telldus-gui/TelldusGui/images/devices/anslut_sl.png new file mode 100644 index 0000000000000000000000000000000000000000..4d64158915c8825b8e2f5c0cf607138ace03823e GIT binary patch literal 10032 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 L)lsQbvJU@$&hklw literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/anslut.png b/telldus-gui/TelldusGui/images/vendors/anslut.png new file mode 100644 index 0000000000000000000000000000000000000000..50949aa32379a9a52c95b7818f113a506a44630d GIT binary patch literal 9862 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 literal 0 HcmV?d00001 diff --git a/telldus-gui/TelldusGui/images/vendors/mandolyn.png b/telldus-gui/TelldusGui/images/vendors/mandolyn.png new file mode 100644 index 0000000000000000000000000000000000000000..1ccc874544189b57293d8eeed7831ea070519efc GIT binary patch literal 1264 zcmeAS@N?(olHy`uVBq!ia0vp^(?FPm4M^HB7Cr(}jKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=85s1GL71^(seKtxkiEpy*OmP?3lFC-qmYy6eg+1X0#6smkcwMx zZ~14)y2>2*n4c^q%%A1tu*Qksi$!$p$`1CurXj5Sa$HT09T5QnFAp|%)H`nZ=XkJr z%cU^GX{#zeEc&9LWcyQHOiN44H%h=HOZVSu-%H1yEABs9dgJEzPxEfP_+9tlqtRyL znRDmfKljFuX_AU3S?Fc_=2s%y{_<|Hx7*#QpM9#2;qiftnrmw&yuSY8gOyp>0gFHH zO}yq$pFO2kQ*-~NUj?gPt$wzsj`0u6m(){h+4`6+vt6rqKhI^+Zr-@LVdI&Pyay7d zOpe+Yy}s|gxbf4nqaU-4%YP_*a5+_Nx1R(zCh!GncQjf35Vl@|o|)%@%gI(&~5VZCKYmzg#7? z%;jJ2%*G#9m$D~UF;Dzoz3lAmNq2##<)z$;3I6!(Cc{6E zPw7hk7x~EF^S)&<CF@otboOckb=q?K&NUYgI^Gw(k8 zpP-z6?j`^n`ceum9o(@)KpJN|su9gU+wW?>hvWdPl9>cB3`OShHw z+Fp8WTKZ1!scb@~a;f*r$fX;5x?@Xo?3&EB@1J(f@}9~DwkV!8ua*Dbot3&_?!S`M zgt?N;meS=9a%@cI#|A%N?Xf(X`|!!=^xe!KV{_s|-hS^5xiT|vlStgnLqQQY;(x`4 zo?g(nwWsfW@1EU{e$Q1a6*DqE@+|1)KR&jkc(npXxz#Iz_x#*DDKpu;{=ab8-JdyK z$@){K9sJ4`R^3?Y{_^Wijt#r4+LiyNoXK%MFxT+3Nb3352@3D}_atw8!*^`jVcVq( z^sevRv!y*W$9#?7HfgcsXIW)-wmP}L&ZSOsWX_h9wKu<)(v|$&d}VR|S?6lyo2xR? z70xl-JOAh2+nH9gy{jW%rW@wX3uCWe6q2^O@oHT{pwx+#Vz0h1@E@tWcJju$3T?T% zZpWLqA3A(Fnqw+@zQMg=`O5#3&xPu|T_k?KbFW0srLOCWmmH+xCWMyAaruY8GVkXGomAUrLGhlJV N;OXk;vd$@?2>|xbPG$fA literal 0 HcmV?d00001 From c7800b90ff9090b55ae91d40010c1a201069d2ac Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 12 May 2011 15:33:49 +0000 Subject: [PATCH 1650/2215] Implemented TDSensorEvent in com.telldus.core --- telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp | 9 ++++++++- telldus-gui/Plugins/TelldusCore/tellduscoreobject.h | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp index ada1a586..cb6c925b 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.cpp @@ -7,11 +7,13 @@ TelldusCoreObject::TelldusCoreObject( QObject * parent ) tdInit(); deviceEventId = tdRegisterDeviceEvent(reinterpret_cast(&TelldusCoreObject::deviceEventCallback), this); deviceChangeEventId = tdRegisterDeviceChangeEvent(reinterpret_cast(&TelldusCoreObject::deviceChangeEventCallback), this); + sensorEventId = tdRegisterSensorEvent(reinterpret_cast(&TelldusCoreObject::sensorEventCallback), this); } TelldusCoreObject::~TelldusCoreObject() { tdUnregisterCallback(deviceEventId); tdUnregisterCallback(deviceChangeEventId); + tdUnregisterCallback(sensorEventId); tdClose(); } @@ -108,7 +110,6 @@ void TelldusCoreObject::triggerError(int deviceId, int errorId) { emit errorOccurred(deviceId, errorId, message); } - void WINAPI TelldusCoreObject::deviceChangeEventCallback(int deviceId, int eventId, int changeType, int callbackId, void *context) { TelldusCoreObject *parent = static_cast(context); if (parent) { @@ -123,3 +124,9 @@ void WINAPI TelldusCoreObject::deviceEventCallback(int deviceId, int method, con } } +void WINAPI TelldusCoreObject::sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context) { + TelldusCoreObject *parent = static_cast(context); + if (parent) { + emit parent->sensorEvent(QString::fromUtf8(protocol), QString::fromUtf8(model), id, dataType, QString::fromUtf8(value), timestamp); + } +} diff --git a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h index d8e14a78..83515258 100644 --- a/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h +++ b/telldus-gui/Plugins/TelldusCore/tellduscoreobject.h @@ -14,6 +14,7 @@ public: signals: void deviceChange( int deviceId, int eventId ); void deviceEvent( int deviceId, int method, const QString &data ); + void sensorEvent( const QString &protocol, const QString &model, int id, int dataType, const QString &value, int timestamp); void errorOccurred( int deviceId, int errorId, const QString &errorString ); public slots: @@ -37,9 +38,11 @@ private: static void WINAPI deviceChangeEventCallback(int deviceId, int eventId, int changeType, int callbackId, void *context); static void WINAPI deviceEventCallback(int deviceId, int method, const char *data, int callbackId, void *context); + static void WINAPI sensorEventCallback(const char *protocol, const char *model, int id, int dataType, const char *value, int timestamp, int callbackId, void *context); int deviceEventId; int deviceChangeEventId; + int sensorEventId; }; From 7ec1ed838d875f47962edf963c5e09968536e77b Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 May 2011 08:51:43 +0000 Subject: [PATCH 1651/2215] Changed parameter name to model instead of type to allow scanning --- telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp index 770c0e32..24c8cbe8 100644 --- a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp +++ b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp @@ -47,7 +47,7 @@ void FilteredDeviceProxyModel::addFilter( const QString &filter ) { QString value = parameter.section(':', -1); if (name == "protocol") { protocol = value; - } else if (name == "type") { + } else if (name == "model") { type = value; } else if (name == "method") { } else { From 228e0302ce11d5b9dae34e7664631f66fb64b7fd Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 May 2011 08:55:42 +0000 Subject: [PATCH 1652/2215] Changed parameter name in code to model instead of type to allow scanning --- .../TelldusGui/filtereddeviceproxymodel.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp index 24c8cbe8..53008894 100644 --- a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp +++ b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp @@ -15,11 +15,11 @@ public: class FilteredDeviceProxyModel::PrivateData::Filter { public: Filter(QString p, QString t); - QString protocol, type; + QString protocol, model; }; FilteredDeviceProxyModel::PrivateData::Filter::Filter(QString p, QString t) - :protocol(p), type(t) + :protocol(p), model(t) {} FilteredDeviceProxyModel::FilteredDeviceProxyModel( QObject * parent ) @@ -41,14 +41,14 @@ void FilteredDeviceProxyModel::setSourceModel( VendorDeviceModel * sourceModel ) void FilteredDeviceProxyModel::addFilter( const QString &filter ) { d->filtered = true; - QString protocol, type; + QString protocol, model; foreach(QString parameter, filter.split(';', QString::SkipEmptyParts)) { QString name = parameter.section(':', 0, 0); QString value = parameter.section(':', -1); if (name == "protocol") { protocol = value; } else if (name == "model") { - type = value; + model = value; } else if (name == "method") { } else { emit setParameter(name, value); @@ -59,12 +59,12 @@ void FilteredDeviceProxyModel::addFilter( const QString &filter ) { if (d->filters.at(i).protocol != protocol) { continue; } - if (d->filters.at(i).type != type) { + if (d->filters.at(i).model != model) { continue; } return; } - d->filters << PrivateData::Filter(protocol, type); + d->filters << PrivateData::Filter(protocol, model); invalidateFilter(); } @@ -104,7 +104,7 @@ bool FilteredDeviceProxyModel::filterAcceptsRow ( int sourceRow, const QModelInd if (strModel.startsWith("selflearning-")) { strModel = "selflearning"; } - if (strModel == d->filters.at(i).type) { + if (strModel == d->filters.at(i).model) { return true; } } From 217c63fe6cc79eaebf8bd2362111c2432d9dda27 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Fri, 13 May 2011 12:36:31 +0000 Subject: [PATCH 1653/2215] Don't scan sensors --- telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp index 53008894..0e20ec6c 100644 --- a/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp +++ b/telldus-gui/TelldusGui/filtereddeviceproxymodel.cpp @@ -50,7 +50,10 @@ void FilteredDeviceProxyModel::addFilter( const QString &filter ) { } else if (name == "model") { model = value; } else if (name == "method") { - } else { + } else if (name == "class" && value!= "command"){ + return; //don't scan sensors here + } + else { emit setParameter(name, value); } } From 57524439c4e7e2898f8c7b01fbd327a459966991 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Mon, 16 May 2011 14:03:51 +0000 Subject: [PATCH 1654/2215] Allow plugins to be loaded both from the build-directory and the system on Linux --- .../TelldusCenter/tellduscenterapplication.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp index 270ac015..7db41951 100644 --- a/telldus-gui/TelldusCenter/tellduscenterapplication.cpp +++ b/telldus-gui/TelldusCenter/tellduscenterapplication.cpp @@ -92,23 +92,25 @@ void TelldusCenterApplication::eventTriggered( const QString &name, const QStrin void TelldusCenterApplication::loadPlugins() { QDir pluginsDir = QDir(qApp->applicationDirPath()); + QStringList paths; #if defined(Q_OS_MAC) if (pluginsDir.dirName() == "MacOS") { pluginsDir.cdUp(); } #endif - + if (pluginsDir.cd("Plugins")) { - this->setLibraryPaths( QStringList(pluginsDir.absolutePath()) ); + paths << pluginsDir.absolutePath(); } #if defined(Q_OS_UNIX) - QStringList paths = QStringList() << DEFINE_STRING(PLUGIN_LIB_PATH); - this->setLibraryPaths( paths ); + paths << DEFINE_STRING(PLUGIN_LIB_PATH); #endif - + + this->setLibraryPaths( paths ); + QScriptValue mainWindowObject = d->scriptEnvironment->engine()->newQObject(d->mainWindow); d->scriptEnvironment->engine()->globalObject().property("application").setProperty("mainwindow", mainWindowObject); From 875bb235caa8da3aa6717bff2e6589dcee91747a Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 18 May 2011 08:10:46 +0000 Subject: [PATCH 1655/2215] Moved the python examples into the examples directory --- .../python/Callback functions => examples/python}/callbacks.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {bindings/python/Callback functions => examples/python}/callbacks.py (100%) diff --git a/bindings/python/Callback functions/callbacks.py b/examples/python/callbacks.py similarity index 100% rename from bindings/python/Callback functions/callbacks.py rename to examples/python/callbacks.py From 7bdbd4f576f3d0234e4b6f153af2e22a7e1758c5 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Wed, 17 Aug 2011 15:56:07 +0000 Subject: [PATCH 1656/2215] Add Hasta blinds --- telldus-gui/TelldusGui/data/telldus/devices.xml | 13 ++++++++----- .../TelldusGui/data/telldus/resources.qrc | 2 ++ telldus-gui/TelldusGui/editdevicedialog.cpp | 4 ++++ telldus-gui/TelldusGui/images/devices/hasta.png | Bin 0 -> 14273 bytes telldus-gui/TelldusGui/images/vendors/hasta.png | Bin 0 -> 5293 bytes 5 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 telldus-gui/TelldusGui/images/devices/hasta.png create mode 100644 telldus-gui/TelldusGui/images/vendors/hasta.png diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index cff993a1..73eea99c 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -117,11 +117,14 @@ Code Switch - - - Projector screen - - + + + Blinds + + + Projector screen + + KP100 diff --git a/telldus-gui/TelldusGui/data/telldus/resources.qrc b/telldus-gui/TelldusGui/data/telldus/resources.qrc index 57c67880..1cd8b8bf 100644 --- a/telldus-gui/TelldusGui/data/telldus/resources.qrc +++ b/telldus-gui/TelldusGui/data/telldus/resources.qrc @@ -14,6 +14,7 @@ ../../images/devices/goobay.png ../../images/devices/gao_cs.png ../../images/devices/gao_sl.png + ../../images/devices/hasta.png ../../images/devices/hq_cs.png ../../images/devices/koppla.png ../../images/devices/kp100.png @@ -34,6 +35,7 @@ ../../images/vendors/elro.png ../../images/vendors/goobay.png ../../images/vendors/gao.png + ../../images/vendors/hasta.png ../../images/vendors/homeeasy.png ../../images/vendors/hq.png ../../images/vendors/ikea.png diff --git a/telldus-gui/TelldusGui/editdevicedialog.cpp b/telldus-gui/TelldusGui/editdevicedialog.cpp index 1c269b56..66afa766 100644 --- a/telldus-gui/TelldusGui/editdevicedialog.cpp +++ b/telldus-gui/TelldusGui/editdevicedialog.cpp @@ -167,6 +167,10 @@ EditDeviceDialog::EditDeviceDialog(Device *device, QWidget *parent, Qt::WFlags f //Kingpin d->deviceSettings[15] = new DeviceSettingSelflearning(device, this); ((DeviceSettingSelflearning *)d->deviceSettings[15])->setRemoteMinMax(1,1048575); + //Hasta + d->deviceSettings[16] = new DeviceSettingArctechSelflearning(device, this); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setRemoteMinMax(1,65536); + ((DeviceSettingArctechSelflearning *)d->deviceSettings[9])->setUnitMinMax(1,15); foreach( DeviceSetting *s, d->deviceSettings ) { connect(d->filteredModel, SIGNAL(setParameter(const QString&, const QString&)), s, SLOT(setValue(const QString&, const QString&))); diff --git a/telldus-gui/TelldusGui/images/devices/hasta.png b/telldus-gui/TelldusGui/images/devices/hasta.png new file mode 100644 index 0000000000000000000000000000000000000000..3e6f9288727bd3f8d2d02724dd7adca56151065f GIT binary patch literal 14273 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 PiGYEQsrD;PmxTWT&=$B_ literal 0 HcmV?d00001 From 58aa13f3ea05012ced201d8e8caafbbcc89cc8fa Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 1 Sep 2011 12:53:07 +0000 Subject: [PATCH 1657/2215] Bump version number --- telldus-gui/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/CMakeLists.txt b/telldus-gui/CMakeLists.txt index d1427b9f..b5236e92 100644 --- a/telldus-gui/CMakeLists.txt +++ b/telldus-gui/CMakeLists.txt @@ -7,8 +7,8 @@ if(COMMAND cmake_policy) endif(COMMAND cmake_policy) SET(PACKAGE_MAJOR_VERSION 2) -SET(PACKAGE_MINOR_VERSION 0) -SET(PACKAGE_PATCH_VERSION 104) +SET(PACKAGE_MINOR_VERSION 1) +SET(PACKAGE_PATCH_VERSION 0) SET(PACKAGE_SOVERSION 2) SET(PACKAGE_VERSION "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}.${PACKAGE_PATCH_VERSION}") SET(DISPLAYED_VERSION ${PACKAGE_VERSION}) From 35d694d62e3f7d7eb81334040f2ae7aa8dcf1471 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 1 Sep 2011 12:53:11 +0000 Subject: [PATCH 1658/2215] Report Mac OS X Lion correctly --- telldus-gui/Plugins/Live/LiveObject.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/telldus-gui/Plugins/Live/LiveObject.cpp b/telldus-gui/Plugins/Live/LiveObject.cpp index 3acb4fe8..4d853d97 100644 --- a/telldus-gui/Plugins/Live/LiveObject.cpp +++ b/telldus-gui/Plugins/Live/LiveObject.cpp @@ -299,6 +299,9 @@ LiveMessageToken LiveObject::generateVersionToken() { case QSysInfo::MV_SNOWLEOPARD: token.dictVal["os-version"] = LiveMessageToken("snowleopard"); break; + case QSysInfo::MV_SNOWLEOPARD+1: //TODO: MV_LION when we build against Qt-4.8 + token.dictVal["os-version"] = LiveMessageToken("lion"); + break; default: token.dictVal["os-version"] = LiveMessageToken("unknown"); } From 58e2f2a4b6762d71445c54f5488f95353f6d9280 Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Thu, 1 Sep 2011 13:12:10 +0000 Subject: [PATCH 1659/2215] Use correct device id for newly created devices --- telldus-gui/Plugins/TelldusCore/__init__.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/Plugins/TelldusCore/__init__.js b/telldus-gui/Plugins/TelldusCore/__init__.js index 410b197a..96323cc6 100644 --- a/telldus-gui/Plugins/TelldusCore/__init__.js +++ b/telldus-gui/Plugins/TelldusCore/__init__.js @@ -24,7 +24,7 @@ __postInit__ = function() { function deviceChangeEvent( deviceId, eventType ) { //print("DeviceChangeEvent", deviceId, eventType); if (eventType == com.telldus.core.TELLSTICK_DEVICE_ADDED) { - devices.push(new Device(com.telldus.core.getDeviceId(i))); + devices.push(new Device(deviceId)); return; } From 74022f1f9a5f6da0667789b7045f4e808cc420db Mon Sep 17 00:00:00 2001 From: Micke Prag Date: Fri, 2 Sep 2011 12:09:50 +0000 Subject: [PATCH 1660/2215] Add 'UK only' for Home Easy devices --- telldus-gui/TelldusGui/data/telldus/devices.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telldus-gui/TelldusGui/data/telldus/devices.xml b/telldus-gui/TelldusGui/data/telldus/devices.xml index 73eea99c..4b5eed67 100644 --- a/telldus-gui/TelldusGui/data/telldus/devices.xml +++ b/telldus-gui/TelldusGui/data/telldus/devices.xml @@ -42,7 +42,7 @@ Code Switch - + Code Switch Self Learning on/off From 3f98c6ea87e729ca98b608142b088b603a87d2a2 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Mon, 5 Sep 2011 10:50:15 +0000 Subject: [PATCH 1661/2215] Updated copyright year --- telldus-gui/TelldusCenter/TelldusCenter.rc.in | 2 +- telldus-gui/TelldusCenter/mainwindow.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/telldus-gui/TelldusCenter/TelldusCenter.rc.in b/telldus-gui/TelldusCenter/TelldusCenter.rc.in index 5b8a7cab..e4113040 100644 --- a/telldus-gui/TelldusCenter/TelldusCenter.rc.in +++ b/telldus-gui/TelldusCenter/TelldusCenter.rc.in @@ -11,7 +11,7 @@ BEGIN VALUE "CompanyName", "Telldus Technologies AB" VALUE "FileDescription", "The home automation control center" VALUE "FileVersion", "${PACKAGE_VERSION}" - VALUE "LegalCopyright", "Copyright (C) 2010 Telldus Technologies AB" + VALUE "LegalCopyright", "Copyright (C) 2011 Telldus Technologies AB" VALUE "OriginalFilename", "TelldusCenter.exe" VALUE "ProductName", "TelldusCenter" VALUE "ProductVersion", "${PACKAGE_MAJOR_VERSION}.${PACKAGE_MINOR_VERSION}" diff --git a/telldus-gui/TelldusCenter/mainwindow.cpp b/telldus-gui/TelldusCenter/mainwindow.cpp index 1fbc33b4..879215a4 100644 --- a/telldus-gui/TelldusCenter/mainwindow.cpp +++ b/telldus-gui/TelldusCenter/mainwindow.cpp @@ -134,7 +134,7 @@ void MainWindow::addWidget( const QString &page, const QIcon &icon, QWidget *wid void MainWindow::slotAboutApplication() { QMessageBox::about(this, tr("About TelldusCenter"), tr("

TelldusCenter %1

" - "

Copyright © 2010 Telldus Technologies AB

").arg(VERSION_STRING(VERSION))); + "

Copyright © 2011 Telldus Technologies AB